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