]>
Commit | Line | Data |
---|---|---|
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 | |
21 | typedef 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 | |
29 | STATIC\r | |
30 | BOOLEAN\r | |
31 | EFIAPI\r | |
32 | IsImageSupported (\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 | |
41 | STATIC\r | |
42 | EFI_IMAGE_ENTRY_POINT\r | |
43 | EFIAPI\r | |
44 | GetCompatEntryPoint (\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 | |
92 | STATIC\r | |
93 | EFI_STATUS\r | |
94 | EFIAPI\r | |
95 | RegisterImage (\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 | |
113 | STATIC\r | |
114 | EFI_STATUS\r | |
115 | EFIAPI\r | |
116 | UnregisterImage (\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 | |
124 | STATIC 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 | |
132 | EFI_STATUS\r | |
133 | EFIAPI\r | |
134 | CompatImageLoaderDxeEntryPoint (\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 |