+++ /dev/null
-/** @file\r
-*\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
-* 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/ArmLib.h>\r
-#include <Library/ArmGicLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PcdLib.h>\r
-\r
-#include <Ppi/ArmMpCoreInfo.h>\r
-\r
-#include <Guid/Fdt.h>\r
-\r
-#include "LinuxLoader.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
-VOID\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
-\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 (PcdGet64 (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
- return Status;\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
- PreparePlatformHardware ();\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
- // We cannot recover the execution at this stage\r
- while (1);\r
-}\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param SystemMemoryBase Base of the system memory\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
- @param MachineType ARM machine type value\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
- @retval RETURN_UNSUPPORTED ATAG is not support by this architecture\r
-\r
-**/\r
-EFI_STATUS\r
-BootLinuxAtag (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* CommandLineArguments,\r
- IN UINTN MachineType\r
- )\r
-{\r
- // NOTE : AArch64 Linux kernel does not support ATAG, FDT only.\r
- ASSERT (0);\r
-\r
- return EFI_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
-BootLinuxFdt (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath,\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 = SystemMemoryBase + 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
- if (FdtDevicePath == NULL) {\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
- } else {\r
- //\r
- // FDT device path explicitly defined. The FDT is relocated later to a\r
- // more appropriate location for the Linux kernel.\r
- //\r
- FdtBlobBase = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (FdtDevicePath, AllocateMaxAddress, &FdtBlobBase, &FdtBlobSize);\r
- if (EFI_ERROR (Status)) {\r
- Print (L"ERROR: Did not find Device Tree blob (%r).\n", Status);\r
- goto EXIT_FREE_INITRD;\r
- }\r
- }\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 (SystemMemoryBase, 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-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
-* 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 "LinuxAtag.h"\r
-#include "LinuxLoader.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
- AsciiStrCpyS (mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, LineLength, 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 EFI_PHYSICAL_ADDRESS SystemMemoryBase,\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
- 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
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\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 = (SYSTEM_MEMORY_RESOURCE*)ResourceLink;\r
- DEBUG ((EFI_D_INFO, "- [0x%08X,0x%08X]\n",\r
- (UINT32)Resource->PhysicalStart,\r
- (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
+++ /dev/null
-/** @file\r
-*\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
-* 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 __LINUX_ATAG_H__\r
-#define __LINUX_ATAG_H__\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
-#endif /* __LINUX_ATAG_H__ */\r
+++ /dev/null
-/** @file\r
-*\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
-* 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/ArmLib.h>\r
-#include <Library/PcdLib.h>\r
-\r
-#include <Guid/Fdt.h>\r
-\r
-#include "LinuxLoader.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
-EFI_STATUS\r
-PrepareAtagList (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\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
-STATIC\r
-VOID\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
-\r
-STATIC\r
-EFI_STATUS\r
-StartLinux (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\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
- return Status;\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
- PreparePlatformHardware ();\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
- // We cannot recover the execution at this stage\r
- while (1);\r
-}\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param SystemMemoryBase Base of the system memory\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
- @param MachineType ARM machine type value\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
- @retval RETURN_UNSUPPORTED ATAG is not support by this architecture\r
-\r
-**/\r
-EFI_STATUS\r
-BootLinuxAtag (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* CommandLineArguments,\r
- IN UINTN MachineType\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 (SystemMemoryBase, 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 (SystemMemoryBase, LinuxImage, LinuxImageSize, AtagBase, AtagSize, MachineType);\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
-BootLinuxFdt (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath,\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
- if (FdtDevicePath == NULL) {\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
- } else {\r
- //\r
- // FDT device path explicitly defined. The FDT is relocated later to a\r
- // more appropriate location for the Linux kernel.\r
- //\r
- FdtBlobBase = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (FdtDevicePath, AllocateMaxAddress, &FdtBlobBase, &FdtBlobSize);\r
- if (EFI_ERROR (Status)) {\r
- Print (L"ERROR: Did not find Device Tree blob (%r).\n", Status);\r
- goto EXIT_FREE_INITRD;\r
- }\r
- }\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 (SystemMemoryBase, 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 (SystemMemoryBase, 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
+++ /dev/null
-/** @file\r
-*\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
-* 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/UefiApplicationEntryPoint.h>\r
-#include <Library/BaseMemoryLib.h>\r
-\r
-#include <Protocol/DevicePathFromText.h>\r
-\r
-#include "LinuxLoader.h"\r
-\r
-/**\r
- The user Entry Point for Application. The user code starts with this function\r
- as the real entry point for the application.\r
-\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
- @param[in] SystemTable A pointer to the EFI System Table.\r
-\r
- @retval EFI_SUCCESS The entry point was executed successfully.\r
- @retval EFI_NOT_FOUND Protocol not found.\r
- @retval EFI_NOT_FOUND Path to the Linux kernel not found.\r
- @retval EFI_ABORTED The initialisation of the Shell Library failed.\r
- @retval EFI_INVALID_PARAMETER At least one parameter is not valid or there is a\r
- conflict between two parameters.\r
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-LinuxLoaderEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
- EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;\r
- CHAR16 *KernelPath;\r
- CHAR16 *FdtPath;\r
- CHAR16 *InitrdPath;\r
- CHAR16 *KernelTextDevicePath;\r
- CHAR16 *FdtTextDevicePath;\r
- CHAR16 *InitrdTextDevicePath;\r
- CHAR16 *LinuxCommandLine;\r
- UINTN AtagMachineType;\r
- EFI_DEVICE_PATH *KernelDevicePath;\r
- EFI_DEVICE_PATH *FdtDevicePath;\r
- EFI_DEVICE_PATH *InitrdDevicePath;\r
- CHAR8 *AsciiLinuxCommandLine;\r
- LIST_ENTRY ResourceList;\r
- LIST_ENTRY *ResourceLink;\r
- SYSTEM_MEMORY_RESOURCE *Resource;\r
- EFI_PHYSICAL_ADDRESS SystemMemoryBase;\r
- UINTN Length;\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiDevicePathFromTextProtocolGuid,\r
- NULL,\r
- (VOID **)&EfiDevicePathFromTextProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Register the strings for the user interface in the HII Database.\r
- // This shows the way to the multi-language support, even if\r
- // only the English language is actually supported. The strings to register\r
- // are stored in the "LinuxLoaderStrings[]" array. This array is\r
- // built by the building process from the "*.uni" file associated to\r
- // the present application (cf. LinuxLoader.inf). Examine the Build\r
- // folder of the application and you will find the array defined in the\r
- // LinuxLoaderStrDefs.h file.\r
- //\r
- mLinuxLoaderHiiHandle = HiiAddPackages (\r
- &mLinuxLoaderHiiGuid,\r
- ImageHandle,\r
- LinuxLoaderStrings,\r
- NULL\r
- );\r
- if (mLinuxLoaderHiiHandle == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- ImageHandle,\r
- &gEfiShellParametersProtocolGuid,\r
- (VOID**)&ShellParameters\r
- );\r
-\r
- KernelDevicePath = NULL;\r
- FdtDevicePath = NULL;\r
- InitrdDevicePath = NULL;\r
- AsciiLinuxCommandLine = NULL;\r
-\r
- //\r
- // Call the proper function to handle the command line\r
- // depending on whether the application has been called\r
- // from the Shell or not.\r
- //\r
-\r
- if (!EFI_ERROR (Status)) {\r
- KernelTextDevicePath = NULL;\r
- FdtTextDevicePath = NULL;\r
- InitrdTextDevicePath = NULL;\r
-\r
- Status = ProcessShellParameters (\r
- &KernelPath, &FdtPath, &InitrdPath, &LinuxCommandLine, &AtagMachineType\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- KernelDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (KernelPath);\r
- if (KernelDevicePath != NULL) {\r
- FreePool (KernelPath);\r
- } else {\r
- KernelTextDevicePath = KernelPath;\r
- }\r
-\r
- if (FdtPath != NULL) {\r
- FdtDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (FdtPath);\r
- if (FdtDevicePath != NULL) {\r
- FreePool (FdtPath);\r
- } else {\r
- FdtTextDevicePath = FdtPath;\r
- }\r
- }\r
-\r
- if (InitrdPath != NULL) {\r
- InitrdDevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (InitrdPath);\r
- if (InitrdDevicePath != NULL) {\r
- FreePool (InitrdPath);\r
- } else {\r
- InitrdTextDevicePath = InitrdPath;\r
- }\r
- }\r
-\r
- } else {\r
- Status = ProcessAppCommandLine (\r
- &KernelTextDevicePath, &FdtTextDevicePath,\r
- &InitrdTextDevicePath, &LinuxCommandLine, &AtagMachineType\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
- }\r
-\r
- Status = EFI_INVALID_PARAMETER;\r
- if (KernelTextDevicePath != NULL) {\r
- KernelDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (\r
- KernelTextDevicePath\r
- );\r
- if (KernelDevicePath == NULL) {\r
- goto Error;\r
- }\r
- }\r
- if (FdtTextDevicePath != NULL) {\r
- FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (\r
- FdtTextDevicePath\r
- );\r
- if (FdtDevicePath == NULL) {\r
- goto Error;\r
- }\r
- }\r
- if (InitrdTextDevicePath != NULL) {\r
- InitrdDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (\r
- InitrdTextDevicePath\r
- );\r
- if (InitrdDevicePath == NULL) {\r
- goto Error;\r
- }\r
- }\r
-\r
- if (LinuxCommandLine != NULL) {\r
- Length = StrLen (LinuxCommandLine) + 1;\r
- AsciiLinuxCommandLine = AllocatePool (Length);\r
- if (AsciiLinuxCommandLine == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
- UnicodeStrToAsciiStrS (LinuxCommandLine, AsciiLinuxCommandLine, Length);\r
- }\r
-\r
- //\r
- // Find Base of System Memory - we keep the lowest physical address\r
- //\r
- SystemMemoryBase = ~0;\r
- GetSystemMemoryResources (&ResourceList);\r
- ResourceLink = ResourceList.ForwardLink;\r
- while (ResourceLink != NULL && ResourceLink != &ResourceList) {\r
- Resource = (SYSTEM_MEMORY_RESOURCE*)ResourceLink;\r
- if (Resource->PhysicalStart < SystemMemoryBase) {\r
- SystemMemoryBase = Resource->PhysicalStart;\r
- }\r
- ResourceLink = ResourceLink->ForwardLink;\r
- }\r
-\r
- if (AtagMachineType != ARM_FDT_MACHINE_TYPE) {\r
- Status = BootLinuxAtag (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, AsciiLinuxCommandLine, AtagMachineType);\r
- } else {\r
- Status = BootLinuxFdt (SystemMemoryBase, KernelDevicePath, InitrdDevicePath, FdtDevicePath, AsciiLinuxCommandLine);\r
- }\r
-\r
-Error:\r
- if (KernelTextDevicePath != NULL) {\r
- FreePool (KernelTextDevicePath);\r
- }\r
- if (FdtTextDevicePath != NULL) {\r
- FreePool (FdtTextDevicePath);\r
- }\r
- if (InitrdTextDevicePath != NULL) {\r
- FreePool (InitrdTextDevicePath);\r
- }\r
- if (LinuxCommandLine != NULL) {\r
- FreePool (LinuxCommandLine);\r
- }\r
- if (KernelDevicePath != NULL) {\r
- FreePool (KernelDevicePath);\r
- }\r
- if (FdtDevicePath != NULL) {\r
- FreePool (FdtDevicePath);\r
- }\r
- if (InitrdDevicePath != NULL) {\r
- FreePool (InitrdDevicePath);\r
- }\r
- if (AsciiLinuxCommandLine != NULL) {\r
- FreePool (AsciiLinuxCommandLine);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- PrintHii (NULL, STRING_TOKEN (STR_ERROR), Status);\r
- }\r
-\r
- HiiRemovePackages (mLinuxLoaderHiiHandle);\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
-*\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
-* 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 __LINUX_LOADER_H__\r
-#define __LINUX_LOADER_H__\r
-\r
-#include <Library/BdsLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/HiiLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/PerformanceLib.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/ShellLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiLib.h>\r
-\r
-#include <Protocol/ShellParameters.h>\r
-#include <Protocol/Shell.h>\r
-\r
-#include <libfdt.h>\r
-\r
-//\r
-// Definitions\r
-//\r
-\r
-#define MAX_MSG_LEN 80\r
-\r
-#define LINUX_UIMAGE_SIGNATURE 0x56190527\r
-#define LINUX_KERNEL_MAX_OFFSET (SystemMemoryBase + PcdGet32(PcdArmLinuxKernelMaxOffset))\r
-#define LINUX_ATAG_MAX_OFFSET (SystemMemoryBase + PcdGet32(PcdArmLinuxAtagMaxOffset))\r
-#define LINUX_FDT_MAX_OFFSET (SystemMemoryBase + PcdGet32(PcdArmLinuxFdtMaxOffset))\r
-\r
-#define ARM_FDT_MACHINE_TYPE 0xFFFFFFFF\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
-//\r
-// Global variables\r
-//\r
-extern CONST EFI_GUID mLinuxLoaderHiiGuid;\r
-extern EFI_HANDLE mLinuxLoaderHiiHandle;\r
-\r
-//\r
-// Local Types\r
-//\r
-typedef struct _SYSTEM_MEMORY_RESOURCE {\r
- LIST_ENTRY Link; // This attribute must be the first entry of this structure (to avoid pointer computation)\r
- EFI_PHYSICAL_ADDRESS PhysicalStart;\r
- UINT64 ResourceLength;\r
-} SYSTEM_MEMORY_RESOURCE;\r
-\r
-typedef VOID (*LINUX_KERNEL)(UINT32 Zero, UINT32 Arch, UINTN ParametersBase);\r
-\r
-//\r
-// Functions\r
-//\r
-EFI_STATUS\r
-PrintHii (\r
- IN CONST CHAR8 *Language OPTIONAL,\r
- IN CONST EFI_STRING_ID HiiFormatStringId,\r
- ...\r
- );\r
-\r
-VOID\r
-PrintHelp (\r
- IN CONST CHAR8 *Language OPTIONAL\r
- );\r
-\r
-EFI_STATUS\r
-ProcessShellParameters (\r
- OUT CHAR16 **KernelPath,\r
- OUT CHAR16 **FdtPath,\r
- OUT CHAR16 **InitrdPath,\r
- OUT CHAR16 **LinuxCommandLine,\r
- OUT UINTN *AtagMachineType\r
- );\r
-\r
-EFI_STATUS\r
-ProcessAppCommandLine (\r
- OUT CHAR16 **KernelTextDevicePath,\r
- OUT CHAR16 **FdtTextDevicePath,\r
- OUT CHAR16 **InitrdTextDevicePath,\r
- OUT CHAR16 **LinuxCommandLine,\r
- OUT UINTN *AtagMachineType\r
- );\r
-\r
-VOID\r
-PrintPerformance (\r
- VOID\r
- );\r
-\r
-EFI_STATUS\r
-GetSystemMemoryResources (\r
- IN LIST_ENTRY *ResourceList\r
- );\r
-\r
-EFI_STATUS\r
-PrepareFdt (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\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
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param SystemMemoryBase Base of the system memory\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
- @param MachineType ARM machine type value\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
- @retval RETURN_UNSUPPORTED ATAG is not support by this architecture\r
-\r
-**/\r
-EFI_STATUS\r
-BootLinuxAtag (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* CommandLineArguments,\r
- IN UINTN MachineType\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
-BootLinuxFdt (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath,\r
- IN CONST CHAR8* Arguments\r
- );\r
-\r
-#endif /* __LINUX_LOADER_H__ */\r
+++ /dev/null
-#/* @file\r
-# Copyright (c) 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
-# 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
-[Defines]\r
- INF_VERSION = 0x00010006\r
- BASE_NAME = LinuxLoader\r
- MODULE_UNI_FILE = LinuxLoader.uni\r
- FILE_GUID = 701f54f2-0d70-4b89-bc0a-d9ca25379059\r
- MODULE_TYPE = UEFI_APPLICATION\r
- VERSION_STRING = 0.1\r
- ENTRY_POINT = LinuxLoaderEntryPoint\r
-\r
-[Sources]\r
- LinuxLoader.c\r
- LinuxLoader.h\r
- LinuxLoader.uni\r
- LinuxLoaderFdt.c\r
- LinuxLoaderHelper.c\r
- LinuxLoaderEfiApp.c\r
- LinuxLoaderShellApp.c\r
-\r
-[Sources.AARCH64]\r
- AArch64/LinuxStarter.c\r
- AArch64/LinuxStarterHelper.S\r
-\r
-[Sources.ARM]\r
- Arm/LinuxAtag.h\r
- Arm/LinuxAtag.c\r
- Arm/LinuxStarter.c\r
-\r
-[Packages]\r
- ArmPkg/ArmPkg.dec\r
- EmbeddedPkg/EmbeddedPkg.dec\r
- MdePkg/MdePkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
- ShellPkg/ShellPkg.dec\r
-\r
-[Guids]\r
- gFdtTableGuid\r
-\r
-[Guids]\r
- gArmMpCoreInfoGuid\r
-\r
-[LibraryClasses]\r
- ArmLib\r
- BdsLib\r
- DebugLib\r
- DxeServicesTableLib\r
- FdtLib\r
- HiiLib\r
- HobLib\r
- PerformanceLib\r
- ShellLib\r
- SerialPortLib\r
- TimerLib\r
- UefiApplicationEntryPoint\r
- UefiLib\r
-\r
-[LibraryClasses.AARCH64]\r
- ArmGicLib\r
- PcdLib\r
-\r
-[Protocols]\r
- gEfiLoadedImageProtocolGuid\r
- gEfiDevicePathToTextProtocolGuid\r
- gEfiShellParametersProtocolGuid\r
-\r
-[FeaturePcd]\r
- gArmTokenSpaceGuid.PcdArmLinuxSpinTable\r
-\r
-[FixedPcd]\r
- gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset\r
- gArmTokenSpaceGuid.PcdArmLinuxFdtAlignment\r
- gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset\r
-\r
-[FixedPcd.ARM]\r
- gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset\r
-\r
-[Pcd.AARCH64]\r
- gArmTokenSpaceGuid.PcdGicDistributorBase\r
- gArmTokenSpaceGuid.PcdGicSgiIntId\r
+++ /dev/null
-// *++\r
-//\r
-// Copyright (c) 2014-2015, ARM Ltd. All rights reserved.<BR>\r
-//\r
-// This program and the accompanying materials are licensed and made available\r
-// under the terms and conditions of the BSD License which accompanies this\r
-// 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
-// Module Name:\r
-//\r
-// LinuxLoader\r
-//\r
-// Abstract:\r
-//\r
-// String definitions for the LinuxLoader UEFI application\r
-//\r
-// Revision History:\r
-//\r
-// --*/\r
-\r
-/=#\r
-\r
-#langdef en-US "English"\r
-\r
-#string STR_SHELL_INVALID_PARAMETER #language en-US "Invalid parameter : '%s'\r\n"\r
-#string STR_ERROR #language en-US "Linux boot loader error - %r.\r\n"\r
-\r
-#string STR_INVALID_FLAG #language en-US "Invalid flag or flag value '%c%c'.\r\n"\r
-#string STR_INVALID_PARAMETER #language en-US "Invalid parameter.\r\n"\r
-#string STR_MISSING_KERNEL_PATH #language en-US "Path to the Linux kernel not defined.\r\n"\r
-#string STR_MISSING_VALUE #language en-US "Missing value for flag '-%c'\r\n"\r
-#string STR_ATAG_FDT_CONFLICT #language en-US "The Linux Kernel can not have both ATAG and FDT support.\r\n"\r
-\r
-\r
-\r
-#string STR_HELP #language en-US "USAGE:\r\n"\r
-"LinuxLoader KernelPath [-f InitrdPath] [-a | -d FdtPath] [-c CommandLine]\r\n"\r
-"\r\n"\r
-" -f Path to the RAM root file system.\r\n"\r
-" -a Indicate a Linux kernel with ATAG support.\r\n"\r
-" -d Path to the Flat Device Tree.\r\n"\r
-" -c Linux Kernel command line.\r\n"\r
-"\r\n"\r
-"The 'LinuxLoader.efi' UEFI application is intended to boot Linux Kernel\r\n"\r
-"images containing or not an 'EFI Boot Stub' (see www.kernel.org/doc/\r\n"\r
-"Documentation/efi-stub.txt for more information).\r\n"\r
-"\r\n"\r
-"This application can be called either from the EFI Shell or during the\r\n"\r
-"Boot Device Selection (BDS) phase of the boot flow.\r\n"\r
-"\r\n"\r
-"If the application is called during the BDS phase then all the paths\r\n"\r
-"must be device paths in the text form.\r\n"\r
-"\r\n"\r
-"If the application is called from the EFI Shell, the usual alias\r\n"\r
-"and variable substitutions apply. Moreover, each path can be either\r\n"\r
-"an EFI Shell file path or a device path in the text form. The application\r\n"\r
-"first tries to interpret the path as an EFI Shell file path. If the\r\n"\r
-"interpretation fails then the path is handled as a device path in the\r\n"\r
-"text form.\r\n"\r
-"\r\n"\r
-"EXAMPLES:\r\n"\r
-" * Boot from the EFI Shell the Linux kernel 'Image' with the command\r\n"\r
-" line 'console=ttyAMA0,115200 earlycon=pl011,0x7ff80000' using the FDT\r\n"\r
-" 'fdt.dtb' and the RAM boot file system 'ramdisk.img', all files\r\n"\r
-" being located at the root of the 'fs2:' volume :\r\n"\r
-" Shell> LinuxLoader fs2:Image -d fs2:fdt.dtb -f fs2:ramdisk.img \\\r\n"\r
-" -c "console=ttyAMA0,115200 earlycon=pl011,0x7ff80000"\r\n"\r
-" or\r
-" fs2:\> LinuxLoader Image -d fdt.dtb -f ramdisk.img \\\r\n"\r
-" -c "console=ttyAMA0,115200 earlycon=pl011,0x7ff80000"\r\n"\r
-" * Arguments to pass to the application for the same boot but from\r\n"\r
-" the boot manager, the device path to the 'fs2:' volume being \r\n"\r
-" VenHw(E7223039-5836-41E1-B542-D7EC736C5E59) :\r\n"\r
-" VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/Image \\\r\n"\r
-" -d VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/fdt.dtb \\\r\n"\r
-" -f VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/ramdisk.img \\\r\n"\r
-" -c "console=ttyAMA0,115200 earlycon=pl011,0x7ff80000"\r\n"\r
-" * Arguments to pass to boot ATAG linux kernel:\r\n"\r
-" VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/Image \\\r\n"\r
-" -a 2272 \\\r\n"\r
-" -f VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/ramdisk.img \\\r\n"\r
-" -c "console=ttyAMA0,115200 earlycon=pl011,0x7ff80000"\r\n"\r
+++ /dev/null
-/** @file\r
-*\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
-* 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 "LinuxLoader.h"\r
-\r
-/**\r
- Extract the next item from the command line.\r
-\r
- The items are separated by spaces. Quotation marks (") are used for argument\r
- grouping and the escaping character is "^" as for the EFI Shell command lines.\r
-\r
- @param[in out] CommandLine Command line pointer.\r
- @param[out] Item Pointer to the allocated buffer where the\r
- item is stored.\r
-\r
- @retval EFI_SUCCESS The token was found and extracted.\r
- @retval EFI_NOT_FOUND No item found.\r
- @retval EFI_OUT_OF_RESOURCES The memory allocation failed.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-ExtractNextItem (\r
- IN OUT CONST CHAR16 **CommandLine,\r
- OUT CHAR16 **Item\r
- )\r
-{\r
- CONST CHAR16 *Walker;\r
- VOID *Buffer;\r
- CHAR16 *WritePtr;\r
- BOOLEAN InQuotedString;\r
- BOOLEAN Interpret;\r
-\r
- for (Walker = *CommandLine; *Walker == L' '; Walker++) {\r
- ;\r
- }\r
-\r
- Buffer = AllocatePool (StrSize (Walker));\r
- if (Buffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- for (WritePtr = Buffer, Interpret = TRUE, InQuotedString = FALSE;\r
- ((*Walker != L' ') || InQuotedString) && (*Walker != L'\0');\r
- Walker++\r
- ) {\r
- if (Interpret) {\r
- if (*Walker == L'^') {\r
- Interpret = FALSE;\r
- continue;\r
- }\r
- if (*Walker == L'"') {\r
- InQuotedString = !InQuotedString;\r
- continue;\r
- }\r
- } else {\r
- Interpret = TRUE;\r
- }\r
- *(WritePtr++) = *Walker;\r
- }\r
-\r
- if (WritePtr == Buffer) {\r
- FreePool (Buffer);\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- *WritePtr = L'\0';\r
- *CommandLine = Walker;\r
- *Item = Buffer;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Check if an item of the command line is a flag or not.\r
-\r
- @param[in] Item Command line item.\r
-\r
- @retval TRUE The item is a flag.\r
- @retval FALSE The item is not a flag.\r
-\r
-**/\r
-STATIC\r
-BOOLEAN\r
-IsFlag (\r
- IN CONST CHAR16 *Item\r
- )\r
-{\r
- return ((Item[0] == L'-') && (Item[2] == L'\0'));\r
-}\r
-\r
-/**\r
- Process the application command line.\r
-\r
- @param[out] KernelTextDevicePath A pointer to the buffer where the device\r
- path to the Linux kernel is stored. The\r
- address of the buffer is NULL in case of\r
- an error. Otherwise, the returned address\r
- is the address of a buffer allocated with\r
- a call to AllocatePool() that has to be\r
- freed by the caller.\r
- @param[out] FdtTextDevicePath A pointer to the buffer where the device\r
- path to the FDT is stored. The address of\r
- the buffer is NULL in case of an error or\r
- if the device path to the FDT is not\r
- defined. Otherwise, the returned address\r
- is the address of a buffer allocated with\r
- a call to AllocatePool() that has to be\r
- freed by the caller.\r
- @param[out] InitrdTextDevicePath A pointer to the buffer where the device\r
- path to the RAM root file system is stored.\r
- The address of the buffer is NULL in case\r
- of an error or if the device path to the\r
- RAM root file system is not defined.\r
- Otherwise, the returned address is the\r
- address of a buffer allocated with a call\r
- to AllocatePool() that has to be freed by\r
- the caller.\r
- @param[out] LinuxCommandLine A pointer to the buffer where the Linux\r
- kernel command line is stored. The address\r
- of the buffer is NULL in case of an error\r
- or if the Linux command line is not\r
- defined. Otherwise, the returned address\r
- is the address of a buffer allocated with\r
- a call to AllocatePool() that has to be\r
- freed by the caller.\r
-\r
- @param[out] AtagMachineType Value of the ARM Machine Type\r
-\r
- @retval EFI_SUCCESS The processing was successfull.\r
- @retval EFI_NOT_FOUND EFI_LOADED_IMAGE_PROTOCOL not found.\r
- @retval EFI_NOT_FOUND Path to the Linux kernel not found.\r
- @retval EFI_INVALID_PARAMETER At least one parameter is not valid or there is a\r
- conflict between two parameters.\r
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-ProcessAppCommandLine (\r
- OUT CHAR16 **KernelTextDevicePath,\r
- OUT CHAR16 **FdtTextDevicePath,\r
- OUT CHAR16 **InitrdTextDevicePath,\r
- OUT CHAR16 **LinuxCommandLine,\r
- OUT UINTN *AtagMachineType\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_STATUS Status2;\r
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
- CONST CHAR16 *Walker;\r
- CHAR16 *Item;\r
- CHAR16 Flag;\r
- BOOLEAN HasAtagSupport;\r
- BOOLEAN HasFdtSupport;\r
-\r
- *KernelTextDevicePath = NULL;\r
- *FdtTextDevicePath = NULL;\r
- *InitrdTextDevicePath = NULL;\r
- *LinuxCommandLine = NULL;\r
- *AtagMachineType = ARM_FDT_MACHINE_TYPE;\r
-\r
- HasAtagSupport = FALSE;\r
- HasFdtSupport = FALSE;\r
-\r
- Status = gBS->HandleProtocol (\r
- gImageHandle,\r
- &gEfiLoadedImageProtocolGuid,\r
- (VOID**)&LoadedImage\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ASSERT_EFI_ERROR (Status);\r
- return Status;\r
- }\r
-\r
- Walker = (CHAR16*)LoadedImage->LoadOptions;\r
- if (Walker == NULL) {\r
- PrintHelp (NULL);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Get the device path to the Linux kernel.\r
- //\r
-\r
- Status = ExtractNextItem (&Walker, &Item);\r
- if (!EFI_ERROR (Status)) {\r
- if (!IsFlag (Item)) {\r
- *KernelTextDevicePath = Item;\r
- } else {\r
- PrintHii (NULL, STRING_TOKEN (STR_MISSING_KERNEL_PATH));\r
- FreePool (Item);\r
- return EFI_NOT_FOUND;\r
- }\r
- } else {\r
- if (Status != EFI_NOT_FOUND) {\r
- return Status;\r
- }\r
- PrintHelp (NULL);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = EFI_INVALID_PARAMETER;\r
- while (*Walker != L'\0') {\r
- Status2 = ExtractNextItem (&Walker, &Item);\r
- if (Status2 == EFI_NOT_FOUND) {\r
- break;\r
- }\r
- if (EFI_ERROR (Status2)) {\r
- Status = Status2;\r
- goto Error;\r
- }\r
-\r
- if (!IsFlag (Item)) {\r
- PrintHii (NULL, STRING_TOKEN (STR_INVALID_FLAG), Item[0], Item[1]);\r
- FreePool (Item);\r
- goto Error;\r
- }\r
- Flag = Item[1];\r
- FreePool (Item);\r
-\r
- Status2 = ExtractNextItem (&Walker, &Item);\r
- if (Status2 == EFI_NOT_FOUND) {\r
- PrintHii (NULL, STRING_TOKEN (STR_MISSING_VALUE), Flag);\r
- goto Error;\r
- }\r
- if (EFI_ERROR (Status2)) {\r
- Status = Status2;\r
- goto Error;\r
- }\r
- if (IsFlag (Item)) {\r
- PrintHii (NULL, STRING_TOKEN (STR_MISSING_VALUE), Flag);\r
- FreePool (Item);\r
- goto Error;\r
- }\r
-\r
- switch (Flag) {\r
- case L'a':\r
- if (HasFdtSupport) {\r
- PrintHii (NULL, STRING_TOKEN (STR_ATAG_FDT_CONFLICT));\r
- goto Error;\r
- }\r
- *AtagMachineType = StrDecimalToUintn (Item);\r
- HasAtagSupport = TRUE;\r
- break;\r
- case L'd':\r
- *FdtTextDevicePath = Item;\r
- if (HasAtagSupport) {\r
- PrintHii (NULL, STRING_TOKEN (STR_ATAG_FDT_CONFLICT));\r
- goto Error;\r
- }\r
- HasFdtSupport = TRUE;\r
- break;\r
-\r
- case L'c':\r
- *LinuxCommandLine = Item;\r
- break;\r
-\r
- case L'f':\r
- *InitrdTextDevicePath = Item;\r
- break;\r
-\r
- default:\r
- PrintHii (NULL, STRING_TOKEN (STR_INVALID_FLAG), L'-', Flag);\r
- FreePool (Item);\r
- goto Error;\r
- }\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
-\r
-Error:\r
- if (EFI_ERROR (Status)) {\r
- if (*KernelTextDevicePath != NULL) {\r
- FreePool (*KernelTextDevicePath);\r
- *KernelTextDevicePath = NULL;\r
- }\r
- if (*FdtTextDevicePath != NULL) {\r
- FreePool (*FdtTextDevicePath);\r
- *FdtTextDevicePath = NULL;\r
- }\r
- if (*InitrdTextDevicePath != NULL) {\r
- FreePool (*InitrdTextDevicePath);\r
- *InitrdTextDevicePath = NULL;\r
- }\r
- if (*LinuxCommandLine != NULL) {\r
- FreePool (*LinuxCommandLine);\r
- *LinuxCommandLine = NULL;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
-*\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
-* 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 <PiDxe.h>\r
-#include <Library/ArmLib.h>\r
-#include <Library/HobLib.h>\r
-\r
-#include <Guid/ArmMpCoreInfo.h>\r
-\r
-#include "LinuxLoader.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
-} FDT_REGION;\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 SystemMemoryBase,\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
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-PrepareFdt (\r
- IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,\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
- FDT_REGION Region;\r
- UINTN Index;\r
- CHAR8 Name[10];\r
- LIST_ENTRY ResourceList;\r
- 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 (SystemMemoryBase, *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 = (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
- // 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-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
-* 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 <PiDxe.h>\r
-#include <Library/HobLib.h>\r
-#include <Library/TimerLib.h>\r
-#include <Library/SerialPortLib.h>\r
-\r
-#include "LinuxLoader.h"\r
-\r
-STATIC CONST CHAR8 *mTokenList[] = {\r
- /*"SEC",*/\r
- "PEI",\r
- "DXE",\r
- "BDS",\r
- NULL\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",\r
- DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));\r
- SerialPortWrite ((UINT8 *) Buffer, CharCount);\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-InsertSystemMemoryResources (\r
- LIST_ENTRY *ResourceList,\r
- EFI_HOB_RESOURCE_DESCRIPTOR *ResHob\r
- )\r
-{\r
- SYSTEM_MEMORY_RESOURCE *NewResource;\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *NextLink;\r
- LIST_ENTRY AttachedResources;\r
- SYSTEM_MEMORY_RESOURCE *Resource;\r
- EFI_PHYSICAL_ADDRESS NewResourceEnd;\r
-\r
- if (IsListEmpty (ResourceList)) {\r
- NewResource = AllocateZeroPool (sizeof (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 = (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 = (SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);\r
- Link = RemoveEntryList (&NewResource->Link);\r
- while (!IsListEmpty (&AttachedResources)) {\r
- // Merge resources\r
- Resource = (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 (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
+++ /dev/null
-/** @file\r
-*\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
-* 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 "LinuxLoader.h"\r
-\r
-//\r
-// Internal variables\r
-//\r
-\r
-CONST EFI_GUID mLinuxLoaderHiiGuid = {\r
- 0xd5d16edc, 0x35c5, 0x4866,\r
- {0xbd, 0xe5, 0x2b, 0x64, 0xa2, 0x26, 0x55, 0x6e}\r
- };\r
-EFI_HANDLE mLinuxLoaderHiiHandle;\r
-\r
-STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
- {L"-f", TypeValue},\r
- {L"-d", TypeValue},\r
- {L"-c", TypeValue},\r
- {L"-a", TypeValue},\r
- {NULL , TypeMax }\r
- };\r
-\r
-/**\r
- Print a string given the "HII Id" of the format string and a list of\r
- arguments.\r
-\r
- @param[in] Language The language of the string to retrieve. If\r
- this parameter is NULL, then the current\r
- platform language is used.\r
- @param[in] HiiFormatStringId The format string Id for getting from Hii.\r
- @param[in] ... The variable argument list.\r
-\r
- @retval EFI_SUCCESS The printing was successful.\r
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-PrintHii (\r
- IN CONST CHAR8 *Language OPTIONAL,\r
- IN CONST EFI_STRING_ID HiiFormatStringId,\r
- ...\r
- )\r
-{\r
- VA_LIST Marker;\r
- CHAR16 *HiiFormatString;\r
- CHAR16 Buffer[MAX_MSG_LEN];\r
-\r
- VA_START (Marker, HiiFormatStringId);\r
-\r
- HiiFormatString = HiiGetString (mLinuxLoaderHiiHandle, HiiFormatStringId, Language);\r
- if (HiiFormatString != NULL) {\r
- UnicodeVSPrint (Buffer, sizeof (Buffer), HiiFormatString, Marker);\r
- Print (L"%s", Buffer);\r
- FreePool (HiiFormatString);\r
- } else {\r
- ASSERT (FALSE);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- VA_END (Marker);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Print the help.\r
-\r
- @param[in] Language The language of the string to retrieve. If this\r
- parameter is NULL, then the current platform\r
- language is used.\r
-**/\r
-VOID\r
-PrintHelp (\r
- IN CONST CHAR8 *Language OPTIONAL\r
- )\r
-{\r
- CHAR16 *Help;\r
- CHAR16 *Walker;\r
- CHAR16 *LineEnd;\r
-\r
- //\r
- // Print the help line by line as it is too big to be printed at once.\r
- //\r
-\r
- Help = HiiGetString (mLinuxLoaderHiiHandle, STRING_TOKEN (STR_HELP), Language);\r
- if (Help != NULL) {\r
- Walker = Help;\r
- while (*Walker != L'\0') {\r
- LineEnd = StrStr (Walker, L"\r\n");\r
- if (LineEnd != NULL) {\r
- *LineEnd = L'\0';\r
- }\r
- Print (L"%s\r\n", Walker);\r
- if (LineEnd == NULL) {\r
- break;\r
- }\r
- Walker = LineEnd + 2;\r
- }\r
- FreePool (Help);\r
- }\r
-\r
-}\r
-\r
-/**\r
- Process the Shell parameters in the case the application has been called\r
- from the EFI Shell.\r
-\r
- @param[out] KernelPath A pointer to the buffer where the path\r
- to the Linux kernel (EFI Shell file path\r
- or device path is stored. The address of\r
- the buffer is NULL in case of an error.\r
- Otherwise, the returned address is the\r
- address of a buffer allocated with\r
- a call to AllocatePool() that has to be\r
- freed by the caller.\r
- @param[out] FdtPath A pointer to the buffer where the path\r
- to the FDT (EFI Shell file path or\r
- device path) is stored. The address of\r
- the buffer is NULL in case of an error or\r
- if the path to the FDT is not defined.\r
- Otherwise, the returned address is the\r
- address of a buffer allocated with a call\r
- to AllocatePool() that has to be freed by\r
- the caller.\r
- @param[out] InitrdPath A pointer to the buffer where the path\r
- (EFI Shell file path or device path)\r
- to the RAM root file system is stored.\r
- The address of the buffer is NULL in case\r
- of an error or if the path to the RAM root\r
- file system is not defined. Otherwise, the\r
- returned address is the address of a\r
- buffer allocated with a call to\r
- AllocatePool() that has to be freed by\r
- the caller.\r
- @param[out] LinuxCommandLine A pointer to the buffer where the Linux\r
- kernel command line is stored. The address\r
- of the buffer is NULL in case of an error\r
- or if the Linux command line is not\r
- defined. Otherwise, the returned address\r
- is the address of a buffer allocated with\r
- a call to AllocatePool() that has to be\r
- freed by the caller.\r
- @param[out] AtagMachineType Value of the ARM Machine Type\r
-\r
- @retval EFI_SUCCESS The processing was successfull.\r
- @retval EFI_ABORTED The initialisation of the Shell Library failed.\r
- @retval EFI_NOT_FOUND Path to the Linux kernel not found.\r
- @retval EFI_INVALID_PARAMETER At least one parameter is not valid or there is a\r
- conflict between two parameters.\r
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-ProcessShellParameters (\r
- OUT CHAR16 **KernelPath,\r
- OUT CHAR16 **FdtPath,\r
- OUT CHAR16 **InitrdPath,\r
- OUT CHAR16 **LinuxCommandLine,\r
- OUT UINTN *AtagMachineType\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *CheckPackage;\r
- CHAR16 *ProblemParam;\r
- CONST CHAR16 *FlagValue;\r
- CONST CHAR16 *ParameterValue;\r
- UINTN LinuxCommandLineLen;\r
-\r
-\r
- *KernelPath = NULL;\r
- *FdtPath = NULL;\r
- *InitrdPath = NULL;\r
- *LinuxCommandLine = NULL;\r
- *AtagMachineType = ARM_FDT_MACHINE_TYPE;\r
-\r
- //\r
- // Initialise the Shell Library as we are going to use it.\r
- // Assert that the return code is EFI_SUCCESS as it should.\r
- // To anticipate any change is the codes returned by\r
- // ShellInitialize(), leave in case of error.\r
- //\r
- Status = ShellInitialize ();\r
- if (EFI_ERROR (Status)) {\r
- ASSERT_EFI_ERROR (Status);\r
- return EFI_ABORTED;\r
- }\r
-\r
- Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);\r
- if (EFI_ERROR (Status)) {\r
- if ((Status == EFI_VOLUME_CORRUPTED) &&\r
- (ProblemParam != NULL) ) {\r
- PrintHii (\r
- NULL, STRING_TOKEN (STR_SHELL_INVALID_PARAMETER), ProblemParam\r
- );\r
- FreePool (ProblemParam);\r
- } else {\r
- ASSERT (FALSE);\r
- }\r
- goto Error;\r
- }\r
-\r
- Status = EFI_INVALID_PARAMETER;\r
- if (ShellCommandLineGetCount (CheckPackage) != 2) {\r
- PrintHelp (NULL);\r
- goto Error;\r
- }\r
-\r
- Status = EFI_OUT_OF_RESOURCES;\r
-\r
- FlagValue = ShellCommandLineGetValue (CheckPackage, L"-a");\r
- if (FlagValue != NULL) {\r
- if (ShellCommandLineGetFlag (CheckPackage, L"-d")) {\r
- PrintHii (NULL, STRING_TOKEN (STR_ATAG_FDT_CONFLICT));\r
- goto Error;\r
- }\r
- *AtagMachineType = StrDecimalToUintn (FlagValue);\r
- }\r
-\r
- ParameterValue = ShellCommandLineGetRawValue (CheckPackage, 1);\r
- *KernelPath = AllocateCopyPool (StrSize (ParameterValue), ParameterValue);\r
- if (*KernelPath == NULL) {\r
- goto Error;\r
- }\r
-\r
- FlagValue = ShellCommandLineGetValue (CheckPackage, L"-d");\r
- if (FlagValue != NULL) {\r
- *FdtPath = AllocateCopyPool (StrSize (FlagValue), FlagValue);\r
- if (*FdtPath == NULL) {\r
- goto Error;\r
- }\r
- }\r
-\r
- FlagValue = ShellCommandLineGetValue (CheckPackage, L"-f");\r
- if (FlagValue != NULL) {\r
- *InitrdPath = AllocateCopyPool (StrSize (FlagValue), FlagValue);\r
- if (*InitrdPath == NULL) {\r
- goto Error;\r
- }\r
- }\r
-\r
- FlagValue = ShellCommandLineGetValue (CheckPackage, L"-c");\r
- if (FlagValue != NULL) {\r
- LinuxCommandLineLen = StrLen (FlagValue);\r
- if ((LinuxCommandLineLen != 0) &&\r
- (FlagValue[0] == L'"' ) &&\r
- (FlagValue[LinuxCommandLineLen - 1] == L'"')) {\r
- FlagValue++;\r
- LinuxCommandLineLen -= 2;\r
- }\r
-\r
- *LinuxCommandLine = AllocateCopyPool (\r
- (LinuxCommandLineLen + 1) * sizeof (CHAR16),\r
- FlagValue\r
- );\r
- if (*LinuxCommandLine == NULL) {\r
- goto Error;\r
- }\r
- (*LinuxCommandLine)[LinuxCommandLineLen] = L'\0';\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
-\r
-Error:\r
- ShellCommandLineFreeVarList (CheckPackage);\r
-\r
- if (EFI_ERROR (Status)) {\r
- if (*KernelPath != NULL) {\r
- FreePool (*KernelPath);\r
- *KernelPath = NULL;\r
- }\r
- if (*FdtPath != NULL) {\r
- FreePool (*FdtPath);\r
- *FdtPath = NULL;\r
- }\r
- if (*InitrdPath != NULL) {\r
- FreePool (*InitrdPath);\r
- *InitrdPath = NULL;\r
- }\r
- if (*LinuxCommandLine != NULL) {\r
- FreePool (*LinuxCommandLine);\r
- *LinuxCommandLine = NULL;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
\r
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf\r
\r
- ArmPkg/Application/LinuxLoader/LinuxLoader.inf\r
-\r
ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf\r
\r
ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf\r