summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds')
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/AprioriSection.py121
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Capsule.py250
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CapsuleData.py239
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CompressSection.py96
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py117
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DepexSection.py111
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py318
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fd.py155
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py4526
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Ffs.py49
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py175
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsInfStatement.py1128
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fv.py431
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FvImageSection.py158
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py800
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py1033
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GuidSection.py278
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomFileStatement.py48
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomInfStatement.py159
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptionRom.py131
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Region.py348
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Rule.py23
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleComplexFile.py25
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleSimpleFile.py25
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py153
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/UiSection.py74
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/VerSection.py76
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/__init__.py9
28 files changed, 11056 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/AprioriSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/AprioriSection.py
new file mode 100755
index 00000000..84ec0976
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/AprioriSection.py
@@ -0,0 +1,121 @@
+## @file
+# process APRIORI file data and generate PEI/DXE APRIORI file
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from struct import pack
+import Common.LongFilePathOs as os
+from io import BytesIO
+from .FfsFileStatement import FileStatement
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from Common.StringUtils import NormPath
+from Common.Misc import SaveFileOnChange, PathClass
+from Common.EdkLogger import error as EdkLoggerError
+from Common.BuildToolError import RESOURCE_NOT_AVAILABLE
+from Common.DataType import TAB_COMMON
+
+DXE_APRIORI_GUID = "FC510EE7-FFDC-11D4-BD41-0080C73C8881"
+PEI_APRIORI_GUID = "1B45CC0A-156A-428A-AF62-49864DA0E6E6"
+
+## process APRIORI file data and generate PEI/DXE APRIORI file
+#
+#
+class AprioriSection (object):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ self.DefineVarDict = {}
+ self.FfsList = []
+ self.AprioriType = ""
+
+ ## GenFfs() method
+ #
+ # Generate FFS for APRIORI file
+ #
+ # @param self The object pointer
+ # @param FvName for whom apriori file generated
+ # @param Dict dictionary contains macro and its value
+ # @retval string Generated file name
+ #
+ def GenFfs (self, FvName, Dict = None, IsMakefile = False):
+ if Dict is None:
+ Dict = {}
+ Buffer = BytesIO()
+ if self.AprioriType == "PEI":
+ AprioriFileGuid = PEI_APRIORI_GUID
+ else:
+ AprioriFileGuid = DXE_APRIORI_GUID
+
+ OutputAprFilePath = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, \
+ GenFdsGlobalVariable.FfsDir,\
+ AprioriFileGuid + FvName)
+ if not os.path.exists(OutputAprFilePath):
+ os.makedirs(OutputAprFilePath)
+
+ OutputAprFileName = os.path.join( OutputAprFilePath, \
+ AprioriFileGuid + FvName + '.Apri' )
+ AprFfsFileName = os.path.join (OutputAprFilePath,\
+ AprioriFileGuid + FvName + '.Ffs')
+
+ Dict.update(self.DefineVarDict)
+ InfFileName = None
+ for FfsObj in self.FfsList:
+ Guid = ""
+ if isinstance(FfsObj, FileStatement):
+ Guid = FfsObj.NameGuid
+ else:
+ InfFileName = NormPath(FfsObj.InfFileName)
+ Arch = FfsObj.GetCurrentArch()
+
+ if Arch:
+ Dict['$(ARCH)'] = Arch
+ InfFileName = GenFdsGlobalVariable.MacroExtend(InfFileName, Dict, Arch)
+
+ if Arch:
+ Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(InfFileName, GenFdsGlobalVariable.WorkSpaceDir), Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ Guid = Inf.Guid
+ else:
+ Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(InfFileName, GenFdsGlobalVariable.WorkSpaceDir), TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ Guid = Inf.Guid
+
+ if not Inf.Module.Binaries:
+ EdkLoggerError("GenFds", RESOURCE_NOT_AVAILABLE,
+ "INF %s not found in build ARCH %s!" \
+ % (InfFileName, GenFdsGlobalVariable.ArchList))
+
+ GuidPart = Guid.split('-')
+ Buffer.write(pack('I', int(GuidPart[0], 16)))
+ Buffer.write(pack('H', int(GuidPart[1], 16)))
+ Buffer.write(pack('H', int(GuidPart[2], 16)))
+
+ for Num in range(2):
+ Char = GuidPart[3][Num*2:Num*2+2]
+ Buffer.write(pack('B', int(Char, 16)))
+
+ for Num in range(6):
+ Char = GuidPart[4][Num*2:Num*2+2]
+ Buffer.write(pack('B', int(Char, 16)))
+
+ SaveFileOnChange(OutputAprFileName, Buffer.getvalue())
+
+ RawSectionFileName = os.path.join( OutputAprFilePath, \
+ AprioriFileGuid + FvName + '.raw' )
+ MakefilePath = None
+ if IsMakefile:
+ if not InfFileName:
+ return None
+ MakefilePath = InfFileName, Arch
+ GenFdsGlobalVariable.GenerateSection(RawSectionFileName, [OutputAprFileName], 'EFI_SECTION_RAW', IsMakefile=IsMakefile)
+ GenFdsGlobalVariable.GenerateFfs(AprFfsFileName, [RawSectionFileName],
+ 'EFI_FV_FILETYPE_FREEFORM', AprioriFileGuid, MakefilePath=MakefilePath)
+
+ return AprFfsFileName
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Capsule.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Capsule.py
new file mode 100755
index 00000000..b155d80e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Capsule.py
@@ -0,0 +1,250 @@
+## @file
+# generate capsule
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from .GenFdsGlobalVariable import GenFdsGlobalVariable, FindExtendTool
+from CommonDataClass.FdfClass import CapsuleClassObject
+import Common.LongFilePathOs as os
+from io import BytesIO
+from Common.Misc import SaveFileOnChange, PackGUID
+import uuid
+from struct import pack
+from Common import EdkLogger
+from Common.BuildToolError import GENFDS_ERROR
+from Common.DataType import TAB_LINE_BREAK
+
+WIN_CERT_REVISION = 0x0200
+WIN_CERT_TYPE_EFI_GUID = 0x0EF1
+EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')
+EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-4977-9420-844712a735bf}')
+
+## create inf file describes what goes into capsule and call GenFv to generate capsule
+#
+#
+class Capsule (CapsuleClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ CapsuleClassObject.__init__(self)
+ # For GenFv
+ self.BlockSize = None
+ # For GenFv
+ self.BlockNum = None
+ self.CapsuleName = None
+
+ ## Generate FMP capsule
+ #
+ # @retval string Generated Capsule file path
+ #
+ def GenFmpCapsule(self):
+ #
+ # Generate capsule header
+ # typedef struct {
+ # EFI_GUID CapsuleGuid;
+ # UINT32 HeaderSize;
+ # UINT32 Flags;
+ # UINT32 CapsuleImageSize;
+ # } EFI_CAPSULE_HEADER;
+ #
+ Header = BytesIO()
+ #
+ # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
+ #
+ Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-')))
+ HdrSize = 0
+ if 'CAPSULE_HEADER_SIZE' in self.TokensDict:
+ Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)))
+ HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)
+ else:
+ Header.write(pack('=I', 0x20))
+ HdrSize = 0x20
+ Flags = 0
+ if 'CAPSULE_FLAGS' in self.TokensDict:
+ for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):
+ flag = flag.strip()
+ if flag == 'PopulateSystemTable':
+ Flags |= 0x00010000 | 0x00020000
+ elif flag == 'PersistAcrossReset':
+ Flags |= 0x00010000
+ elif flag == 'InitiateReset':
+ Flags |= 0x00040000
+ Header.write(pack('=I', Flags))
+ #
+ # typedef struct {
+ # UINT32 Version;
+ # UINT16 EmbeddedDriverCount;
+ # UINT16 PayloadItemCount;
+ # // UINT64 ItemOffsetList[];
+ # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
+ #
+ FwMgrHdr = BytesIO()
+ if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:
+ FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))
+ else:
+ FwMgrHdr.write(pack('=I', 0x00000001))
+ FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))
+ FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))
+
+ #
+ # typedef struct _WIN_CERTIFICATE {
+ # UINT32 dwLength;
+ # UINT16 wRevision;
+ # UINT16 wCertificateType;
+ # //UINT8 bCertificate[ANYSIZE_ARRAY];
+ # } WIN_CERTIFICATE;
+ #
+ # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
+ # WIN_CERTIFICATE Hdr;
+ # EFI_GUID CertType;
+ # //UINT8 CertData[ANYSIZE_ARRAY];
+ # } WIN_CERTIFICATE_UEFI_GUID;
+ #
+ # typedef struct {
+ # UINT64 MonotonicCount;
+ # WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+ # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
+ #
+ # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
+ # EFI_GUID HashType;
+ # UINT8 PublicKey[256];
+ # UINT8 Signature[256];
+ # } EFI_CERT_BLOCK_RSA_2048_SHA256;
+ #
+
+ PreSize = FwMgrHdrSize
+ Content = BytesIO()
+ for driver in self.CapsuleDataList:
+ FileName = driver.GenCapsuleSubItem()
+ FwMgrHdr.write(pack('=Q', PreSize))
+ PreSize += os.path.getsize(FileName)
+ File = open(FileName, 'rb')
+ Content.write(File.read())
+ File.close()
+ for fmp in self.FmpPayloadList:
+ if fmp.Existed:
+ FwMgrHdr.write(pack('=Q', PreSize))
+ PreSize += len(fmp.Buffer)
+ Content.write(fmp.Buffer)
+ continue
+ if fmp.ImageFile:
+ for Obj in fmp.ImageFile:
+ fmp.ImageFile = Obj.GenCapsuleSubItem()
+ if fmp.VendorCodeFile:
+ for Obj in fmp.VendorCodeFile:
+ fmp.VendorCodeFile = Obj.GenCapsuleSubItem()
+ if fmp.Certificate_Guid:
+ ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)
+ CmdOption = ''
+ CapInputFile = fmp.ImageFile
+ if not os.path.isabs(fmp.ImageFile):
+ CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)
+ CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'
+ if ExternalTool is None:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)
+ else:
+ CmdOption += ExternalTool
+ if ExternalOption:
+ CmdOption = CmdOption + ' ' + ExternalOption
+ CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile
+ CmdList = CmdOption.split()
+ GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")
+ if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:
+ dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)
+ else:
+ dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256
+ fmp.ImageFile = CapOutputTmp
+ AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid]
+ fmp.Buffer = fmp.GenCapsuleSubItem(AuthData)
+ else:
+ fmp.Buffer = fmp.GenCapsuleSubItem()
+ FwMgrHdr.write(pack('=Q', PreSize))
+ PreSize += len(fmp.Buffer)
+ Content.write(fmp.Buffer)
+ BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())
+ Header.write(pack('=I', HdrSize + BodySize))
+ #
+ # The real capsule header structure is 28 bytes
+ #
+ Header.write(b'\x00'*(HdrSize-28))
+ Header.write(FwMgrHdr.getvalue())
+ Header.write(Content.getvalue())
+ #
+ # Generate FMP capsule file
+ #
+ CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'
+ SaveFileOnChange(CapOutputFile, Header.getvalue(), True)
+ return CapOutputFile
+
+ ## Generate capsule
+ #
+ # @param self The object pointer
+ # @retval string Generated Capsule file path
+ #
+ def GenCapsule(self):
+ if self.UiCapsuleName.upper() + 'cap' in GenFdsGlobalVariable.ImageBinDict:
+ return GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap']
+
+ GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName)
+ if ('CAPSULE_GUID' in self.TokensDict and
+ uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):
+ return self.GenFmpCapsule()
+
+ CapInfFile = self.GenCapInf()
+ CapInfFile.append("[files]" + TAB_LINE_BREAK)
+ CapFileList = []
+ for CapsuleDataObj in self.CapsuleDataList:
+ CapsuleDataObj.CapsuleName = self.CapsuleName
+ FileName = CapsuleDataObj.GenCapsuleSubItem()
+ CapsuleDataObj.CapsuleName = None
+ CapFileList.append(FileName)
+ CapInfFile.append("EFI_FILE_NAME = " + \
+ FileName + \
+ TAB_LINE_BREAK)
+ SaveFileOnChange(self.CapInfFileName, ''.join(CapInfFile), False)
+ #
+ # Call GenFv tool to generate capsule
+ #
+ CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName)
+ CapOutputFile = CapOutputFile + '.Cap'
+ GenFdsGlobalVariable.GenerateFirmwareVolume(
+ CapOutputFile,
+ [self.CapInfFileName],
+ Capsule=True,
+ FfsList=CapFileList
+ )
+
+ GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)
+ GenFdsGlobalVariable.SharpCounter = 0
+ GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile
+ return CapOutputFile
+
+ ## Generate inf file for capsule
+ #
+ # @param self The object pointer
+ # @retval file inf file object
+ #
+ def GenCapInf(self):
+ self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
+ self.UiCapsuleName + "_Cap" + '.inf')
+ CapInfFile = []
+
+ CapInfFile.append("[options]" + TAB_LINE_BREAK)
+
+ for Item in self.TokensDict:
+ CapInfFile.append("EFI_" + \
+ Item + \
+ ' = ' + \
+ self.TokensDict[Item] + \
+ TAB_LINE_BREAK)
+
+ return CapInfFile
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CapsuleData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CapsuleData.py
new file mode 100755
index 00000000..c7b3b0ca
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CapsuleData.py
@@ -0,0 +1,239 @@
+## @file
+# generate capsule
+#
+# Copyright (c) 2007-2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from io import BytesIO
+from struct import pack
+import os
+from Common.Misc import SaveFileOnChange
+import uuid
+
+## base class for capsule data
+#
+#
+class CapsuleData:
+ ## The constructor
+ #
+ # @param self The object pointer
+ def __init__(self):
+ pass
+
+ ## generate capsule data
+ #
+ # @param self The object pointer
+ def GenCapsuleSubItem(self):
+ pass
+
+## FFS class for capsule data
+#
+#
+class CapsuleFfs (CapsuleData):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self) :
+ self.Ffs = None
+ self.FvName = None
+
+ ## generate FFS capsule data
+ #
+ # @param self The object pointer
+ # @retval string Generated file name
+ #
+ def GenCapsuleSubItem(self):
+ FfsFile = self.Ffs.GenFfs()
+ return FfsFile
+
+## FV class for capsule data
+#
+#
+class CapsuleFv (CapsuleData):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self) :
+ self.Ffs = None
+ self.FvName = None
+ self.CapsuleName = None
+
+ ## generate FV capsule data
+ #
+ # @param self The object pointer
+ # @retval string Generated file name
+ #
+ def GenCapsuleSubItem(self):
+ if self.FvName.find('.fv') == -1:
+ if self.FvName.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict:
+ FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[self.FvName.upper()]
+ FdBuffer = BytesIO()
+ FvObj.CapsuleName = self.CapsuleName
+ FvFile = FvObj.AddToBuffer(FdBuffer)
+ FvObj.CapsuleName = None
+ FdBuffer.close()
+ return FvFile
+ else:
+ FvFile = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FvName)
+ return FvFile
+
+## FD class for capsule data
+#
+#
+class CapsuleFd (CapsuleData):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self) :
+ self.Ffs = None
+ self.FdName = None
+ self.CapsuleName = None
+
+ ## generate FD capsule data
+ #
+ # @param self The object pointer
+ # @retval string Generated file name
+ #
+ def GenCapsuleSubItem(self):
+ if self.FdName.find('.fd') == -1:
+ if self.FdName.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict:
+ FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[self.FdName.upper()]
+ FdFile = FdObj.GenFd()
+ return FdFile
+ else:
+ FdFile = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FdName)
+ return FdFile
+
+## AnyFile class for capsule data
+#
+#
+class CapsuleAnyFile (CapsuleData):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self) :
+ self.Ffs = None
+ self.FileName = None
+
+ ## generate AnyFile capsule data
+ #
+ # @param self The object pointer
+ # @retval string Generated file name
+ #
+ def GenCapsuleSubItem(self):
+ return self.FileName
+
+## Afile class for capsule data
+#
+#
+class CapsuleAfile (CapsuleData):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self) :
+ self.Ffs = None
+ self.FileName = None
+
+ ## generate Afile capsule data
+ #
+ # @param self The object pointer
+ # @retval string Generated file name
+ #
+ def GenCapsuleSubItem(self):
+ return self.FileName
+
+class CapsulePayload(CapsuleData):
+ '''Generate payload file, the header is defined below:
+ #pragma pack(1)
+ typedef struct {
+ UINT32 Version;
+ EFI_GUID UpdateImageTypeId;
+ UINT8 UpdateImageIndex;
+ UINT8 reserved_bytes[3];
+ UINT32 UpdateImageSize;
+ UINT32 UpdateVendorCodeSize;
+ UINT64 UpdateHardwareInstance; //Introduced in v2
+ } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
+ '''
+ def __init__(self):
+ self.UiName = None
+ self.Version = None
+ self.ImageTypeId = None
+ self.ImageIndex = None
+ self.HardwareInstance = None
+ self.ImageFile = []
+ self.VendorCodeFile = []
+ self.Certificate_Guid = None
+ self.MonotonicCount = None
+ self.Existed = False
+ self.Buffer = None
+
+ def GenCapsuleSubItem(self, AuthData=[]):
+ if not self.Version:
+ self.Version = '0x00000002'
+ if not self.ImageIndex:
+ self.ImageIndex = '0x1'
+ if not self.HardwareInstance:
+ self.HardwareInstance = '0x0'
+ ImageFileSize = os.path.getsize(self.ImageFile)
+ if AuthData:
+ # the ImageFileSize need include the full authenticated info size. From first bytes of MonotonicCount to last bytes of certificate.
+ # the 32 bit is the MonotonicCount, dwLength, wRevision, wCertificateType and CertType
+ ImageFileSize += 32
+ VendorFileSize = 0
+ if self.VendorCodeFile:
+ VendorFileSize = os.path.getsize(self.VendorCodeFile)
+
+ #
+ # Fill structure
+ #
+ Guid = self.ImageTypeId.split('-')
+ Buffer = pack('=ILHHBBBBBBBBBBBBIIQ',
+ int(self.Version, 16),
+ int(Guid[0], 16),
+ int(Guid[1], 16),
+ int(Guid[2], 16),
+ int(Guid[3][-4:-2], 16),
+ int(Guid[3][-2:], 16),
+ int(Guid[4][-12:-10], 16),
+ int(Guid[4][-10:-8], 16),
+ int(Guid[4][-8:-6], 16),
+ int(Guid[4][-6:-4], 16),
+ int(Guid[4][-4:-2], 16),
+ int(Guid[4][-2:], 16),
+ int(self.ImageIndex, 16),
+ 0,
+ 0,
+ 0,
+ ImageFileSize,
+ VendorFileSize,
+ int(self.HardwareInstance, 16)
+ )
+ if AuthData:
+ Buffer += pack('QIHH', AuthData[0], AuthData[1], AuthData[2], AuthData[3])
+ Buffer += uuid.UUID(AuthData[4]).bytes_le
+
+ #
+ # Append file content to the structure
+ #
+ ImageFile = open(self.ImageFile, 'rb')
+ Buffer += ImageFile.read()
+ ImageFile.close()
+ if self.VendorCodeFile:
+ VendorFile = open(self.VendorCodeFile, 'rb')
+ Buffer += VendorFile.read()
+ VendorFile.close()
+ self.Existed = True
+ return Buffer
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CompressSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CompressSection.py
new file mode 100755
index 00000000..8d9e20e9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/CompressSection.py
@@ -0,0 +1,96 @@
+## @file
+# process compress section generation
+#
+# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from .Ffs import SectionSuffix
+from . import Section
+import subprocess
+import Common.LongFilePathOs as os
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from CommonDataClass.FdfClass import CompressSectionClassObject
+from Common.DataType import *
+
+## generate compress section
+#
+#
+class CompressSection (CompressSectionClassObject) :
+
+ ## compress types: PI standard and non PI standard
+ CompTypeDict = {
+ 'PI_STD' : 'PI_STD',
+ 'PI_NONE' : 'PI_NONE'
+ }
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ CompressSectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # Generate compressed section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = None, IsMakefile = False):
+
+ if FfsInf is not None:
+ self.CompType = FfsInf.__ExtendMacro__(self.CompType)
+ self.Alignment = FfsInf.__ExtendMacro__(self.Alignment)
+
+ SectFiles = tuple()
+ SectAlign = []
+ Index = 0
+ MaxAlign = None
+ if Dict is None:
+ Dict = {}
+ for Sect in self.SectionList:
+ Index = Index + 1
+ SecIndex = '%s.%d' %(SecNum, Index)
+ ReturnSectList, AlignValue = Sect.GenSection(OutputPath, ModuleName, SecIndex, KeyStringList, FfsInf, Dict, IsMakefile=IsMakefile)
+ if AlignValue is not None:
+ if MaxAlign is None:
+ MaxAlign = AlignValue
+ if GenFdsGlobalVariable.GetAlignment (AlignValue) > GenFdsGlobalVariable.GetAlignment (MaxAlign):
+ MaxAlign = AlignValue
+ if ReturnSectList != []:
+ if AlignValue is None:
+ AlignValue = "1"
+ for FileData in ReturnSectList:
+ SectFiles += (FileData,)
+ SectAlign.append(AlignValue)
+
+ OutputFile = OutputPath + \
+ os.sep + \
+ ModuleName + \
+ SUP_MODULE_SEC + \
+ SecNum + \
+ SectionSuffix['COMPRESS']
+ OutputFile = os.path.normpath(OutputFile)
+ DummyFile = OutputFile + '.dummy'
+ GenFdsGlobalVariable.GenerateSection(DummyFile, SectFiles, InputAlign=SectAlign, IsMakefile=IsMakefile)
+
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [DummyFile], Section.Section.SectionType['COMPRESS'],
+ CompressionType=self.CompTypeDict[self.CompType], IsMakefile=IsMakefile)
+ OutputFileList = []
+ OutputFileList.append(OutputFile)
+ return OutputFileList, self.Alignment
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py
new file mode 100755
index 00000000..4391d333
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py
@@ -0,0 +1,117 @@
+## @file
+# process data section generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Section
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+import subprocess
+from .Ffs import SectionSuffix
+import Common.LongFilePathOs as os
+from CommonDataClass.FdfClass import DataSectionClassObject
+from Common.Misc import PeImageClass
+from Common.LongFilePathSupport import CopyLongFilePath
+from Common.DataType import *
+
+## generate data section
+#
+#
+class DataSection (DataSectionClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ DataSectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # Generate compressed section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name list, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, keyStringList, FfsFile = None, Dict = None, IsMakefile = False):
+ #
+ # Prepare the parameter of GenSection
+ #
+ if Dict is None:
+ Dict = {}
+ if FfsFile is not None:
+ self.SectFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.SectFileName)
+ self.SectFileName = GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict, FfsFile.CurrentArch)
+ else:
+ self.SectFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.SectFileName)
+ self.SectFileName = GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict)
+
+ """Check Section file exist or not !"""
+
+ if not os.path.exists(self.SectFileName):
+ self.SectFileName = os.path.join (GenFdsGlobalVariable.WorkSpaceDir,
+ self.SectFileName)
+
+ """Copy Map file to Ffs output"""
+ Filename = GenFdsGlobalVariable.MacroExtend(self.SectFileName)
+ if Filename[(len(Filename)-4):] == '.efi':
+ MapFile = Filename.replace('.efi', '.map')
+ CopyMapFile = os.path.join(OutputPath, ModuleName + '.map')
+ if IsMakefile:
+ if GenFdsGlobalVariable.CopyList == []:
+ GenFdsGlobalVariable.CopyList = [(MapFile, CopyMapFile)]
+ else:
+ GenFdsGlobalVariable.CopyList.append((MapFile, CopyMapFile))
+ else:
+ if os.path.exists(MapFile):
+ if not os.path.exists(CopyMapFile) or (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)):
+ CopyLongFilePath(MapFile, CopyMapFile)
+
+ #Get PE Section alignment when align is set to AUTO
+ if self.Alignment == 'Auto' and self.SecType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):
+ self.Alignment = "0"
+ NoStrip = True
+ if self.SecType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):
+ if self.KeepReloc is not None:
+ NoStrip = self.KeepReloc
+
+ if not NoStrip:
+ FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi')
+ if not os.path.exists(FileBeforeStrip) or \
+ (os.path.getmtime(self.SectFileName) > os.path.getmtime(FileBeforeStrip)):
+ CopyLongFilePath(self.SectFileName, FileBeforeStrip)
+ StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ StrippedFile,
+ [GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict)],
+ Strip=True,
+ IsMakefile = IsMakefile
+ )
+ self.SectFileName = StrippedFile
+
+ if self.SecType == BINARY_FILE_TYPE_TE:
+ TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ TeFile,
+ [GenFdsGlobalVariable.MacroExtend(self.SectFileName, Dict)],
+ Type='te',
+ IsMakefile = IsMakefile
+ )
+ self.SectFileName = TeFile
+
+ OutputFile = os.path.join (OutputPath, ModuleName + SUP_MODULE_SEC + SecNum + SectionSuffix.get(self.SecType))
+ OutputFile = os.path.normpath(OutputFile)
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [self.SectFileName], Section.Section.SectionType.get(self.SecType), IsMakefile = IsMakefile)
+ FileList = [OutputFile]
+ return FileList, self.Alignment
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DepexSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DepexSection.py
new file mode 100755
index 00000000..b2bcf26a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DepexSection.py
@@ -0,0 +1,111 @@
+## @file
+# process depex section generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Section
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+import Common.LongFilePathOs as os
+from CommonDataClass.FdfClass import DepexSectionClassObject
+from AutoGen.GenDepex import DependencyExpression
+from Common import EdkLogger
+from Common.BuildToolError import *
+from Common.Misc import PathClass
+from Common.DataType import *
+
+## generate data section
+#
+#
+class DepexSection (DepexSectionClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ DepexSectionClassObject.__init__(self)
+
+ def __FindGuidValue(self, CName):
+ for Arch in GenFdsGlobalVariable.ArchList:
+ PkgList = GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform,
+ Arch,
+ GenFdsGlobalVariable.TargetName,
+ GenFdsGlobalVariable.ToolChainTag)
+ for Inf in GenFdsGlobalVariable.FdfParser.Profile.InfList:
+ ModuleData = GenFdsGlobalVariable.WorkSpace.BuildObject[
+ PathClass(Inf, GenFdsGlobalVariable.WorkSpaceDir),
+ Arch,
+ GenFdsGlobalVariable.TargetName,
+ GenFdsGlobalVariable.ToolChainTag
+ ]
+ for Pkg in ModuleData.Packages:
+ if Pkg not in PkgList:
+ PkgList.append(Pkg)
+ for PkgDb in PkgList:
+ if CName in PkgDb.Ppis:
+ return PkgDb.Ppis[CName]
+ if CName in PkgDb.Protocols:
+ return PkgDb.Protocols[CName]
+ if CName in PkgDb.Guids:
+ return PkgDb.Guids[CName]
+ return None
+
+ ## GenSection() method
+ #
+ # Generate compressed section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name list, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, keyStringList, FfsFile = None, Dict = None, IsMakefile = False):
+ if self.ExpressionProcessed == False:
+ self.Expression = self.Expression.replace("\n", " ").replace("\r", " ")
+ ExpList = self.Expression.split()
+
+ for Exp in ExpList:
+ if Exp.upper() not in ('AND', 'OR', 'NOT', 'TRUE', 'FALSE', 'SOR', 'BEFORE', 'AFTER', 'END'):
+ GuidStr = self.__FindGuidValue(Exp)
+ if GuidStr is None:
+ EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE,
+ "Depex GUID %s could not be found in build DB! (ModuleName: %s)" % (Exp, ModuleName))
+
+ self.Expression = self.Expression.replace(Exp, GuidStr)
+
+ self.Expression = self.Expression.strip()
+ self.ExpressionProcessed = True
+
+ if self.DepexType == 'PEI_DEPEX_EXP':
+ ModuleType = SUP_MODULE_PEIM
+ SecType = BINARY_FILE_TYPE_PEI_DEPEX
+ elif self.DepexType == 'DXE_DEPEX_EXP':
+ ModuleType = SUP_MODULE_DXE_DRIVER
+ SecType = BINARY_FILE_TYPE_DXE_DEPEX
+ elif self.DepexType == 'SMM_DEPEX_EXP':
+ ModuleType = SUP_MODULE_DXE_SMM_DRIVER
+ SecType = BINARY_FILE_TYPE_SMM_DEPEX
+ else:
+ EdkLogger.error("GenFds", FORMAT_INVALID,
+ "Depex type %s is not valid for module %s" % (self.DepexType, ModuleName))
+
+ InputFile = os.path.join (OutputPath, ModuleName + SUP_MODULE_SEC + SecNum + '.depex')
+ InputFile = os.path.normpath(InputFile)
+ Depex = DependencyExpression(self.Expression, ModuleType)
+ Depex.Generate(InputFile)
+
+ OutputFile = os.path.join (OutputPath, ModuleName + SUP_MODULE_SEC + SecNum + '.dpx')
+ OutputFile = os.path.normpath(OutputFile)
+
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [InputFile], Section.Section.SectionType.get (SecType), IsMakefile=IsMakefile)
+ return [OutputFile], self.Alignment
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py
new file mode 100755
index 00000000..0e0c0dff
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py
@@ -0,0 +1,318 @@
+## @file
+# process rule section generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from struct import *
+from . import Section
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+import subprocess
+from .Ffs import SectionSuffix
+import Common.LongFilePathOs as os
+from CommonDataClass.FdfClass import EfiSectionClassObject
+from Common import EdkLogger
+from Common.BuildToolError import *
+from Common.Misc import PeImageClass
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.LongFilePathSupport import CopyLongFilePath
+from Common.DataType import *
+
+## generate rule section
+#
+#
+class EfiSection (EfiSectionClassObject):
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ EfiSectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # Generate rule section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name list, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = None, IsMakefile = False) :
+
+ if self.FileName is not None and self.FileName.startswith('PCD('):
+ self.FileName = GenFdsGlobalVariable.GetPcdValue(self.FileName)
+ """Prepare the parameter of GenSection"""
+ if FfsInf is not None :
+ InfFileName = FfsInf.InfFileName
+ SectionType = FfsInf.__ExtendMacro__(self.SectionType)
+ Filename = FfsInf.__ExtendMacro__(self.FileName)
+ BuildNum = FfsInf.__ExtendMacro__(self.BuildNum)
+ StringData = FfsInf.__ExtendMacro__(self.StringData)
+ ModuleNameStr = FfsInf.__ExtendMacro__('$(MODULE_NAME)')
+ NoStrip = True
+ if FfsInf.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE) and SectionType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):
+ if FfsInf.KeepReloc is not None:
+ NoStrip = FfsInf.KeepReloc
+ elif FfsInf.KeepRelocFromRule is not None:
+ NoStrip = FfsInf.KeepRelocFromRule
+ elif self.KeepReloc is not None:
+ NoStrip = self.KeepReloc
+ elif FfsInf.ShadowFromInfFile is not None:
+ NoStrip = FfsInf.ShadowFromInfFile
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s apply rule for None!" %ModuleName)
+
+ """If the file name was pointed out, add it in FileList"""
+ FileList = []
+ if Dict is None:
+ Dict = {}
+ if Filename is not None:
+ Filename = GenFdsGlobalVariable.MacroExtend(Filename, Dict)
+ # check if the path is absolute or relative
+ if os.path.isabs(Filename):
+ Filename = os.path.normpath(Filename)
+ else:
+ Filename = os.path.normpath(os.path.join(FfsInf.EfiOutputPath, Filename))
+
+ if not self.Optional:
+ FileList.append(Filename)
+ elif os.path.exists(Filename):
+ FileList.append(Filename)
+ elif IsMakefile:
+ SuffixMap = FfsInf.GetFinalTargetSuffixMap()
+ if '.depex' in SuffixMap:
+ FileList.append(Filename)
+ else:
+ FileList, IsSect = Section.Section.GetFileList(FfsInf, self.FileType, self.FileExtension, Dict, IsMakefile=IsMakefile, SectionType=SectionType)
+ if IsSect :
+ return FileList, self.Alignment
+
+ Index = 0
+ Align = self.Alignment
+
+ """ If Section type is 'VERSION'"""
+ OutputFileList = []
+ if SectionType == 'VERSION':
+
+ InfOverrideVerString = False
+ if FfsInf.Version is not None:
+ #StringData = FfsInf.Version
+ BuildNum = FfsInf.Version
+ InfOverrideVerString = True
+
+ if InfOverrideVerString:
+ #VerTuple = ('-n', '"' + StringData + '"')
+ if BuildNum is not None and BuildNum != '':
+ BuildNumTuple = ('-j', BuildNum)
+ else:
+ BuildNumTuple = tuple()
+
+ Num = SecNum
+ OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',
+ #Ui=StringData,
+ Ver=BuildNum,
+ IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ elif FileList != []:
+ for File in FileList:
+ Index = Index + 1
+ Num = '%s.%d' %(SecNum, Index)
+ OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))
+ f = open(File, 'r')
+ VerString = f.read()
+ f.close()
+ BuildNum = VerString
+ if BuildNum is not None and BuildNum != '':
+ BuildNumTuple = ('-j', BuildNum)
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',
+ #Ui=VerString,
+ Ver=BuildNum,
+ IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ else:
+ BuildNum = StringData
+ if BuildNum is not None and BuildNum != '':
+ BuildNumTuple = ('-j', BuildNum)
+ else:
+ BuildNumTuple = tuple()
+ BuildNumString = ' ' + ' '.join(BuildNumTuple)
+
+ #if VerString == '' and
+ if BuildNumString == '':
+ if self.Optional == True :
+ GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")
+ return [], None
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss Version Section value" %InfFileName)
+ Num = SecNum
+ OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',
+ #Ui=VerString,
+ Ver=BuildNum,
+ IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ #
+ # If Section Type is BINARY_FILE_TYPE_UI
+ #
+ elif SectionType == BINARY_FILE_TYPE_UI:
+
+ InfOverrideUiString = False
+ if FfsInf.Ui is not None:
+ StringData = FfsInf.Ui
+ InfOverrideUiString = True
+
+ if InfOverrideUiString:
+ Num = SecNum
+ if IsMakefile and StringData == ModuleNameStr:
+ StringData = "$(MODULE_NAME)"
+ OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',
+ Ui=StringData, IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ elif FileList != []:
+ for File in FileList:
+ Index = Index + 1
+ Num = '%s.%d' %(SecNum, Index)
+ OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))
+ f = open(File, 'r')
+ UiString = f.read()
+ f.close()
+ if IsMakefile and UiString == ModuleNameStr:
+ UiString = "$(MODULE_NAME)"
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',
+ Ui=UiString, IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+ else:
+ if StringData is not None and len(StringData) > 0:
+ UiTuple = ('-n', '"' + StringData + '"')
+ else:
+ UiTuple = tuple()
+
+ if self.Optional == True :
+ GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")
+ return '', None
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss UI Section value" %InfFileName)
+
+ Num = SecNum
+ if IsMakefile and StringData == ModuleNameStr:
+ StringData = "$(MODULE_NAME)"
+ OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',
+ Ui=StringData, IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ #
+ # If Section Type is BINARY_FILE_TYPE_RAW
+ #
+ elif SectionType == BINARY_FILE_TYPE_RAW:
+ """If File List is empty"""
+ if FileList == []:
+ if self.Optional == True:
+ GenFdsGlobalVariable.VerboseLogger("Optional Section don't exist!")
+ return [], None
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))
+
+ elif len(FileList) > 1:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ "Files suffixed with %s are not allowed to have more than one file in %s[Binaries] section" % (
+ self.FileExtension, InfFileName))
+ else:
+ for File in FileList:
+ File = GenFdsGlobalVariable.MacroExtend(File, Dict)
+ OutputFileList.append(File)
+
+ else:
+ """If File List is empty"""
+ if FileList == [] :
+ if self.Optional == True:
+ GenFdsGlobalVariable.VerboseLogger("Optional Section don't exist!")
+ return [], None
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))
+
+ else:
+ """Convert the File to Section file one by one """
+ for File in FileList:
+ """ Copy Map file to FFS output path """
+ Index = Index + 1
+ Num = '%s.%d' %(SecNum, Index)
+ OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))
+ File = GenFdsGlobalVariable.MacroExtend(File, Dict)
+
+ #Get PE Section alignment when align is set to AUTO
+ if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
+ Align = "0"
+ if File[(len(File)-4):] == '.efi' and FfsInf.InfModule.BaseName == os.path.basename(File)[:-4]:
+ MapFile = File.replace('.efi', '.map')
+ CopyMapFile = os.path.join(OutputPath, ModuleName + '.map')
+ if IsMakefile:
+ if GenFdsGlobalVariable.CopyList == []:
+ GenFdsGlobalVariable.CopyList = [(MapFile, CopyMapFile)]
+ else:
+ GenFdsGlobalVariable.CopyList.append((MapFile, CopyMapFile))
+ else:
+ if os.path.exists(MapFile):
+ if not os.path.exists(CopyMapFile) or \
+ (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)):
+ CopyLongFilePath(MapFile, CopyMapFile)
+
+ if not NoStrip:
+ FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi')
+ if IsMakefile:
+ if GenFdsGlobalVariable.CopyList == []:
+ GenFdsGlobalVariable.CopyList = [(File, FileBeforeStrip)]
+ else:
+ GenFdsGlobalVariable.CopyList.append((File, FileBeforeStrip))
+ else:
+ if not os.path.exists(FileBeforeStrip) or \
+ (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
+ CopyLongFilePath(File, FileBeforeStrip)
+ StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ StrippedFile,
+ [File],
+ Strip=True,
+ IsMakefile = IsMakefile
+ )
+ File = StrippedFile
+
+ """For TE Section call GenFw to generate TE image"""
+
+ if SectionType == BINARY_FILE_TYPE_TE:
+ TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ TeFile,
+ [File],
+ Type='te',
+ IsMakefile = IsMakefile
+ )
+ File = TeFile
+
+ """Call GenSection"""
+ GenFdsGlobalVariable.GenerateSection(OutputFile,
+ [File],
+ Section.Section.SectionType.get (SectionType),
+ IsMakefile=IsMakefile
+ )
+ OutputFileList.append(OutputFile)
+
+ return OutputFileList, Align
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fd.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fd.py
new file mode 100755
index 00000000..097f6244
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fd.py
@@ -0,0 +1,155 @@
+## @file
+# process FD generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Region
+from . import Fv
+import Common.LongFilePathOs as os
+from io import BytesIO
+import sys
+from struct import *
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from CommonDataClass.FdfClass import FDClassObject
+from Common import EdkLogger
+from Common.BuildToolError import *
+from Common.Misc import SaveFileOnChange
+from Common.DataType import BINARY_FILE_TYPE_FV
+
+## generate FD
+#
+#
+class FD(FDClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ FDClassObject.__init__(self)
+
+ ## GenFd() method
+ #
+ # Generate FD
+ #
+ # @retval string Generated FD file name
+ #
+ def GenFd (self, Flag = False):
+ if self.FdUiName.upper() + 'fd' in GenFdsGlobalVariable.ImageBinDict:
+ return GenFdsGlobalVariable.ImageBinDict[self.FdUiName.upper() + 'fd']
+
+ #
+ # Print Information
+ #
+ FdFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.FdUiName + '.fd')
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger("\nFd File Name:%s (%s)" %(self.FdUiName, FdFileName))
+
+ Offset = 0x00
+ for item in self.BlockSizeList:
+ Offset = Offset + item[0] * item[1]
+ if Offset != self.Size:
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'FD %s Size not consistent with block array' % self.FdUiName)
+ GenFdsGlobalVariable.VerboseLogger('Following Fv will be add to Fd !!!')
+ for FvObj in GenFdsGlobalVariable.FdfParser.Profile.FvDict:
+ GenFdsGlobalVariable.VerboseLogger(FvObj)
+
+ HasCapsuleRegion = False
+ for RegionObj in self.RegionList:
+ if RegionObj.RegionType == 'CAPSULE':
+ HasCapsuleRegion = True
+ break
+ if HasCapsuleRegion:
+ TempFdBuffer = BytesIO()
+ PreviousRegionStart = -1
+ PreviousRegionSize = 1
+
+ for RegionObj in self.RegionList :
+ if RegionObj.RegionType == 'CAPSULE':
+ continue
+ if RegionObj.Offset + RegionObj.Size <= PreviousRegionStart:
+ pass
+ elif RegionObj.Offset <= PreviousRegionStart or (RegionObj.Offset >=PreviousRegionStart and RegionObj.Offset < PreviousRegionStart + PreviousRegionSize):
+ pass
+ elif RegionObj.Offset > PreviousRegionStart + PreviousRegionSize:
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger('Padding region starting from offset 0x%X, with size 0x%X' %(PreviousRegionStart + PreviousRegionSize, RegionObj.Offset - (PreviousRegionStart + PreviousRegionSize)))
+ PadRegion = Region.Region()
+ PadRegion.Offset = PreviousRegionStart + PreviousRegionSize
+ PadRegion.Size = RegionObj.Offset - PadRegion.Offset
+ if not Flag:
+ PadRegion.AddToBuffer(TempFdBuffer, self.BaseAddress, self.BlockSizeList, self.ErasePolarity, GenFdsGlobalVariable.ImageBinDict, self.DefineVarDict)
+ PreviousRegionStart = RegionObj.Offset
+ PreviousRegionSize = RegionObj.Size
+ #
+ # Call each region's AddToBuffer function
+ #
+ if PreviousRegionSize > self.Size:
+ pass
+ GenFdsGlobalVariable.VerboseLogger('Call each region\'s AddToBuffer function')
+ RegionObj.AddToBuffer (TempFdBuffer, self.BaseAddress, self.BlockSizeList, self.ErasePolarity, GenFdsGlobalVariable.ImageBinDict, self.DefineVarDict)
+
+ FdBuffer = BytesIO()
+ PreviousRegionStart = -1
+ PreviousRegionSize = 1
+ for RegionObj in self.RegionList :
+ if RegionObj.Offset + RegionObj.Size <= PreviousRegionStart:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ 'Region offset 0x%X in wrong order with Region starting from 0x%X, size 0x%X\nRegions in FDF must have offsets appear in ascending order.'\
+ % (RegionObj.Offset, PreviousRegionStart, PreviousRegionSize))
+ elif RegionObj.Offset <= PreviousRegionStart or (RegionObj.Offset >=PreviousRegionStart and RegionObj.Offset < PreviousRegionStart + PreviousRegionSize):
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ 'Region offset 0x%X overlaps with Region starting from 0x%X, size 0x%X' \
+ % (RegionObj.Offset, PreviousRegionStart, PreviousRegionSize))
+ elif RegionObj.Offset > PreviousRegionStart + PreviousRegionSize:
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger('Padding region starting from offset 0x%X, with size 0x%X' %(PreviousRegionStart + PreviousRegionSize, RegionObj.Offset - (PreviousRegionStart + PreviousRegionSize)))
+ PadRegion = Region.Region()
+ PadRegion.Offset = PreviousRegionStart + PreviousRegionSize
+ PadRegion.Size = RegionObj.Offset - PadRegion.Offset
+ if not Flag:
+ PadRegion.AddToBuffer(FdBuffer, self.BaseAddress, self.BlockSizeList, self.ErasePolarity, GenFdsGlobalVariable.ImageBinDict, self.DefineVarDict)
+ PreviousRegionStart = RegionObj.Offset
+ PreviousRegionSize = RegionObj.Size
+ #
+ # Verify current region fits within allocated FD section Size
+ #
+ if PreviousRegionStart + PreviousRegionSize > self.Size:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ 'FD %s size too small to fit region with offset 0x%X and size 0x%X'
+ % (self.FdUiName, PreviousRegionStart, PreviousRegionSize))
+ #
+ # Call each region's AddToBuffer function
+ #
+ GenFdsGlobalVariable.VerboseLogger('Call each region\'s AddToBuffer function')
+ RegionObj.AddToBuffer (FdBuffer, self.BaseAddress, self.BlockSizeList, self.ErasePolarity, GenFdsGlobalVariable.ImageBinDict, self.DefineVarDict, Flag=Flag)
+ #
+ # Write the buffer contents to Fd file
+ #
+ GenFdsGlobalVariable.VerboseLogger('Write the buffer contents to Fd file')
+ if not Flag:
+ SaveFileOnChange(FdFileName, FdBuffer.getvalue())
+ FdBuffer.close()
+ GenFdsGlobalVariable.ImageBinDict[self.FdUiName.upper() + 'fd'] = FdFileName
+ return FdFileName
+
+ ## generate flash map file
+ #
+ # @param self The object pointer
+ #
+ def GenFlashMap (self):
+ pass
+
+
+
+
+
+
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
new file mode 100755
index 00000000..73ae5b32
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
@@ -0,0 +1,4526 @@
+## @file
+# parse FDF file
+#
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import print_function
+from __future__ import absolute_import
+from re import compile, DOTALL
+from string import hexdigits
+from uuid import UUID
+
+from Common.BuildToolError import *
+from Common import EdkLogger
+from Common.Misc import PathClass, tdict, ProcessDuplicatedInf, GuidStructureStringToGuidString
+from Common.StringUtils import NormPath, ReplaceMacro
+from Common import GlobalData
+from Common.Expression import *
+from Common.DataType import *
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+import Common.LongFilePathOs as os
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.RangeExpression import RangeExpression
+from collections import OrderedDict
+
+from .Fd import FD
+from .Region import Region
+from .Fv import FV
+from .AprioriSection import AprioriSection
+from .FfsInfStatement import FfsInfStatement
+from .FfsFileStatement import FileStatement
+from .VerSection import VerSection
+from .UiSection import UiSection
+from .FvImageSection import FvImageSection
+from .DataSection import DataSection
+from .DepexSection import DepexSection
+from .CompressSection import CompressSection
+from .GuidSection import GuidSection
+from .Capsule import EFI_CERT_TYPE_PKCS7_GUID, EFI_CERT_TYPE_RSA2048_SHA256_GUID, Capsule
+from .CapsuleData import CapsuleFfs, CapsulePayload, CapsuleFv, CapsuleFd, CapsuleAnyFile, CapsuleAfile
+from .RuleComplexFile import RuleComplexFile
+from .RuleSimpleFile import RuleSimpleFile
+from .EfiSection import EfiSection
+from .OptionRom import OPTIONROM
+from .OptRomInfStatement import OptRomInfStatement, OverrideAttribs
+from .OptRomFileStatement import OptRomFileStatement
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+
+T_CHAR_CR = '\r'
+T_CHAR_TAB = '\t'
+T_CHAR_DOUBLE_QUOTE = '\"'
+T_CHAR_SINGLE_QUOTE = '\''
+T_CHAR_BRACE_R = '}'
+
+SEPARATORS = {TAB_EQUAL_SPLIT, TAB_VALUE_SPLIT, TAB_COMMA_SPLIT, '{', T_CHAR_BRACE_R}
+ALIGNMENTS = {"Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",
+ "256K", "512K", "1M", "2M", "4M", "8M", "16M"}
+ALIGNMENT_NOAUTO = ALIGNMENTS - {"Auto"}
+CR_LB_SET = {T_CHAR_CR, TAB_LINE_BREAK}
+
+RegionSizePattern = compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")
+RegionSizeGuidPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*\|\s*(?P<size>\w+\.\w+[\.\w\[\]]*)\s*")
+RegionOffsetPcdPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*$")
+ShortcutPcdPattern = compile("\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")
+BaseAddrValuePattern = compile('^0[xX][0-9a-fA-F]+')
+FileExtensionPattern = compile(r'([a-zA-Z][a-zA-Z0-9]*)')
+TokenFindPattern = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
+AllIncludeFileList = []
+
+# Get the closest parent
+def GetParentAtLine (Line):
+ for Profile in AllIncludeFileList:
+ if Profile.IsLineInFile(Line):
+ return Profile
+ return None
+
+# Check include loop
+def IsValidInclude (File, Line):
+ for Profile in AllIncludeFileList:
+ if Profile.IsLineInFile(Line) and Profile.FileName == File:
+ return False
+
+ return True
+
+def GetRealFileLine (File, Line):
+ InsertedLines = 0
+ for Profile in AllIncludeFileList:
+ if Profile.IsLineInFile(Line):
+ return Profile.GetLineInFile(Line)
+ elif Line >= Profile.InsertStartLineNumber and Profile.Level == 1:
+ InsertedLines += Profile.GetTotalLines()
+
+ return (File, Line - InsertedLines)
+
+## The exception class that used to report error messages when parsing FDF
+#
+# Currently the "ToolName" is set to be "FdfParser".
+#
+class Warning (Exception):
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param Str The message to record
+ # @param File The FDF name
+ # @param Line The Line number that error occurs
+ #
+ def __init__(self, Str, File = None, Line = None):
+ FileLineTuple = GetRealFileLine(File, Line)
+ self.FileName = FileLineTuple[0]
+ self.LineNumber = FileLineTuple[1]
+ self.OriginalLineNumber = Line
+ self.Message = Str
+ self.ToolName = 'FdfParser'
+
+ def __str__(self):
+ return self.Message
+
+ # helper functions to facilitate consistency in warnings
+ # each function is for a different common warning
+ @staticmethod
+ def Expected(Str, File, Line):
+ return Warning("expected {}".format(Str), File, Line)
+ @staticmethod
+ def ExpectedEquals(File, Line):
+ return Warning.Expected("'='", File, Line)
+ @staticmethod
+ def ExpectedCurlyOpen(File, Line):
+ return Warning.Expected("'{'", File, Line)
+ @staticmethod
+ def ExpectedCurlyClose(File, Line):
+ return Warning.Expected("'}'", File, Line)
+ @staticmethod
+ def ExpectedBracketClose(File, Line):
+ return Warning.Expected("']'", File, Line)
+
+## The Include file content class that used to record file data when parsing include file
+#
+# May raise Exception when opening file.
+#
+class IncludeFileProfile:
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param FileName The file that to be parsed
+ #
+ def __init__(self, FileName):
+ self.FileName = FileName
+ self.FileLinesList = []
+ try:
+ with open(FileName, "r") as fsock:
+ self.FileLinesList = fsock.readlines()
+ for index, line in enumerate(self.FileLinesList):
+ if not line.endswith(TAB_LINE_BREAK):
+ self.FileLinesList[index] += TAB_LINE_BREAK
+ except:
+ EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
+
+ self.InsertStartLineNumber = None
+ self.InsertAdjust = 0
+ self.IncludeFileList = []
+ self.Level = 1 # first level include file
+
+ def GetTotalLines(self):
+ TotalLines = self.InsertAdjust + len(self.FileLinesList)
+
+ for Profile in self.IncludeFileList:
+ TotalLines += Profile.GetTotalLines()
+
+ return TotalLines
+
+ def IsLineInFile(self, Line):
+ if Line >= self.InsertStartLineNumber and Line < self.InsertStartLineNumber + self.GetTotalLines():
+ return True
+
+ return False
+
+ def GetLineInFile(self, Line):
+ if not self.IsLineInFile (Line):
+ return (self.FileName, -1)
+
+ InsertedLines = self.InsertStartLineNumber
+
+ for Profile in self.IncludeFileList:
+ if Profile.IsLineInFile(Line):
+ return Profile.GetLineInFile(Line)
+ elif Line >= Profile.InsertStartLineNumber:
+ InsertedLines += Profile.GetTotalLines()
+
+ return (self.FileName, Line - InsertedLines + 1)
+
+## The FDF content class that used to record file data when parsing FDF
+#
+# May raise Exception when opening file.
+#
+class FileProfile:
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param FileName The file that to be parsed
+ #
+ def __init__(self, FileName):
+ self.FileLinesList = []
+ try:
+ with open(FileName, "r") as fsock:
+ self.FileLinesList = fsock.readlines()
+
+ except:
+ EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
+
+ self.FileName = FileName
+ self.PcdDict = OrderedDict()
+ self.PcdLocalDict = OrderedDict()
+ self.InfList = []
+ self.InfDict = {'ArchTBD':[]}
+ # ECC will use this Dict and List information
+ self.PcdFileLineDict = {}
+ self.InfFileLineList = []
+
+ self.FdDict = {}
+ self.FdNameNotSet = False
+ self.FvDict = {}
+ self.CapsuleDict = {}
+ self.RuleDict = {}
+ self.OptRomDict = {}
+ self.FmpPayloadDict = {}
+
+## The syntax parser for FDF
+#
+# PreprocessFile method should be called prior to ParseFile
+# CycleReferenceCheck method can detect cycles in FDF contents
+#
+# GetNext*** procedures mean these procedures will get next token first, then make judgement.
+# Get*** procedures mean these procedures will make judgement on current token only.
+#
+class FdfParser:
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param FileName The file that to be parsed
+ #
+ def __init__(self, FileName):
+ self.Profile = FileProfile(FileName)
+ self.FileName = FileName
+ self.CurrentLineNumber = 1
+ self.CurrentOffsetWithinLine = 0
+ self.CurrentFdName = None
+ self.CurrentFvName = None
+ self._Token = ""
+ self._SkippedChars = ""
+ GlobalData.gFdfParser = self
+
+ # Used to section info
+ self._CurSection = []
+ # Key: [section name, UI name, arch]
+ # Value: {MACRO_NAME: MACRO_VALUE}
+ self._MacroDict = tdict(True, 3)
+ self._PcdDict = OrderedDict()
+
+ self._WipeOffArea = []
+ if GenFdsGlobalVariable.WorkSpaceDir == '':
+ GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")
+
+ ## _SkipWhiteSpace() method
+ #
+ # Skip white spaces from current char.
+ #
+ # @param self The object pointer
+ #
+ def _SkipWhiteSpace(self):
+ while not self._EndOfFile():
+ if self._CurrentChar() in {TAB_PRINTCHAR_NUL, T_CHAR_CR, TAB_LINE_BREAK, TAB_SPACE_SPLIT, T_CHAR_TAB}:
+ self._SkippedChars += str(self._CurrentChar())
+ self._GetOneChar()
+ else:
+ return
+ return
+
+ ## _EndOfFile() method
+ #
+ # Judge current buffer pos is at file end
+ #
+ # @param self The object pointer
+ # @retval True Current File buffer position is at file end
+ # @retval False Current File buffer position is NOT at file end
+ #
+ def _EndOfFile(self):
+ NumberOfLines = len(self.Profile.FileLinesList)
+ SizeOfLastLine = len(self.Profile.FileLinesList[-1])
+ if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:
+ return True
+ if self.CurrentLineNumber > NumberOfLines:
+ return True
+ return False
+
+ ## _EndOfLine() method
+ #
+ # Judge current buffer pos is at line end
+ #
+ # @param self The object pointer
+ # @retval True Current File buffer position is at line end
+ # @retval False Current File buffer position is NOT at line end
+ #
+ def _EndOfLine(self):
+ if self.CurrentLineNumber > len(self.Profile.FileLinesList):
+ return True
+ SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
+ if self.CurrentOffsetWithinLine >= SizeOfCurrentLine:
+ return True
+ return False
+
+ ## Rewind() method
+ #
+ # Reset file data buffer to the initial state
+ #
+ # @param self The object pointer
+ # @param DestLine Optional new destination line number.
+ # @param DestOffset Optional new destination offset.
+ #
+ def Rewind(self, DestLine = 1, DestOffset = 0):
+ self.CurrentLineNumber = DestLine
+ self.CurrentOffsetWithinLine = DestOffset
+
+ ## _UndoOneChar() method
+ #
+ # Go back one char in the file buffer
+ #
+ # @param self The object pointer
+ # @retval True Successfully go back one char
+ # @retval False Not able to go back one char as file beginning reached
+ #
+ def _UndoOneChar(self):
+ if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:
+ return False
+ elif self.CurrentOffsetWithinLine == 0:
+ self.CurrentLineNumber -= 1
+ self.CurrentOffsetWithinLine = len(self._CurrentLine()) - 1
+ else:
+ self.CurrentOffsetWithinLine -= 1
+ return True
+
+ ## _GetOneChar() method
+ #
+ # Move forward one char in the file buffer
+ #
+ # @param self The object pointer
+ #
+ def _GetOneChar(self):
+ if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
+ self.CurrentLineNumber += 1
+ self.CurrentOffsetWithinLine = 0
+ else:
+ self.CurrentOffsetWithinLine += 1
+
+ ## _CurrentChar() method
+ #
+ # Get the char pointed to by the file buffer pointer
+ #
+ # @param self The object pointer
+ # @retval Char Current char
+ #
+ def _CurrentChar(self):
+ return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]
+
+ ## _NextChar() method
+ #
+ # Get the one char pass the char pointed to by the file buffer pointer
+ #
+ # @param self The object pointer
+ # @retval Char Next char
+ #
+ def _NextChar(self):
+ if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
+ return self.Profile.FileLinesList[self.CurrentLineNumber][0]
+ return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]
+
+ ## _SetCurrentCharValue() method
+ #
+ # Modify the value of current char
+ #
+ # @param self The object pointer
+ # @param Value The new value of current char
+ #
+ def _SetCurrentCharValue(self, Value):
+ self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value
+
+ ## _CurrentLine() method
+ #
+ # Get the list that contains current line contents
+ #
+ # @param self The object pointer
+ # @retval List current line contents
+ #
+ def _CurrentLine(self):
+ return self.Profile.FileLinesList[self.CurrentLineNumber - 1]
+
+ def _StringToList(self):
+ self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]
+ if not self.Profile.FileLinesList:
+ EdkLogger.error('FdfParser', FILE_READ_FAILURE, 'The file is empty!', File=self.FileName)
+ self.Profile.FileLinesList[-1].append(' ')
+
+ def _ReplaceFragment(self, StartPos, EndPos, Value = ' '):
+ if StartPos[0] == EndPos[0]:
+ Offset = StartPos[1]
+ while Offset <= EndPos[1]:
+ self.Profile.FileLinesList[StartPos[0]][Offset] = Value
+ Offset += 1
+ return
+
+ Offset = StartPos[1]
+ while self.Profile.FileLinesList[StartPos[0]][Offset] not in CR_LB_SET:
+ self.Profile.FileLinesList[StartPos[0]][Offset] = Value
+ Offset += 1
+
+ Line = StartPos[0]
+ while Line < EndPos[0]:
+ Offset = 0
+ while self.Profile.FileLinesList[Line][Offset] not in CR_LB_SET:
+ self.Profile.FileLinesList[Line][Offset] = Value
+ Offset += 1
+ Line += 1
+
+ Offset = 0
+ while Offset <= EndPos[1]:
+ self.Profile.FileLinesList[EndPos[0]][Offset] = Value
+ Offset += 1
+
+ def _SetMacroValue(self, Macro, Value):
+ if not self._CurSection:
+ return
+
+ MacroDict = {}
+ if not self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]:
+ self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]] = MacroDict
+ else:
+ MacroDict = self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]
+ MacroDict[Macro] = Value
+
+ def _GetMacroValue(self, Macro):
+ # Highest priority
+ if Macro in GlobalData.gCommandLineDefines:
+ return GlobalData.gCommandLineDefines[Macro]
+ if Macro in GlobalData.gGlobalDefines:
+ return GlobalData.gGlobalDefines[Macro]
+
+ if self._CurSection:
+ MacroDict = self._MacroDict[
+ self._CurSection[0],
+ self._CurSection[1],
+ self._CurSection[2]
+ ]
+ if MacroDict and Macro in MacroDict:
+ return MacroDict[Macro]
+
+ # Lowest priority
+ if Macro in GlobalData.gPlatformDefines:
+ return GlobalData.gPlatformDefines[Macro]
+ return None
+
+ def _SectionHeaderParser(self, Section):
+ # [Defines]
+ # [FD.UiName]: use dummy instead if UI name is optional
+ # [FV.UiName]
+ # [Capsule.UiName]
+ # [Rule]: don't take rule section into account, macro is not allowed in this section
+ # [OptionRom.DriverName]
+ self._CurSection = []
+ Section = Section.strip()[1:-1].upper().replace(' ', '').strip(TAB_SPLIT)
+ ItemList = Section.split(TAB_SPLIT)
+ Item = ItemList[0]
+ if Item == '' or Item == 'RULE':
+ return
+
+ if Item == TAB_COMMON_DEFINES.upper():
+ self._CurSection = [TAB_COMMON, TAB_COMMON, TAB_COMMON]
+ elif len(ItemList) > 1:
+ self._CurSection = [ItemList[0], ItemList[1], TAB_COMMON]
+ elif len(ItemList) > 0:
+ self._CurSection = [ItemList[0], 'DUMMY', TAB_COMMON]
+
+ ## PreprocessFile() method
+ #
+ # Preprocess file contents, replace comments with spaces.
+ # In the end, rewind the file buffer pointer to the beginning
+ # BUGBUG: No !include statement processing contained in this procedure
+ # !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1]
+ #
+ # @param self The object pointer
+ #
+ def PreprocessFile(self):
+ self.Rewind()
+ InComment = False
+ DoubleSlashComment = False
+ HashComment = False
+ # HashComment in quoted string " " is ignored.
+ InString = False
+
+ while not self._EndOfFile():
+
+ if self._CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment:
+ InString = not InString
+ # meet new line, then no longer in a comment for // and '#'
+ if self._CurrentChar() == TAB_LINE_BREAK:
+ self.CurrentLineNumber += 1
+ self.CurrentOffsetWithinLine = 0
+ if InComment and DoubleSlashComment:
+ InComment = False
+ DoubleSlashComment = False
+ if InComment and HashComment:
+ InComment = False
+ HashComment = False
+ # check for */ comment end
+ elif InComment and not DoubleSlashComment and not HashComment and self._CurrentChar() == TAB_STAR and self._NextChar() == TAB_BACK_SLASH:
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ InComment = False
+ # set comments to spaces
+ elif InComment:
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ # check for // comment
+ elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_BACK_SLASH and not self._EndOfLine():
+ InComment = True
+ DoubleSlashComment = True
+ # check for '#' comment
+ elif self._CurrentChar() == TAB_COMMENT_SPLIT and not self._EndOfLine() and not InString:
+ InComment = True
+ HashComment = True
+ # check for /* comment start
+ elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_STAR:
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ InComment = True
+ else:
+ self._GetOneChar()
+
+ # restore from ListOfList to ListOfString
+ self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
+ self.Rewind()
+
+ ## PreprocessIncludeFile() method
+ #
+ # Preprocess file contents, replace !include statements with file contents.
+ # In the end, rewind the file buffer pointer to the beginning
+ #
+ # @param self The object pointer
+ #
+ def PreprocessIncludeFile(self):
+ # nested include support
+ Processed = False
+ MacroDict = {}
+ while self._GetNextToken():
+
+ if self._Token == TAB_DEFINE:
+ if not self._GetNextToken():
+ raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)
+ Macro = self._Token
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ Value = self._GetExpression()
+ MacroDict[Macro] = Value
+
+ elif self._Token == TAB_INCLUDE:
+ Processed = True
+ IncludeLine = self.CurrentLineNumber
+ IncludeOffset = self.CurrentOffsetWithinLine - len(TAB_INCLUDE)
+ if not self._GetNextToken():
+ raise Warning.Expected("include file name", self.FileName, self.CurrentLineNumber)
+ IncFileName = self._Token
+ PreIndex = 0
+ StartPos = IncFileName.find('$(', PreIndex)
+ EndPos = IncFileName.find(')', StartPos+2)
+ while StartPos != -1 and EndPos != -1:
+ Macro = IncFileName[StartPos+2: EndPos]
+ MacroVal = self._GetMacroValue(Macro)
+ if not MacroVal:
+ if Macro in MacroDict:
+ MacroVal = MacroDict[Macro]
+ if MacroVal is not None:
+ IncFileName = IncFileName.replace('$(' + Macro + ')', MacroVal, 1)
+ if MacroVal.find('$(') != -1:
+ PreIndex = StartPos
+ else:
+ PreIndex = StartPos + len(MacroVal)
+ else:
+ raise Warning("The Macro %s is not defined" %Macro, self.FileName, self.CurrentLineNumber)
+ StartPos = IncFileName.find('$(', PreIndex)
+ EndPos = IncFileName.find(')', StartPos+2)
+
+ IncludedFile = NormPath(IncFileName)
+ #
+ # First search the include file under the same directory as FDF file
+ #
+ IncludedFile1 = PathClass(IncludedFile, os.path.dirname(self.FileName))
+ ErrorCode = IncludedFile1.Validate()[0]
+ if ErrorCode != 0:
+ #
+ # Then search the include file under the same directory as DSC file
+ #
+ PlatformDir = ''
+ if GenFdsGlobalVariable.ActivePlatform:
+ PlatformDir = GenFdsGlobalVariable.ActivePlatform.Dir
+ elif GlobalData.gActivePlatform:
+ PlatformDir = GlobalData.gActivePlatform.MetaFile.Dir
+ IncludedFile1 = PathClass(IncludedFile, PlatformDir)
+ ErrorCode = IncludedFile1.Validate()[0]
+ if ErrorCode != 0:
+ #
+ # Also search file under the WORKSPACE directory
+ #
+ IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
+ ErrorCode = IncludedFile1.Validate()[0]
+ if ErrorCode != 0:
+ raise Warning("The include file does not exist under below directories: \n%s\n%s\n%s\n"%(os.path.dirname(self.FileName), PlatformDir, GlobalData.gWorkspace),
+ self.FileName, self.CurrentLineNumber)
+
+ if not IsValidInclude (IncludedFile1.Path, self.CurrentLineNumber):
+ raise Warning("The include file {0} is causing a include loop.\n".format (IncludedFile1.Path), self.FileName, self.CurrentLineNumber)
+
+ IncFileProfile = IncludeFileProfile(IncludedFile1.Path)
+
+ CurrentLine = self.CurrentLineNumber
+ CurrentOffset = self.CurrentOffsetWithinLine
+ # list index of the insertion, note that line number is 'CurrentLine + 1'
+ InsertAtLine = CurrentLine
+ ParentProfile = GetParentAtLine (CurrentLine)
+ if ParentProfile is not None:
+ ParentProfile.IncludeFileList.insert(0, IncFileProfile)
+ IncFileProfile.Level = ParentProfile.Level + 1
+ IncFileProfile.InsertStartLineNumber = InsertAtLine + 1
+ # deal with remaining portions after "!include filename", if exists.
+ if self._GetNextToken():
+ if self.CurrentLineNumber == CurrentLine:
+ RemainingLine = self._CurrentLine()[CurrentOffset:]
+ self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine)
+ IncFileProfile.InsertAdjust += 1
+ self.CurrentLineNumber += 1
+ self.CurrentOffsetWithinLine = 0
+
+ for Line in IncFileProfile.FileLinesList:
+ self.Profile.FileLinesList.insert(InsertAtLine, Line)
+ self.CurrentLineNumber += 1
+ InsertAtLine += 1
+
+ # reversely sorted to better determine error in file
+ AllIncludeFileList.insert(0, IncFileProfile)
+
+ # comment out the processed include file statement
+ TempList = list(self.Profile.FileLinesList[IncludeLine - 1])
+ TempList.insert(IncludeOffset, TAB_COMMENT_SPLIT)
+ self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList)
+ if Processed: # Nested and back-to-back support
+ self.Rewind(DestLine = IncFileProfile.InsertStartLineNumber - 1)
+ Processed = False
+ # Preprocess done.
+ self.Rewind()
+
+ @staticmethod
+ def _GetIfListCurrentItemStat(IfList):
+ if len(IfList) == 0:
+ return True
+
+ for Item in IfList:
+ if Item[1] == False:
+ return False
+
+ return True
+
+ ## PreprocessConditionalStatement() method
+ #
+ # Preprocess conditional statement.
+ # In the end, rewind the file buffer pointer to the beginning
+ #
+ # @param self The object pointer
+ #
+ def PreprocessConditionalStatement(self):
+ # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined]
+ IfList = []
+ RegionLayoutLine = 0
+ ReplacedLine = -1
+ while self._GetNextToken():
+ # Determine section name and the location dependent macro
+ if self._GetIfListCurrentItemStat(IfList):
+ if self._Token.startswith(TAB_SECTION_START):
+ Header = self._Token
+ if not self._Token.endswith(TAB_SECTION_END):
+ self._SkipToToken(TAB_SECTION_END)
+ Header += self._SkippedChars
+ if Header.find('$(') != -1:
+ raise Warning("macro cannot be used in section header", self.FileName, self.CurrentLineNumber)
+ self._SectionHeaderParser(Header)
+ continue
+ # Replace macros except in RULE section or out of section
+ elif self._CurSection and ReplacedLine != self.CurrentLineNumber:
+ ReplacedLine = self.CurrentLineNumber
+ self._UndoToken()
+ CurLine = self.Profile.FileLinesList[ReplacedLine - 1]
+ PreIndex = 0
+ StartPos = CurLine.find('$(', PreIndex)
+ EndPos = CurLine.find(')', StartPos+2)
+ while StartPos != -1 and EndPos != -1 and self._Token not in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF, TAB_ELSE_IF}:
+ MacroName = CurLine[StartPos+2: EndPos]
+ MacroValue = self._GetMacroValue(MacroName)
+ if MacroValue is not None:
+ CurLine = CurLine.replace('$(' + MacroName + ')', MacroValue, 1)
+ if MacroValue.find('$(') != -1:
+ PreIndex = StartPos
+ else:
+ PreIndex = StartPos + len(MacroValue)
+ else:
+ PreIndex = EndPos + 1
+ StartPos = CurLine.find('$(', PreIndex)
+ EndPos = CurLine.find(')', StartPos+2)
+ self.Profile.FileLinesList[ReplacedLine - 1] = CurLine
+ continue
+
+ if self._Token == TAB_DEFINE:
+ if self._GetIfListCurrentItemStat(IfList):
+ if not self._CurSection:
+ raise Warning("macro cannot be defined in Rule section or out of section", self.FileName, self.CurrentLineNumber)
+ DefineLine = self.CurrentLineNumber - 1
+ DefineOffset = self.CurrentOffsetWithinLine - len(TAB_DEFINE)
+ if not self._GetNextToken():
+ raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)
+ Macro = self._Token
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ Value = self._GetExpression()
+ self._SetMacroValue(Macro, Value)
+ self._WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token == 'SET':
+ if not self._GetIfListCurrentItemStat(IfList):
+ continue
+ SetLine = self.CurrentLineNumber - 1
+ SetOffset = self.CurrentOffsetWithinLine - len('SET')
+ PcdPair = self._GetNextPcdSettings()
+ PcdName = "%s.%s" % (PcdPair[1], PcdPair[0])
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ Value = self._GetExpression()
+ Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
+
+ self._PcdDict[PcdName] = Value
+
+ self.Profile.PcdDict[PcdPair] = Value
+ self.SetPcdLocalation(PcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
+
+ self._WipeOffArea.append(((SetLine, SetOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF}:
+ IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))
+ IfList.append([IfStartPos, None, None])
+
+ CondLabel = self._Token
+ Expression = self._GetExpression()
+
+ if CondLabel == TAB_IF:
+ ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
+ else:
+ ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'in')
+ if CondLabel == TAB_IF_N_DEF:
+ ConditionSatisfied = not ConditionSatisfied
+
+ BranchDetermined = ConditionSatisfied
+ IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]
+ if ConditionSatisfied:
+ self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token in {TAB_ELSE_IF, TAB_ELSE}:
+ ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))
+ if len(IfList) <= 0:
+ raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
+
+ if IfList[-1][1]:
+ IfList[-1] = [ElseStartPos, False, True]
+ self._WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ else:
+ self._WipeOffArea.append((IfList[-1][0], ElseStartPos))
+ IfList[-1] = [ElseStartPos, True, IfList[-1][2]]
+ if self._Token == TAB_ELSE_IF:
+ Expression = self._GetExpression()
+ ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
+ IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]]
+
+ if IfList[-1][1]:
+ if IfList[-1][2]:
+ IfList[-1][1] = False
+ else:
+ IfList[-1][2] = True
+ self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token == '!endif':
+ if len(IfList) <= 0:
+ raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
+ if IfList[-1][1]:
+ self._WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ else:
+ self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+
+ IfList.pop()
+ elif not IfList: # Don't use PCDs inside conditional directive
+ if self.CurrentLineNumber <= RegionLayoutLine:
+ # Don't try the same line twice
+ continue
+ SetPcd = ShortcutPcdPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
+ if SetPcd:
+ self._PcdDict[SetPcd.group('name')] = SetPcd.group('value')
+ RegionLayoutLine = self.CurrentLineNumber
+ continue
+ RegionSize = RegionSizePattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
+ if not RegionSize:
+ RegionLayoutLine = self.CurrentLineNumber
+ continue
+ RegionSizeGuid = RegionSizeGuidPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber])
+ if not RegionSizeGuid:
+ RegionLayoutLine = self.CurrentLineNumber + 1
+ continue
+ self._PcdDict[RegionSizeGuid.group('base')] = RegionSize.group('base')
+ self._PcdDict[RegionSizeGuid.group('size')] = RegionSize.group('size')
+ RegionLayoutLine = self.CurrentLineNumber + 1
+
+ if IfList:
+ raise Warning("Missing !endif", self.FileName, self.CurrentLineNumber)
+ self.Rewind()
+
+ def _CollectMacroPcd(self):
+ MacroDict = {}
+
+ # PCD macro
+ MacroDict.update(GlobalData.gPlatformPcds)
+ MacroDict.update(self._PcdDict)
+
+ # Lowest priority
+ MacroDict.update(GlobalData.gPlatformDefines)
+
+ if self._CurSection:
+ # Defines macro
+ ScopeMacro = self._MacroDict[TAB_COMMON, TAB_COMMON, TAB_COMMON]
+ if ScopeMacro:
+ MacroDict.update(ScopeMacro)
+
+ # Section macro
+ ScopeMacro = self._MacroDict[
+ self._CurSection[0],
+ self._CurSection[1],
+ self._CurSection[2]
+ ]
+ if ScopeMacro:
+ MacroDict.update(ScopeMacro)
+
+ MacroDict.update(GlobalData.gGlobalDefines)
+ MacroDict.update(GlobalData.gCommandLineDefines)
+ for Item in GlobalData.BuildOptionPcd:
+ if isinstance(Item, tuple):
+ continue
+ PcdName, TmpValue = Item.split(TAB_EQUAL_SPLIT)
+ TmpValue = BuildOptionValue(TmpValue, {})
+ MacroDict[PcdName.strip()] = TmpValue
+ # Highest priority
+
+ return MacroDict
+
+ def _EvaluateConditional(self, Expression, Line, Op = None, Value = None):
+ MacroPcdDict = self._CollectMacroPcd()
+ if Op == 'eval':
+ try:
+ if Value:
+ return ValueExpression(Expression, MacroPcdDict)(True)
+ else:
+ return ValueExpression(Expression, MacroPcdDict)()
+ except WrnExpression as Excpt:
+ #
+ # Catch expression evaluation warning here. We need to report
+ # the precise number of line and return the evaluation result
+ #
+ EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
+ File=self.FileName, ExtraData=self._CurrentLine(),
+ Line=Line)
+ return Excpt.result
+ except Exception as Excpt:
+ if hasattr(Excpt, 'Pcd'):
+ if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
+ Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
+ raise Warning("Cannot use this PCD (%s) in an expression as"
+ " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
+ " of the DSC file (%s), and it is currently defined in this section:"
+ " %s, line #: %d." % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE'], Info[0], Info[1]),
+ self.FileName, Line)
+ else:
+ raise Warning("PCD (%s) is not defined in DSC file (%s)" % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE']),
+ self.FileName, Line)
+ else:
+ raise Warning(str(Excpt), self.FileName, Line)
+ else:
+ if Expression.startswith('$(') and Expression[-1] == ')':
+ Expression = Expression[2:-1]
+ return Expression in MacroPcdDict
+
+ ## _IsToken() method
+ #
+ # Check whether input string is found from current char position along
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @param String The string to search
+ # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
+ # @retval True Successfully find string, file buffer pointer moved forward
+ # @retval False Not able to find string, file buffer pointer not changed
+ #
+ def _IsToken(self, String, IgnoreCase = False):
+ self._SkipWhiteSpace()
+
+ # Only consider the same line, no multi-line token allowed
+ StartPos = self.CurrentOffsetWithinLine
+ index = -1
+ if IgnoreCase:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())
+ else:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)
+ if index == 0:
+ self.CurrentOffsetWithinLine += len(String)
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+ return False
+
+ ## _IsKeyword() method
+ #
+ # Check whether input keyword is found from current char position along, whole word only!
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @param Keyword The string to search
+ # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
+ # @retval True Successfully find string, file buffer pointer moved forward
+ # @retval False Not able to find string, file buffer pointer not changed
+ #
+ def _IsKeyword(self, KeyWord, IgnoreCase = False):
+ self._SkipWhiteSpace()
+
+ # Only consider the same line, no multi-line token allowed
+ StartPos = self.CurrentOffsetWithinLine
+ index = -1
+ if IgnoreCase:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(KeyWord.upper())
+ else:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(KeyWord)
+ if index == 0:
+ followingChar = self._CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)]
+ if not str(followingChar).isspace() and followingChar not in SEPARATORS:
+ return False
+ self.CurrentOffsetWithinLine += len(KeyWord)
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+ return False
+
+ def _GetExpression(self):
+ Line = self.Profile.FileLinesList[self.CurrentLineNumber - 1]
+ Index = len(Line) - 1
+ while Line[Index] in CR_LB_SET:
+ Index -= 1
+ ExpressionString = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:Index+1]
+ self.CurrentOffsetWithinLine += len(ExpressionString)
+ ExpressionString = ExpressionString.strip()
+ return ExpressionString
+
+ ## _GetNextWord() method
+ #
+ # Get next C name from file lines
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a C name string, file buffer pointer moved forward
+ # @retval False Not able to find a C name string, file buffer pointer not changed
+ #
+ def _GetNextWord(self):
+ self._SkipWhiteSpace()
+ if self._EndOfFile():
+ return False
+
+ TempChar = self._CurrentChar()
+ StartPos = self.CurrentOffsetWithinLine
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_':
+ self._GetOneChar()
+ while not self._EndOfLine():
+ TempChar = self._CurrentChar()
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
+ or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-':
+ self._GetOneChar()
+
+ else:
+ break
+
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+
+ return False
+
+ def _GetNextPcdWord(self):
+ self._SkipWhiteSpace()
+ if self._EndOfFile():
+ return False
+
+ TempChar = self._CurrentChar()
+ StartPos = self.CurrentOffsetWithinLine
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:
+ self._GetOneChar()
+ while not self._EndOfLine():
+ TempChar = self._CurrentChar()
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
+ or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:
+ self._GetOneChar()
+
+ else:
+ break
+
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+
+ return False
+
+ ## _GetNextToken() method
+ #
+ # Get next token unit before a separator
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a token unit, file buffer pointer moved forward
+ # @retval False Not able to find a token unit, file buffer pointer not changed
+ #
+ def _GetNextToken(self):
+ # Skip leading spaces, if exist.
+ self._SkipWhiteSpace()
+ if self._EndOfFile():
+ return False
+ # Record the token start position, the position of the first non-space char.
+ StartPos = self.CurrentOffsetWithinLine
+ StartLine = self.CurrentLineNumber
+ while StartLine == self.CurrentLineNumber:
+ TempChar = self._CurrentChar()
+ # Try to find the end char that is not a space and not in separator tuple.
+ # That is, when we got a space or any char in the tuple, we got the end of token.
+ if not str(TempChar).isspace() and TempChar not in SEPARATORS:
+ self._GetOneChar()
+ # if we happen to meet a separator as the first char, we must proceed to get it.
+ # That is, we get a token that is a separator char. normally it is the boundary of other tokens.
+ elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:
+ self._GetOneChar()
+ break
+ else:
+ break
+# else:
+# return False
+
+ EndPos = self.CurrentOffsetWithinLine
+ if self.CurrentLineNumber != StartLine:
+ EndPos = len(self.Profile.FileLinesList[StartLine-1])
+ self._Token = self.Profile.FileLinesList[StartLine-1][StartPos: EndPos]
+ if self._Token.lower() in {TAB_IF, TAB_END_IF, TAB_ELSE_IF, TAB_ELSE, TAB_IF_DEF, TAB_IF_N_DEF, TAB_ERROR, TAB_INCLUDE}:
+ self._Token = self._Token.lower()
+ if StartPos != self.CurrentOffsetWithinLine:
+ return True
+ else:
+ return False
+
+ ## _GetNextGuid() method
+ #
+ # Get next token unit before a separator
+ # If found, the GUID string is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a registry format GUID, file buffer pointer moved forward
+ # @retval False Not able to find a registry format GUID, file buffer pointer not changed
+ #
+ def _GetNextGuid(self):
+ if not self._GetNextToken():
+ return False
+ if GlobalData.gGuidPattern.match(self._Token) is not None:
+ return True
+ elif self._Token in GlobalData.gGuidDict:
+ return True
+ else:
+ self._UndoToken()
+ return False
+
+ @staticmethod
+ def _Verify(Name, Value, Scope):
+ # value verification only applies to numeric values.
+ if Scope not in TAB_PCD_NUMERIC_TYPES:
+ return
+
+ ValueNumber = 0
+ try:
+ ValueNumber = int(Value, 0)
+ except:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)
+ if ValueNumber < 0:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)
+ if ValueNumber > MAX_VAL_TYPE[Scope]:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
+ return True
+
+ ## _UndoToken() method
+ #
+ # Go back one token unit in file buffer
+ #
+ # @param self The object pointer
+ #
+ def _UndoToken(self):
+ self._UndoOneChar()
+ while self._CurrentChar().isspace():
+ if not self._UndoOneChar():
+ self._GetOneChar()
+ return
+
+
+ StartPos = self.CurrentOffsetWithinLine
+ CurrentLine = self.CurrentLineNumber
+ while CurrentLine == self.CurrentLineNumber:
+
+ TempChar = self._CurrentChar()
+ # Try to find the end char that is not a space and not in separator tuple.
+ # That is, when we got a space or any char in the tuple, we got the end of token.
+ if not str(TempChar).isspace() and not TempChar in SEPARATORS:
+ if not self._UndoOneChar():
+ return
+ # if we happen to meet a separator as the first char, we must proceed to get it.
+ # That is, we get a token that is a separator char. normally it is the boundary of other tokens.
+ elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:
+ return
+ else:
+ break
+
+ self._GetOneChar()
+
+ ## _GetNextHexNumber() method
+ #
+ # Get next HEX data before a separator
+ # If found, the HEX data is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a HEX data, file buffer pointer moved forward
+ # @retval False Not able to find a HEX data, file buffer pointer not changed
+ #
+ def _GetNextHexNumber(self):
+ if not self._GetNextToken():
+ return False
+ if GlobalData.gHexPatternAll.match(self._Token):
+ return True
+ else:
+ self._UndoToken()
+ return False
+
+ ## _GetNextDecimalNumber() method
+ #
+ # Get next decimal data before a separator
+ # If found, the decimal data is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a decimal data, file buffer pointer moved forward
+ # @retval False Not able to find a decimal data, file buffer pointer not changed
+ #
+ def _GetNextDecimalNumber(self):
+ if not self._GetNextToken():
+ return False
+ if self._Token.isdigit():
+ return True
+ else:
+ self._UndoToken()
+ return False
+
+ def _GetNextPcdSettings(self):
+ if not self._GetNextWord():
+ raise Warning.Expected("<PcdTokenSpaceCName>", self.FileName, self.CurrentLineNumber)
+ pcdTokenSpaceCName = self._Token
+
+ if not self._IsToken(TAB_SPLIT):
+ raise Warning.Expected(".", self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextWord():
+ raise Warning.Expected("<PcdCName>", self.FileName, self.CurrentLineNumber)
+ pcdCName = self._Token
+
+ Fields = []
+ while self._IsToken(TAB_SPLIT):
+ if not self._GetNextPcdWord():
+ raise Warning.Expected("Pcd Fields", self.FileName, self.CurrentLineNumber)
+ Fields.append(self._Token)
+
+ return (pcdCName, pcdTokenSpaceCName,TAB_SPLIT.join(Fields))
+
+ ## _GetStringData() method
+ #
+ # Get string contents quoted in ""
+ # If found, the decimal data is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a string data, file buffer pointer moved forward
+ # @retval False Not able to find a string data, file buffer pointer not changed
+ #
+ def _GetStringData(self):
+ QuoteToUse = None
+ if self._Token.startswith(T_CHAR_DOUBLE_QUOTE) or self._Token.startswith("L\""):
+ QuoteToUse = T_CHAR_DOUBLE_QUOTE
+ elif self._Token.startswith(T_CHAR_SINGLE_QUOTE) or self._Token.startswith("L\'"):
+ QuoteToUse = T_CHAR_SINGLE_QUOTE
+ else:
+ return False
+
+ self._UndoToken()
+ self._SkipToToken(QuoteToUse)
+ currentLineNumber = self.CurrentLineNumber
+
+ if not self._SkipToToken(QuoteToUse):
+ raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)
+ if currentLineNumber != self.CurrentLineNumber:
+ raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)
+ self._Token = self._SkippedChars.rstrip(QuoteToUse)
+ return True
+
+ ## _SkipToToken() method
+ #
+ # Search forward in file buffer for the string
+ # The skipped chars are put into self._SkippedChars
+ #
+ # @param self The object pointer
+ # @param String The string to search
+ # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
+ # @retval True Successfully find the string, file buffer pointer moved forward
+ # @retval False Not able to find the string, file buffer pointer not changed
+ #
+ def _SkipToToken(self, String, IgnoreCase = False):
+ StartPos = self.GetFileBufferPos()
+
+ self._SkippedChars = ""
+ while not self._EndOfFile():
+ index = -1
+ if IgnoreCase:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())
+ else:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)
+ if index == 0:
+ self.CurrentOffsetWithinLine += len(String)
+ self._SkippedChars += String
+ return True
+ self._SkippedChars += str(self._CurrentChar())
+ self._GetOneChar()
+
+ self.SetFileBufferPos(StartPos)
+ self._SkippedChars = ""
+ return False
+
+ ## GetFileBufferPos() method
+ #
+ # Return the tuple of current line and offset within the line
+ #
+ # @param self The object pointer
+ # @retval Tuple Line number and offset pair
+ #
+ def GetFileBufferPos(self):
+ return (self.CurrentLineNumber, self.CurrentOffsetWithinLine)
+
+ ## SetFileBufferPos() method
+ #
+ # Restore the file buffer position
+ #
+ # @param self The object pointer
+ # @param Pos The new file buffer position
+ #
+ def SetFileBufferPos(self, Pos):
+ (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos
+
+ ## Preprocess() method
+ #
+ # Preprocess comment, conditional directive, include directive, replace macro.
+ # Exception will be raised if syntax error found
+ #
+ # @param self The object pointer
+ #
+ def Preprocess(self):
+ self._StringToList()
+ self.PreprocessFile()
+ self.PreprocessIncludeFile()
+ self._StringToList()
+ self.PreprocessFile()
+ self.PreprocessConditionalStatement()
+ self._StringToList()
+ for Pos in self._WipeOffArea:
+ self._ReplaceFragment(Pos[0], Pos[1])
+ self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
+
+ while self._GetDefines():
+ pass
+
+ ## ParseFile() method
+ #
+ # Parse the file profile buffer to extract fd, fv ... information
+ # Exception will be raised if syntax error found
+ #
+ # @param self The object pointer
+ #
+ def ParseFile(self):
+ try:
+ self.Preprocess()
+ self._GetError()
+ #
+ # Keep processing sections of the FDF until no new sections or a syntax error is found
+ #
+ while self._GetFd() or self._GetFv() or self._GetFmp() or self._GetCapsule() or self._GetRule() or self._GetOptionRom():
+ pass
+
+ except Warning as X:
+ self._UndoToken()
+ #'\n\tGot Token: \"%s\" from File %s\n' % (self._Token, FileLineTuple[0]) + \
+ # At this point, the closest parent would be the included file itself
+ Profile = GetParentAtLine(X.OriginalLineNumber)
+ if Profile is not None:
+ X.Message += ' near line %d, column %d: %s' \
+ % (X.LineNumber, 0, Profile.FileLinesList[X.LineNumber-1])
+ else:
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ X.Message += ' near line %d, column %d: %s' \
+ % (FileLineTuple[1], self.CurrentOffsetWithinLine + 1, self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:].rstrip(TAB_LINE_BREAK).rstrip(T_CHAR_CR))
+ raise
+
+ ## SectionParser() method
+ #
+ # Parse the file section info
+ # Exception will be raised if syntax error found
+ #
+ # @param self The object pointer
+ # @param section The section string
+
+ def SectionParser(self, section):
+ S = section.upper()
+ if not S.startswith("[DEFINES") and not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \
+ and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM.") and not S.startswith('[FMPPAYLOAD.'):
+ raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [Rule.], [OptionRom.], [FMPPAYLOAD.])", self.FileName, self.CurrentLineNumber)
+
+ ## _GetDefines() method
+ #
+ # Get Defines section contents and store its data into AllMacrosList
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a Defines
+ # @retval False Not able to find a Defines
+ #
+ def _GetDefines(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[DEFINES"):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[DEFINES", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[DEFINES", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ while self._GetNextWord():
+ # handle the SET statement
+ if self._Token == 'SET':
+ self._UndoToken()
+ self._GetSetStatement(None)
+ continue
+
+ Macro = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken() or self._Token.startswith(TAB_SECTION_START):
+ raise Warning.Expected("MACRO value", self.FileName, self.CurrentLineNumber)
+ Value = self._Token
+
+ return False
+
+ ##_GetError() method
+ def _GetError(self):
+ #save the Current information
+ CurrentLine = self.CurrentLineNumber
+ CurrentOffset = self.CurrentOffsetWithinLine
+ while self._GetNextToken():
+ if self._Token == TAB_ERROR:
+ EdkLogger.error('FdfParser', ERROR_STATEMENT, self._CurrentLine().replace(TAB_ERROR, '', 1), File=self.FileName, Line=self.CurrentLineNumber)
+ self.CurrentLineNumber = CurrentLine
+ self.CurrentOffsetWithinLine = CurrentOffset
+
+ ## _GetFd() method
+ #
+ # Get FD section contents and store its data into FD dictionary of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a FD
+ # @retval False Not able to find a FD
+ #
+ def _GetFd(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[FD."):
+ if not S.startswith("[FV.") and not S.startswith('[FMPPAYLOAD.') and not S.startswith("[CAPSULE.") \
+ and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
+ raise Warning("Unknown section", self.FileName, self.CurrentLineNumber)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[FD.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[FD.]", self.FileName, self.CurrentLineNumber)
+
+ FdName = self._GetUiName()
+ if FdName == "":
+ if len (self.Profile.FdDict) == 0:
+ FdName = GenFdsGlobalVariable.PlatformName
+ if FdName == "" and GlobalData.gActivePlatform:
+ FdName = GlobalData.gActivePlatform.PlatformName
+ self.Profile.FdNameNotSet = True
+ else:
+ raise Warning.Expected("FdName in [FD.] section", self.FileName, self.CurrentLineNumber)
+ self.CurrentFdName = FdName.upper()
+
+ if self.CurrentFdName in self.Profile.FdDict:
+ raise Warning("Unexpected the same FD name", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ FdObj = FD()
+ FdObj.FdUiName = self.CurrentFdName
+ self.Profile.FdDict[self.CurrentFdName] = FdObj
+
+ if len (self.Profile.FdDict) > 1 and self.Profile.FdNameNotSet:
+ raise Warning.Expected("all FDs have their name", self.FileName, self.CurrentLineNumber)
+
+ Status = self._GetCreateFile(FdObj)
+ if not Status:
+ raise Warning("FD name error", self.FileName, self.CurrentLineNumber)
+
+ while self._GetTokenStatements(FdObj):
+ pass
+ for Attr in ("BaseAddress", "Size", "ErasePolarity"):
+ if getattr(FdObj, Attr) is None:
+ self._GetNextToken()
+ raise Warning("Keyword %s missing" % Attr, self.FileName, self.CurrentLineNumber)
+
+ if not FdObj.BlockSizeList:
+ FdObj.BlockSizeList.append((1, FdObj.Size, None))
+
+ self._GetDefineStatements(FdObj)
+
+ self._GetSetStatements(FdObj)
+
+ if not self._GetRegionLayout(FdObj):
+ raise Warning.Expected("region layout", self.FileName, self.CurrentLineNumber)
+
+ while self._GetRegionLayout(FdObj):
+ pass
+ return True
+
+ ## _GetUiName() method
+ #
+ # Return the UI name of a section
+ #
+ # @param self The object pointer
+ # @retval FdName UI name
+ #
+ def _GetUiName(self):
+ Name = ""
+ if self._GetNextWord():
+ Name = self._Token
+
+ return Name
+
+ ## _GetCreateFile() method
+ #
+ # Return the output file name of object
+ #
+ # @param self The object pointer
+ # @param Obj object whose data will be stored in file
+ # @retval FdName UI name
+ #
+ def _GetCreateFile(self, Obj):
+ if self._IsKeyword("CREATE_FILE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)
+
+ FileName = self._Token
+ Obj.CreateFileName = FileName
+
+ return True
+
+ def SetPcdLocalation(self,pcdpair):
+ self.Profile.PcdLocalDict[pcdpair] = (self.Profile.FileName,self.CurrentLineNumber)
+
+ ## _GetTokenStatements() method
+ #
+ # Get token statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom token statement is got
+ #
+ def _GetTokenStatements(self, Obj):
+ if self._IsKeyword("BaseAddress"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex base address", self.FileName, self.CurrentLineNumber)
+
+ Obj.BaseAddress = self._Token
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ pcdPair = self._GetNextPcdSettings()
+ Obj.BaseAddressPcd = pcdPair
+ self.Profile.PcdDict[pcdPair] = Obj.BaseAddress
+ self.SetPcdLocalation(pcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
+ return True
+
+ if self._IsKeyword("Size"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex size", self.FileName, self.CurrentLineNumber)
+
+ Size = self._Token
+ if self._IsToken(TAB_VALUE_SPLIT):
+ pcdPair = self._GetNextPcdSettings()
+ Obj.SizePcd = pcdPair
+ self.Profile.PcdDict[pcdPair] = Size
+ self.SetPcdLocalation(pcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
+ Obj.Size = int(Size, 0)
+ return True
+
+ if self._IsKeyword("ErasePolarity"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Erase Polarity", self.FileName, self.CurrentLineNumber)
+
+ if not self._Token in {"1", "0"}:
+ raise Warning.Expected("1 or 0 Erase Polarity", self.FileName, self.CurrentLineNumber)
+
+ Obj.ErasePolarity = self._Token
+ return True
+
+ return self._GetBlockStatements(Obj)
+
+ ## _GetAddressStatements() method
+ #
+ # Get address statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom address statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetAddressStatements(self, Obj):
+ if self._IsKeyword("BsBaseAddress"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
+ raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)
+
+ BsAddress = int(self._Token, 0)
+ Obj.BsBaseAddress = BsAddress
+
+ if self._IsKeyword("RtBaseAddress"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
+ raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)
+
+ RtAddress = int(self._Token, 0)
+ Obj.RtBaseAddress = RtAddress
+
+ ## _GetBlockStatements() method
+ #
+ # Get block statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom block statement is got
+ #
+ def _GetBlockStatements(self, Obj):
+ IsBlock = False
+ while self._GetBlockStatement(Obj):
+ IsBlock = True
+
+ Item = Obj.BlockSizeList[-1]
+ if Item[0] is None or Item[1] is None:
+ raise Warning.Expected("block statement", self.FileName, self.CurrentLineNumber)
+ return IsBlock
+
+ ## _GetBlockStatement() method
+ #
+ # Get block statement
+ #
+ # @param self The object pointer
+ # @param Obj for whom block statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetBlockStatement(self, Obj):
+ if not self._IsKeyword("BlockSize"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():
+ raise Warning.Expected("Hex or Integer block size", self.FileName, self.CurrentLineNumber)
+
+ BlockSize = self._Token
+ BlockSizePcd = None
+ if self._IsToken(TAB_VALUE_SPLIT):
+ PcdPair = self._GetNextPcdSettings()
+ BlockSizePcd = PcdPair
+ self.Profile.PcdDict[PcdPair] = BlockSize
+ self.SetPcdLocalation(PcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
+ BlockSize = int(BlockSize, 0)
+
+ BlockNumber = None
+ if self._IsKeyword("NumBlocks"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
+ raise Warning.Expected("block numbers", self.FileName, self.CurrentLineNumber)
+
+ BlockNumber = int(self._Token, 0)
+
+ Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd))
+ return True
+
+ ## _GetDefineStatements() method
+ #
+ # Get define statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom define statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetDefineStatements(self, Obj):
+ while self._GetDefineStatement(Obj):
+ pass
+
+ ## _GetDefineStatement() method
+ #
+ # Get define statement
+ #
+ # @param self The object pointer
+ # @param Obj for whom define statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetDefineStatement(self, Obj):
+ if self._IsKeyword(TAB_DEFINE):
+ self._GetNextToken()
+ Macro = self._Token
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
+
+ Value = self._Token
+ Macro = '$(' + Macro + ')'
+ Obj.DefineVarDict[Macro] = Value
+ return True
+
+ return False
+
+ ## _GetSetStatements() method
+ #
+ # Get set statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom set statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetSetStatements(self, Obj):
+ while self._GetSetStatement(Obj):
+ pass
+
+ ## _GetSetStatement() method
+ #
+ # Get set statement
+ #
+ # @param self The object pointer
+ # @param Obj for whom set statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetSetStatement(self, Obj):
+ if self._IsKeyword("SET"):
+ PcdPair = self._GetNextPcdSettings()
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ Value = self._GetExpression()
+ Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
+
+ if Obj:
+ Obj.SetVarDict[PcdPair] = Value
+ self.Profile.PcdDict[PcdPair] = Value
+ self.SetPcdLocalation(PcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
+ return True
+
+ return False
+
+ ## _CalcRegionExpr(self)
+ #
+ # Calculate expression for offset or size of a region
+ #
+ # @return: None if invalid expression
+ # Calculated number if successfully
+ #
+ def _CalcRegionExpr(self):
+ StartPos = self.GetFileBufferPos()
+ Expr = ''
+ PairCount = 0
+ while not self._EndOfFile():
+ CurCh = self._CurrentChar()
+ if CurCh == '(':
+ PairCount += 1
+ elif CurCh == ')':
+ PairCount -= 1
+
+ if CurCh in '|\r\n' and PairCount == 0:
+ break
+ Expr += CurCh
+ self._GetOneChar()
+ try:
+ return int(
+ ValueExpression(Expr,
+ self._CollectMacroPcd()
+ )(True), 0)
+ except Exception:
+ self.SetFileBufferPos(StartPos)
+ return None
+
+ ## _GetRegionLayout() method
+ #
+ # Get region layout for FD
+ #
+ # @param self The object pointer
+ # @param theFd for whom region is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetRegionLayout(self, theFd):
+ Offset = self._CalcRegionExpr()
+ if Offset is None:
+ return False
+
+ RegionObj = Region()
+ RegionObj.Offset = Offset
+ theFd.RegionList.append(RegionObj)
+
+ if not self._IsToken(TAB_VALUE_SPLIT):
+ raise Warning.Expected("'|'", self.FileName, self.CurrentLineNumber)
+
+ Size = self._CalcRegionExpr()
+ if Size is None:
+ raise Warning.Expected("Region Size", self.FileName, self.CurrentLineNumber)
+ RegionObj.Size = Size
+
+ if not self._GetNextWord():
+ return True
+
+ if not self._Token in {"SET", BINARY_FILE_TYPE_FV, "FILE", "DATA", "CAPSULE", "INF"}:
+ #
+ # If next token is a word which is not a valid FV type, it might be part of [PcdOffset[|PcdSize]]
+ # Or it might be next region's offset described by an expression which starts with a PCD.
+ # PcdOffset[|PcdSize] or OffsetPcdExpression|Size
+ #
+ self._UndoToken()
+ IsRegionPcd = (RegionSizeGuidPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]) or
+ RegionOffsetPcdPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]))
+ if IsRegionPcd:
+ RegionObj.PcdOffset = self._GetNextPcdSettings()
+ self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + int(theFd.BaseAddress, 0))
+ self.SetPcdLocalation(RegionObj.PcdOffset)
+ self._PcdDict['%s.%s' % (RegionObj.PcdOffset[1], RegionObj.PcdOffset[0])] = "0x%x" % RegionObj.Offset
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple
+ if self._IsToken(TAB_VALUE_SPLIT):
+ RegionObj.PcdSize = self._GetNextPcdSettings()
+ self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size
+ self.SetPcdLocalation(RegionObj.PcdSize)
+ self._PcdDict['%s.%s' % (RegionObj.PcdSize[1], RegionObj.PcdSize[0])] = "0x%x" % RegionObj.Size
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple
+
+ if not self._GetNextWord():
+ return True
+
+ if self._Token == "SET":
+ self._UndoToken()
+ self._GetSetStatements(RegionObj)
+ if not self._GetNextWord():
+ return True
+
+ elif self._Token == BINARY_FILE_TYPE_FV:
+ self._UndoToken()
+ self._GetRegionFvType(RegionObj)
+
+ elif self._Token == "CAPSULE":
+ self._UndoToken()
+ self._GetRegionCapType(RegionObj)
+
+ elif self._Token == "FILE":
+ self._UndoToken()
+ self._GetRegionFileType(RegionObj)
+
+ elif self._Token == "INF":
+ self._UndoToken()
+ RegionObj.RegionType = "INF"
+ while self._IsKeyword("INF"):
+ self._UndoToken()
+ ffsInf = self._ParseInfStatement()
+ if not ffsInf:
+ break
+ RegionObj.RegionDataList.append(ffsInf)
+
+ elif self._Token == "DATA":
+ self._UndoToken()
+ self._GetRegionDataType(RegionObj)
+ else:
+ self._UndoToken()
+ if self._GetRegionLayout(theFd):
+ return True
+ raise Warning("A valid region type was not found. "
+ "Valid types are [SET, FV, CAPSULE, FILE, DATA, INF]. This error occurred",
+ self.FileName, self.CurrentLineNumber)
+
+ return True
+
+ ## _GetRegionFvType() method
+ #
+ # Get region fv data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionFvType(self, RegionObj):
+ if not self._IsKeyword(BINARY_FILE_TYPE_FV):
+ raise Warning.Expected("'FV'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionType = BINARY_FILE_TYPE_FV
+ RegionObj.RegionDataList.append((self._Token).upper())
+
+ while self._IsKeyword(BINARY_FILE_TYPE_FV):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionDataList.append((self._Token).upper())
+
+ ## _GetRegionCapType() method
+ #
+ # Get region capsule data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionCapType(self, RegionObj):
+ if not self._IsKeyword("CAPSULE"):
+ raise Warning.Expected("'CAPSULE'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionType = "CAPSULE"
+ RegionObj.RegionDataList.append(self._Token)
+
+ while self._IsKeyword("CAPSULE"):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionDataList.append(self._Token)
+
+ ## _GetRegionFileType() method
+ #
+ # Get region file data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionFileType(self, RegionObj):
+ if not self._IsKeyword("FILE"):
+ raise Warning.Expected("'FILE'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionType = "FILE"
+ RegionObj.RegionDataList.append(self._Token)
+
+ while self._IsKeyword("FILE"):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FILE name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionDataList.append(self._Token)
+
+ ## _GetRegionDataType() method
+ #
+ # Get region array data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionDataType(self, RegionObj):
+ if not self._IsKeyword("DATA"):
+ raise Warning.Expected("Region Data type", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
+
+ if len(self._Token) > 18:
+ raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
+
+ # convert hex string value to byte hex string array
+ AllString = self._Token
+ AllStrLen = len (AllString)
+ DataString = ""
+ while AllStrLen > 4:
+ DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT
+ AllStrLen = AllStrLen - 2
+ DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT
+
+ # byte value array
+ if len (self._Token) <= 4:
+ while self._IsToken(TAB_COMMA_SPLIT):
+ if not self._GetNextHexNumber():
+ raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+ DataString += self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ DataString = DataString.rstrip(TAB_COMMA_SPLIT)
+ RegionObj.RegionType = "DATA"
+ RegionObj.RegionDataList.append(DataString)
+
+ while self._IsKeyword("DATA"):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
+
+ if len(self._Token) > 18:
+ raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
+
+ # convert hex string value to byte hex string array
+ AllString = self._Token
+ AllStrLen = len (AllString)
+ DataString = ""
+ while AllStrLen > 4:
+ DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT
+ AllStrLen = AllStrLen - 2
+ DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT
+
+ # byte value array
+ if len (self._Token) <= 4:
+ while self._IsToken(TAB_COMMA_SPLIT):
+ if not self._GetNextHexNumber():
+ raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+ DataString += self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ DataString = DataString.rstrip(TAB_COMMA_SPLIT)
+ RegionObj.RegionDataList.append(DataString)
+
+ ## _GetFv() method
+ #
+ # Get FV section contents and store its data into FV dictionary of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a FV
+ # @retval False Not able to find a FV
+ #
+ def _GetFv(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[FV."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[FV.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning("Unknown Keyword '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ FvName = self._GetUiName()
+ self.CurrentFvName = FvName.upper()
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ FvObj = FV(Name=self.CurrentFvName)
+ self.Profile.FvDict[self.CurrentFvName] = FvObj
+
+ Status = self._GetCreateFile(FvObj)
+ if not Status:
+ raise Warning("FV name error", self.FileName, self.CurrentLineNumber)
+
+ self._GetDefineStatements(FvObj)
+
+ self._GetAddressStatements(FvObj)
+
+ while True:
+ self._GetSetStatements(FvObj)
+
+ if not (self._GetBlockStatement(FvObj) or self._GetFvBaseAddress(FvObj) or
+ self._GetFvForceRebase(FvObj) or self._GetFvAlignment(FvObj) or
+ self._GetFvAttributes(FvObj) or self._GetFvNameGuid(FvObj) or
+ self._GetFvExtEntryStatement(FvObj) or self._GetFvNameString(FvObj)):
+ break
+
+ if FvObj.FvNameString == 'TRUE' and not FvObj.FvNameGuid:
+ raise Warning("FvNameString found but FvNameGuid was not found", self.FileName, self.CurrentLineNumber)
+
+ self._GetAprioriSection(FvObj)
+ self._GetAprioriSection(FvObj)
+
+ while True:
+ isInf = self._GetInfStatement(FvObj)
+ isFile = self._GetFileStatement(FvObj)
+ if not isInf and not isFile:
+ break
+
+ return True
+
+ ## _GetFvAlignment() method
+ #
+ # Get alignment for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom alignment is got
+ # @retval True Successfully find a alignment statement
+ # @retval False Not able to find a alignment statement
+ #
+ def _GetFvAlignment(self, Obj):
+ if not self._IsKeyword("FvAlignment"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in {"1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \
+ "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \
+ "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \
+ "1G", "2G"}:
+ raise Warning("Unknown alignment value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ Obj.FvAlignment = self._Token
+ return True
+
+ ## _GetFvBaseAddress() method
+ #
+ # Get BaseAddress for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom FvBaseAddress is got
+ # @retval True Successfully find a FvBaseAddress statement
+ # @retval False Not able to find a FvBaseAddress statement
+ #
+ def _GetFvBaseAddress(self, Obj):
+ if not self._IsKeyword("FvBaseAddress"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV base address value", self.FileName, self.CurrentLineNumber)
+
+ if not BaseAddrValuePattern.match(self._Token.upper()):
+ raise Warning("Unknown FV base address value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ Obj.FvBaseAddress = self._Token
+ return True
+
+ ## _GetFvForceRebase() method
+ #
+ # Get FvForceRebase for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom FvForceRebase is got
+ # @retval True Successfully find a FvForceRebase statement
+ # @retval False Not able to find a FvForceRebase statement
+ #
+ def _GetFvForceRebase(self, Obj):
+ if not self._IsKeyword("FvForceRebase"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FvForceRebase value", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in {"TRUE", "FALSE", "0", "0X0", "0X00", "1", "0X1", "0X01"}:
+ raise Warning("Unknown FvForceRebase value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() in {"TRUE", "1", "0X1", "0X01"}:
+ Obj.FvForceRebase = True
+ elif self._Token.upper() in {"FALSE", "0", "0X0", "0X00"}:
+ Obj.FvForceRebase = False
+ else:
+ Obj.FvForceRebase = None
+
+ return True
+
+
+ ## _GetFvAttributes() method
+ #
+ # Get attributes for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom attribute is got
+ # @retval None
+ #
+ def _GetFvAttributes(self, FvObj):
+ IsWordToken = False
+ while self._GetNextWord():
+ IsWordToken = True
+ name = self._Token
+ if name not in {"ERASE_POLARITY", "MEMORY_MAPPED", \
+ "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \
+ "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \
+ "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \
+ "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \
+ "WRITE_POLICY_RELIABLE", "WEAK_ALIGNMENT", "FvUsedSizeEnable"}:
+ self._UndoToken()
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken() or self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:
+ raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvAttributeDict[name] = self._Token
+
+ return IsWordToken
+
+ ## _GetFvNameGuid() method
+ #
+ # Get FV GUID for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom GUID is got
+ # @retval None
+ #
+ def _GetFvNameGuid(self, FvObj):
+ if not self._IsKeyword("FvNameGuid"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+
+ FvObj.FvNameGuid = self._Token
+
+ return True
+
+ def _GetFvNameString(self, FvObj):
+ if not self._IsKeyword("FvNameString"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken() or self._Token.upper() not in {'TRUE', 'FALSE'}:
+ raise Warning.Expected("TRUE or FALSE for FvNameString", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvNameString = self._Token
+
+ return True
+
+ def _GetFvExtEntryStatement(self, FvObj):
+ if not (self._IsKeyword("FV_EXT_ENTRY") or self._IsKeyword("FV_EXT_ENTRY_TYPE")):
+ return False
+
+ if not self._IsKeyword ("TYPE"):
+ raise Warning.Expected("'TYPE'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():
+ raise Warning.Expected("Hex FV extension entry type value At Line ", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvExtEntryTypeValue.append(self._Token)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsKeyword("FILE") and not self._IsKeyword("DATA"):
+ raise Warning.Expected("'FILE' or 'DATA'", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvExtEntryType.append(self._Token)
+
+ if self._Token == 'DATA':
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
+
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+
+ DataString = self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ while self._IsToken(TAB_COMMA_SPLIT):
+ if not self._GetNextHexNumber():
+ raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+ DataString += self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ DataString = DataString.rstrip(TAB_COMMA_SPLIT)
+ FvObj.FvExtEntryData.append(DataString)
+
+ if self._Token == 'FILE':
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV Extension Entry file path At Line ", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvExtEntryData.append(self._Token)
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ return True
+
+ ## _GetAprioriSection() method
+ #
+ # Get token statements
+ #
+ # @param self The object pointer
+ # @param FvObj for whom apriori is got
+ # @retval True Successfully find apriori statement
+ # @retval False Not able to find apriori statement
+ #
+ def _GetAprioriSection(self, FvObj):
+ if not self._IsKeyword("APRIORI"):
+ return False
+
+ if not self._IsKeyword("PEI") and not self._IsKeyword("DXE"):
+ raise Warning.Expected("Apriori file type", self.FileName, self.CurrentLineNumber)
+ AprType = self._Token
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ AprSectionObj = AprioriSection()
+ AprSectionObj.AprioriType = AprType
+
+ self._GetDefineStatements(AprSectionObj)
+
+ while True:
+ IsInf = self._GetInfStatement(AprSectionObj)
+ IsFile = self._GetFileStatement(AprSectionObj)
+ if not IsInf and not IsFile:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ FvObj.AprioriSectionList.append(AprSectionObj)
+ return True
+
+ def _ParseInfStatement(self):
+ if not self._IsKeyword("INF"):
+ return None
+
+ ffsInf = FfsInfStatement()
+ self._GetInfOptions(ffsInf)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("INF file path", self.FileName, self.CurrentLineNumber)
+ ffsInf.InfFileName = self._Token
+ if not ffsInf.InfFileName.endswith('.inf'):
+ raise Warning.Expected(".inf file path", self.FileName, self.CurrentLineNumber)
+
+ ffsInf.CurrentLineNum = self.CurrentLineNumber
+ ffsInf.CurrentLineContent = self._CurrentLine()
+
+ #Replace $(SAPCE) with real space
+ ffsInf.InfFileName = ffsInf.InfFileName.replace('$(SPACE)', ' ')
+
+ if ffsInf.InfFileName.replace(TAB_WORKSPACE, '').find('$') == -1:
+ #do case sensitive check for file path
+ ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ NewFileName = ffsInf.InfFileName
+ if ffsInf.OverrideGuid:
+ NewFileName = ProcessDuplicatedInf(PathClass(ffsInf.InfFileName,GenFdsGlobalVariable.WorkSpaceDir), ffsInf.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir).Path
+
+ if not NewFileName in self.Profile.InfList:
+ self.Profile.InfList.append(NewFileName)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.InfFileLineList.append(FileLineTuple)
+ if ffsInf.UseArch:
+ if ffsInf.UseArch not in self.Profile.InfDict:
+ self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
+ else:
+ self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
+ else:
+ self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ if self._IsKeyword('RELOCS_STRIPPED'):
+ ffsInf.KeepReloc = False
+ elif self._IsKeyword('RELOCS_RETAINED'):
+ ffsInf.KeepReloc = True
+ else:
+ raise Warning("Unknown reloc strip flag '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ return ffsInf
+
+ ## _GetInfStatement() method
+ #
+ # Get INF statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom inf statement is got
+ # @retval True Successfully find inf statement
+ # @retval False Not able to find inf statement
+ #
+ def _GetInfStatement(self, Obj, ForCapsule=False):
+ ffsInf = self._ParseInfStatement()
+ if not ffsInf:
+ return False
+
+ if ForCapsule:
+ myCapsuleFfs = CapsuleFfs()
+ myCapsuleFfs.Ffs = ffsInf
+ Obj.CapsuleDataList.append(myCapsuleFfs)
+ else:
+ Obj.FfsList.append(ffsInf)
+ return True
+
+ ## _GetInfOptions() method
+ #
+ # Get options for INF
+ #
+ # @param self The object pointer
+ # @param FfsInfObj for whom option is got
+ #
+ def _GetInfOptions(self, FfsInfObj):
+ if self._IsKeyword("FILE_GUID"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ FfsInfObj.OverrideGuid = self._Token
+
+ if self._IsKeyword("RuleOverride"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Rule name", self.FileName, self.CurrentLineNumber)
+ FfsInfObj.Rule = self._Token
+
+ if self._IsKeyword("VERSION"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Version", self.FileName, self.CurrentLineNumber)
+
+ if self._GetStringData():
+ FfsInfObj.Version = self._Token
+
+ if self._IsKeyword(BINARY_FILE_TYPE_UI):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("UI name", self.FileName, self.CurrentLineNumber)
+
+ if self._GetStringData():
+ FfsInfObj.Ui = self._Token
+
+ if self._IsKeyword("USE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("ARCH name", self.FileName, self.CurrentLineNumber)
+ FfsInfObj.UseArch = self._Token
+
+
+ if self._GetNextToken():
+ p = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\))')
+ if p.match(self._Token) and p.match(self._Token).span()[1] == len(self._Token):
+ FfsInfObj.KeyStringList.append(self._Token)
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ return
+ else:
+ self._UndoToken()
+ return
+
+ while self._GetNextToken():
+ if not p.match(self._Token):
+ raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
+ FfsInfObj.KeyStringList.append(self._Token)
+
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ break
+
+ ## _GetFileStatement() method
+ #
+ # Get FILE statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom FILE statement is got
+ # @retval True Successfully find FILE statement
+ # @retval False Not able to find FILE statement
+ #
+ def _GetFileStatement(self, Obj, ForCapsule = False):
+ if not self._IsKeyword("FILE"):
+ return False
+
+ if not self._GetNextWord():
+ raise Warning.Expected("FFS type", self.FileName, self.CurrentLineNumber)
+
+ if ForCapsule and self._Token == 'DATA':
+ self._UndoToken()
+ self._UndoToken()
+ return False
+
+ FfsFileObj = FileStatement()
+ FfsFileObj.FvFileType = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextGuid():
+ if not self._GetNextWord():
+ raise Warning.Expected("File GUID", self.FileName, self.CurrentLineNumber)
+ if self._Token == 'PCD':
+ if not self._IsToken("("):
+ raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
+ PcdPair = self._GetNextPcdSettings()
+ if not self._IsToken(")"):
+ raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
+ self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
+
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ FfsFileObj.NameGuid = self._Token
+
+ self._GetFilePart(FfsFileObj)
+
+ if ForCapsule:
+ capsuleFfs = CapsuleFfs()
+ capsuleFfs.Ffs = FfsFileObj
+ Obj.CapsuleDataList.append(capsuleFfs)
+ else:
+ Obj.FfsList.append(FfsFileObj)
+
+ return True
+
+ ## _FileCouldHaveRelocFlag() method
+ #
+ # Check whether reloc strip flag can be set for a file type.
+ #
+ # @param FileType The file type to check with
+ # @retval True This type could have relocation strip flag
+ # @retval False No way to have it
+ #
+ @staticmethod
+ def _FileCouldHaveRelocFlag (FileType):
+ if FileType in {SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE, 'PEI_DXE_COMBO'}:
+ return True
+ else:
+ return False
+
+ ## _SectionCouldHaveRelocFlag() method
+ #
+ # Check whether reloc strip flag can be set for a section type.
+ #
+ # @param SectionType The section type to check with
+ # @retval True This type could have relocation strip flag
+ # @retval False No way to have it
+ #
+ @staticmethod
+ def _SectionCouldHaveRelocFlag (SectionType):
+ if SectionType in {BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32}:
+ return True
+ else:
+ return False
+
+ ## _GetFilePart() method
+ #
+ # Get components for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom component is got
+ #
+ def _GetFilePart(self, FfsFileObj):
+ self._GetFileOpts(FfsFileObj)
+
+ if not self._IsToken("{"):
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._FileCouldHaveRelocFlag(FfsFileObj.FvFileType):
+ if self._Token == 'RELOCS_STRIPPED':
+ FfsFileObj.KeepReloc = False
+ else:
+ FfsFileObj.KeepReloc = True
+ else:
+ raise Warning("File type %s could not have reloc strip flag%d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File name or section data", self.FileName, self.CurrentLineNumber)
+
+ if self._Token == BINARY_FILE_TYPE_FV:
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FvName = self._Token
+
+ elif self._Token == "FD":
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("FD name", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FdName = self._Token
+
+ elif self._Token in {TAB_DEFINE, "APRIORI", "SECTION"}:
+ self._UndoToken()
+ self._GetSectionData(FfsFileObj)
+
+ elif hasattr(FfsFileObj, 'FvFileType') and FfsFileObj.FvFileType == 'RAW':
+ self._UndoToken()
+ self._GetRAWData(FfsFileObj)
+
+ else:
+ FfsFileObj.CurrentLineNum = self.CurrentLineNumber
+ FfsFileObj.CurrentLineContent = self._CurrentLine()
+ FfsFileObj.FileName = self._Token.replace('$(SPACE)', ' ')
+ self._VerifyFile(FfsFileObj.FileName)
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ ## _GetRAWData() method
+ #
+ # Get RAW data for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom section is got
+ #
+ def _GetRAWData(self, FfsFileObj):
+ FfsFileObj.FileName = []
+ FfsFileObj.SubAlignment = []
+ while True:
+ AlignValue = None
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ #For FFS, Auto is default option same to ""
+ if not self._Token == "Auto":
+ AlignValue = self._Token
+ if not self._GetNextToken():
+ raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)
+
+ FileName = self._Token.replace('$(SPACE)', ' ')
+ if FileName == T_CHAR_BRACE_R:
+ self._UndoToken()
+ raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)
+
+ self._VerifyFile(FileName)
+ File = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir)
+ FfsFileObj.FileName.append(File.Path)
+ FfsFileObj.SubAlignment.append(AlignValue)
+
+ if self._IsToken(T_CHAR_BRACE_R):
+ self._UndoToken()
+ break
+
+ if len(FfsFileObj.SubAlignment) == 1:
+ FfsFileObj.SubAlignment = FfsFileObj.SubAlignment[0]
+ if len(FfsFileObj.FileName) == 1:
+ FfsFileObj.FileName = FfsFileObj.FileName[0]
+
+ ## _GetFileOpts() method
+ #
+ # Get options for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom options is got
+ #
+ def _GetFileOpts(self, FfsFileObj):
+ if self._GetNextToken():
+ if TokenFindPattern.match(self._Token):
+ FfsFileObj.KeyStringList.append(self._Token)
+ if self._IsToken(TAB_COMMA_SPLIT):
+ while self._GetNextToken():
+ if not TokenFindPattern.match(self._Token):
+ raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.KeyStringList.append(self._Token)
+
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ break
+
+ else:
+ self._UndoToken()
+
+ if self._IsKeyword("FIXED", True):
+ FfsFileObj.Fixed = True
+
+ if self._IsKeyword("CHECKSUM", True):
+ FfsFileObj.CheckSum = True
+
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ #For FFS, Auto is default option same to ""
+ if not self._Token == "Auto":
+ FfsFileObj.Alignment = self._Token
+
+ ## _GetAlignment() method
+ #
+ # Return the alignment value
+ #
+ # @param self The object pointer
+ # @retval True Successfully find alignment
+ # @retval False Not able to find alignment
+ #
+ def _GetAlignment(self):
+ if self._IsKeyword("Align", True):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)
+ return True
+
+ return False
+
+ ## _GetSectionData() method
+ #
+ # Get section data for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom section is got
+ #
+ def _GetSectionData(self, FfsFileObj):
+ self._GetDefineStatements(FfsFileObj)
+
+ while True:
+ IsLeafSection = self._GetLeafSection(FfsFileObj)
+ IsEncapSection = self._GetEncapsulationSec(FfsFileObj)
+ if not IsLeafSection and not IsEncapSection:
+ break
+
+ ## _GetLeafSection() method
+ #
+ # Get leaf section for Obj
+ #
+ # @param self The object pointer
+ # @param Obj for whom leaf section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetLeafSection(self, Obj):
+ OldPos = self.GetFileBufferPos()
+
+ if not self._IsKeyword("SECTION"):
+ if len(Obj.SectionList) == 0:
+ raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)
+ else:
+ return False
+
+ AlignValue = None
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ AlignValue = self._Token
+
+ BuildNum = None
+ if self._IsKeyword("BUILD_NUM"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Build number value", self.FileName, self.CurrentLineNumber)
+
+ BuildNum = self._Token
+
+ if self._IsKeyword("VERSION"):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("version", self.FileName, self.CurrentLineNumber)
+ VerSectionObj = VerSection()
+ VerSectionObj.Alignment = AlignValue
+ VerSectionObj.BuildNum = BuildNum
+ if self._GetStringData():
+ VerSectionObj.StringData = self._Token
+ else:
+ VerSectionObj.FileName = self._Token
+ Obj.SectionList.append(VerSectionObj)
+
+ elif self._IsKeyword(BINARY_FILE_TYPE_UI):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("UI", self.FileName, self.CurrentLineNumber)
+ UiSectionObj = UiSection()
+ UiSectionObj.Alignment = AlignValue
+ if self._GetStringData():
+ UiSectionObj.StringData = self._Token
+ else:
+ UiSectionObj.FileName = self._Token
+ Obj.SectionList.append(UiSectionObj)
+
+ elif self._IsKeyword("FV_IMAGE"):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name or FV file path", self.FileName, self.CurrentLineNumber)
+
+ FvName = self._Token
+ FvObj = None
+
+ if self._IsToken("{"):
+ FvObj = FV()
+ FvObj.UiFvName = FvName.upper()
+ self._GetDefineStatements(FvObj)
+
+ self._GetBlockStatement(FvObj)
+ self._GetSetStatements(FvObj)
+ self._GetFvAlignment(FvObj)
+ self._GetFvAttributes(FvObj)
+
+ while True:
+ IsInf = self._GetInfStatement(FvObj)
+ IsFile = self._GetFileStatement(FvObj)
+ if not IsInf and not IsFile:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ FvImageSectionObj = FvImageSection()
+ FvImageSectionObj.Alignment = AlignValue
+ if FvObj is not None:
+ FvImageSectionObj.Fv = FvObj
+ FvImageSectionObj.FvName = None
+ else:
+ FvImageSectionObj.FvName = FvName.upper()
+ FvImageSectionObj.FvFileName = FvName
+
+ Obj.SectionList.append(FvImageSectionObj)
+
+ elif self._IsKeyword("PEI_DEPEX_EXP") or self._IsKeyword("DXE_DEPEX_EXP") or self._IsKeyword("SMM_DEPEX_EXP"):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ DepexSectionObj = DepexSection()
+ DepexSectionObj.Alignment = AlignValue
+ DepexSectionObj.DepexType = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+ if not self._SkipToToken(T_CHAR_BRACE_R):
+ raise Warning.Expected("Depex expression ending '}'", self.FileName, self.CurrentLineNumber)
+
+ DepexSectionObj.Expression = self._SkippedChars.rstrip(T_CHAR_BRACE_R)
+ Obj.SectionList.append(DepexSectionObj)
+
+ else:
+ if not self._GetNextWord():
+ raise Warning.Expected("section type", self.FileName, self.CurrentLineNumber)
+
+ # Encapsulation section appear, UndoToken and return
+ if self._Token == "COMPRESS" or self._Token == "GUIDED":
+ self.SetFileBufferPos(OldPos)
+ return False
+
+ if self._Token not in {"COMPAT16", BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,\
+ BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX}:
+ raise Warning("Unknown section type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ if AlignValue == 'Auto'and (not self._Token == BINARY_FILE_TYPE_PE32) and (not self._Token == BINARY_FILE_TYPE_TE):
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+
+ # DataSection
+ DataSectionObj = DataSection()
+ DataSectionObj.Alignment = AlignValue
+ DataSectionObj.SecType = self._Token
+
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._FileCouldHaveRelocFlag(Obj.FvFileType) and self._SectionCouldHaveRelocFlag(DataSectionObj.SecType):
+ if self._Token == 'RELOCS_STRIPPED':
+ DataSectionObj.KeepReloc = False
+ else:
+ DataSectionObj.KeepReloc = True
+ else:
+ raise Warning("File type %s, section type %s, could not have reloc strip flag%d" % (Obj.FvFileType, DataSectionObj.SecType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if self._IsToken(TAB_EQUAL_SPLIT):
+ if not self._GetNextToken():
+ raise Warning.Expected("section file path", self.FileName, self.CurrentLineNumber)
+ DataSectionObj.SectFileName = self._Token
+ self._VerifyFile(DataSectionObj.SectFileName)
+ else:
+ if not self._GetCglSection(DataSectionObj):
+ return False
+
+ Obj.SectionList.append(DataSectionObj)
+
+ return True
+
+ ## _VerifyFile
+ #
+ # Check if file exists or not:
+ # If current phase if GenFds, the file must exist;
+ # If current phase is AutoGen and the file is not in $(OUTPUT_DIRECTORY), the file must exist
+ # @param FileName: File path to be verified.
+ #
+ def _VerifyFile(self, FileName):
+ if FileName.replace(TAB_WORKSPACE, '').find('$') != -1:
+ return
+ if not GlobalData.gAutoGenPhase or not self._GetMacroValue(TAB_DSC_DEFINES_OUTPUT_DIRECTORY) in FileName:
+ ErrorCode, ErrorInfo = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ ## _GetCglSection() method
+ #
+ # Get compressed or GUIDed section for Obj
+ #
+ # @param self The object pointer
+ # @param Obj for whom leaf section is got
+ # @param AlignValue alignment value for complex section
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetCglSection(self, Obj, AlignValue = None):
+
+ if self._IsKeyword("COMPRESS"):
+ type = "PI_STD"
+ if self._IsKeyword("PI_STD") or self._IsKeyword("PI_NONE"):
+ type = self._Token
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ CompressSectionObj = CompressSection()
+ CompressSectionObj.Alignment = AlignValue
+ CompressSectionObj.CompType = type
+ # Recursive sections...
+ while True:
+ IsLeafSection = self._GetLeafSection(CompressSectionObj)
+ IsEncapSection = self._GetEncapsulationSec(CompressSectionObj)
+ if not IsLeafSection and not IsEncapSection:
+ break
+
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ Obj.SectionList.append(CompressSectionObj)
+ return True
+
+ elif self._IsKeyword("GUIDED"):
+ GuidValue = None
+ if self._GetNextGuid():
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ GuidValue = self._Token
+
+ AttribDict = self._GetGuidAttrib()
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+ GuidSectionObj = GuidSection()
+ GuidSectionObj.Alignment = AlignValue
+ GuidSectionObj.NameGuid = GuidValue
+ GuidSectionObj.SectionType = "GUIDED"
+ GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
+ GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
+ GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
+ # Recursive sections...
+ while True:
+ IsLeafSection = self._GetLeafSection(GuidSectionObj)
+ IsEncapSection = self._GetEncapsulationSec(GuidSectionObj)
+ if not IsLeafSection and not IsEncapSection:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ Obj.SectionList.append(GuidSectionObj)
+
+ return True
+
+ return False
+
+ ## _GetGuidAttri() method
+ #
+ # Get attributes for GUID section
+ #
+ # @param self The object pointer
+ # @retval AttribDict Dictionary of key-value pair of section attributes
+ #
+ def _GetGuidAttrib(self):
+ AttribDict = {}
+ AttribDict["PROCESSING_REQUIRED"] = "NONE"
+ AttribDict["AUTH_STATUS_VALID"] = "NONE"
+ AttribDict["EXTRA_HEADER_SIZE"] = -1
+ while self._IsKeyword("PROCESSING_REQUIRED") or self._IsKeyword("AUTH_STATUS_VALID") \
+ or self._IsKeyword("EXTRA_HEADER_SIZE"):
+ AttribKey = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("TRUE(1)/FALSE(0)/Number", self.FileName, self.CurrentLineNumber)
+ elif AttribKey == "EXTRA_HEADER_SIZE":
+ Base = 10
+ if self._Token[0:2].upper() == "0X":
+ Base = 16
+ try:
+ AttribDict[AttribKey] = int(self._Token, Base)
+ continue
+ except ValueError:
+ raise Warning.Expected("Number", self.FileName, self.CurrentLineNumber)
+ elif self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:
+ raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
+ AttribDict[AttribKey] = self._Token
+
+ return AttribDict
+
+ ## _GetEncapsulationSec() method
+ #
+ # Get encapsulation section for FILE
+ #
+ # @param self The object pointer
+ # @param FfsFile for whom section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetEncapsulationSec(self, FfsFileObj):
+ OldPos = self.GetFileBufferPos()
+ if not self._IsKeyword("SECTION"):
+ if len(FfsFileObj.SectionList) == 0:
+ raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)
+ else:
+ return False
+
+ AlignValue = None
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENT_NOAUTO:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ AlignValue = self._Token
+
+ if not self._GetCglSection(FfsFileObj, AlignValue):
+ self.SetFileBufferPos(OldPos)
+ return False
+ else:
+ return True
+
+ def _GetFmp(self):
+ if not self._GetNextToken():
+ return False
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[FMPPAYLOAD."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ self._SkipToToken("[FMPPAYLOAD.", True)
+ FmpUiName = self._GetUiName().upper()
+ if FmpUiName in self.Profile.FmpPayloadDict:
+ raise Warning("Duplicated FMP UI name found: %s" % FmpUiName, self.FileName, self.CurrentLineNumber)
+
+ FmpData = CapsulePayload()
+ FmpData.UiName = FmpUiName
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)
+ FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']
+ while self._Token in FmpKeyList:
+ Name = self._Token
+ FmpKeyList.remove(Name)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if Name == 'IMAGE_TYPE_ID':
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)
+ FmpData.ImageTypeId = self._Token
+ elif Name == 'CERTIFICATE_GUID':
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
+ FmpData.Certificate_Guid = self._Token
+ if UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:
+ raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
+ else:
+ if not self._GetNextToken():
+ raise Warning.Expected("value of %s" % Name, self.FileName, self.CurrentLineNumber)
+ Value = self._Token
+ if Name == 'IMAGE_HEADER_INIT_VERSION':
+ if FdfParser._Verify(Name, Value, 'UINT8'):
+ FmpData.Version = Value
+ elif Name == 'IMAGE_INDEX':
+ if FdfParser._Verify(Name, Value, 'UINT8'):
+ FmpData.ImageIndex = Value
+ elif Name == 'HARDWARE_INSTANCE':
+ if FdfParser._Verify(Name, Value, 'UINT8'):
+ FmpData.HardwareInstance = Value
+ elif Name == 'MONOTONIC_COUNT':
+ if FdfParser._Verify(Name, Value, 'UINT64'):
+ FmpData.MonotonicCount = Value
+ if FmpData.MonotonicCount.upper().startswith('0X'):
+ FmpData.MonotonicCount = int(FmpData.MonotonicCount, 16)
+ else:
+ FmpData.MonotonicCount = int(FmpData.MonotonicCount)
+ if not self._GetNextToken():
+ break
+ else:
+ self._UndoToken()
+
+ if (FmpData.MonotonicCount and not FmpData.Certificate_Guid) or (not FmpData.MonotonicCount and FmpData.Certificate_Guid):
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "CERTIFICATE_GUID and MONOTONIC_COUNT must be work as a pair.")
+
+ # Only the IMAGE_TYPE_ID is required item
+ if FmpKeyList and 'IMAGE_TYPE_ID' in FmpKeyList:
+ raise Warning("'IMAGE_TYPE_ID' in FMP payload section.", self.FileName, self.CurrentLineNumber)
+ # get the Image file and Vendor code file
+ self._GetFMPCapsuleData(FmpData)
+ if not FmpData.ImageFile:
+ raise Warning("Missing image file in FMP payload section.", self.FileName, self.CurrentLineNumber)
+ # check whether more than one Vendor code file
+ if len(FmpData.VendorCodeFile) > 1:
+ raise Warning("Vendor code file max of 1 per FMP payload section.", self.FileName, self.CurrentLineNumber)
+ self.Profile.FmpPayloadDict[FmpUiName] = FmpData
+ return True
+
+ ## _GetCapsule() method
+ #
+ # Get capsule section contents and store its data into capsule list of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a capsule
+ # @retval False Not able to find a capsule
+ #
+ def _GetCapsule(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[CAPSULE."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[CAPSULE.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[Capsule.]", self.FileName, self.CurrentLineNumber)
+
+ CapsuleObj = Capsule()
+
+ CapsuleName = self._GetUiName()
+ if not CapsuleName:
+ raise Warning.Expected("capsule name", self.FileName, self.CurrentLineNumber)
+
+ CapsuleObj.UiCapsuleName = CapsuleName.upper()
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ if self._IsKeyword("CREATE_FILE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)
+
+ CapsuleObj.CreateFile = self._Token
+
+ self._GetCapsuleStatements(CapsuleObj)
+ self.Profile.CapsuleDict[CapsuleObj.UiCapsuleName] = CapsuleObj
+ return True
+
+ ## _GetCapsuleStatements() method
+ #
+ # Get statements for capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom statements are got
+ #
+ def _GetCapsuleStatements(self, Obj):
+ self._GetCapsuleTokens(Obj)
+ self._GetDefineStatements(Obj)
+ self._GetSetStatements(Obj)
+ self._GetCapsuleData(Obj)
+
+ ## _GetCapsuleTokens() method
+ #
+ # Get token statements for capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom token statements are got
+ #
+ def _GetCapsuleTokens(self, Obj):
+ if not self._GetNextToken():
+ return False
+ while self._Token in {"CAPSULE_GUID", "CAPSULE_HEADER_SIZE", "CAPSULE_FLAGS", "OEM_CAPSULE_FLAGS", "CAPSULE_HEADER_INIT_VERSION"}:
+ Name = self._Token.strip()
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
+ if Name == 'CAPSULE_FLAGS':
+ if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:
+ raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
+ Value = self._Token.strip()
+ while self._IsToken(TAB_COMMA_SPLIT):
+ Value += TAB_COMMA_SPLIT
+ if not self._GetNextToken():
+ raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
+ if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:
+ raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
+ Value += self._Token.strip()
+ elif Name == 'OEM_CAPSULE_FLAGS':
+ Value = self._Token.strip()
+ if not Value.upper().startswith('0X'):
+ raise Warning.Expected("hex value starting with 0x", self.FileName, self.CurrentLineNumber)
+ try:
+ Value = int(Value, 0)
+ except ValueError:
+ raise Warning.Expected("hex string failed to convert to value", self.FileName, self.CurrentLineNumber)
+ if not 0x0000 <= Value <= 0xFFFF:
+ raise Warning.Expected("hex value between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)
+ Value = self._Token.strip()
+ else:
+ Value = self._Token.strip()
+ Obj.TokensDict[Name] = Value
+ if not self._GetNextToken():
+ return False
+ self._UndoToken()
+
+ ## _GetCapsuleData() method
+ #
+ # Get capsule data for capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom capsule data are got
+ #
+ def _GetCapsuleData(self, Obj):
+ while True:
+ IsInf = self._GetInfStatement(Obj, True)
+ IsFile = self._GetFileStatement(Obj, True)
+ IsFv = self._GetFvStatement(Obj)
+ IsFd = self._GetFdStatement(Obj)
+ IsAnyFile = self._GetAnyFileStatement(Obj)
+ IsAfile = self._GetAfileStatement(Obj)
+ IsFmp = self._GetFmpStatement(Obj)
+ if not (IsInf or IsFile or IsFv or IsFd or IsAnyFile or IsAfile or IsFmp):
+ break
+
+ ## _GetFMPCapsuleData() method
+ #
+ # Get capsule data for FMP capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom capsule data are got
+ #
+ def _GetFMPCapsuleData(self, Obj):
+ while True:
+ IsFv = self._GetFvStatement(Obj, True)
+ IsFd = self._GetFdStatement(Obj, True)
+ IsAnyFile = self._GetAnyFileStatement(Obj, True)
+ if not (IsFv or IsFd or IsAnyFile):
+ break
+
+ ## _GetFvStatement() method
+ #
+ # Get FV for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom FV is got
+ # @retval True Successfully find a FV statement
+ # @retval False Not able to find a FV statement
+ #
+ def _GetFvStatement(self, CapsuleObj, FMPCapsule = False):
+ if not self._IsKeyword(BINARY_FILE_TYPE_FV):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in self.Profile.FvDict:
+ raise Warning("FV name does not exist", self.FileName, self.CurrentLineNumber)
+
+ myCapsuleFv = CapsuleFv()
+ myCapsuleFv.FvName = self._Token
+ if FMPCapsule:
+ if not CapsuleObj.ImageFile:
+ CapsuleObj.ImageFile.append(myCapsuleFv)
+ else:
+ CapsuleObj.VendorCodeFile.append(myCapsuleFv)
+ else:
+ CapsuleObj.CapsuleDataList.append(myCapsuleFv)
+ return True
+
+ ## _GetFdStatement() method
+ #
+ # Get FD for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom FD is got
+ # @retval True Successfully find a FD statement
+ # @retval False Not able to find a FD statement
+ #
+ def _GetFdStatement(self, CapsuleObj, FMPCapsule = False):
+ if not self._IsKeyword("FD"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FD name", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in self.Profile.FdDict:
+ raise Warning("FD name does not exist", self.FileName, self.CurrentLineNumber)
+
+ myCapsuleFd = CapsuleFd()
+ myCapsuleFd.FdName = self._Token
+ if FMPCapsule:
+ if not CapsuleObj.ImageFile:
+ CapsuleObj.ImageFile.append(myCapsuleFd)
+ else:
+ CapsuleObj.VendorCodeFile.append(myCapsuleFd)
+ else:
+ CapsuleObj.CapsuleDataList.append(myCapsuleFd)
+ return True
+
+ def _GetFmpStatement(self, CapsuleObj):
+ if not self._IsKeyword("FMP_PAYLOAD"):
+ if not self._IsKeyword("FMP"):
+ return False
+
+ if not self._IsKeyword("PAYLOAD"):
+ self._UndoToken()
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("payload name after FMP_PAYLOAD =", self.FileName, self.CurrentLineNumber)
+ Payload = self._Token.upper()
+ if Payload not in self.Profile.FmpPayloadDict:
+ raise Warning("This FMP Payload does not exist: %s" % self._Token, self.FileName, self.CurrentLineNumber)
+ CapsuleObj.FmpPayloadList.append(self.Profile.FmpPayloadDict[Payload])
+ return True
+
+ def _ParseRawFileStatement(self):
+ if not self._IsKeyword("FILE"):
+ return None
+
+ if not self._IsKeyword("DATA"):
+ self._UndoToken()
+ return None
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
+
+ AnyFileName = self._Token
+ self._VerifyFile(AnyFileName)
+
+ if not os.path.isabs(AnyFileName):
+ AnyFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, AnyFileName)
+
+ return AnyFileName
+
+ ## _GetAnyFileStatement() method
+ #
+ # Get AnyFile for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom AnyFile is got
+ # @retval True Successfully find a Anyfile statement
+ # @retval False Not able to find a AnyFile statement
+ #
+ def _GetAnyFileStatement(self, CapsuleObj, FMPCapsule = False):
+ AnyFileName = self._ParseRawFileStatement()
+ if not AnyFileName:
+ return False
+
+ myCapsuleAnyFile = CapsuleAnyFile()
+ myCapsuleAnyFile.FileName = AnyFileName
+ if FMPCapsule:
+ if not CapsuleObj.ImageFile:
+ CapsuleObj.ImageFile.append(myCapsuleAnyFile)
+ else:
+ CapsuleObj.VendorCodeFile.append(myCapsuleAnyFile)
+ else:
+ CapsuleObj.CapsuleDataList.append(myCapsuleAnyFile)
+ return True
+
+ ## _GetAfileStatement() method
+ #
+ # Get Afile for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom Afile is got
+ # @retval True Successfully find a Afile statement
+ # @retval False Not able to find a Afile statement
+ #
+ def _GetAfileStatement(self, CapsuleObj):
+ if not self._IsKeyword("APPEND"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Afile name", self.FileName, self.CurrentLineNumber)
+
+ AfileName = self._Token
+ AfileBaseName = os.path.basename(AfileName)
+
+ if os.path.splitext(AfileBaseName)[1] not in {".bin", ".BIN", ".Bin", ".dat", ".DAT", ".Dat", ".data", ".DATA", ".Data"}:
+ raise Warning('invalid binary file type, should be one of "bin",BINARY_FILE_TYPE_BIN,"Bin","dat","DAT","Dat","data","DATA","Data"', \
+ self.FileName, self.CurrentLineNumber)
+
+ if not os.path.isabs(AfileName):
+ AfileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(AfileName)
+ self._VerifyFile(AfileName)
+ else:
+ if not os.path.exists(AfileName):
+ raise Warning('%s does not exist' % AfileName, self.FileName, self.CurrentLineNumber)
+ else:
+ pass
+
+ myCapsuleAfile = CapsuleAfile()
+ myCapsuleAfile.FileName = AfileName
+ CapsuleObj.CapsuleDataList.append(myCapsuleAfile)
+ return True
+
+ ## _GetRule() method
+ #
+ # Get Rule section contents and store its data into rule list of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a Rule
+ # @retval False Not able to find a Rule
+ #
+ def _GetRule(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[RULE."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+ self._UndoToken()
+ if not self._IsToken("[Rule.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[Rule.]", self.FileName, self.CurrentLineNumber)
+
+ if not self._SkipToToken(TAB_SPLIT):
+ raise Warning.Expected("'.'", self.FileName, self.CurrentLineNumber)
+
+ Arch = self._SkippedChars.rstrip(TAB_SPLIT)
+
+ ModuleType = self._GetModuleType()
+
+ TemplateName = ""
+ if self._IsToken(TAB_SPLIT):
+ if not self._GetNextWord():
+ raise Warning.Expected("template name", self.FileName, self.CurrentLineNumber)
+ TemplateName = self._Token
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ RuleObj = self._GetRuleFileStatements()
+ RuleObj.Arch = Arch.upper()
+ RuleObj.ModuleType = ModuleType
+ RuleObj.TemplateName = TemplateName
+ if TemplateName == '':
+ self.Profile.RuleDict['RULE' + \
+ TAB_SPLIT + \
+ Arch.upper() + \
+ TAB_SPLIT + \
+ ModuleType.upper() ] = RuleObj
+ else:
+ self.Profile.RuleDict['RULE' + \
+ TAB_SPLIT + \
+ Arch.upper() + \
+ TAB_SPLIT + \
+ ModuleType.upper() + \
+ TAB_SPLIT + \
+ TemplateName.upper() ] = RuleObj
+ return True
+
+ ## _GetModuleType() method
+ #
+ # Return the module type
+ #
+ # @param self The object pointer
+ # @retval string module type
+ #
+ def _GetModuleType(self):
+ if not self._GetNextWord():
+ raise Warning.Expected("Module type", self.FileName, self.CurrentLineNumber)
+ if self._Token.upper() not in {
+ SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM,
+ SUP_MODULE_DXE_CORE, SUP_MODULE_DXE_DRIVER,
+ SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_DXE_SMM_DRIVER,
+ SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_UEFI_DRIVER,
+ SUP_MODULE_UEFI_APPLICATION, SUP_MODULE_USER_DEFINED, SUP_MODULE_HOST_APPLICATION,
+ TAB_DEFAULT, SUP_MODULE_BASE,
+ EDK_COMPONENT_TYPE_SECURITY_CORE,
+ EDK_COMPONENT_TYPE_COMBINED_PEIM_DRIVER,
+ EDK_COMPONENT_TYPE_PIC_PEIM,
+ EDK_COMPONENT_TYPE_RELOCATABLE_PEIM, "PE32_PEIM",
+ EDK_COMPONENT_TYPE_BS_DRIVER, EDK_COMPONENT_TYPE_RT_DRIVER,
+ EDK_COMPONENT_TYPE_SAL_RT_DRIVER,
+ EDK_COMPONENT_TYPE_APPLICATION, "ACPITABLE",
+ SUP_MODULE_SMM_CORE, SUP_MODULE_MM_STANDALONE,
+ SUP_MODULE_MM_CORE_STANDALONE}:
+ raise Warning("Unknown Module type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ return self._Token
+
+ ## _GetFileExtension() method
+ #
+ # Return the file extension
+ #
+ # @param self The object pointer
+ # @retval string file name extension
+ #
+ def _GetFileExtension(self):
+ if not self._IsToken(TAB_SPLIT):
+ raise Warning.Expected("'.'", self.FileName, self.CurrentLineNumber)
+
+ Ext = ""
+ if self._GetNextToken():
+ if FileExtensionPattern.match(self._Token):
+ Ext = self._Token
+ return TAB_SPLIT + Ext
+ else:
+ raise Warning("Unknown file extension '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ else:
+ raise Warning.Expected("file extension", self.FileName, self.CurrentLineNumber)
+
+ ## _GetRuleFileStatement() method
+ #
+ # Get rule contents
+ #
+ # @param self The object pointer
+ # @retval Rule Rule object
+ #
+ def _GetRuleFileStatements(self):
+ if not self._IsKeyword("FILE"):
+ raise Warning.Expected("FILE", self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextWord():
+ raise Warning.Expected("FFS type", self.FileName, self.CurrentLineNumber)
+
+ Type = self._Token.strip().upper()
+ if Type not in {"RAW", "FREEFORM", SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM,
+ "PEI_DXE_COMBO", "DRIVER", SUP_MODULE_DXE_CORE, EDK_COMPONENT_TYPE_APPLICATION,
+ "FV_IMAGE", "SMM", SUP_MODULE_SMM_CORE, SUP_MODULE_MM_STANDALONE,
+ SUP_MODULE_MM_CORE_STANDALONE}:
+ raise Warning("Unknown FV type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsKeyword("$(NAMED_GUID)"):
+ if not self._GetNextWord():
+ NamedGuid = self._CurrentLine()[self.CurrentOffsetWithinLine:].split()[0].strip()
+ if GlobalData.gGuidPatternEnd.match(NamedGuid):
+ self.CurrentOffsetWithinLine += len(NamedGuid)
+ self._Token = NamedGuid
+ else:
+ raise Warning.Expected("$(NAMED_GUID)", self.FileName, self.CurrentLineNumber)
+ if self._Token == 'PCD':
+ if not self._IsToken("("):
+ raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
+ PcdPair = self._GetNextPcdSettings()
+ if not self._IsToken(")"):
+ raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
+ self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
+
+ NameGuid = self._Token
+
+ KeepReloc = None
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._FileCouldHaveRelocFlag(Type):
+ if self._Token == 'RELOCS_STRIPPED':
+ KeepReloc = False
+ else:
+ KeepReloc = True
+ else:
+ raise Warning("File type %s could not have reloc strip flag%d" % (Type, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ KeyStringList = []
+ if self._GetNextToken():
+ if TokenFindPattern.match(self._Token):
+ KeyStringList.append(self._Token)
+ if self._IsToken(TAB_COMMA_SPLIT):
+ while self._GetNextToken():
+ if not TokenFindPattern.match(self._Token):
+ raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
+ KeyStringList.append(self._Token)
+
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ break
+
+ else:
+ self._UndoToken()
+
+
+ Fixed = False
+ if self._IsKeyword("Fixed", True):
+ Fixed = True
+
+ CheckSum = False
+ if self._IsKeyword("CheckSum", True):
+ CheckSum = True
+
+ AlignValue = ""
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ #For FFS, Auto is default option same to ""
+ if not self._Token == "Auto":
+ AlignValue = self._Token
+
+ if self._IsToken("{"):
+ # Complex file rule expected
+ NewRule = RuleComplexFile()
+ NewRule.FvFileType = Type
+ NewRule.NameGuid = NameGuid
+ NewRule.Alignment = AlignValue
+ NewRule.CheckSum = CheckSum
+ NewRule.Fixed = Fixed
+ NewRule.KeyStringList = KeyStringList
+ if KeepReloc is not None:
+ NewRule.KeepReloc = KeepReloc
+
+ while True:
+ IsEncapsulate = self._GetRuleEncapsulationSection(NewRule)
+ IsLeaf = self._GetEfiSection(NewRule)
+ if not IsEncapsulate and not IsLeaf:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ return NewRule
+
+ else:
+ # Simple file rule expected
+ if not self._GetNextWord():
+ raise Warning.Expected("leaf section type", self.FileName, self.CurrentLineNumber)
+
+ SectionName = self._Token
+
+ if SectionName not in {
+ "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE",
+ "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI,
+ BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID",
+ BINARY_FILE_TYPE_SMM_DEPEX}:
+ raise Warning("Unknown leaf section name '%s'" % SectionName, self.FileName, self.CurrentLineNumber)
+
+
+ if self._IsKeyword("Fixed", True):
+ Fixed = True
+
+ if self._IsKeyword("CheckSum", True):
+ CheckSum = True
+
+ SectAlignment = ""
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_TE):
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ SectAlignment = self._Token
+
+ Ext = None
+ if self._IsToken(TAB_VALUE_SPLIT):
+ Ext = self._GetFileExtension()
+ elif not self._GetNextToken():
+ raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
+
+ NewRule = RuleSimpleFile()
+ NewRule.SectionType = SectionName
+ NewRule.FvFileType = Type
+ NewRule.NameGuid = NameGuid
+ NewRule.Alignment = AlignValue
+ NewRule.SectAlignment = SectAlignment
+ NewRule.CheckSum = CheckSum
+ NewRule.Fixed = Fixed
+ NewRule.KeyStringList = KeyStringList
+ if KeepReloc is not None:
+ NewRule.KeepReloc = KeepReloc
+ NewRule.FileExtension = Ext
+ NewRule.FileName = self._Token
+ return NewRule
+
+ ## _GetEfiSection() method
+ #
+ # Get section list for Rule
+ #
+ # @param self The object pointer
+ # @param Obj for whom section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetEfiSection(self, Obj):
+ OldPos = self.GetFileBufferPos()
+ EfiSectionObj = EfiSection()
+ if not self._GetNextWord():
+ CurrentLine = self._CurrentLine()[self.CurrentOffsetWithinLine:].split()[0].strip()
+ if self._Token == '{' and Obj.FvFileType == "RAW" and TAB_SPLIT in CurrentLine:
+ if self._IsToken(TAB_VALUE_SPLIT):
+ EfiSectionObj.FileExtension = self._GetFileExtension()
+ elif self._GetNextToken():
+ EfiSectionObj.FileName = self._Token
+ EfiSectionObj.SectionType = BINARY_FILE_TYPE_RAW
+ Obj.SectionList.append(EfiSectionObj)
+ return True
+ else:
+ return False
+ SectionName = self._Token
+
+ if SectionName not in {
+ "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE",
+ "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI,
+ BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID",
+ BINARY_FILE_TYPE_SMM_DEPEX, BINARY_FILE_TYPE_GUID}:
+ self._UndoToken()
+ return False
+
+ if SectionName == "FV_IMAGE":
+ FvImageSectionObj = FvImageSection()
+ if self._IsKeyword("FV_IMAGE"):
+ pass
+ if self._IsToken("{"):
+ FvObj = FV()
+ self._GetDefineStatements(FvObj)
+ self._GetBlockStatement(FvObj)
+ self._GetSetStatements(FvObj)
+ self._GetFvAlignment(FvObj)
+ self._GetFvAttributes(FvObj)
+ self._GetAprioriSection(FvObj)
+ self._GetAprioriSection(FvObj)
+
+ while True:
+ IsInf = self._GetInfStatement(FvObj)
+ IsFile = self._GetFileStatement(FvObj)
+ if not IsInf and not IsFile:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ FvImageSectionObj.Fv = FvObj
+ FvImageSectionObj.FvName = None
+
+ else:
+ if not self._IsKeyword(BINARY_FILE_TYPE_FV):
+ raise Warning.Expected("'FV'", self.FileName, self.CurrentLineNumber)
+ FvImageSectionObj.FvFileType = self._Token
+
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENT_NOAUTO:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ FvImageSectionObj.Alignment = self._Token
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ FvImageSectionObj.FvFileExtension = self._GetFileExtension()
+ elif self._GetNextToken():
+ if self._Token not in {
+ T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE,
+ "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,
+ BINARY_FILE_TYPE_UI, "VERSION",
+ BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID,
+ BINARY_FILE_TYPE_SMM_DEPEX}:
+ FvImageSectionObj.FvFileName = self._Token
+ else:
+ self._UndoToken()
+ else:
+ raise Warning.Expected("FV file name", self.FileName, self.CurrentLineNumber)
+
+ Obj.SectionList.append(FvImageSectionObj)
+ return True
+
+ EfiSectionObj.SectionType = SectionName
+
+ if not self._GetNextToken():
+ raise Warning.Expected("file type", self.FileName, self.CurrentLineNumber)
+
+ if self._Token == "STRING":
+ if not self._RuleSectionCouldHaveString(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT have string data%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Quoted String", self.FileName, self.CurrentLineNumber)
+
+ if self._GetStringData():
+ EfiSectionObj.StringData = self._Token
+
+ if self._IsKeyword("BUILD_NUM"):
+ if not self._RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Build number", self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.BuildNum = self._Token
+
+ else:
+ EfiSectionObj.FileType = self._Token
+ self._CheckRuleSectionFileType(EfiSectionObj.SectionType, EfiSectionObj.FileType)
+
+ if self._IsKeyword("Optional"):
+ if not self._RuleSectionCouldBeOptional(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT be optional%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.Optional = True
+
+ if self._IsKeyword("BUILD_NUM"):
+ if not self._RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Build number", self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.BuildNum = self._Token
+
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_TE):
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.Alignment = self._Token
+
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._SectionCouldHaveRelocFlag(EfiSectionObj.SectionType):
+ if self._Token == 'RELOCS_STRIPPED':
+ EfiSectionObj.KeepReloc = False
+ else:
+ EfiSectionObj.KeepReloc = True
+ if Obj.KeepReloc is not None and Obj.KeepReloc != EfiSectionObj.KeepReloc:
+ raise Warning("Section type %s has reloc strip flag conflict with Rule" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
+ else:
+ raise Warning("Section type %s could not have reloc strip flag" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
+
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ EfiSectionObj.FileExtension = self._GetFileExtension()
+ elif self._GetNextToken():
+ if self._Token not in {
+ T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE,
+ "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,
+ BINARY_FILE_TYPE_UI, "VERSION",
+ BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID,
+ BINARY_FILE_TYPE_SMM_DEPEX}:
+
+ if self._Token.startswith('PCD'):
+ self._UndoToken()
+ self._GetNextWord()
+
+ if self._Token == 'PCD':
+ if not self._IsToken("("):
+ raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
+ PcdPair = self._GetNextPcdSettings()
+ if not self._IsToken(")"):
+ raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
+ self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
+
+ EfiSectionObj.FileName = self._Token
+
+ else:
+ self._UndoToken()
+ else:
+ raise Warning.Expected("section file name", self.FileName, self.CurrentLineNumber)
+
+ Obj.SectionList.append(EfiSectionObj)
+ return True
+
+ ## _RuleSectionCouldBeOptional() method
+ #
+ # Get whether a section could be optional
+ #
+ # @param SectionType The section type to check
+ # @retval True section could be optional
+ # @retval False section never optional
+ #
+ @staticmethod
+ def _RuleSectionCouldBeOptional(SectionType):
+ if SectionType in {BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "RAW", BINARY_FILE_TYPE_SMM_DEPEX}:
+ return True
+ else:
+ return False
+
+ ## _RuleSectionCouldHaveBuildNum() method
+ #
+ # Get whether a section could have build number information
+ #
+ # @param SectionType The section type to check
+ # @retval True section could have build number information
+ # @retval False section never have build number information
+ #
+ @staticmethod
+ def _RuleSectionCouldHaveBuildNum(SectionType):
+ if SectionType == "VERSION":
+ return True
+ else:
+ return False
+
+ ## _RuleSectionCouldHaveString() method
+ #
+ # Get whether a section could have string
+ #
+ # @param SectionType The section type to check
+ # @retval True section could have string
+ # @retval False section never have string
+ #
+ @staticmethod
+ def _RuleSectionCouldHaveString(SectionType):
+ if SectionType in {BINARY_FILE_TYPE_UI, "VERSION"}:
+ return True
+ else:
+ return False
+
+ ## _CheckRuleSectionFileType() method
+ #
+ # Get whether a section matches a file type
+ #
+ # @param self The object pointer
+ # @param SectionType The section type to check
+ # @param FileType The file type to check
+ #
+ def _CheckRuleSectionFileType(self, SectionType, FileType):
+ WarningString = "Incorrect section file type '%s'"
+ if SectionType == "COMPAT16":
+ if FileType not in {"COMPAT16", "SEC_COMPAT16"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_PE32:
+ if FileType not in {BINARY_FILE_TYPE_PE32, "SEC_PE32"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_PIC:
+ if FileType not in {BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_PIC}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_TE:
+ if FileType not in {BINARY_FILE_TYPE_TE, "SEC_TE"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == "RAW":
+ if FileType not in {BINARY_FILE_TYPE_BIN, "SEC_BIN", "RAW", "ASL", "ACPI"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_DXE_DEPEX or SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
+ if FileType not in {BINARY_FILE_TYPE_DXE_DEPEX, "SEC_DXE_DEPEX", BINARY_FILE_TYPE_SMM_DEPEX}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_UI:
+ if FileType not in {BINARY_FILE_TYPE_UI, "SEC_UI"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == "VERSION":
+ if FileType not in {"VERSION", "SEC_VERSION"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_PEI_DEPEX:
+ if FileType not in {BINARY_FILE_TYPE_PEI_DEPEX, "SEC_PEI_DEPEX"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_GUID:
+ if FileType not in {BINARY_FILE_TYPE_PE32, "SEC_GUID"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+
+ ## _GetRuleEncapsulationSection() method
+ #
+ # Get encapsulation section for Rule
+ #
+ # @param self The object pointer
+ # @param theRule for whom section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetRuleEncapsulationSection(self, theRule):
+ if self._IsKeyword("COMPRESS"):
+ Type = "PI_STD"
+ if self._IsKeyword("PI_STD") or self._IsKeyword("PI_NONE"):
+ Type = self._Token
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ CompressSectionObj = CompressSection()
+
+ CompressSectionObj.CompType = Type
+ # Recursive sections...
+ while True:
+ IsEncapsulate = self._GetRuleEncapsulationSection(CompressSectionObj)
+ IsLeaf = self._GetEfiSection(CompressSectionObj)
+ if not IsEncapsulate and not IsLeaf:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ theRule.SectionList.append(CompressSectionObj)
+
+ return True
+
+ elif self._IsKeyword("GUIDED"):
+ GuidValue = None
+ if self._GetNextGuid():
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ GuidValue = self._Token
+
+ if self._IsKeyword("$(NAMED_GUID)"):
+ GuidValue = self._Token
+
+ AttribDict = self._GetGuidAttrib()
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+ GuidSectionObj = GuidSection()
+ GuidSectionObj.NameGuid = GuidValue
+ GuidSectionObj.SectionType = "GUIDED"
+ GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
+ GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
+ GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
+
+ # Efi sections...
+ while True:
+ IsEncapsulate = self._GetRuleEncapsulationSection(GuidSectionObj)
+ IsLeaf = self._GetEfiSection(GuidSectionObj)
+ if not IsEncapsulate and not IsLeaf:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ theRule.SectionList.append(GuidSectionObj)
+
+ return True
+
+ return False
+
+ ## _GetOptionRom() method
+ #
+ # Get OptionROM section contents and store its data into OptionROM list of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a OptionROM
+ # @retval False Not able to find a OptionROM
+ #
+ def _GetOptionRom(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[OPTIONROM."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[OptionRom.", True):
+ raise Warning("Unknown Keyword '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ OptRomName = self._GetUiName()
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ OptRomObj = OPTIONROM(OptRomName)
+ self.Profile.OptRomDict[OptRomName] = OptRomObj
+
+ while True:
+ isInf = self._GetOptRomInfStatement(OptRomObj)
+ isFile = self._GetOptRomFileStatement(OptRomObj)
+ if not isInf and not isFile:
+ break
+
+ return True
+
+ ## _GetOptRomInfStatement() method
+ #
+ # Get INF statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom inf statement is got
+ # @retval True Successfully find inf statement
+ # @retval False Not able to find inf statement
+ #
+ def _GetOptRomInfStatement(self, Obj):
+ if not self._IsKeyword("INF"):
+ return False
+
+ ffsInf = OptRomInfStatement()
+ self._GetInfOptions(ffsInf)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("INF file path", self.FileName, self.CurrentLineNumber)
+ ffsInf.InfFileName = self._Token
+ if ffsInf.InfFileName.replace(TAB_WORKSPACE, '').find('$') == -1:
+ #check for file path
+ ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ NewFileName = ffsInf.InfFileName
+ if ffsInf.OverrideGuid:
+ NewFileName = ProcessDuplicatedInf(PathClass(ffsInf.InfFileName,GenFdsGlobalVariable.WorkSpaceDir), ffsInf.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir).Path
+
+ if not NewFileName in self.Profile.InfList:
+ self.Profile.InfList.append(NewFileName)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.InfFileLineList.append(FileLineTuple)
+ if ffsInf.UseArch:
+ if ffsInf.UseArch not in self.Profile.InfDict:
+ self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
+ else:
+ self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
+ else:
+ self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
+
+
+ self._GetOptRomOverrides (ffsInf)
+
+ Obj.FfsList.append(ffsInf)
+ return True
+
+ ## _GetOptRomOverrides() method
+ #
+ # Get overrides for OptROM INF & FILE
+ #
+ # @param self The object pointer
+ # @param FfsInfObj for whom overrides is got
+ #
+ def _GetOptRomOverrides(self, Obj):
+ if self._IsToken('{'):
+ Overrides = OverrideAttribs()
+ while True:
+ if self._IsKeyword("PCI_VENDOR_ID"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex vendor id", self.FileName, self.CurrentLineNumber)
+ Overrides.PciVendorId = self._Token
+ continue
+
+ if self._IsKeyword("PCI_CLASS_CODE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex class code", self.FileName, self.CurrentLineNumber)
+ Overrides.PciClassCode = self._Token
+ continue
+
+ if self._IsKeyword("PCI_DEVICE_ID"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ # Get a list of PCI IDs
+ Overrides.PciDeviceId = ""
+ while (self._GetNextHexNumber()):
+ Overrides.PciDeviceId = "{} {}".format(Overrides.PciDeviceId, self._Token)
+ if not Overrides.PciDeviceId:
+ raise Warning.Expected("one or more Hex device ids", self.FileName, self.CurrentLineNumber)
+ continue
+
+ if self._IsKeyword("PCI_REVISION"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex revision", self.FileName, self.CurrentLineNumber)
+ Overrides.PciRevision = self._Token
+ continue
+
+ if self._IsKeyword("PCI_COMPRESS"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("TRUE/FALSE for compress", self.FileName, self.CurrentLineNumber)
+ Overrides.NeedCompress = self._Token.upper() == 'TRUE'
+ continue
+
+ if self._IsToken(T_CHAR_BRACE_R):
+ break
+ else:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, File=self.FileName, Line=self.CurrentLineNumber)
+
+ Obj.OverrideAttribs = Overrides
+
+ ## _GetOptRomFileStatement() method
+ #
+ # Get FILE statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom FILE statement is got
+ # @retval True Successfully find FILE statement
+ # @retval False Not able to find FILE statement
+ #
+ def _GetOptRomFileStatement(self, Obj):
+ if not self._IsKeyword("FILE"):
+ return False
+
+ FfsFileObj = OptRomFileStatement()
+
+ if not self._IsKeyword("EFI") and not self._IsKeyword(BINARY_FILE_TYPE_BIN):
+ raise Warning.Expected("Binary type (EFI/BIN)", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FileType = self._Token
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File path", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FileName = self._Token
+ if FfsFileObj.FileName.replace(TAB_WORKSPACE, '').find('$') == -1:
+ #check for file path
+ ErrorCode, ErrorInfo = PathClass(NormPath(FfsFileObj.FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ if FfsFileObj.FileType == 'EFI':
+ self._GetOptRomOverrides(FfsFileObj)
+
+ Obj.FfsList.append(FfsFileObj)
+
+ return True
+
+ ## _GetCapInFd() method
+ #
+ # Get Cap list contained in FD
+ #
+ # @param self The object pointer
+ # @param FdName FD name
+ # @retval CapList List of Capsule in FD
+ #
+ def _GetCapInFd (self, FdName):
+ CapList = []
+ if FdName.upper() in self.Profile.FdDict:
+ FdObj = self.Profile.FdDict[FdName.upper()]
+ for elementRegion in FdObj.RegionList:
+ if elementRegion.RegionType == 'CAPSULE':
+ for elementRegionData in elementRegion.RegionDataList:
+ if elementRegionData.endswith(".cap"):
+ continue
+ if elementRegionData is not None and elementRegionData.upper() not in CapList:
+ CapList.append(elementRegionData.upper())
+ return CapList
+
+ ## _GetReferencedFdCapTuple() method
+ #
+ # Get FV and FD list referenced by a capsule image
+ #
+ # @param self The object pointer
+ # @param CapObj Capsule section to be searched
+ # @param RefFdList referenced FD by section
+ # @param RefFvList referenced FV by section
+ #
+ def _GetReferencedFdCapTuple(self, CapObj, RefFdList = [], RefFvList = []):
+ for CapsuleDataObj in CapObj.CapsuleDataList:
+ if hasattr(CapsuleDataObj, 'FvName') and CapsuleDataObj.FvName is not None and CapsuleDataObj.FvName.upper() not in RefFvList:
+ RefFvList.append (CapsuleDataObj.FvName.upper())
+ elif hasattr(CapsuleDataObj, 'FdName') and CapsuleDataObj.FdName is not None and CapsuleDataObj.FdName.upper() not in RefFdList:
+ RefFdList.append (CapsuleDataObj.FdName.upper())
+ elif CapsuleDataObj.Ffs is not None:
+ if isinstance(CapsuleDataObj.Ffs, FileStatement):
+ if CapsuleDataObj.Ffs.FvName is not None and CapsuleDataObj.Ffs.FvName.upper() not in RefFvList:
+ RefFvList.append(CapsuleDataObj.Ffs.FvName.upper())
+ elif CapsuleDataObj.Ffs.FdName is not None and CapsuleDataObj.Ffs.FdName.upper() not in RefFdList:
+ RefFdList.append(CapsuleDataObj.Ffs.FdName.upper())
+ else:
+ self._GetReferencedFdFvTupleFromSection(CapsuleDataObj.Ffs, RefFdList, RefFvList)
+
+ ## _GetFvInFd() method
+ #
+ # Get FV list contained in FD
+ #
+ # @param self The object pointer
+ # @param FdName FD name
+ # @retval FvList list of FV in FD
+ #
+ def _GetFvInFd (self, FdName):
+ FvList = []
+ if FdName.upper() in self.Profile.FdDict:
+ FdObj = self.Profile.FdDict[FdName.upper()]
+ for elementRegion in FdObj.RegionList:
+ if elementRegion.RegionType == BINARY_FILE_TYPE_FV:
+ for elementRegionData in elementRegion.RegionDataList:
+ if elementRegionData.endswith(".fv"):
+ continue
+ if elementRegionData is not None and elementRegionData.upper() not in FvList:
+ FvList.append(elementRegionData.upper())
+ return FvList
+
+ ## _GetReferencedFdFvTuple() method
+ #
+ # Get FD and FV list referenced by a FFS file
+ #
+ # @param self The object pointer
+ # @param FfsFile contains sections to be searched
+ # @param RefFdList referenced FD by section
+ # @param RefFvList referenced FV by section
+ #
+ def _GetReferencedFdFvTuple(self, FvObj, RefFdList = [], RefFvList = []):
+ for FfsObj in FvObj.FfsList:
+ if isinstance(FfsObj, FileStatement):
+ if FfsObj.FvName is not None and FfsObj.FvName.upper() not in RefFvList:
+ RefFvList.append(FfsObj.FvName.upper())
+ elif FfsObj.FdName is not None and FfsObj.FdName.upper() not in RefFdList:
+ RefFdList.append(FfsObj.FdName.upper())
+ else:
+ self._GetReferencedFdFvTupleFromSection(FfsObj, RefFdList, RefFvList)
+
+ ## _GetReferencedFdFvTupleFromSection() method
+ #
+ # Get FD and FV list referenced by a FFS section
+ #
+ # @param self The object pointer
+ # @param FfsFile contains sections to be searched
+ # @param FdList referenced FD by section
+ # @param FvList referenced FV by section
+ #
+ def _GetReferencedFdFvTupleFromSection(self, FfsFile, FdList = [], FvList = []):
+ SectionStack = list(FfsFile.SectionList)
+ while SectionStack != []:
+ SectionObj = SectionStack.pop()
+ if isinstance(SectionObj, FvImageSection):
+ if SectionObj.FvName is not None and SectionObj.FvName.upper() not in FvList:
+ FvList.append(SectionObj.FvName.upper())
+ if SectionObj.Fv is not None and SectionObj.Fv.UiFvName is not None and SectionObj.Fv.UiFvName.upper() not in FvList:
+ FvList.append(SectionObj.Fv.UiFvName.upper())
+ self._GetReferencedFdFvTuple(SectionObj.Fv, FdList, FvList)
+
+ if isinstance(SectionObj, CompressSection) or isinstance(SectionObj, GuidSection):
+ SectionStack.extend(SectionObj.SectionList)
+
+ ## CycleReferenceCheck() method
+ #
+ # Check whether cycle reference exists in FDF
+ #
+ # @param self The object pointer
+ # @retval True cycle reference exists
+ # @retval False Not exists cycle reference
+ #
+ def CycleReferenceCheck(self):
+ #
+ # Check the cycle between FV and FD image
+ #
+ MaxLength = len (self.Profile.FvDict)
+ for FvName in self.Profile.FvDict:
+ LogStr = "\nCycle Reference Checking for FV: %s\n" % FvName
+ RefFvStack = set(FvName)
+ FdAnalyzedList = set()
+
+ Index = 0
+ while RefFvStack and Index < MaxLength:
+ Index = Index + 1
+ FvNameFromStack = RefFvStack.pop()
+ if FvNameFromStack.upper() in self.Profile.FvDict:
+ FvObj = self.Profile.FvDict[FvNameFromStack.upper()]
+ else:
+ continue
+
+ RefFdList = []
+ RefFvList = []
+ self._GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
+
+ for RefFdName in RefFdList:
+ if RefFdName in FdAnalyzedList:
+ continue
+
+ LogStr += "FV %s contains FD %s\n" % (FvNameFromStack, RefFdName)
+ FvInFdList = self._GetFvInFd(RefFdName)
+ if FvInFdList != []:
+ for FvNameInFd in FvInFdList:
+ LogStr += "FD %s contains FV %s\n" % (RefFdName, FvNameInFd)
+ if FvNameInFd not in RefFvStack:
+ RefFvStack.add(FvNameInFd)
+
+ if FvName in RefFvStack or FvNameFromStack in RefFvStack:
+ EdkLogger.info(LogStr)
+ return True
+ FdAnalyzedList.add(RefFdName)
+
+ for RefFvName in RefFvList:
+ LogStr += "FV %s contains FV %s\n" % (FvNameFromStack, RefFvName)
+ if RefFvName not in RefFvStack:
+ RefFvStack.add(RefFvName)
+
+ if FvName in RefFvStack or FvNameFromStack in RefFvStack:
+ EdkLogger.info(LogStr)
+ return True
+
+ #
+ # Check the cycle between Capsule and FD image
+ #
+ MaxLength = len (self.Profile.CapsuleDict)
+ for CapName in self.Profile.CapsuleDict:
+ #
+ # Capsule image to be checked.
+ #
+ LogStr = "\n\n\nCycle Reference Checking for Capsule: %s\n" % CapName
+ RefCapStack = {CapName}
+ FdAnalyzedList = set()
+ FvAnalyzedList = set()
+
+ Index = 0
+ while RefCapStack and Index < MaxLength:
+ Index = Index + 1
+ CapNameFromStack = RefCapStack.pop()
+ if CapNameFromStack.upper() in self.Profile.CapsuleDict:
+ CapObj = self.Profile.CapsuleDict[CapNameFromStack.upper()]
+ else:
+ continue
+
+ RefFvList = []
+ RefFdList = []
+ self._GetReferencedFdCapTuple(CapObj, RefFdList, RefFvList)
+
+ FvListLength = 0
+ FdListLength = 0
+ while FvListLength < len (RefFvList) or FdListLength < len (RefFdList):
+ for RefFdName in RefFdList:
+ if RefFdName in FdAnalyzedList:
+ continue
+
+ LogStr += "Capsule %s contains FD %s\n" % (CapNameFromStack, RefFdName)
+ for CapNameInFd in self._GetCapInFd(RefFdName):
+ LogStr += "FD %s contains Capsule %s\n" % (RefFdName, CapNameInFd)
+ if CapNameInFd not in RefCapStack:
+ RefCapStack.append(CapNameInFd)
+
+ if CapName in RefCapStack or CapNameFromStack in RefCapStack:
+ EdkLogger.info(LogStr)
+ return True
+
+ for FvNameInFd in self._GetFvInFd(RefFdName):
+ LogStr += "FD %s contains FV %s\n" % (RefFdName, FvNameInFd)
+ if FvNameInFd not in RefFvList:
+ RefFvList.append(FvNameInFd)
+
+ FdAnalyzedList.add(RefFdName)
+ #
+ # the number of the parsed FV and FD image
+ #
+ FvListLength = len (RefFvList)
+ FdListLength = len (RefFdList)
+ for RefFvName in RefFvList:
+ if RefFvName in FvAnalyzedList:
+ continue
+ LogStr += "Capsule %s contains FV %s\n" % (CapNameFromStack, RefFvName)
+ if RefFvName.upper() in self.Profile.FvDict:
+ FvObj = self.Profile.FvDict[RefFvName.upper()]
+ else:
+ continue
+ self._GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
+ FvAnalyzedList.add(RefFvName)
+
+ return False
+
+ def GetAllIncludedFile (self):
+ global AllIncludeFileList
+ return AllIncludeFileList
+
+if __name__ == "__main__":
+ import sys
+ try:
+ test_file = sys.argv[1]
+ except IndexError as v:
+ print("Usage: %s filename" % sys.argv[0])
+ sys.exit(1)
+
+ parser = FdfParser(test_file)
+ try:
+ parser.ParseFile()
+ parser.CycleReferenceCheck()
+ except Warning as X:
+ print(str(X))
+ else:
+ print("Success!")
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Ffs.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Ffs.py
new file mode 100755
index 00000000..f55524c3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Ffs.py
@@ -0,0 +1,49 @@
+## @file
+# process FFS generation
+#
+# Copyright (c) 2007-2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from Common.DataType import *
+
+# mapping between FILE type in FDF and file type for GenFfs
+FdfFvFileTypeToFileType = {
+ SUP_MODULE_SEC : 'EFI_FV_FILETYPE_SECURITY_CORE',
+ SUP_MODULE_PEI_CORE : 'EFI_FV_FILETYPE_PEI_CORE',
+ SUP_MODULE_PEIM : 'EFI_FV_FILETYPE_PEIM',
+ SUP_MODULE_DXE_CORE : 'EFI_FV_FILETYPE_DXE_CORE',
+ 'FREEFORM' : 'EFI_FV_FILETYPE_FREEFORM',
+ 'DRIVER' : 'EFI_FV_FILETYPE_DRIVER',
+ 'APPLICATION' : 'EFI_FV_FILETYPE_APPLICATION',
+ 'FV_IMAGE' : 'EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE',
+ 'RAW' : 'EFI_FV_FILETYPE_RAW',
+ 'PEI_DXE_COMBO' : 'EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER',
+ 'SMM' : 'EFI_FV_FILETYPE_SMM',
+ SUP_MODULE_SMM_CORE : 'EFI_FV_FILETYPE_SMM_CORE',
+ SUP_MODULE_MM_STANDALONE : 'EFI_FV_FILETYPE_MM_STANDALONE',
+ SUP_MODULE_MM_CORE_STANDALONE : 'EFI_FV_FILETYPE_MM_CORE_STANDALONE'
+}
+
+# mapping between section type in FDF and file suffix
+SectionSuffix = {
+ BINARY_FILE_TYPE_PE32 : '.pe32',
+ BINARY_FILE_TYPE_PIC : '.pic',
+ BINARY_FILE_TYPE_TE : '.te',
+ BINARY_FILE_TYPE_DXE_DEPEX : '.dpx',
+ 'VERSION' : '.ver',
+ BINARY_FILE_TYPE_UI : '.ui',
+ 'COMPAT16' : '.com16',
+ 'RAW' : '.raw',
+ 'FREEFORM_SUBTYPE_GUID': '.guid',
+ 'SUBTYPE_GUID' : '.guid',
+ 'FV_IMAGE' : 'fv.sec',
+ 'COMPRESS' : '.com',
+ 'GUIDED' : '.guided',
+ BINARY_FILE_TYPE_PEI_DEPEX : '.dpx',
+ BINARY_FILE_TYPE_SMM_DEPEX : '.dpx'
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py
new file mode 100755
index 00000000..7ab1507d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py
@@ -0,0 +1,175 @@
+## @file
+# process FFS generation from FILE statement
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from io import BytesIO
+from struct import pack
+from CommonDataClass.FdfClass import FileStatementClassObject
+from Common import EdkLogger
+from Common.BuildToolError import GENFDS_ERROR
+from Common.Misc import GuidStructureByteArrayToGuidString, SaveFileOnChange
+import Common.LongFilePathOs as os
+from .GuidSection import GuidSection
+from .FvImageSection import FvImageSection
+from .Ffs import FdfFvFileTypeToFileType
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+import shutil
+
+## generate FFS from FILE
+#
+#
+class FileStatement (FileStatementClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ FileStatementClassObject.__init__(self)
+ self.CurrentLineNum = None
+ self.CurrentLineContent = None
+ self.FileName = None
+ self.InfFileName = None
+ self.SubAlignment = None
+
+ ## GenFfs() method
+ #
+ # Generate FFS
+ #
+ # @param self The object pointer
+ # @param Dict dictionary contains macro and value pair
+ # @param FvChildAddr Array of the inside FvImage base address
+ # @param FvParentAddr Parent Fv base address
+ # @retval string Generated FFS file name
+ #
+ def GenFfs(self, Dict = None, FvChildAddr=[], FvParentAddr=None, IsMakefile=False, FvName=None):
+
+ if self.NameGuid and self.NameGuid.startswith('PCD('):
+ PcdValue = GenFdsGlobalVariable.GetPcdValue(self.NameGuid)
+ if len(PcdValue) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
+ % (self.NameGuid))
+ if PcdValue.startswith('{'):
+ PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
+ RegistryGuidStr = PcdValue
+ if len(RegistryGuidStr) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
+ % (self.NameGuid))
+ self.NameGuid = RegistryGuidStr
+
+ Str = self.NameGuid
+ if FvName:
+ Str += FvName
+ OutputDir = os.path.join(GenFdsGlobalVariable.FfsDir, Str)
+ if os.path.exists(OutputDir):
+ shutil.rmtree(OutputDir)
+ if not os.path.exists(OutputDir):
+ os.makedirs(OutputDir)
+
+ if Dict is None:
+ Dict = {}
+
+ Dict.update(self.DefineVarDict)
+ SectionAlignments = None
+ if self.FvName:
+ Buffer = BytesIO()
+ if self.FvName.upper() not in GenFdsGlobalVariable.FdfParser.Profile.FvDict:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "FV (%s) is NOT described in FDF file!" % (self.FvName))
+ Fv = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName.upper())
+ FileName = Fv.AddToBuffer(Buffer)
+ SectionFiles = [FileName]
+
+ elif self.FdName:
+ if self.FdName.upper() not in GenFdsGlobalVariable.FdfParser.Profile.FdDict:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "FD (%s) is NOT described in FDF file!" % (self.FdName))
+ Fd = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(self.FdName.upper())
+ FileName = Fd.GenFd()
+ SectionFiles = [FileName]
+
+ elif self.FileName:
+ if hasattr(self, 'FvFileType') and self.FvFileType == 'RAW':
+ if isinstance(self.FileName, list) and isinstance(self.SubAlignment, list) and len(self.FileName) == len(self.SubAlignment):
+ FileContent = BytesIO()
+ MaxAlignIndex = 0
+ MaxAlignValue = 1
+ for Index, File in enumerate(self.FileName):
+ try:
+ f = open(File, 'rb')
+ except:
+ GenFdsGlobalVariable.ErrorLogger("Error opening RAW file %s." % (File))
+ Content = f.read()
+ f.close()
+ AlignValue = 1
+ if self.SubAlignment[Index]:
+ AlignValue = GenFdsGlobalVariable.GetAlignment(self.SubAlignment[Index])
+ if AlignValue > MaxAlignValue:
+ MaxAlignIndex = Index
+ MaxAlignValue = AlignValue
+ FileContent.write(Content)
+ if len(FileContent.getvalue()) % AlignValue != 0:
+ Size = AlignValue - len(FileContent.getvalue()) % AlignValue
+ for i in range(0, Size):
+ FileContent.write(pack('B', 0xFF))
+
+ if FileContent.getvalue() != b'':
+ OutputRAWFile = os.path.join(GenFdsGlobalVariable.FfsDir, self.NameGuid, self.NameGuid + '.raw')
+ SaveFileOnChange(OutputRAWFile, FileContent.getvalue(), True)
+ self.FileName = OutputRAWFile
+ self.SubAlignment = self.SubAlignment[MaxAlignIndex]
+
+ if self.Alignment and self.SubAlignment:
+ if GenFdsGlobalVariable.GetAlignment (self.Alignment) < GenFdsGlobalVariable.GetAlignment (self.SubAlignment):
+ self.Alignment = self.SubAlignment
+ elif self.SubAlignment:
+ self.Alignment = self.SubAlignment
+
+ self.FileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName)
+ #Replace $(SAPCE) with real space
+ self.FileName = self.FileName.replace('$(SPACE)', ' ')
+ SectionFiles = [GenFdsGlobalVariable.MacroExtend(self.FileName, Dict)]
+
+ else:
+ SectionFiles = []
+ Index = 0
+ SectionAlignments = []
+ for section in self.SectionList:
+ Index = Index + 1
+ SecIndex = '%d' %Index
+ # process the inside FvImage from FvSection or GuidSection
+ if FvChildAddr != []:
+ if isinstance(section, FvImageSection):
+ section.FvAddr = FvChildAddr.pop(0)
+ elif isinstance(section, GuidSection):
+ section.FvAddr = FvChildAddr
+ if FvParentAddr and isinstance(section, GuidSection):
+ section.FvParentAddr = FvParentAddr
+
+ if self.KeepReloc == False:
+ section.KeepReloc = False
+ sectList, align = section.GenSection(OutputDir, self.NameGuid, SecIndex, self.KeyStringList, None, Dict)
+ if sectList != []:
+ for sect in sectList:
+ SectionFiles.append(sect)
+ SectionAlignments.append(align)
+
+ #
+ # Prepare the parameter
+ #
+ FfsFileOutput = os.path.join(OutputDir, self.NameGuid + '.ffs')
+ GenFdsGlobalVariable.GenerateFfs(FfsFileOutput, SectionFiles,
+ FdfFvFileTypeToFileType.get(self.FvFileType),
+ self.NameGuid,
+ Fixed=self.Fixed,
+ CheckSum=self.CheckSum,
+ Align=self.Alignment,
+ SectionAlign=SectionAlignments
+ )
+
+ return FfsFileOutput
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsInfStatement.py
new file mode 100755
index 00000000..b7b94231
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsInfStatement.py
@@ -0,0 +1,1128 @@
+## @file
+# process FFS generation from INF statement
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Rule
+import Common.LongFilePathOs as os
+from io import BytesIO
+from struct import *
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from .Ffs import SectionSuffix,FdfFvFileTypeToFileType
+import subprocess
+import sys
+from . import Section
+from . import RuleSimpleFile
+from . import RuleComplexFile
+from CommonDataClass.FdfClass import FfsInfStatementClassObject
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+from Common.DataType import SUP_MODULE_USER_DEFINED
+from Common.DataType import SUP_MODULE_HOST_APPLICATION
+from Common.StringUtils import *
+from Common.Misc import PathClass
+from Common.Misc import GuidStructureByteArrayToGuidString
+from Common.Misc import ProcessDuplicatedInf
+from Common.Misc import GetVariableOffset
+from Common import EdkLogger
+from Common.BuildToolError import *
+from .GuidSection import GuidSection
+from .FvImageSection import FvImageSection
+from Common.Misc import PeImageClass
+from AutoGen.GenDepex import DependencyExpression
+from PatchPcdValue.PatchPcdValue import PatchBinaryFile
+from Common.LongFilePathSupport import CopyLongFilePath
+from Common.LongFilePathSupport import OpenLongFilePath as open
+import Common.GlobalData as GlobalData
+from .DepexSection import DepexSection
+from Common.Misc import SaveFileOnChange
+from Common.Expression import *
+from Common.DataType import *
+
+## generate FFS from INF
+#
+#
+class FfsInfStatement(FfsInfStatementClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ FfsInfStatementClassObject.__init__(self)
+ self.TargetOverrideList = []
+ self.ShadowFromInfFile = None
+ self.KeepRelocFromRule = None
+ self.InDsc = True
+ self.OptRomDefs = {}
+ self.PiSpecVersion = '0x00000000'
+ self.InfModule = None
+ self.FinalTargetSuffixMap = {}
+ self.CurrentLineNum = None
+ self.CurrentLineContent = None
+ self.FileName = None
+ self.InfFileName = None
+ self.OverrideGuid = None
+ self.PatchedBinFile = ''
+ self.MacroDict = {}
+ self.Depex = False
+
+ ## GetFinalTargetSuffixMap() method
+ #
+ # Get final build target list
+ def GetFinalTargetSuffixMap(self):
+ if not self.InfModule or not self.CurrentArch:
+ return []
+ if not self.FinalTargetSuffixMap:
+ FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)
+ for File in FinalBuildTargetList:
+ self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)
+
+ # Check if current INF module has DEPEX
+ if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != SUP_MODULE_USER_DEFINED and self.InfModule.ModuleType != SUP_MODULE_HOST_APPLICATION \
+ and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:
+ ModuleType = self.InfModule.ModuleType
+ PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+
+ if ModuleType != SUP_MODULE_USER_DEFINED and ModuleType != SUP_MODULE_HOST_APPLICATION:
+ for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():
+ if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:
+ self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]
+
+ StrModule = str(self.InfModule)
+ PlatformModule = None
+ if StrModule in PlatformDataBase.Modules:
+ PlatformModule = PlatformDataBase.Modules[StrModule]
+ for LibraryClass in PlatformModule.LibraryClasses:
+ if LibraryClass.startswith("NULL"):
+ self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]
+
+ DependencyList = [self.InfModule]
+ LibraryInstance = {}
+ DepexList = []
+ while len(DependencyList) > 0:
+ Module = DependencyList.pop(0)
+ if not Module:
+ continue
+ for Dep in Module.Depex[self.CurrentArch, ModuleType]:
+ if DepexList != []:
+ DepexList.append('AND')
+ DepexList.append('(')
+ DepexList.extend(Dep)
+ if DepexList[-1] == 'END': # no need of a END at this time
+ DepexList.pop()
+ DepexList.append(')')
+ if 'BEFORE' in DepexList or 'AFTER' in DepexList:
+ break
+ for LibName in Module.LibraryClasses:
+ if LibName in LibraryInstance:
+ continue
+ if PlatformModule and LibName in PlatformModule.LibraryClasses:
+ LibraryPath = PlatformModule.LibraryClasses[LibName]
+ else:
+ LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]
+ if not LibraryPath:
+ LibraryPath = Module.LibraryClasses[LibName]
+ if not LibraryPath:
+ continue
+ LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ LibraryInstance[LibName] = LibraryModule
+ DependencyList.append(LibraryModule)
+ if DepexList:
+ Dpx = DependencyExpression(DepexList, ModuleType, True)
+ if len(Dpx.PostfixNotation) != 0:
+ # It means this module has DEPEX
+ self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']
+ return self.FinalTargetSuffixMap
+
+ ## __InfParse() method
+ #
+ # Parse inf file to get module information
+ #
+ # @param self The object pointer
+ # @param Dict dictionary contains macro and value pair
+ #
+ def __InfParse__(self, Dict = None, IsGenFfs=False):
+
+ GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)
+
+ self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')
+ if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':
+ pass
+ elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :
+ self.InfFileName = self.InfFileName[1:]
+
+ if self.InfFileName.find('$') == -1:
+ InfPath = NormPath(self.InfFileName)
+ if not os.path.exists(InfPath):
+ InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)
+ if not os.path.exists(InfPath):
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))
+
+ self.CurrentArch = self.GetCurrentArch()
+ #
+ # Get the InfClass object
+ #
+
+ PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
+ ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ #
+ # Cache lower case version of INF path before processing FILE_GUID override
+ #
+ InfLowerPath = str(PathClassObj).lower()
+ if self.OverrideGuid:
+ PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)
+ if self.CurrentArch is not None:
+
+ Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ #
+ # Set Ffs BaseName, ModuleGuid, ModuleType, Version, OutputPath
+ #
+ self.BaseName = Inf.BaseName
+ self.ModuleGuid = Inf.Guid
+ self.ModuleType = Inf.ModuleType
+ if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
+ self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
+ if Inf.AutoGenVersion < 0x00010005:
+ self.ModuleType = Inf.ComponentType
+ self.VersionString = Inf.Version
+ self.BinFileList = Inf.Binaries
+ self.SourceFileList = Inf.Sources
+ if self.KeepReloc is None and Inf.Shadow:
+ self.ShadowFromInfFile = Inf.Shadow
+
+ else:
+ Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ self.BaseName = Inf.BaseName
+ self.ModuleGuid = Inf.Guid
+ self.ModuleType = Inf.ModuleType
+ if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
+ self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
+ self.VersionString = Inf.Version
+ self.BinFileList = Inf.Binaries
+ self.SourceFileList = Inf.Sources
+ if self.BinFileList == []:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ "INF %s specified in FDF could not be found in build ARCH %s!" \
+ % (self.InfFileName, GenFdsGlobalVariable.ArchList))
+
+ if self.OverrideGuid:
+ self.ModuleGuid = self.OverrideGuid
+
+ if len(self.SourceFileList) != 0 and not self.InDsc:
+ EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))
+
+ if self.ModuleType == SUP_MODULE_SMM_CORE and int(self.PiSpecVersion, 16) < 0x0001000A:
+ 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)
+
+ if self.ModuleType == SUP_MODULE_MM_CORE_STANDALONE and int(self.PiSpecVersion, 16) < 0x00010032:
+ EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.InfFileName)
+
+ if Inf._Defs is not None and len(Inf._Defs) > 0:
+ self.OptRomDefs.update(Inf._Defs)
+
+ self.PatchPcds = []
+ InfPcds = Inf.Pcds
+ Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict
+ PlatformPcds = Platform.Pcds
+
+ # Workaround here: both build and GenFds tool convert the workspace path to lower case
+ # But INF file path in FDF and DSC file may have real case characters.
+ # Try to convert the path to lower case to see if PCDs value are override by DSC.
+ DscModules = {}
+ for DscModule in Platform.Modules:
+ DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]
+ for PcdKey in InfPcds:
+ Pcd = InfPcds[PcdKey]
+ if not hasattr(Pcd, 'Offset'):
+ continue
+ if Pcd.Type != TAB_PCDS_PATCHABLE_IN_MODULE:
+ continue
+ # Override Patchable PCD value by the value from DSC
+ PatchPcd = None
+ if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:
+ PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]
+ elif PcdKey in Platform.Pcds:
+ PatchPcd = Platform.Pcds[PcdKey]
+ DscOverride = False
+ if PatchPcd and Pcd.Type == PatchPcd.Type:
+ DefaultValue = PatchPcd.DefaultValue
+ DscOverride = True
+
+ # Override Patchable PCD value by the value from FDF
+ FdfOverride = False
+ if PcdKey in FdfPcdDict:
+ DefaultValue = FdfPcdDict[PcdKey]
+ FdfOverride = True
+
+ # Override Patchable PCD value by the value from Build Option
+ BuildOptionOverride = False
+ if GlobalData.BuildOptionPcd:
+ for pcd in GlobalData.BuildOptionPcd:
+ if PcdKey == (pcd[1], pcd[0]):
+ if pcd[2]:
+ continue
+ DefaultValue = pcd[3]
+ BuildOptionOverride = True
+ break
+
+ if not DscOverride and not FdfOverride and not BuildOptionOverride:
+ continue
+
+ # Support Flexible PCD format
+ if DefaultValue:
+ try:
+ DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName)
+
+ if Pcd.InfDefaultValue:
+ try:
+ Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue), File=self.InfFileName)
+
+ # Check value, if value are equal, no need to patch
+ if Pcd.DatumType == TAB_VOID:
+ if Pcd.InfDefaultValue == DefaultValue or not DefaultValue:
+ continue
+ # Get the string size from FDF or DSC
+ if DefaultValue[0] == 'L':
+ # Remove L"", but the '\0' must be appended
+ MaxDatumSize = str((len(DefaultValue) - 2) * 2)
+ elif DefaultValue[0] == '{':
+ MaxDatumSize = str(len(DefaultValue.split(',')))
+ else:
+ MaxDatumSize = str(len(DefaultValue) - 1)
+ if DscOverride:
+ Pcd.MaxDatumSize = PatchPcd.MaxDatumSize
+ # If no defined the maximum size in DSC, try to get current size from INF
+ if not Pcd.MaxDatumSize:
+ Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))
+ else:
+ Base1 = Base2 = 10
+ if Pcd.InfDefaultValue.upper().startswith('0X'):
+ Base1 = 16
+ if DefaultValue.upper().startswith('0X'):
+ Base2 = 16
+ try:
+ PcdValueInImg = int(Pcd.InfDefaultValue, Base1)
+ PcdValueInDscOrFdf = int(DefaultValue, Base2)
+ if PcdValueInImg == PcdValueInDscOrFdf:
+ continue
+ except:
+ continue
+ # Check the Pcd size and data type
+ if Pcd.DatumType == TAB_VOID:
+ if int(MaxDatumSize) > int(Pcd.MaxDatumSize):
+ EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \
+ % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))
+ else:
+ if PcdValueInDscOrFdf > MAX_VAL_TYPE[Pcd.DatumType] \
+ or PcdValueInImg > MAX_VAL_TYPE[Pcd.DatumType]:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \
+ % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
+ self.PatchPcds.append((Pcd, DefaultValue))
+
+ self.InfModule = Inf
+ self.PcdIsDriver = Inf.PcdIsDriver
+ self.IsBinaryModule = Inf.IsBinaryModule
+ if len(Inf.Depex.data) > 0 and len(Inf.DepexExpression.data) > 0:
+ self.Depex = True
+
+ GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)
+ GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)
+ GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)
+ GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)
+ GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)
+
+ #
+ # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${ModuleName}\
+ #
+ if IsGenFfs:
+ Rule = self.__GetRule__()
+ if GlobalData.gGuidPatternEnd.match(Rule.NameGuid):
+ self.ModuleGuid = Rule.NameGuid
+ self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \
+ self.ModuleGuid + self.BaseName)
+ if not os.path.exists(self.OutputPath) :
+ os.makedirs(self.OutputPath)
+
+ self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()
+ GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)
+
+ ## PatchEfiFile
+ #
+ # Patch EFI file with patch PCD
+ #
+ # @param EfiFile: EFI file needs to be patched.
+ # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
+ # If passed in file does not end with efi, return as is
+ #
+ def PatchEfiFile(self, EfiFile, FileType):
+ #
+ # If the module does not have any patches, then return path to input file
+ #
+ if not self.PatchPcds:
+ return EfiFile
+
+ #
+ # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
+ #
+ if FileType != BINARY_FILE_TYPE_PE32 and self.ModuleType != SUP_MODULE_USER_DEFINED and self.ModuleType != SUP_MODULE_HOST_APPLICATION:
+ return EfiFile
+
+ #
+ # Generate path to patched output file
+ #
+ Basename = os.path.basename(EfiFile)
+ Output = os.path.normpath (os.path.join(self.OutputPath, Basename))
+
+ #
+ # If this file has already been patched, then return the path to the patched file
+ #
+ if self.PatchedBinFile == Output:
+ return Output
+
+ #
+ # If a different file from the same module has already been patched, then generate an error
+ #
+ if self.PatchedBinFile:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ 'Only one binary file can be patched:\n'
+ ' a binary file has been patched: %s\n'
+ ' current file: %s' % (self.PatchedBinFile, EfiFile),
+ File=self.InfFileName)
+
+ #
+ # Copy unpatched file contents to output file location to perform patching
+ #
+ CopyLongFilePath(EfiFile, Output)
+
+ #
+ # Apply patches to patched output file
+ #
+ for Pcd, Value in self.PatchPcds:
+ RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)
+ if RetVal:
+ EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)
+
+ #
+ # Save the path of the patched output file
+ #
+ self.PatchedBinFile = Output
+
+ #
+ # Return path to patched output file
+ #
+ return Output
+
+ ## GenFfs() method
+ #
+ # Generate FFS
+ #
+ # @param self The object pointer
+ # @param Dict dictionary contains macro and value pair
+ # @param FvChildAddr Array of the inside FvImage base address
+ # @param FvParentAddr Parent Fv base address
+ # @retval string Generated FFS file name
+ #
+ def GenFfs(self, Dict = None, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None):
+ #
+ # Parse Inf file get Module related information
+ #
+ if Dict is None:
+ Dict = {}
+ self.__InfParse__(Dict, IsGenFfs=True)
+ Arch = self.GetCurrentArch()
+ SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName);
+ DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
+
+ SrcFileDir = "."
+ SrcPath = os.path.dirname(SrcFile)
+ SrcFileName = os.path.basename(SrcFile)
+ SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName)
+ DestPath = os.path.dirname(DestFile)
+ DestFileName = os.path.basename(DestFile)
+ DestFileBase, DestFileExt = os.path.splitext(DestFileName)
+ self.MacroDict = {
+ # source file
+ "${src}" : SrcFile,
+ "${s_path}" : SrcPath,
+ "${s_dir}" : SrcFileDir,
+ "${s_name}" : SrcFileName,
+ "${s_base}" : SrcFileBase,
+ "${s_ext}" : SrcFileExt,
+ # destination file
+ "${dst}" : DestFile,
+ "${d_path}" : DestPath,
+ "${d_name}" : DestFileName,
+ "${d_base}" : DestFileBase,
+ "${d_ext}" : DestFileExt
+ }
+ #
+ # Allow binary type module not specify override rule in FDF file.
+ #
+ if len(self.BinFileList) > 0:
+ if self.Rule is None or self.Rule == "":
+ self.Rule = "BINARY"
+
+ if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':
+ IsMakefile = True
+ #
+ # Get the rule of how to generate Ffs file
+ #
+ Rule = self.__GetRule__()
+ GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
+ #
+ # Convert Fv File Type for PI1.1 SMM driver.
+ #
+ if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
+ if Rule.FvFileType == 'DRIVER':
+ Rule.FvFileType = 'SMM'
+ #
+ # Framework SMM Driver has no SMM FV file type
+ #
+ if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
+ if Rule.FvFileType == 'SMM' or Rule.FvFileType == SUP_MODULE_SMM_CORE:
+ EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)
+ #
+ # For the rule only has simpleFile
+ #
+ MakefilePath = None
+ if self.IsBinaryModule:
+ IsMakefile = False
+ if IsMakefile:
+ PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
+ if self.OverrideGuid:
+ PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)
+ MakefilePath = PathClassObj.Path, Arch
+ if isinstance (Rule, RuleSimpleFile.RuleSimpleFile):
+ SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)
+ FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)
+ return FfsOutput
+ #
+ # For Rule has ComplexFile
+ #
+ elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
+ InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)
+ FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)
+ return FfsOutput
+
+ ## __ExtendMacro__() method
+ #
+ # Replace macro with its value
+ #
+ # @param self The object pointer
+ # @param String The string to be replaced
+ # @retval string Macro replaced string
+ #
+ def __ExtendMacro__ (self, String):
+ MacroDict = {
+ '$(INF_OUTPUT)' : self.EfiOutputPath,
+ '$(MODULE_NAME)' : self.BaseName,
+ '$(BUILD_NUMBER)': self.BuildNum,
+ '$(INF_VERSION)' : self.VersionString,
+ '$(NAMED_GUID)' : self.ModuleGuid
+ }
+ String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)
+ String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict)
+ return String
+
+ ## __GetRule__() method
+ #
+ # Get correct rule for generating FFS for this INF
+ #
+ # @param self The object pointer
+ # @retval Rule Rule object
+ #
+ def __GetRule__ (self) :
+ CurrentArchList = []
+ if self.CurrentArch is None:
+ CurrentArchList = ['common']
+ else:
+ CurrentArchList.append(self.CurrentArch)
+
+ for CurrentArch in CurrentArchList:
+ RuleName = 'RULE' + \
+ '.' + \
+ CurrentArch.upper() + \
+ '.' + \
+ self.ModuleType.upper()
+ if self.Rule is not None:
+ RuleName = RuleName + \
+ '.' + \
+ self.Rule.upper()
+
+ Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
+ if Rule is not None:
+ GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
+ return Rule
+
+ RuleName = 'RULE' + \
+ '.' + \
+ TAB_COMMON + \
+ '.' + \
+ self.ModuleType.upper()
+
+ if self.Rule is not None:
+ RuleName = RuleName + \
+ '.' + \
+ self.Rule.upper()
+
+ GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))
+
+ Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
+ if Rule is not None:
+ GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
+ return Rule
+
+ if Rule is None :
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \
+ % (RuleName, self.InfFileName))
+
+ ## __GetPlatformArchList__() method
+ #
+ # Get Arch list this INF built under
+ #
+ # @param self The object pointer
+ # @retval list Arch list
+ #
+ def __GetPlatformArchList__(self):
+
+ InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
+ DscArchList = []
+ for Arch in GenFdsGlobalVariable.ArchList :
+ PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ if PlatformDataBase is not None:
+ if InfFileKey in PlatformDataBase.Modules:
+ DscArchList.append (Arch)
+ else:
+ #
+ # BaseTools support build same module more than once, the module path with FILE_GUID overridden has
+ # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,
+ # but the path (self.MetaFile.Path) is the real path
+ #
+ for key in PlatformDataBase.Modules:
+ if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):
+ DscArchList.append (Arch)
+ break
+
+ return DscArchList
+
+ ## GetCurrentArch() method
+ #
+ # Get Arch list of the module from this INF is to be placed into flash
+ #
+ # @param self The object pointer
+ # @retval list Arch list
+ #
+ def GetCurrentArch(self) :
+
+ TargetArchList = GenFdsGlobalVariable.ArchList
+
+ PlatformArchList = self.__GetPlatformArchList__()
+
+ CurArchList = TargetArchList
+ if PlatformArchList != []:
+ CurArchList = list(set (TargetArchList) & set (PlatformArchList))
+ GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
+
+ ArchList = []
+ if self.KeyStringList != []:
+ for Key in self.KeyStringList:
+ Key = GenFdsGlobalVariable.MacroExtend(Key)
+ Target, Tag, Arch = Key.split('_')
+ if Arch in CurArchList:
+ ArchList.append(Arch)
+ if Target not in self.TargetOverrideList:
+ self.TargetOverrideList.append(Target)
+ else:
+ ArchList = CurArchList
+
+ UseArchList = TargetArchList
+ if self.UseArch is not None:
+ UseArchList = []
+ UseArchList.append(self.UseArch)
+ ArchList = list(set (UseArchList) & set (ArchList))
+
+ self.InfFileName = NormPath(self.InfFileName)
+ if len(PlatformArchList) == 0:
+ self.InDsc = False
+ PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
+ ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+ if len(ArchList) == 1:
+ Arch = ArchList[0]
+ return Arch
+ elif len(ArchList) > 1:
+ if len(PlatformArchList) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "GenFds command line option has multiple ARCHs %s. Not able to determine which ARCH is valid for Module %s !" % (str(ArchList), self.InfFileName))
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Module built under multiple ARCHs %s. Not able to determine which output to put into flash for Module %s !" % (str(ArchList), self.InfFileName))
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current deduced ARCH is %s, so NO build output could be put into flash." \
+ % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
+
+ ## __GetEFIOutPutPath__() method
+ #
+ # Get the output path for generated files
+ #
+ # @param self The object pointer
+ # @retval string Path that output files from this INF go to
+ #
+ def __GetEFIOutPutPath__(self):
+ Arch = ''
+ OutputPath = ''
+ DebugPath = ''
+ (ModulePath, FileName) = os.path.split(self.InfFileName)
+ Index = FileName.rfind('.')
+ FileName = FileName[0:Index]
+ if self.OverrideGuid:
+ FileName = self.OverrideGuid
+ Arch = "NoneArch"
+ if self.CurrentArch is not None:
+ Arch = self.CurrentArch
+
+ OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
+ Arch,
+ ModulePath,
+ FileName,
+ 'OUTPUT'
+ )
+ DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
+ Arch,
+ ModulePath,
+ FileName,
+ 'DEBUG'
+ )
+ OutputPath = os.path.realpath(OutputPath)
+ DebugPath = os.path.realpath(DebugPath)
+ return OutputPath, DebugPath
+
+ ## __GenSimpleFileSection__() method
+ #
+ # Generate section by specified file name or a list of files with file extension
+ #
+ # @param self The object pointer
+ # @param Rule The rule object used to generate section
+ # @retval string File name of the generated section file
+ #
+ def __GenSimpleFileSection__(self, Rule, IsMakefile = False):
+ #
+ # Prepare the parameter of GenSection
+ #
+ FileList = []
+ OutputFileList = []
+ GenSecInputFile = None
+ if Rule.FileName is not None:
+ GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
+ if os.path.isabs(GenSecInputFile):
+ GenSecInputFile = os.path.normpath(GenSecInputFile)
+ else:
+ GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))
+ else:
+ FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
+
+ Index = 1
+ SectionType = Rule.SectionType
+ #
+ # Convert Fv Section Type for PI1.1 SMM driver.
+ #
+ if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
+ if SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
+ SectionType = BINARY_FILE_TYPE_SMM_DEPEX
+ #
+ # Framework SMM Driver has no SMM_DEPEX section type
+ #
+ if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
+ if SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
+ EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
+ NoStrip = True
+ if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM):
+ if self.KeepReloc is not None:
+ NoStrip = self.KeepReloc
+ elif Rule.KeepReloc is not None:
+ NoStrip = Rule.KeepReloc
+ elif self.ShadowFromInfFile is not None:
+ NoStrip = self.ShadowFromInfFile
+
+ if FileList != [] :
+ for File in FileList:
+
+ SecNum = '%d' %Index
+ GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
+ SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
+ Index = Index + 1
+ OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
+ File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
+
+ #Get PE Section alignment when align is set to AUTO
+ if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
+ ImageObj = PeImageClass (File)
+ if ImageObj.SectionAlignment < 0x400:
+ self.Alignment = str (ImageObj.SectionAlignment)
+ elif ImageObj.SectionAlignment < 0x100000:
+ self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
+ else:
+ self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
+
+ if not NoStrip:
+ FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
+ if not os.path.exists(FileBeforeStrip) or \
+ (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
+ CopyLongFilePath(File, FileBeforeStrip)
+ StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ StrippedFile,
+ [File],
+ Strip=True,
+ IsMakefile=IsMakefile
+ )
+ File = StrippedFile
+
+ if SectionType == BINARY_FILE_TYPE_TE:
+ TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ TeFile,
+ [File],
+ Type='te',
+ IsMakefile=IsMakefile
+ )
+ File = TeFile
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+ else:
+ SecNum = '%d' %Index
+ GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
+ SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
+ OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
+ GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
+
+ #Get PE Section alignment when align is set to AUTO
+ if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
+ ImageObj = PeImageClass (GenSecInputFile)
+ if ImageObj.SectionAlignment < 0x400:
+ self.Alignment = str (ImageObj.SectionAlignment)
+ elif ImageObj.SectionAlignment < 0x100000:
+ self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
+ else:
+ self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
+
+ if not NoStrip:
+ FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
+ if not os.path.exists(FileBeforeStrip) or \
+ (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
+ CopyLongFilePath(GenSecInputFile, FileBeforeStrip)
+
+ StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ StrippedFile,
+ [GenSecInputFile],
+ Strip=True,
+ IsMakefile=IsMakefile
+ )
+ GenSecInputFile = StrippedFile
+
+ if SectionType == BINARY_FILE_TYPE_TE:
+ TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
+ GenFdsGlobalVariable.GenerateFirmwareImage(
+ TeFile,
+ [GenSecInputFile],
+ Type='te',
+ IsMakefile=IsMakefile
+ )
+ GenSecInputFile = TeFile
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ return OutputFileList
+
+ ## __GenSimpleFileFfs__() method
+ #
+ # Generate FFS
+ #
+ # @param self The object pointer
+ # @param Rule The rule object used to generate section
+ # @param InputFileList The output file list from GenSection
+ # @retval string Generated FFS file name
+ #
+ def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):
+ FfsOutput = self.OutputPath + \
+ os.sep + \
+ self.__ExtendMacro__(Rule.NameGuid) + \
+ '.ffs'
+
+ GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
+ InputSection = []
+ SectionAlignments = []
+ for InputFile in InputFileList:
+ InputSection.append(InputFile)
+ SectionAlignments.append(Rule.SectAlignment)
+
+ if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
+ PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
+ if len(PcdValue) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
+ % (Rule.NameGuid))
+ if PcdValue.startswith('{'):
+ PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
+ RegistryGuidStr = PcdValue
+ if len(RegistryGuidStr) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
+ % (Rule.NameGuid))
+ self.ModuleGuid = RegistryGuidStr
+
+ GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
+ FdfFvFileTypeToFileType[Rule.FvFileType],
+ self.ModuleGuid, Fixed=Rule.Fixed,
+ CheckSum=Rule.CheckSum, Align=Rule.Alignment,
+ SectionAlign=SectionAlignments,
+ MakefilePath=MakefilePath
+ )
+ return FfsOutput
+
+ ## __GenComplexFileSection__() method
+ #
+ # Generate section by sections in Rule
+ #
+ # @param self The object pointer
+ # @param Rule The rule object used to generate section
+ # @param FvChildAddr Array of the inside FvImage base address
+ # @param FvParentAddr Parent Fv base address
+ # @retval string File name of the generated section file
+ #
+ def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):
+ if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE):
+ if Rule.KeepReloc is not None:
+ self.KeepRelocFromRule = Rule.KeepReloc
+ SectFiles = []
+ SectAlignments = []
+ Index = 1
+ HasGeneratedFlag = False
+ if self.PcdIsDriver == 'PEI_PCD_DRIVER':
+ if self.IsBinaryModule:
+ PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")
+ else:
+ PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")
+ PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")
+ GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
+ [PcdExDbFileName],
+ "EFI_SECTION_RAW",
+ IsMakefile = IsMakefile
+ )
+ SectFiles.append(PcdExDbSecName)
+ SectAlignments.append(None)
+ elif self.PcdIsDriver == 'DXE_PCD_DRIVER':
+ if self.IsBinaryModule:
+ PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")
+ else:
+ PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")
+ PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")
+ GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,
+ [PcdExDbFileName],
+ "EFI_SECTION_RAW",
+ IsMakefile = IsMakefile
+ )
+ SectFiles.append(PcdExDbSecName)
+ SectAlignments.append(None)
+ for Sect in Rule.SectionList:
+ SecIndex = '%d' %Index
+ SectList = []
+ #
+ # Convert Fv Section Type for PI1.1 SMM driver.
+ #
+ if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
+ if Sect.SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
+ Sect.SectionType = BINARY_FILE_TYPE_SMM_DEPEX
+ #
+ # Framework SMM Driver has no SMM_DEPEX section type
+ #
+ if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
+ if Sect.SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
+ EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
+ #
+ # process the inside FvImage from FvSection or GuidSection
+ #
+ if FvChildAddr != []:
+ if isinstance(Sect, FvImageSection):
+ Sect.FvAddr = FvChildAddr.pop(0)
+ elif isinstance(Sect, GuidSection):
+ Sect.FvAddr = FvChildAddr
+ if FvParentAddr is not None and isinstance(Sect, GuidSection):
+ Sect.FvParentAddr = FvParentAddr
+
+ if Rule.KeyStringList != []:
+ SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)
+ else :
+ SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)
+
+ if not HasGeneratedFlag:
+ UniVfrOffsetFileSection = ""
+ ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
+ InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]
+ #
+ # Search the source list in InfData to find if there are .vfr file exist.
+ #
+ VfrUniBaseName = {}
+ VfrUniOffsetList = []
+ for SourceFile in InfData.Sources:
+ if SourceFile.Type.upper() == ".VFR" :
+ #
+ # search the .map file to find the offset of vfr binary in the PE32+/TE file.
+ #
+ VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
+ if SourceFile.Type.upper() == ".UNI" :
+ #
+ # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
+ #
+ VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")
+
+
+ if len(VfrUniBaseName) > 0:
+ if IsMakefile:
+ if InfData.BuildType != 'UEFI_HII':
+ UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
+ UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
+ UniVfrOffsetFileNameList = []
+ UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
+ TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)
+ GenFdsGlobalVariable.SecCmdList.append(TrimCmd)
+ GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
+ [UniVfrOffsetFileName],
+ "EFI_SECTION_RAW",
+ IsMakefile = True
+ )
+ else:
+ VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
+ #
+ # Generate the Raw data of raw section
+ #
+ if VfrUniOffsetList:
+ UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
+ UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
+ FfsInfStatement.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
+ UniVfrOffsetFileNameList = []
+ UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
+ """Call GenSection"""
+
+ GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
+ UniVfrOffsetFileNameList,
+ "EFI_SECTION_RAW"
+ )
+ #os.remove(UniVfrOffsetFileName)
+ if UniVfrOffsetFileSection:
+ SectList.append(UniVfrOffsetFileSection)
+ HasGeneratedFlag = True
+
+ for SecName in SectList :
+ SectFiles.append(SecName)
+ SectAlignments.append(Align)
+ Index = Index + 1
+ return SectFiles, SectAlignments
+
+ ## __GenComplexFileFfs__() method
+ #
+ # Generate FFS
+ #
+ # @param self The object pointer
+ # @param Rule The rule object used to generate section
+ # @param InputFileList The output file list from GenSection
+ # @retval string Generated FFS file name
+ #
+ def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):
+
+ if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
+ PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
+ if len(PcdValue) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
+ % (Rule.NameGuid))
+ if PcdValue.startswith('{'):
+ PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
+ RegistryGuidStr = PcdValue
+ if len(RegistryGuidStr) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
+ % (Rule.NameGuid))
+ self.ModuleGuid = RegistryGuidStr
+
+ FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
+ GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
+ FdfFvFileTypeToFileType[Rule.FvFileType],
+ self.ModuleGuid, Fixed=Rule.Fixed,
+ CheckSum=Rule.CheckSum, Align=Rule.Alignment,
+ SectionAlign=Alignments,
+ MakefilePath=MakefilePath
+ )
+ return FfsOutput
+
+ ## __GetBuildOutputMapFileVfrUniInfo() method
+ #
+ # Find the offset of UNI/INF object offset in the EFI image file.
+ #
+ # @param self The object pointer
+ # @param VfrUniBaseName A name list contain the UNI/INF object name.
+ # @retval RetValue A list contain offset of UNI/INF object.
+ #
+ def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):
+ MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")
+ EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")
+ return GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
+
+ ## __GenUniVfrOffsetFile() method
+ #
+ # Generate the offset file for the module which contain VFR or UNI file.
+ #
+ # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
+ # @param UniVfrOffsetFileName The output offset file name.
+ #
+ @staticmethod
+ def __GenUniVfrOffsetFile(VfrUniOffsetList, UniVfrOffsetFileName):
+
+ # Use a instance of StringIO to cache data
+ fStringIO = BytesIO()
+
+ for Item in VfrUniOffsetList:
+ if (Item[0].find("Strings") != -1):
+ #
+ # UNI offset in image.
+ # GUID + Offset
+ # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
+ #
+ UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
+ fStringIO.write(UniGuid)
+ UniValue = pack ('Q', int (Item[1], 16))
+ fStringIO.write (UniValue)
+ else:
+ #
+ # VFR binary offset in image.
+ # GUID + Offset
+ # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
+ #
+ VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
+ fStringIO.write(VfrGuid)
+ type (Item[1])
+ VfrValue = pack ('Q', int (Item[1], 16))
+ fStringIO.write (VfrValue)
+
+ #
+ # write data into file.
+ #
+ try :
+ SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())
+ except:
+ EdkLogger.error("GenFds", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %UniVfrOffsetFileName, None)
+
+ fStringIO.close ()
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fv.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fv.py
new file mode 100755
index 00000000..798eb1f5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Fv.py
@@ -0,0 +1,431 @@
+## @file
+# process FV generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+import Common.LongFilePathOs as os
+import subprocess
+from io import BytesIO
+from struct import *
+from . import FfsFileStatement
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from Common.Misc import SaveFileOnChange, PackGUID
+from Common.LongFilePathSupport import CopyLongFilePath
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.DataType import *
+
+FV_UI_EXT_ENTY_GUID = 'A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C'
+
+## generate FV
+#
+#
+class FV (object):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self, Name=None):
+ self.UiFvName = Name
+ self.CreateFileName = None
+ self.BlockSizeList = []
+ self.DefineVarDict = {}
+ self.SetVarDict = {}
+ self.FvAlignment = None
+ self.FvAttributeDict = {}
+ self.FvNameGuid = None
+ self.FvNameString = None
+ self.AprioriSectionList = []
+ self.FfsList = []
+ self.BsBaseAddress = None
+ self.RtBaseAddress = None
+ self.FvInfFile = None
+ self.FvAddressFile = None
+ self.BaseAddress = None
+ self.InfFileName = None
+ self.FvAddressFileName = None
+ self.CapsuleName = None
+ self.FvBaseAddress = None
+ self.FvForceRebase = None
+ self.FvRegionInFD = None
+ self.UsedSizeEnable = False
+ self.FvExtEntryTypeValue = []
+ self.FvExtEntryType = []
+ self.FvExtEntryData = []
+ ## AddToBuffer()
+ #
+ # Generate Fv and add it to the Buffer
+ #
+ # @param self The object pointer
+ # @param Buffer The buffer generated FV data will be put
+ # @param BaseAddress base address of FV
+ # @param BlockSize block size of FV
+ # @param BlockNum How many blocks in FV
+ # @param ErasePolarity Flash erase polarity
+ # @param MacroDict macro value pair
+ # @retval string Generated FV file path
+ #
+ def AddToBuffer (self, Buffer, BaseAddress=None, BlockSize= None, BlockNum=None, ErasePloarity='1', MacroDict = None, Flag=False):
+ if BaseAddress is None and self.UiFvName.upper() + 'fv' in GenFdsGlobalVariable.ImageBinDict:
+ return GenFdsGlobalVariable.ImageBinDict[self.UiFvName.upper() + 'fv']
+ if MacroDict is None:
+ MacroDict = {}
+
+ #
+ # Check whether FV in Capsule is in FD flash region.
+ # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
+ #
+ if self.CapsuleName is not None:
+ for FdObj in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():
+ for RegionObj in FdObj.RegionList:
+ if RegionObj.RegionType == BINARY_FILE_TYPE_FV:
+ for RegionData in RegionObj.RegionDataList:
+ if RegionData.endswith(".fv"):
+ continue
+ elif RegionData.upper() + 'fv' in GenFdsGlobalVariable.ImageBinDict:
+ continue
+ elif self.UiFvName.upper() == RegionData.upper():
+ GenFdsGlobalVariable.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self.CapsuleName, self.UiFvName.upper()))
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger( "\nGenerating %s FV" %self.UiFvName)
+ GenFdsGlobalVariable.LargeFileInFvFlags.append(False)
+ FFSGuid = None
+
+ if self.FvBaseAddress is not None:
+ BaseAddress = self.FvBaseAddress
+ if not Flag:
+ self._InitializeInf(BaseAddress, BlockSize, BlockNum, ErasePloarity)
+ #
+ # First Process the Apriori section
+ #
+ MacroDict.update(self.DefineVarDict)
+
+ GenFdsGlobalVariable.VerboseLogger('First generate Apriori file !')
+ FfsFileList = []
+ for AprSection in self.AprioriSectionList:
+ FileName = AprSection.GenFfs (self.UiFvName, MacroDict, IsMakefile=Flag)
+ FfsFileList.append(FileName)
+ # Add Apriori file name to Inf file
+ if not Flag:
+ self.FvInfFile.append("EFI_FILE_NAME = " + \
+ FileName + \
+ TAB_LINE_BREAK)
+
+ # Process Modules in FfsList
+ for FfsFile in self.FfsList:
+ if Flag:
+ if isinstance(FfsFile, FfsFileStatement.FileStatement):
+ continue
+ if GenFdsGlobalVariable.EnableGenfdsMultiThread and GenFdsGlobalVariable.ModuleFile and GenFdsGlobalVariable.ModuleFile.Path.find(os.path.normpath(FfsFile.InfFileName)) == -1:
+ continue
+ FileName = FfsFile.GenFfs(MacroDict, FvParentAddr=BaseAddress, IsMakefile=Flag, FvName=self.UiFvName)
+ FfsFileList.append(FileName)
+ if not Flag:
+ self.FvInfFile.append("EFI_FILE_NAME = " + \
+ FileName + \
+ TAB_LINE_BREAK)
+ if not Flag:
+ FvInfFile = ''.join(self.FvInfFile)
+ SaveFileOnChange(self.InfFileName, FvInfFile, False)
+ #
+ # Call GenFv tool
+ #
+ FvOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName)
+ FvOutputFile = FvOutputFile + '.Fv'
+ # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
+ if self.CreateFileName is not None:
+ FvOutputFile = self.CreateFileName
+
+ if Flag:
+ GenFdsGlobalVariable.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile
+ return FvOutputFile
+
+ FvInfoFileName = os.path.join(GenFdsGlobalVariable.FfsDir, self.UiFvName + '.inf')
+ if not Flag:
+ CopyLongFilePath(GenFdsGlobalVariable.FvAddressFileName, FvInfoFileName)
+ OrigFvInfo = None
+ if os.path.exists (FvInfoFileName):
+ OrigFvInfo = open(FvInfoFileName, 'r').read()
+ if GenFdsGlobalVariable.LargeFileInFvFlags[-1]:
+ FFSGuid = GenFdsGlobalVariable.EFI_FIRMWARE_FILE_SYSTEM3_GUID
+ GenFdsGlobalVariable.GenerateFirmwareVolume(
+ FvOutputFile,
+ [self.InfFileName],
+ AddressFile=FvInfoFileName,
+ FfsList=FfsFileList,
+ ForceRebase=self.FvForceRebase,
+ FileSystemGuid=FFSGuid
+ )
+
+ NewFvInfo = None
+ if os.path.exists (FvInfoFileName):
+ NewFvInfo = open(FvInfoFileName, 'r').read()
+ if NewFvInfo is not None and NewFvInfo != OrigFvInfo:
+ FvChildAddr = []
+ AddFileObj = open(FvInfoFileName, 'r')
+ AddrStrings = AddFileObj.readlines()
+ AddrKeyFound = False
+ for AddrString in AddrStrings:
+ if AddrKeyFound:
+ #get base address for the inside FvImage
+ FvChildAddr.append (AddrString)
+ elif AddrString.find ("[FV_BASE_ADDRESS]") != -1:
+ AddrKeyFound = True
+ AddFileObj.close()
+
+ if FvChildAddr != []:
+ # Update Ffs again
+ for FfsFile in self.FfsList:
+ FileName = FfsFile.GenFfs(MacroDict, FvChildAddr, BaseAddress, IsMakefile=Flag, FvName=self.UiFvName)
+
+ if GenFdsGlobalVariable.LargeFileInFvFlags[-1]:
+ FFSGuid = GenFdsGlobalVariable.EFI_FIRMWARE_FILE_SYSTEM3_GUID;
+ #Update GenFv again
+ GenFdsGlobalVariable.GenerateFirmwareVolume(
+ FvOutputFile,
+ [self.InfFileName],
+ AddressFile=FvInfoFileName,
+ FfsList=FfsFileList,
+ ForceRebase=self.FvForceRebase,
+ FileSystemGuid=FFSGuid
+ )
+
+ #
+ # Write the Fv contents to Buffer
+ #
+ if os.path.isfile(FvOutputFile) and os.path.getsize(FvOutputFile) >= 0x48:
+ FvFileObj = open(FvOutputFile, 'rb')
+ # PI FvHeader is 0x48 byte
+ FvHeaderBuffer = FvFileObj.read(0x48)
+ Signature = FvHeaderBuffer[0x28:0x32]
+ if Signature and Signature.startswith(b'_FVH'):
+ GenFdsGlobalVariable.VerboseLogger("\nGenerate %s FV Successfully" % self.UiFvName)
+ GenFdsGlobalVariable.SharpCounter = 0
+
+ FvFileObj.seek(0)
+ Buffer.write(FvFileObj.read())
+ # FV alignment position.
+ FvAlignmentValue = 1 << (ord(FvHeaderBuffer[0x2E:0x2F]) & 0x1F)
+ if FvAlignmentValue >= 0x400:
+ if FvAlignmentValue >= 0x100000:
+ if FvAlignmentValue >= 0x1000000:
+ #The max alignment supported by FFS is 16M.
+ self.FvAlignment = "16M"
+ else:
+ self.FvAlignment = str(FvAlignmentValue // 0x100000) + "M"
+ else:
+ self.FvAlignment = str(FvAlignmentValue // 0x400) + "K"
+ else:
+ # FvAlignmentValue is less than 1K
+ self.FvAlignment = str (FvAlignmentValue)
+ FvFileObj.close()
+ GenFdsGlobalVariable.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile
+ GenFdsGlobalVariable.LargeFileInFvFlags.pop()
+ else:
+ GenFdsGlobalVariable.ErrorLogger("Invalid FV file %s." % self.UiFvName)
+ else:
+ GenFdsGlobalVariable.ErrorLogger("Failed to generate %s FV file." %self.UiFvName)
+ return FvOutputFile
+
+ ## _GetBlockSize()
+ #
+ # Calculate FV's block size
+ # Inherit block size from FD if no block size specified in FV
+ #
+ def _GetBlockSize(self):
+ if self.BlockSizeList:
+ return True
+
+ for FdObj in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():
+ for RegionObj in FdObj.RegionList:
+ if RegionObj.RegionType != BINARY_FILE_TYPE_FV:
+ continue
+ for RegionData in RegionObj.RegionDataList:
+ #
+ # Found the FD and region that contain this FV
+ #
+ if self.UiFvName.upper() == RegionData.upper():
+ RegionObj.BlockInfoOfRegion(FdObj.BlockSizeList, self)
+ if self.BlockSizeList:
+ return True
+ return False
+
+ ## _InitializeInf()
+ #
+ # Initialize the inf file to create FV
+ #
+ # @param self The object pointer
+ # @param BaseAddress base address of FV
+ # @param BlockSize block size of FV
+ # @param BlockNum How many blocks in FV
+ # @param ErasePolarity Flash erase polarity
+ #
+ def _InitializeInf (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1'):
+ #
+ # Create FV inf file
+ #
+ self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
+ self.UiFvName + '.inf')
+ self.FvInfFile = []
+
+ #
+ # Add [Options]
+ #
+ self.FvInfFile.append("[options]" + TAB_LINE_BREAK)
+ if BaseAddress is not None:
+ self.FvInfFile.append("EFI_BASE_ADDRESS = " + \
+ BaseAddress + \
+ TAB_LINE_BREAK)
+
+ if BlockSize is not None:
+ self.FvInfFile.append("EFI_BLOCK_SIZE = " + \
+ '0x%X' %BlockSize + \
+ TAB_LINE_BREAK)
+ if BlockNum is not None:
+ self.FvInfFile.append("EFI_NUM_BLOCKS = " + \
+ ' 0x%X' %BlockNum + \
+ TAB_LINE_BREAK)
+ else:
+ if self.BlockSizeList == []:
+ if not self._GetBlockSize():
+ #set default block size is 1
+ self.FvInfFile.append("EFI_BLOCK_SIZE = 0x1" + TAB_LINE_BREAK)
+
+ for BlockSize in self.BlockSizeList:
+ if BlockSize[0] is not None:
+ self.FvInfFile.append("EFI_BLOCK_SIZE = " + \
+ '0x%X' %BlockSize[0] + \
+ TAB_LINE_BREAK)
+
+ if BlockSize[1] is not None:
+ self.FvInfFile.append("EFI_NUM_BLOCKS = " + \
+ ' 0x%X' %BlockSize[1] + \
+ TAB_LINE_BREAK)
+
+ if self.BsBaseAddress is not None:
+ self.FvInfFile.append('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
+ '0x%X' %self.BsBaseAddress)
+ if self.RtBaseAddress is not None:
+ self.FvInfFile.append('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
+ '0x%X' %self.RtBaseAddress)
+ #
+ # Add attribute
+ #
+ self.FvInfFile.append("[attributes]" + TAB_LINE_BREAK)
+
+ self.FvInfFile.append("EFI_ERASE_POLARITY = " + \
+ ' %s' %ErasePloarity + \
+ TAB_LINE_BREAK)
+ if not (self.FvAttributeDict is None):
+ for FvAttribute in self.FvAttributeDict.keys():
+ if FvAttribute == "FvUsedSizeEnable":
+ if self.FvAttributeDict[FvAttribute].upper() in ('TRUE', '1'):
+ self.UsedSizeEnable = True
+ continue
+ self.FvInfFile.append("EFI_" + \
+ FvAttribute + \
+ ' = ' + \
+ self.FvAttributeDict[FvAttribute] + \
+ TAB_LINE_BREAK )
+ if self.FvAlignment is not None:
+ self.FvInfFile.append("EFI_FVB2_ALIGNMENT_" + \
+ self.FvAlignment.strip() + \
+ " = TRUE" + \
+ TAB_LINE_BREAK)
+
+ #
+ # Generate FV extension header file
+ #
+ if not self.FvNameGuid:
+ if len(self.FvExtEntryType) > 0 or self.UsedSizeEnable:
+ GenFdsGlobalVariable.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self.UiFvName))
+ else:
+ TotalSize = 16 + 4
+ Buffer = bytearray()
+ if self.UsedSizeEnable:
+ TotalSize += (4 + 4)
+ ## define EFI_FV_EXT_TYPE_USED_SIZE_TYPE 0x03
+ #typedef struct
+ # {
+ # EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr;
+ # UINT32 UsedSize;
+ # } EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE;
+ Buffer += pack('HHL', 8, 3, 0)
+
+ if self.FvNameString == 'TRUE':
+ #
+ # Create EXT entry for FV UI name
+ # This GUID is used: A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C
+ #
+ FvUiLen = len(self.UiFvName)
+ TotalSize += (FvUiLen + 16 + 4)
+ Guid = FV_UI_EXT_ENTY_GUID.split('-')
+ #
+ # Layout:
+ # EFI_FIRMWARE_VOLUME_EXT_ENTRY: size 4
+ # GUID: size 16
+ # FV UI name
+ #
+ Buffer += (pack('HH', (FvUiLen + 16 + 4), 0x0002)
+ + PackGUID(Guid)
+ + self.UiFvName.encode('utf-8'))
+
+ for Index in range (0, len(self.FvExtEntryType)):
+ if self.FvExtEntryType[Index] == 'FILE':
+ # check if the path is absolute or relative
+ if os.path.isabs(self.FvExtEntryData[Index]):
+ FileFullPath = os.path.normpath(self.FvExtEntryData[Index])
+ else:
+ FileFullPath = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.FvExtEntryData[Index]))
+ # check if the file path exists or not
+ if not os.path.isfile(FileFullPath):
+ GenFdsGlobalVariable.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self.FvExtEntryData[Index]))
+ FvExtFile = open (FileFullPath, 'rb')
+ FvExtFile.seek(0, 2)
+ Size = FvExtFile.tell()
+ if Size >= 0x10000:
+ GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
+ TotalSize += (Size + 4)
+ FvExtFile.seek(0)
+ Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
+ Buffer += FvExtFile.read()
+ FvExtFile.close()
+ if self.FvExtEntryType[Index] == 'DATA':
+ ByteList = self.FvExtEntryData[Index].split(',')
+ Size = len (ByteList)
+ if Size >= 0x10000:
+ GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
+ TotalSize += (Size + 4)
+ Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
+ for Index1 in range (0, Size):
+ Buffer += pack('B', int(ByteList[Index1], 16))
+
+ Guid = self.FvNameGuid.split('-')
+ Buffer = PackGUID(Guid) + pack('=L', TotalSize) + Buffer
+
+ #
+ # Generate FV extension header file if the total size is not zero
+ #
+ if TotalSize > 0:
+ FvExtHeaderFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.ext')
+ FvExtHeaderFile = BytesIO()
+ FvExtHeaderFile.write(Buffer)
+ Changed = SaveFileOnChange(FvExtHeaderFileName, FvExtHeaderFile.getvalue(), True)
+ FvExtHeaderFile.close()
+ if Changed:
+ if os.path.exists (self.InfFileName):
+ os.remove (self.InfFileName)
+ self.FvInfFile.append("EFI_FV_EXT_HEADER_FILE_NAME = " + \
+ FvExtHeaderFileName + \
+ TAB_LINE_BREAK)
+
+ #
+ # Add [Files]
+ #
+ self.FvInfFile.append("[files]" + TAB_LINE_BREAK)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FvImageSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FvImageSection.py
new file mode 100755
index 00000000..8590c64b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FvImageSection.py
@@ -0,0 +1,158 @@
+## @file
+# process FV image section generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Section
+from io import BytesIO
+from .Ffs import SectionSuffix
+import subprocess
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+import Common.LongFilePathOs as os
+from CommonDataClass.FdfClass import FvImageSectionClassObject
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+from Common import EdkLogger
+from Common.BuildToolError import *
+from Common.DataType import *
+
+## generate FV image section
+#
+#
+class FvImageSection(FvImageSectionClassObject):
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ FvImageSectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # Generate FV image section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = None, IsMakefile = False):
+
+ OutputFileList = []
+ if Dict is None:
+ Dict = {}
+ if self.FvFileType is not None:
+ FileList, IsSect = Section.Section.GetFileList(FfsInf, self.FvFileType, self.FvFileExtension)
+ if IsSect :
+ return FileList, self.Alignment
+
+ Num = SecNum
+
+ MaxFvAlignment = 0
+ for FvFileName in FileList:
+ FvAlignmentValue = 0
+ if os.path.isfile(FvFileName):
+ FvFileObj = open (FvFileName, 'rb')
+ FvFileObj.seek(0)
+ # PI FvHeader is 0x48 byte
+ FvHeaderBuffer = FvFileObj.read(0x48)
+ # FV alignment position.
+ if isinstance(FvHeaderBuffer[0x2E], str):
+ FvAlignmentValue = 1 << (ord(FvHeaderBuffer[0x2E]) & 0x1F)
+ else:
+ FvAlignmentValue = 1 << (FvHeaderBuffer[0x2E] & 0x1F)
+ FvFileObj.close()
+ if FvAlignmentValue > MaxFvAlignment:
+ MaxFvAlignment = FvAlignmentValue
+
+ OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get("FV_IMAGE"))
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [FvFileName], 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE', IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ # MaxFvAlignment is larger than or equal to 1K
+ if MaxFvAlignment >= 0x400:
+ if MaxFvAlignment >= 0x100000:
+ #The max alignment supported by FFS is 16M.
+ if MaxFvAlignment >= 0x1000000:
+ self.Alignment = "16M"
+ else:
+ self.Alignment = str(MaxFvAlignment // 0x100000) + "M"
+ else:
+ self.Alignment = str (MaxFvAlignment // 0x400) + "K"
+ else:
+ # MaxFvAlignment is less than 1K
+ self.Alignment = str (MaxFvAlignment)
+
+ return OutputFileList, self.Alignment
+ #
+ # Generate Fv
+ #
+ if self.FvName is not None:
+ Buffer = BytesIO()
+ Fv = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName)
+ if Fv is not None:
+ self.Fv = Fv
+ if not self.FvAddr and self.Fv.BaseAddress:
+ self.FvAddr = self.Fv.BaseAddress
+ FvFileName = Fv.AddToBuffer(Buffer, self.FvAddr, MacroDict = Dict, Flag=IsMakefile)
+ if Fv.FvAlignment is not None:
+ if self.Alignment is None:
+ self.Alignment = Fv.FvAlignment
+ else:
+ if GenFdsGlobalVariable.GetAlignment (Fv.FvAlignment) > GenFdsGlobalVariable.GetAlignment (self.Alignment):
+ self.Alignment = Fv.FvAlignment
+ else:
+ if self.FvFileName is not None:
+ FvFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FvFileName)
+ if os.path.isfile(FvFileName):
+ FvFileObj = open (FvFileName, 'rb')
+ FvFileObj.seek(0)
+ # PI FvHeader is 0x48 byte
+ FvHeaderBuffer = FvFileObj.read(0x48)
+ # FV alignment position.
+ if isinstance(FvHeaderBuffer[0x2E], str):
+ FvAlignmentValue = 1 << (ord(FvHeaderBuffer[0x2E]) & 0x1F)
+ else:
+ FvAlignmentValue = 1 << (FvHeaderBuffer[0x2E] & 0x1F)
+ # FvAlignmentValue is larger than or equal to 1K
+ if FvAlignmentValue >= 0x400:
+ if FvAlignmentValue >= 0x100000:
+ #The max alignment supported by FFS is 16M.
+ if FvAlignmentValue >= 0x1000000:
+ self.Alignment = "16M"
+ else:
+ self.Alignment = str(FvAlignmentValue // 0x100000) + "M"
+ else:
+ self.Alignment = str (FvAlignmentValue // 0x400) + "K"
+ else:
+ # FvAlignmentValue is less than 1K
+ self.Alignment = str (FvAlignmentValue)
+ FvFileObj.close()
+ else:
+ if len (mws.getPkgPath()) == 0:
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, "%s is not found in WORKSPACE: %s" % self.FvFileName, GenFdsGlobalVariable.WorkSpaceDir)
+ else:
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, "%s is not found in packages path:\n\t%s" % (self.FvFileName, '\n\t'.join(mws.getPkgPath())))
+
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "FvImageSection Failed! %s NOT found in FDF" % self.FvName)
+
+ #
+ # Prepare the parameter of GenSection
+ #
+ OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + SecNum + SectionSuffix.get("FV_IMAGE"))
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [FvFileName], 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE', IsMakefile=IsMakefile)
+ OutputFileList.append(OutputFile)
+
+ return OutputFileList, self.Alignment
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py
new file mode 100755
index 00000000..74dca772
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py
@@ -0,0 +1,800 @@
+## @file
+# generate flash image
+#
+# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import print_function
+from __future__ import absolute_import
+from re import compile
+from optparse import OptionParser
+from sys import exit
+from glob import glob
+from struct import unpack
+from linecache import getlines
+from io import BytesIO
+
+import Common.LongFilePathOs as os
+from Common.TargetTxtClassObject import TargetTxtDict
+from Common.DataType import *
+import Common.GlobalData as GlobalData
+from Common import EdkLogger
+from Common.StringUtils import NormPath
+from Common.Misc import DirCache, PathClass, GuidStructureStringToGuidString
+from Common.Misc import SaveFileOnChange, ClearDuplicatedInf
+from Common.BuildVersion import gBUILD_VERSION
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+from Common.BuildToolError import FatalError, GENFDS_ERROR, CODE_ERROR, FORMAT_INVALID, RESOURCE_NOT_AVAILABLE, FILE_NOT_FOUND, OPTION_MISSING, FORMAT_NOT_SUPPORTED, OPTION_VALUE_INVALID, PARAMETER_INVALID
+from Workspace.WorkspaceDatabase import WorkspaceDatabase
+
+from .FdfParser import FdfParser, Warning
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from .FfsFileStatement import FileStatement
+import Common.DataType as DataType
+from struct import Struct
+
+## Version and Copyright
+versionNumber = "1.0" + ' ' + gBUILD_VERSION
+__version__ = "%prog Version " + versionNumber
+__copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation All rights reserved."
+
+## Tool entrance method
+#
+# This method mainly dispatch specific methods per the command line options.
+# If no error found, return zero value so the caller of this tool can know
+# if it's executed successfully or not.
+#
+# @retval 0 Tool was successful
+# @retval 1 Tool failed
+#
+def main():
+ global Options
+ Options = myOptionParser()
+ EdkLogger.Initialize()
+ return GenFdsApi(OptionsToCommandDict(Options))
+
+def resetFdsGlobalVariable():
+ GenFdsGlobalVariable.FvDir = ''
+ GenFdsGlobalVariable.OutputDirDict = {}
+ GenFdsGlobalVariable.BinDir = ''
+ # will be FvDir + os.sep + 'Ffs'
+ GenFdsGlobalVariable.FfsDir = ''
+ GenFdsGlobalVariable.FdfParser = None
+ GenFdsGlobalVariable.LibDir = ''
+ GenFdsGlobalVariable.WorkSpace = None
+ GenFdsGlobalVariable.WorkSpaceDir = ''
+ GenFdsGlobalVariable.ConfDir = ''
+ GenFdsGlobalVariable.OutputDirFromDscDict = {}
+ GenFdsGlobalVariable.TargetName = ''
+ GenFdsGlobalVariable.ToolChainTag = ''
+ GenFdsGlobalVariable.RuleDict = {}
+ GenFdsGlobalVariable.ArchList = None
+ GenFdsGlobalVariable.ActivePlatform = None
+ GenFdsGlobalVariable.FvAddressFileName = ''
+ GenFdsGlobalVariable.VerboseMode = False
+ GenFdsGlobalVariable.DebugLevel = -1
+ GenFdsGlobalVariable.SharpCounter = 0
+ GenFdsGlobalVariable.SharpNumberPerLine = 40
+ GenFdsGlobalVariable.FdfFile = ''
+ GenFdsGlobalVariable.FdfFileTimeStamp = 0
+ GenFdsGlobalVariable.FixedLoadAddress = False
+ GenFdsGlobalVariable.PlatformName = ''
+
+ GenFdsGlobalVariable.BuildRuleFamily = DataType.TAB_COMPILER_MSFT
+ GenFdsGlobalVariable.ToolChainFamily = DataType.TAB_COMPILER_MSFT
+ GenFdsGlobalVariable.__BuildRuleDatabase = None
+ GenFdsGlobalVariable.GuidToolDefinition = {}
+ GenFdsGlobalVariable.FfsCmdDict = {}
+ GenFdsGlobalVariable.SecCmdList = []
+ GenFdsGlobalVariable.CopyList = []
+ GenFdsGlobalVariable.ModuleFile = ''
+ GenFdsGlobalVariable.EnableGenfdsMultiThread = True
+
+ GenFdsGlobalVariable.LargeFileInFvFlags = []
+ GenFdsGlobalVariable.EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
+ GenFdsGlobalVariable.LARGE_FILE_SIZE = 0x1000000
+
+ GenFdsGlobalVariable.SectionHeader = Struct("3B 1B")
+
+ # FvName, FdName, CapName in FDF, Image file name
+ GenFdsGlobalVariable.ImageBinDict = {}
+
+def GenFdsApi(FdsCommandDict, WorkSpaceDataBase=None):
+ global Workspace
+ Workspace = ""
+ ArchList = None
+ ReturnCode = 0
+ resetFdsGlobalVariable()
+
+ try:
+ if FdsCommandDict.get("verbose"):
+ EdkLogger.SetLevel(EdkLogger.VERBOSE)
+ GenFdsGlobalVariable.VerboseMode = True
+
+ if FdsCommandDict.get("FixedAddress"):
+ GenFdsGlobalVariable.FixedLoadAddress = True
+
+ if FdsCommandDict.get("quiet"):
+ EdkLogger.SetLevel(EdkLogger.QUIET)
+ if FdsCommandDict.get("debug"):
+ EdkLogger.SetLevel(FdsCommandDict.get("debug") + 1)
+ GenFdsGlobalVariable.DebugLevel = FdsCommandDict.get("debug")
+ else:
+ EdkLogger.SetLevel(EdkLogger.INFO)
+
+ if not FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')):
+ EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",
+ ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
+ elif not os.path.exists(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE'))):
+ EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",
+ ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
+ else:
+ Workspace = os.path.normcase(FdsCommandDict.get("Workspace",os.environ.get('WORKSPACE')))
+ GenFdsGlobalVariable.WorkSpaceDir = Workspace
+ if FdsCommandDict.get("debug"):
+ GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace)
+ if FdsCommandDict.get("GenfdsMultiThread"):
+ GenFdsGlobalVariable.EnableGenfdsMultiThread = True
+ else:
+ GenFdsGlobalVariable.EnableGenfdsMultiThread = False
+ os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
+
+ # set multiple workspace
+ PackagesPath = os.getenv("PACKAGES_PATH")
+ mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)
+
+ if FdsCommandDict.get("fdf_file"):
+ FdfFilename = FdsCommandDict.get("fdf_file")[0].Path
+ FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)
+
+ if FdfFilename[0:2] == '..':
+ FdfFilename = os.path.realpath(FdfFilename)
+ if not os.path.isabs(FdfFilename):
+ FdfFilename = mws.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename)
+ if not os.path.exists(FdfFilename):
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=FdfFilename)
+
+ GenFdsGlobalVariable.FdfFile = FdfFilename
+ GenFdsGlobalVariable.FdfFileTimeStamp = os.path.getmtime(FdfFilename)
+ else:
+ EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename")
+
+ if FdsCommandDict.get("build_target"):
+ GenFdsGlobalVariable.TargetName = FdsCommandDict.get("build_target")
+
+ if FdsCommandDict.get("toolchain_tag"):
+ GenFdsGlobalVariable.ToolChainTag = FdsCommandDict.get("toolchain_tag")
+
+ if FdsCommandDict.get("active_platform"):
+ ActivePlatform = FdsCommandDict.get("active_platform")
+ ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)
+
+ if ActivePlatform[0:2] == '..':
+ ActivePlatform = os.path.realpath(ActivePlatform)
+
+ if not os.path.isabs (ActivePlatform):
+ ActivePlatform = mws.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform)
+
+ if not os.path.exists(ActivePlatform):
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!")
+ else:
+ EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")
+
+ GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform))
+
+ if FdsCommandDict.get("conf_directory"):
+ # Get alternate Conf location, if it is absolute, then just use the absolute directory name
+ ConfDirectoryPath = os.path.normpath(FdsCommandDict.get("conf_directory"))
+ if ConfDirectoryPath.startswith('"'):
+ ConfDirectoryPath = ConfDirectoryPath[1:]
+ if ConfDirectoryPath.endswith('"'):
+ ConfDirectoryPath = ConfDirectoryPath[:-1]
+ if not os.path.isabs(ConfDirectoryPath):
+ # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
+ # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
+ ConfDirectoryPath = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ConfDirectoryPath)
+ else:
+ if "CONF_PATH" in os.environ:
+ ConfDirectoryPath = os.path.normcase(os.environ["CONF_PATH"])
+ else:
+ # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
+ ConfDirectoryPath = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 'Conf')
+ GenFdsGlobalVariable.ConfDir = ConfDirectoryPath
+ if not GlobalData.gConfDirectory:
+ GlobalData.gConfDirectory = GenFdsGlobalVariable.ConfDir
+ BuildConfigurationFile = os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt"))
+ if os.path.isfile(BuildConfigurationFile) == True:
+ # if no build target given in command line, get it from target.txt
+ TargetObj = TargetTxtDict()
+ TargetTxt = TargetObj.Target
+ if not GenFdsGlobalVariable.TargetName:
+ BuildTargetList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TARGET]
+ if len(BuildTargetList) != 1:
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")
+ GenFdsGlobalVariable.TargetName = BuildTargetList[0]
+
+ # if no tool chain given in command line, get it from target.txt
+ if not GenFdsGlobalVariable.ToolChainTag:
+ ToolChainList = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
+ if ToolChainList is None or len(ToolChainList) == 0:
+ EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")
+ if len(ToolChainList) != 1:
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for ToolChain.")
+ GenFdsGlobalVariable.ToolChainTag = ToolChainList[0]
+ else:
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)
+
+ #Set global flag for build mode
+ GlobalData.gIgnoreSource = FdsCommandDict.get("IgnoreSources")
+
+ if FdsCommandDict.get("macro"):
+ for Pair in FdsCommandDict.get("macro"):
+ if Pair.startswith('"'):
+ Pair = Pair[1:]
+ if Pair.endswith('"'):
+ Pair = Pair[:-1]
+ List = Pair.split('=')
+ if len(List) == 2:
+ if not List[1].strip():
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="No Value given for Macro %s" %List[0])
+ if List[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
+ GlobalData.gGlobalDefines[List[0].strip()] = List[1].strip()
+ else:
+ GlobalData.gCommandLineDefines[List[0].strip()] = List[1].strip()
+ else:
+ GlobalData.gCommandLineDefines[List[0].strip()] = "TRUE"
+ os.environ["WORKSPACE"] = Workspace
+
+ # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
+ if "TARGET" not in GlobalData.gGlobalDefines:
+ GlobalData.gGlobalDefines["TARGET"] = GenFdsGlobalVariable.TargetName
+ if "TOOLCHAIN" not in GlobalData.gGlobalDefines:
+ GlobalData.gGlobalDefines["TOOLCHAIN"] = GenFdsGlobalVariable.ToolChainTag
+ if "TOOL_CHAIN_TAG" not in GlobalData.gGlobalDefines:
+ GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable.ToolChainTag
+
+ """call Workspace build create database"""
+ GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
+
+ if WorkSpaceDataBase:
+ BuildWorkSpace = WorkSpaceDataBase
+ else:
+ BuildWorkSpace = WorkspaceDatabase()
+ #
+ # Get files real name in workspace dir
+ #
+ GlobalData.gAllFiles = DirCache(Workspace)
+ GlobalData.gWorkspace = Workspace
+
+ if FdsCommandDict.get("build_architecture_list"):
+ ArchList = FdsCommandDict.get("build_architecture_list").split(',')
+ else:
+ ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].SupArchList
+
+ TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].SupArchList) & set(ArchList)
+ if len(TargetArchList) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON].SupArchList)))
+
+ for Arch in ArchList:
+ GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].OutputDirectory)
+
+ # assign platform name based on last entry in ArchList
+ GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, ArchList[-1], FdsCommandDict.get("build_target"), FdsCommandDict.get("toolchain_tag")].PlatformName
+
+ if FdsCommandDict.get("platform_build_directory"):
+ OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdsCommandDict.get("platform_build_directory"))
+ if not os.path.isabs (OutputDirFromCommandLine):
+ OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine)
+ for Arch in ArchList:
+ GenFdsGlobalVariable.OutputDirDict[Arch] = OutputDirFromCommandLine
+ else:
+ for Arch in ArchList:
+ GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.join(GenFdsGlobalVariable.OutputDirFromDscDict[Arch], GenFdsGlobalVariable.TargetName + '_' + GenFdsGlobalVariable.ToolChainTag)
+
+ for Key in GenFdsGlobalVariable.OutputDirDict:
+ OutputDir = GenFdsGlobalVariable.OutputDirDict[Key]
+ if OutputDir[0:2] == '..':
+ OutputDir = os.path.realpath(OutputDir)
+
+ if OutputDir[1] != ':':
+ OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir)
+
+ if not os.path.exists(OutputDir):
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=OutputDir)
+ GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir
+
+ """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
+ if WorkSpaceDataBase:
+ FdfParserObj = GlobalData.gFdfParser
+ else:
+ FdfParserObj = FdfParser(FdfFilename)
+ FdfParserObj.ParseFile()
+
+ if FdfParserObj.CycleReferenceCheck():
+ EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file")
+
+ if FdsCommandDict.get("fd"):
+ if FdsCommandDict.get("fd")[0].upper() in FdfParserObj.Profile.FdDict:
+ GenFds.OnlyGenerateThisFd = FdsCommandDict.get("fd")[0]
+ else:
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
+ "No such an FD in FDF file: %s" % FdsCommandDict.get("fd")[0])
+
+ if FdsCommandDict.get("fv"):
+ if FdsCommandDict.get("fv")[0].upper() in FdfParserObj.Profile.FvDict:
+ GenFds.OnlyGenerateThisFv = FdsCommandDict.get("fv")[0]
+ else:
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
+ "No such an FV in FDF file: %s" % FdsCommandDict.get("fv")[0])
+
+ if FdsCommandDict.get("cap"):
+ if FdsCommandDict.get("cap")[0].upper() in FdfParserObj.Profile.CapsuleDict:
+ GenFds.OnlyGenerateThisCap = FdsCommandDict.get("cap")[0]
+ else:
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
+ "No such a Capsule in FDF file: %s" % FdsCommandDict.get("cap")[0])
+
+ GenFdsGlobalVariable.WorkSpace = BuildWorkSpace
+ if ArchList:
+ GenFdsGlobalVariable.ArchList = ArchList
+
+ # Dsc Build Data will handle Pcd Settings from CommandLine.
+
+ """Modify images from build output if the feature of loading driver at fixed address is on."""
+ if GenFdsGlobalVariable.FixedLoadAddress:
+ GenFds.PreprocessImage(BuildWorkSpace, GenFdsGlobalVariable.ActivePlatform)
+
+ # Record the FV Region info that may specific in the FD
+ if FdfParserObj.Profile.FvDict and FdfParserObj.Profile.FdDict:
+ for FvObj in FdfParserObj.Profile.FvDict.values():
+ for FdObj in FdfParserObj.Profile.FdDict.values():
+ for RegionObj in FdObj.RegionList:
+ if RegionObj.RegionType != BINARY_FILE_TYPE_FV:
+ continue
+ for RegionData in RegionObj.RegionDataList:
+ if FvObj.UiFvName.upper() == RegionData.upper():
+ if not FvObj.BaseAddress:
+ FvObj.BaseAddress = '0x%x' % (int(FdObj.BaseAddress, 0) + RegionObj.Offset)
+ if FvObj.FvRegionInFD:
+ if FvObj.FvRegionInFD != RegionObj.Size:
+ EdkLogger.error("GenFds", FORMAT_INVALID, "The FV %s's region is specified in multiple FD with different value." %FvObj.UiFvName)
+ else:
+ FvObj.FvRegionInFD = RegionObj.Size
+ RegionObj.BlockInfoOfRegion(FdObj.BlockSizeList, FvObj)
+
+ """Call GenFds"""
+ GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList)
+
+ """Generate GUID cross reference file"""
+ GenFds.GenerateGuidXRefFile(BuildWorkSpace, ArchList, FdfParserObj)
+
+ """Display FV space info."""
+ GenFds.DisplayFvSpaceInfo(FdfParserObj)
+
+ except Warning as X:
+ EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)
+ ReturnCode = FORMAT_INVALID
+ except FatalError as X:
+ if FdsCommandDict.get("debug") is not None:
+ import traceback
+ EdkLogger.quiet(traceback.format_exc())
+ ReturnCode = X.args[0]
+ except:
+ import traceback
+ EdkLogger.error(
+ "\nPython",
+ CODE_ERROR,
+ "Tools code failure",
+ ExtraData="Please send email to %s for help, attaching following call stack trace!\n" % MSG_EDKII_MAIL_ADDR,
+ RaiseError=False
+ )
+ EdkLogger.quiet(traceback.format_exc())
+ ReturnCode = CODE_ERROR
+ finally:
+ ClearDuplicatedInf()
+ return ReturnCode
+
+def OptionsToCommandDict(Options):
+ FdsCommandDict = {}
+ FdsCommandDict["verbose"] = Options.verbose
+ FdsCommandDict["FixedAddress"] = Options.FixedAddress
+ FdsCommandDict["quiet"] = Options.quiet
+ FdsCommandDict["debug"] = Options.debug
+ FdsCommandDict["Workspace"] = Options.Workspace
+ FdsCommandDict["GenfdsMultiThread"] = not Options.NoGenfdsMultiThread
+ FdsCommandDict["fdf_file"] = [PathClass(Options.filename)] if Options.filename else []
+ FdsCommandDict["build_target"] = Options.BuildTarget
+ FdsCommandDict["toolchain_tag"] = Options.ToolChain
+ FdsCommandDict["active_platform"] = Options.activePlatform
+ FdsCommandDict["OptionPcd"] = Options.OptionPcd
+ FdsCommandDict["conf_directory"] = Options.ConfDirectory
+ FdsCommandDict["IgnoreSources"] = Options.IgnoreSources
+ FdsCommandDict["macro"] = Options.Macros
+ FdsCommandDict["build_architecture_list"] = Options.archList
+ FdsCommandDict["platform_build_directory"] = Options.outputDir
+ FdsCommandDict["fd"] = [Options.uiFdName] if Options.uiFdName else []
+ FdsCommandDict["fv"] = [Options.uiFvName] if Options.uiFvName else []
+ FdsCommandDict["cap"] = [Options.uiCapName] if Options.uiCapName else []
+ return FdsCommandDict
+
+
+gParamCheck = []
+def SingleCheckCallback(option, opt_str, value, parser):
+ if option not in gParamCheck:
+ setattr(parser.values, option.dest, value)
+ gParamCheck.append(option)
+ else:
+ parser.error("Option %s only allows one instance in command line!" % option)
+
+## Parse command line options
+#
+# Using standard Python module optparse to parse command line option of this tool.
+#
+# @retval Opt A optparse.Values object containing the parsed options
+#
+def myOptionParser():
+ usage = "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
+ Parser = OptionParser(usage=usage, description=__copyright__, version="%prog " + str(versionNumber))
+ Parser.add_option("-f", "--file", dest="filename", type="string", help="Name of FDF file to convert", action="callback", callback=SingleCheckCallback)
+ Parser.add_option("-a", "--arch", dest="archList", help="comma separated list containing one or more of: IA32, X64, IPF, ARM, AARCH64 or EBC which should be built, overrides target.txt?s TARGET_ARCH")
+ Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
+ Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.")
+ Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
+ Parser.add_option("-p", "--platform", type="string", dest="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
+ action="callback", callback=SingleCheckCallback)
+ Parser.add_option("-w", "--workspace", type="string", dest="Workspace", default=os.environ.get('WORKSPACE'), help="Set the WORKSPACE",
+ action="callback", callback=SingleCheckCallback)
+ Parser.add_option("-o", "--outputDir", type="string", dest="outputDir", help="Name of Build Output directory",
+ action="callback", callback=SingleCheckCallback)
+ Parser.add_option("-r", "--rom_image", dest="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
+ Parser.add_option("-i", "--FvImage", dest="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
+ Parser.add_option("-C", "--CapsuleImage", dest="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
+ Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
+ action="callback", callback=SingleCheckCallback)
+ Parser.add_option("-t", "--tagname", type="string", dest="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
+ action="callback", callback=SingleCheckCallback)
+ Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")
+ Parser.add_option("-s", "--specifyaddress", dest="FixedAddress", action="store_true", type=None, help="Specify driver load address.")
+ Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")
+ Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")
+ Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
+ Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=True, help="Enable GenFds multi thread to generate ffs file.")
+ Parser.add_option("--no-genfds-multi-thread", action="store_true", dest="NoGenfdsMultiThread", default=False, help="Disable GenFds multi thread to generate ffs file.")
+
+ Options, _ = Parser.parse_args()
+ return Options
+
+## The class implementing the EDK2 flash image generation process
+#
+# This process includes:
+# 1. Collect workspace information, includes platform and module information
+# 2. Call methods of Fd class to generate FD
+# 3. Call methods of Fv class to generate FV that not belong to FD
+#
+class GenFds(object):
+ FdfParsef = None
+ OnlyGenerateThisFd = None
+ OnlyGenerateThisFv = None
+ OnlyGenerateThisCap = None
+
+ ## GenFd()
+ #
+ # @param OutputDir Output directory
+ # @param FdfParserObject FDF contents parser
+ # @param Workspace The directory of workspace
+ # @param ArchList The Arch list of platform
+ #
+ @staticmethod
+ def GenFd (OutputDir, FdfParserObject, WorkSpace, ArchList):
+ GenFdsGlobalVariable.SetDir ('', FdfParserObject, WorkSpace, ArchList)
+
+ GenFdsGlobalVariable.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
+ if GenFds.OnlyGenerateThisCap is not None and GenFds.OnlyGenerateThisCap.upper() in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict:
+ CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict[GenFds.OnlyGenerateThisCap.upper()]
+ if CapsuleObj is not None:
+ CapsuleObj.GenCapsule()
+ return
+
+ if GenFds.OnlyGenerateThisFd is not None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict:
+ FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()]
+ if FdObj is not None:
+ FdObj.GenFd()
+ return
+ elif GenFds.OnlyGenerateThisFd is None and GenFds.OnlyGenerateThisFv is None:
+ for FdObj in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():
+ FdObj.GenFd()
+
+ GenFdsGlobalVariable.VerboseLogger("\n Generate other FV images! ")
+ if GenFds.OnlyGenerateThisFv is not None and GenFds.OnlyGenerateThisFv.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict:
+ FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[GenFds.OnlyGenerateThisFv.upper()]
+ if FvObj is not None:
+ Buffer = BytesIO()
+ FvObj.AddToBuffer(Buffer)
+ Buffer.close()
+ return
+ elif GenFds.OnlyGenerateThisFv is None:
+ for FvObj in GenFdsGlobalVariable.FdfParser.Profile.FvDict.values():
+ Buffer = BytesIO()
+ FvObj.AddToBuffer(Buffer)
+ Buffer.close()
+
+ if GenFds.OnlyGenerateThisFv is None and GenFds.OnlyGenerateThisFd is None and GenFds.OnlyGenerateThisCap is None:
+ if GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict != {}:
+ GenFdsGlobalVariable.VerboseLogger("\n Generate other Capsule images!")
+ for CapsuleObj in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.values():
+ CapsuleObj.GenCapsule()
+
+ if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}:
+ GenFdsGlobalVariable.VerboseLogger("\n Generate all Option ROM!")
+ for OptRomObj in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.values():
+ OptRomObj.AddToBuffer(None)
+
+ @staticmethod
+ def GenFfsMakefile(OutputDir, FdfParserObject, WorkSpace, ArchList, GlobalData):
+ GenFdsGlobalVariable.SetEnv(FdfParserObject, WorkSpace, ArchList, GlobalData)
+ for FdObj in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():
+ FdObj.GenFd(Flag=True)
+
+ for FvObj in GenFdsGlobalVariable.FdfParser.Profile.FvDict.values():
+ FvObj.AddToBuffer(Buffer=None, Flag=True)
+
+ if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}:
+ for OptRomObj in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.values():
+ OptRomObj.AddToBuffer(Buffer=None, Flag=True)
+
+ return GenFdsGlobalVariable.FfsCmdDict
+
+ ## GetFvBlockSize()
+ #
+ # @param FvObj Whose block size to get
+ # @retval int Block size value
+ #
+ @staticmethod
+ def GetFvBlockSize(FvObj):
+ DefaultBlockSize = 0x1
+ FdObj = None
+ if GenFds.OnlyGenerateThisFd is not None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict:
+ FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()]
+ if FdObj is None:
+ for ElementFd in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():
+ for ElementRegion in ElementFd.RegionList:
+ if ElementRegion.RegionType == BINARY_FILE_TYPE_FV:
+ for ElementRegionData in ElementRegion.RegionDataList:
+ if ElementRegionData is not None and ElementRegionData.upper() == FvObj.UiFvName:
+ if FvObj.BlockSizeList != []:
+ return FvObj.BlockSizeList[0][0]
+ else:
+ return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)
+ if FvObj.BlockSizeList != []:
+ return FvObj.BlockSizeList[0][0]
+ return DefaultBlockSize
+ else:
+ for ElementRegion in FdObj.RegionList:
+ if ElementRegion.RegionType == BINARY_FILE_TYPE_FV:
+ for ElementRegionData in ElementRegion.RegionDataList:
+ if ElementRegionData is not None and ElementRegionData.upper() == FvObj.UiFvName:
+ if FvObj.BlockSizeList != []:
+ return FvObj.BlockSizeList[0][0]
+ else:
+ return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)
+ return DefaultBlockSize
+
+ ## DisplayFvSpaceInfo()
+ #
+ # @param FvObj Whose block size to get
+ # @retval None
+ #
+ @staticmethod
+ def DisplayFvSpaceInfo(FdfParserObject):
+
+ FvSpaceInfoList = []
+ MaxFvNameLength = 0
+ for FvName in FdfParserObject.Profile.FvDict:
+ if len(FvName) > MaxFvNameLength:
+ MaxFvNameLength = len(FvName)
+ FvSpaceInfoFileName = os.path.join(GenFdsGlobalVariable.FvDir, FvName.upper() + '.Fv.map')
+ if os.path.exists(FvSpaceInfoFileName):
+ FileLinesList = getlines(FvSpaceInfoFileName)
+ TotalFound = False
+ Total = ''
+ UsedFound = False
+ Used = ''
+ FreeFound = False
+ Free = ''
+ for Line in FileLinesList:
+ NameValue = Line.split('=')
+ if len(NameValue) == 2:
+ if NameValue[0].strip() == 'EFI_FV_TOTAL_SIZE':
+ TotalFound = True
+ Total = NameValue[1].strip()
+ if NameValue[0].strip() == 'EFI_FV_TAKEN_SIZE':
+ UsedFound = True
+ Used = NameValue[1].strip()
+ if NameValue[0].strip() == 'EFI_FV_SPACE_SIZE':
+ FreeFound = True
+ Free = NameValue[1].strip()
+
+ if TotalFound and UsedFound and FreeFound:
+ FvSpaceInfoList.append((FvName, Total, Used, Free))
+
+ GenFdsGlobalVariable.QuietLogger('\nFV Space Information') # VBox: We want this info in -quiet builds too.
+ for FvSpaceInfo in FvSpaceInfoList:
+ Name = FvSpaceInfo[0]
+ TotalSizeValue = int(FvSpaceInfo[1], 0)
+ UsedSizeValue = int(FvSpaceInfo[2], 0)
+ FreeSizeValue = int(FvSpaceInfo[3], 0)
+ if UsedSizeValue == TotalSizeValue:
+ Percentage = '100'
+ else:
+ Percentage = str((UsedSizeValue + 0.0) / TotalSizeValue)[0:4].lstrip('0.')
+
+ GenFdsGlobalVariable.QuietLogger(Name + ' ' + '[' + Percentage + '%Full] '\
+ + str(TotalSizeValue) + ' (' + hex(TotalSizeValue) + ')' + ' total, '\
+ + str(UsedSizeValue) + ' (' + hex(UsedSizeValue) + ')' + ' used, '\
+ + str(FreeSizeValue) + ' (' + hex(FreeSizeValue) + ')' + ' free') # VBox: Same as above
+
+ ## PreprocessImage()
+ #
+ # @param BuildDb Database from build meta data files
+ # @param DscFile modules from dsc file will be preprocessed
+ # @retval None
+ #
+ @staticmethod
+ def PreprocessImage(BuildDb, DscFile):
+ PcdDict = BuildDb.BuildObject[DscFile, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Pcds
+ PcdValue = ''
+ for Key in PcdDict:
+ PcdObj = PcdDict[Key]
+ if PcdObj.TokenCName == 'PcdBsBaseAddress':
+ PcdValue = PcdObj.DefaultValue
+ break
+
+ if PcdValue == '':
+ return
+
+ Int64PcdValue = int(PcdValue, 0)
+ if Int64PcdValue == 0 or Int64PcdValue < -1:
+ return
+
+ TopAddress = 0
+ if Int64PcdValue > 0:
+ TopAddress = Int64PcdValue
+
+ ModuleDict = BuildDb.BuildObject[DscFile, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Modules
+ for Key in ModuleDict:
+ ModuleObj = BuildDb.BuildObject[Key, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ print(ModuleObj.BaseName + ' ' + ModuleObj.ModuleType)
+
+ @staticmethod
+ def GenerateGuidXRefFile(BuildDb, ArchList, FdfParserObj):
+ GuidXRefFileName = os.path.join(GenFdsGlobalVariable.FvDir, "Guid.xref")
+ GuidXRefFile = []
+ PkgGuidDict = {}
+ GuidDict = {}
+ ModuleList = []
+ FileGuidList = []
+ VariableGuidSet = set()
+ for Arch in ArchList:
+ PlatformDataBase = BuildDb.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ PkgList = GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag)
+ for P in PkgList:
+ PkgGuidDict.update(P.Guids)
+ for Name, Guid in PlatformDataBase.Pcds:
+ Pcd = PlatformDataBase.Pcds[Name, Guid]
+ if Pcd.Type in [TAB_PCDS_DYNAMIC_HII, TAB_PCDS_DYNAMIC_EX_HII]:
+ for SkuId in Pcd.SkuInfoList:
+ Sku = Pcd.SkuInfoList[SkuId]
+ if Sku.VariableGuid in VariableGuidSet:continue
+ VariableGuidSet.add(Sku.VariableGuid)
+ if Sku.VariableGuid and Sku.VariableGuid in PkgGuidDict.keys():
+ GuidDict[Sku.VariableGuid] = PkgGuidDict[Sku.VariableGuid]
+ for ModuleFile in PlatformDataBase.Modules:
+ Module = BuildDb.BuildObject[ModuleFile, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ if Module in ModuleList:
+ continue
+ else:
+ ModuleList.append(Module)
+ if GlobalData.gGuidPattern.match(ModuleFile.BaseName):
+ GuidXRefFile.append("%s %s\n" % (ModuleFile.BaseName, Module.BaseName))
+ else:
+ GuidXRefFile.append("%s %s\n" % (Module.Guid, Module.BaseName))
+ GuidDict.update(Module.Protocols)
+ GuidDict.update(Module.Guids)
+ GuidDict.update(Module.Ppis)
+ for FvName in FdfParserObj.Profile.FvDict:
+ for FfsObj in FdfParserObj.Profile.FvDict[FvName].FfsList:
+ if not isinstance(FfsObj, FileStatement):
+ InfPath = PathClass(NormPath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, FfsObj.InfFileName)))
+ FdfModule = BuildDb.BuildObject[InfPath, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ if FdfModule in ModuleList:
+ continue
+ else:
+ ModuleList.append(FdfModule)
+ GuidXRefFile.append("%s %s\n" % (FdfModule.Guid, FdfModule.BaseName))
+ GuidDict.update(FdfModule.Protocols)
+ GuidDict.update(FdfModule.Guids)
+ GuidDict.update(FdfModule.Ppis)
+ else:
+ FileStatementGuid = FfsObj.NameGuid
+ if FileStatementGuid in FileGuidList:
+ continue
+ else:
+ FileGuidList.append(FileStatementGuid)
+ Name = []
+ FfsPath = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
+ FfsPath = glob(os.path.join(FfsPath, FileStatementGuid) + TAB_STAR)
+ if not FfsPath:
+ continue
+ if not os.path.exists(FfsPath[0]):
+ continue
+ MatchDict = {}
+ ReFileEnds = compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
+ FileList = os.listdir(FfsPath[0])
+ for File in FileList:
+ Match = ReFileEnds.search(File)
+ if Match:
+ for Index in range(1, 8):
+ if Match.group(Index) and Match.group(Index) in MatchDict:
+ MatchDict[Match.group(Index)].append(File)
+ elif Match.group(Index):
+ MatchDict[Match.group(Index)] = [File]
+ if not MatchDict:
+ continue
+ if '.ui' in MatchDict:
+ for File in MatchDict['.ui']:
+ with open(os.path.join(FfsPath[0], File), 'rb') as F:
+ F.read()
+ length = F.tell()
+ F.seek(4)
+ TmpStr = unpack('%dh' % ((length - 4) // 2), F.read())
+ Name = ''.join(chr(c) for c in TmpStr[:-1])
+ else:
+ FileList = []
+ if 'fv.sec.txt' in MatchDict:
+ FileList = MatchDict['fv.sec.txt']
+ elif '.pe32.txt' in MatchDict:
+ FileList = MatchDict['.pe32.txt']
+ elif '.te.txt' in MatchDict:
+ FileList = MatchDict['.te.txt']
+ elif '.pic.txt' in MatchDict:
+ FileList = MatchDict['.pic.txt']
+ elif '.raw.txt' in MatchDict:
+ FileList = MatchDict['.raw.txt']
+ elif '.ffs.txt' in MatchDict:
+ FileList = MatchDict['.ffs.txt']
+ else:
+ pass
+ for File in FileList:
+ with open(os.path.join(FfsPath[0], File), 'r') as F:
+ Name.append((F.read().split()[-1]))
+ if not Name:
+ continue
+
+ Name = ' '.join(Name) if isinstance(Name, type([])) else Name
+ GuidXRefFile.append("%s %s\n" %(FileStatementGuid, Name))
+
+ # Append GUIDs, Protocols, and PPIs to the Xref file
+ GuidXRefFile.append("\n")
+ for key, item in GuidDict.items():
+ GuidXRefFile.append("%s %s\n" % (GuidStructureStringToGuidString(item).upper(), key))
+
+ if GuidXRefFile:
+ GuidXRefFile = ''.join(GuidXRefFile)
+ SaveFileOnChange(GuidXRefFileName, GuidXRefFile, False)
+ GenFdsGlobalVariable.QuietLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName) # VBox: We want this info in -quiet builds too.
+ elif os.path.exists(GuidXRefFileName):
+ os.remove(GuidXRefFileName)
+
+
+if __name__ == '__main__':
+ r = main()
+ ## 0-127 is a safe return range, and 1 is a standard default error
+ if r < 0 or r > 127:
+ r = 1
+ exit(r)
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
new file mode 100755
index 00000000..7454359c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
@@ -0,0 +1,1033 @@
+## @file
+# Global variables for GenFds
+#
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import print_function
+from __future__ import absolute_import
+
+import Common.LongFilePathOs as os
+import sys
+from sys import stdout
+from subprocess import PIPE,Popen
+from struct import Struct
+from array import array
+
+from Common.BuildToolError import COMMAND_FAILURE,GENFDS_ERROR
+from Common import EdkLogger
+from Common.Misc import SaveFileOnChange
+
+from Common.TargetTxtClassObject import TargetTxtDict
+from Common.ToolDefClassObject import ToolDefDict
+from AutoGen.BuildEngine import ToolBuildRule
+import Common.DataType as DataType
+from Common.Misc import PathClass,CreateDirectory
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+import Common.GlobalData as GlobalData
+from Common.BuildToolError import *
+from AutoGen.AutoGen import CalculatePriorityValue
+
+## Global variables
+#
+#
+class GenFdsGlobalVariable:
+ FvDir = ''
+ OutputDirDict = {}
+ BinDir = ''
+ # will be FvDir + os.sep + 'Ffs'
+ FfsDir = ''
+ FdfParser = None
+ LibDir = ''
+ WorkSpace = None
+ WorkSpaceDir = ''
+ ConfDir = ''
+ OutputDirFromDscDict = {}
+ TargetName = ''
+ ToolChainTag = ''
+ RuleDict = {}
+ ArchList = None
+ ActivePlatform = None
+ FvAddressFileName = ''
+ VerboseMode = False
+ DebugLevel = -1
+ SharpCounter = 0
+ SharpNumberPerLine = 40
+ FdfFile = ''
+ FdfFileTimeStamp = 0
+ FixedLoadAddress = False
+ PlatformName = ''
+
+ BuildRuleFamily = DataType.TAB_COMPILER_MSFT
+ ToolChainFamily = DataType.TAB_COMPILER_MSFT
+ __BuildRuleDatabase = None
+ GuidToolDefinition = {}
+ FfsCmdDict = {}
+ SecCmdList = []
+ CopyList = []
+ ModuleFile = ''
+ EnableGenfdsMultiThread = True
+
+ #
+ # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
+ # At the beginning of each generation of FV, false flag is appended to the list,
+ # after the call to GenerateSection returns, check the size of the output file,
+ # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
+ # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
+ # At the end of generation of FV, pop the flag.
+ # List is used as a stack to handle nested FV generation.
+ #
+ LargeFileInFvFlags = []
+ EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
+ LARGE_FILE_SIZE = 0x1000000
+
+ SectionHeader = Struct("3B 1B")
+
+ # FvName, FdName, CapName in FDF, Image file name
+ ImageBinDict = {}
+
+ ## LoadBuildRule
+ #
+ @staticmethod
+ def _LoadBuildRule():
+ if GenFdsGlobalVariable.__BuildRuleDatabase:
+ return GenFdsGlobalVariable.__BuildRuleDatabase
+ BuildRule = ToolBuildRule()
+ GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule.ToolBuildRule
+ TargetObj = TargetTxtDict()
+ ToolDefinitionFile = TargetObj.Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
+ if ToolDefinitionFile == '':
+ ToolDefinitionFile = "Conf/tools_def.txt"
+ if os.path.isfile(ToolDefinitionFile):
+ ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+ ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase
+ if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \
+ and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \
+ and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]:
+ GenFdsGlobalVariable.BuildRuleFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]
+
+ if DataType.TAB_TOD_DEFINES_FAMILY in ToolDefinition \
+ and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY] \
+ and ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]:
+ GenFdsGlobalVariable.ToolChainFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]
+ return GenFdsGlobalVariable.__BuildRuleDatabase
+
+ ## GetBuildRules
+ # @param Inf: object of InfBuildData
+ # @param Arch: current arch
+ #
+ @staticmethod
+ def GetBuildRules(Inf, Arch):
+ if not Arch:
+ Arch = DataType.TAB_COMMON
+
+ if not Arch in GenFdsGlobalVariable.OutputDirDict:
+ return {}
+
+ BuildRuleDatabase = GenFdsGlobalVariable._LoadBuildRule()
+ if not BuildRuleDatabase:
+ return {}
+
+ PathClassObj = PathClass(Inf.MetaFile.File,
+ GenFdsGlobalVariable.WorkSpaceDir)
+ BuildDir = os.path.join(
+ GenFdsGlobalVariable.OutputDirDict[Arch],
+ Arch,
+ PathClassObj.SubDir,
+ PathClassObj.BaseName
+ )
+ BinDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch)
+ Macro = {
+ "WORKSPACE":GenFdsGlobalVariable.WorkSpaceDir,
+ "MODULE_NAME":Inf.BaseName,
+ "MODULE_GUID":Inf.Guid,
+ "MODULE_VERSION":Inf.Version,
+ "MODULE_TYPE":Inf.ModuleType,
+ "MODULE_FILE":str(PathClassObj),
+ "MODULE_FILE_BASE_NAME":PathClassObj.BaseName,
+ "MODULE_RELATIVE_DIR":PathClassObj.SubDir,
+ "MODULE_DIR":PathClassObj.SubDir,
+ "BASE_NAME":Inf.BaseName,
+ "ARCH":Arch,
+ "TOOLCHAIN":GenFdsGlobalVariable.ToolChainTag,
+ "TOOLCHAIN_TAG":GenFdsGlobalVariable.ToolChainTag,
+ "TOOL_CHAIN_TAG":GenFdsGlobalVariable.ToolChainTag,
+ "TARGET":GenFdsGlobalVariable.TargetName,
+ "BUILD_DIR":GenFdsGlobalVariable.OutputDirDict[Arch],
+ "BIN_DIR":BinDir,
+ "LIB_DIR":BinDir,
+ "MODULE_BUILD_DIR":BuildDir,
+ "OUTPUT_DIR":os.path.join(BuildDir, "OUTPUT"),
+ "DEBUG_DIR":os.path.join(BuildDir, "DEBUG")
+ }
+
+ BuildRules = {}
+ for Type in BuildRuleDatabase.FileTypeList:
+ #first try getting build rule by BuildRuleFamily
+ RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
+ if not RuleObject:
+ # build type is always module type, but ...
+ if Inf.ModuleType != Inf.BuildType:
+ RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
+ #second try getting build rule by ToolChainFamily
+ if not RuleObject:
+ RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.ToolChainFamily]
+ if not RuleObject:
+ # build type is always module type, but ...
+ if Inf.ModuleType != Inf.BuildType:
+ RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.ToolChainFamily]
+ if not RuleObject:
+ continue
+ RuleObject = RuleObject.Instantiate(Macro)
+ BuildRules[Type] = RuleObject
+ for Ext in RuleObject.SourceFileExtList:
+ BuildRules[Ext] = RuleObject
+ return BuildRules
+
+ ## GetModuleCodaTargetList
+ #
+ # @param Inf: object of InfBuildData
+ # @param Arch: current arch
+ #
+ @staticmethod
+ def GetModuleCodaTargetList(Inf, Arch):
+ BuildRules = GenFdsGlobalVariable.GetBuildRules(Inf, Arch)
+ if not BuildRules:
+ return []
+
+ TargetList = set()
+ FileList = []
+
+ if not Inf.IsBinaryModule:
+ for File in Inf.Sources:
+ if File.TagName in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainTag} and \
+ File.ToolChainFamily in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainFamily}:
+ FileList.append((File, DataType.TAB_UNKNOWN_FILE))
+
+ for File in Inf.Binaries:
+ if File.Target in {DataType.TAB_COMMON, DataType.TAB_STAR, GenFdsGlobalVariable.TargetName}:
+ FileList.append((File, File.Type))
+
+ for File, FileType in FileList:
+ LastTarget = None
+ RuleChain = []
+ SourceList = [File]
+ Index = 0
+ while Index < len(SourceList):
+ Source = SourceList[Index]
+ Index = Index + 1
+
+ if File.IsBinary and File == Source and Inf.Binaries and File in Inf.Binaries:
+ # Skip all files that are not binary libraries
+ if not Inf.LibraryClass:
+ continue
+ RuleObject = BuildRules[DataType.TAB_DEFAULT_BINARY_FILE]
+ elif FileType in BuildRules:
+ RuleObject = BuildRules[FileType]
+ elif Source.Ext in BuildRules:
+ RuleObject = BuildRules[Source.Ext]
+ else:
+ # stop at no more rules
+ if LastTarget:
+ TargetList.add(str(LastTarget))
+ break
+
+ FileType = RuleObject.SourceFileType
+
+ # stop at STATIC_LIBRARY for library
+ if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY:
+ if LastTarget:
+ TargetList.add(str(LastTarget))
+ break
+
+ Target = RuleObject.Apply(Source)
+ if not Target:
+ if LastTarget:
+ TargetList.add(str(LastTarget))
+ break
+ elif not Target.Outputs:
+ # Only do build for target with outputs
+ TargetList.add(str(Target))
+
+ # to avoid cyclic rule
+ if FileType in RuleChain:
+ break
+
+ RuleChain.append(FileType)
+ SourceList.extend(Target.Outputs)
+ LastTarget = Target
+ FileType = DataType.TAB_UNKNOWN_FILE
+ for Cmd in Target.Commands:
+ if "$(CP)" == Cmd.split()[0]:
+ CpTarget = Cmd.split()[2]
+ TargetList.add(CpTarget)
+
+ return list(TargetList)
+
+ ## SetDir()
+ #
+ # @param OutputDir Output directory
+ # @param FdfParser FDF contents parser
+ # @param Workspace The directory of workspace
+ # @param ArchList The Arch list of platform
+ #
+ @staticmethod
+ def SetDir (OutputDir, FdfParser, WorkSpace, ArchList):
+ GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir)
+ GenFdsGlobalVariable.FdfParser = FdfParser
+ GenFdsGlobalVariable.WorkSpace = WorkSpace
+ GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY)
+ if not os.path.exists(GenFdsGlobalVariable.FvDir):
+ os.makedirs(GenFdsGlobalVariable.FvDir)
+ GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
+ if not os.path.exists(GenFdsGlobalVariable.FfsDir):
+ os.makedirs(GenFdsGlobalVariable.FfsDir)
+
+ #
+ # Create FV Address inf file
+ #
+ GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
+ FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
+ #
+ # Add [Options]
+ #
+ FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK)
+ BsAddress = '0'
+ for Arch in ArchList:
+ if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress:
+ BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress
+ break
+
+ FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
+ BsAddress + \
+ DataType.TAB_LINE_BREAK)
+
+ RtAddress = '0'
+ for Arch in reversed(ArchList):
+ temp = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress
+ if temp:
+ RtAddress = temp
+ break
+
+ FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
+ RtAddress + \
+ DataType.TAB_LINE_BREAK)
+
+ FvAddressFile.close()
+
+ @staticmethod
+ def SetEnv(FdfParser, WorkSpace, ArchList, GlobalData):
+ GenFdsGlobalVariable.ModuleFile = WorkSpace.ModuleFile
+ GenFdsGlobalVariable.FdfParser = FdfParser
+ GenFdsGlobalVariable.WorkSpace = WorkSpace.Db
+ GenFdsGlobalVariable.ArchList = ArchList
+ GenFdsGlobalVariable.ToolChainTag = GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]
+ GenFdsGlobalVariable.TargetName = GlobalData.gGlobalDefines["TARGET"]
+ GenFdsGlobalVariable.ActivePlatform = GlobalData.gActivePlatform
+ GenFdsGlobalVariable.ConfDir = GlobalData.gConfDirectory
+ GenFdsGlobalVariable.EnableGenfdsMultiThread = GlobalData.gEnableGenfdsMultiThread
+ for Arch in ArchList:
+ GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.normpath(
+ os.path.join(GlobalData.gWorkspace,
+ WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
+ GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory,
+ GlobalData.gGlobalDefines['TARGET'] +'_' + GlobalData.gGlobalDefines['TOOLCHAIN']))
+ GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = os.path.normpath(
+ WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
+ GlobalData.gGlobalDefines['TARGET'], GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory)
+ GenFdsGlobalVariable.PlatformName = WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
+ GlobalData.gGlobalDefines['TARGET'],
+ GlobalData.gGlobalDefines['TOOLCHAIN']].PlatformName
+ GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY)
+ if not os.path.exists(GenFdsGlobalVariable.FvDir):
+ os.makedirs(GenFdsGlobalVariable.FvDir)
+ GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
+ if not os.path.exists(GenFdsGlobalVariable.FfsDir):
+ os.makedirs(GenFdsGlobalVariable.FfsDir)
+
+ #
+ # Create FV Address inf file
+ #
+ GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
+ FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
+ #
+ # Add [Options]
+ #
+ FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK)
+ BsAddress = '0'
+ for Arch in ArchList:
+ BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
+ GlobalData.gGlobalDefines['TARGET'],
+ GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].BsBaseAddress
+ if BsAddress:
+ break
+
+ FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
+ BsAddress + \
+ DataType.TAB_LINE_BREAK)
+
+ RtAddress = '0'
+ for Arch in reversed(ArchList):
+ temp = GenFdsGlobalVariable.WorkSpace.BuildObject[
+ GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
+ GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress
+ if temp:
+ RtAddress = temp
+ break
+
+ FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
+ RtAddress + \
+ DataType.TAB_LINE_BREAK)
+
+ FvAddressFile.close()
+
+ ## ReplaceWorkspaceMacro()
+ #
+ # @param String String that may contain macro
+ #
+ @staticmethod
+ def ReplaceWorkspaceMacro(String):
+ String = mws.handleWsMacro(String)
+ Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir)
+ if os.path.exists(Str):
+ if not os.path.isabs(Str):
+ Str = os.path.abspath(Str)
+ else:
+ Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String)
+ return os.path.normpath(Str)
+
+ ## Check if the input files are newer than output files
+ #
+ # @param Output Path of output file
+ # @param Input Path list of input files
+ #
+ # @retval True if Output doesn't exist, or any Input is newer
+ # @retval False if all Input is older than Output
+ #
+ @staticmethod
+ def NeedsUpdate(Output, Input):
+ if not os.path.exists(Output):
+ return True
+ # always update "Output" if no "Input" given
+ if not Input:
+ return True
+
+ # if fdf file is changed after the 'Output" is generated, update the 'Output'
+ OutputTime = os.path.getmtime(Output)
+ if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime:
+ return True
+
+ for F in Input:
+ # always update "Output" if any "Input" doesn't exist
+ if not os.path.exists(F):
+ return True
+ # always update "Output" if any "Input" is newer than "Output"
+ if os.path.getmtime(F) > OutputTime:
+ return True
+ return False
+
+ @staticmethod
+ def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None,
+ GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=[], BuildNumber=None, DummyFile=None, IsMakefile=False):
+ Cmd = ["GenSec"]
+ if Type:
+ Cmd += ("-s", Type)
+ if CompressionType:
+ Cmd += ("-c", CompressionType)
+ if Guid:
+ Cmd += ("-g", Guid)
+ if DummyFile:
+ Cmd += ("--dummy", DummyFile)
+ if GuidHdrLen:
+ Cmd += ("-l", GuidHdrLen)
+ #Add each guided attribute
+ for Attr in GuidAttr:
+ Cmd += ("-r", Attr)
+ #Section Align is only for dummy section without section type
+ for SecAlign in InputAlign:
+ Cmd += ("--sectionalign", SecAlign)
+
+ CommandFile = Output + '.txt'
+ if Ui:
+ if IsMakefile:
+ if Ui == "$(MODULE_NAME)":
+ Cmd += ('-n', Ui)
+ else:
+ Cmd += ("-n", '"' + Ui + '"')
+ Cmd += ("-o", Output)
+ if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
+ GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
+ else:
+ SectionData = array('B', [0, 0, 0, 0])
+ SectionData.fromlist(array('B',Ui.encode('utf-16-le')).tolist())
+ SectionData.append(0)
+ SectionData.append(0)
+ Len = len(SectionData)
+ GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
+
+
+ DirName = os.path.dirname(Output)
+ if not CreateDirectory(DirName):
+ EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName)
+ else:
+ if DirName == '':
+ DirName = os.getcwd()
+ if not os.access(DirName, os.W_OK):
+ EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)
+
+ try:
+ with open(Output, "wb") as Fd:
+ SectionData.tofile(Fd)
+ Fd.flush()
+ except IOError as X:
+ EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X)
+
+ elif Ver:
+ Cmd += ("-n", Ver)
+ if BuildNumber:
+ Cmd += ("-j", BuildNumber)
+ Cmd += ("-o", Output)
+
+ SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
+ if IsMakefile:
+ if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
+ GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
+ else:
+ if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
+ return
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
+ else:
+ Cmd += ("-o", Output)
+ Cmd += Input
+
+ SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
+ if IsMakefile:
+ if sys.platform == "win32":
+ Cmd = ['if', 'exist', Input[0]] + Cmd
+ else:
+ Cmd = ['-test', '-e', Input[0], "&&"] + Cmd
+ if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
+ GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
+ elif GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
+ GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
+ if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and
+ GenFdsGlobalVariable.LargeFileInFvFlags):
+ GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True
+
+ @staticmethod
+ def GetAlignment (AlignString):
+ if not AlignString:
+ return 0
+ if AlignString.endswith('K'):
+ return int (AlignString.rstrip('K')) * 1024
+ if AlignString.endswith('M'):
+ return int (AlignString.rstrip('M')) * 1024 * 1024
+ if AlignString.endswith('G'):
+ return int (AlignString.rstrip('G')) * 1024 * 1024 * 1024
+ return int (AlignString)
+
+ @staticmethod
+ def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
+ SectionAlign=None, MakefilePath=None):
+ Cmd = ["GenFfs", "-t", Type, "-g", Guid]
+ mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
+ if Fixed == True:
+ Cmd.append("-x")
+ if CheckSum:
+ Cmd.append("-s")
+ if Align:
+ if Align not in mFfsValidAlign:
+ Align = GenFdsGlobalVariable.GetAlignment (Align)
+ for index in range(0, len(mFfsValidAlign) - 1):
+ if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))):
+ break
+ Align = mFfsValidAlign[index + 1]
+ Cmd += ("-a", Align)
+
+ Cmd += ("-o", Output)
+ for I in range(0, len(Input)):
+ if MakefilePath:
+ Cmd += ("-oi", Input[I])
+ else:
+ Cmd += ("-i", Input[I])
+ if SectionAlign and SectionAlign[I]:
+ Cmd += ("-n", SectionAlign[I])
+
+ CommandFile = Output + '.txt'
+ SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
+
+ GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
+ if MakefilePath:
+ if (tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)) not in GenFdsGlobalVariable.FfsCmdDict:
+ GenFdsGlobalVariable.FfsCmdDict[tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)] = MakefilePath
+ GenFdsGlobalVariable.SecCmdList = []
+ GenFdsGlobalVariable.CopyList = []
+ else:
+ if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
+ return
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS")
+
+ @staticmethod
+ def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False,
+ AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None):
+ if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList):
+ return
+ GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
+
+ Cmd = ["GenFv"]
+ if BaseAddress:
+ Cmd += ("-r", BaseAddress)
+
+ if ForceRebase == False:
+ Cmd += ("-F", "FALSE")
+ elif ForceRebase == True:
+ Cmd += ("-F", "TRUE")
+
+ if Capsule:
+ Cmd.append("-c")
+ if Dump:
+ Cmd.append("-p")
+ if AddressFile:
+ Cmd += ("-a", AddressFile)
+ if MapFile:
+ Cmd += ("-m", MapFile)
+ if FileSystemGuid:
+ Cmd += ("-g", FileSystemGuid)
+ Cmd += ("-o", Output)
+ for I in Input:
+ Cmd += ("-i", I)
+
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV")
+
+ @staticmethod
+ def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False,
+ Strip=False, Replace=False, TimeStamp=None, Join=False,
+ Align=None, Padding=None, Convert=False, IsMakefile=False):
+ if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
+ return
+ GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
+
+ Cmd = ["GenFw"]
+ if Type.lower() == "te":
+ Cmd.append("-t")
+ if SubType:
+ Cmd += ("-e", SubType)
+ if TimeStamp:
+ Cmd += ("-s", TimeStamp)
+ if Align:
+ Cmd += ("-a", Align)
+ if Padding:
+ Cmd += ("-p", Padding)
+ if Zero:
+ Cmd.append("-z")
+ if Strip:
+ Cmd.append("-l")
+ if Replace:
+ Cmd.append("-r")
+ if Join:
+ Cmd.append("-j")
+ if Convert:
+ Cmd.append("-m")
+ Cmd += ("-o", Output)
+ Cmd += Input
+ if IsMakefile:
+ if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
+ GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
+ else:
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image")
+
+ @staticmethod
+ def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None,
+ Revision=None, DeviceId=None, VendorId=None, IsMakefile=False):
+ InputList = []
+ Cmd = ["EfiRom"]
+ if EfiInput:
+
+ if Compress:
+ Cmd.append("-ec")
+ else:
+ Cmd.append("-e")
+
+ for EfiFile in EfiInput:
+ Cmd.append(EfiFile)
+ InputList.append (EfiFile)
+
+ if BinaryInput:
+ Cmd.append("-b")
+ for BinFile in BinaryInput:
+ Cmd.append(BinFile)
+ InputList.append (BinFile)
+
+ # Check List
+ if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList) and not IsMakefile:
+ return
+ GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList))
+
+ if ClassCode:
+ Cmd += ("-l", ClassCode)
+ if Revision:
+ Cmd += ("-r", Revision)
+ if DeviceId:
+ Cmd += ("-i", DeviceId)
+ if VendorId:
+ Cmd += ("-f", VendorId)
+
+ Cmd += ("-o", Output)
+ if IsMakefile:
+ if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
+ GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
+ else:
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom")
+
+ @staticmethod
+ def GuidTool(Output, Input, ToolPath, Options='', returnValue=[], IsMakefile=False):
+ if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
+ return
+ GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
+
+ Cmd = [ToolPath, ]
+ Cmd += Options.split(' ')
+ Cmd += ("-o", Output)
+ Cmd += Input
+ if IsMakefile:
+ if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
+ GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
+ else:
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue)
+
+ @staticmethod
+ def CallExternalTool (cmd, errorMess, returnValue=[]):
+
+ if type(cmd) not in (tuple, list):
+ GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
+
+ if GenFdsGlobalVariable.DebugLevel != -1:
+ cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel))
+ GenFdsGlobalVariable.InfLogger (cmd)
+
+ if GenFdsGlobalVariable.VerboseMode:
+ cmd += ('-v',)
+ GenFdsGlobalVariable.InfLogger (cmd)
+ else:
+ stdout.write ('#')
+ stdout.flush()
+ GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
+ if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
+ stdout.write('\n')
+
+ try:
+ PopenObject = Popen(' '.join(cmd), stdout=PIPE, stderr=PIPE, shell=True)
+ except Exception as X:
+ EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
+ (out, error) = PopenObject.communicate()
+
+ while PopenObject.returncode is None:
+ PopenObject.wait()
+ if returnValue != [] and returnValue[0] != 0:
+ #get command return value
+ returnValue[0] = PopenObject.returncode
+ return
+ if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1:
+ GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode)
+ GenFdsGlobalVariable.InfLogger(out.decode(encoding='utf-8', errors='ignore'))
+ GenFdsGlobalVariable.InfLogger(error.decode(encoding='utf-8', errors='ignore'))
+ if PopenObject.returncode != 0:
+ print("###", cmd)
+ EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
+
+ @staticmethod
+ def VerboseLogger (msg):
+ EdkLogger.verbose(msg)
+
+ @staticmethod
+ def InfLogger (msg):
+ EdkLogger.info(msg)
+
+ # VBox - begin - Used by GenFds to show firmware space allocs during --quiet builds, and maybe more.
+ @staticmethod
+ def QuietLogger (msg):
+ EdkLogger.quiet(msg)
+ # VBox - end
+
+ @staticmethod
+ def ErrorLogger (msg, File=None, Line=None, ExtraData=None):
+ EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
+
+ @staticmethod
+ def DebugLogger (Level, msg):
+ EdkLogger.debug(Level, msg)
+
+ ## MacroExtend()
+ #
+ # @param Str String that may contain macro
+ # @param MacroDict Dictionary that contains macro value pair
+ #
+ @staticmethod
+ def MacroExtend (Str, MacroDict=None, Arch=DataType.TAB_COMMON):
+ if Str is None:
+ return None
+
+ Dict = {'$(WORKSPACE)': GenFdsGlobalVariable.WorkSpaceDir,
+# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
+ '$(TARGET)': GenFdsGlobalVariable.TargetName,
+ '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable.ToolChainTag,
+ '$(SPACE)': ' '
+ }
+
+ if Arch != DataType.TAB_COMMON and Arch in GenFdsGlobalVariable.ArchList:
+ OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
+ else:
+ OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
+
+ Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
+
+ if MacroDict:
+ Dict.update(MacroDict)
+
+ for key in Dict:
+ if Str.find(key) >= 0:
+ Str = Str.replace (key, Dict[key])
+
+ if Str.find('$(ARCH)') >= 0:
+ if len(GenFdsGlobalVariable.ArchList) == 1:
+ Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0])
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str)
+
+ return Str
+
+ ## GetPcdValue()
+ #
+ # @param PcdPattern pattern that labels a PCD.
+ #
+ @staticmethod
+ def GetPcdValue (PcdPattern):
+ if PcdPattern is None:
+ return None
+ if PcdPattern.startswith('PCD('):
+ PcdPair = PcdPattern[4:].rstrip(')').strip().split('.')
+ else:
+ PcdPair = PcdPattern.strip().split('.')
+ TokenSpace = PcdPair[0]
+ TokenCName = PcdPair[1]
+
+ for Arch in GenFdsGlobalVariable.ArchList:
+ Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ PcdDict = Platform.Pcds
+ for Key in PcdDict:
+ PcdObj = PcdDict[Key]
+ if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
+ if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
+ if PcdObj.DatumType != DataType.TAB_VOID:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
+
+ return PcdObj.DefaultValue
+
+ for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform,
+ Arch,
+ GenFdsGlobalVariable.TargetName,
+ GenFdsGlobalVariable.ToolChainTag):
+ PcdDict = Package.Pcds
+ for Key in PcdDict:
+ PcdObj = PcdDict[Key]
+ if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
+ if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
+ if PcdObj.DatumType != DataType.TAB_VOID:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
+
+ return PcdObj.DefaultValue
+
+ return ''
+
+## FindExtendTool()
+#
+# Find location of tools to process data
+#
+# @param KeyStringList Filter for inputs of section generation
+# @param CurrentArchList Arch list
+# @param NameGuid The Guid name
+#
+def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
+ if GenFdsGlobalVariable.GuidToolDefinition:
+ if NameGuid in GenFdsGlobalVariable.GuidToolDefinition:
+ return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
+
+ ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+ ToolDef = ToolDefObj.ToolDef
+ ToolDb = ToolDef.ToolsDefTxtDatabase
+ # if user not specify filter, try to deduce it from global data.
+ if KeyStringList is None or KeyStringList == []:
+ Target = GenFdsGlobalVariable.TargetName
+ ToolChain = GenFdsGlobalVariable.ToolChainTag
+ if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)
+ KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]]
+ for Arch in CurrentArchList:
+ if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:
+ KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
+
+ ToolPathTmp = None
+ ToolOption = None
+ for Arch in CurrentArchList:
+ MatchItem = None
+ MatchPathItem = None
+ MatchOptionsItem = None
+ for KeyString in KeyStringList:
+ KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_')
+ if KeyStringArch != Arch:
+ continue
+ for Item in ToolDef.ToolsDefTxtDictionary:
+ if len(Item.split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemAttr != DataType.TAB_GUID:
+ # Not GUID attribute
+ continue
+ if ToolDef.ToolsDefTxtDictionary[Item].lower() != NameGuid.lower():
+ # No GUID value match
+ continue
+ if MatchItem:
+ if MatchItem.split('_')[3] == ItemTool:
+ # Tool name is the same
+ continue
+ if CalculatePriorityValue(MatchItem) > CalculatePriorityValue(Item):
+ # Current MatchItem is higher priority than new match item
+ continue
+ MatchItem = Item
+ if not MatchItem:
+ continue
+ ToolName = MatchItem.split('_')[3]
+ for Item in ToolDef.ToolsDefTxtDictionary:
+ if len(Item.split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemTool != ToolName:
+ continue
+ if ItemAttr == 'PATH':
+ if MatchPathItem:
+ if CalculatePriorityValue(MatchPathItem) <= CalculatePriorityValue(Item):
+ MatchPathItem = Item
+ else:
+ MatchPathItem = Item
+ if ItemAttr == 'FLAGS':
+ if MatchOptionsItem:
+ if CalculatePriorityValue(MatchOptionsItem) <= CalculatePriorityValue(Item):
+ MatchOptionsItem = Item
+ else:
+ MatchOptionsItem = Item
+ if MatchPathItem:
+ ToolPathTmp = ToolDef.ToolsDefTxtDictionary[MatchPathItem]
+ if MatchOptionsItem:
+ ToolOption = ToolDef.ToolsDefTxtDictionary[MatchOptionsItem]
+
+ for Arch in CurrentArchList:
+ MatchItem = None
+ MatchPathItem = None
+ MatchOptionsItem = None
+ for KeyString in KeyStringList:
+ KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_')
+ if KeyStringArch != Arch:
+ continue
+ Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, KeyStringBuildTarget, KeyStringToolChain]
+ for Item in Platform.BuildOptions:
+ if len(Item[1].split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemAttr != DataType.TAB_GUID:
+ # Not GUID attribute match
+ continue
+ if Platform.BuildOptions[Item].lower() != NameGuid.lower():
+ # No GUID value match
+ continue
+ if MatchItem:
+ if MatchItem[1].split('_')[3] == ItemTool:
+ # Tool name is the same
+ continue
+ if CalculatePriorityValue(MatchItem[1]) > CalculatePriorityValue(Item[1]):
+ # Current MatchItem is higher priority than new match item
+ continue
+ MatchItem = Item
+ if not MatchItem:
+ continue
+ ToolName = MatchItem[1].split('_')[3]
+ for Item in Platform.BuildOptions:
+ if len(Item[1].split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemTool != ToolName:
+ continue
+ if ItemAttr == 'PATH':
+ if MatchPathItem:
+ if CalculatePriorityValue(MatchPathItem[1]) <= CalculatePriorityValue(Item[1]):
+ MatchPathItem = Item
+ else:
+ MatchPathItem = Item
+ if ItemAttr == 'FLAGS':
+ if MatchOptionsItem:
+ if CalculatePriorityValue(MatchOptionsItem[1]) <= CalculatePriorityValue(Item[1]):
+ MatchOptionsItem = Item
+ else:
+ MatchOptionsItem = Item
+ if MatchPathItem:
+ ToolPathTmp = Platform.BuildOptions[MatchPathItem]
+ if MatchOptionsItem:
+ ToolOption = Platform.BuildOptions[MatchOptionsItem]
+ GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
+ return ToolPathTmp, ToolOption
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GuidSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GuidSection.py
new file mode 100755
index 00000000..3e7d9673
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GuidSection.py
@@ -0,0 +1,278 @@
+## @file
+# process GUIDed section generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Section
+import subprocess
+from .Ffs import SectionSuffix
+import Common.LongFilePathOs as os
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from .GenFdsGlobalVariable import FindExtendTool
+from CommonDataClass.FdfClass import GuidSectionClassObject
+import sys
+from Common import EdkLogger
+from Common.BuildToolError import *
+from .FvImageSection import FvImageSection
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.DataType import *
+
+## generate GUIDed section
+#
+#
+class GuidSection(GuidSectionClassObject) :
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ GuidSectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # Generate GUIDed section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf=None, Dict=None, IsMakefile=False):
+ #
+ # Generate all section
+ #
+ self.KeyStringList = KeyStringList
+ self.CurrentArchList = GenFdsGlobalVariable.ArchList
+ if FfsInf is not None:
+ self.Alignment = FfsInf.__ExtendMacro__(self.Alignment)
+ self.NameGuid = FfsInf.__ExtendMacro__(self.NameGuid)
+ self.SectionType = FfsInf.__ExtendMacro__(self.SectionType)
+ self.CurrentArchList = [FfsInf.CurrentArch]
+
+ SectFile = tuple()
+ SectAlign = []
+ Index = 0
+ MaxAlign = None
+ if Dict is None:
+ Dict = {}
+ if self.FvAddr != []:
+ FvAddrIsSet = True
+ else:
+ FvAddrIsSet = False
+
+ if self.ProcessRequired in ("TRUE", "1"):
+ if self.FvAddr != []:
+ #no use FvAddr when the image is processed.
+ self.FvAddr = []
+ if self.FvParentAddr is not None:
+ #no use Parent Addr when the image is processed.
+ self.FvParentAddr = None
+
+ for Sect in self.SectionList:
+ Index = Index + 1
+ SecIndex = '%s.%d' % (SecNum, Index)
+ # set base address for inside FvImage
+ if isinstance(Sect, FvImageSection):
+ if self.FvAddr != []:
+ Sect.FvAddr = self.FvAddr.pop(0)
+ self.IncludeFvSection = True
+ elif isinstance(Sect, GuidSection):
+ Sect.FvAddr = self.FvAddr
+ Sect.FvParentAddr = self.FvParentAddr
+ ReturnSectList, align = Sect.GenSection(OutputPath, ModuleName, SecIndex, KeyStringList, FfsInf, Dict, IsMakefile=IsMakefile)
+ if isinstance(Sect, GuidSection):
+ if Sect.IncludeFvSection:
+ self.IncludeFvSection = Sect.IncludeFvSection
+
+ if align is not None:
+ if MaxAlign is None:
+ MaxAlign = align
+ if GenFdsGlobalVariable.GetAlignment (align) > GenFdsGlobalVariable.GetAlignment (MaxAlign):
+ MaxAlign = align
+ if ReturnSectList != []:
+ if align is None:
+ align = "1"
+ for file in ReturnSectList:
+ SectFile += (file,)
+ SectAlign.append(align)
+
+ if MaxAlign is not None:
+ if self.Alignment is None:
+ self.Alignment = MaxAlign
+ else:
+ if GenFdsGlobalVariable.GetAlignment (MaxAlign) > GenFdsGlobalVariable.GetAlignment (self.Alignment):
+ self.Alignment = MaxAlign
+
+ OutputFile = OutputPath + \
+ os.sep + \
+ ModuleName + \
+ SUP_MODULE_SEC + \
+ SecNum + \
+ SectionSuffix['GUIDED']
+ OutputFile = os.path.normpath(OutputFile)
+
+ ExternalTool = None
+ ExternalOption = None
+ if self.NameGuid is not None:
+ ExternalTool, ExternalOption = FindExtendTool(self.KeyStringList, self.CurrentArchList, self.NameGuid)
+
+ #
+ # If not have GUID , call default
+ # GENCRC32 section
+ #
+ if self.NameGuid is None :
+ GenFdsGlobalVariable.VerboseLogger("Use GenSection function Generate CRC32 Section")
+ GenFdsGlobalVariable.GenerateSection(OutputFile, SectFile, Section.Section.SectionType[self.SectionType], InputAlign=SectAlign, IsMakefile=IsMakefile)
+ OutputFileList = []
+ OutputFileList.append(OutputFile)
+ return OutputFileList, self.Alignment
+ #or GUID not in External Tool List
+ elif ExternalTool is None:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % self.NameGuid)
+ else:
+ DummyFile = OutputFile + ".dummy"
+ #
+ # Call GenSection with DUMMY section type.
+ #
+ GenFdsGlobalVariable.GenerateSection(DummyFile, SectFile, InputAlign=SectAlign, IsMakefile=IsMakefile)
+ #
+ # Use external tool process the Output
+ #
+ TempFile = OutputPath + \
+ os.sep + \
+ ModuleName + \
+ SUP_MODULE_SEC + \
+ SecNum + \
+ '.tmp'
+ TempFile = os.path.normpath(TempFile)
+ #
+ # Remove temp file if its time stamp is older than dummy file
+ # Just in case the external tool fails at this time but succeeded before
+ # Error should be reported if the external tool does not generate a new output based on new input
+ #
+ if os.path.exists(TempFile) and os.path.exists(DummyFile) and os.path.getmtime(TempFile) < os.path.getmtime(DummyFile):
+ os.remove(TempFile)
+
+ FirstCall = False
+ CmdOption = '-e'
+ if ExternalOption is not None:
+ CmdOption = CmdOption + ' ' + ExternalOption
+ if not GenFdsGlobalVariable.EnableGenfdsMultiThread:
+ if self.ProcessRequired not in ("TRUE", "1") and self.IncludeFvSection and not FvAddrIsSet and self.FvParentAddr is not None:
+ #FirstCall is only set for the encapsulated flash FV image without process required attribute.
+ FirstCall = True
+ #
+ # Call external tool
+ #
+ ReturnValue = [1]
+ if FirstCall:
+ #first try to call the guided tool with -z option and CmdOption for the no process required guided tool.
+ GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, '-z' + ' ' + CmdOption, ReturnValue)
+
+ #
+ # when no call or first call failed, ReturnValue are not 1.
+ # Call the guided tool with CmdOption
+ #
+ if ReturnValue[0] != 0:
+ FirstCall = False
+ ReturnValue[0] = 0
+ GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption)
+ #
+ # There is external tool which does not follow standard rule which return nonzero if tool fails
+ # The output file has to be checked
+ #
+
+ if not os.path.exists(TempFile) :
+ EdkLogger.error("GenFds", COMMAND_FAILURE, 'Fail to call %s, no output file was generated' % ExternalTool)
+
+ FileHandleIn = open(DummyFile, 'rb')
+ FileHandleIn.seek(0, 2)
+ InputFileSize = FileHandleIn.tell()
+
+ FileHandleOut = open(TempFile, 'rb')
+ FileHandleOut.seek(0, 2)
+ TempFileSize = FileHandleOut.tell()
+
+ Attribute = []
+ HeaderLength = None
+ if self.ExtraHeaderSize != -1:
+ HeaderLength = str(self.ExtraHeaderSize)
+
+ if self.ProcessRequired == "NONE" and HeaderLength is None:
+ if TempFileSize > InputFileSize:
+ FileHandleIn.seek(0)
+ BufferIn = FileHandleIn.read()
+ FileHandleOut.seek(0)
+ BufferOut = FileHandleOut.read()
+ if BufferIn == BufferOut[TempFileSize - InputFileSize:]:
+ HeaderLength = str(TempFileSize - InputFileSize)
+ #auto sec guided attribute with process required
+ if HeaderLength is None:
+ Attribute.append('PROCESSING_REQUIRED')
+
+ FileHandleIn.close()
+ FileHandleOut.close()
+
+ if FirstCall and 'PROCESSING_REQUIRED' in Attribute:
+ # Guided data by -z option on first call is the process required data. Call the guided tool with the real option.
+ GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption)
+
+ #
+ # Call Gensection Add Section Header
+ #
+ if self.ProcessRequired in ("TRUE", "1"):
+ if 'PROCESSING_REQUIRED' not in Attribute:
+ Attribute.append('PROCESSING_REQUIRED')
+
+ if self.AuthStatusValid in ("TRUE", "1"):
+ Attribute.append('AUTH_STATUS_VALID')
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'],
+ Guid=self.NameGuid, GuidAttr=Attribute, GuidHdrLen=HeaderLength)
+
+ else:
+ #add input file for GenSec get PROCESSING_REQUIRED
+ GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption, IsMakefile=IsMakefile)
+ Attribute = []
+ HeaderLength = None
+ if self.ExtraHeaderSize != -1:
+ HeaderLength = str(self.ExtraHeaderSize)
+ if self.AuthStatusValid in ("TRUE", "1"):
+ Attribute.append('AUTH_STATUS_VALID')
+ if self.ProcessRequired == "NONE" and HeaderLength is None:
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'],
+ Guid=self.NameGuid, GuidAttr=Attribute,
+ GuidHdrLen=HeaderLength, DummyFile=DummyFile, IsMakefile=IsMakefile)
+ else:
+ if self.ProcessRequired in ("TRUE", "1"):
+ if 'PROCESSING_REQUIRED' not in Attribute:
+ Attribute.append('PROCESSING_REQUIRED')
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'],
+ Guid=self.NameGuid, GuidAttr=Attribute,
+ GuidHdrLen=HeaderLength, IsMakefile=IsMakefile)
+
+ OutputFileList = []
+ OutputFileList.append(OutputFile)
+ if 'PROCESSING_REQUIRED' in Attribute:
+ # reset guided section alignment to none for the processed required guided data
+ self.Alignment = None
+ self.IncludeFvSection = False
+ self.ProcessRequired = "TRUE"
+ if IsMakefile and self.Alignment is not None and self.Alignment.strip() == '0':
+ self.Alignment = '1'
+ return OutputFileList, self.Alignment
+
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomFileStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomFileStatement.py
new file mode 100755
index 00000000..f6d8a529
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomFileStatement.py
@@ -0,0 +1,48 @@
+## @file
+# process OptionROM generation from FILE statement
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+import Common.LongFilePathOs as os
+
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+##
+#
+#
+class OptRomFileStatement:
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ self.FileName = None
+ self.FileType = None
+ self.OverrideAttribs = None
+
+ ## GenFfs() method
+ #
+ # Generate FFS
+ #
+ # @param self The object pointer
+ # @param Dict dictionary contains macro and value pair
+ # @retval string Generated FFS file name
+ #
+ def GenFfs(self, Dict = None, IsMakefile=False):
+
+ if Dict is None:
+ Dict = {}
+
+ if self.FileName is not None:
+ self.FileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName)
+
+ return self.FileName
+
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomInfStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomInfStatement.py
new file mode 100755
index 00000000..43fd46ad
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptRomInfStatement.py
@@ -0,0 +1,159 @@
+## @file
+# process OptionROM generation from INF statement
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import RuleSimpleFile
+from . import RuleComplexFile
+from . import Section
+import Common.GlobalData as GlobalData
+
+from Common.DataType import *
+from Common.StringUtils import *
+from .FfsInfStatement import FfsInfStatement
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+
+##
+#
+#
+class OptRomInfStatement (FfsInfStatement):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ FfsInfStatement.__init__(self)
+ self.OverrideAttribs = None
+
+ ## __GetOptRomParams() method
+ #
+ # Parse inf file to get option ROM related parameters
+ #
+ # @param self The object pointer
+ #
+ def __GetOptRomParams(self):
+ if self.OverrideAttribs is None:
+ self.OverrideAttribs = OverrideAttribs()
+
+ if self.OverrideAttribs.NeedCompress is None:
+ self.OverrideAttribs.NeedCompress = self.OptRomDefs.get ('PCI_COMPRESS')
+ if self.OverrideAttribs.NeedCompress is not None:
+ if self.OverrideAttribs.NeedCompress.upper() not in ('TRUE', 'FALSE'):
+ GenFdsGlobalVariable.ErrorLogger( "Expected TRUE/FALSE for PCI_COMPRESS: %s" %self.InfFileName)
+ self.OverrideAttribs.NeedCompress = \
+ self.OverrideAttribs.NeedCompress.upper() == 'TRUE'
+
+ if self.OverrideAttribs.PciVendorId is None:
+ self.OverrideAttribs.PciVendorId = self.OptRomDefs.get ('PCI_VENDOR_ID')
+
+ if self.OverrideAttribs.PciClassCode is None:
+ self.OverrideAttribs.PciClassCode = self.OptRomDefs.get ('PCI_CLASS_CODE')
+
+ if self.OverrideAttribs.PciDeviceId is None:
+ self.OverrideAttribs.PciDeviceId = self.OptRomDefs.get ('PCI_DEVICE_ID')
+
+ if self.OverrideAttribs.PciRevision is None:
+ self.OverrideAttribs.PciRevision = self.OptRomDefs.get ('PCI_REVISION')
+
+# InfObj = GenFdsGlobalVariable.WorkSpace.BuildObject[self.PathClassObj, self.CurrentArch]
+# RecordList = InfObj._RawData[MODEL_META_DATA_HEADER, InfObj._Arch, InfObj._Platform]
+# for Record in RecordList:
+# Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
+# Name = Record[0]
+ ## GenFfs() method
+ #
+ # Generate FFS
+ #
+ # @param self The object pointer
+ # @retval string Generated .efi file name
+ #
+ def GenFfs(self, IsMakefile=False):
+ #
+ # Parse Inf file get Module related information
+ #
+
+ self.__InfParse__()
+ self.__GetOptRomParams()
+ #
+ # Get the rule of how to generate Ffs file
+ #
+ Rule = self.__GetRule__()
+ GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
+ #
+ # For the rule only has simpleFile
+ #
+ if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :
+ EfiOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)
+ return EfiOutputList
+ #
+ # For Rule has ComplexFile
+ #
+ elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
+ EfiOutputList = self.__GenComplexFileSection__(Rule, IsMakefile=IsMakefile)
+ return EfiOutputList
+
+ ## __GenSimpleFileSection__() method
+ #
+ # Get .efi files according to simple rule.
+ #
+ # @param self The object pointer
+ # @param Rule The rule object used to generate section
+ # @retval string File name of the generated section file
+ #
+ def __GenSimpleFileSection__(self, Rule, IsMakefile = False):
+ #
+ # Prepare the parameter of GenSection
+ #
+
+ OutputFileList = []
+ if Rule.FileName is not None:
+ GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
+ OutputFileList.append(GenSecInputFile)
+ else:
+ OutputFileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)
+
+ return OutputFileList
+
+
+ ## __GenComplexFileSection__() method
+ #
+ # Get .efi by sections in complex Rule
+ #
+ # @param self The object pointer
+ # @param Rule The rule object used to generate section
+ # @retval string File name of the generated section file
+ #
+ def __GenComplexFileSection__(self, Rule, IsMakefile=False):
+
+ OutputFileList = []
+ for Sect in Rule.SectionList:
+ if Sect.SectionType == BINARY_FILE_TYPE_PE32:
+ if Sect.FileName is not None:
+ GenSecInputFile = self.__ExtendMacro__(Sect.FileName)
+ OutputFileList.append(GenSecInputFile)
+ else:
+ FileList, IsSect = Section.Section.GetFileList(self, '', Sect.FileExtension)
+ OutputFileList.extend(FileList)
+
+ return OutputFileList
+
+class OverrideAttribs:
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+
+ self.PciVendorId = None
+ self.PciClassCode = None
+ self.PciDeviceId = None
+ self.PciRevision = None
+ self.NeedCompress = None
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptionRom.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptionRom.py
new file mode 100755
index 00000000..b609c15b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/OptionRom.py
@@ -0,0 +1,131 @@
+## @file
+# process OptionROM generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+import Common.LongFilePathOs as os
+import subprocess
+
+from . import OptRomInfStatement
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from CommonDataClass.FdfClass import OptionRomClassObject
+from Common.Misc import SaveFileOnChange
+from Common import EdkLogger
+from Common.BuildToolError import *
+
+##
+#
+#
+class OPTIONROM (OptionRomClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self, Name = ""):
+ OptionRomClassObject.__init__(self)
+ self.DriverName = Name
+
+ ## AddToBuffer()
+ #
+ # Generate Option ROM
+ #
+ # @param self The object pointer
+ # @param Buffer The buffer generated OptROM data will be put
+ # @retval string Generated OptROM file path
+ #
+ def AddToBuffer (self, Buffer, Flag=False) :
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger( "\nGenerating %s Option ROM ..." %self.DriverName)
+
+ EfiFileList = []
+ BinFileList = []
+
+ # Process Modules in FfsList
+ for FfsFile in self.FfsList :
+
+ if isinstance(FfsFile, OptRomInfStatement.OptRomInfStatement):
+ FilePathNameList = FfsFile.GenFfs(IsMakefile=Flag)
+ if len(FilePathNameList) == 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s not produce .efi files, so NO file could be put into option ROM." % (FfsFile.InfFileName))
+ if FfsFile.OverrideAttribs is None:
+ EfiFileList.extend(FilePathNameList)
+ else:
+ FileName = os.path.basename(FilePathNameList[0])
+ TmpOutputDir = os.path.join(GenFdsGlobalVariable.FvDir, self.DriverName, FfsFile.CurrentArch)
+ if not os.path.exists(TmpOutputDir) :
+ os.makedirs(TmpOutputDir)
+ TmpOutputFile = os.path.join(TmpOutputDir, FileName+'.tmp')
+
+ GenFdsGlobalVariable.GenerateOptionRom(TmpOutputFile,
+ FilePathNameList,
+ [],
+ FfsFile.OverrideAttribs.NeedCompress,
+ FfsFile.OverrideAttribs.PciClassCode,
+ FfsFile.OverrideAttribs.PciRevision,
+ FfsFile.OverrideAttribs.PciDeviceId,
+ FfsFile.OverrideAttribs.PciVendorId,
+ IsMakefile = Flag)
+ BinFileList.append(TmpOutputFile)
+ else:
+ FilePathName = FfsFile.GenFfs(IsMakefile=Flag)
+ if FfsFile.OverrideAttribs is not None:
+ FileName = os.path.basename(FilePathName)
+ TmpOutputDir = os.path.join(GenFdsGlobalVariable.FvDir, self.DriverName, FfsFile.CurrentArch)
+ if not os.path.exists(TmpOutputDir) :
+ os.makedirs(TmpOutputDir)
+ TmpOutputFile = os.path.join(TmpOutputDir, FileName+'.tmp')
+
+ GenFdsGlobalVariable.GenerateOptionRom(TmpOutputFile,
+ [FilePathName],
+ [],
+ FfsFile.OverrideAttribs.NeedCompress,
+ FfsFile.OverrideAttribs.PciClassCode,
+ FfsFile.OverrideAttribs.PciRevision,
+ FfsFile.OverrideAttribs.PciDeviceId,
+ FfsFile.OverrideAttribs.PciVendorId,
+ IsMakefile=Flag)
+ BinFileList.append(TmpOutputFile)
+ else:
+ if FfsFile.FileType == 'EFI':
+ EfiFileList.append(FilePathName)
+ else:
+ BinFileList.append(FilePathName)
+
+ #
+ # Call EfiRom tool
+ #
+ OutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.DriverName)
+ OutputFile = OutputFile + '.rom'
+
+ GenFdsGlobalVariable.GenerateOptionRom(
+ OutputFile,
+ EfiFileList,
+ BinFileList,
+ IsMakefile=Flag)
+
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger( "\nGenerate %s Option ROM Successfully" %self.DriverName)
+ GenFdsGlobalVariable.SharpCounter = 0
+
+ return OutputFile
+
+class OverrideAttribs:
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+
+ self.PciVendorId = None
+ self.PciClassCode = None
+ self.PciDeviceId = None
+ self.PciRevision = None
+ self.NeedCompress = None
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Region.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Region.py
new file mode 100755
index 00000000..75909096
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Region.py
@@ -0,0 +1,348 @@
+## @file
+# process FD Region generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from struct import *
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from io import BytesIO
+import string
+import Common.LongFilePathOs as os
+from stat import *
+from Common import EdkLogger
+from Common.BuildToolError import *
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+from Common.DataType import BINARY_FILE_TYPE_FV
+
+## generate Region
+#
+#
+class Region(object):
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ self.Offset = None # The begin position of the Region
+ self.Size = None # The Size of the Region
+ self.PcdOffset = None
+ self.PcdSize = None
+ self.SetVarDict = {}
+ self.RegionType = None
+ self.RegionDataList = []
+
+ ## PadBuffer()
+ #
+ # Add padding bytes to the Buffer
+ #
+ # @param Buffer The buffer the generated region data will be put
+ # in
+ # @param ErasePolarity Flash erase polarity
+ # @param Size Number of padding bytes requested
+ #
+
+ def PadBuffer(self, Buffer, ErasePolarity, Size):
+ if Size > 0:
+ if (ErasePolarity == '1') :
+ PadByte = pack('B', 0xFF)
+ else:
+ PadByte = pack('B', 0)
+ for i in range(0, Size):
+ Buffer.write(PadByte)
+
+ ## AddToBuffer()
+ #
+ # Add region data to the Buffer
+ #
+ # @param self The object pointer
+ # @param Buffer The buffer generated region data will be put
+ # @param BaseAddress base address of region
+ # @param BlockSize block size of region
+ # @param BlockNum How many blocks in region
+ # @param ErasePolarity Flash erase polarity
+ # @param MacroDict macro value pair
+ # @retval string Generated FV file path
+ #
+
+ def AddToBuffer(self, Buffer, BaseAddress, BlockSizeList, ErasePolarity, ImageBinDict, MacroDict=None, Flag=False):
+ Size = self.Size
+ if MacroDict is None:
+ MacroDict = {}
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger('\nGenerate Region at Offset 0x%X' % self.Offset)
+ GenFdsGlobalVariable.InfLogger(" Region Size = 0x%X" % Size)
+ GenFdsGlobalVariable.SharpCounter = 0
+ if Flag and (self.RegionType != BINARY_FILE_TYPE_FV):
+ return
+
+ if self.RegionType == BINARY_FILE_TYPE_FV:
+ #
+ # Get Fv from FvDict
+ #
+ self.FvAddress = int(BaseAddress, 16) + self.Offset
+ FvBaseAddress = '0x%X' % self.FvAddress
+ FvOffset = 0
+ for RegionData in self.RegionDataList:
+ FileName = None
+ if RegionData.endswith(".fv"):
+ RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict)
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger(' Region FV File Name = .fv : %s' % RegionData)
+ if RegionData[1] != ':' :
+ RegionData = mws.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData)
+ if not os.path.exists(RegionData):
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=RegionData)
+
+ FileName = RegionData
+ elif RegionData.upper() + 'fv' in ImageBinDict:
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger(' Region Name = FV')
+ FileName = ImageBinDict[RegionData.upper() + 'fv']
+ else:
+ #
+ # Generate FvImage.
+ #
+ FvObj = None
+ if RegionData.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict:
+ FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[RegionData.upper()]
+
+ if FvObj is not None :
+ if not Flag:
+ GenFdsGlobalVariable.InfLogger(' Region Name = FV')
+ #
+ # Call GenFv tool
+ #
+ self.BlockInfoOfRegion(BlockSizeList, FvObj)
+ self.FvAddress = self.FvAddress + FvOffset
+ FvAlignValue = GenFdsGlobalVariable.GetAlignment(FvObj.FvAlignment)
+ if self.FvAddress % FvAlignValue != 0:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ "FV (%s) is NOT %s Aligned!" % (FvObj.UiFvName, FvObj.FvAlignment))
+ FvBuffer = BytesIO()
+ FvBaseAddress = '0x%X' % self.FvAddress
+ BlockSize = None
+ BlockNum = None
+ FvObj.AddToBuffer(FvBuffer, FvBaseAddress, BlockSize, BlockNum, ErasePolarity, Flag=Flag)
+ if Flag:
+ continue
+
+ FvBufferLen = len(FvBuffer.getvalue())
+ if FvBufferLen > Size:
+ FvBuffer.close()
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData, Size))
+ #
+ # Put the generated image into FD buffer.
+ #
+ Buffer.write(FvBuffer.getvalue())
+ FvBuffer.close()
+ FvOffset = FvOffset + FvBufferLen
+ Size = Size - FvBufferLen
+ continue
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "FV (%s) is NOT described in FDF file!" % (RegionData))
+ #
+ # Add the exist Fv image into FD buffer
+ #
+ if not Flag:
+ if FileName is not None:
+ FileLength = os.stat(FileName)[ST_SIZE]
+ if FileLength > Size:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ "Size of FV File (%s) is larger than Region Size 0x%X specified." \
+ % (RegionData, Size))
+ BinFile = open(FileName, 'rb')
+ Buffer.write(BinFile.read())
+ BinFile.close()
+ Size = Size - FileLength
+ #
+ # Pad the left buffer
+ #
+ if not Flag:
+ self.PadBuffer(Buffer, ErasePolarity, Size)
+
+ if self.RegionType == 'CAPSULE':
+ #
+ # Get Capsule from Capsule Dict
+ #
+ for RegionData in self.RegionDataList:
+ if RegionData.endswith(".cap"):
+ RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict)
+ GenFdsGlobalVariable.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData)
+ if RegionData[1] != ':' :
+ RegionData = mws.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData)
+ if not os.path.exists(RegionData):
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=RegionData)
+
+ FileName = RegionData
+ elif RegionData.upper() + 'cap' in ImageBinDict:
+ GenFdsGlobalVariable.InfLogger(' Region Name = CAPSULE')
+ FileName = ImageBinDict[RegionData.upper() + 'cap']
+ else:
+ #
+ # Generate Capsule image and Put it into FD buffer
+ #
+ CapsuleObj = None
+ if RegionData.upper() in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict:
+ CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict[RegionData.upper()]
+
+ if CapsuleObj is not None :
+ CapsuleObj.CapsuleName = RegionData.upper()
+ GenFdsGlobalVariable.InfLogger(' Region Name = CAPSULE')
+ #
+ # Call GenFv tool to generate Capsule Image
+ #
+ FileName = CapsuleObj.GenCapsule()
+ CapsuleObj.CapsuleName = None
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Capsule (%s) is NOT described in FDF file!" % (RegionData))
+
+ #
+ # Add the capsule image into FD buffer
+ #
+ FileLength = os.stat(FileName)[ST_SIZE]
+ if FileLength > Size:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
+ % (FileLength, RegionData, Size))
+ BinFile = open(FileName, 'rb')
+ Buffer.write(BinFile.read())
+ BinFile.close()
+ Size = Size - FileLength
+ #
+ # Pad the left buffer
+ #
+ self.PadBuffer(Buffer, ErasePolarity, Size)
+
+ if self.RegionType in ('FILE', 'INF'):
+ for RegionData in self.RegionDataList:
+ if self.RegionType == 'INF':
+ RegionData.__InfParse__(None)
+ if len(RegionData.BinFileList) != 1:
+ EdkLogger.error('GenFds', GENFDS_ERROR, 'INF in FD region can only contain one binary: %s' % RegionData)
+ File = RegionData.BinFileList[0]
+ RegionData = RegionData.PatchEfiFile(File.Path, File.Type)
+ else:
+ RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict)
+ if RegionData[1] != ':' :
+ RegionData = mws.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData)
+ if not os.path.exists(RegionData):
+ EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=RegionData)
+ #
+ # Add the file image into FD buffer
+ #
+ FileLength = os.stat(RegionData)[ST_SIZE]
+ if FileLength > Size:
+ EdkLogger.error("GenFds", GENFDS_ERROR,
+ "Size of File (%s) is larger than Region Size 0x%X specified." \
+ % (RegionData, Size))
+ GenFdsGlobalVariable.InfLogger(' Region File Name = %s' % RegionData)
+ BinFile = open(RegionData, 'rb')
+ Buffer.write(BinFile.read())
+ BinFile.close()
+ Size = Size - FileLength
+ #
+ # Pad the left buffer
+ #
+ self.PadBuffer(Buffer, ErasePolarity, Size)
+
+ if self.RegionType == 'DATA' :
+ GenFdsGlobalVariable.InfLogger(' Region Name = DATA')
+ DataSize = 0
+ for RegionData in self.RegionDataList:
+ Data = RegionData.split(',')
+ DataSize = DataSize + len(Data)
+ if DataSize > Size:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Size of DATA is larger than Region Size ")
+ else:
+ for item in Data :
+ Buffer.write(pack('B', int(item, 16)))
+ Size = Size - DataSize
+ #
+ # Pad the left buffer
+ #
+ self.PadBuffer(Buffer, ErasePolarity, Size)
+
+ if self.RegionType is None:
+ GenFdsGlobalVariable.InfLogger(' Region Name = None')
+ self.PadBuffer(Buffer, ErasePolarity, Size)
+
+ ## BlockSizeOfRegion()
+ #
+ # @param BlockSizeList List of block information
+ # @param FvObj The object for FV
+ #
+ def BlockInfoOfRegion(self, BlockSizeList, FvObj):
+ Start = 0
+ End = 0
+ RemindingSize = self.Size
+ ExpectedList = []
+ for (BlockSize, BlockNum, pcd) in BlockSizeList:
+ End = Start + BlockSize * BlockNum
+ # region not started yet
+ if self.Offset >= End:
+ Start = End
+ continue
+ # region located in current blocks
+ else:
+ # region ended within current blocks
+ if self.Offset + self.Size <= End:
+ ExpectedList.append((BlockSize, (RemindingSize + BlockSize - 1) // BlockSize))
+ break
+ # region not ended yet
+ else:
+ # region not started in middle of current blocks
+ if self.Offset <= Start:
+ UsedBlockNum = BlockNum
+ # region started in middle of current blocks
+ else:
+ UsedBlockNum = (End - self.Offset) // BlockSize
+ Start = End
+ ExpectedList.append((BlockSize, UsedBlockNum))
+ RemindingSize -= BlockSize * UsedBlockNum
+
+ if FvObj.BlockSizeList == []:
+ FvObj.BlockSizeList = ExpectedList
+ else:
+ # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
+ # if so, use ExpectedList
+ for Item in FvObj.BlockSizeList:
+ if Item[0] is None or Item[1] is None:
+ FvObj.BlockSizeList = ExpectedList
+ break
+ # make sure region size is no smaller than the summed block size in FV
+ Sum = 0
+ for Item in FvObj.BlockSizeList:
+ Sum += Item[0] * Item[1]
+ if self.Size < Sum:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
+ % (FvObj.UiFvName, Sum, self.Size))
+ # check whether the BlockStatements in FV section is appropriate
+ ExpectedListData = ''
+ for Item in ExpectedList:
+ ExpectedListData += "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
+ Index = 0
+ for Item in FvObj.BlockSizeList:
+ if Item[0] != ExpectedList[Index][0]:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
+ % FvObj.UiFvName, ExtraData=ExpectedListData)
+ elif Item[1] != ExpectedList[Index][1]:
+ if (Item[1] < ExpectedList[Index][1]) and (Index == len(FvObj.BlockSizeList) - 1):
+ break;
+ else:
+ EdkLogger.error("GenFds", GENFDS_ERROR, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
+ % FvObj.UiFvName, ExtraData=ExpectedListData)
+ else:
+ Index += 1
+
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Rule.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Rule.py
new file mode 100755
index 00000000..b14114fc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Rule.py
@@ -0,0 +1,23 @@
+## @file
+# Rule object for generating FFS
+#
+# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from CommonDataClass.FdfClass import RuleClassObject
+
+## Rule base class
+#
+#
+class Rule(RuleClassObject):
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ RuleClassObject.__init__(self)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleComplexFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleComplexFile.py
new file mode 100755
index 00000000..35af9bc1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleComplexFile.py
@@ -0,0 +1,25 @@
+## @file
+# Complex Rule object for generating FFS
+#
+# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Rule
+from CommonDataClass.FdfClass import RuleComplexFileClassObject
+
+## complex rule
+#
+#
+class RuleComplexFile(RuleComplexFileClassObject) :
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ RuleComplexFileClassObject.__init__(self)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleSimpleFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleSimpleFile.py
new file mode 100755
index 00000000..4f4d75f0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/RuleSimpleFile.py
@@ -0,0 +1,25 @@
+## @file
+# Simple Rule object for generating FFS
+#
+# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Rule
+from CommonDataClass.FdfClass import RuleSimpleFileClassObject
+
+## simple rule
+#
+#
+class RuleSimpleFile (RuleSimpleFileClassObject) :
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ RuleSimpleFileClassObject.__init__(self)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py
new file mode 100755
index 00000000..a338cffe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py
@@ -0,0 +1,153 @@
+## @file
+# section base class
+#
+# Copyright (c) 2007-2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from CommonDataClass.FdfClass import SectionClassObject
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+import Common.LongFilePathOs as os, glob
+from Common import EdkLogger
+from Common.BuildToolError import *
+from Common.DataType import *
+
+## section base class
+#
+#
+class Section (SectionClassObject):
+ SectionType = {
+ 'RAW' : 'EFI_SECTION_RAW',
+ 'FREEFORM' : 'EFI_SECTION_FREEFORM_SUBTYPE_GUID',
+ BINARY_FILE_TYPE_PE32 : 'EFI_SECTION_PE32',
+ BINARY_FILE_TYPE_PIC : 'EFI_SECTION_PIC',
+ BINARY_FILE_TYPE_TE : 'EFI_SECTION_TE',
+ 'FV_IMAGE' : 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',
+ BINARY_FILE_TYPE_DXE_DEPEX : 'EFI_SECTION_DXE_DEPEX',
+ BINARY_FILE_TYPE_PEI_DEPEX : 'EFI_SECTION_PEI_DEPEX',
+ 'GUIDED' : 'EFI_SECTION_GUID_DEFINED',
+ 'COMPRESS' : 'EFI_SECTION_COMPRESSION',
+ BINARY_FILE_TYPE_UI : 'EFI_SECTION_USER_INTERFACE',
+ BINARY_FILE_TYPE_SMM_DEPEX : 'EFI_SECTION_SMM_DEPEX'
+ }
+
+ BinFileType = {
+ BINARY_FILE_TYPE_GUID : '.guid',
+ 'ACPI' : '.acpi',
+ 'ASL' : '.asl' ,
+ BINARY_FILE_TYPE_UEFI_APP : '.app',
+ BINARY_FILE_TYPE_LIB : '.lib',
+ BINARY_FILE_TYPE_PE32 : '.pe32',
+ BINARY_FILE_TYPE_PIC : '.pic',
+ BINARY_FILE_TYPE_PEI_DEPEX : '.depex',
+ 'SEC_PEI_DEPEX' : '.depex',
+ BINARY_FILE_TYPE_TE : '.te',
+ BINARY_FILE_TYPE_UNI_VER : '.ver',
+ BINARY_FILE_TYPE_VER : '.ver',
+ BINARY_FILE_TYPE_UNI_UI : '.ui',
+ BINARY_FILE_TYPE_UI : '.ui',
+ BINARY_FILE_TYPE_BIN : '.bin',
+ 'RAW' : '.raw',
+ 'COMPAT16' : '.comp16',
+ BINARY_FILE_TYPE_FV : '.fv'
+ }
+
+ SectFileType = {
+ 'SEC_GUID' : '.sec' ,
+ 'SEC_PE32' : '.sec' ,
+ 'SEC_PIC' : '.sec',
+ 'SEC_TE' : '.sec',
+ 'SEC_VER' : '.sec',
+ 'SEC_UI' : '.sec',
+ 'SEC_COMPAT16' : '.sec',
+ 'SEC_BIN' : '.sec'
+ }
+
+ ToolGuid = {
+ '0xa31280ad-0x481e-0x41b6-0x95e8-0x127f-0x4c984779' : 'TianoCompress',
+ '0xee4e5898-0x3914-0x4259-0x9d6e-0xdc7b-0xd79403cf' : 'LzmaCompress'
+ }
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ SectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # virtual function
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ #
+ def GenSection(self, OutputPath, GuidName, SecNum, keyStringList, FfsInf = None, Dict = None):
+ pass
+
+ ## GetFileList() method
+ #
+ # Generate compressed section
+ #
+ # @param self The object pointer
+ # @param FfsInf FfsInfStatement object that contains file list
+ # @param FileType File type to get
+ # @param FileExtension File extension to get
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (File list, boolean)
+ #
+ def GetFileList(FfsInf, FileType, FileExtension, Dict = None, IsMakefile=False, SectionType=None):
+ IsSect = FileType in Section.SectFileType
+
+ if FileExtension is not None:
+ Suffix = FileExtension
+ elif IsSect :
+ Suffix = Section.SectionType.get(FileType)
+ else:
+ Suffix = Section.BinFileType.get(FileType)
+ if FfsInf is None:
+ EdkLogger.error("GenFds", GENFDS_ERROR, 'Inf File does not exist!')
+
+ FileList = []
+ if FileType is not None:
+ for File in FfsInf.BinFileList:
+ if File.Arch == TAB_ARCH_COMMON or FfsInf.CurrentArch == File.Arch:
+ if File.Type == FileType or (int(FfsInf.PiSpecVersion, 16) >= 0x0001000A \
+ and FileType == 'DXE_DPEX' and File.Type == BINARY_FILE_TYPE_SMM_DEPEX) \
+ or (FileType == BINARY_FILE_TYPE_TE and File.Type == BINARY_FILE_TYPE_PE32):
+ if TAB_STAR in FfsInf.TargetOverrideList or File.Target == TAB_STAR or File.Target in FfsInf.TargetOverrideList or FfsInf.TargetOverrideList == []:
+ FileList.append(FfsInf.PatchEfiFile(File.Path, File.Type))
+ else:
+ GenFdsGlobalVariable.InfLogger ("\nBuild Target \'%s\' of File %s is not in the Scope of %s specified by INF %s in FDF" %(File.Target, File.File, FfsInf.TargetOverrideList, FfsInf.InfFileName))
+ else:
+ GenFdsGlobalVariable.VerboseLogger ("\nFile Type \'%s\' of File %s in %s is not same with file type \'%s\' from Rule in FDF" %(File.Type, File.File, FfsInf.InfFileName, FileType))
+ else:
+ GenFdsGlobalVariable.InfLogger ("\nCurrent ARCH \'%s\' of File %s is not in the Support Arch Scope of %s specified by INF %s in FDF" %(FfsInf.CurrentArch, File.File, File.Arch, FfsInf.InfFileName))
+
+ elif FileType is None and SectionType == BINARY_FILE_TYPE_RAW:
+ for File in FfsInf.BinFileList:
+ if File.Ext == Suffix:
+ FileList.append(File.Path)
+
+ if (not IsMakefile and Suffix is not None and os.path.exists(FfsInf.EfiOutputPath)) or (IsMakefile and Suffix is not None):
+ if not FileList:
+ SuffixMap = FfsInf.GetFinalTargetSuffixMap()
+ if Suffix in SuffixMap:
+ FileList.extend(SuffixMap[Suffix])
+
+ #Process the file lists is alphabetical for a same section type
+ if len (FileList) > 1:
+ FileList.sort()
+
+ return FileList, IsSect
+ GetFileList = staticmethod(GetFileList)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/UiSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/UiSection.py
new file mode 100755
index 00000000..a8aa94c0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/UiSection.py
@@ -0,0 +1,74 @@
+## @file
+# process UI section generation
+#
+# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from . import Section
+from .Ffs import SectionSuffix
+import subprocess
+import Common.LongFilePathOs as os
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from CommonDataClass.FdfClass import UiSectionClassObject
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.DataType import *
+
+## generate UI section
+#
+#
+class UiSection (UiSectionClassObject):
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ UiSectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # Generate UI section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf=None, Dict=None, IsMakefile = False):
+ #
+ # Prepare the parameter of GenSection
+ #
+ if FfsInf is not None:
+ self.Alignment = FfsInf.__ExtendMacro__(self.Alignment)
+ self.StringData = FfsInf.__ExtendMacro__(self.StringData)
+ self.FileName = FfsInf.__ExtendMacro__(self.FileName)
+
+ OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + SecNum + SectionSuffix.get(BINARY_FILE_TYPE_UI))
+
+ if self.StringData is not None :
+ NameString = self.StringData
+ elif self.FileName is not None:
+ if Dict is None:
+ Dict = {}
+ FileNameStr = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName)
+ FileNameStr = GenFdsGlobalVariable.MacroExtend(FileNameStr, Dict)
+ FileObj = open(FileNameStr, 'r')
+ NameString = FileObj.read()
+ FileObj.close()
+ else:
+ NameString = ''
+ GenFdsGlobalVariable.GenerateSection(OutputFile, None, 'EFI_SECTION_USER_INTERFACE', Ui=NameString, IsMakefile=IsMakefile)
+
+ OutputFileList = []
+ OutputFileList.append(OutputFile)
+ return OutputFileList, self.Alignment
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/VerSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/VerSection.py
new file mode 100755
index 00000000..37ba96b9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/VerSection.py
@@ -0,0 +1,76 @@
+## @file
+# process Version section generation
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from .Ffs import SectionSuffix
+import Common.LongFilePathOs as os
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+from CommonDataClass.FdfClass import VerSectionClassObject
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.DataType import SUP_MODULE_SEC
+
+## generate version section
+#
+#
+class VerSection (VerSectionClassObject):
+
+ ## The constructor
+ #
+ # @param self The object pointer
+ #
+ def __init__(self):
+ VerSectionClassObject.__init__(self)
+
+ ## GenSection() method
+ #
+ # Generate version section
+ #
+ # @param self The object pointer
+ # @param OutputPath Where to place output file
+ # @param ModuleName Which module this section belongs to
+ # @param SecNum Index of section
+ # @param KeyStringList Filter for inputs of section generation
+ # @param FfsInf FfsInfStatement object that contains this section data
+ # @param Dict dictionary contains macro and its value
+ # @retval tuple (Generated file name, section alignment)
+ #
+ def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf=None, Dict=None, IsMakefile = False):
+ #
+ # Prepare the parameter of GenSection
+ #
+ if FfsInf:
+ self.Alignment = FfsInf.__ExtendMacro__(self.Alignment)
+ self.BuildNum = FfsInf.__ExtendMacro__(self.BuildNum)
+ self.StringData = FfsInf.__ExtendMacro__(self.StringData)
+ self.FileName = FfsInf.__ExtendMacro__(self.FileName)
+
+ OutputFile = os.path.join(OutputPath,
+ ModuleName + SUP_MODULE_SEC + SecNum + SectionSuffix.get('VERSION'))
+ OutputFile = os.path.normpath(OutputFile)
+
+ # Get String Data
+ StringData = ''
+ if self.StringData:
+ StringData = self.StringData
+ elif self.FileName:
+ if Dict is None:
+ Dict = {}
+ FileNameStr = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName)
+ FileNameStr = GenFdsGlobalVariable.MacroExtend(FileNameStr, Dict)
+ FileObj = open(FileNameStr, 'r')
+ StringData = FileObj.read()
+ StringData = '"' + StringData + '"'
+ FileObj.close()
+ GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',
+ Ver=StringData, BuildNumber=self.BuildNum, IsMakefile=IsMakefile)
+ OutputFileList = []
+ OutputFileList.append(OutputFile)
+ return OutputFileList, self.Alignment
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/__init__.py
new file mode 100644
index 00000000..017d2686
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/__init__.py
@@ -0,0 +1,9 @@
+## @file
+# Python 'GenFds' package initialization file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#