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