diff options
author | Steven Kinney <steven.kinney@linaro.org> | 2013-10-02 16:33:53 -0500 |
---|---|---|
committer | Steven Kinney <steven.kinney@linaro.org> | 2013-10-02 16:33:53 -0500 |
commit | ab8d92488d44da65142dd4d4620bdad399c32c1f (patch) | |
tree | 5820c9f6aafc6af415f4c76723dde2dffc6704bc /ArmPlatformPkg/Bds/BootMenu.c | |
parent | 84502da15069f664cc729da8fdc53bfa832234eb (diff) | |
parent | 9b32ea253dc2761aead1aa1a06eb796c41ac3dc1 (diff) |
Merge branch 'linaro-topic-bds' into x-integ
Diffstat (limited to 'ArmPlatformPkg/Bds/BootMenu.c')
-rw-r--r-- | ArmPlatformPkg/Bds/BootMenu.c | 253 |
1 files changed, 209 insertions, 44 deletions
diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index 1b101d45c..dd03f5a8a 100644 --- a/ArmPlatformPkg/Bds/BootMenu.c +++ b/ArmPlatformPkg/Bds/BootMenu.c @@ -128,9 +128,12 @@ BootMenuAddBootOption ( EFI_DEVICE_PATH_PROTOCOL *DevicePathNodes;
EFI_DEVICE_PATH_PROTOCOL *InitrdPathNodes;
EFI_DEVICE_PATH_PROTOCOL *InitrdPath;
+ EFI_DEVICE_PATH_PROTOCOL *FdtLocalPathNode; + EFI_DEVICE_PATH_PROTOCOL *FdtLocalPath; UINTN CmdLineSize;
BOOLEAN InitrdSupport;
UINTN InitrdSize;
+ UINTN FdtLocalSize; Attributes = 0;
SupportedBootDevice = NULL;
@@ -155,12 +158,12 @@ BootMenuAddBootOption ( goto EXIT;
}
- if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+ if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { Print(L"Add an initrd: ");
Status = GetHIInputBoolean (&InitrdSupport);
if (EFI_ERROR(Status)) {
Status = EFI_ABORTED;
- goto EXIT;
+ goto FREE_DEVICE_PATH; }
if (InitrdSupport) {
@@ -168,7 +171,7 @@ BootMenuAddBootOption ( Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes, NULL, NULL);
if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
Status = EFI_ABORTED;
- goto EXIT;
+ goto FREE_DEVICE_PATH; }
if (InitrdPathNodes != NULL) {
@@ -176,7 +179,7 @@ BootMenuAddBootOption ( InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);
if (InitrdPath == NULL) {
Status = EFI_OUT_OF_RESOURCES;
- goto EXIT;
+ goto FREE_DEVICE_PATH; }
} else {
InitrdPath = NULL;
@@ -192,15 +195,37 @@ BootMenuAddBootOption ( goto FREE_DEVICE_PATH;
}
- CmdLineSize = AsciiStrSize (CmdLine);
- InitrdSize = GetDevicePathSize (InitrdPath);
-
- BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize);
-
- BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
- BootArguments->LinuxArguments.InitrdSize = InitrdSize;
- CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), CmdLine, CmdLineSize);
- CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+ if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + // Create the specific device path node + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"local FDT", &FdtLocalPathNode, NULL, NULL); + if (EFI_ERROR(Status) || (FdtLocalPathNode == NULL)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } +
+ if (FdtLocalPathNode != NULL) { + // Append the Device Path node to the select device path + FdtLocalPath = AppendDevicePathNode (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)FdtLocalPathNode); + } else { + FdtLocalPath = NULL; + } + } else { + FdtLocalPath = NULL; + } +
+ CmdLineSize = AsciiStrSize (CmdLine); + InitrdSize = GetDevicePathSize (InitrdPath); + FdtLocalSize = GetDevicePathSize (FdtLocalPath); + + BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize); + if ( BootArguments != NULL ) { + BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + BootArguments->LinuxArguments.InitrdSize = InitrdSize; + BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize; + CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), CmdLine, CmdLineSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize); + } } else {
BootArguments = NULL;
}
@@ -214,6 +239,10 @@ BootMenuAddBootOption ( // Create new entry
BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY));
+ if ( BdsLoadOptionEntry == NULL ) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, BootArguments, &BdsLoadOptionEntry->BdsLoadOption);
if (!EFI_ERROR(Status)) {
InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link);
@@ -274,7 +303,7 @@ BootMenuSelectBootOption ( Print(L"\t- %s\n",DevicePathTxt);
OptionalData = BdsLoadOption->OptionalData;
LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);
- if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+ if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { Print (L"\t- Arguments: %a\n",&OptionalData->Arguments.LinuxArguments + 1);
}
@@ -366,14 +395,19 @@ BootMenuUpdateBootOption ( CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX];
EFI_DEVICE_PATH *DevicePath;
EFI_DEVICE_PATH *TempInitrdPath;
+ EFI_DEVICE_PATH *TempFdtLocalPath; ARM_BDS_LOADER_TYPE BootType;
ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData;
ARM_BDS_LINUX_ARGUMENTS* LinuxArguments;
EFI_DEVICE_PATH *InitrdPathNodes;
EFI_DEVICE_PATH *InitrdPath;
UINTN InitrdSize;
+ EFI_DEVICE_PATH *FdtLocalPathNode; + EFI_DEVICE_PATH *FdtLocalPath; + UINTN FdtLocalSize; UINTN CmdLineSize;
BOOLEAN InitrdSupport;
+ BOOLEAN FdtLocalSupport; Status = BootMenuSelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, TRUE, &BootOptionEntry);
if (EFI_ERROR(Status)) {
@@ -397,12 +431,65 @@ BootMenuUpdateBootOption ( OptionalData = BootOption->OptionalData;
BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&OptionalData->Header.LoaderType));
- if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+ if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { LinuxArguments = &OptionalData->Arguments.LinuxArguments;
CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);
InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);
+ FdtLocalSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->FdtLocalSize); + + if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + if (FdtLocalSize > 0) { + Print(L"Keep the local FDT: "); + } else { + Print(L"Add a local FDT: "); + } + Status = GetHIInputBoolean (&FdtLocalSupport); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + if (FdtLocalSupport && BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + if (FdtLocalSize > 0) { + // Case we update the FDT local device path + Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize + InitrdSize), L"local FDT", &FdtLocalPath, NULL, NULL); + if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string + Status = EFI_ABORTED; + goto EXIT; + } + FdtLocalSize = GetDevicePathSize (FdtLocalPath); + } else { + // Case we create the FdtLocal device path + + Status = DeviceSupport->CreateDevicePathNode (L"local FDT", &FdtLocalPathNode, NULL, NULL); + if (EFI_ERROR(Status) || (FdtLocalPathNode == NULL)) { + Status = EFI_ABORTED; + goto EXIT; + } + + if (FdtLocalPathNode != NULL) { + // Duplicate Linux kernel Device Path + TempFdtLocalPath = DuplicateDevicePath (BootOption->FilePathList); + if ( TempFdtLocalPath != NULL ) { + // Replace Linux kernel Node by EndNode + SetDevicePathEndNode (GetLastDevicePathNode (TempFdtLocalPath)); + // Append the Device Path node to the select device path + FdtLocalPath = AppendDevicePathNode (TempFdtLocalPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FdtLocalPathNode); + FreePool (TempFdtLocalPath); + FdtLocalSize = GetDevicePathSize (FdtLocalPath); + } + } else { + FdtLocalPath = NULL; + } + } + } else { + FdtLocalSize = 0; + } + } else { + FdtLocalSupport = FALSE; + } + if (InitrdSize > 0) {
Print(L"Keep the initrd: ");
} else {
@@ -467,11 +554,15 @@ BootMenuUpdateBootOption ( CmdLineSize = AsciiStrSize (CmdLine);
- BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize);
- BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
- BootArguments->LinuxArguments.InitrdSize = InitrdSize;
- CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize);
- CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+ BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize); + if ( BootArguments != NULL ) { + BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + BootArguments->LinuxArguments.InitrdSize = InitrdSize; + BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize; + CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize); + } } else {
BootArguments = NULL;
}
@@ -614,12 +705,32 @@ BootShell ( return Status;
}
+EFI_STATUS +Reboot ( + IN LIST_ENTRY *BootOptionsList + ) +{ + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +Shutdown ( + IN LIST_ENTRY *BootOptionsList + ) +{ + gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + return EFI_UNSUPPORTED; +} + struct BOOT_MAIN_ENTRY {
CONST CHAR16* Description;
EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList);
} BootMainEntries[] = {
- { L"Shell", BootShell },
{ L"Boot Manager", BootMenuManager },
+ { L"Shell", BootShell }, + { L"Reboot", Reboot }, + { L"Shutdown", Shutdown }, };
@@ -628,15 +739,21 @@ BootMenuMain ( VOID
)
{
- LIST_ENTRY BootOptionsList;
- UINTN OptionCount;
- UINTN BootOptionCount;
- EFI_STATUS Status;
- LIST_ENTRY* Entry;
- BDS_LOAD_OPTION* BootOption;
- UINTN BootOptionSelected;
- UINTN Index;
- UINTN BootMainEntryCount;
+ LIST_ENTRY BootOptionsList; + UINTN OptionCount; + UINTN BootOptionCount; + EFI_STATUS Status; + LIST_ENTRY* Entry; + BDS_LOAD_OPTION* BootOption; + UINTN BootOptionSelected; + UINTN Index; + UINTN BootMainEntryCount; + CHAR8 BootOptionSelectedStr[BOOT_OPTION_LEN]; + EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath; + UINTN FdtDevicePathSize; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; + CHAR16* DevicePathTxt; + BootOption = NULL;
BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY);
@@ -657,11 +774,10 @@ BootMenuMain ( Print(L"[%d] %s\n", OptionCount, BootOption->Description);
- DEBUG_CODE_BEGIN();
- CHAR16* DevicePathTxt;
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
+ //DEBUG_CODE_BEGIN(); ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData;
UINTN CmdLineSize;
+ UINTN InitrdSize; ARM_BDS_LOADER_TYPE LoaderType;
Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
@@ -678,7 +794,7 @@ BootMenuMain ( if (IS_ARM_BDS_BOOTENTRY (BootOption)) {
OptionalData = BootOption->OptionalData;
LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);
- if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) {
+ if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) {
CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize);
DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (
@@ -697,24 +813,64 @@ BootMenuMain ( Print(L"\t- LoaderType: Linux kernel with ATAG support\n");
break;
- case BDS_LOADER_KERNEL_LINUX_FDT:
- Print(L"\t- LoaderType: Linux kernel with FDT support\n");
+ case BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT: + Print(L"\t- LoaderType: Linux kernel with global FDT support\n"); + break; + case BDS_LOADER_KERNEL_LINUX_LOCAL_FDT: + if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.FdtLocalSize) > 0) { + CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize); + InitrdSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( + GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize + InitrdSize)), TRUE, TRUE); + Print(L"\t- FDT: %s\n", DevicePathTxt); + } else { + Print(L"\t- FDT: error, local FDT not specified, using global FDT\n"); + } + Print(L"\t- LoaderType: Linux kernel with Local FDT\n"); break;
-
default:
Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType);
+ break; }
}
FreePool(DevicePathTxt);
- DEBUG_CODE_END();
+ //DEBUG_CODE_END(); OptionCount++;
}
BootOptionCount = OptionCount-1;
+ // Display the global FDT config + Print(L"-----------------------\n"); + { + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; + EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath; + + // Get the default FDT device path + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR(Status); + DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); + + // Get the FDT device path + FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); + Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); + + // Convert FdtDevicePath to text + if (EFI_ERROR(Status)) { + DevicePathTxt = L"not configured"; + } else { + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( FdtDevicePath, TRUE, TRUE ); + } + Print(L"Global FDT Config\n\t- %s\n", DevicePathTxt); + FreePool(DevicePathTxt); + FreePool(DefaultFdtDevicePath); + } + // Display the hardcoded Boot entries
+ Print(L"-----------------------\n"); for (Index = 0; Index < BootMainEntryCount; Index++) {
- Print(L"[%d] %s\n",OptionCount,BootMainEntries[Index]);
+ Print(L"[%c] %s\n", ('a' + Index), BootMainEntries[Index]); OptionCount++;
}
@@ -722,11 +878,20 @@ BootMenuMain ( BootOptionSelected = 0;
while (BootOptionSelected == 0) {
Print(L"Start: ");
- Status = GetHIInputInteger (&BootOptionSelected);
- if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) {
- Print(L"Invalid input (max %d)\n",(OptionCount-1));
- BootOptionSelected = 0;
- }
+ Status = GetHIInputAscii (BootOptionSelectedStr, BOOT_OPTION_LEN); + + if (!EFI_ERROR(Status)) { + if ((BootOptionSelectedStr[0] - '0') < OptionCount) { + BootOptionSelected = BootOptionSelectedStr[0] - '0'; + } else if ((BootOptionSelectedStr[0] - 'a') < BootMainEntryCount) { + BootOptionSelected = BootOptionCount + 1 + BootOptionSelectedStr[0] - 'a'; + } + + if ((BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) { + Print(L"Invalid input, please choose a menu option from the list above\n"); + BootOptionSelected = 0; + } + } }
// Start the selected entry
|