9071550e |
1 | /*++\r |
2 | \r |
3 | Copyright (c) 2006, Intel Corporation \r |
4 | All rights reserved. This program and the accompanying materials \r |
5 | are licensed and made available under the terms and conditions of the BSD License \r |
6 | which accompanies this distribution. The full text of the license may be found at \r |
7 | http://opensource.org/licenses/bsd-license.php \r |
8 | \r |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r |
11 | \r |
12 | Module Name:\r |
13 | EfiLoader.c\r |
14 | \r |
15 | Abstract:\r |
16 | \r |
17 | Revision History:\r |
18 | \r |
19 | --*/\r |
20 | \r |
21 | #include "EfiLdr.h"\r |
22 | #include "Support.h"\r |
23 | #include "Debug.h"\r |
24 | #include "PeLoader.h"\r |
3da85e63 |
25 | #include "TianoDecompress.h"\r |
26 | \r |
3da85e63 |
27 | VOID\r |
28 | SystemHang(\r |
29 | VOID\r |
30 | )\r |
31 | {\r |
32 | CHAR8 PrintBuffer[256];\r |
33 | AsciiSPrint (PrintBuffer, 256, "## FATEL ERROR ##: Fail to load DUET images! System hang!\n");\r |
34 | CpuDeadLoop();\r |
35 | }\r |
9071550e |
36 | \r |
37 | VOID\r |
38 | EfiLoader (\r |
39 | UINT32 BiosMemoryMapBaseAddress\r |
40 | )\r |
41 | {\r |
42 | BIOS_MEMORY_MAP *BiosMemoryMap; \r |
43 | EFILDR_HEADER *EFILDRHeader;\r |
44 | EFILDR_IMAGE *EFILDRImage;\r |
45 | EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS];\r |
46 | EFI_STATUS Status;\r |
47 | UINTN NumberOfMemoryMapEntries;\r |
48 | UINT32 DestinationSize;\r |
49 | UINT32 ScratchSize;\r |
50 | UINTN BfvPageNumber;\r |
51 | UINTN BfvBase;\r |
52 | EFI_MAIN_ENTRYPOINT EfiMainEntrypoint;\r |
3da85e63 |
53 | CHAR8 PrintBuffer[256];\r |
e56dd2ce |
54 | STATIC EFILDRHANDOFF Handoff;\r |
9071550e |
55 | \r |
9071550e |
56 | ClearScreen();\r |
3da85e63 |
57 | \r |
58 | PrintHeader ('A');\r |
9071550e |
59 | \r |
3da85e63 |
60 | AsciiSPrint (PrintBuffer, 256, "Enter DUET Loader ...\n", BiosMemoryMapBaseAddress);\r |
61 | PrintString (PrintBuffer);\r |
62 | \r |
63 | AsciiSPrint (PrintBuffer, 256, "BiosMemoryMapBaseAddress = 0x%x\n", BiosMemoryMapBaseAddress);\r |
64 | PrintString (PrintBuffer);\r |
9071550e |
65 | \r |
66 | //\r |
67 | // Add all EfiConventionalMemory descriptors to the table. If there are partial pages, then\r |
68 | // round the start address up to the next page, and round the length down to a page boundry.\r |
69 | //\r |
70 | BiosMemoryMap = (BIOS_MEMORY_MAP *)(UINTN)(BiosMemoryMapBaseAddress);\r |
71 | NumberOfMemoryMapEntries = 0;\r |
72 | GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap);\r |
73 | \r |
3da85e63 |
74 | AsciiSPrint (PrintBuffer, 256, "Get %d entries of memory map!\n", NumberOfMemoryMapEntries);\r |
75 | PrintString (PrintBuffer);\r |
76 | \r |
9071550e |
77 | //\r |
78 | // Get information on where the image is in memory\r |
79 | //\r |
80 | \r |
81 | EFILDRHeader = (EFILDR_HEADER *)(UINTN)(EFILDR_HEADER_ADDRESS);\r |
82 | EFILDRImage = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER));\r |
83 | \r |
9071550e |
84 | \r |
85 | //\r |
86 | // Point to the 4th image (Bfv)\r |
87 | //\r |
88 | \r |
89 | EFILDRImage += 3;\r |
90 | \r |
91 | //\r |
92 | // Decompress the image\r |
93 | //\r |
94 | \r |
c5dfb477 |
95 | AsciiSPrint (PrintBuffer, 256, "Decompress BFV image, Image Address=0x%x Offset=0x%x\n", \r |
3da85e63 |
96 | (UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
97 | EFILDRImage->Offset);\r |
98 | PrintString (PrintBuffer);\r |
99 | \r |
100 | Status = TianoGetInfo (\r |
9071550e |
101 | (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
102 | EFILDRImage->Length,\r |
103 | &DestinationSize, \r |
104 | &ScratchSize\r |
105 | );\r |
3da85e63 |
106 | \r |
9071550e |
107 | if (EFI_ERROR (Status)) {\r |
3da85e63 |
108 | AsciiSPrint (PrintBuffer, 256, "Fail to get decompress information for BFV!\n");\r |
109 | PrintString (PrintBuffer);\r |
110 | SystemHang();\r |
9071550e |
111 | }\r |
112 | \r |
113 | Status = TianoDecompress (\r |
9071550e |
114 | (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
115 | EFILDRImage->Length,\r |
116 | (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,\r |
117 | DestinationSize, \r |
118 | (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000),\r |
119 | ScratchSize\r |
120 | );\r |
3da85e63 |
121 | \r |
9071550e |
122 | if (EFI_ERROR (Status)) {\r |
3da85e63 |
123 | AsciiSPrint (PrintBuffer, 256, "Fail to decompress BFV!\n");\r |
124 | PrintString (PrintBuffer);\r |
125 | SystemHang();\r |
9071550e |
126 | }\r |
127 | \r |
128 | BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize);\r |
129 | BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);\r |
130 | if (BfvBase == 0) {\r |
3da85e63 |
131 | SystemHang();\r |
9071550e |
132 | }\r |
133 | ZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE);\r |
134 | CopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize);\r |
135 | \r |
3da85e63 |
136 | PrintHeader ('B');\r |
9071550e |
137 | \r |
138 | //\r |
139 | // Point to the 2nd image (DxeIpl)\r |
140 | //\r |
141 | \r |
142 | EFILDRImage -= 2;\r |
143 | \r |
144 | //\r |
145 | // Decompress the image\r |
146 | //\r |
c5dfb477 |
147 | AsciiSPrint (PrintBuffer, 256, "Decompress DxeIpl image, Image Address=0x%x Offset=0x%x\n", \r |
3da85e63 |
148 | (UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
149 | EFILDRImage->Offset);\r |
ff514e29 |
150 | PrintString (PrintBuffer);\r |
9071550e |
151 | \r |
3da85e63 |
152 | Status = TianoGetInfo (\r |
9071550e |
153 | (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
154 | EFILDRImage->Length,\r |
155 | &DestinationSize, \r |
156 | &ScratchSize\r |
157 | );\r |
158 | if (EFI_ERROR (Status)) {\r |
3da85e63 |
159 | AsciiSPrint (PrintBuffer, 256, "Fail to get decompress information for DxeIpl!\n");\r |
160 | PrintString (PrintBuffer);\r |
161 | SystemHang();\r |
9071550e |
162 | }\r |
163 | \r |
164 | Status = TianoDecompress (\r |
9071550e |
165 | (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
166 | EFILDRImage->Length,\r |
167 | (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,\r |
168 | DestinationSize, \r |
169 | (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000),\r |
170 | ScratchSize\r |
171 | );\r |
172 | if (EFI_ERROR (Status)) {\r |
3da85e63 |
173 | AsciiSPrint (PrintBuffer, 256, "Fail to decompress DxeIpl image\n");\r |
174 | PrintString (PrintBuffer);\r |
175 | SystemHang();\r |
9071550e |
176 | }\r |
177 | \r |
3da85e63 |
178 | AsciiSPrint (PrintBuffer, 256, "Start load DxeIpl PE image\n");\r |
179 | PrintString (PrintBuffer); \r |
180 | \r |
9071550e |
181 | //\r |
182 | // Load and relocate the EFI PE/COFF Firmware Image \r |
183 | //\r |
184 | Status = EfiLdrPeCoffLoadPeImage (\r |
185 | (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), \r |
186 | &DxeIplImage, \r |
187 | &NumberOfMemoryMapEntries, \r |
188 | EfiMemoryDescriptor\r |
189 | );\r |
190 | if (EFI_ERROR (Status)) {\r |
3da85e63 |
191 | AsciiSPrint (PrintBuffer, 256, "Fail to load and relocate DxeIpl PE image!\n");\r |
192 | PrintString (PrintBuffer);\r |
193 | SystemHang();\r |
9071550e |
194 | }\r |
ff514e29 |
195 | AsciiSPrint (PrintBuffer, 256, "DxeIpl PE image is successed loaded at 0x%x, entry=0x%x\n",\r |
196 | (UINTN)DxeIplImage.ImageBasePage, (UINTN)DxeIplImage.EntryPoint);\r |
197 | PrintString (PrintBuffer); \r |
9071550e |
198 | \r |
199 | // PrintString("Image.NoPages = "); \r |
200 | // PrintValue(Image.NoPages);\r |
201 | // PrintString("\n");\r |
202 | \r |
203 | PrintHeader ('C');\r |
204 | \r |
205 | //\r |
206 | // Point to the 3rd image (DxeMain)\r |
207 | //\r |
208 | \r |
209 | EFILDRImage++;\r |
210 | \r |
211 | //\r |
212 | // Decompress the image\r |
213 | //\r |
ff514e29 |
214 | AsciiSPrint (PrintBuffer, 256, "Decompress DXEMain FV image, Image Address=0x%x! Offset=0x%x\n", \r |
215 | (UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
216 | EFILDRImage->Offset);\r |
217 | PrintString (PrintBuffer);\r |
9071550e |
218 | \r |
3da85e63 |
219 | Status = TianoGetInfo (\r |
9071550e |
220 | (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
221 | EFILDRImage->Length,\r |
222 | &DestinationSize, \r |
223 | &ScratchSize\r |
224 | );\r |
225 | if (EFI_ERROR (Status)) {\r |
ff514e29 |
226 | AsciiSPrint (PrintBuffer, 256, "Fail to get decompress information for DXEMain FV image!\n");\r |
227 | PrintString (PrintBuffer);\r |
3da85e63 |
228 | SystemHang();\r |
9071550e |
229 | }\r |
230 | \r |
231 | Status = TianoDecompress (\r |
9071550e |
232 | (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),\r |
233 | EFILDRImage->Length,\r |
234 | (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,\r |
235 | DestinationSize, \r |
236 | (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000),\r |
237 | ScratchSize\r |
238 | );\r |
239 | if (EFI_ERROR (Status)) {\r |
3da85e63 |
240 | SystemHang();\r |
9071550e |
241 | }\r |
242 | \r |
243 | //\r |
244 | // Load and relocate the EFI PE/COFF Firmware Image \r |
245 | //\r |
246 | Status = EfiLdrPeCoffLoadPeImage (\r |
247 | (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), \r |
248 | &DxeCoreImage, \r |
249 | &NumberOfMemoryMapEntries, \r |
250 | EfiMemoryDescriptor\r |
251 | );\r |
252 | if (EFI_ERROR (Status)) {\r |
3da85e63 |
253 | SystemHang();\r |
9071550e |
254 | }\r |
ff514e29 |
255 | AsciiSPrint (PrintBuffer, 256, "DxeCore PE image is successed loaded at 0x%x, entry=0x%x\n",\r |
256 | (UINTN)DxeCoreImage.ImageBasePage, (UINTN)DxeCoreImage.EntryPoint);\r |
257 | PrintString (PrintBuffer); \r |
9071550e |
258 | \r |
259 | PrintHeader ('E');\r |
260 | \r |
261 | //\r |
262 | // Display the table of memory descriptors.\r |
263 | //\r |
264 | \r |
265 | // PrintString("\nEFI Memory Descriptors\n"); \r |
266 | /*\r |
267 | {\r |
268 | UINTN Index;\r |
269 | for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) {\r |
270 | PrintString("Type = "); \r |
271 | PrintValue(EfiMemoryDescriptor[Index].Type);\r |
272 | PrintString(" Start = "); \r |
273 | PrintValue((UINT32)(EfiMemoryDescriptor[Index].PhysicalStart));\r |
274 | PrintString(" NumberOfPages = "); \r |
275 | PrintValue((UINT32)(EfiMemoryDescriptor[Index].NumberOfPages));\r |
276 | PrintString("\n");\r |
277 | }\r |
278 | }\r |
279 | */\r |
280 | \r |
281 | //\r |
282 | // Jump to EFI Firmware\r |
283 | //\r |
284 | \r |
285 | if (DxeIplImage.EntryPoint != NULL) {\r |
286 | \r |
287 | Handoff.MemDescCount = NumberOfMemoryMapEntries;\r |
288 | Handoff.MemDesc = EfiMemoryDescriptor;\r |
289 | Handoff.BfvBase = (VOID *)(UINTN)BfvBase;\r |
290 | Handoff.BfvSize = BfvPageNumber * EFI_PAGE_SIZE;\r |
291 | Handoff.DxeIplImageBase = (VOID *)(UINTN)DxeIplImage.ImageBasePage;\r |
292 | Handoff.DxeIplImageSize = DxeIplImage.NoPages * EFI_PAGE_SIZE;\r |
293 | Handoff.DxeCoreImageBase = (VOID *)(UINTN)DxeCoreImage.ImageBasePage;\r |
294 | Handoff.DxeCoreImageSize = DxeCoreImage.NoPages * EFI_PAGE_SIZE;\r |
295 | Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint;\r |
296 | \r |
ff514e29 |
297 | AsciiSPrint (PrintBuffer, 256, "Transfer to DxeIpl ...Address=0x%x\n", (UINTN)DxeIplImage.EntryPoint);\r |
298 | PrintString (PrintBuffer);\r |
299 | \r |
9071550e |
300 | EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT)(UINTN)DxeIplImage.EntryPoint;\r |
301 | EfiMainEntrypoint (&Handoff);\r |
302 | }\r |
303 | \r |
304 | PrintHeader ('F');\r |
305 | \r |
306 | //\r |
307 | // There was a problem loading the image, so HALT the system.\r |
308 | //\r |
309 | \r |
3da85e63 |
310 | SystemHang();\r |
9071550e |
311 | }\r |
312 | \r |
c51b1cb6 |
313 | EFI_STATUS\r |
314 | EFIAPI\r |
315 | _ModuleEntryPoint (\r |
316 | UINT32 BiosMemoryMapBaseAddress\r |
317 | )\r |
318 | {\r |
319 | EfiLoader(BiosMemoryMapBaseAddress);\r |
320 | return EFI_SUCCESS;\r |
321 | }\r |
322 | \r |
323 | \r |