genfvimagelib.c

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

C
2,197
字号
    return EFI_ABORTED;
  }
  //
  // Get the file size
  //
  FileSize = _filelength (_fileno (NewFile));

  //
  // Read the file into a buffer
  //
  FileBuffer = malloc (FileSize);
  if (FileBuffer == NULL) {
    Error (NULL, 0, 0, "memory allocation failure", NULL);
    return EFI_OUT_OF_RESOURCES;
  }

  NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);

  //
  // Done with the file, from this point on we will just use the buffer read.
  //
  fclose (NewFile);

  //
  // Verify read successful
  //
  if (NumBytesRead != sizeof (UINT8) * FileSize) {
    free (FileBuffer);
    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
    return EFI_ABORTED;
  }
  //
  // Verify space exists to add the file
  //
  if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Update the file state based on polarity of the FV.
  //
  UpdateFfsFileState (
    (EFI_FFS_FILE_HEADER *) FileBuffer,
    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
    );

  //
  // If we have a VTF file, add it at the top.
  //
  if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
    if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
      //
      // No previous VTF, add this one.
      //
      *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
      //
      // Sanity check. The file MUST align appropriately
      //
      if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
        Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
      }
      //
      // copy VTF File Header
      //
      memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));

      //
      // Copy VTF body
      //
      memcpy (
        (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
        FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
        FileSize - sizeof (EFI_FFS_FILE_HEADER)
        );

      //
      // re-calculate the VTF File Header
      //
      FileState = (*VtfFileImage)->State;
      (*VtfFileImage)->State = 0;
      *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
      (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
      (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;

      VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
      (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
      //
      // Determine if it has a tail
      //
      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
        TailSize = sizeof (EFI_FFS_FILE_TAIL);
      } else {
        TailSize = 0;
      }

      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
        VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
        (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
      } else {
        (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
      }
      //
      // If it has a file tail, update it
      //
      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
        TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
        *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
      }
      (*VtfFileImage)->State = FileState;
      free (FileBuffer);
      return EFI_SUCCESS;
    } else {
      //
      // Already found a VTF file.
      //
      Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
      free (FileBuffer);
      return EFI_ABORTED;
    }
  }
  //
  // Check if alignment is required
  //
  Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
  if (EFI_ERROR (Status)) {
    printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
    free (FileBuffer);
    return EFI_ABORTED;
  }
  //
  // Add pad file if necessary
  //
  Status = AddPadFile (FvImage, CurrentFileAlignment);
  if (EFI_ERROR (Status)) {
    printf ("ERROR: Could not align the file data properly.\n");
    free (FileBuffer);
    return EFI_ABORTED;
  }
  //
  // Add file
  //
  if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {
    //
    // Copy the file
    //
    memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);

    //
    // If the file is XIP, rebase
    //
    CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
    //
    //    Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
    //    if (EFI_ERROR(Status)) {
    //      printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
    //      return EFI_ABORTED;
    //    }
    //
    // Update Symbol file
    //
    Status = AddSymFile (
              CurrentFileBaseAddress,
              (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
              SymImage,
              FvInfo->FvFiles[Index]
              );
    assert (!EFI_ERROR (Status));

    //
    // Update the current pointer in the FV image
    //
    FvImage->CurrentFilePointer += FileSize;
  } else {
    printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
    return EFI_ABORTED;
  }
  //
  // Make next file start at QWord Boundry
  //
  while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
    FvImage->CurrentFilePointer++;
  }
  //
  // Free allocated memory.
  //
  free (FileBuffer);

  return EFI_SUCCESS;
}

EFI_STATUS
AddVariableBlock (
  IN UINT8                    *FvImage,
  IN UINTN                    Size,
  IN FV_INFO                  *FvInfo
  )
{
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
  VARIABLE_STORE_HEADER       *VarStoreHeader;
  //
  // Variable block should exclude FvHeader. Since the length of
  // FvHeader depends on the block map, which is variable length,
  // we could only decide the actual variable block length here.
  //
  FvHeader                  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
  FvImage                   = FvImage + FvHeader->HeaderLength;

  VarStoreHeader            = (VARIABLE_STORE_HEADER *) FvImage;

  VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
  VarStoreHeader->Size      = Size - FvHeader->HeaderLength;
  VarStoreHeader->Format    = VARIABLE_STORE_FORMATTED;
  VarStoreHeader->State     = VARIABLE_STORE_HEALTHY;
  VarStoreHeader->Reserved  = 0;
  VarStoreHeader->Reserved1 = 0;

  return EFI_SUCCESS;
}

EFI_STATUS
AddEventLogBlock (
  IN UINT8                    *FvImage,
  IN UINTN                    Size,
  IN FV_INFO                  *FvInfo
  )
{
  return EFI_SUCCESS;
}

EFI_STATUS
AddFTWWorkingBlock (
  IN UINT8                    *FvImage,
  IN UINTN                    Size,
  IN FV_INFO                  *FvInfo
  )
{
  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
  UINT32                                  Crc32;

  Crc32     = 0;
  FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
  memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
  FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
  CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
  FTWHeader->Crc = Crc32;
  if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
    FTWHeader->WorkingBlockValid    = 0;
    FTWHeader->WorkingBlockInvalid  = 1;
  } else {
    FTWHeader->WorkingBlockValid    = 1;
    FTWHeader->WorkingBlockInvalid  = 0;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
AddFTWSpareBlock (
  IN UINT8                    *FvImage,
  IN UINTN                    Size,
  IN FV_INFO                  *FvInfo
  )
{
  return EFI_SUCCESS;
}

EFI_STATUS
GenNonFFSFv (
  IN UINT8                    *FvImage,
  IN FV_INFO                  *FvInfo
  )
/*++

Routine Description:

  This function generate the non FFS FV image, such as the working block
  and spare block. How each component of the FV is built is component
  specific.

Arguments:

  FvImage       The memory image of the FV to add it to.  The current offset
                must be valid.
  FvInfo        Pointer to information about the FV.

Returns:

  EFI_SUCCESS              The function completed successfully.
  EFI_INVALID_PARAMETER    One of the input parameters was invalid.
  EFI_ABORTED              An error occurred.
  EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.

--*/
{
  UINTN                       Index;
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
  UINT64                      TotalSize;

  FvHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
  TotalSize = 0;

  for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
    if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
      AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
    } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
      AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
    } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
      AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
    } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
      AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
    } else {
      printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
      return EFI_ABORTED;
    }

    FvImage   = FvImage + FvInfo->FvComponents[Index].Size;
    TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
  }
  //
  // Index and TotalSize is zero mean there's no component, so this is an empty fv
  //
  if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
    printf ("Error. Component size does not sum up to FV size.\n");
    return EFI_ABORTED;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
PadFvImage (
  IN MEMORY_FILE          *FvImage,
  IN EFI_FFS_FILE_HEADER  *VtfFileImage
  )
/*++

Routine Description:

  This function places a pad file between the last file in the FV and the VTF
  file if the VTF file exists.

Arguments:

  FvImage       Memory file for the FV memory image
  VtfFileImage  The address of the VTF file.  If this is the end of the FV
                image, no VTF exists and no pad file is needed.

Returns:

  EFI_SUCCESS             Completed successfully.
  EFI_INVALID_PARAMETER   One of the input parameters was NULL.

--*/
{
  EFI_FFS_FILE_HEADER *PadFile;
  UINTN               FileSize;

  //
  // If there is no VTF or the VTF naturally follows the previous file without a
  // pad file, then there's nothing to do
  //
  if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
    return EFI_SUCCESS;
  }
  //
  // Pad file starts at beginning of free space
  //
  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;

  //
  // write header
  //
  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
  memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;
  PadFile->Attributes = 0;

  //
  // FileSize includes the EFI_FFS_FILE_HEADER
  //
  FileSize          = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
  PadFile->Size[0]  = (UINT8) (FileSize & 0x000000FF);
  PadFile->Size[1]  = (UINT8) ((FileSize & 0x0000FF00) >> 8);
  PadFile->Size[2]  = (UINT8) ((FileSize & 0x00FF0000) >> 16);

  //
  // Fill in checksums and state, must be zero during checksum calculation.
  //
  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, FileSize);
  } 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
    );
  //
  // Update the current FV pointer
  //
  FvImage->CurrentFilePointer = FvImage->Eof;

  return EFI_SUCCESS;
}

EFI_STATUS
UpdateResetVector (
  IN MEMORY_FILE            *FvImage,
  IN FV_INFO                *FvInfo,
  IN EFI_FFS_FILE_HEADER    *VtfFile
  )
/*++

Routine Description:

  This parses the FV looking for the PEI core and then plugs the address into
  the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
  complete an IA32 Bootstrap FV.

Arguments:

  FvImage       Memory file for the FV memory image
  FvInfo        Information read from INF file.
  VtfFile       Pointer to the VTF file in the FV image.

Returns:

  EFI_SUCCESS             Function Completed successfully.
  EFI_ABORTED             Error encountered.
  EFI_INVALID_PARAMETER   A required param

⌨️ 快捷键说明

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