@@ -136,6 +136,8 @@
gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0|UINT32|0x00000010
gArmPlatformTokenSpaceGuid.PcdFdtDevicePath|L""|VOID*|0x00000011
+ gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath|L""|VOID*|0x0000002E
+
## Timeout value for displaying progressing bar in before boot OS.
# According to UEFI 2.0 spec, the default TimeOut should be 0xffff.
gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000001A
@@ -223,8 +223,10 @@ DefineDefaultBootEntries (
ARM_BDS_LOADER_ARGUMENTS* BootArguments;
ARM_BDS_LOADER_TYPE BootType;
EFI_DEVICE_PATH* InitrdPath;
+ EFI_DEVICE_PATH* FdtLocalPath;
UINTN CmdLineSize;
UINTN InitrdSize;
+ UINTN FdtLocalSize;
//
// If Boot Order does not exist then create a default entry
@@ -262,17 +264,30 @@ DefineDefaultBootEntries (
if (BootDevicePath != NULL) {
BootType = (ARM_BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType);
- 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)) {
CmdLineSize = AsciiStrSize ((CHAR8*)PcdGetPtr(PcdDefaultBootArgument));
InitrdPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootInitrdPath));
InitrdSize = GetDevicePathSize (InitrdPath);
+ if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) {
+ FdtLocalPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultFdtLocalDevicePath));
+ FdtLocalSize = GetDevicePathSize (FdtLocalPath);
+ } else {
+ FdtLocalPath = NULL;
+ FdtLocalSize = 0;
+ }
- BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize);
- BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
- BootArguments->LinuxArguments.InitrdSize = InitrdSize;
-
- CopyMem ((VOID*)(BootArguments + 1), (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), CmdLineSize);
- CopyMem ((VOID*)((UINTN)(BootArguments + 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 ((VOID*)(BootArguments + 1), (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), CmdLineSize);
+ CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+ CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize);
+ }
+ FreePool (FdtLocalPath);
+ FreePool (InitrdPath);
} else {
BootArguments = NULL;
}
@@ -285,6 +300,7 @@ DefineDefaultBootEntries (
&BdsLoadOption
);
FreePool (BdsLoadOption);
+ FreePool (BootDevicePath);
} else {
Status = EFI_UNSUPPORTED;
}
@@ -68,6 +68,7 @@
gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument
gArmPlatformTokenSpaceGuid.PcdDefaultBootType
gArmPlatformTokenSpaceGuid.PcdFdtDevicePath
+ gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath
gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut
gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths
gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths
@@ -38,6 +38,11 @@
#define BOOT_DEVICE_OPTION_MAX 300
#define BOOT_DEVICE_ADDRESS_MAX (sizeof(L"0x0000000000000000"))
+// Length of the buffer used to hold the user input for the main menu
+// This includes the NULL terminator
+// 1 chars + newline + NULL gives room for up to 9 boot device configs
+#define BOOT_OPTION_LEN 3
+
#define ARM_BDS_OPTIONAL_DATA_SIGNATURE SIGNATURE_32('a', 'b', 'o', 'd')
#define IS_ARM_BDS_BOOTENTRY(ptr) (ReadUnaligned32 ((CONST UINT32*)&((ARM_BDS_LOADER_OPTIONAL_DATA*)((ptr)->OptionalData))->Header.Signature) == ARM_BDS_OPTIONAL_DATA_SIGNATURE)
@@ -48,16 +53,20 @@
typedef enum {
BDS_LOADER_EFI_APPLICATION = 0,
BDS_LOADER_KERNEL_LINUX_ATAG,
- BDS_LOADER_KERNEL_LINUX_FDT,
+ BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT,
+ BDS_LOADER_KERNEL_LINUX_LOCAL_FDT,
} ARM_BDS_LOADER_TYPE;
typedef struct {
UINT16 CmdLineSize;
UINT16 InitrdSize;
+ UINT16 FdtLocalSize;
+
// These following fields have variable length and are packed:
//CHAR8 *CmdLine;
//EFI_DEVICE_PATH_PROTOCOL *InitrdPathList;
+ //EFI_DEVICE_PATH_PROTOCOL *FdtLocalPathList;
} ARM_BDS_LINUX_ARGUMENTS;
typedef union {
@@ -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);
+ 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;
+ }
- BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize);
+ 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;
+ }
- BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
- BootArguments->LinuxArguments.InitrdSize = InitrdSize;
- CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), CmdLine, CmdLineSize);
- CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);
+ 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;
}
@@ -648,19 +739,20 @@ BootMenuMain (
VOID
)
{
- LIST_ENTRY BootOptionsList;
- UINTN OptionCount;
- UINTN HardCodedOptionCount;
- UINTN BootOptionCount;
- EFI_STATUS Status;
- LIST_ENTRY* Entry;
- BDS_LOAD_OPTION* BootOption;
- UINTN BootOptionSelected;
- UINTN Index;
- UINTN BootMainEntryCount;
- CHAR8 BootOptionSelectedStr[32];
- EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath;
- UINTN FdtDevicePathSize;
+ 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;
@@ -682,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);
@@ -703,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 (
@@ -722,16 +813,28 @@ 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++;
}
@@ -739,55 +842,56 @@ BootMenuMain (
// Display the global FDT config
Print(L"-----------------------\n");
- {
- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol;
- EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath;
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
- CHAR16* DevicePathTxt;
+ {
+ 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 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);
+ // 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);
+ // 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"[%c] %s\n", ('a'+Index), BootMainEntries[Index]);
+ Print(L"[%c] %s\n", ('a' + Index), BootMainEntries[Index]);
OptionCount++;
}
- HardCodedOptionCount=Index;
// Request the boot entry from the user
BootOptionSelected = 0;
while (BootOptionSelected == 0) {
Print(L"Start: ");
- Status = GetHIInputAscii (BootOptionSelectedStr,8);
+ Status = GetHIInputAscii (BootOptionSelectedStr, BOOT_OPTION_LEN);
- if (BootOptionSelectedStr[0]-'0' <= OptionCount) {
- BootOptionSelected = BootOptionSelectedStr[0] - '0';
- } else if (BootOptionSelectedStr[0]-'a' <= HardCodedOptionCount) {
- BootOptionSelected = BootOptionCount + 1 + BootOptionSelectedStr[0] - 'a';
- }
+ 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 (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) {
- Print(L"Invalid input (max %d)\n",(OptionCount-1));
- BootOptionSelected = 0;
- }
+ 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
@@ -33,6 +33,7 @@ BootOptionStart (
UINTN CmdLineSize;
UINTN InitrdSize;
EFI_DEVICE_PATH* Initrd;
+ UINTN FdtLocalSize;
UINT16 LoadOptionIndexSize;
if (IS_ARM_BDS_BOOTENTRY (BootOption)) {
@@ -59,7 +60,7 @@ BootOptionStart (
Status = BdsBootLinuxAtag (BootOption->FilePathList,
Initrd, // Initrd
(CHAR8*)(LinuxArguments + 1)); // CmdLine
- } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) {
+ } else if ((LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
LinuxArguments = &(OptionalData->Arguments.LinuxArguments);
CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);
InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);
@@ -70,17 +71,27 @@ BootOptionStart (
Initrd = NULL;
}
- // 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);
- ASSERT_EFI_ERROR(Status);
+ if (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) {
+ FdtLocalSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->FdtLocalSize);
+ if (FdtLocalSize > 0) {
+ FdtDevicePath = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize + InitrdSize));
+ } else {
+ FdtDevicePath = NULL;
+ }
+ } else {
+ // 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);
+ ASSERT_EFI_ERROR(Status);
+ FreePool (DefaultFdtDevicePath);
+ }
Status = BdsBootLinuxFdt (BootOption->FilePathList,
Initrd, // Initrd
(CHAR8*)(LinuxArguments + 1),
@@ -159,6 +170,7 @@ BootOptionSetFields (
UINT16 FilePathListLength;
UINT8* EfiLoadOptionPtr;
UINT8* InitrdPathListPtr;
+ UINT8* FdtLocalPathListPtr;
UINTN OptionalDataSize;
ARM_BDS_LINUX_ARGUMENTS* DestLinuxArguments;
ARM_BDS_LINUX_ARGUMENTS* SrcLinuxArguments;
@@ -170,8 +182,8 @@ BootOptionSetFields (
BootDescriptionSize = StrSize (BootDescription);
BootOptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER);
- if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
- BootOptionalDataSize += sizeof(ARM_BDS_LINUX_ARGUMENTS) + BootArguments->LinuxArguments.CmdLineSize + BootArguments->LinuxArguments.InitrdSize;
+ if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) {
+ BootOptionalDataSize += sizeof(ARM_BDS_LINUX_ARGUMENTS) + BootArguments->LinuxArguments.CmdLineSize + BootArguments->LinuxArguments.InitrdSize + BootArguments->LinuxArguments.FdtLocalSize;
}
// Compute the size of the FilePath list
@@ -213,12 +225,13 @@ BootOptionSetFields (
OptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER);
- 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)) {
SrcLinuxArguments = &(BootArguments->LinuxArguments);
DestLinuxArguments = &((ARM_BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments.LinuxArguments;
WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->CmdLineSize), SrcLinuxArguments->CmdLineSize);
WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->InitrdSize), SrcLinuxArguments->InitrdSize);
+ WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->FdtLocalSize), SrcLinuxArguments->FdtLocalSize);
OptionalDataSize += sizeof (ARM_BDS_LINUX_ARGUMENTS);
if (SrcLinuxArguments->CmdLineSize > 0) {
@@ -230,6 +243,11 @@ BootOptionSetFields (
InitrdPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize);
CopyMem (InitrdPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize), SrcLinuxArguments->InitrdSize);
}
+
+ if (SrcLinuxArguments->FdtLocalSize > 0) {
+ FdtLocalPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize + SrcLinuxArguments->InitrdSize);
+ CopyMem (FdtLocalPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize + SrcLinuxArguments->InitrdSize), SrcLinuxArguments->FdtLocalSize);
+ }
}
BootOption->OptionalDataSize = OptionalDataSize;
@@ -25,6 +25,7 @@
#include <Guid/FileSystemInfo.h>
#define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
+#define LOCAL_FDT_RESPONSE_LEN 2 // 1 character, plus carriage return
EFI_STATUS
BdsLoadOptionFileSystemList (
@@ -233,7 +234,7 @@ BootDeviceGetType (
EFI_STATUS Status;
BOOLEAN IsEfiApp;
BOOLEAN IsBootLoader;
- BOOLEAN HasFDTSupport;
+ CHAR16 FDTType[ LOCAL_FDT_RESPONSE_LEN ];
if (FileName == NULL) {
Print(L"Is an EFI Application? ");
@@ -258,15 +259,19 @@ BootDeviceGetType (
}
*BootType = BDS_LOADER_EFI_APPLICATION;
} else {
- Print(L"Has FDT support? ");
- Status = GetHIInputBoolean (&HasFDTSupport);
+ Print(L"Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l] ");
+ Status = GetHIInputStr (FDTType, LOCAL_FDT_RESPONSE_LEN );
if (EFI_ERROR(Status)) {
return EFI_ABORTED;
}
- if (HasFDTSupport) {
- *BootType = BDS_LOADER_KERNEL_LINUX_FDT;
- } else {
+ if (StrCmp(FDTType, L"g") == 0) {
+ *BootType = BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT;
+ } else if (StrCmp(FDTType, L"l") == 0) {
+ *BootType = BDS_LOADER_KERNEL_LINUX_LOCAL_FDT;
+ } else if (StrCmp(FDTType, L"a") == 0) {
*BootType = BDS_LOADER_KERNEL_LINUX_ATAG;
+ } else {
+ return EFI_ABORTED;
}
}
This patch adds a local FDT config option to each boot device. Bds was using a global FDT config for all boot devices of Loader Type = 2. I've added a new Loader Type = 3 that stores an device path to an FDT file this is only used for this boot device. This change will invalidate any existing configs stored on the board due to the change in structure sizes to store the boot device configurations. Signed-off-by: Ryan Harkin <ryan.harkin@linaro.org> --- ArmPlatformPkg/ArmPlatformPkg.dec | 2 + ArmPlatformPkg/Bds/Bds.c | 30 +++- ArmPlatformPkg/Bds/Bds.inf | 1 + ArmPlatformPkg/Bds/BdsInternal.h | 11 +- ArmPlatformPkg/Bds/BootMenu.c | 246 +++++++++++++++++++++++--------- ArmPlatformPkg/Bds/BootOption.c | 46 ++++-- ArmPlatformPkg/Bds/BootOptionSupport.c | 17 ++- 7 files changed, 254 insertions(+), 99 deletions(-)