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
,
50 // FFS helper functions
55 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
,
56 OUT EFI_FIRMWARE_VOLUME_HEADER
**FwVolHeader
61 given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
62 copy the volume header into it.
65 Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume
67 FwVolHeader - Pointer to pointer to allocated buffer in which the volume
71 EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
72 EFI_SUCCESS - Successfully read volume header to the allocated buffer.
78 EFI_FIRMWARE_VOLUME_HEADER TempFvh
;
84 //Determine the real length of FV header
86 FvhLength
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
);
87 Status
= Fvb
->Read (Fvb
, 0, 0, &FvhLength
, (UINT8
*)&TempFvh
);
90 // Allocate a buffer for the caller
92 *FwVolHeader
= CoreAllocateBootServicesPool (TempFvh
.HeaderLength
);
93 if (*FwVolHeader
== NULL
) {
94 return EFI_OUT_OF_RESOURCES
;
98 // Copy the standard header into the buffer
100 CopyMem (*FwVolHeader
, &TempFvh
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
));
103 // Read the rest of the header
105 FvhLength
= TempFvh
.HeaderLength
- sizeof (EFI_FIRMWARE_VOLUME_HEADER
);
106 Buffer
= (UINT8
*)*FwVolHeader
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER
);
107 Status
= Fvb
->Read (Fvb
, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER
), &FvhLength
, Buffer
);
108 if (EFI_ERROR (Status
)) {
110 // Read failed so free buffer
112 CoreFreePool (*FwVolHeader
);
121 FreeFvDeviceResource (
122 IN FV_DEVICE
*FvDevice
127 Free FvDevice resource when error happens
130 FvDevice - pointer to the FvDevice to be freed.
137 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
138 LIST_ENTRY
*NextEntry
;
141 // Free File List Entry
143 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*)FvDevice
->FfsFileListHeader
.ForwardLink
;
144 while (&FfsFileEntry
->Link
!= &FvDevice
->FfsFileListHeader
) {
145 NextEntry
= (&FfsFileEntry
->Link
)->ForwardLink
;
147 if (FfsFileEntry
->StreamHandle
!= 0) {
149 // Close stream and free resources from SEP
151 FfsFileEntry
->Sep
->CloseSectionStream (FfsFileEntry
->Sep
, FfsFileEntry
->StreamHandle
);
154 CoreFreePool (FfsFileEntry
);
156 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*)NextEntry
;
163 CoreFreePool (FvDevice
->CachedFv
);
166 // Free Volume Header
168 CoreFreePool (FvDevice
->FwVolHeader
);
176 IN OUT FV_DEVICE
*FvDevice
181 Check if a FV is consistent and allocate cache
184 FvDevice - pointer to the FvDevice to be checked.
187 EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.
188 EFI_SUCCESS - FV is consistent and cache is allocated.
189 EFI_VOLUME_CORRUPTED - File system is corrupted.
194 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
195 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
196 EFI_FVB_ATTRIBUTES FvbAttributes
;
197 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
198 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
199 EFI_FFS_FILE_HEADER
*FfsHeader
;
200 UINT8
*CacheLocation
;
206 EFI_FFS_FILE_STATE FileState
;
212 FwVolHeader
= FvDevice
->FwVolHeader
;
214 Status
= Fvb
->GetVolumeAttributes (Fvb
, &FvbAttributes
);
215 if (EFI_ERROR (Status
)) {
220 // Size is the size of the FV minus the head. We have already allocated
221 // the header to check to make sure the volume is valid
223 Size
= (UINTN
)(FwVolHeader
->FvLength
- FwVolHeader
->HeaderLength
);
224 FvDevice
->CachedFv
= CoreAllocateBootServicesPool (Size
);
226 if (FvDevice
->CachedFv
== NULL
) {
227 return EFI_OUT_OF_RESOURCES
;
231 // Remember a pointer to the end fo the CachedFv
233 FvDevice
->EndOfCachedFv
= FvDevice
->CachedFv
+ Size
;
236 // Copy FV minus header into memory using the block map we have all ready
239 BlockMap
= FwVolHeader
->FvBlockMap
;
240 CacheLocation
= FvDevice
->CachedFv
;
242 LbaOffset
= FwVolHeader
->HeaderLength
;
243 while ((BlockMap
->NumBlocks
!= 0) || (BlockMap
->BlockLength
!= 0)) {
245 for (Index
= 0; Index
< BlockMap
->NumBlocks
; Index
++) {
247 Size
= BlockMap
->BlockLength
;
250 // Cache does not include FV Header
254 Status
= Fvb
->Read (Fvb
,
261 // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->BlockLength
263 if (EFI_ERROR (Status
)) {
268 // After we skip Fv Header always read from start of block
273 CacheLocation
+= Size
;
279 // Scan to check the free space & File list
281 if (FvbAttributes
& EFI_FVB_ERASE_POLARITY
) {
282 FvDevice
->ErasePolarity
= 1;
284 FvDevice
->ErasePolarity
= 0;
289 // go through the whole FV cache, check the consistence of the FV.
290 // Make a linked list off all the Ffs file headers
292 Status
= EFI_SUCCESS
;
293 InitializeListHead (&FvDevice
->FfsFileListHeader
);
298 FfsHeader
= (EFI_FFS_FILE_HEADER
*)FvDevice
->CachedFv
;
299 TopFvAddress
= FvDevice
->EndOfCachedFv
;
300 while ((UINT8
*)FfsHeader
< TopFvAddress
) {
302 TestLength
= TopFvAddress
- ((UINT8
*)FfsHeader
);
303 if (TestLength
> sizeof (EFI_FFS_FILE_HEADER
)) {
304 TestLength
= sizeof (EFI_FFS_FILE_HEADER
);
307 if (IsBufferErased (FvDevice
->ErasePolarity
, FfsHeader
, TestLength
)) {
309 // We have found the free space so we are done!
314 if (!IsValidFfsHeader (FvDevice
->ErasePolarity
, FfsHeader
, &FileState
)) {
315 if ((FileState
== EFI_FILE_HEADER_INVALID
) ||
316 (FileState
== EFI_FILE_HEADER_CONSTRUCTION
)) {
323 // File system is corrputed
325 Status
= EFI_VOLUME_CORRUPTED
;
330 if (!IsValidFfsFile (FvDevice
->ErasePolarity
, FfsHeader
)) {
332 // File system is corrupted
334 Status
= EFI_VOLUME_CORRUPTED
;
339 // Size[3] is a three byte array, read 4 bytes and throw one away
341 FileLength
= *(UINT32
*)&FfsHeader
->Size
[0] & 0x00FFFFFF;
343 FileState
= GetFileState (FvDevice
->ErasePolarity
, FfsHeader
);
346 // check for non-deleted file
348 if (FileState
!= EFI_FILE_DELETED
) {
350 // Create a FFS list entry for each non-deleted file
352 FfsFileEntry
= CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY
));
353 if (FfsFileEntry
== NULL
) {
354 Status
= EFI_OUT_OF_RESOURCES
;
358 FfsFileEntry
->FfsHeader
= FfsHeader
;
359 InsertTailList (&FvDevice
->FfsFileListHeader
, &FfsFileEntry
->Link
);
362 FfsHeader
= (EFI_FFS_FILE_HEADER
*)(((UINT8
*)FfsHeader
) + FileLength
);
365 // Adjust pointer to the next 8-byte aligned boundry.
367 FfsHeader
= (EFI_FFS_FILE_HEADER
*)(((UINTN
)FfsHeader
+ 7) & ~0x07);
372 if (EFI_ERROR (Status
)) {
373 FreeFvDeviceResource (FvDevice
);
390 This notification function is invoked when an instance of the
391 EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the
392 EFI_FIRMWARE_VOLUME_PROTOCOL on the same handle. This is the function where
393 the actual initialization of the EFI_FIRMWARE_VOLUME_PROTOCOL is done.
396 Event - The event that occured
397 Context - For EFI compatiblity. Not used.
408 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
409 EFI_FIRMWARE_VOLUME_PROTOCOL
*Fv
;
411 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
413 // Examine all new handles
417 // Get the next handle
419 BufferSize
= sizeof (Handle
);
420 Status
= CoreLocateHandle (
423 gEfiFwVolBlockNotifyReg
,
429 // If not found, we're done
431 if (EFI_NOT_FOUND
== Status
) {
435 if (EFI_ERROR (Status
)) {
440 // Get the FirmwareVolumeBlock protocol on that handle
442 Status
= CoreHandleProtocol (Handle
, &gEfiFirmwareVolumeBlockProtocolGuid
, (VOID
**)&Fvb
);
443 ASSERT_EFI_ERROR (Status
);
447 // Make sure the Fv Header is O.K.
449 Status
= GetFwVolHeader (Fvb
, &FwVolHeader
);
450 if (EFI_ERROR (Status
)) {
454 if (!VerifyFvHeaderChecksum (FwVolHeader
)) {
455 CoreFreePool (FwVolHeader
);
461 // Check to see that the file system is indeed formatted in a way we can
464 if (!CompareGuid (&FwVolHeader
->FileSystemGuid
, &gEfiFirmwareFileSystemGuid
)) {
469 // Check if there is an FV protocol already installed in that handle
471 Status
= CoreHandleProtocol (Handle
, &gEfiFirmwareVolumeProtocolGuid
, (VOID
**)&Fv
);
472 if (!EFI_ERROR (Status
)) {
474 // Update Fv to use a new Fvb
476 FvDevice
= _CR (Fv
, FV_DEVICE
, Fv
);
477 if (FvDevice
->Signature
== FV_DEVICE_SIGNATURE
) {
479 // Only write into our device structure if it's our device structure
486 // No FwVol protocol on the handle so create a new one
488 FvDevice
= CoreAllocateCopyPool (sizeof (FV_DEVICE
), &mFvDevice
);
489 if (FvDevice
== NULL
) {
494 FvDevice
->Handle
= Handle
;
495 FvDevice
->FwVolHeader
= FwVolHeader
;
496 FvDevice
->Fv
.ParentHandle
= Fvb
->ParentHandle
;
499 // Install an New FV protocol on the existing handle
501 Status
= CoreInstallProtocolInterface (
503 &gEfiFirmwareVolumeProtocolGuid
,
504 EFI_NATIVE_INTERFACE
,
507 ASSERT_EFI_ERROR (Status
);
518 IN EFI_HANDLE ImageHandle
,
519 IN EFI_SYSTEM_TABLE
*SystemTable
524 This routine is the driver initialization entry point. It initializes the
525 libraries, and registers two notification functions. These notification
526 functions are responsible for building the FV stack dynamically.
529 ImageHandle - The image handle.
530 SystemTable - The system table.
533 EFI_SUCCESS - Function successfully returned.
537 gEfiFwVolBlockEvent
= CoreCreateProtocolNotifyEvent (
538 &gEfiFirmwareVolumeBlockProtocolGuid
,
542 &gEfiFwVolBlockNotifyReg
,