/** @file\r
*\r
-* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.\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
\r
#include <Guid/ArmGlobalVariableHob.h>\r
\r
-extern EFI_HANDLE mImageHandle;\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
if (InitrdPathNodes != NULL) {\r
// Append the Device Path to the selected device path\r
InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);\r
+ // Free the InitrdPathNodes created by Support->CreateDevicePathNode()\r
+ FreePool (InitrdPathNodes);\r
+\r
if (InitrdPath == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto EXIT;\r
// Append the Device Path to the selected device path\r
InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);\r
FreePool (TempInitrdPath);\r
+ // Free the InitrdPathNodes created by Support->CreateDevicePathNode()\r
+ FreePool (InitrdPathNodes);\r
if (InitrdPath == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto EXIT;\r
\r
Print(L"Arguments to pass to the binary: ");\r
if (CmdLineSize > 0) {\r
- AsciiStrnCpy(CmdLine, (CONST CHAR8*)(LinuxArguments + 1), CmdLineSize);\r
+ AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine));\r
+ CmdLine[sizeof (CmdLine) - 1] = '\0';\r
} else {\r
CmdLine[0] = '\0';\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
- StrnCpy (UnicodeCmdLine, BootOption->OptionalData, BootOption->OptionalDataSize / 2);\r
+ CopyMem (\r
+ UnicodeCmdLine, BootOption->OptionalData,\r
+ MIN (sizeof (UnicodeCmdLine),\r
+ BootOption->OptionalDataSize)\r
+ );\r
} else {\r
- AsciiStrnCpy (CmdLine, BootOption->OptionalData, BootOption->OptionalDataSize);\r
+ CopyMem (\r
+ CmdLine, BootOption->OptionalData,\r
+ MIN (sizeof (CmdLine),\r
+ BootOption->OptionalDataSize)\r
+ );\r
}\r
}\r
} else {\r
}\r
\r
SelectedEntry = &BootOptionEntry->Link;\r
+ SecondEntry = NULL;\r
// Note down the previous entry in the list to be able to cancel changes\r
PrevEntry = GetPreviousNode (BootOptionsList, SelectedEntry);\r
\r
} while ((!Move) && (!Save) && (!Cancel));\r
\r
if (Move) {\r
- SwapListEntries (SelectedEntry, SecondEntry);\r
+ if ((SelectedEntry != NULL) && (SecondEntry != NULL)) {\r
+ SwapListEntries (SelectedEntry, SecondEntry);\r
+ }\r
} else {\r
if (Save) {\r
Status = GetGlobalEnvironmentVariable (\r
)\r
{\r
EFI_STATUS Status;\r
- UINTN FdtDevicePathSize;\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
+ 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
+ if (EFI_ERROR (Status)) {\r
Status = EFI_ABORTED;\r
goto EXIT;\r
}\r
\r
if (FdtDevicePathNodes != NULL) {\r
- // Append the Device Path node to the select device path\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+\r
FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes);\r
- FdtDevicePathSize = GetDevicePathSize (FdtDevicePath);\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
- &gArmGlobalVariableGuid,\r
- EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- FdtDevicePathSize,\r
- FdtDevicePath\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
+ ASSERT_EFI_ERROR (Status);\r
+ FreePool (FdtTextDevicePath);\r
} else {\r
- gRT->SetVariable (\r
+ Status = gRT->SetVariable (\r
(CHAR16*)L"Fdt",\r
- &gArmGlobalVariableGuid,\r
- EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\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
+ 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
+ Print (L"\n");\r
}\r
- FreePool(SupportedBootDevice);\r
+\r
+ if (SupportedBootDevice != NULL) {\r
+ FreePool (SupportedBootDevice);\r
+ }\r
+\r
return Status;\r
}\r
\r
IN LIST_ENTRY *BootOptionsList\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH* EfiShellDevicePath;\r
\r
- // Start EFI Shell\r
- Status = BdsLoadApplication (mImageHandle, L"Shell", 0, NULL);\r
+ // Find the EFI Shell\r
+ Status = LocateEfiApplicationInFvByName (L"Shell", &EfiShellDevicePath);\r
if (Status == EFI_NOT_FOUND) {\r
Print (L"Error: EFI Application not found.\n");\r
- } else if (EFI_ERROR(Status)) {\r
- Print (L"Error: Status Code: 0x%X\n",(UINT32)Status);\r
- }\r
+ return Status;\r
+ } else if (EFI_ERROR (Status)) {\r
+ Print (L"Error: Status Code: 0x%X\n", (UINT32)Status);\r
+ return Status;\r
+ } else {\r
+ // Need to connect every drivers to ensure no dependencies are missing for the application\r
+ Status = BdsConnectAllDrivers ();\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));\r
+ return Status;\r
+ }\r
\r
- return Status;\r
+ return BdsStartEfiApplication (gImageHandle, EfiShellDevicePath, 0, NULL);\r
+ }\r
}\r
\r
struct BOOT_MAIN_ENTRY {\r