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