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