summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/Library
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2022-08-15 10:47:51 +0200
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2022-09-10 08:23:27 +0000
commit477b5b7d55783f930a7741f4187ccd4f227ebc86 (patch)
tree6b9178d4a7623c1839cabfd63b0407f3404ee288 /OvmfPkg/Library
parent34969dd260b4ecaba8d4a58d32fc07bd0fee57f9 (diff)
downloadedk2-477b5b7d55783f930a7741f4187ccd4f227ebc86.tar.gz
edk2-477b5b7d55783f930a7741f4187ccd4f227ebc86.tar.bz2
edk2-477b5b7d55783f930a7741f4187ccd4f227ebc86.zip
OvmfPkg: Introduce alternate UefiDriverEntrypoint to inhibit driver load
Add a new library that can be incorporated into any driver built from source, and which permits loading of the driver to be inhibited based on the value of a QEMU fw_cfg boolean variable. This will be used in a subsequent patch to allow dispatch of the IPv4 and IPv6 network protocol driver to be controlled from the QEMU command line. This approach is based on the notion that all UEFI and DXE drivers share a single UefiDriverEntryPoint implementation, which we can easily swap out at build time with one that will abort execution based on the value of some QEMU fw_cfg variable. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'OvmfPkg/Library')
-rw-r--r--OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.c148
-rw-r--r--OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.inf57
2 files changed, 205 insertions, 0 deletions
diff --git a/OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.c b/OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.c
new file mode 100644
index 0000000000..debbacb42f
--- /dev/null
+++ b/OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.c
@@ -0,0 +1,148 @@
+/** @file
+ Entry point to a EFI/DXE driver. This version is specific to QEMU, and ties
+ dispatch of the driver in question on the value of a QEMU fw_cfg boolean
+ variable which is referenced by name via a fixed pointer PCD.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2022, Google LLC. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/LoadedImage.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/QemuFwCfgSimpleParserLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+/**
+ Unloads an image from memory.
+
+ This function is a callback that a driver registers to do cleanup
+ when the UnloadImage boot service function is called.
+
+ @param ImageHandle The handle to the image to unload.
+
+ @return Status returned by all unload().
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+_DriverUnloadHandler (
+ EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // If an UnloadImage() handler is specified, then call it
+ //
+ Status = ProcessModuleUnloadList (ImageHandle);
+
+ //
+ // If the driver specific unload handler does not return an error, then call
+ // all of the library destructors. If the unload handler returned an error,
+ // then the driver can not be unloaded, and the library destructors should
+ // not be called
+ //
+ if (!EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, gST);
+ }
+
+ //
+ // Return the status from the driver specific unload handler
+ //
+ return Status;
+}
+
+/**
+ The entry point of PE/COFF Image for a DXE Driver, DXE Runtime Driver, or
+ UEFI Driver.
+
+ @param ImageHandle The image handle of the DXE Driver, DXE
+ Runtime Driver, or UEFI Driver.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, or
+ UEFI Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
+ SystemTable->Hdr.Revision.
+ @retval Other Return value from
+ ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_ModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ RETURN_STATUS RetStatus;
+ BOOLEAN Enabled;
+
+ if (_gUefiDriverRevision != 0) {
+ //
+ // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI
+ // spec revision of the driver
+ //
+ if (SystemTable->Hdr.Revision < _gUefiDriverRevision) {
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+ }
+
+ //
+ // Call constructor for all libraries
+ //
+ ProcessLibraryConstructorList (ImageHandle, SystemTable);
+
+ //
+ // Install unload handler...
+ //
+ if (_gDriverUnloadImageCount != 0) {
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ LoadedImage->Unload = _DriverUnloadHandler;
+ }
+
+ RetStatus = QemuFwCfgParseBool (
+ FixedPcdGetPtr (PcdEntryPointOverrideFwCfgVarName),
+ &Enabled
+ );
+ if (!RETURN_ERROR (RetStatus) && !Enabled) {
+ //
+ // The QEMU fw_cfg variable tells us not to load this image. So abort.
+ //
+ Status = EFI_ABORTED;
+ } else {
+ //
+ // Call the driver entry point
+ //
+ Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
+ }
+
+ //
+ // If all of the drivers returned errors, or we if are aborting, then invoke
+ // all of the library destructors
+ //
+ if (EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, SystemTable);
+ }
+
+ //
+ // Return the cumulative return status code from all of the driver entry
+ // points
+ //
+ return Status;
+}
diff --git a/OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.inf b/OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.inf
new file mode 100644
index 0000000000..263e00ceef
--- /dev/null
+++ b/OvmfPkg/Library/UefiDriverEntryPointFwCfgOverrideLib/UefiDriverEntryPointFwCfgOverrideLib.inf
@@ -0,0 +1,57 @@
+## @file
+# Entry point to a EFI/DXE driver. This version is specific to QEMU, and ties
+# dispatch of the driver in question on the value of a QEMU fw_cfg boolean
+# variable which is referenced by name via a fixed pointer PCD.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2022, Google LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = UefiDriverEntryPointFwCfgOverrideLib
+ FILE_GUID = 73349b79-f148-43b8-b24e-9098a6f3e1db
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiDriverEntryPoint|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER
+
+[Sources]
+ UefiDriverEntryPointFwCfgOverrideLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ QemuFwCfgSimpleParserLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdEntryPointOverrideFwCfgVarName
+
+#
+# For UEFI drivers, these architectural protocols defined in PI 1.0 spec need
+# to be appended and merged to the final dependency section.
+#
+[Depex.common.UEFI_DRIVER]
+ gEfiBdsArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid AND
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiMonotonicCounterArchProtocolGuid AND
+ gEfiRealTimeClockArchProtocolGuid AND
+ gEfiResetArchProtocolGuid AND
+ gEfiRuntimeArchProtocolGuid AND
+ gEfiSecurityArchProtocolGuid AND
+ gEfiTimerArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiWatchdogTimerArchProtocolGuid