MdeModulePkg/EbcDxe: implement the PE/COFF emulator protocol

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.biesheuvel@linaro.org>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
This commit is contained in:
Ard Biesheuvel 2018-09-14 20:55:36 +02:00
parent 26d60374b8
commit 095fcfc606
4 changed files with 126 additions and 4 deletions

View File

@ -84,6 +84,8 @@
BaseMemoryLib
DebugLib
BaseLib
CacheMaintenanceLib
PeCoffLib
[Protocols]
gEfiDebugSupportProtocolGuid ## PRODUCES
@ -93,6 +95,7 @@
gEfiEbcSimpleDebuggerProtocolGuid ## SOMETIMES_CONSUMES
gEfiPciRootBridgeIoProtocolGuid ## SOMETIMES_CONSUMES
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES
[Guids]
gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID

View File

@ -51,7 +51,9 @@
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
CacheMaintenanceLib
MemoryAllocationLib
PeCoffLib
UefiBootServicesTableLib
BaseMemoryLib
UefiDriverEntryPoint
@ -62,6 +64,7 @@
[Protocols]
gEfiDebugSupportProtocolGuid ## PRODUCES
gEfiEbcProtocolGuid ## PRODUCES
gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES
gEfiEbcVmTestProtocolGuid ## SOMETIMES_PRODUCES
gEfiEbcSimpleDebuggerProtocolGuid ## SOMETIMES_CONSUMES

View File

@ -343,6 +343,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
@ -431,11 +544,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);

View File

@ -17,9 +17,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#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>