]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/FindPeiCore.c
Update the copyright notice format
[mirror_edk2.git] / OvmfPkg / Sec / FindPeiCore.c
CommitLineData
0913fadc 1/** @file
2 Locate the entry point for the PEI Core
3
56d7640a 4 Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
0913fadc 5
56d7640a 6 This program and the accompanying materials
0913fadc 7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include <PiPei.h>
17#include <Library/BaseLib.h>
c1c2669c 18#include <Library/BaseMemoryLib.h>
19#include <Library/DebugLib.h>
20#include <Library/ExtractGuidedSectionLib.h>
21#include <Library/PcdLib.h>
0913fadc 22#include <Library/PeCoffGetEntryPointLib.h>
23
24#include "SecMain.h"
25
26
c1c2669c 27/**
28 Locates the main boot firmware volume.
29
30 @param[in,out] BootFv On input, the base of the BootFv
31 On output, the decompressed main firmware volume
32
33 @retval EFI_SUCCESS The main firmware volume was located and decompressed
34 @retval EFI_NOT_FOUND The main firmware volume was not found
35
36**/
37EFI_STATUS
38FindMainFv (
39 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv
40 )
41{
42 EFI_FIRMWARE_VOLUME_HEADER *Fv;
43 UINTN Distance;
44 BOOLEAN Found;
45
46 ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);
47
48 Found = FALSE;
49 Fv = *BootFv;
50 Distance = (UINTN) (*BootFv)->FvLength;
51 do {
52 Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);
53 Distance += EFI_PAGE_SIZE;
54 if (Distance > SIZE_32MB) {
55 return EFI_NOT_FOUND;
56 }
57
58 if (Fv->Signature != EFI_FVH_SIGNATURE) {
59 continue;
60 }
61
62 if ((UINTN) Fv->FvLength > Distance) {
63 continue;
64 }
65
66 *BootFv = Fv;
67 return EFI_SUCCESS;
68
69 } while (TRUE);
70}
71
72
73/**
74 Locates a section within a series of sections
75 with the specified section type.
76
77 @param[in] Sections The sections to search
78 @param[in] SizeOfSections Total size of all sections
79 @param[in] SectionType The section type to locate
80 @param[out] FoundSection The FFS section if found
81
82 @retval EFI_SUCCESS The file and section was found
83 @retval EFI_NOT_FOUND The file and section was not found
84 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
85
86**/
87EFI_STATUS
88FindFfsSectionInSections (
89 IN VOID *Sections,
90 IN UINTN SizeOfSections,
91 IN EFI_SECTION_TYPE SectionType,
92 OUT EFI_COMMON_SECTION_HEADER **FoundSection
93 )
94{
95 EFI_PHYSICAL_ADDRESS CurrentAddress;
96 UINT32 Size;
97 EFI_PHYSICAL_ADDRESS EndOfSections;
98 EFI_COMMON_SECTION_HEADER *Section;
99 EFI_PHYSICAL_ADDRESS EndOfSection;
100
101 //
102 // Loop through the FFS file sections within the PEI Core FFS file
103 //
104 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;
105 EndOfSections = EndOfSection + SizeOfSections;
106 for (;;) {
107 if (EndOfSection == EndOfSections) {
108 break;
109 }
110 CurrentAddress = (EndOfSection + 3) & ~(3ULL);
111 if (CurrentAddress >= EndOfSections) {
112 return EFI_VOLUME_CORRUPTED;
113 }
114
115 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
116 DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type));
117
118 Size = SECTION_SIZE (Section);
119 if (Size < sizeof (*Section)) {
120 return EFI_VOLUME_CORRUPTED;
121 }
122
123 EndOfSection = CurrentAddress + Size;
124 if (EndOfSection > EndOfSections) {
125 return EFI_VOLUME_CORRUPTED;
126 }
127
128 //
129 // Look for the requested section type
130 //
131 if (Section->Type == SectionType) {
132 *FoundSection = Section;
133 return EFI_SUCCESS;
134 }
135 DEBUG ((EFI_D_INFO, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType));
136 }
137
138 return EFI_NOT_FOUND;
139}
140
141
142/**
143 Locates a FFS file with the specified file type and a section
144 within that file with the specified section type.
145
146 @param[in] Fv The firmware volume to search
147 @param[in] FileType The file type to locate
148 @param[in] SectionType The section type to locate
149 @param[out] FoundSection The FFS section if found
150
151 @retval EFI_SUCCESS The file and section was found
152 @retval EFI_NOT_FOUND The file and section was not found
153 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
154
155**/
156EFI_STATUS
0913fadc 157EFIAPI
c1c2669c 158FindFfsFileAndSection (
159 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
160 IN EFI_FV_FILETYPE FileType,
161 IN EFI_SECTION_TYPE SectionType,
162 OUT EFI_COMMON_SECTION_HEADER **FoundSection
0913fadc 163 )
164{
165 EFI_STATUS Status;
166 EFI_PHYSICAL_ADDRESS CurrentAddress;
167 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
168 EFI_FFS_FILE_HEADER *File;
169 UINT32 Size;
170 EFI_PHYSICAL_ADDRESS EndOfFile;
0913fadc 171
c1c2669c 172 if (Fv->Signature != EFI_FVH_SIGNATURE) {
173 DEBUG ((EFI_D_INFO, "FV at %p does not have FV header signature\n", Fv));
174 return EFI_VOLUME_CORRUPTED;
175 }
0913fadc 176
c1c2669c 177 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;
178 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
0913fadc 179
180 //
181 // Loop through the FFS files in the Boot Firmware Volume
182 //
c1c2669c 183 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
0913fadc 184
c1c2669c 185 CurrentAddress = (EndOfFile + 7) & ~(7ULL);
0913fadc 186 if (CurrentAddress > EndOfFirmwareVolume) {
c1c2669c 187 return EFI_VOLUME_CORRUPTED;
0913fadc 188 }
189
190 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
191 Size = *(UINT32*) File->Size & 0xffffff;
c1c2669c 192 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
193 return EFI_VOLUME_CORRUPTED;
0913fadc 194 }
c1c2669c 195 DEBUG ((EFI_D_INFO, "File->Type: 0x%x\n", File->Type));
0913fadc 196
197 EndOfFile = CurrentAddress + Size;
198 if (EndOfFile > EndOfFirmwareVolume) {
c1c2669c 199 return EFI_VOLUME_CORRUPTED;
0913fadc 200 }
201
202 //
c1c2669c 203 // Look for the request file type
0913fadc 204 //
c1c2669c 205 if (File->Type != FileType) {
206 DEBUG ((EFI_D_INFO, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType));
0913fadc 207 continue;
208 }
209
c1c2669c 210 Status = FindFfsSectionInSections (
211 (VOID*) (File + 1),
212 (UINTN) EndOfFile - (UINTN) (File + 1),
213 SectionType,
214 FoundSection
215 );
216 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
217 return Status;
0913fadc 218 }
c1c2669c 219 }
c1c2669c 220}
221
222
223/**
224 Locates the compressed main firmware volume and decompresses it.
225
226 @param[in,out] Fv On input, the firmware volume to search
227 On output, the decompressed main FV
228
229 @retval EFI_SUCCESS The file and section was found
230 @retval EFI_NOT_FOUND The file and section was not found
231 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
232
233**/
234EFI_STATUS
235EFIAPI
236DecompressGuidedFv (
237 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv
238 )
239{
240 EFI_STATUS Status;
241 EFI_GUID_DEFINED_SECTION *Section;
242 UINT32 OutputBufferSize;
243 UINT32 ScratchBufferSize;
244 UINT16 SectionAttribute;
245 UINT32 AuthenticationStatus;
246 VOID *OutputBuffer;
247 VOID *ScratchBuffer;
248 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;
249 EFI_FIRMWARE_VOLUME_HEADER *NewFv;
0913fadc 250
c1c2669c 251 NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;
252
253 Status = FindFfsFileAndSection (
254 *Fv,
255 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
256 EFI_SECTION_GUID_DEFINED,
257 (EFI_COMMON_SECTION_HEADER**) &Section
258 );
259 if (EFI_ERROR (Status)) {
260 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));
261 return Status;
262 }
263
264 Status = ExtractGuidedSectionGetInfo (
265 Section,
266 &OutputBufferSize,
267 &ScratchBufferSize,
268 &SectionAttribute
269 );
270 if (EFI_ERROR (Status)) {
271 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));
272 return Status;
273 }
274
275 //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)
276 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);
277 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);
278 Status = ExtractGuidedSectionDecode (
279 Section,
280 &OutputBuffer,
281 ScratchBuffer,
282 &AuthenticationStatus
283 );
284 if (EFI_ERROR (Status)) {
285 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));
286 return Status;
287 }
288
289 Status = FindFfsSectionInSections (
290 OutputBuffer,
291 OutputBufferSize,
292 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
293 (EFI_COMMON_SECTION_HEADER**) &NewFvSection
294 );
295 if (EFI_ERROR (Status)) {
296 DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));
297 return Status;
0913fadc 298 }
c1c2669c 299
300 NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);
301 CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));
302
303 if (NewFv->Signature != EFI_FVH_SIGNATURE) {
304 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));
305 CpuDeadLoop ();
306 return EFI_VOLUME_CORRUPTED;
307 }
308
309 *Fv = NewFv;
310 return EFI_SUCCESS;
311}
312
313
314/**
315 Locates the PEI Core entry point address
316
317 @param[in] Fv The firmware volume to search
318 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
319
320 @retval EFI_SUCCESS The file and section was found
321 @retval EFI_NOT_FOUND The file and section was not found
322 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
323
324**/
325EFI_STATUS
326EFIAPI
327FindPeiCoreEntryPointInFv (
328 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
329 OUT VOID **PeiCoreEntryPoint
330 )
331{
332 EFI_STATUS Status;
333 EFI_COMMON_SECTION_HEADER *Section;
334
335 Status = FindFfsFileAndSection (
336 Fv,
337 EFI_FV_FILETYPE_PEI_CORE,
338 EFI_SECTION_PE32,
339 &Section
340 );
341 if (EFI_ERROR (Status)) {
342 Status = FindFfsFileAndSection (
343 Fv,
344 EFI_FV_FILETYPE_PEI_CORE,
345 EFI_SECTION_TE,
346 &Section
347 );
348 if (EFI_ERROR (Status)) {
349 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));
350 return Status;
351 }
352 }
353
354 return PeCoffLoaderGetEntryPoint ((VOID*) (Section + 1), PeiCoreEntryPoint);
355}
356
357
358/**
359 Locates the PEI Core entry point address
360
361 @param[in,out] Fv The firmware volume to search
362 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
363
364 @retval EFI_SUCCESS The file and section was found
365 @retval EFI_NOT_FOUND The file and section was not found
366 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
367
368**/
369VOID
370EFIAPI
371FindPeiCoreEntryPoint (
372 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
373 OUT VOID **PeiCoreEntryPoint
374 )
375{
376 *PeiCoreEntryPoint = NULL;
377
378 FindMainFv (BootFv);
379
380 DecompressGuidedFv (BootFv);
381
382 FindPeiCoreEntryPointInFv (*BootFv, PeiCoreEntryPoint);
0913fadc 383}
384