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 + -
显示快捷键?