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