Implement the new EDK2 PE/COFF image emulator protocol so that we can remove the EBC specific handling in the DXE core and other places in the core code.
Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org> Reviewed-by: Michael D Kinney <michael.d.kin...@intel.com> --- MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf | 3 + MdeModulePkg/Universal/EbcDxe/EbcDxe.inf | 3 + MdeModulePkg/Universal/EbcDxe/EbcInt.c | 121 +++++++++++++++++++- MdeModulePkg/Universal/EbcDxe/EbcInt.h | 3 + 4 files changed, 126 insertions(+), 4 deletions(-) diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf index 8f293f5c7c29..c7a9d519b080 100644 --- a/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf +++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf @@ -89,6 +89,8 @@ BaseMemoryLib DebugLib BaseLib + CacheMaintenanceLib + PeCoffLib [Protocols] gEfiDebugSupportProtocolGuid ## PRODUCES @@ -98,6 +100,7 @@ gEfiEbcSimpleDebuggerProtocolGuid ## SOMETIMES_CONSUMES gEfiPciRootBridgeIoProtocolGuid ## SOMETIMES_CONSUMES gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES [Guids] gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf index d6ee6194a0c8..ecccf2c57ffe 100644 --- a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf +++ b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf @@ -57,7 +57,9 @@ MdeModulePkg/MdeModulePkg.dec [LibraryClasses] + CacheMaintenanceLib MemoryAllocationLib + PeCoffLib UefiBootServicesTableLib BaseMemoryLib UefiDriverEntryPoint @@ -68,6 +70,7 @@ [Protocols] gEfiDebugSupportProtocolGuid ## PRODUCES gEfiEbcProtocolGuid ## PRODUCES + gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES gEfiEbcVmTestProtocolGuid ## SOMETIMES_PRODUCES gEfiEbcSimpleDebuggerProtocolGuid ## SOMETIMES_CONSUMES diff --git a/MdeModulePkg/Universal/EbcDxe/EbcInt.c b/MdeModulePkg/Universal/EbcDxe/EbcInt.c index 727ba8bcae44..3376b5e45184 100644 --- a/MdeModulePkg/Universal/EbcDxe/EbcInt.c +++ b/MdeModulePkg/Universal/EbcDxe/EbcInt.c @@ -349,6 +349,119 @@ UINTN mStackNum = 0; EFI_EVENT mEbcPeriodicEvent; VM_CONTEXT *mVmPtr = NULL; +/** + Check whether the emulator supports executing a certain PE/COFF image + + @param[in] This This pointer for EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL + structure + @param[in] ImageType Whether the image is an application, a boot time + driver or a runtime driver. + @param[in] DevicePath Path to device where the image originated + (e.g., a PCI option ROM) + + @retval TRUE The image is supported by the emulator + @retval FALSE The image is not supported by the emulator. +**/ +BOOLEAN +EFIAPI +EbcIsImageSupported ( + IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, + IN UINT16 ImageType, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL + ) +{ + if (ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && + ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) { + return FALSE; + } + return TRUE; +} + +/** + Register a supported PE/COFF image with the emulator. After this call + completes successfully, the PE/COFF image may be started as usual, and + it is the responsibility of the emulator implementation that any branch + into the code section of the image (including returns from functions called + from the foreign code) is executed as if it were running on the machine + type it was built for. + + @param[in] This This pointer for + EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL structure + @param[in] ImageBase The base address in memory of the PE/COFF image + @param[in] ImageSize The size in memory of the PE/COFF image + @param[in,out] EntryPoint The entry point of the PE/COFF image. Passed by + reference so that the emulator may modify it. + + @retval EFI_SUCCESS The image was registered with the emulator and + can be started as usual. + @retval other The image could not be registered. + + If the PE/COFF machine type or image type are not supported by the emulator, + then ASSERT(). +**/ +EFI_STATUS +EFIAPI +EbcRegisterImage ( + IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize, + IN OUT EFI_IMAGE_ENTRY_POINT *EntryPoint + ) +{ + DEBUG_CODE_BEGIN (); + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_STATUS Status; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + + ImageContext.Handle = (VOID *)(UINTN)ImageBase; + ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (ImageContext.Machine == EFI_IMAGE_MACHINE_EBC); + ASSERT (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION || + ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER); + DEBUG_CODE_END (); + + EbcRegisterICacheFlush (NULL, + (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange); + + return EbcCreateThunk (NULL, (VOID *)(UINTN)ImageBase, + (VOID *)(UINTN)*EntryPoint, (VOID **)EntryPoint); +} + +/** + Unregister a PE/COFF image that has been registered with the emulator. + This should be done before the image is unloaded from memory. + + @param[in] This This pointer for EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL + structure + @param[in] ImageBase The base address in memory of the PE/COFF image + + @retval EFI_SUCCESS The image was unregistered with the emulator. + @retval other Image could not be unloaded. +**/ +EFI_STATUS +EFIAPI +EbcUnregisterImage ( + IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS ImageBase + ) +{ + return EbcUnloadImage (NULL, (VOID *)(UINTN)ImageBase); +} + +STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mPeCoffEmuProtocol = { + EbcIsImageSupported, + EbcRegisterImage, + EbcUnregisterImage, + EDKII_PECOFF_IMAGE_EMULATOR_VERSION, + EFI_IMAGE_MACHINE_EBC +}; /** Initializes the VM EFI interface. Allocates memory for the VM interface @@ -437,11 +550,11 @@ InitializeEbcDriver ( // Add the protocol so someone can locate us if we haven't already. // if (!Installed) { - Status = gBS->InstallProtocolInterface ( + Status = gBS->InstallMultipleProtocolInterfaces ( &ImageHandle, - &gEfiEbcProtocolGuid, - EFI_NATIVE_INTERFACE, - EbcProtocol + &gEfiEbcProtocolGuid, EbcProtocol, + &gEdkiiPeCoffImageEmulatorProtocolGuid, &mPeCoffEmuProtocol, + NULL ); if (EFI_ERROR (Status)) { FreePool (EbcProtocol); diff --git a/MdeModulePkg/Universal/EbcDxe/EbcInt.h b/MdeModulePkg/Universal/EbcDxe/EbcInt.h index 8aa7a4abbd63..9b25e91f951c 100644 --- a/MdeModulePkg/Universal/EbcDxe/EbcInt.h +++ b/MdeModulePkg/Universal/EbcDxe/EbcInt.h @@ -23,9 +23,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include <Protocol/Ebc.h> #include <Protocol/EbcVmTest.h> #include <Protocol/EbcSimpleDebugger.h> +#include <Protocol/PeCoffImageEmulator.h> #include <Library/BaseLib.h> +#include <Library/CacheMaintenanceLib.h> #include <Library/DebugLib.h> +#include <Library/PeCoffLib.h> #include <Library/UefiDriverEntryPoint.h> #include <Library/BaseMemoryLib.h> #include <Library/UefiBootServicesTableLib.h> -- 2.17.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#39011): https://edk2.groups.io/g/devel/message/39011 Mute This Topic: https://groups.io/mt/31133144/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-