EFI_STATUS BdsLoadOptionFileSystemUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { EFI_STATUS Status; CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; UINTN BootFilePathSize; FILEPATH_DEVICE_PATH* EndingDevicePath; FILEPATH_DEVICE_PATH* FilePathDevicePath; EFI_DEVICE_PATH* DevicePath; DevicePath = DuplicateDevicePath (OldDevicePath); EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); Print(L"File path of the %s: ", FileName); StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX); Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); if (EFI_ERROR(Status)) { return Status; } BootFilePathSize = StrSize(BootFilePath); if (BootFilePathSize == 2) { *NewDevicePath = NULL; return EFI_NOT_FOUND; } // Create the FilePath Device Path node FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); if (NULL == FilePathDevicePath) { return EFI_INVALID_PARAMETER; } FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH; FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP; SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); // Generate the new Device Path by replacing the last node by the updated node SetDevicePathEndNode (EndingDevicePath); *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath); FreePool(DevicePath); return EFI_SUCCESS; }
EFI_STATUS BdsLoadOptionMemMapUpdateDevicePath ( IN EFI_DEVICE_PATH *OldDevicePath, IN CHAR16* FileName, OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath ) { EFI_STATUS Status; CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX]; CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX]; MEMMAP_DEVICE_PATH* EndingDevicePath; EFI_DEVICE_PATH* DevicePath; DevicePath = DuplicateDevicePath (OldDevicePath); EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); Print(L"Starting Address of the %s: ", FileName); UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress); Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { //return EFI_ABORTED; goto Exit; } Print(L"Ending Address of the %s: ", FileName); UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress); Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX); if (EFI_ERROR(Status)) { goto Exit; //return EFI_ABORTED; } EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress); EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress); Exit: if (EFI_ERROR(Status)) { FreePool(DevicePath); } else { *NewDevicePath = DevicePath; } return Status; }
EFI_STATUS GenerateDeviceDescriptionName ( IN EFI_HANDLE Handle, IN OUT CHAR16* Description ) { EFI_STATUS Status; EFI_COMPONENT_NAME_PROTOCOL* ComponentName2Protocol; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; CHAR16* DriverName; CHAR16* DevicePathTxt; EFI_DEVICE_PATH* DevicePathNode; ComponentName2Protocol = NULL; Status = gBS->HandleProtocol (Handle, &gEfiComponentName2ProtocolGuid, (VOID **)&ComponentName2Protocol); if (!EFI_ERROR(Status)) { //TODO: Fixme. we must find the best langague Status = ComponentName2Protocol->GetDriverName (ComponentName2Protocol,"en",&DriverName); if (!EFI_ERROR(Status)) { StrnCpy (Description, DriverName, BOOT_DEVICE_DESCRIPTION_MAX); } } if (EFI_ERROR(Status)) { // Use the lastest non null entry of the Device path as a description Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); if (EFI_ERROR(Status)) { return Status; } // Convert the last non end-type Device Path Node in text for the description DevicePathNode = GetLastDevicePathNode (DevicePathProtocol); Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); ASSERT_EFI_ERROR(Status); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePathNode, TRUE, TRUE); StrnCpy (Description, DevicePathTxt, BOOT_DEVICE_DESCRIPTION_MAX); FreePool (DevicePathTxt); } return EFI_SUCCESS; }
EFI_STATUS BootMenuUpdateBootOption ( IN LIST_ENTRY *BootOptionsList ) { 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 IsPrintable; BOOLEAN IsUnicode; DisplayBootOptions (BootOptionsList); Status = SelectBootOption (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->FilePathList, &DeviceSupport); if (EFI_ERROR(Status)) { Print(L"Not possible to retrieve the supported device for the update\n"); return EFI_UNSUPPORTED; } Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (DeviceSupport->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 { BootType = BDS_LOADER_EFI_APPLICATION; } 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); 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); 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); // Free the InitrdPathNodes created by Support->CreateDevicePathNode() FreePool (InitrdPathNodes); 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), sizeof (CmdLine)); CmdLine[sizeof (CmdLine) - 1] = '\0'; } 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) { // // The size in bytes of the string, final zero included, should // be equal to or at least lower than "BootOption->OptionalDataSize" // and the "IsPrintableString()" has already tested that the length // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX, // final '\0' included. We can thus copy the string for editing // using "CopyMem()". Furthermore, note that in the case of an Unicode // string "StrnCpy()" and "StrCpy()" can not be used to copy the // string because the data pointed to by "BootOption->OptionalData" // is not necessarily 2-byte aligned. // if (IsUnicode) { CopyMem ( UnicodeCmdLine, BootOption->OptionalData, MIN (sizeof (UnicodeCmdLine), BootOption->OptionalDataSize) ); } else { CopyMem ( CmdLine, BootOption->OptionalData, MIN (sizeof (CmdLine), 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: "); 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; } // Update the entry 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; }