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