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