| /** @file | |
| EFI Firmware Volume routines which work on a Fv image in buffers. | |
| Copyright (c) 1999 - 2015, 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 "FirmwareVolumeBufferLib.h" | |
| #include "BinderFuncs.h" | |
| // | |
| // Local macros | |
| // | |
| #define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \ | |
| ( \ | |
| (BOOLEAN) ( \ | |
| (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \ | |
| ) \ | |
| ) | |
| // | |
| // Local prototypes | |
| // | |
| STATIC | |
| UINT32 | |
| FvBufGetSecHdrLen( | |
| IN EFI_COMMON_SECTION_HEADER *SectionHeader | |
| ) | |
| { | |
| if (SectionHeader == NULL) { | |
| return 0; | |
| } | |
| if (FvBufExpand3ByteSize(SectionHeader->Size) == 0xffffff) { | |
| return sizeof(EFI_COMMON_SECTION_HEADER2); | |
| } | |
| return sizeof(EFI_COMMON_SECTION_HEADER); | |
| } | |
| STATIC | |
| UINT32 | |
| FvBufGetSecFileLen ( | |
| IN EFI_COMMON_SECTION_HEADER *SectionHeader | |
| ) | |
| { | |
| UINT32 Length; | |
| if (SectionHeader == NULL) { | |
| return 0; | |
| } | |
| Length = FvBufExpand3ByteSize(SectionHeader->Size); | |
| if (Length == 0xffffff) { | |
| Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize; | |
| } | |
| return Length; | |
| } | |
| // | |
| // Local prototypes | |
| // | |
| STATIC | |
| UINT16 | |
| FvBufCalculateChecksum16 ( | |
| IN UINT16 *Buffer, | |
| IN UINTN Size | |
| ); | |
| STATIC | |
| UINT8 | |
| FvBufCalculateChecksum8 ( | |
| IN UINT8 *Buffer, | |
| IN UINTN Size | |
| ); | |
| // | |
| // Procedures start | |
| // | |
| EFI_STATUS | |
| FvBufRemoveFileNew ( | |
| IN OUT VOID *Fv, | |
| IN EFI_GUID *Name | |
| ) | |
| /*++ | |
| Routine Description: | |
| Clears out all files from the Fv buffer in memory | |
| Arguments: | |
| SourceFv - Address of the Fv in memory, this firmware volume volume will | |
| be modified, if SourceFfsFile exists | |
| SourceFfsFile - Input FFS file to replace | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| EFI_FFS_FILE_HEADER* FileToRm; | |
| UINTN FileToRmLength; | |
| Status = FvBufFindFileByName( | |
| Fv, | |
| Name, | |
| (VOID **)&FileToRm | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| FileToRmLength = FvBufGetFfsFileSize (FileToRm); | |
| CommonLibBinderSetMem ( | |
| FileToRm, | |
| FileToRmLength, | |
| (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) | |
| ? 0xFF : 0 | |
| ); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufRemoveFile ( | |
| IN OUT VOID *Fv, | |
| IN EFI_GUID *Name | |
| ) | |
| /*++ | |
| Routine Description: | |
| Clears out all files from the Fv buffer in memory | |
| Arguments: | |
| SourceFv - Address of the Fv in memory, this firmware volume volume will | |
| be modified, if SourceFfsFile exists | |
| SourceFfsFile - Input FFS file to replace | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| EFI_FFS_FILE_HEADER *NextFile; | |
| EFI_FIRMWARE_VOLUME_HEADER *TempFv; | |
| UINTN FileKey; | |
| UINTN FvLength; | |
| Status = FvBufFindFileByName( | |
| Fv, | |
| Name, | |
| NULL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = FvBufGetSize (Fv, &FvLength); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| TempFv = NULL; | |
| Status = FvBufDuplicate (Fv, (VOID **)&TempFv); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = FvBufClearAllFiles (TempFv); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // TempFv has been allocated. It must now be freed | |
| // before returning. | |
| FileKey = 0; | |
| while (TRUE) { | |
| Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile); | |
| if (Status == EFI_NOT_FOUND) { | |
| break; | |
| } else if (EFI_ERROR (Status)) { | |
| CommonLibBinderFree (TempFv); | |
| return Status; | |
| } | |
| if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) { | |
| continue; | |
| } | |
| else { | |
| Status = FvBufAddFile (TempFv, NextFile); | |
| if (EFI_ERROR (Status)) { | |
| CommonLibBinderFree (TempFv); | |
| return Status; | |
| } | |
| } | |
| } | |
| CommonLibBinderCopyMem (Fv, TempFv, FvLength); | |
| CommonLibBinderFree (TempFv); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufChecksumFile ( | |
| IN OUT VOID *FfsFile | |
| ) | |
| /*++ | |
| Routine Description: | |
| Clears out all files from the Fv buffer in memory | |
| Arguments: | |
| SourceFfsFile - Input FFS file to update the checksum for | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| --*/ | |
| { | |
| EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile; | |
| EFI_FFS_FILE_STATE StateBackup; | |
| UINT32 FileSize; | |
| FileSize = FvBufGetFfsFileSize (File); | |
| // | |
| // Fill in checksums and state, they must be 0 for checksumming. | |
| // | |
| File->IntegrityCheck.Checksum.Header = 0; | |
| File->IntegrityCheck.Checksum.File = 0; | |
| StateBackup = File->State; | |
| File->State = 0; | |
| File->IntegrityCheck.Checksum.Header = | |
| FvBufCalculateChecksum8 ( | |
| (UINT8 *) File, | |
| FvBufGetFfsHeaderSize (File) | |
| ); | |
| if (File->Attributes & FFS_ATTRIB_CHECKSUM) { | |
| File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 ( | |
| (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)), | |
| FileSize - FvBufGetFfsHeaderSize (File) | |
| ); | |
| } else { | |
| File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; | |
| } | |
| File->State = StateBackup; | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufChecksumHeader ( | |
| IN OUT VOID *Fv | |
| ) | |
| /*++ | |
| Routine Description: | |
| Clears out all files from the Fv buffer in memory | |
| Arguments: | |
| SourceFv - Address of the Fv in memory, this firmware volume volume will | |
| be modified, if SourceFfsFile exists | |
| SourceFfsFile - Input FFS file to replace | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| --*/ | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| FvHeader->Checksum = 0; | |
| FvHeader->Checksum = | |
| FvBufCalculateChecksum16 ( | |
| (UINT16*) FvHeader, | |
| FvHeader->HeaderLength / sizeof (UINT16) | |
| ); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufDuplicate ( | |
| IN VOID *SourceFv, | |
| IN OUT VOID **DestinationFv | |
| ) | |
| /*++ | |
| Routine Description: | |
| Clears out all files from the Fv buffer in memory | |
| Arguments: | |
| SourceFv - Address of the Fv in memory | |
| DestinationFv - Output for destination Fv | |
| DestinationFv == NULL - invalid parameter | |
| *DestinationFv == NULL - memory will be allocated | |
| *DestinationFv != NULL - this address will be the destination | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN size; | |
| if (DestinationFv == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Status = FvBufGetSize (SourceFv, &size); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (*DestinationFv == NULL) { | |
| *DestinationFv = CommonLibBinderAllocate (size); | |
| } | |
| CommonLibBinderCopyMem (*DestinationFv, SourceFv, size); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufExtend ( | |
| IN VOID **Fv, | |
| IN UINTN Size | |
| ) | |
| /*++ | |
| Routine Description: | |
| Extends a firmware volume by the given number of bytes. | |
| BUGBUG: Does not handle the case where the firmware volume has a | |
| VTF (Volume Top File). The VTF will not be moved to the | |
| end of the extended FV. | |
| Arguments: | |
| Fv - Source and destination firmware volume. | |
| Note: The original firmware volume buffer is freed! | |
| Size - The minimum size that the firmware volume is to be extended by. | |
| The FV may be extended more than this size. | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN OldSize; | |
| UINTN NewSize; | |
| UINTN BlockCount; | |
| VOID* NewFv; | |
| EFI_FIRMWARE_VOLUME_HEADER* hdr; | |
| EFI_FV_BLOCK_MAP_ENTRY* blk; | |
| Status = FvBufGetSize (*Fv, &OldSize); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Locate the block map in the fv header | |
| // | |
| hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv; | |
| blk = hdr->BlockMap; | |
| // | |
| // Calculate the number of blocks needed to achieve the requested | |
| // size extension | |
| // | |
| BlockCount = ((Size + (blk->Length - 1)) / blk->Length); | |
| // | |
| // Calculate the new size from the number of blocks that will be added | |
| // | |
| NewSize = OldSize + (BlockCount * blk->Length); | |
| NewFv = CommonLibBinderAllocate (NewSize); | |
| if (NewFv == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Copy the old data | |
| // | |
| CommonLibBinderCopyMem (NewFv, *Fv, OldSize); | |
| // | |
| // Free the old fv buffer | |
| // | |
| CommonLibBinderFree (*Fv); | |
| // | |
| // Locate the block map in the new fv header | |
| // | |
| hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv; | |
| hdr->FvLength = NewSize; | |
| blk = hdr->BlockMap; | |
| // | |
| // Update the block map for the new fv | |
| // | |
| blk->NumBlocks += (UINT32)BlockCount; | |
| // | |
| // Update the FV header checksum | |
| // | |
| FvBufChecksumHeader (NewFv); | |
| // | |
| // Clear out the new area of the FV | |
| // | |
| CommonLibBinderSetMem ( | |
| (UINT8*)NewFv + OldSize, | |
| (NewSize - OldSize), | |
| (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0 | |
| ); | |
| // | |
| // Set output with new fv that was created | |
| // | |
| *Fv = NewFv; | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufClearAllFiles ( | |
| IN OUT VOID *Fv | |
| ) | |
| /*++ | |
| Routine Description: | |
| Clears out all files from the Fv buffer in memory | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| EFI_STATUS Status; | |
| UINTN size = 0; | |
| Status = FvBufGetSize (Fv, &size); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| CommonLibBinderSetMem( | |
| (UINT8*)hdr + hdr->HeaderLength, | |
| size - hdr->HeaderLength, | |
| (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0 | |
| ); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufGetSize ( | |
| IN VOID *Fv, | |
| OUT UINTN *Size | |
| ) | |
| /*++ | |
| Routine Description: | |
| Clears out all files from the Fv buffer in memory | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap; | |
| *Size = 0; | |
| while (blk->Length != 0 || blk->NumBlocks != 0) { | |
| *Size = *Size + (blk->Length * blk->NumBlocks); | |
| if (*Size >= 0x40000000) { | |
| // If size is greater than 1GB, then assume it is corrupted | |
| return EFI_VOLUME_CORRUPTED; | |
| } | |
| blk++; | |
| } | |
| if (*Size == 0) { | |
| // If size is 0, then assume the volume is corrupted | |
| return EFI_VOLUME_CORRUPTED; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufAddFile ( | |
| IN OUT VOID *Fv, | |
| IN VOID *File | |
| ) | |
| /*++ | |
| Routine Description: | |
| Adds a new FFS file | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| File - FFS file to add to Fv | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| EFI_FFS_FILE_HEADER *fhdr = NULL; | |
| EFI_FVB_ATTRIBUTES_2 FvbAttributes; | |
| UINTN offset; | |
| UINTN fsize; | |
| UINTN newSize; | |
| UINTN clearLoop; | |
| EFI_STATUS Status; | |
| UINTN fvSize; | |
| Status = FvBufGetSize (Fv, &fvSize); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| FvbAttributes = hdr->Attributes; | |
| newSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File); | |
| for( | |
| offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8); | |
| offset + newSize <= fvSize; | |
| offset = (UINTN)ALIGN_POINTER (offset, 8) | |
| ) { | |
| fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset); | |
| if (EFI_TEST_FFS_ATTRIBUTES_BIT( | |
| FvbAttributes, | |
| fhdr->State, | |
| EFI_FILE_HEADER_VALID | |
| ) | |
| ) { | |
| // BUGBUG: Need to make sure that the new file does not already | |
| // exist. | |
| fsize = FvBufGetFfsFileSize (fhdr); | |
| if (fsize == 0 || (offset + fsize > fvSize)) { | |
| return EFI_VOLUME_CORRUPTED; | |
| } | |
| offset = offset + fsize; | |
| continue; | |
| } | |
| clearLoop = 0; | |
| while ((clearLoop < newSize) && | |
| (((UINT8*)fhdr)[clearLoop] == | |
| (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0) | |
| ) | |
| ) { | |
| clearLoop++; | |
| } | |
| // | |
| // We found a place in the FV which is empty and big enough for | |
| // the new file | |
| // | |
| if (clearLoop >= newSize) { | |
| break; | |
| } | |
| offset = offset + 1; // Make some forward progress | |
| } | |
| if (offset + newSize > fvSize) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| CommonLibBinderCopyMem (fhdr, File, newSize); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufAddFileWithExtend ( | |
| IN OUT VOID **Fv, | |
| IN VOID *File | |
| ) | |
| /*++ | |
| Routine Description: | |
| Adds a new FFS file. Extends the firmware volume if needed. | |
| Arguments: | |
| Fv - Source and destination firmware volume. | |
| Note: If the FV is extended, then the original firmware volume | |
| buffer is freed! | |
| Size - The minimum size that the firmware volume is to be extended by. | |
| The FV may be extended more than this size. | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| EFI_FFS_FILE_HEADER* NewFile; | |
| NewFile = (EFI_FFS_FILE_HEADER*)File; | |
| // | |
| // Try to add to the capsule volume | |
| // | |
| Status = FvBufAddFile (*Fv, NewFile); | |
| if (Status == EFI_OUT_OF_RESOURCES) { | |
| // | |
| // Try to extend the capsule volume by the size of the file | |
| // | |
| Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size)); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Now, try to add the file again | |
| // | |
| Status = FvBufAddFile (*Fv, NewFile); | |
| } | |
| return Status; | |
| } | |
| EFI_STATUS | |
| FvBufAddVtfFile ( | |
| IN OUT VOID *Fv, | |
| IN VOID *File | |
| ) | |
| /*++ | |
| Routine Description: | |
| Adds a new FFS VFT (Volume Top File) file. In other words, adds the | |
| file to the end of the firmware volume. | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| File - FFS file to add to Fv | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| EFI_FFS_FILE_HEADER* NewFile; | |
| UINTN NewFileSize; | |
| UINT8 erasedUint8; | |
| UINTN clearLoop; | |
| EFI_FFS_FILE_HEADER *LastFile; | |
| UINTN LastFileSize; | |
| UINTN fvSize; | |
| UINTN Key; | |
| Status = FvBufGetSize (Fv, &fvSize); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0); | |
| NewFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File); | |
| if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| // | |
| // Find the last file in the FV | |
| // | |
| Key = 0; | |
| LastFile = NULL; | |
| LastFileSize = 0; | |
| do { | |
| Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile); | |
| LastFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File); | |
| } while (!EFI_ERROR (Status)); | |
| // | |
| // If no files were found, then we start at the beginning of the FV | |
| // | |
| if (LastFile == NULL) { | |
| LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength); | |
| } | |
| // | |
| // We want to put the new file (VTF) at the end of the FV | |
| // | |
| NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize)); | |
| // | |
| // Check to see if there is enough room for the VTF after the last file | |
| // found in the FV | |
| // | |
| if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Loop to determine if the end of the FV is empty | |
| // | |
| clearLoop = 0; | |
| while ((clearLoop < NewFileSize) && | |
| (((UINT8*)NewFile)[clearLoop] == erasedUint8) | |
| ) { | |
| clearLoop++; | |
| } | |
| // | |
| // Check to see if there was not enough room for the file | |
| // | |
| if (clearLoop < NewFileSize) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| CommonLibBinderCopyMem (NewFile, File, NewFileSize); | |
| return EFI_SUCCESS; | |
| } | |
| VOID | |
| FvBufCompact3ByteSize ( | |
| OUT VOID* SizeDest, | |
| IN UINT32 Size | |
| ) | |
| /*++ | |
| Routine Description: | |
| Expands the 3 byte size commonly used in Firmware Volume data structures | |
| Arguments: | |
| Size - Address of the 3 byte array representing the size | |
| Returns: | |
| UINT32 | |
| --*/ | |
| { | |
| ((UINT8*)SizeDest)[0] = (UINT8)Size; | |
| ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8); | |
| ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16); | |
| } | |
| UINT32 | |
| FvBufGetFfsFileSize ( | |
| IN EFI_FFS_FILE_HEADER *Ffs | |
| ) | |
| /*++ | |
| Routine Description: | |
| Get the FFS file size. | |
| Arguments: | |
| Ffs - Pointer to FFS header | |
| Returns: | |
| UINT32 | |
| --*/ | |
| { | |
| if (Ffs == NULL) { | |
| return 0; | |
| } | |
| if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) { | |
| return (UINT32) ((EFI_FFS_FILE_HEADER2 *)Ffs)->ExtendedSize; | |
| } | |
| return FvBufExpand3ByteSize(Ffs->Size); | |
| } | |
| UINT32 | |
| FvBufGetFfsHeaderSize ( | |
| IN EFI_FFS_FILE_HEADER *Ffs | |
| ) | |
| /*++ | |
| Routine Description: | |
| Get the FFS header size. | |
| Arguments: | |
| Ffs - Pointer to FFS header | |
| Returns: | |
| UINT32 | |
| --*/ | |
| { | |
| if (Ffs == NULL) { | |
| return 0; | |
| } | |
| if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) { | |
| return sizeof(EFI_FFS_FILE_HEADER2); | |
| } | |
| return sizeof(EFI_FFS_FILE_HEADER); | |
| } | |
| UINT32 | |
| FvBufExpand3ByteSize ( | |
| IN VOID* Size | |
| ) | |
| /*++ | |
| Routine Description: | |
| Expands the 3 byte size commonly used in Firmware Volume data structures | |
| Arguments: | |
| Size - Address of the 3 byte array representing the size | |
| Returns: | |
| UINT32 | |
| --*/ | |
| { | |
| return (((UINT8*)Size)[2] << 16) + | |
| (((UINT8*)Size)[1] << 8) + | |
| ((UINT8*)Size)[0]; | |
| } | |
| EFI_STATUS | |
| FvBufFindNextFile ( | |
| IN VOID *Fv, | |
| IN OUT UINTN *Key, | |
| OUT VOID **File | |
| ) | |
| /*++ | |
| Routine Description: | |
| Iterates through the files contained within the firmware volume | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| Key - Should be 0 to get the first file. After that, it should be | |
| passed back in without modifying it's contents to retrieve | |
| subsequent files. | |
| File - Output file pointer | |
| File == NULL - invalid parameter | |
| otherwise - *File will be update to the location of the file | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| EFI_VOLUME_CORRUPTED | |
| --*/ | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| EFI_FFS_FILE_HEADER *fhdr = NULL; | |
| EFI_FVB_ATTRIBUTES_2 FvbAttributes; | |
| UINTN fsize; | |
| EFI_STATUS Status; | |
| UINTN fvSize; | |
| if (Fv == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Status = FvBufGetSize (Fv, &fvSize); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (*Key == 0) { | |
| *Key = hdr->HeaderLength; | |
| } | |
| FvbAttributes = hdr->Attributes; | |
| for( | |
| *Key = (UINTN)ALIGN_POINTER (*Key, 8); | |
| (*Key + sizeof (*fhdr)) < fvSize; | |
| *Key = (UINTN)ALIGN_POINTER (*Key, 8) | |
| ) { | |
| fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key); | |
| fsize = FvBufGetFfsFileSize (fhdr); | |
| if (!EFI_TEST_FFS_ATTRIBUTES_BIT( | |
| FvbAttributes, | |
| fhdr->State, | |
| EFI_FILE_HEADER_VALID | |
| ) || | |
| EFI_TEST_FFS_ATTRIBUTES_BIT( | |
| FvbAttributes, | |
| fhdr->State, | |
| EFI_FILE_HEADER_INVALID | |
| ) | |
| ) { | |
| *Key = *Key + 1; // Make some forward progress | |
| continue; | |
| } else if( | |
| EFI_TEST_FFS_ATTRIBUTES_BIT( | |
| FvbAttributes, | |
| fhdr->State, | |
| EFI_FILE_MARKED_FOR_UPDATE | |
| ) || | |
| EFI_TEST_FFS_ATTRIBUTES_BIT( | |
| FvbAttributes, | |
| fhdr->State, | |
| EFI_FILE_DELETED | |
| ) | |
| ) { | |
| *Key = *Key + fsize; | |
| continue; | |
| } else if (EFI_TEST_FFS_ATTRIBUTES_BIT( | |
| FvbAttributes, | |
| fhdr->State, | |
| EFI_FILE_DATA_VALID | |
| ) | |
| ) { | |
| *File = (UINT8*)hdr + *Key; | |
| *Key = *Key + fsize; | |
| return EFI_SUCCESS; | |
| } | |
| *Key = *Key + 1; // Make some forward progress | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| FvBufFindFileByName ( | |
| IN VOID *Fv, | |
| IN EFI_GUID *Name, | |
| OUT VOID **File | |
| ) | |
| /*++ | |
| Routine Description: | |
| Searches the Fv for a file by its name | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| Name - Guid filename to search for in the firmware volume | |
| File - Output file pointer | |
| File == NULL - Only determine if the file exists, based on return | |
| value from the function call. | |
| otherwise - *File will be update to the location of the file | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| EFI_VOLUME_CORRUPTED | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN Key; | |
| EFI_FFS_FILE_HEADER *NextFile; | |
| Key = 0; | |
| while (TRUE) { | |
| Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) { | |
| if (File != NULL) { | |
| *File = NextFile; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| FvBufFindFileByType ( | |
| IN VOID *Fv, | |
| IN EFI_FV_FILETYPE Type, | |
| OUT VOID **File | |
| ) | |
| /*++ | |
| Routine Description: | |
| Searches the Fv for a file by its type | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| Type - FFS FILE type to search for | |
| File - Output file pointer | |
| (File == NULL) -> Only determine if the file exists, based on return | |
| value from the function call. | |
| otherwise -> *File will be update to the location of the file | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| EFI_VOLUME_CORRUPTED | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN Key; | |
| EFI_FFS_FILE_HEADER *NextFile; | |
| Key = 0; | |
| while (TRUE) { | |
| Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (Type == NextFile->Type) { | |
| if (File != NULL) { | |
| *File = NextFile; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| FvBufGetFileRawData ( | |
| IN VOID* FfsFile, | |
| OUT VOID** RawData, | |
| OUT UINTN* RawDataSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| Searches the requested file for raw data. | |
| This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file, | |
| or finds the EFI_SECTION_RAW section within the file and returns its data. | |
| Arguments: | |
| FfsFile - Address of the FFS file in memory | |
| RawData - Pointer to the raw data within the file | |
| (This is NOT allocated. It is within the file.) | |
| RawDataSize - Size of the raw data within the file | |
| Returns: | |
| EFI_STATUS | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| EFI_FFS_FILE_HEADER* File; | |
| EFI_RAW_SECTION* Section; | |
| File = (EFI_FFS_FILE_HEADER*)FfsFile; | |
| // | |
| // Is the file type == EFI_FV_FILETYPE_RAW? | |
| // | |
| if (File->Type == EFI_FV_FILETYPE_RAW) { | |
| // | |
| // Raw filetypes don't have sections, so we just return the raw data | |
| // | |
| *RawData = (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)); | |
| *RawDataSize = FvBufGetFfsFileSize (File) - FvBufGetFfsHeaderSize (File); | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // Within the file, we now need to find the EFI_SECTION_RAW section. | |
| // | |
| Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| *RawData = (VOID*)((UINT8 *)Section + FvBufGetSecHdrLen(Section)); | |
| *RawDataSize = | |
| FvBufGetSecFileLen (Section) - FvBufGetSecHdrLen(Section); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufPackageFreeformRawFile ( | |
| IN EFI_GUID* Filename, | |
| IN VOID* RawData, | |
| IN UINTN RawDataSize, | |
| OUT VOID** FfsFile | |
| ) | |
| /*++ | |
| Routine Description: | |
| Packages up a FFS file containing the input raw data. | |
| The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will | |
| contain one EFI_FV_FILETYPE_RAW section. | |
| Arguments: | |
| RawData - Pointer to the raw data to be packed | |
| RawDataSize - Size of the raw data to be packed | |
| FfsFile - Address of the packaged FFS file. | |
| Note: The called must deallocate this memory! | |
| Returns: | |
| EFI_STATUS | |
| --*/ | |
| { | |
| EFI_FFS_FILE_HEADER* NewFile; | |
| UINT32 NewFileSize; | |
| EFI_RAW_SECTION* NewSection; | |
| UINT32 NewSectionSize; | |
| UINT32 FfsHdrLen; | |
| UINT32 SecHdrLen; | |
| // | |
| // The section size is the DataSize + the size of the section header | |
| // | |
| NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize; | |
| SecHdrLen = sizeof (EFI_RAW_SECTION); | |
| if (NewSectionSize >= MAX_SECTION_SIZE) { | |
| NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION2) + (UINT32)RawDataSize; | |
| SecHdrLen = sizeof (EFI_RAW_SECTION2); | |
| } | |
| // | |
| // The file size is the size of the file header + the section size | |
| // | |
| NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize; | |
| FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER); | |
| if (NewFileSize >= MAX_FFS_SIZE) { | |
| NewFileSize = sizeof (EFI_FFS_FILE_HEADER2) + NewSectionSize; | |
| FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER2); | |
| } | |
| // | |
| // Try to allocate a buffer to build the new FFS file in | |
| // | |
| NewFile = CommonLibBinderAllocate (NewFileSize); | |
| if (NewFile == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| CommonLibBinderSetMem (NewFile, NewFileSize, 0); | |
| // | |
| // The NewSection follow right after the FFS file header | |
| // | |
| NewSection = (EFI_RAW_SECTION*)((UINT8*)NewFile + FfsHdrLen); | |
| if (NewSectionSize >= MAX_SECTION_SIZE) { | |
| FvBufCompact3ByteSize (NewSection->Size, 0xffffff); | |
| ((EFI_RAW_SECTION2 *)NewSection)->ExtendedSize = NewSectionSize; | |
| } else { | |
| FvBufCompact3ByteSize (NewSection->Size, NewSectionSize); | |
| } | |
| NewSection->Type = EFI_SECTION_RAW; | |
| // | |
| // Copy the actual file data into the buffer | |
| // | |
| CommonLibBinderCopyMem ((UINT8 *)NewSection + SecHdrLen, RawData, RawDataSize); | |
| // | |
| // Initialize the FFS file header | |
| // | |
| CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID)); | |
| NewFile->Attributes = 0; | |
| if (NewFileSize >= MAX_FFS_SIZE) { | |
| FvBufCompact3ByteSize (NewFile->Size, 0x0); | |
| ((EFI_FFS_FILE_HEADER2 *)NewFile)->ExtendedSize = NewFileSize; | |
| NewFile->Attributes |= FFS_ATTRIB_LARGE_FILE; | |
| } else { | |
| FvBufCompact3ByteSize (NewFile->Size, NewFileSize); | |
| } | |
| NewFile->Type = EFI_FV_FILETYPE_FREEFORM; | |
| NewFile->IntegrityCheck.Checksum.Header = | |
| FvBufCalculateChecksum8 ((UINT8*)NewFile, FfsHdrLen); | |
| NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; | |
| NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION | | |
| EFI_FILE_HEADER_VALID | | |
| EFI_FILE_DATA_VALID | |
| ); | |
| *FfsFile = NewFile; | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufFindNextSection ( | |
| IN VOID *SectionsStart, | |
| IN UINTN TotalSectionsSize, | |
| IN OUT UINTN *Key, | |
| OUT VOID **Section | |
| ) | |
| /*++ | |
| Routine Description: | |
| Iterates through the sections contained within a given array of sections | |
| Arguments: | |
| SectionsStart - Address of the start of the FFS sections array | |
| TotalSectionsSize - Total size of all the sections | |
| Key - Should be 0 to get the first section. After that, it should be | |
| passed back in without modifying it's contents to retrieve | |
| subsequent files. | |
| Section - Output section pointer | |
| (Section == NULL) -> invalid parameter | |
| otherwise -> *Section will be update to the location of the file | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| EFI_VOLUME_CORRUPTED | |
| --*/ | |
| { | |
| EFI_COMMON_SECTION_HEADER *sectionHdr; | |
| UINTN sectionSize; | |
| *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned | |
| if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) { | |
| return EFI_NOT_FOUND; | |
| } | |
| sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key); | |
| sectionSize = FvBufGetSecFileLen (sectionHdr); | |
| if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) { | |
| return EFI_NOT_FOUND; | |
| } | |
| if ((*Key + sectionSize) > TotalSectionsSize) { | |
| return EFI_NOT_FOUND; | |
| } | |
| *Section = (UINT8*)sectionHdr; | |
| *Key = *Key + sectionSize; | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufCountSections ( | |
| IN VOID* FfsFile, | |
| IN UINTN* Count | |
| ) | |
| /*++ | |
| Routine Description: | |
| Searches the FFS file and counts the number of sections found. | |
| The sections are NOT recursed. | |
| Arguments: | |
| FfsFile - Address of the FFS file in memory | |
| Count - The location to store the section count in | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| EFI_VOLUME_CORRUPTED | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN Key; | |
| VOID* SectionStart; | |
| UINTN TotalSectionsSize; | |
| EFI_COMMON_SECTION_HEADER* NextSection; | |
| SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile)); | |
| TotalSectionsSize = | |
| FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) - | |
| FvBufGetFfsHeaderSize(FfsFile); | |
| Key = 0; | |
| *Count = 0; | |
| while (TRUE) { | |
| Status = FvBufFindNextSection ( | |
| SectionStart, | |
| TotalSectionsSize, | |
| &Key, | |
| (VOID **)&NextSection | |
| ); | |
| if (Status == EFI_NOT_FOUND) { | |
| return EFI_SUCCESS; | |
| } else if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Increment the section counter | |
| // | |
| *Count += 1; | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| FvBufFindSectionByType ( | |
| IN VOID *FfsFile, | |
| IN UINT8 Type, | |
| OUT VOID **Section | |
| ) | |
| /*++ | |
| Routine Description: | |
| Searches the FFS file for a section by its type | |
| Arguments: | |
| FfsFile - Address of the FFS file in memory | |
| Type - FFS FILE section type to search for | |
| Section - Output section pointer | |
| (Section == NULL) -> Only determine if the section exists, based on return | |
| value from the function call. | |
| otherwise -> *Section will be update to the location of the file | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| EFI_VOLUME_CORRUPTED | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN Key; | |
| VOID* SectionStart; | |
| UINTN TotalSectionsSize; | |
| EFI_COMMON_SECTION_HEADER* NextSection; | |
| SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile)); | |
| TotalSectionsSize = | |
| FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) - | |
| FvBufGetFfsHeaderSize(FfsFile); | |
| Key = 0; | |
| while (TRUE) { | |
| Status = FvBufFindNextSection ( | |
| SectionStart, | |
| TotalSectionsSize, | |
| &Key, | |
| (VOID **)&NextSection | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| if (Type == NextSection->Type) { | |
| if (Section != NULL) { | |
| *Section = NextSection; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| FvBufShrinkWrap ( | |
| IN VOID *Fv | |
| ) | |
| /*++ | |
| Routine Description: | |
| Shrinks a firmware volume (in place) to provide a minimal FV. | |
| BUGBUG: Does not handle the case where the firmware volume has a | |
| VTF (Volume Top File). The VTF will not be moved to the | |
| end of the extended FV. | |
| Arguments: | |
| Fv - Firmware volume. | |
| Returns: | |
| EFI_SUCCESS | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN OldSize; | |
| UINT32 BlockCount; | |
| UINT32 NewBlockSize = 128; | |
| UINTN Key; | |
| EFI_FFS_FILE_HEADER* FileIt; | |
| VOID* EndOfLastFile; | |
| EFI_FIRMWARE_VOLUME_HEADER* FvHdr; | |
| Status = FvBufGetSize (Fv, &OldSize); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| Status = FvBufUnifyBlockSizes (Fv, NewBlockSize); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| // | |
| // Locate the block map in the fv header | |
| // | |
| FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| // | |
| // Find the end of the last file | |
| // | |
| Key = 0; | |
| EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength; | |
| while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) { | |
| EndOfLastFile = | |
| (VOID*)((UINT8*)FileIt + FvBufGetFfsFileSize (FileIt)); | |
| } | |
| // | |
| // Set the BlockCount to have the minimal number of blocks for the Fv. | |
| // | |
| BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv); | |
| BlockCount = BlockCount + NewBlockSize - 1; | |
| BlockCount = BlockCount / NewBlockSize; | |
| // | |
| // Adjust the block count to shrink the Fv in place. | |
| // | |
| FvHdr->BlockMap[0].NumBlocks = BlockCount; | |
| FvHdr->FvLength = BlockCount * NewBlockSize; | |
| // | |
| // Update the FV header checksum | |
| // | |
| FvBufChecksumHeader (Fv); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FvBufUnifyBlockSizes ( | |
| IN OUT VOID *Fv, | |
| IN UINTN BlockSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| Searches the FFS file for a section by its type | |
| Arguments: | |
| Fv - Address of the Fv in memory | |
| BlockSize - The size of the blocks to convert the Fv to. If the total size | |
| of the Fv is not evenly divisible by this size, then | |
| EFI_INVALID_PARAMETER will be returned. | |
| Returns: | |
| EFI_SUCCESS | |
| EFI_NOT_FOUND | |
| EFI_VOLUME_CORRUPTED | |
| --*/ | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; | |
| EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap; | |
| UINT32 Size; | |
| Size = 0; | |
| // | |
| // Scan through the block map list, performing error checking, and adding | |
| // up the total Fv size. | |
| // | |
| while( blk->Length != 0 || | |
| blk->NumBlocks != 0 | |
| ) { | |
| Size = Size + (blk->Length * blk->NumBlocks); | |
| blk++; | |
| if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) { | |
| return EFI_VOLUME_CORRUPTED; | |
| } | |
| } | |
| // | |
| // Make sure that the Fv size is a multiple of the new block size. | |
| // | |
| if ((Size % BlockSize) != 0) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| // | |
| // Zero out the entire block map. | |
| // | |
| CommonLibBinderSetMem ( | |
| &hdr->BlockMap, | |
| (UINTN)blk - (UINTN)&hdr->BlockMap, | |
| 0 | |
| ); | |
| // | |
| // Write out the single block map entry. | |
| // | |
| hdr->BlockMap[0].Length = (UINT32)BlockSize; | |
| hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize; | |
| return EFI_SUCCESS; | |
| } | |
| STATIC | |
| UINT16 | |
| FvBufCalculateSum16 ( | |
| IN UINT16 *Buffer, | |
| IN UINTN Size | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function calculates the UINT16 sum for the requested region. | |
| Arguments: | |
| Buffer Pointer to buffer containing byte data of component. | |
| Size Size of the buffer | |
| Returns: | |
| The 16 bit checksum | |
| --*/ | |
| { | |
| UINTN Index; | |
| UINT16 Sum; | |
| Sum = 0; | |
| // | |
| // Perform the word sum for buffer | |
| // | |
| for (Index = 0; Index < Size; Index++) { | |
| Sum = (UINT16) (Sum + Buffer[Index]); | |
| } | |
| return (UINT16) Sum; | |
| } | |
| STATIC | |
| UINT16 | |
| FvBufCalculateChecksum16 ( | |
| IN UINT16 *Buffer, | |
| IN UINTN Size | |
| ) | |
| /*++ | |
| Routine Description:: | |
| This function calculates the value needed for a valid UINT16 checksum | |
| Arguments: | |
| Buffer Pointer to buffer containing byte data of component. | |
| Size Size of the buffer | |
| Returns: | |
| The 16 bit checksum value needed. | |
| --*/ | |
| { | |
| return (UINT16)(0x10000 - FvBufCalculateSum16 (Buffer, Size)); | |
| } | |
| STATIC | |
| UINT8 | |
| FvBufCalculateSum8 ( | |
| IN UINT8 *Buffer, | |
| IN UINTN Size | |
| ) | |
| /*++ | |
| Description: | |
| This function calculates the UINT8 sum for the requested region. | |
| Input: | |
| Buffer Pointer to buffer containing byte data of component. | |
| Size Size of the buffer | |
| Return: | |
| The 8 bit checksum value needed. | |
| --*/ | |
| { | |
| UINTN Index; | |
| UINT8 Sum; | |
| Sum = 0; | |
| // | |
| // Perform the byte sum for buffer | |
| // | |
| for (Index = 0; Index < Size; Index++) { | |
| Sum = (UINT8) (Sum + Buffer[Index]); | |
| } | |
| return Sum; | |
| } | |
| STATIC | |
| UINT8 | |
| FvBufCalculateChecksum8 ( | |
| IN UINT8 *Buffer, | |
| IN UINTN Size | |
| ) | |
| /*++ | |
| Description: | |
| This function calculates the value needed for a valid UINT8 checksum | |
| Input: | |
| Buffer Pointer to buffer containing byte data of component. | |
| Size Size of the buffer | |
| Return: | |
| The 8 bit checksum value needed. | |
| --*/ | |
| { | |
| return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size)); | |
| } | |