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