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