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