From 76d17c315645552a99691ed0b2024f52b22aa8c9 Mon Sep 17 00:00:00 2001 From: oliviermartin Date: Thu, 22 Sep 2011 22:54:38 +0000 Subject: ArmPkg/BdsLib: Use two distinct functions to boot Linux either by Atag or Fdt Separate the BdsBootLinux() function into two functions for Atag and Fdt specific Linux booting - BdsBootLinuxAtag () - BdsBootLinuxFdt () git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12408 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/Library/BdsLib/BdsInternal.h | 4 + ArmPkg/Library/BdsLib/BdsLinuxLoader.c | 222 +++++++++++++++++++-------------- ArmPkg/Library/BdsLib/BdsLinuxLoader.h | 3 + 3 files changed, 138 insertions(+), 91 deletions(-) (limited to 'ArmPkg/Library/BdsLib') diff --git a/ArmPkg/Library/BdsLib/BdsInternal.h b/ArmPkg/Library/BdsLib/BdsInternal.h index d450e8e6b2..9b73376f96 100644 --- a/ArmPkg/Library/BdsLib/BdsInternal.h +++ b/ArmPkg/Library/BdsLib/BdsInternal.h @@ -16,14 +16,17 @@ #define __BDS_INTERNAL_H__ #include +#include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -38,6 +41,7 @@ #include #include +#include "BdsLinuxLoader.h" typedef BOOLEAN (*BDS_FILE_LOADER_SUPPORT) ( IN EFI_DEVICE_PATH *DevicePath, diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c index ce4b2a43b6..06baf49c55 100644 --- a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c +++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c @@ -13,17 +13,9 @@ **/ #include "BdsInternal.h" -#include "BdsLinuxLoader.h" - -#include -#include -#include #define ALIGN32_BELOW(addr) ALIGN_POINTER(addr - 32,32) -#define LINUX_ATAG_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset)) -#define LINUX_KERNEL_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxKernelMaxOffset)) - // Point to the current ATAG STATIC LINUX_ATAG *mLinuxKernelCurrentAtag; @@ -178,7 +170,7 @@ PreparePlatformHardware ( { //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called. - // clean, invalidate, disable data cache + // Clean, invalidate, disable data cache ArmCleanInvalidateDataCache(); ArmDisableDataCache(); @@ -186,97 +178,24 @@ PreparePlatformHardware ( ArmInvalidateInstructionCache (); ArmDisableInstructionCache (); - // turn off MMU + // Turn off MMU ArmDisableMmu(); return EFI_SUCCESS; } -/** - Start a Linux kernel from a Device Path - - @param LinuxKernel Device Path to the Linux Kernel - @param Parameters Linux kernel agruments - @param Fdt Device Path to the Flat Device Tree - - @retval EFI_SUCCESS All drivers have been connected - @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found - @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results. - -**/ +STATIC EFI_STATUS -BdsBootLinux ( - IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath, - IN CONST CHAR8* Arguments, - IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath +StartLinux ( + IN EFI_PHYSICAL_ADDRESS LinuxImage, + IN UINTN LinuxImageSize, + IN EFI_PHYSICAL_ADDRESS KernelParamsAddress, + IN UINTN KernelParamsSize, + IN UINT32 MachineType ) { EFI_STATUS Status; - UINT32 LinuxImageSize; - UINT32 InitrdImageSize; - UINT32 KernelParamsSize; - EFI_PHYSICAL_ADDRESS KernelParamsAddress; - UINT32 MachineType; - BOOLEAN FdtSupported; LINUX_KERNEL LinuxKernel; - EFI_PHYSICAL_ADDRESS LinuxImage; - EFI_PHYSICAL_ADDRESS InitrdImage; - - InitrdImageSize = 0; - FdtSupported = FALSE; - - // Ensure the System Memory PCDs have been initialized (PcdSystemMemoryBase and PcdSystemMemorySize) - ASSERT (PcdGet32(PcdSystemMemorySize) != 0); - - PERF_START (NULL, "BDS", NULL, 0); - - // Load the Linux kernel from a device path - LinuxImage = LINUX_KERNEL_MAX_OFFSET; - Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize); - if (EFI_ERROR(Status)) { - Print (L"ERROR: Did not find Linux kernel.\n"); - return Status; - } - LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage; - - if (InitrdDevicePath) { - Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize); - if (EFI_ERROR(Status)) { - Print (L"ERROR: Did not find initrd image.\n"); - return Status; - } - } - - if (FdtDevicePath) { - // Load the FDT binary from a device path - KernelParamsAddress = LINUX_ATAG_MAX_OFFSET; - Status = BdsLoadImage (FdtDevicePath, AllocateMaxAddress, &KernelParamsAddress, &KernelParamsSize); - if (EFI_ERROR(Status)) { - Print (L"ERROR: Did not find Device Tree blob.\n"); - return Status; - } - FdtSupported = TRUE; - } - - // - // Setup the Linux Kernel Parameters - // - if (!FdtSupported) { - // Non-FDT requires a specific machine type. - // This OS Boot loader supports just one machine type, - // but that could change in the future. - MachineType = PcdGet32(PcdArmMachineType); - - // By setting address=0 we leave the memory allocation to the function - Status = PrepareAtagList (Arguments, InitrdImage, InitrdImageSize, (LINUX_ATAG**)&KernelParamsAddress, &KernelParamsSize); - if(EFI_ERROR(Status)) { - Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status); - goto Exit; - } - } else { - MachineType = 0xFFFFFFFF; - } // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event. @@ -298,6 +217,8 @@ BdsBootLinux ( if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) { //Note: There is no requirement on the alignment LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize); + } else { + LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage; } //TODO: Check there is no overlapping between kernel and Atag @@ -322,7 +243,7 @@ BdsBootLinux ( DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n")); // jump to kernel with register set - LinuxKernel ((UINTN)0, (UINTN)MachineType, (UINTN)KernelParamsAddress); + LinuxKernel ((UINTN)0, MachineType, (UINTN)KernelParamsAddress); // Kernel should never exit // After Life services are not provided @@ -335,3 +256,122 @@ Exit: // Free Runtimee Memory (kernel and FDT) return Status; } + +/** + Start a Linux kernel from a Device Path + + @param LinuxKernel Device Path to the Linux Kernel + @param Parameters Linux kernel agruments + @param Fdt Device Path to the Flat Device Tree + + @retval EFI_SUCCESS All drivers have been connected + @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found + @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results. + +**/ +EFI_STATUS +BdsBootLinuxAtag ( + IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath, + IN CONST CHAR8* Arguments + ) +{ + EFI_STATUS Status; + UINT32 LinuxImageSize; + UINT32 InitrdImageSize = 0; + UINT32 KernelParamsSize; + EFI_PHYSICAL_ADDRESS KernelParamsAddress; + EFI_PHYSICAL_ADDRESS LinuxImage; + EFI_PHYSICAL_ADDRESS InitrdImage; + + PERF_START (NULL, "BDS", NULL, 0); + + // Load the Linux kernel from a device path + LinuxImage = LINUX_KERNEL_MAX_OFFSET; + Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize); + if (EFI_ERROR(Status)) { + Print (L"ERROR: Did not find Linux kernel.\n"); + return Status; + } + + if (InitrdDevicePath) { + Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize); + if (EFI_ERROR(Status)) { + Print (L"ERROR: Did not find initrd image.\n"); + return Status; + } + } + + // + // Setup the Linux Kernel Parameters + // + + // By setting address=0 we leave the memory allocation to the function + Status = PrepareAtagList (Arguments, InitrdImage, InitrdImageSize, (LINUX_ATAG**)&KernelParamsAddress, &KernelParamsSize); + if (EFI_ERROR(Status)) { + Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status); + return Status; + } + + return StartLinux (LinuxImage, LinuxImageSize, KernelParamsAddress, KernelParamsSize, PcdGet32(PcdArmMachineType)); +} + +/** + Start a Linux kernel from a Device Path + + @param LinuxKernel Device Path to the Linux Kernel + @param Parameters Linux kernel agruments + @param Fdt Device Path to the Flat Device Tree + + @retval EFI_SUCCESS All drivers have been connected + @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found + @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results. + +**/ +EFI_STATUS +BdsBootLinuxFdt ( + IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath, + IN CONST CHAR8* Arguments, + IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath + ) +{ + EFI_STATUS Status; + UINT32 LinuxImageSize; + UINT32 InitrdImageSize = 0; + UINT32 KernelParamsSize; + EFI_PHYSICAL_ADDRESS KernelParamsAddress; + UINT32 FdtMachineType; + EFI_PHYSICAL_ADDRESS LinuxImage; + EFI_PHYSICAL_ADDRESS InitrdImage; + + FdtMachineType = 0xFFFFFFFF; + + PERF_START (NULL, "BDS", NULL, 0); + + // Load the Linux kernel from a device path + LinuxImage = LINUX_KERNEL_MAX_OFFSET; + Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize); + if (EFI_ERROR(Status)) { + Print (L"ERROR: Did not find Linux kernel.\n"); + return Status; + } + + if (InitrdDevicePath) { + Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize); + if (EFI_ERROR(Status)) { + Print (L"ERROR: Did not find initrd image.\n"); + return Status; + } + } + + // Load the FDT binary from a device path + KernelParamsAddress = LINUX_ATAG_MAX_OFFSET; + Status = BdsLoadImage (FdtDevicePath, AllocateMaxAddress, &KernelParamsAddress, &KernelParamsSize); + if (EFI_ERROR(Status)) { + Print (L"ERROR: Did not find Device Tree blob.\n"); + return Status; + } + return StartLinux (LinuxImage, LinuxImageSize, KernelParamsAddress, KernelParamsSize, FdtMachineType); +} + diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.h b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h index 82b7a4f081..e951e2a4be 100644 --- a/ArmPkg/Library/BdsLib/BdsLinuxLoader.h +++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.h @@ -15,6 +15,9 @@ #ifndef __BDSLINUXLOADER_H #define __BDSLINUXLOADER_H +#define LINUX_ATAG_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset)) +#define LINUX_KERNEL_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxKernelMaxOffset)) + #define ATAG_MAX_SIZE 0x3000 /* ATAG : list of possible tags */ -- cgit v1.2.3