EFI_COMMON_SECTION_HEADER TempSectHeader;\r
EFI_TE_IMAGE_HEADER TeHeader;\r
UINT32 TeOffset;\r
+ EFI_GUID_DEFINED_SECTION GuidSectHeader;\r
+ UINT32 HeaderSize;\r
\r
Size = 0;\r
Offset = 0;\r
// Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.\r
//\r
TeOffset = 0;\r
+ HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
fread (&TempSectHeader, 1, sizeof (TempSectHeader), InFile);\r
if (TempSectHeader.Type == EFI_SECTION_TE) {\r
(*PESectionNum) ++;\r
}\r
} else if (TempSectHeader.Type == EFI_SECTION_PE32) {\r
(*PESectionNum) ++;\r
+ } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {\r
+ fseek (InFile, 0, SEEK_SET);\r
+ fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);\r
+ if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
+ HeaderSize = GuidSectHeader.DataOffset;\r
+ }\r
+ (*PESectionNum) ++;\r
} else if (TempSectHeader.Type == EFI_SECTION_COMPRESSION || \r
- TempSectHeader.Type == EFI_SECTION_GUID_DEFINED ||\r
TempSectHeader.Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
//\r
// for the encapsulated section, assume it contains Pe/Te section \r
TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);\r
TeOffset = TeOffset % InputFileAlign [Index];\r
}\r
- \r
+\r
//\r
// make sure section data meet its alignment requirement by adding one raw pad section.\r
// But the different sections have the different section header. Necessary or not?\r
// Based on section type to adjust offset? Todo\r
//\r
- if ((InputFileAlign [Index] != 0) && (((Size + sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset) % InputFileAlign [Index]) != 0)) {\r
- Offset = (Size + 2 * sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
- Offset = Offset - Size - sizeof (EFI_COMMON_SECTION_HEADER) - TeOffset;\r
+ if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {\r
+ Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
+ Offset = Offset - Size - HeaderSize - TeOffset;\r
\r
if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
+ memset (FileBuffer + Size, 0, Offset);\r
SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);\r
SectHeader->Type = EFI_SECTION_RAW;\r
SectHeader->Size[0] = (UINT8) (Offset & 0xff);\r
);\r
DebugMsg (NULL, 0, 9, "Updated runtime driver base address", "%s = 0x%llx", EFI_FV_RUNTIME_DRIVER_BASE_ADDRESS_STRING, (unsigned long long) mFvDataInfo.RuntimeBaseAddress);\r
}\r
+ if (mFvBaseAddressNumber > 0) {\r
+ fprintf (FpFile, FV_BASE_ADDRESS_STRING);\r
+ fprintf (FpFile, "\n");\r
+ for (Index = 0; Index < mFvBaseAddressNumber; Index ++) {\r
+ fprintf (\r
+ FpFile,\r
+ "0x%llx\n",\r
+ (unsigned long long)mFvBaseAddress[Index]\r
+ );\r
+ }\r
+ }\r
fclose (FpFile);\r
}\r
\r
FV_INFO mFvDataInfo;\r
CAP_INFO mCapDataInfo;\r
\r
+EFI_PHYSICAL_ADDRESS mFvBaseAddress[0x10];\r
+UINT32 mFvBaseAddressNumber = 0;\r
+\r
EFI_STATUS\r
ParseFvInf (\r
IN MEMORY_FILE *InfFile,\r
return EFI_SUCCESS;\r
}\r
\r
+EFI_STATUS\r
+GetChildFvFromFfs (\r
+ IN UINT8 FixupFlags,\r
+ IN FV_INFO *FvInfo, \r
+ IN EFI_FFS_FILE_HEADER *FfsFile,\r
+ IN UINTN XipOffset,\r
+ IN FILE *FvMapFile\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 struture.\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_FFS_FILE_STATE SavedState;\r
+ EFI_FFS_FILE_HEADER *SubFfsFile;\r
+ EFI_FFS_FILE_HEADER *NextFfsFile;\r
+ EFI_FIRMWARE_VOLUME_HEADER *SavedFvHeader;\r
+ UINT32 SavedFvSize;\r
+ EFI_FIRMWARE_VOLUME_HEADER *SubFvImageHeader;\r
+ CHAR8 SubFfsName[PRINTED_GUID_BUFFER_SIZE];\r
+ EFI_PHYSICAL_ADDRESS SubFvBaseAddress;\r
+\r
+ ZeroMem (SubFfsName, PRINTED_GUID_BUFFER_SIZE);\r
+ GetFvHeader (&SavedFvHeader, &SavedFvSize);\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 + sizeof (EFI_FIRMWARE_VOLUME_IMAGE_SECTION));\r
+ if ((FixupFlags & REBASE_XIP_FILE) == REBASE_XIP_FILE) {\r
+ //\r
+ // Rebase on Flash\r
+ //\r
+ SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset;\r
+ mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;\r
+ } else {\r
+ //\r
+ // Rebase on Memory\r
+ //\r
+ InitializeFvLib (SubFvImageHeader, (UINT32) SubFvImageHeader->FvLength);\r
+ //\r
+ // Go through FFS in this insided FvImage one by one.\r
+ //\r
+ SubFfsFile = NULL;\r
+ while (TRUE) {\r
+ GetNextFile (SubFfsFile, &NextFfsFile);\r
+ if (NextFfsFile == NULL) {\r
+ break;\r
+ }\r
+ SubFfsFile = NextFfsFile;\r
+ //\r
+ // Use FFS GUID as its File Name.\r
+ //\r
+ PrintGuidToBuffer (&SubFfsFile->Name, SubFfsName, PRINTED_GUID_BUFFER_SIZE, TRUE);\r
+ FfsRebase (FvInfo, SubFfsName, SubFfsFile, (UINTN) SubFfsFile - (UINTN) FfsFile + XipOffset, FvMapFile);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Now update file checksum\r
+ //\r
+ if (((FixupFlags & REBASE_XIP_FILE) == 0) && (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM)) {\r
+ SavedState = FfsFile->State;\r
+ FfsFile->IntegrityCheck.Checksum.File = 0;\r
+ FfsFile->State = 0;\r
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+ (UINT8 *)(FfsFile + 1),\r
+ GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_HEADER)\r
+ );\r
+ FfsFile->State = SavedState;\r
+ }\r
+\r
+ InitializeFvLib (SavedFvHeader, SavedFvSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
EFI_STATUS\r
FfsRebase ( \r
IN OUT FV_INFO *FvInfo, \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
+ if (Flags != 0) {\r
+ GetChildFvFromFfs (Flags, FvInfo, FfsFile, XipOffset, FvMapFile);\r
+ }\r
+ //\r
+ // Search PE/TE section in FV sectin.\r
+ //\r
+ break;\r
default:\r
return EFI_SUCCESS;\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
#define OPTIONS_SECTION_STRING "[options]"\r
#define ATTRIBUTES_SECTION_STRING "[attributes]"\r
#define FILES_SECTION_STRING "[files]"\r
+#define FV_BASE_ADDRESS_STRING "[FV_BASE_ADDRESS]"\r
\r
//\r
// Options section\r
extern EFI_GUID mEfiFirmwareFileSystem2Guid;\r
extern UINT32 mFvTotalSize;\r
extern UINT32 mFvTakenSize;\r
+\r
+extern EFI_PHYSICAL_ADDRESS mFvBaseAddress[];\r
+extern UINT32 mFvBaseAddressNumber;\r
//\r
// Local function prototypes\r
//\r
#include <Common/UefiBaseTypes.h>\r
#include <Common/PiFirmwareFile.h>\r
#include <Protocol/GuidedSectionExtraction.h>\r
+#include <IndustryStandard/PeImage.h>\r
\r
#include "CommonLib.h"\r
#include "Compress.h"\r
#define EFI_GUIDED_SECTION_NONE 0x80\r
STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};\r
\r
+STATIC CHAR8 *mAlignName[] = {\r
+ "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
+ "1K", "2K", "4K", "8K", "16K", "32K", "64K"\r
+};\r
+\r
//\r
// Crc32 GUID section related definitions.\r
//\r
fprintf (stdout, " -j Number, --buildnumber Number\n\\r
Number is an integer value between 0000 and 9999\n\\r
used in Ver section.\n");\r
+ fprintf (stdout, " --sectionalign SectionAlign\n\\r
+ SectionAlign points to section alignment, which support\n\\r
+ the alignment scope 1~64K. It is specified in same\n\\r
+ order that the section file is input.\n");\r
fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");\r
fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");\r
return Status;\r
}\r
\r
+STATIC\r
+EFI_STATUS\r
+StringtoAlignment (\r
+ IN CHAR8 *AlignBuffer,\r
+ OUT UINT32 *AlignNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Converts Align String to align value (1~64K). \r
+\r
+Arguments:\r
+\r
+ AlignBuffer - Pointer to Align string.\r
+ AlignNumber - Pointer to Align value.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS Successfully convert align string to align value.\r
+ EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.\r
+\r
+--*/\r
+{\r
+ UINT32 Index = 0;\r
+ //\r
+ // Check AlignBuffer\r
+ //\r
+ if (AlignBuffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {\r
+ if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {\r
+ *AlignNumber = 1 << Index;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
EFI_STATUS\r
GetSectionContents (\r
CHAR8 **InputFileName,\r
+ UINT32 *InputFileAlign,\r
UINT32 InputFileNum,\r
UINT8 *FileBuffer,\r
UINT32 *BufferLength\r
Arguments:\r
\r
InputFileName - Name of the input file.\r
- \r
+\r
+ InputFileAlign - Alignment required by the input file data.\r
+\r
InputFileNum - Number of input files. Should be at least 1.\r
\r
FileBuffer - Output buffer to contain data\r
EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
--*/\r
{\r
- UINT32 Size;\r
- UINT32 FileSize;\r
- UINT32 Index;\r
- FILE *InFile;\r
+ UINT32 Size;\r
+ UINT32 Offset;\r
+ UINT32 FileSize;\r
+ UINT32 Index;\r
+ FILE *InFile;\r
+ EFI_COMMON_SECTION_HEADER *SectHeader;\r
+ EFI_COMMON_SECTION_HEADER TempSectHeader;\r
+ EFI_TE_IMAGE_HEADER TeHeader;\r
+ UINT32 TeOffset;\r
+ EFI_GUID_DEFINED_SECTION GuidSectHeader;\r
+ UINT32 HeaderSize;\r
\r
if (InputFileNum < 1) {\r
Error (NULL, 0, 2000, "Invalid paramter", "must specify at least one input file");\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Size = 0;\r
+ Size = 0;\r
+ Offset = 0;\r
+ TeOffset = 0;\r
//\r
// Go through our array of file names and copy their contents\r
// to the output buffer.\r
FileSize = ftell (InFile);\r
fseek (InFile, 0, SEEK_SET);\r
DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); \r
+ //\r
+ // Adjust section buffer when section alignment is required.\r
+ //\r
+ if (InputFileAlign != NULL) {\r
+ //\r
+ // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.\r
+ //\r
+ TeOffset = 0;\r
+ HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
+ fread (&TempSectHeader, 1, sizeof (TempSectHeader), InFile);\r
+ if (TempSectHeader.Type == EFI_SECTION_TE) {\r
+ fread (&TeHeader, 1, sizeof (TeHeader), InFile);\r
+ if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+ TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);\r
+ }\r
+ } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {\r
+ fseek (InFile, 0, SEEK_SET);\r
+ fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);\r
+ if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
+ HeaderSize = GuidSectHeader.DataOffset;\r
+ }\r
+ } \r
+\r
+ fseek (InFile, 0, SEEK_SET);\r
+\r
+ //\r
+ // Revert TeOffset to the converse value relative to Alignment\r
+ // This is to assure the original PeImage Header at Alignment.\r
+ //\r
+ if (TeOffset != 0) {\r
+ TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);\r
+ TeOffset = TeOffset % InputFileAlign [Index];\r
+ }\r
+\r
+ //\r
+ // make sure section data meet its alignment requirement by adding one raw pad section.\r
+ //\r
+ if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {\r
+ Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
+ Offset = Offset - Size - HeaderSize - TeOffset;\r
+ \r
+ if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
+ memset (FileBuffer + Size, 0, Offset);\r
+ SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);\r
+ SectHeader->Type = EFI_SECTION_RAW;\r
+ SectHeader->Size[0] = (UINT8) (Offset & 0xff);\r
+ SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);\r
+ SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);\r
+ }\r
+ DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);\r
+\r
+ Size = Size + Offset;\r
+ }\r
+ }\r
+\r
//\r
// Now read the contents of the file into the buffer\r
// Buffer must be enough to contain the file content.\r
//\r
- if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {\r
+ if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {\r
if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {\r
Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);\r
fclose (InFile);\r
EFI_STATUS\r
GenSectionCompressionSection (\r
CHAR8 **InputFileName,\r
+ UINT32 *InputFileAlign,\r
UINT32 InputFileNum,\r
UINT8 SectCompSubType,\r
UINT8 **OutFileBuffer\r
Arguments:\r
\r
InputFileName - Name of the input file.\r
- \r
+\r
+ InputFileAlign - Alignment required by the input file data.\r
+\r
InputFileNum - Number of input files. Should be at least 1.\r
\r
SectCompSubType - Specify the compression algorithm requested. \r
//\r
Status = GetSectionContents (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
FileBuffer,\r
&InputLength\r
//\r
Status = GetSectionContents (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
FileBuffer,\r
&InputLength\r
EFI_STATUS\r
GenSectionGuidDefinedSection (\r
CHAR8 **InputFileName,\r
+ UINT32 *InputFileAlign,\r
UINT32 InputFileNum,\r
EFI_GUID *VendorGuid,\r
UINT16 DataAttribute,\r
\r
InputFileName - Name of the input file.\r
\r
+ InputFileAlign - Alignment required by the input file data.\r
+\r
InputFileNum - Number of input files. Should be at least 1.\r
\r
VendorGuid - Specify vendor guid value.\r
//\r
Status = GetSectionContents (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
FileBuffer,\r
&InputLength\r
//\r
Status = GetSectionContents (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
FileBuffer + Offset,\r
&InputLength\r
UINT8 *OutFileBuffer;\r
EFI_STATUS Status;\r
UINT64 LogLevel;\r
- \r
+ UINT32 *InputFileAlign;\r
+ UINT32 InputFileAlignNum;\r
+\r
+ InputFileAlign = NULL;\r
+ InputFileAlignNum = 0;\r
InputFileName = NULL;\r
OutputFileName = NULL;\r
SectionName = NULL;\r
InputFileNum = 0;\r
SectType = EFI_SECTION_ALL;\r
SectCompSubType = 0;\r
- SectGuidAttribute = 0;\r
+ SectGuidAttribute = EFI_GUIDED_SECTION_NONE;\r
OutFileBuffer = NULL;\r
InputLength = 0;\r
Status = STATUS_SUCCESS;\r
continue;\r
}\r
\r
+ //\r
+ // Section File alignment requirement\r
+ //\r
+ if (stricmp (argv[0], "--sectionalign") == 0) {\r
+ if (InputFileAlignNum == 0) {\r
+ InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
+ if (InputFileAlign == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+ return 1;\r
+ }\r
+ memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
+ } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
+ InputFileAlign = (UINT32 *) realloc (\r
+ InputFileAlign,\r
+ (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
+ );\r
+\r
+ if (InputFileAlign == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+ return 1;\r
+ }\r
+ memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
+ }\r
+ \r
+ Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
+ goto Finish;\r
+ }\r
+ argc -= 2;\r
+ argv += 2;\r
+ InputFileAlignNum ++;\r
+ continue; \r
+ }\r
+\r
//\r
// Get Input file name\r
//\r
Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
return 1;\r
}\r
-\r
memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
} else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
//\r
Error (NULL, 0, 4001, "Resource", "memory cannot be allcoated");\r
return 1;\r
}\r
-\r
memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
}\r
\r
argv ++;\r
}\r
\r
+ if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {\r
+ Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");\r
+ goto Finish;\r
+ }\r
+\r
VerboseMsg ("%s tool start.", UTILITY_NAME);\r
\r
//\r
memcpy (&VendorGuid, &mEfiCrc32SectionGuid, sizeof (EFI_GUID));\r
}\r
\r
- if (SectGuidAttribute == 0) {\r
- SectGuidAttribute = EFI_GUIDED_SECTION_PROCESSING_REQUIRED;\r
- }\r
if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {\r
//\r
// NONE attribute, clear attribute value.\r
//\r
switch (SectType) {\r
case EFI_SECTION_COMPRESSION:\r
+ if (InputFileAlign != NULL) {\r
+ free (InputFileAlign);\r
+ InputFileAlign = NULL;\r
+ }\r
Status = GenSectionCompressionSection (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
SectCompSubType,\r
&OutFileBuffer\r
break;\r
\r
case EFI_SECTION_GUID_DEFINED:\r
+ if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mEfiCrc32SectionGuid) != 0)) {\r
+ //\r
+ // Only process alignment for the default known CRC32 guided section.\r
+ // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.\r
+ //\r
+ free (InputFileAlign);\r
+ InputFileAlign = NULL;\r
+ }\r
Status = GenSectionGuidDefinedSection (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
&VendorGuid,\r
SectGuidAttribute,\r
//\r
Status = GetSectionContents (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
OutFileBuffer,\r
&InputLength\r
//\r
Status = GetSectionContents (\r
InputFileName,\r
+ InputFileAlign,\r
InputFileNum,\r
OutFileBuffer,\r
&InputLength\r
free (InputFileName);\r
}\r
\r
+ if (InputFileAlign != NULL) {\r
+ free (InputFileAlign);\r
+ }\r
+\r
if (OutFileBuffer != NULL) {\r
free (OutFileBuffer);\r
}\r
def __init__(self):\r
self.DepexType = None\r
self.Expression = None\r
+ self.ExpressionProcessed = False\r
\r
## Compress section data in FDF\r
#\r
self.FvFileType = None\r
self.FvFileName = None\r
self.FvFileExtension = None\r
+ self.FvAddr = None\r
\r
## GUIDed section data in FDF\r
#\r
self.SectionType = None\r
self.ProcessRequired = False\r
self.AuthStatusValid = False\r
+ self.FvAddr = None\r
\r
## UI section data in FDF\r
#\r
def __init__(self):\r
self.DriverName = None\r
self.FfsList = []\r
-
\ No newline at end of file
+ \r
# @retval tuple (Generated file name list, section alignment)\r
#\r
def GenSection(self, OutputPath, ModuleName, SecNum, keyStringList, FfsFile = None, Dict = {}):\r
+ \r
+ if self.ExpressionProcessed == False:\r
+ self.Expression = self.Expression.replace("\n", " ").replace("\r", " ")\r
+ ExpList = self.Expression.split()\r
+ ExpGuidDict = {}\r
\r
- self.Expression = self.Expression.replace("\n", " ").replace("\r", " ")\r
- ExpList = self.Expression.split()\r
- ExpGuidDict = {}\r
+ for Exp in ExpList:\r
+ if Exp.upper() not in ('AND', 'OR', 'NOT', 'TRUE', 'FALSE', 'SOR', 'BEFORE', 'AFTER', 'END'):\r
+ GuidStr = self.__FindGuidValue(Exp)\r
+ if GuidStr == None:\r
+ EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE,\r
+ "Depex GUID %s could not be found in build DB! (ModuleName: %s)" % (Exp, ModuleName))\r
\r
- for Exp in ExpList:\r
- if Exp.upper() not in ('AND', 'OR', 'NOT', 'TRUE', 'FALSE', 'SOR', 'BEFORE', 'AFTER', 'END'):\r
- GuidStr = self.__FindGuidValue(Exp)\r
- if GuidStr == None:\r
- EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE,\r
- "Depex GUID %s could not be found in build DB! (ModuleName: %s)" % (Exp, ModuleName))\r
+ ExpGuidDict[Exp] = GuidStr\r
\r
- ExpGuidDict[Exp] = GuidStr\r
+ for Item in ExpGuidDict:\r
+ self.Expression = self.Expression.replace(Item, ExpGuidDict[Item])\r
\r
- for Item in ExpGuidDict:\r
- self.Expression = self.Expression.replace(Item, ExpGuidDict[Item])\r
+ self.Expression = self.Expression.strip()\r
+ self.ExpressionProcessed = True\r
\r
- self.Expression = self.Expression.strip()\r
if self.DepexType == 'PEI_DEPEX_EXP':\r
ModuleType = 'PEIM'\r
SecType = 'PEI_DEPEX'\r
#\r
import Ffs\r
import Rule\r
-from GenFdsGlobalVariable import GenFdsGlobalVariable\r
import os\r
import StringIO\r
import subprocess\r
+\r
+from GenFdsGlobalVariable import GenFdsGlobalVariable\r
from CommonDataClass.FdfClass import FileStatementClassObject\r
from Common import EdkLogger\r
from Common.BuildToolError import *\r
from Common.Misc import GuidStructureByteArrayToGuidString\r
+from GuidSection import GuidSection\r
+from FvImageSection import FvImageSection\r
\r
## generate FFS from FILE\r
#\r
# @param Dict dictionary contains macro and value pair\r
# @retval string Generated FFS file name\r
#\r
- def GenFfs(self, Dict = {}):\r
+ def GenFfs(self, Dict = {}, FvAddr=[]):\r
\r
if self.NameGuid != None and self.NameGuid.startswith('PCD('):\r
PcdValue = GenFdsGlobalVariable.GetPcdValue(self.NameGuid)\r
for section in self.SectionList :\r
Index = Index + 1\r
SecIndex = '%d' %Index\r
+ # process the inside FvImage from FvSection or GuidSection\r
+ if FvAddr != []:\r
+ if isinstance(section, FvImageSection):\r
+ section.FvAddr = FvAddr.pop(0)\r
+ elif isinstance(section, GuidSection):\r
+ if section.ProcessRequired == False:\r
+ section.FvAddr = FvAddr.pop(0)\r
sectList, align = section.GenSection(OutputDir, self.NameGuid, SecIndex, self.KeyStringList, None, Dict)\r
if sectList != []:\r
for sect in sectList:\r
self.BaseName = Inf.BaseName\r
self.ModuleGuid = Inf.Guid\r
self.ModuleType = Inf.ModuleType\r
- if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
+ if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
if Inf.AutoGenVersion < 0x00010005:\r
self.ModuleType = Inf.ComponentType\r
self.BaseName = Inf.BaseName\r
self.ModuleGuid = Inf.Guid\r
self.ModuleType = Inf.ModuleType\r
- if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
+ if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
self.VersionString = Inf.Version\r
self.BinFileList = Inf.Binaries\r
if len(self.SourceFileList) != 0 and not self.InDsc:\r
EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
\r
- if self.ModuleType == 'SMM_CORE' and self.PiSpecVersion < 0x0001000A:
+ if self.ModuleType == 'SMM_CORE' and self.PiSpecVersion < 0x0001000A:\r
EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.InfFileName) \r
\r
if Inf._Defs != None and len(Inf._Defs) > 0:\r
# @param Dict dictionary contains macro and value pair\r
# @retval string Generated FFS file name\r
#\r
- def GenFfs(self, Dict = {}):\r
+ def GenFfs(self, Dict = {}, FvAddr = []):\r
#\r
# Parse Inf file get Module related information\r
#\r
#\r
def AddToBuffer (self, Buffer, BaseAddress=None, BlockSize= None, BlockNum=None, ErasePloarity='1', VtfDict=None, MacroDict = {}) :\r
\r
- if self.UiFvName.upper() + 'fv' in GenFds.ImageBinDict.keys():\r
+ if BaseAddress == None and self.UiFvName.upper() + 'fv' in GenFds.ImageBinDict.keys():\r
return GenFds.ImageBinDict[self.UiFvName.upper() + 'fv']\r
\r
#\r
\r
FvInfoFileName = os.path.join(GenFdsGlobalVariable.FfsDir, self.UiFvName + '.inf')\r
shutil.copy(GenFdsGlobalVariable.FvAddressFileName, FvInfoFileName)\r
+ oldtime = os.path.getmtime(FvInfoFileName)\r
GenFdsGlobalVariable.GenerateFirmwareVolume(\r
FvOutputFile,\r
[self.InfFileName],\r
FfsList=FfsFileList\r
)\r
\r
+ if os.path.getmtime(FvInfoFileName) > oldtime:\r
+ FvAddrString = []\r
+ AddFileObj = open(FvInfoFileName, 'r')\r
+ AddrStrings = AddFileObj.readlines()\r
+ AddrKeyFound = False\r
+ for AddrString in AddrStrings:\r
+ if AddrKeyFound:\r
+ #get base address for the inside FvImage\r
+ FvAddrString.append (AddrString)\r
+ elif AddrString.find ("[FV_BASE_ADDRESS]") != -1:\r
+ AddrKeyFound = True\r
+ AddFileObj.close()\r
+\r
+ if FvAddrString != []:\r
+ # Update Ffs again\r
+ for FfsFile in self.FfsList :\r
+ FileName = FfsFile.GenFfs(MacroDict, FvAddr=FvAddrString)\r
+ \r
+ #Update GenFv again\r
+ GenFdsGlobalVariable.GenerateFirmwareVolume(\r
+ FvOutputFile,\r
+ [self.InfFileName],\r
+ AddressFile=FvInfoFileName,\r
+ FfsList=FfsFileList\r
+ )\r
+\r
#\r
# Write the Fv contents to Buffer\r
#\r
GenFdsGlobalVariable.SharpCounter = 0\r
\r
Buffer.write(FvFileObj.read())\r
+ FvFileObj.seek(0)\r
+ # PI FvHeader is 0x48 byte\r
+ FvHeaderBuffer = FvFileObj.read(0x48)\r
+ # FV alignment position.\r
+ FvAlignmentValue = 1 << (ord (FvHeaderBuffer[0x2E]) & 0x1F)\r
+ # FvAlignmentValue is larger than or equal to 1K\r
+ if FvAlignmentValue >= 0x400:\r
+ if FvAlignmentValue >= 0x10000:\r
+ #The max alignment supported by FFS is 64K.\r
+ self.FvAlignment = "64K"\r
+ else:\r
+ self.FvAlignment = str (FvAlignmentValue / 0x400) + "K"\r
+ else:\r
+ # FvAlignmentValue is less than 1K\r
+ self.FvAlignment = str (FvAlignmentValue)\r
FvFileObj.close()\r
GenFds.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile\r
return FvOutputFile\r
Fv = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName)\r
if Fv != None:\r
self.Fv = Fv\r
- FvFileName = self.Fv.AddToBuffer(Buffer, MacroDict = Dict)\r
+ FvFileName = Fv.AddToBuffer(Buffer, self.FvAddr, MacroDict = Dict)\r
+ if Fv.FvAlignment != None:\r
+ if self.Alignment == None:\r
+ self.Alignment = Fv.FvAlignment\r
+ else:\r
+ if GenFdsGlobalVariable.GetAlignment (Fv.FvAlignment) > GenFdsGlobalVariable.GetAlignment (self.Alignment):\r
+ self.Alignment = Fv.FvAlignment\r
else:\r
if self.FvFileName != None:\r
FvFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FvFileName)\r
@staticmethod
def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None,
- GuidHdrLen=None, GuidAttr=None, Ui=None, Ver=None):
+ GuidHdrLen=None, GuidAttr=None, Ui=None, Ver=None, InputAlign=None):
if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
return
GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
Cmd += ["-l", GuidHdrLen]
if GuidAttr not in [None, '']:
Cmd += ["-r", GuidAttr]
+ if InputAlign != None:
+ #Section Align is only for dummy section without section type
+ for SecAlign in InputAlign:
+ Cmd += ["--sectionalign", SecAlign]
if Ui not in [None, '']:
#Cmd += ["-n", '"' + Ui + '"']
Cmd += Input
GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
+ @staticmethod
+ def GetAlignment (AlignString):
+ if AlignString == None:
+ return 0
+ if AlignString in ("1K", "2K", "4K", "8K", "16K", "32K", "64K"):\r
+ return int (AlignString.rstrip('K')) * 1024\r
+ else:\r
+ return int (AlignString)\r
+
@staticmethod
def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
SectionAlign=None):
import sys\r
from Common import EdkLogger\r
from Common.BuildToolError import *\r
+from FvImageSection import FvImageSection\r
\r
## generate GUIDed section\r
#\r
self.SectionType = FfsInf.__ExtendMacro__(self.SectionType)\r
self.CurrentArchList = [FfsInf.CurrentArch]\r
\r
- SectFile = tuple()\r
+ SectFile = tuple()\r
+ SectAlign = []\r
Index = 0\r
+ MaxAlign = None\r
for Sect in self.SectionList:\r
Index = Index + 1\r
SecIndex = '%s.%d' %(SecNum,Index)\r
+ # set base address for inside FvImage\r
+ if isinstance(Sect, FvImageSection):\r
+ Sect.FvAddr = self.FvAddr\r
ReturnSectList, align = Sect.GenSection(OutputPath, ModuleName, SecIndex, KeyStringList,FfsInf, Dict)\r
+ if align != None:\r
+ if MaxAlign == None:\r
+ MaxAlign = align\r
+ if GenFdsGlobalVariable.GetAlignment (align) > GenFdsGlobalVariable.GetAlignment (MaxAlign):\r
+ MaxAlign = align\r
if ReturnSectList != []:\r
+ if align == None:\r
+ align = "1"\r
for file in ReturnSectList:\r
SectFile += (file,)\r
+ SectAlign.append(align)\r
\r
+ if MaxAlign != None:\r
+ if self.Alignment == None:\r
+ self.Alignment = MaxAlign\r
+ else:\r
+ if GenFdsGlobalVariable.GetAlignment (MaxAlign) > GenFdsGlobalVariable.GetAlignment (self.Alignment):\r
+ self.Alignment = MaxAlign\r
\r
OutputFile = OutputPath + \\r
os.sep + \\r
#\r
if self.NameGuid == None :\r
GenFdsGlobalVariable.VerboseLogger( "Use GenSection function Generate CRC32 Section")\r
- GenFdsGlobalVariable.GenerateSection(OutputFile, SectFile, Section.Section.SectionType[self.SectionType])\r
+ GenFdsGlobalVariable.GenerateSection(OutputFile, SectFile, Section.Section.SectionType[self.SectionType], InputAlign=SectAlign)\r
OutputFileList = []\r
OutputFileList.append(OutputFile)\r
return OutputFileList, self.Alignment\r
#\r
# Call GenSection with DUMMY section type.\r
#\r
- GenFdsGlobalVariable.GenerateSection(OutputFile+".dummy", SectFile)\r
+ GenFdsGlobalVariable.GenerateSection(OutputFile+".dummy", SectFile, InputAlign=SectAlign)\r
#\r
# Use external tool process the Output\r
#\r
'.tmp'\r
TempFile = os.path.normpath(TempFile)\r
\r
- ExternalToolCmd = (\r
- ExternalTool,\r
- '-e',\r
- '-o', TempFile,\r
- InputFile,\r
- )\r
-\r
#\r
# Call external tool\r
#\r
GenFdsGlobalVariable.GuidTool(TempFile, [InputFile], ExternalTool, '-e')\r
\r
+ FileHandleIn = open(InputFile,'rb')\r
+ FileHandleIn.seek(0,2)\r
+ InputFileSize = FileHandleIn.tell()\r
+ \r
+ FileHandleOut = open(TempFile,'rb')\r
+ FileHandleOut.seek(0,2)\r
+ TempFileSize = FileHandleOut.tell()\r
+\r
+ HeaderLength = None\r
+ if TempFileSize > InputFileSize and TempFileSize % 4 == 0:\r
+ FileHandleIn.seek(0)\r
+ BufferIn = FileHandleIn.read()\r
+ FileHandleOut.seek(0)\r
+ BufferOut = FileHandleOut.read()\r
+ if BufferIn in BufferOut[TempFileSize - InputFileSize:]:\r
+ HeaderLength = str(TempFileSize - InputFileSize)\r
+ #auto sec guided attribute with process required\r
+ if HeaderLength == None:\r
+ Attribute = 'PROCESSING_REQUIRED'\r
+\r
+ FileHandleIn.close()\r
+ FileHandleOut.close()\r
+ \r
#\r
- # Call Gensection Add Secntion Header\r
+ # Call Gensection Add Section Header\r
#\r
- Attribute = None\r
- if self.ProcessRequired == True:\r
- Attribute = 'PROCSSING_REQUIRED'\r
- if self.AuthStatusValid == True:\r
+ Attribute = 'NONE'\r
+ if self.ProcessRequired in ("TRUE", "1"):\r
+ Attribute = 'PROCESSING_REQUIRED'\r
+ HeaderLength = None\r
+ if self.AuthStatusValid in ("TRUE", "1"):\r
Attribute = 'AUTH_STATUS_VALID'\r
GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'],\r
- Guid=self.NameGuid, GuidAttr=Attribute)\r
+ Guid=self.NameGuid, GuidAttr=Attribute, GuidHdrLen=HeaderLength)\r
OutputFileList = []\r
OutputFileList.append(OutputFile)\r
return OutputFileList, self.Alignment\r