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