]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools: skip updating temporary variable.
[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
40d841f6 7# This program and the accompanying materials\r
30fdf114
LG
8# are licensed and made available under the terms and conditions of the BSD License\r
9# which accompanies this distribution. The full text of the license may be found at\r
10# http://opensource.org/licenses/bsd-license.php\r
11#\r
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14#\r
15\r
16##\r
17# Import Modules\r
18#\r
19import Rule\r
1be2ed90 20import Common.LongFilePathOs as os\r
da92f276
LG
21import StringIO\r
22from struct import *\r
30fdf114
LG
23from GenFdsGlobalVariable import GenFdsGlobalVariable\r
24import Ffs\r
25import subprocess\r
26import sys\r
27import Section\r
28import RuleSimpleFile\r
29import RuleComplexFile\r
30from CommonDataClass.FdfClass import FfsInfStatementClassObject\r
05cc51ad 31from Common.MultipleWorkspace import MultipleWorkspace as mws\r
30fdf114
LG
32from Common.String import *\r
33from Common.Misc import PathClass\r
34from Common.Misc import GuidStructureByteArrayToGuidString\r
97fa0ee9 35from Common.Misc import ProcessDuplicatedInf\r
22a99b87 36from Common.Misc import GetVariableOffset\r
30fdf114
LG
37from Common import EdkLogger\r
38from Common.BuildToolError import *\r
52302d4d
LG
39from GuidSection import GuidSection\r
40from FvImageSection import FvImageSection\r
41from Common.Misc import PeImageClass\r
b36d134f 42from AutoGen.GenDepex import DependencyExpression\r
e8a47801 43from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
1be2ed90
HC
44from Common.LongFilePathSupport import CopyLongFilePath\r
45from Common.LongFilePathSupport import OpenLongFilePath as open\r
6b17c11b 46import Common.GlobalData as GlobalData\r
37de70b7
YZ
47from DepexSection import DepexSection\r
48from Common.Misc import SaveFileOnChange\r
0537f332 49from Common.Expression import *\r
30fdf114
LG
50\r
51## generate FFS from INF\r
52#\r
53#\r
54class FfsInfStatement(FfsInfStatementClassObject):\r
2bc3256c
LG
55 ## The mapping dictionary from datum type to its maximum number.\r
56 _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}\r
30fdf114
LG
57 ## The constructor\r
58 #\r
59 # @param self The object pointer\r
60 #\r
61 def __init__(self):\r
62 FfsInfStatementClassObject.__init__(self)\r
63 self.TargetOverrideList = []\r
64 self.ShadowFromInfFile = None\r
65 self.KeepRelocFromRule = None\r
66 self.InDsc = True\r
67 self.OptRomDefs = {}\r
da92f276 68 self.PiSpecVersion = '0x00000000'\r
4234283c 69 self.InfModule = None\r
b36d134f 70 self.FinalTargetSuffixMap = {}\r
79b74a03
LG
71 self.CurrentLineNum = None\r
72 self.CurrentLineContent = None\r
73 self.FileName = None\r
74 self.InfFileName = None\r
97fa0ee9
YL
75 self.OverrideGuid = None\r
76 self.PatchedBinFile = ''\r
7ae7dcb9 77 self.MacroDict = {}\r
37de70b7 78 self.Depex = False\r
4234283c 79\r
b36d134f 80 ## GetFinalTargetSuffixMap() method\r
4234283c
LG
81 #\r
82 # Get final build target list\r
b36d134f 83 def GetFinalTargetSuffixMap(self):\r
4234283c
LG
84 if not self.InfModule or not self.CurrentArch:\r
85 return []\r
b36d134f
LG
86 if not self.FinalTargetSuffixMap:\r
87 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)\r
88 for File in FinalBuildTargetList:\r
89 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)\r
90\r
91 # Check if current INF module has DEPEX\r
92 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \\r
93 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:\r
94 ModuleType = self.InfModule.ModuleType\r
95 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
96\r
97 if ModuleType != DataType.SUP_MODULE_USER_DEFINED:\r
98 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():\r
99 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:\r
100 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]\r
101\r
102 StrModule = str(self.InfModule)\r
103 PlatformModule = None\r
104 if StrModule in PlatformDataBase.Modules:\r
105 PlatformModule = PlatformDataBase.Modules[StrModule]\r
106 for LibraryClass in PlatformModule.LibraryClasses:\r
107 if LibraryClass.startswith("NULL"):\r
108 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
109\r
110 DependencyList = [self.InfModule]\r
111 LibraryInstance = {}\r
112 DepexList = []\r
113 while len(DependencyList) > 0:\r
114 Module = DependencyList.pop(0)\r
115 if not Module:\r
116 continue\r
117 for Dep in Module.Depex[self.CurrentArch, ModuleType]:\r
118 if DepexList != []:\r
119 DepexList.append('AND')\r
120 DepexList.append('(')\r
121 DepexList.extend(Dep)\r
122 if DepexList[-1] == 'END': # no need of a END at this time\r
123 DepexList.pop()\r
124 DepexList.append(')')\r
125 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
126 break\r
127 for LibName in Module.LibraryClasses:\r
128 if LibName in LibraryInstance:\r
129 continue\r
130 if PlatformModule and LibName in PlatformModule.LibraryClasses:\r
131 LibraryPath = PlatformModule.LibraryClasses[LibName]\r
132 else:\r
133 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]\r
134 if not LibraryPath:\r
135 LibraryPath = Module.LibraryClasses[LibName]\r
136 if not LibraryPath:\r
137 continue\r
138 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
139 LibraryInstance[LibName] = LibraryModule\r
140 DependencyList.append(LibraryModule)\r
141 if DepexList:\r
142 Dpx = DependencyExpression(DepexList, ModuleType, True)\r
143 if len(Dpx.PostfixNotation) != 0:\r
144 # It means this module has DEPEX\r
145 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']\r
146 return self.FinalTargetSuffixMap\r
4234283c 147\r
30fdf114
LG
148 ## __InfParse() method\r
149 #\r
150 # Parse inf file to get module information\r
151 #\r
152 # @param self The object pointer\r
153 # @param Dict dictionary contains macro and value pair\r
154 #\r
155 def __InfParse__(self, Dict = {}):\r
156\r
157 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
158\r
159 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
97fa0ee9
YL
160 if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':\r
161 pass\r
162 elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
30fdf114
LG
163 self.InfFileName = self.InfFileName[1:]\r
164\r
165 if self.InfFileName.find('$') == -1:\r
166 InfPath = NormPath(self.InfFileName)\r
167 if not os.path.exists(InfPath):\r
168 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)\r
169 if not os.path.exists(InfPath):\r
170 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))\r
171\r
172 self.CurrentArch = self.GetCurrentArch()\r
173 #\r
174 # Get the InfClass object\r
175 #\r
176\r
177 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 178 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
179 if ErrorCode != 0:\r
180 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
97fa0ee9 181\r
4aa9826d
YZ
182 #\r
183 # Cache lower case version of INF path before processing FILE_GUID override\r
184 #\r
185 InfLowerPath = str(PathClassObj).lower()\r
97fa0ee9
YL
186 if self.OverrideGuid:\r
187 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)\r
4231a819 188 if self.CurrentArch is not None:\r
30fdf114 189\r
0d2711a6 190 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
191 #\r
192 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
193 #\r
194 self.BaseName = Inf.BaseName\r
195 self.ModuleGuid = Inf.Guid\r
196 self.ModuleType = Inf.ModuleType\r
4231a819 197 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 198 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
199 if Inf.AutoGenVersion < 0x00010005:\r
200 self.ModuleType = Inf.ComponentType\r
201 self.VersionString = Inf.Version\r
202 self.BinFileList = Inf.Binaries\r
203 self.SourceFileList = Inf.Sources\r
4231a819 204 if self.KeepReloc is None and Inf.Shadow:\r
30fdf114
LG
205 self.ShadowFromInfFile = Inf.Shadow\r
206\r
207 else:\r
0d2711a6 208 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
209 self.BaseName = Inf.BaseName\r
210 self.ModuleGuid = Inf.Guid\r
211 self.ModuleType = Inf.ModuleType\r
4231a819 212 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 213 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
214 self.VersionString = Inf.Version\r
215 self.BinFileList = Inf.Binaries\r
216 self.SourceFileList = Inf.Sources\r
217 if self.BinFileList == []:\r
218 EdkLogger.error("GenFds", GENFDS_ERROR,\r
219 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
220 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
221\r
97fa0ee9
YL
222 if self.OverrideGuid:\r
223 self.ModuleGuid = self.OverrideGuid\r
224\r
30fdf114
LG
225 if len(self.SourceFileList) != 0 and not self.InDsc:\r
226 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
227\r
da92f276 228 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
229 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
230\r
b19df640
SV
231 if self.ModuleType == 'MM_CORE_STANDALONE' and int(self.PiSpecVersion, 16) < 0x00010032:\r
232 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
233\r
4231a819 234 if Inf._Defs is not None and len(Inf._Defs) > 0:\r
30fdf114 235 self.OptRomDefs.update(Inf._Defs)\r
2bc3256c 236\r
e8a47801
LG
237 self.PatchPcds = []\r
238 InfPcds = Inf.Pcds\r
239 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
240 FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict\r
6f49996c 241 PlatformPcds = Platform.Pcds\r
2bc3256c
LG
242\r
243 # Workaround here: both build and GenFds tool convert the workspace path to lower case\r
244 # But INF file path in FDF and DSC file may have real case characters.\r
245 # Try to convert the path to lower case to see if PCDs value are override by DSC.\r
e8a47801
LG
246 DscModules = {}\r
247 for DscModule in Platform.Modules:\r
248 DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]\r
249 for PcdKey in InfPcds:\r
250 Pcd = InfPcds[PcdKey]\r
251 if not hasattr(Pcd, 'Offset'):\r
252 continue\r
253 if Pcd.Type != 'PatchableInModule':\r
254 continue\r
2bc3256c 255 # Override Patchable PCD value by the value from DSC\r
e8a47801 256 PatchPcd = None\r
e8a47801
LG
257 if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:\r
258 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]\r
259 elif PcdKey in Platform.Pcds:\r
260 PatchPcd = Platform.Pcds[PcdKey]\r
261 DscOverride = False\r
262 if PatchPcd and Pcd.Type == PatchPcd.Type:\r
263 DefaultValue = PatchPcd.DefaultValue\r
264 DscOverride = True\r
2bc3256c
LG
265\r
266 # Override Patchable PCD value by the value from FDF\r
e8a47801
LG
267 FdfOverride = False\r
268 if PcdKey in FdfPcdDict:\r
269 DefaultValue = FdfPcdDict[PcdKey]\r
270 FdfOverride = True\r
2bc3256c 271\r
6b17c11b
YZ
272 # Override Patchable PCD value by the value from Build Option\r
273 BuildOptionOverride = False\r
274 if GlobalData.BuildOptionPcd:\r
275 for pcd in GlobalData.BuildOptionPcd:\r
276 if PcdKey == (pcd[1], pcd[0]):\r
8565b582
YZ
277 if pcd[2]:\r
278 continue\r
279 DefaultValue = pcd[3]\r
6b17c11b
YZ
280 BuildOptionOverride = True\r
281 break\r
282\r
283 if not DscOverride and not FdfOverride and not BuildOptionOverride:\r
e8a47801 284 continue\r
0537f332
YF
285\r
286 # Support Flexible PCD format\r
287 if DefaultValue:\r
288 try:\r
289 DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)\r
290 except BadExpression:\r
291 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName)\r
292\r
8565b582 293 if Pcd.InfDefaultValue:\r
0537f332 294 try:\r
8565b582 295 Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True)\r
0537f332
YF
296 except BadExpression:\r
297 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue),File=self.InfFileName)\r
298\r
2bc3256c 299 # Check value, if value are equal, no need to patch\r
e8a47801 300 if Pcd.DatumType == "VOID*":\r
8565b582 301 if Pcd.InfDefaultValue == DefaultValue or DefaultValue in [None, '']:\r
e8a47801 302 continue\r
2bc3256c 303 # Get the string size from FDF or DSC\r
e8a47801 304 if DefaultValue[0] == 'L':\r
2bc3256c 305 # Remove L"", but the '\0' must be appended\r
e8a47801
LG
306 MaxDatumSize = str((len(DefaultValue) - 2) * 2)\r
307 elif DefaultValue[0] == '{':\r
308 MaxDatumSize = str(len(DefaultValue.split(',')))\r
309 else:\r
310 MaxDatumSize = str(len(DefaultValue) - 1)\r
311 if DscOverride:\r
312 Pcd.MaxDatumSize = PatchPcd.MaxDatumSize\r
2bc3256c 313 # If no defined the maximum size in DSC, try to get current size from INF\r
e8a47801 314 if Pcd.MaxDatumSize in ['', None]:\r
8565b582 315 Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))\r
e8a47801
LG
316 else:\r
317 Base1 = Base2 = 10\r
8565b582 318 if Pcd.InfDefaultValue.upper().startswith('0X'):\r
e8a47801
LG
319 Base1 = 16\r
320 if DefaultValue.upper().startswith('0X'):\r
321 Base2 = 16\r
322 try:\r
8565b582 323 PcdValueInImg = int(Pcd.InfDefaultValue, Base1)\r
e8a47801
LG
324 PcdValueInDscOrFdf = int(DefaultValue, Base2)\r
325 if PcdValueInImg == PcdValueInDscOrFdf:\r
326 continue\r
327 except:\r
328 continue\r
2bc3256c 329 # Check the Pcd size and data type\r
e8a47801
LG
330 if Pcd.DatumType == "VOID*":\r
331 if int(MaxDatumSize) > int(Pcd.MaxDatumSize):\r
332 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \\r
333 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))\r
334 else:\r
335 if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \\r
336 or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:\r
337 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \\r
338 % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
97fa0ee9
YL
339 self.PatchPcds.append((Pcd, DefaultValue))\r
340\r
4234283c 341 self.InfModule = Inf\r
e8a47801
LG
342 self.PcdIsDriver = Inf.PcdIsDriver\r
343 self.IsBinaryModule = Inf.IsBinaryModule\r
37de70b7
YZ
344 Inf._GetDepex()\r
345 Inf._GetDepexExpression()\r
346 if len(Inf._Depex.data) > 0 and len(Inf._DepexExpression.data) > 0:\r
347 self.Depex = True\r
348\r
e8a47801
LG
349 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)\r
350 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)\r
351 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)\r
352 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)\r
353 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)\r
30fdf114
LG
354\r
355 #\r
356 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
357 #\r
358\r
359 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
360 self.ModuleGuid + self.BaseName)\r
361 if not os.path.exists(self.OutputPath) :\r
362 os.makedirs(self.OutputPath)\r
363\r
37de70b7 364 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()\r
30fdf114
LG
365 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
366\r
97fa0ee9 367 ## PatchEfiFile\r
e8a47801
LG
368 #\r
369 # Patch EFI file with patch PCD\r
370 #\r
371 # @param EfiFile: EFI file needs to be patched.\r
372 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name\r
373 # If passed in file does not end with efi, return as is\r
374 #\r
97fa0ee9 375 def PatchEfiFile(self, EfiFile, FileType):\r
b21a13fb
YZ
376 #\r
377 # If the module does not have any patches, then return path to input file\r
378 # \r
e8a47801
LG
379 if not self.PatchPcds:\r
380 return EfiFile\r
b21a13fb
YZ
381\r
382 #\r
383 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED\r
384 # \r
97fa0ee9
YL
385 if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":\r
386 return EfiFile\r
b21a13fb
YZ
387\r
388 #\r
389 # Generate path to patched output file\r
390 #\r
391 Basename = os.path.basename(EfiFile)\r
392 Output = os.path.normpath (os.path.join(self.OutputPath, Basename))\r
393\r
394 #\r
395 # If this file has already been patched, then return the path to the patched file\r
396 #\r
397 if self.PatchedBinFile == Output:\r
398 return Output\r
399\r
400 #\r
401 # If a different file from the same module has already been patched, then generate an error\r
402 # \r
97fa0ee9
YL
403 if self.PatchedBinFile:\r
404 EdkLogger.error("GenFds", GENFDS_ERROR,\r
405 'Only one binary file can be patched:\n'\r
406 ' a binary file has been patched: %s\n'\r
407 ' current file: %s' % (self.PatchedBinFile, EfiFile),\r
408 File=self.InfFileName)\r
b21a13fb
YZ
409\r
410 #\r
411 # Copy unpatched file contents to output file location to perform patching\r
412 # \r
1be2ed90 413 CopyLongFilePath(EfiFile, Output)\r
b21a13fb
YZ
414\r
415 #\r
416 # Apply patches to patched output file\r
417 # \r
97fa0ee9
YL
418 for Pcd, Value in self.PatchPcds:\r
419 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)\r
e8a47801
LG
420 if RetVal:\r
421 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)\r
b21a13fb
YZ
422\r
423 #\r
424 # Save the path of the patched output file\r
425 # \r
426 self.PatchedBinFile = Output\r
427\r
428 #\r
429 # Return path to patched output file\r
430 # \r
e8a47801 431 return Output\r
b21a13fb 432\r
30fdf114
LG
433 ## GenFfs() method\r
434 #\r
435 # Generate FFS\r
436 #\r
52302d4d
LG
437 # @param self The object pointer\r
438 # @param Dict dictionary contains macro and value pair\r
439 # @param FvChildAddr Array of the inside FvImage base address\r
440 # @param FvParentAddr Parent Fv base address\r
441 # @retval string Generated FFS file name\r
30fdf114 442 #\r
a743986d 443 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None):\r
30fdf114
LG
444 #\r
445 # Parse Inf file get Module related information\r
446 #\r
447\r
448 self.__InfParse__(Dict)\r
37de70b7 449 Arch = self.GetCurrentArch()\r
05cc51ad 450 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);\r
0acb3d28 451 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
6780eef1 452 \r
0acb3d28
AC
453 SrcFileDir = "."\r
454 SrcPath = os.path.dirname(SrcFile)\r
455 SrcFileName = os.path.basename(SrcFile)\r
456 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName) \r
457 DestPath = os.path.dirname(DestFile)\r
458 DestFileName = os.path.basename(DestFile)\r
459 DestFileBase, DestFileExt = os.path.splitext(DestFileName) \r
460 self.MacroDict = {\r
461 # source file\r
462 "${src}" : SrcFile,\r
463 "${s_path}" : SrcPath,\r
464 "${s_dir}" : SrcFileDir,\r
465 "${s_name}" : SrcFileName,\r
466 "${s_base}" : SrcFileBase,\r
467 "${s_ext}" : SrcFileExt,\r
468 # destination file\r
469 "${dst}" : DestFile,\r
470 "${d_path}" : DestPath,\r
471 "${d_name}" : DestFileName,\r
472 "${d_base}" : DestFileBase,\r
473 "${d_ext}" : DestFileExt\r
474 }\r
6780eef1
LG
475 #\r
476 # Allow binary type module not specify override rule in FDF file.\r
477 # \r
97fa0ee9 478 if len(self.BinFileList) > 0:\r
4231a819 479 if self.Rule is None or self.Rule == "":\r
6780eef1 480 self.Rule = "BINARY"\r
37de70b7
YZ
481\r
482 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':\r
483 IsMakefile = True\r
30fdf114
LG
484 #\r
485 # Get the rule of how to generate Ffs file\r
486 #\r
487 Rule = self.__GetRule__()\r
488 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
b303ea72
LG
489 #\r
490 # Convert Fv File Type for PI1.1 SMM driver.\r
491 #\r
da92f276 492 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
493 if Rule.FvFileType == 'DRIVER':\r
494 Rule.FvFileType = 'SMM'\r
495 #\r
496 # Framework SMM Driver has no SMM FV file type\r
497 #\r
da92f276 498 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
499 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':\r
500 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
501 #\r
502 # For the rule only has simpleFile\r
503 #\r
37de70b7 504 MakefilePath = None\r
a146c532
FY
505 if self.IsBinaryModule:\r
506 IsMakefile = False\r
37de70b7
YZ
507 if IsMakefile:\r
508 MakefilePath = self.InfFileName, 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
0acb3d28 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
573 'COMMON' + \\r
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
615 for key in PlatformDataBase.Modules.keys():\r
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
698 Arch ,\r
699 ModulePath,\r
700 FileName,\r
701 'OUTPUT'\r
702 )\r
37de70b7
YZ
703 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
704 Arch ,\r
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
da92f276 742 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
743 if SectionType == 'DXE_DEPEX':\r
744 SectionType = 'SMM_DEPEX'\r
745 #\r
746 # Framework SMM Driver has no SMM_DEPEX section type\r
747 #\r
da92f276 748 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
749 if SectionType == 'SMM_DEPEX':\r
750 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
30fdf114
LG
751 NoStrip = True\r
752 if self.ModuleType in ('SEC', 'PEI_CORE', '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
765 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
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
771 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
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
52302d4d 776 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
e921f58d
YZ
777 else:\r
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
794 if SectionType == 'TE':\r
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
808 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
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
813 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
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
52302d4d 818 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
e921f58d
YZ
819 else:\r
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
837 if SectionType == 'TE':\r
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
YZ
886 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,\r
887 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
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
30fdf114 906 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\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
da92f276 945 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
946 if Sect.SectionType == 'DXE_DEPEX':\r
947 Sect.SectionType = 'SMM_DEPEX'\r
948 #\r
949 # Framework SMM Driver has no SMM_DEPEX section type\r
950 #\r
da92f276 951 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
952 if Sect.SectionType == 'SMM_DEPEX':\r
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
LG
963 Sect.FvParentAddr = FvParentAddr\r
964 \r
30fdf114 965 if Rule.KeyStringList != []:\r
37de70b7 966 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)\r
30fdf114 967 else :\r
37de70b7 968 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)\r
da92f276 969 \r
37de70b7 970 if not HasGeneratedFlag:\r
da92f276 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
982 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
983 #\r
984 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
985 if SourceFile.Type.upper() == ".UNI" :\r
986 #\r
987 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
988 #\r
989 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")\r
990 \r
991 \r
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
1014 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
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
da92f276 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
37de70b7
YZ
1060 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
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
1068 ## __GetGenFfsCmdParameter__() method\r
1069 #\r
1070 # Create parameter string for GenFfs\r
1071 #\r
1072 # @param self The object pointer\r
1073 # @param Rule The rule object used to generate section\r
1074 # @retval tuple (FileType, Fixed, CheckSum, Alignment)\r
1075 #\r
1076 def __GetGenFfsCmdParameter__(self, Rule):\r
1077 result = tuple()\r
1078 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])\r
1079 if Rule.Fixed != False:\r
1080 result += ('-x',)\r
1081 if Rule.CheckSum != False:\r
1082 result += ('-s',)\r
1083\r
4231a819 1084 if Rule.Alignment is not None and Rule.Alignment != '':\r
30fdf114
LG
1085 result += ('-a', Rule.Alignment)\r
1086\r
1087 return result\r
da92f276
LG
1088 \r
1089 ## __GetBuildOutputMapFileVfrUniInfo() method\r
1090 #\r
1091 # Find the offset of UNI/INF object offset in the EFI image file.\r
1092 #\r
1093 # @param self The object pointer\r
1094 # @param VfrUniBaseName A name list contain the UNI/INF object name.\r
1095 # @retval RetValue A list contain offset of UNI/INF object.\r
1096 # \r
1097 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):\r
da92f276 1098 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")\r
22a99b87
YL
1099 EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")\r
1100 return GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
da92f276
LG
1101 \r
1102 ## __GenUniVfrOffsetFile() method\r
1103 #\r
1104 # Generate the offset file for the module which contain VFR or UNI file.\r
1105 #\r
1106 # @param self The object pointer\r
1107 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.\r
1108 # @param UniVfrOffsetFileName The output offset file name.\r
1109 #\r
1110 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):\r
37de70b7 1111\r
da92f276
LG
1112 # Use a instance of StringIO to cache data\r
1113 fStringIO = StringIO.StringIO('') \r
1114 \r
1115 for Item in VfrUniOffsetList:\r
1116 if (Item[0].find("Strings") != -1):\r
1117 #\r
1118 # UNI offset in image.\r
1119 # GUID + Offset\r
1120 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
1121 #\r
1122 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
1123 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
1124 fStringIO.write(''.join(UniGuid)) \r
1125 UniValue = pack ('Q', int (Item[1], 16))\r
1126 fStringIO.write (UniValue)\r
1127 else:\r
1128 #\r
1129 # VFR binary offset in image.\r
1130 # GUID + Offset\r
1131 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
1132 #\r
1133 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
1134 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
1135 fStringIO.write(''.join(VfrGuid)) \r
1136 type (Item[1]) \r
1137 VfrValue = pack ('Q', int (Item[1], 16))\r
1138 fStringIO.write (VfrValue)\r
1139 \r
1140 #\r
1141 # write data into file.\r
1142 #\r
37de70b7
YZ
1143 try :\r
1144 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())\r
da92f276
LG
1145 except:\r
1146 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
1147 \r
1148 fStringIO.close ()\r
37de70b7 1149\r
da92f276 1150 \r