From 656416bc2ee1409492343cde3f27ce717e90fdf7 Mon Sep 17 00:00:00 2001 From: oliviermartin Date: Thu, 18 Aug 2011 13:21:14 +0000 Subject: ArmPlatformPkg/Bds: Add Linux 'initrd' support to BDS An 'initrd' file can be specified for a Linux kernel. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12169 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/Include/Library/BdsLib.h | 3 +- ArmPkg/Include/Library/BdsUnixLib.h | 1 + ArmPkg/Library/BdsLib/BdsInternal.h | 1 - ArmPkg/Library/BdsLib/BdsLinuxLoader.c | 29 +++++- ArmPlatformPkg/ArmPlatformPkg.dec | 1 + ArmPlatformPkg/Bds/Bds.c | 14 ++- ArmPlatformPkg/Bds/Bds.inf | 1 + ArmPlatformPkg/Bds/BdsInternal.h | 28 +++-- ArmPlatformPkg/Bds/BootMenu.c | 185 +++++++++++++++++++++++---------- ArmPlatformPkg/Bds/BootOption.c | 66 ++++++++++-- ArmPlatformPkg/Bds/BootOptionSupport.c | 53 +++++++--- 11 files changed, 286 insertions(+), 96 deletions(-) diff --git a/ArmPkg/Include/Library/BdsLib.h b/ArmPkg/Include/Library/BdsLib.h index 75d0150..b7aa724 100644 --- a/ArmPkg/Include/Library/BdsLib.h +++ b/ArmPkg/Include/Library/BdsLib.h @@ -62,7 +62,8 @@ BdsConnectAllDrivers ( EFI_STATUS BdsBootLinux ( IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath, - IN CONST CHAR8* Arguments, + IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath, + IN CONST CHAR8* Arguments, IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath ); diff --git a/ArmPkg/Include/Library/BdsUnixLib.h b/ArmPkg/Include/Library/BdsUnixLib.h index d5f5ffa..24fc33a 100644 --- a/ArmPkg/Include/Library/BdsUnixLib.h +++ b/ArmPkg/Include/Library/BdsUnixLib.h @@ -30,6 +30,7 @@ EFI_STATUS BdsBootLinux ( IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath, IN CONST CHAR8* Arguments, IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath ); diff --git a/ArmPkg/Library/BdsLib/BdsInternal.h b/ArmPkg/Library/BdsLib/BdsInternal.h index dd961c8..af69049 100644 --- a/ArmPkg/Library/BdsLib/BdsInternal.h +++ b/ArmPkg/Library/BdsLib/BdsInternal.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c index f463fd9..3c1f134 100644 --- a/ArmPkg/Library/BdsLib/BdsLinuxLoader.c +++ b/ArmPkg/Library/BdsLib/BdsLinuxLoader.c @@ -110,6 +110,8 @@ STATIC EFI_STATUS PrepareAtagList ( IN CONST CHAR8* CommandLineString, + IN EFI_PHYSICAL_ADDRESS InitrdImage, + IN UINTN InitrdImageSize, OUT LINUX_ATAG **AtagBase, OUT UINT32 *AtagSize ) @@ -147,6 +149,17 @@ PrepareAtagList ( // CommandLine setting root device SetupCmdlineTag (CommandLineString); + if (InitrdImageSize > 0 && InitrdImage != 0) { + mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_INITRD2); + mLinuxKernelCurrentAtag->header.type = ATAG_INITRD2; + + mLinuxKernelCurrentAtag->body.initrd2_tag.start = (UINT32)InitrdImage; + mLinuxKernelCurrentAtag->body.initrd2_tag.size = (UINT32)InitrdImageSize; + + // Move pointer to next tag + mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag); + } + // end of tags SetupEndTag(); @@ -194,18 +207,21 @@ PreparePlatformHardware ( EFI_STATUS BdsBootLinux ( IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath, IN CONST CHAR8* Arguments, IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath ) { EFI_STATUS Status; UINT32 LinuxImageSize; + UINT32 InitrdImageSize; UINT32 KernelParamsSize; EFI_PHYSICAL_ADDRESS KernelParamsAddress; UINT32 MachineType; BOOLEAN FdtSupported = FALSE; LINUX_KERNEL LinuxKernel; - EFI_PHYSICAL_ADDRESS LinuxImage;; + EFI_PHYSICAL_ADDRESS LinuxImage; + EFI_PHYSICAL_ADDRESS InitrdImage; PERF_START (NULL, "BDS", NULL, 0); @@ -219,6 +235,15 @@ BdsBootLinux ( } LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage; + if (InitrdDevicePath) { + InitrdImageSize = 0; + Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize); + if (EFI_ERROR(Status)) { + Print (L"ERROR: Did not find initrd image.\n"); + return Status; + } + } + if (FdtDevicePath) { // Load the FDT binary from a device path KernelParamsAddress = LINUX_ATAG_MAX_OFFSET; @@ -240,7 +265,7 @@ BdsBootLinux ( MachineType = PcdGet32(PcdArmMachineType); // By setting address=0 we leave the memory allocation to the function - Status = PrepareAtagList (Arguments, (LINUX_ATAG**)&KernelParamsAddress, &KernelParamsSize); + Status = PrepareAtagList (Arguments, InitrdImage, InitrdImageSize, (LINUX_ATAG**)&KernelParamsAddress, &KernelParamsSize); if(EFI_ERROR(Status)) { Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status); goto Exit; diff --git a/ArmPlatformPkg/ArmPlatformPkg.dec b/ArmPlatformPkg/ArmPlatformPkg.dec index a8c412a..22605dc 100644 --- a/ArmPlatformPkg/ArmPlatformPkg.dec +++ b/ArmPlatformPkg/ArmPlatformPkg.dec @@ -116,6 +116,7 @@ gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"ARM Platform"|VOID*|0x00000019 gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Default Boot Device"|VOID*|0x0000000C gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L""|VOID*|0x0000000D + gArmPlatformTokenSpaceGuid.PcdDefaultBootInitrdPath|L""|VOID*|0x0000000E gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|""|VOID*|0x000000F # PcdDefaultBootType define the type of the binary pointed by PcdDefaultBootDevicePath: # - 0 = an EFI application diff --git a/ArmPlatformPkg/Bds/Bds.c b/ArmPlatformPkg/Bds/Bds.c index 11116ed..a1fa21a 100644 --- a/ArmPlatformPkg/Bds/Bds.c +++ b/ArmPlatformPkg/Bds/Bds.c @@ -203,6 +203,8 @@ DefineDefaultBootEntries ( EFI_STATUS Status; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; EFI_DEVICE_PATH* BootDevicePath; + BDS_LOADER_ARGUMENTS BootArguments; + BDS_LOADER_TYPE BootType; // // If Boot Order does not exist then create a default entry @@ -238,11 +240,19 @@ DefineDefaultBootEntries ( // Create the entry is the Default values are correct if (BootDevicePath != NULL) { + BootType = (BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType); + + if (BootType == BDS_LOADER_KERNEL_LINUX_ATAG) { + BootArguments.LinuxAtagArguments.CmdLine[0] = '\0'; + AsciiStrnCpy (BootArguments.LinuxAtagArguments.CmdLine,(CHAR8*)PcdGetPtr(PcdDefaultBootArgument),BOOT_DEVICE_OPTION_MAX); + BootArguments.LinuxAtagArguments.InitrdPathList = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootInitrdPath)); + } + BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT, (CHAR16*)PcdGetPtr(PcdDefaultBootDescription), BootDevicePath, - (BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType), - (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), + BootType, + &BootArguments, &BdsLoadOption ); FreePool (BdsLoadOption); diff --git a/ArmPlatformPkg/Bds/Bds.inf b/ArmPlatformPkg/Bds/Bds.inf index 5749e7c..bd162fa 100644 --- a/ArmPlatformPkg/Bds/Bds.inf +++ b/ArmPlatformPkg/Bds/Bds.inf @@ -61,6 +61,7 @@ gArmPlatformTokenSpaceGuid.PcdFirmwareVendor gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath + gArmPlatformTokenSpaceGuid.PcdDefaultBootInitrdPath gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument gArmPlatformTokenSpaceGuid.PcdDefaultBootType gArmPlatformTokenSpaceGuid.PcdFdtDevicePath diff --git a/ArmPlatformPkg/Bds/BdsInternal.h b/ArmPlatformPkg/Bds/BdsInternal.h index 9ef36a1..e0bf105 100644 --- a/ArmPlatformPkg/Bds/BdsInternal.h +++ b/ArmPlatformPkg/Bds/BdsInternal.h @@ -35,7 +35,7 @@ #define BOOT_DEVICE_DESCRIPTION_MAX 100 #define BOOT_DEVICE_FILEPATH_MAX 100 -#define BOOT_DEVICE_OPTION_MAX 100 +#define BOOT_DEVICE_OPTION_MAX 300 #define BOOT_DEVICE_ADDRESS_MAX 20 typedef enum { @@ -44,9 +44,19 @@ typedef enum { BDS_LOADER_KERNEL_LINUX_FDT, } BDS_LOADER_TYPE; +typedef struct{ + UINT16 InitrdPathListLength; + EFI_DEVICE_PATH_PROTOCOL *InitrdPathList; + CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX + 1]; +} BDS_LINUX_ATAG_ARGUMENTS; + +typedef union { + BDS_LINUX_ATAG_ARGUMENTS LinuxAtagArguments; +} BDS_LOADER_ARGUMENTS; + typedef struct { - BDS_LOADER_TYPE LoaderType; - CHAR8 Arguments[]; + BDS_LOADER_TYPE LoaderType; + BDS_LOADER_ARGUMENTS Arguments; } BDS_LOADER_OPTIONAL_DATA; typedef enum { @@ -68,6 +78,7 @@ typedef struct { typedef UINT8* EFI_LOAD_OPTION; +/* This is defined by the UEFI specs, don't change it */ typedef struct { LIST_ENTRY Link; @@ -86,8 +97,8 @@ typedef struct _BDS_LOAD_OPTION_SUPPORT { BDS_SUPPORTED_DEVICE_TYPE Type; EFI_STATUS (*ListDevices)(IN OUT LIST_ENTRY* BdsLoadOptionList); BOOLEAN (*IsSupported)(IN BDS_LOAD_OPTION* BdsLoadOption); - EFI_STATUS (*CreateDevicePathNode)(IN BDS_SUPPORTED_DEVICE* BdsLoadOption, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes); - EFI_STATUS (*UpdateDevicePathNode)(IN BDS_LOAD_OPTION *BootOption, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes); + EFI_STATUS (*CreateDevicePathNode)(IN BDS_SUPPORTED_DEVICE* BdsLoadOption, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNode, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes); + EFI_STATUS (*UpdateDevicePathNode)(IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes); } BDS_LOAD_OPTION_SUPPORT; #define LOAD_OPTION_FROM_LINK(a) BASE_CR(a, BDS_LOAD_OPTION, Link) @@ -107,7 +118,8 @@ BootDeviceListSupportedInit ( EFI_STATUS BootDeviceListSupportedFree ( - IN LIST_ENTRY *SupportedDeviceList + IN LIST_ENTRY *SupportedDeviceList, + IN BDS_SUPPORTED_DEVICE *Except ); EFI_STATUS @@ -187,7 +199,7 @@ BootOptionCreate ( IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments, + IN BDS_LOADER_ARGUMENTS *BootArguments, OUT BDS_LOAD_OPTION **BdsLoadOption ); @@ -198,7 +210,7 @@ BootOptionUpdate ( IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments + IN BDS_LOADER_ARGUMENTS *BootArguments ); EFI_STATUS diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index 853ef09..b18a58b 100644 --- a/ArmPlatformPkg/Bds/BootMenu.c +++ b/ArmPlatformPkg/Bds/BootMenu.c @@ -18,28 +18,16 @@ extern EFI_HANDLE mImageHandle; extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList; EFI_STATUS -BootMenuAddBootOption ( - IN LIST_ENTRY *BootOptionsList +SelectBootDevice ( + OUT BDS_SUPPORTED_DEVICE** SupportedBootDevice ) { - EFI_STATUS Status; + EFI_STATUS Status; LIST_ENTRY SupportedDeviceList; UINTN SupportedDeviceCount; - BDS_SUPPORTED_DEVICE* SupportedBootDevice; LIST_ENTRY* Entry; UINTN SupportedDeviceSelected; - CHAR8 AsciiBootOption[BOOT_DEVICE_OPTION_MAX]; - CHAR8 AsciiBootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; - CHAR16 *BootDescription; - UINT32 Attributes; - BDS_LOADER_TYPE BootType; UINTN Index; - BDS_LOAD_OPTION *BdsLoadOption; - EFI_DEVICE_PATH* DevicePath; - EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; - - Attributes = 0; - SupportedBootDevice = NULL; // // List the Boot Devices supported @@ -58,8 +46,8 @@ BootMenuAddBootOption ( Entry = GetNextNode (&SupportedDeviceList,Entry) ) { - SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); - Print(L"[%d] %s\n",SupportedDeviceCount+1,SupportedBootDevice->Description); + *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); + Print(L"[%d] %s\n",SupportedDeviceCount+1,(*SupportedBootDevice)->Description); DEBUG_CODE_BEGIN(); CHAR16* DevicePathTxt; @@ -67,7 +55,7 @@ BootMenuAddBootOption ( Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); ASSERT_EFI_ERROR(Status); - DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(SupportedBootDevice->DevicePathProtocol,TRUE,TRUE); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText((*SupportedBootDevice)->DevicePathProtocol,TRUE,TRUE); Print(L"\t- %s\n",DevicePathTxt); @@ -109,13 +97,46 @@ BootMenuAddBootOption ( ) { if (Index == SupportedDeviceSelected) { - SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); + *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); break; } Index++; } + +EXIT: + BootDeviceListSupportedFree (&SupportedDeviceList, *SupportedBootDevice); + return Status; +} + +EFI_STATUS +BootMenuAddBootOption ( + IN LIST_ENTRY *BootOptionsList + ) +{ + EFI_STATUS Status; + BDS_SUPPORTED_DEVICE* SupportedBootDevice; + BDS_LOADER_ARGUMENTS BootArguments; + CHAR8 AsciiBootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; + CHAR16 *BootDescription; + UINT32 Attributes; + BDS_LOADER_TYPE BootType; + BDS_LOAD_OPTION *BdsLoadOption; + EFI_DEVICE_PATH *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *InitrdPathNode; + + Attributes = 0; + SupportedBootDevice = NULL; + + // List the Boot Devices supported + Status = SelectBootDevice(&SupportedBootDevice); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } // Create the specific device path node + Print(L"File path of the EFI Application or the kernel: "); Status = SupportedBootDevice->Support->CreateDevicePathNode (SupportedBootDevice, &DevicePathNode, &BootType, &Attributes); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; @@ -124,11 +145,29 @@ BootMenuAddBootOption ( // Append the Device Path node to the select device path DevicePath = AppendDevicePathNode (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)DevicePathNode); - Print(L"Arguments to pass to the binary: "); - Status = GetHIInputAscii (AsciiBootOption,BOOT_DEVICE_OPTION_MAX); - if (EFI_ERROR(Status)) { - Status = EFI_ABORTED; - goto FREE_DEVICE_PATH; + if (BootType == BDS_LOADER_KERNEL_LINUX_ATAG) { + // Create the specific device path node + Print(L"File path of the initrd: "); + Status = SupportedBootDevice->Support->CreateDevicePathNode (SupportedBootDevice, &InitrdPathNode, 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; + } + + if (InitrdPathNode != NULL) { + // Append the Device Path node to the select device path + BootArguments.LinuxAtagArguments.InitrdPathList = AppendDevicePathNode (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNode); + } else { + BootArguments.LinuxAtagArguments.InitrdPathList = NULL; + } + + Print(L"Arguments to pass to the binary: "); + Status = GetHIInputAscii (BootArguments.LinuxAtagArguments.CmdLine,BOOT_DEVICE_OPTION_MAX); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } + BootArguments.LinuxAtagArguments.CmdLine[BOOT_DEVICE_OPTION_MAX]= '\0'; } Print(L"Description for this new Entry: "); @@ -143,7 +182,7 @@ BootMenuAddBootOption ( AsciiStrToUnicodeStr (AsciiBootDescription, BootDescription); // Create new entry - Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, AsciiBootOption, &BdsLoadOption); + Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, &BootArguments, &BdsLoadOption); if (!EFI_ERROR(Status)) { InsertTailList (BootOptionsList,&BdsLoadOption->Link); } @@ -153,8 +192,12 @@ BootMenuAddBootOption ( FREE_DEVICE_PATH: FreePool (DevicePath); + EXIT: - BootDeviceListSupportedFree (&SupportedDeviceList); + if (Status == EFI_ABORTED) { + Print(L"\n"); + } + FreePool(SupportedBootDevice); return Status; } @@ -192,8 +235,8 @@ BootMenuSelectBootOption ( DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(BootOption->FilePathList,TRUE,TRUE); Print(L"\t- %s\n",DevicePathTxt); - if ((BootOption->OptionalData != NULL) && (BootOption->OptionalData->Arguments != NULL)) { - Print(L"\t- Arguments: %a\n",BootOption->OptionalData->Arguments); + if ((BDS_LOADER_TYPE)ReadUnaligned32(&BootOption->OptionalData->LoaderType) == BDS_LOADER_KERNEL_LINUX_ATAG) { + Print(L"\t- Arguments: %a\n",BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine); } FreePool(DevicePathTxt); @@ -210,7 +253,7 @@ BootMenuSelectBootOption ( if (EFI_ERROR(Status)) { return Status; } else if ((BootOptionSelected == 0) || (BootOptionSelected >= BootOptionCount)) { - Print(L"Invalid input (max %d)\n",BootOptionCount); + Print(L"Invalid input (max %d)\n",BootOptionCount-1); BootOptionSelected = 0; } } @@ -256,15 +299,14 @@ BootMenuUpdateBootOption ( IN LIST_ENTRY *BootOptionsList ) { - EFI_STATUS Status; - BDS_LOAD_OPTION *BootOption; - BDS_LOAD_OPTION_SUPPORT* DeviceSupport; - CHAR8 AsciiBootOption[BOOT_DEVICE_OPTION_MAX]; - CHAR8 AsciiBootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; - CHAR16 *BootDescription; - EFI_DEVICE_PATH* DevicePath; - UINT32 Attributes; - BDS_LOADER_TYPE BootType; + EFI_STATUS Status; + BDS_LOAD_OPTION *BootOption; + BDS_LOAD_OPTION_SUPPORT *DeviceSupport; + BDS_LOADER_ARGUMENTS BootArguments; + CHAR8 AsciiBootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; + CHAR16 *BootDescription; + EFI_DEVICE_PATH* DevicePath; + BDS_LOADER_TYPE BootType; Status = BootMenuSelectBootOption (BootOptionsList,L"Update entry: ",&BootOption); if (EFI_ERROR(Status)) { @@ -278,27 +320,53 @@ BootMenuUpdateBootOption ( return EFI_UNSUPPORTED; } - Status = DeviceSupport->UpdateDevicePathNode (BootOption,&DevicePath,&BootType,&Attributes); + Print(L"File path of the EFI Application or the kernel: "); + Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, &DevicePath, NULL, NULL); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } - Print(L"Arguments to pass to the binary: "); - if (BootOption->OptionalData) { - AsciiStrnCpy(AsciiBootOption,BootOption->OptionalData->Arguments,BOOT_DEVICE_FILEPATH_MAX); - } else { - AsciiBootOption[0] = '\0'; - } - Status = EditHIInputAscii (AsciiBootOption,BOOT_DEVICE_OPTION_MAX); - if (EFI_ERROR(Status)) { - Status = EFI_ABORTED; - goto FREE_DEVICE_PATH; + BootType = (BDS_LOADER_TYPE)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->LoaderType)); + + // TODO: Allow adding an initrd to a boot entry without one + if (BootType == BDS_LOADER_KERNEL_LINUX_ATAG) { + if (ReadUnaligned16(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathListLength) > 0 + && (EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)) != NULL) { + + Print(L"File path of the initrd: "); + Status = DeviceSupport->UpdateDevicePathNode ( + (EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)), + &BootArguments.LinuxAtagArguments.InitrdPathList, + 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; + } + } else { + BootArguments.LinuxAtagArguments.InitrdPathList = NULL; + BootArguments.LinuxAtagArguments.InitrdPathListLength = 0; + } + + Print(L"Arguments to pass to the binary: "); + if (ReadUnaligned32((CONST UINT32*)&BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine)) { + AsciiStrnCpy(BootArguments.LinuxAtagArguments.CmdLine, + BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine, + BOOT_DEVICE_OPTION_MAX+1); + } else { + BootArguments.LinuxAtagArguments.CmdLine[0] = '\0'; + } + Status = EditHIInputAscii (BootArguments.LinuxAtagArguments.CmdLine, BOOT_DEVICE_OPTION_MAX); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } } Print(L"Description for this new Entry: "); - UnicodeStrToAsciiStr (BootOption->Description,AsciiBootDescription); - Status = EditHIInputAscii (AsciiBootDescription,BOOT_DEVICE_DESCRIPTION_MAX); + UnicodeStrToAsciiStr (BootOption->Description, AsciiBootDescription); + Status = EditHIInputAscii (AsciiBootDescription, BOOT_DEVICE_DESCRIPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; @@ -309,7 +377,7 @@ BootMenuUpdateBootOption ( AsciiStrToUnicodeStr (AsciiBootDescription, BootDescription); // Update the entry - Status = BootOptionUpdate (BootOption, Attributes, BootDescription, DevicePath, BootType, AsciiBootOption); + Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, &BootArguments); FreePool (BootDescription); @@ -441,13 +509,18 @@ BootMenuMain ( DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(BootOption->FilePathList,TRUE,TRUE); Print(L"\t- %s\n",DevicePathTxt); - if (BootOption->OptionalData != NULL) { - Print(L"\t- LoaderType: %d\n", ReadUnaligned32 (&BootOption->OptionalData->LoaderType)); - if (BootOption->OptionalData->Arguments != NULL) { - Print(L"\t- Arguments: %a\n",BootOption->OptionalData->Arguments); + if (ReadUnaligned32(&BootOption->OptionalData->LoaderType) == BDS_LOADER_KERNEL_LINUX_ATAG) { + if (ReadUnaligned16(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathListLength) > 0 + && (EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)) != NULL) { + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)),TRUE,TRUE); + Print(L"\t- Initrd: %s\n", DevicePathTxt); } + + Print(L"\t- Arguments: %a\n", BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine); } + Print(L"\t- LoaderType: %d\n", ReadUnaligned32 (&BootOption->OptionalData->LoaderType)); + FreePool(DevicePathTxt); DEBUG_CODE_END(); diff --git a/ArmPlatformPkg/Bds/BootOption.c b/ArmPlatformPkg/Bds/BootOption.c index dba0d0f..f4ff182 100644 --- a/ArmPlatformPkg/Bds/BootOption.c +++ b/ArmPlatformPkg/Bds/BootOption.c @@ -35,14 +35,21 @@ BootOptionStart ( Status = BdsStartEfiApplication (mImageHandle, BootOption->FilePathList); } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) { - Status = BdsBootLinux (BootOption->FilePathList, BootOption->OptionalData->Arguments, NULL); + Status = BdsBootLinux (BootOption->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL*)ReadUnaligned32((UINT32*)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)), + BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine, + NULL); } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) { // Convert the FDT path into a Device Path Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); ASSERT_EFI_ERROR(Status); FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); - Status = BdsBootLinux (BootOption->FilePathList, BootOption->OptionalData->Arguments, FdtDevicePath); + Status = BdsBootLinux (BootOption->FilePathList, + NULL, + NULL, + FdtDevicePath); + FreePool(FdtDevicePath); } @@ -184,8 +191,8 @@ BootOptionSetFields ( IN UINT32 Attributes, IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, - IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments + IN BDS_LOADER_TYPE BootType, + IN BDS_LOADER_ARGUMENTS* BootArguments ) { EFI_LOAD_OPTION EfiLoadOption; @@ -193,9 +200,12 @@ BootOptionSetFields ( UINTN BootDescriptionSize; UINTN BootOptionalDataSize; UINT16 FilePathListLength; + UINT16 InitrdPathListLength; EFI_DEVICE_PATH_PROTOCOL* DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL* InitrdPathNode; UINTN NodeLength; UINT8* EfiLoadOptionPtr; + UINT8 *InitrdPathListPtr; // If we are overwriting an existent Boot Option then we have to free previously allocated memory if (BootOption->LoadOption) { @@ -203,8 +213,9 @@ BootOptionSetFields ( } BootDescriptionSize = StrSize(BootDescription); - BootOptionalDataSize = sizeof(BDS_LOADER_OPTIONAL_DATA) + - (BootArguments == NULL ? 0 : AsciiStrSize(BootArguments)); + BootOptionalDataSize = sizeof(BDS_LOADER_TYPE) + (BootType == BDS_LOADER_KERNEL_LINUX_ATAG ? + (sizeof(UINT16) + sizeof(EFI_DEVICE_PATH_PROTOCOL*) + BOOT_DEVICE_OPTION_MAX + 1) + : 0); // Compute the size of the FilePath list FilePathListLength = 0; @@ -216,6 +227,18 @@ BootOptionSetFields ( // Add the length of the DevicePath EndType FilePathListLength += DevicePathNodeLength (DevicePathNode); + InitrdPathListLength = 0; + if (BootType == BDS_LOADER_KERNEL_LINUX_ATAG && BootArguments->LinuxAtagArguments.InitrdPathList != NULL) { + // Compute the size of the InitrdPath list + InitrdPathNode = BootArguments->LinuxAtagArguments.InitrdPathList; + while (!IsDevicePathEndType (InitrdPathNode)) { + InitrdPathListLength += DevicePathNodeLength (InitrdPathNode); + InitrdPathNode = NextDevicePathNode (InitrdPathNode); + } + // Add the length of the DevicePath EndType + InitrdPathListLength += DevicePathNodeLength (InitrdPathNode); + } + // Allocate the memory for the EFI Load Option EfiLoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + BootDescriptionSize + FilePathListLength + BootOptionalDataSize; EfiLoadOption = (EFI_LOAD_OPTION)AllocatePool(EfiLoadOptionSize); @@ -257,9 +280,34 @@ BootOptionSetFields ( // Optional Data fields, Do unaligned writes WriteUnaligned32 ((UINT32 *)EfiLoadOptionPtr, BootType); - CopyMem (&((BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments, BootArguments, AsciiStrSize(BootArguments)); BootOption->OptionalData = (BDS_LOADER_OPTIONAL_DATA *)EfiLoadOptionPtr; + if (BootType == BDS_LOADER_KERNEL_LINUX_ATAG) { + CopyMem (&((BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments.LinuxAtagArguments.CmdLine, + BootArguments->LinuxAtagArguments.CmdLine, + AsciiStrSize(BootArguments->LinuxAtagArguments.CmdLine)); + + WriteUnaligned32 ((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathListLength), InitrdPathListLength); + + if ((EFI_DEVICE_PATH_PROTOCOL*)ReadUnaligned32((UINT32 *)&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList) != NULL + && BootArguments->LinuxAtagArguments.InitrdPathList != NULL) { + InitrdPathListPtr = AllocatePool(InitrdPathListLength); + WriteUnaligned32 ((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList), (UINT32)InitrdPathListPtr); + InitrdPathNode = BootArguments->LinuxAtagArguments.InitrdPathList; + + while (!IsDevicePathEndType (InitrdPathNode)) { + NodeLength = DevicePathNodeLength(InitrdPathNode); + CopyMem (InitrdPathListPtr, InitrdPathNode, NodeLength); + InitrdPathListPtr += NodeLength; + InitrdPathNode = NextDevicePathNode (InitrdPathNode); + } + + // Set the End Device Path Type + SetDevicePathEndNode (InitrdPathListPtr); + } else { + WriteUnaligned32 ((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList), (UINT32)NULL); + } + } // If this function is called at the creation of the Boot Device entry (not at the update) the // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry if (BootOption->LoadOptionSize == 0) { @@ -279,7 +327,7 @@ BootOptionCreate ( IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments, + IN BDS_LOADER_ARGUMENTS* BootArguments, OUT BDS_LOAD_OPTION **BdsLoadOption ) { @@ -344,7 +392,7 @@ BootOptionUpdate ( IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments + IN BDS_LOADER_ARGUMENTS* BootArguments ) { EFI_STATUS Status; diff --git a/ArmPlatformPkg/Bds/BootOptionSupport.c b/ArmPlatformPkg/Bds/BootOptionSupport.c index a4396b5..336bcb9 100644 --- a/ArmPlatformPkg/Bds/BootOptionSupport.c +++ b/ArmPlatformPkg/Bds/BootOptionSupport.c @@ -41,7 +41,7 @@ BdsLoadOptionFileSystemCreateDevicePath ( EFI_STATUS BdsLoadOptionFileSystemUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes @@ -67,7 +67,7 @@ BdsLoadOptionMemMapCreateDevicePath ( EFI_STATUS BdsLoadOptionMemMapUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes @@ -93,7 +93,7 @@ BdsLoadOptionPxeCreateDevicePath ( EFI_STATUS BdsLoadOptionPxeUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes @@ -119,7 +119,7 @@ BdsLoadOptionTftpCreateDevicePath ( EFI_STATUS BdsLoadOptionTftpUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes @@ -180,7 +180,8 @@ BootDeviceListSupportedInit ( EFI_STATUS BootDeviceListSupportedFree ( - IN LIST_ENTRY *SupportedDeviceList + IN LIST_ENTRY *SupportedDeviceList, + IN BDS_SUPPORTED_DEVICE *Except ) { LIST_ENTRY *Entry; @@ -190,7 +191,9 @@ BootDeviceListSupportedFree ( while (Entry != SupportedDeviceList) { SupportedDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); Entry = RemoveEntryList (Entry); - FreePool(SupportedDevice); + if (SupportedDevice != Except) { + FreePool(SupportedDevice); + } } return EFI_SUCCESS; @@ -336,12 +339,16 @@ BdsLoadOptionFileSystemCreateDevicePath ( CHAR16 *BootFilePath; UINTN BootFilePathSize; - Print(L"File path of the EFI Application or the kernel: "); Status = GetHIInputAscii (AsciiBootFilePath,BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR(Status)) { return EFI_ABORTED; } + if (AsciiStrSize(AsciiBootFilePath) == 1) { + *DevicePathNode = NULL; + return EFI_NOT_FOUND; + } + // Convert Ascii into Unicode BootFilePath = (CHAR16*)AllocatePool(AsciiStrSize(AsciiBootFilePath) * sizeof(CHAR16)); AsciiStrToUnicodeStr (AsciiBootFilePath, BootFilePath); @@ -355,7 +362,10 @@ BdsLoadOptionFileSystemCreateDevicePath ( CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); FreePool (BootFilePath); - Status = BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); + if (BootType != NULL || Attributes != NULL) { + Status = BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); + } + if (EFI_ERROR(Status)) { FreePool (FilePathDevicePath); } else { @@ -367,7 +377,7 @@ BdsLoadOptionFileSystemCreateDevicePath ( EFI_STATUS BdsLoadOptionFileSystemUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes @@ -381,16 +391,21 @@ BdsLoadOptionFileSystemUpdateDevicePath ( FILEPATH_DEVICE_PATH* FilePathDevicePath; EFI_DEVICE_PATH* DevicePath; - DevicePath = DuplicateDevicePath (BootOption->FilePathList); - EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); + DevicePath = DuplicateDevicePath(OldDevicePath); - Print(L"File path of the EFI Application or the kernel: "); + EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); + UnicodeStrToAsciiStr (EndingDevicePath->PathName,AsciiBootFilePath); Status = EditHIInputAscii (AsciiBootFilePath,BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR(Status)) { return Status; } + if (AsciiStrSize(AsciiBootFilePath) == 1) { + *NewDevicePath = NULL; + return EFI_NOT_FOUND; + } + // Convert Ascii into Unicode BootFilePath = (CHAR16*)AllocatePool(AsciiStrSize(AsciiBootFilePath) * sizeof(CHAR16)); AsciiStrToUnicodeStr (AsciiBootFilePath, BootFilePath); @@ -409,7 +424,11 @@ BdsLoadOptionFileSystemUpdateDevicePath ( *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath); FreePool(DevicePath); - return BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); + if (BootType != NULL || Attributes != NULL) { + return BootDeviceGetType (FilePathDevicePath->PathName, BootType, Attributes); + } + + return EFI_SUCCESS; } BOOLEAN @@ -561,7 +580,7 @@ BdsLoadOptionMemMapCreateDevicePath ( EFI_STATUS BdsLoadOptionMemMapUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes @@ -573,7 +592,7 @@ BdsLoadOptionMemMapUpdateDevicePath ( MEMMAP_DEVICE_PATH* EndingDevicePath; EFI_DEVICE_PATH* DevicePath; - DevicePath = DuplicateDevicePath (BootOption->FilePathList); + DevicePath = DuplicateDevicePath (OldDevicePath); EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); Print(L"Starting Address of the binary: "); @@ -679,7 +698,7 @@ BdsLoadOptionPxeCreateDevicePath ( EFI_STATUS BdsLoadOptionPxeUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes @@ -847,7 +866,7 @@ BdsLoadOptionTftpCreateDevicePath ( EFI_STATUS BdsLoadOptionTftpUpdateDevicePath ( - IN BDS_LOAD_OPTION *BootOption, + IN EFI_DEVICE_PATH *OldDevicePath, OUT EFI_DEVICE_PATH_PROTOCOL** NewDevicePath, OUT BDS_LOADER_TYPE *BootType, OUT UINT32 *Attributes -- cgit v1.1