genfvimagelib.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,197 行 · 第 1/5 页

C
2,197
字号

      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
    } else {
      printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);
    }

    Index++;
    //
    // Read component FV_EVENT_LOG
    //
    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);

    if (Status == EFI_SUCCESS) {
      //
      // Add the component
      //
      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
      if (EFI_ERROR (Status)) {
        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);
        return EFI_ABORTED;
      }

      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
    } else {
      printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);
    }

    Index++;
    //
    // Read component FV_FTW_WORKING
    //
    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);

    if (Status == EFI_SUCCESS) {
      //
      // Add the component
      //
      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
      if (EFI_ERROR (Status)) {
        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);
        return EFI_ABORTED;
      }

      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
    } else {
      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);
    }

    Index++;
    //
    // Read component FV_FTW_SPARE
    //
    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);

    if (Status == EFI_SUCCESS) {
      //
      // Add the component
      //
      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);
      Status = AsciiStringToUint64 (Value, FALSE, &Value64);
      if (EFI_ERROR (Status)) {
        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);
        return EFI_ABORTED;
      }

      FvInfo->FvComponents[Index].Size = (UINTN) Value64;
    } else {
      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);
    }
  }
  //
  // Compute size for easy access later
  //
  FvInfo->Size = 0;
  for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {
    FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;
  }

  return EFI_SUCCESS;
}

VOID
UpdateFfsFileState (
  IN EFI_FFS_FILE_HEADER          *FfsFile,
  IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader
  )
/*++

Routine Description:

  This function changes the FFS file attributes based on the erase polarity
  of the FV.

Arguments:

  FfsFile   File header.
  FvHeader  FV header.

Returns:

  None

--*/
{
  if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
    FfsFile->State = (UINT8)~(FfsFile->State);
  }
}

EFI_STATUS
ReadFfsAlignment (
  IN EFI_FFS_FILE_HEADER    *FfsFile,
  IN OUT UINT32             *Alignment
  )
/*++

Routine Description:

  This function determines the alignment of the FFS input file from the file
  attributes.

Arguments:

  FfsFile       FFS file to parse
  Alignment     The minimum required alignment of the FFS file, in bytes

Returns:

  EFI_SUCCESS              The function completed successfully.
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
  EFI_ABORTED              An error occurred.

--*/
{
  //
  // Verify input parameters.
  //
  if (FfsFile == NULL || Alignment == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  switch ((FfsFile->Attributes >> 3) & 0x07) {

  case 0:
    //
    // 1 byte alignment
    //
    *Alignment = (1 << 0);
    break;

  case 1:
    //
    // 16 byte alignment
    //
    *Alignment = (1 << 4);
    break;

  case 2:
    //
    // 128 byte alignment
    //
    *Alignment = (1 << 7);
    break;

  case 3:
    //
    // 512 byte alignment
    //
    *Alignment = (1 << 9);
    break;

  case 4:
    //
    // 1K byte alignment
    //
    *Alignment = (1 << 10);
    break;

  case 5:
    //
    // 4K byte alignment
    //
    *Alignment = (1 << 12);
    break;

  case 6:
    //
    // 32K byte alignment
    //
    *Alignment = (1 << 15);
    break;

  case 7:
    //
    // 64K byte alignment
    //
    *Alignment = (1 << 16);
    break;

  default:
    Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);
    return EFI_ABORTED;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
AddPadFile (
  IN OUT MEMORY_FILE  *FvImage,
  IN UINT32           DataAlignment
  )
/*++

Routine Description:

  This function adds a pad file to the FV image if it required to align the
  data of the next file.

Arguments:

  FvImage         The memory image of the FV to add it to.  The current offset
                  must be valid.
  DataAlignment   The data alignment of the next FFS file.

Returns:

  EFI_SUCCESS              The function completed successfully.
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
  EFI_OUT_OF_RESOURCES     Insufficient resources exist in the FV to complete
                           the pad file add.

--*/
{
  EFI_FFS_FILE_HEADER *PadFile;
  UUID                PadFileGuid;
  UINTN               PadFileSize;

  //
  // Verify input parameters.
  //
  if (FvImage == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Basic assumption is we start from an 8 byte aligned address
  // and our file header is a multiple of 8 bytes
  //
  assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);
  assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);

  //
  // Check if a pad file is necessary
  //
  if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {
    return EFI_SUCCESS;
  }
  //
  // Write pad file header
  //
  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;

  //
  // Verify that we have enough space for the file header
  //
  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
    return EFI_OUT_OF_RESOURCES;
  }

  UuidCreate (&PadFileGuid);
  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
  memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));
  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;
  PadFile->Attributes = 0;

  //
  // Calculate the pad file size
  //
  //
  // This is the earliest possible valid offset (current plus pad file header
  // plus the next file header)
  //
  PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);

  //
  // Add whatever it takes to get to the next aligned address
  //
  while ((PadFileSize % DataAlignment) != 0) {
    PadFileSize++;
  }
  //
  // Subtract the next file header size
  //
  PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);

  //
  // Subtract the starting offset to get size
  //
  PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;

  //
  // Write pad file size (calculated size minus next file header size)
  //
  PadFile->Size[0]  = (UINT8) (PadFileSize & 0xFF);
  PadFile->Size[1]  = (UINT8) ((PadFileSize >> 8) & 0xFF);
  PadFile->Size[2]  = (UINT8) ((PadFileSize >> 16) & 0xFF);

  //
  // Fill in checksums and state, they must be 0 for checksumming.
  //
  PadFile->IntegrityCheck.Checksum.Header = 0;
  PadFile->IntegrityCheck.Checksum.File   = 0;
  PadFile->State                          = 0;
  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
  if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
    PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);
  } else {
    PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
  }

  PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
  UpdateFfsFileState (
    (EFI_FFS_FILE_HEADER *) PadFile,
    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
    );

  //
  // Verify that we have enough space (including the padding
  //
  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Update the current FV pointer
  //
  FvImage->CurrentFilePointer += PadFileSize;

  return EFI_SUCCESS;
}

BOOLEAN
IsVtfFile (
  IN EFI_FFS_FILE_HEADER    *FileBuffer
  )
/*++

Routine Description:

  This function checks the header to validate if it is a VTF file

Arguments:

  FileBuffer     Buffer in which content of a file has been read.

Returns:

  TRUE    If this is a VTF file
  FALSE   If this is not a VTF file

--*/
{
  EFI_GUID  VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
  if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {
    return TRUE;
  } else {
    return FALSE;
  }
}

EFI_STATUS
FfsRebaseImageRead (
  IN     VOID    *FileHandle,
  IN     UINTN   FileOffset,
  IN OUT UINT32  *ReadSize,
  OUT    VOID    *Buffer
  )
/*++

Routine Description:

  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file

Arguments:

  FileHandle - The handle to the PE/COFF file

  FileOffset - The offset, in bytes, into the file to read

  ReadSize   - The number of bytes to read from the file starting at FileOffset

  Buffer     - A pointer to the buffer to read the data into.

Returns:

  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset

--*/
{
  CHAR8   *Destination8;
  CHAR8   *Source8;
  UINT32  Length;

  Destination8  = Buffer;
  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
  Length        = *ReadSize;
  while (Length--) {
    *(Destination8++) = *(Source8++);
  }

  return EFI_SUCCESS;
}

EFI_STATUS
RebaseFfsFile (
  IN OUT EFI_FFS_FILE_HEADER    *FfsFile,
  IN EFI_PHYSICAL_ADDRESS       BaseAddress
  )
/*++

Routine Description:

  This function determines if a file is XIP and should be rebased.  It will
  rebase any PE32 sections found in the file using the base address.

Arguments:

  FfsFile           A pointer to Ffs file image.
  BaseAddress       The base address to use for rebasing the file image.

Returns:

  EFI_SUCCESS             The image was properly rebased.
  EFI_INVALID_PARAMETER   An input parameter is invalid.
  EFI_ABORTED             An error occurred while rebasing the input file image.
  EFI_OUT_OF_RESOURCES    Could not allocate a required resource.

--*/
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?