/** @file\r
+This file contains the internal functions required to generate a Firmware Volume.\r
\r
-Copyright (c) 2004 - 2008, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- GenFvInternalLib.c\r
-\r
-Abstract:\r
-\r
- This file contains the internal functions required to generate a Firmware Volume.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
+Portions Copyright (c) 2016 HP Development Company, L.P.<BR>\r
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
//\r
// Include files\r
//\r
-#ifdef __GNUC__\r
+\r
+#if defined(__FreeBSD__)\r
+#include <uuid.h>\r
+#elif defined(__GNUC__)\r
#include <uuid/uuid.h>\r
+#endif\r
+#ifdef __GNUC__\r
#include <sys/stat.h>\r
#endif\r
#include <string.h>\r
#endif\r
#include <assert.h>\r
\r
+#include <Guid/FfsSectionAlignmentPadding.h>\r
+\r
+#include "WinNtInclude.h"\r
#include "GenFvInternalLib.h"\r
#include "FvLib.h"\r
#include "PeCoffLib.h"\r
-#include "WinNtInclude.h"\r
+\r
+#define ARMT_UNCONDITIONAL_JUMP_INSTRUCTION 0xEB000000\r
+#define ARM64_UNCONDITIONAL_JUMP_INSTRUCTION 0x14000000\r
\r
BOOLEAN mArm = FALSE;\r
+BOOLEAN mRiscV = FALSE;\r
STATIC UINT32 MaxFfsAlignment = 0;\r
+BOOLEAN VtfFileFlag = FALSE;\r
\r
-EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
+EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
EFI_GUID mFileGuidArray [MAX_NUMBER_OF_FILES_IN_FV];\r
-EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
-EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};\r
+EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
+EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};\r
+EFI_GUID mEfiFfsSectionAlignmentPaddingGuid = EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID;\r
\r
CHAR8 *mFvbAttributeName[] = {\r
- EFI_FVB2_READ_DISABLED_CAP_STRING, \r
- EFI_FVB2_READ_ENABLED_CAP_STRING, \r
- EFI_FVB2_READ_STATUS_STRING, \r
+ EFI_FVB2_READ_DISABLED_CAP_STRING,\r
+ EFI_FVB2_READ_ENABLED_CAP_STRING,\r
+ EFI_FVB2_READ_STATUS_STRING,\r
EFI_FVB2_WRITE_DISABLED_CAP_STRING,\r
- EFI_FVB2_WRITE_ENABLED_CAP_STRING, \r
- EFI_FVB2_WRITE_STATUS_STRING, \r
- EFI_FVB2_LOCK_CAP_STRING, \r
- EFI_FVB2_LOCK_STATUS_STRING, \r
+ EFI_FVB2_WRITE_ENABLED_CAP_STRING,\r
+ EFI_FVB2_WRITE_STATUS_STRING,\r
+ EFI_FVB2_LOCK_CAP_STRING,\r
+ EFI_FVB2_LOCK_STATUS_STRING,\r
NULL,\r
- EFI_FVB2_STICKY_WRITE_STRING, \r
- EFI_FVB2_MEMORY_MAPPED_STRING, \r
- EFI_FVB2_ERASE_POLARITY_STRING, \r
- EFI_FVB2_READ_LOCK_CAP_STRING, \r
- EFI_FVB2_READ_LOCK_STATUS_STRING, \r
- EFI_FVB2_WRITE_LOCK_CAP_STRING, \r
- EFI_FVB2_WRITE_LOCK_STATUS_STRING \r
+ EFI_FVB2_STICKY_WRITE_STRING,\r
+ EFI_FVB2_MEMORY_MAPPED_STRING,\r
+ EFI_FVB2_ERASE_POLARITY_STRING,\r
+ EFI_FVB2_READ_LOCK_CAP_STRING,\r
+ EFI_FVB2_READ_LOCK_STATUS_STRING,\r
+ EFI_FVB2_WRITE_LOCK_CAP_STRING,\r
+ EFI_FVB2_WRITE_LOCK_STATUS_STRING\r
};\r
\r
CHAR8 *mFvbAlignmentName[] = {\r
- EFI_FVB2_ALIGNMENT_1_STRING, \r
- EFI_FVB2_ALIGNMENT_2_STRING, \r
- EFI_FVB2_ALIGNMENT_4_STRING, \r
- EFI_FVB2_ALIGNMENT_8_STRING, \r
- EFI_FVB2_ALIGNMENT_16_STRING, \r
- EFI_FVB2_ALIGNMENT_32_STRING, \r
- EFI_FVB2_ALIGNMENT_64_STRING, \r
- EFI_FVB2_ALIGNMENT_128_STRING, \r
- EFI_FVB2_ALIGNMENT_256_STRING, \r
- EFI_FVB2_ALIGNMENT_512_STRING, \r
- EFI_FVB2_ALIGNMENT_1K_STRING, \r
- EFI_FVB2_ALIGNMENT_2K_STRING, \r
- EFI_FVB2_ALIGNMENT_4K_STRING, \r
- EFI_FVB2_ALIGNMENT_8K_STRING, \r
- EFI_FVB2_ALIGNMENT_16K_STRING, \r
- EFI_FVB2_ALIGNMENT_32K_STRING, \r
- EFI_FVB2_ALIGNMENT_64K_STRING, \r
+ EFI_FVB2_ALIGNMENT_1_STRING,\r
+ EFI_FVB2_ALIGNMENT_2_STRING,\r
+ EFI_FVB2_ALIGNMENT_4_STRING,\r
+ EFI_FVB2_ALIGNMENT_8_STRING,\r
+ EFI_FVB2_ALIGNMENT_16_STRING,\r
+ EFI_FVB2_ALIGNMENT_32_STRING,\r
+ EFI_FVB2_ALIGNMENT_64_STRING,\r
+ EFI_FVB2_ALIGNMENT_128_STRING,\r
+ EFI_FVB2_ALIGNMENT_256_STRING,\r
+ EFI_FVB2_ALIGNMENT_512_STRING,\r
+ EFI_FVB2_ALIGNMENT_1K_STRING,\r
+ EFI_FVB2_ALIGNMENT_2K_STRING,\r
+ EFI_FVB2_ALIGNMENT_4K_STRING,\r
+ EFI_FVB2_ALIGNMENT_8K_STRING,\r
+ EFI_FVB2_ALIGNMENT_16K_STRING,\r
+ EFI_FVB2_ALIGNMENT_32K_STRING,\r
+ EFI_FVB2_ALIGNMENT_64K_STRING,\r
EFI_FVB2_ALIGNMENT_128K_STRING,\r
EFI_FVB2_ALIGNMENT_256K_STRING,\r
- EFI_FVB2_ALIGNMNET_512K_STRING,\r
- EFI_FVB2_ALIGNMENT_1M_STRING, \r
- EFI_FVB2_ALIGNMENT_2M_STRING, \r
- EFI_FVB2_ALIGNMENT_4M_STRING, \r
- EFI_FVB2_ALIGNMENT_8M_STRING, \r
- EFI_FVB2_ALIGNMENT_16M_STRING, \r
- EFI_FVB2_ALIGNMENT_32M_STRING, \r
- EFI_FVB2_ALIGNMENT_64M_STRING, \r
+ EFI_FVB2_ALIGNMENT_512K_STRING,\r
+ EFI_FVB2_ALIGNMENT_1M_STRING,\r
+ EFI_FVB2_ALIGNMENT_2M_STRING,\r
+ EFI_FVB2_ALIGNMENT_4M_STRING,\r
+ EFI_FVB2_ALIGNMENT_8M_STRING,\r
+ EFI_FVB2_ALIGNMENT_16M_STRING,\r
+ EFI_FVB2_ALIGNMENT_32M_STRING,\r
+ EFI_FVB2_ALIGNMENT_64M_STRING,\r
EFI_FVB2_ALIGNMENT_128M_STRING,\r
EFI_FVB2_ALIGNMENT_256M_STRING,\r
EFI_FVB2_ALIGNMENT_512M_STRING,\r
- EFI_FVB2_ALIGNMENT_1G_STRING, \r
+ EFI_FVB2_ALIGNMENT_1G_STRING,\r
EFI_FVB2_ALIGNMENT_2G_STRING\r
};\r
\r
// This data array will be located at the base of the Firmware Volume Header (FVH)\r
// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes\r
// will be used to keep the FVH checksum consistent.\r
-// This code will be run in response to a starutp IPI for HT-enabled systems.\r
+// This code will be run in response to a startup IPI for HT-enabled systems.\r
//\r
#define SIZEOF_STARTUP_DATA_ARRAY 0x10\r
\r
\r
FV_INFO mFvDataInfo;\r
CAP_INFO mCapDataInfo;\r
+BOOLEAN mIsLargeFfs = FALSE;\r
+\r
+EFI_PHYSICAL_ADDRESS mFvBaseAddress[0x10];\r
+UINT32 mFvBaseAddressNumber = 0;\r
\r
EFI_STATUS\r
ParseFvInf (\r
EFI_NOT_FOUND A required string was not found in the INF file.\r
--*/\r
{\r
- CHAR8 Value[_MAX_PATH];\r
+ CHAR8 Value[MAX_LONG_FILE_PATH];\r
UINT64 Value64;\r
- UINTN Index, Number, Index1;\r
+ UINTN Index;\r
+ UINTN Number;\r
EFI_STATUS Status;\r
EFI_GUID GuidValue;\r
\r
DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);\r
\r
FvInfo->BaseAddress = Value64;\r
+ FvInfo->BaseAddressSet = TRUE;\r
}\r
}\r
\r
}\r
\r
//\r
- // Read the FV Name Guid\r
+ // Read the FV Extension Header File Name\r
//\r
- if (!FvInfo->FvNameGuidSet) {\r
- Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_NAMEGUID_STRING, 0, Value);\r
- if (Status == EFI_SUCCESS) {\r
- //\r
- // Get the guid value\r
- //\r
- Status = StringToGuid (Value, &GuidValue);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_NAMEGUID_STRING, Value);\r
- return EFI_ABORTED;\r
- }\r
- memcpy (&FvInfo->FvNameGuid, &GuidValue, sizeof (EFI_GUID));\r
- FvInfo->FvNameGuidSet = TRUE;\r
- }\r
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_EXT_HEADER_FILE_NAME, 0, Value);\r
+ if (Status == EFI_SUCCESS) {\r
+ strcpy (FvInfo->FvExtHeaderFile, Value);\r
}\r
\r
//\r
//\r
strcpy (FvInfo->FvName, Value);\r
}\r
- \r
+\r
//\r
// Read Fv Attribute\r
//\r
}\r
}\r
\r
+ //\r
+ // Read weak alignment flag\r
+ //\r
+ Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_WEAK_ALIGNMENT_STRING, 0, Value);\r
+ if (Status == EFI_SUCCESS) {\r
+ if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) {\r
+ FvInfo->FvAttributes |= EFI_FVB2_WEAK_ALIGNMENT;\r
+ } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) {\r
+ Error (NULL, 0, 2000, "Invalid parameter", "Weak alignment value expected one of TRUE, FALSE, 1 or 0.");\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+\r
//\r
// Read block maps\r
//\r
}\r
}\r
\r
- for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {\r
+ for (Index = 0; Number + Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {\r
//\r
// Read the FFS file list\r
//\r
// Add the file\r
//\r
strcpy (FvInfo->FvFiles[Number + Index], Value);\r
- DebugMsg (NULL, 0, 9, "FV component file", "the %dth name is %s", Index, Value);\r
+ DebugMsg (NULL, 0, 9, "FV component file", "the %uth name is %s", (unsigned) Index, Value);\r
} else {\r
break;\r
}\r
Routine Description:\r
\r
This function changes the FFS file attributes based on the erase polarity\r
- of the FV. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY. \r
+ of the FV. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY.\r
\r
Arguments:\r
\r
\r
case 0:\r
//\r
- // 8 byte alignment, mini alignment requirement for FFS file. \r
+ // 1 byte alignment\r
+ //if bit 1 have set, 128K byte alignment\r
//\r
- *Alignment = 3;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 17;\r
+ } else {\r
+ *Alignment = 0;\r
+ }\r
break;\r
\r
case 1:\r
//\r
// 16 byte alignment\r
+ //if bit 1 have set, 256K byte alignment\r
//\r
- *Alignment = 4;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 18;\r
+ } else {\r
+ *Alignment = 4;\r
+ }\r
break;\r
\r
case 2:\r
//\r
// 128 byte alignment\r
+ //if bit 1 have set, 512K byte alignment\r
//\r
- *Alignment = 7;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 19;\r
+ } else {\r
+ *Alignment = 7;\r
+ }\r
break;\r
\r
case 3:\r
//\r
// 512 byte alignment\r
+ //if bit 1 have set, 1M byte alignment\r
//\r
- *Alignment = 9;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 20;\r
+ } else {\r
+ *Alignment = 9;\r
+ }\r
break;\r
\r
case 4:\r
//\r
// 1K byte alignment\r
+ //if bit 1 have set, 2M byte alignment\r
//\r
- *Alignment = 10;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 21;\r
+ } else {\r
+ *Alignment = 10;\r
+ }\r
break;\r
\r
case 5:\r
//\r
// 4K byte alignment\r
+ //if bit 1 have set, 4M byte alignment\r
//\r
- *Alignment = 12;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 22;\r
+ } else {\r
+ *Alignment = 12;\r
+ }\r
break;\r
\r
case 6:\r
//\r
// 32K byte alignment\r
+ //if bit 1 have set , 8M byte alignment\r
//\r
- *Alignment = 15;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 23;\r
+ } else {\r
+ *Alignment = 15;\r
+ }\r
break;\r
\r
case 7:\r
//\r
// 64K byte alignment\r
+ //if bit 1 have set, 16M alignment\r
//\r
- *Alignment = 16;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {\r
+ *Alignment = 24;\r
+ } else {\r
+ *Alignment = 16;\r
+ }\r
break;\r
\r
default:\r
AddPadFile (\r
IN OUT MEMORY_FILE *FvImage,\r
IN UINT32 DataAlignment,\r
- IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader\r
+ IN VOID *FvEnd,\r
+ IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader,\r
+ IN UINT32 NextFfsSize\r
)\r
/*++\r
\r
\r
Arguments:\r
\r
- FvImage The memory image of the FV to add it to. The current offset\r
- must be valid.\r
+ FvImage The memory image of the FV to add it to.\r
+ The current offset must be valid.\r
DataAlignment The data alignment of the next FFS file.\r
- ExtHeader PI FvExtHeader Optional \r
+ FvEnd End of the empty data in FvImage.\r
+ ExtHeader PI FvExtHeader Optional\r
\r
Returns:\r
\r
{\r
EFI_FFS_FILE_HEADER *PadFile;\r
UINTN PadFileSize;\r
+ UINT32 NextFfsHeaderSize;\r
+ UINT32 CurFfsHeaderSize;\r
+ UINT32 Index;\r
\r
+ Index = 0;\r
+ CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
//\r
// Verify input parameters.\r
//\r
}\r
\r
//\r
- // Check if a pad file is necessary\r
- //\r
- if ((ExtHeader == NULL) && (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0)) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Write pad file header\r
+ // Calculate the pad file size\r
//\r
- PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
\r
//\r
- // Verify that we have enough space for the file header\r
+ // Append extension header size\r
//\r
if (ExtHeader != NULL) {\r
- if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER) + ExtHeader->ExtHeaderSize) >= (UINTN) FvImage->Eof) {\r
- return EFI_OUT_OF_RESOURCES;\r
- } \r
+ PadFileSize = ExtHeader->ExtHeaderSize;\r
+ if (PadFileSize + sizeof (EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) {\r
+ CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+ }\r
+ PadFileSize += CurFfsHeaderSize;\r
} else {\r
- if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+ if (NextFfsSize >= MAX_FFS_SIZE) {\r
+ NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+ }\r
+ //\r
+ // Check if a pad file is necessary\r
+ //\r
+ if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + NextFfsHeaderSize) % DataAlignment == 0) {\r
+ return EFI_SUCCESS;\r
}\r
+ PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER) + NextFfsHeaderSize;\r
+ //\r
+ // Add whatever it takes to get to the next aligned address\r
+ //\r
+ while ((PadFileSize % DataAlignment) != 0) {\r
+ PadFileSize++;\r
+ }\r
+ //\r
+ // Subtract the next file header size\r
+ //\r
+ PadFileSize -= NextFfsHeaderSize;\r
+ //\r
+ // Subtract the starting offset to get size\r
+ //\r
+ PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
}\r
\r
//\r
- // write PadFile FFS header with PadType, don't need to set PAD file guid in its header.\r
- //\r
- PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
- PadFile->Attributes = 0;\r
-\r
- //\r
- // Calculate the pad file size\r
- //\r
- //\r
- // This is the earliest possible valid offset (current plus pad file header\r
- // plus the next file header)\r
+ // Verify that we have enough space for the file header\r
//\r
- if (ExtHeader != NULL) {\r
- PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2) + ExtHeader->ExtHeaderSize;\r
- } else {\r
- PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);\r
+ if (((UINTN) FvImage->CurrentFilePointer + PadFileSize) > (UINTN) FvEnd) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
//\r
- // Add whatever it takes to get to the next aligned address\r
- //\r
- while ((PadFileSize % DataAlignment) != 0) {\r
- PadFileSize++;\r
- }\r
- //\r
- // Subtract the next file header size\r
+ // Write pad file header\r
//\r
- PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
+ PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
\r
//\r
- // Subtract the starting offset to get size\r
+ // Write PadFile FFS header with PadType, don't need to set PAD file guid in its header.\r
//\r
- PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
- \r
+ PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
+ PadFile->Attributes = 0;\r
+\r
//\r
// Write pad file size (calculated size minus next file header size)\r
//\r
- PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);\r
- PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
- PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
+ if (PadFileSize >= MAX_FFS_SIZE) {\r
+ memset(PadFile->Size, 0, sizeof(UINT8) * 3);\r
+ ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = PadFileSize;\r
+ PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
+ } else {\r
+ PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);\r
+ PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
+ PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
+ }\r
\r
//\r
// Fill in checksums and state, they must be 0 for checksumming.\r
PadFile->IntegrityCheck.Checksum.Header = 0;\r
PadFile->IntegrityCheck.Checksum.File = 0;\r
PadFile->State = 0;\r
- PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, CurFfsHeaderSize);\r
PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
\r
PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
(EFI_FFS_FILE_HEADER *) PadFile,\r
(EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
);\r
- \r
- if (ExtHeader != NULL) {\r
- //\r
- // Copy Fv Extension Header and Set Fv Extension header offset\r
- //\r
- memcpy (PadFile + 1, ExtHeader, ExtHeader->ExtHeaderSize);\r
- ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) (PadFile + 1) - (UINTN) FvImage->FileImage);\r
- }\r
\r
- //\r
- // Verify that we have enough space (including the padding)\r
- //\r
- if (((UINTN)PadFile + PadFileSize) >= (UINTN) FvImage->Eof) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
//\r
// Update the current FV pointer\r
//\r
FvImage->CurrentFilePointer += PadFileSize;\r
\r
+ if (ExtHeader != NULL) {\r
+ //\r
+ // Copy Fv Extension Header and Set Fv Extension header offset\r
+ //\r
+ if (ExtHeader->ExtHeaderSize > sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER)) {\r
+ for (Index = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); Index < ExtHeader->ExtHeaderSize;) {\r
+ if (((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntryType == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {\r
+ if (VtfFileFlag) {\r
+ ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTotalSize;\r
+ } else {\r
+ ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTakenSize;\r
+ }\r
+ break;\r
+ }\r
+ Index += ((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntrySize;\r
+ }\r
+ }\r
+ memcpy ((UINT8 *)PadFile + CurFfsHeaderSize, ExtHeader, ExtHeader->ExtHeaderSize);\r
+ ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) ((UINT8 *)PadFile + CurFfsHeaderSize) - (UINTN) FvImage->FileImage);\r
+ //\r
+ // Make next file start at QWord Boundary\r
+ //\r
+ while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {\r
+ FvImage->CurrentFilePointer++;\r
+ }\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
WriteMapFile (\r
IN OUT FILE *FvMapFile,\r
IN CHAR8 *FileName,\r
- IN EFI_GUID *FileGuidPtr, \r
+ IN EFI_FFS_FILE_HEADER *FfsFile,\r
IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,\r
IN PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext\r
)\r
\r
FvMapFile A pointer to FvMap File\r
FileName Ffs File PathName\r
- FileGuidPtr Guid Value of Ffs file\r
+ FfsFile A pointer to Ffs file image.\r
ImageBaseAddress PeImage Base Address.\r
pImageContext Image Context Information.\r
\r
\r
--*/\r
{\r
- CHAR8 PeMapFileName [_MAX_PATH];\r
+ CHAR8 PeMapFileName [MAX_LONG_FILE_PATH];\r
CHAR8 *Cptr, *Cptr2;\r
CHAR8 FileGuidName [MAX_LINE_LEN];\r
FILE *PeMapFile;\r
CHAR8 Line [MAX_LINE_LEN];\r
CHAR8 KeyWord [MAX_LINE_LEN];\r
+ CHAR8 KeyWord2 [MAX_LINE_LEN];\r
CHAR8 FunctionName [MAX_LINE_LEN];\r
EFI_PHYSICAL_ADDRESS FunctionAddress;\r
UINT32 FunctionType;\r
EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
EFI_TE_IMAGE_HEADER *TEImageHeader;\r
EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
- \r
+ long long TempLongAddress;\r
+ UINT32 TextVirtualAddress;\r
+ UINT32 DataVirtualAddress;\r
+ EFI_PHYSICAL_ADDRESS LinkTimeBaseAddress;\r
+ BOOLEAN IsUseClang;\r
+\r
//\r
// Init local variable\r
//\r
FunctionType = 0;\r
//\r
- // Print FileGuid to string buffer. \r
+ // Print FileGuid to string buffer.\r
//\r
- PrintGuidToBuffer (FileGuidPtr, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);\r
- \r
+ PrintGuidToBuffer (&FfsFile->Name, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);\r
+\r
//\r
- // Construct Map file Name \r
+ // Construct Map file Name\r
//\r
- strcpy (PeMapFileName, FileName);\r
- \r
+ if (strlen (FileName) >= MAX_LONG_FILE_PATH) {\r
+ return EFI_ABORTED;\r
+ }\r
+ strncpy (PeMapFileName, FileName, MAX_LONG_FILE_PATH - 1);\r
+ PeMapFileName[MAX_LONG_FILE_PATH - 1] = 0;\r
+\r
//\r
// Change '\\' to '/', unified path format.\r
//\r
}\r
Cptr ++;\r
}\r
- \r
+\r
//\r
// Get Map file\r
- // \r
+ //\r
Cptr = PeMapFileName + strlen (PeMapFileName);\r
while ((*Cptr != '.') && (Cptr >= PeMapFileName)) {\r
Cptr --;\r
while ((*Cptr != FILE_SEP_CHAR) && (Cptr >= PeMapFileName)) {\r
Cptr --;\r
}\r
- *Cptr2 = '\0';\r
- strcpy (KeyWord, Cptr + 1);\r
- *Cptr2 = '.';\r
+ *Cptr2 = '\0';\r
+ if (strlen (Cptr + 1) >= MAX_LINE_LEN) {\r
+ return EFI_ABORTED;\r
+ }\r
+ strncpy (KeyWord, Cptr + 1, MAX_LINE_LEN - 1);\r
+ KeyWord[MAX_LINE_LEN - 1] = 0;\r
+ *Cptr2 = '.';\r
\r
//\r
// AddressOfEntryPoint and Offset in Image\r
//\r
if (!pImageContext->IsTeImage) {\r
- ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset);\r
- AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;\r
- Offset = 0;\r
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset);\r
+ AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;\r
+ Offset = 0;\r
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
(UINT8 *) ImgHdr +\r
- sizeof (UINT32) + \r
- sizeof (EFI_IMAGE_FILE_HEADER) + \r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
);\r
Index = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
} else {\r
- TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle;\r
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle;\r
AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint;\r
Offset = TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);\r
Index = TEImageHeader->NumberOfSections;\r
}\r
- \r
+\r
//\r
// module information output\r
//\r
if (ImageBaseAddress == 0) {\r
fprintf (FvMapFile, "%s (dummy) (", KeyWord);\r
- fprintf (FvMapFile, "BaseAddress=%08lx, ", ImageBaseAddress);\r
+ fprintf (FvMapFile, "BaseAddress=%010llx, ", (unsigned long long) ImageBaseAddress);\r
} else {\r
- fprintf (FvMapFile, "%s (", KeyWord);\r
- fprintf (FvMapFile, "BaseAddress=%08lx, ", ImageBaseAddress + Offset);\r
+ fprintf (FvMapFile, "%s (Fixed Flash Address, ", KeyWord);\r
+ fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset));\r
}\r
- fprintf (FvMapFile, "EntryPoint=%08lx, ", ImageBaseAddress + AddressOfEntryPoint);\r
- fprintf (FvMapFile, "GUID=%s", FileGuidName);\r
- fprintf (FvMapFile, ")\n"); \r
- \r
+\r
+ fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));\r
+ fprintf (FvMapFile, ")\n");\r
+\r
+ fprintf (FvMapFile, "(GUID=%s", FileGuidName);\r
+ TextVirtualAddress = 0;\r
+ DataVirtualAddress = 0;\r
for (; Index > 0; Index --, SectionHeader ++) {\r
- if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {\r
- fprintf (FvMapFile, ".textbaseaddress=%08lx ",ImageBaseAddress + SectionHeader->VirtualAddress);\r
- } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {\r
- fprintf (FvMapFile, ".databaseaddress=%08lx ",ImageBaseAddress + SectionHeader->VirtualAddress);\r
- }\r
+ if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {\r
+ TextVirtualAddress = SectionHeader->VirtualAddress;\r
+ } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {\r
+ DataVirtualAddress = SectionHeader->VirtualAddress;\r
+ } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".sdata") == 0) {\r
+ DataVirtualAddress = SectionHeader->VirtualAddress;\r
+ }\r
}\r
- fprintf (FvMapFile, "\n\n"); \r
- \r
+ fprintf (FvMapFile, " .textbaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + TextVirtualAddress));\r
+ fprintf (FvMapFile, " .databaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + DataVirtualAddress));\r
+ fprintf (FvMapFile, ")\n\n");\r
+\r
//\r
// Open PeMapFile\r
//\r
- PeMapFile = fopen (PeMapFileName, "r");\r
+ PeMapFile = fopen (LongFilePath (PeMapFileName), "r");\r
if (PeMapFile == NULL) {\r
// fprintf (stdout, "can't open %s file to reading\n", PeMapFileName);\r
return EFI_ABORTED;\r
}\r
VerboseMsg ("The map file is %s", PeMapFileName);\r
- \r
+\r
//\r
// Output Functions information into Fv Map file\r
//\r
+ LinkTimeBaseAddress = 0;\r
+ IsUseClang = FALSE;\r
while (fgets (Line, MAX_LINE_LEN, PeMapFile) != NULL) {\r
//\r
// Skip blank line\r
}\r
//\r
// By Address and Static keyword\r
- // \r
+ //\r
if (FunctionType == 0) {\r
sscanf (Line, "%s", KeyWord);\r
if (stricmp (KeyWord, "Address") == 0) {\r
+ sscanf (Line, "%s %s", KeyWord, KeyWord2);\r
+ if (stricmp (KeyWord2, "Size") == 0) {\r
+ IsUseClang = TRUE;\r
+ FunctionType = 1;\r
+ continue;\r
+ }\r
//\r
// function list\r
//\r
//\r
FunctionType = 2;\r
fgets (Line, MAX_LINE_LEN, PeMapFile);\r
+ } else if (stricmp (KeyWord, "Preferred") ==0) {\r
+ sscanf (Line + strlen (" Preferred load address is"), "%llx", &TempLongAddress);\r
+ LinkTimeBaseAddress = (UINT64) TempLongAddress;\r
}\r
continue;\r
}\r
// Printf Function Information\r
//\r
if (FunctionType == 1) {\r
- sscanf (Line, "%s %s %lx %s", KeyWord, FunctionName, &FunctionAddress, FunctionTypeName);\r
- if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {\r
- fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress);\r
- fprintf (FvMapFile, "(%08lx) F ", FunctionAddress - Offset);\r
- fprintf (FvMapFile, "%s\n", FunctionName);\r
- } else {\r
- fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress);\r
- fprintf (FvMapFile, "(%08lx) ", FunctionAddress - Offset);\r
- fprintf (FvMapFile, "%s\n", FunctionName);\r
+ if (IsUseClang) {\r
+ sscanf (Line, "%llx %s %s %s", &TempLongAddress, KeyWord, KeyWord2, FunctionTypeName);\r
+ FunctionAddress = (UINT64) TempLongAddress;\r
+ if (FunctionTypeName [0] == '_' ) {\r
+ fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));\r
+ fprintf (FvMapFile, "%s\n", FunctionTypeName);\r
+ }\r
+ } else {\r
+ sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);\r
+ FunctionAddress = (UINT64) TempLongAddress;\r
+ if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {\r
+ fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));\r
+ fprintf (FvMapFile, "%s\n", FunctionName);\r
+ }\r
}\r
} else if (FunctionType == 2) {\r
- sscanf (Line, "%s %s %lx %s", KeyWord, FunctionName, &FunctionAddress, FunctionTypeName);\r
+ sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);\r
+ FunctionAddress = (UINT64) TempLongAddress;\r
if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {\r
- fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress);\r
- fprintf (FvMapFile, "(%08lx) FS ", FunctionAddress - Offset);\r
- fprintf (FvMapFile, "%s\n", FunctionName);\r
- } else {\r
- fprintf (FvMapFile, " %016lx ", ImageBaseAddress + FunctionAddress);\r
- fprintf (FvMapFile, "(%08lx) ", FunctionAddress - Offset);\r
+ fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));\r
fprintf (FvMapFile, "%s\n", FunctionName);\r
}\r
}\r
//\r
fprintf (FvMapFile, "\n\n");\r
fclose (PeMapFile);\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r
+STATIC\r
+BOOLEAN\r
+AdjustInternalFfsPadding (\r
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
+ IN OUT MEMORY_FILE *FvImage,\r
+ IN UINTN Alignment,\r
+ IN OUT UINTN *FileSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function looks for a dedicated alignment padding section in the FFS, and\r
+ shrinks it to the size required to line up subsequent sections correctly.\r
+\r
+Arguments:\r
+\r
+ FfsFile A pointer to Ffs file image.\r
+ FvImage The memory image of the FV to adjust it to.\r
+ Alignment Current file alignment\r
+ FileSize Reference to a variable holding the size of the FFS file\r
+\r
+Returns:\r
+\r
+ TRUE Padding section was found and updated successfully\r
+ FALSE Otherwise\r
+\r
+--*/\r
+{\r
+ EFI_FILE_SECTION_POINTER PadSection;\r
+ UINT8 *Remainder;\r
+ EFI_STATUS Status;\r
+ UINT32 FfsHeaderLength;\r
+ UINT32 FfsFileLength;\r
+ UINT32 PadSize;\r
+ UINTN Misalignment;\r
+ EFI_FFS_INTEGRITY_CHECK *IntegrityCheck;\r
+\r
+ //\r
+ // Figure out the misalignment: all FFS sections are aligned relative to the\r
+ // start of the FFS payload, so use that as the base of the misalignment\r
+ // computation.\r
+ //\r
+ FfsHeaderLength = GetFfsHeaderLength(FfsFile);\r
+ Misalignment = (UINTN) FvImage->CurrentFilePointer -\r
+ (UINTN) FvImage->FileImage + FfsHeaderLength;\r
+ Misalignment &= Alignment - 1;\r
+ if (Misalignment == 0) {\r
+ // Nothing to do, return success\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // We only apply this optimization to FFS files with the FIXED attribute set,\r
+ // since the FFS will not be loadable at arbitrary offsets anymore after\r
+ // we adjust the size of the padding section.\r
+ //\r
+ if ((FfsFile->Attributes & FFS_ATTRIB_FIXED) == 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Look for a dedicated padding section that we can adjust to compensate\r
+ // for the misalignment. If such a padding section exists, it precedes all\r
+ // sections with alignment requirements, and so the adjustment will correct\r
+ // all of them.\r
+ //\r
+ Status = GetSectionByType (FfsFile, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 1,\r
+ &PadSection);\r
+ if (EFI_ERROR (Status) ||\r
+ CompareGuid (&PadSection.FreeformSubtypeSection->SubTypeGuid,\r
+ &mEfiFfsSectionAlignmentPaddingGuid) != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Find out if the size of the padding section is sufficient to compensate\r
+ // for the misalignment.\r
+ //\r
+ PadSize = GetSectionFileLength (PadSection.CommonHeader);\r
+ if (Misalignment > PadSize - sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Move the remainder of the FFS file towards the front, and adjust the\r
+ // file size output parameter.\r
+ //\r
+ Remainder = (UINT8 *) PadSection.CommonHeader + PadSize;\r
+ memmove (Remainder - Misalignment, Remainder,\r
+ *FileSize - (UINTN) (Remainder - (UINTN) FfsFile));\r
+ *FileSize -= Misalignment;\r
+\r
+ //\r
+ // Update the padding section's length with the new values. Note that the\r
+ // padding is always < 64 KB, so we can ignore EFI_COMMON_SECTION_HEADER2\r
+ // ExtendedSize.\r
+ //\r
+ PadSize -= Misalignment;\r
+ PadSection.CommonHeader->Size[0] = (UINT8) (PadSize & 0xff);\r
+ PadSection.CommonHeader->Size[1] = (UINT8) ((PadSize & 0xff00) >> 8);\r
+ PadSection.CommonHeader->Size[2] = (UINT8) ((PadSize & 0xff0000) >> 16);\r
+\r
+ //\r
+ // Update the FFS header with the new overall length\r
+ //\r
+ FfsFileLength = GetFfsFileLength (FfsFile) - Misalignment;\r
+ if (FfsHeaderLength > sizeof(EFI_FFS_FILE_HEADER)) {\r
+ ((EFI_FFS_FILE_HEADER2 *)FfsFile)->ExtendedSize = FfsFileLength;\r
+ } else {\r
+ FfsFile->Size[0] = (UINT8) (FfsFileLength & 0x000000FF);\r
+ FfsFile->Size[1] = (UINT8) ((FfsFileLength & 0x0000FF00) >> 8);\r
+ FfsFile->Size[2] = (UINT8) ((FfsFileLength & 0x00FF0000) >> 16);\r
+ }\r
+\r
+ //\r
+ // Clear the alignment bits: these have become meaningless now that we have\r
+ // adjusted the padding section.\r
+ //\r
+ FfsFile->Attributes &= ~(FFS_ATTRIB_DATA_ALIGNMENT | FFS_ATTRIB_DATA_ALIGNMENT2);\r
+\r
+ //\r
+ // Recalculate the FFS header checksum. Instead of setting Header and State\r
+ // both to zero, set Header to (UINT8)(-State) so State preserves its original\r
+ // value\r
+ //\r
+ IntegrityCheck = &FfsFile->IntegrityCheck;\r
+ IntegrityCheck->Checksum.Header = (UINT8) (0x100 - FfsFile->State);\r
+ IntegrityCheck->Checksum.File = 0;\r
+\r
+ IntegrityCheck->Checksum.Header = CalculateChecksum8 (\r
+ (UINT8 *) FfsFile, FfsHeaderLength);\r
+\r
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ //\r
+ // Ffs header checksum = zero, so only need to calculate ffs body.\r
+ //\r
+ IntegrityCheck->Checksum.File = CalculateChecksum8 (\r
+ (UINT8 *) FfsFile + FfsHeaderLength,\r
+ FfsFileLength - FfsHeaderLength);\r
+ } else {\r
+ IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
EFI_STATUS\r
AddFile (\r
IN OUT MEMORY_FILE *FvImage,\r
IN FV_INFO *FvInfo,\r
IN UINTN Index,\r
IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,\r
- IN FILE *FvMapFile \r
+ IN FILE *FvMapFile,\r
+ IN FILE *FvReportFile\r
)\r
/*++\r
\r
VtfFileImage A pointer to the VTF file within the FvImage. If this is equal\r
to the end of the FvImage then no VTF previously found.\r
FvMapFile Pointer to FvMap File\r
+ FvReportFile Pointer to FvReport File\r
\r
Returns:\r
\r
UINT32 CurrentFileAlignment;\r
EFI_STATUS Status;\r
UINTN Index1;\r
- \r
+ UINT8 FileGuidString[PRINTED_GUID_BUFFER_SIZE];\r
+\r
Index1 = 0;\r
//\r
// Verify input parameters.\r
//\r
// Read the file to add\r
//\r
- NewFile = fopen (FvInfo->FvFiles[Index], "rb");\r
+ NewFile = fopen (LongFilePath (FvInfo->FvFiles[Index]), "rb");\r
\r
if (NewFile == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", FvInfo->FvFiles[Index]);\r
//\r
FileBuffer = malloc (FileSize);\r
if (FileBuffer == NULL) {\r
- Error (NULL, 0, 4001, "Resouce", "memory cannot be allocated!");\r
+ fclose (NewFile);\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
// Done with the file, from this point on we will just use the buffer read.\r
//\r
fclose (NewFile);\r
- \r
+\r
//\r
// Verify read successful\r
//\r
Error (NULL, 0, 0004, "Error reading file", FvInfo->FvFiles[Index]);\r
return EFI_ABORTED;\r
}\r
- \r
+\r
//\r
// For None PI Ffs file, directly add them into FvImage.\r
//\r
if (!FvInfo->IsPiFvImage) {\r
memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
if (FvInfo->SizeofFvFiles[Index] > FileSize) {\r
- FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index];\r
+ FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index];\r
} else {\r
- FvImage->CurrentFilePointer += FileSize;\r
+ FvImage->CurrentFilePointer += FileSize;\r
}\r
goto Done;\r
}\r
- \r
+\r
//\r
// Verify Ffs file\r
//\r
Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer);\r
if (EFI_ERROR (Status)) {\r
free (FileBuffer);\r
- Error (NULL, 0, 3000, "Invalid", "%s is a FFS file.", FvInfo->FvFiles[Index]);\r
+ Error (NULL, 0, 3000, "Invalid", "%s is not a valid FFS file.", FvInfo->FvFiles[Index]);\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
for (Index1 = 0; Index1 < Index; Index1 ++) {\r
if (CompareGuid ((EFI_GUID *) FileBuffer, &mFileGuidArray [Index1]) == 0) {\r
- Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %dth file have the same file GUID.", Index1 + 1, Index + 1);\r
+ Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %uth file have the same file GUID.", (unsigned) Index1 + 1, (unsigned) Index + 1);\r
PrintGuid ((EFI_GUID *) FileBuffer);\r
+ free (FileBuffer);\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
// Check if alignment is required\r
//\r
ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);\r
- \r
+\r
//\r
// Find the largest alignment of all the FFS files in the FV\r
//\r
//\r
// Sanity check. The file MUST align appropriately\r
//\r
- if (((UINTN) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {\r
- Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %d-byte boundary.", 1 << CurrentFileAlignment);\r
+ if (((UINTN) *VtfFileImage + GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)FileBuffer) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {\r
+ Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %u-byte boundary.", (unsigned) (1 << CurrentFileAlignment));\r
free (FileBuffer);\r
return EFI_ABORTED;\r
}\r
//\r
- // Rebase the PE or TE image in FileBuffer of FFS file for XIP \r
+ // Rebase the PE or TE image in FileBuffer of FFS file for XIP\r
// Rebase for the debug genfvmap tool\r
//\r
- FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);\r
+ Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);\r
+ return Status;\r
+ }\r
//\r
// copy VTF File\r
//\r
memcpy (*VtfFileImage, FileBuffer, FileSize);\r
+\r
+ PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE);\r
+ fprintf (FvReportFile, "0x%08X %s\n", (unsigned)(UINTN) (((UINT8 *)*VtfFileImage) - (UINTN)FvImage->FileImage), FileGuidString);\r
+\r
free (FileBuffer);\r
DebugMsg (NULL, 0, 9, "Add VTF FFS file in FV image", NULL);\r
return EFI_SUCCESS;\r
//\r
// Add pad file if necessary\r
//\r
- Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, NULL);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property.");\r
- free (FileBuffer);\r
- return EFI_ABORTED;\r
+ if (!AdjustInternalFfsPadding ((EFI_FFS_FILE_HEADER *) FileBuffer, FvImage,\r
+ 1 << CurrentFileAlignment, &FileSize)) {\r
+ Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL, FileSize);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property.");\r
+ free (FileBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
}\r
//\r
// Add file\r
//\r
- if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {\r
+ if ((UINTN) (FvImage->CurrentFilePointer + FileSize) <= (UINTN) (*VtfFileImage)) {\r
//\r
- // Rebase the PE or TE image in FileBuffer of FFS file for XIP. \r
+ // Rebase the PE or TE image in FileBuffer of FFS file for XIP.\r
// Rebase Bs and Rt drivers for the debug genfvmap tool.\r
//\r
- FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);\r
+ Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);\r
+ return Status;\r
+ }\r
//\r
// Copy the file\r
//\r
memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
+ PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE);\r
+ fprintf (FvReportFile, "0x%08X %s\n", (unsigned) (FvImage->CurrentFilePointer - FvImage->FileImage), FileGuidString);\r
FvImage->CurrentFilePointer += FileSize;\r
} else {\r
Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add file %s.", FvInfo->FvFiles[Index]);\r
return EFI_ABORTED;\r
}\r
//\r
- // Make next file start at QWord Boundry\r
+ // Make next file start at QWord Boundary\r
//\r
while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {\r
FvImage->CurrentFilePointer++;\r
}\r
\r
-Done: \r
+Done:\r
//\r
// Free allocated memory.\r
//\r
{\r
EFI_FFS_FILE_HEADER *PadFile;\r
UINTN FileSize;\r
+ UINT32 FfsHeaderSize;\r
\r
//\r
// If there is no VTF or the VTF naturally follows the previous file without a\r
return EFI_SUCCESS;\r
}\r
\r
+ if ((UINTN) VtfFileImage < (UINTN) FvImage->CurrentFilePointer) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
//\r
// Pad file starts at beginning of free space\r
//\r
PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
\r
//\r
- // write PadFile FFS header with PadType, don't need to set PAD file guid in its header. \r
+ // write PadFile FFS header with PadType, don't need to set PAD file guid in its header.\r
//\r
PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;\r
PadFile->Attributes = 0;\r
// FileSize includes the EFI_FFS_FILE_HEADER\r
//\r
FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;\r
- PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);\r
- PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
- PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
+ if (FileSize >= MAX_FFS_SIZE) {\r
+ PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
+ memset(PadFile->Size, 0, sizeof(UINT8) * 3);\r
+ ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = FileSize;\r
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);\r
+ mIsLargeFfs = TRUE;\r
+ } else {\r
+ PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);\r
+ PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
+ PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);\r
+ }\r
\r
//\r
// Fill in checksums and state, must be zero during checksum calculation.\r
PadFile->IntegrityCheck.Checksum.Header = 0;\r
PadFile->IntegrityCheck.Checksum.File = 0;\r
PadFile->State = 0;\r
- PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
+ PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, FfsHeaderSize);\r
PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
\r
PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
UINT16 MachineType;\r
EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;\r
EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;\r
- EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;\r
INT32 Ia32SecEntryOffset;\r
UINT32 *Ia32ResetAddressPtr;\r
UINT8 *BytePointer;\r
UINT8 *BytePointer2;\r
UINT16 *WordPointer;\r
UINT16 CheckSum;\r
+ UINT32 IpiVector;\r
UINTN Index;\r
EFI_FFS_FILE_STATE SavedState;\r
- UINT64 FitAddress;\r
- FIT_TABLE *FitTablePtr;\r
- UINT32 IpiVector;\r
+ BOOLEAN Vtf0Detected;\r
+ UINT32 FfsHeaderSize;\r
+ UINT32 SecHeaderSize;\r
\r
//\r
// Verify input parameters\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ if (\r
+ (((UINTN)FvImage->Eof - (UINTN)FvImage->FileImage) >=\r
+ IA32_X64_VTF_SIGNATURE_OFFSET) &&\r
+ (*(UINT32 *)(VOID*)((UINTN) FvImage->Eof -\r
+ IA32_X64_VTF_SIGNATURE_OFFSET) ==\r
+ IA32_X64_VTF0_SIGNATURE)\r
+ ) {\r
+ Vtf0Detected = TRUE;\r
+ } else {\r
+ Vtf0Detected = FALSE;\r
+ }\r
+\r
//\r
// Find the Sec Core\r
//\r
Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
+ if (Vtf0Detected) {\r
+ //\r
+ // If the SEC core file is not found, but the VTF-0 signature\r
+ // is found, we'll treat it as a VTF-0 'Volume Top File'.\r
+ // This means no modifications are required to the VTF.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
Error (NULL, 0, 3000, "Invalid", "could not find the SEC core file in the FV.");\r
return EFI_ABORTED;\r
}\r
return EFI_ABORTED;\r
}\r
\r
+ SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);\r
Status = GetPe32Info (\r
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),\r
&EntryPoint,\r
&BaseOfCode,\r
&MachineType\r
if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core.");\r
return EFI_ABORTED;\r
- } \r
+ }\r
+\r
+ if (\r
+ Vtf0Detected &&\r
+ (MachineType == EFI_IMAGE_MACHINE_IA32 ||\r
+ MachineType == EFI_IMAGE_MACHINE_X64)\r
+ ) {\r
+ //\r
+ // If the SEC core code is IA32 or X64 and the VTF-0 signature\r
+ // is found, we'll treat it as a VTF-0 'Volume Top File'.\r
+ // This means no modifications are required to the VTF.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
\r
//\r
// Physical address is FV base + offset of PE32 + offset of the entry point\r
//\r
SecCorePhysicalAddress = FvInfo->BaseAddress;\r
- SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+ SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;\r
SecCorePhysicalAddress += EntryPoint;\r
- DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%X", SecCorePhysicalAddress); \r
+ DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);\r
\r
//\r
// Find the PEI Core\r
//\r
+ PeiCorePhysicalAddress = 0;\r
Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);\r
- if (EFI_ERROR (Status) || PeiCoreFile == NULL) {\r
- Error (NULL, 0, 3000, "Invalid", "could not find the PEI core in the FV.");\r
- return EFI_ABORTED;\r
- }\r
- //\r
- // PEI Core found, now find PE32 or TE section\r
- //\r
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
- if (Status == EFI_NOT_FOUND) {\r
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file.");\r
- return EFI_ABORTED;\r
- }\r
-\r
- Status = GetPe32Info (\r
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
- &EntryPoint,\r
- &BaseOfCode,\r
- &MachineType\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core.");\r
- return EFI_ABORTED;\r
- }\r
- //\r
- // Physical address is FV base + offset of PE32 + offset of the entry point\r
- //\r
- PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
- PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
- PeiCorePhysicalAddress += EntryPoint;\r
- DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%X", PeiCorePhysicalAddress);\r
-\r
- if (MachineType == EFI_IMAGE_MACHINE_IA64) {\r
+ if (!EFI_ERROR (Status) && (PeiCoreFile != NULL)) {\r
//\r
- // Update PEI_CORE address\r
- //\r
- //\r
- // Set the uncached attribute bit in the physical address\r
+ // PEI Core found, now find PE32 or TE section\r
//\r
- PeiCorePhysicalAddress |= 0x8000000000000000ULL;\r
+ Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
+ }\r
\r
- //\r
- // Check if address is aligned on a 16 byte boundary\r
- //\r
- if (PeiCorePhysicalAddress & 0xF) {\r
- Error (NULL, 0, 3000, "Invalid",\r
- "PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.",\r
- PeiCorePhysicalAddress\r
- );\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file.");\r
return EFI_ABORTED;\r
}\r
- //\r
- // First Get the FIT table address\r
- //\r
- FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;\r
-\r
- FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));\r
-\r
- Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);\r
\r
- if (!EFI_ERROR (Status)) {\r
- UpdateFitCheckSum (FitTablePtr);\r
- }\r
+ SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);\r
+ Status = GetPe32Info (\r
+ (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),\r
+ &EntryPoint,\r
+ &BaseOfCode,\r
+ &MachineType\r
+ );\r
\r
- //\r
- // Update SEC_CORE address\r
- //\r
- //\r
- // Set the uncached attribute bit in the physical address\r
- //\r
- SecCorePhysicalAddress |= 0x8000000000000000ULL;\r
- //\r
- // Check if address is aligned on a 16 byte boundary\r
- //\r
- if (SecCorePhysicalAddress & 0xF) {\r
- Error (NULL, 0, 3000, "Invalid",\r
- "SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.",\r
- SecCorePhysicalAddress\r
- );\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core.");\r
return EFI_ABORTED;\r
}\r
//\r
- // Update the address\r
+ // Physical address is FV base + offset of PE32 + offset of the entry point\r
//\r
- SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);\r
- *SecCoreEntryAddressPtr = SecCorePhysicalAddress;\r
+ PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
+ PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;\r
+ PeiCorePhysicalAddress += EntryPoint;\r
+ DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);\r
+ }\r
\r
- } else if (\r
- (MachineType == EFI_IMAGE_MACHINE_IA32 ||\r
- MachineType == EFI_IMAGE_MACHINE_X64) &&\r
- (((UINTN)FvImage->Eof - (UINTN)FvImage->FileImage) >= IA32_X64_VTF_SIGNATURE_OFFSET) &&\r
- (*(UINT32 *)(VOID*)((UINTN) FvImage->Eof - IA32_X64_VTF_SIGNATURE_OFFSET) ==\r
- IA32_X64_VTF0_SIGNATURE)\r
- ) {\r
- //\r
- // If VTF-0 signature is found, then no modifications are needed.\r
- //\r
- } else if (MachineType == EFI_IMAGE_MACHINE_IA32 || MachineType == EFI_IMAGE_MACHINE_X64) {\r
- //\r
- // Get the location to update\r
- //\r
- Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
+if (MachineType == EFI_IMAGE_MACHINE_IA32 || MachineType == EFI_IMAGE_MACHINE_X64) {\r
+ if (PeiCorePhysicalAddress != 0) {\r
+ //\r
+ // Get the location to update\r
+ //\r
+ Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
\r
- //\r
- // Write lower 32 bits of physical address for Pei Core entry\r
- //\r
- *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;\r
- \r
+ //\r
+ // Write lower 32 bits of physical address for Pei Core entry\r
+ //\r
+ *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;\r
+ }\r
//\r
// Write SecCore Entry point relative address into the jmp instruction in reset vector.\r
- // \r
+ //\r
Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_SEC_CORE_ENTRY_OFFSET);\r
- \r
- Ia32SecEntryOffset = SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2);\r
+\r
+ Ia32SecEntryOffset = (INT32) (SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2));\r
if (Ia32SecEntryOffset <= -65536) {\r
Error (NULL, 0, 3000, "Invalid", "The SEC EXE file size is too large, it must be less than 64K.");\r
return STATUS_ERROR;\r
}\r
- \r
+\r
*(UINT16 *) Ia32ResetAddressPtr = (UINT16) Ia32SecEntryOffset;\r
\r
//\r
//\r
Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);\r
*Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);\r
- DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%X.", FvInfo->BaseAddress);\r
+ DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%llX.", (unsigned long long) FvInfo->BaseAddress);\r
\r
//\r
// Update the Startup AP in the FVH header block ZeroVector region.\r
//\r
Status = FindApResetVectorPosition (FvImage, &BytePointer);\r
if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "Cannot find the appropriate location in FvImage to add Ap reset vector!");\r
+ 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.");\r
return EFI_ABORTED;\r
}\r
}\r
//\r
WordPointer = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2);\r
*WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);\r
- \r
+\r
//\r
- // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV. \r
+ // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV.\r
//\r
- IpiVector = FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer);\r
- DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", IpiVector);\r
- if (IpiVector & 0xFFF != 0) {\r
+ IpiVector = (UINT32) (FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer));\r
+ DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", (unsigned) IpiVector);\r
+ if ((IpiVector & 0xFFF) != 0) {\r
Error (NULL, 0, 3000, "Invalid", "Startup AP Vector address are not 4K aligned, because the FV size is not 4K aligned");\r
return EFI_ABORTED;\r
}\r
// Since the ARM reset vector is in the FV Header you really don't need a\r
// Volume Top File, but if you have one for some reason don't crash...\r
//\r
+ } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
+ //\r
+ // Since the AArch64 reset vector is in the FV Header you really don't need a\r
+ // Volume Top File, but if you have one for some reason don't crash...\r
+ //\r
} else {\r
- Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", (UINT32) MachineType);\r
+ Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", MachineType);\r
return EFI_ABORTED;\r
}\r
\r
VtfFile->IntegrityCheck.Checksum.File = 0;\r
VtfFile->State = 0;\r
if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ FfsHeaderSize = GetFfsHeaderLength(VtfFile);\r
VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
- (UINT8 *) VtfFile,\r
- GetLength (VtfFile->Size)\r
+ (UINT8 *) ((UINT8 *)VtfFile + FfsHeaderSize),\r
+ GetFfsFileLength (VtfFile) - FfsHeaderSize\r
);\r
} else {\r
VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
return EFI_SUCCESS;\r
}\r
\r
+EFI_STATUS\r
+FindCorePeSection(\r
+ IN VOID *FvImageBuffer,\r
+ IN UINT64 FvSize,\r
+ IN EFI_FV_FILETYPE FileType,\r
+ OUT EFI_FILE_SECTION_POINTER *Pe32Section\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Recursively searches the FV for the FFS file of specified type (typically\r
+ SEC or PEI core) and extracts the PE32 section for further processing.\r
+\r
+Arguments:\r
+\r
+ FvImageBuffer Buffer containing FV data\r
+ FvSize Size of the FV\r
+ FileType Type of FFS file to search for\r
+ Pe32Section PE32 section pointer when FFS file is found.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Function Completed successfully.\r
+ EFI_ABORTED Error encountered.\r
+ EFI_INVALID_PARAMETER A required parameter was NULL.\r
+ EFI_NOT_FOUND Core file not found.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_VOLUME_HEADER *OrigFvHeader;\r
+ UINT32 OrigFvLength;\r
+ EFI_FFS_FILE_HEADER *CoreFfsFile;\r
+ UINTN FvImageFileCount;\r
+ EFI_FFS_FILE_HEADER *FvImageFile;\r
+ UINTN EncapFvSectionCount;\r
+ EFI_FILE_SECTION_POINTER EncapFvSection;\r
+ EFI_FIRMWARE_VOLUME_HEADER *EncapsulatedFvHeader;\r
+\r
+ if (Pe32Section == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize FV library, saving previous values\r
+ //\r
+ OrigFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NULL;\r
+ GetFvHeader (&OrigFvHeader, &OrigFvLength);\r
+ InitializeFvLib(FvImageBuffer, (UINT32)FvSize);\r
+\r
+ //\r
+ // First see if we can obtain the file directly in outer FV\r
+ //\r
+ Status = GetFileByType(FileType, 1, &CoreFfsFile);\r
+ if (!EFI_ERROR(Status) && (CoreFfsFile != NULL) ) {\r
+\r
+ //\r
+ // Core found, now find PE32 or TE section\r
+ //\r
+ Status = GetSectionByType(CoreFfsFile, EFI_SECTION_PE32, 1, Pe32Section);\r
+ if (EFI_ERROR(Status)) {\r
+ Status = GetSectionByType(CoreFfsFile, EFI_SECTION_TE, 1, Pe32Section);\r
+ }\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "could not find a PE32 section in the core file.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Core PE/TE section, found, return\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ goto EarlyExit;\r
+ }\r
+\r
+ //\r
+ // File was not found, look for FV Image file\r
+ //\r
+\r
+ // iterate through all FV image files in outer FV\r
+ for (FvImageFileCount = 1;; FvImageFileCount++) {\r
+\r
+ Status = GetFileByType(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, FvImageFileCount, &FvImageFile);\r
+\r
+ if (EFI_ERROR(Status) || (FvImageFile == NULL) ) {\r
+ // exit FV image file loop, no more found\r
+ break;\r
+ }\r
+\r
+ // Found an fv image file, look for an FV image section. The PI spec does not\r
+ // preclude multiple FV image sections so we loop accordingly.\r
+ for (EncapFvSectionCount = 1;; EncapFvSectionCount++) {\r
+\r
+ // Look for the next FV image section. The section search code will\r
+ // iterate into encapsulation sections. For example, it will iterate\r
+ // into an EFI_SECTION_GUID_DEFINED encapsulation section to find the\r
+ // EFI_SECTION_FIRMWARE_VOLUME_IMAGE sections contained therein.\r
+ Status = GetSectionByType(FvImageFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EncapFvSectionCount, &EncapFvSection);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ // exit section inner loop, no more found\r
+ break;\r
+ }\r
+\r
+ EncapsulatedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)EncapFvSection.FVImageSection + GetSectionHeaderLength(EncapFvSection.FVImageSection));\r
+\r
+ // recurse to search the encapsulated FV for this core file type\r
+ Status = FindCorePeSection(EncapsulatedFvHeader, EncapsulatedFvHeader->FvLength, FileType, Pe32Section);\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ // we found the core in the capsulated image, success\r
+ goto EarlyExit;\r
+ }\r
+\r
+ } // end encapsulated fv image section loop\r
+ } // end fv image file loop\r
+\r
+ // core was not found\r
+ Status = EFI_NOT_FOUND;\r
+\r
+EarlyExit:\r
+\r
+ // restore FV lib values\r
+ if(OrigFvHeader != NULL) {\r
+ InitializeFvLib(OrigFvHeader, OrigFvLength);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+GetCoreMachineType(\r
+ IN EFI_FILE_SECTION_POINTER Pe32Section,\r
+ OUT UINT16 *CoreMachineType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Returns the machine type of a P32 image, typically SEC or PEI core.\r
+\r
+Arguments:\r
+\r
+ Pe32Section PE32 section data\r
+ CoreMachineType The extracted machine type\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Function Completed successfully.\r
+ EFI_ABORTED Error encountered.\r
+ EFI_INVALID_PARAMETER A required parameter was NULL.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 EntryPoint;\r
+ UINT32 BaseOfCode;\r
+\r
+ if (CoreMachineType == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = GetPe32Info(\r
+ (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),\r
+ &EntryPoint,\r
+ &BaseOfCode,\r
+ CoreMachineType\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "could not get the PE32 machine type for the core.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetCoreEntryPointAddress(\r
+ IN VOID *FvImageBuffer,\r
+ IN FV_INFO *FvInfo,\r
+ IN EFI_FILE_SECTION_POINTER Pe32Section,\r
+ OUT EFI_PHYSICAL_ADDRESS *CoreEntryAddress\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Returns the physical address of the core (SEC or PEI) entry point.\r
+\r
+Arguments:\r
+\r
+ FvImageBuffer Pointer to buffer containing FV data\r
+ FvInfo Info for the parent FV\r
+ Pe32Section PE32 section data\r
+ CoreEntryAddress The extracted core entry physical address\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Function Completed successfully.\r
+ EFI_ABORTED Error encountered.\r
+ EFI_INVALID_PARAMETER A required parameter was NULL.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 EntryPoint;\r
+ UINT32 BaseOfCode;\r
+ UINT16 MachineType;\r
+ EFI_PHYSICAL_ADDRESS EntryPhysicalAddress;\r
+\r
+ if (CoreEntryAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = GetPe32Info(\r
+ (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),\r
+ &EntryPoint,\r
+ &BaseOfCode,\r
+ &MachineType\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the core.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Physical address is FV base + offset of PE32 + offset of the entry point\r
+ //\r
+ EntryPhysicalAddress = FvInfo->BaseAddress;\r
+ EntryPhysicalAddress += (UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader) - (UINTN)FvImageBuffer;\r
+ EntryPhysicalAddress += EntryPoint;\r
+\r
+ *CoreEntryAddress = EntryPhysicalAddress;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
EFI_STATUS\r
UpdateArmResetVectorIfNeeded (\r
/*++\r
\r
Routine Description:\r
- This parses the FV looking for SEC and patches that address into the \r
+ This parses the FV looking for SEC and patches that address into the\r
beginning of the FV header.\r
\r
- For ARM the reset vector is at 0x00000000 or 0xFFFF0000.\r
- This would commonly map to the first entry in the ROM. \r
- ARM Exceptions:\r
- Reset +0 \r
+ For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000.\r
+ For AArch64 the reset vector is at 0x00000000.\r
+\r
+ This would commonly map to the first entry in the ROM.\r
+ ARM32 Exceptions:\r
+ Reset +0\r
Undefined +4\r
SWI +8\r
Prefetch Abort +12\r
FIQ +24\r
\r
We support two schemes on ARM.\r
- 1) Begining of the FV is the reset vector\r
- 2) Reset vector is data bytes FDF file and that code branches to reset vector \r
+ 1) Beginning of the FV is the reset vector\r
+ 2) Reset vector is data bytes FDF file and that code branches to reset vector\r
in the beginning of the FV (fixed size offset).\r
\r
-\r
Need to have the jump for the reset vector at location zero.\r
We also need to store the address or PEI (if it exists).\r
- We stub out a return from interrupt in case the debugger \r
- is using SWI.\r
- The optional entry to the common exception handler is \r
- to support full featured exception handling from ROM and is currently \r
+ We stub out a return from interrupt in case the debugger\r
+ is using SWI (not done for AArch64, not enough space in struct).\r
+ The optional entry to the common exception handler is\r
+ to support full featured exception handling from ROM and is currently\r
not support by this tool.\r
\r
Arguments:\r
\r
--*/\r
{\r
- EFI_FFS_FILE_HEADER *PeiCoreFile;\r
- EFI_FFS_FILE_HEADER *SecCoreFile;\r
- EFI_STATUS Status;\r
- EFI_FILE_SECTION_POINTER Pe32Section;\r
- UINT32 EntryPoint;\r
- UINT32 BaseOfCode;\r
- UINT16 MachineType;\r
- EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;\r
- EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;\r
- INT32 ResetVector[4]; // 0 - is branch relative to SEC entry point\r
- // 1 - PEI Entry Point\r
- // 2 - movs pc,lr for a SWI handler\r
- // 3 - Place holder for Common Exception Handler\r
+ EFI_STATUS Status;\r
+ EFI_FILE_SECTION_POINTER SecPe32;\r
+ EFI_FILE_SECTION_POINTER PeiPe32;\r
+ BOOLEAN UpdateVectorSec = FALSE;\r
+ BOOLEAN UpdateVectorPei = FALSE;\r
+ UINT16 MachineType = 0;\r
+ EFI_PHYSICAL_ADDRESS SecCoreEntryAddress = 0;\r
+ UINT16 PeiMachineType = 0;\r
+ EFI_PHYSICAL_ADDRESS PeiCoreEntryAddress = 0;\r
\r
//\r
// Verify input parameters\r
if (FvImage == NULL || FvInfo == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
+\r
//\r
- // Initialize FV library\r
+ // Locate an SEC Core instance and if found extract the machine type and entry point address\r
//\r
- InitializeFvLib (FvImage->FileImage, FvInfo->Size);\r
+ Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32);\r
+ if (!EFI_ERROR(Status)) {\r
+\r
+ Status = GetCoreMachineType(SecPe32, &MachineType);\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC Core.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress);\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ VerboseMsg("UpdateArmResetVectorIfNeeded found SEC core entry at 0x%llx", (unsigned long long)SecCoreEntryAddress);\r
+ UpdateVectorSec = TRUE;\r
+ }\r
\r
//\r
- // Find the Sec Core\r
+ // Locate a PEI Core instance and if found extract the machine type and entry point address\r
//\r
- Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
- if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
- //\r
- // Maybe hardware does SEC job and we only have PEI Core?\r
- //\r
+ Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_PEI_CORE, &PeiPe32);\r
+ if (!EFI_ERROR(Status)) {\r
\r
- //\r
- // Find the PEI Core. It may not exist if SEC loads DXE core directly\r
- //\r
- PeiCorePhysicalAddress = 0;\r
- Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);\r
- if (!EFI_ERROR (Status) && PeiCoreFile != NULL) {\r
- //\r
- // PEI Core found, now find PE32 or TE section\r
- //\r
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
- if (Status == EFI_NOT_FOUND) {\r
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
- }\r
- \r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!");\r
+ Status = GetCoreMachineType(PeiPe32, &PeiMachineType);\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for PEI Core.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, PeiPe32, &PeiCoreEntryAddress);\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for PEI Core.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ VerboseMsg("UpdateArmResetVectorIfNeeded found PEI core entry at 0x%llx", (unsigned long long)PeiCoreEntryAddress);\r
+\r
+ // if we previously found an SEC Core make sure machine types match\r
+ if (UpdateVectorSec && (MachineType != PeiMachineType)) {\r
+ Error(NULL, 0, 3000, "Invalid", "SEC and PEI machine types do not match, can't update reset vector");\r
+ return EFI_ABORTED;\r
+ }\r
+ else {\r
+ MachineType = PeiMachineType;\r
+ }\r
+\r
+ UpdateVectorPei = TRUE;\r
+ }\r
+\r
+ if (!UpdateVectorSec && !UpdateVectorPei) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (MachineType == EFI_IMAGE_MACHINE_ARMT) {\r
+ // ARM: Array of 4 UINT32s:\r
+ // 0 - is branch relative to SEC entry point\r
+ // 1 - PEI Entry Point\r
+ // 2 - movs pc,lr for a SWI handler\r
+ // 3 - Place holder for Common Exception Handler\r
+ UINT32 ResetVector[4];\r
+\r
+ memset(ResetVector, 0, sizeof (ResetVector));\r
+\r
+ // if we found an SEC core entry point then generate a branch instruction\r
+ // to it and populate a debugger SWI entry as well\r
+ if (UpdateVectorSec) {\r
+\r
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM SEC vector");\r
+\r
+ // B SecEntryPoint - signed_immed_24 part +/-32MB offset\r
+ // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8\r
+ ResetVector[0] = (INT32)(SecCoreEntryAddress - FvInfo->BaseAddress - 8) >> 2;\r
+\r
+ if (ResetVector[0] > 0x00FFFFFF) {\r
+ Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");\r
return EFI_ABORTED;\r
}\r
- \r
- Status = GetPe32Info (\r
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
- &EntryPoint,\r
- &BaseOfCode,\r
- &MachineType\r
- );\r
- \r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!");\r
+\r
+ // Add opcode for an unconditional branch with no link. i.e.: " B SecEntryPoint"\r
+ ResetVector[0] |= ARMT_UNCONDITIONAL_JUMP_INSTRUCTION;\r
+\r
+ // SWI handler movs pc,lr. Just in case a debugger uses SWI\r
+ ResetVector[2] = 0xE1B0F07E;\r
+\r
+ // Place holder to support a common interrupt handler from ROM.\r
+ // Currently not supported. For this to be used the reset vector would not be in this FV\r
+ // and the exception vectors would be hard coded in the ROM and just through this address\r
+ // to find a common handler in the a module in the FV.\r
+ ResetVector[3] = 0;\r
+ }\r
+\r
+ // if a PEI core entry was found place its address in the vector area\r
+ if (UpdateVectorPei) {\r
+\r
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM PEI address");\r
+\r
+ // Address of PEI Core, if we have one\r
+ ResetVector[1] = (UINT32)PeiCoreEntryAddress;\r
+ }\r
+\r
+ //\r
+ // Copy to the beginning of the FV\r
+ //\r
+ memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector));\r
+\r
+ } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {\r
+ // AArch64: Used as UINT64 ResetVector[2]\r
+ // 0 - is branch relative to SEC entry point\r
+ // 1 - PEI Entry Point\r
+ UINT64 ResetVector[2];\r
+\r
+ memset(ResetVector, 0, sizeof (ResetVector));\r
+\r
+ /* NOTE:\r
+ ARMT above has an entry in ResetVector[2] for SWI. The way we are using the ResetVector\r
+ array at the moment, for AArch64, does not allow us space for this as the header only\r
+ allows for a fixed amount of bytes at the start. If we are sure that UEFI will live\r
+ within the first 4GB of addressable RAM we could potentially adopt the same ResetVector\r
+ layout as above. But for the moment we replace the four 32bit vectors with two 64bit\r
+ vectors in the same area of the Image heasder. This allows UEFI to start from a 64bit\r
+ base.\r
+ */\r
+\r
+ // if we found an SEC core entry point then generate a branch instruction to it\r
+ if (UpdateVectorSec) {\r
+\r
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 SEC vector");\r
+\r
+ ResetVector[0] = (UINT64)(SecCoreEntryAddress - FvInfo->BaseAddress) >> 2;\r
+\r
+ // B SecEntryPoint - signed_immed_26 part +/-128MB offset\r
+ if (ResetVector[0] > 0x03FFFFFF) {\r
+ Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 128MB of the start of the FV");\r
return EFI_ABORTED;\r
}\r
- //\r
- // Physical address is FV base + offset of PE32 + offset of the entry point\r
- //\r
- PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
- PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
- PeiCorePhysicalAddress += EntryPoint;\r
- DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%X", PeiCorePhysicalAddress);\r
-\r
- if (MachineType == EFI_IMAGE_MACHINE_ARMT) {\r
- memset (ResetVector, 0, sizeof (ResetVector));\r
- // Address of PEI Core, if we have one\r
- ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
- }\r
- \r
- //\r
- // Copy to the beginning of the FV \r
- //\r
- memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector));\r
+ // Add opcode for an unconditional branch with no link. i.e.: " B SecEntryPoint"\r
+ ResetVector[0] |= ARM64_UNCONDITIONAL_JUMP_INSTRUCTION;\r
+ }\r
\r
+ // if a PEI core entry was found place its address in the vector area\r
+ if (UpdateVectorPei) {\r
+\r
+ VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 PEI address");\r
+\r
+ // Address of PEI Core, if we have one\r
+ ResetVector[1] = (UINT64)PeiCoreEntryAddress;\r
}\r
\r
- return EFI_SUCCESS;\r
+ //\r
+ // Copy to the beginning of the FV\r
+ //\r
+ memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector));\r
+\r
+ } else {\r
+ Error(NULL, 0, 3000, "Invalid", "Unknown machine type");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdateRiscvResetVectorIfNeeded (\r
+ MEMORY_FILE *FvImage,\r
+ FV_INFO *FvInfo\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This parses the FV looking for SEC and patches that address into the\r
+ beginning of the FV header.\r
+\r
+ For RISC-V ISA, the reset vector is at 0xfff~ff00h or 200h\r
+\r
+Arguments:\r
+ FvImage Memory file for the FV memory image/\r
+ FvInfo Information read from INF file.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Function Completed successfully.\r
+ EFI_ABORTED Error encountered.\r
+ EFI_INVALID_PARAMETER A required parameter was NULL.\r
+ EFI_NOT_FOUND PEI Core file not found.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 MachineType;\r
+ EFI_FILE_SECTION_POINTER SecPe32;\r
+ EFI_PHYSICAL_ADDRESS SecCoreEntryAddress;\r
+\r
+ UINT32 bSecCore;\r
+ UINT32 tmp;\r
+\r
+\r
+ //\r
+ // Verify input parameters\r
+ //\r
+ if (FvImage == NULL || FvInfo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
- \r
//\r
- // Sec Core found, now find PE32 section\r
+ // Initialize FV library\r
//\r
- Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
- if (Status == EFI_NOT_FOUND) {\r
- Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
+ InitializeFvLib (FvImage->FileImage, FvInfo->Size);\r
+\r
+ //\r
+ // Find the Sec Core\r
+ //\r
+ Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32);\r
+ if(EFI_ERROR(Status)) {\r
+ printf("skip because Secutiry Core not found\n");\r
+ return EFI_SUCCESS;\r
}\r
\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file.");\r
+ DebugMsg (NULL, 0, 9, "Update SEC core in FV Header", NULL);\r
+\r
+ Status = GetCoreMachineType(SecPe32, &MachineType);\r
+ if(EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC core.");\r
return EFI_ABORTED;\r
}\r
\r
- Status = GetPe32Info (\r
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
- &EntryPoint,\r
- &BaseOfCode,\r
- &MachineType\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core.");\r
+ if (MachineType != EFI_IMAGE_MACHINE_RISCV64) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not update SEC core because Machine type is not RiscV.");\r
return EFI_ABORTED;\r
}\r
- \r
- if (MachineType != EFI_IMAGE_MACHINE_ARMT) {\r
- //\r
- // If SEC is not ARM we have nothing to do\r
- //\r
- return EFI_SUCCESS;\r
+\r
+ Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress);\r
+ if(EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core.");\r
+ return EFI_ABORTED;\r
}\r
- \r
- //\r
- // Physical address is FV base + offset of PE32 + offset of the entry point\r
- //\r
- SecCorePhysicalAddress = FvInfo->BaseAddress;\r
- SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
- SecCorePhysicalAddress += EntryPoint;\r
- DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%X", SecCorePhysicalAddress); \r
\r
- //\r
- // Find the PEI Core. It may not exist if SEC loads DXE core directly\r
- //\r
- PeiCorePhysicalAddress = 0;\r
- Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);\r
- if (!EFI_ERROR (Status) && PeiCoreFile != NULL) {\r
- //\r
- // PEI Core found, now find PE32 or TE section\r
- //\r
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
- if (Status == EFI_NOT_FOUND) {\r
- Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
- }\r
- \r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file!");\r
- return EFI_ABORTED;\r
- }\r
- \r
- Status = GetPe32Info (\r
- (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
- &EntryPoint,\r
- &BaseOfCode,\r
- &MachineType\r
- );\r
- \r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core!");\r
- return EFI_ABORTED;\r
- }\r
- //\r
- // Physical address is FV base + offset of PE32 + offset of the entry point\r
- //\r
- PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
- PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
- PeiCorePhysicalAddress += EntryPoint;\r
- DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%X", PeiCorePhysicalAddress);\r
- }\r
- \r
- \r
- // B SecEntryPoint - signed_immed_24 part +/-32MB offset\r
- // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8\r
- ResetVector[0] = (INT32)(SecCorePhysicalAddress - FvInfo->BaseAddress - 8) >> 2;\r
- \r
- if (ResetVector[0] > 0x00FFFFFF) {\r
- Error (NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV");\r
- return EFI_ABORTED; \r
- }\r
- \r
- // Add opcode for an uncondional branch with no link. AKA B SecEntryPoint\r
- ResetVector[0] |= 0xEA000000;\r
- \r
- \r
- // Address of PEI Core, if we have one\r
- ResetVector[1] = (UINT32)PeiCorePhysicalAddress;\r
- \r
- // SWI handler movs pc,lr. Just in case a debugger uses SWI\r
- ResetVector[2] = 0xE1B0F07E;\r
- \r
- // Place holder to support a common interrupt handler from ROM. \r
- // Currently not suppprted. For this to be used the reset vector would not be in this FV\r
- // and the exception vectors would be hard coded in the ROM and just through this address \r
- // to find a common handler in the a module in the FV.\r
- ResetVector[3] = 0;\r
-\r
- //\r
- // Copy to the beginning of the FV \r
- //\r
- memcpy ((UINT8 *) ((UINTN) FvImage->FileImage), ResetVector, sizeof (ResetVector));\r
-\r
- DebugMsg (NULL, 0, 9, "Update Reset vector in FV Header", NULL);\r
+ VerboseMsg("SecCore entry point Address = 0x%llX", (unsigned long long) SecCoreEntryAddress);\r
+ VerboseMsg("BaseAddress = 0x%llX", (unsigned long long) FvInfo->BaseAddress);\r
+ bSecCore = (UINT32)(SecCoreEntryAddress - FvInfo->BaseAddress);\r
+ VerboseMsg("offset = 0x%llX", bSecCore);\r
+\r
+ if(bSecCore > 0x0fffff) {\r
+ Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 1MB of start of the FV");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ tmp = bSecCore;\r
+ bSecCore = 0;\r
+ //J-type\r
+ bSecCore = (tmp&0x100000)<<11; //imm[20] at bit[31]\r
+ bSecCore |= (tmp&0x0007FE)<<20; //imm[10:1] at bit[30:21]\r
+ bSecCore |= (tmp&0x000800)<<9; //imm[11] at bit[20]\r
+ bSecCore |= (tmp&0x0FF000); //imm[19:12] at bit[19:12]\r
+ bSecCore |= 0x6F; //JAL opcode\r
+\r
+ memcpy(FvImage->FileImage, &bSecCore, sizeof(bSecCore));\r
\r
return EFI_SUCCESS;\r
}\r
\r
Routine Description:\r
\r
- Retrieves the PE32 entry point offset and machine type from PE image or TeImage. \r
- See EfiImage.h for machine types. The entry point offset is from the beginning \r
+ Retrieves the PE32 entry point offset and machine type from PE image or TeImage.\r
+ See EfiImage.h for machine types. The entry point offset is from the beginning\r
of the PE32 buffer passed in.\r
\r
Arguments:\r
*BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;\r
*MachineType = TeHeader->Machine;\r
} else {\r
- \r
+\r
//\r
- // Then check whether \r
+ // Then check whether\r
// First is the DOS header\r
//\r
DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;\r
- \r
+\r
//\r
// Verify DOS header is expected\r
//\r
// Immediately following is the NT header.\r
//\r
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN) Pe32 + DosHeader->e_lfanew);\r
- \r
+\r
//\r
// Verify NT header is expected\r
//\r
if (ImgHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
- Error (NULL, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", ImgHdr->Pe32.Signature);\r
+ Error (NULL, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", (unsigned) ImgHdr->Pe32.Signature);\r
return EFI_UNSUPPORTED;\r
}\r
//\r
//\r
// Verify machine type is supported\r
//\r
- if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC && \r
- *MachineType != EFI_IMAGE_MACHINE_ARMT) {\r
+ if ((*MachineType != EFI_IMAGE_MACHINE_IA32) && (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) &&\r
+ (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64) &&\r
+ (*MachineType != EFI_IMAGE_MACHINE_RISCV64)) {\r
Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");\r
return EFI_UNSUPPORTED;\r
}\r
\r
--*/\r
{\r
- EFI_STATUS Status;\r
- MEMORY_FILE InfMemoryFile;\r
- MEMORY_FILE FvImageMemoryFile;\r
- UINTN Index;\r
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
- EFI_FFS_FILE_HEADER *VtfFileImage;\r
- UINT8 *FvBufferHeader; // to make sure fvimage header 8 type alignment.\r
- UINT8 *FvImage;\r
- UINTN FvImageSize;\r
- FILE *FvFile;\r
- CHAR8 FvMapName [_MAX_PATH];\r
- FILE *FvMapFile;\r
- EFI_FIRMWARE_VOLUME_EXT_HEADER FvExtHeader;\r
+ EFI_STATUS Status;\r
+ MEMORY_FILE InfMemoryFile;\r
+ MEMORY_FILE FvImageMemoryFile;\r
+ UINTN Index;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+ EFI_FFS_FILE_HEADER *VtfFileImage;\r
+ UINT8 *FvBufferHeader; // to make sure fvimage header 8 type alignment.\r
+ UINT8 *FvImage;\r
+ UINTN FvImageSize;\r
+ FILE *FvFile;\r
+ CHAR8 *FvMapName;\r
+ FILE *FvMapFile;\r
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;\r
+ FILE *FvExtHeaderFile;\r
+ UINTN FileSize;\r
+ CHAR8 *FvReportName;\r
+ FILE *FvReportFile;\r
\r
FvBufferHeader = NULL;\r
FvFile = NULL;\r
+ FvMapName = NULL;\r
FvMapFile = NULL;\r
+ FvReportName = NULL;\r
+ FvReportFile = NULL;\r
\r
if (InfFileImage != NULL) {\r
//\r
InfMemoryFile.FileImage = InfFileImage;\r
InfMemoryFile.CurrentFilePointer = InfFileImage;\r
InfMemoryFile.Eof = InfFileImage + InfFileSize;\r
- \r
+\r
//\r
// Parse the FV inf file for header information\r
//\r
Error (NULL, 0, 1001, "Missing option", "Output file name");\r
return EFI_ABORTED;\r
}\r
- \r
+\r
if (mFvDataInfo.FvBlocks[0].Length == 0) {\r
Error (NULL, 0, 1001, "Missing required argument", "Block Size");\r
return EFI_ABORTED;\r
}\r
- \r
+\r
//\r
// Debug message Fv File System Guid\r
//\r
if (mFvDataInfo.FvFileSystemGuidSet) {\r
- DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
- mFvDataInfo.FvFileSystemGuid.Data1,\r
+ DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
+ (unsigned) mFvDataInfo.FvFileSystemGuid.Data1,\r
mFvDataInfo.FvFileSystemGuid.Data2,\r
mFvDataInfo.FvFileSystemGuid.Data3,\r
mFvDataInfo.FvFileSystemGuid.Data4[0],\r
mFvDataInfo.FvFileSystemGuid.Data4[6],\r
mFvDataInfo.FvFileSystemGuid.Data4[7]);\r
}\r
+\r
+ //\r
+ // Add PI FV extension header\r
+ //\r
+ FvExtHeader = NULL;\r
+ FvExtHeaderFile = NULL;\r
+ if (mFvDataInfo.FvExtHeaderFile[0] != 0) {\r
+ //\r
+ // Open the FV Extension Header file\r
+ //\r
+ FvExtHeaderFile = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");\r
+ if (FvExtHeaderFile == NULL) {\r
+ Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get the file size\r
+ //\r
+ FileSize = _filelength (fileno (FvExtHeaderFile));\r
+\r
+ //\r
+ // Allocate a buffer for the FV Extension Header\r
+ //\r
+ FvExtHeader = malloc(FileSize);\r
+ if (FvExtHeader == NULL) {\r
+ fclose (FvExtHeaderFile);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Read the FV Extension Header\r
+ //\r
+ fread (FvExtHeader, sizeof (UINT8), FileSize, FvExtHeaderFile);\r
+ fclose (FvExtHeaderFile);\r
+\r
+ //\r
+ // See if there is an override for the FV Name GUID\r
+ //\r
+ if (mFvDataInfo.FvNameGuidSet) {\r
+ memcpy (&FvExtHeader->FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID));\r
+ }\r
+ memcpy (&mFvDataInfo.FvNameGuid, &FvExtHeader->FvName, sizeof (EFI_GUID));\r
+ mFvDataInfo.FvNameGuidSet = TRUE;\r
+ } else if (mFvDataInfo.FvNameGuidSet) {\r
+ //\r
+ // Allocate a buffer for the FV Extension Header\r
+ //\r
+ FvExtHeader = malloc(sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER));\r
+ if (FvExtHeader == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memcpy (&FvExtHeader->FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID));\r
+ FvExtHeader->ExtHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);\r
+ }\r
+\r
//\r
// Debug message Fv Name Guid\r
//\r
if (mFvDataInfo.FvNameGuidSet) {\r
- DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
- mFvDataInfo.FvNameGuid.Data1,\r
+ DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
+ (unsigned) mFvDataInfo.FvNameGuid.Data1,\r
mFvDataInfo.FvNameGuid.Data2,\r
mFvDataInfo.FvNameGuid.Data3,\r
mFvDataInfo.FvNameGuid.Data4[0],\r
mFvDataInfo.FvNameGuid.Data4[7]);\r
}\r
\r
- if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {\r
+ if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0 ||\r
+ CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem3Guid) == 0) {\r
mFvDataInfo.IsPiFvImage = TRUE;\r
}\r
\r
// FvMap file to log the function address of all modules in one Fvimage\r
//\r
if (MapFileName != NULL) {\r
+ if (strlen (MapFileName) > MAX_LONG_FILE_PATH - 1) {\r
+ Error (NULL, 0, 1003, "Invalid option value", "MapFileName %s is too long!", MapFileName);\r
+ Status = EFI_ABORTED;\r
+ goto Finish;\r
+ }\r
+\r
+ FvMapName = malloc (strlen (MapFileName) + 1);\r
+ if (FvMapName == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
+\r
strcpy (FvMapName, MapFileName);\r
} else {\r
+ if (strlen (FvFileName) + strlen (".map") > MAX_LONG_FILE_PATH - 1) {\r
+ Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName);\r
+ Status = EFI_ABORTED;\r
+ goto Finish;\r
+ }\r
+\r
+ FvMapName = malloc (strlen (FvFileName) + strlen (".map") + 1);\r
+ if (FvMapName == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
+\r
strcpy (FvMapName, FvFileName);\r
strcat (FvMapName, ".map");\r
}\r
VerboseMsg ("FV Map file name is %s", FvMapName);\r
\r
+ //\r
+ // FvReport file to log the FV information in one Fvimage\r
+ //\r
+ if (strlen (FvFileName) + strlen (".txt") > MAX_LONG_FILE_PATH - 1) {\r
+ Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName);\r
+ Status = EFI_ABORTED;\r
+ goto Finish;\r
+ }\r
+\r
+ FvReportName = malloc (strlen (FvFileName) + strlen (".txt") + 1);\r
+ if (FvReportName == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
+\r
+ strcpy (FvReportName, FvFileName);\r
+ strcat (FvReportName, ".txt");\r
+\r
//\r
// Calculate the FV size and Update Fv Size based on the actual FFS files.\r
// And Update mFvDataInfo data.\r
//\r
Status = CalculateFvSize (&mFvDataInfo);\r
if (EFI_ERROR (Status)) {\r
- return Status; \r
+ goto Finish;\r
}\r
- VerboseMsg ("the generated FV image size is %d bytes", mFvDataInfo.Size);\r
- \r
+ VerboseMsg ("the generated FV image size is %u bytes", (unsigned) mFvDataInfo.Size);\r
+\r
//\r
// support fv image and empty fv image\r
//\r
//\r
FvBufferHeader = malloc (FvImageSize + sizeof (UINT64));\r
if (FvBufferHeader == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
}\r
FvImage = (UINT8 *) (((UINTN) FvBufferHeader + 7) & ~7);\r
\r
//\r
if (mFvDataInfo.FvAttributes == 0) {\r
//\r
- // Set Default Fv Attribute \r
+ // Set Default Fv Attribute\r
//\r
mFvDataInfo.FvAttributes = FV_DEFAULT_ATTRIBUTE;\r
}\r
FvHeader->Revision = EFI_FVH_REVISION;\r
FvHeader->ExtHeaderOffset = 0;\r
FvHeader->Reserved[0] = 0;\r
- \r
+\r
//\r
// Copy firmware block map\r
//\r
//\r
// If there is no FFS file, generate one empty FV\r
//\r
- if (mFvDataInfo.FvFiles[0][0] == 0) {\r
+ if (mFvDataInfo.FvFiles[0][0] == 0 && !mFvDataInfo.FvNameGuidSet) {\r
goto WriteFile;\r
}\r
\r
//\r
// Open FvMap file\r
//\r
- FvMapFile = fopen (FvMapName, "w");\r
+ FvMapFile = fopen (LongFilePath (FvMapName), "w");\r
if (FvMapFile == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", FvMapName);\r
- return EFI_ABORTED;\r
+ Status = EFI_ABORTED;\r
+ goto Finish;\r
+ }\r
+\r
+ //\r
+ // Open FvReport file\r
+ //\r
+ FvReportFile = fopen (LongFilePath (FvReportName), "w");\r
+ if (FvReportFile == NULL) {\r
+ Error (NULL, 0, 0001, "Error opening file", FvReportName);\r
+ Status = EFI_ABORTED;\r
+ goto Finish;\r
}\r
- \r
//\r
// record FV size information into FvMap file.\r
//\r
if (mFvTotalSize != 0) {\r
fprintf (FvMapFile, EFI_FV_TOTAL_SIZE_STRING);\r
- fprintf (FvMapFile, " = 0x%x\n", mFvTotalSize);\r
+ fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTotalSize);\r
}\r
if (mFvTakenSize != 0) {\r
fprintf (FvMapFile, EFI_FV_TAKEN_SIZE_STRING);\r
- fprintf (FvMapFile, " = 0x%x\n", mFvTakenSize);\r
+ fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTakenSize);\r
}\r
if (mFvTotalSize != 0 && mFvTakenSize != 0) {\r
fprintf (FvMapFile, EFI_FV_SPACE_SIZE_STRING);\r
- fprintf (FvMapFile, " = 0x%x\n\n", mFvTotalSize - mFvTakenSize);\r
+ fprintf (FvMapFile, " = 0x%x\n\n", (unsigned) (mFvTotalSize - mFvTakenSize));\r
}\r
\r
//\r
- // Set PI FV extension header\r
+ // record FV size information to FvReportFile.\r
//\r
- if (mFvDataInfo.FvNameGuidSet) {\r
- memcpy (&FvExtHeader.FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID));\r
- FvExtHeader.ExtHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);\r
- AddPadFile (&FvImageMemoryFile, 8, &FvExtHeader);\r
+ fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TOTAL_SIZE_STRING, (unsigned) mFvTotalSize);\r
+ fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TAKEN_SIZE_STRING, (unsigned) mFvTakenSize);\r
+\r
+ //\r
+ // Add PI FV extension header\r
+ //\r
+ if (FvExtHeader != NULL) {\r
+ //\r
+ // Add FV Extended Header contents to the FV as a PAD file\r
+ //\r
+ AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, FvExtHeader, 0);\r
+\r
//\r
// Fv Extension header change update Fv Header Check sum\r
//\r
//\r
// Add the file\r
//\r
- Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile);\r
+ Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile, FvReportFile);\r
\r
//\r
// Exit if error detected while adding the file\r
Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file.");\r
goto Finish;\r
}\r
- if (!mArm) {\r
+\r
+ if (!mArm && !mRiscV) {\r
//\r
// Update reset vector (SALE_ENTRY for IPF)\r
- // Now for IA32 and IA64 platform, the fv which has bsf file must have the \r
- // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the \r
- // reset vector. If the PEI Core is found, the VTF file will probably get \r
- // corrupted by updating the entry point. \r
+ // Now for IA32 and IA64 platform, the fv which has bsf file must have the\r
+ // EndAddress of 0xFFFFFFFF (unless the section was rebased).\r
+ // Thus, only this type fv needs to update the reset vector.\r
+ // If the PEI Core is found, the VTF file will probably get\r
+ // corrupted by updating the entry point.\r
//\r
- if ((mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) { \r
+ if (mFvDataInfo.ForceRebase == 1 ||\r
+ (mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) {\r
Status = UpdateResetVector (&FvImageMemoryFile, &mFvDataInfo, VtfFileImage);\r
- if (EFI_ERROR(Status)) { \r
+ if (EFI_ERROR(Status)) {\r
Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");\r
- goto Finish; \r
+ goto Finish;\r
}\r
DebugMsg (NULL, 0, 9, "Update Reset vector in VTF file", NULL);\r
}\r
}\r
- } \r
+ }\r
\r
if (mArm) {\r
Status = UpdateArmResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);\r
- if (EFI_ERROR (Status)) { \r
+ if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");\r
- goto Finish; \r
- } \r
- \r
+ goto Finish;\r
+ }\r
+\r
+ //\r
+ // Update Checksum for FvHeader\r
+ //\r
+ FvHeader->Checksum = 0;\r
+ FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
+ }\r
+\r
+ if (mRiscV) {\r
+ //\r
+ // Update RISCV reset vector.\r
+ //\r
+ Status = UpdateRiscvResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector for RISC-V.");\r
+ goto Finish;\r
+ }\r
//\r
// Update Checksum for FvHeader\r
//\r
FvHeader->Checksum = 0;\r
FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
}\r
- \r
+\r
//\r
// Update FV Alignment attribute to the largest alignment of all the FFS files in the FV\r
//\r
- if ((((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {\r
+ if (((FvHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) &&\r
+ (((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {\r
FvHeader->Attributes = ((MaxFfsAlignment << 16) | (FvHeader->Attributes & 0xFFFF));\r
//\r
// Update Checksum for FvHeader\r
FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
}\r
\r
-WriteFile: \r
+ //\r
+ // If there are large FFS in FV, the file system GUID should set to system 3 GUID.\r
+ //\r
+ if (mIsLargeFfs && CompareGuid (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {\r
+ memcpy (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem3Guid, sizeof (EFI_GUID));\r
+ FvHeader->Checksum = 0;\r
+ FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
+ }\r
+\r
+WriteFile:\r
//\r
// Write fv file\r
//\r
- FvFile = fopen (FvFileName, "wb");\r
+ FvFile = fopen (LongFilePath (FvFileName), "wb");\r
if (FvFile == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", FvFileName);\r
Status = EFI_ABORTED;\r
if (FvBufferHeader != NULL) {\r
free (FvBufferHeader);\r
}\r
- \r
+\r
+ if (FvExtHeader != NULL) {\r
+ free (FvExtHeader);\r
+ }\r
+\r
+ if (FvMapName != NULL) {\r
+ free (FvMapName);\r
+ }\r
+\r
+ if (FvReportName != NULL) {\r
+ free (FvReportName);\r
+ }\r
+\r
if (FvFile != NULL) {\r
+ fflush (FvFile);\r
fclose (FvFile);\r
}\r
- \r
+\r
if (FvMapFile != NULL) {\r
+ fflush (FvMapFile);\r
fclose (FvMapFile);\r
}\r
\r
+ if (FvReportFile != NULL) {\r
+ fflush (FvReportFile);\r
+ fclose (FvReportFile);\r
+ }\r
return Status;\r
}\r
\r
--*/\r
{\r
UINTN CurrentOffset;\r
+ UINTN OrigOffset;\r
UINTN Index;\r
FILE *fpin;\r
UINTN FfsFileSize;\r
+ UINTN FvExtendHeaderSize;\r
UINT32 FfsAlignment;\r
+ UINT32 FfsHeaderSize;\r
EFI_FFS_FILE_HEADER FfsHeader;\r
- BOOLEAN VtfFileFlag;\r
- \r
- VtfFileFlag = FALSE;\r
+ UINTN VtfFileSize;\r
+ UINTN MaxPadFileSize;\r
+\r
+ FvExtendHeaderSize = 0;\r
+ MaxPadFileSize = 0;\r
+ VtfFileSize = 0;\r
fpin = NULL;\r
Index = 0;\r
\r
for (Index = 0; FvInfoPtr->FvBlocks[Index].NumBlocks > 0 && FvInfoPtr->FvBlocks[Index].Length > 0; Index++) {\r
FvInfoPtr->Size += FvInfoPtr->FvBlocks[Index].NumBlocks * FvInfoPtr->FvBlocks[Index].Length;\r
}\r
- \r
+\r
//\r
- // Caculate the required sizes for all FFS files.\r
+ // Calculate the required sizes for all FFS files.\r
//\r
CurrentOffset = sizeof (EFI_FIRMWARE_VOLUME_HEADER);\r
- \r
+\r
for (Index = 1;; Index ++) {\r
CurrentOffset += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
if (FvInfoPtr->FvBlocks[Index].NumBlocks == 0 || FvInfoPtr->FvBlocks[Index].Length == 0) {\r
break;\r
}\r
}\r
- \r
+\r
//\r
// Calculate PI extension header\r
//\r
- if (CompareGuid (&mFvDataInfo.FvNameGuid, &mZeroGuid) != 0) {\r
+ if (mFvDataInfo.FvExtHeaderFile[0] != '\0') {\r
+ fpin = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");\r
+ if (fpin == NULL) {\r
+ Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ FvExtendHeaderSize = _filelength (fileno (fpin));\r
+ fclose (fpin);\r
+ if (sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize >= MAX_FFS_SIZE) {\r
+ CurrentOffset += sizeof (EFI_FFS_FILE_HEADER2) + FvExtendHeaderSize;\r
+ mIsLargeFfs = TRUE;\r
+ } else {\r
+ CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize;\r
+ }\r
+ CurrentOffset = (CurrentOffset + 7) & (~7);\r
+ } else if (mFvDataInfo.FvNameGuidSet) {\r
CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);\r
CurrentOffset = (CurrentOffset + 7) & (~7);\r
}\r
\r
//\r
- // Accumlate every FFS file size.\r
+ // Accumulate every FFS file size.\r
//\r
for (Index = 0; FvInfoPtr->FvFiles[Index][0] != 0; Index++) {\r
//\r
// Open FFS file\r
//\r
fpin = NULL;\r
- fpin = fopen (FvInfoPtr->FvFiles[Index], "rb");\r
+ fpin = fopen (LongFilePath (FvInfoPtr->FvFiles[Index]), "rb");\r
if (fpin == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", FvInfoPtr->FvFiles[Index]);\r
return EFI_ABORTED;\r
// Get the file size\r
//\r
FfsFileSize = _filelength (fileno (fpin));\r
+ if (FfsFileSize >= MAX_FFS_SIZE) {\r
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);\r
+ mIsLargeFfs = TRUE;\r
+ } else {\r
+ FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);\r
+ }\r
//\r
// Read Ffs File header\r
//\r
// close file\r
//\r
fclose (fpin);\r
- \r
+\r
if (FvInfoPtr->IsPiFvImage) {\r
- //\r
- // Check whether this ffs file is vtf file\r
- //\r
- if (IsVtfFile (&FfsHeader)) {\r
- if (VtfFileFlag) {\r
- //\r
- // One Fv image can't have two vtf files.\r
- //\r
- return EFI_ABORTED;\r
- }\r
- VtfFileFlag = TRUE;\r
- //\r
- // The space between Vft File and the latest file must be able to contain \r
- // one ffs file header in order to add one pad file.\r
- //\r
- CurrentOffset += sizeof (EFI_FFS_FILE_HEADER);\r
- }\r
- //\r
- // Get the alignment of FFS file \r
- //\r
- ReadFfsAlignment (&FfsHeader, &FfsAlignment);\r
- FfsAlignment = 1 << FfsAlignment;\r
- //\r
- // Add Pad file\r
- //\r
- if (((CurrentOffset + sizeof (EFI_FFS_FILE_HEADER)) % FfsAlignment) != 0) {\r
- CurrentOffset = (CurrentOffset + sizeof (EFI_FFS_FILE_HEADER) * 2 + FfsAlignment - 1) & ~(FfsAlignment - 1);\r
- CurrentOffset -= sizeof (EFI_FFS_FILE_HEADER);\r
- }\r
- }\r
+ //\r
+ // Check whether this ffs file is vtf file\r
+ //\r
+ if (IsVtfFile (&FfsHeader)) {\r
+ if (VtfFileFlag) {\r
+ //\r
+ // One Fv image can't have two vtf files.\r
+ //\r
+ Error (NULL, 0, 3000,"Invalid", "One Fv image can't have two vtf files.");\r
+ return EFI_ABORTED;\r
+ }\r
+ VtfFileFlag = TRUE;\r
+ VtfFileSize = FfsFileSize;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Get the alignment of FFS file\r
+ //\r
+ ReadFfsAlignment (&FfsHeader, &FfsAlignment);\r
+ FfsAlignment = 1 << FfsAlignment;\r
+ //\r
+ // Add Pad file\r
+ //\r
+ if (((CurrentOffset + FfsHeaderSize) % FfsAlignment) != 0) {\r
+ //\r
+ // Only EFI_FFS_FILE_HEADER is needed for a pad section.\r
+ //\r
+ OrigOffset = CurrentOffset;\r
+ CurrentOffset = (CurrentOffset + FfsHeaderSize + sizeof(EFI_FFS_FILE_HEADER) + FfsAlignment - 1) & ~(FfsAlignment - 1);\r
+ CurrentOffset -= FfsHeaderSize;\r
+ if ((CurrentOffset - OrigOffset) > MaxPadFileSize) {\r
+ MaxPadFileSize = CurrentOffset - OrigOffset;\r
+ }\r
+ }\r
+ }\r
\r
//\r
// Add ffs file size\r
//\r
if (FvInfoPtr->SizeofFvFiles[Index] > FfsFileSize) {\r
- CurrentOffset += FvInfoPtr->SizeofFvFiles[Index];\r
+ CurrentOffset += FvInfoPtr->SizeofFvFiles[Index];\r
} else {\r
- CurrentOffset += FfsFileSize;\r
+ CurrentOffset += FfsFileSize;\r
}\r
- \r
+\r
//\r
- // Make next ffs file start at QWord Boundry\r
+ // Make next ffs file start at QWord Boundary\r
//\r
if (FvInfoPtr->IsPiFvImage) {\r
- CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);\r
+ CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);\r
}\r
}\r
- \r
- DebugMsg (NULL, 0, 9, "FvImage size", "The caculated fv image size is 0x%x and the current set fv image size is 0x%x", CurrentOffset, FvInfoPtr->Size);\r
- \r
- if (FvInfoPtr->Size == 0) { \r
+ CurrentOffset += VtfFileSize;\r
+ 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);\r
+\r
+ if (FvInfoPtr->Size == 0) {\r
//\r
// Update FvInfo data\r
//\r
//\r
// Not invalid\r
//\r
- Error (NULL, 0, 3000, "Invalid", "the required fv image size 0x%x exceeds the set fv image size 0x%x", CurrentOffset, FvInfoPtr->Size);\r
+ 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);\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// Set Fv Size Information\r
//\r
mFvTotalSize = FvInfoPtr->Size;\r
mFvTakenSize = CurrentOffset;\r
+ if ((mFvTakenSize == mFvTotalSize) && (MaxPadFileSize > 0)) {\r
+ //\r
+ // This FV means TOP FFS has been taken. Then, check whether there is padding data for use.\r
+ //\r
+ mFvTakenSize = mFvTakenSize - MaxPadFileSize;\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
}\r
\r
EFI_STATUS\r
-FfsRebase ( \r
- IN OUT FV_INFO *FvInfo, \r
- IN CHAR8 *FileName, \r
+GetChildFvFromFfs (\r
+ IN FV_INFO *FvInfo,\r
+ IN EFI_FFS_FILE_HEADER *FfsFile,\r
+ IN UINTN XipOffset\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function gets all child FvImages in the input FfsFile, and records\r
+ their base address to the parent image.\r
+\r
+Arguments:\r
+ FvInfo A pointer to FV_INFO structure.\r
+ FfsFile A pointer to Ffs file image that may contain FvImage.\r
+ XipOffset The offset address to the parent FvImage base.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Base address of child Fv image is recorded.\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_FILE_SECTION_POINTER SubFvSection;\r
+ EFI_FIRMWARE_VOLUME_HEADER *SubFvImageHeader;\r
+ EFI_PHYSICAL_ADDRESS SubFvBaseAddress;\r
+ EFI_FILE_SECTION_POINTER CorePe32;\r
+ UINT16 MachineType;\r
+\r
+ for (Index = 1;; Index++) {\r
+ //\r
+ // Find FV section\r
+ //\r
+ Status = GetSectionByType (FfsFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, Index, &SubFvSection);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + GetSectionHeaderLength(SubFvSection.FVImageSection));\r
+\r
+ //\r
+ // See if there's an SEC core in the child FV\r
+ Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_SECURITY_CORE, &CorePe32);\r
+\r
+ // if we couldn't find the SEC core, look for a PEI core\r
+ if (EFI_ERROR(Status)) {\r
+ Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_PEI_CORE, &CorePe32);\r
+ }\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = GetCoreMachineType(CorePe32, &MachineType);\r
+ if (EFI_ERROR(Status)) {\r
+ Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC/PEI Core.");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ // machine type is ARM, set a flag so ARM reset vector processing occurs\r
+ if ((MachineType == EFI_IMAGE_MACHINE_ARMT) || (MachineType == EFI_IMAGE_MACHINE_AARCH64)) {\r
+ VerboseMsg("Located ARM/AArch64 SEC/PEI core in child FV");\r
+ mArm = TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Rebase on Flash\r
+ //\r
+ SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset;\r
+ mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FfsRebase (\r
+ IN OUT FV_INFO *FvInfo,\r
+ IN CHAR8 *FileName,\r
IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
IN UINTN XipOffset,\r
IN FILE *FvMapFile\r
rebase any PE32 sections found in the file using the base address.\r
\r
Arguments:\r
- \r
- FvInfo A pointer to FV_INFO struture.\r
+\r
+ FvInfo A pointer to FV_INFO structure.\r
FileName Ffs File PathName\r
FfsFile A pointer to Ffs file image.\r
XipOffset The offset address to use for rebasing the XIP file image.\r
{\r
EFI_STATUS Status;\r
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
- PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext; \r
+ PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext;\r
EFI_PHYSICAL_ADDRESS XipBase;\r
EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;\r
- EFI_PHYSICAL_ADDRESS *BaseToUpdate;\r
UINTN Index;\r
EFI_FILE_SECTION_POINTER CurrentPe32Section;\r
EFI_FFS_FILE_STATE SavedState;\r
EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
EFI_TE_IMAGE_HEADER *TEImageHeader;\r
- UINT8 Flags;\r
UINT8 *MemoryImagePointer;\r
EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
- CHAR8 PeFileName [_MAX_PATH];\r
+ CHAR8 PeFileName [MAX_LONG_FILE_PATH];\r
CHAR8 *Cptr;\r
FILE *PeFile;\r
UINT8 *PeFileBuffer;\r
UINT32 PeFileSize;\r
CHAR8 *PdbPointer;\r
+ UINT32 FfsHeaderSize;\r
+ UINT32 CurSecHdrSize;\r
\r
- Index = 0; \r
+ Index = 0;\r
MemoryImagePointer = NULL;\r
- BaseToUpdate = NULL;\r
TEImageHeader = NULL;\r
ImgHdr = NULL;\r
SectionHeader = NULL;\r
PeFileBuffer = NULL;\r
\r
//\r
- // Check XipAddress, BootAddress and RuntimeAddress\r
+ // Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified.\r
//\r
- Flags = 0;\r
-\r
- if (FvInfo->BaseAddress != 0) {\r
- Flags |= REBASE_XIP_FILE;\r
- XipBase = FvInfo->BaseAddress + XipOffset;\r
- }\r
- if (FvInfo->BootBaseAddress != 0) {\r
- Flags |= REBASE_BOOTTIME_FILE;\r
- }\r
- if (FvInfo->RuntimeBaseAddress != 0) {\r
- Flags |= REBASE_RUNTIME_FILE;\r
+ if ((FvInfo->BaseAddress == 0) && (FvInfo->ForceRebase == -1)) {\r
+ return EFI_SUCCESS;\r
}\r
\r
//\r
- // Don't Rebase this FFS.\r
- // Only copy the original map file into the FvMap file \r
- // for the image that is not required to be relocated.\r
+ // If ForceRebase Flag specified to FALSE, will always not take rebase action.\r
//\r
+ if (FvInfo->ForceRebase == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+\r
+ XipBase = FvInfo->BaseAddress + XipOffset;\r
\r
//\r
// We only process files potentially containing PE32 sections.\r
case EFI_FV_FILETYPE_DRIVER:\r
case EFI_FV_FILETYPE_DXE_CORE:\r
break;\r
+ case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:\r
+ //\r
+ // Rebase the inside FvImage.\r
+ //\r
+ GetChildFvFromFfs (FvInfo, FfsFile, XipOffset);\r
+\r
+ //\r
+ // Search PE/TE section in FV sectin.\r
+ //\r
+ break;\r
default:\r
return EFI_SUCCESS;\r
}\r
+\r
+ FfsHeaderSize = GetFfsHeaderLength(FfsFile);\r
//\r
// Rebase each PE32 section\r
//\r
// Init Value\r
//\r
NewPe32BaseAddress = 0;\r
- \r
+\r
//\r
// Find Pe Image\r
//\r
if (EFI_ERROR (Status)) {\r
break;\r
}\r
+ CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);\r
\r
//\r
// Initialize context\r
//\r
memset (&ImageContext, 0, sizeof (ImageContext));\r
- ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
+ ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);\r
ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, Status);\r
+ Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);\r
return Status;\r
}\r
\r
- if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {\r
+ if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||\r
+ (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {\r
mArm = TRUE;\r
}\r
\r
+ if (ImageContext.Machine == EFI_IMAGE_MACHINE_RISCV64) {\r
+ mRiscV = TRUE;\r
+ }\r
+\r
//\r
// Keep Image Context for PE image in FV\r
//\r
memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext));\r
- \r
+\r
//\r
// Get File PdbPointer\r
//\r
//\r
// Get PeHeader pointer\r
//\r
- ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + ImageContext.PeCoffHeaderOffset);\r
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize + ImageContext.PeCoffHeaderOffset);\r
\r
//\r
// Calculate the PE32 base address, based on file type\r
case EFI_FV_FILETYPE_PEI_CORE:\r
case EFI_FV_FILETYPE_PEIM:\r
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:\r
- if ((Flags & REBASE_XIP_FILE) == 0) {\r
- //\r
- // We aren't relocating XIP code, so skip it.\r
- //\r
- goto WritePeMap;\r
- }\r
- \r
//\r
// Check if section-alignment and file-alignment match or not\r
//\r
//\r
// Xip module has the same section alignment and file alignment.\r
//\r
- Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);\r
+ Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName);\r
return EFI_ABORTED;\r
}\r
//\r
- // PeImage has no reloc section. It will try to get reloc data from the original EFI image. \r
+ // PeImage has no reloc section. It will try to get reloc data from the original EFI image.\r
//\r
if (ImageContext.RelocationsStripped) {\r
//\r
- // Construct the original efi file Name \r
+ // Construct the original efi file Name\r
//\r
- strcpy (PeFileName, FileName);\r
+ if (strlen (FileName) >= MAX_LONG_FILE_PATH) {\r
+ Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName);\r
+ return EFI_ABORTED;\r
+ }\r
+ strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1);\r
+ PeFileName[MAX_LONG_FILE_PATH - 1] = 0;\r
Cptr = PeFileName + strlen (PeFileName);\r
while (*Cptr != '.') {\r
Cptr --;\r
*(Cptr + 3) = 'i';\r
*(Cptr + 4) = '\0';\r
}\r
- PeFile = fopen (PeFileName, "rb");\r
+ PeFile = fopen (LongFilePath (PeFileName), "rb");\r
if (PeFile == NULL) {\r
Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
//Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);\r
PeFileSize = _filelength (fileno (PeFile));\r
PeFileBuffer = (UINT8 *) malloc (PeFileSize);\r
if (PeFileBuffer == NULL) {\r
+ fclose (PeFile);\r
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
ImageContext.Handle = PeFileBuffer;\r
Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, Status);\r
+ Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);\r
return Status;\r
}\r
ImageContext.RelocationsStripped = FALSE;\r
}\r
\r
- NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
- BaseToUpdate = &XipBase;\r
+ NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;\r
break;\r
\r
case EFI_FV_FILETYPE_DRIVER:\r
case EFI_FV_FILETYPE_DXE_CORE:\r
- switch (ImgHdr->Pe32.OptionalHeader.Subsystem) {\r
- case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
- if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {\r
- //\r
- // Check if section-alignment and file-alignment match or not\r
- //\r
- if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {\r
- //\r
- // Xip module has the same section alignment and file alignment.\r
- //\r
- Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);\r
- return EFI_ABORTED;\r
- }\r
- NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
- BaseToUpdate = &XipBase; \r
- } else if ((Flags & REBASE_RUNTIME_FILE) == REBASE_RUNTIME_FILE) {\r
- //\r
- // make sure image base address at the section alignment\r
- //\r
- FvInfo->RuntimeBaseAddress = (FvInfo->RuntimeBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));\r
- FvInfo->RuntimeBaseAddress = FvInfo->RuntimeBaseAddress & (~(EFI_PAGE_SIZE - 1));\r
- NewPe32BaseAddress = FvInfo->RuntimeBaseAddress;\r
- BaseToUpdate = &(FvInfo->RuntimeBaseAddress);\r
- } else {\r
- //\r
- // RT drivers aren't supposed to be relocated\r
- //\r
- goto WritePeMap;\r
- }\r
- break;\r
-\r
- default:\r
- //\r
- // We treat all other subsystems the same as BS_DRIVER\r
- //\r
- if ((Flags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {\r
- //\r
- // Check if section-alignment and file-alignment match or not\r
- //\r
- if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {\r
- //\r
- // Xip module has the same section alignment and file alignment.\r
- //\r
- Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment do not match : %s.", FileName);\r
- return EFI_ABORTED;\r
- }\r
- NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) - (UINTN)FfsFile;\r
- BaseToUpdate = &XipBase; \r
- } else if ((Flags & REBASE_BOOTTIME_FILE) == REBASE_BOOTTIME_FILE) {\r
- //\r
- // make sure image base address at the Section and Page alignment\r
- //\r
- FvInfo->BootBaseAddress = (FvInfo->BootBaseAddress - ImageContext.ImageSize) & (~(ImageContext.SectionAlignment - 1));\r
- FvInfo->BootBaseAddress = FvInfo->BootBaseAddress & (~(EFI_PAGE_SIZE - 1));\r
- NewPe32BaseAddress = FvInfo->BootBaseAddress;\r
- BaseToUpdate = &(FvInfo->BootBaseAddress);\r
- } else {\r
- //\r
- // Skip all BS_DRIVER's\r
- //\r
- goto WritePeMap;\r
- }\r
- break;\r
+ //\r
+ // Check if section-alignment and file-alignment match or not\r
+ //\r
+ if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {\r
+ //\r
+ // Xip module has the same section alignment and file alignment.\r
+ //\r
+ Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName);\r
+ return EFI_ABORTED;\r
}\r
+ NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;\r
break;\r
\r
default:\r
//\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
+ //\r
+ // Relocation doesn't exist\r
+ //\r
+ if (ImageContext.RelocationsStripped) {\r
+ Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
+ continue;\r
+ }\r
+\r
//\r
// Relocation exist and rebase\r
//\r
- if (!ImageContext.RelocationsStripped) { \r
- //\r
- // Load and Relocate Image Data\r
- //\r
- MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
- if (MemoryImagePointer == NULL) {\r
- Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
- ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1));\r
- \r
- Status = PeCoffLoaderLoadImage (&ImageContext);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
- free ((VOID *) MemoryImagePointer);\r
- return Status;\r
- }\r
- \r
- ImageContext.DestinationAddress = NewPe32BaseAddress;\r
- Status = PeCoffLoaderRelocateImage (&ImageContext);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);\r
- free ((VOID *) MemoryImagePointer);\r
- return Status;\r
- }\r
+ //\r
+ // Load and Relocate Image Data\r
+ //\r
+ MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+ if (MemoryImagePointer == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+ ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));\r
\r
- //\r
- // Copy Relocated data to raw image file.\r
- //\r
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
- (UINTN) ImgHdr +\r
- sizeof (UINT32) + \r
- sizeof (EFI_IMAGE_FILE_HEADER) + \r
- ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
- );\r
- \r
- for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
- CopyMem (\r
- (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) + SectionHeader->PointerToRawData, \r
- (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
- SectionHeader->SizeOfRawData\r
- );\r
- }\r
- \r
+ Status = PeCoffLoaderLoadImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
free ((VOID *) MemoryImagePointer);\r
- MemoryImagePointer = NULL;\r
- if (PeFileBuffer != NULL) {\r
- free (PeFileBuffer);\r
- PeFileBuffer = NULL;\r
- }\r
+ return Status;\r
+ }\r
+\r
+ ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+ Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s Status=%d", FileName, Status);\r
+ free ((VOID *) MemoryImagePointer);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Copy Relocated data to raw image file.\r
+ //\r
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
+ (UINTN) ImgHdr +\r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+ );\r
+\r
+ for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
+ CopyMem (\r
+ (UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize + SectionHeader->PointerToRawData,\r
+ (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),\r
+ SectionHeader->SizeOfRawData\r
+ );\r
+ }\r
+\r
+ free ((VOID *) MemoryImagePointer);\r
+ MemoryImagePointer = NULL;\r
+ if (PeFileBuffer != NULL) {\r
+ free (PeFileBuffer);\r
+ PeFileBuffer = NULL;\r
}\r
- \r
+\r
//\r
// Update Image Base Address\r
//\r
if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
- ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;\r
+ ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;\r
} else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
- ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;\r
+ ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;\r
} else {\r
Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",\r
- (UINT32) ImgHdr->Pe32.OptionalHeader.Magic,\r
+ ImgHdr->Pe32.OptionalHeader.Magic,\r
FileName\r
);\r
return EFI_ABORTED;\r
}\r
\r
- //\r
- // Update BASE address by add one page size.\r
- //\r
- *BaseToUpdate -= EFI_PAGE_SIZE;\r
-\r
//\r
// Now update file checksum\r
//\r
SavedState = FfsFile->State;\r
FfsFile->IntegrityCheck.Checksum.File = 0;\r
FfsFile->State = 0;\r
- if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
- FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
- (UINT8 *) FfsFile,\r
- GetLength (FfsFile->Size)\r
- );\r
- } else {\r
- FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
- }\r
-\r
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+ (UINT8 *) ((UINT8 *)FfsFile + FfsHeaderSize),\r
+ GetFfsFileLength (FfsFile) - FfsHeaderSize\r
+ );\r
FfsFile->State = SavedState;\r
}\r
\r
//\r
// Get this module function address from ModulePeMapFile and add them into FvMap file\r
//\r
-WritePeMap:\r
+\r
//\r
// Default use FileName as map file path\r
//\r
PdbPointer = FileName;\r
}\r
\r
- WriteMapFile (FvMapFile, PdbPointer, (EFI_GUID *) FfsFile, NewPe32BaseAddress, &OrigImageContext);\r
+ WriteMapFile (FvMapFile, PdbPointer, FfsFile, NewPe32BaseAddress, &OrigImageContext);\r
}\r
\r
if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
FfsFile->Type != EFI_FV_FILETYPE_PEIM &&\r
- FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
+ FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER &&\r
+ FfsFile->Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\r
) {\r
//\r
// Only Peim code may have a TE section\r
//\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
//\r
// Now process TE sections\r
//\r
for (Index = 1;; Index++) {\r
NewPe32BaseAddress = 0;\r
- \r
+\r
//\r
// Find Te Image\r
//\r
if (EFI_ERROR (Status)) {\r
break;\r
}\r
- \r
+\r
+ CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);\r
+\r
//\r
// Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off\r
// by GenTEImage\r
//\r
- TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize);\r
\r
//\r
// Initialize context, load image info.\r
ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, Status);\r
+ Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);\r
return Status;\r
}\r
\r
- if (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) {\r
+ if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||\r
+ (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {\r
mArm = TRUE;\r
}\r
\r
// Get File PdbPointer\r
//\r
PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle);\r
- \r
- if ((Flags & REBASE_XIP_FILE) == 0) {\r
- //\r
- // For none XIP PEIM module, their map info also are collected.\r
- //\r
- goto WriteTeMap;\r
- }\r
\r
//\r
// Set new rebased address.\r
//\r
// if reloc is stripped, try to get the original efi image to get reloc info.\r
//\r
- if (ImageContext.RelocationsStripped == TRUE) {\r
+ if (ImageContext.RelocationsStripped) {\r
//\r
- // Construct the original efi file name \r
+ // Construct the original efi file name\r
//\r
- strcpy (PeFileName, FileName);\r
+ if (strlen (FileName) >= MAX_LONG_FILE_PATH) {\r
+ Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName);\r
+ return EFI_ABORTED;\r
+ }\r
+ strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1);\r
+ PeFileName[MAX_LONG_FILE_PATH - 1] = 0;\r
Cptr = PeFileName + strlen (PeFileName);\r
while (*Cptr != '.') {\r
Cptr --;\r
*(Cptr + 4) = '\0';\r
}\r
\r
- PeFile = fopen (PeFileName, "rb");\r
+ PeFile = fopen (LongFilePath (PeFileName), "rb");\r
if (PeFile == NULL) {\r
Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
//Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);\r
PeFileSize = _filelength (fileno (PeFile));\r
PeFileBuffer = (UINT8 *) malloc (PeFileSize);\r
if (PeFileBuffer == NULL) {\r
+ fclose (PeFile);\r
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
ImageContext.Handle = PeFileBuffer;\r
Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, Status);\r
+ Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);\r
return Status;\r
}\r
ImageContext.RelocationsStripped = FALSE;\r
}\r
}\r
+ //\r
+ // Relocation doesn't exist\r
+ //\r
+ if (ImageContext.RelocationsStripped) {\r
+ Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);\r
+ continue;\r
+ }\r
\r
//\r
// Relocation exist and rebase\r
//\r
- if (!ImageContext.RelocationsStripped) {\r
- //\r
- // Load and Relocate Image Data\r
- //\r
- MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
- if (MemoryImagePointer == NULL) {\r
- Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
- ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~(ImageContext.SectionAlignment - 1));\r
- \r
- Status = PeCoffLoaderLoadImage (&ImageContext);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
- free ((VOID *) MemoryImagePointer);\r
- return Status;\r
- }\r
- //\r
- // Reloacate TeImage\r
- // \r
- ImageContext.DestinationAddress = NewPe32BaseAddress;\r
- Status = PeCoffLoaderRelocateImage (&ImageContext);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);\r
- free ((VOID *) MemoryImagePointer);\r
- return Status;\r
- }\r
- \r
- //\r
- // Copy the relocated image into raw image file.\r
- //\r
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);\r
- for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {\r
- if (!ImageContext.IsTeImage) {\r
- CopyMem (\r
- (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, \r
- (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
- SectionHeader->SizeOfRawData\r
- );\r
- } else {\r
- CopyMem (\r
- (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, \r
- (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress), \r
- SectionHeader->SizeOfRawData\r
- );\r
- }\r
- }\r
- \r
- //\r
- // Free the allocated memory resource\r
- //\r
+ //\r
+ // Load and Relocate Image Data\r
+ //\r
+ MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+ if (MemoryImagePointer == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+ ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));\r
+\r
+ Status = PeCoffLoaderLoadImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
+ free ((VOID *) MemoryImagePointer);\r
+ return Status;\r
+ }\r
+ //\r
+ // Reloacate TeImage\r
+ //\r
+ ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+ Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);\r
free ((VOID *) MemoryImagePointer);\r
- MemoryImagePointer = NULL;\r
- if (PeFileBuffer != NULL) {\r
- free (PeFileBuffer);\r
- PeFileBuffer = NULL;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Copy the relocated image into raw image file.\r
+ //\r
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);\r
+ for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {\r
+ if (!ImageContext.IsTeImage) {\r
+ CopyMem (\r
+ (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,\r
+ (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),\r
+ SectionHeader->SizeOfRawData\r
+ );\r
+ } else {\r
+ CopyMem (\r
+ (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,\r
+ (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress),\r
+ SectionHeader->SizeOfRawData\r
+ );\r
}\r
}\r
- \r
+\r
+ //\r
+ // Free the allocated memory resource\r
+ //\r
+ free ((VOID *) MemoryImagePointer);\r
+ MemoryImagePointer = NULL;\r
+ if (PeFileBuffer != NULL) {\r
+ free (PeFileBuffer);\r
+ PeFileBuffer = NULL;\r
+ }\r
+\r
//\r
// Update Image Base Address\r
//\r
SavedState = FfsFile->State;\r
FfsFile->IntegrityCheck.Checksum.File = 0;\r
FfsFile->State = 0;\r
- if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
- FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
- (UINT8 *) FfsFile,\r
- GetLength (FfsFile->Size)\r
- );\r
- } else {\r
- FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
- }\r
-\r
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+ (UINT8 *)((UINT8 *)FfsFile + FfsHeaderSize),\r
+ GetFfsFileLength (FfsFile) - FfsHeaderSize\r
+ );\r
FfsFile->State = SavedState;\r
}\r
//\r
// Get this module function address from ModulePeMapFile and add them into FvMap file\r
//\r
-WriteTeMap:\r
+\r
//\r
// Default use FileName as map file path\r
//\r
}\r
\r
WriteMapFile (\r
- FvMapFile, \r
- PdbPointer, \r
- (EFI_GUID *) FfsFile,\r
- NewPe32BaseAddress, \r
+ FvMapFile,\r
+ PdbPointer,\r
+ FfsFile,\r
+ NewPe32BaseAddress,\r
&OrigImageContext\r
);\r
}\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r
//\r
// Get Pad file size.\r
//\r
- FileLength = (*(UINT32 *)(PadFile->Size)) & 0x00FFFFFF;\r
- FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1); \r
+ FileLength = GetFfsFileLength(PadFile);\r
+ FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);\r
//\r
// FixPoint must be align on 0x1000 relative to FvImage Header\r
//\r
- FixPoint = (UINT8*) PadFile + sizeof (EFI_FFS_FILE_HEADER);\r
+ FixPoint = (UINT8*) PadFile + GetFfsHeaderLength(PadFile);\r
FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF);\r
//\r
// FixPoint be larger at the last place of one fv image.\r
FixPoint += 0x1000;\r
}\r
FixPoint -= 0x1000;\r
- \r
- if ((UINTN) FixPoint < ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER))) {\r
+\r
+ if ((UINTN) FixPoint < ((UINTN) PadFile + GetFfsHeaderLength(PadFile))) {\r
//\r
// No alignment FixPoint in this Pad File.\r
//\r
continue;\r
}\r
\r
- if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) { \r
+ if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) {\r
//\r
// Find the position to place ApResetVector\r
//\r
return EFI_SUCCESS;\r
}\r
}\r
- \r
+\r
return EFI_NOT_FOUND;\r
}\r
\r
EFI_NOT_FOUND A required string was not found in the INF file.\r
--*/\r
{\r
- CHAR8 Value[_MAX_PATH];\r
+ CHAR8 Value[MAX_LONG_FILE_PATH];\r
UINT64 Value64;\r
UINTN Index, Number;\r
EFI_STATUS Status;\r
if (Status == EFI_SUCCESS) {\r
if (strstr (Value, "PopulateSystemTable") != NULL) {\r
CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;\r
+ if (strstr (Value, "InitiateReset") != NULL) {\r
+ CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;\r
+ }\r
} else if (strstr (Value, "PersistAcrossReset") != NULL) {\r
- CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET; \r
+ CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET;\r
+ if (strstr (Value, "InitiateReset") != NULL) {\r
+ CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;\r
+ }\r
} else {\r
Error (NULL, 0, 2000, "Invalid parameter", "invalid Flag setting for %s.", EFI_CAPSULE_FLAGS_STRING);\r
return EFI_ABORTED;\r
DebugMsg (NULL, 0, 9, "Capsule Flag", Value);\r
}\r
\r
+ Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_OEM_CAPSULE_FLAGS_STRING, 0, Value);\r
+ if (Status == EFI_SUCCESS) {\r
+ Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+ if (EFI_ERROR (Status) || Value64 > 0xffff) {\r
+ Error (NULL, 0, 2000, "Invalid parameter",\r
+ "invalid Flag setting for %s. Must be integer value between 0x0000 and 0xffff.",\r
+ EFI_OEM_CAPSULE_FLAGS_STRING);\r
+ return EFI_ABORTED;\r
+ }\r
+ CapInfo->Flags |= Value64;\r
+ DebugMsg (NULL, 0, 9, "Capsule Extend Flag", Value);\r
+ }\r
+\r
//\r
// Read Capsule File name\r
//\r
// Add the file\r
//\r
strcpy (CapInfo->CapFiles[Index], Value);\r
- DebugMsg (NULL, 0, 9, "Capsule component file", "the %dth file name is %s", Index, CapInfo->CapFiles[Index]); \r
+ DebugMsg (NULL, 0, 9, "Capsule component file", "the %uth file name is %s", (unsigned) Index, CapInfo->CapFiles[Index]);\r
} else {\r
break;\r
}\r
}\r
- \r
+\r
if (Index == 0) {\r
Warning (NULL, 0, 0, "Capsule components are not specified.", NULL);\r
}\r
UINT32 Index;\r
FILE *fpin, *fpout;\r
EFI_STATUS Status;\r
- \r
+\r
if (InfFileImage != NULL) {\r
//\r
// Initialize file structures\r
InfMemoryFile.FileImage = InfFileImage;\r
InfMemoryFile.CurrentFilePointer = InfFileImage;\r
InfMemoryFile.Eof = InfFileImage + InfFileSize;\r
- \r
+\r
//\r
// Parse the Cap inf file for header information\r
//\r
return Status;\r
}\r
}\r
- \r
+\r
if (mCapDataInfo.HeaderSize == 0) {\r
//\r
// make header size align 16 bytes.\r
Error (NULL, 0, 2000, "Invalid parameter", "The specified HeaderSize cannot be less than the size of EFI_CAPSULE_HEADER.");\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
if (CapFileName == NULL && mCapDataInfo.CapName[0] != '\0') {\r
CapFileName = mCapDataInfo.CapName;\r
}\r
- \r
+\r
if (CapFileName == NULL) {\r
Error (NULL, 0, 2001, "Missing required argument", "Output Capsule file name");\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// Set Default Capsule Guid value\r
//\r
FileSize = 0;\r
CapSize = mCapDataInfo.HeaderSize;\r
while (mCapDataInfo.CapFiles [Index][0] != '\0') {\r
- fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");\r
+ fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");\r
if (fpin == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);\r
return EFI_ABORTED;\r
// Initialize the capsule header to zero\r
//\r
memset (CapBuffer, 0, mCapDataInfo.HeaderSize);\r
- \r
+\r
//\r
// create capsule header and get capsule body\r
//\r
FileSize = 0;\r
CapSize = CapsuleHeader->HeaderSize;\r
while (mCapDataInfo.CapFiles [Index][0] != '\0') {\r
- fpin = fopen (mCapDataInfo.CapFiles[Index], "rb");\r
+ fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");\r
if (fpin == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);\r
free (CapBuffer);\r
Index ++;\r
CapSize += FileSize;\r
}\r
- \r
+\r
//\r
// write capsule data into the output file\r
//\r
- fpout = fopen (CapFileName, "wb");\r
+ fpout = fopen (LongFilePath (CapFileName), "wb");\r
if (fpout == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", CapFileName);\r
free (CapBuffer);\r
\r
fwrite (CapBuffer, 1, CapSize, fpout);\r
fclose (fpout);\r
- \r
- VerboseMsg ("The size of the generated capsule image is %d bytes", CapSize);\r
+ free (CapBuffer);\r
+\r
+ VerboseMsg ("The size of the generated capsule image is %u bytes", (unsigned) CapSize);\r
\r
return EFI_SUCCESS;\r
}\r