2 Firmware File System driver that produce Firmware Volume protocol.
3 Layers on top of Firmware Block protocol to produce a file abstraction
6 Copyright (c) 2006 - 2007 Intel Corporation. <BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #define KEYSIZE sizeof (UINTN)
22 // Protocol notify related globals
24 VOID
*gEfiFwVolBlockNotifyReg
;
25 EFI_EVENT gEfiFwVolBlockEvent
;
27 FV_DEVICE mFvDevice
= {
32 FvGetVolumeAttributes
,
33 FvSetVolumeAttributes
,
53 // FFS helper functions
58 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
,
59 OUT EFI_FIRMWARE_VOLUME_HEADER
**FwVolHeader
64 given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
65 copy the volume header into it.
68 Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
70 FwVolHeader - Pointer to pointer to allocated buffer in which the volume
74 EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
75 EFI_SUCCESS - Successfully read volume header to the allocated buffer.
81 EFI_FIRMWARE_VOLUME_HEADER TempFvh
;
87 //Determine the real length of FV header
89 FvhLength
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
);
90 Status
= Fvb
->Read (Fvb
, 0, 0, &FvhLength
, (UINT8
*)&TempFvh
);
93 // Allocate a buffer for the caller
95 *FwVolHeader
= CoreAllocateBootServicesPool (TempFvh
.HeaderLength
);
96 if (*FwVolHeader
== NULL
) {
97 return EFI_OUT_OF_RESOURCES
;
101 // Copy the standard header into the buffer
103 CopyMem (*FwVolHeader
, &TempFvh
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
));
106 // Read the rest of the header
108 FvhLength
= TempFvh
.HeaderLength
- sizeof (EFI_FIRMWARE_VOLUME_HEADER
);
109 Buffer
= (UINT8
*)*FwVolHeader
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER
);
110 Status
= Fvb
->Read (Fvb
, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER
), &FvhLength
, Buffer
);
111 if (EFI_ERROR (Status
)) {
113 // Read failed so free buffer
115 CoreFreePool (*FwVolHeader
);
124 FreeFvDeviceResource (
125 IN FV_DEVICE
*FvDevice
130 Free FvDevice resource when error happens
133 FvDevice - pointer to the FvDevice to be freed.
140 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
141 LIST_ENTRY
*NextEntry
;
144 // Free File List Entry
146 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*)FvDevice
->FfsFileListHeader
.ForwardLink
;
147 while (&FfsFileEntry
->Link
!= &FvDevice
->FfsFileListHeader
) {
148 NextEntry
= (&FfsFileEntry
->Link
)->ForwardLink
;
150 if (FfsFileEntry
->StreamHandle
!= 0) {
152 // Close stream and free resources from SEP
154 FfsFileEntry
->Sep
->CloseSectionStream (FfsFileEntry
->Sep
, FfsFileEntry
->StreamHandle
);
157 CoreFreePool (FfsFileEntry
);
159 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*)NextEntry
;
166 CoreFreePool (FvDevice
->CachedFv
);
169 // Free Volume Header
171 CoreFreePool (FvDevice
->FwVolHeader
);
179 IN OUT FV_DEVICE
*FvDevice
184 Check if a FV is consistent and allocate cache
187 FvDevice - pointer to the FvDevice to be checked.
190 EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
191 EFI_SUCCESS - FV is consistent and cache is allocated.
192 EFI_VOLUME_CORRUPTED - File system is corrupted.
197 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
198 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
199 EFI_FVB_ATTRIBUTES FvbAttributes
;
200 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
201 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
202 EFI_FFS_FILE_HEADER
*FfsHeader
;
203 UINT8
*CacheLocation
;
209 EFI_FFS_FILE_STATE FileState
;
215 FwVolHeader
= FvDevice
->FwVolHeader
;
217 Status
= Fvb
->GetAttributes (Fvb
, &FvbAttributes
);
218 if (EFI_ERROR (Status
)) {
223 // Size is the size of the FV minus the head. We have already allocated
224 // the header to check to make sure the volume is valid
226 Size
= (UINTN
)(FwVolHeader
->FvLength
- FwVolHeader
->HeaderLength
);
227 FvDevice
->CachedFv
= CoreAllocateBootServicesPool (Size
);
229 if (FvDevice
->CachedFv
== NULL
) {
230 return EFI_OUT_OF_RESOURCES
;
234 // Remember a pointer to the end fo the CachedFv
236 FvDevice
->EndOfCachedFv
= FvDevice
->CachedFv
+ Size
;
239 // Copy FV minus header into memory using the block map we have all ready
242 BlockMap
= FwVolHeader
->BlockMap
;
243 CacheLocation
= FvDevice
->CachedFv
;
245 LbaOffset
= FwVolHeader
->HeaderLength
;
246 while ((BlockMap
->NumBlocks
!= 0) || (BlockMap
->Length
!= 0)) {
248 for (Index
= 0; Index
< BlockMap
->NumBlocks
; Index
++) {
250 Size
= BlockMap
->Length
;
253 // Cache does not include FV Header
257 Status
= Fvb
->Read (Fvb
,
264 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length
266 if (EFI_ERROR (Status
)) {
271 // After we skip Fv Header always read from start of block
276 CacheLocation
+= Size
;
282 // Scan to check the free space & File list
284 if (FvbAttributes
& EFI_FVB_ERASE_POLARITY
) {
285 FvDevice
->ErasePolarity
= 1;
287 FvDevice
->ErasePolarity
= 0;
292 // go through the whole FV cache, check the consistence of the FV.
293 // Make a linked list off all the Ffs file headers
295 Status
= EFI_SUCCESS
;
296 InitializeListHead (&FvDevice
->FfsFileListHeader
);
301 FfsHeader
= (EFI_FFS_FILE_HEADER
*)FvDevice
->CachedFv
;
302 TopFvAddress
= FvDevice
->EndOfCachedFv
;
303 while ((UINT8
*)FfsHeader
< TopFvAddress
) {
305 TestLength
= TopFvAddress
- ((UINT8
*)FfsHeader
);
306 if (TestLength
> sizeof (EFI_FFS_FILE_HEADER
)) {
307 TestLength
= sizeof (EFI_FFS_FILE_HEADER
);
310 if (IsBufferErased (FvDevice
->ErasePolarity
, FfsHeader
, TestLength
)) {
312 // We have found the free space so we are done!
317 if (!IsValidFfsHeader (FvDevice
->ErasePolarity
, FfsHeader
, &FileState
)) {
318 if ((FileState
== EFI_FILE_HEADER_INVALID
) ||
319 (FileState
== EFI_FILE_HEADER_CONSTRUCTION
)) {
326 // File system is corrputed
328 Status
= EFI_VOLUME_CORRUPTED
;
333 if (!IsValidFfsFile (FvDevice
->ErasePolarity
, FfsHeader
)) {
335 // File system is corrupted
337 Status
= EFI_VOLUME_CORRUPTED
;
342 // Size[3] is a three byte array, read 4 bytes and throw one away
344 FileLength
= *(UINT32
*)&FfsHeader
->Size
[0] & 0x00FFFFFF;
346 FileState
= GetFileState (FvDevice
->ErasePolarity
, FfsHeader
);
349 // check for non-deleted file
351 if (FileState
!= EFI_FILE_DELETED
) {
353 // Create a FFS list entry for each non-deleted file
355 FfsFileEntry
= CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY
));
356 if (FfsFileEntry
== NULL
) {
357 Status
= EFI_OUT_OF_RESOURCES
;
361 FfsFileEntry
->FfsHeader
= FfsHeader
;
362 InsertTailList (&FvDevice
->FfsFileListHeader
, &FfsFileEntry
->Link
);
365 FfsHeader
= (EFI_FFS_FILE_HEADER
*)(((UINT8
*)FfsHeader
) + FileLength
);
368 // Adjust pointer to the next 8-byte aligned boundry.
370 FfsHeader
= (EFI_FFS_FILE_HEADER
*)(((UINTN
)FfsHeader
+ 7) & ~0x07);
375 if (EFI_ERROR (Status
)) {
376 FreeFvDeviceResource (FvDevice
);
393 This notification function is invoked when an instance of the
394 EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
395 EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where
396 the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.
399 Event - The event that occured
400 Context - For EFI compatiblity. Not used.
411 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
412 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
414 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
416 // Examine all new handles
420 // Get the next handle
422 BufferSize
= sizeof (Handle
);
423 Status
= CoreLocateHandle (
426 gEfiFwVolBlockNotifyReg
,
432 // If not found, we're done
434 if (EFI_NOT_FOUND
== Status
) {
438 if (EFI_ERROR (Status
)) {
443 // Get the FirmwareVolumeBlock protocol on that handle
445 Status
= CoreHandleProtocol (Handle
, &gEfiFirmwareVolumeBlockProtocolGuid
, (VOID
**)&Fvb
);
446 ASSERT_EFI_ERROR (Status
);
450 // Make sure the Fv Header is O.K.
452 Status
= GetFwVolHeader (Fvb
, &FwVolHeader
);
453 if (EFI_ERROR (Status
)) {
457 if (!VerifyFvHeaderChecksum (FwVolHeader
)) {
458 CoreFreePool (FwVolHeader
);
464 // Check to see that the file system is indeed formatted in a way we can
467 if (!CompareGuid (&FwVolHeader
->FileSystemGuid
, &gEfiFirmwareFileSystem2Guid
)) {
472 // Check if there is an FV protocol already installed in that handle
474 Status
= CoreHandleProtocol (Handle
, &gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&Fv
);
475 if (!EFI_ERROR (Status
)) {
477 // Update Fv to use a new Fvb
479 FvDevice
= _CR (Fv
, FV_DEVICE
, Fv
);
480 if (FvDevice
->Signature
== FV2_DEVICE_SIGNATURE
) {
482 // Only write into our device structure if it's our device structure
489 // No FwVol protocol on the handle so create a new one
491 FvDevice
= CoreAllocateCopyPool (sizeof (FV_DEVICE
), &mFvDevice
);
492 if (FvDevice
== NULL
) {
497 FvDevice
->Handle
= Handle
;
498 FvDevice
->FwVolHeader
= FwVolHeader
;
499 FvDevice
->Fv
.ParentHandle
= Fvb
->ParentHandle
;
502 // Install an New FV protocol on the existing handle
504 Status
= CoreInstallProtocolInterface (
506 &gEfiFirmwareVolume2ProtocolGuid
,
507 EFI_NATIVE_INTERFACE
,
510 ASSERT_EFI_ERROR (Status
);
521 IN EFI_HANDLE ImageHandle
,
522 IN EFI_SYSTEM_TABLE
*SystemTable
527 This routine is the driver initialization entry point. It initializes the
528 libraries, and registers two notification functions. These notification
529 functions are responsible for building the FV stack dynamically.
532 ImageHandle - The image handle.
533 SystemTable - The system table.
536 EFI_SUCCESS - Function successfully returned.
540 gEfiFwVolBlockEvent
= CoreCreateProtocolNotifyEvent (
541 &gEfiFirmwareVolumeBlockProtocolGuid
,
545 &gEfiFwVolBlockNotifyReg
,