-/**@file\r
+/** @file\r
Firmware File System driver that produce Firmware Volume protocol.\r
- Layers on top of Firmware Block protocol to produce a file abstraction \r
+ Layers on top of Firmware Block protocol to produce a file abstraction\r
of FV based files.\r
- \r
-Copyright (c) 2006 - 2007 Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-#include <DxeMain.h>\r
+#include "DxeMain.h"\r
+#include "FwVolDriver.h"\r
\r
-#define KEYSIZE sizeof (UINTN)\r
\r
//\r
// Protocol notify related globals\r
FvReadFileSection,\r
FvWriteFile,\r
FvGetNextFile,\r
- KEYSIZE,\r
+ sizeof (UINTN),\r
NULL,\r
FvGetVolumeInfo,\r
FvSetVolumeInfo\r
NULL,\r
NULL,\r
{ NULL, NULL },\r
- 0\r
+ 0,\r
+ 0,\r
+ FALSE,\r
+ FALSE\r
};\r
\r
\r
//\r
// FFS helper functions\r
//\r
-\r
+/**\r
+ Read data from Firmware Block by FVB protocol Read.\r
+ The data may cross the multi block ranges.\r
+\r
+ @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read data.\r
+ @param StartLba Pointer to StartLba.\r
+ On input, the start logical block index from which to read.\r
+ On output,the end logical block index after reading.\r
+ @param Offset Pointer to Offset\r
+ On input, offset into the block at which to begin reading.\r
+ On output, offset into the end block after reading.\r
+ @param DataSize Size of data to be read.\r
+ @param Data Pointer to Buffer that the data will be read into.\r
+\r
+ @retval EFI_SUCCESS Successfully read data from firmware block.\r
+ @retval others\r
+**/\r
EFI_STATUS\r
-GetFwVolHeader (\r
+ReadFvbData (\r
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,\r
- OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader\r
+ IN OUT EFI_LBA *StartLba,\r
+ IN OUT UINTN *Offset,\r
+ IN UINTN DataSize,\r
+ OUT UINT8 *Data\r
)\r
-/*++\r
+{\r
+ UINTN BlockSize;\r
+ UINTN NumberOfBlocks;\r
+ UINTN BlockIndex;\r
+ UINTN ReadDataSize;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Try read data in current block\r
+ //\r
+ BlockIndex = 0;\r
+ ReadDataSize = DataSize;\r
+ Status = Fvb->Read (Fvb, *StartLba, *Offset, &ReadDataSize, Data);\r
+ if (Status == EFI_SUCCESS) {\r
+ *Offset += DataSize;\r
+ return EFI_SUCCESS;\r
+ } else if (Status != EFI_BAD_BUFFER_SIZE) {\r
+ //\r
+ // other error will direct return\r
+ //\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Data crosses the blocks, read data from next block\r
+ //\r
+ DataSize -= ReadDataSize;\r
+ Data += ReadDataSize;\r
+ *StartLba = *StartLba + 1;\r
+ while (DataSize > 0) {\r
+ Status = Fvb->GetBlockSize (Fvb, *StartLba, &BlockSize, &NumberOfBlocks);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Read data from the crossing blocks\r
+ //\r
+ BlockIndex = 0;\r
+ while (BlockIndex < NumberOfBlocks && DataSize >= BlockSize) {\r
+ Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &BlockSize, Data);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Data += BlockSize;\r
+ DataSize -= BlockSize;\r
+ BlockIndex ++;\r
+ }\r
\r
-Routine Description:\r
- given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
- copy the volume header into it.\r
+ //\r
+ // Data doesn't exceed the current block range.\r
+ //\r
+ if (DataSize < BlockSize) {\r
+ break;\r
+ }\r
\r
-Arguments:\r
- Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume\r
- header\r
- FwVolHeader - Pointer to pointer to allocated buffer in which the volume\r
- header is returned.\r
+ //\r
+ // Data must be got from the next block range.\r
+ //\r
+ *StartLba += NumberOfBlocks;\r
+ }\r
\r
-Returns:\r
- EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.\r
- EFI_SUCCESS - Successfully read volume header to the allocated buffer.\r
+ //\r
+ // read the remaining data\r
+ //\r
+ if (DataSize > 0) {\r
+ Status = Fvb->Read (Fvb, *StartLba + BlockIndex, 0, &DataSize, Data);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
\r
---*/\r
+ //\r
+ // Update Lba and Offset used by the following read.\r
+ //\r
+ *StartLba += BlockIndex;\r
+ *Offset = DataSize;\r
\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
+ copy the real length volume header into it.\r
+\r
+ @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to\r
+ read the volume header\r
+ @param FwVolHeader Pointer to pointer to allocated buffer in which\r
+ the volume header is returned.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
+ @retval EFI_SUCCESS Successfully read volume header to the allocated\r
+ buffer.\r
+ @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or\r
+ the file system could not be understood.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFwVolHeader (\r
+ IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,\r
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader\r
+ )\r
{\r
EFI_STATUS Status;\r
EFI_FIRMWARE_VOLUME_HEADER TempFvh;\r
UINTN FvhLength;\r
+ EFI_LBA StartLba;\r
+ UINTN Offset;\r
UINT8 *Buffer;\r
\r
-\r
//\r
- //Determine the real length of FV header\r
+ // Read the standard FV header\r
//\r
+ StartLba = 0;\r
+ Offset = 0;\r
FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
- Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh);\r
+ Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, (UINT8 *)&TempFvh);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Validate FV Header signature, if not as expected, continue.\r
+ //\r
+ if (TempFvh.Signature != EFI_FVH_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check to see that the file system is indeed formatted in a way we can\r
+ // understand it...\r
+ //\r
+ if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&\r
+ (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
//\r
// Allocate a buffer for the caller\r
//\r
- *FwVolHeader = CoreAllocateBootServicesPool (TempFvh.HeaderLength);\r
+ *FwVolHeader = AllocatePool (TempFvh.HeaderLength);\r
if (*FwVolHeader == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
//\r
FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
- Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer);\r
+ Status = ReadFvbData (Fvb, &StartLba, &Offset, FvhLength, Buffer);\r
if (EFI_ERROR (Status)) {\r
//\r
// Read failed so free buffer\r
//\r
CoreFreePool (*FwVolHeader);\r
}\r
- \r
+\r
return Status;\r
}\r
\r
\r
-STATIC\r
-VOID\r
-FreeFvDeviceResource (\r
- IN FV_DEVICE *FvDevice\r
- )\r
-/*++\r
\r
-Routine Description:\r
+/**\r
Free FvDevice resource when error happens\r
\r
-Arguments:\r
- FvDevice - pointer to the FvDevice to be freed.\r
-\r
-Returns:\r
- None.\r
+ @param FvDevice pointer to the FvDevice to be freed.\r
\r
---*/\r
+**/\r
+VOID\r
+FreeFvDeviceResource (\r
+ IN FV_DEVICE *FvDevice\r
+ )\r
{\r
FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
LIST_ENTRY *NextEntry;\r
FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink;\r
while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {\r
NextEntry = (&FfsFileEntry->Link)->ForwardLink;\r
- \r
+\r
if (FfsFileEntry->StreamHandle != 0) {\r
//\r
// Close stream and free resources from SEP\r
//\r
- CloseSectionStream (FfsFileEntry->StreamHandle);\r
+ CloseSectionStream (FfsFileEntry->StreamHandle, FALSE);\r
+ }\r
+\r
+ if (FfsFileEntry->FileCached) {\r
+ //\r
+ // Free the cached file buffer.\r
+ //\r
+ CoreFreePool (FfsFileEntry->FfsHeader);\r
}\r
\r
CoreFreePool (FfsFileEntry);\r
\r
- FfsFileEntry = (FFS_FILE_LIST_ENTRY *)NextEntry;\r
+ FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;\r
}\r
\r
-\r
- //\r
- // Free the cache\r
- //\r
- CoreFreePool (FvDevice->CachedFv);\r
+ if (!FvDevice->IsMemoryMapped) {\r
+ //\r
+ // Free the cached FV buffer.\r
+ //\r
+ CoreFreePool (FvDevice->CachedFv);\r
+ }\r
\r
//\r
// Free Volume Header\r
}\r
\r
\r
-EFI_STATUS\r
-FvCheck (\r
- IN OUT FV_DEVICE *FvDevice\r
- )\r
-/*++\r
\r
-Routine Description:\r
- Check if a FV is consistent and allocate cache\r
+/**\r
+ Check if an FV is consistent and allocate cache for it.\r
\r
-Arguments:\r
- FvDevice - pointer to the FvDevice to be checked.\r
+ @param FvDevice A pointer to the FvDevice to be checked.\r
\r
-Returns:\r
- EFI_OUT_OF_RESOURCES - No enough buffer could be allocated.\r
- EFI_SUCCESS - FV is consistent and cache is allocated.\r
- EFI_VOLUME_CORRUPTED - File system is corrupted.\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.\r
+ @retval EFI_SUCCESS FV is consistent and cache is allocated.\r
+ @retval EFI_VOLUME_CORRUPTED File system is corrupted.\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+FvCheck (\r
+ IN OUT FV_DEVICE *FvDevice\r
+ )\r
{\r
EFI_STATUS Status;\r
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
- EFI_FVB_ATTRIBUTES FvbAttributes;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;\r
+ EFI_FVB_ATTRIBUTES_2 FvbAttributes;\r
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
FFS_FILE_LIST_ENTRY *FfsFileEntry;\r
EFI_FFS_FILE_HEADER *FfsHeader;\r
UINT8 *CacheLocation;\r
- UINTN LbaOffset;\r
UINTN Index;\r
EFI_LBA LbaIndex;\r
UINTN Size;\r
- UINTN FileLength;\r
EFI_FFS_FILE_STATE FileState;\r
UINT8 *TopFvAddress;\r
UINTN TestLength;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
+ BOOLEAN FileCached;\r
+ UINTN WholeFileSize;\r
+ EFI_FFS_FILE_HEADER *CacheFfsHeader;\r
\r
+ FileCached = FALSE;\r
+ CacheFfsHeader = NULL;\r
\r
Fvb = FvDevice->Fvb;\r
FwVolHeader = FvDevice->FwVolHeader;\r
- \r
+\r
Status = Fvb->GetAttributes (Fvb, &FvbAttributes);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- //\r
- // Size is the size of the FV minus the head. We have already allocated\r
- // the header to check to make sure the volume is valid\r
- //\r
- Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);\r
- FvDevice->CachedFv = CoreAllocateBootServicesPool (Size);\r
+ Size = (UINTN) FwVolHeader->FvLength;\r
+ if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
+ FvDevice->IsMemoryMapped = TRUE;\r
\r
- if (FvDevice->CachedFv == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Don't cache memory mapped FV really.\r
+ //\r
+ FvDevice->CachedFv = (UINT8 *) (UINTN) PhysicalAddress;\r
+ } else {\r
+ FvDevice->IsMemoryMapped = FALSE;\r
+ FvDevice->CachedFv = AllocatePool (Size);\r
+\r
+ if (FvDevice->CachedFv == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
}\r
\r
//\r
- // Remember a pointer to the end fo the CachedFv\r
+ // Remember a pointer to the end of the CachedFv\r
//\r
FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;\r
\r
- //\r
- // Copy FV minus header into memory using the block map we have all ready\r
- // read into memory.\r
- //\r
- BlockMap = FwVolHeader->BlockMap;\r
- CacheLocation = FvDevice->CachedFv;\r
- LbaIndex = 0;\r
- LbaOffset = FwVolHeader->HeaderLength;\r
- while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
- \r
- for (Index = 0; Index < BlockMap->NumBlocks; Index ++) {\r
-\r
+ if (!FvDevice->IsMemoryMapped) {\r
+ //\r
+ // Copy FV into memory using the block map.\r
+ //\r
+ BlockMap = FwVolHeader->BlockMap;\r
+ CacheLocation = FvDevice->CachedFv;\r
+ LbaIndex = 0;\r
+ while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
+ //\r
+ // read the FV data\r
+ //\r
Size = BlockMap->Length;\r
- if (Index == 0) {\r
+ for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
+ Status = Fvb->Read (\r
+ Fvb,\r
+ LbaIndex,\r
+ 0,\r
+ &Size,\r
+ CacheLocation\r
+ );\r
+\r
//\r
- // Cache does not include FV Header\r
+ // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
//\r
- Size -= LbaOffset;\r
- }\r
- Status = Fvb->Read (Fvb,\r
- LbaIndex,\r
- LbaOffset,\r
- &Size,\r
- CacheLocation\r
- );\r
- //\r
- // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
- //\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ LbaIndex++;\r
+ CacheLocation += BlockMap->Length;\r
}\r
- \r
- //\r
- // After we skip Fv Header always read from start of block\r
- //\r
- LbaOffset = 0;\r
\r
- LbaIndex++;\r
- CacheLocation += Size;\r
+ BlockMap++;\r
}\r
- BlockMap++;\r
}\r
\r
//\r
// Scan to check the free space & File list\r
//\r
- if (FvbAttributes & EFI_FVB2_ERASE_POLARITY) {\r
+ if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {\r
FvDevice->ErasePolarity = 1;\r
} else {\r
FvDevice->ErasePolarity = 0;\r
- } \r
+ }\r
\r
\r
//\r
// go through the whole FV cache, check the consistence of the FV.\r
- // Make a linked list off all the Ffs file headers\r
+ // Make a linked list of all the Ffs file headers\r
//\r
Status = EFI_SUCCESS;\r
InitializeListHead (&FvDevice->FfsFileListHeader);\r
//\r
// Build FFS list\r
//\r
- FfsHeader = (EFI_FFS_FILE_HEADER *)FvDevice->CachedFv;\r
+ if (FwVolHeader->ExtHeaderOffset != 0) {\r
+ //\r
+ // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.\r
+ //\r
+ FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + FwVolHeader->ExtHeaderOffset);\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize);\r
+ } else {\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv + FwVolHeader->HeaderLength);\r
+ }\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8);\r
TopFvAddress = FvDevice->EndOfCachedFv;\r
- while ((UINT8 *)FfsHeader < TopFvAddress) {\r
+ while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) {\r
\r
- TestLength = TopFvAddress - ((UINT8 *)FfsHeader);\r
+ if (FileCached) {\r
+ CoreFreePool (CacheFfsHeader);\r
+ FileCached = FALSE;\r
+ }\r
+\r
+ TestLength = TopFvAddress - ((UINT8 *) FfsHeader);\r
if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {\r
TestLength = sizeof (EFI_FFS_FILE_HEADER);\r
}\r
}\r
\r
if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) {\r
- if ((FileState == EFI_FILE_HEADER_INVALID) || \r
+ if ((FileState == EFI_FILE_HEADER_INVALID) ||\r
(FileState == EFI_FILE_HEADER_CONSTRUCTION)) {\r
- FfsHeader++;\r
- \r
+ if (IS_FFS_FILE2 (FfsHeader)) {\r
+ if (!FvDevice->IsFfs3Fv) {\r
+ DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsHeader->Name));\r
+ }\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2));\r
+ } else {\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER));\r
+ }\r
continue;\r
- \r
} else {\r
//\r
// File system is corrputed\r
}\r
}\r
\r
- if (!IsValidFfsFile (FvDevice->ErasePolarity, FfsHeader)) {\r
+ CacheFfsHeader = FfsHeader;\r
+ if ((CacheFfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {\r
+ if (FvDevice->IsMemoryMapped) {\r
+ //\r
+ // Memory mapped FV has not been cached.\r
+ // Here is to cache FFS file to memory buffer for following checksum calculating.\r
+ // And then, the cached file buffer can be also used for FvReadFile.\r
+ //\r
+ WholeFileSize = IS_FFS_FILE2 (CacheFfsHeader) ? FFS_FILE2_SIZE (CacheFfsHeader): FFS_FILE_SIZE (CacheFfsHeader);\r
+ CacheFfsHeader = AllocateCopyPool (WholeFileSize, CacheFfsHeader);\r
+ if (CacheFfsHeader == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ FileCached = TRUE;\r
+ }\r
+ }\r
+\r
+ if (!IsValidFfsFile (FvDevice->ErasePolarity, CacheFfsHeader)) {\r
//\r
// File system is corrupted\r
//\r
goto Done;\r
}\r
\r
- //\r
- // Size[3] is a three byte array, read 4 bytes and throw one away\r
- //\r
- FileLength = *(UINT32 *)&FfsHeader->Size[0] & 0x00FFFFFF;\r
+ if (IS_FFS_FILE2 (CacheFfsHeader)) {\r
+ ASSERT (FFS_FILE2_SIZE (CacheFfsHeader) > 0x00FFFFFF);\r
+ if (!FvDevice->IsFfs3Fv) {\r
+ DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &CacheFfsHeader->Name));\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));\r
+ //\r
+ // Adjust pointer to the next 8-byte aligned boundary.\r
+ //\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) (((UINTN) FfsHeader + 7) & ~0x07);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ FileState = GetFileState (FvDevice->ErasePolarity, CacheFfsHeader);\r
\r
- FileState = GetFileState (FvDevice->ErasePolarity, FfsHeader);\r
- \r
//\r
// check for non-deleted file\r
//\r
//\r
// Create a FFS list entry for each non-deleted file\r
//\r
- FfsFileEntry = CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY));\r
+ FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));\r
if (FfsFileEntry == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Done;\r
}\r
- \r
- FfsFileEntry->FfsHeader = FfsHeader;\r
+\r
+ FfsFileEntry->FfsHeader = CacheFfsHeader;\r
+ FfsFileEntry->FileCached = FileCached;\r
+ FileCached = FALSE;\r
InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r
}\r
\r
- FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FfsHeader) + FileLength);\r
- \r
+ if (IS_FFS_FILE2 (CacheFfsHeader)) {\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE2_SIZE (CacheFfsHeader));\r
+ } else {\r
+ FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsHeader + FFS_FILE_SIZE (CacheFfsHeader));\r
+ }\r
+\r
//\r
- // Adjust pointer to the next 8-byte aligned boundry.\r
+ // Adjust pointer to the next 8-byte aligned boundary.\r
//\r
FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07);\r
- \r
+\r
}\r
\r
Done:\r
if (EFI_ERROR (Status)) {\r
+ if (FileCached) {\r
+ CoreFreePool (CacheFfsHeader);\r
+ FileCached = FALSE;\r
+ }\r
FreeFvDeviceResource (FvDevice);\r
}\r
\r
}\r
\r
\r
-STATIC\r
+\r
+/**\r
+ This notification function is invoked when an instance of the\r
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where\r
+ the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.\r
+\r
+ @param Event The event that occured\r
+ @param Context For EFI compatiblity. Not used.\r
+\r
+**/\r
VOID\r
EFIAPI\r
NotifyFwVolBlock (\r
IN EFI_EVENT Event,\r
IN VOID *Context\r
)\r
-/*++\r
-\r
-Routine Description:\r
- This notification function is invoked when an instance of the\r
- EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where\r
- the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.\r
-\r
-Arguments:\r
- Event - The event that occured\r
- Context - For EFI compatiblity. Not used.\r
-\r
-Returns:\r
-\r
- None.\r
-\r
---*/\r
{\r
EFI_HANDLE Handle;\r
EFI_STATUS Status;\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
- \r
+\r
//\r
// Get the FirmwareVolumeBlock protocol on that handle\r
//\r
- Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); \r
+ Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);\r
ASSERT_EFI_ERROR (Status);\r
- \r
+ ASSERT (Fvb != NULL);\r
\r
//\r
// Make sure the Fv Header is O.K.\r
//\r
Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
if (EFI_ERROR (Status)) {\r
- return;\r
+ continue;\r
}\r
+ ASSERT (FwVolHeader != NULL);\r
\r
if (!VerifyFvHeaderChecksum (FwVolHeader)) {\r
CoreFreePool (FwVolHeader);\r
continue;\r
}\r
\r
-\r
- //\r
- // Check to see that the file system is indeed formatted in a way we can\r
- // understand it...\r
- //\r
- if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) {\r
- continue;\r
- }\r
-\r
//\r
// Check if there is an FV protocol already installed in that handle\r
//\r
//\r
// Update Fv to use a new Fvb\r
//\r
- FvDevice = _CR (Fv, FV_DEVICE, Fv);\r
+ FvDevice = BASE_CR (Fv, FV_DEVICE, Fv);\r
if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) {\r
//\r
// Only write into our device structure if it's our device structure\r
//\r
// No FwVol protocol on the handle so create a new one\r
//\r
- FvDevice = CoreAllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);\r
+ FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);\r
if (FvDevice == NULL) {\r
return;\r
}\r
- \r
- FvDevice->Fvb = Fvb;\r
- FvDevice->Handle = Handle;\r
- FvDevice->FwVolHeader = FwVolHeader;\r
+\r
+ FvDevice->Fvb = Fvb;\r
+ FvDevice->Handle = Handle;\r
+ FvDevice->FwVolHeader = FwVolHeader;\r
+ FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
FvDevice->Fv.ParentHandle = Fvb->ParentHandle;\r
- \r
//\r
- // Install an New FV protocol on the existing handle\r
+ // Inherit the authentication status from FVB.\r
//\r
- Status = CoreInstallProtocolInterface (\r
- &Handle,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &FvDevice->Fv\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb);\r
+\r
+ if (!EFI_ERROR (FvCheck (FvDevice))) {\r
+ //\r
+ // Install an New FV protocol on the existing handle\r
+ //\r
+ Status = CoreInstallProtocolInterface (\r
+ &Handle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &FvDevice->Fv\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ //\r
+ // Free FvDevice Buffer for the corrupt FV image.\r
+ //\r
+ CoreFreePool (FvDevice);\r
+ }\r
}\r
}\r
- \r
+\r
return;\r
}\r
\r
\r
+\r
+/**\r
+ This routine is the driver initialization entry point. It registers\r
+ a notification function. This notification function are responsible\r
+ for building the FV stack dynamically.\r
+\r
+ @param ImageHandle The image handle.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCCESS Function successfully returned.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
FwVolDriverInit (\r
IN EFI_HANDLE ImageHandle,\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
-/*++\r
-\r
-Routine Description:\r
- This routine is the driver initialization entry point. It initializes the\r
- libraries, and registers two notification functions. These notification\r
- functions are responsible for building the FV stack dynamically.\r
- \r
-Arguments:\r
- ImageHandle - The image handle.\r
- SystemTable - The system table.\r
- \r
-Returns:\r
- EFI_SUCCESS - Function successfully returned.\r
-\r
---*/\r
{\r
- gEfiFwVolBlockEvent = CoreCreateProtocolNotifyEvent (\r
+ gEfiFwVolBlockEvent = EfiCreateProtocolNotifyEvent (\r
&gEfiFirmwareVolumeBlockProtocolGuid,\r
TPL_CALLBACK,\r
NotifyFwVolBlock,\r
NULL,\r
- &gEfiFwVolBlockNotifyReg,\r
- TRUE\r
+ &gEfiFwVolBlockNotifyReg\r
);\r
return EFI_SUCCESS;\r
}\r
\r
+\r