1 /** @file
2
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <PrePi.h>
16
17 //
18 // Hack to work in NT32
19 //
20 EFI_STATUS
21
22 EFIAPI
23
24 SecWinNtPeiLoadFile (
25 IN VOID *Pe32Data,
26 IN EFI_PHYSICAL_ADDRESS *ImageAddress,
27 IN UINT64 *ImageSize,
28 IN EFI_PHYSICAL_ADDRESS *EntryPoint
29 );
30
31
32 EFI_STATUS
33 EFIAPI
LoadPeCoffImage(IN VOID * PeCoffImage,OUT EFI_PHYSICAL_ADDRESS * ImageAddress,OUT UINT64 * ImageSize,OUT EFI_PHYSICAL_ADDRESS * EntryPoint)34 LoadPeCoffImage (
35 IN VOID *PeCoffImage,
36 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
37 OUT UINT64 *ImageSize,
38 OUT EFI_PHYSICAL_ADDRESS *EntryPoint
39 )
40 {
41 RETURN_STATUS Status;
42 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
43 VOID *Buffer;
44
45 ZeroMem (&ImageContext, sizeof (ImageContext));
46
47 ImageContext.Handle = PeCoffImage;
48 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
49
50 Status = PeCoffLoaderGetImageInfo (&ImageContext);
51 ASSERT_EFI_ERROR (Status);
52
53
54 //
55 // Allocate Memory for the image
56 //
57 Buffer = AllocatePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize));
58 ASSERT (Buffer != 0);
59
60
61 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
62
63 //
64 // Load the image to our new buffer
65 //
66 Status = PeCoffLoaderLoadImage (&ImageContext);
67 ASSERT_EFI_ERROR (Status);
68
69 //
70 // Relocate the image in our new buffer
71 //
72 Status = PeCoffLoaderRelocateImage (&ImageContext);
73 ASSERT_EFI_ERROR (Status);
74
75
76 *ImageAddress = ImageContext.ImageAddress;
77 *ImageSize = ImageContext.ImageSize;
78 *EntryPoint = ImageContext.EntryPoint;
79
80 //
81 // Flush not needed for all architectures. We could have a processor specific
82 // function in this library that does the no-op if needed.
83 //
84 InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize);
85
86 return Status;
87 }
88
89
90
91 typedef
92 VOID
93 (EFIAPI *DXE_CORE_ENTRY_POINT) (
94 IN VOID *HobStart
95 );
96
97 EFI_STATUS
98 EFIAPI
LoadDxeCoreFromFfsFile(IN EFI_PEI_FILE_HANDLE FileHandle,IN UINTN StackSize)99 LoadDxeCoreFromFfsFile (
100 IN EFI_PEI_FILE_HANDLE FileHandle,
101 IN UINTN StackSize
102 )
103 {
104 EFI_STATUS Status;
105 VOID *PeCoffImage;
106 EFI_PHYSICAL_ADDRESS ImageAddress;
107 UINT64 ImageSize;
108 EFI_PHYSICAL_ADDRESS EntryPoint;
109 VOID *BaseOfStack;
110 VOID *TopOfStack;
111 VOID *Hob;
112 EFI_FV_FILE_INFO FvFileInfo;
113
114 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage);
115 if (EFI_ERROR (Status)) {
116 return Status;
117 }
118
119
120 Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
121 // For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
122 ASSERT_EFI_ERROR (Status);
123
124 //
125 // Extract the DxeCore GUID file name.
126 //
127 Status = FfsGetFileInfo (FileHandle, &FvFileInfo);
128 ASSERT_EFI_ERROR (Status);
129
130 BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint);
131
132 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint));
133
134 Hob = GetHobList ();
135 if (StackSize == 0) {
136 // User the current stack
137
138 ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob);
139 } else {
140
141 //
142 // Allocate 128KB for the Stack
143 //
144 BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize));
145 ASSERT (BaseOfStack != NULL);
146
147 //
148 // Compute the top of the stack we were allocated. Pre-allocate a UINTN
149 // for safety.
150 //
151 TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
152 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
153
154 //
155 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
156 //
157 UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize);
158
159 SwitchStack (
160 (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint,
161 Hob,
162 NULL,
163 TopOfStack
164 );
165
166 }
167
168 // Should never get here as DXE Core does not return
169 DEBUG ((EFI_D_ERROR, "DxeCore returned\n"));
170 ASSERT (FALSE);
171
172 return EFI_DEVICE_ERROR;
173 }
174
175
176
177 EFI_STATUS
178 EFIAPI
LoadDxeCoreFromFv(IN UINTN * FvInstance,OPTIONAL IN UINTN StackSize)179 LoadDxeCoreFromFv (
180 IN UINTN *FvInstance, OPTIONAL
181 IN UINTN StackSize
182 )
183 {
184 EFI_STATUS Status;
185 EFI_PEI_FV_HANDLE VolumeHandle;
186 EFI_PEI_FILE_HANDLE FileHandle = NULL;
187
188 if (FvInstance != NULL) {
189 //
190 // Caller passed in a specific FV to try, so only try that one
191 //
192 Status = FfsFindNextVolume (*FvInstance, &VolumeHandle);
193 if (!EFI_ERROR (Status)) {
194 Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
195 }
196 } else {
197 Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);
198 }
199
200 if (!EFI_ERROR (Status)) {
201 return LoadDxeCoreFromFfsFile (FileHandle, StackSize);
202 }
203
204 return Status;
205 }
206
207
208 EFI_STATUS
209 EFIAPI
DecompressFirstFv(VOID)210 DecompressFirstFv (
211 VOID
212 )
213 {
214 EFI_STATUS Status;
215 EFI_PEI_FV_HANDLE VolumeHandle;
216 EFI_PEI_FILE_HANDLE FileHandle;
217
218 Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle);
219 if (!EFI_ERROR (Status)) {
220 Status = FfsProcessFvFile (FileHandle);
221 }
222
223 return Status;
224 }
225
226
227