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