]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPlatformPkg/Bds/BootMenu.c
ArmPlatformPkg/Bds: Added support for booting legacy kernel from BDS
[mirror_edk2.git] / ArmPlatformPkg / Bds / BootMenu.c
index af7f1f1ac402ba5cc384eed55eb44f63cf4b9e80..8caa3ce5ced7bb4024ecbbb5e4dfa1799158212c 100644 (file)
@@ -269,6 +269,8 @@ BootMenuAddBootOption (
   EFI_DEVICE_PATH_PROTOCOL  *DevicePathNodes;\r
   UINT8*                    OptionalData;\r
   UINTN                     OptionalDataSize;\r
+  BOOLEAN                   EfiBinary;\r
+  CHAR16                    *LinuxDevicePath;\r
 \r
   Attributes                = 0;\r
   SupportedBootDevice = NULL;\r
@@ -281,8 +283,12 @@ BootMenuAddBootOption (
   }\r
 \r
   // Create the specific device path node\r
-  Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes);\r
-  if (EFI_ERROR(Status)) {\r
+  if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
+    Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes);\r
+  } else {\r
+    Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application", &DevicePathNodes);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
     Status = EFI_ABORTED;\r
     goto EXIT;\r
   }\r
@@ -293,8 +299,39 @@ BootMenuAddBootOption (
     goto EXIT;\r
   }\r
 \r
+  // Is it an EFI application?\r
+  if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
+    Status = IsEfiBinary (DevicePath, &EfiBinary);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_ABORTED;\r
+      goto EXIT;\r
+    }\r
+\r
+    if (EfiBinary == FALSE) {\r
+      Print (L"It is assumed the binary is a Linux kernel and the embedded Linux Loader is going to be used.\n");\r
+      Print (L"Supported command line formats by the embedded Linux Loader:\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\"\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -f <EFI Device Path of the Linux initrd>\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -a <Machine Type for ATAG Linux kernel>\n");\r
+\r
+      // Copy the Linux path into the command line\r
+      LinuxDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
+      CopyMem (CmdLine, LinuxDevicePath, MAX (sizeof (CmdLine), StrSize (LinuxDevicePath)));\r
+      FreePool (LinuxDevicePath);\r
+\r
+      // Free the generated Device Path\r
+      FreePool (DevicePath);\r
+      // and use the embedded Linux Loader as the EFI application\r
+      DevicePath = mLinuxLoaderDevicePath;\r
+    } else {\r
+      CmdLine[0] = L'\0';\r
+    }\r
+  } else {\r
+    CmdLine[0] = L'\0';\r
+  }\r
+\r
   Print (L"Arguments to pass to the EFI Application: ");\r
-  Status = GetHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
+  Status = EditHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
   if (EFI_ERROR (Status)) {\r
     Status = EFI_ABORTED;\r
     goto EXIT;\r
@@ -366,11 +403,13 @@ BootMenuUpdateBootOption (
   CHAR16                        BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
   CHAR8                         CmdLine[BOOT_DEVICE_OPTION_MAX];\r
   CHAR16                        UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX];\r
+  CHAR16                        *LinuxDevicePath;\r
   EFI_DEVICE_PATH               *DevicePath;\r
   UINT8*                        OptionalData;\r
   UINTN                         OptionalDataSize;\r
   BOOLEAN                       IsPrintable;\r
   BOOLEAN                       IsUnicode;\r
+  BOOLEAN                       EfiBinary;\r
 \r
   DisplayBootOptions (BootOptionsList);\r
   Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry);\r
@@ -386,46 +425,87 @@ BootMenuUpdateBootOption (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath);\r
-  if (EFI_ERROR(Status)) {\r
-    Status = EFI_ABORTED;\r
-    goto EXIT;\r
+  EfiBinary = TRUE;\r
+  if (FeaturePcdGet (PcdBdsLinuxSupport) && mLinuxLoaderDevicePath) {\r
+    Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_ABORTED;\r
+      goto EXIT;\r
+    }\r
+\r
+    // Is it an EFI application?\r
+    Status = IsEfiBinary (DevicePath, &EfiBinary);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_ABORTED;\r
+      goto EXIT;\r
+    }\r
+\r
+    if (EfiBinary == FALSE) {\r
+      Print (L"It is assumed the binary is a Linux kernel and the embedded Linux Loader is going to be used.\n");\r
+      Print (L"Supported command line formats by the embedded Linux Loader:\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\"\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -f <EFI Device Path of the Linux initrd>\n");\r
+      Print (L"- <EFI device path of the Linux kernel> -c \"<Linux kernel command line>\" -a <Machine Type for ATAG Linux kernel>\n");\r
+\r
+      // Copy the Linux path into the command line\r
+      LinuxDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
+      CopyMem (UnicodeCmdLine, LinuxDevicePath, MAX (sizeof (UnicodeCmdLine), StrSize (LinuxDevicePath)));\r
+      FreePool (LinuxDevicePath);\r
+\r
+      // Free the generated Device Path\r
+      FreePool (DevicePath);\r
+      // and use the embedded Linux Loader as the EFI application\r
+      DevicePath = mLinuxLoaderDevicePath;\r
+\r
+      // The command line is a unicode printable string\r
+      IsPrintable = TRUE;\r
+      IsUnicode = TRUE;\r
+    }\r
+  } else {\r
+    Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application", &DevicePath);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_ABORTED;\r
+      goto EXIT;\r
+    }\r
   }\r
 \r
   Print (L"Arguments to pass to the EFI Application: ");\r
 \r
-  if (BootOption->OptionalDataSize > 0) {\r
-    IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode);\r
-    if (IsPrintable) {\r
-        //\r
-        // The size in bytes of the string, final zero included, should\r
-        // be equal to or at least lower than "BootOption->OptionalDataSize"\r
-        // and the "IsPrintableString()" has already tested that the length\r
-        // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX,\r
-        // final '\0' included. We can thus copy the string for editing\r
-        // using "CopyMem()". Furthermore, note that in the case of an Unicode\r
-        // string "StrnCpy()" and "StrCpy()" can not be used to copy the\r
-        // string because the data pointed to by "BootOption->OptionalData"\r
-        // is not necessarily 2-byte aligned.\r
-        //\r
-      if (IsUnicode) {\r
-        CopyMem (\r
-          UnicodeCmdLine, BootOption->OptionalData,\r
-          MIN (sizeof (UnicodeCmdLine),\r
-               BootOption->OptionalDataSize)\r
-          );\r
-      } else {\r
-        CopyMem (\r
-          CmdLine, BootOption->OptionalData,\r
-          MIN (sizeof (CmdLine),\r
-               BootOption->OptionalDataSize)\r
-          );\r
+  // When the command line has not been initialized by the embedded Linux loader earlier\r
+  if (EfiBinary) {\r
+    if (BootOption->OptionalDataSize > 0) {\r
+      IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode);\r
+      if (IsPrintable) {\r
+          //\r
+          // The size in bytes of the string, final zero included, should\r
+          // be equal to or at least lower than "BootOption->OptionalDataSize"\r
+          // and the "IsPrintableString()" has already tested that the length\r
+          // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX,\r
+          // final '\0' included. We can thus copy the string for editing\r
+          // using "CopyMem()". Furthermore, note that in the case of an Unicode\r
+          // string "StrnCpy()" and "StrCpy()" can not be used to copy the\r
+          // string because the data pointed to by "BootOption->OptionalData"\r
+          // is not necessarily 2-byte aligned.\r
+          //\r
+        if (IsUnicode) {\r
+          CopyMem (\r
+            UnicodeCmdLine, BootOption->OptionalData,\r
+            MIN (sizeof (UnicodeCmdLine),\r
+                 BootOption->OptionalDataSize)\r
+            );\r
+        } else {\r
+          CopyMem (\r
+            CmdLine, BootOption->OptionalData,\r
+            MIN (sizeof (CmdLine),\r
+                 BootOption->OptionalDataSize)\r
+            );\r
+        }\r
       }\r
+    } else {\r
+      UnicodeCmdLine[0] = L'\0';\r
+      IsPrintable = TRUE;\r
+      IsUnicode = TRUE;\r
     }\r
-  } else {\r
-    UnicodeCmdLine[0] = L'\0';\r
-    IsPrintable = TRUE;\r
-    IsUnicode = TRUE;\r
   }\r
 \r
   // We do not request arguments for OptionalData that cannot be printed\r
@@ -909,7 +989,6 @@ struct BOOT_MAIN_ENTRY {
     { L"Boot Manager", BootMenuManager },\r
 };\r
 \r
-\r
 EFI_STATUS\r
 BootMenuMain (\r
   VOID\r
@@ -929,6 +1008,12 @@ BootMenuMain (
   BootOption         = NULL;\r
   BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY);\r
 \r
+  if (FeaturePcdGet (PcdBdsLinuxSupport)) {\r
+    // Check Linux Loader is present\r
+    Status = LocateEfiApplicationInFvByGuid (&mLinuxLoaderAppGuid, &mLinuxLoaderDevicePath);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
   while (TRUE) {\r
     // Get Boot#### list\r
     BootOptionList (&BootOptionsList);\r