]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/FwVol/FwVol.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / FwVol / FwVol.c
CommitLineData
162ed594 1/** @file\r
28a00297 2 Firmware File System driver that produce Firmware Volume protocol.\r
022c6d45 3 Layers on top of Firmware Block protocol to produce a file abstraction\r
28a00297 4 of FV based files.\r
23c98c94 5\r
9aef5156 6Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
9d510e61 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
28a00297 8\r
9**/\r
10\r
9c4ac31c 11#include "DxeMain.h"\r
ec90508b 12#include "FwVolDriver.h"\r
28a00297 13\r
28a00297 14\r
15//\r
16// Protocol notify related globals\r
17//\r
18VOID *gEfiFwVolBlockNotifyReg;\r
19EFI_EVENT gEfiFwVolBlockEvent;\r
20\r
21FV_DEVICE mFvDevice = {\r
0c2b5da8 22 FV2_DEVICE_SIGNATURE,\r
28a00297 23 NULL,\r
24 NULL,\r
25 {\r
26 FvGetVolumeAttributes,\r
27 FvSetVolumeAttributes,\r
28 FvReadFile,\r
29 FvReadFileSection,\r
30 FvWriteFile,\r
d1102dba
LG
31 FvGetNextFile,\r
32 sizeof (UINTN),\r
0c2b5da8 33 NULL,\r
34 FvGetVolumeInfo,\r
35 FvSetVolumeInfo\r
28a00297 36 },\r
37 NULL,\r
38 NULL,\r
39 NULL,\r
40 NULL,\r
41 { NULL, NULL },\r
0c3a1db4 42 0,\r
eb1cace2 43 0,\r
0c3a1db4 44 FALSE,\r
eb1cace2 45 FALSE\r
28a00297 46};\r
47\r
48\r
49//\r
50// FFS helper functions\r
51//\r
162ed594 52/**\r
d1102dba 53 Read data from Firmware Block by FVB protocol Read.\r
657abcff
LG
54 The data may cross the multi block ranges.\r
55\r
56 @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read data.\r
57 @param StartLba Pointer to StartLba.\r
58 On input, the start logical block index from which to read.\r
59 On output,the end logical block index after reading.\r
60 @param Offset Pointer to Offset\r
61 On input, offset into the block at which to begin reading.\r
62 On output, offset into the end block after reading.\r
63 @param DataSize Size of data to be read.\r
64 @param Data Pointer to Buffer that the data will be read into.\r
65\r
66 @retval EFI_SUCCESS Successfully read data from firmware block.\r
67 @retval others\r
68**/\r
69EFI_STATUS\r
70ReadFvbData (\r
71 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,\r
72 IN OUT EFI_LBA *StartLba,\r
73 IN OUT UINTN *Offset,\r
74 IN UINTN DataSize,\r
75 OUT UINT8 *Data\r
76 )\r
77{\r
78 UINTN BlockSize;\r
79 UINTN NumberOfBlocks;\r
80 UINTN BlockIndex;\r
81 UINTN ReadDataSize;\r
82 EFI_STATUS Status;\r
d1102dba 83\r
657abcff
LG
84 //\r
85 // Try read data in current block\r
86 //\r
87 BlockIndex = 0;\r
88 ReadDataSize = DataSize;\r
89 Status = Fvb->Read (Fvb, *StartLba, *Offset, &ReadDataSize, Data);\r
90 if (Status == EFI_SUCCESS) {\r
91 *Offset += DataSize;\r
92 return EFI_SUCCESS;\r
93 } else if (Status != EFI_BAD_BUFFER_SIZE) {\r
94 //\r
95 // other error will direct return\r
96 //\r
97 return Status;\r
98 }\r
d1102dba 99\r
657abcff
LG
100 //\r
101 // Data crosses the blocks, read data from next block\r
102 //\r
103 DataSize -= ReadDataSize;\r
104 Data += ReadDataSize;\r
105 *StartLba = *StartLba + 1;\r
106 while (DataSize > 0) {\r
107 Status = Fvb->GetBlockSize (Fvb, *StartLba, &BlockSize, &NumberOfBlocks);\r
108 if (EFI_ERROR (Status)) {\r
109 return Status;\r
110 }\r
111\r
112 //\r
113 // Read data from the crossing blocks\r
114 //\r
d1102dba 115 BlockIndex = 0;\r
657abcff
LG
116 while (BlockIndex < NumberOfBlocks && DataSize >= BlockSize) {\r
117 Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &BlockSize, Data);\r
118 if (EFI_ERROR (Status)) {\r
119 return Status;\r
120 }\r
121 Data += BlockSize;\r
122 DataSize -= BlockSize;\r
123 BlockIndex ++;\r
124 }\r
d1102dba 125\r
657abcff
LG
126 //\r
127 // Data doesn't exceed the current block range.\r
128 //\r
129 if (DataSize < BlockSize) {\r
130 break;\r
131 }\r
d1102dba 132\r
657abcff
LG
133 //\r
134 // Data must be got from the next block range.\r
135 //\r
136 *StartLba += NumberOfBlocks;\r
137 }\r
d1102dba 138\r
657abcff
LG
139 //\r
140 // read the remaining data\r
141 //\r
142 if (DataSize > 0) {\r
143 Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &DataSize, Data);\r
144 if (EFI_ERROR (Status)) {\r
145 return Status;\r
146 }\r
147 }\r
d1102dba 148\r
657abcff
LG
149 //\r
150 // Update Lba and Offset used by the following read.\r
151 //\r
152 *StartLba += BlockIndex;\r
153 *Offset = DataSize;\r
154\r
155 return EFI_SUCCESS;\r
156}\r
157\r
158/**\r
159 Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
160 copy the real length volume header into it.\r
28a00297 161\r
022c6d45 162 @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to\r
163 read the volume header\r
164 @param FwVolHeader Pointer to pointer to allocated buffer in which\r
165 the volume header is returned.\r
28a00297 166\r
022c6d45 167 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
168 @retval EFI_SUCCESS Successfully read volume header to the allocated\r
162ed594 169 buffer.\r
4888d15e
SZ
170 @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or\r
171 the file system could not be understood.\r
28a00297 172\r
162ed594 173**/\r
174EFI_STATUS\r
175GetFwVolHeader (\r
176 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,\r
177 OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader\r
178 )\r
28a00297 179{\r
180 EFI_STATUS Status;\r
181 EFI_FIRMWARE_VOLUME_HEADER TempFvh;\r
182 UINTN FvhLength;\r
657abcff
LG
183 EFI_LBA StartLba;\r
184 UINTN Offset;\r
28a00297 185 UINT8 *Buffer;\r
d1102dba 186\r
28a00297 187 //\r
657abcff 188 // Read the standard FV header\r
28a00297 189 //\r
657abcff
LG
190 StartLba = 0;\r
191 Offset = 0;\r
28a00297 192 FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
657abcff 193 Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, (UINT8 *)&TempFvh);\r
13492369 194 if (EFI_ERROR (Status)) {\r
195 return Status;\r
196 }\r
28a00297 197\r
4888d15e
SZ
198 //\r
199 // Validate FV Header signature, if not as expected, continue.\r
200 //\r
201 if (TempFvh.Signature != EFI_FVH_SIGNATURE) {\r
202 return EFI_INVALID_PARAMETER;\r
203 }\r
204\r
205 //\r
206 // Check to see that the file system is indeed formatted in a way we can\r
207 // understand it...\r
208 //\r
209 if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&\r
210 (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {\r
211 return EFI_INVALID_PARAMETER;\r
212 }\r
213\r
28a00297 214 //\r
215 // Allocate a buffer for the caller\r
216 //\r
9c4ac31c 217 *FwVolHeader = AllocatePool (TempFvh.HeaderLength);\r
28a00297 218 if (*FwVolHeader == NULL) {\r
219 return EFI_OUT_OF_RESOURCES;\r
220 }\r
221\r
222 //\r
223 // Copy the standard header into the buffer\r
224 //\r
225 CopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
226\r
227 //\r
228 // Read the rest of the header\r
229 //\r
230 FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
231 Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
657abcff 232 Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, Buffer);\r
28a00297 233 if (EFI_ERROR (Status)) {\r
234 //\r
235 // Read failed so free buffer\r
236 //\r
237 CoreFreePool (*FwVolHeader);\r
238 }\r
022c6d45 239\r
28a00297 240 return Status;\r
241}\r
242\r
243\r
28a00297 244\r
162ed594 245/**\r
28a00297 246 Free FvDevice resource when error happens\r
247\r
022c6d45 248 @param FvDevice pointer to the FvDevice to be freed.\r
28a00297 249\r
162ed594 250**/\r
162ed594 251VOID\r
252FreeFvDeviceResource (\r
253 IN FV_DEVICE *FvDevice\r
254 )\r
28a00297 255{\r
256 FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
257 LIST_ENTRY *NextEntry;\r
258\r
259 //\r
260 // Free File List Entry\r
261 //\r
262 FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink;\r
263 while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {\r
264 NextEntry = (&FfsFileEntry->Link)->ForwardLink;\r
022c6d45 265\r
28a00297 266 if (FfsFileEntry->StreamHandle != 0) {\r
267 //\r
268 // Close stream and free resources from SEP\r
269 //\r
eb1cace2
SZ
270 CloseSectionStream (FfsFileEntry->StreamHandle, FALSE);\r
271 }\r
272\r
273 if (FfsFileEntry->FileCached) {\r
274 //\r
275 // Free the cached file buffer.\r
276 //\r
277 CoreFreePool (FfsFileEntry->FfsHeader);\r
28a00297 278 }\r
279\r
280 CoreFreePool (FfsFileEntry);\r
281\r
e94a9ff7 282 FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;\r
28a00297 283 }\r
284\r
eb1cace2
SZ
285 if (!FvDevice->IsMemoryMapped) {\r
286 //\r
287 // Free the cached FV buffer.\r
288 //\r
289 CoreFreePool (FvDevice->CachedFv);\r
290 }\r
28a00297 291\r
292 //\r
293 // Free Volume Header\r
294 //\r
295 CoreFreePool (FvDevice->FwVolHeader);\r
296\r
297 return;\r
298}\r
299\r
300\r
28a00297 301\r
162ed594 302/**\r
e94a9ff7 303 Check if an FV is consistent and allocate cache for it.\r
28a00297 304\r
022c6d45 305 @param FvDevice A pointer to the FvDevice to be checked.\r
28a00297 306\r
022c6d45 307 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
308 @retval EFI_SUCCESS FV is consistent and cache is allocated.\r
162ed594 309 @retval EFI_VOLUME_CORRUPTED File system is corrupted.\r
28a00297 310\r
162ed594 311**/\r
312EFI_STATUS\r
313FvCheck (\r
314 IN OUT FV_DEVICE *FvDevice\r
315 )\r
28a00297 316{\r
317 EFI_STATUS Status;\r
318 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
319 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
f95f107c 320 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;\r
8ee3a199 321 EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
28a00297 322 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
323 FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
324 EFI_FFS_FILE_HEADER *FfsHeader;\r
325 UINT8 *CacheLocation;\r
28a00297 326 UINTN Index;\r
327 EFI_LBA LbaIndex;\r
328 UINTN Size;\r
28a00297 329 EFI_FFS_FILE_STATE FileState;\r
330 UINT8 *TopFvAddress;\r
331 UINTN TestLength;\r
eb1cace2 332 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
bc012551
SZ
333 BOOLEAN FileCached;\r
334 UINTN WholeFileSize;\r
335 EFI_FFS_FILE_HEADER *CacheFfsHeader;\r
336\r
337 FileCached = FALSE;\r
338 CacheFfsHeader = NULL;\r
28a00297 339\r
340 Fvb = FvDevice->Fvb;\r
341 FwVolHeader = FvDevice->FwVolHeader;\r
022c6d45 342\r
28a00297 343 Status = Fvb->GetAttributes (Fvb, &FvbAttributes);\r
344 if (EFI_ERROR (Status)) {\r
345 return Status;\r
346 }\r
347\r
9aef5156 348 Size = (UINTN) FwVolHeader->FvLength;\r
eb1cace2
SZ
349 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
350 FvDevice->IsMemoryMapped = TRUE;\r
28a00297 351\r
eb1cace2
SZ
352 Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress);\r
353 if (EFI_ERROR (Status)) {\r
354 return Status;\r
355 }\r
356\r
357 //\r
358 // Don't cache memory mapped FV really.\r
359 //\r
9aef5156 360 FvDevice->CachedFv = (UINT8 *) (UINTN) PhysicalAddress;\r
eb1cace2
SZ
361 } else {\r
362 FvDevice->IsMemoryMapped = FALSE;\r
363 FvDevice->CachedFv = AllocatePool (Size);\r
364\r
365 if (FvDevice->CachedFv == NULL) {\r
366 return EFI_OUT_OF_RESOURCES;\r
367 }\r
28a00297 368 }\r
369\r
370 //\r
9aef5156 371 // Remember a pointer to the end of the CachedFv\r
28a00297 372 //\r
373 FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;\r
374\r
eb1cace2 375 if (!FvDevice->IsMemoryMapped) {\r
657abcff 376 //\r
9aef5156 377 // Copy FV into memory using the block map.\r
657abcff 378 //\r
eb1cace2
SZ
379 BlockMap = FwVolHeader->BlockMap;\r
380 CacheLocation = FvDevice->CachedFv;\r
381 LbaIndex = 0;\r
eb1cace2 382 while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
28a00297 383 //\r
d1102dba 384 // read the FV data\r
28a00297 385 //\r
9aef5156
SZ
386 Size = BlockMap->Length;\r
387 for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
388 Status = Fvb->Read (\r
389 Fvb,\r
eb1cace2 390 LbaIndex,\r
9aef5156 391 0,\r
eb1cace2
SZ
392 &Size,\r
393 CacheLocation\r
394 );\r
395\r
396 //\r
397 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
398 //\r
399 if (EFI_ERROR (Status)) {\r
400 goto Done;\r
401 }\r
402\r
403 LbaIndex++;\r
9aef5156 404 CacheLocation += BlockMap->Length;\r
28a00297 405 }\r
022c6d45 406\r
eb1cace2 407 BlockMap++;\r
28a00297 408 }\r
28a00297 409 }\r
410\r
411 //\r
412 // Scan to check the free space & File list\r
413 //\r
71f68914 414 if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {\r
28a00297 415 FvDevice->ErasePolarity = 1;\r
416 } else {\r
417 FvDevice->ErasePolarity = 0;\r
022c6d45 418 }\r
28a00297 419\r
420\r
421 //\r
422 // go through the whole FV cache, check the consistence of the FV.\r
f95f107c 423 // Make a linked list of all the Ffs file headers\r
28a00297 424 //\r
425 Status = EFI_SUCCESS;\r
426 InitializeListHead (&FvDevice->FfsFileListHeader);\r
427\r
428 //\r
429 // Build FFS list\r
430 //\r
f95f107c
SZ
431 if (FwVolHeader->ExtHeaderOffset != 0) {\r
432 //\r
433 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.\r
434 //\r
9aef5156 435 FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + FwVolHeader->ExtHeaderOffset);\r
f95f107c 436 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize);\r
f95f107c 437 } else {\r
9aef5156 438 FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv + FwVolHeader->HeaderLength);\r
f95f107c 439 }\r
9aef5156 440 FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8);\r
28a00297 441 TopFvAddress = FvDevice->EndOfCachedFv;\r
fd8a2eb0 442 while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) {\r
28a00297 443\r
bc012551
SZ
444 if (FileCached) {\r
445 CoreFreePool (CacheFfsHeader);\r
446 FileCached = FALSE;\r
447 }\r
448\r
e94a9ff7 449 TestLength = TopFvAddress - ((UINT8 *) FfsHeader);\r
28a00297 450 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
451 TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
452 }\r
453\r
454 if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) {\r
455 //\r
456 // We have found the free space so we are done!\r
457 //\r
458 goto Done;\r
459 }\r
460\r
461 if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) {\r
022c6d45 462 if ((FileState == EFI_FILE_HEADER_INVALID) ||\r
28a00297 463 (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {\r
6c85d162
SZ
464 if (IS_FFS_FILE2 (FfsHeader)) {\r
465 if (!FvDevice->IsFfs3Fv) {\r
466 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name));\r
467 }\r
468 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2));\r
469 } else {\r
470 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER));\r
471 }\r
28a00297 472 continue;\r
28a00297 473 } else {\r
474 //\r
475 // File system is corrputed\r
476 //\r
477 Status = EFI_VOLUME_CORRUPTED;\r
478 goto Done;\r
479 }\r
480 }\r
481\r
bc012551
SZ
482 CacheFfsHeader = FfsHeader;\r
483 if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {\r
484 if (FvDevice->IsMemoryMapped) {\r
485 //\r
486 // Memory mapped FV has not been cached.\r
487 // Here is to cache FFS file to memory buffer for following checksum calculating.\r
488 // And then, the cached file buffer can be also used for FvReadFile.\r
489 //\r
490 WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader);\r
491 CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader);\r
492 if (CacheFfsHeader == NULL) {\r
493 Status = EFI_OUT_OF_RESOURCES;\r
494 goto Done;\r
495 }\r
496 FileCached = TRUE;\r
497 }\r
498 }\r
499\r
500 if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) {\r
28a00297 501 //\r
502 // File system is corrupted\r
503 //\r
504 Status = EFI_VOLUME_CORRUPTED;\r
505 goto Done;\r
506 }\r
507\r
bc012551
SZ
508 if (IS_FFS_FILE2 (CacheFfsHeader)) {\r
509 ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF);\r
6c85d162 510 if (!FvDevice->IsFfs3Fv) {\r
bc012551
SZ
511 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name));\r
512 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));\r
6c85d162 513 //\r
6393d9c8 514 // Adjust pointer to the next 8-byte aligned boundary.\r
6c85d162
SZ
515 //\r
516 FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07);\r
517 continue;\r
518 }\r
519 }\r
28a00297 520\r
bc012551 521 FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader);\r
022c6d45 522\r
28a00297 523 //\r
524 // check for non-deleted file\r
525 //\r
526 if (FileState != EFI_FILE_DELETED) {\r
527 //\r
528 // Create a FFS list entry for each non-deleted file\r
529 //\r
9c4ac31c 530 FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));\r
28a00297 531 if (FfsFileEntry == NULL) {\r
532 Status = EFI_OUT_OF_RESOURCES;\r
533 goto Done;\r
534 }\r
022c6d45 535\r
bc012551
SZ
536 FfsFileEntry->FfsHeader = CacheFfsHeader;\r
537 FfsFileEntry->FileCached = FileCached;\r
538 FileCached = FALSE;\r
28a00297 539 InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r
540 }\r
541\r
bc012551
SZ
542 if (IS_FFS_FILE2 (CacheFfsHeader)) {\r
543 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));\r
6c85d162 544 } else {\r
bc012551 545 FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader));\r
6c85d162 546 }\r
022c6d45 547\r
28a00297 548 //\r
6393d9c8 549 // Adjust pointer to the next 8-byte aligned boundary.\r
28a00297 550 //\r
551 FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07);\r
022c6d45 552\r
28a00297 553 }\r
554\r
555Done:\r
556 if (EFI_ERROR (Status)) {\r
bc012551
SZ
557 if (FileCached) {\r
558 CoreFreePool (CacheFfsHeader);\r
559 FileCached = FALSE;\r
560 }\r
28a00297 561 FreeFvDeviceResource (FvDevice);\r
562 }\r
563\r
564 return Status;\r
565}\r
566\r
567\r
162ed594 568\r
569/**\r
570 This notification function is invoked when an instance of the\r
6c85d162 571 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the\r
162ed594 572 EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where\r
573 the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.\r
574\r
022c6d45 575 @param Event The event that occured\r
162ed594 576 @param Context For EFI compatiblity. Not used.\r
577\r
578**/\r
28a00297 579VOID\r
580EFIAPI\r
581NotifyFwVolBlock (\r
582 IN EFI_EVENT Event,\r
583 IN VOID *Context\r
584 )\r
28a00297 585{\r
586 EFI_HANDLE Handle;\r
587 EFI_STATUS Status;\r
588 UINTN BufferSize;\r
589 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
0c2b5da8 590 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
28a00297 591 FV_DEVICE *FvDevice;\r
592 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
593 //\r
594 // Examine all new handles\r
595 //\r
596 for (;;) {\r
597 //\r
598 // Get the next handle\r
599 //\r
600 BufferSize = sizeof (Handle);\r
601 Status = CoreLocateHandle (\r
602 ByRegisterNotify,\r
603 NULL,\r
604 gEfiFwVolBlockNotifyReg,\r
605 &BufferSize,\r
606 &Handle\r
607 );\r
608\r
609 //\r
610 // If not found, we're done\r
611 //\r
612 if (EFI_NOT_FOUND == Status) {\r
613 break;\r
614 }\r
615\r
616 if (EFI_ERROR (Status)) {\r
617 continue;\r
618 }\r
022c6d45 619\r
28a00297 620 //\r
621 // Get the FirmwareVolumeBlock protocol on that handle\r
622 //\r
022c6d45 623 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);\r
28a00297 624 ASSERT_EFI_ERROR (Status);\r
20bcdbcb 625 ASSERT (Fvb != NULL);\r
28a00297 626\r
627 //\r
628 // Make sure the Fv Header is O.K.\r
629 //\r
630 Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
631 if (EFI_ERROR (Status)) {\r
684a565a 632 continue;\r
28a00297 633 }\r
d2fbaaab 634 ASSERT (FwVolHeader != NULL);\r
28a00297 635\r
636 if (!VerifyFvHeaderChecksum (FwVolHeader)) {\r
637 CoreFreePool (FwVolHeader);\r
638 continue;\r
639 }\r
640\r
28a00297 641 //\r
642 // Check if there is an FV protocol already installed in that handle\r
643 //\r
0c2b5da8 644 Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);\r
28a00297 645 if (!EFI_ERROR (Status)) {\r
646 //\r
647 // Update Fv to use a new Fvb\r
648 //\r
50d7ebad 649 FvDevice = BASE_CR (Fv, FV_DEVICE, Fv);\r
0c2b5da8 650 if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) {\r
28a00297 651 //\r
652 // Only write into our device structure if it's our device structure\r
653 //\r
654 FvDevice->Fvb = Fvb;\r
655 }\r
656\r
657 } else {\r
658 //\r
659 // No FwVol protocol on the handle so create a new one\r
660 //\r
9c4ac31c 661 FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);\r
28a00297 662 if (FvDevice == NULL) {\r
663 return;\r
664 }\r
022c6d45 665\r
e94a9ff7 666 FvDevice->Fvb = Fvb;\r
667 FvDevice->Handle = Handle;\r
668 FvDevice->FwVolHeader = FwVolHeader;\r
6c85d162 669 FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
0c3a1db4 670 FvDevice->Fv.ParentHandle = Fvb->ParentHandle;\r
c6037045
SZ
671 //\r
672 // Inherit the authentication status from FVB.\r
673 //\r
674 FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb);\r
d1102dba 675\r
1f33d186
LG
676 if (!EFI_ERROR (FvCheck (FvDevice))) {\r
677 //\r
678 // Install an New FV protocol on the existing handle\r
679 //\r
680 Status = CoreInstallProtocolInterface (\r
681 &Handle,\r
682 &gEfiFirmwareVolume2ProtocolGuid,\r
683 EFI_NATIVE_INTERFACE,\r
684 &FvDevice->Fv\r
685 );\r
686 ASSERT_EFI_ERROR (Status);\r
687 } else {\r
688 //\r
689 // Free FvDevice Buffer for the corrupt FV image.\r
690 //\r
691 CoreFreePool (FvDevice);\r
692 }\r
28a00297 693 }\r
694 }\r
022c6d45 695\r
28a00297 696 return;\r
697}\r
698\r
699\r
162ed594 700\r
701/**\r
13492369 702 This routine is the driver initialization entry point. It registers\r
703 a notification function. This notification function are responsible\r
704 for building the FV stack dynamically.\r
162ed594 705\r
022c6d45 706 @param ImageHandle The image handle.\r
707 @param SystemTable The system table.\r
162ed594 708\r
709 @retval EFI_SUCCESS Function successfully returned.\r
710\r
711**/\r
28a00297 712EFI_STATUS\r
713EFIAPI\r
714FwVolDriverInit (\r
715 IN EFI_HANDLE ImageHandle,\r
716 IN EFI_SYSTEM_TABLE *SystemTable\r
717 )\r
28a00297 718{\r
7899b797 719 gEfiFwVolBlockEvent = EfiCreateProtocolNotifyEvent (\r
28a00297 720 &gEfiFirmwareVolumeBlockProtocolGuid,\r
721 TPL_CALLBACK,\r
722 NotifyFwVolBlock,\r
723 NULL,\r
7899b797 724 &gEfiFwVolBlockNotifyReg\r
28a00297 725 );\r
726 return EFI_SUCCESS;\r
727}\r
728\r
162ed594 729\r