X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FC%2FGenFv%2FGenFvInternalLib.c;h=6a874f4e944fd56f6f286f1b91bfbaa78b8b6b02;hb=ecbaa856da0c94b7054f795d001ee3f5aaee033e;hp=6b5d6bda2a15fcf8a05c0cf4e3c1eeae933cb3c5;hpb=b303ea726e1c8ed240dad2bce54821318567eab3;p=mirror_edk2.git
diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/BaseTools/Source/C/GenFv/GenFvInternalLib.c
index 6b5d6bda2a..6a874f4e94 100644
--- a/BaseTools/Source/C/GenFv/GenFvInternalLib.c
+++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.c
@@ -1,29 +1,29 @@
/** @file
+This file contains the internal functions required to generate a Firmware Volume.
-Copyright (c) 2004 - 2009, Intel Corporation
-All rights reserved. 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
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2016 HP Development Company, L.P.
+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
+http://opensource.org/licenses/bsd-license.php
-Module Name:
-
- GenFvInternalLib.c
-
-Abstract:
-
- This file contains the internal functions required to generate a Firmware Volume.
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
//
// Include files
//
-#ifdef __GNUC__
+
+#if defined(__FreeBSD__)
+#include
+#elif defined(__GNUC__)
#include
+#endif
+#ifdef __GNUC__
#include
#endif
#include
@@ -32,70 +32,77 @@ Abstract:
#endif
#include
+#include
+
+#include "WinNtInclude.h"
#include "GenFvInternalLib.h"
#include "FvLib.h"
#include "PeCoffLib.h"
-#include "WinNtInclude.h"
+
+#define ARMT_UNCONDITIONAL_JUMP_INSTRUCTION 0xEB000000
+#define ARM64_UNCONDITIONAL_JUMP_INSTRUCTION 0x14000000
BOOLEAN mArm = FALSE;
STATIC UINT32 MaxFfsAlignment = 0;
+BOOLEAN VtfFileFlag = FALSE;
-EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
+EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
EFI_GUID mFileGuidArray [MAX_NUMBER_OF_FILES_IN_FV];
-EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
-EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};
+EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
+EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};
+EFI_GUID mEfiFfsSectionAlignmentPaddingGuid = EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID;
CHAR8 *mFvbAttributeName[] = {
- EFI_FVB2_READ_DISABLED_CAP_STRING,
- EFI_FVB2_READ_ENABLED_CAP_STRING,
- EFI_FVB2_READ_STATUS_STRING,
+ EFI_FVB2_READ_DISABLED_CAP_STRING,
+ EFI_FVB2_READ_ENABLED_CAP_STRING,
+ EFI_FVB2_READ_STATUS_STRING,
EFI_FVB2_WRITE_DISABLED_CAP_STRING,
- EFI_FVB2_WRITE_ENABLED_CAP_STRING,
- EFI_FVB2_WRITE_STATUS_STRING,
- EFI_FVB2_LOCK_CAP_STRING,
- EFI_FVB2_LOCK_STATUS_STRING,
+ EFI_FVB2_WRITE_ENABLED_CAP_STRING,
+ EFI_FVB2_WRITE_STATUS_STRING,
+ EFI_FVB2_LOCK_CAP_STRING,
+ EFI_FVB2_LOCK_STATUS_STRING,
NULL,
- EFI_FVB2_STICKY_WRITE_STRING,
- EFI_FVB2_MEMORY_MAPPED_STRING,
- EFI_FVB2_ERASE_POLARITY_STRING,
- EFI_FVB2_READ_LOCK_CAP_STRING,
- EFI_FVB2_READ_LOCK_STATUS_STRING,
- EFI_FVB2_WRITE_LOCK_CAP_STRING,
- EFI_FVB2_WRITE_LOCK_STATUS_STRING
+ EFI_FVB2_STICKY_WRITE_STRING,
+ EFI_FVB2_MEMORY_MAPPED_STRING,
+ EFI_FVB2_ERASE_POLARITY_STRING,
+ EFI_FVB2_READ_LOCK_CAP_STRING,
+ EFI_FVB2_READ_LOCK_STATUS_STRING,
+ EFI_FVB2_WRITE_LOCK_CAP_STRING,
+ EFI_FVB2_WRITE_LOCK_STATUS_STRING
};
CHAR8 *mFvbAlignmentName[] = {
- EFI_FVB2_ALIGNMENT_1_STRING,
- EFI_FVB2_ALIGNMENT_2_STRING,
- EFI_FVB2_ALIGNMENT_4_STRING,
- EFI_FVB2_ALIGNMENT_8_STRING,
- EFI_FVB2_ALIGNMENT_16_STRING,
- EFI_FVB2_ALIGNMENT_32_STRING,
- EFI_FVB2_ALIGNMENT_64_STRING,
- EFI_FVB2_ALIGNMENT_128_STRING,
- EFI_FVB2_ALIGNMENT_256_STRING,
- EFI_FVB2_ALIGNMENT_512_STRING,
- EFI_FVB2_ALIGNMENT_1K_STRING,
- EFI_FVB2_ALIGNMENT_2K_STRING,
- EFI_FVB2_ALIGNMENT_4K_STRING,
- EFI_FVB2_ALIGNMENT_8K_STRING,
- EFI_FVB2_ALIGNMENT_16K_STRING,
- EFI_FVB2_ALIGNMENT_32K_STRING,
- EFI_FVB2_ALIGNMENT_64K_STRING,
+ EFI_FVB2_ALIGNMENT_1_STRING,
+ EFI_FVB2_ALIGNMENT_2_STRING,
+ EFI_FVB2_ALIGNMENT_4_STRING,
+ EFI_FVB2_ALIGNMENT_8_STRING,
+ EFI_FVB2_ALIGNMENT_16_STRING,
+ EFI_FVB2_ALIGNMENT_32_STRING,
+ EFI_FVB2_ALIGNMENT_64_STRING,
+ EFI_FVB2_ALIGNMENT_128_STRING,
+ EFI_FVB2_ALIGNMENT_256_STRING,
+ EFI_FVB2_ALIGNMENT_512_STRING,
+ EFI_FVB2_ALIGNMENT_1K_STRING,
+ EFI_FVB2_ALIGNMENT_2K_STRING,
+ EFI_FVB2_ALIGNMENT_4K_STRING,
+ EFI_FVB2_ALIGNMENT_8K_STRING,
+ EFI_FVB2_ALIGNMENT_16K_STRING,
+ EFI_FVB2_ALIGNMENT_32K_STRING,
+ EFI_FVB2_ALIGNMENT_64K_STRING,
EFI_FVB2_ALIGNMENT_128K_STRING,
EFI_FVB2_ALIGNMENT_256K_STRING,
- EFI_FVB2_ALIGNMNET_512K_STRING,
- EFI_FVB2_ALIGNMENT_1M_STRING,
- EFI_FVB2_ALIGNMENT_2M_STRING,
- EFI_FVB2_ALIGNMENT_4M_STRING,
- EFI_FVB2_ALIGNMENT_8M_STRING,
- EFI_FVB2_ALIGNMENT_16M_STRING,
- EFI_FVB2_ALIGNMENT_32M_STRING,
- EFI_FVB2_ALIGNMENT_64M_STRING,
+ EFI_FVB2_ALIGNMENT_512K_STRING,
+ EFI_FVB2_ALIGNMENT_1M_STRING,
+ EFI_FVB2_ALIGNMENT_2M_STRING,
+ EFI_FVB2_ALIGNMENT_4M_STRING,
+ EFI_FVB2_ALIGNMENT_8M_STRING,
+ EFI_FVB2_ALIGNMENT_16M_STRING,
+ EFI_FVB2_ALIGNMENT_32M_STRING,
+ EFI_FVB2_ALIGNMENT_64M_STRING,
EFI_FVB2_ALIGNMENT_128M_STRING,
EFI_FVB2_ALIGNMENT_256M_STRING,
EFI_FVB2_ALIGNMENT_512M_STRING,
- EFI_FVB2_ALIGNMENT_1G_STRING,
+ EFI_FVB2_ALIGNMENT_1G_STRING,
EFI_FVB2_ALIGNMENT_2G_STRING
};
@@ -158,6 +165,10 @@ UINT8 m64kRecoveryStartupApDataArray[SIZEOF_ST
FV_INFO mFvDataInfo;
CAP_INFO mCapDataInfo;
+BOOLEAN mIsLargeFfs = FALSE;
+
+EFI_PHYSICAL_ADDRESS mFvBaseAddress[0x10];
+UINT32 mFvBaseAddressNumber = 0;
EFI_STATUS
ParseFvInf (
@@ -182,7 +193,7 @@ Returns:
EFI_NOT_FOUND A required string was not found in the INF file.
--*/
{
- CHAR8 Value[_MAX_PATH];
+ CHAR8 Value[MAX_LONG_FILE_PATH];
UINT64 Value64;
UINTN Index;
UINTN Number;
@@ -206,6 +217,7 @@ Returns:
DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);
FvInfo->BaseAddress = Value64;
+ FvInfo->BaseAddressSet = TRUE;
}
}
@@ -246,7 +258,7 @@ Returns:
//
strcpy (FvInfo->FvName, Value);
}
-
+
//
// Read Fv Attribute
//
@@ -275,6 +287,19 @@ Returns:
}
}
+ //
+ // Read weak alignment flag
+ //
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_WEAK_ALIGNMENT_STRING, 0, Value);
+ if (Status == EFI_SUCCESS) {
+ if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) {
+ FvInfo->FvAttributes |= EFI_FVB2_WEAK_ALIGNMENT;
+ } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Weak alignment value expected one of TRUE, FALSE, 1 or 0.");
+ return EFI_ABORTED;
+ }
+ }
+
//
// Read block maps
//
@@ -350,7 +375,7 @@ Returns:
}
}
- for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
+ for (Index = 0; Number + Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
//
// Read the FFS file list
//
@@ -384,7 +409,7 @@ UpdateFfsFileState (
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.
+ of the FV. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY.
Arguments:
@@ -439,58 +464,98 @@ Returns:
case 0:
//
- // 8 byte alignment, mini alignment requirement for FFS file.
+ // 1 byte alignment
+ //if bit 1 have set, 128K byte alignmnet
//
- *Alignment = 3;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 17;
+ } else {
+ *Alignment = 0;
+ }
break;
case 1:
//
// 16 byte alignment
+ //if bit 1 have set, 256K byte alignment
//
- *Alignment = 4;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 18;
+ } else {
+ *Alignment = 4;
+ }
break;
case 2:
//
// 128 byte alignment
+ //if bit 1 have set, 512K byte alignment
//
- *Alignment = 7;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 19;
+ } else {
+ *Alignment = 7;
+ }
break;
case 3:
//
// 512 byte alignment
+ //if bit 1 have set, 1M byte alignment
//
- *Alignment = 9;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 20;
+ } else {
+ *Alignment = 9;
+ }
break;
case 4:
//
// 1K byte alignment
+ //if bit 1 have set, 2M byte alignment
//
- *Alignment = 10;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 21;
+ } else {
+ *Alignment = 10;
+ }
break;
case 5:
//
// 4K byte alignment
+ //if bit 1 have set, 4M byte alignment
//
- *Alignment = 12;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 22;
+ } else {
+ *Alignment = 12;
+ }
break;
case 6:
//
// 32K byte alignment
+ //if bit 1 have set , 8M byte alignment
//
- *Alignment = 15;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 23;
+ } else {
+ *Alignment = 15;
+ }
break;
case 7:
//
// 64K byte alignment
+ //if bit 1 have set, 16M alignment
//
- *Alignment = 16;
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
+ *Alignment = 24;
+ } else {
+ *Alignment = 16;
+ }
break;
default:
@@ -505,7 +570,8 @@ AddPadFile (
IN OUT MEMORY_FILE *FvImage,
IN UINT32 DataAlignment,
IN VOID *FvEnd,
- IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader
+ IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader,
+ IN UINT32 NextFfsSize
)
/*++
@@ -520,7 +586,7 @@ Arguments:
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
+ ExtHeader PI FvExtHeader Optional
Returns:
@@ -533,7 +599,12 @@ Returns:
{
EFI_FFS_FILE_HEADER *PadFile;
UINTN PadFileSize;
+ UINT32 NextFfsHeaderSize;
+ UINT32 CurFfsHeaderSize;
+ UINT32 Index;
+ Index = 0;
+ CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);
//
// Verify input parameters.
//
@@ -541,43 +612,45 @@ Returns:
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
- //
- PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
-
//
// Append extension header size
//
if (ExtHeader != NULL) {
- PadFileSize = PadFileSize + ExtHeader->ExtHeaderSize;
+ PadFileSize = ExtHeader->ExtHeaderSize;
+ if (PadFileSize + sizeof (EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) {
+ CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
+ }
+ PadFileSize += CurFfsHeaderSize;
+ } else {
+ NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);
+ if (NextFfsSize >= MAX_FFS_SIZE) {
+ NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
+ }
+ //
+ // Check if a pad file is necessary
+ //
+ if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + NextFfsHeaderSize) % DataAlignment == 0) {
+ return EFI_SUCCESS;
+ }
+ PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER) + NextFfsHeaderSize;
+ //
+ // Add whatever it takes to get to the next aligned address
+ //
+ while ((PadFileSize % DataAlignment) != 0) {
+ PadFileSize++;
+ }
+ //
+ // Subtract the next file header size
+ //
+ PadFileSize -= NextFfsHeaderSize;
+ //
+ // Subtract the starting offset to get size
+ //
+ PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
}
//
@@ -601,9 +674,15 @@ Returns:
//
// 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);
+ if (PadFileSize >= MAX_FFS_SIZE) {
+ memset(PadFile->Size, 0, sizeof(UINT8) * 3);
+ ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = PadFileSize;
+ PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
+ } else {
+ 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.
@@ -611,7 +690,7 @@ Returns:
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));
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, CurFfsHeaderSize);
PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
@@ -629,14 +708,27 @@ Returns:
//
// Copy Fv Extension Header and Set Fv Extension header offset
//
- memcpy (PadFile + 1, ExtHeader, ExtHeader->ExtHeaderSize);
- ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) (PadFile + 1) - (UINTN) FvImage->FileImage);
- //
- // Make next file start at QWord Boundry
- //
- while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {
- FvImage->CurrentFilePointer++;
- }
+ if (ExtHeader->ExtHeaderSize > sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER)) {
+ for (Index = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); Index < ExtHeader->ExtHeaderSize;) {
+ if (((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntryType == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {
+ if (VtfFileFlag) {
+ ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTotalSize;
+ } else {
+ ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTakenSize;
+ }
+ break;
+ }
+ Index += ((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntrySize;
+ }
+ }
+ memcpy ((UINT8 *)PadFile + CurFfsHeaderSize, ExtHeader, ExtHeader->ExtHeaderSize);
+ ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) ((UINT8 *)PadFile + CurFfsHeaderSize) - (UINTN) FvImage->FileImage);
+ //
+ // Make next file start at QWord Boundry
+ //
+ while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {
+ FvImage->CurrentFilePointer++;
+ }
}
return EFI_SUCCESS;
@@ -674,7 +766,7 @@ EFI_STATUS
WriteMapFile (
IN OUT FILE *FvMapFile,
IN CHAR8 *FileName,
- IN EFI_GUID *FileGuidPtr,
+ IN EFI_FFS_FILE_HEADER *FfsFile,
IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,
IN PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext
)
@@ -689,7 +781,7 @@ Arguments:
FvMapFile A pointer to FvMap File
FileName Ffs File PathName
- FileGuidPtr Guid Value of Ffs file
+ FfsFile A pointer to Ffs file image.
ImageBaseAddress PeImage Base Address.
pImageContext Image Context Information.
@@ -699,7 +791,7 @@ Returns:
--*/
{
- CHAR8 PeMapFileName [_MAX_PATH];
+ CHAR8 PeMapFileName [MAX_LONG_FILE_PATH];
CHAR8 *Cptr, *Cptr2;
CHAR8 FileGuidName [MAX_LINE_LEN];
FILE *PeMapFile;
@@ -715,21 +807,29 @@ Returns:
EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
EFI_TE_IMAGE_HEADER *TEImageHeader;
EFI_IMAGE_SECTION_HEADER *SectionHeader;
- unsigned long long TempLongAddress;
+ long long TempLongAddress;
+ UINT32 TextVirtualAddress;
+ UINT32 DataVirtualAddress;
+ EFI_PHYSICAL_ADDRESS LinkTimeBaseAddress;
+
//
// Init local variable
//
FunctionType = 0;
//
- // Print FileGuid to string buffer.
+ // Print FileGuid to string buffer.
//
- PrintGuidToBuffer (FileGuidPtr, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);
-
+ PrintGuidToBuffer (&FfsFile->Name, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);
+
//
- // Construct Map file Name
+ // Construct Map file Name
//
- strcpy (PeMapFileName, FileName);
-
+ if (strlen (FileName) >= MAX_LONG_FILE_PATH) {
+ return EFI_ABORTED;
+ }
+ strncpy (PeMapFileName, FileName, MAX_LONG_FILE_PATH - 1);
+ PeMapFileName[MAX_LONG_FILE_PATH - 1] = 0;
+
//
// Change '\\' to '/', unified path format.
//
@@ -740,10 +840,10 @@ Returns:
}
Cptr ++;
}
-
+
//
// Get Map file
- //
+ //
Cptr = PeMapFileName + strlen (PeMapFileName);
while ((*Cptr != '.') && (Cptr >= PeMapFileName)) {
Cptr --;
@@ -764,68 +864,88 @@ Returns:
while ((*Cptr != FILE_SEP_CHAR) && (Cptr >= PeMapFileName)) {
Cptr --;
}
- *Cptr2 = '\0';
- strcpy (KeyWord, Cptr + 1);
- *Cptr2 = '.';
+ *Cptr2 = '\0';
+ if (strlen (Cptr + 1) >= MAX_LINE_LEN) {
+ return EFI_ABORTED;
+ }
+ strncpy (KeyWord, Cptr + 1, MAX_LINE_LEN - 1);
+ KeyWord[MAX_LINE_LEN - 1] = 0;
+ *Cptr2 = '.';
//
// AddressOfEntryPoint and Offset in Image
//
if (!pImageContext->IsTeImage) {
- ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset);
- AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
- Offset = 0;
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset);
+ AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
+ Offset = 0;
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
(UINT8 *) ImgHdr +
- sizeof (UINT32) +
- sizeof (EFI_IMAGE_FILE_HEADER) +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
);
Index = ImgHdr->Pe32.FileHeader.NumberOfSections;
} else {
- TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle;
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle;
AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint;
Offset = TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);
Index = TEImageHeader->NumberOfSections;
}
-
+
//
// module information output
//
if (ImageBaseAddress == 0) {
fprintf (FvMapFile, "%s (dummy) (", KeyWord);
- fprintf (FvMapFile, "BaseAddress=%08llx, ", (unsigned long long) ImageBaseAddress);
+ fprintf (FvMapFile, "BaseAddress=%010llx, ", (unsigned long long) ImageBaseAddress);
+ } else {
+ fprintf (FvMapFile, "%s (Fixed Flash Address, ", KeyWord);
+ fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset));
+ }
+
+ 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, "%s (", KeyWord);
- fprintf (FvMapFile, "BaseAddress=%08llx, ", (unsigned long long) (ImageBaseAddress + Offset));
+ fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));
}
- fprintf (FvMapFile, "EntryPoint=%08llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));
- fprintf (FvMapFile, "GUID=%s", FileGuidName);
- fprintf (FvMapFile, ")\n");
-
+ fprintf (FvMapFile, ")\n");
+
+ fprintf (FvMapFile, "(GUID=%s", FileGuidName);
+ TextVirtualAddress = 0;
+ DataVirtualAddress = 0;
for (; Index > 0; Index --, SectionHeader ++) {
- if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {
- fprintf (FvMapFile, ".textbaseaddress=%08llx ", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));
- } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {
- fprintf (FvMapFile, ".databaseaddress=%08llx ", (unsigned long long) (ImageBaseAddress + SectionHeader->VirtualAddress));
- }
+ if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {
+ TextVirtualAddress = SectionHeader->VirtualAddress;
+ } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {
+ DataVirtualAddress = SectionHeader->VirtualAddress;
+ } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".sdata") == 0) {
+ DataVirtualAddress = SectionHeader->VirtualAddress;
+ }
}
- fprintf (FvMapFile, "\n\n");
-
+ fprintf (FvMapFile, " .textbaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + TextVirtualAddress));
+ fprintf (FvMapFile, " .databaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + DataVirtualAddress));
+ fprintf (FvMapFile, ")\n\n");
+
//
// Open PeMapFile
//
- PeMapFile = fopen (PeMapFileName, "r");
+ PeMapFile = fopen (LongFilePath (PeMapFileName), "r");
if (PeMapFile == NULL) {
// fprintf (stdout, "can't open %s file to reading\n", PeMapFileName);
return EFI_ABORTED;
}
VerboseMsg ("The map file is %s", PeMapFileName);
-
+
//
// Output Functions information into Fv Map file
//
+ LinkTimeBaseAddress = 0;
while (fgets (Line, MAX_LINE_LEN, PeMapFile) != NULL) {
//
// Skip blank line
@@ -836,7 +956,7 @@ Returns:
}
//
// By Address and Static keyword
- //
+ //
if (FunctionType == 0) {
sscanf (Line, "%s", KeyWord);
if (stricmp (KeyWord, "Address") == 0) {
@@ -851,6 +971,9 @@ Returns:
//
FunctionType = 2;
fgets (Line, MAX_LINE_LEN, PeMapFile);
+ } else if (stricmp (KeyWord, "Preferred") ==0) {
+ sscanf (Line + strlen (" Preferred load address is"), "%llx", &TempLongAddress);
+ LinkTimeBaseAddress = (UINT64) TempLongAddress;
}
continue;
}
@@ -861,24 +984,14 @@ Returns:
sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);
FunctionAddress = (UINT64) TempLongAddress;
if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {
- fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
- fprintf (FvMapFile, "(%08llx) F ", (unsigned long long) (FunctionAddress - Offset));
- fprintf (FvMapFile, "%s\n", FunctionName);
- } else {
- fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
- fprintf (FvMapFile, "(%08llx) ", (unsigned long long) (FunctionAddress - Offset));
+ fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));
fprintf (FvMapFile, "%s\n", FunctionName);
}
} else if (FunctionType == 2) {
sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);
FunctionAddress = (UINT64) TempLongAddress;
if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {
- fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
- fprintf (FvMapFile, "(%08llx) FS ", (unsigned long long) (FunctionAddress - Offset));
- fprintf (FvMapFile, "%s\n", FunctionName);
- } else {
- fprintf (FvMapFile, " %016llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress));
- fprintf (FvMapFile, "(%08llx) ", (unsigned long long) (FunctionAddress - Offset));
+ fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));
fprintf (FvMapFile, "%s\n", FunctionName);
}
}
@@ -888,17 +1001,165 @@ Returns:
//
fprintf (FvMapFile, "\n\n");
fclose (PeMapFile);
-
+
return EFI_SUCCESS;
}
+STATIC
+BOOLEAN
+AdjustInternalFfsPadding (
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,
+ IN OUT MEMORY_FILE *FvImage,
+ IN UINTN Alignment,
+ IN OUT UINTN *FileSize
+ )
+/*++
+
+Routine Description:
+
+ This function looks for a dedicated alignment padding section in the FFS, and
+ shrinks it to the size required to line up subsequent sections correctly.
+
+Arguments:
+
+ FfsFile A pointer to Ffs file image.
+ FvImage The memory image of the FV to adjust it to.
+ Alignment Current file alignment
+ FileSize Reference to a variable holding the size of the FFS file
+
+Returns:
+
+ TRUE Padding section was found and updated successfully
+ FALSE Otherwise
+
+--*/
+{
+ EFI_FILE_SECTION_POINTER PadSection;
+ UINT8 *Remainder;
+ EFI_STATUS Status;
+ UINT32 FfsHeaderLength;
+ UINT32 FfsFileLength;
+ UINT32 PadSize;
+ UINTN Misalignment;
+ EFI_FFS_INTEGRITY_CHECK *IntegrityCheck;
+
+ //
+ // Figure out the misalignment: all FFS sections are aligned relative to the
+ // start of the FFS payload, so use that as the base of the misalignment
+ // computation.
+ //
+ FfsHeaderLength = GetFfsHeaderLength(FfsFile);
+ Misalignment = (UINTN) FvImage->CurrentFilePointer -
+ (UINTN) FvImage->FileImage + FfsHeaderLength;
+ Misalignment &= Alignment - 1;
+ if (Misalignment == 0) {
+ // Nothing to do, return success
+ return TRUE;
+ }
+
+ //
+ // We only apply this optimization to FFS files with the FIXED attribute set,
+ // since the FFS will not be loadable at arbitrary offsets anymore after
+ // we adjust the size of the padding section.
+ //
+ if ((FfsFile->Attributes & FFS_ATTRIB_FIXED) == 0) {
+ return FALSE;
+ }
+
+ //
+ // Look for a dedicated padding section that we can adjust to compensate
+ // for the misalignment. If such a padding section exists, it precedes all
+ // sections with alignment requirements, and so the adjustment will correct
+ // all of them.
+ //
+ Status = GetSectionByType (FfsFile, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 1,
+ &PadSection);
+ if (EFI_ERROR (Status) ||
+ CompareGuid (&PadSection.FreeformSubtypeSection->SubTypeGuid,
+ &mEfiFfsSectionAlignmentPaddingGuid) != 0) {
+ return FALSE;
+ }
+
+ //
+ // Find out if the size of the padding section is sufficient to compensate
+ // for the misalignment.
+ //
+ PadSize = GetSectionFileLength (PadSection.CommonHeader);
+ if (Misalignment > PadSize - sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION)) {
+ return FALSE;
+ }
+
+ //
+ // Move the remainder of the FFS file towards the front, and adjust the
+ // file size output parameter.
+ //
+ Remainder = (UINT8 *) PadSection.CommonHeader + PadSize;
+ memmove (Remainder - Misalignment, Remainder,
+ *FileSize - (UINTN) (Remainder - (UINTN) FfsFile));
+ *FileSize -= Misalignment;
+
+ //
+ // Update the padding section's length with the new values. Note that the
+ // padding is always < 64 KB, so we can ignore EFI_COMMON_SECTION_HEADER2
+ // ExtendedSize.
+ //
+ PadSize -= Misalignment;
+ PadSection.CommonHeader->Size[0] = (UINT8) (PadSize & 0xff);
+ PadSection.CommonHeader->Size[1] = (UINT8) ((PadSize & 0xff00) >> 8);
+ PadSection.CommonHeader->Size[2] = (UINT8) ((PadSize & 0xff0000) >> 16);
+
+ //
+ // Update the FFS header with the new overall length
+ //
+ FfsFileLength = GetFfsFileLength (FfsFile) - Misalignment;
+ if (FfsHeaderLength > sizeof(EFI_FFS_FILE_HEADER)) {
+ ((EFI_FFS_FILE_HEADER2 *)FfsFile)->ExtendedSize = FfsFileLength;
+ } else {
+ FfsFile->Size[0] = (UINT8) (FfsFileLength & 0x000000FF);
+ FfsFile->Size[1] = (UINT8) ((FfsFileLength & 0x0000FF00) >> 8);
+ FfsFile->Size[2] = (UINT8) ((FfsFileLength & 0x00FF0000) >> 16);
+ }
+
+ //
+ // Clear the alignment bits: these have become meaningless now that we have
+ // adjusted the padding section.
+ //
+ FfsFile->Attributes &= ~(FFS_ATTRIB_DATA_ALIGNMENT | FFS_ATTRIB_DATA_ALIGNMENT2);
+
+ //
+ // Recalculate the FFS header checksum. Instead of setting Header and State
+ // both to zero, set Header to (UINT8)(-State) so State preserves its original
+ // value
+ //
+ IntegrityCheck = &FfsFile->IntegrityCheck;
+ IntegrityCheck->Checksum.Header = (UINT8) (0x100 - FfsFile->State);
+ IntegrityCheck->Checksum.File = 0;
+
+ IntegrityCheck->Checksum.Header = CalculateChecksum8 (
+ (UINT8 *) FfsFile, FfsHeaderLength);
+
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ //
+ // Ffs header checksum = zero, so only need to calculate ffs body.
+ //
+ IntegrityCheck->Checksum.File = CalculateChecksum8 (
+ (UINT8 *) FfsFile + FfsHeaderLength,
+ FfsFileLength - FfsHeaderLength);
+ } else {
+ IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ return TRUE;
+}
+
EFI_STATUS
AddFile (
IN OUT MEMORY_FILE *FvImage,
IN FV_INFO *FvInfo,
IN UINTN Index,
IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
- IN FILE *FvMapFile
+ IN FILE *FvMapFile,
+ IN FILE *FvReportFile
)
/*++
@@ -916,6 +1177,7 @@ Arguments:
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:
@@ -933,7 +1195,8 @@ Returns:
UINT32 CurrentFileAlignment;
EFI_STATUS Status;
UINTN Index1;
-
+ UINT8 FileGuidString[PRINTED_GUID_BUFFER_SIZE];
+
Index1 = 0;
//
// Verify input parameters.
@@ -945,7 +1208,7 @@ Returns:
//
// Read the file to add
//
- NewFile = fopen (FvInfo->FvFiles[Index], "rb");
+ NewFile = fopen (LongFilePath (FvInfo->FvFiles[Index]), "rb");
if (NewFile == NULL) {
Error (NULL, 0, 0001, "Error opening file", FvInfo->FvFiles[Index]);
@@ -962,6 +1225,7 @@ Returns:
//
FileBuffer = malloc (FileSize);
if (FileBuffer == NULL) {
+ fclose (NewFile);
Error (NULL, 0, 4001, "Resouce", "memory cannot be allocated!");
return EFI_OUT_OF_RESOURCES;
}
@@ -972,7 +1236,7 @@ Returns:
// Done with the file, from this point on we will just use the buffer read.
//
fclose (NewFile);
-
+
//
// Verify read successful
//
@@ -981,27 +1245,27 @@ Returns:
Error (NULL, 0, 0004, "Error reading file", FvInfo->FvFiles[Index]);
return EFI_ABORTED;
}
-
+
//
// For None PI Ffs file, directly add them into FvImage.
//
if (!FvInfo->IsPiFvImage) {
memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
if (FvInfo->SizeofFvFiles[Index] > FileSize) {
- FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index];
+ FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index];
} else {
- FvImage->CurrentFilePointer += FileSize;
+ FvImage->CurrentFilePointer += FileSize;
}
goto Done;
}
-
+
//
// Verify Ffs file
//
Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer);
if (EFI_ERROR (Status)) {
free (FileBuffer);
- Error (NULL, 0, 3000, "Invalid", "%s is a FFS file.", FvInfo->FvFiles[Index]);
+ Error (NULL, 0, 3000, "Invalid", "%s is not a valid FFS file.", FvInfo->FvFiles[Index]);
return EFI_INVALID_PARAMETER;
}
@@ -1021,6 +1285,7 @@ Returns:
if (CompareGuid ((EFI_GUID *) FileBuffer, &mFileGuidArray [Index1]) == 0) {
Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %uth file have the same file GUID.", (unsigned) Index1 + 1, (unsigned) Index + 1);
PrintGuid ((EFI_GUID *) FileBuffer);
+ free (FileBuffer);
return EFI_INVALID_PARAMETER;
}
}
@@ -1038,7 +1303,7 @@ Returns:
// Check if alignment is required
//
ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
-
+
//
// Find the largest alignment of all the FFS files in the FV
//
@@ -1057,20 +1322,28 @@ Returns:
//
// Sanity check. The file MUST align appropriately
//
- if (((UINTN) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {
+ if (((UINTN) *VtfFileImage + GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)FileBuffer) - (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 the PE or TE image in FileBuffer of FFS file for XIP
// Rebase for the debug genfvmap tool
//
- FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);
+ Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);
+ return Status;
+ }
//
// copy VTF File
//
memcpy (*VtfFileImage, FileBuffer, FileSize);
+
+ PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE);
+ fprintf (FvReportFile, "0x%08X %s\n", (unsigned)(UINTN) (((UINT8 *)*VtfFileImage) - (UINTN)FvImage->FileImage), FileGuidString);
+
free (FileBuffer);
DebugMsg (NULL, 0, 9, "Add VTF FFS file in FV image", NULL);
return EFI_SUCCESS;
@@ -1087,25 +1360,34 @@ Returns:
//
// Add pad file if necessary
//
- Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property.");
- free (FileBuffer);
- return EFI_ABORTED;
+ if (!AdjustInternalFfsPadding ((EFI_FFS_FILE_HEADER *) FileBuffer, FvImage,
+ 1 << CurrentFileAlignment, &FileSize)) {
+ Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL, FileSize);
+ if (EFI_ERROR (Status)) {
+ 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
//
if ((UINTN) (FvImage->CurrentFilePointer + FileSize) <= (UINTN) (*VtfFileImage)) {
//
- // Rebase the PE or TE image in FileBuffer of FFS file for XIP.
+ // Rebase the PE or TE image in FileBuffer of FFS file for XIP.
// Rebase Bs and Rt drivers for the debug genfvmap tool.
//
- FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);
+ Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);
+ return Status;
+ }
//
// Copy the file
//
memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
+ PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE);
+ fprintf (FvReportFile, "0x%08X %s\n", (unsigned) (FvImage->CurrentFilePointer - FvImage->FileImage), FileGuidString);
FvImage->CurrentFilePointer += FileSize;
} else {
Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add file %s.", FvInfo->FvFiles[Index]);
@@ -1119,7 +1401,7 @@ Returns:
FvImage->CurrentFilePointer++;
}
-Done:
+Done:
//
// Free allocated memory.
//
@@ -1155,6 +1437,7 @@ Returns:
{
EFI_FFS_FILE_HEADER *PadFile;
UINTN FileSize;
+ UINT32 FfsHeaderSize;
//
// If there is no VTF or the VTF naturally follows the previous file without a
@@ -1175,7 +1458,7 @@ Returns:
PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
//
- // write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
+ // write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
//
PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
PadFile->Attributes = 0;
@@ -1184,9 +1467,18 @@ Returns:
// 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);
+ if (FileSize >= MAX_FFS_SIZE) {
+ PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
+ memset(PadFile->Size, 0, sizeof(UINT8) * 3);
+ ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = FileSize;
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+ mIsLargeFfs = TRUE;
+ } else {
+ PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
+ PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
+ PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+ }
//
// Fill in checksums and state, must be zero during checksum calculation.
@@ -1194,7 +1486,7 @@ Returns:
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));
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, FfsHeaderSize);
PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
@@ -1262,6 +1554,8 @@ Returns:
UINT64 FitAddress;
FIT_TABLE *FitTablePtr;
BOOLEAN Vtf0Detected;
+ UINT32 FfsHeaderSize;
+ UINT32 SecHeaderSize;
//
// Verify input parameters
@@ -1324,8 +1618,9 @@ Returns:
return EFI_ABORTED;
}
+ SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);
Status = GetPe32Info (
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),
&EntryPoint,
&BaseOfCode,
&MachineType
@@ -1334,7 +1629,7 @@ Returns:
if (EFI_ERROR (Status)) {
Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core.");
return EFI_ABORTED;
- }
+ }
if (
Vtf0Detected &&
@@ -1353,9 +1648,9 @@ Returns:
// Physical address is FV base + offset of PE32 + offset of the entry point
//
SecCorePhysicalAddress = FvInfo->BaseAddress;
- SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
+ SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;
SecCorePhysicalAddress += EntryPoint;
- DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
+ DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
//
// Find the PEI Core
@@ -1378,8 +1673,9 @@ Returns:
return EFI_ABORTED;
}
+ SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);
Status = GetPe32Info (
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),
&EntryPoint,
&BaseOfCode,
&MachineType
@@ -1393,7 +1689,7 @@ Returns:
// Physical address is FV base + offset of PE32 + offset of the entry point
//
PeiCorePhysicalAddress = FvInfo->BaseAddress;
- PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
+ PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;
PeiCorePhysicalAddress += EntryPoint;
DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
@@ -1462,18 +1758,18 @@ Returns:
// Write lower 32 bits of physical address for Pei Core entry
//
*Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
-
+
//
// Write SecCore Entry point relative address into the jmp instruction in reset vector.
- //
+ //
Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_SEC_CORE_ENTRY_OFFSET);
-
+
Ia32SecEntryOffset = (INT32) (SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2));
if (Ia32SecEntryOffset <= -65536) {
Error (NULL, 0, 3000, "Invalid", "The SEC EXE file size is too large, it must be less than 64K.");
return STATUS_ERROR;
}
-
+
*(UINT16 *) Ia32ResetAddressPtr = (UINT16) Ia32SecEntryOffset;
//
@@ -1501,7 +1797,7 @@ Returns:
//
Status = FindApResetVectorPosition (FvImage, &BytePointer);
if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "Cannot find the appropriate location in FvImage to add Ap reset vector!");
+ 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;
}
}
@@ -1523,9 +1819,9 @@ Returns:
//
WordPointer = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2);
*WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
-
+
//
- // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV.
+ // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV.
//
IpiVector = (UINT32) (FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer));
DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", (unsigned) IpiVector);
@@ -1546,6 +1842,11 @@ Returns:
// 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 if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {
+ //
+ // Since the AArch64 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 {
Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", MachineType);
return EFI_ABORTED;
@@ -1558,9 +1859,10 @@ Returns:
VtfFile->IntegrityCheck.Checksum.File = 0;
VtfFile->State = 0;
if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ FfsHeaderSize = GetFfsHeaderLength(VtfFile);
VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
- (UINT8 *) (VtfFile + 1),
- GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_HEADER)
+ (UINT8 *) ((UINT8 *)VtfFile + FfsHeaderSize),
+ GetFfsFileLength (VtfFile) - FfsHeaderSize
);
} else {
VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
@@ -1571,254 +1873,474 @@ Returns:
return EFI_SUCCESS;
}
-
EFI_STATUS
-UpdateArmResetVectorIfNeeded (
- IN MEMORY_FILE *FvImage,
- IN FV_INFO *FvInfo
+FindCorePeSection(
+ IN VOID *FvImageBuffer,
+ IN UINT64 FvSize,
+ IN EFI_FV_FILETYPE FileType,
+ OUT EFI_FILE_SECTION_POINTER *Pe32Section
)
/*++
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.
+ Recursively searches the FV for the FFS file of specified type (typically
+ SEC or PEI core) and extracts the PE32 section for further processing.
Arguments:
- FvImage Memory file for the FV memory image
- FvInfo Information read from INF file.
+
+ FvImageBuffer Buffer containing FV data
+ FvSize Size of the FV
+ FileType Type of FFS file to search for
+ Pe32Section PE32 section pointer when FFS file is found.
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.
+ EFI_NOT_FOUND Core file not found.
--*/
{
- EFI_FFS_FILE_HEADER *PeiCoreFile;
- EFI_FFS_FILE_HEADER *SecCoreFile;
- EFI_STATUS Status;
- EFI_FILE_SECTION_POINTER Pe32Section;
- UINT32 EntryPoint;
- UINT32 BaseOfCode;
- UINT16 MachineType;
- EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
- EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
- INT32 ResetVector[4]; // 0 - is branch relative to SEC entry point
- // 1 - PEI Entry Point
- // 2 - movs pc,lr for a SWI handler
- // 3 - Place holder for Common Exception Handler
-
- //
- // Verify input parameters
- //
- if (FvImage == NULL || FvInfo == NULL) {
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER *OrigFvHeader;
+ UINT32 OrigFvLength;
+ EFI_FFS_FILE_HEADER *CoreFfsFile;
+ UINTN FvImageFileCount;
+ EFI_FFS_FILE_HEADER *FvImageFile;
+ UINTN EncapFvSectionCount;
+ EFI_FILE_SECTION_POINTER EncapFvSection;
+ EFI_FIRMWARE_VOLUME_HEADER *EncapsulatedFvHeader;
+
+ if (Pe32Section == NULL) {
return EFI_INVALID_PARAMETER;
}
+
//
- // Initialize FV library
+ // Initialize FV library, saving previous values
//
- InitializeFvLib (FvImage->FileImage, FvInfo->Size);
+ OrigFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NULL;
+ GetFvHeader (&OrigFvHeader, &OrigFvLength);
+ InitializeFvLib(FvImageBuffer, (UINT32)FvSize);
//
- // Find the Sec Core
+ // First see if we can obtain the file directly in outer FV
//
- Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
- if (EFI_ERROR (Status) || SecCoreFile == NULL) {
- //
- // Maybe hardware does SEC job and we only have PEI Core?
- //
+ Status = GetFileByType(FileType, 1, &CoreFfsFile);
+ if (!EFI_ERROR(Status) && (CoreFfsFile != NULL) ) {
//
- // Find the PEI Core. It may not exist if SEC loads DXE core directly
+ // Core found, now find PE32 or TE section
//
- PeiCorePhysicalAddress = 0;
- Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
- if (!EFI_ERROR (Status) && PeiCoreFile != NULL) {
- //
- // PEI Core found, now find PE32 or TE section
- //
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
- if (Status == EFI_NOT_FOUND) {
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
- }
-
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!");
- return EFI_ABORTED;
- }
-
- Status = GetPe32Info (
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
- &EntryPoint,
- &BaseOfCode,
- &MachineType
- );
-
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!");
- return EFI_ABORTED;
- }
- //
- // Physical address is FV base + offset of PE32 + offset of the entry point
- //
- PeiCorePhysicalAddress = FvInfo->BaseAddress;
- PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
- PeiCorePhysicalAddress += EntryPoint;
- DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
-
- if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
- memset (ResetVector, 0, sizeof (ResetVector));
- // Address of PEI Core, if we have one
- ResetVector[1] = (UINT32)PeiCorePhysicalAddress;
- }
-
- //
- // Copy to the beginning of the FV
- //
- memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector));
+ Status = GetSectionByType(CoreFfsFile, EFI_SECTION_PE32, 1, Pe32Section);
+ if (EFI_ERROR(Status)) {
+ Status = GetSectionByType(CoreFfsFile, EFI_SECTION_TE, 1, Pe32Section);
+ }
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "could not find a PE32 section in the core file.");
+ return EFI_ABORTED;
}
- return EFI_SUCCESS;
+ //
+ // Core PE/TE section, found, return
+ //
+ Status = EFI_SUCCESS;
+ goto EarlyExit;
}
-
+
//
- // Sec Core found, now find PE32 section
+ // File was not found, look for FV Image file
//
- Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
- if (Status == EFI_NOT_FOUND) {
- Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
+
+ // iterate through all FV image files in outer FV
+ for (FvImageFileCount = 1;; FvImageFileCount++) {
+
+ Status = GetFileByType(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, FvImageFileCount, &FvImageFile);
+
+ if (EFI_ERROR(Status) || (FvImageFile == NULL) ) {
+ // exit FV image file loop, no more found
+ break;
+ }
+
+ // Found an fv image file, look for an FV image section. The PI spec does not
+ // preclude multiple FV image sections so we loop accordingly.
+ for (EncapFvSectionCount = 1;; EncapFvSectionCount++) {
+
+ // Look for the next FV image section. The section search code will
+ // iterate into encapsulation sections. For example, it will iterate
+ // into an EFI_SECTION_GUID_DEFINED encapsulation section to find the
+ // EFI_SECTION_FIRMWARE_VOLUME_IMAGE sections contained therein.
+ Status = GetSectionByType(FvImageFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EncapFvSectionCount, &EncapFvSection);
+
+ if (EFI_ERROR(Status)) {
+ // exit section inner loop, no more found
+ break;
+ }
+
+ EncapsulatedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)EncapFvSection.FVImageSection + GetSectionHeaderLength(EncapFvSection.FVImageSection));
+
+ // recurse to search the encapsulated FV for this core file type
+ Status = FindCorePeSection(EncapsulatedFvHeader, EncapsulatedFvHeader->FvLength, FileType, Pe32Section);
+
+ if (!EFI_ERROR(Status)) {
+ // we found the core in the capsulated image, success
+ goto EarlyExit;
+ }
+
+ } // end encapsulated fv image section loop
+ } // end fv image file loop
+
+ // core was not found
+ Status = EFI_NOT_FOUND;
+
+EarlyExit:
+
+ // restore FV lib values
+ if(OrigFvHeader != NULL) {
+ InitializeFvLib(OrigFvHeader, OrigFvLength);
}
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file.");
- return EFI_ABORTED;
+ return Status;
+}
+
+EFI_STATUS
+GetCoreMachineType(
+ IN EFI_FILE_SECTION_POINTER Pe32Section,
+ OUT UINT16 *CoreMachineType
+ )
+/*++
+
+Routine Description:
+
+ Returns the machine type of a P32 image, typically SEC or PEI core.
+
+Arguments:
+
+ Pe32Section PE32 section data
+ CoreMachineType The extracted machine type
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 EntryPoint;
+ UINT32 BaseOfCode;
+
+ if (CoreMachineType == NULL) {
+ return EFI_INVALID_PARAMETER;
}
- Status = GetPe32Info (
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
- &EntryPoint,
- &BaseOfCode,
- &MachineType
- );
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core.");
+ Status = GetPe32Info(
+ (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),
+ &EntryPoint,
+ &BaseOfCode,
+ CoreMachineType
+ );
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "could not get the PE32 machine type for the core.");
return EFI_ABORTED;
}
-
- if (MachineType != EFI_IMAGE_MACHINE_ARMT) {
- //
- // If SEC is not ARM we have nothing to do
- //
- return EFI_SUCCESS;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetCoreEntryPointAddress(
+ IN VOID *FvImageBuffer,
+ IN FV_INFO *FvInfo,
+ IN EFI_FILE_SECTION_POINTER Pe32Section,
+ OUT EFI_PHYSICAL_ADDRESS *CoreEntryAddress
+)
+/*++
+
+Routine Description:
+
+ Returns the physical address of the core (SEC or PEI) entry point.
+
+Arguments:
+
+ FvImageBuffer Pointer to buffer containing FV data
+ FvInfo Info for the parent FV
+ Pe32Section PE32 section data
+ CoreEntryAddress The extracted core entry physical address
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_ABORTED Error encountered.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 EntryPoint;
+ UINT32 BaseOfCode;
+ UINT16 MachineType;
+ EFI_PHYSICAL_ADDRESS EntryPhysicalAddress;
+
+ if (CoreEntryAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GetPe32Info(
+ (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),
+ &EntryPoint,
+ &BaseOfCode,
+ &MachineType
+ );
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the core.");
+ return EFI_ABORTED;
}
-
+
//
// Physical address is FV base + offset of PE32 + offset of the entry point
//
- SecCorePhysicalAddress = FvInfo->BaseAddress;
- SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
- SecCorePhysicalAddress += EntryPoint;
- DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
+ EntryPhysicalAddress = FvInfo->BaseAddress;
+ EntryPhysicalAddress += (UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader) - (UINTN)FvImageBuffer;
+ EntryPhysicalAddress += EntryPoint;
+
+ *CoreEntryAddress = EntryPhysicalAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateArmResetVectorIfNeeded (
+ IN MEMORY_FILE *FvImage,
+ IN FV_INFO *FvInfo
+ )
+/*++
+
+Routine Description:
+ This parses the FV looking for SEC and patches that address into the
+ beginning of the FV header.
+
+ For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000.
+ For AArch64 the reset vector is at 0x00000000.
+
+ This would commonly map to the first entry in the ROM.
+ ARM32 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 (not done for AArch64, not enough space in struct).
+ 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.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FILE_SECTION_POINTER SecPe32;
+ EFI_FILE_SECTION_POINTER PeiPe32;
+ BOOLEAN UpdateVectorSec = FALSE;
+ BOOLEAN UpdateVectorPei = FALSE;
+ UINT16 MachineType = 0;
+ EFI_PHYSICAL_ADDRESS SecCoreEntryAddress = 0;
+ UINT16 PeiMachineType = 0;
+ EFI_PHYSICAL_ADDRESS PeiCoreEntryAddress = 0;
//
- // Find the PEI Core. It may not exist if SEC loads DXE core directly
+ // Verify input parameters
//
- PeiCorePhysicalAddress = 0;
- Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
- if (!EFI_ERROR (Status) && PeiCoreFile != NULL) {
- //
- // PEI Core found, now find PE32 or TE section
- //
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
- if (Status == EFI_NOT_FOUND) {
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
- }
-
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!");
+ if (FvImage == NULL || FvInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Locate an SEC Core instance and if found extract the machine type and entry point address
+ //
+ Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32);
+ if (!EFI_ERROR(Status)) {
+
+ Status = GetCoreMachineType(SecPe32, &MachineType);
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC Core.");
return EFI_ABORTED;
}
-
- Status = GetPe32Info (
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
- &EntryPoint,
- &BaseOfCode,
- &MachineType
- );
-
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!");
+
+ Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress);
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core.");
return EFI_ABORTED;
}
- //
- // Physical address is FV base + offset of PE32 + offset of the entry point
- //
- PeiCorePhysicalAddress = FvInfo->BaseAddress;
- PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
- PeiCorePhysicalAddress += EntryPoint;
- 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
- ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2;
-
- if (ResetVector[0] > 0x00FFFFFF) {
- Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");
- return EFI_ABORTED;
+
+ VerboseMsg("UpdateArmResetVectorIfNeeded found SEC core entry at 0x%llx", (unsigned long long)SecCoreEntryAddress);
+ UpdateVectorSec = TRUE;
}
-
- // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint
- ResetVector[0] |= 0xEA000000;
-
-
- // Address of PEI Core, if we have one
- ResetVector[1] = (UINT32)PeiCorePhysicalAddress;
-
- // SWI handler movs pc,lr. Just in case a debugger uses SWI
- ResetVector[2] = 0xE1B0F07E;
-
- // 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
+ // Locate a PEI Core instance and if found extract the machine type and entry point address
//
- memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector));
+ Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_PEI_CORE, &PeiPe32);
+ if (!EFI_ERROR(Status)) {
+
+ Status = GetCoreMachineType(PeiPe32, &PeiMachineType);
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for PEI Core.");
+ return EFI_ABORTED;
+ }
+
+ Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, PeiPe32, &PeiCoreEntryAddress);
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for PEI Core.");
+ return EFI_ABORTED;
+ }
+
+ VerboseMsg("UpdateArmResetVectorIfNeeded found PEI core entry at 0x%llx", (unsigned long long)PeiCoreEntryAddress);
+
+ // if we previously found an SEC Core make sure machine types match
+ if (UpdateVectorSec && (MachineType != PeiMachineType)) {
+ Error(NULL, 0, 3000, "Invalid", "SEC and PEI machine types do not match, can't update reset vector");
+ return EFI_ABORTED;
+ }
+ else {
+ MachineType = PeiMachineType;
+ }
+
+ UpdateVectorPei = TRUE;
+ }
+
+ if (!UpdateVectorSec && !UpdateVectorPei) {
+ return EFI_SUCCESS;
+ }
+
+ if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
+ // ARM: Array of 4 UINT32s:
+ // 0 - is branch relative to SEC entry point
+ // 1 - PEI Entry Point
+ // 2 - movs pc,lr for a SWI handler
+ // 3 - Place holder for Common Exception Handler
+ UINT32 ResetVector[4];
+
+ memset(ResetVector, 0, sizeof (ResetVector));
+
+ // if we found an SEC core entry point then generate a branch instruction
+ // to it and populate a debugger SWI entry as well
+ if (UpdateVectorSec) {
+
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM SEC vector");
+
+ // 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
+ ResetVector[0] = (INT32)(SecCoreEntryAddress - FvInfo->BaseAddress - 8) >> 2;
+
+ if (ResetVector[0] > 0x00FFFFFF) {
+ Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");
+ return EFI_ABORTED;
+ }
+
+ // Add opcode for an uncondional branch with no link. i.e.: " B SecEntryPoint"
+ ResetVector[0] |= ARMT_UNCONDITIONAL_JUMP_INSTRUCTION;
+
+ // SWI handler movs pc,lr. Just in case a debugger uses SWI
+ ResetVector[2] = 0xE1B0F07E;
+
+ // 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;
+ }
+
+ // if a PEI core entry was found place its address in the vector area
+ if (UpdateVectorPei) {
+
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM PEI address");
+
+ // Address of PEI Core, if we have one
+ ResetVector[1] = (UINT32)PeiCoreEntryAddress;
+ }
+
+ //
+ // Copy to the beginning of the FV
+ //
+ memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector));
+
+ } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {
+ // AArch64: Used as UINT64 ResetVector[2]
+ // 0 - is branch relative to SEC entry point
+ // 1 - PEI Entry Point
+ UINT64 ResetVector[2];
+
+ memset(ResetVector, 0, sizeof (ResetVector));
+
+ /* NOTE:
+ ARMT above has an entry in ResetVector[2] for SWI. The way we are using the ResetVector
+ array at the moment, for AArch64, does not allow us space for this as the header only
+ allows for a fixed amount of bytes at the start. If we are sure that UEFI will live
+ within the first 4GB of addressable RAM we could potensioally adopt the same ResetVector
+ layout as above. But for the moment we replace the four 32bit vectors with two 64bit
+ vectors in the same area of the Image heasder. This allows UEFI to start from a 64bit
+ base.
+ */
+
+ // if we found an SEC core entry point then generate a branch instruction to it
+ if (UpdateVectorSec) {
+
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 SEC vector");
+
+ ResetVector[0] = (UINT64)(SecCoreEntryAddress - FvInfo->BaseAddress) >> 2;
+
+ // B SecEntryPoint - signed_immed_26 part +/-128MB offset
+ if (ResetVector[0] > 0x03FFFFFF) {
+ Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 128MB of the start of the FV");
+ return EFI_ABORTED;
+ }
+ // Add opcode for an uncondional branch with no link. i.e.: " B SecEntryPoint"
+ ResetVector[0] |= ARM64_UNCONDITIONAL_JUMP_INSTRUCTION;
+ }
+
+ // if a PEI core entry was found place its address in the vector area
+ if (UpdateVectorPei) {
+
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 PEI address");
+
+ // Address of PEI Core, if we have one
+ ResetVector[1] = (UINT64)PeiCoreEntryAddress;
+ }
+
+ //
+ // Copy to the beginning of the FV
+ //
+ memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector));
- DebugMsg (NULL, 0, 9, "Update Reset vector in FV Header", NULL);
+ } else {
+ Error(NULL, 0, 3000, "Invalid", "Unknown machine type");
+ return EFI_ABORTED;
+ }
return EFI_SUCCESS;
}
@@ -1834,8 +2356,8 @@ GetPe32Info (
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
+ 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:
@@ -1877,13 +2399,13 @@ Returns:
*BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
*MachineType = TeHeader->Machine;
} else {
-
+
//
- // Then check whether
+ // Then check whether
// First is the DOS header
//
DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
-
+
//
// Verify DOS header is expected
//
@@ -1895,7 +2417,7 @@ Returns:
// Immediately following is the NT header.
//
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN) Pe32 + DosHeader->e_lfanew);
-
+
//
// Verify NT header is expected
//
@@ -1914,8 +2436,8 @@ Returns:
//
// 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 &&
- *MachineType != EFI_IMAGE_MACHINE_ARMT) {
+ if ((*MachineType != EFI_IMAGE_MACHINE_IA32) && (*MachineType != EFI_IMAGE_MACHINE_IA64) && (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) &&
+ (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64)) {
Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");
return EFI_UNSUPPORTED;
}
@@ -1962,15 +2484,20 @@ Returns:
UINT8 *FvImage;
UINTN FvImageSize;
FILE *FvFile;
- CHAR8 FvMapName [_MAX_PATH];
+ CHAR8 *FvMapName;
FILE *FvMapFile;
EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
FILE *FvExtHeaderFile;
UINTN FileSize;
+ CHAR8 *FvReportName;
+ FILE *FvReportFile;
FvBufferHeader = NULL;
FvFile = NULL;
+ FvMapName = NULL;
FvMapFile = NULL;
+ FvReportName = NULL;
+ FvReportFile = NULL;
if (InfFileImage != NULL) {
//
@@ -1979,7 +2506,7 @@ Returns:
InfMemoryFile.FileImage = InfFileImage;
InfMemoryFile.CurrentFilePointer = InfFileImage;
InfMemoryFile.Eof = InfFileImage + InfFileSize;
-
+
//
// Parse the FV inf file for header information
//
@@ -2001,17 +2528,17 @@ Returns:
Error (NULL, 0, 1001, "Missing option", "Output file name");
return EFI_ABORTED;
}
-
+
if (mFvDataInfo.FvBlocks[0].Length == 0) {
Error (NULL, 0, 1001, "Missing required argument", "Block Size");
return EFI_ABORTED;
}
-
+
//
// Debug message Fv File System Guid
//
if (mFvDataInfo.FvFileSystemGuidSet) {
- DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
(unsigned) mFvDataInfo.FvFileSystemGuid.Data1,
mFvDataInfo.FvFileSystemGuid.Data2,
mFvDataInfo.FvFileSystemGuid.Data3,
@@ -2034,7 +2561,11 @@ Returns:
//
// Open the FV Extension Header file
//
- FvExtHeaderFile = fopen (mFvDataInfo.FvExtHeaderFile, "rb");
+ FvExtHeaderFile = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");
+ if (FvExtHeaderFile == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile);
+ return EFI_ABORTED;
+ }
//
// Get the file size
@@ -2080,7 +2611,7 @@ Returns:
// Debug message Fv Name Guid
//
if (mFvDataInfo.FvNameGuidSet) {
- DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
(unsigned) mFvDataInfo.FvNameGuid.Data1,
mFvDataInfo.FvNameGuid.Data2,
mFvDataInfo.FvNameGuid.Data3,
@@ -2094,7 +2625,8 @@ Returns:
mFvDataInfo.FvNameGuid.Data4[7]);
}
- if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {
+ if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0 ||
+ CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem3Guid) == 0) {
mFvDataInfo.IsPiFvImage = TRUE;
}
@@ -2102,23 +2634,68 @@ Returns:
// FvMap file to log the function address of all modules in one Fvimage
//
if (MapFileName != NULL) {
+ if (strlen (MapFileName) > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 1003, "Invalid option value", "MapFileName %s is too long!", MapFileName);
+ Status = EFI_ABORTED;
+ goto Finish;
+ }
+
+ FvMapName = malloc (strlen (MapFileName) + 1);
+ if (FvMapName == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Finish;
+ }
+
strcpy (FvMapName, MapFileName);
} else {
+ if (strlen (FvFileName) + strlen (".map") > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName);
+ Status = EFI_ABORTED;
+ goto Finish;
+ }
+
+ FvMapName = malloc (strlen (FvFileName) + strlen (".map") + 1);
+ if (FvMapName == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Finish;
+ }
+
strcpy (FvMapName, FvFileName);
strcat (FvMapName, ".map");
}
VerboseMsg ("FV Map file name is %s", FvMapName);
+ //
+ // FvReport file to log the FV information in one Fvimage
+ //
+ if (strlen (FvFileName) + strlen (".txt") > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName);
+ Status = EFI_ABORTED;
+ goto Finish;
+ }
+
+ FvReportName = malloc (strlen (FvFileName) + strlen (".txt") + 1);
+ if (FvReportName == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Finish;
+ }
+
+ strcpy (FvReportName, FvFileName);
+ strcat (FvReportName, ".txt");
+
//
// Calculate the FV size and Update Fv Size based on the actual FFS files.
// And Update mFvDataInfo data.
//
Status = CalculateFvSize (&mFvDataInfo);
if (EFI_ERROR (Status)) {
- return Status;
+ goto Finish;
}
VerboseMsg ("the generated FV image size is %u bytes", (unsigned) mFvDataInfo.Size);
-
+
//
// support fv image and empty fv image
//
@@ -2129,7 +2706,8 @@ Returns:
//
FvBufferHeader = malloc (FvImageSize + sizeof (UINT64));
if (FvBufferHeader == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Finish;
}
FvImage = (UINT8 *) (((UINTN) FvBufferHeader + 7) & ~7);
@@ -2138,7 +2716,7 @@ Returns:
//
if (mFvDataInfo.FvAttributes == 0) {
//
- // Set Default Fv Attribute
+ // Set Default Fv Attribute
//
mFvDataInfo.FvAttributes = FV_DEFAULT_ATTRIBUTE;
}
@@ -2169,7 +2747,7 @@ Returns:
FvHeader->Revision = EFI_FVH_REVISION;
FvHeader->ExtHeaderOffset = 0;
FvHeader->Reserved[0] = 0;
-
+
//
// Copy firmware block map
//
@@ -2218,12 +2796,22 @@ Returns:
//
// Open FvMap file
//
- FvMapFile = fopen (FvMapName, "w");
+ FvMapFile = fopen (LongFilePath (FvMapName), "w");
if (FvMapFile == NULL) {
Error (NULL, 0, 0001, "Error opening file", FvMapName);
- return EFI_ABORTED;
+ Status = EFI_ABORTED;
+ goto Finish;
+ }
+
+ //
+ // Open FvReport file
+ //
+ FvReportFile = fopen (LongFilePath (FvReportName), "w");
+ if (FvReportFile == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", FvReportName);
+ Status = EFI_ABORTED;
+ goto Finish;
}
-
//
// record FV size information into FvMap file.
//
@@ -2240,6 +2828,12 @@ Returns:
fprintf (FvMapFile, " = 0x%x\n\n", (unsigned) (mFvTotalSize - mFvTakenSize));
}
+ //
+ // record FV size information to FvReportFile.
+ //
+ fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TOTAL_SIZE_STRING, (unsigned) mFvTotalSize);
+ fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TAKEN_SIZE_STRING, (unsigned) mFvTakenSize);
+
//
// Add PI FV extension header
//
@@ -2247,7 +2841,7 @@ Returns:
//
// Add FV Extended Header contents to the FV as a PAD file
//
- AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, FvExtHeader);
+ AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, FvExtHeader, 0);
//
// Fv Extension header change update Fv Header Check sum
@@ -2263,7 +2857,7 @@ Returns:
//
// Add the file
//
- Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile);
+ Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile, FvReportFile);
//
// Exit if error detected while adding the file
@@ -2289,40 +2883,43 @@ Returns:
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.
+ // Now for IA32 and IA64 platform, the fv which has bsf file must have the
+ // EndAddress of 0xFFFFFFFF (unless the section was rebased).
+ // 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.
//
- if ((mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
+ if (mFvDataInfo.ForceRebase == 1 ||
+ (mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
Status = UpdateResetVector (&FvImageMemoryFile, &mFvDataInfo, VtfFileImage);
- if (EFI_ERROR(Status)) {
+ if (EFI_ERROR(Status)) {
Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");
- goto Finish;
+ goto Finish;
}
DebugMsg (NULL, 0, 9, "Update Reset vector in VTF file", NULL);
}
}
- }
+ }
if (mArm) {
Status = UpdateArmResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status)) {
Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");
- goto Finish;
- }
-
+ goto Finish;
+ }
+
//
// Update Checksum for FvHeader
//
FvHeader->Checksum = 0;
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
//
- if ((((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {
+ if (((FvHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) &&
+ (((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {
FvHeader->Attributes = ((MaxFfsAlignment << 16) | (FvHeader->Attributes & 0xFFFF));
//
// Update Checksum for FvHeader
@@ -2331,11 +2928,20 @@ Returns:
FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
}
-WriteFile:
+ //
+ // If there are large FFS in FV, the file system GUID should set to system 3 GUID.
+ //
+ if (mIsLargeFfs && CompareGuid (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {
+ memcpy (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem3Guid, sizeof (EFI_GUID));
+ FvHeader->Checksum = 0;
+ FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
+ }
+
+WriteFile:
//
// Write fv file
//
- FvFile = fopen (FvFileName, "wb");
+ FvFile = fopen (LongFilePath (FvFileName), "wb");
if (FvFile == NULL) {
Error (NULL, 0, 0001, "Error opening file", FvFileName);
Status = EFI_ABORTED;
@@ -2356,15 +2962,29 @@ Finish:
if (FvExtHeader != NULL) {
free (FvExtHeader);
}
-
+
+ if (FvMapName != NULL) {
+ free (FvMapName);
+ }
+
+ if (FvReportName != NULL) {
+ free (FvReportName);
+ }
+
if (FvFile != NULL) {
+ fflush (FvFile);
fclose (FvFile);
}
-
+
if (FvMapFile != NULL) {
+ fflush (FvMapFile);
fclose (FvMapFile);
}
+ if (FvReportFile != NULL) {
+ fflush (FvReportFile);
+ fclose (FvReportFile);
+ }
return Status;
}
@@ -2461,13 +3081,12 @@ Returns:
UINTN FfsFileSize;
UINTN FvExtendHeaderSize;
UINT32 FfsAlignment;
+ UINT32 FfsHeaderSize;
EFI_FFS_FILE_HEADER FfsHeader;
- BOOLEAN VtfFileFlag;
UINTN VtfFileSize;
-
+
FvExtendHeaderSize = 0;
VtfFileSize = 0;
- VtfFileFlag = FALSE;
fpin = NULL;
Index = 0;
@@ -2478,31 +3097,36 @@ Returns:
for (Index = 0; FvInfoPtr->FvBlocks[Index].NumBlocks > 0 && FvInfoPtr->FvBlocks[Index].Length > 0; Index++) {
FvInfoPtr->Size += FvInfoPtr->FvBlocks[Index].NumBlocks * FvInfoPtr->FvBlocks[Index].Length;
}
-
+
//
- // Caculate the required sizes for all FFS files.
+ // Calculate the required sizes for all FFS files.
//
CurrentOffset = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
-
+
for (Index = 1;; Index ++) {
CurrentOffset += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
if (FvInfoPtr->FvBlocks[Index].NumBlocks == 0 || FvInfoPtr->FvBlocks[Index].Length == 0) {
break;
}
}
-
+
//
// Calculate PI extension header
//
if (mFvDataInfo.FvExtHeaderFile[0] != '\0') {
- fpin = fopen (mFvDataInfo.FvExtHeaderFile, "rb");
+ fpin = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");
if (fpin == NULL) {
Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile);
return EFI_ABORTED;
}
FvExtendHeaderSize = _filelength (fileno (fpin));
fclose (fpin);
- CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize;
+ if (sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize >= MAX_FFS_SIZE) {
+ CurrentOffset += sizeof (EFI_FFS_FILE_HEADER2) + FvExtendHeaderSize;
+ mIsLargeFfs = TRUE;
+ } else {
+ CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize;
+ }
CurrentOffset = (CurrentOffset + 7) & (~7);
} else if (mFvDataInfo.FvNameGuidSet) {
CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);
@@ -2517,7 +3141,7 @@ Returns:
// Open FFS file
//
fpin = NULL;
- fpin = fopen (FvInfoPtr->FvFiles[Index], "rb");
+ fpin = fopen (LongFilePath (FvInfoPtr->FvFiles[Index]), "rb");
if (fpin == NULL) {
Error (NULL, 0, 0001, "Error opening file", FvInfoPtr->FvFiles[Index]);
return EFI_ABORTED;
@@ -2526,6 +3150,12 @@ Returns:
// Get the file size
//
FfsFileSize = _filelength (fileno (fpin));
+ if (FfsFileSize >= MAX_FFS_SIZE) {
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
+ mIsLargeFfs = TRUE;
+ } else {
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
+ }
//
// Read Ffs File header
//
@@ -2534,57 +3164,61 @@ Returns:
// close file
//
fclose (fpin);
-
+
if (FvInfoPtr->IsPiFvImage) {
- //
- // Check whether this ffs file is vtf file
- //
- if (IsVtfFile (&FfsHeader)) {
- if (VtfFileFlag) {
- //
- // One Fv image can't have two vtf files.
- //
- return EFI_ABORTED;
- }
- VtfFileFlag = TRUE;
+ //
+ // Check whether this ffs file is vtf file
+ //
+ if (IsVtfFile (&FfsHeader)) {
+ if (VtfFileFlag) {
+ //
+ // One Fv image can't have two vtf files.
+ //
+ Error (NULL, 0, 3000,"Invalid", "One Fv image can't have two vtf files.");
+ return EFI_ABORTED;
+ }
+ VtfFileFlag = TRUE;
VtfFileSize = FfsFileSize;
continue;
}
//
- // Get the alignment of FFS file
+ // Get the alignment of FFS file
//
ReadFfsAlignment (&FfsHeader, &FfsAlignment);
FfsAlignment = 1 << FfsAlignment;
//
// Add Pad file
//
- if (((CurrentOffset + sizeof (EFI_FFS_FILE_HEADER)) % FfsAlignment) != 0) {
- CurrentOffset = (CurrentOffset + sizeof (EFI_FFS_FILE_HEADER) * 2 + FfsAlignment - 1) & ~(FfsAlignment - 1);
- CurrentOffset -= sizeof (EFI_FFS_FILE_HEADER);
+ if (((CurrentOffset + FfsHeaderSize) % FfsAlignment) != 0) {
+ //
+ // Only EFI_FFS_FILE_HEADER is needed for a pad section.
+ //
+ CurrentOffset = (CurrentOffset + FfsHeaderSize + sizeof(EFI_FFS_FILE_HEADER) + FfsAlignment - 1) & ~(FfsAlignment - 1);
+ CurrentOffset -= FfsHeaderSize;
}
- }
+ }
//
// Add ffs file size
//
if (FvInfoPtr->SizeofFvFiles[Index] > FfsFileSize) {
- CurrentOffset += FvInfoPtr->SizeofFvFiles[Index];
+ CurrentOffset += FvInfoPtr->SizeofFvFiles[Index];
} else {
- CurrentOffset += FfsFileSize;
+ CurrentOffset += FfsFileSize;
}
-
+
//
// 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);
+ CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
}
}
CurrentOffset += VtfFileSize;
- 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);
-
- if (FvInfoPtr->Size == 0) {
+ DebugMsg (NULL, 0, 9, "FvImage size", "The calculated fv image size is 0x%x and the current set fv image size is 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size);
+
+ if (FvInfoPtr->Size == 0) {
//
// Update FvInfo data
//
@@ -2599,7 +3233,7 @@ Returns:
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
//
@@ -2653,9 +3287,83 @@ Returns:
}
EFI_STATUS
-FfsRebase (
- IN OUT FV_INFO *FvInfo,
- IN CHAR8 *FileName,
+GetChildFvFromFfs (
+ IN FV_INFO *FvInfo,
+ IN EFI_FFS_FILE_HEADER *FfsFile,
+ IN UINTN XipOffset
+ )
+/*++
+
+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.
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_FILE_SECTION_POINTER SubFvSection;
+ EFI_FIRMWARE_VOLUME_HEADER *SubFvImageHeader;
+ EFI_PHYSICAL_ADDRESS SubFvBaseAddress;
+ EFI_FILE_SECTION_POINTER CorePe32;
+ UINT16 MachineType;
+
+ for (Index = 1;; Index++) {
+ //
+ // Find FV section
+ //
+ Status = GetSectionByType (FfsFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, Index, &SubFvSection);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + GetSectionHeaderLength(SubFvSection.FVImageSection));
+
+ //
+ // See if there's an SEC core in the child FV
+ Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_SECURITY_CORE, &CorePe32);
+
+ // if we couldn't find the SEC core, look for a PEI core
+ if (EFI_ERROR(Status)) {
+ Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_PEI_CORE, &CorePe32);
+ }
+
+ if (!EFI_ERROR(Status)) {
+ Status = GetCoreMachineType(CorePe32, &MachineType);
+ if (EFI_ERROR(Status)) {
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC/PEI Core.");
+ return EFI_ABORTED;
+ }
+
+ // machine type is ARM, set a flag so ARM reset vector procesing occurs
+ if ((MachineType == EFI_IMAGE_MACHINE_ARMT) || (MachineType == EFI_IMAGE_MACHINE_AARCH64)) {
+ VerboseMsg("Located ARM/AArch64 SEC/PEI core in child FV");
+ mArm = TRUE;
+ }
+ }
+
+ //
+ // Rebase on Flash
+ //
+ SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset;
+ mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FfsRebase (
+ IN OUT FV_INFO *FvInfo,
+ IN CHAR8 *FileName,
IN OUT EFI_FFS_FILE_HEADER *FfsFile,
IN UINTN XipOffset,
IN FILE *FvMapFile
@@ -2668,7 +3376,7 @@ Routine Description:
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.
@@ -2687,28 +3395,27 @@ Returns:
{
EFI_STATUS Status;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
- PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext;
+ PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext;
EFI_PHYSICAL_ADDRESS XipBase;
EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;
- EFI_PHYSICAL_ADDRESS *BaseToUpdate;
UINTN Index;
EFI_FILE_SECTION_POINTER CurrentPe32Section;
EFI_FFS_FILE_STATE SavedState;
EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
EFI_TE_IMAGE_HEADER *TEImageHeader;
- UINT8 Flags;
UINT8 *MemoryImagePointer;
EFI_IMAGE_SECTION_HEADER *SectionHeader;
- CHAR8 PeFileName [_MAX_PATH];
+ CHAR8 PeFileName [MAX_LONG_FILE_PATH];
CHAR8 *Cptr;
FILE *PeFile;
UINT8 *PeFileBuffer;
UINT32 PeFileSize;
CHAR8 *PdbPointer;
+ UINT32 FfsHeaderSize;
+ UINT32 CurSecHdrSize;
- Index = 0;
+ Index = 0;
MemoryImagePointer = NULL;
- BaseToUpdate = NULL;
TEImageHeader = NULL;
ImgHdr = NULL;
SectionHeader = NULL;
@@ -2717,26 +3424,21 @@ Returns:
PeFileBuffer = NULL;
//
- // Check XipAddress, BootAddress and RuntimeAddress
+ // Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified.
//
- Flags = 0;
- XipBase = 0;
- if (FvInfo->BaseAddress != 0) {
- Flags |= REBASE_XIP_FILE;
- XipBase = FvInfo->BaseAddress + XipOffset;
- }
- if (FvInfo->BootBaseAddress != 0) {
- Flags |= REBASE_BOOTTIME_FILE;
- }
- if (FvInfo->RuntimeBaseAddress != 0) {
- Flags |= REBASE_RUNTIME_FILE;
+ if ((FvInfo->BaseAddress == 0) && (FvInfo->ForceRebase == -1)) {
+ return EFI_SUCCESS;
}
//
- // Don't Rebase this FFS.
- // Only copy the original map file into the FvMap file
- // for the image that is not required to be relocated.
+ // If ForceRebase Flag specified to FALSE, will always not take rebase action.
//
+ if (FvInfo->ForceRebase == 0) {
+ return EFI_SUCCESS;
+ }
+
+
+ XipBase = FvInfo->BaseAddress + XipOffset;
//
// We only process files potentially containing PE32 sections.
@@ -2749,9 +3451,21 @@ Returns:
case EFI_FV_FILETYPE_DRIVER:
case EFI_FV_FILETYPE_DXE_CORE:
break;
+ case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
+ //
+ // Rebase the inside FvImage.
+ //
+ GetChildFvFromFfs (FvInfo, FfsFile, XipOffset);
+
+ //
+ // Search PE/TE section in FV sectin.
+ //
+ break;
default:
return EFI_SUCCESS;
}
+
+ FfsHeaderSize = GetFfsHeaderLength(FfsFile);
//
// Rebase each PE32 section
//
@@ -2761,7 +3475,7 @@ Returns:
// Init Value
//
NewPe32BaseAddress = 0;
-
+
//
// Find Pe Image
//
@@ -2769,12 +3483,13 @@ Returns:
if (EFI_ERROR (Status)) {
break;
}
+ CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);
//
// Initialize context
//
memset (&ImageContext, 0, sizeof (ImageContext));
- ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
+ ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);
ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
Status = PeCoffLoaderGetImageInfo (&ImageContext);
if (EFI_ERROR (Status)) {
@@ -2782,7 +3497,8 @@ Returns:
return Status;
}
- if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {
+ if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||
+ (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {
mArm = TRUE;
}
@@ -2790,7 +3506,7 @@ Returns:
// Keep Image Context for PE image in FV
//
memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext));
-
+
//
// Get File PdbPointer
//
@@ -2799,7 +3515,7 @@ Returns:
//
// Get PeHeader pointer
//
- ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + ImageContext.PeCoffHeaderOffset);
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize + ImageContext.PeCoffHeaderOffset);
//
// Calculate the PE32 base address, based on file type
@@ -2809,13 +3525,6 @@ Returns:
case EFI_FV_FILETYPE_PEI_CORE:
case EFI_FV_FILETYPE_PEIM:
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
- if ((Flags & REBASE_XIP_FILE) == 0) {
- //
- // We aren't relocating XIP code, so skip it.
- //
- goto WritePeMap;
- }
-
//
// Check if section-alignment and file-alignment match or not
//
@@ -2823,17 +3532,22 @@ Returns:
//
// 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);
+ Error (NULL, 0, 3000, "Invalid", "PE image 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.
+ // 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
+ // Construct the original efi file Name
//
- strcpy (PeFileName, FileName);
+ if (strlen (FileName) >= MAX_LONG_FILE_PATH) {
+ Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName);
+ return EFI_ABORTED;
+ }
+ strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1);
+ PeFileName[MAX_LONG_FILE_PATH - 1] = 0;
Cptr = PeFileName + strlen (PeFileName);
while (*Cptr != '.') {
Cptr --;
@@ -2847,7 +3561,7 @@ Returns:
*(Cptr + 3) = 'i';
*(Cptr + 4) = '\0';
}
- PeFile = fopen (PeFileName, "rb");
+ PeFile = fopen (LongFilePath (PeFileName), "rb");
if (PeFile == NULL) {
Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
//Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
@@ -2860,6 +3574,7 @@ Returns:
PeFileSize = _filelength (fileno (PeFile));
PeFileBuffer = (UINT8 *) malloc (PeFileSize);
if (PeFileBuffer == NULL) {
+ fclose (PeFile);
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
return EFI_OUT_OF_RESOURCES;
}
@@ -2883,76 +3598,22 @@ Returns:
ImageContext.RelocationsStripped = FALSE;
}
- NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;
- BaseToUpdate = &XipBase;
+ NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;
break;
case EFI_FV_FILETYPE_DRIVER:
case EFI_FV_FILETYPE_DXE_CORE:
- switch (ImgHdr->Pe32.OptionalHeader.Subsystem) {
- case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
- if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {
- //
- // Check if section-alignment and file-alignment match or not
- //
- if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
- //
- // 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;
- BaseToUpdate = &XipBase;
- } else if ((Flags & REBASE_RUNTIME_FILE) == REBASE_RUNTIME_FILE) {
- //
- // make sure image base address at the section alignment
- //
- FvInfo->RuntimeBaseAddress = (FvInfo->RuntimeBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));
- FvInfo->RuntimeBaseAddress = FvInfo->RuntimeBaseAddress & (~(EFI_PAGE_SIZE - 1));
- NewPe32BaseAddress = FvInfo->RuntimeBaseAddress;
- BaseToUpdate = &(FvInfo->RuntimeBaseAddress);
- } else {
- //
- // RT drivers aren't supposed to be relocated
- //
- goto WritePeMap;
- }
- break;
-
- default:
- //
- // We treat all other subsystems the same as BS_DRIVER
- //
- if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {
- //
- // Check if section-alignment and file-alignment match or not
- //
- if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
- //
- // 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;
- BaseToUpdate = &XipBase;
- } else if ((Flags & REBASE_BOOTTIME_FILE) == REBASE_BOOTTIME_FILE) {
- //
- // make sure image base address at the Section and Page alignment
- //
- FvInfo->BootBaseAddress = (FvInfo->BootBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));
- FvInfo->BootBaseAddress = FvInfo->BootBaseAddress & (~(EFI_PAGE_SIZE - 1));
- NewPe32BaseAddress = FvInfo->BootBaseAddress;
- BaseToUpdate = &(FvInfo->BootBaseAddress);
- } else {
- //
- // Skip all BS_DRIVER's
- //
- goto WritePeMap;
- }
- break;
+ //
+ // Check if section-alignment and file-alignment match or not
+ //
+ if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
+ //
+ // Xip module has the same section alignment and file alignment.
+ //
+ Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName);
+ return EFI_ABORTED;
}
+ NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;
break;
default:
@@ -2961,70 +3622,76 @@ Returns:
//
return EFI_SUCCESS;
}
-
+
+ //
+ // Relocation doesn't exist
+ //
+ if (ImageContext.RelocationsStripped) {
+ Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
+ continue;
+ }
+
//
// Relocation exist and rebase
//
- if (!ImageContext.RelocationsStripped) {
- //
- // Load and Relocate Image Data
- //
- MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
- if (MemoryImagePointer == NULL) {
- Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
- return EFI_OUT_OF_RESOURCES;
- }
- memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
- ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1));
-
- Status = PeCoffLoaderLoadImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
- free ((VOID *) MemoryImagePointer);
- return Status;
- }
-
- ImageContext.DestinationAddress = NewPe32BaseAddress;
- Status = PeCoffLoaderRelocateImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
- free ((VOID *) MemoryImagePointer);
- return Status;
- }
+ //
+ // Load and Relocate Image Data
+ //
+ MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
+ if (MemoryImagePointer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
+ 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));
- //
- // Copy Relocated data to raw image file.
- //
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
- (UINTN) ImgHdr +
- sizeof (UINT32) +
- sizeof (EFI_IMAGE_FILE_HEADER) +
- ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
- );
-
- for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
- CopyMem (
- (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) + SectionHeader->PointerToRawData,
- (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
- SectionHeader->SizeOfRawData
- );
- }
-
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
free ((VOID *) MemoryImagePointer);
- MemoryImagePointer = NULL;
- if (PeFileBuffer != NULL) {
- free (PeFileBuffer);
- PeFileBuffer = NULL;
- }
+ return Status;
+ }
+
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
}
-
+
+ //
+ // Copy Relocated data to raw image file.
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN) ImgHdr +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+
+ for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ CopyMem (
+ (UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize + SectionHeader->PointerToRawData,
+ (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
+ SectionHeader->SizeOfRawData
+ );
+ }
+
+ free ((VOID *) MemoryImagePointer);
+ MemoryImagePointer = NULL;
+ if (PeFileBuffer != NULL) {
+ free (PeFileBuffer);
+ PeFileBuffer = NULL;
+ }
+
//
// Update Image Base Address
//
if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
- ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
+ ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
} else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
+ ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
} else {
Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
ImgHdr->Pe32.OptionalHeader.Magic,
@@ -3033,11 +3700,6 @@ Returns:
return EFI_ABORTED;
}
- //
- // Update BASE address by add one page size.
- //
- *BaseToUpdate -= EFI_PAGE_SIZE;
-
//
// Now update file checksum
//
@@ -3046,8 +3708,8 @@ Returns:
FfsFile->IntegrityCheck.Checksum.File = 0;
FfsFile->State = 0;
FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
- (UINT8 *) (FfsFile + 1),
- GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_HEADER)
+ (UINT8 *) ((UINT8 *)FfsFile + FfsHeaderSize),
+ GetFfsFileLength (FfsFile) - FfsHeaderSize
);
FfsFile->State = SavedState;
}
@@ -3055,7 +3717,7 @@ Returns:
//
// Get this module function address from ModulePeMapFile and add them into FvMap file
//
-WritePeMap:
+
//
// Default use FileName as map file path
//
@@ -3063,26 +3725,27 @@ WritePeMap:
PdbPointer = FileName;
}
- WriteMapFile (FvMapFile, PdbPointer, (EFI_GUID *) FfsFile, NewPe32BaseAddress, &OrigImageContext);
+ WriteMapFile (FvMapFile, PdbPointer, FfsFile, NewPe32BaseAddress, &OrigImageContext);
}
if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
- FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
+ FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER &&
+ FfsFile->Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
//
// Only Peim code may have a TE section
//
return EFI_SUCCESS;
}
-
+
//
// Now process TE sections
//
for (Index = 1;; Index++) {
NewPe32BaseAddress = 0;
-
+
//
// Find Te Image
//
@@ -3090,12 +3753,14 @@ WritePeMap:
if (EFI_ERROR (Status)) {
break;
}
-
+
+ CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);
+
//
// 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));
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize);
//
// Initialize context, load image info.
@@ -3109,7 +3774,8 @@ WritePeMap:
return Status;
}
- if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {
+ if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||
+ (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {
mArm = TRUE;
}
@@ -3122,13 +3788,6 @@ WritePeMap:
// Get File PdbPointer
//
PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle);
-
- if ((Flags & REBASE_XIP_FILE) == 0) {
- //
- // For none XIP PEIM module, their map info also are collected.
- //
- goto WriteTeMap;
- }
//
// Set new rebased address.
@@ -3139,11 +3798,16 @@ WritePeMap:
//
// if reloc is stripped, try to get the original efi image to get reloc info.
//
- if (ImageContext.RelocationsStripped == TRUE) {
+ if (ImageContext.RelocationsStripped) {
//
- // Construct the original efi file name
+ // Construct the original efi file name
//
- strcpy (PeFileName, FileName);
+ if (strlen (FileName) >= MAX_LONG_FILE_PATH) {
+ Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName);
+ return EFI_ABORTED;
+ }
+ strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1);
+ PeFileName[MAX_LONG_FILE_PATH - 1] = 0;
Cptr = PeFileName + strlen (PeFileName);
while (*Cptr != '.') {
Cptr --;
@@ -3159,7 +3823,7 @@ WritePeMap:
*(Cptr + 4) = '\0';
}
- PeFile = fopen (PeFileName, "rb");
+ PeFile = fopen (LongFilePath (PeFileName), "rb");
if (PeFile == NULL) {
Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
//Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
@@ -3171,6 +3835,7 @@ WritePeMap:
PeFileSize = _filelength (fileno (PeFile));
PeFileBuffer = (UINT8 *) malloc (PeFileSize);
if (PeFileBuffer == NULL) {
+ fclose (PeFile);
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
return EFI_OUT_OF_RESOURCES;
}
@@ -3194,70 +3859,75 @@ WritePeMap:
ImageContext.RelocationsStripped = FALSE;
}
}
+ //
+ // Relocation doesn't exist
+ //
+ if (ImageContext.RelocationsStripped) {
+ Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
+ continue;
+ }
//
// Relocation exist and rebase
//
- if (!ImageContext.RelocationsStripped) {
- //
- // Load and Relocate Image Data
- //
- MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
- if (MemoryImagePointer == NULL) {
- Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
- return EFI_OUT_OF_RESOURCES;
- }
- memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
- ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1));
-
- Status = PeCoffLoaderLoadImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
- free ((VOID *) MemoryImagePointer);
- return Status;
- }
- //
- // Reloacate TeImage
- //
- ImageContext.DestinationAddress = NewPe32BaseAddress;
- Status = PeCoffLoaderRelocateImage (&ImageContext);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);
- free ((VOID *) MemoryImagePointer);
- return Status;
- }
-
- //
- // Copy the relocated image into raw image file.
- //
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);
- for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {
- if (!ImageContext.IsTeImage) {
- CopyMem (
- (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
- (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
- SectionHeader->SizeOfRawData
- );
- } 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),
- SectionHeader->SizeOfRawData
- );
- }
- }
-
- //
- // Free the allocated memory resource
- //
+ //
+ // Load and Relocate Image Data
+ //
+ MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
+ if (MemoryImagePointer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
+ 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));
+
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+ //
+ // Reloacate TeImage
+ //
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);
free ((VOID *) MemoryImagePointer);
- MemoryImagePointer = NULL;
- if (PeFileBuffer != NULL) {
- free (PeFileBuffer);
- PeFileBuffer = NULL;
+ return Status;
+ }
+
+ //
+ // Copy the relocated image into raw image file.
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);
+ for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {
+ if (!ImageContext.IsTeImage) {
+ CopyMem (
+ (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
+ (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
+ SectionHeader->SizeOfRawData
+ );
+ } 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),
+ SectionHeader->SizeOfRawData
+ );
}
}
-
+
+ //
+ // Free the allocated memory resource
+ //
+ free ((VOID *) MemoryImagePointer);
+ MemoryImagePointer = NULL;
+ if (PeFileBuffer != NULL) {
+ free (PeFileBuffer);
+ PeFileBuffer = NULL;
+ }
+
//
// Update Image Base Address
//
@@ -3271,15 +3941,15 @@ WritePeMap:
FfsFile->IntegrityCheck.Checksum.File = 0;
FfsFile->State = 0;
FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
- (UINT8 *)(FfsFile + 1),
- GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_HEADER)
+ (UINT8 *)((UINT8 *)FfsFile + FfsHeaderSize),
+ GetFfsFileLength (FfsFile) - FfsHeaderSize
);
FfsFile->State = SavedState;
}
//
// Get this module function address from ModulePeMapFile and add them into FvMap file
//
-WriteTeMap:
+
//
// Default use FileName as map file path
//
@@ -3288,14 +3958,14 @@ WriteTeMap:
}
WriteMapFile (
- FvMapFile,
- PdbPointer,
- (EFI_GUID *) FfsFile,
- NewPe32BaseAddress,
+ FvMapFile,
+ PdbPointer,
+ FfsFile,
+ NewPe32BaseAddress,
&OrigImageContext
);
}
-
+
return EFI_SUCCESS;
}
@@ -3342,12 +4012,12 @@ Returns:
//
// Get Pad file size.
//
- FileLength = (*(UINT32 *)(PadFile->Size)) & 0x00FFFFFF;
- FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
+ FileLength = GetFfsFileLength(PadFile);
+ 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 = (UINT8*) PadFile + sizeof (EFI_FFS_FILE_HEADER);
+ FixPoint = (UINT8*) PadFile + GetFfsHeaderLength(PadFile);
FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF);
//
// FixPoint be larger at the last place of one fv image.
@@ -3356,15 +4026,15 @@ Returns:
FixPoint += 0x1000;
}
FixPoint -= 0x1000;
-
- if ((UINTN) FixPoint < ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER))) {
+
+ if ((UINTN) FixPoint < ((UINTN) PadFile + GetFfsHeaderLength(PadFile))) {
//
// No alignment FixPoint in this Pad File.
//
continue;
}
- if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) {
+ if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) {
//
// Find the position to place ApResetVector
//
@@ -3372,7 +4042,7 @@ Returns:
return EFI_SUCCESS;
}
}
-
+
return EFI_NOT_FOUND;
}
@@ -3399,7 +4069,7 @@ Returns:
EFI_NOT_FOUND A required string was not found in the INF file.
--*/
{
- CHAR8 Value[_MAX_PATH];
+ CHAR8 Value[MAX_LONG_FILE_PATH];
UINT64 Value64;
UINTN Index, Number;
EFI_STATUS Status;
@@ -3451,7 +4121,7 @@ Returns:
CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;
}
} else if (strstr (Value, "PersistAcrossReset") != NULL) {
- CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+ CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
if (strstr (Value, "InitiateReset") != NULL) {
CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;
}
@@ -3462,6 +4132,19 @@ Returns:
DebugMsg (NULL, 0, 9, "Capsule Flag", Value);
}
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_OEM_CAPSULE_FLAGS_STRING, 0, Value);
+ if (Status == EFI_SUCCESS) {
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);
+ if (EFI_ERROR (Status) || Value64 > 0xffff) {
+ Error (NULL, 0, 2000, "Invalid parameter",
+ "invalid Flag setting for %s. Must be integer value between 0x0000 and 0xffff.",
+ EFI_OEM_CAPSULE_FLAGS_STRING);
+ return EFI_ABORTED;
+ }
+ CapInfo->Flags |= Value64;
+ DebugMsg (NULL, 0, 9, "Capsule Extend Flag", Value);
+ }
+
//
// Read Capsule File name
//
@@ -3491,12 +4174,12 @@ Returns:
// Add the file
//
strcpy (CapInfo->CapFiles[Index], Value);
- DebugMsg (NULL, 0, 9, "Capsule component file", "the %uth file name is %s", (unsigned) Index, CapInfo->CapFiles[Index]);
+ DebugMsg (NULL, 0, 9, "Capsule component file", "the %uth file name is %s", (unsigned) Index, CapInfo->CapFiles[Index]);
} else {
break;
}
}
-
+
if (Index == 0) {
Warning (NULL, 0, 0, "Capsule components are not specified.", NULL);
}
@@ -3539,7 +4222,7 @@ Returns:
UINT32 Index;
FILE *fpin, *fpout;
EFI_STATUS Status;
-
+
if (InfFileImage != NULL) {
//
// Initialize file structures
@@ -3547,7 +4230,7 @@ Returns:
InfMemoryFile.FileImage = InfFileImage;
InfMemoryFile.CurrentFilePointer = InfFileImage;
InfMemoryFile.Eof = InfFileImage + InfFileSize;
-
+
//
// Parse the Cap inf file for header information
//
@@ -3556,7 +4239,7 @@ Returns:
return Status;
}
}
-
+
if (mCapDataInfo.HeaderSize == 0) {
//
// make header size align 16 bytes.
@@ -3569,16 +4252,16 @@ Returns:
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 && mCapDataInfo.CapName[0] != '\0') {
CapFileName = mCapDataInfo.CapName;
}
-
+
if (CapFileName == NULL) {
Error (NULL, 0, 2001, "Missing required argument", "Output Capsule file name");
return EFI_INVALID_PARAMETER;
}
-
+
//
// Set Default Capsule Guid value
//
@@ -3592,7 +4275,7 @@ Returns:
FileSize = 0;
CapSize = mCapDataInfo.HeaderSize;
while (mCapDataInfo.CapFiles [Index][0] != '\0') {
- fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");
+ fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");
if (fpin == NULL) {
Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);
return EFI_ABORTED;
@@ -3616,7 +4299,7 @@ Returns:
// Initialize the capsule header to zero
//
memset (CapBuffer, 0, mCapDataInfo.HeaderSize);
-
+
//
// create capsule header and get capsule body
//
@@ -3630,7 +4313,7 @@ Returns:
FileSize = 0;
CapSize = CapsuleHeader->HeaderSize;
while (mCapDataInfo.CapFiles [Index][0] != '\0') {
- fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");
+ fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");
if (fpin == NULL) {
Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);
free (CapBuffer);
@@ -3642,11 +4325,11 @@ Returns:
Index ++;
CapSize += FileSize;
}
-
+
//
// write capsule data into the output file
//
- fpout = fopen (CapFileName, "wb");
+ fpout = fopen (LongFilePath (CapFileName), "wb");
if (fpout == NULL) {
Error (NULL, 0, 0001, "Error opening file", CapFileName);
free (CapBuffer);
@@ -3655,7 +4338,8 @@ Returns:
fwrite (CapBuffer, 1, CapSize, fpout);
fclose (fpout);
-
+ free (CapBuffer);
+
VerboseMsg ("The size of the generated capsule image is %u bytes", (unsigned) CapSize);
return EFI_SUCCESS;