]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.c
OvmfPkg/QemuKernelLoaderFsDxe: add support for new Linux initrd device path
[mirror_edk2.git] / OvmfPkg / CompatImageLoaderDxe / CompatImageLoaderDxe.c
CommitLineData
d55cfdc5
AB
1/** @file\r
2 * PE/COFF emulator protocol implementation to start Linux kernel\r
3 * images from non-native firmware\r
4 *\r
5 * Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>\r
6 *\r
7 * SPDX-License-Identifier: BSD-2-Clause-Patent\r
8 *\r
9 */\r
10\r
11#include <PiDxe.h>\r
12\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/PeCoffLib.h>\r
16#include <Library/UefiBootServicesTableLib.h>\r
17\r
18#include <Protocol/PeCoffImageEmulator.h>\r
19\r
20#pragma pack (1)\r
21typedef struct {\r
22 UINT8 Type;\r
23 UINT8 Size;\r
24 UINT16 MachineType;\r
25 UINT32 EntryPoint;\r
26} PE_COMPAT_TYPE1;\r
27#pragma pack ()\r
28\r
29STATIC\r
30BOOLEAN\r
31EFIAPI\r
32IsImageSupported (\r
33 IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This,\r
34 IN UINT16 ImageType,\r
35 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL\r
36 )\r
37{\r
38 return ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
39}\r
40\r
41STATIC\r
42EFI_IMAGE_ENTRY_POINT\r
43EFIAPI\r
44GetCompatEntryPoint (\r
45 IN EFI_PHYSICAL_ADDRESS ImageBase\r
46 )\r
47{\r
48 EFI_IMAGE_DOS_HEADER *DosHdr;\r
49 UINTN PeCoffHeaderOffset;\r
50 EFI_IMAGE_NT_HEADERS32 *Pe32;\r
51 EFI_IMAGE_SECTION_HEADER *Section;\r
52 UINTN NumberOfSections;\r
53 PE_COMPAT_TYPE1 *PeCompat;\r
54 UINTN PeCompatEnd;\r
55\r
56 DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;\r
57 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
58 return NULL;\r
59 }\r
60\r
61 PeCoffHeaderOffset = DosHdr->e_lfanew;\r
62 Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageBase + PeCoffHeaderOffset);\r
63\r
64 Section = (EFI_IMAGE_SECTION_HEADER *)((UINTN)&Pe32->OptionalHeader +\r
65 Pe32->FileHeader.SizeOfOptionalHeader);\r
66 NumberOfSections = (UINTN)Pe32->FileHeader.NumberOfSections;\r
67\r
68 while (NumberOfSections--) {\r
69 if (!CompareMem (Section->Name, ".compat", sizeof (Section->Name))) {\r
70 //\r
71 // Dereference the section contents to find the mixed mode entry point\r
72 //\r
73 PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)ImageBase + Section->VirtualAddress);\r
74 PeCompatEnd = (UINTN)(VOID *)PeCompat + Section->Misc.VirtualSize;\r
75\r
76 while (PeCompat->Type != 0 && (UINTN)(VOID *)PeCompat < PeCompatEnd) {\r
77 if (PeCompat->Type == 1 &&\r
78 PeCompat->Size >= sizeof (PE_COMPAT_TYPE1) &&\r
79 EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCompat->MachineType)) {\r
80\r
81 return (EFI_IMAGE_ENTRY_POINT)((UINTN)ImageBase + PeCompat->EntryPoint);\r
82 }\r
83 PeCompat = (PE_COMPAT_TYPE1 *)((UINTN)PeCompat + PeCompat->Size);\r
84 ASSERT ((UINTN)(VOID *)PeCompat < PeCompatEnd);\r
85 }\r
86 }\r
87 Section++;\r
88 }\r
89 return NULL;\r
90}\r
91\r
92STATIC\r
93EFI_STATUS\r
94EFIAPI\r
95RegisterImage (\r
96 IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This,\r
97 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
98 IN UINT64 ImageSize,\r
99 IN OUT EFI_IMAGE_ENTRY_POINT *EntryPoint\r
100 )\r
101{\r
102 EFI_IMAGE_ENTRY_POINT CompatEntryPoint;\r
103\r
104 CompatEntryPoint = GetCompatEntryPoint (ImageBase);\r
105 if (CompatEntryPoint == NULL) {\r
106 return EFI_UNSUPPORTED;\r
107 }\r
108\r
109 *EntryPoint = CompatEntryPoint;\r
110 return EFI_SUCCESS;\r
111}\r
112\r
113STATIC\r
114EFI_STATUS\r
115EFIAPI\r
116UnregisterImage (\r
117 IN EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL *This,\r
118 IN EFI_PHYSICAL_ADDRESS ImageBase\r
119 )\r
120{\r
121 return EFI_SUCCESS;\r
122}\r
123\r
124STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL mCompatLoaderPeCoffEmuProtocol = {\r
125 IsImageSupported,\r
126 RegisterImage,\r
127 UnregisterImage,\r
128 EDKII_PECOFF_IMAGE_EMULATOR_VERSION,\r
129 EFI_IMAGE_MACHINE_X64\r
130};\r
131\r
132EFI_STATUS\r
133EFIAPI\r
134CompatImageLoaderDxeEntryPoint (\r
135 IN EFI_HANDLE ImageHandle,\r
136 IN EFI_SYSTEM_TABLE *SystemTable\r
137 )\r
138{\r
139 return gBS->InstallProtocolInterface (&ImageHandle,\r
140 &gEdkiiPeCoffImageEmulatorProtocolGuid,\r
141 EFI_NATIVE_INTERFACE,\r
142 &mCompatLoaderPeCoffEmuProtocol);\r
143}\r