]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/GenFds.py
MdeModulePkg EhciPei: Remove a redundant function
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / GenFds.py
CommitLineData
f51461c8
LG
1## @file\r
2# generate flash image\r
3#\r
541a3f58 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
f51461c8
LG
5#\r
6# This program and the accompanying materials\r
7# are licensed and made available under the terms and conditions of the BSD License\r
8# which accompanies this distribution. The full text of the license may be found at\r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14\r
15##\r
16# Import Modules\r
17#\r
72443dd2 18from __future__ import print_function\r
bfa65b61 19from __future__ import absolute_import\r
f51461c8
LG
20from optparse import OptionParser\r
21import sys\r
1be2ed90 22import Common.LongFilePathOs as os\r
f51461c8 23import linecache\r
bfa65b61 24from . import FdfParser\r
f51461c8 25import Common.BuildToolError as BuildToolError\r
bfa65b61 26from .GenFdsGlobalVariable import GenFdsGlobalVariable\r
f51461c8
LG
27from Workspace.WorkspaceDatabase import WorkspaceDatabase\r
28from Workspace.BuildClassObject import PcdClassObject\r
bfa65b61
GL
29from . import RuleComplexFile\r
30from .EfiSection import EfiSection\r
86379ac4 31from io import BytesIO\r
f51461c8
LG
32import Common.TargetTxtClassObject as TargetTxtClassObject\r
33import Common.ToolDefClassObject as ToolDefClassObject\r
95816356 34from Common.DataType import *\r
f51461c8
LG
35import Common.GlobalData as GlobalData\r
36from Common import EdkLogger\r
5a57246e 37from Common.StringUtils import *\r
47fea6af 38from Common.Misc import DirCache, PathClass\r
f51461c8 39from Common.Misc import SaveFileOnChange\r
97fa0ee9 40from Common.Misc import ClearDuplicatedInf\r
e4ac870f 41from Common.Misc import GuidStructureStringToGuidString\r
f51461c8 42from Common.BuildVersion import gBUILD_VERSION\r
05cc51ad 43from Common.MultipleWorkspace import MultipleWorkspace as mws\r
bfa65b61 44from . import FfsFileStatement\r
5e9256cd
YZ
45import glob\r
46from struct import unpack\r
cefc8d88 47from Common.GlobalData import gGuidPattern\r
f51461c8
LG
48\r
49## Version and Copyright\r
50versionNumber = "1.0" + ' ' + gBUILD_VERSION\r
51__version__ = "%prog Version " + versionNumber\r
f7496d71 52__copyright__ = "Copyright (c) 2007 - 2018, Intel Corporation All rights reserved."\r
f51461c8
LG
53\r
54## Tool entrance method\r
55#\r
56# This method mainly dispatch specific methods per the command line options.\r
57# If no error found, return zero value so the caller of this tool can know\r
58# if it's executed successfully or not.\r
59#\r
60# @retval 0 Tool was successful\r
61# @retval 1 Tool failed\r
62#\r
63def main():\r
64 global Options\r
65 Options = myOptionParser()\r
66\r
67 global Workspace\r
68 Workspace = ""\r
69 ArchList = None\r
70 ReturnCode = 0\r
71\r
72 EdkLogger.Initialize()\r
73 try:\r
4231a819 74 if Options.verbose is not None:\r
f51461c8
LG
75 EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
76 GenFdsGlobalVariable.VerboseMode = True\r
f7496d71 77\r
4231a819 78 if Options.FixedAddress is not None:\r
f51461c8 79 GenFdsGlobalVariable.FixedLoadAddress = True\r
f7496d71 80\r
4231a819 81 if Options.quiet is not None:\r
f51461c8 82 EdkLogger.SetLevel(EdkLogger.QUIET)\r
4231a819 83 if Options.debug is not None:\r
f51461c8
LG
84 EdkLogger.SetLevel(Options.debug + 1)\r
85 GenFdsGlobalVariable.DebugLevel = Options.debug\r
86 else:\r
87 EdkLogger.SetLevel(EdkLogger.INFO)\r
88\r
4231a819 89 if (Options.Workspace is None):\r
f51461c8
LG
90 EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",\r
91 ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")\r
92 elif not os.path.exists(Options.Workspace):\r
93 EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",\r
94 ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")\r
95 else:\r
96 Workspace = os.path.normcase(Options.Workspace)\r
97 GenFdsGlobalVariable.WorkSpaceDir = Workspace\r
9eb87141 98 if 'EDK_SOURCE' in os.environ:\r
f51461c8
LG
99 GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE'])\r
100 if (Options.debug):\r
47fea6af 101 GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace)\r
37de70b7
YZ
102 if Options.GenfdsMultiThread:\r
103 GenFdsGlobalVariable.EnableGenfdsMultiThread = True\r
f51461c8 104 os.chdir(GenFdsGlobalVariable.WorkSpaceDir)\r
f7496d71 105\r
05cc51ad
LY
106 # set multiple workspace\r
107 PackagesPath = os.getenv("PACKAGES_PATH")\r
108 mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)\r
f51461c8
LG
109\r
110 if (Options.filename):\r
111 FdfFilename = Options.filename\r
112 FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)\r
113\r
114 if FdfFilename[0:2] == '..':\r
115 FdfFilename = os.path.realpath(FdfFilename)\r
47fea6af 116 if not os.path.isabs(FdfFilename):\r
05cc51ad 117 FdfFilename = mws.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename)\r
f51461c8
LG
118 if not os.path.exists(FdfFilename):\r
119 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=FdfFilename)\r
f51461c8
LG
120\r
121 GenFdsGlobalVariable.FdfFile = FdfFilename\r
122 GenFdsGlobalVariable.FdfFileTimeStamp = os.path.getmtime(FdfFilename)\r
123 else:\r
124 EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename")\r
125\r
126 if (Options.BuildTarget):\r
127 GenFdsGlobalVariable.TargetName = Options.BuildTarget\r
f51461c8
LG
128\r
129 if (Options.ToolChain):\r
130 GenFdsGlobalVariable.ToolChainTag = Options.ToolChain\r
f51461c8
LG
131\r
132 if (Options.activePlatform):\r
133 ActivePlatform = Options.activePlatform\r
134 ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)\r
135\r
136 if ActivePlatform[0:2] == '..':\r
137 ActivePlatform = os.path.realpath(ActivePlatform)\r
138\r
139 if not os.path.isabs (ActivePlatform):\r
05cc51ad 140 ActivePlatform = mws.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform)\r
f51461c8
LG
141\r
142 if not os.path.exists(ActivePlatform) :\r
143 EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!")\r
f51461c8
LG
144 else:\r
145 EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")\r
146\r
705ed563 147 GlobalData.BuildOptionPcd = Options.OptionPcd if Options.OptionPcd else {}\r
e642ceb8 148 GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform))\r
f51461c8 149\r
97fa0ee9
YL
150 if (Options.ConfDirectory):\r
151 # Get alternate Conf location, if it is absolute, then just use the absolute directory name\r
152 ConfDirectoryPath = os.path.normpath(Options.ConfDirectory)\r
153 if ConfDirectoryPath.startswith('"'):\r
154 ConfDirectoryPath = ConfDirectoryPath[1:]\r
155 if ConfDirectoryPath.endswith('"'):\r
156 ConfDirectoryPath = ConfDirectoryPath[:-1]\r
157 if not os.path.isabs(ConfDirectoryPath):\r
158 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE\r
159 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf\r
160 ConfDirectoryPath = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ConfDirectoryPath)\r
161 else:\r
9eb87141 162 if "CONF_PATH" in os.environ:\r
00bcb5c2
YZ
163 ConfDirectoryPath = os.path.normcase(os.environ["CONF_PATH"])\r
164 else:\r
165 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf\r
166 ConfDirectoryPath = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 'Conf')\r
97fa0ee9 167 GenFdsGlobalVariable.ConfDir = ConfDirectoryPath\r
541a3f58
FY
168 if not GlobalData.gConfDirectory:\r
169 GlobalData.gConfDirectory = GenFdsGlobalVariable.ConfDir\r
97fa0ee9 170 BuildConfigurationFile = os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt"))\r
f51461c8 171 if os.path.isfile(BuildConfigurationFile) == True:\r
e4979bee
YZ
172 TargetTxt = TargetTxtClassObject.TargetTxtClassObject()\r
173 TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)\r
174 # if no build target given in command line, get it from target.txt\r
175 if not GenFdsGlobalVariable.TargetName:\r
176 BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET]\r
177 if len(BuildTargetList) != 1:\r
178 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")\r
179 GenFdsGlobalVariable.TargetName = BuildTargetList[0]\r
180\r
181 # if no tool chain given in command line, get it from target.txt\r
182 if not GenFdsGlobalVariable.ToolChainTag:\r
183 ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]\r
4231a819 184 if ToolChainList is None or len(ToolChainList) == 0:\r
e4979bee
YZ
185 EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")\r
186 if len(ToolChainList) != 1:\r
187 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for ToolChain.")\r
188 GenFdsGlobalVariable.ToolChainTag = ToolChainList[0]\r
f51461c8
LG
189 else:\r
190 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)\r
191\r
97fa0ee9
YL
192 #Set global flag for build mode\r
193 GlobalData.gIgnoreSource = Options.IgnoreSources\r
194\r
f51461c8
LG
195 if Options.Macros:\r
196 for Pair in Options.Macros:\r
97fa0ee9
YL
197 if Pair.startswith('"'):\r
198 Pair = Pair[1:]\r
199 if Pair.endswith('"'):\r
200 Pair = Pair[:-1]\r
f51461c8
LG
201 List = Pair.split('=')\r
202 if len(List) == 2:\r
e4979bee
YZ
203 if not List[1].strip():\r
204 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="No Value given for Macro %s" %List[0])\r
f51461c8
LG
205 if List[0].strip() == "EFI_SOURCE":\r
206 GlobalData.gEfiSource = List[1].strip()\r
207 GlobalData.gGlobalDefines["EFI_SOURCE"] = GlobalData.gEfiSource\r
208 continue\r
209 elif List[0].strip() == "EDK_SOURCE":\r
210 GlobalData.gEdkSource = List[1].strip()\r
211 GlobalData.gGlobalDefines["EDK_SOURCE"] = GlobalData.gEdkSource\r
212 continue\r
213 elif List[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:\r
214 GlobalData.gGlobalDefines[List[0].strip()] = List[1].strip()\r
215 else:\r
216 GlobalData.gCommandLineDefines[List[0].strip()] = List[1].strip()\r
217 else:\r
218 GlobalData.gCommandLineDefines[List[0].strip()] = "TRUE"\r
219 os.environ["WORKSPACE"] = Workspace\r
220\r
e4979bee 221 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined\r
9eb87141 222 if "TARGET" not in GlobalData.gGlobalDefines:\r
e4979bee 223 GlobalData.gGlobalDefines["TARGET"] = GenFdsGlobalVariable.TargetName\r
9eb87141 224 if "TOOLCHAIN" not in GlobalData.gGlobalDefines:\r
e4979bee 225 GlobalData.gGlobalDefines["TOOLCHAIN"] = GenFdsGlobalVariable.ToolChainTag\r
9eb87141 226 if "TOOL_CHAIN_TAG" not in GlobalData.gGlobalDefines:\r
e4979bee
YZ
227 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable.ToolChainTag\r
228\r
f51461c8 229 """call Workspace build create database"""\r
97fa0ee9
YL
230 GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))\r
231 BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)\r
f51461c8 232 BuildWorkSpace.InitDatabase()\r
f7496d71 233\r
f51461c8
LG
234 #\r
235 # Get files real name in workspace dir\r
236 #\r
237 GlobalData.gAllFiles = DirCache(Workspace)\r
238 GlobalData.gWorkspace = Workspace\r
239\r
240 if (Options.archList) :\r
241 ArchList = Options.archList.split(',')\r
242 else:\r
243# EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")\r
55c84777 244 ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList\r
f51461c8 245\r
55c84777 246 TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON, Options.BuildTarget, Options.ToolChain].SupArchList) & set(ArchList)\r
f51461c8 247 if len(TargetArchList) == 0:\r
55c84777 248 EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, TAB_COMMON].SupArchList)))\r
f7496d71 249\r
f51461c8
LG
250 for Arch in ArchList:\r
251 GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].OutputDirectory)\r
252 GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].PlatformName\r
253\r
254 if (Options.outputDir):\r
255 OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)\r
256 if not os.path.isabs (OutputDirFromCommandLine):\r
257 OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine)\r
258 for Arch in ArchList:\r
259 GenFdsGlobalVariable.OutputDirDict[Arch] = OutputDirFromCommandLine\r
260 else:\r
261 for Arch in ArchList:\r
262 GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.join(GenFdsGlobalVariable.OutputDirFromDscDict[Arch], GenFdsGlobalVariable.TargetName + '_' + GenFdsGlobalVariable.ToolChainTag)\r
263\r
264 for Key in GenFdsGlobalVariable.OutputDirDict:\r
265 OutputDir = GenFdsGlobalVariable.OutputDirDict[Key]\r
266 if OutputDir[0:2] == '..':\r
267 OutputDir = os.path.realpath(OutputDir)\r
268\r
269 if OutputDir[1] != ':':\r
270 OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir)\r
271\r
272 if not os.path.exists(OutputDir):\r
273 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=OutputDir)\r
274 GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir\r
275\r
276 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """\r
277 FdfParserObj = FdfParser.FdfParser(FdfFilename)\r
278 FdfParserObj.ParseFile()\r
279\r
280 if FdfParserObj.CycleReferenceCheck():\r
281 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file")\r
282\r
283 if (Options.uiFdName) :\r
9eb87141 284 if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict:\r
f51461c8
LG
285 GenFds.OnlyGenerateThisFd = Options.uiFdName\r
286 else:\r
287 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,\r
288 "No such an FD in FDF file: %s" % Options.uiFdName)\r
289\r
290 if (Options.uiFvName) :\r
9eb87141 291 if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict:\r
f51461c8
LG
292 GenFds.OnlyGenerateThisFv = Options.uiFvName\r
293 else:\r
294 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,\r
295 "No such an FV in FDF file: %s" % Options.uiFvName)\r
296\r
297 if (Options.uiCapName) :\r
9eb87141 298 if Options.uiCapName.upper() in FdfParserObj.Profile.CapsuleDict:\r
f51461c8
LG
299 GenFds.OnlyGenerateThisCap = Options.uiCapName\r
300 else:\r
301 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,\r
302 "No such a Capsule in FDF file: %s" % Options.uiCapName)\r
303\r
6b17c11b 304 GenFdsGlobalVariable.WorkSpace = BuildWorkSpace\r
4231a819 305 if ArchList is not None:\r
6b17c11b
YZ
306 GenFdsGlobalVariable.ArchList = ArchList\r
307\r
6f49996c 308 # Dsc Build Data will handle Pcd Settings from CommandLine.\r
6b17c11b 309\r
f51461c8
LG
310 """Modify images from build output if the feature of loading driver at fixed address is on."""\r
311 if GenFdsGlobalVariable.FixedLoadAddress:\r
312 GenFds.PreprocessImage(BuildWorkSpace, GenFdsGlobalVariable.ActivePlatform)\r
135ae8c8
YZ
313\r
314 # Record the FV Region info that may specific in the FD\r
315 if FdfParserObj.Profile.FvDict and FdfParserObj.Profile.FdDict:\r
316 for Fv in FdfParserObj.Profile.FvDict:\r
317 FvObj = FdfParserObj.Profile.FvDict[Fv]\r
318 for Fd in FdfParserObj.Profile.FdDict:\r
319 FdObj = FdfParserObj.Profile.FdDict[Fd]\r
320 for RegionObj in FdObj.RegionList:\r
91fa33ee 321 if RegionObj.RegionType != BINARY_FILE_TYPE_FV:\r
135ae8c8
YZ
322 continue\r
323 for RegionData in RegionObj.RegionDataList:\r
324 if FvObj.UiFvName.upper() == RegionData.upper():\r
325 if FvObj.FvRegionInFD:\r
326 if FvObj.FvRegionInFD != RegionObj.Size:\r
327 EdkLogger.error("GenFds", FORMAT_INVALID, "The FV %s's region is specified in multiple FD with different value." %FvObj.UiFvName)\r
328 else:\r
329 FvObj.FvRegionInFD = RegionObj.Size\r
330 RegionObj.BlockInfoOfRegion(FdObj.BlockSizeList, FvObj)\r
331\r
f51461c8
LG
332 """Call GenFds"""\r
333 GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList)\r
334\r
335 """Generate GUID cross reference file"""\r
5e9256cd 336 GenFds.GenerateGuidXRefFile(BuildWorkSpace, ArchList, FdfParserObj)\r
f51461c8
LG
337\r
338 """Display FV space info."""\r
339 GenFds.DisplayFvSpaceInfo(FdfParserObj)\r
340\r
5b0671c1 341 except FdfParser.Warning as X:\r
47fea6af 342 EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)\r
f51461c8 343 ReturnCode = FORMAT_INVALID\r
5b0671c1 344 except FatalError as X:\r
4231a819 345 if Options.debug is not None:\r
f51461c8
LG
346 import traceback\r
347 EdkLogger.quiet(traceback.format_exc())\r
348 ReturnCode = X.args[0]\r
349 except:\r
350 import traceback\r
351 EdkLogger.error(\r
352 "\nPython",\r
353 CODE_ERROR,\r
354 "Tools code failure",\r
3a0f8bde 355 ExtraData="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",\r
f51461c8
LG
356 RaiseError=False\r
357 )\r
358 EdkLogger.quiet(traceback.format_exc())\r
359 ReturnCode = CODE_ERROR\r
97fa0ee9
YL
360 finally:\r
361 ClearDuplicatedInf()\r
f51461c8
LG
362 return ReturnCode\r
363\r
364gParamCheck = []\r
365def SingleCheckCallback(option, opt_str, value, parser):\r
366 if option not in gParamCheck:\r
367 setattr(parser.values, option.dest, value)\r
368 gParamCheck.append(option)\r
369 else:\r
370 parser.error("Option %s only allows one instance in command line!" % option)\r
6b17c11b 371\r
f51461c8
LG
372## Parse command line options\r
373#\r
374# Using standard Python module optparse to parse command line option of this tool.\r
375#\r
376# @retval Opt A optparse.Values object containing the parsed options\r
377# @retval Args Target of build command\r
378#\r
379def myOptionParser():\r
380 usage = "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""\r
47fea6af 381 Parser = OptionParser(usage=usage, description=__copyright__, version="%prog " + str(versionNumber))\r
f51461c8
LG
382 Parser.add_option("-f", "--file", dest="filename", type="string", help="Name of FDF file to convert", action="callback", callback=SingleCheckCallback)\r
383 Parser.add_option("-a", "--arch", dest="archList", help="comma separated list containing one or more of: IA32, X64, IPF, ARM, AARCH64 or EBC which should be built, overrides target.txt?s TARGET_ARCH")\r
384 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")\r
385 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.")\r
386 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r
387 Parser.add_option("-p", "--platform", type="string", dest="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",\r
388 action="callback", callback=SingleCheckCallback)\r
389 Parser.add_option("-w", "--workspace", type="string", dest="Workspace", default=os.environ.get('WORKSPACE'), help="Set the WORKSPACE",\r
390 action="callback", callback=SingleCheckCallback)\r
391 Parser.add_option("-o", "--outputDir", type="string", dest="outputDir", help="Name of Build Output directory",\r
392 action="callback", callback=SingleCheckCallback)\r
393 Parser.add_option("-r", "--rom_image", dest="uiFdName", help="Build the image using the [FD] section named by FdUiName.")\r
394 Parser.add_option("-i", "--FvImage", dest="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")\r
395 Parser.add_option("-C", "--CapsuleImage", dest="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")\r
396 Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",\r
397 action="callback", callback=SingleCheckCallback)\r
398 Parser.add_option("-t", "--tagname", type="string", dest="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",\r
399 action="callback", callback=SingleCheckCallback)\r
400 Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")\r
401 Parser.add_option("-s", "--specifyaddress", dest="FixedAddress", action="store_true", type=None, help="Specify driver load address.")\r
97fa0ee9
YL
402 Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")\r
403 Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")\r
6b17c11b 404 Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")\r
37de70b7 405 Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=False, help="Enable GenFds multi thread to generate ffs file.")\r
97fa0ee9 406\r
f51461c8
LG
407 (Options, args) = Parser.parse_args()\r
408 return Options\r
409\r
410## The class implementing the EDK2 flash image generation process\r
411#\r
412# This process includes:\r
413# 1. Collect workspace information, includes platform and module information\r
414# 2. Call methods of Fd class to generate FD\r
415# 3. Call methods of Fv class to generate FV that not belong to FD\r
416#\r
417class GenFds :\r
418 FdfParsef = None\r
f51461c8
LG
419 OnlyGenerateThisFd = None\r
420 OnlyGenerateThisFv = None\r
421 OnlyGenerateThisCap = None\r
422\r
423 ## GenFd()\r
424 #\r
425 # @param OutputDir Output directory\r
426 # @param FdfParser FDF contents parser\r
427 # @param Workspace The directory of workspace\r
428 # @param ArchList The Arch list of platform\r
429 #\r
430 def GenFd (OutputDir, FdfParser, WorkSpace, ArchList):\r
431 GenFdsGlobalVariable.SetDir ('', FdfParser, WorkSpace, ArchList)\r
432\r
433 GenFdsGlobalVariable.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")\r
9eb87141
CJ
434 if GenFds.OnlyGenerateThisCap is not None and GenFds.OnlyGenerateThisCap.upper() in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict:\r
435 CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict[GenFds.OnlyGenerateThisCap.upper()]\r
4231a819 436 if CapsuleObj is not None:\r
f51461c8
LG
437 CapsuleObj.GenCapsule()\r
438 return\r
439\r
9eb87141
CJ
440 if GenFds.OnlyGenerateThisFd is not None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict:\r
441 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()]\r
4231a819 442 if FdObj is not None:\r
f51461c8
LG
443 FdObj.GenFd()\r
444 return\r
4231a819 445 elif GenFds.OnlyGenerateThisFd is None and GenFds.OnlyGenerateThisFv is None:\r
9eb87141 446 for FdObj in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():\r
f51461c8
LG
447 FdObj.GenFd()\r
448\r
449 GenFdsGlobalVariable.VerboseLogger("\n Generate other FV images! ")\r
9eb87141
CJ
450 if GenFds.OnlyGenerateThisFv is not None and GenFds.OnlyGenerateThisFv.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict:\r
451 FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[GenFds.OnlyGenerateThisFv.upper()]\r
4231a819 452 if FvObj is not None:\r
86379ac4 453 Buffer = BytesIO()\r
f51461c8
LG
454 FvObj.AddToBuffer(Buffer)\r
455 Buffer.close()\r
456 return\r
4231a819 457 elif GenFds.OnlyGenerateThisFv is None:\r
9eb87141 458 for FvObj in GenFdsGlobalVariable.FdfParser.Profile.FvDict.values():\r
86379ac4 459 Buffer = BytesIO('')\r
f51461c8
LG
460 FvObj.AddToBuffer(Buffer)\r
461 Buffer.close()\r
f7496d71 462\r
4231a819 463 if GenFds.OnlyGenerateThisFv is None and GenFds.OnlyGenerateThisFd is None and GenFds.OnlyGenerateThisCap is None:\r
f51461c8
LG
464 if GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict != {}:\r
465 GenFdsGlobalVariable.VerboseLogger("\n Generate other Capsule images!")\r
9eb87141 466 for CapsuleObj in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.values():\r
f51461c8
LG
467 CapsuleObj.GenCapsule()\r
468\r
469 if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}:\r
470 GenFdsGlobalVariable.VerboseLogger("\n Generate all Option ROM!")\r
9eb87141 471 for OptRomObj in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.values():\r
f51461c8 472 OptRomObj.AddToBuffer(None)\r
37de70b7
YZ
473 @staticmethod\r
474 def GenFfsMakefile(OutputDir, FdfParser, WorkSpace, ArchList, GlobalData):\r
475 GenFdsGlobalVariable.SetEnv(FdfParser, WorkSpace, ArchList, GlobalData)\r
9eb87141 476 for FdObj in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():\r
37de70b7
YZ
477 FdObj.GenFd(Flag=True)\r
478\r
9eb87141 479 for FvObj in GenFdsGlobalVariable.FdfParser.Profile.FvDict.values():\r
37de70b7
YZ
480 FvObj.AddToBuffer(Buffer=None, Flag=True)\r
481\r
482 if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}:\r
9eb87141 483 for OptRomObj in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.values():\r
37de70b7
YZ
484 OptRomObj.AddToBuffer(Buffer=None, Flag=True)\r
485\r
486 return GenFdsGlobalVariable.FfsCmdDict\r
f51461c8
LG
487\r
488 ## GetFvBlockSize()\r
489 #\r
490 # @param FvObj Whose block size to get\r
491 # @retval int Block size value\r
492 #\r
493 def GetFvBlockSize(FvObj):\r
494 DefaultBlockSize = 0x1\r
495 FdObj = None\r
9eb87141 496 if GenFds.OnlyGenerateThisFd is not None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict:\r
f51461c8 497 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()]\r
4231a819 498 if FdObj is None:\r
f51461c8
LG
499 for ElementFd in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():\r
500 for ElementRegion in ElementFd.RegionList:\r
91fa33ee 501 if ElementRegion.RegionType == BINARY_FILE_TYPE_FV:\r
f51461c8 502 for ElementRegionData in ElementRegion.RegionDataList:\r
4231a819 503 if ElementRegionData is not None and ElementRegionData.upper() == FvObj.UiFvName:\r
f51461c8
LG
504 if FvObj.BlockSizeList != []:\r
505 return FvObj.BlockSizeList[0][0]\r
506 else:\r
507 return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)\r
508 if FvObj.BlockSizeList != []:\r
509 return FvObj.BlockSizeList[0][0]\r
510 return DefaultBlockSize\r
511 else:\r
512 for ElementRegion in FdObj.RegionList:\r
91fa33ee 513 if ElementRegion.RegionType == BINARY_FILE_TYPE_FV:\r
f51461c8 514 for ElementRegionData in ElementRegion.RegionDataList:\r
4231a819 515 if ElementRegionData is not None and ElementRegionData.upper() == FvObj.UiFvName:\r
f51461c8
LG
516 if FvObj.BlockSizeList != []:\r
517 return FvObj.BlockSizeList[0][0]\r
518 else:\r
519 return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)\r
520 return DefaultBlockSize\r
521\r
522 ## DisplayFvSpaceInfo()\r
523 #\r
524 # @param FvObj Whose block size to get\r
525 # @retval None\r
526 #\r
527 def DisplayFvSpaceInfo(FdfParser):\r
f7496d71 528\r
f51461c8
LG
529 FvSpaceInfoList = []\r
530 MaxFvNameLength = 0\r
531 for FvName in FdfParser.Profile.FvDict:\r
532 if len(FvName) > MaxFvNameLength:\r
533 MaxFvNameLength = len(FvName)\r
534 FvSpaceInfoFileName = os.path.join(GenFdsGlobalVariable.FvDir, FvName.upper() + '.Fv.map')\r
535 if os.path.exists(FvSpaceInfoFileName):\r
536 FileLinesList = linecache.getlines(FvSpaceInfoFileName)\r
537 TotalFound = False\r
538 Total = ''\r
539 UsedFound = False\r
540 Used = ''\r
541 FreeFound = False\r
542 Free = ''\r
543 for Line in FileLinesList:\r
544 NameValue = Line.split('=')\r
545 if len(NameValue) == 2:\r
546 if NameValue[0].strip() == 'EFI_FV_TOTAL_SIZE':\r
547 TotalFound = True\r
548 Total = NameValue[1].strip()\r
549 if NameValue[0].strip() == 'EFI_FV_TAKEN_SIZE':\r
550 UsedFound = True\r
551 Used = NameValue[1].strip()\r
552 if NameValue[0].strip() == 'EFI_FV_SPACE_SIZE':\r
553 FreeFound = True\r
554 Free = NameValue[1].strip()\r
f7496d71 555\r
f51461c8
LG
556 if TotalFound and UsedFound and FreeFound:\r
557 FvSpaceInfoList.append((FvName, Total, Used, Free))\r
f7496d71 558\r
f51461c8
LG
559 GenFdsGlobalVariable.InfLogger('\nFV Space Information')\r
560 for FvSpaceInfo in FvSpaceInfoList:\r
561 Name = FvSpaceInfo[0]\r
562 TotalSizeValue = long(FvSpaceInfo[1], 0)\r
563 UsedSizeValue = long(FvSpaceInfo[2], 0)\r
564 FreeSizeValue = long(FvSpaceInfo[3], 0)\r
565 if UsedSizeValue == TotalSizeValue:\r
566 Percentage = '100'\r
567 else:\r
47fea6af
YZ
568 Percentage = str((UsedSizeValue + 0.0) / TotalSizeValue)[0:4].lstrip('0.')\r
569\r
f51461c8
LG
570 GenFdsGlobalVariable.InfLogger(Name + ' ' + '[' + Percentage + '%Full] ' + str(TotalSizeValue) + ' total, ' + str(UsedSizeValue) + ' used, ' + str(FreeSizeValue) + ' free')\r
571\r
572 ## PreprocessImage()\r
573 #\r
574 # @param BuildDb Database from build meta data files\r
575 # @param DscFile modules from dsc file will be preprocessed\r
576 # @retval None\r
577 #\r
578 def PreprocessImage(BuildDb, DscFile):\r
55c84777 579 PcdDict = BuildDb.BuildObject[DscFile, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Pcds\r
f51461c8
LG
580 PcdValue = ''\r
581 for Key in PcdDict:\r
582 PcdObj = PcdDict[Key]\r
583 if PcdObj.TokenCName == 'PcdBsBaseAddress':\r
584 PcdValue = PcdObj.DefaultValue\r
585 break\r
f7496d71 586\r
f51461c8
LG
587 if PcdValue == '':\r
588 return\r
f7496d71 589\r
f51461c8 590 Int64PcdValue = long(PcdValue, 0)\r
f7496d71 591 if Int64PcdValue == 0 or Int64PcdValue < -1:\r
f51461c8 592 return\r
f7496d71 593\r
f51461c8
LG
594 TopAddress = 0\r
595 if Int64PcdValue > 0:\r
596 TopAddress = Int64PcdValue\r
f7496d71 597\r
55c84777 598 ModuleDict = BuildDb.BuildObject[DscFile, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Modules\r
f51461c8 599 for Key in ModuleDict:\r
55c84777 600 ModuleObj = BuildDb.BuildObject[Key, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
72443dd2 601 print(ModuleObj.BaseName + ' ' + ModuleObj.ModuleType)\r
f51461c8 602\r
5e9256cd 603 def GenerateGuidXRefFile(BuildDb, ArchList, FdfParserObj):\r
f51461c8 604 GuidXRefFileName = os.path.join(GenFdsGlobalVariable.FvDir, "Guid.xref")\r
86379ac4 605 GuidXRefFile = BytesIO('')\r
e4ac870f 606 GuidDict = {}\r
5e9256cd
YZ
607 ModuleList = []\r
608 FileGuidList = []\r
cefc8d88 609 GuidPattern = gGuidPattern\r
f51461c8
LG
610 for Arch in ArchList:\r
611 PlatformDataBase = BuildDb.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
612 for ModuleFile in PlatformDataBase.Modules:\r
613 Module = BuildDb.BuildObject[ModuleFile, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
5e9256cd
YZ
614 if Module in ModuleList:\r
615 continue\r
616 else:\r
617 ModuleList.append(Module)\r
1d802e23
YF
618 GuidMatch = GuidPattern.match(ModuleFile.BaseName)\r
619 if GuidMatch is not None:\r
620 GuidXRefFile.write("%s %s\n" % (ModuleFile.BaseName, Module.BaseName))\r
621 else:\r
622 GuidXRefFile.write("%s %s\n" % (Module.Guid, Module.BaseName))\r
e4ac870f
LG
623 for key, item in Module.Protocols.items():\r
624 GuidDict[key] = item\r
625 for key, item in Module.Guids.items():\r
626 GuidDict[key] = item\r
627 for key, item in Module.Ppis.items():\r
628 GuidDict[key] = item\r
5e9256cd
YZ
629 for FvName in FdfParserObj.Profile.FvDict:\r
630 for FfsObj in FdfParserObj.Profile.FvDict[FvName].FfsList:\r
631 if not isinstance(FfsObj, FfsFileStatement.FileStatement):\r
632 InfPath = PathClass(NormPath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, FfsObj.InfFileName)))\r
633 FdfModule = BuildDb.BuildObject[InfPath, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
634 if FdfModule in ModuleList:\r
635 continue\r
636 else:\r
637 ModuleList.append(FdfModule)\r
638 GuidXRefFile.write("%s %s\n" % (FdfModule.Guid, FdfModule.BaseName))\r
639 for key, item in FdfModule.Protocols.items():\r
640 GuidDict[key] = item\r
641 for key, item in FdfModule.Guids.items():\r
642 GuidDict[key] = item\r
643 for key, item in FdfModule.Ppis.items():\r
644 GuidDict[key] = item\r
645 else:\r
646 FileStatementGuid = FfsObj.NameGuid\r
647 if FileStatementGuid in FileGuidList:\r
648 continue\r
649 else:\r
650 FileGuidList.append(FileStatementGuid)\r
651 Name = []\r
652 FfsPath = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')\r
653 FfsPath = glob.glob(os.path.join(FfsPath, FileStatementGuid) + '*')\r
654 if not FfsPath:\r
655 continue\r
656 if not os.path.exists(FfsPath[0]):\r
657 continue\r
658 MatchDict = {}\r
659 ReFileEnds = re.compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')\r
660 FileList = os.listdir(FfsPath[0])\r
661 for File in FileList:\r
662 Match = ReFileEnds.search(File)\r
663 if Match:\r
664 for Index in range(1, 8):\r
665 if Match.group(Index) and Match.group(Index) in MatchDict:\r
666 MatchDict[Match.group(Index)].append(File)\r
667 elif Match.group(Index):\r
668 MatchDict[Match.group(Index)] = [File]\r
669 if not MatchDict:\r
670 continue\r
671 if '.ui' in MatchDict:\r
672 for File in MatchDict['.ui']:\r
673 with open(os.path.join(FfsPath[0], File), 'rb') as F:\r
674 F.read()\r
675 length = F.tell()\r
676 F.seek(4)\r
677 TmpStr = unpack('%dh' % ((length - 4) / 2), F.read())\r
8252e6bf 678 Name = ''.join(chr(c) for c in TmpStr[:-1])\r
5e9256cd
YZ
679 else:\r
680 FileList = []\r
681 if 'fv.sec.txt' in MatchDict:\r
682 FileList = MatchDict['fv.sec.txt']\r
683 elif '.pe32.txt' in MatchDict:\r
684 FileList = MatchDict['.pe32.txt']\r
685 elif '.te.txt' in MatchDict:\r
686 FileList = MatchDict['.te.txt']\r
687 elif '.pic.txt' in MatchDict:\r
688 FileList = MatchDict['.pic.txt']\r
689 elif '.raw.txt' in MatchDict:\r
690 FileList = MatchDict['.raw.txt']\r
691 elif '.ffs.txt' in MatchDict:\r
692 FileList = MatchDict['.ffs.txt']\r
693 else:\r
694 pass\r
695 for File in FileList:\r
696 with open(os.path.join(FfsPath[0], File), 'r') as F:\r
697 Name.append((F.read().split()[-1]))\r
698 if not Name:\r
699 continue\r
700\r
0d1f5b2b 701 Name = ' '.join(Name) if isinstance(Name, type([])) else Name\r
5e9256cd
YZ
702 GuidXRefFile.write("%s %s\n" %(FileStatementGuid, Name))\r
703\r
e4ac870f
LG
704 # Append GUIDs, Protocols, and PPIs to the Xref file\r
705 GuidXRefFile.write("\n")\r
706 for key, item in GuidDict.items():\r
707 GuidXRefFile.write("%s %s\n" % (GuidStructureStringToGuidString(item).upper(), key))\r
708\r
f51461c8
LG
709 if GuidXRefFile.getvalue():\r
710 SaveFileOnChange(GuidXRefFileName, GuidXRefFile.getvalue(), False)\r
711 GenFdsGlobalVariable.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName)\r
712 elif os.path.exists(GuidXRefFileName):\r
713 os.remove(GuidXRefFileName)\r
714 GuidXRefFile.close()\r
715\r
716 ##Define GenFd as static function\r
717 GenFd = staticmethod(GenFd)\r
718 GetFvBlockSize = staticmethod(GetFvBlockSize)\r
719 DisplayFvSpaceInfo = staticmethod(DisplayFvSpaceInfo)\r
720 PreprocessImage = staticmethod(PreprocessImage)\r
721 GenerateGuidXRefFile = staticmethod(GenerateGuidXRefFile)\r
722\r
723if __name__ == '__main__':\r
724 r = main()\r
725 ## 0-127 is a safe return range, and 1 is a standard default error\r
726 if r < 0 or r > 127: r = 1\r
727 sys.exit(r)\r
728\r