genfvimagelib.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,197 行 · 第 1/5 页
C
2,197 行
EFI_STATUS Status;
EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
UINTN MemoryImagePointer;
UINTN MemoryImagePointerAligned;
EFI_PHYSICAL_ADDRESS ImageAddress;
UINT64 ImageSize;
EFI_PHYSICAL_ADDRESS EntryPoint;
UINT32 Pe32FileSize;
UINT32 NewPe32BaseAddress;
UINTN Index;
EFI_FILE_SECTION_POINTER CurrentPe32Section;
UINT8 FileGuidString[80];
//
// Verify input parameters
//
if (FfsFile == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Convert the GUID to a string so we can at least report which file
// if we find an error.
//
PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
//
// Do some nominal checks on the file, then check for XIP.
//
Status = VerifyFfsFile (FfsFile);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "invalid FFS file", FileGuidString);
return EFI_INVALID_PARAMETER;
}
if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
FfsFile->Type != EFI_FV_FILETYPE_PEIM
) {
//
// File is not XIP, so don't rebase
//
return EFI_SUCCESS;
}
//
// Rebase each PE32 section
//
for (Index = 1;; Index++) {
Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
if (EFI_ERROR (Status)) {
break;
}
//
// Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
//
NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);
//
// Initialize context
//
memset (&ImageContext, 0, sizeof (ImageContext));
ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);
return Status;
}
//
// Allocate a buffer for the image to be loaded into.
//
Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);
MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000));
MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
if (MemoryImagePointerAligned == 0) {
Error (NULL, 0, 0, "memory allocation failure", NULL);
return EFI_OUT_OF_RESOURCES;
}
//
// bugbug
//
ImageContext.ImageAddress = MemoryImagePointerAligned;
Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);
free ((VOID *) MemoryImagePointer);
return Status;
}
Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);
free ((VOID *) MemoryImagePointer);
return Status;
}
ImageAddress = ImageContext.ImageAddress;
ImageSize = ImageContext.ImageSize;
EntryPoint = ImageContext.EntryPoint;
if (ImageSize > Pe32FileSize) {
Error (
NULL,
0,
0,
"rebased PE32 is larger than original PE32 image",
"0x%X > 0x%X on file %s",
ImageSize,
Pe32FileSize,
FileGuidString
);
free ((VOID *) MemoryImagePointer);
return EFI_ABORTED;
}
memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);
free ((VOID *) MemoryImagePointer);
}
//
// the above for loop will always exit with EFI_NOT_FOUND if it completes
// normally. If Index == 1 at exit, then no PE32 sections were found. If it
// exits with any other error code, then something broke...
//
if (Status != EFI_NOT_FOUND) {
Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);
return Status;
}
return EFI_SUCCESS;
}
EFI_STATUS
AddSymFile (
IN UINT64 BaseAddress,
IN EFI_FFS_FILE_HEADER *FfsFile,
IN OUT MEMORY_FILE *SymImage,
IN CHAR8 *SourceFileName
)
/*++
Routine Description:
This function adds the SYM tokens in the source file to the destination file.
The SYM tokens are updated to reflect the base address.
Arguments:
BaseAddress The base address for the new SYM tokens.
FfsFile Pointer to the beginning of the FFS file in question.
SymImage The memory file to update with symbol information.
SourceFileName The source file.
Returns:
EFI_SUCCESS The function completed successfully.
EFI_INVALID_PARAMETER One of the input parameters was invalid.
EFI_ABORTED An error occurred.
--*/
{
FILE *SourceFile;
CHAR8 Buffer[_MAX_PATH];
CHAR8 Type[_MAX_PATH];
CHAR8 Address[_MAX_PATH];
CHAR8 Section[_MAX_PATH];
CHAR8 Token[_MAX_PATH];
CHAR8 SymFileName[_MAX_PATH];
CHAR8 CodeModuleName[_MAX_PATH];
CHAR8 *Ptr;
UINT64 TokenAddress;
EFI_STATUS Status;
EFI_FILE_SECTION_POINTER Pe32Section;
UINT32 EntryPoint;
UINT32 BaseOfCode;
UINT16 MachineType;
//
// Verify input parameters.
//
if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
return EFI_INVALID_PARAMETER;
}
//
// Check if we want to add this file
//
//
// Get the file name
//
strcpy (Buffer, SourceFileName);
//
// Copy the file name for the path of the sym file and truncate the name portion.
//
strcpy (SymFileName, Buffer);
Ptr = strrchr (SymFileName, '\\');
assert (Ptr);
Ptr[0] = 0;
//
// Find the file extension and make it lower case
//
Ptr = strrchr (SymFileName, '.');
if (Ptr != NULL) {
_strlwr (Ptr);
}
//
// Check if it is PEI file
//
if (strstr (Buffer, ".pei") != NULL) {
//
// Find the human readable portion
//
if (!strtok (Buffer, "-") ||
!strtok (NULL, "-") ||
!strtok (NULL, "-") ||
!strtok (NULL, "-") ||
!strtok (NULL, "-") ||
!strcpy (Buffer, strtok (NULL, "."))
) {
Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
return EFI_ABORTED;
}
//
// Save code module name
//
strcpy (CodeModuleName, Buffer);
//
// Add the symbol file name and extension to the file path.
//
strcat (Buffer, ".sym");
strcat (SymFileName, "\\");
strcat (SymFileName, Buffer);
} else {
//
// Only handle PEIM files.
//
return EFI_SUCCESS;
}
//
// Find PE32 section
//
Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
//
// BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
//
if (Status == EFI_NOT_FOUND) {
Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
}
if (Status == EFI_SUCCESS) {
Status = GetPe32Info (
(VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
&EntryPoint,
&BaseOfCode,
&MachineType
);
} else {
if (Status == EFI_NOT_FOUND) {
BaseOfCode = 0x60;
Status = EFI_SUCCESS;
} else {
Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
return Status;
}
}
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
return Status;
}
//
// Open the source file
//
SourceFile = fopen (SymFileName, "r");
if (SourceFile == NULL) {
//
// SYM files are not required.
//
return EFI_SUCCESS;
}
//
// Read the first line
//
if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
Buffer[0] = 0;
}
//
// Make sure it matches the expected sym format
//
if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
fclose (SourceFile);
Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
return EFI_ABORTED;
}
//
// Read in the file
//
while (feof (SourceFile) == 0) {
//
// Read a line
//
if (fscanf (
SourceFile,
"%s | %s | %s | %s\n",
Type,
Address,
Section,
Token
) == 4) {
//
// If the token starts with "??" ignore it
//
if (Token[0] == '?' && Token[1] == '?') {
continue;
}
//
// Get the token address
//
AsciiStringToUint64 (Address, TRUE, &TokenAddress);
//
// Add the base address
//
TokenAddress += BaseAddress;
//
// If PE32 or TE section then find the start of code. For PIC it is hardcoded.
//
if (Pe32Section.Pe32Section) {
//
// Add the offset of the PE32 section
//
TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
//
// Add the size of the PE32 section header
//
TokenAddress += sizeof (EFI_PE32_SECTION);
} else {
//
// BUGBUG: Don't know why this is 0x28 bytes.
//
TokenAddress += 0x28;
}
//
// Add the beginning of the code
//
TokenAddress += BaseOfCode;
sprintf (
Buffer,
"%s | %016I64X | %s | _%s%s\n",
Type,
TokenAddress,
Section,
CodeModuleName,
Token
);
memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
}
}
fclose (SourceFile);
return EFI_SUCCESS;
}
EFI_STATUS
AddFile (
IN OUT MEMORY_FILE *FvImage,
IN FV_INFO *FvInfo,
IN UINTN Index,
IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
IN OUT MEMORY_FILE *SymImage
)
/*++
Routine Description:
This function adds a file to the FV image. The file will pad to the
appropriate alignment if required.
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.
Index The file in the FvInfo file list to add.
VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
to the end of the FvImage then no VTF previously found.
SymImage The memory image of the Sym file to update if symbols are present.
The current offset must be valid.
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.
--*/
{
FILE *NewFile;
UINTN FileSize;
UINT8 *FileBuffer;
UINTN NumBytesRead;
UINT32 CurrentFileAlignment;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
UINT8 VtfHeaderChecksum;
UINT8 VtfFileChecksum;
UINT8 FileState;
EFI_FFS_FILE_TAIL TailValue;
UINT32 TailSize;
//
// Verify input parameters.
//
if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Read the file to add
//
NewFile = fopen (FvInfo->FvFiles[Index], "rb");
if (NewFile == NULL) {
Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?