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