]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVol.c
StdLib: Some deployed versions of the Simple Text Input Protocol randomly return...
[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
0c3a1db4
SZ
177/**\r
178\r
179 Firmware volume inherits authentication status from the FV image file and section(in another firmware volume)\r
180 where it came from.\r
181\r
182 @param FvDevice A pointer to the FvDevice.\r
183\r
184**/\r
185VOID\r
186FwVolInheritAuthenticationStatus (\r
187 IN FV_DEVICE *FvDevice\r
188 )\r
189{\r
190 EFI_STATUS Status;\r
191 EFI_FIRMWARE_VOLUME_HEADER *CachedFvHeader;\r
192 EFI_FIRMWARE_VOLUME_EXT_HEADER *CachedFvExtHeader;\r
193 EFI_FIRMWARE_VOLUME2_PROTOCOL *ParentFvProtocol;\r
194 UINTN Key;\r
195 EFI_GUID FileNameGuid;\r
196 EFI_FV_FILETYPE FileType;\r
197 EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
198 UINTN FileSize;\r
199 EFI_SECTION_TYPE SectionType;\r
200 UINT32 AuthenticationStatus;\r
201 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
202 EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;\r
203 UINTN BufferSize;\r
204\r
205 CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv;\r
206\r
207 if (FvDevice->Fv.ParentHandle != NULL) {\r
208 //\r
209 // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from \r
210 //\r
211 Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol);\r
212 if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) {\r
213 Key = 0;\r
214 do {\r
215 FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;\r
216 Status = ParentFvProtocol->GetNextFile (\r
217 ParentFvProtocol,\r
218 &Key,\r
219 &FileType,\r
220 &FileNameGuid,\r
221 &FileAttributes,\r
222 &FileSize\r
223 );\r
224 if (EFI_ERROR (Status)) {\r
225 return;\r
226 }\r
227\r
228 SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
229 FvHeader = NULL;\r
230 BufferSize = 0;\r
231 Status = ParentFvProtocol->ReadSection (\r
232 ParentFvProtocol,\r
233 &FileNameGuid,\r
234 SectionType,\r
235 0,\r
236 (VOID **) &FvHeader,\r
237 &BufferSize,\r
238 &AuthenticationStatus\r
239 );\r
240 if (!EFI_ERROR (Status)) {\r
241 if ((FvHeader->FvLength == CachedFvHeader->FvLength) &&\r
242 (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) {\r
243 if (FvHeader->ExtHeaderOffset !=0) {\r
244 //\r
245 // Both FVs contain extension header, then compare their FV Name GUID\r
246 //\r
247 FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset);\r
248 CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset);\r
249 if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) {\r
250 //\r
251 // Found the FV image section where the firmware volume came from,\r
252 // and then inherit authentication status from it.\r
253 //\r
254 FvDevice->AuthenticationStatus = AuthenticationStatus;\r
255 FreePool ((VOID *) FvHeader);\r
256 return;\r
257 }\r
258 } else {\r
259 //\r
260 // Both FVs don't contain extension header, then compare their whole FV Image.\r
261 //\r
25fbcc0a 262 if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, (UINTN) FvHeader->FvLength) == 0) {\r
0c3a1db4
SZ
263 //\r
264 // Found the FV image section where the firmware volume came from\r
265 // and then inherit authentication status from it.\r
266 //\r
267 FvDevice->AuthenticationStatus = AuthenticationStatus;\r
268 FreePool ((VOID *) FvHeader);\r
269 return;\r
270 }\r
271 }\r
272 }\r
273 FreePool ((VOID *) FvHeader);\r
274 }\r
275 } while (TRUE);\r
276 }\r
277 }\r
278}\r
279\r
c2df8e13 280/**\r
281 Check if an FV is consistent and allocate cache for it.\r
282\r
283 @param FvDevice A pointer to the FvDevice to be checked.\r
284\r
285 @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
286 @retval EFI_VOLUME_CORRUPTED File system is corrupted.\r
287 @retval EFI_SUCCESS FV is consistent and cache is allocated.\r
288\r
289**/\r
290EFI_STATUS\r
291FvCheck (\r
292 IN FV_DEVICE *FvDevice\r
293 )\r
294{\r
295 EFI_STATUS Status;\r
296 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
297 EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
298 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
299 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
f95f107c 300 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;\r
c2df8e13 301 UINT8 *FwCache;\r
302 LBA_ENTRY *LbaEntry;\r
303 FREE_SPACE_ENTRY *FreeSpaceEntry;\r
304 FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
305 UINT8 *LbaStart;\r
306 UINTN Index;\r
307 EFI_LBA LbaIndex;\r
308 UINT8 *Ptr;\r
309 UINTN Size;\r
310 UINT8 *FreeStart;\r
311 UINTN FreeSize;\r
312 UINT8 ErasePolarity;\r
c2df8e13 313 EFI_FFS_FILE_STATE FileState;\r
314 UINT8 *TopFvAddress;\r
315 UINTN TestLength;\r
316 EFI_PHYSICAL_ADDRESS BaseAddress;\r
317\r
318 Fvb = FvDevice->Fvb;\r
319\r
320 Status = Fvb->GetAttributes (Fvb, &FvbAttributes);\r
321 if (EFI_ERROR (Status)) {\r
322 return Status;\r
323 }\r
324\r
325 InitializeListHead (&FvDevice->LbaHeader);\r
326 InitializeListHead (&FvDevice->FreeSpaceHeader);\r
327 InitializeListHead (&FvDevice->FfsFileListHeader);\r
328\r
329 FwVolHeader = NULL;\r
330 Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
331 if (EFI_ERROR (Status)) {\r
332 return Status;\r
333 }\r
334 ASSERT (FwVolHeader != NULL);\r
335\r
23491d5c
SZ
336 FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
337\r
c2df8e13 338 //\r
339 // Double Check firmware volume header here\r
340 //\r
341 if (!VerifyFvHeaderChecksum (FwVolHeader)) {\r
342 FreePool (FwVolHeader);\r
343 return EFI_VOLUME_CORRUPTED;\r
344 }\r
345\r
346 BlockMap = FwVolHeader->BlockMap;\r
347\r
348 //\r
349 // FwVolHeader->FvLength is the whole FV length including FV header\r
350 //\r
351 FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength);\r
352 if (FwCache == NULL) {\r
353 FreePool (FwVolHeader);\r
354 return EFI_OUT_OF_RESOURCES;\r
355 }\r
356\r
357 FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache;\r
358\r
359 //\r
360 // Copy to memory\r
361 //\r
362 LbaStart = FwCache;\r
363 LbaIndex = 0;\r
364 Ptr = NULL;\r
365\r
366 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
367 //\r
368 // Get volume base address\r
369 //\r
370 Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);\r
371 if (EFI_ERROR (Status)) {\r
372 FreePool (FwVolHeader);\r
373 return Status;\r
374 }\r
375\r
376 Ptr = (UINT8 *) ((UINTN) BaseAddress);\r
377\r
378 DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress));\r
379 }\r
380 //\r
381 // Copy whole FV into the memory\r
382 //\r
383 while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
384\r
385 for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
386 LbaEntry = AllocatePool (sizeof (LBA_ENTRY));\r
387 if (LbaEntry == NULL) {\r
388 FreePool (FwVolHeader);\r
389 FreeFvDeviceResource (FvDevice);\r
390 return EFI_OUT_OF_RESOURCES;\r
391 }\r
392\r
393 LbaEntry->LbaIndex = LbaIndex;\r
394 LbaEntry->StartingAddress = LbaStart;\r
395 LbaEntry->BlockLength = BlockMap->Length;\r
396\r
397 //\r
398 // Copy each LBA into memory\r
399 //\r
400 if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
401\r
402 CopyMem (LbaStart, Ptr, BlockMap->Length);\r
403 Ptr += BlockMap->Length;\r
404\r
405 } else {\r
406\r
407 Size = BlockMap->Length;\r
408 Status = Fvb->Read (\r
409 Fvb,\r
410 LbaIndex,\r
411 0,\r
412 &Size,\r
413 LbaStart\r
414 );\r
415 //\r
416 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
417 //\r
418 if (EFI_ERROR (Status)) {\r
419 FreePool (FwVolHeader);\r
420 FreeFvDeviceResource (FvDevice);\r
421 return Status;\r
422 }\r
423\r
424 }\r
425\r
426 LbaIndex++;\r
427 LbaStart += BlockMap->Length;\r
428\r
429 InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link);\r
430 }\r
431\r
432 BlockMap++;\r
433 }\r
434\r
435 FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache;\r
436\r
437 //\r
438 // it is not used any more, so free FwVolHeader\r
439 //\r
440 FreePool (FwVolHeader);\r
441\r
442 //\r
443 // Scan to check the free space & File list\r
444 //\r
445 if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {\r
446 ErasePolarity = 1;\r
447 } else {\r
448 ErasePolarity = 0;\r
449 }\r
450\r
451 FvDevice->ErasePolarity = ErasePolarity;\r
452\r
453 //\r
454 // go through the whole FV cache, check the consistence of the FV\r
455 //\r
f95f107c
SZ
456 if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) {\r
457 //\r
458 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.\r
459 //\r
460 FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset);\r
461 Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize;\r
462 Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8);\r
463 } else {\r
464 Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);\r
465 }\r
466 TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength);\r
c2df8e13 467\r
468 //\r
469 // Build FFS list & Free Space List here\r
470 //\r
f95f107c
SZ
471 while (Ptr < TopFvAddress) {\r
472 TestLength = TopFvAddress - Ptr;\r
c2df8e13 473\r
474 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
475 TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
476 }\r
477\r
478 if (IsBufferErased (ErasePolarity, Ptr, TestLength)) {\r
479 //\r
480 // We found free space\r
481 //\r
482 FreeStart = Ptr;\r
483 FreeSize = 0;\r
484\r
485 do {\r
f95f107c 486 TestLength = TopFvAddress - Ptr;\r
c2df8e13 487\r
488 if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
489 TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
490 }\r
491\r
492 if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) {\r
493 break;\r
494 }\r
495\r
496 FreeSize += TestLength;\r
497 Ptr += TestLength;\r
f95f107c 498 } while (Ptr < TopFvAddress);\r
c2df8e13 499\r
500 FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY));\r
501 if (FreeSpaceEntry == NULL) {\r
502 FreeFvDeviceResource (FvDevice);\r
503 return EFI_OUT_OF_RESOURCES;\r
504 }\r
505 //\r
506 // Create a Free space entry\r
507 //\r
508 FreeSpaceEntry->StartingAddress = FreeStart;\r
509 FreeSpaceEntry->Length = FreeSize;\r
510 InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link);\r
511 continue;\r
512 }\r
513 //\r
514 // double check boundry\r
515 //\r
516 if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) {\r
517 break;\r
518 }\r
519\r
520 if (!IsValidFFSHeader (\r
521 FvDevice->ErasePolarity,\r
522 (EFI_FFS_FILE_HEADER *) Ptr\r
523 )) {\r
524 FileState = GetFileState (\r
525 FvDevice->ErasePolarity,\r
526 (EFI_FFS_FILE_HEADER *) Ptr\r
527 );\r
528 if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {\r
23491d5c
SZ
529 if (IS_FFS_FILE2 (Ptr)) {\r
530 if (!FvDevice->IsFfs3Fv) {\r
531 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
532 }\r
533 Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2);\r
534 } else {\r
535 Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER);\r
536 }\r
c2df8e13 537\r
538 continue;\r
539\r
540 } else {\r
541 //\r
542 // File system is corrputed, return\r
543 //\r
544 FreeFvDeviceResource (FvDevice);\r
545 return EFI_VOLUME_CORRUPTED;\r
546 }\r
547 }\r
548\r
23491d5c
SZ
549 if (IS_FFS_FILE2 (Ptr)) {\r
550 ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF);\r
551 if (!FvDevice->IsFfs3Fv) {\r
552 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));\r
553 Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
554 //\r
555 // Adjust Ptr to the next 8-byte aligned boundry.\r
556 //\r
557 while (((UINTN) Ptr & 0x07) != 0) {\r
558 Ptr++;\r
559 }\r
560 continue;\r
561 }\r
562 }\r
563\r
c2df8e13 564 if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) {\r
c2df8e13 565 FileState = GetFileState (\r
566 FvDevice->ErasePolarity,\r
567 (EFI_FFS_FILE_HEADER *) Ptr\r
568 );\r
569\r
570 //\r
571 // check for non-deleted file\r
572 //\r
573 if (FileState != EFI_FILE_DELETED) {\r
574 //\r
575 // Create a FFS list entry for each non-deleted file\r
576 //\r
577 FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));\r
578 if (FfsFileEntry == NULL) {\r
579 FreeFvDeviceResource (FvDevice);\r
580 return EFI_OUT_OF_RESOURCES;\r
581 }\r
582\r
583 FfsFileEntry->FfsHeader = Ptr;\r
584 InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r
585 }\r
586\r
23491d5c
SZ
587 if (IS_FFS_FILE2 (Ptr)) {\r
588 Ptr = Ptr + FFS_FILE2_SIZE (Ptr);\r
589 } else {\r
590 Ptr = Ptr + FFS_FILE_SIZE (Ptr);\r
591 }\r
c2df8e13 592\r
593 //\r
594 // Adjust Ptr to the next 8-byte aligned boundry.\r
595 //\r
596 while (((UINTN) Ptr & 0x07) != 0) {\r
597 Ptr++;\r
598 }\r
599 } else {\r
600 //\r
601 // File system is corrupted, return\r
602 //\r
603 FreeFvDeviceResource (FvDevice);\r
604 return EFI_VOLUME_CORRUPTED;\r
605 }\r
606 }\r
607\r
608 FvDevice->CurrentFfsFile = NULL;\r
609\r
610 return EFI_SUCCESS;\r
611}\r
612\r
613/**\r
614 Entry point function does install/reinstall FV2 protocol with full functionality.\r
615\r
616 @param ImageHandle A handle for the image that is initializing this driver\r
617 @param SystemTable A pointer to the EFI system table\r
618\r
619 @retval EFI_SUCCESS At least one Fv protocol install/reinstall successfully.\r
620 @retval EFI_NOT_FOUND No FV protocol install/reinstall successfully.\r
621**/\r
622EFI_STATUS\r
623EFIAPI\r
624FwVolDriverInit (\r
625 IN EFI_HANDLE ImageHandle,\r
626 IN EFI_SYSTEM_TABLE *SystemTable\r
627 )\r
628{\r
629 EFI_STATUS Status;\r
630 EFI_HANDLE *HandleBuffer;\r
631 UINTN HandleCount;\r
632 UINTN Index;\r
633 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
634 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
635 FV_DEVICE *FvDevice;\r
636 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
637 BOOLEAN Reinstall;\r
638 BOOLEAN InstallFlag;\r
639\r
640 DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n"));\r
641 InstallFlag = FALSE;\r
642 //\r
643 // Locate all handles of Fvb protocol\r
644 //\r
645 Status = gBS->LocateHandleBuffer (\r
646 ByProtocol,\r
647 &gEfiFirmwareVolumeBlockProtocolGuid,\r
648 NULL,\r
649 &HandleCount,\r
650 &HandleBuffer\r
651 );\r
652 if (EFI_ERROR (Status)) {\r
653 return EFI_NOT_FOUND;\r
654 }\r
23491d5c 655\r
c2df8e13 656 for (Index = 0; Index < HandleCount; Index += 1) {\r
657 Status = gBS->HandleProtocol (\r
658 HandleBuffer[Index],\r
659 &gEfiFirmwareVolumeBlockProtocolGuid,\r
660 (VOID **) &Fvb\r
661 );\r
662 if (EFI_ERROR (Status)) {\r
663 continue;\r
664 }\r
665\r
666 FwVolHeader = NULL;\r
667 Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
668 if (EFI_ERROR (Status)) {\r
669 continue;\r
670 }\r
671 ASSERT (FwVolHeader != NULL);\r
672 //\r
673 // Check to see that the file system is indeed formatted in a way we can\r
674 // understand it...\r
675 //\r
23491d5c
SZ
676 if ((!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&\r
677 (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {\r
c2df8e13 678 FreePool (FwVolHeader);\r
679 continue;\r
680 }\r
681 FreePool (FwVolHeader);\r
682\r
683 Reinstall = FALSE;\r
684 //\r
685 // Check if there is an FV protocol already installed in that handle\r
686 //\r
687 Status = gBS->HandleProtocol (\r
688 HandleBuffer[Index],\r
689 &gEfiFirmwareVolume2ProtocolGuid,\r
690 (VOID **) &Fv\r
691 );\r
692 if (!EFI_ERROR (Status)) {\r
693 Reinstall = TRUE;\r
694 }\r
695 //\r
696 // FwVol protocol on the handle so create a new one\r
697 //\r
698 FvDevice = AllocateZeroPool (sizeof (FV_DEVICE));\r
699 if (FvDevice == NULL) {\r
700 goto Done;\r
701 }\r
702\r
703 FvDevice->Signature = FV_DEVICE_SIGNATURE;\r
704 FvDevice->Fvb = Fvb;\r
705\r
706 //\r
707 // Firmware Volume Protocol interface\r
708 //\r
709 FvDevice->Fv.GetVolumeAttributes = FvGetVolumeAttributes;\r
710 FvDevice->Fv.SetVolumeAttributes = FvSetVolumeAttributes;\r
711 FvDevice->Fv.ReadFile = FvReadFile;\r
712 FvDevice->Fv.ReadSection = FvReadFileSection;\r
713 FvDevice->Fv.WriteFile = FvWriteFile;\r
714 FvDevice->Fv.GetNextFile = FvGetNextFile;\r
715 FvDevice->Fv.KeySize = KEYSIZE;\r
716 FvDevice->Fv.GetInfo = FvGetVolumeInfo;\r
717 FvDevice->Fv.SetInfo = FvSetVolumeInfo;\r
0c3a1db4 718 FvDevice->Fv.ParentHandle = Fvb->ParentHandle;\r
c2df8e13 719\r
720 Status = FvCheck (FvDevice);\r
721 if (EFI_ERROR (Status)) {\r
722 //\r
723 // The file system is not consistence\r
724 //\r
725 FreePool (FvDevice);\r
726 continue;\r
727 }\r
728\r
0c3a1db4
SZ
729 FwVolInheritAuthenticationStatus (FvDevice);\r
730\r
c2df8e13 731 if (Reinstall) {\r
732 //\r
733 // Reinstall an New FV protocol\r
734 //\r
735 // FvDevice = FV_DEVICE_FROM_THIS (Fv);\r
736 // FvDevice->Fvb = Fvb;\r
737 // FreeFvDeviceResource (FvDevice);\r
738 //\r
739 Status = gBS->ReinstallProtocolInterface (\r
740 HandleBuffer[Index],\r
741 &gEfiFirmwareVolume2ProtocolGuid,\r
742 Fv,\r
743 &FvDevice->Fv\r
744 );\r
745 if (!EFI_ERROR (Status)) {\r
746 InstallFlag = TRUE;\r
747 } else {\r
748 FreePool (FvDevice);\r
749 }\r
750 \r
751 DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status));\r
752 ASSERT_EFI_ERROR (Status);\r
753 } else {\r
754 //\r
755 // Install an New FV protocol\r
756 //\r
757 Status = gBS->InstallProtocolInterface (\r
758 &FvDevice->Handle,\r
759 &gEfiFirmwareVolume2ProtocolGuid,\r
760 EFI_NATIVE_INTERFACE,\r
761 &FvDevice->Fv\r
762 );\r
763 if (!EFI_ERROR (Status)) {\r
764 InstallFlag = TRUE;\r
765 } else {\r
766 FreePool (FvDevice);\r
767 }\r
768 \r
769 DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status));\r
770 ASSERT_EFI_ERROR (Status);\r
771 }\r
772 }\r
773\r
774Done:\r
775 //\r
776 // As long as one Fv protocol install/reinstall successfully,\r
777 // success should return to ensure this image will be not unloaded.\r
778 // Otherwise, new Fv protocols are corrupted by other loaded driver.\r
779 //\r
780 if (InstallFlag) {\r
781 return EFI_SUCCESS;\r
782 }\r
783 \r
784 //\r
785 // No FV protocol install/reinstall successfully.\r
786 // EFI_NOT_FOUND should return to ensure this image will be unloaded.\r
787 //\r
788 return EFI_NOT_FOUND;\r
789}\r