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