]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c
Optimize the log entry search algorithm to save boot performance.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / FwVolDxe / FwVol.c
CommitLineData
c2df8e13 1/** @file\r
2\r
3 Firmware File System driver that produce full Firmware Volume2 protocol.\r
4 Layers on top of Firmware Block protocol to produce a file abstraction\r
5 of FV based files.\r
6\r
f95f107c 7 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
c2df8e13 8\r
9 This program and the accompanying materials\r
10 are licensed and made available under the terms and conditions\r
11 of the BSD License which accompanies this distribution. The\r
12 full text of the license may be found at\r
13 http://opensource.org/licenses/bsd-license.php\r
14\r
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
17\r
18**/\r
19\r
20#include "FwVolDriver.h"\r
21\r
22#define KEYSIZE sizeof (UINTN)\r
23\r
24/**\r
25 Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
26 copy the real length volume header into it.\r
27\r
28 @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to\r
29 read the volume header\r
30 @param FwVolHeader Pointer to pointer to allocated buffer in which\r
31 the volume header is returned.\r
32\r
33 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
34 @retval EFI_SUCCESS Successfully read volume header to the allocated\r
35 buffer.\r
36 @retval EFI_ACCESS_DENIED Read status of FV is not enabled.\r
37**/\r
38EFI_STATUS\r
39GetFwVolHeader (\r
40 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,\r
41 OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader\r
42 )\r
43{\r
44 EFI_STATUS Status;\r
45 EFI_FIRMWARE_VOLUME_HEADER TempFvh;\r
46 EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
47 UINTN FvhLength;\r
48 EFI_PHYSICAL_ADDRESS BaseAddress;\r
49\r
50 //\r
51 // Determine the real length of FV header\r
52 //\r
53 Status = Fvb->GetAttributes (\r
54 Fvb,\r
55 &FvbAttributes\r
56 );\r
57 if (EFI_ERROR (Status)) {\r
58 return Status;\r
59 }\r
60\r
61 if ((FvbAttributes & EFI_FVB2_READ_STATUS) == 0) {\r
62 return EFI_ACCESS_DENIED;\r
63 }\r
64\r
65 //\r
66 // Just avoid compiling warning\r
67 //\r
68 BaseAddress = 0;\r
69 FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
70\r
71 //\r
72 // memory-mapped FV and non memory-mapped has different ways to read\r
73 //\r
74 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
75 Status = Fvb->GetPhysicalAddress (\r
76 Fvb,\r
77 &BaseAddress\r
78 );\r
79 if (EFI_ERROR (Status)) {\r
80 return Status;\r
81 }\r
82 CopyMem (&TempFvh, (VOID *) (UINTN) BaseAddress, FvhLength);\r
83 } else {\r
84 Status = Fvb->Read (\r
85 Fvb,\r
86 0,\r
87 0,\r
88 &FvhLength,\r
89 (UINT8 *) &TempFvh\r
90 );\r
91 }\r
92\r
93 *FwVolHeader = AllocatePool (TempFvh.HeaderLength);\r
94 if (*FwVolHeader == NULL) {\r
95 return EFI_OUT_OF_RESOURCES;\r
96 }\r
97 //\r
98 // Read the whole header\r
99 //\r
100 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
101 CopyMem (*FwVolHeader, (VOID *) (UINTN) BaseAddress, TempFvh.HeaderLength);\r
102 } else {\r
103 //\r
104 // Assumed the first block is bigger than the length of Fv headder\r
105 //\r
106 FvhLength = TempFvh.HeaderLength;\r
107 Status = Fvb->Read (\r
108 Fvb,\r
109 0,\r
110 0,\r
111 &FvhLength,\r
112 (UINT8 *) *FwVolHeader\r
113 );\r
114 //\r
115 // Check whether Read successes.\r
116 //\r
117 if (EFI_ERROR (Status)) {\r
118 FreePool (*FwVolHeader);\r
119 *FwVolHeader = NULL;\r
120 return Status;\r
121 }\r
122 }\r
123\r
124 return EFI_SUCCESS;\r
125}\r
126\r
127/**\r
128 Free FvDevice resource when error happens.\r
129\r
130 @param FvDevice Pointer to the FvDevice to be freed.\r
131**/\r
132VOID\r
133FreeFvDeviceResource (\r
134 IN FV_DEVICE *FvDevice\r
135 )\r
136{\r
137 LBA_ENTRY *LbaEntry;\r
138 FREE_SPACE_ENTRY *FreeSpaceEntry;\r
139 FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
140 LIST_ENTRY *NextEntry;\r
141\r
142 //\r
143 // Free LAB Entry\r
144 //\r
145 LbaEntry = (LBA_ENTRY *) FvDevice->LbaHeader.ForwardLink;\r
146 while (&LbaEntry->Link != &FvDevice->LbaHeader) {\r
147 NextEntry = (&LbaEntry->Link)->ForwardLink;\r
148 FreePool (LbaEntry);\r
149 LbaEntry = (LBA_ENTRY *) NextEntry;\r
150 }\r
151 //\r
152 // Free File List Entry\r
153 //\r
154 FfsFileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r
155 while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {\r
156 NextEntry = (&FfsFileEntry->Link)->ForwardLink;\r
157 FreePool (FfsFileEntry);\r
158 FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;\r
159 }\r
160 //\r
161 // Free Space Entry\r
162 //\r
163 FreeSpaceEntry = (FREE_SPACE_ENTRY *) FvDevice->FreeSpaceHeader.ForwardLink;\r
164 while (&FreeSpaceEntry->Link != &FvDevice->FreeSpaceHeader) {\r
165 NextEntry = (&FreeSpaceEntry->Link)->ForwardLink;\r
166 FreePool (FreeSpaceEntry);\r
167 FreeSpaceEntry = (FREE_SPACE_ENTRY *) NextEntry;\r
168 }\r
169 //\r
170 // Free the cache\r
171 //\r
172 FreePool ((UINT8 *) (UINTN) FvDevice->CachedFv);\r
173\r
174 return ;\r
175}\r
176\r
177/**\r
178 Check if an FV is consistent and allocate cache for it.\r
179\r
180 @param FvDevice A pointer to the FvDevice to be checked.\r
181\r
182 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
183 @retval EFI_VOLUME_CORRUPTED File system is corrupted.\r
184 @retval EFI_SUCCESS FV is consistent and cache is allocated.\r
185\r
186**/\r
187EFI_STATUS\r
188FvCheck (\r
189 IN FV_DEVICE *FvDevice\r
190 )\r
191{\r
192 EFI_STATUS Status;\r
193 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
194 EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
195 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
196 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
f95f107c 197 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;\r
c2df8e13 198 UINT8 *FwCache;\r
199 LBA_ENTRY *LbaEntry;\r
200 FREE_SPACE_ENTRY *FreeSpaceEntry;\r
201 FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
202 UINT8 *LbaStart;\r
203 UINTN Index;\r
204 EFI_LBA LbaIndex;\r
205 UINT8 *Ptr;\r
206 UINTN Size;\r
207 UINT8 *FreeStart;\r
208 UINTN FreeSize;\r
209 UINT8 ErasePolarity;\r
c2df8e13 210 EFI_FFS_FILE_STATE FileState;\r
211 UINT8 *TopFvAddress;\r
212 UINTN TestLength;\r
213 EFI_PHYSICAL_ADDRESS BaseAddress;\r
214\r
215 Fvb = FvDevice->Fvb;\r
216\r
217 Status = Fvb->GetAttributes (Fvb, &FvbAttributes);\r
218 if (EFI_ERROR (Status)) {\r
219 return Status;\r
220 }\r
221\r
222 InitializeListHead (&FvDevice->LbaHeader);\r
223 InitializeListHead (&FvDevice->FreeSpaceHeader);\r
224 InitializeListHead (&FvDevice->FfsFileListHeader);\r
225\r
226 FwVolHeader = NULL;\r
227 Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
228 if (EFI_ERROR (Status)) {\r
229 return Status;\r
230 }\r
231 ASSERT (FwVolHeader != NULL);\r
232\r
23491d5c
SZ
233 FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
234\r
c2df8e13 235 //\r
236 // Double Check firmware volume header here\r
237 //\r
238 if (!VerifyFvHeaderChecksum (FwVolHeader)) {\r
239 FreePool (FwVolHeader);\r
240 return EFI_VOLUME_CORRUPTED;\r
241 }\r
242\r
243 BlockMap = FwVolHeader->BlockMap;\r
244\r
245 //\r
246 // FwVolHeader->FvLength is the whole FV length including FV header\r
247 //\r
248 FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength);\r
249 if (FwCache == NULL) {\r
250 FreePool (FwVolHeader);\r
251 return EFI_OUT_OF_RESOURCES;\r
252 }\r
253\r
254 FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache;\r
255\r
256 //\r
257 // Copy to memory\r
258 //\r
259 LbaStart = FwCache;\r
260 LbaIndex = 0;\r
261 Ptr = NULL;\r
262\r
263 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
264 //\r
265 // Get volume base address\r
266 //\r
267 Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);\r
268 if (EFI_ERROR (Status)) {\r
269 FreePool (FwVolHeader);\r
270 return Status;\r
271 }\r
272\r
273 Ptr = (UINT8 *) ((UINTN) BaseAddress);\r
274\r
275 DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress));\r
276 }\r
277 //\r
278 // Copy whole FV into the memory\r
279 //\r
280 while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
281\r
282 for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
283 LbaEntry = AllocatePool (sizeof (LBA_ENTRY));\r
284 if (LbaEntry == NULL) {\r
285 FreePool (FwVolHeader);\r
286 FreeFvDeviceResource (FvDevice);\r
287 return EFI_OUT_OF_RESOURCES;\r
288 }\r
289\r
290 LbaEntry->LbaIndex = LbaIndex;\r
291 LbaEntry->StartingAddress = LbaStart;\r
292 LbaEntry->BlockLength = BlockMap->Length;\r
293\r
294 //\r
295 // Copy each LBA into memory\r
296 //\r
297 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
298\r
299 CopyMem (LbaStart, Ptr, BlockMap->Length);\r
300 Ptr += BlockMap->Length;\r
301\r
302 } else {\r
303\r
304 Size = BlockMap->Length;\r
305 Status = Fvb->Read (\r
306 Fvb,\r
307 LbaIndex,\r
308 0,\r
309 &Size,\r
310 LbaStart\r
311 );\r
312 //\r
313 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
314 //\r
315 if (EFI_ERROR (Status)) {\r
316 FreePool (FwVolHeader);\r
317 FreeFvDeviceResource (FvDevice);\r
318 return Status;\r
319 }\r
320\r
321 }\r
322\r
323 LbaIndex++;\r
324 LbaStart += BlockMap->Length;\r
325\r
326 InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link);\r
327 }\r
328\r
329 BlockMap++;\r
330 }\r
331\r
332 FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache;\r
333\r
334 //\r
335 // it is not used any more, so free FwVolHeader\r
336 //\r
337 FreePool (FwVolHeader);\r
338\r
339 //\r
340 // Scan to check the free space & File list\r
341 //\r
342 if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {\r
343 ErasePolarity = 1;\r
344 } else {\r
345 ErasePolarity = 0;\r
346 }\r
347\r
348 FvDevice->ErasePolarity = ErasePolarity;\r
349\r
350 //\r
351 // go through the whole FV cache, check the consistence of the FV\r
352 //\r
f95f107c
SZ
353 if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) {\r
354 //\r
355 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.\r
356 //\r
357 FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset);\r
358 Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize;\r
359 Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8);\r
360 } else {\r
361 Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);\r
362 }\r
363 TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength);\r
c2df8e13 364\r
365 //\r
366 // Build FFS list & Free Space List here\r
367 //\r
f95f107c
SZ
368 while (Ptr < TopFvAddress) {\r
369 TestLength = TopFvAddress - Ptr;\r
c2df8e13 370\r
371 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
372 TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
373 }\r
374\r
375 if (IsBufferErased (ErasePolarity, Ptr, TestLength)) {\r
376 //\r
377 // We found free space\r
378 //\r
379 FreeStart = Ptr;\r
380 FreeSize = 0;\r
381\r
382 do {\r
f95f107c 383 TestLength = TopFvAddress - Ptr;\r
c2df8e13 384\r
385 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
386 TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
387 }\r
388\r
389 if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) {\r
390 break;\r
391 }\r
392\r
393 FreeSize += TestLength;\r
394 Ptr += TestLength;\r
f95f107c 395 } while (Ptr < TopFvAddress);\r
c2df8e13 396\r
397 FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY));\r
398 if (FreeSpaceEntry == NULL) {\r
399 FreeFvDeviceResource (FvDevice);\r
400 return EFI_OUT_OF_RESOURCES;\r
401 }\r
402 //\r
403 // Create a Free space entry\r
404 //\r
405 FreeSpaceEntry->StartingAddress = FreeStart;\r
406 FreeSpaceEntry->Length = FreeSize;\r
407 InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link);\r
408 continue;\r
409 }\r
410 //\r
411 // double check boundry\r
412 //\r
413 if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) {\r
414 break;\r
415 }\r
416\r
417 if (!IsValidFFSHeader (\r
418 FvDevice->ErasePolarity,\r
419 (EFI_FFS_FILE_HEADER *) Ptr\r
420 )) {\r
421 FileState = GetFileState (\r
422 FvDevice->ErasePolarity,\r
423 (EFI_FFS_FILE_HEADER *) Ptr\r
424 );\r
425 if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {\r
23491d5c
SZ
426 if (IS_FFS_FILE2 (Ptr)) {\r
427 if (!FvDevice->IsFfs3Fv) {\r
428 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
429 }\r
430 Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2);\r
431 } else {\r
432 Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER);\r
433 }\r
c2df8e13 434\r
435 continue;\r
436\r
437 } else {\r
438 //\r
439 // File system is corrputed, return\r
440 //\r
441 FreeFvDeviceResource (FvDevice);\r
442 return EFI_VOLUME_CORRUPTED;\r
443 }\r
444 }\r
445\r
23491d5c
SZ
446 if (IS_FFS_FILE2 (Ptr)) {\r
447 ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF);\r
448 if (!FvDevice->IsFfs3Fv) {\r
449 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
450 Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
451 //\r
452 // Adjust Ptr to the next 8-byte aligned boundry.\r
453 //\r
454 while (((UINTN) Ptr & 0x07) != 0) {\r
455 Ptr++;\r
456 }\r
457 continue;\r
458 }\r
459 }\r
460\r
c2df8e13 461 if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) {\r
c2df8e13 462 FileState = GetFileState (\r
463 FvDevice->ErasePolarity,\r
464 (EFI_FFS_FILE_HEADER *) Ptr\r
465 );\r
466\r
467 //\r
468 // check for non-deleted file\r
469 //\r
470 if (FileState != EFI_FILE_DELETED) {\r
471 //\r
472 // Create a FFS list entry for each non-deleted file\r
473 //\r
474 FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));\r
475 if (FfsFileEntry == NULL) {\r
476 FreeFvDeviceResource (FvDevice);\r
477 return EFI_OUT_OF_RESOURCES;\r
478 }\r
479\r
480 FfsFileEntry->FfsHeader = Ptr;\r
481 InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r
482 }\r
483\r
23491d5c
SZ
484 if (IS_FFS_FILE2 (Ptr)) {\r
485 Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
486 } else {\r
487 Ptr = Ptr + FFS_FILE_SIZE (Ptr);\r
488 }\r
c2df8e13 489\r
490 //\r
491 // Adjust Ptr to the next 8-byte aligned boundry.\r
492 //\r
493 while (((UINTN) Ptr & 0x07) != 0) {\r
494 Ptr++;\r
495 }\r
496 } else {\r
497 //\r
498 // File system is corrupted, return\r
499 //\r
500 FreeFvDeviceResource (FvDevice);\r
501 return EFI_VOLUME_CORRUPTED;\r
502 }\r
503 }\r
504\r
505 FvDevice->CurrentFfsFile = NULL;\r
506\r
507 return EFI_SUCCESS;\r
508}\r
509\r
510/**\r
511 Entry point function does install/reinstall FV2 protocol with full functionality.\r
512\r
513 @param ImageHandle A handle for the image that is initializing this driver\r
514 @param SystemTable A pointer to the EFI system table\r
515\r
516 @retval EFI_SUCCESS At least one Fv protocol install/reinstall successfully.\r
517 @retval EFI_NOT_FOUND No FV protocol install/reinstall successfully.\r
518**/\r
519EFI_STATUS\r
520EFIAPI\r
521FwVolDriverInit (\r
522 IN EFI_HANDLE ImageHandle,\r
523 IN EFI_SYSTEM_TABLE *SystemTable\r
524 )\r
525{\r
526 EFI_STATUS Status;\r
527 EFI_HANDLE *HandleBuffer;\r
528 UINTN HandleCount;\r
529 UINTN Index;\r
530 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
531 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
532 FV_DEVICE *FvDevice;\r
533 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
534 BOOLEAN Reinstall;\r
535 BOOLEAN InstallFlag;\r
536\r
537 DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n"));\r
538 InstallFlag = FALSE;\r
539 //\r
540 // Locate all handles of Fvb protocol\r
541 //\r
542 Status = gBS->LocateHandleBuffer (\r
543 ByProtocol,\r
544 &gEfiFirmwareVolumeBlockProtocolGuid,\r
545 NULL,\r
546 &HandleCount,\r
547 &HandleBuffer\r
548 );\r
549 if (EFI_ERROR (Status)) {\r
550 return EFI_NOT_FOUND;\r
551 }\r
23491d5c 552\r
c2df8e13 553 for (Index = 0; Index < HandleCount; Index += 1) {\r
554 Status = gBS->HandleProtocol (\r
555 HandleBuffer[Index],\r
556 &gEfiFirmwareVolumeBlockProtocolGuid,\r
557 (VOID **) &Fvb\r
558 );\r
559 if (EFI_ERROR (Status)) {\r
560 continue;\r
561 }\r
562\r
563 FwVolHeader = NULL;\r
564 Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
565 if (EFI_ERROR (Status)) {\r
566 continue;\r
567 }\r
568 ASSERT (FwVolHeader != NULL);\r
569 //\r
570 // Check to see that the file system is indeed formatted in a way we can\r
571 // understand it...\r
572 //\r
23491d5c
SZ
573 if ((!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&\r
574 (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {\r
c2df8e13 575 FreePool (FwVolHeader);\r
576 continue;\r
577 }\r
578 FreePool (FwVolHeader);\r
579\r
580 Reinstall = FALSE;\r
581 //\r
582 // Check if there is an FV protocol already installed in that handle\r
583 //\r
584 Status = gBS->HandleProtocol (\r
585 HandleBuffer[Index],\r
586 &gEfiFirmwareVolume2ProtocolGuid,\r
587 (VOID **) &Fv\r
588 );\r
589 if (!EFI_ERROR (Status)) {\r
590 Reinstall = TRUE;\r
591 }\r
592 //\r
593 // FwVol protocol on the handle so create a new one\r
594 //\r
595 FvDevice = AllocateZeroPool (sizeof (FV_DEVICE));\r
596 if (FvDevice == NULL) {\r
597 goto Done;\r
598 }\r
599\r
600 FvDevice->Signature = FV_DEVICE_SIGNATURE;\r
601 FvDevice->Fvb = Fvb;\r
602\r
603 //\r
604 // Firmware Volume Protocol interface\r
605 //\r
606 FvDevice->Fv.GetVolumeAttributes = FvGetVolumeAttributes;\r
607 FvDevice->Fv.SetVolumeAttributes = FvSetVolumeAttributes;\r
608 FvDevice->Fv.ReadFile = FvReadFile;\r
609 FvDevice->Fv.ReadSection = FvReadFileSection;\r
610 FvDevice->Fv.WriteFile = FvWriteFile;\r
611 FvDevice->Fv.GetNextFile = FvGetNextFile;\r
612 FvDevice->Fv.KeySize = KEYSIZE;\r
613 FvDevice->Fv.GetInfo = FvGetVolumeInfo;\r
614 FvDevice->Fv.SetInfo = FvSetVolumeInfo;\r
615\r
616 Status = FvCheck (FvDevice);\r
617 if (EFI_ERROR (Status)) {\r
618 //\r
619 // The file system is not consistence\r
620 //\r
621 FreePool (FvDevice);\r
622 continue;\r
623 }\r
624\r
625 if (Reinstall) {\r
626 //\r
627 // Reinstall an New FV protocol\r
628 //\r
629 // FvDevice = FV_DEVICE_FROM_THIS (Fv);\r
630 // FvDevice->Fvb = Fvb;\r
631 // FreeFvDeviceResource (FvDevice);\r
632 //\r
633 Status = gBS->ReinstallProtocolInterface (\r
634 HandleBuffer[Index],\r
635 &gEfiFirmwareVolume2ProtocolGuid,\r
636 Fv,\r
637 &FvDevice->Fv\r
638 );\r
639 if (!EFI_ERROR (Status)) {\r
640 InstallFlag = TRUE;\r
641 } else {\r
642 FreePool (FvDevice);\r
643 }\r
644 \r
645 DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status));\r
646 ASSERT_EFI_ERROR (Status);\r
647 } else {\r
648 //\r
649 // Install an New FV protocol\r
650 //\r
651 Status = gBS->InstallProtocolInterface (\r
652 &FvDevice->Handle,\r
653 &gEfiFirmwareVolume2ProtocolGuid,\r
654 EFI_NATIVE_INTERFACE,\r
655 &FvDevice->Fv\r
656 );\r
657 if (!EFI_ERROR (Status)) {\r
658 InstallFlag = TRUE;\r
659 } else {\r
660 FreePool (FvDevice);\r
661 }\r
662 \r
663 DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status));\r
664 ASSERT_EFI_ERROR (Status);\r
665 }\r
666 }\r
667\r
668Done:\r
669 //\r
670 // As long as one Fv protocol install/reinstall successfully,\r
671 // success should return to ensure this image will be not unloaded.\r
672 // Otherwise, new Fv protocols are corrupted by other loaded driver.\r
673 //\r
674 if (InstallFlag) {\r
675 return EFI_SUCCESS;\r
676 }\r
677 \r
678 //\r
679 // No FV protocol install/reinstall successfully.\r
680 // EFI_NOT_FOUND should return to ensure this image will be unloaded.\r
681 //\r
682 return EFI_NOT_FOUND;\r
683}\r