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(-)
diff --git a/ArmPlatformPkg/ArmPlatformPkg.dec b/ArmPlatformPkg/ArmPlatformPkg.dec index 3e2900b..e672ce2 100644 --- a/ArmPlatformPkg/ArmPlatformPkg.dec +++ b/ArmPlatformPkg/ArmPlatformPkg.dec @@ -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 diff --git a/ArmPlatformPkg/Bds/Bds.c b/ArmPlatformPkg/Bds/Bds.c index 2801fac..d0fc6a3 100644 --- a/ArmPlatformPkg/Bds/Bds.c +++ b/ArmPlatformPkg/Bds/Bds.c @@ -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; } diff --git a/ArmPlatformPkg/Bds/Bds.inf b/ArmPlatformPkg/Bds/Bds.inf index 5faa4b2..8b3f1d2 100644 --- a/ArmPlatformPkg/Bds/Bds.inf +++ b/ArmPlatformPkg/Bds/Bds.inf @@ -68,6 +68,7 @@ gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument gArmPlatformTokenSpaceGuid.PcdDefaultBootType gArmPlatformTokenSpaceGuid.PcdFdtDevicePath + gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths diff --git a/ArmPlatformPkg/Bds/BdsInternal.h b/ArmPlatformPkg/Bds/BdsInternal.h index a8d836d..7830066 100644 --- a/ArmPlatformPkg/Bds/BdsInternal.h +++ b/ArmPlatformPkg/Bds/BdsInternal.h @@ -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 { diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index 2b32e83..de2117b 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); + 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 diff --git a/ArmPlatformPkg/Bds/BootOption.c b/ArmPlatformPkg/Bds/BootOption.c index ee0301e..6b756a3 100644 --- a/ArmPlatformPkg/Bds/BootOption.c +++ b/ArmPlatformPkg/Bds/BootOption.c @@ -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;
diff --git a/ArmPlatformPkg/Bds/BootOptionSupport.c b/ArmPlatformPkg/Bds/BootOptionSupport.c index 190169a..c2df7f9 100644 --- a/ArmPlatformPkg/Bds/BootOptionSupport.c +++ b/ArmPlatformPkg/Bds/BootOptionSupport.c @@ -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; } }