2 * PE/COFF emulator protocol implementation to start Linux kernel
3 * images from non-native firmware
5 * Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
7 * SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/PeCoffLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
18 #include <Protocol/PeCoffImageEmulator.h>
33 IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
*This
,
35 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath OPTIONAL
38 return ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
;
45 IN EFI_PHYSICAL_ADDRESS ImageBase
48 EFI_IMAGE_DOS_HEADER
*DosHdr
;
49 UINTN PeCoffHeaderOffset
;
50 EFI_IMAGE_NT_HEADERS32
*Pe32
;
51 EFI_IMAGE_SECTION_HEADER
*Section
;
52 UINTN NumberOfSections
;
53 PE_COMPAT_TYPE1
*PeCompat
;
56 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(UINTN
)ImageBase
;
57 if (DosHdr
->e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
61 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
62 Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
)ImageBase
+ PeCoffHeaderOffset
);
64 Section
= (EFI_IMAGE_SECTION_HEADER
*)((UINTN
)&Pe32
->OptionalHeader
+
65 Pe32
->FileHeader
.SizeOfOptionalHeader
);
66 NumberOfSections
= (UINTN
)Pe32
->FileHeader
.NumberOfSections
;
68 while (NumberOfSections
--) {
69 if (!CompareMem (Section
->Name
, ".compat", sizeof (Section
->Name
))) {
71 // Dereference the section contents to find the mixed mode entry point
73 PeCompat
= (PE_COMPAT_TYPE1
*)((UINTN
)ImageBase
+ Section
->VirtualAddress
);
74 PeCompatEnd
= (UINTN
)(VOID
*)PeCompat
+ Section
->Misc
.VirtualSize
;
76 while (PeCompat
->Type
!= 0 && (UINTN
)(VOID
*)PeCompat
< PeCompatEnd
) {
77 if (PeCompat
->Type
== 1 &&
78 PeCompat
->Size
>= sizeof (PE_COMPAT_TYPE1
) &&
79 EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat
->MachineType
)) {
81 return (EFI_IMAGE_ENTRY_POINT
)((UINTN
)ImageBase
+ PeCompat
->EntryPoint
);
83 PeCompat
= (PE_COMPAT_TYPE1
*)((UINTN
)PeCompat
+ PeCompat
->Size
);
84 ASSERT ((UINTN
)(VOID
*)PeCompat
< PeCompatEnd
);
96 IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
*This
,
97 IN EFI_PHYSICAL_ADDRESS ImageBase
,
99 IN OUT EFI_IMAGE_ENTRY_POINT
*EntryPoint
102 EFI_IMAGE_ENTRY_POINT CompatEntryPoint
;
104 CompatEntryPoint
= GetCompatEntryPoint (ImageBase
);
105 if (CompatEntryPoint
== NULL
) {
106 return EFI_UNSUPPORTED
;
109 *EntryPoint
= CompatEntryPoint
;
117 IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL
*This
,
118 IN EFI_PHYSICAL_ADDRESS ImageBase
124 STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mCompatLoaderPeCoffEmuProtocol
= {
128 EDKII_PECOFF_IMAGE_EMULATOR_VERSION
,
129 EFI_IMAGE_MACHINE_X64
134 CompatImageLoaderDxeEntryPoint (
135 IN EFI_HANDLE ImageHandle
,
136 IN EFI_SYSTEM_TABLE
*SystemTable
139 return gBS
->InstallProtocolInterface (&ImageHandle
,
140 &gEdkiiPeCoffImageEmulatorProtocolGuid
,
141 EFI_NATIVE_INTERFACE
,
142 &mCompatLoaderPeCoffEmuProtocol
);