mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10502 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1668 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1668 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
Copyright (c) 1999 - 2008, 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.
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  FirmwareVolumeBuffer.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  EFI Firmware Volume routines which work on a Fv image in buffers.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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
 | 
						|
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 = FvBufExpand3ByteSize (FileToRm->Size);
 | 
						|
 | 
						|
  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 = FvBufExpand3ByteSize (File->Size);
 | 
						|
 | 
						|
  //
 | 
						|
  // 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,
 | 
						|
      sizeof (EFI_FFS_FILE_HEADER)
 | 
						|
      );
 | 
						|
 | 
						|
  if (File->Attributes & FFS_ATTRIB_CHECKSUM) {
 | 
						|
    File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 (
 | 
						|
                                                (VOID*)(File + 1),
 | 
						|
                                                FileSize - sizeof (EFI_FFS_FILE_HEADER)
 | 
						|
                                                );
 | 
						|
  } 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 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 = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size);
 | 
						|
 | 
						|
  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 = FvBufExpand3ByteSize (fhdr->Size);
 | 
						|
      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 = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size);
 | 
						|
 | 
						|
  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 = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size);
 | 
						|
  } 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
 | 
						|
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 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 = FvBufExpand3ByteSize (fhdr->Size);
 | 
						|
 | 
						|
    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*)(File + 1);
 | 
						|
    *RawDataSize = FvBufExpand3ByteSize (File->Size) - sizeof (*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*)(Section + 1);
 | 
						|
  *RawDataSize =
 | 
						|
    FvBufExpand3ByteSize (Section->Size) - sizeof (*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;
 | 
						|
 | 
						|
  //
 | 
						|
  // The section size is the DataSize + the size of the section header
 | 
						|
  //
 | 
						|
  NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // The file size is the size of the file header + the section size
 | 
						|
  //
 | 
						|
  NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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*)(NewFile + 1);
 | 
						|
  FvBufCompact3ByteSize (NewSection->Size, NewSectionSize);
 | 
						|
  NewSection->Type = EFI_SECTION_RAW;
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the actual file data into the buffer
 | 
						|
  //
 | 
						|
  CommonLibBinderCopyMem (NewSection + 1, RawData, RawDataSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the FFS file header
 | 
						|
  //
 | 
						|
  CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID));
 | 
						|
  FvBufCompact3ByteSize (NewFile->Size, NewFileSize);
 | 
						|
  NewFile->Type = EFI_FV_FILETYPE_FREEFORM;
 | 
						|
  NewFile->Attributes = 0;
 | 
						|
  NewFile->IntegrityCheck.Checksum.Header =
 | 
						|
    FvBufCalculateChecksum8 ((UINT8*)NewFile, sizeof (*NewFile));
 | 
						|
  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 = FvBufExpand3ByteSize (sectionHdr->Size);
 | 
						|
 | 
						|
  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 + sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
  TotalSectionsSize =
 | 
						|
    FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)FfsFile)->Size) -
 | 
						|
    sizeof (EFI_FFS_FILE_HEADER);
 | 
						|
  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 + sizeof (EFI_FFS_FILE_HEADER));
 | 
						|
  TotalSectionsSize =
 | 
						|
    FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)FfsFile)->Size) -
 | 
						|
    sizeof (EFI_FFS_FILE_HEADER);
 | 
						|
  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 + FvBufExpand3ByteSize (FileIt->Size));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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));
 | 
						|
}
 | 
						|
 | 
						|
 |