X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ArmPlatformPkg%2FBds%2FBootMenu.c;h=62e7927defd6cc8eb291667f57b192520e619519;hb=5382a857be5061106f36d18640f685588cb827d5;hp=a2360d14f5e50c34b33d96df9afc44a04f77c975;hpb=ea46ebbe6a5a579ff341071a13ae625e15edae64;p=mirror_edk2.git diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index a2360d14f5..62e7927def 100644 --- a/ArmPlatformPkg/Bds/BootMenu.c +++ b/ArmPlatformPkg/Bds/BootMenu.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011, ARM Limited. All rights reserved. +* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved. * * This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License @@ -14,31 +14,23 @@ #include "BdsInternal.h" +#include + 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; // // List the Boot Devices supported @@ -57,16 +49,16 @@ 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; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; - Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); + 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); @@ -93,7 +85,7 @@ BootMenuAddBootOption ( Status = EFI_ABORTED; goto EXIT; } else if ((SupportedDeviceSelected == 0) || (SupportedDeviceSelected > SupportedDeviceCount)) { - Print(L"Invalid input (max %d)\n",SupportedDeviceSelected); + Print(L"Invalid input (max %d)\n",SupportedDeviceCount); SupportedDeviceSelected = 0; } } @@ -108,91 +100,214 @@ BootMenuAddBootOption ( ) { if (Index == SupportedDeviceSelected) { - SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); + *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); break; } Index++; } - // Create the specific device path node - Status = SupportedBootDevice->Support->CreateDevicePathNode (SupportedBootDevice, &DevicePathNode, &BootType, &Attributes); +EXIT: + BootDeviceListSupportedFree (&SupportedDeviceList, *SupportedBootDevice); + return Status; +} + +EFI_STATUS +BootMenuAddBootOption ( + IN LIST_ENTRY *BootOptionsList + ) +{ + EFI_STATUS Status; + BDS_SUPPORTED_DEVICE* SupportedBootDevice; + ARM_BDS_LOADER_ARGUMENTS* BootArguments; + CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; + CHAR8 AsciiCmdLine[BOOT_DEVICE_OPTION_MAX]; + CHAR16 CmdLine[BOOT_DEVICE_OPTION_MAX]; + UINT32 Attributes; + ARM_BDS_LOADER_TYPE BootType; + BDS_LOAD_OPTION_ENTRY *BdsLoadOptionEntry; + EFI_DEVICE_PATH *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathNodes; + EFI_DEVICE_PATH_PROTOCOL *InitrdPathNodes; + EFI_DEVICE_PATH_PROTOCOL *InitrdPath; + UINTN CmdLineSize; + BOOLEAN InitrdSupport; + UINTN InitrdSize; + UINT8* OptionalData; + UINTN OptionalDataSize; + BOOLEAN RequestBootType; + + Attributes = 0; + SupportedBootDevice = NULL; + + // List the Boot Devices supported + Status = SelectBootDevice (&SupportedBootDevice); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } - // 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); + // Create the specific device path node + RequestBootType = TRUE; + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes, &RequestBootType); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; - goto FREE_DEVICE_PATH; + goto EXIT; + } + // Append the Device Path to the selected device path + DevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)DevicePathNodes); + if (DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + if (RequestBootType) { + Status = BootDeviceGetType (DevicePath, &BootType, &Attributes); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + } else { + BootType = BDS_LOADER_EFI_APPLICATION; + } + + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + Print(L"Add an initrd: "); + Status = GetHIInputBoolean (&InitrdSupport); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + + if (InitrdSupport) { + // Create the specific device path node + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes, 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 (InitrdPathNodes != NULL) { + // Append the Device Path to the selected device path + InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); + if (InitrdPath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT; + } + } else { + InitrdPath = NULL; + } + } else { + InitrdPath = NULL; + } + + Print(L"Arguments to pass to the binary: "); + Status = GetHIInputAscii (AsciiCmdLine, BOOT_DEVICE_OPTION_MAX); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } + + CmdLineSize = AsciiStrSize (AsciiCmdLine); + InitrdSize = GetDevicePathSize (InitrdPath); + + OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize; + BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); + + BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + BootArguments->LinuxArguments.InitrdSize = InitrdSize; + CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), AsciiCmdLine, CmdLineSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + + OptionalData = (UINT8*)BootArguments; + } else { + Print (L"Arguments to pass to the EFI Application: "); + Status = GetHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX); + if (EFI_ERROR (Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + + OptionalData = (UINT8*)CmdLine; + OptionalDataSize = StrSize (CmdLine); } Print(L"Description for this new Entry: "); - Status = GetHIInputAscii (AsciiBootDescription,BOOT_DEVICE_DESCRIPTION_MAX); + Status = GetHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } - // Convert Ascii into Unicode - BootDescription = (CHAR16*)AllocatePool(AsciiStrSize(AsciiBootDescription) * sizeof(CHAR16)); - AsciiStrToUnicodeStr (AsciiBootDescription, BootDescription); - // Create new entry - Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, AsciiBootOption, &BdsLoadOption); + BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY)); + Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize, &BdsLoadOptionEntry->BdsLoadOption); if (!EFI_ERROR(Status)) { - InsertTailList (BootOptionsList,&BdsLoadOption->Link); + InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link); } - FreePool (BootDescription); - FREE_DEVICE_PATH: FreePool (DevicePath); EXIT: - BootDeviceListSupportedFree (&SupportedDeviceList); + if (Status == EFI_ABORTED) { + Print(L"\n"); + } + FreePool(SupportedBootDevice); return Status; } STATIC EFI_STATUS BootMenuSelectBootOption ( - IN LIST_ENTRY *BootOptionsList, - IN CONST CHAR16* InputStatement, - OUT BDS_LOAD_OPTION **BdsLoadOption + IN LIST_ENTRY* BootOptionsList, + IN CONST CHAR16* InputStatement, + OUT BDS_LOAD_OPTION_ENTRY** BdsLoadOptionEntry ) { - EFI_STATUS Status; - LIST_ENTRY* Entry; - BDS_LOAD_OPTION *BootOption; - UINTN BootOptionSelected; - UINTN BootOptionCount; - UINTN Index; + EFI_STATUS Status; + LIST_ENTRY* Entry; + BDS_LOAD_OPTION* BdsLoadOption; + UINTN BootOptionSelected; + UINTN BootOptionCount; + UINTN Index; + BOOLEAN IsUnicode; // Display the list of supported boot devices - BootOptionCount = 1; + BootOptionCount = 0; for (Entry = GetFirstNode (BootOptionsList); !IsNull (BootOptionsList,Entry); - Entry = GetNextNode (BootOptionsList,Entry) + Entry = GetNextNode (BootOptionsList, Entry) ) { - BootOption = LOAD_OPTION_FROM_LINK(Entry); - Print(L"[%d] %s\n",BootOptionCount,BootOption->Description); + BdsLoadOption = LOAD_OPTION_FROM_LINK(Entry); + + Print (L"[%d] %s\n", (BootOptionCount + 1), BdsLoadOption->Description); DEBUG_CODE_BEGIN(); CHAR16* DevicePathTxt; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; + ARM_BDS_LOADER_TYPE LoaderType; + ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); ASSERT_EFI_ERROR(Status); - DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(BootOption->FilePathList,TRUE,TRUE); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(BdsLoadOption->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); + OptionalData = BdsLoadOption->OptionalData; + if (IS_ARM_BDS_BOOTENTRY (BdsLoadOption)) { + LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); + if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) { + Print (L"\t- Arguments: %a\n",&OptionalData->Arguments.LinuxArguments + 1); + } + } else if (OptionalData != NULL) { + if (IsPrintableString (OptionalData, &IsUnicode)) { + if (IsUnicode) { + Print (L"\t- Arguments: %s\n", OptionalData); + } else { + AsciiPrint ("\t- Arguments: %a\n", OptionalData); + } + } } FreePool(DevicePathTxt); @@ -201,6 +316,19 @@ BootMenuSelectBootOption ( BootOptionCount++; } + // Check if a valid boot option(s) is found + if (BootOptionCount == 0) { + if (StrCmp (InputStatement, DELETE_BOOT_ENTRY) == 0) { + Print (L"Nothing to remove!\n"); + } else if (StrCmp (InputStatement, UPDATE_BOOT_ENTRY) == 0) { + Print (L"Couldn't find valid boot entries\n"); + } else{ + Print (L"No supported Boot Entry.\n"); + } + + return EFI_NOT_FOUND; + } + // Get the index of the boot device to delete BootOptionSelected = 0; while (BootOptionSelected == 0) { @@ -208,7 +336,7 @@ BootMenuSelectBootOption ( Status = GetHIInputInteger (&BootOptionSelected); if (EFI_ERROR(Status)) { return Status; - } else if ((BootOptionSelected == 0) || (BootOptionSelected >= BootOptionCount)) { + } else if ((BootOptionSelected == 0) || (BootOptionSelected > BootOptionCount)) { Print(L"Invalid input (max %d)\n",BootOptionCount); BootOptionSelected = 0; } @@ -217,12 +345,12 @@ BootMenuSelectBootOption ( // Get the structure of the Boot device to delete Index = 1; for (Entry = GetFirstNode (BootOptionsList); - !IsNull (BootOptionsList,Entry); + !IsNull (BootOptionsList, Entry); Entry = GetNextNode (BootOptionsList,Entry) ) { if (Index == BootOptionSelected) { - *BdsLoadOption = LOAD_OPTION_FROM_LINK(Entry); + *BdsLoadOptionEntry = LOAD_OPTION_ENTRY_FROM_LINK(Entry); break; } Index++; @@ -236,16 +364,22 @@ BootMenuRemoveBootOption ( IN LIST_ENTRY *BootOptionsList ) { - EFI_STATUS Status; - BDS_LOAD_OPTION *BootOption; + EFI_STATUS Status; + BDS_LOAD_OPTION_ENTRY* BootOptionEntry; - Status = BootMenuSelectBootOption (BootOptionsList,L"Delete entry: ",&BootOption); + Status = BootMenuSelectBootOption (BootOptionsList, DELETE_BOOT_ENTRY, &BootOptionEntry); if (EFI_ERROR(Status)) { return Status; } + // If the Boot Option was attached to a list remove it + if (!IsListEmpty (&BootOptionEntry->Link)) { + // Remove the entry from the list + RemoveEntryList (&BootOptionEntry->Link); + } + // Delete the BDS Load option structures - BootOptionDelete (BootOption); + BootOptionDelete (BootOptionEntry->BdsLoadOption); return EFI_SUCCESS; } @@ -255,67 +389,262 @@ 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; - - Status = BootMenuSelectBootOption (BootOptionsList,L"Update entry: ",&BootOption); + EFI_STATUS Status; + BDS_LOAD_OPTION_ENTRY *BootOptionEntry; + BDS_LOAD_OPTION *BootOption; + BDS_LOAD_OPTION_SUPPORT* DeviceSupport; + ARM_BDS_LOADER_ARGUMENTS* BootArguments; + CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; + CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX]; + CHAR16 UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX]; + EFI_DEVICE_PATH *DevicePath; + EFI_DEVICE_PATH *TempInitrdPath; + ARM_BDS_LOADER_TYPE BootType; + ARM_BDS_LOADER_OPTIONAL_DATA* LoaderOptionalData; + ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; + EFI_DEVICE_PATH *InitrdPathNodes; + EFI_DEVICE_PATH *InitrdPath; + UINTN InitrdSize; + UINTN CmdLineSize; + BOOLEAN InitrdSupport; + UINT8* OptionalData; + UINTN OptionalDataSize; + BOOLEAN RequestBootType; + BOOLEAN IsPrintable; + BOOLEAN IsUnicode; + + Status = BootMenuSelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry); if (EFI_ERROR(Status)) { return Status; } + BootOption = BootOptionEntry->BdsLoadOption; // Get the device support for this Boot Option - Status = BootDeviceGetDeviceSupport (BootOption,&DeviceSupport); + Status = BootDeviceGetDeviceSupport (BootOption->FilePathList, &DeviceSupport); if (EFI_ERROR(Status)) { - Print(L"Impossible to retrieve the supported device for the update\n"); + Print(L"Not possible to retrieve the supported device for the update\n"); return EFI_UNSUPPORTED; } - Status = DeviceSupport->UpdateDevicePathNode (BootOption,&DevicePath,&BootType,&Attributes); + RequestBootType = TRUE; + Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath, &RequestBootType); 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); + if (RequestBootType) { + Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + } + + LoaderOptionalData = BootOption->OptionalData; + if (LoaderOptionalData != NULL) { + BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType)); } else { - AsciiBootOption[0] = '\0'; + BootType = BDS_LOADER_EFI_APPLICATION; } - Status = EditHIInputAscii (AsciiBootOption,BOOT_DEVICE_OPTION_MAX); - if (EFI_ERROR(Status)) { - Status = EFI_ABORTED; - goto FREE_DEVICE_PATH; + + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + LinuxArguments = &LoaderOptionalData->Arguments.LinuxArguments; + + CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); + + InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); + if (InitrdSize > 0) { + Print(L"Keep the initrd: "); + } else { + Print(L"Add an initrd: "); + } + Status = GetHIInputBoolean (&InitrdSupport); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + + if (InitrdSupport) { + if (InitrdSize > 0) { + // Case we update the initrd device path + Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath, 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; + } + InitrdSize = GetDevicePathSize (InitrdPath); + } else { + // Case we create the initrd device path + + Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes, 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 (InitrdPathNodes != NULL) { + // Duplicate Linux kernel Device Path + TempInitrdPath = DuplicateDevicePath (BootOption->FilePathList); + // Replace Linux kernel Node by EndNode + SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath)); + // Append the Device Path to the selected device path + InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); + FreePool (TempInitrdPath); + if (InitrdPath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT; + } + InitrdSize = GetDevicePathSize (InitrdPath); + } else { + InitrdPath = NULL; + } + } + } else { + InitrdSize = 0; + } + + Print(L"Arguments to pass to the binary: "); + if (CmdLineSize > 0) { + AsciiStrnCpy(CmdLine, (CONST CHAR8*)(LinuxArguments + 1), CmdLineSize); + } else { + CmdLine[0] = '\0'; + } + Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } + + CmdLineSize = AsciiStrSize (CmdLine); + + OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize; + BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); + BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + BootArguments->LinuxArguments.InitrdSize = InitrdSize; + CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + + OptionalData = (UINT8*)BootArguments; + } else { + Print (L"Arguments to pass to the EFI Application: "); + + if (BootOption->OptionalDataSize > 0) { + IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode); + if (IsPrintable) { + if (IsUnicode) { + StrnCpy (UnicodeCmdLine, BootOption->OptionalData, BootOption->OptionalDataSize / 2); + } else { + AsciiStrnCpy (CmdLine, BootOption->OptionalData, BootOption->OptionalDataSize); + } + } + } else { + UnicodeCmdLine[0] = L'\0'; + IsPrintable = TRUE; + IsUnicode = TRUE; + } + + // We do not request arguments for OptionalData that cannot be printed + if (IsPrintable) { + if (IsUnicode) { + Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX); + if (EFI_ERROR (Status)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } + + OptionalData = (UINT8*)UnicodeCmdLine; + OptionalDataSize = StrSize (UnicodeCmdLine); + } else { + Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); + if (EFI_ERROR (Status)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } + + OptionalData = (UINT8*)CmdLine; + OptionalDataSize = AsciiStrSize (CmdLine); + } + } else { + // We keep the former OptionalData + OptionalData = BootOption->OptionalData; + OptionalDataSize = BootOption->OptionalDataSize; + } } Print(L"Description for this new Entry: "); - UnicodeStrToAsciiStr (BootOption->Description,AsciiBootDescription); - Status = EditHIInputAscii (AsciiBootDescription,BOOT_DEVICE_DESCRIPTION_MAX); + StrnCpy (BootDescription, BootOption->Description, BOOT_DEVICE_DESCRIPTION_MAX); + Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } - // Convert Ascii into Unicode - BootDescription = (CHAR16*)AllocatePool(AsciiStrSize(AsciiBootDescription) * sizeof(CHAR16)); - AsciiStrToUnicodeStr (AsciiBootDescription, BootDescription); - // Update the entry - Status = BootOptionUpdate (BootOption, Attributes, BootDescription, DevicePath, BootType, AsciiBootOption); - - FreePool (BootDescription); + Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize); FREE_DEVICE_PATH: FreePool (DevicePath); EXIT: + if (Status == EFI_ABORTED) { + Print(L"\n"); + } + return Status; +} + +EFI_STATUS +UpdateFdtPath ( + IN LIST_ENTRY *BootOptionsList + ) +{ + EFI_STATUS Status; + UINTN FdtDevicePathSize; + BDS_SUPPORTED_DEVICE *SupportedBootDevice; + EFI_DEVICE_PATH_PROTOCOL *FdtDevicePathNodes; + EFI_DEVICE_PATH_PROTOCOL *FdtDevicePath; + + Status = SelectBootDevice (&SupportedBootDevice); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + + // Create the specific device path node + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes, NULL); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + + if (FdtDevicePathNodes != NULL) { + // Append the Device Path node to the select device path + FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes); + FdtDevicePathSize = GetDevicePathSize (FdtDevicePath); + Status = gRT->SetVariable ( + (CHAR16*)L"Fdt", + &gArmGlobalVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + FdtDevicePathSize, + FdtDevicePath + ); + ASSERT_EFI_ERROR(Status); + } else { + gRT->SetVariable ( + (CHAR16*)L"Fdt", + &gArmGlobalVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, + NULL + ); + ASSERT_EFI_ERROR(Status); + } + +EXIT: + if (Status == EFI_ABORTED) { + Print(L"\n"); + } + FreePool(SupportedBootDevice); return Status; } @@ -326,6 +655,7 @@ struct BOOT_MANAGER_ENTRY { { L"Add Boot Device Entry", BootMenuAddBootOption }, { L"Update Boot Device Entry", BootMenuUpdateBootOption }, { L"Remove Boot Device Entry", BootMenuRemoveBootOption }, + { L"Update FDT path", UpdateFdtPath }, }; EFI_STATUS @@ -351,24 +681,26 @@ BootMenuManager ( Print(L"Choice: "); Status = GetHIInputInteger (&OptionSelected); if (EFI_ERROR(Status) || (OptionSelected == (BootManagerEntryCount+1))) { + if (EFI_ERROR(Status)) { + Print(L"\n"); + } return EFI_SUCCESS; } else if ((OptionSelected > 0) && (OptionSelected <= BootManagerEntryCount)) { - Status = BootManagerEntries[OptionSelected-1].Callback (BootOptionsList); + BootManagerEntries[OptionSelected-1].Callback (BootOptionsList); } } - - return EFI_SUCCESS; + // Should never go here } EFI_STATUS -BootEBL ( +BootShell ( IN LIST_ENTRY *BootOptionsList ) { EFI_STATUS Status; // Start EFI Shell - Status = BdsLoadApplication(mImageHandle, L"Ebl"); + Status = BdsLoadApplication (mImageHandle, L"Shell", 0, NULL); if (Status == EFI_NOT_FOUND) { Print (L"Error: EFI Application not found.\n"); } else if (EFI_ERROR(Status)) { @@ -382,7 +714,7 @@ struct BOOT_MAIN_ENTRY { CONST CHAR16* Description; EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList); } BootMainEntries[] = { - { L"EBL", BootEBL }, + { L"Shell", BootShell }, { L"Boot Manager", BootMenuManager }, }; @@ -392,22 +724,24 @@ 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; + BOOLEAN IsUnicode; + + BootOption = NULL; BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY); - - // Get Boot#### list - BootOptionList (&BootOptionsList); while (TRUE) { + // Get Boot#### list + BootOptionList (&BootOptionsList); + OptionCount = 1; // Display the Boot options @@ -418,24 +752,66 @@ BootMenuMain ( { BootOption = LOAD_OPTION_FROM_LINK(Entry); - Print(L"[%d] %s\n",OptionCount,BootOption->Description); + Print(L"[%d] %s\n", OptionCount, BootOption->Description); DEBUG_CODE_BEGIN(); CHAR16* DevicePathTxt; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; - - Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); - ASSERT_EFI_ERROR(Status); - DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(BootOption->FilePathList,TRUE,TRUE); + ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; + UINTN CmdLineSize; + ARM_BDS_LOADER_TYPE LoaderType; + + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); + if (EFI_ERROR(Status)) { + // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe) + DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathToTextProtocol\n")); + return Status; + } + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootOption->FilePathList, TRUE, TRUE); Print(L"\t- %s\n",DevicePathTxt); - if (BootOption->OptionalData != NULL) { - Print(L"\t- LoaderType: %d\n",BootOption->OptionalData->LoaderType); - if (BootOption->OptionalData->Arguments != NULL) { - Print(L"\t- Arguments: %a\n",BootOption->OptionalData->Arguments); + + // If it is a supported BootEntry then print its details + 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 (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) { + CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( + GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize)), TRUE, TRUE); + Print(L"\t- Initrd: %s\n", DevicePathTxt); + } + if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize) > 0) { + Print(L"\t- Arguments: %a\n", (&OptionalData->Arguments.LinuxArguments + 1)); + } } - } + switch (LoaderType) { + case BDS_LOADER_EFI_APPLICATION: + Print(L"\t- LoaderType: EFI Application\n"); + break; + + case BDS_LOADER_KERNEL_LINUX_ATAG: + 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"); + break; + + default: + Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType); + } + } else if (BootOption->OptionalData != NULL) { + if (IsPrintableString (BootOption->OptionalData, &IsUnicode)) { + if (IsUnicode) { + Print (L"\t- Arguments: %s\n", BootOption->OptionalData); + } else { + AsciiPrint ("\t- Arguments: %a\n", BootOption->OptionalData); + } + } + } FreePool(DevicePathTxt); DEBUG_CODE_END(); @@ -482,6 +858,5 @@ BootMenuMain ( Status = BootOptionStart (BootOption); } } - - return Status; + // Should never go here }