]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/FfsInfStatement.py
Sync BaseTools Trunk (version r2518) to EDKII main trunk.
[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
da92f276 4# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
30fdf114 5#\r
40d841f6 6# This program and the accompanying materials\r
30fdf114
LG
7# are licensed and made available under the terms and conditions of the BSD License\r
8# which accompanies this distribution. The full text of the license may be found at\r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14\r
15##\r
16# Import Modules\r
17#\r
18import Rule\r
19import os\r
20import shutil\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
31from Common.String import *\r
32from Common.Misc import PathClass\r
33from Common.Misc import GuidStructureByteArrayToGuidString\r
34from Common import EdkLogger\r
35from Common.BuildToolError import *\r
52302d4d
LG
36from GuidSection import GuidSection\r
37from FvImageSection import FvImageSection\r
38from Common.Misc import PeImageClass\r
b36d134f 39from AutoGen.GenDepex import DependencyExpression\r
30fdf114
LG
40\r
41## generate FFS from INF\r
42#\r
43#\r
44class FfsInfStatement(FfsInfStatementClassObject):\r
45 ## The constructor\r
46 #\r
47 # @param self The object pointer\r
48 #\r
49 def __init__(self):\r
50 FfsInfStatementClassObject.__init__(self)\r
51 self.TargetOverrideList = []\r
52 self.ShadowFromInfFile = None\r
53 self.KeepRelocFromRule = None\r
54 self.InDsc = True\r
55 self.OptRomDefs = {}\r
da92f276 56 self.PiSpecVersion = '0x00000000'\r
4234283c 57 self.InfModule = None\r
b36d134f 58 self.FinalTargetSuffixMap = {}\r
79b74a03
LG
59 self.CurrentLineNum = None\r
60 self.CurrentLineContent = None\r
61 self.FileName = None\r
62 self.InfFileName = None\r
4234283c 63\r
b36d134f 64 ## GetFinalTargetSuffixMap() method\r
4234283c
LG
65 #\r
66 # Get final build target list\r
b36d134f 67 def GetFinalTargetSuffixMap(self):\r
4234283c
LG
68 if not self.InfModule or not self.CurrentArch:\r
69 return []\r
b36d134f
LG
70 if not self.FinalTargetSuffixMap:\r
71 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)\r
72 for File in FinalBuildTargetList:\r
73 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)\r
74\r
75 # Check if current INF module has DEPEX\r
76 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \\r
77 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:\r
78 ModuleType = self.InfModule.ModuleType\r
79 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
80\r
81 if ModuleType != DataType.SUP_MODULE_USER_DEFINED:\r
82 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():\r
83 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:\r
84 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]\r
85\r
86 StrModule = str(self.InfModule)\r
87 PlatformModule = None\r
88 if StrModule in PlatformDataBase.Modules:\r
89 PlatformModule = PlatformDataBase.Modules[StrModule]\r
90 for LibraryClass in PlatformModule.LibraryClasses:\r
91 if LibraryClass.startswith("NULL"):\r
92 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
93\r
94 DependencyList = [self.InfModule]\r
95 LibraryInstance = {}\r
96 DepexList = []\r
97 while len(DependencyList) > 0:\r
98 Module = DependencyList.pop(0)\r
99 if not Module:\r
100 continue\r
101 for Dep in Module.Depex[self.CurrentArch, ModuleType]:\r
102 if DepexList != []:\r
103 DepexList.append('AND')\r
104 DepexList.append('(')\r
105 DepexList.extend(Dep)\r
106 if DepexList[-1] == 'END': # no need of a END at this time\r
107 DepexList.pop()\r
108 DepexList.append(')')\r
109 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
110 break\r
111 for LibName in Module.LibraryClasses:\r
112 if LibName in LibraryInstance:\r
113 continue\r
114 if PlatformModule and LibName in PlatformModule.LibraryClasses:\r
115 LibraryPath = PlatformModule.LibraryClasses[LibName]\r
116 else:\r
117 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]\r
118 if not LibraryPath:\r
119 LibraryPath = Module.LibraryClasses[LibName]\r
120 if not LibraryPath:\r
121 continue\r
122 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
123 LibraryInstance[LibName] = LibraryModule\r
124 DependencyList.append(LibraryModule)\r
125 if DepexList:\r
126 Dpx = DependencyExpression(DepexList, ModuleType, True)\r
127 if len(Dpx.PostfixNotation) != 0:\r
128 # It means this module has DEPEX\r
129 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']\r
130 return self.FinalTargetSuffixMap\r
4234283c 131\r
30fdf114
LG
132 ## __InfParse() method\r
133 #\r
134 # Parse inf file to get module information\r
135 #\r
136 # @param self The object pointer\r
137 # @param Dict dictionary contains macro and value pair\r
138 #\r
139 def __InfParse__(self, Dict = {}):\r
140\r
141 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
142\r
143 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
144 if self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
145 self.InfFileName = self.InfFileName[1:]\r
146\r
147 if self.InfFileName.find('$') == -1:\r
148 InfPath = NormPath(self.InfFileName)\r
149 if not os.path.exists(InfPath):\r
150 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)\r
151 if not os.path.exists(InfPath):\r
152 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))\r
153\r
154 self.CurrentArch = self.GetCurrentArch()\r
155 #\r
156 # Get the InfClass object\r
157 #\r
158\r
159 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 160 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
161 if ErrorCode != 0:\r
162 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
163 \r
164 if self.CurrentArch != None:\r
165\r
0d2711a6 166 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
167 #\r
168 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
169 #\r
170 self.BaseName = Inf.BaseName\r
171 self.ModuleGuid = Inf.Guid\r
172 self.ModuleType = Inf.ModuleType\r
52302d4d 173 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 174 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
175 if Inf.AutoGenVersion < 0x00010005:\r
176 self.ModuleType = Inf.ComponentType\r
177 self.VersionString = Inf.Version\r
178 self.BinFileList = Inf.Binaries\r
179 self.SourceFileList = Inf.Sources\r
180 if self.KeepReloc == None and Inf.Shadow:\r
181 self.ShadowFromInfFile = Inf.Shadow\r
182\r
183 else:\r
0d2711a6 184 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
185 self.BaseName = Inf.BaseName\r
186 self.ModuleGuid = Inf.Guid\r
187 self.ModuleType = Inf.ModuleType\r
52302d4d 188 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 189 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
190 self.VersionString = Inf.Version\r
191 self.BinFileList = Inf.Binaries\r
192 self.SourceFileList = Inf.Sources\r
193 if self.BinFileList == []:\r
194 EdkLogger.error("GenFds", GENFDS_ERROR,\r
195 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
196 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
197\r
198 if len(self.SourceFileList) != 0 and not self.InDsc:\r
199 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
200\r
da92f276 201 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
202 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
203\r
30fdf114
LG
204 if Inf._Defs != None and len(Inf._Defs) > 0:\r
205 self.OptRomDefs.update(Inf._Defs)\r
4234283c
LG
206 \r
207 self.InfModule = Inf\r
30fdf114
LG
208 \r
209 GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName)\r
210 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid)\r
211 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType)\r
212 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString)\r
213 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" %self.InfFileName)\r
214\r
215 #\r
216 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
217 #\r
218\r
219 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
220 self.ModuleGuid + self.BaseName)\r
221 if not os.path.exists(self.OutputPath) :\r
222 os.makedirs(self.OutputPath)\r
223\r
224 self.EfiOutputPath = self.__GetEFIOutPutPath__()\r
225 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
226\r
227 ## GenFfs() method\r
228 #\r
229 # Generate FFS\r
230 #\r
52302d4d
LG
231 # @param self The object pointer\r
232 # @param Dict dictionary contains macro and value pair\r
233 # @param FvChildAddr Array of the inside FvImage base address\r
234 # @param FvParentAddr Parent Fv base address\r
235 # @retval string Generated FFS file name\r
30fdf114 236 #\r
52302d4d 237 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None):\r
30fdf114
LG
238 #\r
239 # Parse Inf file get Module related information\r
240 #\r
241\r
242 self.__InfParse__(Dict)\r
6780eef1
LG
243 \r
244 #\r
245 # Allow binary type module not specify override rule in FDF file.\r
246 # \r
247 if len(self.BinFileList) >0 and not self.InDsc:\r
248 if self.Rule == None or self.Rule == "":\r
249 self.Rule = "BINARY"\r
250 \r
30fdf114
LG
251 #\r
252 # Get the rule of how to generate Ffs file\r
253 #\r
254 Rule = self.__GetRule__()\r
255 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
b303ea72
LG
256 #\r
257 # Convert Fv File Type for PI1.1 SMM driver.\r
258 #\r
da92f276 259 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
260 if Rule.FvFileType == 'DRIVER':\r
261 Rule.FvFileType = 'SMM'\r
262 #\r
263 # Framework SMM Driver has no SMM FV file type\r
264 #\r
da92f276 265 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
266 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':\r
267 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
268 #\r
269 # For the rule only has simpleFile\r
270 #\r
271 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :\r
272 SectionOutputList = self.__GenSimpleFileSection__(Rule)\r
273 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList)\r
274 return FfsOutput\r
275 #\r
276 # For Rule has ComplexFile\r
277 #\r
278 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):\r
52302d4d 279 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr)\r
30fdf114
LG
280 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments)\r
281\r
282 return FfsOutput\r
283\r
284 ## __ExtendMacro__() method\r
285 #\r
286 # Replace macro with its value\r
287 #\r
288 # @param self The object pointer\r
289 # @param String The string to be replaced\r
290 # @retval string Macro replaced string\r
291 #\r
292 def __ExtendMacro__ (self, String):\r
293 MacroDict = {\r
294 '$(INF_OUTPUT)' : self.EfiOutputPath,\r
295 '$(MODULE_NAME)' : self.BaseName,\r
296 '$(BUILD_NUMBER)': self.BuildNum,\r
297 '$(INF_VERSION)' : self.VersionString,\r
298 '$(NAMED_GUID)' : self.ModuleGuid\r
299 }\r
300 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
301 return String\r
302\r
303 ## __GetRule__() method\r
304 #\r
305 # Get correct rule for generating FFS for this INF\r
306 #\r
307 # @param self The object pointer\r
308 # @retval Rule Rule object\r
309 #\r
310 def __GetRule__ (self) :\r
311 CurrentArchList = []\r
312 if self.CurrentArch == None:\r
313 CurrentArchList = ['common']\r
314 else:\r
315 CurrentArchList.append(self.CurrentArch)\r
316\r
317 for CurrentArch in CurrentArchList:\r
318 RuleName = 'RULE' + \\r
319 '.' + \\r
320 CurrentArch.upper() + \\r
321 '.' + \\r
322 self.ModuleType.upper()\r
323 if self.Rule != None:\r
324 RuleName = RuleName + \\r
325 '.' + \\r
326 self.Rule.upper()\r
327\r
328 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
329 if Rule != None:\r
330 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
331 return Rule\r
332\r
333 RuleName = 'RULE' + \\r
334 '.' + \\r
335 'COMMON' + \\r
336 '.' + \\r
337 self.ModuleType.upper()\r
338\r
339 if self.Rule != None:\r
340 RuleName = RuleName + \\r
341 '.' + \\r
342 self.Rule.upper()\r
343\r
344 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))\r
345\r
346 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
347 if Rule != None:\r
348 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
349 return Rule\r
350\r
351 if Rule == None :\r
352 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \\r
353 % (RuleName, self.InfFileName))\r
354\r
355 ## __GetPlatformArchList__() method\r
356 #\r
357 # Get Arch list this INF built under\r
358 #\r
359 # @param self The object pointer\r
360 # @retval list Arch list\r
361 #\r
362 def __GetPlatformArchList__(self):\r
363\r
364 InfFileKey = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))\r
365 DscArchList = []\r
0d2711a6 366 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
367 if PlatformDataBase != None:\r
368 if InfFileKey in PlatformDataBase.Modules:\r
369 DscArchList.append ('IA32')\r
370\r
0d2711a6 371 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
372 if PlatformDataBase != None:\r
373 if InfFileKey in PlatformDataBase.Modules:\r
374 DscArchList.append ('X64')\r
375\r
0d2711a6 376 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
377 if PlatformDataBase != None:\r
378 if InfFileKey in (PlatformDataBase.Modules):\r
379 DscArchList.append ('IPF')\r
380\r
0d2711a6 381 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
382 if PlatformDataBase != None:\r
383 if InfFileKey in (PlatformDataBase.Modules):\r
384 DscArchList.append ('ARM')\r
385\r
0d2711a6 386 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
387 if PlatformDataBase != None:\r
388 if InfFileKey in (PlatformDataBase.Modules):\r
389 DscArchList.append ('EBC')\r
390\r
391 return DscArchList\r
392\r
393 ## GetCurrentArch() method\r
394 #\r
395 # Get Arch list of the module from this INF is to be placed into flash\r
396 #\r
397 # @param self The object pointer\r
398 # @retval list Arch list\r
399 #\r
400 def GetCurrentArch(self) :\r
401\r
402 TargetArchList = GenFdsGlobalVariable.ArchList\r
403\r
404 PlatformArchList = self.__GetPlatformArchList__()\r
405\r
406 CurArchList = TargetArchList\r
407 if PlatformArchList != []:\r
408 CurArchList = list(set (TargetArchList) & set (PlatformArchList))\r
409 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))\r
410\r
411 ArchList = []\r
412 if self.KeyStringList != []:\r
413 for Key in self.KeyStringList:\r
414 Key = GenFdsGlobalVariable.MacroExtend(Key)\r
415 Target, Tag, Arch = Key.split('_')\r
416 if Arch in CurArchList:\r
417 ArchList.append(Arch)\r
418 if Target not in self.TargetOverrideList:\r
419 self.TargetOverrideList.append(Target)\r
420 else:\r
421 ArchList = CurArchList\r
422\r
423 UseArchList = TargetArchList\r
424 if self.UseArch != None:\r
425 UseArchList = []\r
426 UseArchList.append(self.UseArch)\r
427 ArchList = list(set (UseArchList) & set (ArchList))\r
428\r
429 self.InfFileName = NormPath(self.InfFileName)\r
430 if len(PlatformArchList) == 0:\r
431 self.InDsc = False\r
432 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 433 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
434 if ErrorCode != 0:\r
435 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
436 if len(ArchList) == 1:\r
437 Arch = ArchList[0]\r
438 return Arch\r
439 elif len(ArchList) > 1:\r
440 if len(PlatformArchList) == 0:\r
441 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
442 else:\r
443 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
444 else:\r
445 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
446 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))\r
447\r
448 ## __GetEFIOutPutPath__() method\r
449 #\r
450 # Get the output path for generated files\r
451 #\r
452 # @param self The object pointer\r
453 # @retval string Path that output files from this INF go to\r
454 #\r
455 def __GetEFIOutPutPath__(self):\r
456 Arch = ''\r
457 OutputPath = ''\r
458 (ModulePath, FileName) = os.path.split(self.InfFileName)\r
79b74a03 459 Index = FileName.rfind('.')\r
30fdf114
LG
460 FileName = FileName[0:Index]\r
461 Arch = "NoneArch"\r
462 if self.CurrentArch != None:\r
463 Arch = self.CurrentArch\r
464\r
465 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
466 Arch ,\r
467 ModulePath,\r
468 FileName,\r
469 'OUTPUT'\r
470 )\r
471 OutputPath = os.path.realpath(OutputPath)\r
472 return OutputPath\r
473\r
474 ## __GenSimpleFileSection__() method\r
475 #\r
476 # Generate section by specified file name or a list of files with file extension\r
477 #\r
478 # @param self The object pointer\r
479 # @param Rule The rule object used to generate section\r
480 # @retval string File name of the generated section file\r
481 #\r
482 def __GenSimpleFileSection__(self, Rule):\r
483 #\r
484 # Prepare the parameter of GenSection\r
485 #\r
486 FileList = []\r
487 OutputFileList = []\r
52302d4d 488 GenSecInputFile = None\r
30fdf114
LG
489 if Rule.FileName != None:\r
490 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)\r
da92f276
LG
491 if os.path.isabs(GenSecInputFile):\r
492 GenSecInputFile = os.path.normpath(GenSecInputFile)\r
493 else:\r
52302d4d 494 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))\r
30fdf114
LG
495 else:\r
496 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)\r
497\r
498 Index = 1\r
b303ea72
LG
499 SectionType = Rule.SectionType\r
500 #\r
501 # Convert Fv Section Type for PI1.1 SMM driver.\r
502 #\r
da92f276 503 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
504 if SectionType == 'DXE_DEPEX':\r
505 SectionType = 'SMM_DEPEX'\r
506 #\r
507 # Framework SMM Driver has no SMM_DEPEX section type\r
508 #\r
da92f276 509 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
510 if SectionType == 'SMM_DEPEX':\r
511 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
30fdf114
LG
512 NoStrip = True\r
513 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
514 if self.KeepReloc != None:\r
515 NoStrip = self.KeepReloc\r
516 elif Rule.KeepReloc != None:\r
517 NoStrip = Rule.KeepReloc\r
518 elif self.ShadowFromInfFile != None:\r
519 NoStrip = self.ShadowFromInfFile\r
520\r
521 if FileList != [] :\r
522 for File in FileList:\r
523\r
524 SecNum = '%d' %Index\r
525 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
526 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
527 Index = Index + 1\r
528 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
529 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)\r
530\r
531 #Get PE Section alignment when align is set to AUTO\r
532 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
533 ImageObj = PeImageClass (File)\r
534 if ImageObj.SectionAlignment < 0x400:\r
535 self.Alignment = str (ImageObj.SectionAlignment)\r
536 else:\r
537 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
30fdf114
LG
538\r
539 if not NoStrip:\r
540 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
541 if not os.path.exists(FileBeforeStrip) or \\r
542 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
543 shutil.copyfile(File, FileBeforeStrip)\r
544 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
545 GenFdsGlobalVariable.GenerateFirmwareImage(\r
546 StrippedFile,\r
52302d4d 547 [File],\r
30fdf114
LG
548 Strip=True\r
549 )\r
550 File = StrippedFile\r
551\r
552 if SectionType == 'TE':\r
553 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
554 GenFdsGlobalVariable.GenerateFirmwareImage(\r
555 TeFile,\r
52302d4d 556 [File],\r
30fdf114
LG
557 Type='te'\r
558 )\r
559 File = TeFile\r
560\r
561 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType])\r
562 OutputFileList.append(OutputFile)\r
563 else:\r
564 SecNum = '%d' %Index\r
565 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
566 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
567 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
568 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)\r
569\r
570 #Get PE Section alignment when align is set to AUTO\r
571 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
572 ImageObj = PeImageClass (GenSecInputFile)\r
573 if ImageObj.SectionAlignment < 0x400:\r
574 self.Alignment = str (ImageObj.SectionAlignment)\r
575 else:\r
576 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
30fdf114
LG
577\r
578 if not NoStrip:\r
579 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
580 if not os.path.exists(FileBeforeStrip) or \\r
581 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):\r
582 shutil.copyfile(GenSecInputFile, FileBeforeStrip)\r
583 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
584 GenFdsGlobalVariable.GenerateFirmwareImage(\r
585 StrippedFile,\r
52302d4d 586 [GenSecInputFile],\r
30fdf114
LG
587 Strip=True\r
588 )\r
589 GenSecInputFile = StrippedFile\r
590\r
591 if SectionType == 'TE':\r
592 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
593 GenFdsGlobalVariable.GenerateFirmwareImage(\r
594 TeFile,\r
52302d4d 595 [GenSecInputFile],\r
30fdf114
LG
596 Type='te'\r
597 )\r
598 GenSecInputFile = TeFile\r
599\r
600 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType])\r
601 OutputFileList.append(OutputFile)\r
602\r
603 return OutputFileList\r
604\r
605 ## __GenSimpleFileFfs__() method\r
606 #\r
607 # Generate FFS\r
608 #\r
609 # @param self The object pointer\r
610 # @param Rule The rule object used to generate section\r
611 # @param InputFileList The output file list from GenSection\r
612 # @retval string Generated FFS file name\r
613 #\r
614 def __GenSimpleFileFfs__(self, Rule, InputFileList):\r
615 FfsOutput = self.OutputPath + \\r
616 os.sep + \\r
617 self.__ExtendMacro__(Rule.NameGuid) + \\r
618 '.ffs'\r
619\r
620 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))\r
621 InputSection = []\r
622 SectionAlignments = []\r
623 for InputFile in InputFileList:\r
624 InputSection.append(InputFile)\r
52302d4d 625 SectionAlignments.append(Rule.SectAlignment)\r
30fdf114
LG
626\r
627 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
628 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
629 if len(PcdValue) == 0:\r
630 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
631 % (Rule.NameGuid))\r
632 if PcdValue.startswith('{'):\r
633 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
634 RegistryGuidStr = PcdValue\r
635 if len(RegistryGuidStr) == 0:\r
636 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
637 % (Rule.NameGuid))\r
638 self.ModuleGuid = RegistryGuidStr\r
639\r
640 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,\r
641 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
642 self.ModuleGuid, Fixed=Rule.Fixed,\r
643 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
644 SectionAlign=SectionAlignments\r
645 )\r
646 return FfsOutput\r
647\r
648 ## __GenComplexFileSection__() method\r
649 #\r
650 # Generate section by sections in Rule\r
651 #\r
52302d4d
LG
652 # @param self The object pointer\r
653 # @param Rule The rule object used to generate section\r
654 # @param FvChildAddr Array of the inside FvImage base address\r
655 # @param FvParentAddr Parent Fv base address\r
656 # @retval string File name of the generated section file\r
30fdf114 657 #\r
52302d4d 658 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr):\r
30fdf114
LG
659 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
660 if Rule.KeepReloc != None:\r
661 self.KeepRelocFromRule = Rule.KeepReloc\r
662 SectFiles = []\r
663 SectAlignments = []\r
664 Index = 1\r
da92f276 665 HasGneratedFlag = False\r
30fdf114
LG
666 for Sect in Rule.SectionList:\r
667 SecIndex = '%d' %Index\r
668 SectList = []\r
b303ea72
LG
669 #\r
670 # Convert Fv Section Type for PI1.1 SMM driver.\r
671 #\r
da92f276 672 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
673 if Sect.SectionType == 'DXE_DEPEX':\r
674 Sect.SectionType = 'SMM_DEPEX'\r
675 #\r
676 # Framework SMM Driver has no SMM_DEPEX section type\r
677 #\r
da92f276 678 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
679 if Sect.SectionType == 'SMM_DEPEX':\r
680 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
52302d4d
LG
681 #\r
682 # process the inside FvImage from FvSection or GuidSection\r
683 #\r
684 if FvChildAddr != []:\r
685 if isinstance(Sect, FvImageSection):\r
686 Sect.FvAddr = FvChildAddr.pop(0)\r
687 elif isinstance(Sect, GuidSection):\r
688 Sect.FvAddr = FvChildAddr\r
689 if FvParentAddr != None and isinstance(Sect, GuidSection):\r
690 Sect.FvParentAddr = FvParentAddr\r
691 \r
30fdf114
LG
692 if Rule.KeyStringList != []:\r
693 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self)\r
694 else :\r
695 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self)\r
da92f276
LG
696 \r
697 if not HasGneratedFlag:\r
698 UniVfrOffsetFileSection = "" \r
699 ModuleFileName = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)\r
700 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]\r
701 #\r
702 # Search the source list in InfData to find if there are .vfr file exist.\r
703 #\r
704 VfrUniBaseName = {}\r
705 VfrUniOffsetList = []\r
706 for SourceFile in InfData.Sources:\r
707 if SourceFile.Type.upper() == ".VFR" :\r
708 #\r
709 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
710 #\r
711 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
712 if SourceFile.Type.upper() == ".UNI" :\r
713 #\r
714 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
715 #\r
716 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")\r
717 \r
718 \r
719 if len(VfrUniBaseName) > 0:\r
720 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)\r
721 #\r
722 # Generate the Raw data of raw section\r
723 #\r
724 os.path.join( self.OutputPath, self.BaseName + '.offset')\r
725 UniVfrOffsetFileName = os.path.join( self.OutputPath, self.BaseName + '.offset')\r
726 UniVfrOffsetFileSection = os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
727 \r
728 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
729 \r
730 UniVfrOffsetFileNameList = []\r
731 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
732 """Call GenSection"""\r
733 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
734 UniVfrOffsetFileNameList,\r
735 "EFI_SECTION_RAW"\r
736 )\r
737 os.remove(UniVfrOffsetFileName) \r
738 SectList.append(UniVfrOffsetFileSection)\r
739 HasGneratedFlag = True\r
740 \r
30fdf114
LG
741 for SecName in SectList :\r
742 SectFiles.append(SecName)\r
743 SectAlignments.append(Align)\r
744 Index = Index + 1\r
745 return SectFiles, SectAlignments\r
746\r
747 ## __GenComplexFileFfs__() method\r
748 #\r
749 # Generate FFS\r
750 #\r
751 # @param self The object pointer\r
752 # @param Rule The rule object used to generate section\r
753 # @param InputFileList The output file list from GenSection\r
754 # @retval string Generated FFS file name\r
755 #\r
756 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments):\r
757\r
758 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
759 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
760 if len(PcdValue) == 0:\r
761 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
762 % (Rule.NameGuid))\r
763 if PcdValue.startswith('{'):\r
764 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
765 RegistryGuidStr = PcdValue\r
766 if len(RegistryGuidStr) == 0:\r
767 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
768 % (Rule.NameGuid))\r
769 self.ModuleGuid = RegistryGuidStr\r
770\r
771 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
772 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,\r
773 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
774 self.ModuleGuid, Fixed=Rule.Fixed,\r
775 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
776 SectionAlign=Alignments\r
777 )\r
778 return FfsOutput\r
779\r
780 ## __GetGenFfsCmdParameter__() method\r
781 #\r
782 # Create parameter string for GenFfs\r
783 #\r
784 # @param self The object pointer\r
785 # @param Rule The rule object used to generate section\r
786 # @retval tuple (FileType, Fixed, CheckSum, Alignment)\r
787 #\r
788 def __GetGenFfsCmdParameter__(self, Rule):\r
789 result = tuple()\r
790 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])\r
791 if Rule.Fixed != False:\r
792 result += ('-x',)\r
793 if Rule.CheckSum != False:\r
794 result += ('-s',)\r
795\r
796 if Rule.Alignment != None and Rule.Alignment != '':\r
797 result += ('-a', Rule.Alignment)\r
798\r
799 return result\r
da92f276
LG
800 \r
801 ## __GetBuildOutputMapFileVfrUniInfo() method\r
802 #\r
803 # Find the offset of UNI/INF object offset in the EFI image file.\r
804 #\r
805 # @param self The object pointer\r
806 # @param VfrUniBaseName A name list contain the UNI/INF object name.\r
807 # @retval RetValue A list contain offset of UNI/INF object.\r
808 # \r
809 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):\r
810 \r
811 RetValue = []\r
812 \r
813 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")\r
814 try:\r
815 fInputfile = open(MapFileName, "r", 0)\r
816 try:\r
817 FileLinesList = fInputfile.readlines()\r
818 except:\r
819 EdkLogger.error("GenFds", FILE_READ_FAILURE, "File read failed for %s" %MapFileName,None)\r
820 finally:\r
821 fInputfile.close()\r
822 except:\r
823 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %MapFileName,None)\r
824 \r
825 IsHex = False\r
826 for eachLine in FileLinesList:\r
827 for eachName in VfrUniBaseName.values():\r
828 if eachLine.find(eachName) != -1:\r
829 eachLine = eachLine.strip()\r
830 Element = eachLine.split()\r
831 #\r
832 # MSFT/ICC/EBC map file\r
833 #\r
834 if (len(Element) == 4):\r
835 try:\r
836 int (Element[2], 16)\r
837 IsHex = True\r
838 except:\r
839 IsHex = False\r
840 \r
841 if IsHex:\r
842 RetValue.append((eachName, Element[2]))\r
843 IsHex = False\r
844 #\r
845 # GCC map file\r
846 #\r
847 elif (len(Element) == 2) and Element[0].startswith("0x"):\r
848 RetValue.append((eachName, Element[0]))\r
849 \r
850 return RetValue\r
851 \r
852 ## __GenUniVfrOffsetFile() method\r
853 #\r
854 # Generate the offset file for the module which contain VFR or UNI file.\r
855 #\r
856 # @param self The object pointer\r
857 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.\r
858 # @param UniVfrOffsetFileName The output offset file name.\r
859 #\r
860 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):\r
861 \r
862 try:\r
863 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)\r
864 except:\r
865 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %UniVfrOffsetFileName,None)\r
866 \r
867 # Use a instance of StringIO to cache data\r
868 fStringIO = StringIO.StringIO('') \r
869 \r
870 for Item in VfrUniOffsetList:\r
871 if (Item[0].find("Strings") != -1):\r
872 #\r
873 # UNI offset in image.\r
874 # GUID + Offset\r
875 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
876 #\r
877 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
878 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
879 fStringIO.write(''.join(UniGuid)) \r
880 UniValue = pack ('Q', int (Item[1], 16))\r
881 fStringIO.write (UniValue)\r
882 else:\r
883 #\r
884 # VFR binary offset in image.\r
885 # GUID + Offset\r
886 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
887 #\r
888 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
889 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
890 fStringIO.write(''.join(VfrGuid)) \r
891 type (Item[1]) \r
892 VfrValue = pack ('Q', int (Item[1], 16))\r
893 fStringIO.write (VfrValue)\r
894 \r
895 #\r
896 # write data into file.\r
897 #\r
898 try : \r
899 fInputfile.write (fStringIO.getvalue())\r
900 except:\r
901 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
902 \r
903 fStringIO.close ()\r
904 fInputfile.close ()\r
905 \r
906 \r
907 \r
908 \r
909 \r
910 \r
911 \r
912 \r