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