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