]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools: Update --pcd parser to support flexible pcd format
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FfsInfStatement.py
... / ...
CommitLineData
1## @file\r
2# process FFS generation from INF statement\r
3#\r
4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
5# Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>\r
6#\r
7# This program and the accompanying materials\r
8# are licensed and made available under the terms and conditions of the BSD License\r
9# which accompanies this distribution. The full text of the license may be found at\r
10# http://opensource.org/licenses/bsd-license.php\r
11#\r
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14#\r
15\r
16##\r
17# Import Modules\r
18#\r
19import Rule\r
20import Common.LongFilePathOs as os\r
21import StringIO\r
22from struct import *\r
23from GenFdsGlobalVariable import GenFdsGlobalVariable\r
24import Ffs\r
25import subprocess\r
26import sys\r
27import Section\r
28import RuleSimpleFile\r
29import RuleComplexFile\r
30from CommonDataClass.FdfClass import FfsInfStatementClassObject\r
31from Common.MultipleWorkspace import MultipleWorkspace as mws\r
32from Common.String import *\r
33from Common.Misc import PathClass\r
34from Common.Misc import GuidStructureByteArrayToGuidString\r
35from Common.Misc import ProcessDuplicatedInf\r
36from Common.Misc import GetVariableOffset\r
37from Common import EdkLogger\r
38from Common.BuildToolError import *\r
39from GuidSection import GuidSection\r
40from FvImageSection import FvImageSection\r
41from Common.Misc import PeImageClass\r
42from AutoGen.GenDepex import DependencyExpression\r
43from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
44from Common.LongFilePathSupport import CopyLongFilePath\r
45from Common.LongFilePathSupport import OpenLongFilePath as open\r
46import Common.GlobalData as GlobalData\r
47from DepexSection import DepexSection\r
48from Common.Misc import SaveFileOnChange\r
49from Common.Expression import *\r
50\r
51## generate FFS from INF\r
52#\r
53#\r
54class FfsInfStatement(FfsInfStatementClassObject):\r
55 ## The mapping dictionary from datum type to its maximum number.\r
56 _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}\r
57 ## The constructor\r
58 #\r
59 # @param self The object pointer\r
60 #\r
61 def __init__(self):\r
62 FfsInfStatementClassObject.__init__(self)\r
63 self.TargetOverrideList = []\r
64 self.ShadowFromInfFile = None\r
65 self.KeepRelocFromRule = None\r
66 self.InDsc = True\r
67 self.OptRomDefs = {}\r
68 self.PiSpecVersion = '0x00000000'\r
69 self.InfModule = None\r
70 self.FinalTargetSuffixMap = {}\r
71 self.CurrentLineNum = None\r
72 self.CurrentLineContent = None\r
73 self.FileName = None\r
74 self.InfFileName = None\r
75 self.OverrideGuid = None\r
76 self.PatchedBinFile = ''\r
77 self.MacroDict = {}\r
78 self.Depex = False\r
79\r
80 ## GetFinalTargetSuffixMap() method\r
81 #\r
82 # Get final build target list\r
83 def GetFinalTargetSuffixMap(self):\r
84 if not self.InfModule or not self.CurrentArch:\r
85 return []\r
86 if not self.FinalTargetSuffixMap:\r
87 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)\r
88 for File in FinalBuildTargetList:\r
89 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)\r
90\r
91 # Check if current INF module has DEPEX\r
92 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \\r
93 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:\r
94 ModuleType = self.InfModule.ModuleType\r
95 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
96\r
97 if ModuleType != DataType.SUP_MODULE_USER_DEFINED:\r
98 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():\r
99 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:\r
100 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]\r
101\r
102 StrModule = str(self.InfModule)\r
103 PlatformModule = None\r
104 if StrModule in PlatformDataBase.Modules:\r
105 PlatformModule = PlatformDataBase.Modules[StrModule]\r
106 for LibraryClass in PlatformModule.LibraryClasses:\r
107 if LibraryClass.startswith("NULL"):\r
108 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
109\r
110 DependencyList = [self.InfModule]\r
111 LibraryInstance = {}\r
112 DepexList = []\r
113 while len(DependencyList) > 0:\r
114 Module = DependencyList.pop(0)\r
115 if not Module:\r
116 continue\r
117 for Dep in Module.Depex[self.CurrentArch, ModuleType]:\r
118 if DepexList != []:\r
119 DepexList.append('AND')\r
120 DepexList.append('(')\r
121 DepexList.extend(Dep)\r
122 if DepexList[-1] == 'END': # no need of a END at this time\r
123 DepexList.pop()\r
124 DepexList.append(')')\r
125 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
126 break\r
127 for LibName in Module.LibraryClasses:\r
128 if LibName in LibraryInstance:\r
129 continue\r
130 if PlatformModule and LibName in PlatformModule.LibraryClasses:\r
131 LibraryPath = PlatformModule.LibraryClasses[LibName]\r
132 else:\r
133 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]\r
134 if not LibraryPath:\r
135 LibraryPath = Module.LibraryClasses[LibName]\r
136 if not LibraryPath:\r
137 continue\r
138 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
139 LibraryInstance[LibName] = LibraryModule\r
140 DependencyList.append(LibraryModule)\r
141 if DepexList:\r
142 Dpx = DependencyExpression(DepexList, ModuleType, True)\r
143 if len(Dpx.PostfixNotation) != 0:\r
144 # It means this module has DEPEX\r
145 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']\r
146 return self.FinalTargetSuffixMap\r
147\r
148 ## __InfParse() method\r
149 #\r
150 # Parse inf file to get module information\r
151 #\r
152 # @param self The object pointer\r
153 # @param Dict dictionary contains macro and value pair\r
154 #\r
155 def __InfParse__(self, Dict = {}):\r
156\r
157 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
158\r
159 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
160 if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':\r
161 pass\r
162 elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
163 self.InfFileName = self.InfFileName[1:]\r
164\r
165 if self.InfFileName.find('$') == -1:\r
166 InfPath = NormPath(self.InfFileName)\r
167 if not os.path.exists(InfPath):\r
168 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)\r
169 if not os.path.exists(InfPath):\r
170 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))\r
171\r
172 self.CurrentArch = self.GetCurrentArch()\r
173 #\r
174 # Get the InfClass object\r
175 #\r
176\r
177 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
178 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
179 if ErrorCode != 0:\r
180 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
181\r
182 #\r
183 # Cache lower case version of INF path before processing FILE_GUID override\r
184 #\r
185 InfLowerPath = str(PathClassObj).lower()\r
186 if self.OverrideGuid:\r
187 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)\r
188 if self.CurrentArch != None:\r
189\r
190 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
191 #\r
192 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
193 #\r
194 self.BaseName = Inf.BaseName\r
195 self.ModuleGuid = Inf.Guid\r
196 self.ModuleType = Inf.ModuleType\r
197 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
198 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
199 if Inf.AutoGenVersion < 0x00010005:\r
200 self.ModuleType = Inf.ComponentType\r
201 self.VersionString = Inf.Version\r
202 self.BinFileList = Inf.Binaries\r
203 self.SourceFileList = Inf.Sources\r
204 if self.KeepReloc == None and Inf.Shadow:\r
205 self.ShadowFromInfFile = Inf.Shadow\r
206\r
207 else:\r
208 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
209 self.BaseName = Inf.BaseName\r
210 self.ModuleGuid = Inf.Guid\r
211 self.ModuleType = Inf.ModuleType\r
212 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
213 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
214 self.VersionString = Inf.Version\r
215 self.BinFileList = Inf.Binaries\r
216 self.SourceFileList = Inf.Sources\r
217 if self.BinFileList == []:\r
218 EdkLogger.error("GenFds", GENFDS_ERROR,\r
219 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
220 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
221\r
222 if self.OverrideGuid:\r
223 self.ModuleGuid = self.OverrideGuid\r
224\r
225 if len(self.SourceFileList) != 0 and not self.InDsc:\r
226 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
227\r
228 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
229 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.InfFileName) \r
230\r
231 if self.ModuleType == 'MM_CORE_STANDALONE' and int(self.PiSpecVersion, 16) < 0x00010032:\r
232 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.InfFileName)\r
233\r
234 if Inf._Defs != None and len(Inf._Defs) > 0:\r
235 self.OptRomDefs.update(Inf._Defs)\r
236\r
237 self.PatchPcds = []\r
238 InfPcds = Inf.Pcds\r
239 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
240 FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict\r
241 PlatformPcds = Platform.Pcds\r
242\r
243 # Workaround here: both build and GenFds tool convert the workspace path to lower case\r
244 # But INF file path in FDF and DSC file may have real case characters.\r
245 # Try to convert the path to lower case to see if PCDs value are override by DSC.\r
246 DscModules = {}\r
247 for DscModule in Platform.Modules:\r
248 DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]\r
249 for PcdKey in InfPcds:\r
250 Pcd = InfPcds[PcdKey]\r
251 if not hasattr(Pcd, 'Offset'):\r
252 continue\r
253 if Pcd.Type != 'PatchableInModule':\r
254 continue\r
255 # Override Patchable PCD value by the value from DSC\r
256 PatchPcd = None\r
257 if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:\r
258 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]\r
259 elif PcdKey in Platform.Pcds:\r
260 PatchPcd = Platform.Pcds[PcdKey]\r
261 DscOverride = False\r
262 if PatchPcd and Pcd.Type == PatchPcd.Type:\r
263 DefaultValue = PatchPcd.DefaultValue\r
264 DscOverride = True\r
265\r
266 # Override Patchable PCD value by the value from FDF\r
267 FdfOverride = False\r
268 if PcdKey in FdfPcdDict:\r
269 DefaultValue = FdfPcdDict[PcdKey]\r
270 FdfOverride = True\r
271\r
272 # Override Patchable PCD value by the value from Build Option\r
273 BuildOptionOverride = False\r
274 if GlobalData.BuildOptionPcd:\r
275 for pcd in GlobalData.BuildOptionPcd:\r
276 if PcdKey == (pcd[1], pcd[0]):\r
277 if pcd[2]:\r
278 continue\r
279 DefaultValue = pcd[3]\r
280 BuildOptionOverride = True\r
281 break\r
282\r
283 if not DscOverride and not FdfOverride and not BuildOptionOverride:\r
284 continue\r
285\r
286 # Support Flexible PCD format\r
287 if DefaultValue:\r
288 try:\r
289 DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)\r
290 except BadExpression:\r
291 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName)\r
292\r
293 if Pcd.InfDefaultValue:\r
294 try:\r
295 Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True)\r
296 except BadExpression:\r
297 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue),File=self.InfFileName)\r
298\r
299 # Check value, if value are equal, no need to patch\r
300 if Pcd.DatumType == "VOID*":\r
301 if Pcd.InfDefaultValue == DefaultValue or DefaultValue in [None, '']:\r
302 continue\r
303 # Get the string size from FDF or DSC\r
304 if DefaultValue[0] == 'L':\r
305 # Remove L"", but the '\0' must be appended\r
306 MaxDatumSize = str((len(DefaultValue) - 2) * 2)\r
307 elif DefaultValue[0] == '{':\r
308 MaxDatumSize = str(len(DefaultValue.split(',')))\r
309 else:\r
310 MaxDatumSize = str(len(DefaultValue) - 1)\r
311 if DscOverride:\r
312 Pcd.MaxDatumSize = PatchPcd.MaxDatumSize\r
313 # If no defined the maximum size in DSC, try to get current size from INF\r
314 if Pcd.MaxDatumSize in ['', None]:\r
315 Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))\r
316 else:\r
317 Base1 = Base2 = 10\r
318 if Pcd.InfDefaultValue.upper().startswith('0X'):\r
319 Base1 = 16\r
320 if DefaultValue.upper().startswith('0X'):\r
321 Base2 = 16\r
322 try:\r
323 PcdValueInImg = int(Pcd.InfDefaultValue, Base1)\r
324 PcdValueInDscOrFdf = int(DefaultValue, Base2)\r
325 if PcdValueInImg == PcdValueInDscOrFdf:\r
326 continue\r
327 except:\r
328 continue\r
329 # Check the Pcd size and data type\r
330 if Pcd.DatumType == "VOID*":\r
331 if int(MaxDatumSize) > int(Pcd.MaxDatumSize):\r
332 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \\r
333 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))\r
334 else:\r
335 if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \\r
336 or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:\r
337 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \\r
338 % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
339 self.PatchPcds.append((Pcd, DefaultValue))\r
340\r
341 self.InfModule = Inf\r
342 self.PcdIsDriver = Inf.PcdIsDriver\r
343 self.IsBinaryModule = Inf.IsBinaryModule\r
344 Inf._GetDepex()\r
345 Inf._GetDepexExpression()\r
346 if len(Inf._Depex.data) > 0 and len(Inf._DepexExpression.data) > 0:\r
347 self.Depex = True\r
348\r
349 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)\r
350 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)\r
351 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)\r
352 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)\r
353 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)\r
354\r
355 #\r
356 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
357 #\r
358\r
359 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
360 self.ModuleGuid + self.BaseName)\r
361 if not os.path.exists(self.OutputPath) :\r
362 os.makedirs(self.OutputPath)\r
363\r
364 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()\r
365 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
366\r
367 ## PatchEfiFile\r
368 #\r
369 # Patch EFI file with patch PCD\r
370 #\r
371 # @param EfiFile: EFI file needs to be patched.\r
372 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name\r
373 # If passed in file does not end with efi, return as is\r
374 #\r
375 def PatchEfiFile(self, EfiFile, FileType):\r
376 #\r
377 # If the module does not have any patches, then return path to input file\r
378 # \r
379 if not self.PatchPcds:\r
380 return EfiFile\r
381\r
382 #\r
383 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED\r
384 # \r
385 if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":\r
386 return EfiFile\r
387\r
388 #\r
389 # Generate path to patched output file\r
390 #\r
391 Basename = os.path.basename(EfiFile)\r
392 Output = os.path.normpath (os.path.join(self.OutputPath, Basename))\r
393\r
394 #\r
395 # If this file has already been patched, then return the path to the patched file\r
396 #\r
397 if self.PatchedBinFile == Output:\r
398 return Output\r
399\r
400 #\r
401 # If a different file from the same module has already been patched, then generate an error\r
402 # \r
403 if self.PatchedBinFile:\r
404 EdkLogger.error("GenFds", GENFDS_ERROR,\r
405 'Only one binary file can be patched:\n'\r
406 ' a binary file has been patched: %s\n'\r
407 ' current file: %s' % (self.PatchedBinFile, EfiFile),\r
408 File=self.InfFileName)\r
409\r
410 #\r
411 # Copy unpatched file contents to output file location to perform patching\r
412 # \r
413 CopyLongFilePath(EfiFile, Output)\r
414\r
415 #\r
416 # Apply patches to patched output file\r
417 # \r
418 for Pcd, Value in self.PatchPcds:\r
419 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)\r
420 if RetVal:\r
421 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)\r
422\r
423 #\r
424 # Save the path of the patched output file\r
425 # \r
426 self.PatchedBinFile = Output\r
427\r
428 #\r
429 # Return path to patched output file\r
430 # \r
431 return Output\r
432\r
433 ## GenFfs() method\r
434 #\r
435 # Generate FFS\r
436 #\r
437 # @param self The object pointer\r
438 # @param Dict dictionary contains macro and value pair\r
439 # @param FvChildAddr Array of the inside FvImage base address\r
440 # @param FvParentAddr Parent Fv base address\r
441 # @retval string Generated FFS file name\r
442 #\r
443 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None):\r
444 #\r
445 # Parse Inf file get Module related information\r
446 #\r
447\r
448 self.__InfParse__(Dict)\r
449 Arch = self.GetCurrentArch()\r
450 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);\r
451 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
452 \r
453 SrcFileDir = "."\r
454 SrcPath = os.path.dirname(SrcFile)\r
455 SrcFileName = os.path.basename(SrcFile)\r
456 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName) \r
457 DestPath = os.path.dirname(DestFile)\r
458 DestFileName = os.path.basename(DestFile)\r
459 DestFileBase, DestFileExt = os.path.splitext(DestFileName) \r
460 self.MacroDict = {\r
461 # source file\r
462 "${src}" : SrcFile,\r
463 "${s_path}" : SrcPath,\r
464 "${s_dir}" : SrcFileDir,\r
465 "${s_name}" : SrcFileName,\r
466 "${s_base}" : SrcFileBase,\r
467 "${s_ext}" : SrcFileExt,\r
468 # destination file\r
469 "${dst}" : DestFile,\r
470 "${d_path}" : DestPath,\r
471 "${d_name}" : DestFileName,\r
472 "${d_base}" : DestFileBase,\r
473 "${d_ext}" : DestFileExt\r
474 }\r
475 #\r
476 # Allow binary type module not specify override rule in FDF file.\r
477 # \r
478 if len(self.BinFileList) > 0:\r
479 if self.Rule == None or self.Rule == "":\r
480 self.Rule = "BINARY"\r
481\r
482 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':\r
483 IsMakefile = True\r
484 #\r
485 # Get the rule of how to generate Ffs file\r
486 #\r
487 Rule = self.__GetRule__()\r
488 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
489 #\r
490 # Convert Fv File Type for PI1.1 SMM driver.\r
491 #\r
492 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
493 if Rule.FvFileType == 'DRIVER':\r
494 Rule.FvFileType = 'SMM'\r
495 #\r
496 # Framework SMM Driver has no SMM FV file type\r
497 #\r
498 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
499 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':\r
500 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)\r
501 #\r
502 # For the rule only has simpleFile\r
503 #\r
504 MakefilePath = None\r
505 if IsMakefile:\r
506 MakefilePath = self.InfFileName, Arch\r
507 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :\r
508 SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)\r
509 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)\r
510 return FfsOutput\r
511 #\r
512 # For Rule has ComplexFile\r
513 #\r
514 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):\r
515 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)\r
516 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)\r
517 return FfsOutput\r
518\r
519 ## __ExtendMacro__() method\r
520 #\r
521 # Replace macro with its value\r
522 #\r
523 # @param self The object pointer\r
524 # @param String The string to be replaced\r
525 # @retval string Macro replaced string\r
526 #\r
527 def __ExtendMacro__ (self, String):\r
528 MacroDict = {\r
529 '$(INF_OUTPUT)' : self.EfiOutputPath,\r
530 '$(MODULE_NAME)' : self.BaseName,\r
531 '$(BUILD_NUMBER)': self.BuildNum,\r
532 '$(INF_VERSION)' : self.VersionString,\r
533 '$(NAMED_GUID)' : self.ModuleGuid\r
534 }\r
535 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
536 String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict) \r
537 return String\r
538\r
539 ## __GetRule__() method\r
540 #\r
541 # Get correct rule for generating FFS for this INF\r
542 #\r
543 # @param self The object pointer\r
544 # @retval Rule Rule object\r
545 #\r
546 def __GetRule__ (self) :\r
547 CurrentArchList = []\r
548 if self.CurrentArch == None:\r
549 CurrentArchList = ['common']\r
550 else:\r
551 CurrentArchList.append(self.CurrentArch)\r
552\r
553 for CurrentArch in CurrentArchList:\r
554 RuleName = 'RULE' + \\r
555 '.' + \\r
556 CurrentArch.upper() + \\r
557 '.' + \\r
558 self.ModuleType.upper()\r
559 if self.Rule != None:\r
560 RuleName = RuleName + \\r
561 '.' + \\r
562 self.Rule.upper()\r
563\r
564 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
565 if Rule != None:\r
566 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
567 return Rule\r
568\r
569 RuleName = 'RULE' + \\r
570 '.' + \\r
571 'COMMON' + \\r
572 '.' + \\r
573 self.ModuleType.upper()\r
574\r
575 if self.Rule != None:\r
576 RuleName = RuleName + \\r
577 '.' + \\r
578 self.Rule.upper()\r
579\r
580 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))\r
581\r
582 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
583 if Rule != None:\r
584 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
585 return Rule\r
586\r
587 if Rule == None :\r
588 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \\r
589 % (RuleName, self.InfFileName))\r
590\r
591 ## __GetPlatformArchList__() method\r
592 #\r
593 # Get Arch list this INF built under\r
594 #\r
595 # @param self The object pointer\r
596 # @retval list Arch list\r
597 #\r
598 def __GetPlatformArchList__(self):\r
599\r
600 InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))\r
601 DscArchList = []\r
602 for Arch in GenFdsGlobalVariable.ArchList :\r
603 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
604 if PlatformDataBase != None:\r
605 if InfFileKey in PlatformDataBase.Modules:\r
606 DscArchList.append (Arch)\r
607 else:\r
608 #\r
609 # BaseTools support build same module more than once, the module path with FILE_GUID overridden has\r
610 # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,\r
611 # but the path (self.MetaFile.Path) is the real path\r
612 #\r
613 for key in PlatformDataBase.Modules.keys():\r
614 if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):\r
615 DscArchList.append (Arch)\r
616 break\r
617\r
618 return DscArchList\r
619\r
620 ## GetCurrentArch() method\r
621 #\r
622 # Get Arch list of the module from this INF is to be placed into flash\r
623 #\r
624 # @param self The object pointer\r
625 # @retval list Arch list\r
626 #\r
627 def GetCurrentArch(self) :\r
628\r
629 TargetArchList = GenFdsGlobalVariable.ArchList\r
630\r
631 PlatformArchList = self.__GetPlatformArchList__()\r
632\r
633 CurArchList = TargetArchList\r
634 if PlatformArchList != []:\r
635 CurArchList = list(set (TargetArchList) & set (PlatformArchList))\r
636 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))\r
637\r
638 ArchList = []\r
639 if self.KeyStringList != []:\r
640 for Key in self.KeyStringList:\r
641 Key = GenFdsGlobalVariable.MacroExtend(Key)\r
642 Target, Tag, Arch = Key.split('_')\r
643 if Arch in CurArchList:\r
644 ArchList.append(Arch)\r
645 if Target not in self.TargetOverrideList:\r
646 self.TargetOverrideList.append(Target)\r
647 else:\r
648 ArchList = CurArchList\r
649\r
650 UseArchList = TargetArchList\r
651 if self.UseArch != None:\r
652 UseArchList = []\r
653 UseArchList.append(self.UseArch)\r
654 ArchList = list(set (UseArchList) & set (ArchList))\r
655\r
656 self.InfFileName = NormPath(self.InfFileName)\r
657 if len(PlatformArchList) == 0:\r
658 self.InDsc = False\r
659 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
660 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
661 if ErrorCode != 0:\r
662 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
663 if len(ArchList) == 1:\r
664 Arch = ArchList[0]\r
665 return Arch\r
666 elif len(ArchList) > 1:\r
667 if len(PlatformArchList) == 0:\r
668 EdkLogger.error("GenFds", GENFDS_ERROR, "GenFds command line option has multiple ARCHs %s. Not able to determine which ARCH is valid for Module %s !" % (str(ArchList), self.InfFileName))\r
669 else:\r
670 EdkLogger.error("GenFds", GENFDS_ERROR, "Module built under multiple ARCHs %s. Not able to determine which output to put into flash for Module %s !" % (str(ArchList), self.InfFileName))\r
671 else:\r
672 EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current deduced ARCH is %s, so NO build output could be put into flash." \\r
673 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))\r
674\r
675 ## __GetEFIOutPutPath__() method\r
676 #\r
677 # Get the output path for generated files\r
678 #\r
679 # @param self The object pointer\r
680 # @retval string Path that output files from this INF go to\r
681 #\r
682 def __GetEFIOutPutPath__(self):\r
683 Arch = ''\r
684 OutputPath = ''\r
685 DebugPath = ''\r
686 (ModulePath, FileName) = os.path.split(self.InfFileName)\r
687 Index = FileName.rfind('.')\r
688 FileName = FileName[0:Index]\r
689 if self.OverrideGuid:\r
690 FileName = self.OverrideGuid\r
691 Arch = "NoneArch"\r
692 if self.CurrentArch != None:\r
693 Arch = self.CurrentArch\r
694\r
695 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
696 Arch ,\r
697 ModulePath,\r
698 FileName,\r
699 'OUTPUT'\r
700 )\r
701 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
702 Arch ,\r
703 ModulePath,\r
704 FileName,\r
705 'DEBUG'\r
706 )\r
707 OutputPath = os.path.realpath(OutputPath)\r
708 DebugPath = os.path.realpath(DebugPath)\r
709 return OutputPath, DebugPath\r
710\r
711 ## __GenSimpleFileSection__() method\r
712 #\r
713 # Generate section by specified file name or a list of files with file extension\r
714 #\r
715 # @param self The object pointer\r
716 # @param Rule The rule object used to generate section\r
717 # @retval string File name of the generated section file\r
718 #\r
719 def __GenSimpleFileSection__(self, Rule, IsMakefile = False):\r
720 #\r
721 # Prepare the parameter of GenSection\r
722 #\r
723 FileList = []\r
724 OutputFileList = []\r
725 GenSecInputFile = None\r
726 if Rule.FileName != None:\r
727 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)\r
728 if os.path.isabs(GenSecInputFile):\r
729 GenSecInputFile = os.path.normpath(GenSecInputFile)\r
730 else:\r
731 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))\r
732 else:\r
733 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)\r
734\r
735 Index = 1\r
736 SectionType = Rule.SectionType\r
737 #\r
738 # Convert Fv Section Type for PI1.1 SMM driver.\r
739 #\r
740 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
741 if SectionType == 'DXE_DEPEX':\r
742 SectionType = 'SMM_DEPEX'\r
743 #\r
744 # Framework SMM Driver has no SMM_DEPEX section type\r
745 #\r
746 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
747 if SectionType == 'SMM_DEPEX':\r
748 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
749 NoStrip = True\r
750 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
751 if self.KeepReloc != None:\r
752 NoStrip = self.KeepReloc\r
753 elif Rule.KeepReloc != None:\r
754 NoStrip = Rule.KeepReloc\r
755 elif self.ShadowFromInfFile != None:\r
756 NoStrip = self.ShadowFromInfFile\r
757\r
758 if FileList != [] :\r
759 for File in FileList:\r
760\r
761 SecNum = '%d' %Index\r
762 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
763 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
764 Index = Index + 1\r
765 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
766 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)\r
767\r
768 #Get PE Section alignment when align is set to AUTO\r
769 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
770 ImageObj = PeImageClass (File)\r
771 if ImageObj.SectionAlignment < 0x400:\r
772 self.Alignment = str (ImageObj.SectionAlignment)\r
773 elif ImageObj.SectionAlignment < 0x100000:\r
774 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
775 else:\r
776 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'\r
777\r
778 if not NoStrip:\r
779 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
780 if not os.path.exists(FileBeforeStrip) or \\r
781 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
782 CopyLongFilePath(File, FileBeforeStrip)\r
783 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
784 GenFdsGlobalVariable.GenerateFirmwareImage(\r
785 StrippedFile,\r
786 [File],\r
787 Strip=True,\r
788 IsMakefile=IsMakefile\r
789 )\r
790 File = StrippedFile\r
791\r
792 if SectionType == 'TE':\r
793 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
794 GenFdsGlobalVariable.GenerateFirmwareImage(\r
795 TeFile,\r
796 [File],\r
797 Type='te',\r
798 IsMakefile=IsMakefile\r
799 )\r
800 File = TeFile\r
801 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)\r
802 OutputFileList.append(OutputFile)\r
803 else:\r
804 SecNum = '%d' %Index\r
805 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
806 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
807 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
808 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)\r
809\r
810 #Get PE Section alignment when align is set to AUTO\r
811 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
812 ImageObj = PeImageClass (GenSecInputFile)\r
813 if ImageObj.SectionAlignment < 0x400:\r
814 self.Alignment = str (ImageObj.SectionAlignment)\r
815 elif ImageObj.SectionAlignment < 0x100000:\r
816 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
817 else:\r
818 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'\r
819\r
820 if not NoStrip:\r
821 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
822 if not os.path.exists(FileBeforeStrip) or \\r
823 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):\r
824 CopyLongFilePath(GenSecInputFile, FileBeforeStrip)\r
825\r
826 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
827 GenFdsGlobalVariable.GenerateFirmwareImage(\r
828 StrippedFile,\r
829 [GenSecInputFile],\r
830 Strip=True,\r
831 IsMakefile=IsMakefile\r
832 )\r
833 GenSecInputFile = StrippedFile\r
834\r
835 if SectionType == 'TE':\r
836 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
837 GenFdsGlobalVariable.GenerateFirmwareImage(\r
838 TeFile,\r
839 [GenSecInputFile],\r
840 Type='te',\r
841 IsMakefile=IsMakefile\r
842 )\r
843 GenSecInputFile = TeFile\r
844 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)\r
845 OutputFileList.append(OutputFile)\r
846\r
847 return OutputFileList\r
848\r
849 ## __GenSimpleFileFfs__() method\r
850 #\r
851 # Generate FFS\r
852 #\r
853 # @param self The object pointer\r
854 # @param Rule The rule object used to generate section\r
855 # @param InputFileList The output file list from GenSection\r
856 # @retval string Generated FFS file name\r
857 #\r
858 def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):\r
859 FfsOutput = self.OutputPath + \\r
860 os.sep + \\r
861 self.__ExtendMacro__(Rule.NameGuid) + \\r
862 '.ffs'\r
863\r
864 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))\r
865 InputSection = []\r
866 SectionAlignments = []\r
867 for InputFile in InputFileList:\r
868 InputSection.append(InputFile)\r
869 SectionAlignments.append(Rule.SectAlignment)\r
870\r
871 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
872 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
873 if len(PcdValue) == 0:\r
874 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
875 % (Rule.NameGuid))\r
876 if PcdValue.startswith('{'):\r
877 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
878 RegistryGuidStr = PcdValue\r
879 if len(RegistryGuidStr) == 0:\r
880 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
881 % (Rule.NameGuid))\r
882 self.ModuleGuid = RegistryGuidStr\r
883\r
884 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,\r
885 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
886 self.ModuleGuid, Fixed=Rule.Fixed,\r
887 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
888 SectionAlign=SectionAlignments,\r
889 MakefilePath=MakefilePath\r
890 )\r
891 return FfsOutput\r
892\r
893 ## __GenComplexFileSection__() method\r
894 #\r
895 # Generate section by sections in Rule\r
896 #\r
897 # @param self The object pointer\r
898 # @param Rule The rule object used to generate section\r
899 # @param FvChildAddr Array of the inside FvImage base address\r
900 # @param FvParentAddr Parent Fv base address\r
901 # @retval string File name of the generated section file\r
902 #\r
903 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):\r
904 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
905 if Rule.KeepReloc != None:\r
906 self.KeepRelocFromRule = Rule.KeepReloc\r
907 SectFiles = []\r
908 SectAlignments = []\r
909 Index = 1\r
910 HasGeneratedFlag = False\r
911 if self.PcdIsDriver == 'PEI_PCD_DRIVER':\r
912 if self.IsBinaryModule:\r
913 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")\r
914 else:\r
915 PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")\r
916 PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")\r
917 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
918 [PcdExDbFileName],\r
919 "EFI_SECTION_RAW",\r
920 IsMakefile = IsMakefile\r
921 )\r
922 SectFiles.append(PcdExDbSecName)\r
923 SectAlignments.append(None)\r
924 elif self.PcdIsDriver == 'DXE_PCD_DRIVER':\r
925 if self.IsBinaryModule:\r
926 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")\r
927 else:\r
928 PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")\r
929 PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")\r
930 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
931 [PcdExDbFileName],\r
932 "EFI_SECTION_RAW",\r
933 IsMakefile = IsMakefile\r
934 )\r
935 SectFiles.append(PcdExDbSecName)\r
936 SectAlignments.append(None)\r
937 for Sect in Rule.SectionList:\r
938 SecIndex = '%d' %Index\r
939 SectList = []\r
940 #\r
941 # Convert Fv Section Type for PI1.1 SMM driver.\r
942 #\r
943 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
944 if Sect.SectionType == 'DXE_DEPEX':\r
945 Sect.SectionType = 'SMM_DEPEX'\r
946 #\r
947 # Framework SMM Driver has no SMM_DEPEX section type\r
948 #\r
949 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
950 if Sect.SectionType == 'SMM_DEPEX':\r
951 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
952 #\r
953 # process the inside FvImage from FvSection or GuidSection\r
954 #\r
955 if FvChildAddr != []:\r
956 if isinstance(Sect, FvImageSection):\r
957 Sect.FvAddr = FvChildAddr.pop(0)\r
958 elif isinstance(Sect, GuidSection):\r
959 Sect.FvAddr = FvChildAddr\r
960 if FvParentAddr != None and isinstance(Sect, GuidSection):\r
961 Sect.FvParentAddr = FvParentAddr\r
962 \r
963 if Rule.KeyStringList != []:\r
964 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)\r
965 else :\r
966 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)\r
967 \r
968 if not HasGeneratedFlag:\r
969 UniVfrOffsetFileSection = "" \r
970 ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)\r
971 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]\r
972 #\r
973 # Search the source list in InfData to find if there are .vfr file exist.\r
974 #\r
975 VfrUniBaseName = {}\r
976 VfrUniOffsetList = []\r
977 for SourceFile in InfData.Sources:\r
978 if SourceFile.Type.upper() == ".VFR" :\r
979 #\r
980 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
981 #\r
982 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
983 if SourceFile.Type.upper() == ".UNI" :\r
984 #\r
985 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
986 #\r
987 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")\r
988 \r
989 \r
990 if len(VfrUniBaseName) > 0:\r
991 if IsMakefile:\r
992 if InfData.BuildType != 'UEFI_HII':\r
993 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')\r
994 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
995 UniVfrOffsetFileNameList = []\r
996 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
997 TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)\r
998 GenFdsGlobalVariable.SecCmdList.append(TrimCmd)\r
999 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
1000 [UniVfrOffsetFileName],\r
1001 "EFI_SECTION_RAW",\r
1002 IsMakefile = True\r
1003 )\r
1004 else:\r
1005 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)\r
1006 #\r
1007 # Generate the Raw data of raw section\r
1008 #\r
1009 if VfrUniOffsetList:\r
1010 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')\r
1011 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
1012 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
1013 UniVfrOffsetFileNameList = []\r
1014 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
1015 """Call GenSection"""\r
1016\r
1017 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
1018 UniVfrOffsetFileNameList,\r
1019 "EFI_SECTION_RAW"\r
1020 )\r
1021 #os.remove(UniVfrOffsetFileName)\r
1022 if UniVfrOffsetFileSection:\r
1023 SectList.append(UniVfrOffsetFileSection)\r
1024 HasGeneratedFlag = True\r
1025 \r
1026 for SecName in SectList :\r
1027 SectFiles.append(SecName)\r
1028 SectAlignments.append(Align)\r
1029 Index = Index + 1\r
1030 return SectFiles, SectAlignments\r
1031\r
1032 ## __GenComplexFileFfs__() method\r
1033 #\r
1034 # Generate FFS\r
1035 #\r
1036 # @param self The object pointer\r
1037 # @param Rule The rule object used to generate section\r
1038 # @param InputFileList The output file list from GenSection\r
1039 # @retval string Generated FFS file name\r
1040 #\r
1041 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):\r
1042\r
1043 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
1044 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
1045 if len(PcdValue) == 0:\r
1046 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
1047 % (Rule.NameGuid))\r
1048 if PcdValue.startswith('{'):\r
1049 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
1050 RegistryGuidStr = PcdValue\r
1051 if len(RegistryGuidStr) == 0:\r
1052 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
1053 % (Rule.NameGuid))\r
1054 self.ModuleGuid = RegistryGuidStr\r
1055\r
1056 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
1057 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,\r
1058 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
1059 self.ModuleGuid, Fixed=Rule.Fixed,\r
1060 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
1061 SectionAlign=Alignments,\r
1062 MakefilePath=MakefilePath\r
1063 )\r
1064 return FfsOutput\r
1065\r
1066 ## __GetGenFfsCmdParameter__() method\r
1067 #\r
1068 # Create parameter string for GenFfs\r
1069 #\r
1070 # @param self The object pointer\r
1071 # @param Rule The rule object used to generate section\r
1072 # @retval tuple (FileType, Fixed, CheckSum, Alignment)\r
1073 #\r
1074 def __GetGenFfsCmdParameter__(self, Rule):\r
1075 result = tuple()\r
1076 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])\r
1077 if Rule.Fixed != False:\r
1078 result += ('-x',)\r
1079 if Rule.CheckSum != False:\r
1080 result += ('-s',)\r
1081\r
1082 if Rule.Alignment != None and Rule.Alignment != '':\r
1083 result += ('-a', Rule.Alignment)\r
1084\r
1085 return result\r
1086 \r
1087 ## __GetBuildOutputMapFileVfrUniInfo() method\r
1088 #\r
1089 # Find the offset of UNI/INF object offset in the EFI image file.\r
1090 #\r
1091 # @param self The object pointer\r
1092 # @param VfrUniBaseName A name list contain the UNI/INF object name.\r
1093 # @retval RetValue A list contain offset of UNI/INF object.\r
1094 # \r
1095 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):\r
1096 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")\r
1097 EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")\r
1098 return GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
1099 \r
1100 ## __GenUniVfrOffsetFile() method\r
1101 #\r
1102 # Generate the offset file for the module which contain VFR or UNI file.\r
1103 #\r
1104 # @param self The object pointer\r
1105 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.\r
1106 # @param UniVfrOffsetFileName The output offset file name.\r
1107 #\r
1108 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):\r
1109\r
1110 # Use a instance of StringIO to cache data\r
1111 fStringIO = StringIO.StringIO('') \r
1112 \r
1113 for Item in VfrUniOffsetList:\r
1114 if (Item[0].find("Strings") != -1):\r
1115 #\r
1116 # UNI offset in image.\r
1117 # GUID + Offset\r
1118 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
1119 #\r
1120 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
1121 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
1122 fStringIO.write(''.join(UniGuid)) \r
1123 UniValue = pack ('Q', int (Item[1], 16))\r
1124 fStringIO.write (UniValue)\r
1125 else:\r
1126 #\r
1127 # VFR binary offset in image.\r
1128 # GUID + Offset\r
1129 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
1130 #\r
1131 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
1132 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
1133 fStringIO.write(''.join(VfrGuid)) \r
1134 type (Item[1]) \r
1135 VfrValue = pack ('Q', int (Item[1], 16))\r
1136 fStringIO.write (VfrValue)\r
1137 \r
1138 #\r
1139 # write data into file.\r
1140 #\r
1141 try :\r
1142 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())\r
1143 except:\r
1144 EdkLogger.error("GenFds", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %UniVfrOffsetFileName,None)\r
1145 \r
1146 fStringIO.close ()\r
1147\r
1148 \r