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