On 02/25/20 10:39, Ard Biesheuvel wrote: > This is the UEFI counterpart to my Linux series which generalizes > mixed mode support into a feature that requires very little internal > knowledge about the architecture specifics of booting Linux on the > part of the bootloader or firmware. > > Instead, we add a .compat PE/COFF header containing an array of > PE_COMPAT nodes containing <machine type, entrypoint> tuples that > describe alternate entrypoints into the image for different native > machine types, e.g., IA-32 in a 64-bit image so it can be booted > from IA-32 firmware. > > This patch implements the PE/COFF emulator protocol to take this new > section into account, so that such images can simply be loaded via > LoadImage/StartImage, e.g., straight from the shell. > > This feature is based on the EDK2 specific PE/COFF emulator protocol > that was introduced in commit 57df17fe26cd ("MdeModulePkg/DxeCore: > invoke the emulator protocol for foreign images", 2019-04-14). > > Signed-off-by: Ard Biesheuvel <ard.biesheu...@linaro.org> > --- > OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c | 140 > ++++++++++++++++++++ > OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf | 36 +++++ > OvmfPkg/OvmfPkgIa32.dsc | 5 + > OvmfPkg/OvmfPkgIa32.fdf | 4 + > 4 files changed, 185 insertions(+) > > diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c > b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c > new file mode 100644 > index 000000000000..d2ae03eabf7f > --- /dev/null > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c > @@ -0,0 +1,140 @@ > +/** @file > + * PE/COFF emulator protocol implementation to start Linux kernel > + * images from non-native firmware > + * > + * Copyright (c) 2020, ARM Ltd. All rights reserved.<BR> > + * > + * SPDX-License-Identifier: BSD-2-Clause-Patent > + * > + */ > + > +#include <PiDxe.h> > + > +#include <Library/BaseMemoryLib.h> > +#include <Library/PeCoffLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiDriverEntryPoint.h>
(1) Do we actually need anything from "MdePkg/Include/Library/UefiDriverEntryPoint.h"? (We need it in [LibraryClasses], in the INF file, yes, but likely not as an #include in the C source.) > + > +#include <Protocol/PeCoffImageEmulator.h> > + > +#pragma pack(1) (2) whitespace please > +typedef struct { > + UINT8 Type; > + UINT8 Size; > + UINT16 MachineType; > + UINT32 EntryPoint; > +} PE_COMPAT_TYPE1; > +#pragma pack() (3) ditto. With these addressed: Acked-by: Laszlo Ersek <ler...@redhat.com> Thanks! Laszlo > + > +STATIC > +BOOLEAN > +EFIAPI > +IsImageSupported ( > + IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, > + IN UINT16 ImageType, > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL > + ) > +{ > + return ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; > +} > + > +STATIC > +EFI_IMAGE_ENTRY_POINT > +EFIAPI > +GetCompatEntryPoint ( > + IN EFI_PHYSICAL_ADDRESS ImageBase > + ) > +{ > + EFI_IMAGE_DOS_HEADER *DosHdr; > + UINTN PeCoffHeaderOffset; > + EFI_IMAGE_NT_HEADERS32 *Pe32; > + EFI_IMAGE_SECTION_HEADER *Section; > + UINTN NumberOfSections; > + PE_COMPAT_TYPE1 *PeCompat; > + > + DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase; > + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { > + return NULL; > + } > + > + PeCoffHeaderOffset = DosHdr->e_lfanew; > + Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageBase + PeCoffHeaderOffset); > + > + Section = (EFI_IMAGE_SECTION_HEADER *)((UINTN)&Pe32->OptionalHeader + > + > Pe32->FileHeader.SizeOfOptionalHeader); > + NumberOfSections = (UINTN)Pe32->FileHeader.NumberOfSections; > + > + while (NumberOfSections--) { > + if (!CompareMem (Section->Name, ".compat", sizeof (Section->Name))) { > + // > + // Dereference the section contents to find the mixed mode entry point > + // > + PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)ImageBase + > Section->VirtualAddress); > + > + while (PeCompat->Type != 0) { > + if (PeCompat->Type == 1 && > + PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) && > + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) { > + > + return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + > PeCompat->EntryPoint); > + } > + PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size); > + } > + } > + Section++; > + } > + return NULL; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +RegisterImage ( > + IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, > + IN EFI_PHYSICAL_ADDRESS ImageBase, > + IN UINT64 ImageSize, > + IN OUT EFI_IMAGE_ENTRY_POINT *EntryPoint > + ) > +{ > + EFI_IMAGE_ENTRY_POINT CompatEntryPoint; > + > + CompatEntryPoint = GetCompatEntryPoint (ImageBase); > + if (CompatEntryPoint == NULL) { > + return EFI_UNSUPPORTED; > + } > + > + *EntryPoint = CompatEntryPoint; > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +UnregisterImage ( > + IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This, > + IN EFI_PHYSICAL_ADDRESS ImageBase > + ) > +{ > + return EFI_SUCCESS; > +} > + > +STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mCompatLoaderPeCoffEmuProtocol = > { > + IsImageSupported, > + RegisterImage, > + UnregisterImage, > + EDKII_PECOFF_IMAGE_EMULATOR_VERSION, > + EFI_IMAGE_MACHINE_X64 > +}; > + > +EFI_STATUS > +EFIAPI > +CompatImageLoaderDxeEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + return gBS->InstallProtocolInterface (&ImageHandle, > + &gEdkiiPeCoffImageEmulatorProtocolGuid, > + EFI_NATIVE_INTERFACE, > + &mCompatLoaderPeCoffEmuProtocol); > +} > diff --git a/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf > b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf > new file mode 100644 > index 000000000000..82369384fbe6 > --- /dev/null > +++ b/OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf > @@ -0,0 +1,36 @@ > +## @file > +# PE/COFF emulator protocol implementation to start Linux kernel > +# images from non-native firmware > +# > +# Copyright (c) 2020, ARM Ltd. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 1.27 > + BASE_NAME = CompatImageLoaderDxe > + FILE_GUID = 1019f54a-2560-41b2-87b0-6750b98f3eff > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = CompatImageLoaderDxeEntryPoint > + > +[Sources] > + CompatImageLoaderDxe.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + PeCoffLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + > +[Protocols] > + gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES > + > +[Depex] > + TRUE > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc > index 870eb7aa7429..a996c0a7a7c9 100644 > --- a/OvmfPkg/OvmfPkgIa32.dsc > +++ b/OvmfPkg/OvmfPkgIa32.dsc > @@ -33,6 +33,7 @@ [Defines] > DEFINE SOURCE_DEBUG_ENABLE = FALSE > DEFINE TPM2_ENABLE = FALSE > DEFINE TPM2_CONFIG_ENABLE = FALSE > + DEFINE LOAD_X64_ON_IA32_ENABLE = FALSE > > # > # Network definition > @@ -932,3 +933,7 @@ [Components] > SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf > !endif > !endif > + > +!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE > + OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf > +!endif > diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf > index b6cd5da4f2b3..ff8d80859fb9 100644 > --- a/OvmfPkg/OvmfPkgIa32.fdf > +++ b/OvmfPkg/OvmfPkgIa32.fdf > @@ -354,6 +354,10 @@ [FV.DXEFV] > !endif > !endif > > +!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE > +INF OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf > +!endif > + > > ################################################################################ > > [FV.FVMAIN_COMPACT] > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54809): https://edk2.groups.io/g/devel/message/54809 Mute This Topic: https://groups.io/mt/71530301/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-