1 /*++
2
3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4 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 EFILDR_LOADED_IMAGE DxeCoreImage;
28 EFILDR_LOADED_IMAGE DxeIplImage;
29
30 VOID
SystemHang(CHAR8 * Message)31 SystemHang (
32 CHAR8 *Message
33 )
34 {
35 PrintString (
36 "%s## FATAL ERROR ##: Fail to load DUET images! System hang!\n",
37 Message
38 );
39 CpuDeadLoop();
40 }
41
42 VOID
EfiLoader(UINT32 BiosMemoryMapBaseAddress)43 EfiLoader (
44 UINT32 BiosMemoryMapBaseAddress
45 )
46 {
47 BIOS_MEMORY_MAP *BiosMemoryMap;
48 EFILDR_IMAGE *EFILDRImage;
49 EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS];
50 EFI_STATUS Status;
51 UINTN NumberOfMemoryMapEntries;
52 UINT32 DestinationSize;
53 UINT32 ScratchSize;
54 UINTN BfvPageNumber;
55 UINTN BfvBase;
56 EFI_MAIN_ENTRYPOINT EfiMainEntrypoint;
57 EFILDRHANDOFF Handoff;
58 UINTN Index;
59
60 ClearScreen();
61
62 PrintHeader ('A');
63
64 PrintString ("Enter DUET Loader...\n");
65 PrintString ("BiosMemoryMapBaseAddress = %x\n", (UINTN) BiosMemoryMapBaseAddress);
66
67 //
68 // Add all EfiConventionalMemory descriptors to the table. If there are partial pages, then
69 // round the start address up to the next page, and round the length down to a page boundary.
70 //
71 BiosMemoryMap = (BIOS_MEMORY_MAP *) (UINTN) BiosMemoryMapBaseAddress;
72 NumberOfMemoryMapEntries = 0;
73 GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap);
74
75 PrintString ("Get %d entries of memory map!\n", NumberOfMemoryMapEntries);
76
77 //
78 // Get information on where the image is in memory
79 //
80 EFILDRImage = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER));
81
82
83 //
84 // Point to the 4th image (Bfv)
85 //
86 EFILDRImage += 3;
87
88 //
89 // Decompress the image
90 //
91 PrintString (
92 "Decompress BFV image, Image Address = %x Offset = %x\n",
93 (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
94 (UINTN) EFILDRImage->Offset
95 );
96 Status = LzmaUefiDecompressGetInfo (
97 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
98 EFILDRImage->Length,
99 &DestinationSize,
100 &ScratchSize
101 );
102
103 if (EFI_ERROR (Status)) {
104 SystemHang ("Failed to get decompress information for BFV!\n");
105 }
106
107 PrintString ("BFV decompress: DestinationSize = %x, ScratchSize = %x\n", (UINTN) DestinationSize, (UINTN) ScratchSize);
108 Status = LzmaUefiDecompress (
109 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
110 EFILDRImage->Length,
111 (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,
112 (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)
113 );
114
115
116 if (EFI_ERROR (Status)) {
117 SystemHang ("Failed to decompress BFV!\n");
118 }
119
120 BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize);
121 BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);
122 if (BfvBase == 0) {
123 SystemHang ("Failed to find free space to hold decompressed BFV\n");
124 }
125 ZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE);
126 CopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize);
127
128 PrintHeader ('B');
129
130 //
131 // Point to the 2nd image (DxeIpl)
132 //
133
134 EFILDRImage -= 2;
135
136 //
137 // Decompress the image
138 //
139 PrintString (
140 "Decompress DxeIpl image, Image Address = %x Offset = %x\n",
141 (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
142 (UINTN) EFILDRImage->Offset
143 );
144
145 Status = LzmaUefiDecompressGetInfo (
146 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
147 EFILDRImage->Length,
148 &DestinationSize,
149 &ScratchSize
150 );
151 if (EFI_ERROR (Status)) {
152 SystemHang ("Failed to get decompress information for DxeIpl!\n");
153 }
154
155 Status = LzmaUefiDecompress (
156 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
157 EFILDRImage->Length,
158 (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,
159 (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)
160 );
161 if (EFI_ERROR (Status)) {
162 SystemHang ("Failed to decompress DxeIpl image\n");
163 }
164
165 PrintString ("Start load DxeIpl PE image\n");
166
167 //
168 // Load and relocate the EFI PE/COFF Firmware Image
169 //
170 Status = EfiLdrPeCoffLoadPeImage (
171 (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS),
172 &DxeIplImage,
173 &NumberOfMemoryMapEntries,
174 EfiMemoryDescriptor
175 );
176 if (EFI_ERROR (Status)) {
177 SystemHang ("Failed to load and relocate DxeIpl PE image!\n");
178 }
179 PrintString (
180 "DxeIpl PE image is successed loaded at %lx, entry=%p\n",
181 DxeIplImage.ImageBasePage,
182 DxeIplImage.EntryPoint
183 );
184
185 PrintHeader ('C');
186
187 //
188 // Point to the 3rd image (DxeMain)
189 //
190 EFILDRImage++;
191
192 //
193 // Decompress the image
194 //
195 PrintString (
196 "Decompress DxeMain FV image, Image Address = %x Offset = %x\n",
197 (UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
198 (UINTN) EFILDRImage->Offset
199 );
200
201 Status = LzmaUefiDecompressGetInfo (
202 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
203 EFILDRImage->Length,
204 &DestinationSize,
205 &ScratchSize
206 );
207 if (EFI_ERROR (Status)) {
208 SystemHang ("Failed to get decompress information for DxeMain FV image!\n");
209 }
210
211 Status = LzmaUefiDecompress (
212 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
213 EFILDRImage->Length,
214 (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,
215 (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)
216 );
217 if (EFI_ERROR (Status)) {
218 SystemHang ("Failed to decompress DxeMain FV image!\n");
219 }
220
221 //
222 // Load and relocate the EFI PE/COFF Firmware Image
223 //
224 Status = EfiLdrPeCoffLoadPeImage (
225 (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS),
226 &DxeCoreImage,
227 &NumberOfMemoryMapEntries,
228 EfiMemoryDescriptor
229 );
230 if (EFI_ERROR (Status)) {
231 SystemHang ("Failed to load/relocate DxeMain!\n");
232 }
233 PrintString (
234 "DxeCore PE image is successed loaded at %lx, entry=%p\n",
235 DxeCoreImage.ImageBasePage,
236 DxeCoreImage.EntryPoint
237 );
238
239 PrintHeader ('E');
240
241 //
242 // Display the table of memory descriptors.
243 //
244 PrintString ("\nEFI Memory Descriptors\n");
245 for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) {
246 PrintString (
247 "Type = %x Start = %08lx NumberOfPages = %08lx\n",
248 EfiMemoryDescriptor[Index].Type, EfiMemoryDescriptor[Index].PhysicalStart, EfiMemoryDescriptor[Index].NumberOfPages
249 );
250 }
251
252 //
253 // Jump to EFI Firmware
254 //
255
256 if (DxeIplImage.EntryPoint != NULL) {
257
258 Handoff.MemDescCount = NumberOfMemoryMapEntries;
259 Handoff.MemDesc = EfiMemoryDescriptor;
260 Handoff.BfvBase = (VOID *)(UINTN)BfvBase;
261 Handoff.BfvSize = BfvPageNumber * EFI_PAGE_SIZE;
262 Handoff.DxeIplImageBase = (VOID *)(UINTN)DxeIplImage.ImageBasePage;
263 Handoff.DxeIplImageSize = DxeIplImage.NoPages * EFI_PAGE_SIZE;
264 Handoff.DxeCoreImageBase = (VOID *)(UINTN)DxeCoreImage.ImageBasePage;
265 Handoff.DxeCoreImageSize = DxeCoreImage.NoPages * EFI_PAGE_SIZE;
266 Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint;
267
268 PrintString ("Transfer to DxeIpl ...EntryPoint = %p\n", DxeIplImage.EntryPoint);
269
270 EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT) DxeIplImage.EntryPoint;
271 EfiMainEntrypoint (&Handoff);
272 }
273
274 PrintHeader ('F');
275
276 //
277 // There was a problem loading the image, so HALT the system.
278 //
279
280 SystemHang ("Failed to jump to DxeIpl!\n");
281 }
282
283 EFI_STATUS
284 EFIAPI
_ModuleEntryPoint(UINT32 BiosMemoryMapBaseAddress)285 _ModuleEntryPoint (
286 UINT32 BiosMemoryMapBaseAddress
287 )
288 {
289 SerialPortInitialize ();
290 EfiLoader(BiosMemoryMapBaseAddress);
291 return EFI_SUCCESS;
292 }
293
294
295