From f51461c829c124288a930829a78e2a5a799f4039 Mon Sep 17 00:00:00 2001 From: "Gao, Liming" Date: Mon, 27 Jan 2014 05:23:15 +0000 Subject: Sync BaseTool trunk (version r2649) into EDKII BaseTools. Signed-off-by: Gao, Liming git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15188 6f19259b-4bc3-4df7-8a09-765794883524 --- BaseTools/Source/Python/AutoGen/BuildEngine.py | 1254 +++++----- BaseTools/Source/Python/AutoGen/GenC.py | 3146 ++++++++++++------------ BaseTools/Source/Python/AutoGen/GenMake.py | 2822 ++++++++++----------- 3 files changed, 3611 insertions(+), 3611 deletions(-) (limited to 'BaseTools/Source/Python/AutoGen') diff --git a/BaseTools/Source/Python/AutoGen/BuildEngine.py b/BaseTools/Source/Python/AutoGen/BuildEngine.py index 5a7527ef4b..b3083d0395 100644 --- a/BaseTools/Source/Python/AutoGen/BuildEngine.py +++ b/BaseTools/Source/Python/AutoGen/BuildEngine.py @@ -1,627 +1,627 @@ -## @file -# The engine for building files -# -# Copyright (c) 2007, Intel Corporation. All rights reserved.
-# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# - -## -# Import Modules -# -import os -import re -import copy -import string - -from Common.GlobalData import * -from Common.BuildToolError import * -from Common.Misc import tdict, PathClass -from Common.String import NormPath -from Common.DataType import * - -import Common.EdkLogger as EdkLogger - -## Convert file type to file list macro name -# -# @param FileType The name of file type -# -# @retval string The name of macro -# -def FileListMacro(FileType): - return "%sS" % FileType.replace("-", "_").upper() - -## Convert file type to list file macro name -# -# @param FileType The name of file type -# -# @retval string The name of macro -# -def ListFileMacro(FileType): - return "%s_LIST" % FileListMacro(FileType) - -class TargetDescBlock(object): - _Cache_ = {} # {TargetFile : TargetDescBlock object} - - # Factory method - def __new__(Class, Inputs, Outputs, Commands, Dependencies): - if Outputs[0] in Class._Cache_: - Tdb = Class._Cache_[Outputs[0]] - for File in Inputs: - Tdb.AddInput(File) - else: - Tdb = super(TargetDescBlock, Class).__new__(Class) - Tdb._Init(Inputs, Outputs, Commands, Dependencies) - #Class._Cache_[Outputs[0]] = Tdb - return Tdb - - def _Init(self, Inputs, Outputs, Commands, Dependencies): - self.Inputs = Inputs - self.Outputs = Outputs - self.Commands = Commands - self.Dependencies = Dependencies - if self.Outputs: - self.Target = self.Outputs[0] - else: - self.Target = None - - def __str__(self): - return self.Target.Path - - def __hash__(self): - return hash(self.Target.Path) - - def __eq__(self, Other): - if type(Other) == type(self): - return Other.Target.Path == self.Target.Path - else: - return str(Other) == self.Target.Path - - def AddInput(self, Input): - if Input not in self.Inputs: - self.Inputs.append(Input) - - def IsMultipleInput(self): - return len(self.Inputs) > 1 - - @staticmethod - def Renew(): - TargetDescBlock._Cache_ = {} - -## Class for one build rule -# -# This represents a build rule which can give out corresponding command list for -# building the given source file(s). The result can be used for generating the -# target for makefile. -# -class FileBuildRule: - INC_LIST_MACRO = "INC_LIST" - INC_MACRO = "INC" - - ## constructor - # - # @param Input The dictionary represeting input file(s) for a rule - # @param Output The list represeting output file(s) for a rule - # @param Command The list containing commands to generate the output from input - # - def __init__(self, Type, Input, Output, Command, ExtraDependency=None): - # The Input should not be empty - if not Input: - Input = [] - if not Output: - Output = [] - if not Command: - Command = [] - - self.FileListMacro = FileListMacro(Type) - self.ListFileMacro = ListFileMacro(Type) - self.IncListFileMacro = self.INC_LIST_MACRO - - self.SourceFileType = Type - # source files listed not in "*" or "?" pattern format - if not ExtraDependency: - self.ExtraSourceFileList = [] - else: - self.ExtraSourceFileList = ExtraDependency - - # - # Search macros used in command lines for _LIST and INC_LIST. - # If found, generate a file to keep the input files used to get over the - # limitation of command line length - # - self.MacroList = [] - self.CommandList = [] - for CmdLine in Command: - self.MacroList.extend(gMacroRefPattern.findall(CmdLine)) - # replace path separator with native one - self.CommandList.append(CmdLine) - - # Indicate what should be generated - if self.FileListMacro in self.MacroList: - self.GenFileListMacro = True - else: - self.GenFileListMacro = False - - if self.ListFileMacro in self.MacroList: - self.GenListFile = True - self.GenFileListMacro = True - else: - self.GenListFile = False - - if self.INC_LIST_MACRO in self.MacroList: - self.GenIncListFile = True - else: - self.GenIncListFile = False - - # Check input files - self.IsMultipleInput = False - self.SourceFileExtList = [] - for File in Input: - Base, Ext = os.path.splitext(File) - if Base.find("*") >= 0: - # There's "*" in the file name - self.IsMultipleInput = True - self.GenFileListMacro = True - elif Base.find("?") < 0: - # There's no "*" and "?" in file name - self.ExtraSourceFileList.append(File) - continue - if Ext not in self.SourceFileExtList: - self.SourceFileExtList.append(Ext) - - # Check output files - self.DestFileList = [] - for File in Output: - self.DestFileList.append(File) - - # All build targets generated by this rule for a module - self.BuildTargets = {} - - ## str() function support - # - # @retval string - # - def __str__(self): - SourceString = "" - SourceString += " %s %s %s" % (self.SourceFileType, " ".join(self.SourceFileExtList), self.ExtraSourceFileList) - DestString = ", ".join(self.DestFileList) - CommandString = "\n\t".join(self.CommandList) - return "%s : %s\n\t%s" % (DestString, SourceString, CommandString) - - ## Check if given file extension is supported by this rule - # - # @param FileExt The extension of a file - # - # @retval True If the extension is supported - # @retval False If the extension is not supported - # - def IsSupported(self, FileExt): - return FileExt in self.SourceFileExtList - - def Instantiate(self, Macros={}): - NewRuleObject = copy.copy(self) - NewRuleObject.BuildTargets = {} - NewRuleObject.DestFileList = [] - for File in self.DestFileList: - NewRuleObject.DestFileList.append(PathClass(NormPath(File, Macros))) - return NewRuleObject - - ## Apply the rule to given source file(s) - # - # @param SourceFile One file or a list of files to be built - # @param RelativeToDir The relative path of the source file - # @param PathSeparator Path separator - # - # @retval tuple (Source file in full path, List of individual sourcefiles, Destionation file, List of build commands) - # - def Apply(self, SourceFile): - if not self.CommandList or not self.DestFileList: - return None - - # source file - if self.IsMultipleInput: - SrcFileName = "" - SrcFileBase = "" - SrcFileExt = "" - SrcFileDir = "" - SrcPath = "" - # SourceFile must be a list - SrcFile = "$(%s)" % self.FileListMacro - else: - SrcFileName, SrcFileBase, SrcFileExt = SourceFile.Name, SourceFile.BaseName, SourceFile.Ext - if SourceFile.Root: - SrcFileDir = SourceFile.SubDir - if SrcFileDir == "": - SrcFileDir = "." - else: - SrcFileDir = "." - SrcFile = SourceFile.Path - SrcPath = SourceFile.Dir - - # destination file (the first one) - if self.DestFileList: - DestFile = self.DestFileList[0].Path - DestPath = self.DestFileList[0].Dir - DestFileName = self.DestFileList[0].Name - DestFileBase, DestFileExt = self.DestFileList[0].BaseName, self.DestFileList[0].Ext - else: - DestFile = "" - DestPath = "" - DestFileName = "" - DestFileBase = "" - DestFileExt = "" - - BuildRulePlaceholderDict = { - # 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, - } - - DstFile = [] - for File in self.DestFileList: - File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict) - File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict) - DstFile.append(PathClass(File, IsBinary=True)) - - if DstFile[0] in self.BuildTargets: - TargetDesc = self.BuildTargets[DstFile[0]] - TargetDesc.AddInput(SourceFile) - else: - CommandList = [] - for CommandString in self.CommandList: - CommandString = string.Template(CommandString).safe_substitute(BuildRulePlaceholderDict) - CommandString = string.Template(CommandString).safe_substitute(BuildRulePlaceholderDict) - CommandList.append(CommandString) - TargetDesc = TargetDescBlock([SourceFile], DstFile, CommandList, self.ExtraSourceFileList) - TargetDesc.ListFileMacro = self.ListFileMacro - TargetDesc.FileListMacro = self.FileListMacro - TargetDesc.IncListFileMacro = self.IncListFileMacro - TargetDesc.GenFileListMacro = self.GenFileListMacro - TargetDesc.GenListFile = self.GenListFile - TargetDesc.GenIncListFile = self.GenIncListFile - self.BuildTargets[DstFile[0]] = TargetDesc - return TargetDesc - -## Class for build rules -# -# BuildRule class parses rules defined in a file or passed by caller, and converts -# the rule into FileBuildRule object. -# -class BuildRule: - _SectionHeader = "SECTIONHEADER" - _Section = "SECTION" - _SubSectionHeader = "SUBSECTIONHEADER" - _SubSection = "SUBSECTION" - _InputFile = "INPUTFILE" - _OutputFile = "OUTPUTFILE" - _ExtraDependency = "EXTRADEPENDENCY" - _Command = "COMMAND" - _UnknownSection = "UNKNOWNSECTION" - - _SubSectionList = [_InputFile, _OutputFile, _Command] - - _PATH_SEP = "(+)" - _FileTypePattern = re.compile("^[_a-zA-Z][_\-0-9a-zA-Z]*$") - _BinaryFileRule = FileBuildRule(TAB_DEFAULT_BINARY_FILE, [], [os.path.join("$(OUTPUT_DIR)", "${s_name}")], - ["$(CP) ${src} ${dst}"], []) - - ## Constructor - # - # @param File The file containing build rules in a well defined format - # @param Content The string list of build rules in a well defined format - # @param LineIndex The line number from which the parsing will begin - # @param SupportedFamily The list of supported tool chain families - # - def __init__(self, File=None, Content=None, LineIndex=0, SupportedFamily=["MSFT", "INTEL", "GCC", "RVCT"]): - self.RuleFile = File - # Read build rules from file if it's not none - if File != None: - try: - self.RuleContent = open(File, 'r').readlines() - except: - EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File) - elif Content != None: - self.RuleContent = Content - else: - EdkLogger.error("build", PARAMETER_MISSING, ExtraData="No rule file or string given") - - self.SupportedToolChainFamilyList = SupportedFamily - self.RuleDatabase = tdict(True, 4) # {FileExt, ModuleType, Arch, Family : FileBuildRule object} - self.Ext2FileType = {} # {ext : file-type} - self.FileTypeList = set() - - self._LineIndex = LineIndex - self._State = "" - self._RuleInfo = tdict(True, 2) # {toolchain family : {"InputFile": {}, "OutputFile" : [], "Command" : []}} - self._FileType = '' - self._BuildTypeList = [] - self._ArchList = [] - self._FamilyList = [] - self._TotalToolChainFamilySet = set() - self._RuleObjectList = [] # FileBuildRule object list - self._FileVersion = "" - - self.Parse() - - # some intrinsic rules - self.RuleDatabase[TAB_DEFAULT_BINARY_FILE, "COMMON", "COMMON", "COMMON"] = self._BinaryFileRule - self.FileTypeList.add(TAB_DEFAULT_BINARY_FILE) - - ## Parse the build rule strings - def Parse(self): - self._State = self._Section - for Index in range(self._LineIndex, len(self.RuleContent)): - # Clean up the line and replace path separator with native one - Line = self.RuleContent[Index].strip().replace(self._PATH_SEP, os.path.sep) - self.RuleContent[Index] = Line - - # find the build_rule_version - if Line and Line[0] == "#" and Line.find(TAB_BUILD_RULE_VERSION) <> -1: - if Line.find("=") <> -1 and Line.find("=") < (len(Line)-1) and (Line[(Line.find("=") + 1):]).split(): - self._FileVersion = (Line[(Line.find("=") + 1):]).split()[0] - # skip empty or comment line - if Line == "" or Line[0] == "#": - continue - - # find out section header, enclosed by [] - if Line[0] == '[' and Line[-1] == ']': - # merge last section information into rule database - self.EndOfSection() - self._State = self._SectionHeader - # find out sub-section header, enclosed by <> - elif Line[0] == '<' and Line[-1] == '>': - if self._State != self._UnknownSection: - self._State = self._SubSectionHeader - - # call section handler to parse each (sub)section - self._StateHandler[self._State](self, Index) - # merge last section information into rule database - self.EndOfSection() - - ## Parse definitions under a section - # - # @param LineIndex The line index of build rule text - # - def ParseSection(self, LineIndex): - pass - - ## Parse definitions under a subsection - # - # @param LineIndex The line index of build rule text - # - def ParseSubSection(self, LineIndex): - # currenly nothing here - pass - - ## Placeholder for not supported sections - # - # @param LineIndex The line index of build rule text - # - def SkipSection(self, LineIndex): - pass - - ## Merge section information just got into rule database - def EndOfSection(self): - Database = self.RuleDatabase - # if there's specific toochain family, 'COMMON' doesn't make sense any more - if len(self._TotalToolChainFamilySet) > 1 and 'COMMON' in self._TotalToolChainFamilySet: - self._TotalToolChainFamilySet.remove('COMMON') - for Family in self._TotalToolChainFamilySet: - Input = self._RuleInfo[Family, self._InputFile] - Output = self._RuleInfo[Family, self._OutputFile] - Command = self._RuleInfo[Family, self._Command] - ExtraDependency = self._RuleInfo[Family, self._ExtraDependency] - - BuildRule = FileBuildRule(self._FileType, Input, Output, Command, ExtraDependency) - for BuildType in self._BuildTypeList: - for Arch in self._ArchList: - Database[self._FileType, BuildType, Arch, Family] = BuildRule - for FileExt in BuildRule.SourceFileExtList: - self.Ext2FileType[FileExt] = self._FileType - - ## Parse section header - # - # @param LineIndex The line index of build rule text - # - def ParseSectionHeader(self, LineIndex): - self._RuleInfo = tdict(True, 2) - self._BuildTypeList = [] - self._ArchList = [] - self._FamilyList = [] - self._TotalToolChainFamilySet = set() - FileType = '' - RuleNameList = self.RuleContent[LineIndex][1:-1].split(',') - for RuleName in RuleNameList: - Arch = 'COMMON' - BuildType = 'COMMON' - TokenList = [Token.strip().upper() for Token in RuleName.split('.')] - # old format: Build.File-Type - if TokenList[0] == "BUILD": - if len(TokenList) == 1: - EdkLogger.error("build", FORMAT_INVALID, "Invalid rule section", - File=self.RuleFile, Line=LineIndex+1, - ExtraData=self.RuleContent[LineIndex]) - - FileType = TokenList[1] - if FileType == '': - EdkLogger.error("build", FORMAT_INVALID, "No file type given", - File=self.RuleFile, Line=LineIndex+1, - ExtraData=self.RuleContent[LineIndex]) - if self._FileTypePattern.match(FileType) == None: - EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex+1, - ExtraData="Only character, number (non-first character), '_' and '-' are allowed in file type") - # new format: File-Type.Build-Type.Arch - else: - if FileType == '': - FileType = TokenList[0] - elif FileType != TokenList[0]: - EdkLogger.error("build", FORMAT_INVALID, - "Different file types are not allowed in the same rule section", - File=self.RuleFile, Line=LineIndex+1, - ExtraData=self.RuleContent[LineIndex]) - if len(TokenList) > 1: - BuildType = TokenList[1] - if len(TokenList) > 2: - Arch = TokenList[2] - if BuildType not in self._BuildTypeList: - self._BuildTypeList.append(BuildType) - if Arch not in self._ArchList: - self._ArchList.append(Arch) - - if 'COMMON' in self._BuildTypeList and len(self._BuildTypeList) > 1: - EdkLogger.error("build", FORMAT_INVALID, - "Specific build types must not be mixed with common one", - File=self.RuleFile, Line=LineIndex+1, - ExtraData=self.RuleContent[LineIndex]) - if 'COMMON' in self._ArchList and len(self._ArchList) > 1: - EdkLogger.error("build", FORMAT_INVALID, - "Specific ARCH must not be mixed with common one", - File=self.RuleFile, Line=LineIndex+1, - ExtraData=self.RuleContent[LineIndex]) - - self._FileType = FileType - self._State = self._Section - self.FileTypeList.add(FileType) - - ## Parse sub-section header - # - # @param LineIndex The line index of build rule text - # - def ParseSubSectionHeader(self, LineIndex): - SectionType = "" - List = self.RuleContent[LineIndex][1:-1].split(',') - FamilyList = [] - for Section in List: - TokenList = Section.split('.') - Type = TokenList[0].strip().upper() - - if SectionType == "": - SectionType = Type - elif SectionType != Type: - EdkLogger.error("build", FORMAT_INVALID, - "Two different section types are not allowed in the same sub-section", - File=self.RuleFile, Line=LineIndex+1, - ExtraData=self.RuleContent[LineIndex]) - - if len(TokenList) > 1: - Family = TokenList[1].strip().upper() - else: - Family = "COMMON" - - if Family not in FamilyList: - FamilyList.append(Family) - - self._FamilyList = FamilyList - self._TotalToolChainFamilySet.update(FamilyList) - self._State = SectionType.upper() - if 'COMMON' in FamilyList and len(FamilyList) > 1: - EdkLogger.error("build", FORMAT_INVALID, - "Specific tool chain family should not be mixed with general one", - File=self.RuleFile, Line=LineIndex+1, - ExtraData=self.RuleContent[LineIndex]) - if self._State not in self._StateHandler: - EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex+1, - ExtraData="Unknown subsection: %s" % self.RuleContent[LineIndex]) - ## Parse sub-section - # - # @param LineIndex The line index of build rule text - # - def ParseInputFile(self, LineIndex): - FileList = [File.strip() for File in self.RuleContent[LineIndex].split(",")] - for ToolChainFamily in self._FamilyList: - InputFiles = self._RuleInfo[ToolChainFamily, self._State] - if InputFiles == None: - InputFiles = [] - self._RuleInfo[ToolChainFamily, self._State] = InputFiles - InputFiles.extend(FileList) - - ## Parse sub-section - # - # @param LineIndex The line index of build rule text - # - def ParseCommon(self, LineIndex): - for ToolChainFamily in self._FamilyList: - Items = self._RuleInfo[ToolChainFamily, self._State] - if Items == None: - Items = [] - self._RuleInfo[ToolChainFamily, self._State] = Items - Items.append(self.RuleContent[LineIndex]) - - ## Get a build rule via [] operator - # - # @param FileExt The extension of a file - # @param ToolChainFamily The tool chain family name - # @param BuildVersion The build version number. "*" means any rule - # is applicalbe. - # - # @retval FileType The file type string - # @retval FileBuildRule The object of FileBuildRule - # - # Key = (FileExt, ModuleType, Arch, ToolChainFamily) - def __getitem__(self, Key): - if not Key: - return None - - if Key[0] in self.Ext2FileType: - Type = self.Ext2FileType[Key[0]] - elif Key[0].upper() in self.FileTypeList: - Type = Key[0].upper() - else: - return None - - if len(Key) > 1: - Key = (Type,) + Key[1:] - else: - Key = (Type,) - return self.RuleDatabase[Key] - - _StateHandler = { - _SectionHeader : ParseSectionHeader, - _Section : ParseSection, - _SubSectionHeader : ParseSubSectionHeader, - _SubSection : ParseSubSection, - _InputFile : ParseInputFile, - _OutputFile : ParseCommon, - _ExtraDependency : ParseCommon, - _Command : ParseCommon, - _UnknownSection : SkipSection, - } - -# This acts like the main() function for the script, unless it is 'import'ed into another -# script. -if __name__ == '__main__': - import sys - EdkLogger.Initialize() - if len(sys.argv) > 1: - Br = BuildRule(sys.argv[1]) - print str(Br[".c", "DXE_DRIVER", "IA32", "MSFT"][1]) - print - print str(Br[".c", "DXE_DRIVER", "IA32", "INTEL"][1]) - print - print str(Br[".c", "DXE_DRIVER", "IA32", "GCC"][1]) - print - print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1]) - print - print str(Br[".h", "ACPI_TABLE", "IA32", "INTEL"][1]) - print - print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1]) - print - print str(Br[".s", "SEC", "IPF", "COMMON"][1]) - print - print str(Br[".s", "SEC"][1]) - +## @file +# The engine for building files +# +# Copyright (c) 2007, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +## +# Import Modules +# +import os +import re +import copy +import string + +from Common.GlobalData import * +from Common.BuildToolError import * +from Common.Misc import tdict, PathClass +from Common.String import NormPath +from Common.DataType import * + +import Common.EdkLogger as EdkLogger + +## Convert file type to file list macro name +# +# @param FileType The name of file type +# +# @retval string The name of macro +# +def FileListMacro(FileType): + return "%sS" % FileType.replace("-", "_").upper() + +## Convert file type to list file macro name +# +# @param FileType The name of file type +# +# @retval string The name of macro +# +def ListFileMacro(FileType): + return "%s_LIST" % FileListMacro(FileType) + +class TargetDescBlock(object): + _Cache_ = {} # {TargetFile : TargetDescBlock object} + + # Factory method + def __new__(Class, Inputs, Outputs, Commands, Dependencies): + if Outputs[0] in Class._Cache_: + Tdb = Class._Cache_[Outputs[0]] + for File in Inputs: + Tdb.AddInput(File) + else: + Tdb = super(TargetDescBlock, Class).__new__(Class) + Tdb._Init(Inputs, Outputs, Commands, Dependencies) + #Class._Cache_[Outputs[0]] = Tdb + return Tdb + + def _Init(self, Inputs, Outputs, Commands, Dependencies): + self.Inputs = Inputs + self.Outputs = Outputs + self.Commands = Commands + self.Dependencies = Dependencies + if self.Outputs: + self.Target = self.Outputs[0] + else: + self.Target = None + + def __str__(self): + return self.Target.Path + + def __hash__(self): + return hash(self.Target.Path) + + def __eq__(self, Other): + if type(Other) == type(self): + return Other.Target.Path == self.Target.Path + else: + return str(Other) == self.Target.Path + + def AddInput(self, Input): + if Input not in self.Inputs: + self.Inputs.append(Input) + + def IsMultipleInput(self): + return len(self.Inputs) > 1 + + @staticmethod + def Renew(): + TargetDescBlock._Cache_ = {} + +## Class for one build rule +# +# This represents a build rule which can give out corresponding command list for +# building the given source file(s). The result can be used for generating the +# target for makefile. +# +class FileBuildRule: + INC_LIST_MACRO = "INC_LIST" + INC_MACRO = "INC" + + ## constructor + # + # @param Input The dictionary represeting input file(s) for a rule + # @param Output The list represeting output file(s) for a rule + # @param Command The list containing commands to generate the output from input + # + def __init__(self, Type, Input, Output, Command, ExtraDependency=None): + # The Input should not be empty + if not Input: + Input = [] + if not Output: + Output = [] + if not Command: + Command = [] + + self.FileListMacro = FileListMacro(Type) + self.ListFileMacro = ListFileMacro(Type) + self.IncListFileMacro = self.INC_LIST_MACRO + + self.SourceFileType = Type + # source files listed not in "*" or "?" pattern format + if not ExtraDependency: + self.ExtraSourceFileList = [] + else: + self.ExtraSourceFileList = ExtraDependency + + # + # Search macros used in command lines for _LIST and INC_LIST. + # If found, generate a file to keep the input files used to get over the + # limitation of command line length + # + self.MacroList = [] + self.CommandList = [] + for CmdLine in Command: + self.MacroList.extend(gMacroRefPattern.findall(CmdLine)) + # replace path separator with native one + self.CommandList.append(CmdLine) + + # Indicate what should be generated + if self.FileListMacro in self.MacroList: + self.GenFileListMacro = True + else: + self.GenFileListMacro = False + + if self.ListFileMacro in self.MacroList: + self.GenListFile = True + self.GenFileListMacro = True + else: + self.GenListFile = False + + if self.INC_LIST_MACRO in self.MacroList: + self.GenIncListFile = True + else: + self.GenIncListFile = False + + # Check input files + self.IsMultipleInput = False + self.SourceFileExtList = [] + for File in Input: + Base, Ext = os.path.splitext(File) + if Base.find("*") >= 0: + # There's "*" in the file name + self.IsMultipleInput = True + self.GenFileListMacro = True + elif Base.find("?") < 0: + # There's no "*" and "?" in file name + self.ExtraSourceFileList.append(File) + continue + if Ext not in self.SourceFileExtList: + self.SourceFileExtList.append(Ext) + + # Check output files + self.DestFileList = [] + for File in Output: + self.DestFileList.append(File) + + # All build targets generated by this rule for a module + self.BuildTargets = {} + + ## str() function support + # + # @retval string + # + def __str__(self): + SourceString = "" + SourceString += " %s %s %s" % (self.SourceFileType, " ".join(self.SourceFileExtList), self.ExtraSourceFileList) + DestString = ", ".join(self.DestFileList) + CommandString = "\n\t".join(self.CommandList) + return "%s : %s\n\t%s" % (DestString, SourceString, CommandString) + + ## Check if given file extension is supported by this rule + # + # @param FileExt The extension of a file + # + # @retval True If the extension is supported + # @retval False If the extension is not supported + # + def IsSupported(self, FileExt): + return FileExt in self.SourceFileExtList + + def Instantiate(self, Macros={}): + NewRuleObject = copy.copy(self) + NewRuleObject.BuildTargets = {} + NewRuleObject.DestFileList = [] + for File in self.DestFileList: + NewRuleObject.DestFileList.append(PathClass(NormPath(File, Macros))) + return NewRuleObject + + ## Apply the rule to given source file(s) + # + # @param SourceFile One file or a list of files to be built + # @param RelativeToDir The relative path of the source file + # @param PathSeparator Path separator + # + # @retval tuple (Source file in full path, List of individual sourcefiles, Destionation file, List of build commands) + # + def Apply(self, SourceFile): + if not self.CommandList or not self.DestFileList: + return None + + # source file + if self.IsMultipleInput: + SrcFileName = "" + SrcFileBase = "" + SrcFileExt = "" + SrcFileDir = "" + SrcPath = "" + # SourceFile must be a list + SrcFile = "$(%s)" % self.FileListMacro + else: + SrcFileName, SrcFileBase, SrcFileExt = SourceFile.Name, SourceFile.BaseName, SourceFile.Ext + if SourceFile.Root: + SrcFileDir = SourceFile.SubDir + if SrcFileDir == "": + SrcFileDir = "." + else: + SrcFileDir = "." + SrcFile = SourceFile.Path + SrcPath = SourceFile.Dir + + # destination file (the first one) + if self.DestFileList: + DestFile = self.DestFileList[0].Path + DestPath = self.DestFileList[0].Dir + DestFileName = self.DestFileList[0].Name + DestFileBase, DestFileExt = self.DestFileList[0].BaseName, self.DestFileList[0].Ext + else: + DestFile = "" + DestPath = "" + DestFileName = "" + DestFileBase = "" + DestFileExt = "" + + BuildRulePlaceholderDict = { + # 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, + } + + DstFile = [] + for File in self.DestFileList: + File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict) + File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict) + DstFile.append(PathClass(File, IsBinary=True)) + + if DstFile[0] in self.BuildTargets: + TargetDesc = self.BuildTargets[DstFile[0]] + TargetDesc.AddInput(SourceFile) + else: + CommandList = [] + for CommandString in self.CommandList: + CommandString = string.Template(CommandString).safe_substitute(BuildRulePlaceholderDict) + CommandString = string.Template(CommandString).safe_substitute(BuildRulePlaceholderDict) + CommandList.append(CommandString) + TargetDesc = TargetDescBlock([SourceFile], DstFile, CommandList, self.ExtraSourceFileList) + TargetDesc.ListFileMacro = self.ListFileMacro + TargetDesc.FileListMacro = self.FileListMacro + TargetDesc.IncListFileMacro = self.IncListFileMacro + TargetDesc.GenFileListMacro = self.GenFileListMacro + TargetDesc.GenListFile = self.GenListFile + TargetDesc.GenIncListFile = self.GenIncListFile + self.BuildTargets[DstFile[0]] = TargetDesc + return TargetDesc + +## Class for build rules +# +# BuildRule class parses rules defined in a file or passed by caller, and converts +# the rule into FileBuildRule object. +# +class BuildRule: + _SectionHeader = "SECTIONHEADER" + _Section = "SECTION" + _SubSectionHeader = "SUBSECTIONHEADER" + _SubSection = "SUBSECTION" + _InputFile = "INPUTFILE" + _OutputFile = "OUTPUTFILE" + _ExtraDependency = "EXTRADEPENDENCY" + _Command = "COMMAND" + _UnknownSection = "UNKNOWNSECTION" + + _SubSectionList = [_InputFile, _OutputFile, _Command] + + _PATH_SEP = "(+)" + _FileTypePattern = re.compile("^[_a-zA-Z][_\-0-9a-zA-Z]*$") + _BinaryFileRule = FileBuildRule(TAB_DEFAULT_BINARY_FILE, [], [os.path.join("$(OUTPUT_DIR)", "${s_name}")], + ["$(CP) ${src} ${dst}"], []) + + ## Constructor + # + # @param File The file containing build rules in a well defined format + # @param Content The string list of build rules in a well defined format + # @param LineIndex The line number from which the parsing will begin + # @param SupportedFamily The list of supported tool chain families + # + def __init__(self, File=None, Content=None, LineIndex=0, SupportedFamily=["MSFT", "INTEL", "GCC", "RVCT"]): + self.RuleFile = File + # Read build rules from file if it's not none + if File != None: + try: + self.RuleContent = open(File, 'r').readlines() + except: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File) + elif Content != None: + self.RuleContent = Content + else: + EdkLogger.error("build", PARAMETER_MISSING, ExtraData="No rule file or string given") + + self.SupportedToolChainFamilyList = SupportedFamily + self.RuleDatabase = tdict(True, 4) # {FileExt, ModuleType, Arch, Family : FileBuildRule object} + self.Ext2FileType = {} # {ext : file-type} + self.FileTypeList = set() + + self._LineIndex = LineIndex + self._State = "" + self._RuleInfo = tdict(True, 2) # {toolchain family : {"InputFile": {}, "OutputFile" : [], "Command" : []}} + self._FileType = '' + self._BuildTypeList = [] + self._ArchList = [] + self._FamilyList = [] + self._TotalToolChainFamilySet = set() + self._RuleObjectList = [] # FileBuildRule object list + self._FileVersion = "" + + self.Parse() + + # some intrinsic rules + self.RuleDatabase[TAB_DEFAULT_BINARY_FILE, "COMMON", "COMMON", "COMMON"] = self._BinaryFileRule + self.FileTypeList.add(TAB_DEFAULT_BINARY_FILE) + + ## Parse the build rule strings + def Parse(self): + self._State = self._Section + for Index in range(self._LineIndex, len(self.RuleContent)): + # Clean up the line and replace path separator with native one + Line = self.RuleContent[Index].strip().replace(self._PATH_SEP, os.path.sep) + self.RuleContent[Index] = Line + + # find the build_rule_version + if Line and Line[0] == "#" and Line.find(TAB_BUILD_RULE_VERSION) <> -1: + if Line.find("=") <> -1 and Line.find("=") < (len(Line)-1) and (Line[(Line.find("=") + 1):]).split(): + self._FileVersion = (Line[(Line.find("=") + 1):]).split()[0] + # skip empty or comment line + if Line == "" or Line[0] == "#": + continue + + # find out section header, enclosed by [] + if Line[0] == '[' and Line[-1] == ']': + # merge last section information into rule database + self.EndOfSection() + self._State = self._SectionHeader + # find out sub-section header, enclosed by <> + elif Line[0] == '<' and Line[-1] == '>': + if self._State != self._UnknownSection: + self._State = self._SubSectionHeader + + # call section handler to parse each (sub)section + self._StateHandler[self._State](self, Index) + # merge last section information into rule database + self.EndOfSection() + + ## Parse definitions under a section + # + # @param LineIndex The line index of build rule text + # + def ParseSection(self, LineIndex): + pass + + ## Parse definitions under a subsection + # + # @param LineIndex The line index of build rule text + # + def ParseSubSection(self, LineIndex): + # currenly nothing here + pass + + ## Placeholder for not supported sections + # + # @param LineIndex The line index of build rule text + # + def SkipSection(self, LineIndex): + pass + + ## Merge section information just got into rule database + def EndOfSection(self): + Database = self.RuleDatabase + # if there's specific toochain family, 'COMMON' doesn't make sense any more + if len(self._TotalToolChainFamilySet) > 1 and 'COMMON' in self._TotalToolChainFamilySet: + self._TotalToolChainFamilySet.remove('COMMON') + for Family in self._TotalToolChainFamilySet: + Input = self._RuleInfo[Family, self._InputFile] + Output = self._RuleInfo[Family, self._OutputFile] + Command = self._RuleInfo[Family, self._Command] + ExtraDependency = self._RuleInfo[Family, self._ExtraDependency] + + BuildRule = FileBuildRule(self._FileType, Input, Output, Command, ExtraDependency) + for BuildType in self._BuildTypeList: + for Arch in self._ArchList: + Database[self._FileType, BuildType, Arch, Family] = BuildRule + for FileExt in BuildRule.SourceFileExtList: + self.Ext2FileType[FileExt] = self._FileType + + ## Parse section header + # + # @param LineIndex The line index of build rule text + # + def ParseSectionHeader(self, LineIndex): + self._RuleInfo = tdict(True, 2) + self._BuildTypeList = [] + self._ArchList = [] + self._FamilyList = [] + self._TotalToolChainFamilySet = set() + FileType = '' + RuleNameList = self.RuleContent[LineIndex][1:-1].split(',') + for RuleName in RuleNameList: + Arch = 'COMMON' + BuildType = 'COMMON' + TokenList = [Token.strip().upper() for Token in RuleName.split('.')] + # old format: Build.File-Type + if TokenList[0] == "BUILD": + if len(TokenList) == 1: + EdkLogger.error("build", FORMAT_INVALID, "Invalid rule section", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + + FileType = TokenList[1] + if FileType == '': + EdkLogger.error("build", FORMAT_INVALID, "No file type given", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if self._FileTypePattern.match(FileType) == None: + EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex+1, + ExtraData="Only character, number (non-first character), '_' and '-' are allowed in file type") + # new format: File-Type.Build-Type.Arch + else: + if FileType == '': + FileType = TokenList[0] + elif FileType != TokenList[0]: + EdkLogger.error("build", FORMAT_INVALID, + "Different file types are not allowed in the same rule section", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if len(TokenList) > 1: + BuildType = TokenList[1] + if len(TokenList) > 2: + Arch = TokenList[2] + if BuildType not in self._BuildTypeList: + self._BuildTypeList.append(BuildType) + if Arch not in self._ArchList: + self._ArchList.append(Arch) + + if 'COMMON' in self._BuildTypeList and len(self._BuildTypeList) > 1: + EdkLogger.error("build", FORMAT_INVALID, + "Specific build types must not be mixed with common one", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if 'COMMON' in self._ArchList and len(self._ArchList) > 1: + EdkLogger.error("build", FORMAT_INVALID, + "Specific ARCH must not be mixed with common one", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + + self._FileType = FileType + self._State = self._Section + self.FileTypeList.add(FileType) + + ## Parse sub-section header + # + # @param LineIndex The line index of build rule text + # + def ParseSubSectionHeader(self, LineIndex): + SectionType = "" + List = self.RuleContent[LineIndex][1:-1].split(',') + FamilyList = [] + for Section in List: + TokenList = Section.split('.') + Type = TokenList[0].strip().upper() + + if SectionType == "": + SectionType = Type + elif SectionType != Type: + EdkLogger.error("build", FORMAT_INVALID, + "Two different section types are not allowed in the same sub-section", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + + if len(TokenList) > 1: + Family = TokenList[1].strip().upper() + else: + Family = "COMMON" + + if Family not in FamilyList: + FamilyList.append(Family) + + self._FamilyList = FamilyList + self._TotalToolChainFamilySet.update(FamilyList) + self._State = SectionType.upper() + if 'COMMON' in FamilyList and len(FamilyList) > 1: + EdkLogger.error("build", FORMAT_INVALID, + "Specific tool chain family should not be mixed with general one", + File=self.RuleFile, Line=LineIndex+1, + ExtraData=self.RuleContent[LineIndex]) + if self._State not in self._StateHandler: + EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex+1, + ExtraData="Unknown subsection: %s" % self.RuleContent[LineIndex]) + ## Parse sub-section + # + # @param LineIndex The line index of build rule text + # + def ParseInputFile(self, LineIndex): + FileList = [File.strip() for File in self.RuleContent[LineIndex].split(",")] + for ToolChainFamily in self._FamilyList: + InputFiles = self._RuleInfo[ToolChainFamily, self._State] + if InputFiles == None: + InputFiles = [] + self._RuleInfo[ToolChainFamily, self._State] = InputFiles + InputFiles.extend(FileList) + + ## Parse sub-section + # + # @param LineIndex The line index of build rule text + # + def ParseCommon(self, LineIndex): + for ToolChainFamily in self._FamilyList: + Items = self._RuleInfo[ToolChainFamily, self._State] + if Items == None: + Items = [] + self._RuleInfo[ToolChainFamily, self._State] = Items + Items.append(self.RuleContent[LineIndex]) + + ## Get a build rule via [] operator + # + # @param FileExt The extension of a file + # @param ToolChainFamily The tool chain family name + # @param BuildVersion The build version number. "*" means any rule + # is applicalbe. + # + # @retval FileType The file type string + # @retval FileBuildRule The object of FileBuildRule + # + # Key = (FileExt, ModuleType, Arch, ToolChainFamily) + def __getitem__(self, Key): + if not Key: + return None + + if Key[0] in self.Ext2FileType: + Type = self.Ext2FileType[Key[0]] + elif Key[0].upper() in self.FileTypeList: + Type = Key[0].upper() + else: + return None + + if len(Key) > 1: + Key = (Type,) + Key[1:] + else: + Key = (Type,) + return self.RuleDatabase[Key] + + _StateHandler = { + _SectionHeader : ParseSectionHeader, + _Section : ParseSection, + _SubSectionHeader : ParseSubSectionHeader, + _SubSection : ParseSubSection, + _InputFile : ParseInputFile, + _OutputFile : ParseCommon, + _ExtraDependency : ParseCommon, + _Command : ParseCommon, + _UnknownSection : SkipSection, + } + +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +if __name__ == '__main__': + import sys + EdkLogger.Initialize() + if len(sys.argv) > 1: + Br = BuildRule(sys.argv[1]) + print str(Br[".c", "DXE_DRIVER", "IA32", "MSFT"][1]) + print + print str(Br[".c", "DXE_DRIVER", "IA32", "INTEL"][1]) + print + print str(Br[".c", "DXE_DRIVER", "IA32", "GCC"][1]) + print + print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1]) + print + print str(Br[".h", "ACPI_TABLE", "IA32", "INTEL"][1]) + print + print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1]) + print + print str(Br[".s", "SEC", "IPF", "COMMON"][1]) + print + print str(Br[".s", "SEC"][1]) + diff --git a/BaseTools/Source/Python/AutoGen/GenC.py b/BaseTools/Source/Python/AutoGen/GenC.py index 621b57282d..2646b29697 100644 --- a/BaseTools/Source/Python/AutoGen/GenC.py +++ b/BaseTools/Source/Python/AutoGen/GenC.py @@ -1,1573 +1,1573 @@ -## @file -# Routines for generating AutoGen.h and AutoGen.c -# -# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.
-# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# - -## Import Modules -# -import string - -from Common import EdkLogger - -from Common.BuildToolError import * -from Common.DataType import * -from Common.Misc import * -from Common.String import StringToArray -from StrGather import * -from GenPcdDb import CreatePcdDatabaseCode - -## PCD type string -gItemTypeStringDatabase = { - TAB_PCDS_FEATURE_FLAG : 'FixedAtBuild', - TAB_PCDS_FIXED_AT_BUILD : 'FixedAtBuild', - TAB_PCDS_PATCHABLE_IN_MODULE: 'BinaryPatch', - TAB_PCDS_DYNAMIC : '', - TAB_PCDS_DYNAMIC_DEFAULT : '', - TAB_PCDS_DYNAMIC_VPD : '', - TAB_PCDS_DYNAMIC_HII : '', - TAB_PCDS_DYNAMIC_EX : '', - TAB_PCDS_DYNAMIC_EX_DEFAULT : '', - TAB_PCDS_DYNAMIC_EX_VPD : '', - TAB_PCDS_DYNAMIC_EX_HII : '', -} - -## Dynamic PCD types -gDynamicPcd = [TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_DEFAULT, TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_HII] - -## Dynamic-ex PCD types -gDynamicExPcd = [TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, TAB_PCDS_DYNAMIC_EX_VPD, TAB_PCDS_DYNAMIC_EX_HII] - -## Datum size -gDatumSizeStringDatabase = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'BOOLEAN','VOID*':'8'} -gDatumSizeStringDatabaseH = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'BOOL','VOID*':'PTR'} -gDatumSizeStringDatabaseLib = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'Bool','VOID*':'Ptr'} - -## AutoGen File Header Templates -gAutoGenHeaderString = TemplateString("""\ -/** - DO NOT EDIT - FILE auto-generated - Module name: - ${FileName} - Abstract: Auto-generated ${FileName} for building module or library. -**/ -""") - -gAutoGenHPrologueString = TemplateString(""" -#ifndef _${File}_${Guid} -#define _${File}_${Guid} - -""") - -gAutoGenHCppPrologueString = """\ -#ifdef __cplusplus -extern "C" { -#endif - -""" - -gAutoGenHEpilogueString = """ - -#ifdef __cplusplus -} -#endif - -#endif -""" - -## PEI Core Entry Point Templates -gPeiCoreEntryPointPrototype = TemplateString(""" -${BEGIN} -VOID -EFIAPI -${Function} ( - IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, - IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, - IN VOID *Context - ); -${END} -""") - -gPeiCoreEntryPointString = TemplateString(""" -${BEGIN} -VOID -EFIAPI -ProcessModuleEntryPointList ( - IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, - IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, - IN VOID *Context - ) - -{ - ${Function} (SecCoreData, PpiList, Context); -} -${END} -""") - - -## DXE Core Entry Point Templates -gDxeCoreEntryPointPrototype = TemplateString(""" -${BEGIN} -VOID -EFIAPI -${Function} ( - IN VOID *HobStart - ); -${END} -""") - -gDxeCoreEntryPointString = TemplateString(""" -${BEGIN} -VOID -EFIAPI -ProcessModuleEntryPointList ( - IN VOID *HobStart - ) - -{ - ${Function} (HobStart); -} -${END} -""") - -## PEIM Entry Point Templates -gPeimEntryPointPrototype = TemplateString(""" -${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - ); -${END} -""") - -gPeimEntryPointString = [ -TemplateString(""" -GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - ) - -{ - return EFI_SUCCESS; -} -"""), -TemplateString(""" -GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; -${BEGIN} -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - ) - -{ - return ${Function} (FileHandle, PeiServices); -} -${END} -"""), -TemplateString(""" -GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - ) - -{ - EFI_STATUS Status; - EFI_STATUS CombinedStatus; - - CombinedStatus = EFI_LOAD_ERROR; -${BEGIN} - Status = ${Function} (FileHandle, PeiServices); - if (!EFI_ERROR (Status) || EFI_ERROR (CombinedStatus)) { - CombinedStatus = Status; - } -${END} - return CombinedStatus; -} -""") -] - -## SMM_CORE Entry Point Templates -gSmmCoreEntryPointPrototype = TemplateString(""" -${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); -${END} -""") - -gSmmCoreEntryPointString = TemplateString(""" -${BEGIN} -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; -const UINT32 _gDxeRevision = ${PiSpecVersion}; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return ${Function} (ImageHandle, SystemTable); -} -${END} -""") - -## DXE SMM Entry Point Templates -gDxeSmmEntryPointPrototype = TemplateString(""" -${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); -${END} -""") - -gDxeSmmEntryPointString = [ -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; -const UINT32 _gDxeRevision = ${PiSpecVersion}; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) - -{ - return EFI_SUCCESS; -} -"""), -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; -const UINT32 _gDxeRevision = ${PiSpecVersion}; - -static BASE_LIBRARY_JUMP_BUFFER mJumpContext; -static EFI_STATUS mDriverEntryPointStatus; - -VOID -EFIAPI -ExitDriver ( - IN EFI_STATUS Status - ) -{ - if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { - mDriverEntryPointStatus = Status; - } - LongJump (&mJumpContext, (UINTN)-1); - ASSERT (FALSE); -} - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - mDriverEntryPointStatus = EFI_LOAD_ERROR; - -${BEGIN} - if (SetJump (&mJumpContext) == 0) { - ExitDriver (${Function} (ImageHandle, SystemTable)); - ASSERT (FALSE); - } -${END} - - return mDriverEntryPointStatus; -} -""") -] - -## UEFI Driver Entry Point Templates -gUefiDriverEntryPointPrototype = TemplateString(""" -${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); -${END} -""") - -gUefiDriverEntryPointString = [ -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; -const UINT32 _gDxeRevision = ${PiSpecVersion}; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} -"""), -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; -const UINT32 _gDxeRevision = ${PiSpecVersion}; - -${BEGIN} -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) - -{ - return ${Function} (ImageHandle, SystemTable); -} -${END} -VOID -EFIAPI -ExitDriver ( - IN EFI_STATUS Status - ) -{ - if (EFI_ERROR (Status)) { - ProcessLibraryDestructorList (gImageHandle, gST); - } - gBS->Exit (gImageHandle, Status, 0, NULL); -} -"""), -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; -const UINT32 _gDxeRevision = ${PiSpecVersion}; - -static BASE_LIBRARY_JUMP_BUFFER mJumpContext; -static EFI_STATUS mDriverEntryPointStatus; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - mDriverEntryPointStatus = EFI_LOAD_ERROR; - ${BEGIN} - if (SetJump (&mJumpContext) == 0) { - ExitDriver (${Function} (ImageHandle, SystemTable)); - ASSERT (FALSE); - } - ${END} - return mDriverEntryPointStatus; -} - -VOID -EFIAPI -ExitDriver ( - IN EFI_STATUS Status - ) -{ - if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { - mDriverEntryPointStatus = Status; - } - LongJump (&mJumpContext, (UINTN)-1); - ASSERT (FALSE); -} -""") -] - - -## UEFI Application Entry Point Templates -gUefiApplicationEntryPointPrototype = TemplateString(""" -${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); -${END} -""") - -gUefiApplicationEntryPointString = [ -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - return EFI_SUCCESS; -} -"""), -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; - -${BEGIN} -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) - -{ - return ${Function} (ImageHandle, SystemTable); -} -${END} -VOID -EFIAPI -ExitDriver ( - IN EFI_STATUS Status - ) -{ - if (EFI_ERROR (Status)) { - ProcessLibraryDestructorList (gImageHandle, gST); - } - gBS->Exit (gImageHandle, Status, 0, NULL); -} -"""), -TemplateString(""" -const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; - -EFI_STATUS -EFIAPI -ProcessModuleEntryPointList ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) - -{ - ${BEGIN} - if (SetJump (&mJumpContext) == 0) { - ExitDriver (${Function} (ImageHandle, SystemTable)); - ASSERT (FALSE); - } - ${END} - return mDriverEntryPointStatus; -} - -static BASE_LIBRARY_JUMP_BUFFER mJumpContext; -static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR; - -VOID -EFIAPI -ExitDriver ( - IN EFI_STATUS Status - ) -{ - if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { - mDriverEntryPointStatus = Status; - } - LongJump (&mJumpContext, (UINTN)-1); - ASSERT (FALSE); -} -""") -] - -## UEFI Unload Image Templates -gUefiUnloadImagePrototype = TemplateString(""" -${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_HANDLE ImageHandle - ); -${END} -""") - -gUefiUnloadImageString = [ -TemplateString(""" -GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; - -EFI_STATUS -EFIAPI -ProcessModuleUnloadList ( - IN EFI_HANDLE ImageHandle - ) -{ - return EFI_SUCCESS; -} -"""), -TemplateString(""" -GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; - -${BEGIN} -EFI_STATUS -EFIAPI -ProcessModuleUnloadList ( - IN EFI_HANDLE ImageHandle - ) -{ - return ${Function} (ImageHandle); -} -${END} -"""), -TemplateString(""" -GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; - -EFI_STATUS -EFIAPI -ProcessModuleUnloadList ( - IN EFI_HANDLE ImageHandle - ) -{ - EFI_STATUS Status; - - Status = EFI_SUCCESS; -${BEGIN} - if (EFI_ERROR (Status)) { - ${Function} (ImageHandle); - } else { - Status = ${Function} (ImageHandle); - } -${END} - return Status; -} -""") -] - -gLibraryStructorPrototype = { -'BASE' : TemplateString("""${BEGIN} -RETURN_STATUS -EFIAPI -${Function} ( - VOID - );${END} -"""), - -'PEI' : TemplateString("""${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - );${END} -"""), - -'DXE' : TemplateString("""${BEGIN} -EFI_STATUS -EFIAPI -${Function} ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - );${END} -"""), -} - -gLibraryStructorCall = { -'BASE' : TemplateString("""${BEGIN} - Status = ${Function} (); - ASSERT_EFI_ERROR (Status);${END} -"""), - -'PEI' : TemplateString("""${BEGIN} - Status = ${Function} (FileHandle, PeiServices); - ASSERT_EFI_ERROR (Status);${END} -"""), - -'DXE' : TemplateString("""${BEGIN} - Status = ${Function} (ImageHandle, SystemTable); - ASSERT_EFI_ERROR (Status);${END} -"""), -} - -## Library Constructor and Destructor Templates -gLibraryString = { -'BASE' : TemplateString(""" -${BEGIN}${FunctionPrototype}${END} - -VOID -EFIAPI -ProcessLibrary${Type}List ( - VOID - ) -{ -${BEGIN} EFI_STATUS Status; -${FunctionCall}${END} -} -"""), - -'PEI' : TemplateString(""" -${BEGIN}${FunctionPrototype}${END} - -VOID -EFIAPI -ProcessLibrary${Type}List ( - IN EFI_PEI_FILE_HANDLE FileHandle, - IN CONST EFI_PEI_SERVICES **PeiServices - ) -{ -${BEGIN} EFI_STATUS Status; -${FunctionCall}${END} -} -"""), - -'DXE' : TemplateString(""" -${BEGIN}${FunctionPrototype}${END} - -VOID -EFIAPI -ProcessLibrary${Type}List ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ -${BEGIN} EFI_STATUS Status; -${FunctionCall}${END} -} -"""), -} - -gBasicHeaderFile = "Base.h" - -gModuleTypeHeaderFile = { - "BASE" : [gBasicHeaderFile], - "SEC" : ["PiPei.h", "Library/DebugLib.h"], - "PEI_CORE" : ["PiPei.h", "Library/DebugLib.h", "Library/PeiCoreEntryPoint.h"], - "PEIM" : ["PiPei.h", "Library/DebugLib.h", "Library/PeimEntryPoint.h"], - "DXE_CORE" : ["PiDxe.h", "Library/DebugLib.h", "Library/DxeCoreEntryPoint.h"], - "DXE_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], - "DXE_SMM_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], - "DXE_RUNTIME_DRIVER": ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], - "DXE_SAL_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], - "UEFI_DRIVER" : ["Uefi.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], - "UEFI_APPLICATION" : ["Uefi.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiApplicationEntryPoint.h"], - "SMM_CORE" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiDriverEntryPoint.h"], - "USER_DEFINED" : [gBasicHeaderFile] -} - -## Autogen internal worker macro to define DynamicEx PCD name includes both the TokenSpaceGuidName -# the TokenName and Guid comparison to avoid define name collisions. -# -# @param Info The ModuleAutoGen object -# @param AutoGenH The TemplateString object for header file -# -# -def DynExPcdTokenNumberMapping(Info, AutoGenH): - ExTokenCNameList = [] - PcdExList = [] - if Info.IsLibrary: - PcdList = Info.LibraryPcdList - else: - PcdList = Info.ModulePcdList - for Pcd in PcdList: - if Pcd.Type in gDynamicExPcd: - ExTokenCNameList.append(Pcd.TokenCName) - PcdExList.append(Pcd) - if len(ExTokenCNameList) == 0: - return - AutoGenH.Append('\n#define COMPAREGUID(Guid1, Guid2) (BOOLEAN)(*(CONST UINT64*)Guid1 == *(CONST UINT64*)Guid2 && *((CONST UINT64*)Guid1 + 1) == *((CONST UINT64*)Guid2 + 1))\n') - # AutoGen for each PCD listed in a [PcdEx] section of a Module/Lib INF file. - # Auto generate a macro for each TokenName that takes a Guid pointer as a parameter. - # Use the Guid pointer to see if it matches any of the token space GUIDs. - TokenCNameList = [] - for TokenCName in ExTokenCNameList: - if TokenCName in TokenCNameList: - continue - Index = 0 - Count = ExTokenCNameList.count(TokenCName) - for Pcd in PcdExList: - if Pcd.TokenCName == TokenCName: - Index = Index + 1 - if Index == 1: - AutoGenH.Append('\n#define __PCD_%s_ADDR_CMP(GuidPtr) (' % (Pcd.TokenCName)) - AutoGenH.Append('\\\n (GuidPtr == &%s) ? _PCD_TOKEN_%s_%s:' - % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) - else: - AutoGenH.Append('\\\n (GuidPtr == &%s) ? _PCD_TOKEN_%s_%s:' - % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) - if Index == Count: - AutoGenH.Append('0 \\\n )\n') - TokenCNameList.append(TokenCName) - - TokenCNameList = [] - for TokenCName in ExTokenCNameList: - if TokenCName in TokenCNameList: - continue - Index = 0 - Count = ExTokenCNameList.count(TokenCName) - for Pcd in PcdExList: - if Pcd.Type in gDynamicExPcd and Pcd.TokenCName == TokenCName: - Index = Index + 1 - if Index == 1: - AutoGenH.Append('\n#define __PCD_%s_VAL_CMP(GuidPtr) (' % (Pcd.TokenCName)) - AutoGenH.Append('\\\n COMPAREGUID (GuidPtr, &%s) ? _PCD_TOKEN_%s_%s:' - % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) - else: - AutoGenH.Append('\\\n COMPAREGUID (GuidPtr, &%s) ? _PCD_TOKEN_%s_%s:' - % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) - if Index == Count: - AutoGenH.Append('0 \\\n )\n') - # Autogen internal worker macro to compare GUIDs. Guid1 is a pointer to a GUID. - # Guid2 is a C name for a GUID. Compare pointers first because optimizing compiler - # can do this at build time on CONST GUID pointers and optimize away call to COMPAREGUID(). - # COMPAREGUID() will only be used if the Guid passed in is local to the module. - AutoGenH.Append('#define _PCD_TOKEN_EX_%s(GuidPtr) __PCD_%s_ADDR_CMP(GuidPtr) ? __PCD_%s_ADDR_CMP(GuidPtr) : __PCD_%s_VAL_CMP(GuidPtr) \n' - % (Pcd.TokenCName, Pcd.TokenCName, Pcd.TokenCName, Pcd.TokenCName)) - TokenCNameList.append(TokenCName) - -## Create code for module PCDs -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# @param Pcd The PCD object -# -def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd): - TokenSpaceGuidValue = Pcd.TokenSpaceGuidValue #Info.GuidList[Pcd.TokenSpaceGuidCName] - PcdTokenNumber = Info.PlatformInfo.PcdTokenNumber - # - # Write PCDs - # - PcdTokenName = '_PCD_TOKEN_' + Pcd.TokenCName - if Pcd.Type in gDynamicExPcd: - TokenNumber = int(Pcd.TokenValue, 0) - # Add TokenSpaceGuidValue value to PcdTokenName to discriminate the DynamicEx PCDs with - # different Guids but same TokenCName - PcdExTokenName = '_PCD_TOKEN_' + Pcd.TokenSpaceGuidCName + '_' + Pcd.TokenCName - AutoGenH.Append('\n#define %s %dU\n' % (PcdExTokenName, TokenNumber)) - else: - if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in PcdTokenNumber: - # If one of the Source built modules listed in the DSC is not listed in FDF modules, - # and the INF lists a PCD can only use the PcdsDynamic access method (it is only - # listed in the DEC file that declares the PCD as PcdsDynamic), then build tool will - # report warning message notify the PI that they are attempting to build a module - # that must be included in a flash image in order to be functional. These Dynamic PCD - # will not be added into the Database unless it is used by other modules that are - # included in the FDF file. - # In this case, just assign an invalid token number to make it pass build. - if Pcd.Type in PCD_DYNAMIC_TYPE_LIST: - TokenNumber = 0 - else: - EdkLogger.error("build", AUTOGEN_ERROR, - "No generated token number for %s.%s\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - else: - TokenNumber = PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] - AutoGenH.Append('\n#define %s %dU\n' % (PcdTokenName, TokenNumber)) - - EdkLogger.debug(EdkLogger.DEBUG_3, "Creating code for " + Pcd.TokenCName + "." + Pcd.TokenSpaceGuidCName) - if Pcd.Type not in gItemTypeStringDatabase: - EdkLogger.error("build", AUTOGEN_ERROR, - "Unknown PCD type [%s] of PCD %s.%s" % (Pcd.Type, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - if Pcd.DatumType not in gDatumSizeStringDatabase: - EdkLogger.error("build", AUTOGEN_ERROR, - "Unknown datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - - DatumSize = gDatumSizeStringDatabase[Pcd.DatumType] - DatumSizeLib = gDatumSizeStringDatabaseLib[Pcd.DatumType] - GetModeName = '_PCD_GET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName - SetModeName = '_PCD_SET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName - - PcdExCNameList = [] - if Pcd.Type in gDynamicExPcd: - if Info.IsLibrary: - PcdList = Info.LibraryPcdList - else: - PcdList = Info.ModulePcdList - for PcdModule in PcdList: - if PcdModule.Type in gDynamicExPcd: - PcdExCNameList.append(PcdModule.TokenCName) - # Be compatible with the current code which using PcdToken and PcdGet/Set for DynamicEx Pcd. - # If only PcdToken and PcdGet/Set used in all Pcds with different CName, it should succeed to build. - # If PcdToken and PcdGet/Set used in the Pcds with different Guids but same CName, it should failed to build. - if PcdExCNameList.count(Pcd.TokenCName) > 1: - AutoGenH.Append('// Disabled the macros, as PcdToken and PcdGet/Set are not allowed in the case that more than one DynamicEx Pcds are different Guids but same CName.\n') - AutoGenH.Append('// #define %s %s\n' % (PcdTokenName, PcdExTokenName)) - AutoGenH.Append('// #define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - if Pcd.DatumType == 'VOID*': - AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - else: - AutoGenH.Append('// #define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - else: - AutoGenH.Append('#define %s %s\n' % (PcdTokenName, PcdExTokenName)) - AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - if Pcd.DatumType == 'VOID*': - AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - else: - AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - elif Pcd.Type in gDynamicPcd: - AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName)) - if Pcd.DatumType == 'VOID*': - AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName)) - else: - AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName)) - else: - PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[Pcd.Type] + '_' + Pcd.TokenCName - Const = 'const' - if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: - Const = '' - Type = '' - Array = '' - Value = Pcd.DefaultValue - Unicode = False - ValueNumber = 0 - - if Pcd.DatumType == 'BOOLEAN': - BoolValue = Value.upper() - if BoolValue == 'TRUE' or BoolValue == '1': - Value = '1U' - elif BoolValue == 'FALSE' or BoolValue == '0': - Value = '0U' - - if Pcd.DatumType in ['UINT64', 'UINT32', 'UINT16', 'UINT8']: - try: - if Value.upper().startswith('0X'): - ValueNumber = int (Value, 16) - else: - ValueNumber = int (Value) - except: - EdkLogger.error("build", AUTOGEN_ERROR, - "PCD value is not valid dec or hex number for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - if Pcd.DatumType == 'UINT64': - if ValueNumber < 0: - EdkLogger.error("build", AUTOGEN_ERROR, - "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - elif ValueNumber >= 0x10000000000000000: - EdkLogger.error("build", AUTOGEN_ERROR, - "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - if not Value.endswith('ULL'): - Value += 'ULL' - elif Pcd.DatumType == 'UINT32': - if ValueNumber < 0: - EdkLogger.error("build", AUTOGEN_ERROR, - "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - elif ValueNumber >= 0x100000000: - EdkLogger.error("build", AUTOGEN_ERROR, - "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - if not Value.endswith('U'): - Value += 'U' - elif Pcd.DatumType == 'UINT16': - if ValueNumber < 0: - EdkLogger.error("build", AUTOGEN_ERROR, - "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - elif ValueNumber >= 0x10000: - EdkLogger.error("build", AUTOGEN_ERROR, - "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - if not Value.endswith('U'): - Value += 'U' - elif Pcd.DatumType == 'UINT8': - if ValueNumber < 0: - EdkLogger.error("build", AUTOGEN_ERROR, - "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - elif ValueNumber >= 0x100: - EdkLogger.error("build", AUTOGEN_ERROR, - "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - if not Value.endswith('U'): - Value += 'U' - if Pcd.DatumType == 'VOID*': - if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '': - EdkLogger.error("build", AUTOGEN_ERROR, - "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - - ArraySize = int(Pcd.MaxDatumSize, 0) - if Value[0] == '{': - Type = '(VOID *)' - else: - if Value[0] == 'L': - Unicode = True - Value = Value.lstrip('L') #.strip('"') - Value = eval(Value) # translate escape character - NewValue = '{' - for Index in range(0,len(Value)): - if Unicode: - NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ', ' - else: - NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ', ' - if Unicode: - ArraySize = ArraySize / 2; - - if ArraySize < (len(Value) + 1): - EdkLogger.error("build", AUTOGEN_ERROR, - "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - Value = NewValue + '0 }' - Array = '[%d]' % ArraySize - # - # skip casting for fixed at build since it breaks ARM assembly. - # Long term we need PCD macros that work in assembly - # - elif Pcd.Type != TAB_PCDS_FIXED_AT_BUILD: - Value = "((%s)%s)" % (Pcd.DatumType, Value) - - if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: - PcdValueName = '_PCD_PATCHABLE_VALUE_' + Pcd.TokenCName - else: - PcdValueName = '_PCD_VALUE_' + Pcd.TokenCName - - if Pcd.DatumType == 'VOID*': - # - # For unicode, UINT16 array will be generated, so the alignment of unicode is guaranteed. - # - if Unicode: - AutoGenH.Append('#define _PCD_PATCHABLE_%s_SIZE %s\n' % (Pcd.TokenCName, Pcd.MaxDatumSize)) - AutoGenH.Append('#define %s %s%s\n' %(PcdValueName, Type, PcdVariableName)) - AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s UINT16 %s%s = %s;\n' % (Const, PcdVariableName, Array, Value)) - AutoGenH.Append('extern %s UINT16 %s%s;\n' %(Const, PcdVariableName, Array)) - AutoGenH.Append('#define %s %s%s\n' %(GetModeName, Type, PcdVariableName)) - else: - AutoGenH.Append('#define _PCD_PATCHABLE_%s_SIZE %s\n' % (Pcd.TokenCName, Pcd.MaxDatumSize)) - AutoGenH.Append('#define %s %s%s\n' %(PcdValueName, Type, PcdVariableName)) - AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s UINT8 %s%s = %s;\n' % (Const, PcdVariableName, Array, Value)) - AutoGenH.Append('extern %s UINT8 %s%s;\n' %(Const, PcdVariableName, Array)) - AutoGenH.Append('#define %s %s%s\n' %(GetModeName, Type, PcdVariableName)) - elif Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: - AutoGenH.Append('#define %s %s\n' %(PcdValueName, Value)) - AutoGenC.Append('volatile %s %s %s = %s;\n' %(Const, Pcd.DatumType, PcdVariableName, PcdValueName)) - AutoGenH.Append('extern volatile %s %s %s%s;\n' % (Const, Pcd.DatumType, PcdVariableName, Array)) - AutoGenH.Append('#define %s %s%s\n' % (GetModeName, Type, PcdVariableName)) - else: - AutoGenH.Append('#define %s %s\n' %(PcdValueName, Value)) - AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s %s = %s;\n' %(Const, Pcd.DatumType, PcdVariableName, PcdValueName)) - AutoGenH.Append('extern %s %s %s%s;\n' % (Const, Pcd.DatumType, PcdVariableName, Array)) - AutoGenH.Append('#define %s %s%s\n' % (GetModeName, Type, PcdVariableName)) - - if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: - if Pcd.DatumType == 'VOID*': - AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPatchPcdSetPtr(_gPcd_BinaryPatch_%s, (UINTN)_PCD_PATCHABLE_%s_SIZE, (SizeOfBuffer), (Buffer))\n' % (SetModeName, Pcd.TokenCName, Pcd.TokenCName)) - else: - AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName)) - else: - AutoGenH.Append('//#define %s ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName) - -## Create code for library module PCDs -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# @param Pcd The PCD object -# -def CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd): - PcdTokenNumber = Info.PlatformInfo.PcdTokenNumber - TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName - TokenCName = Pcd.TokenCName - PcdTokenName = '_PCD_TOKEN_' + TokenCName - # - # Write PCDs - # - if Pcd.Type in gDynamicExPcd: - TokenNumber = int(Pcd.TokenValue, 0) - else: - if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in PcdTokenNumber: - # If one of the Source built modules listed in the DSC is not listed in FDF modules, - # and the INF lists a PCD can only use the PcdsDynamic access method (it is only - # listed in the DEC file that declares the PCD as PcdsDynamic), then build tool will - # report warning message notify the PI that they are attempting to build a module - # that must be included in a flash image in order to be functional. These Dynamic PCD - # will not be added into the Database unless it is used by other modules that are - # included in the FDF file. - # In this case, just assign an invalid token number to make it pass build. - if Pcd.Type in PCD_DYNAMIC_TYPE_LIST: - TokenNumber = 0 - else: - EdkLogger.error("build", AUTOGEN_ERROR, - "No generated token number for %s.%s\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - else: - TokenNumber = PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] - - if Pcd.Type not in gItemTypeStringDatabase: - EdkLogger.error("build", AUTOGEN_ERROR, - "Unknown PCD type [%s] of PCD %s.%s" % (Pcd.Type, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - if Pcd.DatumType not in gDatumSizeStringDatabase: - EdkLogger.error("build", AUTOGEN_ERROR, - "Unknown datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), - ExtraData="[%s]" % str(Info)) - - DatumType = Pcd.DatumType - DatumSize = gDatumSizeStringDatabaseH[DatumType] - DatumSizeLib= gDatumSizeStringDatabaseLib[DatumType] - GetModeName = '_PCD_GET_MODE_' + DatumSize + '_' + TokenCName - SetModeName = '_PCD_SET_MODE_' + DatumSize + '_' + TokenCName - - Type = '' - Array = '' - if Pcd.DatumType == 'VOID*': - Type = '(VOID *)' - Array = '[]' - PcdItemType = Pcd.Type - PcdExCNameList = [] - if PcdItemType in gDynamicExPcd: - PcdExTokenName = '_PCD_TOKEN_' + TokenSpaceGuidCName + '_' + Pcd.TokenCName - AutoGenH.Append('\n#define %s %dU\n' % (PcdExTokenName, TokenNumber)) - - if Info.IsLibrary: - PcdList = Info.LibraryPcdList - else: - PcdList = Info.ModulePcdList - for PcdModule in PcdList: - if PcdModule.Type in gDynamicExPcd: - PcdExCNameList.append(PcdModule.TokenCName) - # Be compatible with the current code which using PcdGet/Set for DynamicEx Pcd. - # If only PcdGet/Set used in all Pcds with different CName, it should succeed to build. - # If PcdGet/Set used in the Pcds with different Guids but same CName, it should failed to build. - if PcdExCNameList.count(Pcd.TokenCName) > 1: - AutoGenH.Append('// Disabled the macros, as PcdToken and PcdGet/Set are not allowed in the case that more than one DynamicEx Pcds are different Guids but same CName.\n') - AutoGenH.Append('// #define %s %s\n' % (PcdTokenName, PcdExTokenName)) - AutoGenH.Append('// #define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - if Pcd.DatumType == 'VOID*': - AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - else: - AutoGenH.Append('// #define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - else: - AutoGenH.Append('#define %s %s\n' % (PcdTokenName, PcdExTokenName)) - AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - if Pcd.DatumType == 'VOID*': - AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - else: - AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) - else: - AutoGenH.Append('#define _PCD_TOKEN_%s %dU\n' % (TokenCName, TokenNumber)) - if PcdItemType in gDynamicPcd: - AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName)) - if DatumType == 'VOID*': - AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName)) - else: - AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName)) - if PcdItemType == TAB_PCDS_PATCHABLE_IN_MODULE: - PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[TAB_PCDS_PATCHABLE_IN_MODULE] + '_' + TokenCName - AutoGenH.Append('extern volatile %s _gPcd_BinaryPatch_%s%s;\n' %(DatumType, TokenCName, Array) ) - AutoGenH.Append('#define %s %s_gPcd_BinaryPatch_%s\n' %(GetModeName, Type, TokenCName)) - AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName)) - if PcdItemType == TAB_PCDS_FIXED_AT_BUILD or PcdItemType == TAB_PCDS_FEATURE_FLAG: - key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName)) - - AutoGenH.Append('extern const %s _gPcd_FixedAtBuild_%s%s;\n' %(DatumType, TokenCName, Array)) - AutoGenH.Append('#define %s %s_gPcd_FixedAtBuild_%s\n' %(GetModeName, Type, TokenCName)) - AutoGenH.Append('//#define %s ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName) - - if PcdItemType == TAB_PCDS_FIXED_AT_BUILD and key in Info.ConstPcd: - AutoGenH.Append('#define _PCD_VALUE_%s %s\n' %(TokenCName, Pcd.DefaultValue)) - - - -## Create code for library constructor -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateLibraryConstructorCode(Info, AutoGenC, AutoGenH): - # - # Library Constructors - # - ConstructorPrototypeString = TemplateString() - ConstructorCallingString = TemplateString() - if Info.IsLibrary: - DependentLibraryList = [Info.Module] - else: - DependentLibraryList = Info.DependentLibraryList - for Lib in DependentLibraryList: - if len(Lib.ConstructorList) <= 0: - continue - Dict = {'Function':Lib.ConstructorList} - if Lib.ModuleType in ['BASE', 'SEC']: - ConstructorPrototypeString.Append(gLibraryStructorPrototype['BASE'].Replace(Dict)) - ConstructorCallingString.Append(gLibraryStructorCall['BASE'].Replace(Dict)) - elif Lib.ModuleType in ['PEI_CORE','PEIM']: - ConstructorPrototypeString.Append(gLibraryStructorPrototype['PEI'].Replace(Dict)) - ConstructorCallingString.Append(gLibraryStructorCall['PEI'].Replace(Dict)) - elif Lib.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', - 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION','SMM_CORE']: - ConstructorPrototypeString.Append(gLibraryStructorPrototype['DXE'].Replace(Dict)) - ConstructorCallingString.Append(gLibraryStructorCall['DXE'].Replace(Dict)) - - if str(ConstructorPrototypeString) == '': - ConstructorPrototypeList = [] - else: - ConstructorPrototypeList = [str(ConstructorPrototypeString)] - if str(ConstructorCallingString) == '': - ConstructorCallingList = [] - else: - ConstructorCallingList = [str(ConstructorCallingString)] - - Dict = { - 'Type' : 'Constructor', - 'FunctionPrototype' : ConstructorPrototypeList, - 'FunctionCall' : ConstructorCallingList - } - if Info.IsLibrary: - AutoGenH.Append("${BEGIN}${FunctionPrototype}${END}", Dict) - else: - if Info.ModuleType in ['BASE', 'SEC']: - AutoGenC.Append(gLibraryString['BASE'].Replace(Dict)) - elif Info.ModuleType in ['PEI_CORE','PEIM']: - AutoGenC.Append(gLibraryString['PEI'].Replace(Dict)) - elif Info.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', - 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION','SMM_CORE']: - AutoGenC.Append(gLibraryString['DXE'].Replace(Dict)) - -## Create code for library destructor -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateLibraryDestructorCode(Info, AutoGenC, AutoGenH): - # - # Library Destructors - # - DestructorPrototypeString = TemplateString() - DestructorCallingString = TemplateString() - if Info.IsLibrary: - DependentLibraryList = [Info.Module] - else: - DependentLibraryList = Info.DependentLibraryList - for Index in range(len(DependentLibraryList)-1, -1, -1): - Lib = DependentLibraryList[Index] - if len(Lib.DestructorList) <= 0: - continue - Dict = {'Function':Lib.DestructorList} - if Lib.ModuleType in ['BASE', 'SEC']: - DestructorPrototypeString.Append(gLibraryStructorPrototype['BASE'].Replace(Dict)) - DestructorCallingString.Append(gLibraryStructorCall['BASE'].Replace(Dict)) - elif Lib.ModuleType in ['PEI_CORE','PEIM']: - DestructorPrototypeString.Append(gLibraryStructorPrototype['PEI'].Replace(Dict)) - DestructorCallingString.Append(gLibraryStructorCall['PEI'].Replace(Dict)) - elif Lib.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', - 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION', 'SMM_CORE']: - DestructorPrototypeString.Append(gLibraryStructorPrototype['DXE'].Replace(Dict)) - DestructorCallingString.Append(gLibraryStructorCall['DXE'].Replace(Dict)) - - if str(DestructorPrototypeString) == '': - DestructorPrototypeList = [] - else: - DestructorPrototypeList = [str(DestructorPrototypeString)] - if str(DestructorCallingString) == '': - DestructorCallingList = [] - else: - DestructorCallingList = [str(DestructorCallingString)] - - Dict = { - 'Type' : 'Destructor', - 'FunctionPrototype' : DestructorPrototypeList, - 'FunctionCall' : DestructorCallingList - } - if Info.IsLibrary: - AutoGenH.Append("${BEGIN}${FunctionPrototype}${END}", Dict) - else: - if Info.ModuleType in ['BASE', 'SEC']: - AutoGenC.Append(gLibraryString['BASE'].Replace(Dict)) - elif Info.ModuleType in ['PEI_CORE','PEIM']: - AutoGenC.Append(gLibraryString['PEI'].Replace(Dict)) - elif Info.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', - 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION','SMM_CORE']: - AutoGenC.Append(gLibraryString['DXE'].Replace(Dict)) - - -## Create code for ModuleEntryPoint -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateModuleEntryPointCode(Info, AutoGenC, AutoGenH): - if Info.IsLibrary or Info.ModuleType in ['USER_DEFINED', 'SEC']: - return - # - # Module Entry Points - # - NumEntryPoints = len(Info.Module.ModuleEntryPointList) - if 'PI_SPECIFICATION_VERSION' in Info.Module.Specification: - PiSpecVersion = Info.Module.Specification['PI_SPECIFICATION_VERSION'] - else: - PiSpecVersion = '0x00000000' - if 'UEFI_SPECIFICATION_VERSION' in Info.Module.Specification: - UefiSpecVersion = Info.Module.Specification['UEFI_SPECIFICATION_VERSION'] - else: - UefiSpecVersion = '0x00000000' - Dict = { - 'Function' : Info.Module.ModuleEntryPointList, - 'PiSpecVersion' : PiSpecVersion + 'U', - 'UefiSpecVersion': UefiSpecVersion + 'U' - } - - if Info.ModuleType in ['PEI_CORE', 'DXE_CORE', 'SMM_CORE']: - if Info.SourceFileList <> None and Info.SourceFileList <> []: - if NumEntryPoints != 1: - EdkLogger.error( - "build", - AUTOGEN_ERROR, - '%s must have exactly one entry point' % Info.ModuleType, - File=str(Info), - ExtraData= ", ".join(Info.Module.ModuleEntryPointList) - ) - if Info.ModuleType == 'PEI_CORE': - AutoGenC.Append(gPeiCoreEntryPointString.Replace(Dict)) - AutoGenH.Append(gPeiCoreEntryPointPrototype.Replace(Dict)) - elif Info.ModuleType == 'DXE_CORE': - AutoGenC.Append(gDxeCoreEntryPointString.Replace(Dict)) - AutoGenH.Append(gDxeCoreEntryPointPrototype.Replace(Dict)) - elif Info.ModuleType == 'SMM_CORE': - AutoGenC.Append(gSmmCoreEntryPointString.Replace(Dict)) - AutoGenH.Append(gSmmCoreEntryPointPrototype.Replace(Dict)) - elif Info.ModuleType == 'PEIM': - if NumEntryPoints < 2: - AutoGenC.Append(gPeimEntryPointString[NumEntryPoints].Replace(Dict)) - else: - AutoGenC.Append(gPeimEntryPointString[2].Replace(Dict)) - AutoGenH.Append(gPeimEntryPointPrototype.Replace(Dict)) - elif Info.ModuleType in ['DXE_RUNTIME_DRIVER','DXE_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']: - if NumEntryPoints < 2: - AutoGenC.Append(gUefiDriverEntryPointString[NumEntryPoints].Replace(Dict)) - else: - AutoGenC.Append(gUefiDriverEntryPointString[2].Replace(Dict)) - AutoGenH.Append(gUefiDriverEntryPointPrototype.Replace(Dict)) - elif Info.ModuleType == 'DXE_SMM_DRIVER': - if NumEntryPoints == 0: - AutoGenC.Append(gDxeSmmEntryPointString[0].Replace(Dict)) - else: - AutoGenC.Append(gDxeSmmEntryPointString[1].Replace(Dict)) - AutoGenH.Append(gDxeSmmEntryPointPrototype.Replace(Dict)) - elif Info.ModuleType == 'UEFI_APPLICATION': - if NumEntryPoints < 2: - AutoGenC.Append(gUefiApplicationEntryPointString[NumEntryPoints].Replace(Dict)) - else: - AutoGenC.Append(gUefiApplicationEntryPointString[2].Replace(Dict)) - AutoGenH.Append(gUefiApplicationEntryPointPrototype.Replace(Dict)) - -## Create code for ModuleUnloadImage -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateModuleUnloadImageCode(Info, AutoGenC, AutoGenH): - if Info.IsLibrary or Info.ModuleType in ['USER_DEFINED', 'SEC']: - return - # - # Unload Image Handlers - # - NumUnloadImage = len(Info.Module.ModuleUnloadImageList) - Dict = {'Count':str(NumUnloadImage) + 'U', 'Function':Info.Module.ModuleUnloadImageList} - if NumUnloadImage < 2: - AutoGenC.Append(gUefiUnloadImageString[NumUnloadImage].Replace(Dict)) - else: - AutoGenC.Append(gUefiUnloadImageString[2].Replace(Dict)) - AutoGenH.Append(gUefiUnloadImagePrototype.Replace(Dict)) - -## Create code for GUID -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateGuidDefinitionCode(Info, AutoGenC, AutoGenH): - if Info.IsLibrary: - return - - if Info.ModuleType in ["USER_DEFINED", "BASE"]: - GuidType = "GUID" - else: - GuidType = "EFI_GUID" - - if Info.GuidList: - AutoGenC.Append("\n// Guids\n") - # - # GUIDs - # - for Key in Info.GuidList: - AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.GuidList[Key])) - -## Create code for protocol -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateProtocolDefinitionCode(Info, AutoGenC, AutoGenH): - if Info.IsLibrary: - return - - if Info.ModuleType in ["USER_DEFINED", "BASE"]: - GuidType = "GUID" - else: - GuidType = "EFI_GUID" - - if Info.ProtocolList: - AutoGenC.Append("\n// Protocols\n") - # - # Protocol GUIDs - # - for Key in Info.ProtocolList: - AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.ProtocolList[Key])) - -## Create code for PPI -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreatePpiDefinitionCode(Info, AutoGenC, AutoGenH): - if Info.IsLibrary: - return - - if Info.ModuleType in ["USER_DEFINED", "BASE"]: - GuidType = "GUID" - else: - GuidType = "EFI_GUID" - - if Info.PpiList: - AutoGenC.Append("\n// PPIs\n") - # - # PPI GUIDs - # - for Key in Info.PpiList: - AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.PpiList[Key])) - -## Create code for PCD -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreatePcdCode(Info, AutoGenC, AutoGenH): - - # Collect Token Space GUIDs used by DynamicEc PCDs - TokenSpaceList = [] - for Pcd in Info.ModulePcdList: - if Pcd.Type in gDynamicExPcd and Pcd.TokenSpaceGuidCName not in TokenSpaceList: - TokenSpaceList += [Pcd.TokenSpaceGuidCName] - - # Add extern declarations to AutoGen.h if one or more Token Space GUIDs were found - if TokenSpaceList <> []: - AutoGenH.Append("\n// Definition of PCD Token Space GUIDs used in this module\n\n") - if Info.ModuleType in ["USER_DEFINED", "BASE"]: - GuidType = "GUID" - else: - GuidType = "EFI_GUID" - for Item in TokenSpaceList: - AutoGenH.Append('extern %s %s;\n' % (GuidType, Item)) - - if Info.IsLibrary: - if Info.ModulePcdList: - AutoGenH.Append("\n// PCD definitions\n") - for Pcd in Info.ModulePcdList: - CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd) - DynExPcdTokenNumberMapping (Info, AutoGenH) - else: - if Info.ModulePcdList: - AutoGenH.Append("\n// Definition of PCDs used in this module\n") - AutoGenC.Append("\n// Definition of PCDs used in this module\n") - for Pcd in Info.ModulePcdList: - CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd) - DynExPcdTokenNumberMapping (Info, AutoGenH) - if Info.LibraryPcdList: - AutoGenH.Append("\n// Definition of PCDs used in libraries is in AutoGen.c\n") - AutoGenC.Append("\n// Definition of PCDs used in libraries\n") - for Pcd in Info.LibraryPcdList: - CreateModulePcdCode(Info, AutoGenC, AutoGenC, Pcd) - CreatePcdDatabaseCode(Info, AutoGenC, AutoGenH) - -## Create code for unicode string definition -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# @param UniGenCFlag UniString is generated into AutoGen C file when it is set to True -# @param UniGenBinBuffer Buffer to store uni string package data -# -def CreateUnicodeStringCode(Info, AutoGenC, AutoGenH, UniGenCFlag, UniGenBinBuffer): - WorkingDir = os.getcwd() - os.chdir(Info.WorkspaceDir) - - IncList = [Info.MetaFile.Dir] - # Get all files under [Sources] section in inf file for EDK-II module - EDK2Module = True - SrcList = [F for F in Info.SourceFileList] - if Info.AutoGenVersion < 0x00010005: - EDK2Module = False - # Get all files under the module directory for EDK-I module - Cwd = os.getcwd() - os.chdir(Info.MetaFile.Dir) - for Root, Dirs, Files in os.walk("."): - if 'CVS' in Dirs: - Dirs.remove('CVS') - if '.svn' in Dirs: - Dirs.remove('.svn') - for File in Files: - File = PathClass(os.path.join(Root, File), Info.MetaFile.Dir) - if File in SrcList: - continue - SrcList.append(File) - os.chdir(Cwd) - - if 'BUILD' in Info.BuildOption and Info.BuildOption['BUILD']['FLAGS'].find('-c') > -1: - CompatibleMode = True - else: - CompatibleMode = False - - # - # -s is a temporary option dedicated for building .UNI files with ISO 639-2 language codes of EDK Shell in EDK2 - # - if 'BUILD' in Info.BuildOption and Info.BuildOption['BUILD']['FLAGS'].find('-s') > -1: - if CompatibleMode: - EdkLogger.error("build", AUTOGEN_ERROR, - "-c and -s build options should be used exclusively", - ExtraData="[%s]" % str(Info)) - ShellMode = True - else: - ShellMode = False - - #RFC4646 is only for EDKII modules and ISO639-2 for EDK modules - if EDK2Module: - FilterInfo = [EDK2Module] + [Info.PlatformInfo.Platform.RFCLanguages] - else: - FilterInfo = [EDK2Module] + [Info.PlatformInfo.Platform.ISOLanguages] - Header, Code = GetStringFiles(Info.UnicodeFileList, SrcList, IncList, Info.IncludePathList, ['.uni', '.inf'], Info.Name, CompatibleMode, ShellMode, UniGenCFlag, UniGenBinBuffer, FilterInfo) - if CompatibleMode or UniGenCFlag: - AutoGenC.Append("\n//\n//Unicode String Pack Definition\n//\n") - AutoGenC.Append(Code) - AutoGenC.Append("\n") - AutoGenH.Append("\n//\n//Unicode String ID\n//\n") - AutoGenH.Append(Header) - if CompatibleMode or UniGenCFlag: - AutoGenH.Append("\n#define STRING_ARRAY_NAME %sStrings\n" % Info.Name) - os.chdir(WorkingDir) - -## Create common code -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateHeaderCode(Info, AutoGenC, AutoGenH): - # file header - AutoGenH.Append(gAutoGenHeaderString.Replace({'FileName':'AutoGen.h'})) - # header file Prologue - AutoGenH.Append(gAutoGenHPrologueString.Replace({'File':'AUTOGENH','Guid':Info.Guid.replace('-','_')})) - AutoGenH.Append(gAutoGenHCppPrologueString) - if Info.AutoGenVersion >= 0x00010005: - # header files includes - AutoGenH.Append("#include <%s>\n" % gBasicHeaderFile) - if Info.ModuleType in gModuleTypeHeaderFile \ - and gModuleTypeHeaderFile[Info.ModuleType][0] != gBasicHeaderFile: - AutoGenH.Append("#include <%s>\n" % gModuleTypeHeaderFile[Info.ModuleType][0]) - # - # if either PcdLib in [LibraryClasses] sections or there exist Pcd section, add PcdLib.h - # As if modules only uses FixedPcd, then PcdLib is not needed in [LibraryClasses] section. - # - if 'PcdLib' in Info.Module.LibraryClasses or Info.Module.Pcds: - AutoGenH.Append("#include \n") - - AutoGenH.Append('\nextern GUID gEfiCallerIdGuid;') - AutoGenH.Append('\nextern CHAR8 *gEfiCallerBaseName;\n\n') - - if Info.IsLibrary: - return - - AutoGenH.Append("#define EFI_CALLER_ID_GUID \\\n %s\n" % GuidStringToGuidStructureString(Info.Guid)) - - if Info.IsLibrary: - return - # C file header - AutoGenC.Append(gAutoGenHeaderString.Replace({'FileName':'AutoGen.c'})) - if Info.AutoGenVersion >= 0x00010005: - # C file header files includes - if Info.ModuleType in gModuleTypeHeaderFile: - for Inc in gModuleTypeHeaderFile[Info.ModuleType]: - AutoGenC.Append("#include <%s>\n" % Inc) - else: - AutoGenC.Append("#include <%s>\n" % gBasicHeaderFile) - - # - # Publish the CallerId Guid - # - AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED GUID gEfiCallerIdGuid = %s;\n' % GuidStringToGuidStructureString(Info.Guid)) - AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gEfiCallerBaseName = "%s";\n' % Info.Name) - -## Create common code for header file -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# -def CreateFooterCode(Info, AutoGenC, AutoGenH): - AutoGenH.Append(gAutoGenHEpilogueString) - -## Create code for a module -# -# @param Info The ModuleAutoGen object -# @param AutoGenC The TemplateString object for C code -# @param AutoGenH The TemplateString object for header file -# @param UniGenCFlag UniString is generated into AutoGen C file when it is set to True -# @param UniGenBinBuffer Buffer to store uni string package data -# -def CreateCode(Info, AutoGenC, AutoGenH, StringH, UniGenCFlag, UniGenBinBuffer): - CreateHeaderCode(Info, AutoGenC, AutoGenH) - - if Info.AutoGenVersion >= 0x00010005: - CreateGuidDefinitionCode(Info, AutoGenC, AutoGenH) - CreateProtocolDefinitionCode(Info, AutoGenC, AutoGenH) - CreatePpiDefinitionCode(Info, AutoGenC, AutoGenH) - CreatePcdCode(Info, AutoGenC, AutoGenH) - CreateLibraryConstructorCode(Info, AutoGenC, AutoGenH) - CreateLibraryDestructorCode(Info, AutoGenC, AutoGenH) - CreateModuleEntryPointCode(Info, AutoGenC, AutoGenH) - CreateModuleUnloadImageCode(Info, AutoGenC, AutoGenH) - - if Info.UnicodeFileList: - FileName = "%sStrDefs.h" % Info.Name - StringH.Append(gAutoGenHeaderString.Replace({'FileName':FileName})) - StringH.Append(gAutoGenHPrologueString.Replace({'File':'STRDEFS', 'Guid':Info.Guid.replace('-','_')})) - CreateUnicodeStringCode(Info, AutoGenC, StringH, UniGenCFlag, UniGenBinBuffer) - StringH.Append("\n#endif\n") - AutoGenH.Append('#include "%s"\n' % FileName) - - CreateFooterCode(Info, AutoGenC, AutoGenH) - - # no generation of AutoGen.c for Edk modules without unicode file - if Info.AutoGenVersion < 0x00010005 and len(Info.UnicodeFileList) == 0: - AutoGenC.String = '' - -## Create the code file -# -# @param FilePath The path of code file -# @param Content The content of code file -# @param IsBinaryFile The flag indicating if the file is binary file or not -# -# @retval True If file content is changed or file doesn't exist -# @retval False If the file exists and the content is not changed -# -def Generate(FilePath, Content, IsBinaryFile): - return SaveFileOnChange(FilePath, Content, IsBinaryFile) - +## @file +# Routines for generating AutoGen.h and AutoGen.c +# +# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +## Import Modules +# +import string + +from Common import EdkLogger + +from Common.BuildToolError import * +from Common.DataType import * +from Common.Misc import * +from Common.String import StringToArray +from StrGather import * +from GenPcdDb import CreatePcdDatabaseCode + +## PCD type string +gItemTypeStringDatabase = { + TAB_PCDS_FEATURE_FLAG : 'FixedAtBuild', + TAB_PCDS_FIXED_AT_BUILD : 'FixedAtBuild', + TAB_PCDS_PATCHABLE_IN_MODULE: 'BinaryPatch', + TAB_PCDS_DYNAMIC : '', + TAB_PCDS_DYNAMIC_DEFAULT : '', + TAB_PCDS_DYNAMIC_VPD : '', + TAB_PCDS_DYNAMIC_HII : '', + TAB_PCDS_DYNAMIC_EX : '', + TAB_PCDS_DYNAMIC_EX_DEFAULT : '', + TAB_PCDS_DYNAMIC_EX_VPD : '', + TAB_PCDS_DYNAMIC_EX_HII : '', +} + +## Dynamic PCD types +gDynamicPcd = [TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_DEFAULT, TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_HII] + +## Dynamic-ex PCD types +gDynamicExPcd = [TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, TAB_PCDS_DYNAMIC_EX_VPD, TAB_PCDS_DYNAMIC_EX_HII] + +## Datum size +gDatumSizeStringDatabase = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'BOOLEAN','VOID*':'8'} +gDatumSizeStringDatabaseH = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'BOOL','VOID*':'PTR'} +gDatumSizeStringDatabaseLib = {'UINT8':'8','UINT16':'16','UINT32':'32','UINT64':'64','BOOLEAN':'Bool','VOID*':'Ptr'} + +## AutoGen File Header Templates +gAutoGenHeaderString = TemplateString("""\ +/** + DO NOT EDIT + FILE auto-generated + Module name: + ${FileName} + Abstract: Auto-generated ${FileName} for building module or library. +**/ +""") + +gAutoGenHPrologueString = TemplateString(""" +#ifndef _${File}_${Guid} +#define _${File}_${Guid} + +""") + +gAutoGenHCppPrologueString = """\ +#ifdef __cplusplus +extern "C" { +#endif + +""" + +gAutoGenHEpilogueString = """ + +#ifdef __cplusplus +} +#endif + +#endif +""" + +## PEI Core Entry Point Templates +gPeiCoreEntryPointPrototype = TemplateString(""" +${BEGIN} +VOID +EFIAPI +${Function} ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Context + ); +${END} +""") + +gPeiCoreEntryPointString = TemplateString(""" +${BEGIN} +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Context + ) + +{ + ${Function} (SecCoreData, PpiList, Context); +} +${END} +""") + + +## DXE Core Entry Point Templates +gDxeCoreEntryPointPrototype = TemplateString(""" +${BEGIN} +VOID +EFIAPI +${Function} ( + IN VOID *HobStart + ); +${END} +""") + +gDxeCoreEntryPointString = TemplateString(""" +${BEGIN} +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN VOID *HobStart + ) + +{ + ${Function} (HobStart); +} +${END} +""") + +## PEIM Entry Point Templates +gPeimEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); +${END} +""") + +gPeimEntryPointString = [ +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) + +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) + +{ + return ${Function} (FileHandle, PeiServices); +} +${END} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) + +{ + EFI_STATUS Status; + EFI_STATUS CombinedStatus; + + CombinedStatus = EFI_LOAD_ERROR; +${BEGIN} + Status = ${Function} (FileHandle, PeiServices); + if (!EFI_ERROR (Status) || EFI_ERROR (CombinedStatus)) { + CombinedStatus = Status; + } +${END} + return CombinedStatus; +} +""") +] + +## SMM_CORE Entry Point Templates +gSmmCoreEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +${END} +""") + +gSmmCoreEntryPointString = TemplateString(""" +${BEGIN} +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return ${Function} (ImageHandle, SystemTable); +} +${END} +""") + +## DXE SMM Entry Point Templates +gDxeSmmEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +${END} +""") + +gDxeSmmEntryPointString = [ +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +static BASE_LIBRARY_JUMP_BUFFER mJumpContext; +static EFI_STATUS mDriverEntryPointStatus; + +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { + mDriverEntryPointStatus = Status; + } + LongJump (&mJumpContext, (UINTN)-1); + ASSERT (FALSE); +} + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mDriverEntryPointStatus = EFI_LOAD_ERROR; + +${BEGIN} + if (SetJump (&mJumpContext) == 0) { + ExitDriver (${Function} (ImageHandle, SystemTable)); + ASSERT (FALSE); + } +${END} + + return mDriverEntryPointStatus; +} +""") +] + +## UEFI Driver Entry Point Templates +gUefiDriverEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +${END} +""") + +gUefiDriverEntryPointString = [ +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + return ${Function} (ImageHandle, SystemTable); +} +${END} +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (gImageHandle, gST); + } + gBS->Exit (gImageHandle, Status, 0, NULL); +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; +const UINT32 _gDxeRevision = ${PiSpecVersion}; + +static BASE_LIBRARY_JUMP_BUFFER mJumpContext; +static EFI_STATUS mDriverEntryPointStatus; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mDriverEntryPointStatus = EFI_LOAD_ERROR; + ${BEGIN} + if (SetJump (&mJumpContext) == 0) { + ExitDriver (${Function} (ImageHandle, SystemTable)); + ASSERT (FALSE); + } + ${END} + return mDriverEntryPointStatus; +} + +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { + mDriverEntryPointStatus = Status; + } + LongJump (&mJumpContext, (UINTN)-1); + ASSERT (FALSE); +} +""") +] + + +## UEFI Application Entry Point Templates +gUefiApplicationEntryPointPrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); +${END} +""") + +gUefiApplicationEntryPointString = [ +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; + +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + return ${Function} (ImageHandle, SystemTable); +} +${END} +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (gImageHandle, gST); + } + gBS->Exit (gImageHandle, Status, 0, NULL); +} +"""), +TemplateString(""" +const UINT32 _gUefiDriverRevision = ${UefiSpecVersion}; + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + ${BEGIN} + if (SetJump (&mJumpContext) == 0) { + ExitDriver (${Function} (ImageHandle, SystemTable)); + ASSERT (FALSE); + } + ${END} + return mDriverEntryPointStatus; +} + +static BASE_LIBRARY_JUMP_BUFFER mJumpContext; +static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR; + +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ) +{ + if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) { + mDriverEntryPointStatus = Status; + } + LongJump (&mJumpContext, (UINTN)-1); + ASSERT (FALSE); +} +""") +] + +## UEFI Unload Image Templates +gUefiUnloadImagePrototype = TemplateString(""" +${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle + ); +${END} +""") + +gUefiUnloadImageString = [ +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; + +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ) +{ + return EFI_SUCCESS; +} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; + +${BEGIN} +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ) +{ + return ${Function} (ImageHandle); +} +${END} +"""), +TemplateString(""" +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = ${Count}; + +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; +${BEGIN} + if (EFI_ERROR (Status)) { + ${Function} (ImageHandle); + } else { + Status = ${Function} (ImageHandle); + } +${END} + return Status; +} +""") +] + +gLibraryStructorPrototype = { +'BASE' : TemplateString("""${BEGIN} +RETURN_STATUS +EFIAPI +${Function} ( + VOID + );${END} +"""), + +'PEI' : TemplateString("""${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + );${END} +"""), + +'DXE' : TemplateString("""${BEGIN} +EFI_STATUS +EFIAPI +${Function} ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + );${END} +"""), +} + +gLibraryStructorCall = { +'BASE' : TemplateString("""${BEGIN} + Status = ${Function} (); + ASSERT_EFI_ERROR (Status);${END} +"""), + +'PEI' : TemplateString("""${BEGIN} + Status = ${Function} (FileHandle, PeiServices); + ASSERT_EFI_ERROR (Status);${END} +"""), + +'DXE' : TemplateString("""${BEGIN} + Status = ${Function} (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status);${END} +"""), +} + +## Library Constructor and Destructor Templates +gLibraryString = { +'BASE' : TemplateString(""" +${BEGIN}${FunctionPrototype}${END} + +VOID +EFIAPI +ProcessLibrary${Type}List ( + VOID + ) +{ +${BEGIN} EFI_STATUS Status; +${FunctionCall}${END} +} +"""), + +'PEI' : TemplateString(""" +${BEGIN}${FunctionPrototype}${END} + +VOID +EFIAPI +ProcessLibrary${Type}List ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ +${BEGIN} EFI_STATUS Status; +${FunctionCall}${END} +} +"""), + +'DXE' : TemplateString(""" +${BEGIN}${FunctionPrototype}${END} + +VOID +EFIAPI +ProcessLibrary${Type}List ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ +${BEGIN} EFI_STATUS Status; +${FunctionCall}${END} +} +"""), +} + +gBasicHeaderFile = "Base.h" + +gModuleTypeHeaderFile = { + "BASE" : [gBasicHeaderFile], + "SEC" : ["PiPei.h", "Library/DebugLib.h"], + "PEI_CORE" : ["PiPei.h", "Library/DebugLib.h", "Library/PeiCoreEntryPoint.h"], + "PEIM" : ["PiPei.h", "Library/DebugLib.h", "Library/PeimEntryPoint.h"], + "DXE_CORE" : ["PiDxe.h", "Library/DebugLib.h", "Library/DxeCoreEntryPoint.h"], + "DXE_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "DXE_SMM_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "DXE_RUNTIME_DRIVER": ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "DXE_SAL_DRIVER" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "UEFI_DRIVER" : ["Uefi.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiDriverEntryPoint.h"], + "UEFI_APPLICATION" : ["Uefi.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiBootServicesTableLib.h", "Library/UefiApplicationEntryPoint.h"], + "SMM_CORE" : ["PiDxe.h", "Library/BaseLib.h", "Library/DebugLib.h", "Library/UefiDriverEntryPoint.h"], + "USER_DEFINED" : [gBasicHeaderFile] +} + +## Autogen internal worker macro to define DynamicEx PCD name includes both the TokenSpaceGuidName +# the TokenName and Guid comparison to avoid define name collisions. +# +# @param Info The ModuleAutoGen object +# @param AutoGenH The TemplateString object for header file +# +# +def DynExPcdTokenNumberMapping(Info, AutoGenH): + ExTokenCNameList = [] + PcdExList = [] + if Info.IsLibrary: + PcdList = Info.LibraryPcdList + else: + PcdList = Info.ModulePcdList + for Pcd in PcdList: + if Pcd.Type in gDynamicExPcd: + ExTokenCNameList.append(Pcd.TokenCName) + PcdExList.append(Pcd) + if len(ExTokenCNameList) == 0: + return + AutoGenH.Append('\n#define COMPAREGUID(Guid1, Guid2) (BOOLEAN)(*(CONST UINT64*)Guid1 == *(CONST UINT64*)Guid2 && *((CONST UINT64*)Guid1 + 1) == *((CONST UINT64*)Guid2 + 1))\n') + # AutoGen for each PCD listed in a [PcdEx] section of a Module/Lib INF file. + # Auto generate a macro for each TokenName that takes a Guid pointer as a parameter. + # Use the Guid pointer to see if it matches any of the token space GUIDs. + TokenCNameList = [] + for TokenCName in ExTokenCNameList: + if TokenCName in TokenCNameList: + continue + Index = 0 + Count = ExTokenCNameList.count(TokenCName) + for Pcd in PcdExList: + if Pcd.TokenCName == TokenCName: + Index = Index + 1 + if Index == 1: + AutoGenH.Append('\n#define __PCD_%s_ADDR_CMP(GuidPtr) (' % (Pcd.TokenCName)) + AutoGenH.Append('\\\n (GuidPtr == &%s) ? _PCD_TOKEN_%s_%s:' + % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) + else: + AutoGenH.Append('\\\n (GuidPtr == &%s) ? _PCD_TOKEN_%s_%s:' + % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) + if Index == Count: + AutoGenH.Append('0 \\\n )\n') + TokenCNameList.append(TokenCName) + + TokenCNameList = [] + for TokenCName in ExTokenCNameList: + if TokenCName in TokenCNameList: + continue + Index = 0 + Count = ExTokenCNameList.count(TokenCName) + for Pcd in PcdExList: + if Pcd.Type in gDynamicExPcd and Pcd.TokenCName == TokenCName: + Index = Index + 1 + if Index == 1: + AutoGenH.Append('\n#define __PCD_%s_VAL_CMP(GuidPtr) (' % (Pcd.TokenCName)) + AutoGenH.Append('\\\n COMPAREGUID (GuidPtr, &%s) ? _PCD_TOKEN_%s_%s:' + % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) + else: + AutoGenH.Append('\\\n COMPAREGUID (GuidPtr, &%s) ? _PCD_TOKEN_%s_%s:' + % (Pcd.TokenSpaceGuidCName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) + if Index == Count: + AutoGenH.Append('0 \\\n )\n') + # Autogen internal worker macro to compare GUIDs. Guid1 is a pointer to a GUID. + # Guid2 is a C name for a GUID. Compare pointers first because optimizing compiler + # can do this at build time on CONST GUID pointers and optimize away call to COMPAREGUID(). + # COMPAREGUID() will only be used if the Guid passed in is local to the module. + AutoGenH.Append('#define _PCD_TOKEN_EX_%s(GuidPtr) __PCD_%s_ADDR_CMP(GuidPtr) ? __PCD_%s_ADDR_CMP(GuidPtr) : __PCD_%s_VAL_CMP(GuidPtr) \n' + % (Pcd.TokenCName, Pcd.TokenCName, Pcd.TokenCName, Pcd.TokenCName)) + TokenCNameList.append(TokenCName) + +## Create code for module PCDs +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# @param Pcd The PCD object +# +def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd): + TokenSpaceGuidValue = Pcd.TokenSpaceGuidValue #Info.GuidList[Pcd.TokenSpaceGuidCName] + PcdTokenNumber = Info.PlatformInfo.PcdTokenNumber + # + # Write PCDs + # + PcdTokenName = '_PCD_TOKEN_' + Pcd.TokenCName + if Pcd.Type in gDynamicExPcd: + TokenNumber = int(Pcd.TokenValue, 0) + # Add TokenSpaceGuidValue value to PcdTokenName to discriminate the DynamicEx PCDs with + # different Guids but same TokenCName + PcdExTokenName = '_PCD_TOKEN_' + Pcd.TokenSpaceGuidCName + '_' + Pcd.TokenCName + AutoGenH.Append('\n#define %s %dU\n' % (PcdExTokenName, TokenNumber)) + else: + if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in PcdTokenNumber: + # If one of the Source built modules listed in the DSC is not listed in FDF modules, + # and the INF lists a PCD can only use the PcdsDynamic access method (it is only + # listed in the DEC file that declares the PCD as PcdsDynamic), then build tool will + # report warning message notify the PI that they are attempting to build a module + # that must be included in a flash image in order to be functional. These Dynamic PCD + # will not be added into the Database unless it is used by other modules that are + # included in the FDF file. + # In this case, just assign an invalid token number to make it pass build. + if Pcd.Type in PCD_DYNAMIC_TYPE_LIST: + TokenNumber = 0 + else: + EdkLogger.error("build", AUTOGEN_ERROR, + "No generated token number for %s.%s\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + else: + TokenNumber = PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] + AutoGenH.Append('\n#define %s %dU\n' % (PcdTokenName, TokenNumber)) + + EdkLogger.debug(EdkLogger.DEBUG_3, "Creating code for " + Pcd.TokenCName + "." + Pcd.TokenSpaceGuidCName) + if Pcd.Type not in gItemTypeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown PCD type [%s] of PCD %s.%s" % (Pcd.Type, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if Pcd.DatumType not in gDatumSizeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + + DatumSize = gDatumSizeStringDatabase[Pcd.DatumType] + DatumSizeLib = gDatumSizeStringDatabaseLib[Pcd.DatumType] + GetModeName = '_PCD_GET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName + SetModeName = '_PCD_SET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName + + PcdExCNameList = [] + if Pcd.Type in gDynamicExPcd: + if Info.IsLibrary: + PcdList = Info.LibraryPcdList + else: + PcdList = Info.ModulePcdList + for PcdModule in PcdList: + if PcdModule.Type in gDynamicExPcd: + PcdExCNameList.append(PcdModule.TokenCName) + # Be compatible with the current code which using PcdToken and PcdGet/Set for DynamicEx Pcd. + # If only PcdToken and PcdGet/Set used in all Pcds with different CName, it should succeed to build. + # If PcdToken and PcdGet/Set used in the Pcds with different Guids but same CName, it should failed to build. + if PcdExCNameList.count(Pcd.TokenCName) > 1: + AutoGenH.Append('// Disabled the macros, as PcdToken and PcdGet/Set are not allowed in the case that more than one DynamicEx Pcds are different Guids but same CName.\n') + AutoGenH.Append('// #define %s %s\n' % (PcdTokenName, PcdExTokenName)) + AutoGenH.Append('// #define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('// #define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('#define %s %s\n' % (PcdTokenName, PcdExTokenName)) + AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + elif Pcd.Type in gDynamicPcd: + AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName)) + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName)) + else: + PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[Pcd.Type] + '_' + Pcd.TokenCName + Const = 'const' + if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + Const = '' + Type = '' + Array = '' + Value = Pcd.DefaultValue + Unicode = False + ValueNumber = 0 + + if Pcd.DatumType == 'BOOLEAN': + BoolValue = Value.upper() + if BoolValue == 'TRUE' or BoolValue == '1': + Value = '1U' + elif BoolValue == 'FALSE' or BoolValue == '0': + Value = '0U' + + if Pcd.DatumType in ['UINT64', 'UINT32', 'UINT16', 'UINT8']: + try: + if Value.upper().startswith('0X'): + ValueNumber = int (Value, 16) + else: + ValueNumber = int (Value) + except: + EdkLogger.error("build", AUTOGEN_ERROR, + "PCD value is not valid dec or hex number for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if Pcd.DatumType == 'UINT64': + if ValueNumber < 0: + EdkLogger.error("build", AUTOGEN_ERROR, + "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + elif ValueNumber >= 0x10000000000000000: + EdkLogger.error("build", AUTOGEN_ERROR, + "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if not Value.endswith('ULL'): + Value += 'ULL' + elif Pcd.DatumType == 'UINT32': + if ValueNumber < 0: + EdkLogger.error("build", AUTOGEN_ERROR, + "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + elif ValueNumber >= 0x100000000: + EdkLogger.error("build", AUTOGEN_ERROR, + "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if not Value.endswith('U'): + Value += 'U' + elif Pcd.DatumType == 'UINT16': + if ValueNumber < 0: + EdkLogger.error("build", AUTOGEN_ERROR, + "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + elif ValueNumber >= 0x10000: + EdkLogger.error("build", AUTOGEN_ERROR, + "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if not Value.endswith('U'): + Value += 'U' + elif Pcd.DatumType == 'UINT8': + if ValueNumber < 0: + EdkLogger.error("build", AUTOGEN_ERROR, + "PCD can't be set to negative value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + elif ValueNumber >= 0x100: + EdkLogger.error("build", AUTOGEN_ERROR, + "Too large PCD value for datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if not Value.endswith('U'): + Value += 'U' + if Pcd.DatumType == 'VOID*': + if Pcd.MaxDatumSize == None or Pcd.MaxDatumSize == '': + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + + ArraySize = int(Pcd.MaxDatumSize, 0) + if Value[0] == '{': + Type = '(VOID *)' + else: + if Value[0] == 'L': + Unicode = True + Value = Value.lstrip('L') #.strip('"') + Value = eval(Value) # translate escape character + NewValue = '{' + for Index in range(0,len(Value)): + if Unicode: + NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ', ' + else: + NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ', ' + if Unicode: + ArraySize = ArraySize / 2; + + if ArraySize < (len(Value) + 1): + EdkLogger.error("build", AUTOGEN_ERROR, + "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + Value = NewValue + '0 }' + Array = '[%d]' % ArraySize + # + # skip casting for fixed at build since it breaks ARM assembly. + # Long term we need PCD macros that work in assembly + # + elif Pcd.Type != TAB_PCDS_FIXED_AT_BUILD: + Value = "((%s)%s)" % (Pcd.DatumType, Value) + + if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + PcdValueName = '_PCD_PATCHABLE_VALUE_' + Pcd.TokenCName + else: + PcdValueName = '_PCD_VALUE_' + Pcd.TokenCName + + if Pcd.DatumType == 'VOID*': + # + # For unicode, UINT16 array will be generated, so the alignment of unicode is guaranteed. + # + if Unicode: + AutoGenH.Append('#define _PCD_PATCHABLE_%s_SIZE %s\n' % (Pcd.TokenCName, Pcd.MaxDatumSize)) + AutoGenH.Append('#define %s %s%s\n' %(PcdValueName, Type, PcdVariableName)) + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s UINT16 %s%s = %s;\n' % (Const, PcdVariableName, Array, Value)) + AutoGenH.Append('extern %s UINT16 %s%s;\n' %(Const, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' %(GetModeName, Type, PcdVariableName)) + else: + AutoGenH.Append('#define _PCD_PATCHABLE_%s_SIZE %s\n' % (Pcd.TokenCName, Pcd.MaxDatumSize)) + AutoGenH.Append('#define %s %s%s\n' %(PcdValueName, Type, PcdVariableName)) + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s UINT8 %s%s = %s;\n' % (Const, PcdVariableName, Array, Value)) + AutoGenH.Append('extern %s UINT8 %s%s;\n' %(Const, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' %(GetModeName, Type, PcdVariableName)) + elif Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + AutoGenH.Append('#define %s %s\n' %(PcdValueName, Value)) + AutoGenC.Append('volatile %s %s %s = %s;\n' %(Const, Pcd.DatumType, PcdVariableName, PcdValueName)) + AutoGenH.Append('extern volatile %s %s %s%s;\n' % (Const, Pcd.DatumType, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' % (GetModeName, Type, PcdVariableName)) + else: + AutoGenH.Append('#define %s %s\n' %(PcdValueName, Value)) + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s %s = %s;\n' %(Const, Pcd.DatumType, PcdVariableName, PcdValueName)) + AutoGenH.Append('extern %s %s %s%s;\n' % (Const, Pcd.DatumType, PcdVariableName, Array)) + AutoGenH.Append('#define %s %s%s\n' % (GetModeName, Type, PcdVariableName)) + + if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE: + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPatchPcdSetPtr(_gPcd_BinaryPatch_%s, (UINTN)_PCD_PATCHABLE_%s_SIZE, (SizeOfBuffer), (Buffer))\n' % (SetModeName, Pcd.TokenCName, Pcd.TokenCName)) + else: + AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName)) + else: + AutoGenH.Append('//#define %s ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName) + +## Create code for library module PCDs +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# @param Pcd The PCD object +# +def CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd): + PcdTokenNumber = Info.PlatformInfo.PcdTokenNumber + TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName + TokenCName = Pcd.TokenCName + PcdTokenName = '_PCD_TOKEN_' + TokenCName + # + # Write PCDs + # + if Pcd.Type in gDynamicExPcd: + TokenNumber = int(Pcd.TokenValue, 0) + else: + if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in PcdTokenNumber: + # If one of the Source built modules listed in the DSC is not listed in FDF modules, + # and the INF lists a PCD can only use the PcdsDynamic access method (it is only + # listed in the DEC file that declares the PCD as PcdsDynamic), then build tool will + # report warning message notify the PI that they are attempting to build a module + # that must be included in a flash image in order to be functional. These Dynamic PCD + # will not be added into the Database unless it is used by other modules that are + # included in the FDF file. + # In this case, just assign an invalid token number to make it pass build. + if Pcd.Type in PCD_DYNAMIC_TYPE_LIST: + TokenNumber = 0 + else: + EdkLogger.error("build", AUTOGEN_ERROR, + "No generated token number for %s.%s\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + else: + TokenNumber = PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] + + if Pcd.Type not in gItemTypeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown PCD type [%s] of PCD %s.%s" % (Pcd.Type, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + if Pcd.DatumType not in gDatumSizeStringDatabase: + EdkLogger.error("build", AUTOGEN_ERROR, + "Unknown datum type [%s] of PCD %s.%s" % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName), + ExtraData="[%s]" % str(Info)) + + DatumType = Pcd.DatumType + DatumSize = gDatumSizeStringDatabaseH[DatumType] + DatumSizeLib= gDatumSizeStringDatabaseLib[DatumType] + GetModeName = '_PCD_GET_MODE_' + DatumSize + '_' + TokenCName + SetModeName = '_PCD_SET_MODE_' + DatumSize + '_' + TokenCName + + Type = '' + Array = '' + if Pcd.DatumType == 'VOID*': + Type = '(VOID *)' + Array = '[]' + PcdItemType = Pcd.Type + PcdExCNameList = [] + if PcdItemType in gDynamicExPcd: + PcdExTokenName = '_PCD_TOKEN_' + TokenSpaceGuidCName + '_' + Pcd.TokenCName + AutoGenH.Append('\n#define %s %dU\n' % (PcdExTokenName, TokenNumber)) + + if Info.IsLibrary: + PcdList = Info.LibraryPcdList + else: + PcdList = Info.ModulePcdList + for PcdModule in PcdList: + if PcdModule.Type in gDynamicExPcd: + PcdExCNameList.append(PcdModule.TokenCName) + # Be compatible with the current code which using PcdGet/Set for DynamicEx Pcd. + # If only PcdGet/Set used in all Pcds with different CName, it should succeed to build. + # If PcdGet/Set used in the Pcds with different Guids but same CName, it should failed to build. + if PcdExCNameList.count(Pcd.TokenCName) > 1: + AutoGenH.Append('// Disabled the macros, as PcdToken and PcdGet/Set are not allowed in the case that more than one DynamicEx Pcds are different Guids but same CName.\n') + AutoGenH.Append('// #define %s %s\n' % (PcdTokenName, PcdExTokenName)) + AutoGenH.Append('// #define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('// #define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('#define %s %s\n' % (PcdTokenName, PcdExTokenName)) + AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + if Pcd.DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName)) + else: + AutoGenH.Append('#define _PCD_TOKEN_%s %dU\n' % (TokenCName, TokenNumber)) + if PcdItemType in gDynamicPcd: + AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName)) + if DatumType == 'VOID*': + AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName)) + else: + AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName)) + if PcdItemType == TAB_PCDS_PATCHABLE_IN_MODULE: + PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[TAB_PCDS_PATCHABLE_IN_MODULE] + '_' + TokenCName + AutoGenH.Append('extern volatile %s _gPcd_BinaryPatch_%s%s;\n' %(DatumType, TokenCName, Array) ) + AutoGenH.Append('#define %s %s_gPcd_BinaryPatch_%s\n' %(GetModeName, Type, TokenCName)) + AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName)) + if PcdItemType == TAB_PCDS_FIXED_AT_BUILD or PcdItemType == TAB_PCDS_FEATURE_FLAG: + key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName)) + + AutoGenH.Append('extern const %s _gPcd_FixedAtBuild_%s%s;\n' %(DatumType, TokenCName, Array)) + AutoGenH.Append('#define %s %s_gPcd_FixedAtBuild_%s\n' %(GetModeName, Type, TokenCName)) + AutoGenH.Append('//#define %s ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName) + + if PcdItemType == TAB_PCDS_FIXED_AT_BUILD and key in Info.ConstPcd: + AutoGenH.Append('#define _PCD_VALUE_%s %s\n' %(TokenCName, Pcd.DefaultValue)) + + + +## Create code for library constructor +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateLibraryConstructorCode(Info, AutoGenC, AutoGenH): + # + # Library Constructors + # + ConstructorPrototypeString = TemplateString() + ConstructorCallingString = TemplateString() + if Info.IsLibrary: + DependentLibraryList = [Info.Module] + else: + DependentLibraryList = Info.DependentLibraryList + for Lib in DependentLibraryList: + if len(Lib.ConstructorList) <= 0: + continue + Dict = {'Function':Lib.ConstructorList} + if Lib.ModuleType in ['BASE', 'SEC']: + ConstructorPrototypeString.Append(gLibraryStructorPrototype['BASE'].Replace(Dict)) + ConstructorCallingString.Append(gLibraryStructorCall['BASE'].Replace(Dict)) + elif Lib.ModuleType in ['PEI_CORE','PEIM']: + ConstructorPrototypeString.Append(gLibraryStructorPrototype['PEI'].Replace(Dict)) + ConstructorCallingString.Append(gLibraryStructorCall['PEI'].Replace(Dict)) + elif Lib.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION','SMM_CORE']: + ConstructorPrototypeString.Append(gLibraryStructorPrototype['DXE'].Replace(Dict)) + ConstructorCallingString.Append(gLibraryStructorCall['DXE'].Replace(Dict)) + + if str(ConstructorPrototypeString) == '': + ConstructorPrototypeList = [] + else: + ConstructorPrototypeList = [str(ConstructorPrototypeString)] + if str(ConstructorCallingString) == '': + ConstructorCallingList = [] + else: + ConstructorCallingList = [str(ConstructorCallingString)] + + Dict = { + 'Type' : 'Constructor', + 'FunctionPrototype' : ConstructorPrototypeList, + 'FunctionCall' : ConstructorCallingList + } + if Info.IsLibrary: + AutoGenH.Append("${BEGIN}${FunctionPrototype}${END}", Dict) + else: + if Info.ModuleType in ['BASE', 'SEC']: + AutoGenC.Append(gLibraryString['BASE'].Replace(Dict)) + elif Info.ModuleType in ['PEI_CORE','PEIM']: + AutoGenC.Append(gLibraryString['PEI'].Replace(Dict)) + elif Info.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION','SMM_CORE']: + AutoGenC.Append(gLibraryString['DXE'].Replace(Dict)) + +## Create code for library destructor +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateLibraryDestructorCode(Info, AutoGenC, AutoGenH): + # + # Library Destructors + # + DestructorPrototypeString = TemplateString() + DestructorCallingString = TemplateString() + if Info.IsLibrary: + DependentLibraryList = [Info.Module] + else: + DependentLibraryList = Info.DependentLibraryList + for Index in range(len(DependentLibraryList)-1, -1, -1): + Lib = DependentLibraryList[Index] + if len(Lib.DestructorList) <= 0: + continue + Dict = {'Function':Lib.DestructorList} + if Lib.ModuleType in ['BASE', 'SEC']: + DestructorPrototypeString.Append(gLibraryStructorPrototype['BASE'].Replace(Dict)) + DestructorCallingString.Append(gLibraryStructorCall['BASE'].Replace(Dict)) + elif Lib.ModuleType in ['PEI_CORE','PEIM']: + DestructorPrototypeString.Append(gLibraryStructorPrototype['PEI'].Replace(Dict)) + DestructorCallingString.Append(gLibraryStructorCall['PEI'].Replace(Dict)) + elif Lib.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION', 'SMM_CORE']: + DestructorPrototypeString.Append(gLibraryStructorPrototype['DXE'].Replace(Dict)) + DestructorCallingString.Append(gLibraryStructorCall['DXE'].Replace(Dict)) + + if str(DestructorPrototypeString) == '': + DestructorPrototypeList = [] + else: + DestructorPrototypeList = [str(DestructorPrototypeString)] + if str(DestructorCallingString) == '': + DestructorCallingList = [] + else: + DestructorCallingList = [str(DestructorCallingString)] + + Dict = { + 'Type' : 'Destructor', + 'FunctionPrototype' : DestructorPrototypeList, + 'FunctionCall' : DestructorCallingList + } + if Info.IsLibrary: + AutoGenH.Append("${BEGIN}${FunctionPrototype}${END}", Dict) + else: + if Info.ModuleType in ['BASE', 'SEC']: + AutoGenC.Append(gLibraryString['BASE'].Replace(Dict)) + elif Info.ModuleType in ['PEI_CORE','PEIM']: + AutoGenC.Append(gLibraryString['PEI'].Replace(Dict)) + elif Info.ModuleType in ['DXE_CORE','DXE_DRIVER','DXE_SMM_DRIVER','DXE_RUNTIME_DRIVER', + 'DXE_SAL_DRIVER','UEFI_DRIVER','UEFI_APPLICATION','SMM_CORE']: + AutoGenC.Append(gLibraryString['DXE'].Replace(Dict)) + + +## Create code for ModuleEntryPoint +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateModuleEntryPointCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary or Info.ModuleType in ['USER_DEFINED', 'SEC']: + return + # + # Module Entry Points + # + NumEntryPoints = len(Info.Module.ModuleEntryPointList) + if 'PI_SPECIFICATION_VERSION' in Info.Module.Specification: + PiSpecVersion = Info.Module.Specification['PI_SPECIFICATION_VERSION'] + else: + PiSpecVersion = '0x00000000' + if 'UEFI_SPECIFICATION_VERSION' in Info.Module.Specification: + UefiSpecVersion = Info.Module.Specification['UEFI_SPECIFICATION_VERSION'] + else: + UefiSpecVersion = '0x00000000' + Dict = { + 'Function' : Info.Module.ModuleEntryPointList, + 'PiSpecVersion' : PiSpecVersion + 'U', + 'UefiSpecVersion': UefiSpecVersion + 'U' + } + + if Info.ModuleType in ['PEI_CORE', 'DXE_CORE', 'SMM_CORE']: + if Info.SourceFileList <> None and Info.SourceFileList <> []: + if NumEntryPoints != 1: + EdkLogger.error( + "build", + AUTOGEN_ERROR, + '%s must have exactly one entry point' % Info.ModuleType, + File=str(Info), + ExtraData= ", ".join(Info.Module.ModuleEntryPointList) + ) + if Info.ModuleType == 'PEI_CORE': + AutoGenC.Append(gPeiCoreEntryPointString.Replace(Dict)) + AutoGenH.Append(gPeiCoreEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'DXE_CORE': + AutoGenC.Append(gDxeCoreEntryPointString.Replace(Dict)) + AutoGenH.Append(gDxeCoreEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'SMM_CORE': + AutoGenC.Append(gSmmCoreEntryPointString.Replace(Dict)) + AutoGenH.Append(gSmmCoreEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'PEIM': + if NumEntryPoints < 2: + AutoGenC.Append(gPeimEntryPointString[NumEntryPoints].Replace(Dict)) + else: + AutoGenC.Append(gPeimEntryPointString[2].Replace(Dict)) + AutoGenH.Append(gPeimEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType in ['DXE_RUNTIME_DRIVER','DXE_DRIVER','DXE_SAL_DRIVER','UEFI_DRIVER']: + if NumEntryPoints < 2: + AutoGenC.Append(gUefiDriverEntryPointString[NumEntryPoints].Replace(Dict)) + else: + AutoGenC.Append(gUefiDriverEntryPointString[2].Replace(Dict)) + AutoGenH.Append(gUefiDriverEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'DXE_SMM_DRIVER': + if NumEntryPoints == 0: + AutoGenC.Append(gDxeSmmEntryPointString[0].Replace(Dict)) + else: + AutoGenC.Append(gDxeSmmEntryPointString[1].Replace(Dict)) + AutoGenH.Append(gDxeSmmEntryPointPrototype.Replace(Dict)) + elif Info.ModuleType == 'UEFI_APPLICATION': + if NumEntryPoints < 2: + AutoGenC.Append(gUefiApplicationEntryPointString[NumEntryPoints].Replace(Dict)) + else: + AutoGenC.Append(gUefiApplicationEntryPointString[2].Replace(Dict)) + AutoGenH.Append(gUefiApplicationEntryPointPrototype.Replace(Dict)) + +## Create code for ModuleUnloadImage +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateModuleUnloadImageCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary or Info.ModuleType in ['USER_DEFINED', 'SEC']: + return + # + # Unload Image Handlers + # + NumUnloadImage = len(Info.Module.ModuleUnloadImageList) + Dict = {'Count':str(NumUnloadImage) + 'U', 'Function':Info.Module.ModuleUnloadImageList} + if NumUnloadImage < 2: + AutoGenC.Append(gUefiUnloadImageString[NumUnloadImage].Replace(Dict)) + else: + AutoGenC.Append(gUefiUnloadImageString[2].Replace(Dict)) + AutoGenH.Append(gUefiUnloadImagePrototype.Replace(Dict)) + +## Create code for GUID +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateGuidDefinitionCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary: + return + + if Info.ModuleType in ["USER_DEFINED", "BASE"]: + GuidType = "GUID" + else: + GuidType = "EFI_GUID" + + if Info.GuidList: + AutoGenC.Append("\n// Guids\n") + # + # GUIDs + # + for Key in Info.GuidList: + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.GuidList[Key])) + +## Create code for protocol +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateProtocolDefinitionCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary: + return + + if Info.ModuleType in ["USER_DEFINED", "BASE"]: + GuidType = "GUID" + else: + GuidType = "EFI_GUID" + + if Info.ProtocolList: + AutoGenC.Append("\n// Protocols\n") + # + # Protocol GUIDs + # + for Key in Info.ProtocolList: + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.ProtocolList[Key])) + +## Create code for PPI +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreatePpiDefinitionCode(Info, AutoGenC, AutoGenH): + if Info.IsLibrary: + return + + if Info.ModuleType in ["USER_DEFINED", "BASE"]: + GuidType = "GUID" + else: + GuidType = "EFI_GUID" + + if Info.PpiList: + AutoGenC.Append("\n// PPIs\n") + # + # PPI GUIDs + # + for Key in Info.PpiList: + AutoGenC.Append('GLOBAL_REMOVE_IF_UNREFERENCED %s %s = %s;\n' % (GuidType, Key, Info.PpiList[Key])) + +## Create code for PCD +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreatePcdCode(Info, AutoGenC, AutoGenH): + + # Collect Token Space GUIDs used by DynamicEc PCDs + TokenSpaceList = [] + for Pcd in Info.ModulePcdList: + if Pcd.Type in gDynamicExPcd and Pcd.TokenSpaceGuidCName not in TokenSpaceList: + TokenSpaceList += [Pcd.TokenSpaceGuidCName] + + # Add extern declarations to AutoGen.h if one or more Token Space GUIDs were found + if TokenSpaceList <> []: + AutoGenH.Append("\n// Definition of PCD Token Space GUIDs used in this module\n\n") + if Info.ModuleType in ["USER_DEFINED", "BASE"]: + GuidType = "GUID" + else: + GuidType = "EFI_GUID" + for Item in TokenSpaceList: + AutoGenH.Append('extern %s %s;\n' % (GuidType, Item)) + + if Info.IsLibrary: + if Info.ModulePcdList: + AutoGenH.Append("\n// PCD definitions\n") + for Pcd in Info.ModulePcdList: + CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd) + DynExPcdTokenNumberMapping (Info, AutoGenH) + else: + if Info.ModulePcdList: + AutoGenH.Append("\n// Definition of PCDs used in this module\n") + AutoGenC.Append("\n// Definition of PCDs used in this module\n") + for Pcd in Info.ModulePcdList: + CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd) + DynExPcdTokenNumberMapping (Info, AutoGenH) + if Info.LibraryPcdList: + AutoGenH.Append("\n// Definition of PCDs used in libraries is in AutoGen.c\n") + AutoGenC.Append("\n// Definition of PCDs used in libraries\n") + for Pcd in Info.LibraryPcdList: + CreateModulePcdCode(Info, AutoGenC, AutoGenC, Pcd) + CreatePcdDatabaseCode(Info, AutoGenC, AutoGenH) + +## Create code for unicode string definition +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# @param UniGenCFlag UniString is generated into AutoGen C file when it is set to True +# @param UniGenBinBuffer Buffer to store uni string package data +# +def CreateUnicodeStringCode(Info, AutoGenC, AutoGenH, UniGenCFlag, UniGenBinBuffer): + WorkingDir = os.getcwd() + os.chdir(Info.WorkspaceDir) + + IncList = [Info.MetaFile.Dir] + # Get all files under [Sources] section in inf file for EDK-II module + EDK2Module = True + SrcList = [F for F in Info.SourceFileList] + if Info.AutoGenVersion < 0x00010005: + EDK2Module = False + # Get all files under the module directory for EDK-I module + Cwd = os.getcwd() + os.chdir(Info.MetaFile.Dir) + for Root, Dirs, Files in os.walk("."): + if 'CVS' in Dirs: + Dirs.remove('CVS') + if '.svn' in Dirs: + Dirs.remove('.svn') + for File in Files: + File = PathClass(os.path.join(Root, File), Info.MetaFile.Dir) + if File in SrcList: + continue + SrcList.append(File) + os.chdir(Cwd) + + if 'BUILD' in Info.BuildOption and Info.BuildOption['BUILD']['FLAGS'].find('-c') > -1: + CompatibleMode = True + else: + CompatibleMode = False + + # + # -s is a temporary option dedicated for building .UNI files with ISO 639-2 language codes of EDK Shell in EDK2 + # + if 'BUILD' in Info.BuildOption and Info.BuildOption['BUILD']['FLAGS'].find('-s') > -1: + if CompatibleMode: + EdkLogger.error("build", AUTOGEN_ERROR, + "-c and -s build options should be used exclusively", + ExtraData="[%s]" % str(Info)) + ShellMode = True + else: + ShellMode = False + + #RFC4646 is only for EDKII modules and ISO639-2 for EDK modules + if EDK2Module: + FilterInfo = [EDK2Module] + [Info.PlatformInfo.Platform.RFCLanguages] + else: + FilterInfo = [EDK2Module] + [Info.PlatformInfo.Platform.ISOLanguages] + Header, Code = GetStringFiles(Info.UnicodeFileList, SrcList, IncList, Info.IncludePathList, ['.uni', '.inf'], Info.Name, CompatibleMode, ShellMode, UniGenCFlag, UniGenBinBuffer, FilterInfo) + if CompatibleMode or UniGenCFlag: + AutoGenC.Append("\n//\n//Unicode String Pack Definition\n//\n") + AutoGenC.Append(Code) + AutoGenC.Append("\n") + AutoGenH.Append("\n//\n//Unicode String ID\n//\n") + AutoGenH.Append(Header) + if CompatibleMode or UniGenCFlag: + AutoGenH.Append("\n#define STRING_ARRAY_NAME %sStrings\n" % Info.Name) + os.chdir(WorkingDir) + +## Create common code +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateHeaderCode(Info, AutoGenC, AutoGenH): + # file header + AutoGenH.Append(gAutoGenHeaderString.Replace({'FileName':'AutoGen.h'})) + # header file Prologue + AutoGenH.Append(gAutoGenHPrologueString.Replace({'File':'AUTOGENH','Guid':Info.Guid.replace('-','_')})) + AutoGenH.Append(gAutoGenHCppPrologueString) + if Info.AutoGenVersion >= 0x00010005: + # header files includes + AutoGenH.Append("#include <%s>\n" % gBasicHeaderFile) + if Info.ModuleType in gModuleTypeHeaderFile \ + and gModuleTypeHeaderFile[Info.ModuleType][0] != gBasicHeaderFile: + AutoGenH.Append("#include <%s>\n" % gModuleTypeHeaderFile[Info.ModuleType][0]) + # + # if either PcdLib in [LibraryClasses] sections or there exist Pcd section, add PcdLib.h + # As if modules only uses FixedPcd, then PcdLib is not needed in [LibraryClasses] section. + # + if 'PcdLib' in Info.Module.LibraryClasses or Info.Module.Pcds: + AutoGenH.Append("#include \n") + + AutoGenH.Append('\nextern GUID gEfiCallerIdGuid;') + AutoGenH.Append('\nextern CHAR8 *gEfiCallerBaseName;\n\n') + + if Info.IsLibrary: + return + + AutoGenH.Append("#define EFI_CALLER_ID_GUID \\\n %s\n" % GuidStringToGuidStructureString(Info.Guid)) + + if Info.IsLibrary: + return + # C file header + AutoGenC.Append(gAutoGenHeaderString.Replace({'FileName':'AutoGen.c'})) + if Info.AutoGenVersion >= 0x00010005: + # C file header files includes + if Info.ModuleType in gModuleTypeHeaderFile: + for Inc in gModuleTypeHeaderFile[Info.ModuleType]: + AutoGenC.Append("#include <%s>\n" % Inc) + else: + AutoGenC.Append("#include <%s>\n" % gBasicHeaderFile) + + # + # Publish the CallerId Guid + # + AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED GUID gEfiCallerIdGuid = %s;\n' % GuidStringToGuidStructureString(Info.Guid)) + AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gEfiCallerBaseName = "%s";\n' % Info.Name) + +## Create common code for header file +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# +def CreateFooterCode(Info, AutoGenC, AutoGenH): + AutoGenH.Append(gAutoGenHEpilogueString) + +## Create code for a module +# +# @param Info The ModuleAutoGen object +# @param AutoGenC The TemplateString object for C code +# @param AutoGenH The TemplateString object for header file +# @param UniGenCFlag UniString is generated into AutoGen C file when it is set to True +# @param UniGenBinBuffer Buffer to store uni string package data +# +def CreateCode(Info, AutoGenC, AutoGenH, StringH, UniGenCFlag, UniGenBinBuffer): + CreateHeaderCode(Info, AutoGenC, AutoGenH) + + if Info.AutoGenVersion >= 0x00010005: + CreateGuidDefinitionCode(Info, AutoGenC, AutoGenH) + CreateProtocolDefinitionCode(Info, AutoGenC, AutoGenH) + CreatePpiDefinitionCode(Info, AutoGenC, AutoGenH) + CreatePcdCode(Info, AutoGenC, AutoGenH) + CreateLibraryConstructorCode(Info, AutoGenC, AutoGenH) + CreateLibraryDestructorCode(Info, AutoGenC, AutoGenH) + CreateModuleEntryPointCode(Info, AutoGenC, AutoGenH) + CreateModuleUnloadImageCode(Info, AutoGenC, AutoGenH) + + if Info.UnicodeFileList: + FileName = "%sStrDefs.h" % Info.Name + StringH.Append(gAutoGenHeaderString.Replace({'FileName':FileName})) + StringH.Append(gAutoGenHPrologueString.Replace({'File':'STRDEFS', 'Guid':Info.Guid.replace('-','_')})) + CreateUnicodeStringCode(Info, AutoGenC, StringH, UniGenCFlag, UniGenBinBuffer) + StringH.Append("\n#endif\n") + AutoGenH.Append('#include "%s"\n' % FileName) + + CreateFooterCode(Info, AutoGenC, AutoGenH) + + # no generation of AutoGen.c for Edk modules without unicode file + if Info.AutoGenVersion < 0x00010005 and len(Info.UnicodeFileList) == 0: + AutoGenC.String = '' + +## Create the code file +# +# @param FilePath The path of code file +# @param Content The content of code file +# @param IsBinaryFile The flag indicating if the file is binary file or not +# +# @retval True If file content is changed or file doesn't exist +# @retval False If the file exists and the content is not changed +# +def Generate(FilePath, Content, IsBinaryFile): + return SaveFileOnChange(FilePath, Content, IsBinaryFile) + diff --git a/BaseTools/Source/Python/AutoGen/GenMake.py b/BaseTools/Source/Python/AutoGen/GenMake.py index b2ebff324d..00d0af0cb7 100644 --- a/BaseTools/Source/Python/AutoGen/GenMake.py +++ b/BaseTools/Source/Python/AutoGen/GenMake.py @@ -1,1411 +1,1411 @@ -## @file -# Create makefile for MS nmake and GNU make -# -# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
-# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# - -## Import Modules -# -import os -import sys -import string -import re -import os.path as path - -from Common.BuildToolError import * -from Common.Misc import * -from Common.String import * -from BuildEngine import * -import Common.GlobalData as GlobalData - -## Regular expression for finding header file inclusions -gIncludePattern = re.compile(r"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE|re.UNICODE|re.IGNORECASE) - -## Regular expression for matching macro used in header file inclusion -gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE) - -gIsFileMap = {} - -## pattern for include style in Edk.x code -gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h" -gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h" -gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h" -gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h" -gIncludeMacroConversion = { - "EFI_PROTOCOL_DEFINITION" : gProtocolDefinition, - "EFI_GUID_DEFINITION" : gGuidDefinition, - "EFI_ARCH_PROTOCOL_DEFINITION" : gArchProtocolDefinition, - "EFI_PROTOCOL_PRODUCER" : gProtocolDefinition, - "EFI_PROTOCOL_CONSUMER" : gProtocolDefinition, - "EFI_PROTOCOL_DEPENDENCY" : gProtocolDefinition, - "EFI_ARCH_PROTOCOL_PRODUCER" : gArchProtocolDefinition, - "EFI_ARCH_PROTOCOL_CONSUMER" : gArchProtocolDefinition, - "EFI_ARCH_PROTOCOL_DEPENDENCY" : gArchProtocolDefinition, - "EFI_PPI_DEFINITION" : gPpiDefinition, - "EFI_PPI_PRODUCER" : gPpiDefinition, - "EFI_PPI_CONSUMER" : gPpiDefinition, - "EFI_PPI_DEPENDENCY" : gPpiDefinition, -} - -## default makefile type -gMakeType = "" -if sys.platform == "win32": - gMakeType = "nmake" -else: - gMakeType = "gmake" - - -## BuildFile class -# -# This base class encapsules build file and its generation. It uses template to generate -# the content of build file. The content of build file will be got from AutoGen objects. -# -class BuildFile(object): - ## template used to generate the build file (i.e. makefile if using make) - _TEMPLATE_ = TemplateString('') - - _DEFAULT_FILE_NAME_ = "Makefile" - - ## default file name for each type of build file - _FILE_NAME_ = { - "nmake" : "Makefile", - "gmake" : "GNUmakefile" - } - - ## Fixed header string for makefile - _MAKEFILE_HEADER = '''# -# DO NOT EDIT -# This file is auto-generated by build utility -# -# Module Name: -# -# %s -# -# Abstract: -# -# Auto-generated makefile for building modules, libraries or platform -# - ''' - - ## Header string for each type of build file - _FILE_HEADER_ = { - "nmake" : _MAKEFILE_HEADER % _FILE_NAME_["nmake"], - "gmake" : _MAKEFILE_HEADER % _FILE_NAME_["gmake"] - } - - ## shell commands which can be used in build file in the form of macro - # $(CP) copy file command - # $(MV) move file command - # $(RM) remove file command - # $(MD) create dir command - # $(RD) remove dir command - # - _SHELL_CMD_ = { - "nmake" : { - "CP" : "copy /y", - "MV" : "move /y", - "RM" : "del /f /q", - "MD" : "mkdir", - "RD" : "rmdir /s /q", - }, - - "gmake" : { - "CP" : "cp -f", - "MV" : "mv -f", - "RM" : "rm -f", - "MD" : "mkdir -p", - "RD" : "rm -r -f", - } - } - - ## directory separator - _SEP_ = { - "nmake" : "\\", - "gmake" : "/" - } - - ## directory creation template - _MD_TEMPLATE_ = { - "nmake" : 'if not exist %(dir)s $(MD) %(dir)s', - "gmake" : "$(MD) %(dir)s" - } - - ## directory removal template - _RD_TEMPLATE_ = { - "nmake" : 'if exist %(dir)s $(RD) %(dir)s', - "gmake" : "$(RD) %(dir)s" - } - - _CD_TEMPLATE_ = { - "nmake" : 'if exist %(dir)s cd %(dir)s', - "gmake" : "test -e %(dir)s && cd %(dir)s" - } - - _MAKE_TEMPLATE_ = { - "nmake" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s', - "gmake" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s' - } - - _INCLUDE_CMD_ = { - "nmake" : '!INCLUDE', - "gmake" : "include" - } - - _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"} - - ## Constructor of BuildFile - # - # @param AutoGenObject Object of AutoGen class - # - def __init__(self, AutoGenObject): - self._AutoGenObject = AutoGenObject - self._FileType = gMakeType - - ## Create build file - # - # @param FileType Type of build file. Only nmake and gmake are supported now. - # - # @retval TRUE The build file is created or re-created successfully - # @retval FALSE The build file exists and is the same as the one to be generated - # - def Generate(self, FileType=gMakeType): - if FileType not in self._FILE_NAME_: - EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType, - ExtraData="[%s]" % str(self._AutoGenObject)) - self._FileType = FileType - FileContent = self._TEMPLATE_.Replace(self._TemplateDict) - FileName = self._FILE_NAME_[FileType] - return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False) - - ## Return a list of directory creation command string - # - # @param DirList The list of directory to be created - # - # @retval list The directory creation command list - # - def GetCreateDirectoryCommand(self, DirList): - return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] - - ## Return a list of directory removal command string - # - # @param DirList The list of directory to be removed - # - # @retval list The directory removal command list - # - def GetRemoveDirectoryCommand(self, DirList): - return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] - - def PlaceMacro(self, Path, MacroDefinitions={}): - if Path.startswith("$("): - return Path - else: - PathLength = len(Path) - for MacroName in MacroDefinitions: - MacroValue = MacroDefinitions[MacroName] - MacroValueLength = len(MacroValue) - if MacroValueLength <= PathLength and Path.startswith(MacroValue): - Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:]) - break - return Path - -## ModuleMakefile class -# -# This class encapsules makefie and its generation for module. It uses template to generate -# the content of makefile. The content of makefile will be got from ModuleAutoGen object. -# -class ModuleMakefile(BuildFile): - ## template used to generate the makefile for module - _TEMPLATE_ = TemplateString('''\ -${makefile_header} - -# -# Platform Macro Definition -# -PLATFORM_NAME = ${platform_name} -PLATFORM_GUID = ${platform_guid} -PLATFORM_VERSION = ${platform_version} -PLATFORM_RELATIVE_DIR = ${platform_relative_directory} -PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} -PLATFORM_OUTPUT_DIR = ${platform_output_directory} - -# -# Module Macro Definition -# -MODULE_NAME = ${module_name} -MODULE_GUID = ${module_guid} -MODULE_VERSION = ${module_version} -MODULE_TYPE = ${module_type} -MODULE_FILE = ${module_file} -MODULE_FILE_BASE_NAME = ${module_file_base_name} -BASE_NAME = $(MODULE_NAME) -MODULE_RELATIVE_DIR = ${module_relative_directory} -MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} - -MODULE_ENTRY_POINT = ${module_entry_point} -ARCH_ENTRY_POINT = ${arch_entry_point} -IMAGE_ENTRY_POINT = ${image_entry_point} - -${BEGIN}${module_extra_defines} -${END} -# -# Build Configuration Macro Definition -# -ARCH = ${architecture} -TOOLCHAIN = ${toolchain_tag} -TOOLCHAIN_TAG = ${toolchain_tag} -TARGET = ${build_target} - -# -# Build Directory Macro Definition -# -# PLATFORM_BUILD_DIR = ${platform_build_directory} -BUILD_DIR = ${platform_build_directory} -BIN_DIR = $(BUILD_DIR)${separator}${architecture} -LIB_DIR = $(BIN_DIR) -MODULE_BUILD_DIR = ${module_build_directory} -OUTPUT_DIR = ${module_output_directory} -DEBUG_DIR = ${module_debug_directory} -DEST_DIR_OUTPUT = $(OUTPUT_DIR) -DEST_DIR_DEBUG = $(DEBUG_DIR) - -# -# Shell Command Macro -# -${BEGIN}${shell_command_code} = ${shell_command} -${END} - -# -# Tools definitions specific to this module -# -${BEGIN}${module_tool_definitions} -${END} -MAKE_FILE = ${makefile_path} - -# -# Build Macro -# -${BEGIN}${file_macro} -${END} - -COMMON_DEPS = ${BEGIN}${common_dependency_file} \\ - ${END} - -# -# Overridable Target Macro Definitions -# -FORCE_REBUILD = force_build -INIT_TARGET = init -PCH_TARGET = -BC_TARGET = ${BEGIN}${backward_compatible_target} ${END} -CODA_TARGET = ${BEGIN}${remaining_build_target} \\ - ${END} - -# -# Default target, which will build dependent libraries in addition to source files -# - -all: mbuild - - -# -# Target used when called from platform makefile, which will bypass the build of dependent libraries -# - -pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) - -# -# ModuleTarget -# - -mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET) - -# -# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets -# - -tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) - -# -# Phony target which is used to force executing commands for a target -# -force_build: -\t-@ - -# -# Target to update the FD -# - -fds: mbuild gen_fds - -# -# Initialization target: print build information and create necessary directories -# -init: info dirs - -info: -\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] - -dirs: -${BEGIN}\t-@${create_directory_command}\n${END} - -strdefs: -\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h - -# -# GenLibsTarget -# -gen_libs: -\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name} -\t${END}@cd $(MODULE_BUILD_DIR) - -# -# Build Flash Device Image -# -gen_fds: -\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds -\t@cd $(MODULE_BUILD_DIR) - -# -# Individual Object Build Targets -# -${BEGIN}${file_build_target} -${END} - -# -# clean all intermediate files -# -clean: -\t${BEGIN}${clean_command} -\t${END} - -# -# clean all generated files -# -cleanall: -${BEGIN}\t${cleanall_command} -${END}\t$(RM) *.pdb *.idb > NUL 2>&1 -\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi - -# -# clean all dependent libraries built -# -cleanlib: -\t${BEGIN}-@${library_build_command} cleanall -\t${END}@cd $(MODULE_BUILD_DIR)\n\n''') - - _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n") - _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n") - - ## Constructor of ModuleMakefile - # - # @param ModuleAutoGen Object of ModuleAutoGen class - # - def __init__(self, ModuleAutoGen): - BuildFile.__init__(self, ModuleAutoGen) - self.PlatformInfo = self._AutoGenObject.PlatformInfo - - self.ResultFileList = [] - self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] - - self.SourceFileDatabase = {} # {file type : file path} - self.DestFileDatabase = {} # {file type : file path} - self.FileBuildTargetList = [] # [(src, target string)] - self.BuildTargetList = [] # [target string] - self.PendingBuildTargetList = [] # [FileBuildRule objects] - self.CommonFileDependency = [] - self.FileListMacros = {} - self.ListFileMacros = {} - - self.FileCache = {} - self.FileDependency = [] - self.LibraryBuildCommandList = [] - self.LibraryFileList = [] - self.LibraryMakefileList = [] - self.LibraryBuildDirectoryList = [] - self.SystemLibraryList = [] - self.Macros = sdict() - self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"] - self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"] - self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"] - self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"] - self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"] - self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"] - - # Compose a dict object containing information used to do replacement in template - def _CreateTemplateDict(self): - if self._FileType not in self._SEP_: - EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType, - ExtraData="[%s]" % str(self._AutoGenObject)) - Separator = self._SEP_[self._FileType] - - # break build if no source files and binary files are found - if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0: - EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]" - % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), - ExtraData="[%s]" % str(self._AutoGenObject)) - - # convert dependent libraries to build command - self.ProcessDependentLibrary() - if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0: - ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0] - else: - ModuleEntryPoint = "_ModuleEntryPoint" - - # Intel EBC compiler enforces EfiMain - if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC": - ArchEntryPoint = "EfiMain" - else: - ArchEntryPoint = ModuleEntryPoint - - if self._AutoGenObject.Arch == "EBC": - # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules - ImageEntryPoint = "EfiStart" - elif self._AutoGenObject.AutoGenVersion < 0x00010005: - # Edk modules use entry point specified in INF file - ImageEntryPoint = ModuleEntryPoint - else: - # EdkII modules always use "_ModuleEntryPoint" as entry point - ImageEntryPoint = "_ModuleEntryPoint" - - # tools definitions - ToolsDef = [] - IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily] - for Tool in self._AutoGenObject.BuildOption: - for Attr in self._AutoGenObject.BuildOption[Tool]: - Value = self._AutoGenObject.BuildOption[Tool][Attr] - if Attr == "FAMILY": - continue - elif Attr == "PATH": - ToolsDef.append("%s = %s" % (Tool, Value)) - else: - # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. - if Tool == "MAKE": - continue - # Remove duplicated include path, if any - if Attr == "FLAGS": - Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList) - ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value)) - ToolsDef.append("") - - # convert source files and binary files to build targets - self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList] - if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0: - EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build", - ExtraData="[%s]" % str(self._AutoGenObject)) - - self.ProcessBuildTargetList() - - # Generate macros used to represent input files - FileMacroList = [] # macro name = file list - for FileListMacro in self.FileListMacros: - FileMacro = self._FILE_MACRO_TEMPLATE.Replace( - { - "macro_name" : FileListMacro, - "source_file" : self.FileListMacros[FileListMacro] - } - ) - FileMacroList.append(FileMacro) - - # INC_LIST is special - FileMacro = "" - IncludePathList = [] - for P in self._AutoGenObject.IncludePathList: - IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros)) - if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros: - self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P) - FileMacro += self._FILE_MACRO_TEMPLATE.Replace( - { - "macro_name" : "INC", - "source_file" : IncludePathList - } - ) - FileMacroList.append(FileMacro) - - # Generate macros used to represent files containing list of input files - for ListFileMacro in self.ListFileMacros: - ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5]) - FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName)) - SaveFileOnChange( - ListFileName, - "\n".join(self.ListFileMacros[ListFileMacro]), - False - ) - - # Edk modules need StrDefs.h for string ID - #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0: - # BcTargetList = ['strdefs'] - #else: - # BcTargetList = [] - BcTargetList = [] - - MakefileName = self._FILE_NAME_[self._FileType] - LibraryMakeCommandList = [] - for D in self.LibraryBuildDirectoryList: - Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)} - LibraryMakeCommandList.append(Command) - - MakefileTemplateDict = { - "makefile_header" : self._FILE_HEADER_[self._FileType], - "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), - "makefile_name" : MakefileName, - "platform_name" : self.PlatformInfo.Name, - "platform_guid" : self.PlatformInfo.Guid, - "platform_version" : self.PlatformInfo.Version, - "platform_relative_directory": self.PlatformInfo.SourceDir, - "platform_output_directory" : self.PlatformInfo.OutputDir, - - "module_name" : self._AutoGenObject.Name, - "module_guid" : self._AutoGenObject.Guid, - "module_version" : self._AutoGenObject.Version, - "module_type" : self._AutoGenObject.ModuleType, - "module_file" : self._AutoGenObject.MetaFile.Name, - "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, - "module_relative_directory" : self._AutoGenObject.SourceDir, - "module_extra_defines" : ["%s = %s" % (k, v) for k,v in self._AutoGenObject.Module.Defines.iteritems()], - - "architecture" : self._AutoGenObject.Arch, - "toolchain_tag" : self._AutoGenObject.ToolChain, - "build_target" : self._AutoGenObject.BuildTarget, - - "platform_build_directory" : self.PlatformInfo.BuildDir, - "module_build_directory" : self._AutoGenObject.BuildDir, - "module_output_directory" : self._AutoGenObject.OutputDir, - "module_debug_directory" : self._AutoGenObject.DebugDir, - - "separator" : Separator, - "module_tool_definitions" : ToolsDef, - - "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), - "shell_command" : self._SHELL_CMD_[self._FileType].values(), - - "module_entry_point" : ModuleEntryPoint, - "image_entry_point" : ImageEntryPoint, - "arch_entry_point" : ArchEntryPoint, - "remaining_build_target" : self.ResultFileList, - "common_dependency_file" : self.CommonFileDependency, - "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), - "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]), - "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]), - "dependent_library_build_directory" : self.LibraryBuildDirectoryList, - "library_build_command" : LibraryMakeCommandList, - "file_macro" : FileMacroList, - "file_build_target" : self.BuildTargetList, - "backward_compatible_target": BcTargetList, - } - - return MakefileTemplateDict - - def ProcessBuildTargetList(self): - # - # Search dependency file list for each source file - # - ForceIncludedFile = [] - for File in self._AutoGenObject.AutoGenFileList: - if File.Ext == '.h': - ForceIncludedFile.append(File) - SourceFileList = [] - for Target in self._AutoGenObject.IntroTargetList: - SourceFileList.extend(Target.Inputs) - - self.FileDependency = self.GetFileDependency( - SourceFileList, - ForceIncludedFile, - self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList - ) - DepSet = None - for File in self.FileDependency: - if not self.FileDependency[File]: - self.FileDependency[File] = ['$(FORCE_REBUILD)'] - continue - # skip non-C files - if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": - continue - elif DepSet == None: - DepSet = set(self.FileDependency[File]) - else: - DepSet &= set(self.FileDependency[File]) - # in case nothing in SourceFileList - if DepSet == None: - DepSet = set() - # - # Extract common files list in the dependency files - # - for File in DepSet: - self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros)) - - for File in self.FileDependency: - # skip non-C files - if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": - continue - NewDepSet = set(self.FileDependency[File]) - NewDepSet -= DepSet - self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet) - - # Convert target description object to target string in makefile - for Type in self._AutoGenObject.Targets: - for T in self._AutoGenObject.Targets[Type]: - # Generate related macros if needed - if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros: - self.FileListMacros[T.FileListMacro] = [] - if T.GenListFile and T.ListFileMacro not in self.ListFileMacros: - self.ListFileMacros[T.ListFileMacro] = [] - if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros: - self.ListFileMacros[T.IncListFileMacro] = [] - - Deps = [] - # Add force-dependencies - for Dep in T.Dependencies: - Deps.append(self.PlaceMacro(str(Dep), self.Macros)) - # Add inclusion-dependencies - if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency: - for F in self.FileDependency[T.Inputs[0]]: - Deps.append(self.PlaceMacro(str(F), self.Macros)) - # Add source-dependencies - for F in T.Inputs: - NewFile = self.PlaceMacro(str(F), self.Macros) - # In order to use file list macro as dependency - if T.GenListFile: - self.ListFileMacros[T.ListFileMacro].append(str(F)) - self.FileListMacros[T.FileListMacro].append(NewFile) - elif T.GenFileListMacro: - self.FileListMacros[T.FileListMacro].append(NewFile) - else: - Deps.append(NewFile) - - # Use file list macro as dependency - if T.GenFileListMacro: - Deps.append("$(%s)" % T.FileListMacro) - - TargetDict = { - "target" : self.PlaceMacro(T.Target.Path, self.Macros), - "cmd" : "\n\t".join(T.Commands), - "deps" : Deps - } - self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict)) - - ## For creating makefile targets for dependent libraries - def ProcessDependentLibrary(self): - for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: - self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros)) - - ## Return a list containing source file's dependencies - # - # @param FileList The list of source files - # @param ForceInculeList The list of files which will be included forcely - # @param SearchPathList The list of search path - # - # @retval dict The mapping between source file path and its dependencies - # - def GetFileDependency(self, FileList, ForceInculeList, SearchPathList): - Dependency = {} - for F in FileList: - Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList) - return Dependency - - ## Find dependencies for one source file - # - # By searching recursively "#include" directive in file, find out all the - # files needed by given source file. The dependecies will be only searched - # in given search path list. - # - # @param File The source file - # @param ForceInculeList The list of files which will be included forcely - # @param SearchPathList The list of search path - # - # @retval list The list of files the given source file depends on - # - def GetDependencyList(self, File, ForceList, SearchPathList): - EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File) - FileStack = [File] + ForceList - DependencySet = set() - - if self._AutoGenObject.Arch not in gDependencyDatabase: - gDependencyDatabase[self._AutoGenObject.Arch] = {} - DepDb = gDependencyDatabase[self._AutoGenObject.Arch] - - while len(FileStack) > 0: - F = FileStack.pop() - - FullPathDependList = [] - if F in self.FileCache: - for CacheFile in self.FileCache[F]: - FullPathDependList.append(CacheFile) - if CacheFile not in DependencySet: - FileStack.append(CacheFile) - DependencySet.update(FullPathDependList) - continue - - CurrentFileDependencyList = [] - if F in DepDb: - CurrentFileDependencyList = DepDb[F] - else: - try: - Fd = open(F.Path, 'r') - except BaseException, X: - EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X)) - - FileContent = Fd.read() - Fd.close() - if len(FileContent) == 0: - continue - - if FileContent[0] == 0xff or FileContent[0] == 0xfe: - FileContent = unicode(FileContent, "utf-16") - IncludedFileList = gIncludePattern.findall(FileContent) - - for Inc in IncludedFileList: - Inc = Inc.strip() - # if there's macro used to reference header file, expand it - HeaderList = gMacroPattern.findall(Inc) - if len(HeaderList) == 1 and len(HeaderList[0]) == 2: - HeaderType = HeaderList[0][0] - HeaderKey = HeaderList[0][1] - if HeaderType in gIncludeMacroConversion: - Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey} - else: - # not known macro used in #include, always build the file by - # returning a empty dependency - self.FileCache[File] = [] - return [] - Inc = os.path.normpath(Inc) - CurrentFileDependencyList.append(Inc) - DepDb[F] = CurrentFileDependencyList - - CurrentFilePath = F.Dir - PathList = [CurrentFilePath] + SearchPathList - for Inc in CurrentFileDependencyList: - for SearchPath in PathList: - FilePath = os.path.join(SearchPath, Inc) - if FilePath in gIsFileMap: - if not gIsFileMap[FilePath]: - continue - # If isfile is called too many times, the performance is slow down. - elif not os.path.isfile(FilePath): - gIsFileMap[FilePath] = False - continue - else: - gIsFileMap[FilePath] = True - FilePath = PathClass(FilePath) - FullPathDependList.append(FilePath) - if FilePath not in DependencySet: - FileStack.append(FilePath) - break - else: - EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\ - "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList))) - - self.FileCache[F] = FullPathDependList - DependencySet.update(FullPathDependList) - - DependencySet.update(ForceList) - if File in DependencySet: - DependencySet.remove(File) - DependencyList = list(DependencySet) # remove duplicate ones - - return DependencyList - - _TemplateDict = property(_CreateTemplateDict) - -## CustomMakefile class -# -# This class encapsules makefie and its generation for module. It uses template to generate -# the content of makefile. The content of makefile will be got from ModuleAutoGen object. -# -class CustomMakefile(BuildFile): - ## template used to generate the makefile for module with custom makefile - _TEMPLATE_ = TemplateString('''\ -${makefile_header} - -# -# Platform Macro Definition -# -PLATFORM_NAME = ${platform_name} -PLATFORM_GUID = ${platform_guid} -PLATFORM_VERSION = ${platform_version} -PLATFORM_RELATIVE_DIR = ${platform_relative_directory} -PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} -PLATFORM_OUTPUT_DIR = ${platform_output_directory} - -# -# Module Macro Definition -# -MODULE_NAME = ${module_name} -MODULE_GUID = ${module_guid} -MODULE_VERSION = ${module_version} -MODULE_TYPE = ${module_type} -MODULE_FILE = ${module_file} -MODULE_FILE_BASE_NAME = ${module_file_base_name} -BASE_NAME = $(MODULE_NAME) -MODULE_RELATIVE_DIR = ${module_relative_directory} -MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} - -# -# Build Configuration Macro Definition -# -ARCH = ${architecture} -TOOLCHAIN = ${toolchain_tag} -TOOLCHAIN_TAG = ${toolchain_tag} -TARGET = ${build_target} - -# -# Build Directory Macro Definition -# -# PLATFORM_BUILD_DIR = ${platform_build_directory} -BUILD_DIR = ${platform_build_directory} -BIN_DIR = $(BUILD_DIR)${separator}${architecture} -LIB_DIR = $(BIN_DIR) -MODULE_BUILD_DIR = ${module_build_directory} -OUTPUT_DIR = ${module_output_directory} -DEBUG_DIR = ${module_debug_directory} -DEST_DIR_OUTPUT = $(OUTPUT_DIR) -DEST_DIR_DEBUG = $(DEBUG_DIR) - -# -# Tools definitions specific to this module -# -${BEGIN}${module_tool_definitions} -${END} -MAKE_FILE = ${makefile_path} - -# -# Shell Command Macro -# -${BEGIN}${shell_command_code} = ${shell_command} -${END} - -${custom_makefile_content} - -# -# Target used when called from platform makefile, which will bypass the build of dependent libraries -# - -pbuild: init all - - -# -# ModuleTarget -# - -mbuild: init all - -# -# Build Target used in multi-thread build mode, which no init target is needed -# - -tbuild: all - -# -# Initialization target: print build information and create necessary directories -# -init: -\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] -${BEGIN}\t-@${create_directory_command}\n${END}\ - -''') - - ## Constructor of CustomMakefile - # - # @param ModuleAutoGen Object of ModuleAutoGen class - # - def __init__(self, ModuleAutoGen): - BuildFile.__init__(self, ModuleAutoGen) - self.PlatformInfo = self._AutoGenObject.PlatformInfo - self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] - - # Compose a dict object containing information used to do replacement in template - def _CreateTemplateDict(self): - Separator = self._SEP_[self._FileType] - if self._FileType not in self._AutoGenObject.CustomMakefile: - EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType, - ExtraData="[%s]" % str(self._AutoGenObject)) - MakefilePath = os.path.join( - self._AutoGenObject.WorkspaceDir, - self._AutoGenObject.CustomMakefile[self._FileType] - ) - try: - CustomMakefile = open(MakefilePath, 'r').read() - except: - EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject), - ExtraData=self._AutoGenObject.CustomMakefile[self._FileType]) - - # tools definitions - ToolsDef = [] - for Tool in self._AutoGenObject.BuildOption: - # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. - if Tool == "MAKE": - continue - for Attr in self._AutoGenObject.BuildOption[Tool]: - if Attr == "FAMILY": - continue - elif Attr == "PATH": - ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr])) - else: - ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr])) - ToolsDef.append("") - - MakefileName = self._FILE_NAME_[self._FileType] - MakefileTemplateDict = { - "makefile_header" : self._FILE_HEADER_[self._FileType], - "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), - "platform_name" : self.PlatformInfo.Name, - "platform_guid" : self.PlatformInfo.Guid, - "platform_version" : self.PlatformInfo.Version, - "platform_relative_directory": self.PlatformInfo.SourceDir, - "platform_output_directory" : self.PlatformInfo.OutputDir, - - "module_name" : self._AutoGenObject.Name, - "module_guid" : self._AutoGenObject.Guid, - "module_version" : self._AutoGenObject.Version, - "module_type" : self._AutoGenObject.ModuleType, - "module_file" : self._AutoGenObject.MetaFile, - "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, - "module_relative_directory" : self._AutoGenObject.SourceDir, - - "architecture" : self._AutoGenObject.Arch, - "toolchain_tag" : self._AutoGenObject.ToolChain, - "build_target" : self._AutoGenObject.BuildTarget, - - "platform_build_directory" : self.PlatformInfo.BuildDir, - "module_build_directory" : self._AutoGenObject.BuildDir, - "module_output_directory" : self._AutoGenObject.OutputDir, - "module_debug_directory" : self._AutoGenObject.DebugDir, - - "separator" : Separator, - "module_tool_definitions" : ToolsDef, - - "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), - "shell_command" : self._SHELL_CMD_[self._FileType].values(), - - "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), - "custom_makefile_content" : CustomMakefile - } - - return MakefileTemplateDict - - _TemplateDict = property(_CreateTemplateDict) - -## PlatformMakefile class -# -# This class encapsules makefie and its generation for platform. It uses -# template to generate the content of makefile. The content of makefile will be -# got from PlatformAutoGen object. -# -class PlatformMakefile(BuildFile): - ## template used to generate the makefile for platform - _TEMPLATE_ = TemplateString('''\ -${makefile_header} - -# -# Platform Macro Definition -# -PLATFORM_NAME = ${platform_name} -PLATFORM_GUID = ${platform_guid} -PLATFORM_VERSION = ${platform_version} -PLATFORM_FILE = ${platform_file} -PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} -PLATFORM_OUTPUT_DIR = ${platform_output_directory} - -# -# Build Configuration Macro Definition -# -TOOLCHAIN = ${toolchain_tag} -TOOLCHAIN_TAG = ${toolchain_tag} -TARGET = ${build_target} - -# -# Build Directory Macro Definition -# -BUILD_DIR = ${platform_build_directory} -FV_DIR = ${platform_build_directory}${separator}FV - -# -# Shell Command Macro -# -${BEGIN}${shell_command_code} = ${shell_command} -${END} - -MAKE = ${make_path} -MAKE_FILE = ${makefile_path} - -# -# Default target -# -all: init build_libraries build_modules - -# -# Initialization target: print build information and create necessary directories -# -init: -\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}] -\t${BEGIN}-@${create_directory_command} -\t${END} -# -# library build target -# -libraries: init build_libraries - -# -# module build target -# -modules: init build_libraries build_modules - -# -# Build all libraries: -# -build_libraries: -${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild -${END}\t@cd $(BUILD_DIR) - -# -# Build all modules: -# -build_modules: -${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild -${END}\t@cd $(BUILD_DIR) - -# -# Clean intermediate files -# -clean: -\t${BEGIN}-@${library_build_command} clean -\t${END}${BEGIN}-@${module_build_command} clean -\t${END}@cd $(BUILD_DIR) - -# -# Clean all generated files except to makefile -# -cleanall: -${BEGIN}\t${cleanall_command} -${END} - -# -# Clean all library files -# -cleanlib: -\t${BEGIN}-@${library_build_command} cleanall -\t${END}@cd $(BUILD_DIR)\n -''') - - ## Constructor of PlatformMakefile - # - # @param ModuleAutoGen Object of PlatformAutoGen class - # - def __init__(self, PlatformAutoGen): - BuildFile.__init__(self, PlatformAutoGen) - self.ModuleBuildCommandList = [] - self.ModuleMakefileList = [] - self.IntermediateDirectoryList = [] - self.ModuleBuildDirectoryList = [] - self.LibraryBuildDirectoryList = [] - - # Compose a dict object containing information used to do replacement in template - def _CreateTemplateDict(self): - Separator = self._SEP_[self._FileType] - - PlatformInfo = self._AutoGenObject - if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: - EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", - ExtraData="[%s]" % str(self._AutoGenObject)) - - self.IntermediateDirectoryList = ["$(BUILD_DIR)"] - self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList() - self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList() - - MakefileName = self._FILE_NAME_[self._FileType] - LibraryMakefileList = [] - LibraryMakeCommandList = [] - for D in self.LibraryBuildDirectoryList: - D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) - Makefile = os.path.join(D, MakefileName) - Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} - LibraryMakefileList.append(Makefile) - LibraryMakeCommandList.append(Command) - - ModuleMakefileList = [] - ModuleMakeCommandList = [] - for D in self.ModuleBuildDirectoryList: - D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) - Makefile = os.path.join(D, MakefileName) - Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} - ModuleMakefileList.append(Makefile) - ModuleMakeCommandList.append(Command) - - MakefileTemplateDict = { - "makefile_header" : self._FILE_HEADER_[self._FileType], - "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), - "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], - "makefile_name" : MakefileName, - "platform_name" : PlatformInfo.Name, - "platform_guid" : PlatformInfo.Guid, - "platform_version" : PlatformInfo.Version, - "platform_file" : self._AutoGenObject.MetaFile, - "platform_relative_directory": PlatformInfo.SourceDir, - "platform_output_directory" : PlatformInfo.OutputDir, - "platform_build_directory" : PlatformInfo.BuildDir, - - "toolchain_tag" : PlatformInfo.ToolChain, - "build_target" : PlatformInfo.BuildTarget, - "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), - "shell_command" : self._SHELL_CMD_[self._FileType].values(), - "build_architecture_list" : self._AutoGenObject.Arch, - "architecture" : self._AutoGenObject.Arch, - "separator" : Separator, - "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), - "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), - "library_makefile_list" : LibraryMakefileList, - "module_makefile_list" : ModuleMakefileList, - "library_build_command" : LibraryMakeCommandList, - "module_build_command" : ModuleMakeCommandList, - } - - return MakefileTemplateDict - - ## Get the root directory list for intermediate files of all modules build - # - # @retval list The list of directory - # - def GetModuleBuildDirectoryList(self): - DirList = [] - for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: - DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) - return DirList - - ## Get the root directory list for intermediate files of all libraries build - # - # @retval list The list of directory - # - def GetLibraryBuildDirectoryList(self): - DirList = [] - for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: - DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) - return DirList - - _TemplateDict = property(_CreateTemplateDict) - -## TopLevelMakefile class -# -# This class encapsules makefie and its generation for entrance makefile. It -# uses template to generate the content of makefile. The content of makefile -# will be got from WorkspaceAutoGen object. -# -class TopLevelMakefile(BuildFile): - ## template used to generate toplevel makefile - _TEMPLATE_ = TemplateString('''\ -${makefile_header} - -# -# Platform Macro Definition -# -PLATFORM_NAME = ${platform_name} -PLATFORM_GUID = ${platform_guid} -PLATFORM_VERSION = ${platform_version} - -# -# Build Configuration Macro Definition -# -TOOLCHAIN = ${toolchain_tag} -TOOLCHAIN_TAG = ${toolchain_tag} -TARGET = ${build_target} - -# -# Build Directory Macro Definition -# -BUILD_DIR = ${platform_build_directory} -FV_DIR = ${platform_build_directory}${separator}FV - -# -# Shell Command Macro -# -${BEGIN}${shell_command_code} = ${shell_command} -${END} - -MAKE = ${make_path} -MAKE_FILE = ${makefile_path} - -# -# Default target -# -all: modules fds - -# -# Initialization target: print build information and create necessary directories -# -init: -\t-@ -\t${BEGIN}-@${create_directory_command} -\t${END} -# -# library build target -# -libraries: init -${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) libraries -${END}\t@cd $(BUILD_DIR) - -# -# module build target -# -modules: init -${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) modules -${END}\t@cd $(BUILD_DIR) - -# -# Flash Device Image Target -# -fds: init -\t-@cd $(FV_DIR) -${BEGIN}\tGenFds -f ${fdf_file} -o $(BUILD_DIR) -t $(TOOLCHAIN) -b $(TARGET) -p ${active_platform} -a ${build_architecture_list} ${extra_options}${END}${BEGIN} -r ${fd} ${END}${BEGIN} -i ${fv} ${END}${BEGIN} -C ${cap} ${END}${BEGIN} -D ${macro} ${END} - -# -# run command for emulator platform only -# -run: -\tcd $(BUILD_DIR)${separator}IA32 && ".${separator}SecMain" -\tcd $(BUILD_DIR) - -# -# Clean intermediate files -# -clean: -${BEGIN}\t-@${sub_build_command} clean -${END}\t@cd $(BUILD_DIR) - -# -# Clean all generated files except to makefile -# -cleanall: -${BEGIN}\t${cleanall_command} -${END} - -# -# Clean all library files -# -cleanlib: -${BEGIN}\t-@${sub_build_command} cleanlib -${END}\t@cd $(BUILD_DIR)\n -''') - - ## Constructor of TopLevelMakefile - # - # @param Workspace Object of WorkspaceAutoGen class - # - def __init__(self, Workspace): - BuildFile.__init__(self, Workspace) - self.IntermediateDirectoryList = [] - - # Compose a dict object containing information used to do replacement in template - def _CreateTemplateDict(self): - Separator = self._SEP_[self._FileType] - - # any platform autogen object is ok because we just need common information - PlatformInfo = self._AutoGenObject - - if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: - EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", - ExtraData="[%s]" % str(self._AutoGenObject)) - - for Arch in PlatformInfo.ArchList: - self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch])) - self.IntermediateDirectoryList.append("$(FV_DIR)") - - # TRICK: for not generating GenFds call in makefile if no FDF file - MacroList = [] - if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "": - FdfFileList = [PlatformInfo.FdfFile] - # macros passed to GenFds - MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\'))) - MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\'))) - MacroDict = {} - MacroDict.update(GlobalData.gGlobalDefines) - MacroDict.update(GlobalData.gCommandLineDefines) - MacroDict.pop("EFI_SOURCE", "dummy") - MacroDict.pop("EDK_SOURCE", "dummy") - for MacroName in MacroDict: - if MacroDict[MacroName] != "": - MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\'))) - else: - MacroList.append('"%s"' % MacroName) - else: - FdfFileList = [] - - # pass extra common options to external program called in makefile, currently GenFds.exe - ExtraOption = '' - LogLevel = EdkLogger.GetLevel() - if LogLevel == EdkLogger.VERBOSE: - ExtraOption += " -v" - elif LogLevel <= EdkLogger.DEBUG_9: - ExtraOption += " -d %d" % (LogLevel - 1) - elif LogLevel == EdkLogger.QUIET: - ExtraOption += " -q" - - if GlobalData.gCaseInsensitive: - ExtraOption += " -c" - - MakefileName = self._FILE_NAME_[self._FileType] - SubBuildCommandList = [] - for A in PlatformInfo.ArchList: - Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)} - SubBuildCommandList.append(Command) - - MakefileTemplateDict = { - "makefile_header" : self._FILE_HEADER_[self._FileType], - "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), - "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], - "platform_name" : PlatformInfo.Name, - "platform_guid" : PlatformInfo.Guid, - "platform_version" : PlatformInfo.Version, - "platform_build_directory" : PlatformInfo.BuildDir, - - "toolchain_tag" : PlatformInfo.ToolChain, - "build_target" : PlatformInfo.BuildTarget, - "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), - "shell_command" : self._SHELL_CMD_[self._FileType].values(), - 'arch' : list(PlatformInfo.ArchList), - "build_architecture_list" : ','.join(PlatformInfo.ArchList), - "separator" : Separator, - "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), - "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), - "sub_build_command" : SubBuildCommandList, - "fdf_file" : FdfFileList, - "active_platform" : str(PlatformInfo), - "fd" : PlatformInfo.FdTargetList, - "fv" : PlatformInfo.FvTargetList, - "cap" : PlatformInfo.CapTargetList, - "extra_options" : ExtraOption, - "macro" : MacroList, - } - - return MakefileTemplateDict - - ## Get the root directory list for intermediate files of all modules build - # - # @retval list The list of directory - # - def GetModuleBuildDirectoryList(self): - DirList = [] - for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: - DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) - return DirList - - ## Get the root directory list for intermediate files of all libraries build - # - # @retval list The list of directory - # - def GetLibraryBuildDirectoryList(self): - DirList = [] - for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: - DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) - return DirList - - _TemplateDict = property(_CreateTemplateDict) - -# This acts like the main() function for the script, unless it is 'import'ed into another script. -if __name__ == '__main__': - pass - +## @file +# Create makefile for MS nmake and GNU make +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +## Import Modules +# +import os +import sys +import string +import re +import os.path as path + +from Common.BuildToolError import * +from Common.Misc import * +from Common.String import * +from BuildEngine import * +import Common.GlobalData as GlobalData + +## Regular expression for finding header file inclusions +gIncludePattern = re.compile(r"^[ \t]*#?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE|re.UNICODE|re.IGNORECASE) + +## Regular expression for matching macro used in header file inclusion +gMacroPattern = re.compile("([_A-Z][_A-Z0-9]*)[ \t]*\((.+)\)", re.UNICODE) + +gIsFileMap = {} + +## pattern for include style in Edk.x code +gProtocolDefinition = "Protocol/%(HeaderKey)s/%(HeaderKey)s.h" +gGuidDefinition = "Guid/%(HeaderKey)s/%(HeaderKey)s.h" +gArchProtocolDefinition = "ArchProtocol/%(HeaderKey)s/%(HeaderKey)s.h" +gPpiDefinition = "Ppi/%(HeaderKey)s/%(HeaderKey)s.h" +gIncludeMacroConversion = { + "EFI_PROTOCOL_DEFINITION" : gProtocolDefinition, + "EFI_GUID_DEFINITION" : gGuidDefinition, + "EFI_ARCH_PROTOCOL_DEFINITION" : gArchProtocolDefinition, + "EFI_PROTOCOL_PRODUCER" : gProtocolDefinition, + "EFI_PROTOCOL_CONSUMER" : gProtocolDefinition, + "EFI_PROTOCOL_DEPENDENCY" : gProtocolDefinition, + "EFI_ARCH_PROTOCOL_PRODUCER" : gArchProtocolDefinition, + "EFI_ARCH_PROTOCOL_CONSUMER" : gArchProtocolDefinition, + "EFI_ARCH_PROTOCOL_DEPENDENCY" : gArchProtocolDefinition, + "EFI_PPI_DEFINITION" : gPpiDefinition, + "EFI_PPI_PRODUCER" : gPpiDefinition, + "EFI_PPI_CONSUMER" : gPpiDefinition, + "EFI_PPI_DEPENDENCY" : gPpiDefinition, +} + +## default makefile type +gMakeType = "" +if sys.platform == "win32": + gMakeType = "nmake" +else: + gMakeType = "gmake" + + +## BuildFile class +# +# This base class encapsules build file and its generation. It uses template to generate +# the content of build file. The content of build file will be got from AutoGen objects. +# +class BuildFile(object): + ## template used to generate the build file (i.e. makefile if using make) + _TEMPLATE_ = TemplateString('') + + _DEFAULT_FILE_NAME_ = "Makefile" + + ## default file name for each type of build file + _FILE_NAME_ = { + "nmake" : "Makefile", + "gmake" : "GNUmakefile" + } + + ## Fixed header string for makefile + _MAKEFILE_HEADER = '''# +# DO NOT EDIT +# This file is auto-generated by build utility +# +# Module Name: +# +# %s +# +# Abstract: +# +# Auto-generated makefile for building modules, libraries or platform +# + ''' + + ## Header string for each type of build file + _FILE_HEADER_ = { + "nmake" : _MAKEFILE_HEADER % _FILE_NAME_["nmake"], + "gmake" : _MAKEFILE_HEADER % _FILE_NAME_["gmake"] + } + + ## shell commands which can be used in build file in the form of macro + # $(CP) copy file command + # $(MV) move file command + # $(RM) remove file command + # $(MD) create dir command + # $(RD) remove dir command + # + _SHELL_CMD_ = { + "nmake" : { + "CP" : "copy /y", + "MV" : "move /y", + "RM" : "del /f /q", + "MD" : "mkdir", + "RD" : "rmdir /s /q", + }, + + "gmake" : { + "CP" : "cp -f", + "MV" : "mv -f", + "RM" : "rm -f", + "MD" : "mkdir -p", + "RD" : "rm -r -f", + } + } + + ## directory separator + _SEP_ = { + "nmake" : "\\", + "gmake" : "/" + } + + ## directory creation template + _MD_TEMPLATE_ = { + "nmake" : 'if not exist %(dir)s $(MD) %(dir)s', + "gmake" : "$(MD) %(dir)s" + } + + ## directory removal template + _RD_TEMPLATE_ = { + "nmake" : 'if exist %(dir)s $(RD) %(dir)s', + "gmake" : "$(RD) %(dir)s" + } + + _CD_TEMPLATE_ = { + "nmake" : 'if exist %(dir)s cd %(dir)s', + "gmake" : "test -e %(dir)s && cd %(dir)s" + } + + _MAKE_TEMPLATE_ = { + "nmake" : 'if exist %(file)s "$(MAKE)" $(MAKE_FLAGS) -f %(file)s', + "gmake" : 'test -e %(file)s && "$(MAKE)" $(MAKE_FLAGS) -f %(file)s' + } + + _INCLUDE_CMD_ = { + "nmake" : '!INCLUDE', + "gmake" : "include" + } + + _INC_FLAG_ = {"MSFT" : "/I", "GCC" : "-I", "INTEL" : "-I", "RVCT" : "-I"} + + ## Constructor of BuildFile + # + # @param AutoGenObject Object of AutoGen class + # + def __init__(self, AutoGenObject): + self._AutoGenObject = AutoGenObject + self._FileType = gMakeType + + ## Create build file + # + # @param FileType Type of build file. Only nmake and gmake are supported now. + # + # @retval TRUE The build file is created or re-created successfully + # @retval FALSE The build file exists and is the same as the one to be generated + # + def Generate(self, FileType=gMakeType): + if FileType not in self._FILE_NAME_: + EdkLogger.error("build", PARAMETER_INVALID, "Invalid build type [%s]" % FileType, + ExtraData="[%s]" % str(self._AutoGenObject)) + self._FileType = FileType + FileContent = self._TEMPLATE_.Replace(self._TemplateDict) + FileName = self._FILE_NAME_[FileType] + return SaveFileOnChange(os.path.join(self._AutoGenObject.MakeFileDir, FileName), FileContent, False) + + ## Return a list of directory creation command string + # + # @param DirList The list of directory to be created + # + # @retval list The directory creation command list + # + def GetCreateDirectoryCommand(self, DirList): + return [self._MD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] + + ## Return a list of directory removal command string + # + # @param DirList The list of directory to be removed + # + # @retval list The directory removal command list + # + def GetRemoveDirectoryCommand(self, DirList): + return [self._RD_TEMPLATE_[self._FileType] % {'dir':Dir} for Dir in DirList] + + def PlaceMacro(self, Path, MacroDefinitions={}): + if Path.startswith("$("): + return Path + else: + PathLength = len(Path) + for MacroName in MacroDefinitions: + MacroValue = MacroDefinitions[MacroName] + MacroValueLength = len(MacroValue) + if MacroValueLength <= PathLength and Path.startswith(MacroValue): + Path = "$(%s)%s" % (MacroName, Path[MacroValueLength:]) + break + return Path + +## ModuleMakefile class +# +# This class encapsules makefie and its generation for module. It uses template to generate +# the content of makefile. The content of makefile will be got from ModuleAutoGen object. +# +class ModuleMakefile(BuildFile): + ## template used to generate the makefile for module + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_RELATIVE_DIR = ${platform_relative_directory} +PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Module Macro Definition +# +MODULE_NAME = ${module_name} +MODULE_GUID = ${module_guid} +MODULE_VERSION = ${module_version} +MODULE_TYPE = ${module_type} +MODULE_FILE = ${module_file} +MODULE_FILE_BASE_NAME = ${module_file_base_name} +BASE_NAME = $(MODULE_NAME) +MODULE_RELATIVE_DIR = ${module_relative_directory} +MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} + +MODULE_ENTRY_POINT = ${module_entry_point} +ARCH_ENTRY_POINT = ${arch_entry_point} +IMAGE_ENTRY_POINT = ${image_entry_point} + +${BEGIN}${module_extra_defines} +${END} +# +# Build Configuration Macro Definition +# +ARCH = ${architecture} +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +# PLATFORM_BUILD_DIR = ${platform_build_directory} +BUILD_DIR = ${platform_build_directory} +BIN_DIR = $(BUILD_DIR)${separator}${architecture} +LIB_DIR = $(BIN_DIR) +MODULE_BUILD_DIR = ${module_build_directory} +OUTPUT_DIR = ${module_output_directory} +DEBUG_DIR = ${module_debug_directory} +DEST_DIR_OUTPUT = $(OUTPUT_DIR) +DEST_DIR_DEBUG = $(DEBUG_DIR) + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +# +# Tools definitions specific to this module +# +${BEGIN}${module_tool_definitions} +${END} +MAKE_FILE = ${makefile_path} + +# +# Build Macro +# +${BEGIN}${file_macro} +${END} + +COMMON_DEPS = ${BEGIN}${common_dependency_file} \\ + ${END} + +# +# Overridable Target Macro Definitions +# +FORCE_REBUILD = force_build +INIT_TARGET = init +PCH_TARGET = +BC_TARGET = ${BEGIN}${backward_compatible_target} ${END} +CODA_TARGET = ${BEGIN}${remaining_build_target} \\ + ${END} + +# +# Default target, which will build dependent libraries in addition to source files +# + +all: mbuild + + +# +# Target used when called from platform makefile, which will bypass the build of dependent libraries +# + +pbuild: $(INIT_TARGET) $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) + +# +# ModuleTarget +# + +mbuild: $(INIT_TARGET) $(BC_TARGET) gen_libs $(PCH_TARGET) $(CODA_TARGET) + +# +# Build Target used in multi-thread build mode, which will bypass the init and gen_libs targets +# + +tbuild: $(BC_TARGET) $(PCH_TARGET) $(CODA_TARGET) + +# +# Phony target which is used to force executing commands for a target +# +force_build: +\t-@ + +# +# Target to update the FD +# + +fds: mbuild gen_fds + +# +# Initialization target: print build information and create necessary directories +# +init: info dirs + +info: +\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] + +dirs: +${BEGIN}\t-@${create_directory_command}\n${END} + +strdefs: +\t-@$(CP) $(DEBUG_DIR)${separator}AutoGen.h $(DEBUG_DIR)${separator}$(MODULE_NAME)StrDefs.h + +# +# GenLibsTarget +# +gen_libs: +\t${BEGIN}@"$(MAKE)" $(MAKE_FLAGS) -f ${dependent_library_build_directory}${separator}${makefile_name} +\t${END}@cd $(MODULE_BUILD_DIR) + +# +# Build Flash Device Image +# +gen_fds: +\t@"$(MAKE)" $(MAKE_FLAGS) -f $(BUILD_DIR)${separator}${makefile_name} fds +\t@cd $(MODULE_BUILD_DIR) + +# +# Individual Object Build Targets +# +${BEGIN}${file_build_target} +${END} + +# +# clean all intermediate files +# +clean: +\t${BEGIN}${clean_command} +\t${END} + +# +# clean all generated files +# +cleanall: +${BEGIN}\t${cleanall_command} +${END}\t$(RM) *.pdb *.idb > NUL 2>&1 +\t$(RM) $(BIN_DIR)${separator}$(MODULE_NAME).efi + +# +# clean all dependent libraries built +# +cleanlib: +\t${BEGIN}-@${library_build_command} cleanall +\t${END}@cd $(MODULE_BUILD_DIR)\n\n''') + + _FILE_MACRO_TEMPLATE = TemplateString("${macro_name} = ${BEGIN} \\\n ${source_file}${END}\n") + _BUILD_TARGET_TEMPLATE = TemplateString("${BEGIN}${target} : ${deps}\n${END}\t${cmd}\n") + + ## Constructor of ModuleMakefile + # + # @param ModuleAutoGen Object of ModuleAutoGen class + # + def __init__(self, ModuleAutoGen): + BuildFile.__init__(self, ModuleAutoGen) + self.PlatformInfo = self._AutoGenObject.PlatformInfo + + self.ResultFileList = [] + self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] + + self.SourceFileDatabase = {} # {file type : file path} + self.DestFileDatabase = {} # {file type : file path} + self.FileBuildTargetList = [] # [(src, target string)] + self.BuildTargetList = [] # [target string] + self.PendingBuildTargetList = [] # [FileBuildRule objects] + self.CommonFileDependency = [] + self.FileListMacros = {} + self.ListFileMacros = {} + + self.FileCache = {} + self.FileDependency = [] + self.LibraryBuildCommandList = [] + self.LibraryFileList = [] + self.LibraryMakefileList = [] + self.LibraryBuildDirectoryList = [] + self.SystemLibraryList = [] + self.Macros = sdict() + self.Macros["OUTPUT_DIR" ] = self._AutoGenObject.Macros["OUTPUT_DIR"] + self.Macros["DEBUG_DIR" ] = self._AutoGenObject.Macros["DEBUG_DIR"] + self.Macros["MODULE_BUILD_DIR"] = self._AutoGenObject.Macros["MODULE_BUILD_DIR"] + self.Macros["BIN_DIR" ] = self._AutoGenObject.Macros["BIN_DIR"] + self.Macros["BUILD_DIR" ] = self._AutoGenObject.Macros["BUILD_DIR"] + self.Macros["WORKSPACE" ] = self._AutoGenObject.Macros["WORKSPACE"] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + if self._FileType not in self._SEP_: + EdkLogger.error("build", PARAMETER_INVALID, "Invalid Makefile type [%s]" % self._FileType, + ExtraData="[%s]" % str(self._AutoGenObject)) + Separator = self._SEP_[self._FileType] + + # break build if no source files and binary files are found + if len(self._AutoGenObject.SourceFileList) == 0 and len(self._AutoGenObject.BinaryFileList) == 0: + EdkLogger.error("build", AUTOGEN_ERROR, "No files to be built in module [%s, %s, %s]" + % (self._AutoGenObject.BuildTarget, self._AutoGenObject.ToolChain, self._AutoGenObject.Arch), + ExtraData="[%s]" % str(self._AutoGenObject)) + + # convert dependent libraries to build command + self.ProcessDependentLibrary() + if len(self._AutoGenObject.Module.ModuleEntryPointList) > 0: + ModuleEntryPoint = self._AutoGenObject.Module.ModuleEntryPointList[0] + else: + ModuleEntryPoint = "_ModuleEntryPoint" + + # Intel EBC compiler enforces EfiMain + if self._AutoGenObject.AutoGenVersion < 0x00010005 and self._AutoGenObject.Arch == "EBC": + ArchEntryPoint = "EfiMain" + else: + ArchEntryPoint = ModuleEntryPoint + + if self._AutoGenObject.Arch == "EBC": + # EBC compiler always use "EfiStart" as entry point. Only applies to EdkII modules + ImageEntryPoint = "EfiStart" + elif self._AutoGenObject.AutoGenVersion < 0x00010005: + # Edk modules use entry point specified in INF file + ImageEntryPoint = ModuleEntryPoint + else: + # EdkII modules always use "_ModuleEntryPoint" as entry point + ImageEntryPoint = "_ModuleEntryPoint" + + # tools definitions + ToolsDef = [] + IncPrefix = self._INC_FLAG_[self._AutoGenObject.ToolChainFamily] + for Tool in self._AutoGenObject.BuildOption: + for Attr in self._AutoGenObject.BuildOption[Tool]: + Value = self._AutoGenObject.BuildOption[Tool][Attr] + if Attr == "FAMILY": + continue + elif Attr == "PATH": + ToolsDef.append("%s = %s" % (Tool, Value)) + else: + # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. + if Tool == "MAKE": + continue + # Remove duplicated include path, if any + if Attr == "FLAGS": + Value = RemoveDupOption(Value, IncPrefix, self._AutoGenObject.IncludePathList) + ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value)) + ToolsDef.append("") + + # convert source files and binary files to build targets + self.ResultFileList = [str(T.Target) for T in self._AutoGenObject.CodaTargetList] + if len(self.ResultFileList) == 0 and len(self._AutoGenObject.SourceFileList) <> 0: + EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build", + ExtraData="[%s]" % str(self._AutoGenObject)) + + self.ProcessBuildTargetList() + + # Generate macros used to represent input files + FileMacroList = [] # macro name = file list + for FileListMacro in self.FileListMacros: + FileMacro = self._FILE_MACRO_TEMPLATE.Replace( + { + "macro_name" : FileListMacro, + "source_file" : self.FileListMacros[FileListMacro] + } + ) + FileMacroList.append(FileMacro) + + # INC_LIST is special + FileMacro = "" + IncludePathList = [] + for P in self._AutoGenObject.IncludePathList: + IncludePathList.append(IncPrefix+self.PlaceMacro(P, self.Macros)) + if FileBuildRule.INC_LIST_MACRO in self.ListFileMacros: + self.ListFileMacros[FileBuildRule.INC_LIST_MACRO].append(IncPrefix+P) + FileMacro += self._FILE_MACRO_TEMPLATE.Replace( + { + "macro_name" : "INC", + "source_file" : IncludePathList + } + ) + FileMacroList.append(FileMacro) + + # Generate macros used to represent files containing list of input files + for ListFileMacro in self.ListFileMacros: + ListFileName = os.path.join(self._AutoGenObject.OutputDir, "%s.lst" % ListFileMacro.lower()[:len(ListFileMacro)-5]) + FileMacroList.append("%s = %s" % (ListFileMacro, ListFileName)) + SaveFileOnChange( + ListFileName, + "\n".join(self.ListFileMacros[ListFileMacro]), + False + ) + + # Edk modules need StrDefs.h for string ID + #if self._AutoGenObject.AutoGenVersion < 0x00010005 and len(self._AutoGenObject.UnicodeFileList) > 0: + # BcTargetList = ['strdefs'] + #else: + # BcTargetList = [] + BcTargetList = [] + + MakefileName = self._FILE_NAME_[self._FileType] + LibraryMakeCommandList = [] + for D in self.LibraryBuildDirectoryList: + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join(D, MakefileName)} + LibraryMakeCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), + "makefile_name" : MakefileName, + "platform_name" : self.PlatformInfo.Name, + "platform_guid" : self.PlatformInfo.Guid, + "platform_version" : self.PlatformInfo.Version, + "platform_relative_directory": self.PlatformInfo.SourceDir, + "platform_output_directory" : self.PlatformInfo.OutputDir, + + "module_name" : self._AutoGenObject.Name, + "module_guid" : self._AutoGenObject.Guid, + "module_version" : self._AutoGenObject.Version, + "module_type" : self._AutoGenObject.ModuleType, + "module_file" : self._AutoGenObject.MetaFile.Name, + "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, + "module_relative_directory" : self._AutoGenObject.SourceDir, + "module_extra_defines" : ["%s = %s" % (k, v) for k,v in self._AutoGenObject.Module.Defines.iteritems()], + + "architecture" : self._AutoGenObject.Arch, + "toolchain_tag" : self._AutoGenObject.ToolChain, + "build_target" : self._AutoGenObject.BuildTarget, + + "platform_build_directory" : self.PlatformInfo.BuildDir, + "module_build_directory" : self._AutoGenObject.BuildDir, + "module_output_directory" : self._AutoGenObject.OutputDir, + "module_debug_directory" : self._AutoGenObject.DebugDir, + + "separator" : Separator, + "module_tool_definitions" : ToolsDef, + + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + + "module_entry_point" : ModuleEntryPoint, + "image_entry_point" : ImageEntryPoint, + "arch_entry_point" : ArchEntryPoint, + "remaining_build_target" : self.ResultFileList, + "common_dependency_file" : self.CommonFileDependency, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "clean_command" : self.GetRemoveDirectoryCommand(["$(OUTPUT_DIR)"]), + "cleanall_command" : self.GetRemoveDirectoryCommand(["$(DEBUG_DIR)", "$(OUTPUT_DIR)"]), + "dependent_library_build_directory" : self.LibraryBuildDirectoryList, + "library_build_command" : LibraryMakeCommandList, + "file_macro" : FileMacroList, + "file_build_target" : self.BuildTargetList, + "backward_compatible_target": BcTargetList, + } + + return MakefileTemplateDict + + def ProcessBuildTargetList(self): + # + # Search dependency file list for each source file + # + ForceIncludedFile = [] + for File in self._AutoGenObject.AutoGenFileList: + if File.Ext == '.h': + ForceIncludedFile.append(File) + SourceFileList = [] + for Target in self._AutoGenObject.IntroTargetList: + SourceFileList.extend(Target.Inputs) + + self.FileDependency = self.GetFileDependency( + SourceFileList, + ForceIncludedFile, + self._AutoGenObject.IncludePathList + self._AutoGenObject.BuildOptionIncPathList + ) + DepSet = None + for File in self.FileDependency: + if not self.FileDependency[File]: + self.FileDependency[File] = ['$(FORCE_REBUILD)'] + continue + # skip non-C files + if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": + continue + elif DepSet == None: + DepSet = set(self.FileDependency[File]) + else: + DepSet &= set(self.FileDependency[File]) + # in case nothing in SourceFileList + if DepSet == None: + DepSet = set() + # + # Extract common files list in the dependency files + # + for File in DepSet: + self.CommonFileDependency.append(self.PlaceMacro(File.Path, self.Macros)) + + for File in self.FileDependency: + # skip non-C files + if File.Ext not in [".c", ".C"] or File.Name == "AutoGen.c": + continue + NewDepSet = set(self.FileDependency[File]) + NewDepSet -= DepSet + self.FileDependency[File] = ["$(COMMON_DEPS)"] + list(NewDepSet) + + # Convert target description object to target string in makefile + for Type in self._AutoGenObject.Targets: + for T in self._AutoGenObject.Targets[Type]: + # Generate related macros if needed + if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros: + self.FileListMacros[T.FileListMacro] = [] + if T.GenListFile and T.ListFileMacro not in self.ListFileMacros: + self.ListFileMacros[T.ListFileMacro] = [] + if T.GenIncListFile and T.IncListFileMacro not in self.ListFileMacros: + self.ListFileMacros[T.IncListFileMacro] = [] + + Deps = [] + # Add force-dependencies + for Dep in T.Dependencies: + Deps.append(self.PlaceMacro(str(Dep), self.Macros)) + # Add inclusion-dependencies + if len(T.Inputs) == 1 and T.Inputs[0] in self.FileDependency: + for F in self.FileDependency[T.Inputs[0]]: + Deps.append(self.PlaceMacro(str(F), self.Macros)) + # Add source-dependencies + for F in T.Inputs: + NewFile = self.PlaceMacro(str(F), self.Macros) + # In order to use file list macro as dependency + if T.GenListFile: + self.ListFileMacros[T.ListFileMacro].append(str(F)) + self.FileListMacros[T.FileListMacro].append(NewFile) + elif T.GenFileListMacro: + self.FileListMacros[T.FileListMacro].append(NewFile) + else: + Deps.append(NewFile) + + # Use file list macro as dependency + if T.GenFileListMacro: + Deps.append("$(%s)" % T.FileListMacro) + + TargetDict = { + "target" : self.PlaceMacro(T.Target.Path, self.Macros), + "cmd" : "\n\t".join(T.Commands), + "deps" : Deps + } + self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict)) + + ## For creating makefile targets for dependent libraries + def ProcessDependentLibrary(self): + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + self.LibraryBuildDirectoryList.append(self.PlaceMacro(LibraryAutoGen.BuildDir, self.Macros)) + + ## Return a list containing source file's dependencies + # + # @param FileList The list of source files + # @param ForceInculeList The list of files which will be included forcely + # @param SearchPathList The list of search path + # + # @retval dict The mapping between source file path and its dependencies + # + def GetFileDependency(self, FileList, ForceInculeList, SearchPathList): + Dependency = {} + for F in FileList: + Dependency[F] = self.GetDependencyList(F, ForceInculeList, SearchPathList) + return Dependency + + ## Find dependencies for one source file + # + # By searching recursively "#include" directive in file, find out all the + # files needed by given source file. The dependecies will be only searched + # in given search path list. + # + # @param File The source file + # @param ForceInculeList The list of files which will be included forcely + # @param SearchPathList The list of search path + # + # @retval list The list of files the given source file depends on + # + def GetDependencyList(self, File, ForceList, SearchPathList): + EdkLogger.debug(EdkLogger.DEBUG_1, "Try to get dependency files for %s" % File) + FileStack = [File] + ForceList + DependencySet = set() + + if self._AutoGenObject.Arch not in gDependencyDatabase: + gDependencyDatabase[self._AutoGenObject.Arch] = {} + DepDb = gDependencyDatabase[self._AutoGenObject.Arch] + + while len(FileStack) > 0: + F = FileStack.pop() + + FullPathDependList = [] + if F in self.FileCache: + for CacheFile in self.FileCache[F]: + FullPathDependList.append(CacheFile) + if CacheFile not in DependencySet: + FileStack.append(CacheFile) + DependencySet.update(FullPathDependList) + continue + + CurrentFileDependencyList = [] + if F in DepDb: + CurrentFileDependencyList = DepDb[F] + else: + try: + Fd = open(F.Path, 'r') + except BaseException, X: + EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F.Path+"\n\t"+str(X)) + + FileContent = Fd.read() + Fd.close() + if len(FileContent) == 0: + continue + + if FileContent[0] == 0xff or FileContent[0] == 0xfe: + FileContent = unicode(FileContent, "utf-16") + IncludedFileList = gIncludePattern.findall(FileContent) + + for Inc in IncludedFileList: + Inc = Inc.strip() + # if there's macro used to reference header file, expand it + HeaderList = gMacroPattern.findall(Inc) + if len(HeaderList) == 1 and len(HeaderList[0]) == 2: + HeaderType = HeaderList[0][0] + HeaderKey = HeaderList[0][1] + if HeaderType in gIncludeMacroConversion: + Inc = gIncludeMacroConversion[HeaderType] % {"HeaderKey" : HeaderKey} + else: + # not known macro used in #include, always build the file by + # returning a empty dependency + self.FileCache[File] = [] + return [] + Inc = os.path.normpath(Inc) + CurrentFileDependencyList.append(Inc) + DepDb[F] = CurrentFileDependencyList + + CurrentFilePath = F.Dir + PathList = [CurrentFilePath] + SearchPathList + for Inc in CurrentFileDependencyList: + for SearchPath in PathList: + FilePath = os.path.join(SearchPath, Inc) + if FilePath in gIsFileMap: + if not gIsFileMap[FilePath]: + continue + # If isfile is called too many times, the performance is slow down. + elif not os.path.isfile(FilePath): + gIsFileMap[FilePath] = False + continue + else: + gIsFileMap[FilePath] = True + FilePath = PathClass(FilePath) + FullPathDependList.append(FilePath) + if FilePath not in DependencySet: + FileStack.append(FilePath) + break + else: + EdkLogger.debug(EdkLogger.DEBUG_9, "%s included by %s was not found "\ + "in any given path:\n\t%s" % (Inc, F, "\n\t".join(SearchPathList))) + + self.FileCache[F] = FullPathDependList + DependencySet.update(FullPathDependList) + + DependencySet.update(ForceList) + if File in DependencySet: + DependencySet.remove(File) + DependencyList = list(DependencySet) # remove duplicate ones + + return DependencyList + + _TemplateDict = property(_CreateTemplateDict) + +## CustomMakefile class +# +# This class encapsules makefie and its generation for module. It uses template to generate +# the content of makefile. The content of makefile will be got from ModuleAutoGen object. +# +class CustomMakefile(BuildFile): + ## template used to generate the makefile for module with custom makefile + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_RELATIVE_DIR = ${platform_relative_directory} +PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Module Macro Definition +# +MODULE_NAME = ${module_name} +MODULE_GUID = ${module_guid} +MODULE_VERSION = ${module_version} +MODULE_TYPE = ${module_type} +MODULE_FILE = ${module_file} +MODULE_FILE_BASE_NAME = ${module_file_base_name} +BASE_NAME = $(MODULE_NAME) +MODULE_RELATIVE_DIR = ${module_relative_directory} +MODULE_DIR = $(WORKSPACE)${separator}${module_relative_directory} + +# +# Build Configuration Macro Definition +# +ARCH = ${architecture} +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +# PLATFORM_BUILD_DIR = ${platform_build_directory} +BUILD_DIR = ${platform_build_directory} +BIN_DIR = $(BUILD_DIR)${separator}${architecture} +LIB_DIR = $(BIN_DIR) +MODULE_BUILD_DIR = ${module_build_directory} +OUTPUT_DIR = ${module_output_directory} +DEBUG_DIR = ${module_debug_directory} +DEST_DIR_OUTPUT = $(OUTPUT_DIR) +DEST_DIR_DEBUG = $(DEBUG_DIR) + +# +# Tools definitions specific to this module +# +${BEGIN}${module_tool_definitions} +${END} +MAKE_FILE = ${makefile_path} + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +${custom_makefile_content} + +# +# Target used when called from platform makefile, which will bypass the build of dependent libraries +# + +pbuild: init all + + +# +# ModuleTarget +# + +mbuild: init all + +# +# Build Target used in multi-thread build mode, which no init target is needed +# + +tbuild: all + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@echo Building ... $(MODULE_DIR)${separator}$(MODULE_FILE) [$(ARCH)] +${BEGIN}\t-@${create_directory_command}\n${END}\ + +''') + + ## Constructor of CustomMakefile + # + # @param ModuleAutoGen Object of ModuleAutoGen class + # + def __init__(self, ModuleAutoGen): + BuildFile.__init__(self, ModuleAutoGen) + self.PlatformInfo = self._AutoGenObject.PlatformInfo + self.IntermediateDirectoryList = ["$(DEBUG_DIR)", "$(OUTPUT_DIR)"] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + Separator = self._SEP_[self._FileType] + if self._FileType not in self._AutoGenObject.CustomMakefile: + EdkLogger.error('build', OPTION_NOT_SUPPORTED, "No custom makefile for %s" % self._FileType, + ExtraData="[%s]" % str(self._AutoGenObject)) + MakefilePath = os.path.join( + self._AutoGenObject.WorkspaceDir, + self._AutoGenObject.CustomMakefile[self._FileType] + ) + try: + CustomMakefile = open(MakefilePath, 'r').read() + except: + EdkLogger.error('build', FILE_OPEN_FAILURE, File=str(self._AutoGenObject), + ExtraData=self._AutoGenObject.CustomMakefile[self._FileType]) + + # tools definitions + ToolsDef = [] + for Tool in self._AutoGenObject.BuildOption: + # Don't generate MAKE_FLAGS in makefile. It's put in environment variable. + if Tool == "MAKE": + continue + for Attr in self._AutoGenObject.BuildOption[Tool]: + if Attr == "FAMILY": + continue + elif Attr == "PATH": + ToolsDef.append("%s = %s" % (Tool, self._AutoGenObject.BuildOption[Tool][Attr])) + else: + ToolsDef.append("%s_%s = %s" % (Tool, Attr, self._AutoGenObject.BuildOption[Tool][Attr])) + ToolsDef.append("") + + MakefileName = self._FILE_NAME_[self._FileType] + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(MODULE_BUILD_DIR)", MakefileName), + "platform_name" : self.PlatformInfo.Name, + "platform_guid" : self.PlatformInfo.Guid, + "platform_version" : self.PlatformInfo.Version, + "platform_relative_directory": self.PlatformInfo.SourceDir, + "platform_output_directory" : self.PlatformInfo.OutputDir, + + "module_name" : self._AutoGenObject.Name, + "module_guid" : self._AutoGenObject.Guid, + "module_version" : self._AutoGenObject.Version, + "module_type" : self._AutoGenObject.ModuleType, + "module_file" : self._AutoGenObject.MetaFile, + "module_file_base_name" : self._AutoGenObject.MetaFile.BaseName, + "module_relative_directory" : self._AutoGenObject.SourceDir, + + "architecture" : self._AutoGenObject.Arch, + "toolchain_tag" : self._AutoGenObject.ToolChain, + "build_target" : self._AutoGenObject.BuildTarget, + + "platform_build_directory" : self.PlatformInfo.BuildDir, + "module_build_directory" : self._AutoGenObject.BuildDir, + "module_output_directory" : self._AutoGenObject.OutputDir, + "module_debug_directory" : self._AutoGenObject.DebugDir, + + "separator" : Separator, + "module_tool_definitions" : ToolsDef, + + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "custom_makefile_content" : CustomMakefile + } + + return MakefileTemplateDict + + _TemplateDict = property(_CreateTemplateDict) + +## PlatformMakefile class +# +# This class encapsules makefie and its generation for platform. It uses +# template to generate the content of makefile. The content of makefile will be +# got from PlatformAutoGen object. +# +class PlatformMakefile(BuildFile): + ## template used to generate the makefile for platform + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} +PLATFORM_FILE = ${platform_file} +PLATFORM_DIR = $(WORKSPACE)${separator}${platform_relative_directory} +PLATFORM_OUTPUT_DIR = ${platform_output_directory} + +# +# Build Configuration Macro Definition +# +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +BUILD_DIR = ${platform_build_directory} +FV_DIR = ${platform_build_directory}${separator}FV + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +MAKE = ${make_path} +MAKE_FILE = ${makefile_path} + +# +# Default target +# +all: init build_libraries build_modules + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@echo Building ... $(PLATFORM_FILE) [${build_architecture_list}] +\t${BEGIN}-@${create_directory_command} +\t${END} +# +# library build target +# +libraries: init build_libraries + +# +# module build target +# +modules: init build_libraries build_modules + +# +# Build all libraries: +# +build_libraries: +${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${library_makefile_list} pbuild +${END}\t@cd $(BUILD_DIR) + +# +# Build all modules: +# +build_modules: +${BEGIN}\t@"$(MAKE)" $(MAKE_FLAGS) -f ${module_makefile_list} pbuild +${END}\t@cd $(BUILD_DIR) + +# +# Clean intermediate files +# +clean: +\t${BEGIN}-@${library_build_command} clean +\t${END}${BEGIN}-@${module_build_command} clean +\t${END}@cd $(BUILD_DIR) + +# +# Clean all generated files except to makefile +# +cleanall: +${BEGIN}\t${cleanall_command} +${END} + +# +# Clean all library files +# +cleanlib: +\t${BEGIN}-@${library_build_command} cleanall +\t${END}@cd $(BUILD_DIR)\n +''') + + ## Constructor of PlatformMakefile + # + # @param ModuleAutoGen Object of PlatformAutoGen class + # + def __init__(self, PlatformAutoGen): + BuildFile.__init__(self, PlatformAutoGen) + self.ModuleBuildCommandList = [] + self.ModuleMakefileList = [] + self.IntermediateDirectoryList = [] + self.ModuleBuildDirectoryList = [] + self.LibraryBuildDirectoryList = [] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + Separator = self._SEP_[self._FileType] + + PlatformInfo = self._AutoGenObject + if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: + EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", + ExtraData="[%s]" % str(self._AutoGenObject)) + + self.IntermediateDirectoryList = ["$(BUILD_DIR)"] + self.ModuleBuildDirectoryList = self.GetModuleBuildDirectoryList() + self.LibraryBuildDirectoryList = self.GetLibraryBuildDirectoryList() + + MakefileName = self._FILE_NAME_[self._FileType] + LibraryMakefileList = [] + LibraryMakeCommandList = [] + for D in self.LibraryBuildDirectoryList: + D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) + Makefile = os.path.join(D, MakefileName) + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} + LibraryMakefileList.append(Makefile) + LibraryMakeCommandList.append(Command) + + ModuleMakefileList = [] + ModuleMakeCommandList = [] + for D in self.ModuleBuildDirectoryList: + D = self.PlaceMacro(D, {"BUILD_DIR":PlatformInfo.BuildDir}) + Makefile = os.path.join(D, MakefileName) + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":Makefile} + ModuleMakefileList.append(Makefile) + ModuleMakeCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), + "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], + "makefile_name" : MakefileName, + "platform_name" : PlatformInfo.Name, + "platform_guid" : PlatformInfo.Guid, + "platform_version" : PlatformInfo.Version, + "platform_file" : self._AutoGenObject.MetaFile, + "platform_relative_directory": PlatformInfo.SourceDir, + "platform_output_directory" : PlatformInfo.OutputDir, + "platform_build_directory" : PlatformInfo.BuildDir, + + "toolchain_tag" : PlatformInfo.ToolChain, + "build_target" : PlatformInfo.BuildTarget, + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + "build_architecture_list" : self._AutoGenObject.Arch, + "architecture" : self._AutoGenObject.Arch, + "separator" : Separator, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), + "library_makefile_list" : LibraryMakefileList, + "module_makefile_list" : ModuleMakefileList, + "library_build_command" : LibraryMakeCommandList, + "module_build_command" : ModuleMakeCommandList, + } + + return MakefileTemplateDict + + ## Get the root directory list for intermediate files of all modules build + # + # @retval list The list of directory + # + def GetModuleBuildDirectoryList(self): + DirList = [] + for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) + return DirList + + ## Get the root directory list for intermediate files of all libraries build + # + # @retval list The list of directory + # + def GetLibraryBuildDirectoryList(self): + DirList = [] + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) + return DirList + + _TemplateDict = property(_CreateTemplateDict) + +## TopLevelMakefile class +# +# This class encapsules makefie and its generation for entrance makefile. It +# uses template to generate the content of makefile. The content of makefile +# will be got from WorkspaceAutoGen object. +# +class TopLevelMakefile(BuildFile): + ## template used to generate toplevel makefile + _TEMPLATE_ = TemplateString('''\ +${makefile_header} + +# +# Platform Macro Definition +# +PLATFORM_NAME = ${platform_name} +PLATFORM_GUID = ${platform_guid} +PLATFORM_VERSION = ${platform_version} + +# +# Build Configuration Macro Definition +# +TOOLCHAIN = ${toolchain_tag} +TOOLCHAIN_TAG = ${toolchain_tag} +TARGET = ${build_target} + +# +# Build Directory Macro Definition +# +BUILD_DIR = ${platform_build_directory} +FV_DIR = ${platform_build_directory}${separator}FV + +# +# Shell Command Macro +# +${BEGIN}${shell_command_code} = ${shell_command} +${END} + +MAKE = ${make_path} +MAKE_FILE = ${makefile_path} + +# +# Default target +# +all: modules fds + +# +# Initialization target: print build information and create necessary directories +# +init: +\t-@ +\t${BEGIN}-@${create_directory_command} +\t${END} +# +# library build target +# +libraries: init +${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) libraries +${END}\t@cd $(BUILD_DIR) + +# +# module build target +# +modules: init +${BEGIN}\t@cd $(BUILD_DIR)${separator}${arch} && "$(MAKE)" $(MAKE_FLAGS) modules +${END}\t@cd $(BUILD_DIR) + +# +# Flash Device Image Target +# +fds: init +\t-@cd $(FV_DIR) +${BEGIN}\tGenFds -f ${fdf_file} -o $(BUILD_DIR) -t $(TOOLCHAIN) -b $(TARGET) -p ${active_platform} -a ${build_architecture_list} ${extra_options}${END}${BEGIN} -r ${fd} ${END}${BEGIN} -i ${fv} ${END}${BEGIN} -C ${cap} ${END}${BEGIN} -D ${macro} ${END} + +# +# run command for emulator platform only +# +run: +\tcd $(BUILD_DIR)${separator}IA32 && ".${separator}SecMain" +\tcd $(BUILD_DIR) + +# +# Clean intermediate files +# +clean: +${BEGIN}\t-@${sub_build_command} clean +${END}\t@cd $(BUILD_DIR) + +# +# Clean all generated files except to makefile +# +cleanall: +${BEGIN}\t${cleanall_command} +${END} + +# +# Clean all library files +# +cleanlib: +${BEGIN}\t-@${sub_build_command} cleanlib +${END}\t@cd $(BUILD_DIR)\n +''') + + ## Constructor of TopLevelMakefile + # + # @param Workspace Object of WorkspaceAutoGen class + # + def __init__(self, Workspace): + BuildFile.__init__(self, Workspace) + self.IntermediateDirectoryList = [] + + # Compose a dict object containing information used to do replacement in template + def _CreateTemplateDict(self): + Separator = self._SEP_[self._FileType] + + # any platform autogen object is ok because we just need common information + PlatformInfo = self._AutoGenObject + + if "MAKE" not in PlatformInfo.ToolDefinition or "PATH" not in PlatformInfo.ToolDefinition["MAKE"]: + EdkLogger.error("build", OPTION_MISSING, "No MAKE command defined. Please check your tools_def.txt!", + ExtraData="[%s]" % str(self._AutoGenObject)) + + for Arch in PlatformInfo.ArchList: + self.IntermediateDirectoryList.append(Separator.join(["$(BUILD_DIR)", Arch])) + self.IntermediateDirectoryList.append("$(FV_DIR)") + + # TRICK: for not generating GenFds call in makefile if no FDF file + MacroList = [] + if PlatformInfo.FdfFile != None and PlatformInfo.FdfFile != "": + FdfFileList = [PlatformInfo.FdfFile] + # macros passed to GenFds + MacroList.append('"%s=%s"' % ("EFI_SOURCE", GlobalData.gEfiSource.replace('\\', '\\\\'))) + MacroList.append('"%s=%s"' % ("EDK_SOURCE", GlobalData.gEdkSource.replace('\\', '\\\\'))) + MacroDict = {} + MacroDict.update(GlobalData.gGlobalDefines) + MacroDict.update(GlobalData.gCommandLineDefines) + MacroDict.pop("EFI_SOURCE", "dummy") + MacroDict.pop("EDK_SOURCE", "dummy") + for MacroName in MacroDict: + if MacroDict[MacroName] != "": + MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\'))) + else: + MacroList.append('"%s"' % MacroName) + else: + FdfFileList = [] + + # pass extra common options to external program called in makefile, currently GenFds.exe + ExtraOption = '' + LogLevel = EdkLogger.GetLevel() + if LogLevel == EdkLogger.VERBOSE: + ExtraOption += " -v" + elif LogLevel <= EdkLogger.DEBUG_9: + ExtraOption += " -d %d" % (LogLevel - 1) + elif LogLevel == EdkLogger.QUIET: + ExtraOption += " -q" + + if GlobalData.gCaseInsensitive: + ExtraOption += " -c" + + MakefileName = self._FILE_NAME_[self._FileType] + SubBuildCommandList = [] + for A in PlatformInfo.ArchList: + Command = self._MAKE_TEMPLATE_[self._FileType] % {"file":os.path.join("$(BUILD_DIR)", A, MakefileName)} + SubBuildCommandList.append(Command) + + MakefileTemplateDict = { + "makefile_header" : self._FILE_HEADER_[self._FileType], + "makefile_path" : os.path.join("$(BUILD_DIR)", MakefileName), + "make_path" : PlatformInfo.ToolDefinition["MAKE"]["PATH"], + "platform_name" : PlatformInfo.Name, + "platform_guid" : PlatformInfo.Guid, + "platform_version" : PlatformInfo.Version, + "platform_build_directory" : PlatformInfo.BuildDir, + + "toolchain_tag" : PlatformInfo.ToolChain, + "build_target" : PlatformInfo.BuildTarget, + "shell_command_code" : self._SHELL_CMD_[self._FileType].keys(), + "shell_command" : self._SHELL_CMD_[self._FileType].values(), + 'arch' : list(PlatformInfo.ArchList), + "build_architecture_list" : ','.join(PlatformInfo.ArchList), + "separator" : Separator, + "create_directory_command" : self.GetCreateDirectoryCommand(self.IntermediateDirectoryList), + "cleanall_command" : self.GetRemoveDirectoryCommand(self.IntermediateDirectoryList), + "sub_build_command" : SubBuildCommandList, + "fdf_file" : FdfFileList, + "active_platform" : str(PlatformInfo), + "fd" : PlatformInfo.FdTargetList, + "fv" : PlatformInfo.FvTargetList, + "cap" : PlatformInfo.CapTargetList, + "extra_options" : ExtraOption, + "macro" : MacroList, + } + + return MakefileTemplateDict + + ## Get the root directory list for intermediate files of all modules build + # + # @retval list The list of directory + # + def GetModuleBuildDirectoryList(self): + DirList = [] + for ModuleAutoGen in self._AutoGenObject.ModuleAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, ModuleAutoGen.BuildDir)) + return DirList + + ## Get the root directory list for intermediate files of all libraries build + # + # @retval list The list of directory + # + def GetLibraryBuildDirectoryList(self): + DirList = [] + for LibraryAutoGen in self._AutoGenObject.LibraryAutoGenList: + DirList.append(os.path.join(self._AutoGenObject.BuildDir, LibraryAutoGen.BuildDir)) + return DirList + + _TemplateDict = property(_CreateTemplateDict) + +# This acts like the main() function for the script, unless it is 'import'ed into another script. +if __name__ == '__main__': + pass + -- cgit v1.2.3