summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonald Cron <Ronald.Cron@arm.com>2015-07-06 16:41:36 +0000
committeroliviermartin <oliviermartin@Edk2>2015-07-06 16:41:36 +0000
commit0ae6a518f7b853ef0bad36916e99d40f40472c11 (patch)
tree2f256922cb2d02c8a35d5839b543fecadc81e2c5
parent093b7c8769d2c8d6276a1ad7c155d14f260d3170 (diff)
downloadedk2-0ae6a518f7b853ef0bad36916e99d40f40472c11.zip
edk2-0ae6a518f7b853ef0bad36916e99d40f40472c11.tar.gz
edk2-0ae6a518f7b853ef0bad36916e99d40f40472c11.tar.bz2
ArmPlatformPkg/Bds: Restore the setting of the FDT device path in the boot manager
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
-rw-r--r--ArmPlatformPkg/Bds/Bds.inf2
-rw-r--r--ArmPlatformPkg/Bds/BdsInternal.h1
-rw-r--r--ArmPlatformPkg/Bds/BootMenu.c149
3 files changed, 151 insertions, 1 deletions
diff --git a/ArmPlatformPkg/Bds/Bds.inf b/ArmPlatformPkg/Bds/Bds.inf
index e04c86d..f4c0f1c 100644
--- a/ArmPlatformPkg/Bds/Bds.inf
+++ b/ArmPlatformPkg/Bds/Bds.inf
@@ -36,6 +36,7 @@
MdeModulePkg/MdeModulePkg.dec
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
BdsLib
@@ -53,6 +54,7 @@
gEfiEndOfDxeEventGroupGuid
gEfiFileSystemInfoGuid
gArmGlobalVariableGuid
+ gFdtVariableGuid
[Protocols]
gEfiBdsArchProtocolGuid
diff --git a/ArmPlatformPkg/Bds/BdsInternal.h b/ArmPlatformPkg/Bds/BdsInternal.h
index 95cc0b6..1cb154e 100644
--- a/ArmPlatformPkg/Bds/BdsInternal.h
+++ b/ArmPlatformPkg/Bds/BdsInternal.h
@@ -31,6 +31,7 @@
#include <Protocol/DevicePathToText.h>
#include <Guid/GlobalVariable.h>
+#include <Guid/Fdt.h>
#define BOOT_DEVICE_DESCRIPTION_MAX 100
#define BOOT_DEVICE_FILEPATH_MAX 100
diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c
index 76c66fd..d2dccbc 100644
--- a/ArmPlatformPkg/Bds/BootMenu.c
+++ b/ArmPlatformPkg/Bds/BootMenu.c
@@ -16,7 +16,7 @@
#include <Guid/ArmGlobalVariableHob.h>
-extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList;
+#include <libfdt.h>
/**
Worker function that displays the list of boot options that is passed in.
@@ -824,6 +824,152 @@ ErrorExit:
return Status ;
}
+EFI_STATUS
+UpdateFdtPath (
+ IN LIST_ENTRY *BootOptionsList
+ )
+{
+ EFI_STATUS Status;
+ BDS_SUPPORTED_DEVICE *SupportedBootDevice;
+ EFI_DEVICE_PATH_PROTOCOL *FdtDevicePathNodes;
+ EFI_DEVICE_PATH_PROTOCOL *FdtDevicePath;
+ CHAR16 *FdtTextDevicePath;
+ EFI_PHYSICAL_ADDRESS FdtBlobBase;
+ UINTN FdtBlobSize;
+ UINTN NumPages;
+ EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase;
+
+ SupportedBootDevice = NULL;
+
+ Status = SelectBootDevice (&SupportedBootDevice);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_ABORTED;
+ goto EXIT;
+ }
+
+ // Create the specific device path node
+ Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_ABORTED;
+ goto EXIT;
+ }
+
+ if (FdtDevicePathNodes != NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+
+ FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes);
+ FreePool (FdtDevicePathNodes);
+ if (FdtDevicePath == NULL) {
+ goto EXIT;
+ }
+
+ FdtTextDevicePath = ConvertDevicePathToText (FdtDevicePath, TRUE, TRUE);
+ if (FdtTextDevicePath == NULL) {
+ goto EXIT;
+ }
+
+ Status = gRT->SetVariable (
+ (CHAR16*)L"Fdt",
+ &gFdtVariableGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ StrSize (FdtTextDevicePath),
+ FdtTextDevicePath
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (FdtTextDevicePath);
+ } else {
+ Status = gRT->SetVariable (
+ (CHAR16*)L"Fdt",
+ &gFdtVariableGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Try to load FDT from the new EFI Device Path
+ //
+
+ //
+ // Load the FDT given its device path.
+ // This operation may fail if the device path is not supported.
+ //
+ FdtBlobBase = 0;
+ NumPages = 0;
+ Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);
+ FreePool (FdtDevicePath);
+
+ if (EFI_ERROR (Status)) {
+ goto EXIT_LOAD_FDT;
+ }
+
+ // Check the FDT header is valid. We only make this check in DEBUG mode in
+ // case the FDT header change on production device and this ASSERT() becomes
+ // not valid.
+ ASSERT (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) == 0);
+
+ //
+ // Ensure the Size of the Device Tree is smaller than the size of the read file
+ //
+ ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);
+
+ //
+ // Store the FDT as Runtime Service Data to prevent the Kernel from
+ // overwritting its data.
+ //
+ NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize);
+ Status = gBS->AllocatePages (
+ AllocateAnyPages, EfiRuntimeServicesData,
+ NumPages, &FdtConfigurationTableBase
+ );
+ if (EFI_ERROR (Status)) {
+ goto EXIT_LOAD_FDT;
+ }
+ gBS->CopyMem (
+ (VOID*)(UINTN)FdtConfigurationTableBase,
+ (VOID*)(UINTN)FdtBlobBase,
+ FdtBlobSize
+ );
+
+ //
+ // Install the FDT into the Configuration Table
+ //
+ Status = gBS->InstallConfigurationTable (
+ &gFdtTableGuid,
+ (VOID*)(UINTN)FdtConfigurationTableBase
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (FdtConfigurationTableBase, NumPages);
+ }
+
+EXIT_LOAD_FDT:
+ if (EFI_ERROR (Status)) {
+ Print (L"\nWarning: Did not manage to install the new device tree. Try to restart the platform.\n");
+ }
+
+ if (FdtBlobBase != 0) {
+ gBS->FreePages (FdtBlobBase, NumPages);
+ }
+
+EXIT:
+ if (Status == EFI_ABORTED) {
+ Print (L"\n");
+ }
+
+ if (SupportedBootDevice != NULL) {
+ FreePool (SupportedBootDevice);
+ }
+
+ return Status;
+}
+
/**
Set boot timeout
@@ -880,6 +1026,7 @@ struct BOOT_MANAGER_ENTRY {
{ L"Update Boot Device Entry", BootMenuUpdateBootOption },
{ L"Remove Boot Device Entry", BootMenuRemoveBootOption },
{ L"Reorder Boot Device Entries", BootMenuReorderBootOptions },
+ { L"Update FDT path", UpdateFdtPath },
{ L"Set Boot Timeout", BootMenuSetBootTimeout },
};