]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPlatformPkg/Bds: Restore the setting of the FDT device path in the boot manager
authorRonald Cron <Ronald.Cron@arm.com>
Mon, 6 Jul 2015 16:41:36 +0000 (16:41 +0000)
committeroliviermartin <oliviermartin@Edk2>
Mon, 6 Jul 2015 16:41:36 +0000 (16:41 +0000)
People has requested this feature to be restaured in the
ARM Boot Manager.
The configuration from the EFI Shell is always possible
and it is the recommended approach to update the FDT
Device Path.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ronald Cron <Ronald.Cron@arm.com>
Reviewed-by: Olivier Martin <Olivier.Martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17826 6f19259b-4bc3-4df7-8a09-765794883524

ArmPlatformPkg/Bds/Bds.inf
ArmPlatformPkg/Bds/BdsInternal.h
ArmPlatformPkg/Bds/BootMenu.c

index e04c86db1774d3015066ada979d9363f6ed3ac7b..f4c0f1c55dcae4e77cb6d6d447a1f5c5531ca975 100644 (file)
@@ -36,6 +36,7 @@
   MdeModulePkg/MdeModulePkg.dec\r
   ArmPkg/ArmPkg.dec\r
   ArmPlatformPkg/ArmPlatformPkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
   ArmPkg/ArmPkg.dec\r
   ArmPlatformPkg/ArmPlatformPkg.dec\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
 \r
 [LibraryClasses]\r
   BdsLib\r
 \r
 [LibraryClasses]\r
   BdsLib\r
@@ -53,6 +54,7 @@
   gEfiEndOfDxeEventGroupGuid\r
   gEfiFileSystemInfoGuid\r
   gArmGlobalVariableGuid\r
   gEfiEndOfDxeEventGroupGuid\r
   gEfiFileSystemInfoGuid\r
   gArmGlobalVariableGuid\r
+  gFdtVariableGuid\r
 \r
 [Protocols]\r
   gEfiBdsArchProtocolGuid\r
 \r
 [Protocols]\r
   gEfiBdsArchProtocolGuid\r
index 95cc0b65c91c1c4c5b657829dd3640212a38fea2..1cb154eab70f2947c49fa610cb047996ced8b35a 100644 (file)
@@ -31,6 +31,7 @@
 #include <Protocol/DevicePathToText.h>\r
 \r
 #include <Guid/GlobalVariable.h>\r
 #include <Protocol/DevicePathToText.h>\r
 \r
 #include <Guid/GlobalVariable.h>\r
+#include <Guid/Fdt.h>\r
 \r
 #define BOOT_DEVICE_DESCRIPTION_MAX   100\r
 #define BOOT_DEVICE_FILEPATH_MAX      100\r
 \r
 #define BOOT_DEVICE_DESCRIPTION_MAX   100\r
 #define BOOT_DEVICE_FILEPATH_MAX      100\r
index 76c66fd0bb3f867442dbdbc3473774e4d715dc4b..d2dccbc9f274782719efdef8b8e29823967cabdc 100644 (file)
@@ -16,7 +16,7 @@
 \r
 #include <Guid/ArmGlobalVariableHob.h>\r
 \r
 \r
 #include <Guid/ArmGlobalVariableHob.h>\r
 \r
-extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList;\r
+#include <libfdt.h>\r
 \r
 /**\r
   Worker function that displays the list of boot options that is passed in.\r
 \r
 /**\r
   Worker function that displays the list of boot options that is passed in.\r
@@ -824,6 +824,152 @@ ErrorExit:
   return Status ;\r
 }\r
 \r
   return Status ;\r
 }\r
 \r
+EFI_STATUS\r
+UpdateFdtPath (\r
+  IN LIST_ENTRY *BootOptionsList\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  BDS_SUPPORTED_DEVICE      *SupportedBootDevice;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FdtDevicePathNodes;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FdtDevicePath;\r
+  CHAR16                    *FdtTextDevicePath;\r
+  EFI_PHYSICAL_ADDRESS      FdtBlobBase;\r
+  UINTN                     FdtBlobSize;\r
+  UINTN                     NumPages;\r
+  EFI_PHYSICAL_ADDRESS      FdtConfigurationTableBase;\r
+\r
+  SupportedBootDevice = NULL;\r
+\r
+  Status = SelectBootDevice (&SupportedBootDevice);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_ABORTED;\r
+    goto EXIT;\r
+  }\r
+\r
+  // Create the specific device path node\r
+  Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_ABORTED;\r
+    goto EXIT;\r
+  }\r
+\r
+  if (FdtDevicePathNodes != NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+\r
+    FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes);\r
+    FreePool (FdtDevicePathNodes);\r
+    if (FdtDevicePath == NULL) {\r
+      goto EXIT;\r
+    }\r
+\r
+    FdtTextDevicePath = ConvertDevicePathToText (FdtDevicePath, TRUE, TRUE);\r
+    if (FdtTextDevicePath == NULL) {\r
+      goto EXIT;\r
+    }\r
+\r
+    Status = gRT->SetVariable (\r
+                    (CHAR16*)L"Fdt",\r
+                    &gFdtVariableGuid,\r
+                    EFI_VARIABLE_RUNTIME_ACCESS |\r
+                    EFI_VARIABLE_NON_VOLATILE   |\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                    StrSize (FdtTextDevicePath),\r
+                    FdtTextDevicePath\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+    FreePool (FdtTextDevicePath);\r
+  } else {\r
+    Status = gRT->SetVariable (\r
+           (CHAR16*)L"Fdt",\r
+           &gFdtVariableGuid,\r
+           EFI_VARIABLE_RUNTIME_ACCESS |\r
+           EFI_VARIABLE_NON_VOLATILE   |\r
+           EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+           0,\r
+           NULL\r
+           );\r
+    ASSERT_EFI_ERROR (Status);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Try to load FDT from the new EFI Device Path\r
+  //\r
+\r
+  //\r
+  // Load the FDT given its device path.\r
+  // This operation may fail if the device path is not supported.\r
+  //\r
+  FdtBlobBase = 0;\r
+  NumPages    = 0;\r
+  Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
+  FreePool (FdtDevicePath);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto EXIT_LOAD_FDT;\r
+  }\r
+\r
+  // Check the FDT header is valid. We only make this check in DEBUG mode in\r
+  // case the FDT header change on production device and this ASSERT() becomes\r
+  // not valid.\r
+  ASSERT (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) == 0);\r
+\r
+  //\r
+  // Ensure the Size of the Device Tree is smaller than the size of the read file\r
+  //\r
+  ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);\r
+\r
+  //\r
+  // Store the FDT as Runtime Service Data to prevent the Kernel from\r
+  // overwritting its data.\r
+  //\r
+  NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize);\r
+  Status = gBS->AllocatePages (\r
+                  AllocateAnyPages, EfiRuntimeServicesData,\r
+                  NumPages, &FdtConfigurationTableBase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto EXIT_LOAD_FDT;\r
+  }\r
+  gBS->CopyMem (\r
+    (VOID*)(UINTN)FdtConfigurationTableBase,\r
+    (VOID*)(UINTN)FdtBlobBase,\r
+    FdtBlobSize\r
+    );\r
+\r
+  //\r
+  // Install the FDT into the Configuration Table\r
+  //\r
+  Status = gBS->InstallConfigurationTable (\r
+                  &gFdtTableGuid,\r
+                  (VOID*)(UINTN)FdtConfigurationTableBase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePages (FdtConfigurationTableBase, NumPages);\r
+  }\r
+\r
+EXIT_LOAD_FDT:\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"\nWarning: Did not manage to install the new device tree. Try to restart the platform.\n");\r
+  }\r
+\r
+  if (FdtBlobBase != 0) {\r
+    gBS->FreePages (FdtBlobBase, NumPages);\r
+  }\r
+\r
+EXIT:\r
+  if (Status == EFI_ABORTED) {\r
+    Print (L"\n");\r
+  }\r
+\r
+  if (SupportedBootDevice != NULL) {\r
+    FreePool (SupportedBootDevice);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Set boot timeout\r
 \r
 /**\r
   Set boot timeout\r
 \r
@@ -880,6 +1026,7 @@ struct BOOT_MANAGER_ENTRY {
     { L"Update Boot Device Entry", BootMenuUpdateBootOption },\r
     { L"Remove Boot Device Entry", BootMenuRemoveBootOption },\r
     { L"Reorder Boot Device Entries", BootMenuReorderBootOptions },\r
     { L"Update Boot Device Entry", BootMenuUpdateBootOption },\r
     { L"Remove Boot Device Entry", BootMenuRemoveBootOption },\r
     { L"Reorder Boot Device Entries", BootMenuReorderBootOptions },\r
+    { L"Update FDT path", UpdateFdtPath },\r
     { L"Set Boot Timeout", BootMenuSetBootTimeout },\r
 };\r
 \r
     { L"Set Boot Timeout", BootMenuSetBootTimeout },\r
 };\r
 \r