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