]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/FwVol/FwVol.c
Merge the PI enabling works from the branch
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
CommitLineData
192f6d4c 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
192f6d4c 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_FVB2_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_FVB2_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
0c2b5da8 254 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 255 IN EFI_SECTION_TYPE SectionType,\r
0c2b5da8 256 IN EFI_PEI_FILE_HANDLE FileHandle,\r
192f6d4c 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
0c2b5da8 282 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
192f6d4c 283\r
0c2b5da8 284 FfsFileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;\r
285 \r
192f6d4c 286 //\r
287 // Size is 24 bits wide so mask upper 8 bits. \r
288 // Does not include FfsFileHeader header size\r
289 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
290 //\r
291 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);\r
292 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
293 FileSize -= sizeof(EFI_FFS_FILE_HEADER);\r
294 \r
295 *SectionData = NULL;\r
296 ParsedLength = 0;\r
297 while (ParsedLength < FileSize) {\r
298 if (Section->Type == SectionType) {\r
299 *SectionData = (VOID *)(Section + 1);\r
300\r
301\r
302 return EFI_SUCCESS;\r
303 }\r
304 //\r
305 // Size is 24 bits wide so mask upper 8 bits. \r
306 // SectionLength is adjusted it is 4 byte aligned.\r
307 // Go to the next section\r
308 //\r
309 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
310 SectionLength = GETOCCUPIEDSIZE (SectionLength, 4);\r
311 ASSERT (SectionLength != 0);\r
312 ParsedLength += SectionLength;\r
313 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
314 }\r
315 \r
316 return EFI_NOT_FOUND;\r
317 \r
318}\r
319\r
320\r
321EFI_STATUS\r
322FindNextPeim (\r
323 IN EFI_PEI_SERVICES **PeiServices,\r
324 IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,\r
325 IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader\r
326 )\r
327/*++\r
328\r
329Routine Description:\r
330 Given the input file pointer, search for the next matching file in the\r
331 FFS volume. The search starts from FileHeader inside\r
332 the Firmware Volume defined by FwVolHeader.\r
333\r
334Arguments:\r
335 PeiServices - Pointer to the PEI Core Services Table.\r
336\r
337 FwVolHeader - Pointer to the FV header of the volume to search.\r
338 This parameter must point to a valid FFS volume.\r
339 \r
340 PeimFileHeader - Pointer to the current file from which to begin searching.\r
341 This pointer will be updated upon return to reflect the file found.\r
342\r
343Returns:\r
344 EFI_NOT_FOUND - No files matching the search criteria were found\r
345 EFI_SUCCESS\r
346\r
347--*/\r
348{\r
349 return PeiFfsFindNextFileEx ( \r
350 0,\r
351 FwVolHeader,\r
352 PeimFileHeader,\r
353 TRUE\r
354 );\r
355}\r
356\r
357EFI_STATUS\r
358EFIAPI\r
359PeiFfsFindNextFile (\r
0c2b5da8 360 IN CONST EFI_PEI_SERVICES **PeiServices,\r
361 IN UINT8 SearchType,\r
362 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
363 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
192f6d4c 364 )\r
365/*++\r
366\r
367Routine Description:\r
368 Given the input file pointer, search for the next matching file in the\r
369 FFS volume as defined by SearchType. The search starts from FileHeader inside\r
370 the Firmware Volume defined by FwVolHeader.\r
371\r
372Arguments:\r
373 PeiServices - Pointer to the PEI Core Services Table.\r
374 \r
375 SearchType - Filter to find only files of this type.\r
376 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
377 \r
378 FwVolHeader - Pointer to the FV header of the volume to search.\r
379 This parameter must point to a valid FFS volume.\r
380 \r
381 FileHeader - Pointer to the current file from which to begin searching.\r
382 This pointer will be updated upon return to reflect the file found.\r
383 \r
384Returns:\r
385 EFI_NOT_FOUND - No files matching the search criteria were found\r
386 EFI_SUCCESS\r
387\r
388--*/\r
389{\r
0c2b5da8 390 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
391 EFI_FFS_FILE_HEADER **FileHeader;\r
392\r
393 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)VolumeHandle;\r
394 FileHeader = (EFI_FFS_FILE_HEADER **) FileHandle;\r
395\r
192f6d4c 396 return PeiFfsFindNextFileEx ( \r
397 SearchType,\r
398 FwVolHeader,\r
399 FileHeader,\r
400 FALSE\r
401 );\r
402}\r
403\r
404EFI_STATUS \r
405EFIAPI\r
406PeiFvFindNextVolume (\r
0c2b5da8 407 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 408 IN UINTN Instance,\r
0c2b5da8 409 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
192f6d4c 410 )\r
411/*++\r
412\r
413Routine Description:\r
414\r
415 Return the BFV location\r
416\r
417 BugBug -- Move this to the location of this code to where the\r
418 other FV and FFS support code lives.\r
419 Also, update to use FindFV for instances #'s >= 1.\r
420\r
421Arguments:\r
422\r
423 PeiServices - The PEI core services table.\r
424 Instance - Instance of FV to find\r
425 FwVolHeader - Pointer to contain the data to return\r
426\r
427Returns:\r
428 Pointer to the Firmware Volume instance requested\r
429\r
430 EFI_INVALID_PARAMETER - FwVolHeader is NULL\r
431 \r
432 EFI_SUCCESS - Firmware volume instance successfully found.\r
433\r
434--*/\r
435{\r
436 PEI_CORE_INSTANCE *PrivateData;\r
437 EFI_STATUS Status;\r
438 EFI_PEI_FIND_FV_PPI *FindFvPpi;\r
439 UINT8 LocalInstance;\r
0c2b5da8 440 EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader;\r
192f6d4c 441\r
0c2b5da8 442 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER **) VolumeHandle;\r
192f6d4c 443\r
444 LocalInstance = (UINT8) Instance;\r
445\r
446 Status = EFI_SUCCESS;\r
447 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);\r
448\r
449 if (FwVolHeader == NULL) {\r
450\r
451 return EFI_INVALID_PARAMETER;\r
452 }\r
453\r
454 if (Instance == 0) {\r
455 *FwVolHeader = PrivateData->DispatchData.BootFvAddress;\r
456\r
457\r
458 return Status;\r
459 } else {\r
460 //\r
461 // Locate all instances of FindFV\r
462 // Alternately, could use FV HOBs, but the PPI is cleaner\r
463 //\r
464 Status = PeiServicesLocatePpi (\r
465 &gEfiFindFvPpiGuid,\r
466 0,\r
467 NULL,\r
468 (VOID **)&FindFvPpi\r
469 );\r
470\r
471 if (Status != EFI_SUCCESS) {\r
472 Status = EFI_NOT_FOUND;\r
473 } else {\r
474 Status = FindFvPpi->FindFv (\r
475 FindFvPpi,\r
0c2b5da8 476 (EFI_PEI_SERVICES **)PeiServices,\r
192f6d4c 477 &LocalInstance,\r
478 FwVolHeader\r
479 ); \r
480\r
481 }\r
482 }\r
483 return Status;\r
484}\r