VOID\r
);\r
\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param LinuxKernel Device Path to the Linux Kernel\r
- @param Parameters Linux kernel arguments\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxAtag (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* Arguments\r
- );\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param[in] LinuxKernelDevicePath Device Path to the Linux Kernel\r
- @param[in] InitrdDevicePath Device Path to the Initrd\r
- @param[in] Arguments Linux kernel arguments\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxFdt (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* Arguments\r
- );\r
-\r
/**\r
Start an EFI Application from a Device Path\r
\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-#include <Library/ArmGicLib.h>\r
-#include <Ppi/ArmMpCoreInfo.h>\r
-#include <Library/IoLib.h>\r
-#include <Guid/Fdt.h>\r
-#include <libfdt.h>\r
-\r
-#include "BdsInternal.h"\r
-#include "BdsLinuxLoader.h"\r
-\r
-/*\r
- Linux kernel booting: Look at the doc in the Kernel source :\r
- Documentation/arm64/booting.txt\r
- The kernel image must be placed at the start of the memory to be used by the\r
- kernel (2MB aligned) + 0x80000.\r
-\r
- The Device tree blob is expected to be under 2MB and be within the first 512MB\r
- of kernel memory and be 2MB aligned.\r
-\r
- A Flattened Device Tree (FDT) used to boot linux needs to be updated before\r
- the kernel is started. It needs to indicate how secondary cores are brought up\r
- and where they are waiting before loading Linux. The FDT also needs to hold\r
- the correct kernel command line and filesystem RAM-disk information.\r
- At the moment we do not fully support generating this FDT information at\r
- runtime. A prepared FDT should be provided at boot. FDT is the only supported\r
- method for booting the AArch64 Linux kernel.\r
-\r
- Linux does not use any runtime services at this time, so we can let it\r
- overwrite UEFI.\r
-*/\r
-\r
-\r
-#define LINUX_ALIGN_VAL (0x080000) // 2MB + 0x80000 mask\r
-#define LINUX_ALIGN_MASK (0x1FFFFF) // Bottom 21bits\r
-#define ALIGN_2MB(addr) ALIGN_POINTER(addr , (2*1024*1024))\r
-\r
-/* ARM32 and AArch64 kernel handover differ.\r
- * x0 is set to FDT base.\r
- * x1-x3 are reserved for future use and should be set to zero.\r
- */\r
-typedef VOID (*LINUX_KERNEL64)(UINTN ParametersBase, UINTN Reserved0,\r
- UINTN Reserved1, UINTN Reserved2);\r
-\r
-/* These externs are used to relocate some ASM code into Linux memory. */\r
-extern VOID *SecondariesPenStart;\r
-extern VOID *SecondariesPenEnd;\r
-extern UINTN *AsmMailboxbase;\r
-\r
-\r
-STATIC\r
-EFI_STATUS\r
-PreparePlatformHardware (\r
- VOID\r
- )\r
-{\r
- //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.\r
-\r
- // Clean before Disable else the Stack gets corrupted with old data.\r
- ArmCleanDataCache ();\r
- ArmDisableDataCache ();\r
- // Invalidate all the entries that might have snuck in.\r
- ArmInvalidateDataCache ();\r
-\r
- // Disable and invalidate the instruction cache\r
- ArmDisableInstructionCache ();\r
- ArmInvalidateInstructionCache ();\r
-\r
- // Turn off MMU\r
- ArmDisableMmu();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-StartLinux (\r
- IN EFI_PHYSICAL_ADDRESS LinuxImage,\r
- IN UINTN LinuxImageSize,\r
- IN EFI_PHYSICAL_ADDRESS FdtBlobBase,\r
- IN UINTN FdtBlobSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LINUX_KERNEL64 LinuxKernel = (LINUX_KERNEL64)LinuxImage;\r
-\r
- // Send msg to secondary cores to go to the kernel pen.\r
- ArmGicSendSgiTo (PcdGet32(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E, PcdGet32 (PcdGicSgiIntId));\r
-\r
- // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on\r
- // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.\r
- Status = ShutdownUefiBootServices ();\r
- if(EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status));\r
- goto Exit;\r
- }\r
-\r
- // Check if the Linux Image is a uImage\r
- if (*(UINTN*)LinuxKernel == LINUX_UIMAGE_SIGNATURE) {\r
- // Assume the Image Entry Point is just after the uImage header (64-byte size)\r
- LinuxKernel = (LINUX_KERNEL64)((UINTN)LinuxKernel + 64);\r
- LinuxImageSize -= 64;\r
- }\r
-\r
- //\r
- // Switch off interrupts, caches, mmu, etc\r
- //\r
- Status = PreparePlatformHardware ();\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- // Register and print out performance information\r
- PERF_END (NULL, "BDS", NULL, 0);\r
- if (PerformanceMeasurementEnabled ()) {\r
- PrintPerformance ();\r
- }\r
-\r
- //\r
- // Start the Linux Kernel\r
- //\r
-\r
- // x1-x3 are reserved (set to zero) for future use.\r
- LinuxKernel ((UINTN)FdtBlobBase, 0, 0, 0);\r
-\r
- // Kernel should never exit\r
- // After Life services are not provided\r
- ASSERT(FALSE);\r
-\r
-Exit:\r
- // Only be here if we fail to start Linux\r
- Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status);\r
-\r
- // Free Runtimee Memory (kernel and FDT)\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param LinuxKernel Device Path to the Linux Kernel\r
- @param Parameters Linux kernel agruments\r
- @param Fdt Device Path to the Flat Device Tree\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxAtag (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* Arguments\r
- )\r
-{\r
- // NOTE : AArch64 Linux kernel does not support ATAG, FDT only.\r
- ASSERT(0);\r
-\r
- return RETURN_UNSUPPORTED;\r
-}\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param[in] LinuxKernelDevicePath Device Path to the Linux Kernel\r
- @param[in] InitrdDevicePath Device Path to the Initrd\r
- @param[in] Arguments Linux kernel arguments\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxFdt (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* Arguments\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_STATUS PenBaseStatus;\r
- UINTN LinuxImageSize;\r
- UINTN InitrdImageSize;\r
- UINTN InitrdImageBaseSize;\r
- VOID *InstalledFdtBase;\r
- UINTN FdtBlobSize;\r
- EFI_PHYSICAL_ADDRESS FdtBlobBase;\r
- EFI_PHYSICAL_ADDRESS LinuxImage;\r
- EFI_PHYSICAL_ADDRESS InitrdImage;\r
- EFI_PHYSICAL_ADDRESS InitrdImageBase;\r
- ARM_PROCESSOR_TABLE *ArmProcessorTable;\r
- ARM_CORE_INFO *ArmCoreInfoTable;\r
- UINTN Index;\r
- EFI_PHYSICAL_ADDRESS PenBase;\r
- UINTN PenSize;\r
- UINTN MailBoxBase;\r
-\r
- PenBaseStatus = EFI_UNSUPPORTED;\r
- PenSize = 0;\r
- InitrdImage = 0;\r
- InitrdImageSize = 0;\r
- InitrdImageBase = 0;\r
- InitrdImageBaseSize = 0;\r
-\r
- PERF_START (NULL, "BDS", NULL, 0);\r
-\r
- //\r
- // Load the Linux kernel from a device path\r
- //\r
-\r
- // Try to put the kernel at the start of RAM so as to give it access to all memory.\r
- // If that fails fall back to try loading it within LINUX_KERNEL_MAX_OFFSET of memory start.\r
- LinuxImage = PcdGet64 (PcdSystemMemoryBase) + 0x80000;\r
- Status = BdsLoadImage (LinuxKernelDevicePath, AllocateAddress, &LinuxImage, &LinuxImageSize);\r
- if (EFI_ERROR(Status)) {\r
- // Try again but give the loader more freedom of where to put the image.\r
- LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find Linux kernel (%r).\n", Status);\r
- return Status;\r
- }\r
- }\r
- // Adjust the kernel location slightly if required. The kernel needs to be placed at start\r
- // of memory (2MB aligned) + 0x80000.\r
- if ((LinuxImage & LINUX_ALIGN_MASK) != LINUX_ALIGN_VAL) {\r
- LinuxImage = (EFI_PHYSICAL_ADDRESS)CopyMem (ALIGN_2MB(LinuxImage) + 0x80000, (VOID*)(UINTN)LinuxImage, LinuxImageSize);\r
- }\r
-\r
- if (InitrdDevicePath) {\r
- InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- Print (L"ERROR: Did not find initrd image (%r).\n", Status);\r
- goto EXIT_FREE_LINUX;\r
- }\r
-\r
- // Check if the initrd is a uInitrd\r
- if (*(UINTN*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) {\r
- // Skip the 64-byte image header\r
- InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);\r
- InitrdImageSize = InitrdImageBaseSize - 64;\r
- } else {\r
- InitrdImage = InitrdImageBase;\r
- InitrdImageSize = InitrdImageBaseSize;\r
- }\r
- }\r
-\r
- //\r
- // Get the FDT from the Configuration Table.\r
- // The FDT will be reloaded in PrepareFdt() to a more appropriate\r
- // location for the Linux Kernel.\r
- //\r
- Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &InstalledFdtBase);\r
- if (EFI_ERROR (Status)) {\r
- Print (L"ERROR: Did not get the Device Tree blob (%r).\n", Status);\r
- goto EXIT_FREE_INITRD;\r
- }\r
- FdtBlobBase = (EFI_PHYSICAL_ADDRESS)InstalledFdtBase;\r
- FdtBlobSize = fdt_totalsize (InstalledFdtBase);\r
-\r
- //\r
- // Install secondary core pens if the Power State Coordination Interface is not supported\r
- //\r
- if (FeaturePcdGet (PcdArmLinuxSpinTable)) {\r
- // Place Pen at the start of Linux memory. We can then tell Linux to not use this bit of memory\r
- PenBase = LinuxImage - 0x80000;\r
- PenSize = (UINTN)&SecondariesPenEnd - (UINTN)&SecondariesPenStart;\r
-\r
- // Reserve the memory as RuntimeServices\r
- PenBaseStatus = gBS->AllocatePages (AllocateAddress, EfiRuntimeServicesCode, EFI_SIZE_TO_PAGES (PenSize), &PenBase);\r
- if (EFI_ERROR (PenBaseStatus)) {\r
- Print (L"Warning: Failed to reserve the memory required for the secondary cores at 0x%lX, Status = %r\n", PenBase, PenBaseStatus);\r
- // Even if there is a risk of memory corruption we carry on\r
- }\r
-\r
- // Put mailboxes below the pen code so we know where they are relative to code.\r
- MailBoxBase = (UINTN)PenBase + ((UINTN)&SecondariesPenEnd - (UINTN)&SecondariesPenStart);\r
- // Make sure this is 8 byte aligned.\r
- if (MailBoxBase % sizeof(MailBoxBase) != 0) {\r
- MailBoxBase += sizeof(MailBoxBase) - MailBoxBase % sizeof(MailBoxBase);\r
- }\r
-\r
- CopyMem ( (VOID*)(PenBase), (VOID*)&SecondariesPenStart, PenSize);\r
-\r
- // Update the MailboxBase variable used in the pen code\r
- *(UINTN*)(PenBase + ((UINTN)&AsmMailboxbase - (UINTN)&SecondariesPenStart)) = MailBoxBase;\r
-\r
- for (Index=0; Index < gST->NumberOfTableEntries; Index++) {\r
- // Check for correct GUID type\r
- if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {\r
- UINTN i;\r
-\r
- // Get them under our control. Move from depending on 32bit reg(sys_flags) and SWI\r
- // to 64 bit addr and WFE\r
- ArmProcessorTable = (ARM_PROCESSOR_TABLE *)gST->ConfigurationTable[Index].VendorTable;\r
- ArmCoreInfoTable = ArmProcessorTable->ArmCpus;\r
-\r
- for (i = 0; i < ArmProcessorTable->NumberOfEntries; i++ ) {\r
- // This goes into the SYSFLAGS register for the VE platform. We only have one 32bit reg to use\r
- MmioWrite32(ArmCoreInfoTable[i].MailboxSetAddress, (UINTN)PenBase);\r
-\r
- // So FDT can set the mailboxes correctly with the parser. These are 64bit Memory locations.\r
- ArmCoreInfoTable[i].MailboxSetAddress = (UINTN)MailBoxBase + i*sizeof(MailBoxBase);\r
-\r
- // Clear the mailboxes for the respective cores\r
- *((UINTN*)(ArmCoreInfoTable[i].MailboxSetAddress)) = 0x0;\r
- }\r
- }\r
- }\r
- // Flush caches to make sure our pen gets to mem before we free the cores.\r
- ArmCleanDataCache();\r
- }\r
-\r
- // By setting address=0 we leave the memory allocation to the function\r
- Status = PrepareFdt (Arguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);\r
- if (EFI_ERROR(Status)) {\r
- Print(L"ERROR: Can not load Linux kernel with Device Tree. Status=0x%X\n", Status);\r
- goto EXIT_FREE_FDT;\r
- }\r
-\r
- return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize);\r
-\r
-EXIT_FREE_FDT:\r
- if (!EFI_ERROR (PenBaseStatus)) {\r
- gBS->FreePages (PenBase, EFI_SIZE_TO_PAGES (PenSize));\r
- }\r
-\r
- gBS->FreePages (FdtBlobBase, EFI_SIZE_TO_PAGES (FdtBlobSize));\r
-\r
-EXIT_FREE_INITRD:\r
- if (InitrdDevicePath) {\r
- gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));\r
- }\r
-\r
-EXIT_FREE_LINUX:\r
- gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-//\r
-// Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
-//\r
-// This program and the accompanying materials\r
-// are licensed and made available under the terms and conditions of the BSD License\r
-// which accompanies this distribution. The full text of the license may be found at\r
-// http://opensource.org/licenses/bsd-license.php\r
-//\r
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-//\r
-//\r
-\r
-\r
-/* Secondary core pens for AArch64 Linux booting.\r
-\r
- This code it placed in Linux kernel memory and marked reserved. UEFI ensures\r
- that the secondary cores get to this pen and the kernel can then start the\r
- cores from here.\r
- NOTE: This code must be self-contained.\r
-*/\r
-\r
-#include <Library/ArmLib.h>\r
-\r
-.text\r
-.align 3\r
-\r
-GCC_ASM_EXPORT(SecondariesPenStart)\r
-ASM_GLOBAL SecondariesPenEnd\r
-\r
-ASM_PFX(SecondariesPenStart):\r
- // Registers x0-x3 are reserved for future use and should be set to zero.\r
- mov x0, xzr\r
- mov x1, xzr\r
- mov x2, xzr\r
- mov x3, xzr\r
-\r
- // Get core position. Taken from ArmPlatformGetCorePosition().\r
- // Assumes max 4 cores per cluster.\r
- mrs x4, mpidr_el1 // Get MPCore register.\r
- and x5, x4, #ARM_CORE_MASK // Get core number.\r
- and x4, x4, #ARM_CLUSTER_MASK // Get cluster number.\r
- add x4, x5, x4, LSR #6 // Add scaled cluster number to core number.\r
- lsl x4, x4, 3 // Get mailbox offset for this core.\r
- ldr x5, AsmMailboxbase // Get mailbox addr relative to pc (36 bytes ahead).\r
- add x4, x4, x5 // Add core mailbox offset to base of mailbox.\r
-1: ldr x5, [x4] // Load value from mailbox.\r
- cmp xzr, x5 // Has the mailbox been set?\r
- b.ne 2f // If so break out of loop.\r
- wfe // If not, wait a bit.\r
- b 1b // Wait over, check if mailbox set again.\r
-2: br x5 // Jump to mailbox value.\r
-\r
-.align 3 // Make sure the variable below is 8 byte aligned.\r
- .global AsmMailboxbase\r
-AsmMailboxbase: .xword 0xdeaddeadbeefbeef\r
-\r
-SecondariesPenEnd:\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-#include "BdsLinuxLoader.h"\r
-\r
-// Point to the current ATAG\r
-STATIC LINUX_ATAG *mLinuxKernelCurrentAtag;\r
-\r
-STATIC\r
-VOID\r
-SetupCoreTag (\r
- IN UINT32 PageSize\r
- )\r
-{\r
- mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_CORE);\r
- mLinuxKernelCurrentAtag->header.type = ATAG_CORE;\r
-\r
- mLinuxKernelCurrentAtag->body.core_tag.flags = 1; /* ensure read-only */\r
- mLinuxKernelCurrentAtag->body.core_tag.pagesize = PageSize; /* systems PageSize (4k) */\r
- mLinuxKernelCurrentAtag->body.core_tag.rootdev = 0; /* zero root device (typically overridden from kernel command line )*/\r
-\r
- // move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
-}\r
-\r
-STATIC\r
-VOID\r
-SetupMemTag (\r
- IN UINTN StartAddress,\r
- IN UINT32 Size\r
- )\r
-{\r
- mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_MEM);\r
- mLinuxKernelCurrentAtag->header.type = ATAG_MEM;\r
-\r
- mLinuxKernelCurrentAtag->body.mem_tag.start = StartAddress; /* Start of memory chunk for AtagMem */\r
- mLinuxKernelCurrentAtag->body.mem_tag.size = Size; /* Size of memory chunk for AtagMem */\r
-\r
- // move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
-}\r
-\r
-STATIC\r
-VOID\r
-SetupCmdlineTag (\r
- IN CONST CHAR8 *CmdLine\r
- )\r
-{\r
- UINT32 LineLength;\r
-\r
- // Increment the line length by 1 to account for the null string terminator character\r
- LineLength = AsciiStrLen(CmdLine) + 1;\r
-\r
- /* Check for NULL strings.\r
- * Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer.\r
- * Remember, you have at least one null string terminator character.\r
- */\r
- if(LineLength > 1) {\r
- mLinuxKernelCurrentAtag->header.size = ((UINT32)sizeof(LINUX_ATAG_HEADER) + LineLength + (UINT32)3) >> 2;\r
- mLinuxKernelCurrentAtag->header.type = ATAG_CMDLINE;\r
-\r
- /* place CommandLine into tag */\r
- AsciiStrCpy(mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, CmdLine);\r
-\r
- // move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
- }\r
-}\r
-\r
-STATIC\r
-VOID\r
-SetupInitrdTag (\r
- IN UINT32 InitrdImage,\r
- IN UINT32 InitrdImageSize\r
- )\r
-{\r
- mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_INITRD2);\r
- mLinuxKernelCurrentAtag->header.type = ATAG_INITRD2;\r
-\r
- mLinuxKernelCurrentAtag->body.initrd2_tag.start = InitrdImage;\r
- mLinuxKernelCurrentAtag->body.initrd2_tag.size = InitrdImageSize;\r
-\r
- // Move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
-}\r
-STATIC\r
-VOID\r
-SetupEndTag (\r
- VOID\r
- )\r
-{\r
- // Empty tag ends list; this has zero length and no body\r
- mLinuxKernelCurrentAtag->header.type = ATAG_NONE;\r
- mLinuxKernelCurrentAtag->header.size = 0;\r
-\r
- /* We can not calculate the next address by using the standard macro:\r
- * Params = next_tag_address(Params);\r
- * because it relies on the header.size, which here it is 0 (zero).\r
- * The easiest way is to add the sizeof(mLinuxKernelCurrentAtag->header).\r
- */\r
- mLinuxKernelCurrentAtag = (LINUX_ATAG*)((UINT32)mLinuxKernelCurrentAtag + sizeof(mLinuxKernelCurrentAtag->header));\r
-}\r
-\r
-EFI_STATUS\r
-PrepareAtagList (\r
- IN CONST CHAR8* CommandLineString,\r
- IN EFI_PHYSICAL_ADDRESS InitrdImage,\r
- IN UINTN InitrdImageSize,\r
- OUT EFI_PHYSICAL_ADDRESS *AtagBase,\r
- OUT UINT32 *AtagSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *ResourceLink;\r
- LIST_ENTRY ResourceList;\r
- EFI_PHYSICAL_ADDRESS AtagStartAddress;\r
- BDS_SYSTEM_MEMORY_RESOURCE *Resource;\r
-\r
- AtagStartAddress = LINUX_ATAG_MAX_OFFSET;\r
- Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_WARN, "Warning: Failed to allocate Atag at 0x%lX (%r). The Atag will be allocated somewhere else in System Memory.\n", AtagStartAddress, Status));\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);\r
- ASSERT_EFI_ERROR(Status);\r
- }\r
-\r
- // Ready to setup the atag list\r
- mLinuxKernelCurrentAtag = (LINUX_ATAG*)(UINTN)AtagStartAddress;\r
-\r
- // Standard core tag 4k PageSize\r
- SetupCoreTag( (UINT32)SIZE_4KB );\r
-\r
- // Physical memory setup\r
- GetSystemMemoryResources (&ResourceList);\r
- ResourceLink = ResourceList.ForwardLink;\r
- while (ResourceLink != NULL && ResourceLink != &ResourceList) {\r
- Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceLink;\r
- DEBUG((EFI_D_INFO,"- [0x%08X,0x%08X]\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->PhysicalStart+(UINT32)Resource->ResourceLength));\r
- SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength );\r
- ResourceLink = ResourceLink->ForwardLink;\r
- }\r
-\r
- // CommandLine setting root device\r
- if (CommandLineString) {\r
- SetupCmdlineTag (CommandLineString);\r
- }\r
-\r
- if (InitrdImageSize > 0 && InitrdImage != 0) {\r
- SetupInitrdTag ((UINT32)InitrdImage, (UINT32)InitrdImageSize);\r
- }\r
-\r
- // End of tags\r
- SetupEndTag();\r
-\r
- // Calculate atag list size\r
- *AtagBase = AtagStartAddress;\r
- *AtagSize = (UINT32)mLinuxKernelCurrentAtag - (UINT32)AtagStartAddress + 1;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include <Guid/Fdt.h>\r
-#include <libfdt.h>\r
-\r
-#include "BdsInternal.h"\r
-#include "BdsLinuxLoader.h"\r
-\r
-#define ALIGN32_BELOW(addr) ALIGN_POINTER(addr - 32,32)\r
-\r
-#define IS_ADDRESS_IN_REGION(RegionStart, RegionSize, Address) \\r
- (((UINTN)(RegionStart) <= (UINTN)(Address)) && ((UINTN)(Address) <= ((UINTN)(RegionStart) + (UINTN)(RegionSize))))\r
-\r
-STATIC\r
-EFI_STATUS\r
-PreparePlatformHardware (\r
- VOID\r
- )\r
-{\r
- //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.\r
-\r
- // Clean before Disable else the Stack gets corrupted with old data.\r
- ArmCleanDataCache ();\r
- ArmDisableDataCache ();\r
- // Invalidate all the entries that might have snuck in.\r
- ArmInvalidateDataCache ();\r
-\r
- // Invalidate and disable the Instruction cache\r
- ArmDisableInstructionCache ();\r
- ArmInvalidateInstructionCache ();\r
-\r
- // Turn off MMU\r
- ArmDisableMmu();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-StartLinux (\r
- IN EFI_PHYSICAL_ADDRESS LinuxImage,\r
- IN UINTN LinuxImageSize,\r
- IN EFI_PHYSICAL_ADDRESS KernelParamsAddress,\r
- IN UINTN KernelParamsSize,\r
- IN UINT32 MachineType\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LINUX_KERNEL LinuxKernel;\r
-\r
- // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on\r
- // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.\r
- Status = ShutdownUefiBootServices ();\r
- if(EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status));\r
- goto Exit;\r
- }\r
-\r
- // Move the kernel parameters to any address inside the first 1MB.\r
- // This is necessary because the ARM Linux kernel requires\r
- // the FTD / ATAG List to reside entirely inside the first 1MB of\r
- // physical memory.\r
- //Note: There is no requirement on the alignment\r
- if (MachineType != ARM_FDT_MACHINE_TYPE) {\r
- if (((UINTN)KernelParamsAddress > LINUX_ATAG_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxAtagMaxOffset))) {\r
- KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_ATAG_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);\r
- }\r
- } else {\r
- if (((UINTN)KernelParamsAddress > LINUX_FDT_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxFdtMaxOffset))) {\r
- KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_FDT_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);\r
- }\r
- }\r
-\r
- if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) {\r
- //Note: There is no requirement on the alignment\r
- LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize);\r
- } else {\r
- LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage;\r
- }\r
-\r
- // Check if the Linux Image is a uImage\r
- if (*(UINT32*)LinuxKernel == LINUX_UIMAGE_SIGNATURE) {\r
- // Assume the Image Entry Point is just after the uImage header (64-byte size)\r
- LinuxKernel = (LINUX_KERNEL)((UINTN)LinuxKernel + 64);\r
- LinuxImageSize -= 64;\r
- }\r
-\r
- // Check there is no overlapping between kernel and its parameters\r
- // We can only assert because it is too late to fallback to UEFI (ExitBootServices has been called).\r
- ASSERT (!IS_ADDRESS_IN_REGION(LinuxKernel, LinuxImageSize, KernelParamsAddress) &&\r
- !IS_ADDRESS_IN_REGION(LinuxKernel, LinuxImageSize, KernelParamsAddress + KernelParamsSize));\r
-\r
- //\r
- // Switch off interrupts, caches, mmu, etc\r
- //\r
- Status = PreparePlatformHardware ();\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- // Register and print out performance information\r
- PERF_END (NULL, "BDS", NULL, 0);\r
- if (PerformanceMeasurementEnabled ()) {\r
- PrintPerformance ();\r
- }\r
-\r
- //\r
- // Start the Linux Kernel\r
- //\r
-\r
- // Outside BootServices, so can't use Print();\r
- DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));\r
-\r
- // Jump to kernel with register set\r
- LinuxKernel ((UINTN)0, MachineType, (UINTN)KernelParamsAddress);\r
-\r
- // Kernel should never exit\r
- // After Life services are not provided\r
- ASSERT(FALSE);\r
-\r
-Exit:\r
- // Only be here if we fail to start Linux\r
- Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status);\r
-\r
- // Free Runtimee Memory (kernel and FDT)\r
- return Status;\r
-}\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param LinuxKernel Device Path to the Linux Kernel\r
- @param Parameters Linux kernel arguments\r
- @param Fdt Device Path to the Flat Device Tree\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxAtag (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* CommandLineArguments\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 LinuxImageSize;\r
- UINT32 InitrdImageBaseSize = 0;\r
- UINT32 InitrdImageSize = 0;\r
- UINT32 AtagSize;\r
- EFI_PHYSICAL_ADDRESS AtagBase;\r
- EFI_PHYSICAL_ADDRESS LinuxImage;\r
- EFI_PHYSICAL_ADDRESS InitrdImageBase = 0;\r
- EFI_PHYSICAL_ADDRESS InitrdImage = 0;\r
-\r
- PERF_START (NULL, "BDS", NULL, 0);\r
-\r
- // Load the Linux kernel from a device path\r
- LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find Linux kernel.\n");\r
- return Status;\r
- }\r
-\r
- if (InitrdDevicePath) {\r
- // Load the initrd near to the Linux kernel\r
- InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);\r
- }\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find initrd image.\n");\r
- goto EXIT_FREE_LINUX;\r
- }\r
-\r
- // Check if the initrd is a uInitrd\r
- if (*(UINT32*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) {\r
- // Skip the 64-byte image header\r
- InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);\r
- InitrdImageSize = InitrdImageBaseSize - 64;\r
- } else {\r
- InitrdImage = InitrdImageBase;\r
- InitrdImageSize = InitrdImageBaseSize;\r
- }\r
- }\r
-\r
- //\r
- // Setup the Linux Kernel Parameters\r
- //\r
-\r
- // By setting address=0 we leave the memory allocation to the function\r
- Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);\r
- if (EFI_ERROR(Status)) {\r
- Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);\r
- goto EXIT_FREE_INITRD;\r
- }\r
-\r
- return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, PcdGet32(PcdArmMachineType));\r
-\r
-EXIT_FREE_INITRD:\r
- if (InitrdDevicePath) {\r
- gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));\r
- }\r
-\r
-EXIT_FREE_LINUX:\r
- gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param LinuxKernelDevicePath Device Path to the Linux Kernel\r
- @param InitrdDevicePath Device Path to the Initrd\r
- @param CommandLineArguments Linux command line\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxFdt (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* CommandLineArguments\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 LinuxImageSize;\r
- UINT32 InitrdImageBaseSize = 0;\r
- UINT32 InitrdImageSize = 0;\r
- VOID *InstalledFdtBase;\r
- UINT32 FdtBlobSize;\r
- EFI_PHYSICAL_ADDRESS FdtBlobBase;\r
- EFI_PHYSICAL_ADDRESS LinuxImage;\r
- EFI_PHYSICAL_ADDRESS InitrdImageBase = 0;\r
- EFI_PHYSICAL_ADDRESS InitrdImage = 0;\r
-\r
- PERF_START (NULL, "BDS", NULL, 0);\r
-\r
- // Load the Linux kernel from a device path\r
- LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find Linux kernel.\n");\r
- return Status;\r
- }\r
-\r
- if (InitrdDevicePath) {\r
- InitrdImageBase = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImageBase, &InitrdImageBaseSize);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);\r
- }\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find initrd image.\n");\r
- goto EXIT_FREE_LINUX;\r
- }\r
-\r
- // Check if the initrd is a uInitrd\r
- if (*(UINT32*)((UINTN)InitrdImageBase) == LINUX_UIMAGE_SIGNATURE) {\r
- // Skip the 64-byte image header\r
- InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImageBase + 64);\r
- InitrdImageSize = InitrdImageBaseSize - 64;\r
- } else {\r
- InitrdImage = InitrdImageBase;\r
- InitrdImageSize = InitrdImageBaseSize;\r
- }\r
- }\r
-\r
- //\r
- // Get the FDT from the Configuration Table.\r
- // The FDT will be reloaded in PrepareFdt() to a more appropriate\r
- // location for the Linux Kernel.\r
- //\r
- Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &InstalledFdtBase);\r
- if (EFI_ERROR (Status)) {\r
- Print (L"ERROR: Did not get the Device Tree blob (%r).\n", Status);\r
- goto EXIT_FREE_INITRD;\r
- }\r
- FdtBlobBase = (EFI_PHYSICAL_ADDRESS)(UINTN)InstalledFdtBase;\r
- FdtBlobSize = fdt_totalsize (InstalledFdtBase);\r
-\r
- // Update the Fdt with the Initrd information. The FDT will increase in size.\r
- // By setting address=0 we leave the memory allocation to the function\r
- Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);\r
- if (EFI_ERROR(Status)) {\r
- Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);\r
- goto EXIT_FREE_FDT;\r
- }\r
-\r
- return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE);\r
-\r
-EXIT_FREE_FDT:\r
- gBS->FreePages (FdtBlobBase, EFI_SIZE_TO_PAGES (FdtBlobSize));\r
-\r
-EXIT_FREE_INITRD:\r
- if (InitrdDevicePath) {\r
- gBS->FreePages (InitrdImageBase, EFI_SIZE_TO_PAGES (InitrdImageBaseSize));\r
- }\r
-\r
-EXIT_FREE_LINUX:\r
- gBS->FreePages (LinuxImage, EFI_SIZE_TO_PAGES (LinuxImageSize));\r
-\r
- return Status;\r
-}\r
-\r
/** @file\r
*\r
-* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
*\r
* This program and the accompanying materials\r
* are licensed and made available under the terms and conditions of the BSD License\r
\r
#include "BdsInternal.h"\r
\r
-#include <Library/HobLib.h>\r
-#include <Library/TimerLib.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/SerialPortLib.h>\r
-\r
-STATIC CHAR8 *mTokenList[] = {\r
- /*"SEC",*/\r
- "PEI",\r
- "DXE",\r
- "BDS",\r
- NULL\r
-};\r
-\r
EFI_STATUS\r
ShutdownUefiBootServices (\r
VOID\r
return EFI_SUCCESS;\r
}\r
\r
-STATIC\r
-EFI_STATUS\r
-InsertSystemMemoryResources (\r
- LIST_ENTRY *ResourceList,\r
- EFI_HOB_RESOURCE_DESCRIPTOR *ResHob\r
- )\r
-{\r
- BDS_SYSTEM_MEMORY_RESOURCE *NewResource;\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *NextLink;\r
- LIST_ENTRY AttachedResources;\r
- BDS_SYSTEM_MEMORY_RESOURCE *Resource;\r
- EFI_PHYSICAL_ADDRESS NewResourceEnd;\r
-\r
- if (IsListEmpty (ResourceList)) {\r
- NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));\r
- NewResource->PhysicalStart = ResHob->PhysicalStart;\r
- NewResource->ResourceLength = ResHob->ResourceLength;\r
- InsertTailList (ResourceList, &NewResource->Link);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- InitializeListHead (&AttachedResources);\r
-\r
- Link = ResourceList->ForwardLink;\r
- ASSERT (Link != NULL);\r
- while (Link != ResourceList) {\r
- Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;\r
-\r
- // Sanity Check. The resources should not overlapped.\r
- ASSERT(!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))));\r
- ASSERT(!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) &&\r
- ((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength))));\r
-\r
- // The new resource is attached after this resource descriptor\r
- if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) {\r
- Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;\r
-\r
- NextLink = RemoveEntryList (&Resource->Link);\r
- InsertTailList (&AttachedResources, &Resource->Link);\r
- Link = NextLink;\r
- }\r
- // The new resource is attached before this resource descriptor\r
- else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) {\r
- Resource->PhysicalStart = ResHob->PhysicalStart;\r
- Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;\r
-\r
- NextLink = RemoveEntryList (&Resource->Link);\r
- InsertTailList (&AttachedResources, &Resource->Link);\r
- Link = NextLink;\r
- } else {\r
- Link = Link->ForwardLink;\r
- }\r
- }\r
-\r
- if (!IsListEmpty (&AttachedResources)) {\r
- // See if we can merge the attached resource with other resources\r
-\r
- NewResource = (BDS_SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);\r
- Link = RemoveEntryList (&NewResource->Link);\r
- while (!IsListEmpty (&AttachedResources)) {\r
- // Merge resources\r
- Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;\r
-\r
- // Ensure they overlap each other\r
- ASSERT(\r
- ((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) ||\r
- (((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength)))\r
- );\r
-\r
- NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength);\r
- NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart);\r
- NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart;\r
-\r
- Link = RemoveEntryList (Link);\r
- }\r
- } else {\r
- // None of the Resource of the list is attached to this ResHob. Create a new entry for it\r
- NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));\r
- NewResource->PhysicalStart = ResHob->PhysicalStart;\r
- NewResource->ResourceLength = ResHob->ResourceLength;\r
- }\r
- InsertTailList (ResourceList, &NewResource->Link);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GetSystemMemoryResources (\r
- IN LIST_ENTRY *ResourceList\r
- )\r
-{\r
- EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;\r
-\r
- InitializeListHead (ResourceList);\r
-\r
- // Find the first System Memory Resource Descriptor\r
- ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
- while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) {\r
- ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
- }\r
-\r
- // Did not find any\r
- if (ResHob == NULL) {\r
- return EFI_NOT_FOUND;\r
- } else {\r
- InsertSystemMemoryResources (ResourceList, ResHob);\r
- }\r
-\r
- ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
- while (ResHob != NULL) {\r
- if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
- InsertSystemMemoryResources (ResourceList, ResHob);\r
- }\r
- ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-PrintPerformance (\r
- VOID\r
- )\r
-{\r
- UINTN Key;\r
- CONST VOID *Handle;\r
- CONST CHAR8 *Token, *Module;\r
- UINT64 Start, Stop, TimeStamp;\r
- UINT64 Delta, TicksPerSecond, Milliseconds;\r
- UINTN Index;\r
- CHAR8 Buffer[100];\r
- UINTN CharCount;\r
- BOOLEAN CountUp;\r
-\r
- TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop);\r
- if (Start < Stop) {\r
- CountUp = TRUE;\r
- } else {\r
- CountUp = FALSE;\r
- }\r
-\r
- TimeStamp = 0;\r
- Key = 0;\r
- do {\r
- Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
- if (Key != 0) {\r
- for (Index = 0; mTokenList[Index] != NULL; Index++) {\r
- if (AsciiStriCmp (mTokenList[Index], Token) == 0) {\r
- Delta = CountUp?(Stop - Start):(Start - Stop);\r
- TimeStamp += Delta;\r
- Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);\r
- CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"%6a %6ld ms\n", Token, Milliseconds);\r
- SerialPortWrite ((UINT8 *) Buffer, CharCount);\r
- break;\r
- }\r
- }\r
- }\r
- } while (Key != 0);\r
-\r
- CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));\r
- SerialPortWrite ((UINT8 *) Buffer, CharCount);\r
-}\r
-\r
EFI_STATUS\r
GetGlobalEnvironmentVariable (\r
IN CONST CHAR16* VariableName,\r
#include <Library/DebugLib.h>\r
#include <Library/BdsLib.h>\r
#include <Library/PcdLib.h>\r
-#include <Library/PerformanceLib.h>\r
#include <Library/PrintLib.h>\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
\r
-#include <Guid/ArmMpCoreInfo.h>\r
#include <Guid/GlobalVariable.h>\r
#include <Guid/FileInfo.h>\r
\r
UINT64 LastReportedNbOfBytes;\r
} BDS_TFTP_CONTEXT;\r
\r
-// BdsHelper.c\r
-EFI_STATUS\r
-GetSystemMemoryResources (\r
- LIST_ENTRY *ResourceList\r
- );\r
-\r
-VOID\r
-PrintPerformance (\r
- VOID\r
- );\r
-\r
EFI_STATUS\r
BdsLoadImage (\r
IN EFI_DEVICE_PATH *DevicePath,\r
BdsAppLoader.c\r
BdsHelper.c\r
BdsLoadOption.c\r
- BdsLinuxFdt.c\r
-\r
-[Sources.ARM]\r
- Arm/BdsLinuxLoader.c\r
- Arm/BdsLinuxAtag.c\r
-\r
-[Sources.AARCH64]\r
- AArch64/BdsLinuxLoader.c\r
- AArch64/BdsLinuxLoaderHelper.S\r
\r
[Packages]\r
EmbeddedPkg/EmbeddedPkg.dec\r
\r
[LibraryClasses]\r
ArmLib\r
- ArmSmcLib\r
BaseLib\r
DebugLib\r
DevicePathLib\r
HobLib\r
PcdLib\r
- PerformanceLib\r
- SerialPortLib\r
- FdtLib\r
- TimerLib\r
NetLib\r
\r
-[LibraryClasses.AARCH64]\r
- ArmGicLib\r
-\r
[Guids]\r
gEfiFileInfoGuid\r
- gArmMpCoreInfoGuid\r
gArmGlobalVariableGuid\r
- gFdtTableGuid\r
\r
[Protocols]\r
gEfiBdsArchProtocolGuid\r
gEfiMtftp4ServiceBindingProtocolGuid\r
gEfiMtftp4ProtocolGuid\r
\r
-[FeaturePcd]\r
- gArmTokenSpaceGuid.PcdArmLinuxSpinTable\r
-\r
-[Pcd]\r
- gArmTokenSpaceGuid.PcdSystemMemoryBase\r
- gArmTokenSpaceGuid.PcdSystemMemorySize\r
-\r
[FixedPcd]\r
- gArmTokenSpaceGuid.PcdArmMachineType\r
- gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset\r
- gArmTokenSpaceGuid.PcdArmLinuxFdtAlignment\r
- gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset\r
-\r
gArmTokenSpaceGuid.PcdMaxTftpFileSize\r
\r
-[FixedPcd.ARM]\r
- gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset\r
-\r
-[Pcd.AARCH64]\r
- gArmTokenSpaceGuid.PcdGicDistributorBase\r
- gArmTokenSpaceGuid.PcdGicSgiIntId\r
-\r
[Depex]\r
TRUE\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include <Library/ArmSmcLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <libfdt.h>\r
-\r
-#include "BdsInternal.h"\r
-#include "BdsLinuxLoader.h"\r
-\r
-#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))\r
-#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))\r
-#define GET_CELL(p) (p += 4, *((const UINT32 *)(p-4)))\r
-\r
-STATIC\r
-UINTN\r
-cpu_to_fdtn (UINTN x) {\r
- if (sizeof (UINTN) == sizeof (UINT32)) {\r
- return cpu_to_fdt32 (x);\r
- } else {\r
- return cpu_to_fdt64 (x);\r
- }\r
-}\r
-\r
-typedef struct {\r
- UINTN Base;\r
- UINTN Size;\r
-} FdtRegion;\r
-\r
-\r
-STATIC\r
-UINTN\r
-IsPrintableString (\r
- IN CONST VOID* data,\r
- IN UINTN len\r
- )\r
-{\r
- CONST CHAR8 *s = data;\r
- CONST CHAR8 *ss;\r
-\r
- // Zero length is not\r
- if (len == 0) {\r
- return 0;\r
- }\r
-\r
- // Must terminate with zero\r
- if (s[len - 1] != '\0') {\r
- return 0;\r
- }\r
-\r
- ss = s;\r
- while (*s/* && isprint(*s)*/) {\r
- s++;\r
- }\r
-\r
- // Not zero, or not done yet\r
- if (*s != '\0' || (s + 1 - ss) < len) {\r
- return 0;\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-STATIC\r
-VOID\r
-PrintData (\r
- IN CONST CHAR8* data,\r
- IN UINTN len\r
- )\r
-{\r
- UINTN i;\r
- CONST CHAR8 *p = data;\r
-\r
- // No data, don't print\r
- if (len == 0)\r
- return;\r
-\r
- if (IsPrintableString (data, len)) {\r
- Print(L" = \"%a\"", (const char *)data);\r
- } else if ((len % 4) == 0) {\r
- Print(L" = <");\r
- for (i = 0; i < len; i += 4) {\r
- Print(L"0x%08x%a", fdt32_to_cpu(GET_CELL(p)),i < (len - 4) ? " " : "");\r
- }\r
- Print(L">");\r
- } else {\r
- Print(L" = [");\r
- for (i = 0; i < len; i++)\r
- Print(L"%02x%a", *p++, i < len - 1 ? " " : "");\r
- Print(L"]");\r
- }\r
-}\r
-\r
-VOID\r
-DebugDumpFdt (\r
- IN VOID* FdtBlob\r
- )\r
-{\r
- struct fdt_header *bph;\r
- UINT32 off_dt;\r
- UINT32 off_str;\r
- CONST CHAR8* p_struct;\r
- CONST CHAR8* p_strings;\r
- CONST CHAR8* p;\r
- CONST CHAR8* s;\r
- CONST CHAR8* t;\r
- UINT32 tag;\r
- UINTN sz;\r
- UINTN depth;\r
- UINTN shift;\r
- UINT32 version;\r
-\r
- {\r
- // Can 'memreserve' be printed by below code?\r
- INTN num = fdt_num_mem_rsv(FdtBlob);\r
- INTN i, err;\r
- UINT64 addr = 0,size = 0;\r
-\r
- for (i = 0; i < num; i++) {\r
- err = fdt_get_mem_rsv(FdtBlob, i, &addr, &size);\r
- if (err) {\r
- DEBUG((EFI_D_ERROR, "Error (%d) : Cannot get memreserve section (%d)\n", err, i));\r
- }\r
- else {\r
- Print(L"/memreserve/ \t0x%lx \t0x%lx;\n",addr,size);\r
- }\r
- }\r
- }\r
-\r
- depth = 0;\r
- shift = 4;\r
-\r
- bph = FdtBlob;\r
- off_dt = fdt32_to_cpu(bph->off_dt_struct);\r
- off_str = fdt32_to_cpu(bph->off_dt_strings);\r
- p_struct = (CONST CHAR8*)FdtBlob + off_dt;\r
- p_strings = (CONST CHAR8*)FdtBlob + off_str;\r
- version = fdt32_to_cpu(bph->version);\r
-\r
- p = p_struct;\r
- while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {\r
- if (tag == FDT_BEGIN_NODE) {\r
- s = p;\r
- p = PALIGN(p + AsciiStrLen (s) + 1, 4);\r
-\r
- if (*s == '\0')\r
- s = "/";\r
-\r
- Print(L"%*s%a {\n", depth * shift, L" ", s);\r
-\r
- depth++;\r
- continue;\r
- }\r
-\r
- if (tag == FDT_END_NODE) {\r
- depth--;\r
-\r
- Print(L"%*s};\n", depth * shift, L" ");\r
- continue;\r
- }\r
-\r
- if (tag == FDT_NOP) {\r
- Print(L"%*s// [NOP]\n", depth * shift, L" ");\r
- continue;\r
- }\r
-\r
- if (tag != FDT_PROP) {\r
- Print(L"%*s ** Unknown tag 0x%08x\n", depth * shift, L" ", tag);\r
- break;\r
- }\r
- sz = fdt32_to_cpu(GET_CELL(p));\r
- s = p_strings + fdt32_to_cpu(GET_CELL(p));\r
- if (version < 16 && sz >= 8)\r
- p = PALIGN(p, 8);\r
- t = p;\r
-\r
- p = PALIGN(p + sz, 4);\r
-\r
- Print(L"%*s%a", depth * shift, L" ", s);\r
- PrintData(t, sz);\r
- Print(L";\n");\r
- }\r
-}\r
-\r
-STATIC\r
-BOOLEAN\r
-IsLinuxReservedRegion (\r
- IN EFI_MEMORY_TYPE MemoryType\r
- )\r
-{\r
- switch(MemoryType) {\r
- case EfiRuntimeServicesCode:\r
- case EfiRuntimeServicesData:\r
- case EfiUnusableMemory:\r
- case EfiACPIReclaimMemory:\r
- case EfiACPIMemoryNVS:\r
- case EfiReservedMemoryType:\r
- return TRUE;\r
- default:\r
- return FALSE;\r
- }\r
-}\r
-\r
-/**\r
-** Relocate the FDT blob to a more appropriate location for the Linux kernel.\r
-** This function will allocate memory for the relocated FDT blob.\r
-**\r
-** @retval EFI_SUCCESS on success.\r
-** @retval EFI_OUT_OF_RESOURCES or EFI_INVALID_PARAMETER on failure.\r
-*/\r
-STATIC\r
-EFI_STATUS\r
-RelocateFdt (\r
- EFI_PHYSICAL_ADDRESS OriginalFdt,\r
- UINTN OriginalFdtSize,\r
- EFI_PHYSICAL_ADDRESS *RelocatedFdt,\r
- UINTN *RelocatedFdtSize,\r
- EFI_PHYSICAL_ADDRESS *RelocatedFdtAlloc\r
- )\r
-{\r
- EFI_STATUS Status;\r
- INTN Error;\r
- UINT64 FdtAlignment;\r
-\r
- *RelocatedFdtSize = OriginalFdtSize + FDT_ADDITIONAL_ENTRIES_SIZE;\r
-\r
- // If FDT load address needs to be aligned, allocate more space.\r
- FdtAlignment = PcdGet32 (PcdArmLinuxFdtAlignment);\r
- if (FdtAlignment != 0) {\r
- *RelocatedFdtSize += FdtAlignment;\r
- }\r
-\r
- // Try below a watermark address.\r
- Status = EFI_NOT_FOUND;\r
- if (PcdGet32 (PcdArmLinuxFdtMaxOffset) != 0) {\r
- *RelocatedFdt = LINUX_FDT_MAX_OFFSET;\r
- Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,\r
- EFI_SIZE_TO_PAGES (*RelocatedFdtSize), RelocatedFdt);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_WARN, "Warning: Failed to load FDT below address 0x%lX (%r). Will try again at a random address anywhere.\n", *RelocatedFdt, Status));\r
- }\r
- }\r
-\r
- // Try anywhere there is available space.\r
- if (EFI_ERROR (Status)) {\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData,\r
- EFI_SIZE_TO_PAGES (*RelocatedFdtSize), RelocatedFdt);\r
- if (EFI_ERROR (Status)) {\r
- ASSERT_EFI_ERROR (Status);\r
- return EFI_OUT_OF_RESOURCES;\r
- } else {\r
- DEBUG ((EFI_D_WARN, "WARNING: Loaded FDT at random address 0x%lX.\nWARNING: There is a risk of accidental overwriting by other code/data.\n", *RelocatedFdt));\r
- }\r
- }\r
-\r
- *RelocatedFdtAlloc = *RelocatedFdt;\r
- if (FdtAlignment != 0) {\r
- *RelocatedFdt = ALIGN (*RelocatedFdt, FdtAlignment);\r
- }\r
-\r
- // Load the Original FDT tree into the new region\r
- Error = fdt_open_into ((VOID*)(UINTN) OriginalFdt,\r
- (VOID*)(UINTN)(*RelocatedFdt), *RelocatedFdtSize);\r
- if (Error) {\r
- DEBUG ((EFI_D_ERROR, "fdt_open_into(): %a\n", fdt_strerror (Error)));\r
- gBS->FreePages (*RelocatedFdtAlloc, EFI_SIZE_TO_PAGES (*RelocatedFdtSize));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- DEBUG_CODE_BEGIN();\r
- //DebugDumpFdt (fdt);\r
- DEBUG_CODE_END();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-PrepareFdt (\r
- IN CONST CHAR8* CommandLineArguments,\r
- IN EFI_PHYSICAL_ADDRESS InitrdImage,\r
- IN UINTN InitrdImageSize,\r
- IN OUT EFI_PHYSICAL_ADDRESS *FdtBlobBase,\r
- IN OUT UINTN *FdtBlobSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PHYSICAL_ADDRESS NewFdtBlobBase;\r
- EFI_PHYSICAL_ADDRESS NewFdtBlobAllocation;\r
- UINTN NewFdtBlobSize;\r
- VOID* fdt;\r
- INTN err;\r
- INTN node;\r
- INTN cpu_node;\r
- INT32 lenp;\r
- CONST VOID* BootArg;\r
- CONST VOID* Method;\r
- EFI_PHYSICAL_ADDRESS InitrdImageStart;\r
- EFI_PHYSICAL_ADDRESS InitrdImageEnd;\r
- FdtRegion Region;\r
- UINTN Index;\r
- CHAR8 Name[10];\r
- LIST_ENTRY ResourceList;\r
- BDS_SYSTEM_MEMORY_RESOURCE *Resource;\r
- ARM_PROCESSOR_TABLE *ArmProcessorTable;\r
- ARM_CORE_INFO *ArmCoreInfoTable;\r
- UINT32 MpId;\r
- UINT32 ClusterId;\r
- UINT32 CoreId;\r
- UINT64 CpuReleaseAddr;\r
- UINTN MemoryMapSize;\r
- EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
- EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;\r
- UINTN MapKey;\r
- UINTN DescriptorSize;\r
- UINT32 DescriptorVersion;\r
- UINTN Pages;\r
- UINTN OriginalFdtSize;\r
- BOOLEAN CpusNodeExist;\r
- UINTN CoreMpId;\r
-\r
- NewFdtBlobAllocation = 0;\r
-\r
- //\r
- // Sanity checks on the original FDT blob.\r
- //\r
- err = fdt_check_header ((VOID*)(UINTN)(*FdtBlobBase));\r
- if (err != 0) {\r
- Print (L"ERROR: Device Tree header not valid (err:%d)\n", err);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- // The original FDT blob might have been loaded partially.\r
- // Check that it is not the case.\r
- OriginalFdtSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(*FdtBlobBase));\r
- if (OriginalFdtSize > *FdtBlobSize) {\r
- Print (L"ERROR: Incomplete FDT. Only %d/%d bytes have been loaded.\n",\r
- *FdtBlobSize, OriginalFdtSize);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Relocate the FDT to its final location.\r
- //\r
- Status = RelocateFdt (*FdtBlobBase, OriginalFdtSize,\r
- &NewFdtBlobBase, &NewFdtBlobSize, &NewFdtBlobAllocation);\r
- if (EFI_ERROR (Status)) {\r
- goto FAIL_RELOCATE_FDT;\r
- }\r
-\r
- fdt = (VOID*)(UINTN)NewFdtBlobBase;\r
-\r
- node = fdt_subnode_offset (fdt, 0, "chosen");\r
- if (node < 0) {\r
- // The 'chosen' node does not exist, create it\r
- node = fdt_add_subnode(fdt, 0, "chosen");\r
- if (node < 0) {\r
- DEBUG((EFI_D_ERROR,"Error on finding 'chosen' node\n"));\r
- Status = EFI_INVALID_PARAMETER;\r
- goto FAIL_COMPLETE_FDT;\r
- }\r
- }\r
-\r
- DEBUG_CODE_BEGIN();\r
- BootArg = fdt_getprop(fdt, node, "bootargs", &lenp);\r
- if (BootArg != NULL) {\r
- DEBUG((EFI_D_ERROR,"BootArg: %a\n",BootArg));\r
- }\r
- DEBUG_CODE_END();\r
-\r
- //\r
- // Set Linux CmdLine\r
- //\r
- if ((CommandLineArguments != NULL) && (AsciiStrLen (CommandLineArguments) > 0)) {\r
- err = fdt_setprop(fdt, node, "bootargs", CommandLineArguments, AsciiStrSize(CommandLineArguments));\r
- if (err) {\r
- DEBUG((EFI_D_ERROR,"Fail to set new 'bootarg' (err:%d)\n",err));\r
- }\r
- }\r
-\r
- //\r
- // Set Linux Initrd\r
- //\r
- if (InitrdImageSize != 0) {\r
- InitrdImageStart = cpu_to_fdt64 (InitrdImage);\r
- err = fdt_setprop(fdt, node, "linux,initrd-start", &InitrdImageStart, sizeof(EFI_PHYSICAL_ADDRESS));\r
- if (err) {\r
- DEBUG((EFI_D_ERROR,"Fail to set new 'linux,initrd-start' (err:%d)\n",err));\r
- }\r
- InitrdImageEnd = cpu_to_fdt64 (InitrdImage + InitrdImageSize);\r
- err = fdt_setprop(fdt, node, "linux,initrd-end", &InitrdImageEnd, sizeof(EFI_PHYSICAL_ADDRESS));\r
- if (err) {\r
- DEBUG((EFI_D_ERROR,"Fail to set new 'linux,initrd-start' (err:%d)\n",err));\r
- }\r
- }\r
-\r
- //\r
- // Set Physical memory setup if does not exist\r
- //\r
- node = fdt_subnode_offset(fdt, 0, "memory");\r
- if (node < 0) {\r
- // The 'memory' node does not exist, create it\r
- node = fdt_add_subnode(fdt, 0, "memory");\r
- if (node >= 0) {\r
- fdt_setprop_string(fdt, node, "name", "memory");\r
- fdt_setprop_string(fdt, node, "device_type", "memory");\r
-\r
- GetSystemMemoryResources (&ResourceList);\r
- Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceList.ForwardLink;\r
-\r
- Region.Base = cpu_to_fdtn ((UINTN)Resource->PhysicalStart);\r
- Region.Size = cpu_to_fdtn ((UINTN)Resource->ResourceLength);\r
-\r
- err = fdt_setprop(fdt, node, "reg", &Region, sizeof(Region));\r
- if (err) {\r
- DEBUG((EFI_D_ERROR,"Fail to set new 'memory region' (err:%d)\n",err));\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Add the memory regions reserved by the UEFI Firmware\r
- //\r
-\r
- // Retrieve the UEFI Memory Map\r
- MemoryMap = NULL;\r
- MemoryMapSize = 0;\r
- Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- // The UEFI specification advises to allocate more memory for the MemoryMap buffer between successive\r
- // calls to GetMemoryMap(), since allocation of the new buffer may potentially increase memory map size.\r
- Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;\r
- MemoryMap = AllocatePages (Pages);\r
- if (MemoryMap == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto FAIL_COMPLETE_FDT;\r
- }\r
- Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
- }\r
-\r
- // Go through the list and add the reserved region to the Device Tree\r
- if (!EFI_ERROR(Status)) {\r
- MemoryMapPtr = MemoryMap;\r
- for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {\r
- if (IsLinuxReservedRegion ((EFI_MEMORY_TYPE)MemoryMapPtr->Type)) {\r
- DEBUG((DEBUG_VERBOSE, "Reserved region of type %d [0x%lX, 0x%lX]\n",\r
- MemoryMapPtr->Type,\r
- (UINTN)MemoryMapPtr->PhysicalStart,\r
- (UINTN)(MemoryMapPtr->PhysicalStart + MemoryMapPtr->NumberOfPages * EFI_PAGE_SIZE)));\r
- err = fdt_add_mem_rsv(fdt, MemoryMapPtr->PhysicalStart, MemoryMapPtr->NumberOfPages * EFI_PAGE_SIZE);\r
- if (err != 0) {\r
- Print(L"Warning: Fail to add 'memreserve' (err:%d)\n", err);\r
- }\r
- }\r
- MemoryMapPtr = (EFI_MEMORY_DESCRIPTOR*)((UINTN)MemoryMapPtr + DescriptorSize);\r
- }\r
- }\r
-\r
- //\r
- // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms.\r
- //\r
- // For 'cpus' and 'cpu' device tree nodes bindings, refer to this file\r
- // in the kernel documentation:\r
- // Documentation/devicetree/bindings/arm/cpus.txt\r
- //\r
- for (Index=0; Index < gST->NumberOfTableEntries; Index++) {\r
- // Check for correct GUID type\r
- if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {\r
- MpId = ArmReadMpidr ();\r
- ClusterId = GET_CLUSTER_ID(MpId);\r
- CoreId = GET_CORE_ID(MpId);\r
-\r
- node = fdt_subnode_offset(fdt, 0, "cpus");\r
- if (node < 0) {\r
- // Create the /cpus node\r
- node = fdt_add_subnode(fdt, 0, "cpus");\r
- fdt_setprop_string(fdt, node, "name", "cpus");\r
- fdt_setprop_cell (fdt, node, "#address-cells", sizeof (UINTN) / 4);\r
- fdt_setprop_cell(fdt, node, "#size-cells", 0);\r
- CpusNodeExist = FALSE;\r
- } else {\r
- CpusNodeExist = TRUE;\r
- }\r
-\r
- // Get pointer to ARM processor table\r
- ArmProcessorTable = (ARM_PROCESSOR_TABLE *)gST->ConfigurationTable[Index].VendorTable;\r
- ArmCoreInfoTable = ArmProcessorTable->ArmCpus;\r
-\r
- for (Index = 0; Index < ArmProcessorTable->NumberOfEntries; Index++) {\r
- CoreMpId = (UINTN) GET_MPID (ArmCoreInfoTable[Index].ClusterId,\r
- ArmCoreInfoTable[Index].CoreId);\r
- AsciiSPrint (Name, 10, "cpu@%x", CoreMpId);\r
-\r
- // If the 'cpus' node did not exist then create all the 'cpu' nodes.\r
- // In case 'cpus' node is provided in the original FDT then we do not add\r
- // any 'cpu' node.\r
- if (!CpusNodeExist) {\r
- cpu_node = fdt_add_subnode (fdt, node, Name);\r
- if (cpu_node < 0) {\r
- DEBUG ((EFI_D_ERROR, "Error on creating '%s' node\n", Name));\r
- Status = EFI_INVALID_PARAMETER;\r
- goto FAIL_COMPLETE_FDT;\r
- }\r
-\r
- fdt_setprop_string (fdt, cpu_node, "device_type", "cpu");\r
-\r
- CoreMpId = cpu_to_fdtn (CoreMpId);\r
- fdt_setprop (fdt, cpu_node, "reg", &CoreMpId, sizeof (CoreMpId));\r
- } else {\r
- cpu_node = fdt_subnode_offset(fdt, node, Name);\r
- }\r
-\r
- if (cpu_node >= 0) {\r
- Method = fdt_getprop (fdt, cpu_node, "enable-method", &lenp);\r
- // We only care when 'enable-method' == 'spin-table'. If the enable-method is not defined\r
- // or defined as 'psci' then we ignore its properties.\r
- if ((Method != NULL) && (AsciiStrCmp ((CHAR8 *)Method, "spin-table") == 0)) {\r
- // There are two cases;\r
- // - UEFI firmware parked the secondary cores and/or UEFI firmware is aware of the CPU\r
- // release addresses (PcdArmLinuxSpinTable == TRUE)\r
- // - the parking of the secondary cores has been managed before starting UEFI and/or UEFI\r
- // does not anything about the CPU release addresses - in this case we do nothing\r
- if (FeaturePcdGet (PcdArmLinuxSpinTable)) {\r
- CpuReleaseAddr = cpu_to_fdt64 (ArmCoreInfoTable[Index].MailboxSetAddress);\r
- fdt_setprop (fdt, cpu_node, "cpu-release-addr", &CpuReleaseAddr, sizeof(CpuReleaseAddr));\r
-\r
- // If it is not the primary core than the cpu should be disabled\r
- if (((ArmCoreInfoTable[Index].ClusterId != ClusterId) || (ArmCoreInfoTable[Index].CoreId != CoreId))) {\r
- fdt_setprop_string(fdt, cpu_node, "status", "disabled");\r
- }\r
- }\r
- }\r
- }\r
- }\r
- break;\r
- }\r
- }\r
-\r
- DEBUG_CODE_BEGIN();\r
- //DebugDumpFdt (fdt);\r
- DEBUG_CODE_END();\r
-\r
- // If we succeeded to generate the new Device Tree then free the old Device Tree\r
- gBS->FreePages (*FdtBlobBase, EFI_SIZE_TO_PAGES (*FdtBlobSize));\r
-\r
- // Update the real size of the Device Tree\r
- fdt_pack ((VOID*)(UINTN)(NewFdtBlobBase));\r
-\r
- *FdtBlobBase = NewFdtBlobBase;\r
- *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(NewFdtBlobBase));\r
- return EFI_SUCCESS;\r
-\r
-FAIL_COMPLETE_FDT:\r
- gBS->FreePages (NewFdtBlobAllocation, EFI_SIZE_TO_PAGES (NewFdtBlobSize));\r
-\r
-FAIL_RELOCATE_FDT:\r
- *FdtBlobSize = (UINTN)fdt_totalsize ((VOID*)(UINTN)(*FdtBlobBase));\r
- // Return success even if we failed to update the FDT blob.\r
- // The original one is still valid.\r
- return EFI_SUCCESS;\r
-}\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
-*\r
-* This program and the accompanying materials\r
-* are licensed and made available under the terms and conditions of the BSD License\r
-* which accompanies this distribution. The full text of the license may be found at\r
-* http://opensource.org/licenses/bsd-license.php\r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#ifndef __BDSLINUXLOADER_H\r
-#define __BDSLINUXLOADER_H\r
-\r
-#define LINUX_UIMAGE_SIGNATURE 0x56190527\r
-#define LINUX_KERNEL_MAX_OFFSET (PcdGet64 (PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxKernelMaxOffset))\r
-#define LINUX_ATAG_MAX_OFFSET (PcdGet64 (PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset))\r
-#define LINUX_FDT_MAX_OFFSET (PcdGet64 (PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxFdtMaxOffset))\r
-\r
-// Additional size that could be used for FDT entries added by the UEFI OS Loader\r
-// Estimation based on: EDID (300bytes) + bootargs (200bytes) + initrd region (20bytes)\r
-// + system memory region (20bytes) + mp_core entries (200 bytes)\r
-#define FDT_ADDITIONAL_ENTRIES_SIZE 0x300\r
-\r
-#define ARM_FDT_MACHINE_TYPE 0xFFFFFFFF\r
-\r
-typedef VOID (*LINUX_KERNEL)(UINT32 Zero, UINT32 Arch, UINTN ParametersBase);\r
-\r
-//\r
-// ATAG Definitions\r
-//\r
-\r
-#define ATAG_MAX_SIZE 0x3000\r
-\r
-/* ATAG : list of possible tags */\r
-#define ATAG_NONE 0x00000000\r
-#define ATAG_CORE 0x54410001\r
-#define ATAG_MEM 0x54410002\r
-#define ATAG_VIDEOTEXT 0x54410003\r
-#define ATAG_RAMDISK 0x54410004\r
-#define ATAG_INITRD2 0x54420005\r
-#define ATAG_SERIAL 0x54410006\r
-#define ATAG_REVISION 0x54410007\r
-#define ATAG_VIDEOLFB 0x54410008\r
-#define ATAG_CMDLINE 0x54410009\r
-#define ATAG_ARM_MP_CORE 0x5441000A\r
-\r
-#define next_tag_address(t) ((LINUX_ATAG*)((UINT32)(t) + (((t)->header.size) << 2) ))\r
-#define tag_size(type) ((UINT32)((sizeof(LINUX_ATAG_HEADER) + sizeof(type)) >> 2))\r
-\r
-typedef struct {\r
- UINT32 size; /* length of tag in words including this header */\r
- UINT32 type; /* tag type */\r
-} LINUX_ATAG_HEADER;\r
-\r
-typedef struct {\r
- UINT32 flags;\r
- UINT32 pagesize;\r
- UINT32 rootdev;\r
-} LINUX_ATAG_CORE;\r
-\r
-typedef struct {\r
- UINT32 size;\r
- UINTN start;\r
-} LINUX_ATAG_MEM;\r
-\r
-typedef struct {\r
- UINT8 x;\r
- UINT8 y;\r
- UINT16 video_page;\r
- UINT8 video_mode;\r
- UINT8 video_cols;\r
- UINT16 video_ega_bx;\r
- UINT8 video_lines;\r
- UINT8 video_isvga;\r
- UINT16 video_points;\r
-} LINUX_ATAG_VIDEOTEXT;\r
-\r
-typedef struct {\r
- UINT32 flags;\r
- UINT32 size;\r
- UINTN start;\r
-} LINUX_ATAG_RAMDISK;\r
-\r
-typedef struct {\r
- UINT32 start;\r
- UINT32 size;\r
-} LINUX_ATAG_INITRD2;\r
-\r
-typedef struct {\r
- UINT32 low;\r
- UINT32 high;\r
-} LINUX_ATAG_SERIALNR;\r
-\r
-typedef struct {\r
- UINT32 rev;\r
-} LINUX_ATAG_REVISION;\r
-\r
-typedef struct {\r
- UINT16 lfb_width;\r
- UINT16 lfb_height;\r
- UINT16 lfb_depth;\r
- UINT16 lfb_linelength;\r
- UINT32 lfb_base;\r
- UINT32 lfb_size;\r
- UINT8 red_size;\r
- UINT8 red_pos;\r
- UINT8 green_size;\r
- UINT8 green_pos;\r
- UINT8 blue_size;\r
- UINT8 blue_pos;\r
- UINT8 rsvd_size;\r
- UINT8 rsvd_pos;\r
-} LINUX_ATAG_VIDEOLFB;\r
-\r
-typedef struct {\r
- CHAR8 cmdline[1];\r
-} LINUX_ATAG_CMDLINE;\r
-\r
-typedef struct {\r
- LINUX_ATAG_HEADER header;\r
- union {\r
- LINUX_ATAG_CORE core_tag;\r
- LINUX_ATAG_MEM mem_tag;\r
- LINUX_ATAG_VIDEOTEXT videotext_tag;\r
- LINUX_ATAG_RAMDISK ramdisk_tag;\r
- LINUX_ATAG_INITRD2 initrd2_tag;\r
- LINUX_ATAG_SERIALNR serialnr_tag;\r
- LINUX_ATAG_REVISION revision_tag;\r
- LINUX_ATAG_VIDEOLFB videolfb_tag;\r
- LINUX_ATAG_CMDLINE cmdline_tag;\r
- } body;\r
-} LINUX_ATAG;\r
-\r
-EFI_STATUS\r
-PrepareAtagList (\r
- IN CONST CHAR8* CommandLineString,\r
- IN EFI_PHYSICAL_ADDRESS InitrdImage,\r
- IN UINTN InitrdImageSize,\r
- OUT EFI_PHYSICAL_ADDRESS *AtagBase,\r
- OUT UINT32 *AtagSize\r
- );\r
-\r
-EFI_STATUS\r
-PrepareFdt (\r
- IN CONST CHAR8* CommandLineArguments,\r
- IN EFI_PHYSICAL_ADDRESS InitrdImage,\r
- IN UINTN InitrdImageSize,\r
- IN OUT EFI_PHYSICAL_ADDRESS *FdtBlobBase,\r
- IN OUT UINTN *FdtBlobSize\r
- );\r
-\r
-#endif\r
EmbeddedPkg/EmbeddedPkg.dec\r
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
\r
+[Guids]\r
+ gFdtTableGuid\r
+\r
[LibraryClasses]\r
BdsLib\r
TimerLib\r
DebugLib\r
PrintLib\r
BaseLib\r
+ FdtLib\r
NetLib\r
\r
[Guids]\r
/** @file\r
*\r
-* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
+* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
*\r
* This program and the accompanying materials\r
* are licensed and made available under the terms and conditions of the BSD License\r
EFI_STATUS Status;\r
UINT32 LoaderType;\r
ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData;\r
- ARM_BDS_LINUX_ARGUMENTS* LinuxArguments;\r
- UINTN CmdLineSize;\r
- UINTN InitrdSize;\r
- EFI_DEVICE_PATH* Initrd;\r
UINT16 LoadOptionIndexSize;\r
\r
if (IS_ARM_BDS_BOOTENTRY (BootOption)) {\r
\r
Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, 0, NULL);\r
} else if (LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) {\r
- LinuxArguments = &(OptionalData->Arguments.LinuxArguments);\r
- CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);\r
- InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);\r
-\r
- if (InitrdSize > 0) {\r
- Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize));\r
- } else {\r
- Initrd = NULL;\r
- }\r
-\r
- Status = BdsBootLinuxAtag (BootOption->FilePathList,\r
- Initrd, // Initrd\r
- (CHAR8*)(LinuxArguments + 1)); // CmdLine\r
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
} else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) {\r
- LinuxArguments = &(OptionalData->Arguments.LinuxArguments);\r
- CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);\r
- InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);\r
-\r
- if (InitrdSize > 0) {\r
- Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize));\r
- } else {\r
- Initrd = NULL;\r
- }\r
- Status = BdsBootLinuxFdt (\r
- BootOption->FilePathList,\r
- Initrd,\r
- (CHAR8*)(LinuxArguments + 1)\r
- );\r
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
}\r
} else {\r
// Connect all the drivers if the EFI Application is not a EFI OS Loader\r