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