--- /dev/null
+/** @file\r
+ * PE/COFF emulator protocol implementation to start Linux kernel\r
+ * images from non-native firmware\r
+ *\r
+ * Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>\r
+ *\r
+ * SPDX-License-Identifier: BSD-2-Clause-Patent\r
+ *\r
+ */\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/PeCoffImageEmulator.h>\r
+\r
+#pragma pack (1)\r
+typedef struct {\r
+ UINT8 Type;\r
+ UINT8 Size;\r
+ UINT16 MachineType;\r
+ UINT32 EntryPoint;\r
+} PE_COMPAT_TYPE1;\r
+#pragma pack ()\r
+\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsImageSupported (\r
+ IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This,\r
+ IN UINT16 ImageType,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL\r
+ )\r
+{\r
+ return ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
+}\r
+\r
+STATIC\r
+EFI_IMAGE_ENTRY_POINT\r
+EFIAPI\r
+GetCompatEntryPoint (\r
+ IN EFI_PHYSICAL_ADDRESS ImageBase\r
+ )\r
+{\r
+ EFI_IMAGE_DOS_HEADER *DosHdr;\r
+ UINTN PeCoffHeaderOffset;\r
+ EFI_IMAGE_NT_HEADERS32 *Pe32;\r
+ EFI_IMAGE_SECTION_HEADER *Section;\r
+ UINTN NumberOfSections;\r
+ PE_COMPAT_TYPE1 *PeCompat;\r
+ UINTN PeCompatEnd;\r
+\r
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;\r
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ return NULL;\r
+ }\r
+\r
+ PeCoffHeaderOffset = DosHdr->e_lfanew;\r
+ Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageBase + PeCoffHeaderOffset);\r
+\r
+ Section = (EFI_IMAGE_SECTION_HEADER *)((UINTN)&Pe32->OptionalHeader +\r
+ Pe32->FileHeader.SizeOfOptionalHeader);\r
+ NumberOfSections = (UINTN)Pe32->FileHeader.NumberOfSections;\r
+\r
+ while (NumberOfSections--) {\r
+ if (!CompareMem (Section->Name, ".compat", sizeof (Section->Name))) {\r
+ //\r
+ // Dereference the section contents to find the mixed mode entry point\r
+ //\r
+ PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)ImageBase + Section->VirtualAddress);\r
+ PeCompatEnd = (UINTN)(VOID *)PeCompat + Section->Misc.VirtualSize;\r
+\r
+ while (PeCompat->Type != 0 && (UINTN)(VOID *)PeCompat < PeCompatEnd) {\r
+ if (PeCompat->Type == 1 &&\r
+ PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&\r
+ EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {\r
+\r
+ return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);\r
+ }\r
+ PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);\r
+ ASSERT ((UINTN)(VOID *)PeCompat < PeCompatEnd);\r
+ }\r
+ }\r
+ Section++;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterImage (\r
+ IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS ImageBase,\r
+ IN UINT64 ImageSize,\r
+ IN OUT EFI_IMAGE_ENTRY_POINT *EntryPoint\r
+ )\r
+{\r
+ EFI_IMAGE_ENTRY_POINT CompatEntryPoint;\r
+\r
+ CompatEntryPoint = GetCompatEntryPoint (ImageBase);\r
+ if (CompatEntryPoint == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ *EntryPoint = CompatEntryPoint;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UnregisterImage (\r
+ IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS ImageBase\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mCompatLoaderPeCoffEmuProtocol = {\r
+ IsImageSupported,\r
+ RegisterImage,\r
+ UnregisterImage,\r
+ EDKII_PECOFF_IMAGE_EMULATOR_VERSION,\r
+ EFI_IMAGE_MACHINE_X64\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CompatImageLoaderDxeEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ return gBS->InstallProtocolInterface (&ImageHandle,\r
+ &gEdkiiPeCoffImageEmulatorProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mCompatLoaderPeCoffEmuProtocol);\r
+}\r
--- /dev/null
+## @file\r
+# PE/COFF emulator protocol implementation to start Linux kernel\r
+# images from non-native firmware\r
+#\r
+# Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 1.27\r
+ BASE_NAME = CompatImageLoaderDxe\r
+ FILE_GUID = 1019f54a-2560-41b2-87b0-6750b98f3eff\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = CompatImageLoaderDxeEntryPoint\r
+\r
+[Sources]\r
+ CompatImageLoaderDxe.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PeCoffLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+\r
+[Protocols]\r
+ gEdkiiPeCoffImageEmulatorProtocolGuid ## PRODUCES\r
+\r
+[Depex]\r
+ TRUE\r