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