From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- EDK/Foundation/Core/Dxe/FwVol/Ffs.c | 266 +++++++++++++ EDK/Foundation/Core/Dxe/FwVol/FwVol.c | 556 ++++++++++++++++++++++++++++ EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c | 99 +++++ EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h | 487 ++++++++++++++++++++++++ EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c | 520 ++++++++++++++++++++++++++ EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c | 60 +++ 6 files changed, 1988 insertions(+) create mode 100644 EDK/Foundation/Core/Dxe/FwVol/Ffs.c create mode 100644 EDK/Foundation/Core/Dxe/FwVol/FwVol.c create mode 100644 EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c create mode 100644 EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h create mode 100644 EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c create mode 100644 EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c (limited to 'EDK/Foundation/Core/Dxe/FwVol') diff --git a/EDK/Foundation/Core/Dxe/FwVol/Ffs.c b/EDK/Foundation/Core/Dxe/FwVol/Ffs.c new file mode 100644 index 0000000..3361ce2 --- /dev/null +++ b/EDK/Foundation/Core/Dxe/FwVol/Ffs.c @@ -0,0 +1,266 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + Ffs.c + +Abstract: + + FFS file access utilities. + +--*/ + + +#include "FwVolDriver.h" + +#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *)((UINTN)(Address))) + + +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Get the FFS file state by checking the highest bit set in the header's state field + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header + +Returns: + FFS File state + +--*/ +{ + 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; +} + + +BOOLEAN +IsBufferErased ( + IN UINT8 ErasePolarity, + IN VOID *InBuffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Check if a block of buffer is erased + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + InBuffer - The buffer to be checked + BufferSize - Size of the buffer in bytes + +Returns: + TRUE - The block of buffer is erased + FALSE - The block of buffer is not erased + +--*/ +{ + UINTN Count; + UINT8 EraseByte; + UINT8 *Buffer; + + if(ErasePolarity == 1) { + EraseByte = 0xFF; + } else { + EraseByte = 0; + } + + Buffer = InBuffer; + for (Count = 0; Count < BufferSize; Count++) { + if (Buffer[Count] != EraseByte) { + return FALSE; + } + } + + return TRUE; +} + + +BOOLEAN +VerifyFvHeaderChecksum ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + Verify checksum of the firmware volume header + +Arguments: + FvHeader - Points to the firmware volume header to be checked + +Returns: + TRUE - Checksum verification passed + FALSE - Checksum verification failed + +--*/ +{ + UINT32 Index; + UINT32 HeaderLength; + UINT16 Checksum; + UINT16 *ptr; + + HeaderLength = FvHeader->HeaderLength; + ptr = (UINT16 *)FvHeader; + Checksum = 0; + + for (Index = 0; Index < HeaderLength / sizeof (UINT16); Index++) { + Checksum = (UINT16)(Checksum + ptr[Index]); + } + + if (Checksum == 0) { + return TRUE; + } else { + return FALSE; + } +} + + +BOOLEAN +VerifyHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Verify checksum of the FFS file header + +Arguments: + FfsHeader - Points to the FFS file header to be checked + +Returns: + TRUE - Checksum verification passed + FALSE - Checksum verification failed + +--*/ +{ + UINT32 Index; + UINT8 *ptr; + UINT8 HeaderChecksum; + + ptr = (UINT8 *)FfsHeader; + HeaderChecksum = 0; + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + HeaderChecksum = (UINT8)(HeaderChecksum + ptr[Index]); + } + + HeaderChecksum = HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File; + + if (HeaderChecksum == 0) { + return TRUE; + } else { + return FALSE; + } +} + + +BOOLEAN +IsValidFfsHeader ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_FFS_FILE_STATE *FileState + ) +/*++ + +Routine Description: + Check if it's a valid FFS file header + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header to be checked + FileState - FFS file state to be returned + +Returns: + TRUE - Valid FFS file header + FALSE - Invalid FFS file header + +--*/ +{ + *FileState = GetFileState (ErasePolarity, FfsHeader); + + switch (*FileState) { + case EFI_FILE_HEADER_VALID: + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + case EFI_FILE_DELETED: + // + // Here we need to verify header checksum + // + return VerifyHeaderChecksum (FfsHeader); + + case EFI_FILE_HEADER_CONSTRUCTION: + case EFI_FILE_HEADER_INVALID: + default: + return FALSE; + } +} + + +BOOLEAN +IsValidFfsFile ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + 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. + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file to be checked + +Returns: + TRUE - Valid FFS file + FALSE - Invalid FFS file + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + + FileState = GetFileState (ErasePolarity, FfsHeader); + switch (FileState) { + + case EFI_FILE_DELETED: + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + // + // Some other vliadation like file content checksum might be done here. + // For performance issue, Tiano only do FileState check. + // + return TRUE; + + default: + return FALSE; + } +} + diff --git a/EDK/Foundation/Core/Dxe/FwVol/FwVol.c b/EDK/Foundation/Core/Dxe/FwVol/FwVol.c new file mode 100644 index 0000000..eb0117c --- /dev/null +++ b/EDK/Foundation/Core/Dxe/FwVol/FwVol.c @@ -0,0 +1,556 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. 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. + +Module Name: + + FwVol.c + +Abstract: + + Firmware File System driver that produce Firmware Volume protocol. + Layers on top of Firmware Block protocol to produce a file abstraction + of FV based files. + +--*/ + +#include "FwVolDriver.h" +#include "DxeCore.h" + +#define KEYSIZE sizeof (UINTN) + +// +// Protocol notify related globals +// +VOID *gEfiFwVolBlockNotifyReg; +EFI_EVENT gEfiFwVolBlockEvent; + +FV_DEVICE mFvDevice = { + FV_DEVICE_SIGNATURE, + NULL, + NULL, + { + FvGetVolumeAttributes, + FvSetVolumeAttributes, + FvReadFile, + FvReadFileSection, + FvWriteFile, + FvGetNextFile, + KEYSIZE + }, + NULL, + NULL, + NULL, + NULL, + { NULL, NULL }, + 0 +}; + + +// +// FFS helper functions +// + +EFI_STATUS +GetFwVolHeader ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and + copy the volume header into it. + +Arguments: + Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume + header + FwVolHeader - Pointer to pointer to allocated buffer in which the volume + header is returned. + +Returns: + EFI_OUT_OF_RESOURCES - No enough buffer could be allocated. + EFI_SUCCESS - Successfully read volume header to the allocated buffer. + +--*/ + +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER TempFvh; + UINTN FvhLength; + UINT8 *Buffer; + + + // + //Determine the real length of FV header + // + FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER); + Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh); + + // + // Allocate a buffer for the caller + // + *FwVolHeader = CoreAllocateBootServicesPool (TempFvh.HeaderLength); + if (*FwVolHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy the standard header into the buffer + // + EfiCommonLibCopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + + // + // Read the rest of the header + // + FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER); + Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER); + Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer); + if (EFI_ERROR (Status)) { + // + // Read failed so free buffer + // + CoreFreePool (*FwVolHeader); + } + + return Status; +} + + +STATIC +VOID +FreeFvDeviceResource ( + IN FV_DEVICE *FvDevice + ) +/*++ + +Routine Description: + Free FvDevice resource when error happens + +Arguments: + FvDevice - pointer to the FvDevice to be freed. + +Returns: + None. + +--*/ +{ + FFS_FILE_LIST_ENTRY *FfsFileEntry; + EFI_LIST_ENTRY *NextEntry; + + // + // Free File List Entry + // + FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink; + while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) { + NextEntry = (&FfsFileEntry->Link)->ForwardLink; + + if (FfsFileEntry->StreamHandle != 0) { + // + // Close stream and free resources from SEP + // + FfsFileEntry->Sep->CloseSectionStream (FfsFileEntry->Sep, FfsFileEntry->StreamHandle); + } + + CoreFreePool (FfsFileEntry); + + FfsFileEntry = (FFS_FILE_LIST_ENTRY *)NextEntry; + } + + + // + // Free the cache + // + CoreFreePool (FvDevice->CachedFv); + + // + // Free Volume Header + // + CoreFreePool (FvDevice->FwVolHeader); + + return; +} + + +EFI_STATUS +FvCheck ( + IN OUT FV_DEVICE *FvDevice + ) +/*++ + +Routine Description: + Check if a FV is consistent and allocate cache + +Arguments: + FvDevice - pointer to the FvDevice to be checked. + +Returns: + EFI_OUT_OF_RESOURCES - No enough buffer could be allocated. + EFI_SUCCESS - FV is consistent and cache is allocated. + EFI_VOLUME_CORRUPTED - File system is corrupted. + +--*/ +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FVB_ATTRIBUTES FvbAttributes; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + EFI_FFS_FILE_HEADER *FfsHeader; + UINT8 *CacheLocation; + UINTN LbaOffset; + UINTN Index; + EFI_LBA LbaIndex; + UINTN Size; + UINTN FileLength; + EFI_FFS_FILE_STATE FileState; + UINT8 *TopFvAddress; + UINTN TestLength; + + + Fvb = FvDevice->Fvb; + FwVolHeader = FvDevice->FwVolHeader; + + Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Size is the size of the FV minus the head. We have already allocated + // the header to check to make sure the volume is valid + // + Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength); + FvDevice->CachedFv = CoreAllocateZeroBootServicesPool (Size); + if (FvDevice->CachedFv == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Remember a pointer to the end fo the CachedFv + // + FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size; + + // + // Copy FV minus header into memory using the block map we have all ready + // read into memory. + // + BlockMap = FwVolHeader->FvBlockMap; + CacheLocation = FvDevice->CachedFv; + LbaIndex = 0; + LbaOffset = FwVolHeader->HeaderLength; + while ((BlockMap->NumBlocks != 0) || (BlockMap->BlockLength != 0)) { + + for (Index = 0; Index < BlockMap->NumBlocks; Index ++) { + + Size = BlockMap->BlockLength; + if (Index == 0) { + // + // Cache does not include FV Header + // + Size -= LbaOffset; + } + Status = Fvb->Read (Fvb, + LbaIndex, + LbaOffset, + &Size, + CacheLocation + ); + // + // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->BlockLength + // + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // After we skip Fv Header always read from start of block + // + LbaOffset = 0; + + LbaIndex++; + CacheLocation += Size; + } + BlockMap++; + } + + // + // Scan to check the free space & File list + // + if (FvbAttributes & EFI_FVB_ERASE_POLARITY) { + FvDevice->ErasePolarity = 1; + } else { + FvDevice->ErasePolarity = 0; + } + + + // + // go through the whole FV cache, check the consistence of the FV. + // Make a linked list off all the Ffs file headers + // + Status = EFI_SUCCESS; + InitializeListHead (&FvDevice->FfsFileListHeader); + + // + // Build FFS list + // + FfsHeader = (EFI_FFS_FILE_HEADER *)FvDevice->CachedFv; + TopFvAddress = FvDevice->EndOfCachedFv; + while ((UINT8 *)FfsHeader < TopFvAddress) { + + TestLength = TopFvAddress - ((UINT8 *)FfsHeader); + if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { + TestLength = sizeof (EFI_FFS_FILE_HEADER); + } + + if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) { + // + // We have found the free space so we are done! + // + goto Done; + } + + if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) { + if ((FileState == EFI_FILE_HEADER_INVALID) || + (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { + FfsHeader++; + + continue; + + } else { + // + // File system is corrputed + // + Status = EFI_VOLUME_CORRUPTED; + goto Done; + } + } + + if (!IsValidFfsFile (FvDevice->ErasePolarity, FfsHeader)) { + // + // File system is corrupted + // + Status = EFI_VOLUME_CORRUPTED; + goto Done; + } + + // + // Size[3] is a three byte array, read 4 bytes and throw one away + // + FileLength = *(UINT32 *)&FfsHeader->Size[0] & 0x00FFFFFF; + + FileState = GetFileState (FvDevice->ErasePolarity, FfsHeader); + + // + // check for non-deleted file + // + if (FileState != EFI_FILE_DELETED) { + // + // Create a FFS list entry for each non-deleted file + // + FfsFileEntry = CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY)); + if (FfsFileEntry == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + FfsFileEntry->FfsHeader = FfsHeader; + InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); + } + + FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FfsHeader) + FileLength); + + // + // Adjust pointer to the next 8-byte aligned boundry. + // + FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07); + + } + +Done: + if (EFI_ERROR (Status)) { + FreeFvDeviceResource (FvDevice); + } + + return Status; +} + + +STATIC +VOID +EFIAPI +NotifyFwVolBlock ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This notification function is invoked when an instance of the + EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the + EFI_FIRMWARE_VOLUME_PROTOCOL on the same handle. This is the function where + the actual initialization of the EFI_FIRMWARE_VOLUME_PROTOCOL is done. + +Arguments: + Event - The event that occured + Context - For EFI compatiblity. Not used. + +Returns: + + None. + +--*/ +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + UINTN BufferSize; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + FV_DEVICE *FvDevice; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + // + // Examine all new handles + // + for (;;) { + // + // Get the next handle + // + BufferSize = sizeof (Handle); + Status = CoreLocateHandle ( + ByRegisterNotify, + NULL, + gEfiFwVolBlockNotifyReg, + &BufferSize, + &Handle + ); + + // + // If not found, we're done + // + if (EFI_NOT_FOUND == Status) { + break; + } + + if (EFI_ERROR (Status)) { + continue; + } + + // + // Get the FirmwareVolumeBlock protocol on that handle + // + Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, &Fvb); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status) || (Fvb == NULL)) { + return; + } + + // + // Make sure the Fv Header is O.K. + // + Status = GetFwVolHeader (Fvb, &FwVolHeader); + if (EFI_ERROR (Status) || (FwVolHeader == NULL)) { + return; + } + + if (!VerifyFvHeaderChecksum (FwVolHeader)) { + CoreFreePool (FwVolHeader); + continue; + } + + + // + // Check to see that the file system is indeed formatted in a way we can + // understand it... + // + if (!EfiCompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystemGuid)) { + continue; + } + + // + // Check if there is an FV protocol already installed in that handle + // + Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeProtocolGuid, &Fv); + if (!EFI_ERROR (Status)) { + // + // Update Fv to use a new Fvb + // + FvDevice = _CR (Fv, FV_DEVICE, Fv); + if (FvDevice->Signature == FV_DEVICE_SIGNATURE) { + // + // Only write into our device structure if it's our device structure + // + FvDevice->Fvb = Fvb; + } + + } else { + // + // No FwVol protocol on the handle so create a new one + // + FvDevice = CoreAllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice); + if (FvDevice == NULL) { + return; + } + + FvDevice->Fvb = Fvb; + FvDevice->Handle = Handle; + FvDevice->FwVolHeader = FwVolHeader; + FvDevice->Fv.ParentHandle = Fvb->ParentHandle; + + // + // Install an New FV protocol on the existing handle + // + Status = CoreInstallProtocolInterface ( + &Handle, + &gEfiFirmwareVolumeProtocolGuid, + EFI_NATIVE_INTERFACE, + &FvDevice->Fv + ); + ASSERT_EFI_ERROR (Status); + } + } + + return; +} + + +EFI_STATUS +EFIAPI +FwVolDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This routine is the driver initialization entry point. It initializes the + libraries, and registers two notification functions. These notification + functions are responsible for building the FV stack dynamically. + +Arguments: + ImageHandle - The image handle. + SystemTable - The system table. + +Returns: + EFI_SUCCESS - Function successfully returned. + +--*/ +{ + gEfiFwVolBlockEvent = CoreCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeBlockProtocolGuid, + EFI_TPL_CALLBACK, + NotifyFwVolBlock, + NULL, + &gEfiFwVolBlockNotifyReg, + TRUE + ); + return EFI_SUCCESS; +} + diff --git a/EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c b/EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c new file mode 100644 index 0000000..690d919 --- /dev/null +++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolAttrib.c @@ -0,0 +1,99 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + FwVolAttrib.c + +Abstract: + + Implements get/set firmware volume attributes + +--*/ + +#include "FwVolDriver.h" + +EFI_STATUS +EFIAPI +FvGetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully got volume attributes + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FVB_ATTRIBUTES FvbAttributes; + + FvDevice = FV_DEVICE_FROM_THIS (This); + Fvb = FvDevice->Fvb; + + if (FvDevice->CachedFv == NULL) { + Status = FvCheck (FvDevice); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // First get the Firmware Volume Block Attributes + // + Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes); + + // + // Mask out Fvb bits that are not defined in FV + // + FvbAttributes &= 0xfffff0ff; + + *Attributes = (EFI_FV_ATTRIBUTES)FvbAttributes; + + return Status; +} + + +EFI_STATUS +EFIAPI +FvSetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Sets current attributes for volume + +Arguments: + This - Calling context + Attributes - At input, contains attributes to be set. At output contains + new value of FV + +Returns: + EFI_UNSUPPORTED - Could not be set. + +--*/ +{ + return EFI_UNSUPPORTED; +} + diff --git a/EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h b/EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h new file mode 100644 index 0000000..4bd336d --- /dev/null +++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolDriver.h @@ -0,0 +1,487 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. 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. + +Module Name: + + FwVolDriver.h + +Abstract: + + Firmware File System protocol. Layers on top of Firmware + Block protocol to produce a file abstraction of FV based files. + +--*/ + +#ifndef __FWVOL_H +#define __FWVOL_H + +#include "Tiano.h" +#include "DxeCore.h" +#include "EfiFirmwareFileSystem.h" +#include "EfiFirmwareVolumeHeader.h" + +// +// Consumed protocol +// +#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeBlock) +#include EFI_PROTOCOL_DEFINITION (SectionExtraction) + +// +// Consumed GUID +// +#include EFI_GUID_DEFINITION (FirmwareFileSystem) + +// +// Produced protocol +// +#include EFI_PROTOCOL_DEFINITION (FirmwareVolume) + + +// +// Used to track all non-deleted files +// +typedef struct { + EFI_LIST_ENTRY Link; + EFI_FFS_FILE_HEADER *FfsHeader; + UINTN StreamHandle; + EFI_SECTION_EXTRACTION_PROTOCOL *Sep; +} FFS_FILE_LIST_ENTRY; + +typedef struct { + UINTN Signature; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_HANDLE Handle; + EFI_FIRMWARE_VOLUME_PROTOCOL Fv; + + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINT8 *CachedFv; + UINT8 *EndOfCachedFv; + + FFS_FILE_LIST_ENTRY *LastKey; + + EFI_LIST_ENTRY FfsFileListHeader; + + UINT8 ErasePolarity; +} FV_DEVICE; + +#define FV_DEVICE_FROM_THIS(a) CR(a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE) + + +EFI_STATUS +EFIAPI +FvGetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully got volume attributes + +--*/ +; + +EFI_STATUS +EFIAPI +FvSetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Sets current attributes for volume + +Arguments: + This - Calling context + Attributes - At input, contains attributes to be set. At output contains + new value of FV + +Returns: + EFI_UNSUPPORTED - Could not be set. +--*/ +; + +EFI_STATUS +EFIAPI +FvGetNextFile ( + IN EFI_FIRMWARE_VOLUME_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 + ) +/*++ + +Routine Description: + Given the input key, search for the next matching file in the volume. + +Arguments: + This - Indicates the calling context. + 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. + 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(). + 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. + 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. + 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. + +Returns: + EFI_SUCCESS - Successfully find the file. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Fv could not read. + EFI_NOT_FOUND - No matching file found. + EFI_INVALID_PARAMETER - Invalid parameter + +--*/ +; + + +EFI_STATUS +EFIAPI +FvReadFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN 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 + ) +/*++ + +Routine Description: + Locates a file in the firmware volume and + copies it to the supplied buffer. + +Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + Buffer - Buffer is a pointer to pointer to a buffer in + which the file or section contents or are returned. + 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. + 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. + 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. + AuthenticationStatus - AuthenticationStatus is a pointer to a caller + allocated UINTN in which the authentication status + is returned. +Returns: + EFI_SUCCESS - Successfully read to memory buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + +--*/ +; + +EFI_STATUS +EFIAPI +FvReadFileSection ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +/*++ + + Routine Description: + Locates a section in a given FFS File and + copies it to the supplied buffer (not including section header). + + Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + SectionType - Indicates the section type to return. + SectionInstance - Indicates which instance of sections with a type of + SectionType to return. + Buffer - Buffer is a pointer to pointer to a buffer in which + the file or section contents or are returned. + BufferSize - BufferSize is a pointer to caller allocated UINTN. + AuthenticationStatus -AuthenticationStatus is a pointer to a caller + allocated UINT32 in which the authentication status + is returned. + + Returns: + EFI_SUCCESS - Successfully read the file section into buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Section not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + +--*/ +; + +EFI_STATUS +EFIAPI +FvWriteFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData + ) +/*++ + + Routine Description: + Writes one or more files to the firmware volume. + + Arguments: + This - Indicates the calling context. + 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. + FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA. + Each element of FileData[] represents a file to be written. + + Returns: + EFI_SUCCESS - Files successfully written to firmware volume + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + EFI_DEVICE_ERROR - Device error. + EFI_WRITE_PROTECTED - Write protected. + EFI_NOT_FOUND - Not found. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_UNSUPPORTED - This function not supported. + +--*/ +; + + + +// +//Internal functions +// +typedef enum { + EfiCheckSumUint8 = 0, + EfiCheckSumUint16 = 1, + EfiCheckSumUint32 = 2, + EfiCheckSumUint64 = 3, + EfiCheckSumMaximum = 4 +} EFI_CHECKSUM_TYPE; + + +BOOLEAN +IsBufferErased ( + IN UINT8 ErasePolarity, + IN VOID *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Check if a block of buffer is erased + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + Buffer - The buffer to be checked + BufferSize - Size of the buffer in bytes + +Returns: + TRUE - The block of buffer is erased + FALSE - The block of buffer is not erased + +--*/ +; + +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Get the FFS file state by checking the highest bit set in the header's state field + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header + +Returns: + FFS File state + +--*/ +; + +VOID +SetFileState ( + IN UINT8 State, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Set the FFS file state. + +Arguments: + State - The state to be set. + FfsHeader - Points to the FFS file header + +Returns: + None. + +--*/ +; + +BOOLEAN +VerifyFvHeaderChecksum ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + Verify checksum of the firmware volume header + +Arguments: + FvHeader - Points to the firmware volume header to be checked + +Returns: + TRUE - Checksum verification passed + FALSE - Checksum verification failed + +--*/ +; + +BOOLEAN +IsValidFfsHeader ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_FFS_FILE_STATE *FileState + ) +/*++ + +Routine Description: + Check if it's a valid FFS file header + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header to be checked + FileState - FFS file state to be returned + +Returns: + TRUE - Valid FFS file header + FALSE - Invalid FFS file header + +--*/ +; + +BOOLEAN +IsValidFfsFile ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + 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. + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file to be checked + +Returns: + TRUE - Valid FFS file + FALSE - Invalid FFS file + +--*/ +; + +EFI_STATUS +GetFwVolHeader ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and + copy the volume header into it. + +Arguments: + Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume + header + FwVolHeader - Pointer to pointer to allocated buffer in which the volume + header is returned. + +Returns: + Status code. + +--*/ +; + + +EFI_STATUS +FvCheck ( + IN OUT FV_DEVICE *FvDevice + ) +/*++ + +Routine Description: + Check if a FV is consistent and allocate cache + +Arguments: + FvDevice - pointer to the FvDevice to be checked. + +Returns: + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + EFI_SUCCESS - FV is consistent and cache is allocated. + EFI_VOLUME_CORRUPTED - File system is corrupted. + +--*/ +; + +#endif \ No newline at end of file diff --git a/EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c b/EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c new file mode 100644 index 0000000..acaffa8 --- /dev/null +++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolRead.c @@ -0,0 +1,520 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + FwVolRead.c + +Abstract: + + Implements read firmware file + +--*/ + +#include "FwVolDriver.h" +#include "DxeCore.h" + +/*++ + +Required Alignment Alignment Value in FFS Alignment Value in +(bytes) Attributes Field Firmware Volume Interfaces +1 0 0 +2 0 1 +4 0 2 +8 0 3 +16 1 4 +128 2 7 +512 3 9 +1 KB 4 10 +4 KB 5 12 +32 KB 6 15 +64 KB 7 16 + +--*/ + +UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16}; + + +STATIC +EFI_FV_FILE_ATTRIBUTES +FfsAttributes2FvFileAttributes ( + IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes + ) +/*++ + + Routine Description: + Convert the FFS File Attributes to FV File Attributes + + Arguments: + FfsAttributes - The attributes of UINT8 type. + + Returns: + The attributes of EFI_FV_FILE_ATTRIBUTES + +--*/ +{ + FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3); + ASSERT (FfsAttributes < 8); + + return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes]; +} + + +EFI_STATUS +EFIAPI +FvGetNextFile ( + IN EFI_FIRMWARE_VOLUME_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 + ) +/*++ + +Routine Description: + Given the input key, search for the next matching file in the volume. + +Arguments: + This - Indicates the calling context. + 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. + 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(). + 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. + 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. + 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. + +Returns: + EFI_SUCCESS - Successfully find the file. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Fv could not read. + EFI_NOT_FOUND - No matching file found. + EFI_INVALID_PARAMETER - Invalid parameter + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FV_ATTRIBUTES FvAttributes; + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINTN *KeyValue; + EFI_LIST_ENTRY *Link; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + UINTN FileLength; + + FvDevice = FV_DEVICE_FROM_THIS (This); + + Status = FvGetVolumeAttributes (This, &FvAttributes); + if (EFI_ERROR (Status)){ + return Status; + } + + // + // Check if read operation is enabled + // + if ((FvAttributes & EFI_FV_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // File type needs to be in 0 - 0x0B + // + return EFI_INVALID_PARAMETER; + } + + KeyValue = (UINTN *)Key; + for (;;) { + if (*KeyValue == 0) { + // + // Search for 1st matching file + // + Link = &FvDevice->FfsFileListHeader; + } else { + // + // Key is pointer to FFsFileEntry, so get next one + // + Link = (EFI_LIST_ENTRY *)(*KeyValue); + } + + if (Link->ForwardLink == &FvDevice->FfsFileListHeader) { + // + // Next is end of list so we did not find data + // + return EFI_NOT_FOUND; + } + + FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader; + + // + // remember the key + // + *KeyValue = (UINTN)FfsFileEntry; + + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { + // + // we ignore pad files + // + continue; + } + + if (*FileType == 0) { + // + // Process all file types so we have a match + // + break; + } + + if (*FileType == FfsFileHeader->Type) { + // + // Found a matching file type + // + break; + } + + } + + // + // Return FileType, NameGuid, and Attributes + // + *FileType = FfsFileHeader->Type; + EfiCommonLibCopyMem (NameGuid, &FfsFileHeader->Name, sizeof (EFI_GUID)); + *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes); + + // + // Read four bytes out of the 3 byte array and throw out extra data + // + FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF; + + // + // we need to substract the header size + // + *Size = FileLength - sizeof(EFI_FFS_FILE_HEADER); + + if (FfsFileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // If tail is present substract it's size; + // + *Size -= sizeof(EFI_FFS_FILE_TAIL); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FvReadFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN 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 + ) +/*++ + +Routine Description: + Locates a file in the firmware volume and + copies it to the supplied buffer. + +Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + Buffer - Buffer is a pointer to pointer to a buffer in + which the file or section contents or are returned. + 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. + 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. + 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. + AuthenticationStatus - AuthenticationStatus is a pointer to a caller + allocated UINTN in which the authentication status + is returned. +Returns: + EFI_SUCCESS - Successfully read to memory buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_GUID SearchNameGuid; + EFI_FV_FILETYPE LocalFoundType; + EFI_FV_FILE_ATTRIBUTES LocalAttributes; + UINTN FileSize; + UINT8 *SrcPtr; + EFI_FFS_FILE_HEADER *FfsHeader; + UINTN InputBufferSize; + + if (NULL == NameGuid) { + return EFI_INVALID_PARAMETER; + } + + FvDevice = FV_DEVICE_FROM_THIS (This); + + + // + // Keep looking until we find the matching NameGuid. + // The Key is really an FfsFileEntry + // + FvDevice->LastKey = 0; + do { + LocalFoundType = 0; + Status = FvGetNextFile ( + This, + &FvDevice->LastKey, + &LocalFoundType, + &SearchNameGuid, + &LocalAttributes, + &FileSize + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } while (!EfiCompareGuid (&SearchNameGuid, NameGuid)); + + // + // Get a pointer to the header + // + FfsHeader = FvDevice->LastKey->FfsHeader; + + // + // Remember callers buffer size + // + InputBufferSize = *BufferSize; + + // + // Calculate return values + // + *FoundType = FfsHeader->Type; + *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes); + *AuthenticationStatus = 0; + *BufferSize = FileSize; + + if (Buffer == NULL) { + // + // If Buffer is NULL, we only want to get the information colected so far + // + return EFI_SUCCESS; + } + + // + // Skip over file header + // + SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER); + + Status = EFI_SUCCESS; + if (*Buffer == NULL) { + // + // Caller passed in a pointer so allocate buffer for them + // + *Buffer = CoreAllocateBootServicesPool (FileSize); + if (*Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else if (FileSize > InputBufferSize) { + // + // Callers buffer was not big enough + // + Status = EFI_WARN_BUFFER_TOO_SMALL; + FileSize = InputBufferSize; + } + + // + // Copy data into callers buffer + // + EfiCommonLibCopyMem (*Buffer, SrcPtr, FileSize); + + return Status; +} + + +EFI_STATUS +EFIAPI +FvReadFileSection ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +/*++ + + Routine Description: + Locates a section in a given FFS File and + copies it to the supplied buffer (not including section header). + + Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + SectionType - Indicates the section type to return. + SectionInstance - Indicates which instance of sections with a type of + SectionType to return. + Buffer - Buffer is a pointer to pointer to a buffer in which + the file or section contents or are returned. + BufferSize - BufferSize is a pointer to caller allocated UINTN. + AuthenticationStatus -AuthenticationStatus is a pointer to a caller + allocated UINT32 in which the authentication status + is returned. + + Returns: + EFI_SUCCESS - Successfully read the file section into buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Section not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINTN FileSize; + UINT8 *FileBuffer; + EFI_SECTION_EXTRACTION_PROTOCOL *Sep; + FFS_FILE_LIST_ENTRY *FfsEntry; + + if (NULL == NameGuid || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + FvDevice = FV_DEVICE_FROM_THIS (This); + + // + // Read the whole file into buffer + // + FileBuffer = NULL; + Status = FvReadFile ( + This, + NameGuid, + &FileBuffer, + &FileSize, + &FileType, + &FileAttributes, + AuthenticationStatus + ); + // + // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file. + // + FfsEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->LastKey; + + 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) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Use FfsEntry to cache Section Extraction Protocol Inforomation + // + if (FfsEntry->StreamHandle == 0) { + // + // Located the protocol + // + Status = CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid, NULL, &Sep); + // + // Section Extraction Protocol is part of Dxe Core so this should never fail + // + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status) || (Sep == NULL)) { + goto Done; + } + + Status = Sep->OpenSectionStream ( + Sep, + FileSize, + FileBuffer, + &FfsEntry->StreamHandle + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + FfsEntry->Sep = Sep; + } else { + // + // Get cached copy of Sep + // + Sep = FfsEntry->Sep; + } + + // + // If SectionType == 0 We need the whole section stream + // + Status = Sep->GetSection ( + Sep, + FfsEntry->StreamHandle, + (SectionType == 0) ? NULL : &SectionType, + NULL, + (SectionType == 0) ? 0 : SectionInstance, + Buffer, + BufferSize, + AuthenticationStatus + ); + + // + // Close of stream defered to close of FfsHeader list to allow SEP to cache data + // + +Done: + CoreFreePool (FileBuffer); + + return Status; +} + diff --git a/EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c b/EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c new file mode 100644 index 0000000..1db7305 --- /dev/null +++ b/EDK/Foundation/Core/Dxe/FwVol/FwVolWrite.c @@ -0,0 +1,60 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. 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. + +Module Name: + + FwVolWrite.c + +Abstract: + + Implements write firmware file + +--*/ + +#include "FwVolDriver.h" + + +EFI_STATUS +EFIAPI +FvWriteFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData + ) +/*++ + + Routine Description: + Writes one or more files to the firmware volume. + + Arguments: + This - Indicates the calling context. + NumberOfFiles - Number of files. + 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. + FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA. + Each element of FileData[] represents a file to be written. + + Returns: + EFI_SUCCESS - Files successfully written to firmware volume + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + EFI_DEVICE_ERROR - Device error. + EFI_WRITE_PROTECTED - Write protected. + EFI_NOT_FOUND - Not found. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_UNSUPPORTED - This function not supported. + +--*/ +{ + return EFI_UNSUPPORTED; +} + -- cgit v1.2.3