]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/FfsInfStatement.py
MdeModulePkg/DxePrintLibPrint2Protocol: fix GCC5 build break
[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
30fdf114
LG
49\r
50## generate FFS from INF\r
51#\r
52#\r
53class FfsInfStatement(FfsInfStatementClassObject):\r
2bc3256c
LG
54 ## The mapping dictionary from datum type to its maximum number.\r
55 _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}\r
30fdf114
LG
56 ## The constructor\r
57 #\r
58 # @param self The object pointer\r
59 #\r
60 def __init__(self):\r
61 FfsInfStatementClassObject.__init__(self)\r
62 self.TargetOverrideList = []\r
63 self.ShadowFromInfFile = None\r
64 self.KeepRelocFromRule = None\r
65 self.InDsc = True\r
66 self.OptRomDefs = {}\r
da92f276 67 self.PiSpecVersion = '0x00000000'\r
4234283c 68 self.InfModule = None\r
b36d134f 69 self.FinalTargetSuffixMap = {}\r
79b74a03
LG
70 self.CurrentLineNum = None\r
71 self.CurrentLineContent = None\r
72 self.FileName = None\r
73 self.InfFileName = None\r
97fa0ee9
YL
74 self.OverrideGuid = None\r
75 self.PatchedBinFile = ''\r
7ae7dcb9 76 self.MacroDict = {}\r
37de70b7 77 self.Depex = False\r
4234283c 78\r
b36d134f 79 ## GetFinalTargetSuffixMap() method\r
4234283c
LG
80 #\r
81 # Get final build target list\r
b36d134f 82 def GetFinalTargetSuffixMap(self):\r
4234283c
LG
83 if not self.InfModule or not self.CurrentArch:\r
84 return []\r
b36d134f
LG
85 if not self.FinalTargetSuffixMap:\r
86 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)\r
87 for File in FinalBuildTargetList:\r
88 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)\r
89\r
90 # Check if current INF module has DEPEX\r
91 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \\r
92 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:\r
93 ModuleType = self.InfModule.ModuleType\r
94 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
95\r
96 if ModuleType != DataType.SUP_MODULE_USER_DEFINED:\r
97 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():\r
98 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:\r
99 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]\r
100\r
101 StrModule = str(self.InfModule)\r
102 PlatformModule = None\r
103 if StrModule in PlatformDataBase.Modules:\r
104 PlatformModule = PlatformDataBase.Modules[StrModule]\r
105 for LibraryClass in PlatformModule.LibraryClasses:\r
106 if LibraryClass.startswith("NULL"):\r
107 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
108\r
109 DependencyList = [self.InfModule]\r
110 LibraryInstance = {}\r
111 DepexList = []\r
112 while len(DependencyList) > 0:\r
113 Module = DependencyList.pop(0)\r
114 if not Module:\r
115 continue\r
116 for Dep in Module.Depex[self.CurrentArch, ModuleType]:\r
117 if DepexList != []:\r
118 DepexList.append('AND')\r
119 DepexList.append('(')\r
120 DepexList.extend(Dep)\r
121 if DepexList[-1] == 'END': # no need of a END at this time\r
122 DepexList.pop()\r
123 DepexList.append(')')\r
124 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
125 break\r
126 for LibName in Module.LibraryClasses:\r
127 if LibName in LibraryInstance:\r
128 continue\r
129 if PlatformModule and LibName in PlatformModule.LibraryClasses:\r
130 LibraryPath = PlatformModule.LibraryClasses[LibName]\r
131 else:\r
132 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]\r
133 if not LibraryPath:\r
134 LibraryPath = Module.LibraryClasses[LibName]\r
135 if not LibraryPath:\r
136 continue\r
137 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
138 LibraryInstance[LibName] = LibraryModule\r
139 DependencyList.append(LibraryModule)\r
140 if DepexList:\r
141 Dpx = DependencyExpression(DepexList, ModuleType, True)\r
142 if len(Dpx.PostfixNotation) != 0:\r
143 # It means this module has DEPEX\r
144 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']\r
145 return self.FinalTargetSuffixMap\r
4234283c 146\r
30fdf114
LG
147 ## __InfParse() method\r
148 #\r
149 # Parse inf file to get module information\r
150 #\r
151 # @param self The object pointer\r
152 # @param Dict dictionary contains macro and value pair\r
153 #\r
154 def __InfParse__(self, Dict = {}):\r
155\r
156 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
157\r
158 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
97fa0ee9
YL
159 if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':\r
160 pass\r
161 elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
30fdf114
LG
162 self.InfFileName = self.InfFileName[1:]\r
163\r
164 if self.InfFileName.find('$') == -1:\r
165 InfPath = NormPath(self.InfFileName)\r
166 if not os.path.exists(InfPath):\r
167 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)\r
168 if not os.path.exists(InfPath):\r
169 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))\r
170\r
171 self.CurrentArch = self.GetCurrentArch()\r
172 #\r
173 # Get the InfClass object\r
174 #\r
175\r
176 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 177 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
178 if ErrorCode != 0:\r
179 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
97fa0ee9 180\r
4aa9826d
YZ
181 #\r
182 # Cache lower case version of INF path before processing FILE_GUID override\r
183 #\r
184 InfLowerPath = str(PathClassObj).lower()\r
97fa0ee9
YL
185 if self.OverrideGuid:\r
186 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)\r
30fdf114
LG
187 if self.CurrentArch != None:\r
188\r
0d2711a6 189 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
190 #\r
191 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
192 #\r
193 self.BaseName = Inf.BaseName\r
194 self.ModuleGuid = Inf.Guid\r
195 self.ModuleType = Inf.ModuleType\r
52302d4d 196 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 197 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
198 if Inf.AutoGenVersion < 0x00010005:\r
199 self.ModuleType = Inf.ComponentType\r
200 self.VersionString = Inf.Version\r
201 self.BinFileList = Inf.Binaries\r
202 self.SourceFileList = Inf.Sources\r
203 if self.KeepReloc == None and Inf.Shadow:\r
204 self.ShadowFromInfFile = Inf.Shadow\r
205\r
206 else:\r
0d2711a6 207 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
208 self.BaseName = Inf.BaseName\r
209 self.ModuleGuid = Inf.Guid\r
210 self.ModuleType = Inf.ModuleType\r
52302d4d 211 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 212 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
213 self.VersionString = Inf.Version\r
214 self.BinFileList = Inf.Binaries\r
215 self.SourceFileList = Inf.Sources\r
216 if self.BinFileList == []:\r
217 EdkLogger.error("GenFds", GENFDS_ERROR,\r
218 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
219 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
220\r
97fa0ee9
YL
221 if self.OverrideGuid:\r
222 self.ModuleGuid = self.OverrideGuid\r
223\r
30fdf114
LG
224 if len(self.SourceFileList) != 0 and not self.InDsc:\r
225 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
226\r
da92f276 227 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
228 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
229\r
b19df640
SV
230 if self.ModuleType == 'MM_CORE_STANDALONE' and int(self.PiSpecVersion, 16) < 0x00010032:\r
231 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
232\r
30fdf114
LG
233 if Inf._Defs != None and len(Inf._Defs) > 0:\r
234 self.OptRomDefs.update(Inf._Defs)\r
2bc3256c 235\r
e8a47801
LG
236 self.PatchPcds = []\r
237 InfPcds = Inf.Pcds\r
238 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
239 FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict\r
2bc3256c
LG
240\r
241 # Workaround here: both build and GenFds tool convert the workspace path to lower case\r
242 # But INF file path in FDF and DSC file may have real case characters.\r
243 # Try to convert the path to lower case to see if PCDs value are override by DSC.\r
e8a47801
LG
244 DscModules = {}\r
245 for DscModule in Platform.Modules:\r
246 DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]\r
247 for PcdKey in InfPcds:\r
248 Pcd = InfPcds[PcdKey]\r
249 if not hasattr(Pcd, 'Offset'):\r
250 continue\r
251 if Pcd.Type != 'PatchableInModule':\r
252 continue\r
2bc3256c 253 # Override Patchable PCD value by the value from DSC\r
e8a47801 254 PatchPcd = None\r
e8a47801
LG
255 if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:\r
256 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]\r
257 elif PcdKey in Platform.Pcds:\r
258 PatchPcd = Platform.Pcds[PcdKey]\r
259 DscOverride = False\r
260 if PatchPcd and Pcd.Type == PatchPcd.Type:\r
261 DefaultValue = PatchPcd.DefaultValue\r
262 DscOverride = True\r
2bc3256c
LG
263\r
264 # Override Patchable PCD value by the value from FDF\r
e8a47801
LG
265 FdfOverride = False\r
266 if PcdKey in FdfPcdDict:\r
267 DefaultValue = FdfPcdDict[PcdKey]\r
268 FdfOverride = True\r
2bc3256c 269\r
6b17c11b
YZ
270 # Override Patchable PCD value by the value from Build Option\r
271 BuildOptionOverride = False\r
272 if GlobalData.BuildOptionPcd:\r
273 for pcd in GlobalData.BuildOptionPcd:\r
274 if PcdKey == (pcd[1], pcd[0]):\r
275 DefaultValue = pcd[2]\r
276 BuildOptionOverride = True\r
277 break\r
278\r
279 if not DscOverride and not FdfOverride and not BuildOptionOverride:\r
e8a47801 280 continue\r
2bc3256c 281 # Check value, if value are equal, no need to patch\r
e8a47801
LG
282 if Pcd.DatumType == "VOID*":\r
283 if Pcd.DefaultValue == DefaultValue or DefaultValue in [None, '']:\r
284 continue\r
2bc3256c 285 # Get the string size from FDF or DSC\r
e8a47801 286 if DefaultValue[0] == 'L':\r
2bc3256c 287 # Remove L"", but the '\0' must be appended\r
e8a47801
LG
288 MaxDatumSize = str((len(DefaultValue) - 2) * 2)\r
289 elif DefaultValue[0] == '{':\r
290 MaxDatumSize = str(len(DefaultValue.split(',')))\r
291 else:\r
292 MaxDatumSize = str(len(DefaultValue) - 1)\r
293 if DscOverride:\r
294 Pcd.MaxDatumSize = PatchPcd.MaxDatumSize\r
2bc3256c 295 # If no defined the maximum size in DSC, try to get current size from INF\r
e8a47801
LG
296 if Pcd.MaxDatumSize in ['', None]:\r
297 Pcd.MaxDatumSize = str(len(Pcd.DefaultValue.split(',')))\r
298 else:\r
299 Base1 = Base2 = 10\r
300 if Pcd.DefaultValue.upper().startswith('0X'):\r
301 Base1 = 16\r
302 if DefaultValue.upper().startswith('0X'):\r
303 Base2 = 16\r
304 try:\r
305 PcdValueInImg = int(Pcd.DefaultValue, Base1)\r
306 PcdValueInDscOrFdf = int(DefaultValue, Base2)\r
307 if PcdValueInImg == PcdValueInDscOrFdf:\r
308 continue\r
309 except:\r
310 continue\r
2bc3256c 311 # Check the Pcd size and data type\r
e8a47801
LG
312 if Pcd.DatumType == "VOID*":\r
313 if int(MaxDatumSize) > int(Pcd.MaxDatumSize):\r
314 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \\r
315 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))\r
316 else:\r
317 if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \\r
318 or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:\r
319 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \\r
320 % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
97fa0ee9
YL
321 self.PatchPcds.append((Pcd, DefaultValue))\r
322\r
4234283c 323 self.InfModule = Inf\r
e8a47801
LG
324 self.PcdIsDriver = Inf.PcdIsDriver\r
325 self.IsBinaryModule = Inf.IsBinaryModule\r
37de70b7
YZ
326 Inf._GetDepex()\r
327 Inf._GetDepexExpression()\r
328 if len(Inf._Depex.data) > 0 and len(Inf._DepexExpression.data) > 0:\r
329 self.Depex = True\r
330\r
e8a47801
LG
331 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)\r
332 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)\r
333 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)\r
334 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)\r
335 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)\r
30fdf114
LG
336\r
337 #\r
338 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
339 #\r
340\r
341 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
342 self.ModuleGuid + self.BaseName)\r
343 if not os.path.exists(self.OutputPath) :\r
344 os.makedirs(self.OutputPath)\r
345\r
37de70b7 346 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()\r
30fdf114
LG
347 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
348\r
97fa0ee9 349 ## PatchEfiFile\r
e8a47801
LG
350 #\r
351 # Patch EFI file with patch PCD\r
352 #\r
353 # @param EfiFile: EFI file needs to be patched.\r
354 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name\r
355 # If passed in file does not end with efi, return as is\r
356 #\r
97fa0ee9 357 def PatchEfiFile(self, EfiFile, FileType):\r
b21a13fb
YZ
358 #\r
359 # If the module does not have any patches, then return path to input file\r
360 # \r
e8a47801
LG
361 if not self.PatchPcds:\r
362 return EfiFile\r
b21a13fb
YZ
363\r
364 #\r
365 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED\r
366 # \r
97fa0ee9
YL
367 if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":\r
368 return EfiFile\r
b21a13fb
YZ
369\r
370 #\r
371 # Generate path to patched output file\r
372 #\r
373 Basename = os.path.basename(EfiFile)\r
374 Output = os.path.normpath (os.path.join(self.OutputPath, Basename))\r
375\r
376 #\r
377 # If this file has already been patched, then return the path to the patched file\r
378 #\r
379 if self.PatchedBinFile == Output:\r
380 return Output\r
381\r
382 #\r
383 # If a different file from the same module has already been patched, then generate an error\r
384 # \r
97fa0ee9
YL
385 if self.PatchedBinFile:\r
386 EdkLogger.error("GenFds", GENFDS_ERROR,\r
387 'Only one binary file can be patched:\n'\r
388 ' a binary file has been patched: %s\n'\r
389 ' current file: %s' % (self.PatchedBinFile, EfiFile),\r
390 File=self.InfFileName)\r
b21a13fb
YZ
391\r
392 #\r
393 # Copy unpatched file contents to output file location to perform patching\r
394 # \r
1be2ed90 395 CopyLongFilePath(EfiFile, Output)\r
b21a13fb
YZ
396\r
397 #\r
398 # Apply patches to patched output file\r
399 # \r
97fa0ee9
YL
400 for Pcd, Value in self.PatchPcds:\r
401 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)\r
e8a47801
LG
402 if RetVal:\r
403 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)\r
b21a13fb
YZ
404\r
405 #\r
406 # Save the path of the patched output file\r
407 # \r
408 self.PatchedBinFile = Output\r
409\r
410 #\r
411 # Return path to patched output file\r
412 # \r
e8a47801 413 return Output\r
b21a13fb 414\r
30fdf114
LG
415 ## GenFfs() method\r
416 #\r
417 # Generate FFS\r
418 #\r
52302d4d
LG
419 # @param self The object pointer\r
420 # @param Dict dictionary contains macro and value pair\r
421 # @param FvChildAddr Array of the inside FvImage base address\r
422 # @param FvParentAddr Parent Fv base address\r
423 # @retval string Generated FFS file name\r
30fdf114 424 #\r
37de70b7 425 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None, IsMakefile=False):\r
30fdf114
LG
426 #\r
427 # Parse Inf file get Module related information\r
428 #\r
429\r
430 self.__InfParse__(Dict)\r
37de70b7 431 Arch = self.GetCurrentArch()\r
05cc51ad 432 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);\r
0acb3d28 433 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
6780eef1 434 \r
0acb3d28
AC
435 SrcFileDir = "."\r
436 SrcPath = os.path.dirname(SrcFile)\r
437 SrcFileName = os.path.basename(SrcFile)\r
438 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName) \r
439 DestPath = os.path.dirname(DestFile)\r
440 DestFileName = os.path.basename(DestFile)\r
441 DestFileBase, DestFileExt = os.path.splitext(DestFileName) \r
442 self.MacroDict = {\r
443 # source file\r
444 "${src}" : SrcFile,\r
445 "${s_path}" : SrcPath,\r
446 "${s_dir}" : SrcFileDir,\r
447 "${s_name}" : SrcFileName,\r
448 "${s_base}" : SrcFileBase,\r
449 "${s_ext}" : SrcFileExt,\r
450 # destination file\r
451 "${dst}" : DestFile,\r
452 "${d_path}" : DestPath,\r
453 "${d_name}" : DestFileName,\r
454 "${d_base}" : DestFileBase,\r
455 "${d_ext}" : DestFileExt\r
456 }\r
6780eef1
LG
457 #\r
458 # Allow binary type module not specify override rule in FDF file.\r
459 # \r
97fa0ee9 460 if len(self.BinFileList) > 0:\r
6780eef1
LG
461 if self.Rule == None or self.Rule == "":\r
462 self.Rule = "BINARY"\r
37de70b7
YZ
463\r
464 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':\r
465 IsMakefile = True\r
30fdf114
LG
466 #\r
467 # Get the rule of how to generate Ffs file\r
468 #\r
469 Rule = self.__GetRule__()\r
470 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
b303ea72
LG
471 #\r
472 # Convert Fv File Type for PI1.1 SMM driver.\r
473 #\r
da92f276 474 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
475 if Rule.FvFileType == 'DRIVER':\r
476 Rule.FvFileType = 'SMM'\r
477 #\r
478 # Framework SMM Driver has no SMM FV file type\r
479 #\r
da92f276 480 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
481 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':\r
482 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
483 #\r
484 # For the rule only has simpleFile\r
485 #\r
37de70b7
YZ
486 MakefilePath = None\r
487 if IsMakefile:\r
488 MakefilePath = self.InfFileName, Arch\r
30fdf114 489 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :\r
37de70b7
YZ
490 SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)\r
491 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)\r
30fdf114
LG
492 return FfsOutput\r
493 #\r
494 # For Rule has ComplexFile\r
495 #\r
496 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):\r
37de70b7
YZ
497 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)\r
498 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)\r
30fdf114
LG
499 return FfsOutput\r
500\r
501 ## __ExtendMacro__() method\r
502 #\r
503 # Replace macro with its value\r
504 #\r
505 # @param self The object pointer\r
506 # @param String The string to be replaced\r
507 # @retval string Macro replaced string\r
508 #\r
509 def __ExtendMacro__ (self, String):\r
510 MacroDict = {\r
511 '$(INF_OUTPUT)' : self.EfiOutputPath,\r
512 '$(MODULE_NAME)' : self.BaseName,\r
513 '$(BUILD_NUMBER)': self.BuildNum,\r
514 '$(INF_VERSION)' : self.VersionString,\r
515 '$(NAMED_GUID)' : self.ModuleGuid\r
516 }\r
517 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
0acb3d28 518 String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict) \r
30fdf114
LG
519 return String\r
520\r
521 ## __GetRule__() method\r
522 #\r
523 # Get correct rule for generating FFS for this INF\r
524 #\r
525 # @param self The object pointer\r
526 # @retval Rule Rule object\r
527 #\r
528 def __GetRule__ (self) :\r
529 CurrentArchList = []\r
530 if self.CurrentArch == None:\r
531 CurrentArchList = ['common']\r
532 else:\r
533 CurrentArchList.append(self.CurrentArch)\r
534\r
535 for CurrentArch in CurrentArchList:\r
536 RuleName = 'RULE' + \\r
537 '.' + \\r
538 CurrentArch.upper() + \\r
539 '.' + \\r
540 self.ModuleType.upper()\r
541 if self.Rule != None:\r
542 RuleName = RuleName + \\r
543 '.' + \\r
544 self.Rule.upper()\r
545\r
546 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
547 if Rule != None:\r
548 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
549 return Rule\r
550\r
551 RuleName = 'RULE' + \\r
552 '.' + \\r
553 'COMMON' + \\r
554 '.' + \\r
555 self.ModuleType.upper()\r
556\r
557 if self.Rule != None:\r
558 RuleName = RuleName + \\r
559 '.' + \\r
560 self.Rule.upper()\r
561\r
562 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))\r
563\r
564 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
565 if Rule != None:\r
566 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
567 return Rule\r
568\r
569 if Rule == None :\r
570 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \\r
571 % (RuleName, self.InfFileName))\r
572\r
573 ## __GetPlatformArchList__() method\r
574 #\r
575 # Get Arch list this INF built under\r
576 #\r
577 # @param self The object pointer\r
578 # @retval list Arch list\r
579 #\r
580 def __GetPlatformArchList__(self):\r
581\r
05cc51ad 582 InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))\r
30fdf114 583 DscArchList = []\r
77177984
TP
584 for Arch in GenFdsGlobalVariable.ArchList :\r
585 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
586 if PlatformDataBase != None:\r
587 if InfFileKey in PlatformDataBase.Modules:\r
588 DscArchList.append (Arch)\r
4ce415e5
YZ
589 else:\r
590 #\r
591 # BaseTools support build same module more than once, the module path with FILE_GUID overridden has\r
592 # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,\r
593 # but the path (self.MetaFile.Path) is the real path\r
594 #\r
595 for key in PlatformDataBase.Modules.keys():\r
596 if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):\r
597 DscArchList.append (Arch)\r
598 break\r
4afd3d04 599\r
30fdf114
LG
600 return DscArchList\r
601\r
602 ## GetCurrentArch() method\r
603 #\r
604 # Get Arch list of the module from this INF is to be placed into flash\r
605 #\r
606 # @param self The object pointer\r
607 # @retval list Arch list\r
608 #\r
609 def GetCurrentArch(self) :\r
610\r
611 TargetArchList = GenFdsGlobalVariable.ArchList\r
612\r
613 PlatformArchList = self.__GetPlatformArchList__()\r
614\r
615 CurArchList = TargetArchList\r
616 if PlatformArchList != []:\r
617 CurArchList = list(set (TargetArchList) & set (PlatformArchList))\r
618 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))\r
619\r
620 ArchList = []\r
621 if self.KeyStringList != []:\r
622 for Key in self.KeyStringList:\r
623 Key = GenFdsGlobalVariable.MacroExtend(Key)\r
624 Target, Tag, Arch = Key.split('_')\r
625 if Arch in CurArchList:\r
626 ArchList.append(Arch)\r
627 if Target not in self.TargetOverrideList:\r
628 self.TargetOverrideList.append(Target)\r
629 else:\r
630 ArchList = CurArchList\r
631\r
632 UseArchList = TargetArchList\r
633 if self.UseArch != None:\r
634 UseArchList = []\r
635 UseArchList.append(self.UseArch)\r
636 ArchList = list(set (UseArchList) & set (ArchList))\r
637\r
638 self.InfFileName = NormPath(self.InfFileName)\r
639 if len(PlatformArchList) == 0:\r
640 self.InDsc = False\r
641 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 642 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
643 if ErrorCode != 0:\r
644 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
645 if len(ArchList) == 1:\r
646 Arch = ArchList[0]\r
647 return Arch\r
648 elif len(ArchList) > 1:\r
649 if len(PlatformArchList) == 0:\r
650 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
651 else:\r
652 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
653 else:\r
654 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
655 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))\r
656\r
657 ## __GetEFIOutPutPath__() method\r
658 #\r
659 # Get the output path for generated files\r
660 #\r
661 # @param self The object pointer\r
662 # @retval string Path that output files from this INF go to\r
663 #\r
664 def __GetEFIOutPutPath__(self):\r
665 Arch = ''\r
666 OutputPath = ''\r
37de70b7 667 DebugPath = ''\r
30fdf114 668 (ModulePath, FileName) = os.path.split(self.InfFileName)\r
79b74a03 669 Index = FileName.rfind('.')\r
30fdf114 670 FileName = FileName[0:Index]\r
97fa0ee9
YL
671 if self.OverrideGuid:\r
672 FileName = self.OverrideGuid\r
30fdf114
LG
673 Arch = "NoneArch"\r
674 if self.CurrentArch != None:\r
675 Arch = self.CurrentArch\r
676\r
677 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
678 Arch ,\r
679 ModulePath,\r
680 FileName,\r
681 'OUTPUT'\r
682 )\r
37de70b7
YZ
683 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
684 Arch ,\r
685 ModulePath,\r
686 FileName,\r
687 'DEBUG'\r
688 )\r
30fdf114 689 OutputPath = os.path.realpath(OutputPath)\r
37de70b7
YZ
690 DebugPath = os.path.realpath(DebugPath)\r
691 return OutputPath, DebugPath\r
30fdf114
LG
692\r
693 ## __GenSimpleFileSection__() method\r
694 #\r
695 # Generate section by specified file name or a list of files with file extension\r
696 #\r
697 # @param self The object pointer\r
698 # @param Rule The rule object used to generate section\r
699 # @retval string File name of the generated section file\r
700 #\r
37de70b7 701 def __GenSimpleFileSection__(self, Rule, IsMakefile = False):\r
30fdf114
LG
702 #\r
703 # Prepare the parameter of GenSection\r
704 #\r
705 FileList = []\r
706 OutputFileList = []\r
52302d4d 707 GenSecInputFile = None\r
30fdf114
LG
708 if Rule.FileName != None:\r
709 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)\r
da92f276
LG
710 if os.path.isabs(GenSecInputFile):\r
711 GenSecInputFile = os.path.normpath(GenSecInputFile)\r
712 else:\r
52302d4d 713 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))\r
30fdf114
LG
714 else:\r
715 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)\r
716\r
717 Index = 1\r
b303ea72
LG
718 SectionType = Rule.SectionType\r
719 #\r
720 # Convert Fv Section Type for PI1.1 SMM driver.\r
721 #\r
da92f276 722 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
723 if SectionType == 'DXE_DEPEX':\r
724 SectionType = 'SMM_DEPEX'\r
725 #\r
726 # Framework SMM Driver has no SMM_DEPEX section type\r
727 #\r
da92f276 728 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
729 if SectionType == 'SMM_DEPEX':\r
730 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
30fdf114
LG
731 NoStrip = True\r
732 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
733 if self.KeepReloc != None:\r
734 NoStrip = self.KeepReloc\r
735 elif Rule.KeepReloc != None:\r
736 NoStrip = Rule.KeepReloc\r
737 elif self.ShadowFromInfFile != None:\r
738 NoStrip = self.ShadowFromInfFile\r
739\r
740 if FileList != [] :\r
741 for File in FileList:\r
742\r
743 SecNum = '%d' %Index\r
744 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
745 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
746 Index = Index + 1\r
747 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
748 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)\r
749\r
750 #Get PE Section alignment when align is set to AUTO\r
751 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
752 ImageObj = PeImageClass (File)\r
753 if ImageObj.SectionAlignment < 0x400:\r
754 self.Alignment = str (ImageObj.SectionAlignment)\r
e921f58d 755 elif ImageObj.SectionAlignment < 0x100000:\r
52302d4d 756 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
e921f58d
YZ
757 else:\r
758 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'\r
30fdf114
LG
759\r
760 if not NoStrip:\r
761 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
762 if not os.path.exists(FileBeforeStrip) or \\r
1be2ed90
HC
763 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
764 CopyLongFilePath(File, FileBeforeStrip)\r
30fdf114
LG
765 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
766 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
767 StrippedFile,\r
768 [File],\r
769 Strip=True,\r
770 IsMakefile=IsMakefile\r
771 )\r
30fdf114
LG
772 File = StrippedFile\r
773\r
774 if SectionType == 'TE':\r
775 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
776 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
777 TeFile,\r
778 [File],\r
779 Type='te',\r
780 IsMakefile=IsMakefile\r
781 )\r
30fdf114 782 File = TeFile\r
37de70b7 783 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)\r
30fdf114
LG
784 OutputFileList.append(OutputFile)\r
785 else:\r
786 SecNum = '%d' %Index\r
787 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
788 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
789 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
790 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)\r
791\r
792 #Get PE Section alignment when align is set to AUTO\r
793 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
794 ImageObj = PeImageClass (GenSecInputFile)\r
795 if ImageObj.SectionAlignment < 0x400:\r
796 self.Alignment = str (ImageObj.SectionAlignment)\r
e921f58d 797 elif ImageObj.SectionAlignment < 0x100000:\r
52302d4d 798 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
e921f58d
YZ
799 else:\r
800 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'\r
30fdf114
LG
801\r
802 if not NoStrip:\r
803 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
804 if not os.path.exists(FileBeforeStrip) or \\r
1be2ed90
HC
805 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):\r
806 CopyLongFilePath(GenSecInputFile, FileBeforeStrip)\r
807\r
30fdf114
LG
808 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
809 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
810 StrippedFile,\r
811 [GenSecInputFile],\r
812 Strip=True,\r
813 IsMakefile=IsMakefile\r
814 )\r
30fdf114
LG
815 GenSecInputFile = StrippedFile\r
816\r
817 if SectionType == 'TE':\r
818 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
819 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
820 TeFile,\r
821 [GenSecInputFile],\r
822 Type='te',\r
823 IsMakefile=IsMakefile\r
824 )\r
30fdf114 825 GenSecInputFile = TeFile\r
37de70b7 826 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)\r
30fdf114
LG
827 OutputFileList.append(OutputFile)\r
828\r
829 return OutputFileList\r
830\r
831 ## __GenSimpleFileFfs__() method\r
832 #\r
833 # Generate FFS\r
834 #\r
835 # @param self The object pointer\r
836 # @param Rule The rule object used to generate section\r
837 # @param InputFileList The output file list from GenSection\r
838 # @retval string Generated FFS file name\r
839 #\r
37de70b7 840 def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):\r
30fdf114
LG
841 FfsOutput = self.OutputPath + \\r
842 os.sep + \\r
843 self.__ExtendMacro__(Rule.NameGuid) + \\r
844 '.ffs'\r
845\r
846 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))\r
847 InputSection = []\r
848 SectionAlignments = []\r
849 for InputFile in InputFileList:\r
850 InputSection.append(InputFile)\r
52302d4d 851 SectionAlignments.append(Rule.SectAlignment)\r
30fdf114
LG
852\r
853 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
854 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
855 if len(PcdValue) == 0:\r
856 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
857 % (Rule.NameGuid))\r
858 if PcdValue.startswith('{'):\r
859 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
860 RegistryGuidStr = PcdValue\r
861 if len(RegistryGuidStr) == 0:\r
862 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
863 % (Rule.NameGuid))\r
864 self.ModuleGuid = RegistryGuidStr\r
865\r
37de70b7
YZ
866 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,\r
867 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
868 self.ModuleGuid, Fixed=Rule.Fixed,\r
869 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
870 SectionAlign=SectionAlignments,\r
871 MakefilePath=MakefilePath\r
872 )\r
30fdf114
LG
873 return FfsOutput\r
874\r
875 ## __GenComplexFileSection__() method\r
876 #\r
877 # Generate section by sections in Rule\r
878 #\r
52302d4d
LG
879 # @param self The object pointer\r
880 # @param Rule The rule object used to generate section\r
881 # @param FvChildAddr Array of the inside FvImage base address\r
882 # @param FvParentAddr Parent Fv base address\r
883 # @retval string File name of the generated section file\r
30fdf114 884 #\r
37de70b7 885 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):\r
30fdf114
LG
886 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
887 if Rule.KeepReloc != None:\r
888 self.KeepRelocFromRule = Rule.KeepReloc\r
889 SectFiles = []\r
890 SectAlignments = []\r
891 Index = 1\r
37de70b7 892 HasGeneratedFlag = False\r
e8a47801
LG
893 if self.PcdIsDriver == 'PEI_PCD_DRIVER':\r
894 if self.IsBinaryModule:\r
895 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")\r
896 else:\r
897 PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")\r
898 PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")\r
899 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
900 [PcdExDbFileName],\r
901 "EFI_SECTION_RAW",\r
37de70b7 902 IsMakefile = IsMakefile\r
e8a47801
LG
903 )\r
904 SectFiles.append(PcdExDbSecName)\r
905 SectAlignments.append(None)\r
906 elif self.PcdIsDriver == 'DXE_PCD_DRIVER':\r
907 if self.IsBinaryModule:\r
908 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")\r
909 else:\r
910 PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")\r
911 PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")\r
912 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
37de70b7
YZ
913 [PcdExDbFileName],\r
914 "EFI_SECTION_RAW",\r
915 IsMakefile = IsMakefile\r
916 )\r
e8a47801
LG
917 SectFiles.append(PcdExDbSecName)\r
918 SectAlignments.append(None)\r
30fdf114
LG
919 for Sect in Rule.SectionList:\r
920 SecIndex = '%d' %Index\r
921 SectList = []\r
b303ea72
LG
922 #\r
923 # Convert Fv Section Type for PI1.1 SMM driver.\r
924 #\r
da92f276 925 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
926 if Sect.SectionType == 'DXE_DEPEX':\r
927 Sect.SectionType = 'SMM_DEPEX'\r
928 #\r
929 # Framework SMM Driver has no SMM_DEPEX section type\r
930 #\r
da92f276 931 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
932 if Sect.SectionType == 'SMM_DEPEX':\r
933 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
52302d4d
LG
934 #\r
935 # process the inside FvImage from FvSection or GuidSection\r
936 #\r
937 if FvChildAddr != []:\r
938 if isinstance(Sect, FvImageSection):\r
939 Sect.FvAddr = FvChildAddr.pop(0)\r
940 elif isinstance(Sect, GuidSection):\r
941 Sect.FvAddr = FvChildAddr\r
942 if FvParentAddr != None and isinstance(Sect, GuidSection):\r
943 Sect.FvParentAddr = FvParentAddr\r
944 \r
30fdf114 945 if Rule.KeyStringList != []:\r
37de70b7 946 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)\r
30fdf114 947 else :\r
37de70b7 948 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)\r
da92f276 949 \r
37de70b7 950 if not HasGeneratedFlag:\r
da92f276 951 UniVfrOffsetFileSection = "" \r
05cc51ad 952 ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)\r
da92f276
LG
953 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]\r
954 #\r
955 # Search the source list in InfData to find if there are .vfr file exist.\r
956 #\r
957 VfrUniBaseName = {}\r
958 VfrUniOffsetList = []\r
959 for SourceFile in InfData.Sources:\r
960 if SourceFile.Type.upper() == ".VFR" :\r
961 #\r
962 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
963 #\r
964 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
965 if SourceFile.Type.upper() == ".UNI" :\r
966 #\r
967 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
968 #\r
969 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")\r
970 \r
971 \r
972 if len(VfrUniBaseName) > 0:\r
37de70b7
YZ
973 if IsMakefile:\r
974 if InfData.BuildType != 'UEFI_HII':\r
975 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')\r
976 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
977 UniVfrOffsetFileNameList = []\r
978 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
979 TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)\r
980 GenFdsGlobalVariable.SecCmdList.append(TrimCmd)\r
981 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
982 [UniVfrOffsetFileName],\r
983 "EFI_SECTION_RAW",\r
984 IsMakefile = True\r
985 )\r
986 else:\r
987 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)\r
988 #\r
989 # Generate the Raw data of raw section\r
990 #\r
991 if VfrUniOffsetList:\r
992 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')\r
993 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
994 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
995 UniVfrOffsetFileNameList = []\r
996 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
997 """Call GenSection"""\r
998\r
999 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
1000 UniVfrOffsetFileNameList,\r
1001 "EFI_SECTION_RAW"\r
1002 )\r
1003 #os.remove(UniVfrOffsetFileName)\r
1004 if UniVfrOffsetFileSection:\r
587e9dfb 1005 SectList.append(UniVfrOffsetFileSection)\r
37de70b7 1006 HasGeneratedFlag = True\r
da92f276 1007 \r
30fdf114
LG
1008 for SecName in SectList :\r
1009 SectFiles.append(SecName)\r
1010 SectAlignments.append(Align)\r
1011 Index = Index + 1\r
1012 return SectFiles, SectAlignments\r
1013\r
1014 ## __GenComplexFileFfs__() method\r
1015 #\r
1016 # Generate FFS\r
1017 #\r
1018 # @param self The object pointer\r
1019 # @param Rule The rule object used to generate section\r
1020 # @param InputFileList The output file list from GenSection\r
1021 # @retval string Generated FFS file name\r
1022 #\r
37de70b7 1023 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):\r
30fdf114
LG
1024\r
1025 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
1026 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
1027 if len(PcdValue) == 0:\r
1028 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
1029 % (Rule.NameGuid))\r
1030 if PcdValue.startswith('{'):\r
1031 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
1032 RegistryGuidStr = PcdValue\r
1033 if len(RegistryGuidStr) == 0:\r
1034 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
1035 % (Rule.NameGuid))\r
1036 self.ModuleGuid = RegistryGuidStr\r
1037\r
1038 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
1039 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,\r
37de70b7
YZ
1040 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
1041 self.ModuleGuid, Fixed=Rule.Fixed,\r
1042 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
1043 SectionAlign=Alignments,\r
1044 MakefilePath=MakefilePath\r
1045 )\r
30fdf114
LG
1046 return FfsOutput\r
1047\r
1048 ## __GetGenFfsCmdParameter__() method\r
1049 #\r
1050 # Create parameter string for GenFfs\r
1051 #\r
1052 # @param self The object pointer\r
1053 # @param Rule The rule object used to generate section\r
1054 # @retval tuple (FileType, Fixed, CheckSum, Alignment)\r
1055 #\r
1056 def __GetGenFfsCmdParameter__(self, Rule):\r
1057 result = tuple()\r
1058 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])\r
1059 if Rule.Fixed != False:\r
1060 result += ('-x',)\r
1061 if Rule.CheckSum != False:\r
1062 result += ('-s',)\r
1063\r
1064 if Rule.Alignment != None and Rule.Alignment != '':\r
1065 result += ('-a', Rule.Alignment)\r
1066\r
1067 return result\r
da92f276
LG
1068 \r
1069 ## __GetBuildOutputMapFileVfrUniInfo() method\r
1070 #\r
1071 # Find the offset of UNI/INF object offset in the EFI image file.\r
1072 #\r
1073 # @param self The object pointer\r
1074 # @param VfrUniBaseName A name list contain the UNI/INF object name.\r
1075 # @retval RetValue A list contain offset of UNI/INF object.\r
1076 # \r
1077 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):\r
da92f276 1078 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")\r
22a99b87
YL
1079 EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")\r
1080 return GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
da92f276
LG
1081 \r
1082 ## __GenUniVfrOffsetFile() method\r
1083 #\r
1084 # Generate the offset file for the module which contain VFR or UNI file.\r
1085 #\r
1086 # @param self The object pointer\r
1087 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.\r
1088 # @param UniVfrOffsetFileName The output offset file name.\r
1089 #\r
1090 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):\r
37de70b7 1091\r
da92f276
LG
1092 # Use a instance of StringIO to cache data\r
1093 fStringIO = StringIO.StringIO('') \r
1094 \r
1095 for Item in VfrUniOffsetList:\r
1096 if (Item[0].find("Strings") != -1):\r
1097 #\r
1098 # UNI offset in image.\r
1099 # GUID + Offset\r
1100 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
1101 #\r
1102 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
1103 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
1104 fStringIO.write(''.join(UniGuid)) \r
1105 UniValue = pack ('Q', int (Item[1], 16))\r
1106 fStringIO.write (UniValue)\r
1107 else:\r
1108 #\r
1109 # VFR binary offset in image.\r
1110 # GUID + Offset\r
1111 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
1112 #\r
1113 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
1114 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
1115 fStringIO.write(''.join(VfrGuid)) \r
1116 type (Item[1]) \r
1117 VfrValue = pack ('Q', int (Item[1], 16))\r
1118 fStringIO.write (VfrValue)\r
1119 \r
1120 #\r
1121 # write data into file.\r
1122 #\r
37de70b7
YZ
1123 try :\r
1124 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())\r
da92f276
LG
1125 except:\r
1126 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
1127 \r
1128 fStringIO.close ()\r
37de70b7 1129\r
da92f276 1130 \r