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