mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-24 06:04:52 +02:00
OvmfPkg IA32: add support for loading X64 images
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). Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2564 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
parent
d8dd54f071
commit
d55cfdc51f
143
OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
Normal file
143
OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/** @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/DebugLib.h>
|
||||||
|
#include <Library/PeCoffLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
|
||||||
|
#include <Protocol/PeCoffImageEmulator.h>
|
||||||
|
|
||||||
|
#pragma pack (1)
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Type;
|
||||||
|
UINT8 Size;
|
||||||
|
UINT16 MachineType;
|
||||||
|
UINT32 EntryPoint;
|
||||||
|
} PE_COMPAT_TYPE1;
|
||||||
|
#pragma pack ()
|
||||||
|
|
||||||
|
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;
|
||||||
|
UINTN PeCompatEnd;
|
||||||
|
|
||||||
|
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);
|
||||||
|
PeCompatEnd = (UINTN)(VOID *)PeCompat + Section->Misc.VirtualSize;
|
||||||
|
|
||||||
|
while (PeCompat->Type != 0 && (UINTN)(VOID *)PeCompat < PeCompatEnd) {
|
||||||
|
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);
|
||||||
|
ASSERT ((UINTN)(VOID *)PeCompat < PeCompatEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
37
OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
Normal file
37
OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
## @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
|
||||||
|
DebugLib
|
||||||
|
PeCoffLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
TRUE
|
@ -33,6 +33,7 @@
|
|||||||
DEFINE SOURCE_DEBUG_ENABLE = FALSE
|
DEFINE SOURCE_DEBUG_ENABLE = FALSE
|
||||||
DEFINE TPM2_ENABLE = FALSE
|
DEFINE TPM2_ENABLE = FALSE
|
||||||
DEFINE TPM2_CONFIG_ENABLE = FALSE
|
DEFINE TPM2_CONFIG_ENABLE = FALSE
|
||||||
|
DEFINE LOAD_X64_ON_IA32_ENABLE = FALSE
|
||||||
|
|
||||||
#
|
#
|
||||||
# Network definition
|
# Network definition
|
||||||
@ -932,3 +933,7 @@
|
|||||||
SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
|
SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
|
||||||
!endif
|
!endif
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
|
||||||
|
OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
|
||||||
|
!endif
|
||||||
|
@ -354,6 +354,10 @@ INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
|
|||||||
!endif
|
!endif
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
|
||||||
|
INF OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
|
||||||
|
!endif
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
[FV.FVMAIN_COMPACT]
|
[FV.FVMAIN_COMPACT]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user