/** @file
Copyright (c) 2004 - 2011, 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
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:
Abstract:
This file contains the internal functions required to generate a Firmware Volume.
**/
//
// Include files
//
#ifdef __GNUC__
#endif
#include <string.h>
#ifndef __GNUC__
#include <io.h>
#endif
#include <assert.h>
#include "GenFvInternalLib.h"
#include "FvLib.h"
#include "PeCoffLib.h"
#include "WinNtInclude.h"
EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};
NULL,
};
};
//
// This data array will be located at the base of the Firmware Volume Header (FVH)
// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
// will be used to keep the FVH checksum consistent.
// This code will be run in response to a starutp IPI for HT-enabled systems.
//
//
// EA D0 FF 00 F0 ; far jmp F000:FFD0
// 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
// 0, 0 ; Checksum Padding
//
0xEA,
0xD0,
0xFF,
0x0,
0xF0,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
//
// EB CE ; jmp short ($-0x30)
// ; (from offset 0x0 to offset 0xFFD0)
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
// 0, 0 ; Checksum Padding
//
0xEB,
0xCE,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
)
/*++
Routine Description:
This function parses a FV.INF file and copies info into a FV_INFO structure.
Arguments:
InfFile Memory file image.
FvInfo Information read from INF file.
Returns:
EFI_SUCCESS INF file information successfully retrieved.
EFI_ABORTED INF file has an invalid format.
EFI_NOT_FOUND A required string was not found in the INF file.
--*/
{
//
// Read the FV base address
//
if (!mFvDataInfo.BaseAddressSet) {
if (Status == EFI_SUCCESS) {
//
// Get the base address
//
return EFI_ABORTED;
}
}
}
//
// Read the FV File System Guid
//
if (!FvInfo->FvFileSystemGuidSet) {
if (Status == EFI_SUCCESS) {
//
// Get the guid value
//
return EFI_ABORTED;
}
}
}
//
// Read the FV Extension Header File Name
//
if (Status == EFI_SUCCESS) {
}
//
// Read the FV file name
//
if (Status == EFI_SUCCESS) {
//
// copy the file name
//
}
//
// Read Fv Attribute
//
(FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAttributeName [Index], 0, Value) == EFI_SUCCESS)) {
Error (NULL, 0, 2000, "Invalid parameter", "%s expected %s | %s", mFvbAttributeName [Index], TRUE_STRING, FALSE_STRING);
return EFI_ABORTED;
}
}
}
//
// Read Fv Alignment
//
if (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAlignmentName [Index], 0, Value) == EFI_SUCCESS) {
break;
}
}
}
//
// Read block maps
//
//
// Read block size
//
if (Status == EFI_SUCCESS) {
//
// Update the size of block
//
return EFI_ABORTED;
}
} else {
//
// If there is no blocks size, but there is the number of block, then we have a mismatched pair
// and should return an error.
//
Error (NULL, 0, 2000, "Invalid parameter", "both %s and %s must be specified.", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
return EFI_ABORTED;
} else {
//
// We are done
//
break;
}
}
//
// Read blocks number
//
if (Status == EFI_SUCCESS) {
//
// Update the number of blocks
//
return EFI_ABORTED;
}
}
}
}
if (Index == 0) {
return EFI_ABORTED;
}
//
// Read files
//
Number = 0;
break;
}
}
//
// Read the FFS file list
//
if (Status == EFI_SUCCESS) {
//
// Add the file
//
} else {
break;
}
}
}
return EFI_SUCCESS;
}
)
/*++
Routine Description:
This function changes the FFS file attributes based on the erase polarity
of the FV. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY.
Arguments:
FfsFile File header.
FvHeader FV header.
Returns:
None
--*/
{
// FfsFile->State |= ~(UINT8) EFI_FILE_ALL_STATE_BITS;
}
}
)
/*++
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 offset of the FFS file
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.
//
return EFI_INVALID_PARAMETER;
}
case 0:
//
// 8 byte alignment, mini alignment requirement for FFS file.
//
*Alignment = 3;
break;
case 1:
//
// 16 byte alignment
//
*Alignment = 4;
break;
case 2:
//
// 128 byte alignment
//
*Alignment = 7;
break;
case 3:
//
// 512 byte alignment
//
*Alignment = 9;
break;
case 4:
//
// 1K byte alignment
//
*Alignment = 10;
break;
case 5:
//
// 4K byte alignment
//
*Alignment = 12;
break;
case 6:
//
// 32K byte alignment
//
*Alignment = 15;
break;
case 7:
//
// 64K byte alignment
//
*Alignment = 16;
break;
default:
break;
}
return EFI_SUCCESS;
}
)
/*++
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.
FvEnd End of the empty data in FvImage.
ExtHeader PI FvExtHeader Optional
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.
--*/
{
//
// Verify input parameters.
//
return EFI_INVALID_PARAMETER;
}
//
// Check if a pad file is necessary
//
if ((ExtHeader == NULL) && (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0)) {
return EFI_SUCCESS;
}
//
// 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
//
//
// Append extension header size
//
}
//
// Verify that we have enough space for the file header
//
return EFI_OUT_OF_RESOURCES;
}
//
// Write pad file header
//
//
// Write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
//
PadFile->Attributes = 0;
//
// Write pad file size (calculated size minus next file header size)
//
//
// Fill in checksums and state, they must be 0 for checksumming.
//
PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
);
//
// Update the current FV pointer
//
//
// Copy Fv Extension Header and Set Fv Extension header offset
//
((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) (PadFile + 1) - (UINTN) FvImage->FileImage);
//
// Make next file start at QWord Boundry
//
}
}
return EFI_SUCCESS;
}
)
/*++
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
--*/
{
return TRUE;
} else {
return FALSE;
}
}
)
/*++
Routine Description:
This function gets the basic debug information (entrypoint, baseaddress, .text, .data section base address)
Arguments:
FvMapFile A pointer to FvMap File
FileName Ffs File PathName
FfsFile A pointer to Ffs file image.
ImageBaseAddress PeImage Base Address.
pImageContext Image Context Information.
Returns:
EFI_SUCCESS Added required map information.
--*/
{
unsigned long long TempLongAddress;
//
// Init local variable
//
FunctionType = 0;
//
// Print FileGuid to string buffer.
//
//
// Construct Map file Name
//
//
// Change '\\' to '/', unified path format.
//
while (*Cptr != '\0') {
if (*Cptr == '\\') {
*Cptr = FILE_SEP_CHAR;
}
Cptr ++;
}
//
// Get Map file
//
Cptr --;
}
if (Cptr < PeMapFileName) {
return EFI_NOT_FOUND;
} else {
}
//
// Get module Name
//
Cptr --;
}
*Cptr2 = '\0';
*Cptr2 = '.';
//
// AddressOfEntryPoint and Offset in Image
//
if (!pImageContext->IsTeImage) {
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset);
Offset = 0;
sizeof (UINT32) +
sizeof (EFI_IMAGE_FILE_HEADER) +
);
} else {
}
//
// module information output
//
if (ImageBaseAddress == 0) {
} else {
}
if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && pImageContext->Machine == EFI_IMAGE_MACHINE_IA64) {
//
// Process IPF PLABEL to get the real address after the image has been rebased.
// PLABEL structure is got by AddressOfEntryPoint offset to ImageBuffer stored in pImageContext->Handle.
//
fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (*(UINT64 *)((UINTN) pImageContext->Handle + (UINTN) AddressOfEntryPoint)));
} else {
fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));
}
TextVirtualAddress = 0;
DataVirtualAddress = 0;
}
}
fprintf (FvMapFile, " .textbaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + TextVirtualAddress));
fprintf (FvMapFile, " .databaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + DataVirtualAddress));
//
// Open PeMapFile
//
// fprintf (stdout, "can't open %s file to reading\n", PeMapFileName);
return EFI_ABORTED;
}
//
// Output Functions information into Fv Map file
//
LinkTimeBaseAddress = 0;
//
// Skip blank line
//
if (Line[0] == 0x0a) {
FunctionType = 0;
continue;
}
//
// By Address and Static keyword
//
if (FunctionType == 0) {
//
// function list
//
FunctionType = 1;
//
// static function list
//
FunctionType = 2;
}
continue;
}
//
// Printf Function Information
//
if (FunctionType == 1) {
fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));
}
} else if (FunctionType == 2) {
fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));
}
}
}
//
// Close PeMap file
//
return EFI_SUCCESS;
}
AddFile (
)
/*++
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.
FvMapFile Pointer to FvMap File
FvReportFile Pointer to FvReport File
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.
--*/
{
Index1 = 0;
//
// Verify input parameters.
//
return EFI_INVALID_PARAMETER;
}
//
// Read the file to add
//
return EFI_ABORTED;
}
//
// Get the file size
//
//
// Read the file into a buffer
//
if (FileBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Done with the file, from this point on we will just use the buffer read.
//
//
// Verify read successful
//
free (FileBuffer);
return EFI_ABORTED;
}
//
// For None PI Ffs file, directly add them into FvImage.
//
if (!FvInfo->IsPiFvImage) {
} else {
}
goto Done;
}
//
// Verify Ffs file
//
free (FileBuffer);
return EFI_INVALID_PARAMETER;
}
//
// Verify space exists to add the file
//
free (FileBuffer);
Error (NULL, 0, 4002, "Resource", "FV space is full, not enough room to add file %s.", FvInfo->FvFiles[Index]);
return EFI_OUT_OF_RESOURCES;
}
//
// Verify the input file is the duplicated file in this Fv image
//
Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %uth file have the same file GUID.", (unsigned) Index1 + 1, (unsigned) Index + 1);
return EFI_INVALID_PARAMETER;
}
}
//
// Update the file state based on polarity of the FV.
//
);
//
// Check if alignment is required
//
//
// Find the largest alignment of all the FFS files in the FV
//
if (CurrentFileAlignment > MaxFfsAlignment) {
}
//
// If we have a VTF file, add it at the top.
//
//
// 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 + sizeof (EFI_FFS_FILE_HEADER) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {
Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %u-byte boundary.", (unsigned) (1 << CurrentFileAlignment));
free (FileBuffer);
return EFI_ABORTED;
}
//
// Rebase the PE or TE image in FileBuffer of FFS file for XIP
// Rebase for the debug genfvmap tool
//
Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);
return Status;
}
//
// copy VTF File
//
fprintf (FvReportFile, "0x%08X %s\n", (unsigned)(UINTN) (((UINT8 *)*VtfFileImage) - (UINTN)FvImage->FileImage), FileGuidString);
free (FileBuffer);
return EFI_SUCCESS;
} else {
//
// Already found a VTF file.
//
free (FileBuffer);
return EFI_ABORTED;
}
}
//
// Add pad file if necessary
//
Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property.");
free (FileBuffer);
return EFI_ABORTED;
}
//
// Add file
//
//
// Rebase the PE or TE image in FileBuffer of FFS file for XIP.
// Rebase Bs and Rt drivers for the debug genfvmap tool.
//
Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);
return Status;
}
//
// Copy the file
//
fprintf (FvReportFile, "0x%08X %s\n", (unsigned) (FvImage->CurrentFilePointer - FvImage->FileImage), FileGuidString);
} else {
free (FileBuffer);
return EFI_ABORTED;
}
//
// Make next file start at QWord Boundry
//
}
Done:
//
// Free allocated memory.
//
free (FileBuffer);
return EFI_SUCCESS;
}
)
/*++
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.
--*/
{
//
// If there is no VTF or the VTF naturally follows the previous file without a
// pad file, then there's nothing to do
//
return EFI_SUCCESS;
}
return EFI_INVALID_PARAMETER;
}
//
// Pad file starts at beginning of free space
//
//
// write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
//
PadFile->Attributes = 0;
//
// FileSize includes the EFI_FFS_FILE_HEADER
//
//
// Fill in checksums and state, must be zero during checksum calculation.
//
PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
);
//
// Update the current FV pointer
//
return EFI_SUCCESS;
}
)
/*++
Routine Description:
This parses the FV looking for the PEI core and then plugs the address into
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 parameter was NULL.
EFI_NOT_FOUND PEI Core file not found.
--*/
{
//
// Verify input parameters
//
return EFI_INVALID_PARAMETER;
}
//
// Initialize FV library
//
//
// Verify VTF file
//
return EFI_INVALID_PARAMETER;
}
if (
) {
Vtf0Detected = TRUE;
} else {
}
//
// Find the Sec Core
//
if (Vtf0Detected) {
//
// If the SEC core file is not found, but the VTF-0 signature
// is found, we'll treat it as a VTF-0 'Volume Top File'.
// This means no modifications are required to the VTF.
//
return EFI_SUCCESS;
}
return EFI_ABORTED;
}
//
// Sec Core found, now find PE32 section
//
if (Status == EFI_NOT_FOUND) {
}
return EFI_ABORTED;
}
Status = GetPe32Info (
);
return EFI_ABORTED;
}
if (
Vtf0Detected &&
) {
//
// If the SEC core code is IA32 or X64 and the VTF-0 signature
// is found, we'll treat it as a VTF-0 'Volume Top File'.
// This means no modifications are required to the VTF.
//
return EFI_SUCCESS;
}
//
// Physical address is FV base + offset of PE32 + offset of the entry point
//
SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
//
// Find the PEI Core
//
return EFI_ABORTED;
}
//
// PEI Core found, now find PE32 or TE section
//
if (Status == EFI_NOT_FOUND) {
}
return EFI_ABORTED;
}
Status = GetPe32Info (
);
return EFI_ABORTED;
}
//
// Physical address is FV base + offset of PE32 + offset of the entry point
//
PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
if (MachineType == EFI_IMAGE_MACHINE_IA64) {
//
// Update PEI_CORE address
//
//
// Set the uncached attribute bit in the physical address
//
PeiCorePhysicalAddress |= 0x8000000000000000ULL;
//
// Check if address is aligned on a 16 byte boundary
//
if (PeiCorePhysicalAddress & 0xF) {
"PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %llXh.",
(unsigned long long) PeiCorePhysicalAddress
);
return EFI_ABORTED;
}
//
// First Get the FIT table address
//
}
//
// Update SEC_CORE address
//
//
// Set the uncached attribute bit in the physical address
//
SecCorePhysicalAddress |= 0x8000000000000000ULL;
//
// Check if address is aligned on a 16 byte boundary
//
if (SecCorePhysicalAddress & 0xF) {
"SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %llXh.",
(unsigned long long) SecCorePhysicalAddress
);
return EFI_ABORTED;
}
//
// Update the address
//
SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
//
// Get the location to update
//
//
// Write lower 32 bits of physical address for Pei Core entry
//
//
// Write SecCore Entry point relative address into the jmp instruction in reset vector.
//
Ia32SecEntryOffset = (INT32) (SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2));
if (Ia32SecEntryOffset <= -65536) {
return STATUS_ERROR;
}
//
// Update the BFV base address
//
DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%llX.", (unsigned long long) FvInfo->BaseAddress);
//
// Update the Startup AP in the FVH header block ZeroVector region.
//
} else {
//
// Find the position to place Ap reset vector, the offset
// between the position and the end of Fvrecovery.fv file
// should not exceed 128kB to prevent Ap reset vector from
// outside legacy E and F segment
//
Error (NULL, 0, 3000, "Invalid", "FV image does not have enough space to place AP reset vector. The FV image needs to reserve at least 4KB of unused space.");
return EFI_ABORTED;
}
}
}
//
// Calculate the checksum
//
CheckSum = 0x0000;
WordPointer++;
}
//
// Update the checksum field
//
//
// IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV.
//
if ((IpiVector & 0xFFF) != 0) {
Error (NULL, 0, 3000, "Invalid", "Startup AP Vector address are not 4K aligned, because the FV size is not 4K aligned");
return EFI_ABORTED;
}
//
// Write IPI Vector at Offset FvrecoveryFileSize - 8
//
} else if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
//
// Since the ARM reset vector is in the FV Header you really don't need a
// Volume Top File, but if you have one for some reason don't crash...
//
} else {
return EFI_ABORTED;
}
//
// Now update file checksum
//
);
} else {
}
return EFI_SUCCESS;
}
)
/*++
Routine Description:
This parses the FV looking for SEC and patches that address into the
beginning of the FV header.
For ARM the reset vector is at 0x00000000 or 0xFFFF0000.
This would commonly map to the first entry in the ROM.
ARM Exceptions:
Reset +0
Undefined +4
SWI +8
Prefetch Abort +12
Data Abort +16
IRQ +20
FIQ +24
We support two schemes on ARM.
1) Beginning of the FV is the reset vector
2) Reset vector is data bytes FDF file and that code branches to reset vector
in the beginning of the FV (fixed size offset).
Need to have the jump for the reset vector at location zero.
We also need to store the address or PEI (if it exists).
We stub out a return from interrupt in case the debugger
is using SWI.
The optional entry to the common exception handler is
to support full featured exception handling from ROM and is currently
not support by this tool.
Arguments:
FvImage Memory file for the FV memory image
FvInfo Information read from INF file.
Returns:
EFI_SUCCESS Function Completed successfully.
EFI_ABORTED Error encountered.
EFI_INVALID_PARAMETER A required parameter was NULL.
EFI_NOT_FOUND PEI Core file not found.
--*/
{
// 1 - PEI Entry Point
// 2 - movs pc,lr for a SWI handler
// 3 - Place holder for Common Exception Handler
//
// Verify input parameters
//
return EFI_INVALID_PARAMETER;
}
//
// Initialize FV library
//
//
// Find the Sec Core
//
//
// Maybe hardware does SEC job and we only have PEI Core?
//
//
// Find the PEI Core. It may not exist if SEC loads DXE core directly
//
//
// PEI Core found, now find PE32 or TE section
//
if (Status == EFI_NOT_FOUND) {
}
return EFI_ABORTED;
}
Status = GetPe32Info (
);
return EFI_ABORTED;
}
//
// Physical address is FV base + offset of PE32 + offset of the entry point
//
PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
// Address of PEI Core, if we have one
}
//
// Copy to the beginning of the FV
//
}
return EFI_SUCCESS;
}
//
// Sec Core found, now find PE32 section
//
if (Status == EFI_NOT_FOUND) {
}
return EFI_ABORTED;
}
Status = GetPe32Info (
);
return EFI_ABORTED;
}
if (MachineType != EFI_IMAGE_MACHINE_ARMT) {
//
// If SEC is not ARM we have nothing to do
//
return EFI_SUCCESS;
}
//
// Physical address is FV base + offset of PE32 + offset of the entry point
//
SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
//
// Find the PEI Core. It may not exist if SEC loads DXE core directly
//
//
// PEI Core found, now find PE32 or TE section
//
if (Status == EFI_NOT_FOUND) {
}
return EFI_ABORTED;
}
Status = GetPe32Info (
);
return EFI_ABORTED;
}
//
// Physical address is FV base + offset of PE32 + offset of the entry point
//
PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
}
// B SecEntryPoint - signed_immed_24 part +/-32MB offset
// on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8
if (ResetVector[0] > 0x00FFFFFF) {
return EFI_ABORTED;
}
// Add opcode for an uncondional branch with no link. AKA B SecEntryPoint
ResetVector[0] |= 0xEB000000;
// Address of PEI Core, if we have one
// SWI handler movs pc,lr. Just in case a debugger uses SWI
// Place holder to support a common interrupt handler from ROM.
// Currently not suppprted. For this to be used the reset vector would not be in this FV
// and the exception vectors would be hard coded in the ROM and just through this address
// to find a common handler in the a module in the FV.
ResetVector[3] = 0;
//
// Copy to the beginning of the FV
//
return EFI_SUCCESS;
}
)
/*++
Routine Description:
Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
See EfiImage.h for machine types. The entry point offset is from the beginning
of the PE32 buffer passed in.
Arguments:
Pe32 Beginning of the PE32.
EntryPoint Offset from the beginning of the PE32 to the image entry point.
BaseOfCode Base address of code.
MachineType Magic number for the machine type.
Returns:
EFI_SUCCESS Function completed successfully.
EFI_ABORTED Error encountered.
EFI_INVALID_PARAMETER A required parameter was NULL.
EFI_UNSUPPORTED The operation is unsupported.
--*/
{
//
// Verify input parameters
//
return EFI_INVALID_PARAMETER;
}
//
// First check whether it is one TE Image.
//
//
// By TeImage Header to get output
//
*EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
} else {
//
// Then check whether
// First is the DOS header
//
//
// Verify DOS header is expected
//
Error (NULL, 0, 3000, "Invalid", "Unknown magic number in the DOS header, 0x%04X.", DosHeader->e_magic);
return EFI_UNSUPPORTED;
}
//
// Immediately following is the NT header.
//
//
// Verify NT header is expected
//
Error (NULL, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", (unsigned) ImgHdr->Pe32.Signature);
return EFI_UNSUPPORTED;
}
//
// Get output
//
}
//
// Verify machine type is supported
//
if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC &&
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
)
/*++
Routine Description:
This is the main function which will be called from application.
Arguments:
InfFileImage Buffer containing the INF file contents.
InfFileSize Size of the contents of the InfFileImage buffer.
FvFileName Requested name for the FV file.
MapFileName Fv map file to log fv driver information.
Returns:
EFI_SUCCESS Function completed successfully.
EFI_OUT_OF_RESOURCES Could not allocate required resources.
EFI_ABORTED Error encountered.
EFI_INVALID_PARAMETER A required parameter was NULL.
--*/
{
FvReportFile = NULL;
if (InfFileImage != NULL) {
//
// Initialize file structures
//
//
// Parse the FV inf file for header information
//
return Status;
}
}
//
// Update the file name return values
//
}
if (FvFileName == NULL) {
return EFI_ABORTED;
}
return EFI_ABORTED;
}
//
// Debug message Fv File System Guid
//
if (mFvDataInfo.FvFileSystemGuidSet) {
}
//
// Add PI FV extension header
//
FvExtHeader = NULL;
if (mFvDataInfo.FvExtHeaderFile[0] != 0) {
//
// Open the FV Extension Header file
//
//
// Get the file size
//
//
// Allocate a buffer for the FV Extension Header
//
if (FvExtHeader == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Read the FV Extension Header
//
//
// See if there is an override for the FV Name GUID
//
if (mFvDataInfo.FvNameGuidSet) {
}
} else if (mFvDataInfo.FvNameGuidSet) {
//
// Allocate a buffer for the FV Extension Header
//
if (FvExtHeader == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
//
// Debug message Fv Name Guid
//
if (mFvDataInfo.FvNameGuidSet) {
}
}
//
// FvMap file to log the function address of all modules in one Fvimage
//
if (MapFileName != NULL) {
} else {
}
//
// FvReport file to log the FV information in one Fvimage
//
//
// Calculate the FV size and Update Fv Size based on the actual FFS files.
// And Update mFvDataInfo data.
//
return Status;
}
//
// support fv image and empty fv image
//
//
// Allocate the FV, assure FvImage Header 8 byte alignment
//
if (FvBufferHeader == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize the FV to the erase polarity
//
if (mFvDataInfo.FvAttributes == 0) {
//
// Set Default Fv Attribute
//
}
} else {
}
//
// Initialize FV header
//
//
// Initialize the zero vector to all zeros.
//
//
// Copy the Fv file system GUID
//
FvHeader->ExtHeaderOffset = 0;
//
// Copy firmware block map
//
}
//
// Add block map terminator
//
//
// Complete the header
//
FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
//
// If there is no FFS file, generate one empty FV
//
goto WriteFile;
}
//
// Initialize our "file" view of the buffer
//
//
// Initialize the FV library.
//
//
// Initialize the VTF file address.
//
//
// Open FvMap file
//
return EFI_ABORTED;
}
//
// Open FvReport file
//
if (FvReportFile == NULL) {
return EFI_ABORTED;
}
//
// record FV size information into FvMap file.
//
if (mFvTotalSize != 0) {
}
if (mFvTakenSize != 0) {
}
if (mFvTotalSize != 0 && mFvTakenSize != 0) {
}
//
// record FV size information to FvReportFile.
//
//
// Add PI FV extension header
//
if (FvExtHeader != NULL) {
//
// Add FV Extended Header contents to the FV as a PAD file
//
//
// Fv Extension header change update Fv Header Check sum
//
FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
}
//
// Add files to FV
//
//
// Add the file
//
//
// Exit if error detected while adding the file
//
goto Finish;
}
}
//
// If there is a VTF file, some special actions need to occur.
//
//
// Pad from the end of the last file to the beginning of the VTF file.
// If the left space is less than sizeof (EFI_FFS_FILE_HEADER)?
//
Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file.");
goto Finish;
}
if (!mArm) {
//
// Update reset vector (SALE_ENTRY for IPF)
// Now for IA32 and IA64 platform, the fv which has bsf file must have the
// EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
// reset vector. If the PEI Core is found, the VTF file will probably get
// corrupted by updating the entry point.
//
goto Finish;
}
}
}
}
if (mArm) {
goto Finish;
}
//
// Update Checksum for FvHeader
//
FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
}
//
// Update FV Alignment attribute to the largest alignment of all the FFS files in the FV
//
//
// Update Checksum for FvHeader
//
FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
}
//
// Write fv file
//
goto Finish;
}
goto Finish;
}
if (FvBufferHeader != NULL) {
}
if (FvExtHeader != NULL) {
free (FvExtHeader);
}
}
}
if (FvReportFile != NULL) {
}
return Status;
}
)
/*++
Routine Description:
This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
Sec to Pei Core
Arguments:
FitTablePtr - The pointer of FIT_TABLE.
PeiCorePhysicalAddress - The address of Pei Core entry.
Returns:
EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
--*/
{
return EFI_SUCCESS;
}
TmpFitPtr++;
}
return EFI_NOT_FOUND;
}
)
/*++
Routine Description:
This function is used to update the checksum for FIT.
Arguments:
FitTablePtr - The pointer of FIT_TABLE.
Returns:
None.
--*/
{
FitTablePtr->CheckSum = 0;
}
}
)
/*++
Routine Description:
Calculate the FV size and Update Fv Size based on the actual FFS files.
And Update FvInfo data.
Arguments:
FvInfoPtr - The pointer to FV_INFO structure.
Returns:
EFI_ABORTED - Ffs Image Error
EFI_SUCCESS - Successfully update FvSize
--*/
{
FvExtendHeaderSize = 0;
VtfFileSize = 0;
VtfFileFlag = FALSE;
Index = 0;
//
// Compute size for easy access later
//
for (Index = 0; FvInfoPtr->FvBlocks[Index].NumBlocks > 0 && FvInfoPtr->FvBlocks[Index].Length > 0; Index++) {
}
//
// Caculate the required sizes for all FFS files.
//
CurrentOffset = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
CurrentOffset += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
break;
}
}
//
// Calculate PI extension header
//
return EFI_ABORTED;
}
} else if (mFvDataInfo.FvNameGuidSet) {
}
//
// Accumlate every FFS file size.
//
//
// Open FFS file
//
return EFI_ABORTED;
}
//
// Get the file size
//
//
// Read Ffs File header
//
//
// close file
//
if (FvInfoPtr->IsPiFvImage) {
//
// Check whether this ffs file is vtf file
//
if (VtfFileFlag) {
//
// One Fv image can't have two vtf files.
//
return EFI_ABORTED;
}
VtfFileFlag = TRUE;
continue;
}
//
// Get the alignment of FFS file
//
//
// Add Pad file
//
CurrentOffset = (CurrentOffset + sizeof (EFI_FFS_FILE_HEADER) * 2 + FfsAlignment - 1) & ~(FfsAlignment - 1);
CurrentOffset -= sizeof (EFI_FFS_FILE_HEADER);
}
}
//
// Add ffs file size
//
} else {
}
//
// Make next ffs file start at QWord Boundry
//
if (FvInfoPtr->IsPiFvImage) {
CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
}
}
DebugMsg (NULL, 0, 9, "FvImage size", "The caculated fv image size is 0x%x and the current set fv image size is 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size);
//
// Update FvInfo data
//
FvInfoPtr->FvBlocks[0].NumBlocks = CurrentOffset / FvInfoPtr->FvBlocks[0].Length + ((CurrentOffset % FvInfoPtr->FvBlocks[0].Length)?1:0);
//
// Not invalid
//
Error (NULL, 0, 3000, "Invalid", "the required fv image size 0x%x exceeds the set fv image size 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size);
return EFI_INVALID_PARAMETER;
}
//
// Set Fv Size Information
//
return EFI_SUCCESS;
}
)
/*++
Routine Description:
Arguments:
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
--*/
{
while (Length--) {
*(Destination8++) = *(Source8++);
}
return EFI_SUCCESS;
}
)
/*++
Routine Description:
This function gets all child FvImages in the input FfsFile, and records
their base address to the parent image.
Arguments:
FvInfo A pointer to FV_INFO struture.
FfsFile A pointer to Ffs file image that may contain FvImage.
XipOffset The offset address to the parent FvImage base.
Returns:
EFI_SUCCESS Base address of child Fv image is recorded.
--*/
{
//
// Find FV section
//
break;
}
SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + sizeof (EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
//
// Rebase on Flash
//
}
return EFI_SUCCESS;
}
)
/*++
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:
FvInfo A pointer to FV_INFO struture.
FileName Ffs File PathName
FfsFile A pointer to Ffs file image.
XipOffset The offset address to use for rebasing the XIP file image.
FvMapFile FvMapFile to record the function address in one Fvimage
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.
EFI_NOT_FOUND No compressed sections could be found.
--*/
{
Index = 0;
PeFileBuffer = NULL;
//
// Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified.
//
return EFI_SUCCESS;
}
//
// If ForceRebase Flag specified to FALSE, will always not take rebase action.
//
if (FvInfo->ForceRebase == 0) {
return EFI_SUCCESS;
}
//
// We only process files potentially containing PE32 sections.
//
case EFI_FV_FILETYPE_PEI_CORE:
case EFI_FV_FILETYPE_PEIM:
case EFI_FV_FILETYPE_DRIVER:
case EFI_FV_FILETYPE_DXE_CORE:
break;
//
// Rebase the inside FvImage.
//
//
//
break;
default:
return EFI_SUCCESS;
}
//
// Rebase each PE32 section
//
//
// Init Value
//
NewPe32BaseAddress = 0;
//
// Find Pe Image
//
break;
}
//
// Initialize context
//
ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
return Status;
}
}
//
// Keep Image Context for PE image in FV
//
//
// Get File PdbPointer
//
//
// Get PeHeader pointer
//
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + ImageContext.PeCoffHeaderOffset);
//
// Calculate the PE32 base address, based on file type
//
case EFI_FV_FILETYPE_PEI_CORE:
case EFI_FV_FILETYPE_PEIM:
//
// Check if section-alignment and file-alignment match or not
//
//
// Xip module has the same section alignment and file alignment.
//
Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);
return EFI_ABORTED;
}
//
// PeImage has no reloc section. It will try to get reloc data from the original EFI image.
//
if (ImageContext.RelocationsStripped) {
//
// Construct the original efi file Name
//
while (*Cptr != '.') {
Cptr --;
}
if (*Cptr != '.') {
return EFI_ABORTED;
} else {
}
//Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
//return EFI_ABORTED;
break;
}
//
// Get the file size
//
if (PeFileBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Read Pe File
//
//
// close file
//
//
// Handle pointer to the original efi image.
//
Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
return Status;
}
}
NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;
break;
case EFI_FV_FILETYPE_DRIVER:
case EFI_FV_FILETYPE_DXE_CORE:
//
// Check if section-alignment and file-alignment match or not
//
//
// Xip module has the same section alignment and file alignment.
//
Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);
return EFI_ABORTED;
}
NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;
break;
default:
//
// Not supported file type
//
return EFI_SUCCESS;
}
//
// Relocation doesn't exist
//
if (ImageContext.RelocationsStripped) {
continue;
}
//
// Relocation exist and rebase
//
//
// Load and Relocate Image Data
//
MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
if (MemoryImagePointer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));
return Status;
}
return Status;
}
//
// Copy Relocated data to raw image file.
//
sizeof (UINT32) +
sizeof (EFI_IMAGE_FILE_HEADER) +
);
CopyMem (
(UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) + SectionHeader->PointerToRawData,
);
}
if (PeFileBuffer != NULL) {
free (PeFileBuffer);
PeFileBuffer = NULL;
}
//
// Update Image Base Address
//
} else {
);
return EFI_ABORTED;
}
//
// Now update file checksum
//
);
}
//
// Get this module function address from ModulePeMapFile and add them into FvMap file
//
//
// Default use FileName as map file path
//
if (PdbPointer == NULL) {
}
}
) {
//
// Only Peim code may have a TE section
//
return EFI_SUCCESS;
}
//
// Now process TE sections
//
NewPe32BaseAddress = 0;
//
// Find Te Image
//
break;
}
//
// Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
// by GenTEImage
//
TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
//
// Initialize context, load image info.
//
Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
return Status;
}
}
//
// Keep Image Context for TE image in FV
//
//
// Get File PdbPointer
//
//
// Set new rebased address.
//
//
// if reloc is stripped, try to get the original efi image to get reloc info.
//
if (ImageContext.RelocationsStripped) {
//
// Construct the original efi file name
//
while (*Cptr != '.') {
Cptr --;
}
if (*Cptr != '.') {
return EFI_ABORTED;
} else {
}
//Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
//return EFI_ABORTED;
} else {
//
// Get the file size
//
if (PeFileBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Read Pe File
//
//
// close file
//
//
// Append reloc section into TeImage
//
Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
return Status;
}
}
}
//
// Relocation doesn't exist
//
if (ImageContext.RelocationsStripped) {
continue;
}
//
// Relocation exist and rebase
//
//
// Load and Relocate Image Data
//
MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
if (MemoryImagePointer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));
return Status;
}
//
// Reloacate TeImage
//
return Status;
}
//
// Copy the relocated image into raw image file.
//
if (!ImageContext.IsTeImage) {
CopyMem (
(UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
);
} else {
CopyMem (
(UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
(VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress),
);
}
}
//
// Free the allocated memory resource
//
if (PeFileBuffer != NULL) {
free (PeFileBuffer);
PeFileBuffer = NULL;
}
//
// Update Image Base Address
//
//
// Now update file checksum
//
);
}
//
// Get this module function address from ModulePeMapFile and add them into FvMap file
//
//
// Default use FileName as map file path
//
if (PdbPointer == NULL) {
}
);
}
return EFI_SUCCESS;
}
)
/*++
Routine Description:
Find the position in this FvImage to place Ap reset vector.
Arguments:
FvImage Memory file for the FV memory image.
Pointer Pointer to pointer to position.
Returns:
EFI_NOT_FOUND - No satisfied position is found.
EFI_SUCCESS - The suitable position is return.
--*/
{
//
// Find Pad File to add ApResetVector info
//
//
// No Pad file to be found.
//
break;
}
//
// Get Pad file size.
//
FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
//
// FixPoint must be align on 0x1000 relative to FvImage Header
//
//
// FixPoint be larger at the last place of one fv image.
//
FixPoint += 0x1000;
}
FixPoint -= 0x1000;
//
// No alignment FixPoint in this Pad File.
//
continue;
}
//
// Find the position to place ApResetVector
//
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
)
/*++
Routine Description:
This function parses a Cap.INF file and copies info into a CAP_INFO structure.
Arguments:
InfFile Memory file image.
CapInfo Information read from INF file.
Returns:
EFI_SUCCESS INF file information successfully retrieved.
EFI_ABORTED INF file has an invalid format.
EFI_NOT_FOUND A required string was not found in the INF file.
--*/
{
//
// Initialize Cap info
//
// memset (CapInfo, 0, sizeof (CAP_INFO));
//
//
// Read the Capsule Guid
//
if (Status == EFI_SUCCESS) {
//
// Get the Capsule Guid
//
return EFI_ABORTED;
}
}
//
// Read the Capsule Header Size
//
if (Status == EFI_SUCCESS) {
return EFI_ABORTED;
}
}
//
// Read the Capsule Flag
//
if (Status == EFI_SUCCESS) {
}
}
} else {
Error (NULL, 0, 2000, "Invalid parameter", "invalid Flag setting for %s.", EFI_CAPSULE_FLAGS_STRING);
return EFI_ABORTED;
}
}
//
// Read Capsule File name
//
if (Status == EFI_SUCCESS) {
//
// Get output file name
//
}
//
// Read the Capsule FileImage
//
Number = 0;
continue;
}
//
// Read the capsule file name
//
if (Status == EFI_SUCCESS) {
//
// Add the file
//
DebugMsg (NULL, 0, 9, "Capsule component file", "the %uth file name is %s", (unsigned) Index, CapInfo->CapFiles[Index]);
} else {
break;
}
}
if (Index == 0) {
}
return EFI_SUCCESS;
}
)
/*++
Routine Description:
This is the main function which will be called from application to create UEFI Capsule image.
Arguments:
InfFileImage Buffer containing the INF file contents.
InfFileSize Size of the contents of the InfFileImage buffer.
CapFileName Requested name for the Cap file.
Returns:
EFI_SUCCESS Function completed successfully.
EFI_OUT_OF_RESOURCES Could not allocate required resources.
EFI_ABORTED Error encountered.
EFI_INVALID_PARAMETER A required parameter was NULL.
--*/
{
if (InfFileImage != NULL) {
//
// Initialize file structures
//
//
// Parse the Cap inf file for header information
//
if (Status != EFI_SUCCESS) {
return Status;
}
}
if (mCapDataInfo.HeaderSize == 0) {
//
// make header size align 16 bytes.
//
}
Error (NULL, 0, 2000, "Invalid parameter", "The specified HeaderSize cannot be less than the size of EFI_CAPSULE_HEADER.");
return EFI_INVALID_PARAMETER;
}
}
if (CapFileName == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Set Default Capsule Guid value
//
}
//
// Calculate the size of capsule image.
//
Index = 0;
FileSize = 0;
return EFI_ABORTED;
}
Index ++;
}
//
// Allocate buffer for capsule image.
//
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize the capsule header to zero
//
//
// create capsule header and get capsule body
//
Index = 0;
FileSize = 0;
return EFI_ABORTED;
}
Index ++;
}
//
// write capsule data into the output file
//
return EFI_ABORTED;
}
return EFI_SUCCESS;
}