]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Library/BdsLib/AArch64/BdsLinuxLoader.c
ArmPlatformPkg: Add the LinuxLoader.efi EFI application
[mirror_edk2.git] / ArmPkg / Library / BdsLib / AArch64 / BdsLinuxLoader.c
index b66d96f05c9bdd3f0933ac1c5132f455e3a58127..76515978fc9948ffb9068245be64a5f72a3c94fd 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 *\r
-*  Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
+*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
 *\r
 *  This program and the accompanying materials\r
 *  are licensed and made available under the terms and conditions of the BSD License\r
@@ -14,6 +14,8 @@
 #include <Library/ArmGicLib.h>\r
 #include <Ppi/ArmMpCoreInfo.h>\r
 #include <Library/IoLib.h>\r
+#include <Guid/Fdt.h>\r
+#include <libfdt.h>\r
 \r
 #include "BdsInternal.h"\r
 #include "BdsLinuxLoader.h"\r
@@ -87,8 +89,7 @@ StartLinux (
   IN  EFI_PHYSICAL_ADDRESS  LinuxImage,\r
   IN  UINTN                 LinuxImageSize,\r
   IN  EFI_PHYSICAL_ADDRESS  FdtBlobBase,\r
-  IN  UINTN                 FdtBlobSize,\r
-  IN  UINT32                MachineType\r
+  IN  UINTN                 FdtBlobSize\r
   )\r
 {\r
   EFI_STATUS            Status;\r
@@ -172,9 +173,9 @@ BdsBootLinuxAtag (
 /**\r
   Start a Linux kernel from a Device Path\r
 \r
-  @param  LinuxKernel           Device Path to the Linux Kernel\r
-  @param  Parameters            Linux kernel agruments\r
-  @param  Fdt                   Device Path to the Flat Device Tree\r
+  @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
@@ -185,31 +186,29 @@ EFI_STATUS
 BdsBootLinuxFdt (\r
   IN  EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
   IN  EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
-  IN  CONST CHAR8*              Arguments,\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
-  UINTN                 FdtBlobSize;\r
-  EFI_PHYSICAL_ADDRESS  FdtBlobBase;\r
-  UINT32                FdtMachineType;\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
+  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
-  FdtMachineType = 0xFFFFFFFF;\r
   InitrdImage = 0;\r
   InitrdImageSize = 0;\r
   InitrdImageBase = 0;\r
@@ -223,14 +222,14 @@ BdsBootLinuxFdt (
 \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 = PcdGet32(PcdSystemMemoryBase) + 0x80000;\r
+  LinuxImage = PcdGet64 (PcdSystemMemoryBase) + 0x80000;\r
   Status = BdsLoadImage (LinuxKernelDevicePath, AllocateAddress, &LinuxImage, &LinuxImageSize);\r
   if (EFI_ERROR(Status)) {\r
     // Try again but give the loader more freedom of where to put the image.\r
     LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
     Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
     if (EFI_ERROR(Status)) {\r
-      Print (L"ERROR: Did not find Linux kernel.\n");\r
+      Print (L"ERROR: Did not find Linux kernel (%r).\n", Status);\r
       return Status;\r
     }\r
   }\r
@@ -247,7 +246,7 @@ BdsBootLinuxFdt (
       Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImageBase, &InitrdImageBaseSize);\r
     }\r
     if (EFI_ERROR (Status)) {\r
-      Print (L"ERROR: Did not find initrd image.\n");\r
+      Print (L"ERROR: Did not find initrd image (%r).\n", Status);\r
       goto EXIT_FREE_LINUX;\r
     }\r
 \r
@@ -262,19 +261,23 @@ BdsBootLinuxFdt (
     }\r
   }\r
 \r
-  // Load the FDT binary from a device path.\r
-  // The FDT will be reloaded later to a more appropriate location for the Linux kernel.\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.\n");\r
+  //\r
+  // Get the FDT from the Configuration Table.\r
+  // The FDT will be reloaded in PrepareFdt() to a more appropriate\r
+  // location for the Linux Kernel.\r
+  //\r
+  Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &InstalledFdtBase);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"ERROR: Did not get the Device Tree blob (%r).\n", Status);\r
     goto EXIT_FREE_INITRD;\r
   }\r
+  FdtBlobBase = (EFI_PHYSICAL_ADDRESS)InstalledFdtBase;\r
+  FdtBlobSize = fdt_totalsize (InstalledFdtBase);\r
 \r
   //\r
   // Install secondary core pens if the Power State Coordination Interface is not supported\r
   //\r
-  if (FeaturePcdGet (PcdArmPsciSupport) == FALSE) {\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
@@ -298,9 +301,6 @@ BdsBootLinuxFdt (
     // Update the MailboxBase variable used in the pen code\r
     *(UINTN*)(PenBase + ((UINTN)&AsmMailboxbase - (UINTN)&SecondariesPenStart)) = MailBoxBase;\r
 \r
-    // Flush caches to make sure our pen gets to mem before we free the cores.\r
-    ArmCleanDataCache();\r
-\r
     for (Index=0; Index < gST->NumberOfTableEntries; Index++) {\r
       // Check for correct GUID type\r
       if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {\r
@@ -323,6 +323,8 @@ BdsBootLinuxFdt (
         }\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
@@ -332,7 +334,7 @@ BdsBootLinuxFdt (
     goto EXIT_FREE_FDT;\r
   }\r
 \r
-  return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, FdtMachineType);\r
+  return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize);\r
 \r
 EXIT_FREE_FDT:\r
   if (!EFI_ERROR (PenBaseStatus)) {\r