From 5eeb088ad64124229b32a5593fada578b935e207 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 19 Jul 2022 17:12:48 +0200 Subject: OvmfPkg/QemuBootOrderLib: add StoreQemuBootOrder() The function reads the boot order from qemu fw_cfg, translates it into device paths and stores them in 'QemuBootOrderNNNN' variables. In case there is no boot ordering configured the function will do nothing. Use case: Allow applications loaded via 'qemu -kernel bootloader.efi' obey the boot order. Signed-off-by: Gerd Hoffmann Reviewed-by: Ard Biesheuvel --- OvmfPkg/Include/Library/QemuBootOrderLib.h | 14 +++ .../Library/PlatformBootManagerLib/BdsPlatform.c | 5 + .../Library/QemuBootOrderLib/QemuBootOrderLib.c | 122 +++++++++++++++++++++ .../Library/QemuBootOrderLib/QemuBootOrderLib.inf | 1 + OvmfPkg/OvmfPkg.dec | 1 + 5 files changed, 143 insertions(+) diff --git a/OvmfPkg/Include/Library/QemuBootOrderLib.h b/OvmfPkg/Include/Library/QemuBootOrderLib.h index 9f06439..f036929 100644 --- a/OvmfPkg/Include/Library/QemuBootOrderLib.h +++ b/OvmfPkg/Include/Library/QemuBootOrderLib.h @@ -48,6 +48,20 @@ ConnectDevicesFromQemu ( ); /** + Write qemu boot order to uefi variables. + + Attempt to retrieve the "bootorder" fw_cfg file from QEMU. Translate + the OpenFirmware device paths therein to UEFI device path fragments. + + On Success store the device path in QemuBootOrderNNNN variables. +**/ +VOID +EFIAPI +StoreQemuBootOrder ( + VOID + ); + +/** Set the boot order based on configuration retrieved from QEMU. diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c index 51016a5..98f6f07 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -1695,6 +1695,11 @@ PlatformBootManagerAfterConsole ( PciAcpiInitialization (); // + // Write qemu bootorder to efi variables + // + StoreQemuBootOrder (); + + // // Process QEMU's -kernel command line option // TryRunningQemuKernel (); diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c index 67d29ac..398de7f 100644 --- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c +++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c @@ -1687,6 +1687,128 @@ FreeFwCfg: } /** + Write qemu boot order to uefi variables. + + Attempt to retrieve the "bootorder" fw_cfg file from QEMU. Translate + the OpenFirmware device paths therein to UEFI device path fragments. + + On Success store the device path in QemuBootOrderNNNN variables. +**/ +VOID +EFIAPI +StoreQemuBootOrder ( + VOID + ) +{ + RETURN_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + CHAR8 *FwCfg; + EFI_STATUS EfiStatus; + EXTRA_ROOT_BUS_MAP *ExtraPciRoots; + CONST CHAR8 *FwCfgPtr; + UINTN TranslatedSize; + CHAR16 Translated[TRANSLATION_OUTPUT_SIZE]; + UINTN VariableIndex = 0; + CHAR16 VariableName[20]; + + Status = QemuFwCfgFindFile ("bootorder", &FwCfgItem, &FwCfgSize); + if (RETURN_ERROR (Status)) { + return; + } + + if (FwCfgSize == 0) { + return; + } + + FwCfg = AllocatePool (FwCfgSize); + if (FwCfg == NULL) { + return; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (FwCfgSize, FwCfg); + if (FwCfg[FwCfgSize - 1] != '\0') { + Status = RETURN_INVALID_PARAMETER; + goto FreeFwCfg; + } + + DEBUG ((DEBUG_VERBOSE, "%a: FwCfg:\n", __FUNCTION__)); + DEBUG ((DEBUG_VERBOSE, "%a\n", FwCfg)); + DEBUG ((DEBUG_VERBOSE, "%a: FwCfg: \n", __FUNCTION__)); + + if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) { + EfiStatus = CreateExtraRootBusMap (&ExtraPciRoots); + if (EFI_ERROR (EfiStatus)) { + Status = (RETURN_STATUS)EfiStatus; + goto FreeFwCfg; + } + } else { + ExtraPciRoots = NULL; + } + + // + // Translate each OpenFirmware path to a UEFI devpath prefix. + // + FwCfgPtr = FwCfg; + TranslatedSize = ARRAY_SIZE (Translated); + Status = TranslateOfwPath ( + &FwCfgPtr, + ExtraPciRoots, + Translated, + &TranslatedSize + ); + while (!RETURN_ERROR (Status)) { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Convert the UEFI devpath prefix to binary representation. + // + ASSERT (Translated[TranslatedSize] == L'\0'); + DevicePath = ConvertTextToDevicePath (Translated); + if (DevicePath == NULL) { + Status = RETURN_OUT_OF_RESOURCES; + goto FreeExtraPciRoots; + } + + UnicodeSPrint ( + VariableName, + sizeof (VariableName), + L"QemuBootOrder%04d", + VariableIndex++ + ); + DEBUG ((DEBUG_INFO, "%a: %s = %s\n", __FUNCTION__, VariableName, Translated)); + gRT->SetVariable ( + VariableName, + &gQemuBootOrderGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + GetDevicePathSize (DevicePath), + DevicePath + ); + FreePool (DevicePath); + + // + // Move to the next OFW devpath. + // + TranslatedSize = ARRAY_SIZE (Translated); + Status = TranslateOfwPath ( + &FwCfgPtr, + ExtraPciRoots, + Translated, + &TranslatedSize + ); + } + +FreeExtraPciRoots: + if (ExtraPciRoots != NULL) { + DestroyExtraRootBusMap (ExtraPciRoots); + } + +FreeFwCfg: + FreePool (FwCfg); +} + +/** Convert the UEFI DevicePath to full text representation with DevPathToText, then match the UEFI device path fragment in Translated against it. diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf index 7c02f04..211344f 100644 --- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf +++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf @@ -49,6 +49,7 @@ [Guids] gEfiGlobalVariableGuid gVirtioMmioTransportGuid + gQemuBootOrderGuid [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 5af76a5..6b1296b 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -146,6 +146,7 @@ gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} gConfidentialComputingSevSnpBlobGuid = {0x067b1f5f, 0xcf26, 0x44c5, {0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42}} gUefiOvmfPkgPlatformInfoGuid = {0xdec9b486, 0x1f16, 0x47c7, {0x8f, 0x68, 0xdf, 0x1a, 0x41, 0x88, 0x8b, 0xa5}} + gQemuBootOrderGuid = {0x668f4529, 0x63d0, 0x4bb5, {0xb6, 0x5d, 0x6f, 0xbb, 0x9d, 0x36, 0xa4, 0x4a}} [Ppis] # PPI whose presence in the PPI database signals that the TPM base address -- cgit v1.1