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