Enable Nt32 platform boot to DXE phase.
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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
14 FwVol.c
15
16 Abstract:
17
18 Pei Core Firmware File System service routines.
19
20 --*/
21
22 //
23 // Include common header file for this module.
24 //
25 #include "CommonHeader.h"
26
27 #include <PeiMain.h>
28
29 #define GETOCCUPIEDSIZE(ActualSize, Alignment) \
30 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
31
32 STATIC
33 EFI_FFS_FILE_STATE
34 GetFileState(
35 IN UINT8 ErasePolarity,
36 IN EFI_FFS_FILE_HEADER *FfsHeader
37 )
38 /*++
39
40 Routine Description:
41
42 Returns the highest bit set of the State field
43
44 Arguments:
45
46 ErasePolarity - Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
47 in the Attributes field.
48 FfsHeader - Pointer to FFS File Header.
49
50 Returns:
51 Returns the highest bit in the State field
52
53 --*/
54 {
55 EFI_FFS_FILE_STATE FileState;
56 EFI_FFS_FILE_STATE HighestBit;
57
58 FileState = FfsHeader->State;
59
60 if (ErasePolarity != 0) {
61 FileState = (EFI_FFS_FILE_STATE)~FileState;
62 }
63
64 HighestBit = 0x80;
65 while (HighestBit != 0 && (HighestBit & FileState) == 0) {
66 HighestBit >>= 1;
67 }
68
69 return HighestBit;
70 }
71
72 STATIC
73 UINT8
74 CalculateHeaderChecksum (
75 IN EFI_FFS_FILE_HEADER *FileHeader
76 )
77 /*++
78
79 Routine Description:
80
81 Calculates the checksum of the header of a file.
82
83 Arguments:
84
85 FileHeader - Pointer to FFS File Header.
86
87 Returns:
88 Checksum of the header.
89
90 The header is zero byte checksum.
91 - Zero means the header is good.
92 - Non-zero means the header is bad.
93
94
95 Bugbug: For PEI performance reason, we comments this code at this time.
96 --*/
97 {
98 UINT8 *ptr;
99 UINTN Index;
100 UINT8 Sum;
101
102 Sum = 0;
103 ptr = (UINT8 *)FileHeader;
104
105 for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {
106 Sum = (UINT8)(Sum + ptr[Index]);
107 Sum = (UINT8)(Sum + ptr[Index+1]);
108 Sum = (UINT8)(Sum + ptr[Index+2]);
109 Sum = (UINT8)(Sum + ptr[Index+3]);
110 }
111
112 for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
113 Sum = (UINT8)(Sum + ptr[Index]);
114 }
115
116 //
117 // State field (since this indicates the different state of file).
118 //
119 Sum = (UINT8)(Sum - FileHeader->State);
120 //
121 // Checksum field of the file is not part of the header checksum.
122 //
123 Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);
124
125 return Sum;
126 }
127
128 STATIC
129 EFI_STATUS
130 PeiFfsFindNextFileEx (
131 IN EFI_FV_FILETYPE SearchType,
132 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
133 IN OUT EFI_FFS_FILE_HEADER **FileHeader,
134 IN BOOLEAN Flag
135 )
136 /*++
137
138 Routine Description:
139 Given the input file pointer, search for the next matching file in the
140 FFS volume as defined by SearchType. The search starts from FileHeader inside
141 the Firmware Volume defined by FwVolHeader.
142
143 Arguments:
144 PeiServices - Pointer to the PEI Core Services Table.
145 SearchType - Filter to find only files of this type.
146 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
147 FwVolHeader - Pointer to the FV header of the volume to search.
148 This parameter must point to a valid FFS volume.
149 FileHeader - Pointer to the current file from which to begin searching.
150 This pointer will be updated upon return to reflect the file found.
151 Flag - Indicator for if this is for PEI Dispath search
152 Returns:
153 EFI_NOT_FOUND - No files matching the search criteria were found
154 EFI_SUCCESS
155
156 --*/
157 {
158 EFI_FFS_FILE_HEADER *FfsFileHeader;
159 UINT32 FileLength;
160 UINT32 FileOccupiedSize;
161 UINT32 FileOffset;
162 UINT64 FvLength;
163 UINT8 ErasePolarity;
164 UINT8 FileState;
165
166
167 FvLength = FwVolHeader->FvLength;
168 if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
169 ErasePolarity = 1;
170 } else {
171 ErasePolarity = 0;
172 }
173
174 //
175 // If FileHeader is not specified (NULL) start with the first file in the
176 // firmware volume. Otherwise, start from the FileHeader.
177 //
178 if (*FileHeader == NULL) {
179 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
180 } else {
181 //
182 // Length is 24 bits wide so mask upper 8 bits
183 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
184 //
185 FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;
186 FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
187 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
188 }
189
190 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
191 ASSERT (FileOffset <= 0xFFFFFFFF);
192
193 while (FileOffset < (FvLength - sizeof(EFI_FFS_FILE_HEADER))) {
194 //
195 // Get FileState which is the highest bit of the State
196 //
197 FileState = GetFileState (ErasePolarity, FfsFileHeader);
198
199 switch (FileState) {
200
201 case EFI_FILE_HEADER_INVALID:
202 FileOffset += sizeof(EFI_FFS_FILE_HEADER);
203 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
204 break;
205
206 case EFI_FILE_DATA_VALID:
207 case EFI_FILE_MARKED_FOR_UPDATE:
208 if (CalculateHeaderChecksum (FfsFileHeader) == 0) {
209 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
210 FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
211 if (Flag) {
212 if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) ||
213 (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) {
214
215 *FileHeader = FfsFileHeader;
216
217
218 return EFI_SUCCESS;
219 }
220 } else {
221 if ((SearchType == FfsFileHeader->Type) ||
222 (SearchType == EFI_FV_FILETYPE_ALL)) {
223
224 *FileHeader = FfsFileHeader;
225
226
227 return EFI_SUCCESS;
228 }
229 }
230
231 FileOffset += FileOccupiedSize;
232 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
233 } else {
234 ASSERT (FALSE);
235 return EFI_NOT_FOUND;
236 }
237 break;
238
239 case EFI_FILE_DELETED:
240 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
241 FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
242 FileOffset += FileOccupiedSize;
243 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
244 break;
245
246 default:
247 return EFI_NOT_FOUND;
248
249 }
250 }
251
252 return EFI_NOT_FOUND;
253 }
254
255
256 EFI_STATUS
257 EFIAPI
258 PeiFfsFindSectionData (
259 IN EFI_PEI_SERVICES **PeiServices,
260 IN EFI_SECTION_TYPE SectionType,
261 IN EFI_FFS_FILE_HEADER *FfsFileHeader,
262 IN OUT VOID **SectionData
263 )
264 /*++
265
266 Routine Description:
267 Given the input file pointer, search for the next matching section in the
268 FFS volume.
269
270 Arguments:
271 PeiServices - Pointer to the PEI Core Services Table.
272 SearchType - Filter to find only sections of this type.
273 FfsFileHeader - Pointer to the current file to search.
274 SectionData - Pointer to the Section matching SectionType in FfsFileHeader.
275 - NULL if section not found
276
277 Returns:
278 EFI_NOT_FOUND - No files matching the search criteria were found
279 EFI_SUCCESS
280
281 --*/
282 {
283 UINT32 FileSize;
284 EFI_COMMON_SECTION_HEADER *Section;
285 UINT32 SectionLength;
286 UINT32 ParsedLength;
287
288
289 //
290 // Size is 24 bits wide so mask upper 8 bits.
291 // Does not include FfsFileHeader header size
292 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
293 //
294 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);
295 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
296 FileSize -= sizeof(EFI_FFS_FILE_HEADER);
297
298 *SectionData = NULL;
299 ParsedLength = 0;
300 while (ParsedLength < FileSize) {
301 if (Section->Type == SectionType) {
302 *SectionData = (VOID *)(Section + 1);
303
304
305 return EFI_SUCCESS;
306 }
307 //
308 // Size is 24 bits wide so mask upper 8 bits.
309 // SectionLength is adjusted it is 4 byte aligned.
310 // Go to the next section
311 //
312 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
313 SectionLength = GETOCCUPIEDSIZE (SectionLength, 4);
314 ASSERT (SectionLength != 0);
315 ParsedLength += SectionLength;
316 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
317 }
318
319 return EFI_NOT_FOUND;
320
321 }
322
323
324 EFI_STATUS
325 FindNextPeim (
326 IN EFI_PEI_SERVICES **PeiServices,
327 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
328 IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader
329 )
330 /*++
331
332 Routine Description:
333 Given the input file pointer, search for the next matching file in the
334 FFS volume. The search starts from FileHeader inside
335 the Firmware Volume defined by FwVolHeader.
336
337 Arguments:
338 PeiServices - Pointer to the PEI Core Services Table.
339
340 FwVolHeader - Pointer to the FV header of the volume to search.
341 This parameter must point to a valid FFS volume.
342
343 PeimFileHeader - Pointer to the current file from which to begin searching.
344 This pointer will be updated upon return to reflect the file found.
345
346 Returns:
347 EFI_NOT_FOUND - No files matching the search criteria were found
348 EFI_SUCCESS
349
350 --*/
351 {
352 return PeiFfsFindNextFileEx (
353 0,
354 FwVolHeader,
355 PeimFileHeader,
356 TRUE
357 );
358 }
359
360 EFI_STATUS
361 EFIAPI
362 PeiFfsFindNextFile (
363 IN EFI_PEI_SERVICES **PeiServices,
364 IN EFI_FV_FILETYPE SearchType,
365 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
366 IN OUT EFI_FFS_FILE_HEADER **FileHeader
367 )
368 /*++
369
370 Routine Description:
371 Given the input file pointer, search for the next matching file in the
372 FFS volume as defined by SearchType. The search starts from FileHeader inside
373 the Firmware Volume defined by FwVolHeader.
374
375 Arguments:
376 PeiServices - Pointer to the PEI Core Services Table.
377
378 SearchType - Filter to find only files of this type.
379 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
380
381 FwVolHeader - Pointer to the FV header of the volume to search.
382 This parameter must point to a valid FFS volume.
383
384 FileHeader - Pointer to the current file from which to begin searching.
385 This pointer will be updated upon return to reflect the file found.
386
387 Returns:
388 EFI_NOT_FOUND - No files matching the search criteria were found
389 EFI_SUCCESS
390
391 --*/
392 {
393 return PeiFfsFindNextFileEx (
394 SearchType,
395 FwVolHeader,
396 FileHeader,
397 FALSE
398 );
399 }
400
401 EFI_STATUS
402 EFIAPI
403 PeiFvFindNextVolume (
404 IN EFI_PEI_SERVICES **PeiServices,
405 IN UINTN Instance,
406 IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
407 )
408 /*++
409
410 Routine Description:
411
412 Return the BFV location
413
414 BugBug -- Move this to the location of this code to where the
415 other FV and FFS support code lives.
416 Also, update to use FindFV for instances #'s >= 1.
417
418 Arguments:
419
420 PeiServices - The PEI core services table.
421 Instance - Instance of FV to find
422 FwVolHeader - Pointer to contain the data to return
423
424 Returns:
425 Pointer to the Firmware Volume instance requested
426
427 EFI_INVALID_PARAMETER - FwVolHeader is NULL
428
429 EFI_SUCCESS - Firmware volume instance successfully found.
430
431 --*/
432 {
433 PEI_CORE_INSTANCE *PrivateData;
434 EFI_STATUS Status;
435 EFI_PEI_FIND_FV_PPI *FindFvPpi;
436 UINT8 LocalInstance;
437
438
439 LocalInstance = (UINT8) Instance;
440
441 Status = EFI_SUCCESS;
442 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);
443
444 if (FwVolHeader == NULL) {
445
446 return EFI_INVALID_PARAMETER;
447 }
448
449 if (Instance == 0) {
450 *FwVolHeader = PrivateData->DispatchData.BootFvAddress;
451
452
453 return Status;
454 } else {
455 //
456 // Locate all instances of FindFV
457 // Alternately, could use FV HOBs, but the PPI is cleaner
458 //
459 Status = PeiServicesLocatePpi (
460 &gEfiFindFvPpiGuid,
461 0,
462 NULL,
463 (VOID **)&FindFvPpi
464 );
465
466 if (Status != EFI_SUCCESS) {
467 Status = EFI_NOT_FOUND;
468 } else {
469 Status = FindFvPpi->FindFv (
470 FindFvPpi,
471 PeiServices,
472 &LocalInstance,
473 FwVolHeader
474 );
475
476 }
477 }
478 return Status;
479 }