IntelFrameworkModulePkg: Add FwVolDxe driver
Signed-off-by: jljusten Reviewed-by: rsun3 Reviewed-by: lgao4 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12256 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
16d88c2d20
commit
c2df8e13f6
@ -162,6 +162,7 @@
|
|||||||
IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
|
IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
|
||||||
IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf
|
IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf
|
||||||
IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf
|
IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf
|
||||||
|
IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolDxe.inf
|
||||||
|
|
||||||
[Components.IA32,Components.X64]
|
[Components.IA32,Components.X64]
|
||||||
IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf
|
IntelFrameworkModulePkg/Universal/Acpi/AcpiS3SaveDxe/AcpiS3SaveDxe.inf
|
||||||
|
625
IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c
Normal file
625
IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/Ffs.c
Normal file
@ -0,0 +1,625 @@
|
|||||||
|
/** @file
|
||||||
|
FFS file access utilities.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FwVolDriver.h"
|
||||||
|
|
||||||
|
#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address))
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set File State in the FfsHeader.
|
||||||
|
|
||||||
|
@param State File state to be set into FFS header.
|
||||||
|
@param FfsHeader Points to the FFS file header
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SetFileState (
|
||||||
|
IN UINT8 State,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Set File State in the FfsHeader
|
||||||
|
//
|
||||||
|
FfsHeader->State = (EFI_FFS_FILE_STATE) (FfsHeader->State ^ State);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the FFS file state by checking the highest bit set in the header's state field.
|
||||||
|
|
||||||
|
@param ErasePolarity Erase polarity attribute of the firmware volume
|
||||||
|
@param FfsHeader Points to the FFS file header
|
||||||
|
|
||||||
|
@return FFS File state
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_FFS_FILE_STATE
|
||||||
|
GetFileState (
|
||||||
|
IN UINT8 ErasePolarity,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_FFS_FILE_STATE FileState;
|
||||||
|
UINT8 HighestBit;
|
||||||
|
|
||||||
|
FileState = FfsHeader->State;
|
||||||
|
|
||||||
|
if (ErasePolarity != 0) {
|
||||||
|
FileState = (EFI_FFS_FILE_STATE)~FileState;
|
||||||
|
}
|
||||||
|
|
||||||
|
HighestBit = 0x80;
|
||||||
|
while (HighestBit != 0 && ((HighestBit & FileState) == 0)) {
|
||||||
|
HighestBit >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (EFI_FFS_FILE_STATE) HighestBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert the Buffer Address to LBA Entry Address.
|
||||||
|
|
||||||
|
@param FvDevice Cached FvDevice
|
||||||
|
@param BufferAddress Address of Buffer
|
||||||
|
@param LbaListEntry Pointer to the got LBA entry that contains the address.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND Buffer address is out of FvDevice.
|
||||||
|
@retval EFI_SUCCESS LBA entry is found for Buffer address.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
Buffer2LbaEntry (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS BufferAddress,
|
||||||
|
OUT LBA_ENTRY **LbaListEntry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LBA_ENTRY *LbaEntry;
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
|
||||||
|
Link = FvDevice->LbaHeader.ForwardLink;
|
||||||
|
LbaEntry = (LBA_ENTRY *) Link;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate LBA which contains the address
|
||||||
|
//
|
||||||
|
while (&LbaEntry->Link != &FvDevice->LbaHeader) {
|
||||||
|
if ((EFI_PHYSICAL_ADDRESS) (UINTN) (LbaEntry->StartingAddress) > BufferAddress) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Link = LbaEntry->Link.ForwardLink;
|
||||||
|
LbaEntry = (LBA_ENTRY *) Link;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&LbaEntry->Link == &FvDevice->LbaHeader) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
Link = LbaEntry->Link.BackLink;
|
||||||
|
LbaEntry = (LBA_ENTRY *) Link;
|
||||||
|
|
||||||
|
if (&LbaEntry->Link == &FvDevice->LbaHeader) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
*LbaListEntry = LbaEntry;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert the Buffer Address to LBA Address & Offset.
|
||||||
|
|
||||||
|
@param FvDevice Cached FvDevice
|
||||||
|
@param BufferAddress Address of Buffer
|
||||||
|
@param Lba Pointer to the gob Lba value
|
||||||
|
@param Offset Pointer to the got Offset
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND Buffer address is out of FvDevice.
|
||||||
|
@retval EFI_SUCCESS LBA and Offset is found for Buffer address.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
Buffer2Lba (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS BufferAddress,
|
||||||
|
OUT EFI_LBA *Lba,
|
||||||
|
OUT UINTN *Offset
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LBA_ENTRY *LbaEntry;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
LbaEntry = NULL;
|
||||||
|
|
||||||
|
Status = Buffer2LbaEntry (
|
||||||
|
FvDevice,
|
||||||
|
BufferAddress,
|
||||||
|
&LbaEntry
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Lba = LbaEntry->LbaIndex;
|
||||||
|
*Offset = (UINTN) BufferAddress - (UINTN) LbaEntry->StartingAddress;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if a block of buffer is erased.
|
||||||
|
|
||||||
|
@param ErasePolarity Erase polarity attribute of the firmware volume
|
||||||
|
@param Buffer The buffer to be checked
|
||||||
|
@param BufferSize Size of the buffer in bytes
|
||||||
|
|
||||||
|
@retval TRUE The block of buffer is erased
|
||||||
|
@retval FALSE The block of buffer is not erased
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsBufferErased (
|
||||||
|
IN UINT8 ErasePolarity,
|
||||||
|
IN UINT8 *Buffer,
|
||||||
|
IN UINTN BufferSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Count;
|
||||||
|
UINT8 EraseByte;
|
||||||
|
|
||||||
|
if (ErasePolarity == 1) {
|
||||||
|
EraseByte = 0xFF;
|
||||||
|
} else {
|
||||||
|
EraseByte = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Count = 0; Count < BufferSize; Count++) {
|
||||||
|
if (Buffer[Count] != EraseByte) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify checksum of the firmware volume header.
|
||||||
|
|
||||||
|
@param FvHeader Points to the firmware volume header to be checked
|
||||||
|
|
||||||
|
@retval TRUE Checksum verification passed
|
||||||
|
@retval FALSE Checksum verification failed
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
VerifyFvHeaderChecksum (
|
||||||
|
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT16 Checksum;
|
||||||
|
|
||||||
|
Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength);
|
||||||
|
|
||||||
|
if (Checksum == 0) {
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify checksum of the FFS file header.
|
||||||
|
|
||||||
|
@param FfsHeader Points to the FFS file header to be checked
|
||||||
|
|
||||||
|
@retval TRUE Checksum verification passed
|
||||||
|
@retval FALSE Checksum verification failed
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
VerifyHeaderChecksum (
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 HeaderChecksum;
|
||||||
|
|
||||||
|
HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
|
||||||
|
HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File);
|
||||||
|
|
||||||
|
if (HeaderChecksum == 0) {
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify checksum of the FFS file data.
|
||||||
|
|
||||||
|
@param FfsHeader Points to the FFS file header to be checked
|
||||||
|
|
||||||
|
@retval TRUE Checksum verification passed
|
||||||
|
@retval FALSE Checksum verification failed
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
VerifyFileChecksum (
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 FileChecksum;
|
||||||
|
EFI_FV_FILE_ATTRIBUTES Attributes;
|
||||||
|
UINT32 FileSize;
|
||||||
|
|
||||||
|
Attributes = FfsHeader->Attributes;
|
||||||
|
|
||||||
|
if ((Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
|
||||||
|
|
||||||
|
FileSize = *(UINT32 *) FfsHeader->Size & 0x00FFFFFF;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check checksum of FFS data
|
||||||
|
//
|
||||||
|
FileChecksum = CalculateSum8 ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FileSize - sizeof (EFI_FFS_FILE_HEADER));
|
||||||
|
FileChecksum = (UINT8) (FileChecksum + FfsHeader->IntegrityCheck.Checksum.File);
|
||||||
|
|
||||||
|
if (FileChecksum == 0) {
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if it's a valid FFS file header.
|
||||||
|
|
||||||
|
@param ErasePolarity Erase polarity attribute of the firmware volume
|
||||||
|
@param FfsHeader Points to the FFS file header to be checked
|
||||||
|
|
||||||
|
@retval TRUE Valid FFS file header
|
||||||
|
@retval FALSE Invalid FFS file header
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsValidFFSHeader (
|
||||||
|
IN UINT8 ErasePolarity,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_FFS_FILE_STATE FileState;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if it is a free space
|
||||||
|
//
|
||||||
|
if (IsBufferErased (
|
||||||
|
ErasePolarity,
|
||||||
|
(UINT8 *) FfsHeader,
|
||||||
|
sizeof (EFI_FFS_FILE_HEADER)
|
||||||
|
)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileState = GetFileState (ErasePolarity, FfsHeader);
|
||||||
|
|
||||||
|
switch (FileState) {
|
||||||
|
case EFI_FILE_HEADER_CONSTRUCTION:
|
||||||
|
//
|
||||||
|
// fall through
|
||||||
|
//
|
||||||
|
case EFI_FILE_HEADER_INVALID:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case EFI_FILE_HEADER_VALID:
|
||||||
|
//
|
||||||
|
// fall through
|
||||||
|
//
|
||||||
|
case EFI_FILE_DATA_VALID:
|
||||||
|
//
|
||||||
|
// fall through
|
||||||
|
//
|
||||||
|
case EFI_FILE_MARKED_FOR_UPDATE:
|
||||||
|
//
|
||||||
|
// fall through
|
||||||
|
//
|
||||||
|
case EFI_FILE_DELETED:
|
||||||
|
//
|
||||||
|
// Here we need to verify header checksum
|
||||||
|
//
|
||||||
|
if (!VerifyHeaderChecksum (FfsHeader)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//
|
||||||
|
// return
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get next possible of Firmware File System Header.
|
||||||
|
|
||||||
|
@param ErasePolarity Erase polarity attribute of the firmware volume
|
||||||
|
@param FfsHeader Points to the FFS file header to be skipped.
|
||||||
|
|
||||||
|
@return Pointer to next FFS header.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_PHYSICAL_ADDRESS
|
||||||
|
GetNextPossibleFileHeader (
|
||||||
|
IN UINT8 ErasePolarity,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 FileLength;
|
||||||
|
UINT32 SkipLength;
|
||||||
|
|
||||||
|
if (!IsValidFFSHeader (ErasePolarity, FfsHeader)) {
|
||||||
|
//
|
||||||
|
// Skip this header
|
||||||
|
//
|
||||||
|
return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileLength = *(UINT32 *) FfsHeader->Size & 0x00FFFFFF;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Since FileLength is not multiple of 8, we need skip some bytes
|
||||||
|
// to get next possible header
|
||||||
|
//
|
||||||
|
SkipLength = FileLength;
|
||||||
|
while ((SkipLength & 0x07) != 0) {
|
||||||
|
SkipLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + SkipLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Search FFS file with the same FFS name in FV Cache.
|
||||||
|
|
||||||
|
@param FvDevice Cached FV image.
|
||||||
|
@param FfsHeader Points to the FFS file header to be skipped.
|
||||||
|
@param StateBit FFS file state bit to be checked.
|
||||||
|
|
||||||
|
@return Pointer to next found FFS header. NULL will return if no found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_FFS_FILE_HEADER *
|
||||||
|
DuplicateFileExist (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader,
|
||||||
|
IN EFI_FFS_FILE_STATE StateBit
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 *Ptr;
|
||||||
|
EFI_FFS_FILE_HEADER *NextFfsFile;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search duplicate file, not from the beginning of FV,
|
||||||
|
// just search the next ocurrence of this file
|
||||||
|
//
|
||||||
|
NextFfsFile = FfsHeader;
|
||||||
|
|
||||||
|
do {
|
||||||
|
Ptr = (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (
|
||||||
|
GetNextPossibleFileHeader (FvDevice->ErasePolarity,
|
||||||
|
NextFfsFile)
|
||||||
|
);
|
||||||
|
NextFfsFile = (EFI_FFS_FILE_HEADER *) Ptr;
|
||||||
|
|
||||||
|
if ((UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength - Ptr <
|
||||||
|
sizeof (EFI_FFS_FILE_HEADER)
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsValidFFSHeader (FvDevice->ErasePolarity, NextFfsFile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!VerifyFileChecksum (NextFfsFile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareGuid (&NextFfsFile->Name, &FfsHeader->Name)) {
|
||||||
|
if (GetFileState (FvDevice->ErasePolarity, NextFfsFile) == StateBit) {
|
||||||
|
return NextFfsFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (Ptr < (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Change FFS file header state and write to FV.
|
||||||
|
|
||||||
|
@param FvDevice Cached FV image.
|
||||||
|
@param FfsHeader Points to the FFS file header to be updated.
|
||||||
|
@param State FFS file state to be set.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS File state is writen into FV.
|
||||||
|
@retval others File state can't be writen into FV.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UpdateHeaderBit (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader,
|
||||||
|
IN EFI_FFS_FILE_STATE State
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_LBA Lba;
|
||||||
|
UINTN Offset;
|
||||||
|
UINTN NumBytesWritten;
|
||||||
|
|
||||||
|
Lba = 0;
|
||||||
|
Offset = 0;
|
||||||
|
|
||||||
|
SetFileState (State, FfsHeader);
|
||||||
|
|
||||||
|
Buffer2Lba (
|
||||||
|
FvDevice,
|
||||||
|
(EFI_PHYSICAL_ADDRESS) (UINTN) (&FfsHeader->State),
|
||||||
|
&Lba,
|
||||||
|
&Offset
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// Write the state byte into FV
|
||||||
|
//
|
||||||
|
NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
|
||||||
|
Status = FvDevice->Fvb->Write (
|
||||||
|
FvDevice->Fvb,
|
||||||
|
Lba,
|
||||||
|
Offset,
|
||||||
|
&NumBytesWritten,
|
||||||
|
&FfsHeader->State
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if it's a valid FFS file.
|
||||||
|
Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
|
||||||
|
|
||||||
|
@param FvDevice Cached FV image.
|
||||||
|
@param FfsHeader Points to the FFS file to be checked
|
||||||
|
|
||||||
|
@retval TRUE Valid FFS file
|
||||||
|
@retval FALSE Invalid FFS file
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsValidFFSFile (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_FFS_FILE_STATE FileState;
|
||||||
|
UINT8 ErasePolarity;
|
||||||
|
|
||||||
|
ErasePolarity = FvDevice->ErasePolarity;
|
||||||
|
|
||||||
|
FileState = GetFileState (ErasePolarity, FfsHeader);
|
||||||
|
|
||||||
|
switch (FileState) {
|
||||||
|
case EFI_FILE_DATA_VALID:
|
||||||
|
if (!VerifyFileChecksum (FfsHeader)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check if there is another duplicated file with the EFI_FILE_DATA_VALID
|
||||||
|
//
|
||||||
|
if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_FILE_MARKED_FOR_UPDATE:
|
||||||
|
if (!VerifyFileChecksum (FfsHeader)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
|
||||||
|
//
|
||||||
|
// since its data area is not unperturbed, it cannot be reclaimed,
|
||||||
|
// marked it as deleted
|
||||||
|
//
|
||||||
|
UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
} else if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) {
|
||||||
|
//
|
||||||
|
// Here the found file is more recent than this file,
|
||||||
|
// mark it as deleted
|
||||||
|
//
|
||||||
|
UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EFI_FILE_DELETED:
|
||||||
|
if (!VerifyFileChecksum (FfsHeader)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locate the first file in FV.
|
||||||
|
|
||||||
|
@param FvDevice Cached FV image.
|
||||||
|
@param FirstFile Points to the got first FFS file header.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND No FFS file is found in FV.
|
||||||
|
@retval EFI_SUCCESS The first FFS file is got.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvLocateFirstFile (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
OUT EFI_FFS_FILE_HEADER **FirstFile
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FFS_FILE_LIST_ENTRY *TmpFileList;
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
|
||||||
|
Link = FvDevice->FfsFileListHeader.ForwardLink;
|
||||||
|
|
||||||
|
if (Link == &FvDevice->FfsFileListHeader) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
TmpFileList = (FFS_FILE_LIST_ENTRY *) Link;
|
||||||
|
*FirstFile = (EFI_FFS_FILE_HEADER *) TmpFileList->FfsHeader;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,651 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
Firmware File System driver that produce full Firmware Volume2 protocol.
|
||||||
|
Layers on top of Firmware Block protocol to produce a file abstraction
|
||||||
|
of FV based files.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FwVolDriver.h"
|
||||||
|
|
||||||
|
#define KEYSIZE sizeof (UINTN)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
|
||||||
|
copy the real length volume header into it.
|
||||||
|
|
||||||
|
@param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to
|
||||||
|
read the volume header
|
||||||
|
@param FwVolHeader Pointer to pointer to allocated buffer in which
|
||||||
|
the volume header is returned.
|
||||||
|
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.
|
||||||
|
@retval EFI_SUCCESS Successfully read volume header to the allocated
|
||||||
|
buffer.
|
||||||
|
@retval EFI_ACCESS_DENIED Read status of FV is not enabled.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFwVolHeader (
|
||||||
|
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FIRMWARE_VOLUME_HEADER TempFvh;
|
||||||
|
EFI_FVB_ATTRIBUTES_2 FvbAttributes;
|
||||||
|
UINTN FvhLength;
|
||||||
|
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine the real length of FV header
|
||||||
|
//
|
||||||
|
Status = Fvb->GetAttributes (
|
||||||
|
Fvb,
|
||||||
|
&FvbAttributes
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((FvbAttributes & EFI_FVB2_READ_STATUS) == 0) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Just avoid compiling warning
|
||||||
|
//
|
||||||
|
BaseAddress = 0;
|
||||||
|
FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
|
||||||
|
|
||||||
|
//
|
||||||
|
// memory-mapped FV and non memory-mapped has different ways to read
|
||||||
|
//
|
||||||
|
if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
|
||||||
|
Status = Fvb->GetPhysicalAddress (
|
||||||
|
Fvb,
|
||||||
|
&BaseAddress
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
CopyMem (&TempFvh, (VOID *) (UINTN) BaseAddress, FvhLength);
|
||||||
|
} else {
|
||||||
|
Status = Fvb->Read (
|
||||||
|
Fvb,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&FvhLength,
|
||||||
|
(UINT8 *) &TempFvh
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
*FwVolHeader = AllocatePool (TempFvh.HeaderLength);
|
||||||
|
if (*FwVolHeader == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Read the whole header
|
||||||
|
//
|
||||||
|
if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
|
||||||
|
CopyMem (*FwVolHeader, (VOID *) (UINTN) BaseAddress, TempFvh.HeaderLength);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Assumed the first block is bigger than the length of Fv headder
|
||||||
|
//
|
||||||
|
FvhLength = TempFvh.HeaderLength;
|
||||||
|
Status = Fvb->Read (
|
||||||
|
Fvb,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&FvhLength,
|
||||||
|
(UINT8 *) *FwVolHeader
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// Check whether Read successes.
|
||||||
|
//
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
FreePool (*FwVolHeader);
|
||||||
|
*FwVolHeader = NULL;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Free FvDevice resource when error happens.
|
||||||
|
|
||||||
|
@param FvDevice Pointer to the FvDevice to be freed.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FreeFvDeviceResource (
|
||||||
|
IN FV_DEVICE *FvDevice
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LBA_ENTRY *LbaEntry;
|
||||||
|
FREE_SPACE_ENTRY *FreeSpaceEntry;
|
||||||
|
FFS_FILE_LIST_ENTRY *FfsFileEntry;
|
||||||
|
LIST_ENTRY *NextEntry;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free LAB Entry
|
||||||
|
//
|
||||||
|
LbaEntry = (LBA_ENTRY *) FvDevice->LbaHeader.ForwardLink;
|
||||||
|
while (&LbaEntry->Link != &FvDevice->LbaHeader) {
|
||||||
|
NextEntry = (&LbaEntry->Link)->ForwardLink;
|
||||||
|
FreePool (LbaEntry);
|
||||||
|
LbaEntry = (LBA_ENTRY *) NextEntry;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Free File List Entry
|
||||||
|
//
|
||||||
|
FfsFileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;
|
||||||
|
while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {
|
||||||
|
NextEntry = (&FfsFileEntry->Link)->ForwardLink;
|
||||||
|
FreePool (FfsFileEntry);
|
||||||
|
FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Free Space Entry
|
||||||
|
//
|
||||||
|
FreeSpaceEntry = (FREE_SPACE_ENTRY *) FvDevice->FreeSpaceHeader.ForwardLink;
|
||||||
|
while (&FreeSpaceEntry->Link != &FvDevice->FreeSpaceHeader) {
|
||||||
|
NextEntry = (&FreeSpaceEntry->Link)->ForwardLink;
|
||||||
|
FreePool (FreeSpaceEntry);
|
||||||
|
FreeSpaceEntry = (FREE_SPACE_ENTRY *) NextEntry;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Free the cache
|
||||||
|
//
|
||||||
|
FreePool ((UINT8 *) (UINTN) FvDevice->CachedFv);
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if an FV is consistent and allocate cache for it.
|
||||||
|
|
||||||
|
@param FvDevice A pointer to the FvDevice to be checked.
|
||||||
|
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.
|
||||||
|
@retval EFI_VOLUME_CORRUPTED File system is corrupted.
|
||||||
|
@retval EFI_SUCCESS FV is consistent and cache is allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvCheck (
|
||||||
|
IN FV_DEVICE *FvDevice
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
|
EFI_FVB_ATTRIBUTES_2 FvbAttributes;
|
||||||
|
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
|
||||||
|
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||||
|
UINT8 *FwCache;
|
||||||
|
LBA_ENTRY *LbaEntry;
|
||||||
|
FREE_SPACE_ENTRY *FreeSpaceEntry;
|
||||||
|
FFS_FILE_LIST_ENTRY *FfsFileEntry;
|
||||||
|
UINT8 *LbaStart;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_LBA LbaIndex;
|
||||||
|
UINT8 *Ptr;
|
||||||
|
UINTN Size;
|
||||||
|
UINT8 *FreeStart;
|
||||||
|
UINTN FreeSize;
|
||||||
|
UINT8 ErasePolarity;
|
||||||
|
UINTN FileLength;
|
||||||
|
EFI_FFS_FILE_STATE FileState;
|
||||||
|
UINT8 *TopFvAddress;
|
||||||
|
UINTN TestLength;
|
||||||
|
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||||||
|
|
||||||
|
Fvb = FvDevice->Fvb;
|
||||||
|
|
||||||
|
Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeListHead (&FvDevice->LbaHeader);
|
||||||
|
InitializeListHead (&FvDevice->FreeSpaceHeader);
|
||||||
|
InitializeListHead (&FvDevice->FfsFileListHeader);
|
||||||
|
|
||||||
|
FwVolHeader = NULL;
|
||||||
|
Status = GetFwVolHeader (Fvb, &FwVolHeader);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
ASSERT (FwVolHeader != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Double Check firmware volume header here
|
||||||
|
//
|
||||||
|
if (!VerifyFvHeaderChecksum (FwVolHeader)) {
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockMap = FwVolHeader->BlockMap;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FwVolHeader->FvLength is the whole FV length including FV header
|
||||||
|
//
|
||||||
|
FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength);
|
||||||
|
if (FwCache == NULL) {
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Copy to memory
|
||||||
|
//
|
||||||
|
LbaStart = FwCache;
|
||||||
|
LbaIndex = 0;
|
||||||
|
Ptr = NULL;
|
||||||
|
|
||||||
|
if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
|
||||||
|
//
|
||||||
|
// Get volume base address
|
||||||
|
//
|
||||||
|
Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ptr = (UINT8 *) ((UINTN) BaseAddress);
|
||||||
|
|
||||||
|
DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress));
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Copy whole FV into the memory
|
||||||
|
//
|
||||||
|
while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
|
||||||
|
|
||||||
|
for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
|
||||||
|
LbaEntry = AllocatePool (sizeof (LBA_ENTRY));
|
||||||
|
if (LbaEntry == NULL) {
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
FreeFvDeviceResource (FvDevice);
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
LbaEntry->LbaIndex = LbaIndex;
|
||||||
|
LbaEntry->StartingAddress = LbaStart;
|
||||||
|
LbaEntry->BlockLength = BlockMap->Length;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Copy each LBA into memory
|
||||||
|
//
|
||||||
|
if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
|
||||||
|
|
||||||
|
CopyMem (LbaStart, Ptr, BlockMap->Length);
|
||||||
|
Ptr += BlockMap->Length;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Size = BlockMap->Length;
|
||||||
|
Status = Fvb->Read (
|
||||||
|
Fvb,
|
||||||
|
LbaIndex,
|
||||||
|
0,
|
||||||
|
&Size,
|
||||||
|
LbaStart
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length
|
||||||
|
//
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
FreeFvDeviceResource (FvDevice);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
LbaIndex++;
|
||||||
|
LbaStart += BlockMap->Length;
|
||||||
|
|
||||||
|
InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockMap++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache;
|
||||||
|
|
||||||
|
//
|
||||||
|
// it is not used any more, so free FwVolHeader
|
||||||
|
//
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Scan to check the free space & File list
|
||||||
|
//
|
||||||
|
if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {
|
||||||
|
ErasePolarity = 1;
|
||||||
|
} else {
|
||||||
|
ErasePolarity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FvDevice->ErasePolarity = ErasePolarity;
|
||||||
|
|
||||||
|
//
|
||||||
|
// go through the whole FV cache, check the consistence of the FV
|
||||||
|
//
|
||||||
|
Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);
|
||||||
|
TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength - 1);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build FFS list & Free Space List here
|
||||||
|
//
|
||||||
|
while (Ptr <= TopFvAddress) {
|
||||||
|
TestLength = TopFvAddress - Ptr + 1;
|
||||||
|
|
||||||
|
if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
|
||||||
|
TestLength = sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsBufferErased (ErasePolarity, Ptr, TestLength)) {
|
||||||
|
//
|
||||||
|
// We found free space
|
||||||
|
//
|
||||||
|
FreeStart = Ptr;
|
||||||
|
FreeSize = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
TestLength = TopFvAddress - Ptr + 1;
|
||||||
|
|
||||||
|
if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
|
||||||
|
TestLength = sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeSize += TestLength;
|
||||||
|
Ptr += TestLength;
|
||||||
|
} while (Ptr <= TopFvAddress);
|
||||||
|
|
||||||
|
FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY));
|
||||||
|
if (FreeSpaceEntry == NULL) {
|
||||||
|
FreeFvDeviceResource (FvDevice);
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Create a Free space entry
|
||||||
|
//
|
||||||
|
FreeSpaceEntry->StartingAddress = FreeStart;
|
||||||
|
FreeSpaceEntry->Length = FreeSize;
|
||||||
|
InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// double check boundry
|
||||||
|
//
|
||||||
|
if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsValidFFSHeader (
|
||||||
|
FvDevice->ErasePolarity,
|
||||||
|
(EFI_FFS_FILE_HEADER *) Ptr
|
||||||
|
)) {
|
||||||
|
FileState = GetFileState (
|
||||||
|
FvDevice->ErasePolarity,
|
||||||
|
(EFI_FFS_FILE_HEADER *) Ptr
|
||||||
|
);
|
||||||
|
if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
|
||||||
|
Ptr += sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// File system is corrputed, return
|
||||||
|
//
|
||||||
|
FreeFvDeviceResource (FvDevice);
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) {
|
||||||
|
FileLength = *(UINT32 *) ((EFI_FFS_FILE_HEADER *) Ptr)->Size & 0x00FFFFFF;
|
||||||
|
FileState = GetFileState (
|
||||||
|
FvDevice->ErasePolarity,
|
||||||
|
(EFI_FFS_FILE_HEADER *) Ptr
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check for non-deleted file
|
||||||
|
//
|
||||||
|
if (FileState != EFI_FILE_DELETED) {
|
||||||
|
//
|
||||||
|
// Create a FFS list entry for each non-deleted file
|
||||||
|
//
|
||||||
|
FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
|
||||||
|
if (FfsFileEntry == NULL) {
|
||||||
|
FreeFvDeviceResource (FvDevice);
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
FfsFileEntry->FfsHeader = Ptr;
|
||||||
|
InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ptr += FileLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Adjust Ptr to the next 8-byte aligned boundry.
|
||||||
|
//
|
||||||
|
while (((UINTN) Ptr & 0x07) != 0) {
|
||||||
|
Ptr++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// File system is corrupted, return
|
||||||
|
//
|
||||||
|
FreeFvDeviceResource (FvDevice);
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FvDevice->CurrentFfsFile = NULL;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Entry point function does install/reinstall FV2 protocol with full functionality.
|
||||||
|
|
||||||
|
@param ImageHandle A handle for the image that is initializing this driver
|
||||||
|
@param SystemTable A pointer to the EFI system table
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS At least one Fv protocol install/reinstall successfully.
|
||||||
|
@retval EFI_NOT_FOUND No FV protocol install/reinstall successfully.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FwVolDriverInit (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_HANDLE *HandleBuffer;
|
||||||
|
UINTN HandleCount;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
||||||
|
FV_DEVICE *FvDevice;
|
||||||
|
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||||
|
BOOLEAN Reinstall;
|
||||||
|
BOOLEAN InstallFlag;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n"));
|
||||||
|
InstallFlag = FALSE;
|
||||||
|
//
|
||||||
|
// Locate all handles of Fvb protocol
|
||||||
|
//
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&HandleCount,
|
||||||
|
&HandleBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Get FV with gEfiFirmwareFileSystemGuid
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < HandleCount; Index += 1) {
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
HandleBuffer[Index],
|
||||||
|
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||||
|
(VOID **) &Fvb
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FwVolHeader = NULL;
|
||||||
|
Status = GetFwVolHeader (Fvb, &FwVolHeader);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ASSERT (FwVolHeader != NULL);
|
||||||
|
//
|
||||||
|
// Check to see that the file system is indeed formatted in a way we can
|
||||||
|
// understand it...
|
||||||
|
//
|
||||||
|
if (!CompareGuid (
|
||||||
|
&FwVolHeader->FileSystemGuid,
|
||||||
|
&gEfiFirmwareFileSystem2Guid
|
||||||
|
)) {
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FreePool (FwVolHeader);
|
||||||
|
|
||||||
|
Reinstall = FALSE;
|
||||||
|
//
|
||||||
|
// Check if there is an FV protocol already installed in that handle
|
||||||
|
//
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
HandleBuffer[Index],
|
||||||
|
&gEfiFirmwareVolume2ProtocolGuid,
|
||||||
|
(VOID **) &Fv
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Reinstall = TRUE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// FwVol protocol on the handle so create a new one
|
||||||
|
//
|
||||||
|
FvDevice = AllocateZeroPool (sizeof (FV_DEVICE));
|
||||||
|
if (FvDevice == NULL) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
FvDevice->Signature = FV_DEVICE_SIGNATURE;
|
||||||
|
FvDevice->Fvb = Fvb;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Firmware Volume Protocol interface
|
||||||
|
//
|
||||||
|
FvDevice->Fv.GetVolumeAttributes = FvGetVolumeAttributes;
|
||||||
|
FvDevice->Fv.SetVolumeAttributes = FvSetVolumeAttributes;
|
||||||
|
FvDevice->Fv.ReadFile = FvReadFile;
|
||||||
|
FvDevice->Fv.ReadSection = FvReadFileSection;
|
||||||
|
FvDevice->Fv.WriteFile = FvWriteFile;
|
||||||
|
FvDevice->Fv.GetNextFile = FvGetNextFile;
|
||||||
|
FvDevice->Fv.KeySize = KEYSIZE;
|
||||||
|
FvDevice->Fv.GetInfo = FvGetVolumeInfo;
|
||||||
|
FvDevice->Fv.SetInfo = FvSetVolumeInfo;
|
||||||
|
|
||||||
|
Status = FvCheck (FvDevice);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// The file system is not consistence
|
||||||
|
//
|
||||||
|
FreePool (FvDevice);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reinstall) {
|
||||||
|
//
|
||||||
|
// Reinstall an New FV protocol
|
||||||
|
//
|
||||||
|
// FvDevice = FV_DEVICE_FROM_THIS (Fv);
|
||||||
|
// FvDevice->Fvb = Fvb;
|
||||||
|
// FreeFvDeviceResource (FvDevice);
|
||||||
|
//
|
||||||
|
Status = gBS->ReinstallProtocolInterface (
|
||||||
|
HandleBuffer[Index],
|
||||||
|
&gEfiFirmwareVolume2ProtocolGuid,
|
||||||
|
Fv,
|
||||||
|
&FvDevice->Fv
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
InstallFlag = TRUE;
|
||||||
|
} else {
|
||||||
|
FreePool (FvDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status));
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Install an New FV protocol
|
||||||
|
//
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&FvDevice->Handle,
|
||||||
|
&gEfiFirmwareVolume2ProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&FvDevice->Fv
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
InstallFlag = TRUE;
|
||||||
|
} else {
|
||||||
|
FreePool (FvDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status));
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
//
|
||||||
|
// As long as one Fv protocol install/reinstall successfully,
|
||||||
|
// success should return to ensure this image will be not unloaded.
|
||||||
|
// Otherwise, new Fv protocols are corrupted by other loaded driver.
|
||||||
|
//
|
||||||
|
if (InstallFlag) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// No FV protocol install/reinstall successfully.
|
||||||
|
// EFI_NOT_FOUND should return to ensure this image will be unloaded.
|
||||||
|
//
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
@ -0,0 +1,220 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
Implements get/set firmware volume attributes.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FwVolDriver.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves attributes, insures positive polarity of attribute bits, returns
|
||||||
|
resulting attributes in output parameter.
|
||||||
|
|
||||||
|
@param This Calling context
|
||||||
|
@param Attributes output buffer which contains attributes
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully got volume attributes
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvGetVolumeAttributes (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
OUT EFI_FV_ATTRIBUTES *Attributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FV_DEVICE *FvDevice;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
|
EFI_FVB_ATTRIBUTES_2 FvbAttributes;
|
||||||
|
|
||||||
|
FvDevice = FV_DEVICE_FROM_THIS (This);
|
||||||
|
Fvb = FvDevice->Fvb;
|
||||||
|
|
||||||
|
//
|
||||||
|
// First get the Firmware Volume Block Attributes
|
||||||
|
//
|
||||||
|
Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
|
||||||
|
FvbAttributes &= 0xfffff0ff;
|
||||||
|
|
||||||
|
*Attributes = FvbAttributes;
|
||||||
|
*Attributes |= EFI_FV2_WRITE_POLICY_RELIABLE;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets current attributes for volume.
|
||||||
|
|
||||||
|
@param This Calling context
|
||||||
|
@param Attributes On input, FvAttributes is a pointer to
|
||||||
|
an EFI_FV_ATTRIBUTES containing the
|
||||||
|
desired firmware volume settings. On
|
||||||
|
successful return, it contains the new
|
||||||
|
settings of the firmware volume. On
|
||||||
|
unsuccessful return, FvAttributes is not
|
||||||
|
modified and the firmware volume
|
||||||
|
settings are not changed.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The requested firmware volume attributes
|
||||||
|
were set and the resulting
|
||||||
|
EFI_FV_ATTRIBUTES is returned in
|
||||||
|
FvAttributes.
|
||||||
|
@retval EFI_ACCESS_DENIED Atrribute is locked down.
|
||||||
|
@retval EFI_INVALID_PARAMETER Atrribute is not valid.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvSetVolumeAttributes (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN OUT EFI_FV_ATTRIBUTES *Attributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FV_DEVICE *FvDevice;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
|
EFI_FVB_ATTRIBUTES_2 OldFvbAttributes;
|
||||||
|
EFI_FVB_ATTRIBUTES_2 NewFvbAttributes;
|
||||||
|
UINT64 NewStatus;
|
||||||
|
UINT32 Capabilities;
|
||||||
|
|
||||||
|
FvDevice = FV_DEVICE_FROM_THIS (This);
|
||||||
|
Fvb = FvDevice->Fvb;
|
||||||
|
|
||||||
|
//
|
||||||
|
// First get the current Volume Attributes
|
||||||
|
//
|
||||||
|
Status = Fvb->GetAttributes (
|
||||||
|
Fvb,
|
||||||
|
&OldFvbAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
if ((OldFvbAttributes & EFI_FVB2_LOCK_STATUS) != 0) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Only status attributes can be updated.
|
||||||
|
//
|
||||||
|
Capabilities = OldFvbAttributes & EFI_FVB2_CAPABILITIES;
|
||||||
|
NewStatus = (*Attributes) & EFI_FVB2_STATUS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test read disable
|
||||||
|
//
|
||||||
|
if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
|
||||||
|
if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Test read enable
|
||||||
|
//
|
||||||
|
if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
|
||||||
|
if ((NewStatus & EFI_FVB2_READ_STATUS) != 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Test write disable
|
||||||
|
//
|
||||||
|
if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
|
||||||
|
if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Test write enable
|
||||||
|
//
|
||||||
|
if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
|
||||||
|
if ((NewStatus & EFI_FVB2_WRITE_STATUS) != 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Test lock
|
||||||
|
//
|
||||||
|
if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
|
||||||
|
if ((NewStatus & EFI_FVB2_LOCK_STATUS) != 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NewFvbAttributes = OldFvbAttributes & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
|
||||||
|
NewFvbAttributes |= NewStatus;
|
||||||
|
Status = Fvb->SetAttributes (
|
||||||
|
Fvb,
|
||||||
|
&NewFvbAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Attributes = 0;
|
||||||
|
|
||||||
|
This->GetVolumeAttributes (
|
||||||
|
This,
|
||||||
|
Attributes
|
||||||
|
);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return information of type InformationType for the requested firmware
|
||||||
|
volume.
|
||||||
|
|
||||||
|
@param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
|
||||||
|
@param InformationType InformationType for requested.
|
||||||
|
@param BufferSize On input, size of Buffer.On output, the amount of
|
||||||
|
data returned in Buffer.
|
||||||
|
@param Buffer A poniter to the data buffer to return.
|
||||||
|
|
||||||
|
@return EFI_UNSUPPORTED Could not get.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvGetVolumeInfo (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *InformationType,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set information with InformationType into the requested firmware volume.
|
||||||
|
|
||||||
|
@param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
|
||||||
|
@param InformationType InformationType for requested.
|
||||||
|
@param BufferSize Size of Buffer data.
|
||||||
|
@param Buffer A poniter to the data buffer to be set.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED Could not set.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvSetVolumeInfo (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *InformationType,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN CONST VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
@ -0,0 +1,773 @@
|
|||||||
|
/** @file
|
||||||
|
Common defines and definitions for a FwVolDxe driver.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _FWVOL_DRIVER_H_
|
||||||
|
#define _FWVOL_DRIVER_H_
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
|
||||||
|
#include <Guid/FirmwareFileSystem2.h>
|
||||||
|
#include <Protocol/SectionExtraction.h>
|
||||||
|
#include <Protocol/FaultTolerantWrite.h>
|
||||||
|
#include <Protocol/FirmwareVolume2.h>
|
||||||
|
#include <Protocol/FirmwareVolumeBlock.h>
|
||||||
|
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/UefiDriverEntryPoint.h>
|
||||||
|
#include <Library/UefiLib.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
|
||||||
|
#define FV_DEVICE_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', '_')
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define two helper macro to extract the Capability field or Status field in FVB
|
||||||
|
// bit fields
|
||||||
|
//
|
||||||
|
#define EFI_FVB2_CAPABILITIES (EFI_FVB2_READ_DISABLED_CAP | \
|
||||||
|
EFI_FVB2_READ_ENABLED_CAP | \
|
||||||
|
EFI_FVB2_WRITE_DISABLED_CAP | \
|
||||||
|
EFI_FVB2_WRITE_ENABLED_CAP | \
|
||||||
|
EFI_FVB2_LOCK_CAP \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
|
||||||
|
|
||||||
|
#define MAX_FILES 32
|
||||||
|
|
||||||
|
//
|
||||||
|
// Used to caculate from address -> Lba
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
EFI_LBA LbaIndex;
|
||||||
|
UINT8 *StartingAddress;
|
||||||
|
UINTN BlockLength;
|
||||||
|
} LBA_ENTRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Used to track free space in the Fv
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
UINT8 *StartingAddress;
|
||||||
|
UINTN Length;
|
||||||
|
} FREE_SPACE_ENTRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Used to track all non-deleted files
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
UINT8 *FfsHeader;
|
||||||
|
} FFS_FILE_LIST_ENTRY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
|
EFI_FIRMWARE_VOLUME2_PROTOCOL Fv;
|
||||||
|
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||||
|
UINT8 *Key;
|
||||||
|
EFI_HANDLE Handle;
|
||||||
|
|
||||||
|
UINT8 ErasePolarity;
|
||||||
|
EFI_PHYSICAL_ADDRESS CachedFv;
|
||||||
|
LIST_ENTRY LbaHeader;
|
||||||
|
LIST_ENTRY FreeSpaceHeader;
|
||||||
|
LIST_ENTRY FfsFileListHeader;
|
||||||
|
|
||||||
|
FFS_FILE_LIST_ENTRY *CurrentFfsFile;
|
||||||
|
|
||||||
|
} FV_DEVICE;
|
||||||
|
|
||||||
|
#define FV_DEVICE_FROM_THIS(a) CR (a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves attributes, insures positive polarity of attribute bits, returns
|
||||||
|
resulting attributes in output parameter.
|
||||||
|
|
||||||
|
@param This Calling context
|
||||||
|
@param Attributes output buffer which contains attributes
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully got volume attributes
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvGetVolumeAttributes (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
OUT EFI_FV_ATTRIBUTES *Attributes
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets current attributes for volume.
|
||||||
|
|
||||||
|
@param This Calling context
|
||||||
|
@param Attributes On input, FvAttributes is a pointer to
|
||||||
|
an EFI_FV_ATTRIBUTES containing the
|
||||||
|
desired firmware volume settings. On
|
||||||
|
successful return, it contains the new
|
||||||
|
settings of the firmware volume. On
|
||||||
|
unsuccessful return, FvAttributes is not
|
||||||
|
modified and the firmware volume
|
||||||
|
settings are not changed.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The requested firmware volume attributes
|
||||||
|
were set and the resulting
|
||||||
|
EFI_FV_ATTRIBUTES is returned in
|
||||||
|
FvAttributes.
|
||||||
|
@retval EFI_ACCESS_DENIED Atrribute is locked down.
|
||||||
|
@retval EFI_INVALID_PARAMETER Atrribute is not valid.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvSetVolumeAttributes (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN OUT EFI_FV_ATTRIBUTES *Attributes
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Given the input key, search for the next matching file in the volume.
|
||||||
|
|
||||||
|
@param This Indicates the calling context.
|
||||||
|
@param Key Key is a pointer to a caller allocated
|
||||||
|
buffer that contains implementation specific
|
||||||
|
data that is used to track where to begin
|
||||||
|
the search for the next file. The size of
|
||||||
|
the buffer must be at least This->KeySize
|
||||||
|
bytes long. To reinitialize the search and
|
||||||
|
begin from the beginning of the firmware
|
||||||
|
volume, the entire buffer must be cleared to
|
||||||
|
zero. Other than clearing the buffer to
|
||||||
|
initiate a new search, the caller must not
|
||||||
|
modify the data in the buffer between calls
|
||||||
|
to GetNextFile().
|
||||||
|
@param FileType FileType is a pointer to a caller allocated
|
||||||
|
EFI_FV_FILETYPE. The GetNextFile() API can
|
||||||
|
filter it's search for files based on the
|
||||||
|
value of *FileType input. A *FileType input
|
||||||
|
of 0 causes GetNextFile() to search for
|
||||||
|
files of all types. If a file is found, the
|
||||||
|
file's type is returned in *FileType.
|
||||||
|
*FileType is not modified if no file is
|
||||||
|
found.
|
||||||
|
@param NameGuid NameGuid is a pointer to a caller allocated
|
||||||
|
EFI_GUID. If a file is found, the file's
|
||||||
|
name is returned in *NameGuid. *NameGuid is
|
||||||
|
not modified if no file is found.
|
||||||
|
@param Attributes Attributes is a pointer to a caller
|
||||||
|
allocated EFI_FV_FILE_ATTRIBUTES. If a file
|
||||||
|
is found, the file's attributes are returned
|
||||||
|
in *Attributes. *Attributes is not modified
|
||||||
|
if no file is found.
|
||||||
|
@param Size Size is a pointer to a caller allocated
|
||||||
|
UINTN. If a file is found, the file's size
|
||||||
|
is returned in *Size. *Size is not modified
|
||||||
|
if no file is found.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully find the file.
|
||||||
|
@retval EFI_DEVICE_ERROR Device error.
|
||||||
|
@retval EFI_ACCESS_DENIED Fv could not read.
|
||||||
|
@retval EFI_NOT_FOUND No matching file found.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvGetNextFile (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN OUT VOID *Key,
|
||||||
|
IN OUT EFI_FV_FILETYPE *FileType,
|
||||||
|
OUT EFI_GUID *NameGuid,
|
||||||
|
OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
|
||||||
|
OUT UINTN *Size
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locates a file in the firmware volume and
|
||||||
|
copies it to the supplied buffer.
|
||||||
|
|
||||||
|
@param This Indicates the calling context.
|
||||||
|
@param NameGuid Pointer to an EFI_GUID, which is the
|
||||||
|
filename.
|
||||||
|
@param Buffer Buffer is a pointer to pointer to a buffer
|
||||||
|
in which the file or section contents or are
|
||||||
|
returned.
|
||||||
|
@param BufferSize BufferSize is a pointer to caller allocated
|
||||||
|
UINTN. On input *BufferSize indicates the
|
||||||
|
size in bytes of the memory region pointed
|
||||||
|
to by Buffer. On output, *BufferSize
|
||||||
|
contains the number of bytes required to
|
||||||
|
read the file.
|
||||||
|
@param FoundType FoundType is a pointer to a caller allocated
|
||||||
|
EFI_FV_FILETYPE that on successful return
|
||||||
|
from Read() contains the type of file read.
|
||||||
|
This output reflects the file type
|
||||||
|
irrespective of the value of the SectionType
|
||||||
|
input.
|
||||||
|
@param FileAttributes FileAttributes is a pointer to a caller
|
||||||
|
allocated EFI_FV_FILE_ATTRIBUTES. On
|
||||||
|
successful return from Read(),
|
||||||
|
*FileAttributes contains the attributes of
|
||||||
|
the file read.
|
||||||
|
@param AuthenticationStatus AuthenticationStatus is a pointer to a
|
||||||
|
caller allocated UINTN in which the
|
||||||
|
authentication status is returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully read to memory buffer.
|
||||||
|
@retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
|
||||||
|
@retval EFI_NOT_FOUND Not found.
|
||||||
|
@retval EFI_DEVICE_ERROR Device error.
|
||||||
|
@retval EFI_ACCESS_DENIED Could not read.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvReadFile (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *NameGuid,
|
||||||
|
IN OUT VOID **Buffer,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT EFI_FV_FILETYPE *FoundType,
|
||||||
|
OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
|
||||||
|
OUT UINT32 *AuthenticationStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locates a section in a given FFS File and
|
||||||
|
copies it to the supplied buffer (not including section header).
|
||||||
|
|
||||||
|
@param This Indicates the calling context.
|
||||||
|
@param NameGuid Pointer to an EFI_GUID, which is the
|
||||||
|
filename.
|
||||||
|
@param SectionType Indicates the section type to return.
|
||||||
|
@param SectionInstance Indicates which instance of sections with a
|
||||||
|
type of SectionType to return.
|
||||||
|
@param Buffer Buffer is a pointer to pointer to a buffer
|
||||||
|
in which the file or section contents or are
|
||||||
|
returned.
|
||||||
|
@param BufferSize BufferSize is a pointer to caller allocated
|
||||||
|
UINTN.
|
||||||
|
@param AuthenticationStatus AuthenticationStatus is a pointer to a
|
||||||
|
caller allocated UINT32 in which the
|
||||||
|
authentication status is returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully read the file section into
|
||||||
|
buffer.
|
||||||
|
@retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
|
||||||
|
@retval EFI_NOT_FOUND Section not found.
|
||||||
|
@retval EFI_DEVICE_ERROR Device error.
|
||||||
|
@retval EFI_ACCESS_DENIED Could not read.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvReadFileSection (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *NameGuid,
|
||||||
|
IN EFI_SECTION_TYPE SectionType,
|
||||||
|
IN UINTN SectionInstance,
|
||||||
|
IN OUT VOID **Buffer,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT UINT32 *AuthenticationStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes one or more files to the firmware volume.
|
||||||
|
|
||||||
|
@param This Indicates the calling context.
|
||||||
|
@param NumberOfFiles Number of files.
|
||||||
|
@param WritePolicy WritePolicy indicates the level of reliability
|
||||||
|
for the write in the event of a power failure or
|
||||||
|
other system failure during the write operation.
|
||||||
|
@param FileData FileData is an pointer to an array of
|
||||||
|
EFI_FV_WRITE_DATA. Each element of array
|
||||||
|
FileData represents a file to be written.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Files successfully written to firmware volume
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.
|
||||||
|
@retval EFI_DEVICE_ERROR Device error.
|
||||||
|
@retval EFI_WRITE_PROTECTED Write protected.
|
||||||
|
@retval EFI_NOT_FOUND Not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_UNSUPPORTED This function not supported.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvWriteFile (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN UINT32 NumberOfFiles,
|
||||||
|
IN EFI_FV_WRITE_POLICY WritePolicy,
|
||||||
|
IN EFI_FV_WRITE_FILE_DATA *FileData
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return information of type InformationType for the requested firmware
|
||||||
|
volume.
|
||||||
|
|
||||||
|
@param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
|
||||||
|
@param InformationType InformationType for requested.
|
||||||
|
@param BufferSize On input, size of Buffer.On output, the amount of
|
||||||
|
data returned in Buffer.
|
||||||
|
@param Buffer A poniter to the data buffer to return.
|
||||||
|
|
||||||
|
@return EFI_UNSUPPORTED Could not get.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvGetVolumeInfo (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *InformationType,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set information with InformationType into the requested firmware volume.
|
||||||
|
|
||||||
|
@param This Pointer to EFI_FIRMWARE_VOLUME2_PROTOCOL.
|
||||||
|
@param InformationType InformationType for requested.
|
||||||
|
@param BufferSize Size of Buffer data.
|
||||||
|
@param Buffer A poniter to the data buffer to be set.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED Could not set.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvSetVolumeInfo (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *InformationType,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN CONST VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes data beginning at Lba:Offset from FV. The write terminates either
|
||||||
|
when *NumBytes of data have been written, or when the firmware end is
|
||||||
|
reached. *NumBytes is updated to reflect the actual number of bytes
|
||||||
|
written.
|
||||||
|
|
||||||
|
@param FvDevice Cached Firmware Volume
|
||||||
|
@param Offset Offset in the block at which to begin write
|
||||||
|
@param NumBytes At input, indicates the requested write size.
|
||||||
|
At output, indicates the actual number of bytes written.
|
||||||
|
@param Buffer Buffer containing source data for the write.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Data is successfully written into FV.
|
||||||
|
@return error Data is failed written.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvcWrite (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN UINTN Offset,
|
||||||
|
IN OUT UINTN *NumBytes,
|
||||||
|
IN UINT8 *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if a block of buffer is erased.
|
||||||
|
|
||||||
|
@param ErasePolarity Erase polarity attribute of the firmware volume
|
||||||
|
@param Buffer The buffer to be checked
|
||||||
|
@param BufferSize Size of the buffer in bytes
|
||||||
|
|
||||||
|
@retval TRUE The block of buffer is erased
|
||||||
|
@retval FALSE The block of buffer is not erased
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsBufferErased (
|
||||||
|
IN UINT8 ErasePolarity,
|
||||||
|
IN UINT8 *Buffer,
|
||||||
|
IN UINTN BufferSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the FFS file state by checking the highest bit set in the header's state field.
|
||||||
|
|
||||||
|
@param ErasePolarity Erase polarity attribute of the firmware volume
|
||||||
|
@param FfsHeader Points to the FFS file header
|
||||||
|
|
||||||
|
@return FFS File state
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_FFS_FILE_STATE
|
||||||
|
GetFileState (
|
||||||
|
IN UINT8 ErasePolarity,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify checksum of the firmware volume header.
|
||||||
|
|
||||||
|
@param FvHeader Points to the firmware volume header to be checked
|
||||||
|
|
||||||
|
@retval TRUE Checksum verification passed
|
||||||
|
@retval FALSE Checksum verification failed
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
VerifyFvHeaderChecksum (
|
||||||
|
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if it's a valid FFS file header.
|
||||||
|
|
||||||
|
@param ErasePolarity Erase polarity attribute of the firmware volume
|
||||||
|
@param FfsHeader Points to the FFS file header to be checked
|
||||||
|
|
||||||
|
@retval TRUE Valid FFS file header
|
||||||
|
@retval FALSE Invalid FFS file header
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsValidFFSHeader (
|
||||||
|
IN UINT8 ErasePolarity,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if it's a valid FFS file.
|
||||||
|
Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
|
||||||
|
|
||||||
|
@param FvDevice Cached FV image.
|
||||||
|
@param FfsHeader Points to the FFS file to be checked
|
||||||
|
|
||||||
|
@retval TRUE Valid FFS file
|
||||||
|
@retval FALSE Invalid FFS file
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsValidFFSFile (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
|
||||||
|
copy the real length volume header into it.
|
||||||
|
|
||||||
|
@param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to
|
||||||
|
read the volume header
|
||||||
|
@param FwVolHeader Pointer to pointer to allocated buffer in which
|
||||||
|
the volume header is returned.
|
||||||
|
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated.
|
||||||
|
@retval EFI_SUCCESS Successfully read volume header to the allocated
|
||||||
|
buffer.
|
||||||
|
@retval EFI_ACCESS_DENIED Read status of FV is not enabled.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFwVolHeader (
|
||||||
|
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locate the first file in FV.
|
||||||
|
|
||||||
|
@param FvDevice Cached FV image.
|
||||||
|
@param FirstFile Points to the got first FFS file header.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND No FFS file is found in FV.
|
||||||
|
@retval EFI_SUCCESS The first FFS file is got.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvLocateFirstFile (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
OUT EFI_FFS_FILE_HEADER **FirstFile
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert the Buffer Address to LBA Entry Address.
|
||||||
|
|
||||||
|
@param FvDevice Cached FvDevice
|
||||||
|
@param BufferAddress Address of Buffer
|
||||||
|
@param LbaListEntry Pointer to the got LBA entry that contains the address.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND Buffer address is out of FvDevice.
|
||||||
|
@retval EFI_SUCCESS LBA entry is found for Buffer address.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
Buffer2LbaEntry (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS BufferAddress,
|
||||||
|
OUT LBA_ENTRY **LbaListEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert the Buffer Address to LBA Address & Offset.
|
||||||
|
|
||||||
|
@param FvDevice Cached FvDevice
|
||||||
|
@param BufferAddress Address of Buffer
|
||||||
|
@param Lba Pointer to the gob Lba value
|
||||||
|
@param Offset Pointer to the got Offset
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND Buffer address is out of FvDevice.
|
||||||
|
@retval EFI_SUCCESS LBA and Offset is found for Buffer address.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
Buffer2Lba (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS BufferAddress,
|
||||||
|
OUT EFI_LBA *Lba,
|
||||||
|
OUT UINTN *Offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set File State in the FfsHeader.
|
||||||
|
|
||||||
|
@param State File state to be set into FFS header.
|
||||||
|
@param FfsHeader Points to the FFS file header
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SetFileState (
|
||||||
|
IN UINT8 State,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a PAD File in the Free Space.
|
||||||
|
|
||||||
|
@param FvDevice Firmware Volume Device.
|
||||||
|
@param FreeSpaceEntry Indicating in which Free Space(Cache) the Pad file will be inserted.
|
||||||
|
@param Size Pad file Size, not include the header.
|
||||||
|
@param PadFileEntry The Ffs File Entry that points to this Pad File.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully create a PAD file.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough free space to create a PAD file.
|
||||||
|
@retval EFI_INVALID_PARAMETER Size is not 8 byte alignment.
|
||||||
|
@retval EFI_DEVICE_ERROR Free space is not erased.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvCreatePadFileInFreeSpace (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN FREE_SPACE_ENTRY *FreeSpaceEntry,
|
||||||
|
IN UINTN Size,
|
||||||
|
OUT FFS_FILE_LIST_ENTRY **PadFileEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a new file within a PAD file area.
|
||||||
|
|
||||||
|
@param FvDevice Firmware Volume Device.
|
||||||
|
@param FfsFileBuffer A buffer that holds an FFS file,(it contains a File Header which is in init state).
|
||||||
|
@param BufferSize The size of FfsFileBuffer.
|
||||||
|
@param ActualFileSize The actual file length, it may not be multiples of 8.
|
||||||
|
@param FileName The FFS File Name.
|
||||||
|
@param FileType The FFS File Type.
|
||||||
|
@param FileAttributes The Attributes of the FFS File to be created.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully create a new file within the found PAD file area.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No suitable PAD file is found.
|
||||||
|
@retval other errors New file is created failed.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvCreateNewFileInsidePadFile (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN UINT8 *FfsFileBuffer,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN UINTN ActualFileSize,
|
||||||
|
IN EFI_GUID *FileName,
|
||||||
|
IN EFI_FV_FILETYPE FileType,
|
||||||
|
IN EFI_FV_FILE_ATTRIBUTES FileAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write multiple files into FV in reliable method.
|
||||||
|
|
||||||
|
@param FvDevice Firmware Volume Device.
|
||||||
|
@param NumOfFiles Total File number to be written.
|
||||||
|
@param FileData The array of EFI_FV_WRITE_FILE_DATA structure,
|
||||||
|
used to get name, attributes, type, etc
|
||||||
|
@param FileOperation The array of operation for each file.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Files are added into FV.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough free PAD files to add the input files.
|
||||||
|
@retval EFI_INVALID_PARAMETER File number is less than or equal to 1.
|
||||||
|
@retval EFI_UNSUPPORTED File number exceeds the supported max numbers of files.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvCreateMultipleFiles (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN UINTN NumOfFiles,
|
||||||
|
IN EFI_FV_WRITE_FILE_DATA *FileData,
|
||||||
|
IN BOOLEAN *FileOperation
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Caculate the checksum for the FFS header.
|
||||||
|
|
||||||
|
@param FfsHeader FFS File Header which needs to caculate the checksum
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SetHeaderChecksum (
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Caculate the checksum for the FFS File.
|
||||||
|
|
||||||
|
@param FfsHeader FFS File Header which needs to caculate the checksum
|
||||||
|
@param ActualFileSize The whole Ffs File Length.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SetFileChecksum (
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader,
|
||||||
|
IN UINTN ActualFileSize
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the alignment value from File Attributes.
|
||||||
|
|
||||||
|
@param FfsAttributes FFS attribute
|
||||||
|
|
||||||
|
@return Alignment value.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
GetRequiredAlignment (
|
||||||
|
IN EFI_FV_FILE_ATTRIBUTES FfsAttributes
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locate Pad File for writing, this is got from FV Cache.
|
||||||
|
|
||||||
|
@param FvDevice Cached Firmware Volume.
|
||||||
|
@param Size The required FFS file size.
|
||||||
|
@param RequiredAlignment FFS File Data alignment requirement.
|
||||||
|
@param PadSize Pointer to the size of leading Pad File.
|
||||||
|
@param PadFileEntry Pointer to the Pad File Entry that meets the requirement.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The required pad file is found.
|
||||||
|
@retval EFI_NOT_FOUND The required pad file can't be found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvLocatePadFile (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN UINTN Size,
|
||||||
|
IN UINTN RequiredAlignment,
|
||||||
|
OUT UINTN *PadSize,
|
||||||
|
OUT FFS_FILE_LIST_ENTRY **PadFileEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locate a suitable pad file for multiple file writing.
|
||||||
|
|
||||||
|
@param FvDevice Cached Firmware Volume.
|
||||||
|
@param NumOfFiles The number of Files that needed updating
|
||||||
|
@param BufferSize The array of each file size.
|
||||||
|
@param RequiredAlignment The array of of FFS File Data alignment requirement.
|
||||||
|
@param PadSize The array of size of each leading Pad File.
|
||||||
|
@param TotalSizeNeeded The totalsize that can hold these files.
|
||||||
|
@param PadFileEntry Pointer to the Pad File Entry that meets the requirement.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The required pad file is found.
|
||||||
|
@retval EFI_NOT_FOUND The required pad file can't be found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvSearchSuitablePadFile (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN UINTN NumOfFiles,
|
||||||
|
IN UINTN *BufferSize,
|
||||||
|
IN UINTN *RequiredAlignment,
|
||||||
|
OUT UINTN *PadSize,
|
||||||
|
OUT UINTN *TotalSizeNeeded,
|
||||||
|
OUT FFS_FILE_LIST_ENTRY **PadFileEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locate a Free Space entry which can hold these files, including
|
||||||
|
meeting the alignment requirements.
|
||||||
|
|
||||||
|
@param FvDevice Cached Firmware Volume.
|
||||||
|
@param NumOfFiles The number of Files that needed updating
|
||||||
|
@param BufferSize The array of each file size.
|
||||||
|
@param RequiredAlignment The array of of FFS File Data alignment requirement.
|
||||||
|
@param PadSize The array of size of each leading Pad File.
|
||||||
|
@param TotalSizeNeeded The got total size that can hold these files.
|
||||||
|
@param FreeSpaceEntry The Free Space Entry that can hold these files.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The free space entry is found.
|
||||||
|
@retval EFI_NOT_FOUND The free space entry can't be found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FvSearchSuitableFreeSpace (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN UINTN NumOfFiles,
|
||||||
|
IN UINTN *BufferSize,
|
||||||
|
IN UINTN *RequiredAlignment,
|
||||||
|
OUT UINTN *PadSize,
|
||||||
|
OUT UINTN *TotalSizeNeeded,
|
||||||
|
OUT FREE_SPACE_ENTRY **FreeSpaceEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Change FFS file header state and write to FV.
|
||||||
|
|
||||||
|
@param FvDevice Cached FV image.
|
||||||
|
@param FfsHeader Points to the FFS file header to be updated.
|
||||||
|
@param State FFS file state to be set.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS File state is writen into FV.
|
||||||
|
@retval others File state can't be writen into FV.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UpdateHeaderBit (
|
||||||
|
IN FV_DEVICE *FvDevice,
|
||||||
|
IN EFI_FFS_FILE_HEADER *FfsHeader,
|
||||||
|
IN EFI_FFS_FILE_STATE State
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES.
|
||||||
|
|
||||||
|
@param FvFileAttrib The value of EFI_FV_FILE_ATTRIBUTES
|
||||||
|
@param FfsFileAttrib Pointer to the got FFS_FILE_ATTRIBUTES value.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FvFileAttrib2FfsFileAttrib (
|
||||||
|
IN EFI_FV_FILE_ATTRIBUTES FvFileAttrib,
|
||||||
|
OUT UINT8 *FfsFileAttrib
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,68 @@
|
|||||||
|
## @file
|
||||||
|
# FwVolDxe driver produces Firmware Volume2 protocol with full services
|
||||||
|
# (read/write, get/set) based on Firmware Volume Block protocol.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials are
|
||||||
|
# licensed and made available under the terms and conditions of the BSD License
|
||||||
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = FwVolDxe
|
||||||
|
FILE_GUID = 233C2592-1CEC-494a-A097-15DC96379777
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
|
||||||
|
ENTRY_POINT = FwVolDriverInit
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
FwVolDriver.h
|
||||||
|
FwPadFile.c
|
||||||
|
Ffs.c
|
||||||
|
FwVolWrite.c
|
||||||
|
FwVolRead.c
|
||||||
|
FwVolAttrib.c
|
||||||
|
FwVol.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||||
|
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
BaseMemoryLib
|
||||||
|
BaseLib
|
||||||
|
UefiLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
DebugLib
|
||||||
|
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiFirmwareVolumeTopFileGuid ## CONSUMES
|
||||||
|
gEfiFirmwareFileSystem2Guid ## CONSUMES
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiSectionExtractionProtocolGuid ## CONSUMES
|
||||||
|
gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES
|
||||||
|
gEfiFirmwareVolume2ProtocolGuid ## PRODUCES
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiFirmwareVolumeBlockProtocolGuid AND gEfiSectionExtractionProtocolGuid
|
||||||
|
|
@ -0,0 +1,580 @@
|
|||||||
|
/** @file
|
||||||
|
Implements functions to read firmware file.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions
|
||||||
|
of the BSD License which accompanies this distribution. The
|
||||||
|
full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FwVolDriver.h"
|
||||||
|
|
||||||
|
UINT8 mFvAttributes[] = { 0, 4, 7, 9, 10, 12, 15, 16 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert the FFS File Attributes to FV File Attributes.
|
||||||
|
|
||||||
|
@param FfsAttributes The attributes of UINT8 type.
|
||||||
|
|
||||||
|
@return The attributes of EFI_FV_FILE_ATTRIBUTES
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_FV_FILE_ATTRIBUTES
|
||||||
|
FfsAttributes2FvFileAttributes (
|
||||||
|
IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES) ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
|
||||||
|
ASSERT (FfsAttributes < 8);
|
||||||
|
return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Given the input key, search for the next matching file in the volume.
|
||||||
|
|
||||||
|
@param This Indicates the calling context.
|
||||||
|
@param Key Key is a pointer to a caller allocated
|
||||||
|
buffer that contains implementation specific
|
||||||
|
data that is used to track where to begin
|
||||||
|
the search for the next file. The size of
|
||||||
|
the buffer must be at least This->KeySize
|
||||||
|
bytes long. To reinitialize the search and
|
||||||
|
begin from the beginning of the firmware
|
||||||
|
volume, the entire buffer must be cleared to
|
||||||
|
zero. Other than clearing the buffer to
|
||||||
|
initiate a new search, the caller must not
|
||||||
|
modify the data in the buffer between calls
|
||||||
|
to GetNextFile().
|
||||||
|
@param FileType FileType is a pointer to a caller allocated
|
||||||
|
EFI_FV_FILETYPE. The GetNextFile() API can
|
||||||
|
filter it's search for files based on the
|
||||||
|
value of *FileType input. A *FileType input
|
||||||
|
of 0 causes GetNextFile() to search for
|
||||||
|
files of all types. If a file is found, the
|
||||||
|
file's type is returned in *FileType.
|
||||||
|
*FileType is not modified if no file is
|
||||||
|
found.
|
||||||
|
@param NameGuid NameGuid is a pointer to a caller allocated
|
||||||
|
EFI_GUID. If a file is found, the file's
|
||||||
|
name is returned in *NameGuid. *NameGuid is
|
||||||
|
not modified if no file is found.
|
||||||
|
@param Attributes Attributes is a pointer to a caller
|
||||||
|
allocated EFI_FV_FILE_ATTRIBUTES. If a file
|
||||||
|
is found, the file's attributes are returned
|
||||||
|
in *Attributes. *Attributes is not modified
|
||||||
|
if no file is found.
|
||||||
|
@param Size Size is a pointer to a caller allocated
|
||||||
|
UINTN. If a file is found, the file's size
|
||||||
|
is returned in *Size. *Size is not modified
|
||||||
|
if no file is found.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully find the file.
|
||||||
|
@retval EFI_DEVICE_ERROR Device error.
|
||||||
|
@retval EFI_ACCESS_DENIED Fv could not read.
|
||||||
|
@retval EFI_NOT_FOUND No matching file found.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvGetNextFile (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN OUT VOID *Key,
|
||||||
|
IN OUT EFI_FV_FILETYPE *FileType,
|
||||||
|
OUT EFI_GUID *NameGuid,
|
||||||
|
OUT EFI_FV_FILE_ATTRIBUTES *Attributes,
|
||||||
|
OUT UINTN *Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FV_DEVICE *FvDevice;
|
||||||
|
EFI_FV_ATTRIBUTES FvAttributes;
|
||||||
|
EFI_FFS_FILE_HEADER *FfsFileHeader;
|
||||||
|
UINTN *KeyValue;
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
FFS_FILE_LIST_ENTRY *FfsFileEntry;
|
||||||
|
UINTN FileLength;
|
||||||
|
|
||||||
|
FvDevice = FV_DEVICE_FROM_THIS (This);
|
||||||
|
|
||||||
|
Status = This->GetVolumeAttributes (This, &FvAttributes);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyValue = (UINTN *) Key;
|
||||||
|
FfsFileHeader = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if read operation is enabled
|
||||||
|
//
|
||||||
|
if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {
|
||||||
|
//
|
||||||
|
// File type needs to be in 0 - 0x0D
|
||||||
|
//
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (*KeyValue == 0) {
|
||||||
|
//
|
||||||
|
// Search for 1st matching file
|
||||||
|
//
|
||||||
|
Link = &FvDevice->FfsFileListHeader;
|
||||||
|
if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink;
|
||||||
|
FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
|
||||||
|
|
||||||
|
//
|
||||||
|
// remember the key
|
||||||
|
//
|
||||||
|
*KeyValue = (UINTN) FfsFileEntry;
|
||||||
|
|
||||||
|
//
|
||||||
|
// we ignore pad files
|
||||||
|
//
|
||||||
|
if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*FileType == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*FileType == FfsFileHeader->Type) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Getting link from last Ffs
|
||||||
|
//
|
||||||
|
Link = (LIST_ENTRY *) (*KeyValue);
|
||||||
|
if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink;
|
||||||
|
FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
|
||||||
|
|
||||||
|
//
|
||||||
|
// remember the key
|
||||||
|
//
|
||||||
|
*KeyValue = (UINTN) FfsFileEntry;
|
||||||
|
|
||||||
|
//
|
||||||
|
// we ignore pad files
|
||||||
|
//
|
||||||
|
if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*FileType == EFI_FV_FILETYPE_ALL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*FileType == FfsFileHeader->Type) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (Link->ForwardLink != &FvDevice->FfsFileListHeader);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cache this file entry
|
||||||
|
//
|
||||||
|
FvDevice->CurrentFfsFile = FfsFileEntry;
|
||||||
|
|
||||||
|
*FileType = FfsFileHeader->Type;
|
||||||
|
CopyGuid (NameGuid, &FfsFileHeader->Name);
|
||||||
|
*Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
|
||||||
|
|
||||||
|
FileLength = *(UINT32 *) FfsFileHeader->Size & 0x00FFFFFF;
|
||||||
|
|
||||||
|
//
|
||||||
|
// we need to substract the header size
|
||||||
|
//
|
||||||
|
*Size = FileLength - sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
|
||||||
|
if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) {
|
||||||
|
//
|
||||||
|
// specially deal with VTF file
|
||||||
|
//
|
||||||
|
UINT8 *SrcPtr;
|
||||||
|
UINT32 Tmp;
|
||||||
|
|
||||||
|
SrcPtr = (UINT8 *) FfsFileHeader;
|
||||||
|
SrcPtr += sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
|
||||||
|
while (*Size >= 4) {
|
||||||
|
Tmp = *(UINT32 *) SrcPtr;
|
||||||
|
if (Tmp == 0) {
|
||||||
|
SrcPtr += 4;
|
||||||
|
(*Size) -= 4;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locates a file in the firmware volume and
|
||||||
|
copies it to the supplied buffer.
|
||||||
|
|
||||||
|
@param This Indicates the calling context.
|
||||||
|
@param NameGuid Pointer to an EFI_GUID, which is the
|
||||||
|
filename.
|
||||||
|
@param Buffer Buffer is a pointer to pointer to a buffer
|
||||||
|
in which the file or section contents or are
|
||||||
|
returned.
|
||||||
|
@param BufferSize BufferSize is a pointer to caller allocated
|
||||||
|
UINTN. On input *BufferSize indicates the
|
||||||
|
size in bytes of the memory region pointed
|
||||||
|
to by Buffer. On output, *BufferSize
|
||||||
|
contains the number of bytes required to
|
||||||
|
read the file.
|
||||||
|
@param FoundType FoundType is a pointer to a caller allocated
|
||||||
|
EFI_FV_FILETYPE that on successful return
|
||||||
|
from Read() contains the type of file read.
|
||||||
|
This output reflects the file type
|
||||||
|
irrespective of the value of the SectionType
|
||||||
|
input.
|
||||||
|
@param FileAttributes FileAttributes is a pointer to a caller
|
||||||
|
allocated EFI_FV_FILE_ATTRIBUTES. On
|
||||||
|
successful return from Read(),
|
||||||
|
*FileAttributes contains the attributes of
|
||||||
|
the file read.
|
||||||
|
@param AuthenticationStatus AuthenticationStatus is a pointer to a
|
||||||
|
caller allocated UINTN in which the
|
||||||
|
authentication status is returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully read to memory buffer.
|
||||||
|
@retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
|
||||||
|
@retval EFI_NOT_FOUND Not found.
|
||||||
|
@retval EFI_DEVICE_ERROR Device error.
|
||||||
|
@retval EFI_ACCESS_DENIED Could not read.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvReadFile (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *NameGuid,
|
||||||
|
IN OUT VOID **Buffer,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT EFI_FV_FILETYPE *FoundType,
|
||||||
|
OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes,
|
||||||
|
OUT UINT32 *AuthenticationStatus
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FV_DEVICE *FvDevice;
|
||||||
|
UINTN Key;
|
||||||
|
EFI_GUID SearchNameGuid;
|
||||||
|
EFI_FV_ATTRIBUTES FvAttributes;
|
||||||
|
EFI_FV_FILETYPE LocalFoundType;
|
||||||
|
EFI_FV_FILE_ATTRIBUTES LocalAttributes;
|
||||||
|
UINTN FileSize;
|
||||||
|
UINT8 *SrcPtr;
|
||||||
|
FFS_FILE_LIST_ENTRY *FfsFileEntry;
|
||||||
|
EFI_FFS_FILE_HEADER *FfsHeader;
|
||||||
|
UINT8 *FileBuffer;
|
||||||
|
|
||||||
|
if (NULL == This || NULL == NameGuid) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
FvDevice = FV_DEVICE_FROM_THIS (This);
|
||||||
|
|
||||||
|
Status = This->GetVolumeAttributes (This, &FvAttributes);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// First check to see that FV is enabled for reads...
|
||||||
|
//
|
||||||
|
if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
FfsHeader = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if the file was read last time.
|
||||||
|
//
|
||||||
|
FfsFileEntry = FvDevice->CurrentFfsFile;
|
||||||
|
|
||||||
|
if (FfsFileEntry != NULL) {
|
||||||
|
FfsHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((FfsFileEntry == NULL) || (!CompareGuid (&FfsHeader->Name, NameGuid))) {
|
||||||
|
//
|
||||||
|
// If not match or no file cached, search this file
|
||||||
|
//
|
||||||
|
Key = 0;
|
||||||
|
do {
|
||||||
|
LocalFoundType = 0;
|
||||||
|
Status = This->GetNextFile (
|
||||||
|
This,
|
||||||
|
&Key,
|
||||||
|
&LocalFoundType,
|
||||||
|
&SearchNameGuid,
|
||||||
|
&LocalAttributes,
|
||||||
|
&FileSize
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
} while (!CompareGuid (&SearchNameGuid, NameGuid));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get file entry
|
||||||
|
//
|
||||||
|
FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update the cache
|
||||||
|
//
|
||||||
|
FvDevice->CurrentFfsFile = FfsFileEntry;
|
||||||
|
|
||||||
|
FfsHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Get File Size of the cached file
|
||||||
|
//
|
||||||
|
FileSize = *(UINT32 *) FfsHeader->Size & 0x00FFFFFF;
|
||||||
|
FileSize -= sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Get file info
|
||||||
|
//
|
||||||
|
*FoundType = FfsHeader->Type;
|
||||||
|
*FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
|
||||||
|
*AuthenticationStatus = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If Buffer is NULL, we only want to get some information
|
||||||
|
//
|
||||||
|
if (Buffer == NULL) {
|
||||||
|
*BufferSize = FileSize;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrcPtr = (UINT8 *) FfsHeader;
|
||||||
|
SrcPtr += sizeof (EFI_FFS_FILE_HEADER);
|
||||||
|
|
||||||
|
if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) {
|
||||||
|
//
|
||||||
|
// specially deal with VTF file
|
||||||
|
//
|
||||||
|
UINT32 Tmp;
|
||||||
|
|
||||||
|
while (FileSize >= 4) {
|
||||||
|
Tmp = *(UINT32 *) SrcPtr;
|
||||||
|
if (Tmp == 0) {
|
||||||
|
SrcPtr += 4;
|
||||||
|
FileSize -= 4;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If we drop out of the above loop, we've found the correct file header...
|
||||||
|
//
|
||||||
|
if (*Buffer == NULL) {
|
||||||
|
FileBuffer = AllocateCopyPool (FileSize, SrcPtr);
|
||||||
|
if (FileBuffer == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
*BufferSize = FileSize;
|
||||||
|
*Buffer = FileBuffer;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the user's buffer is smaller than the file size, then copy as much
|
||||||
|
// as we can and return an appropriate status.
|
||||||
|
//
|
||||||
|
if (FileSize > *BufferSize) {
|
||||||
|
CopyMem (*Buffer, SrcPtr, *BufferSize);
|
||||||
|
*BufferSize = FileSize;
|
||||||
|
return EFI_WARN_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// User's buffer size is ok, so copy the entire file to their buffer.
|
||||||
|
//
|
||||||
|
*BufferSize = FileSize;
|
||||||
|
CopyMem (*Buffer, SrcPtr, *BufferSize);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Locates a section in a given FFS File and
|
||||||
|
copies it to the supplied buffer (not including section header).
|
||||||
|
|
||||||
|
@param This Indicates the calling context.
|
||||||
|
@param NameGuid Pointer to an EFI_GUID, which is the
|
||||||
|
filename.
|
||||||
|
@param SectionType Indicates the section type to return.
|
||||||
|
@param SectionInstance Indicates which instance of sections with a
|
||||||
|
type of SectionType to return.
|
||||||
|
@param Buffer Buffer is a pointer to pointer to a buffer
|
||||||
|
in which the file or section contents or are
|
||||||
|
returned.
|
||||||
|
@param BufferSize BufferSize is a pointer to caller allocated
|
||||||
|
UINTN.
|
||||||
|
@param AuthenticationStatus AuthenticationStatus is a pointer to a
|
||||||
|
caller allocated UINT32 in which the
|
||||||
|
authentication status is returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully read the file section into
|
||||||
|
buffer.
|
||||||
|
@retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
|
||||||
|
@retval EFI_NOT_FOUND Section not found.
|
||||||
|
@retval EFI_DEVICE_ERROR Device error.
|
||||||
|
@retval EFI_ACCESS_DENIED Could not read.
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvReadFileSection (
|
||||||
|
IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
|
||||||
|
IN CONST EFI_GUID *NameGuid,
|
||||||
|
IN EFI_SECTION_TYPE SectionType,
|
||||||
|
IN UINTN SectionInstance,
|
||||||
|
IN OUT VOID **Buffer,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT UINT32 *AuthenticationStatus
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FV_ATTRIBUTES FvAttributes;
|
||||||
|
EFI_FV_FILETYPE FileType;
|
||||||
|
EFI_FV_FILE_ATTRIBUTES FileAttributes;
|
||||||
|
UINTN FileSize;
|
||||||
|
UINT8 *FileBuffer;
|
||||||
|
EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
|
||||||
|
UINTN StreamHandle;
|
||||||
|
|
||||||
|
if (NULL == This || NULL == NameGuid || Buffer == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = This->GetVolumeAttributes (This, &FvAttributes);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// First check to see that FV is enabled for reads...
|
||||||
|
//
|
||||||
|
if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Read the whole file into buffer
|
||||||
|
//
|
||||||
|
FileBuffer = NULL;
|
||||||
|
Status = This->ReadFile (
|
||||||
|
This,
|
||||||
|
NameGuid,
|
||||||
|
(VOID **) &FileBuffer,
|
||||||
|
&FileSize,
|
||||||
|
&FileType,
|
||||||
|
&FileAttributes,
|
||||||
|
AuthenticationStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check to see that the file actually HAS sections before we go any further.
|
||||||
|
//
|
||||||
|
if (FileType == EFI_FV_FILETYPE_RAW) {
|
||||||
|
FreePool (FileBuffer);
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Located the protocol
|
||||||
|
//
|
||||||
|
Status = gBS->LocateProtocol (
|
||||||
|
&gEfiSectionExtractionProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
(VOID **) &Sep
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
FreePool (FileBuffer);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = Sep->OpenSectionStream (
|
||||||
|
Sep,
|
||||||
|
FileSize,
|
||||||
|
FileBuffer,
|
||||||
|
&StreamHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
FreePool (FileBuffer);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SectionType == 0) {
|
||||||
|
//
|
||||||
|
// We need the whole section stream
|
||||||
|
//
|
||||||
|
Status = Sep->GetSection (
|
||||||
|
Sep,
|
||||||
|
StreamHandle,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
Buffer,
|
||||||
|
BufferSize,
|
||||||
|
AuthenticationStatus
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Status = Sep->GetSection (
|
||||||
|
Sep,
|
||||||
|
StreamHandle,
|
||||||
|
&SectionType,
|
||||||
|
NULL,
|
||||||
|
SectionInstance,
|
||||||
|
Buffer,
|
||||||
|
BufferSize,
|
||||||
|
AuthenticationStatus
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Handle AuthenticationStatus if necessary
|
||||||
|
//
|
||||||
|
Sep->CloseSectionStream (Sep, StreamHandle);
|
||||||
|
|
||||||
|
FreePool (FileBuffer);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user