public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 1/1] OvmfPkg/QemuBootOrderLib: add StoreQemuBootOrder()
@ 2022-07-19 15:12 Gerd Hoffmann
  2022-09-06 16:56 ` Ard Biesheuvel
  0 siblings, 1 reply; 2+ messages in thread
From: Gerd Hoffmann @ 2022-07-19 15:12 UTC (permalink / raw)
  To: devel
  Cc: Anthony Perard, Jiewen Yao, Ard Biesheuvel,
	Marc-André Lureau, Oliver Steffen, Jordan Justen,
	Stefan Berger, Gerd Hoffmann, Julien Grall, Pawel Polawski

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 <kraxel@redhat.com>
---
 OvmfPkg/OvmfPkg.dec                           |   1 +
 .../QemuBootOrderLib/QemuBootOrderLib.inf     |   1 +
 OvmfPkg/Include/Library/QemuBootOrderLib.h    |  14 ++
 .../PlatformBootManagerLib/BdsPlatform.c      |   5 +
 .../QemuBootOrderLib/QemuBootOrderLib.c       | 122 ++++++++++++++++++
 5 files changed, 143 insertions(+)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 5af76a540529..6b1296b15afa 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -146,6 +146,7 @@ [Guids]
   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
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
index 7c02f04e7009..211344fb0b89 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
@@ -49,6 +49,7 @@ [LibraryClasses]
 [Guids]
   gEfiGlobalVariableGuid
   gVirtioMmioTransportGuid
+  gQemuBootOrderGuid
 
 [FeaturePcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation
diff --git a/OvmfPkg/Include/Library/QemuBootOrderLib.h b/OvmfPkg/Include/Library/QemuBootOrderLib.h
index 9f06439aed1e..f0369298a134 100644
--- a/OvmfPkg/Include/Library/QemuBootOrderLib.h
+++ b/OvmfPkg/Include/Library/QemuBootOrderLib.h
@@ -47,6 +47,20 @@ ConnectDevicesFromQemu (
   VOID
   );
 
+/**
+  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 51016a5548cb..98f6f07341ec 100644
--- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
+++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -1694,6 +1694,11 @@ PlatformBootManagerAfterConsole (
   //
   PciAcpiInitialization ();
 
+  //
+  // Write qemu bootorder to efi variables
+  //
+  StoreQemuBootOrder ();
+
   //
   // Process QEMU's -kernel command line option
   //
diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
index 67d29ac6429f..398de7fab4ba 100644
--- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
+++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
@@ -1686,6 +1686,128 @@ ConnectDevicesFromQemu (
   return Status;
 }
 
+/**
+  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: <end>\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,
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH 1/1] OvmfPkg/QemuBootOrderLib: add StoreQemuBootOrder()
  2022-07-19 15:12 [PATCH 1/1] OvmfPkg/QemuBootOrderLib: add StoreQemuBootOrder() Gerd Hoffmann
@ 2022-09-06 16:56 ` Ard Biesheuvel
  0 siblings, 0 replies; 2+ messages in thread
From: Ard Biesheuvel @ 2022-09-06 16:56 UTC (permalink / raw)
  To: Gerd Hoffmann
  Cc: devel, Anthony Perard, Jiewen Yao, Marc-André Lureau,
	Oliver Steffen, Jordan Justen, Stefan Berger, Julien Grall,
	Pawel Polawski

On Tue, 19 Jul 2022 at 17:12, Gerd Hoffmann <kraxel@redhat.com> wrote:
>
> 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 <kraxel@redhat.com>

Reviewed-by: Ard Biesheuvel <ardb@kernel.org

Merged as #3298



> ---
>  OvmfPkg/OvmfPkg.dec                           |   1 +
>  .../QemuBootOrderLib/QemuBootOrderLib.inf     |   1 +
>  OvmfPkg/Include/Library/QemuBootOrderLib.h    |  14 ++
>  .../PlatformBootManagerLib/BdsPlatform.c      |   5 +
>  .../QemuBootOrderLib/QemuBootOrderLib.c       | 122 ++++++++++++++++++
>  5 files changed, 143 insertions(+)
>
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index 5af76a540529..6b1296b15afa 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -146,6 +146,7 @@ [Guids]
>    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
> diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
> index 7c02f04e7009..211344fb0b89 100644
> --- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
> +++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
> @@ -49,6 +49,7 @@ [LibraryClasses]
>  [Guids]
>    gEfiGlobalVariableGuid
>    gVirtioMmioTransportGuid
> +  gQemuBootOrderGuid
>
>  [FeaturePcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation
> diff --git a/OvmfPkg/Include/Library/QemuBootOrderLib.h b/OvmfPkg/Include/Library/QemuBootOrderLib.h
> index 9f06439aed1e..f0369298a134 100644
> --- a/OvmfPkg/Include/Library/QemuBootOrderLib.h
> +++ b/OvmfPkg/Include/Library/QemuBootOrderLib.h
> @@ -47,6 +47,20 @@ ConnectDevicesFromQemu (
>    VOID
>    );
>
> +/**
> +  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 51016a5548cb..98f6f07341ec 100644
> --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
> +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
> @@ -1694,6 +1694,11 @@ PlatformBootManagerAfterConsole (
>    //
>    PciAcpiInitialization ();
>
> +  //
> +  // Write qemu bootorder to efi variables
> +  //
> +  StoreQemuBootOrder ();
> +
>    //
>    // Process QEMU's -kernel command line option
>    //
> diff --git a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
> index 67d29ac6429f..398de7fab4ba 100644
> --- a/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
> +++ b/OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.c
> @@ -1686,6 +1686,128 @@ ConnectDevicesFromQemu (
>    return Status;
>  }
>
> +/**
> +  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: <end>\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,
> --
> 2.36.1
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-09-06 16:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-07-19 15:12 [PATCH 1/1] OvmfPkg/QemuBootOrderLib: add StoreQemuBootOrder() Gerd Hoffmann
2022-09-06 16:56 ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox