2 # Generate AutoGen.h, AutoGen.c and *.depex files
4 # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
5 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
6 # Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>
8 # This program and the accompanying materials
9 # are licensed and made available under the terms and conditions of the BSD License
10 # which accompanies this distribution. The full text of the license may be found at
11 # http://opensource.org/licenses/bsd-license.php
13 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 from __future__
import print_function
20 from __future__
import absolute_import
21 import Common
.LongFilePathOs
as os
23 import os
.path
as path
29 from . import GenDepex
30 from io
import BytesIO
32 from .StrGather
import *
33 from .BuildEngine
import BuildRule
35 from Common
.LongFilePathSupport
import CopyLongFilePath
36 from Common
.BuildToolError
import *
37 from Common
.DataType
import *
38 from Common
.Misc
import *
39 from Common
.StringUtils
import *
40 import Common
.GlobalData
as GlobalData
41 from GenFds
.FdfParser
import *
42 from CommonDataClass
.CommonClass
import SkuInfoClass
43 from GenPatchPcdTable
.GenPatchPcdTable
import parsePcdInfoFromMapFile
44 import Common
.VpdInfoFile
as VpdInfoFile
45 from .GenPcdDb
import CreatePcdDatabaseCode
46 from Workspace
.MetaFileCommentParser
import UsageList
47 from Workspace
.WorkspaceCommon
import GetModuleLibInstances
48 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
49 from . import InfSectionParser
52 from .GenVar
import VariableMgr
, var_info
53 from collections
import OrderedDict
54 from collections
import defaultdict
55 from Workspace
.WorkspaceCommon
import OrderedListDict
56 from Common
.ToolDefClassObject
import gDefaultToolsDefFile
58 from Common
.caching
import cached_property
, cached_class_function
60 ## Regular expression for splitting Dependency Expression string into tokens
61 gDepexTokenPattern
= re
.compile("(\(|\)|\w+| \S+\.inf)")
63 ## Regular expression for match: PCD(xxxx.yyy)
64 gPCDAsGuidPattern
= re
.compile(r
"^PCD\(.+\..+\)$")
67 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
68 # is the former use /I , the Latter used -I to specify include directories
70 gBuildOptIncludePatternMsft
= re
.compile(r
"(?:.*?)/I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
71 gBuildOptIncludePatternOther
= re
.compile(r
"(?:.*?)-I[ \t]*([^ ]*)", re
.MULTILINE | re
.DOTALL
)
74 # Match name = variable
76 gEfiVarStoreNamePattern
= re
.compile("\s*name\s*=\s*(\w+)")
78 # The format of guid in efivarstore statement likes following and must be correct:
79 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
81 gEfiVarStoreGuidPattern
= re
.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
83 ## Mapping Makefile type
84 gMakeTypeMap
= {TAB_COMPILER_MSFT
:"nmake", "GCC":"gmake"}
87 ## Build rule configuration file
88 gDefaultBuildRuleFile
= 'build_rule.txt'
90 ## Build rule default version
91 AutoGenReqBuildRuleVerNum
= "0.1"
93 ## default file name for AutoGen
94 gAutoGenCodeFileName
= "AutoGen.c"
95 gAutoGenHeaderFileName
= "AutoGen.h"
96 gAutoGenStringFileName
= "%(module_name)sStrDefs.h"
97 gAutoGenStringFormFileName
= "%(module_name)sStrDefs.hpk"
98 gAutoGenDepexFileName
= "%(module_name)s.depex"
99 gAutoGenImageDefFileName
= "%(module_name)sImgDefs.h"
100 gAutoGenIdfFileName
= "%(module_name)sIdf.hpk"
101 gInfSpecVersion
= "0x00010017"
104 # Template string to generic AsBuilt INF
106 gAsBuiltInfHeaderString
= TemplateString("""${header_comments}
109 # FILE auto-generated
112 INF_VERSION = ${module_inf_version}
113 BASE_NAME = ${module_name}
114 FILE_GUID = ${module_guid}
115 MODULE_TYPE = ${module_module_type}${BEGIN}
116 VERSION_STRING = ${module_version_string}${END}${BEGIN}
117 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
118 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
119 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
120 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
121 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
122 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
123 DESTRUCTOR = ${module_destructor}${END}${BEGIN}
124 SHADOW = ${module_shadow}${END}${BEGIN}
125 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
126 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
127 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
128 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
129 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
130 SPEC = ${module_spec}${END}${BEGIN}
131 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
132 MODULE_UNI_FILE = ${module_uni_file}${END}
134 [Packages.${module_arch}]${BEGIN}
135 ${package_item}${END}
137 [Binaries.${module_arch}]${BEGIN}
140 [PatchPcd.${module_arch}]${BEGIN}
144 [Protocols.${module_arch}]${BEGIN}
148 [Ppis.${module_arch}]${BEGIN}
152 [Guids.${module_arch}]${BEGIN}
156 [PcdEx.${module_arch}]${BEGIN}
160 [LibraryClasses.${module_arch}]
161 ## @LIB_INSTANCES${BEGIN}
162 # ${libraryclasses_item}${END}
166 ${userextension_tianocore_item}
170 [BuildOptions.${module_arch}]
172 ## ${flags_item}${END}
174 ## Split command line option string to list
176 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
177 # in non-windows platform to launch command
179 def _SplitOption(OptionString
):
184 for Index
in range(0, len(OptionString
)):
185 CurrentChar
= OptionString
[Index
]
186 if CurrentChar
in ['"', "'"]:
187 if QuotationMark
== CurrentChar
:
189 elif QuotationMark
== "":
190 QuotationMark
= CurrentChar
195 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
196 if Index
> OptionStart
:
197 OptionList
.append(OptionString
[OptionStart
:Index
- 1])
199 LastChar
= CurrentChar
200 OptionList
.append(OptionString
[OptionStart
:])
204 # Convert string to C format array
206 def _ConvertStringToByteArray(Value
):
207 Value
= Value
.strip()
211 if not Value
.endswith('}'):
213 Value
= Value
.replace(' ', '').replace('{', '').replace('}', '')
214 ValFields
= Value
.split(',')
216 for Index
in range(len(ValFields
)):
217 ValFields
[Index
] = str(int(ValFields
[Index
], 0))
220 Value
= '{' + ','.join(ValFields
) + '}'
224 if Value
.startswith('L"'):
225 if not Value
.endswith('"'):
229 elif not Value
.startswith('"') or not Value
.endswith('"'):
232 Value
= eval(Value
) # translate escape character
234 for Index
in range(0, len(Value
)):
236 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x10000) + ','
238 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x100) + ','
239 Value
= NewValue
+ '0}'
242 ## Base class for AutoGen
244 # This class just implements the cache mechanism of AutoGen objects.
246 class AutoGen(object):
247 # database to maintain the objects in each child class
248 __ObjectCache
= {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
252 # @param Class class object of real AutoGen class
253 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
254 # @param Workspace Workspace directory or WorkspaceAutoGen object
255 # @param MetaFile The path of meta file
256 # @param Target Build target
257 # @param Toolchain Tool chain name
258 # @param Arch Target arch
259 # @param *args The specific class related parameters
260 # @param **kwargs The specific class related dict parameters
262 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
263 # check if the object has been created
264 Key
= (Target
, Toolchain
, Arch
, MetaFile
)
265 if Key
in cls
.__ObjectCache
:
266 # if it exists, just return it directly
267 return cls
.__ObjectCache
[Key
]
268 # it didnt exist. create it, cache it, then return it
269 RetVal
= cls
.__ObjectCache
[Key
] = super(AutoGen
, cls
).__new
__(cls
)
272 def __init__ (self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
273 super(AutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
277 # The file path of platform file will be used to represent hash value of this object
279 # @retval int Hash value of the file path of platform file
282 return hash(self
.MetaFile
)
286 # The file path of platform file will be used to represent this object
288 # @retval string String of platform file path
291 return str(self
.MetaFile
)
294 def __eq__(self
, Other
):
295 return Other
and self
.MetaFile
== Other
297 ## Workspace AutoGen class
299 # This class is used mainly to control the whole platform build for different
300 # architecture. This class will generate top level makefile.
302 class WorkspaceAutoGen(AutoGen
):
303 # call super().__init__ then call the worker function with different parameter count
304 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
305 if not hasattr(self
, "_Init"):
306 super(WorkspaceAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
307 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
310 ## Initialize WorkspaceAutoGen
312 # @param WorkspaceDir Root directory of workspace
313 # @param ActivePlatform Meta-file of active platform
314 # @param Target Build target
315 # @param Toolchain Tool chain name
316 # @param ArchList List of architecture of current build
317 # @param MetaFileDb Database containing meta-files
318 # @param BuildConfig Configuration of build
319 # @param ToolDefinition Tool chain definitions
320 # @param FlashDefinitionFile File of flash definition
321 # @param Fds FD list to be generated
322 # @param Fvs FV list to be generated
323 # @param Caps Capsule list to be generated
324 # @param SkuId SKU id from command line
326 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
327 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
328 Progress
=None, BuildModule
=None):
329 self
.BuildDatabase
= MetaFileDb
330 self
.MetaFile
= ActivePlatform
331 self
.WorkspaceDir
= WorkspaceDir
332 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
333 GlobalData
.gActivePlatform
= self
.Platform
334 self
.BuildTarget
= Target
335 self
.ToolChain
= Toolchain
336 self
.ArchList
= ArchList
338 self
.UniFlag
= UniFlag
340 self
.TargetTxt
= BuildConfig
341 self
.ToolDef
= ToolDefinition
342 self
.FdfFile
= FlashDefinitionFile
343 self
.FdTargetList
= Fds
if Fds
else []
344 self
.FvTargetList
= Fvs
if Fvs
else []
345 self
.CapTargetList
= Caps
if Caps
else []
346 self
.AutoGenObjectList
= []
349 # there's many relative directory operations, so ...
350 os
.chdir(self
.WorkspaceDir
)
355 if not self
.ArchList
:
356 ArchList
= set(self
.Platform
.SupArchList
)
358 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
360 EdkLogger
.error("build", PARAMETER_INVALID
,
361 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
362 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
363 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
364 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
365 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
366 self
.ArchList
= tuple(ArchList
)
368 # Validate build target
369 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
370 EdkLogger
.error("build", PARAMETER_INVALID
,
371 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
372 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
375 # parse FDF file to get PCDs in it, if any
377 self
.FdfFile
= self
.Platform
.FlashDefinition
381 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
382 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
383 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
385 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
387 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
390 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
392 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
395 Progress
.Start("\nProcessing meta-data")
399 # Mark now build in AutoGen Phase
401 GlobalData
.gAutoGenPhase
= True
402 Fdf
= FdfParser(self
.FdfFile
.Path
)
404 GlobalData
.gFdfParser
= Fdf
405 GlobalData
.gAutoGenPhase
= False
406 PcdSet
= Fdf
.Profile
.PcdDict
407 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
408 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
409 for FdRegion
in FdDict
.RegionList
:
410 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
411 if int(FdRegion
.Offset
) % 8 != 0:
412 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
413 ModuleList
= Fdf
.Profile
.InfList
414 self
.FdfProfile
= Fdf
.Profile
415 for fvname
in self
.FvTargetList
:
416 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
417 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
418 "No such an FV in FDF file: %s" % fvname
)
420 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
421 # but the path (self.MetaFile.Path) is the real path
422 for key
in self
.FdfProfile
.InfDict
:
424 MetaFile_cache
= defaultdict(set)
425 for Arch
in self
.ArchList
:
426 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
427 for Pkey
in Current_Platform_cache
.Modules
:
428 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
429 for Inf
in self
.FdfProfile
.InfDict
[key
]:
430 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
431 for Arch
in self
.ArchList
:
432 if ModuleFile
in MetaFile_cache
[Arch
]:
435 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
436 if not ModuleData
.IsBinaryModule
:
437 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
440 for Arch
in self
.ArchList
:
442 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
444 for Pkey
in Platform
.Modules
:
445 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
446 for Inf
in self
.FdfProfile
.InfDict
[key
]:
447 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
448 if ModuleFile
in MetaFileList
:
450 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
451 if not ModuleData
.IsBinaryModule
:
452 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
457 self
.FdfProfile
= None
458 if self
.FdTargetList
:
459 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
460 self
.FdTargetList
= []
461 if self
.FvTargetList
:
462 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
463 self
.FvTargetList
= []
464 if self
.CapTargetList
:
465 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
466 self
.CapTargetList
= []
468 # apply SKU and inject PCDs from Flash Definition file
469 for Arch
in self
.ArchList
:
470 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
471 PlatformPcds
= Platform
.Pcds
472 self
._GuidDict
= Platform
._GuidDict
473 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
474 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
475 SourcePcdDict_Keys
= SourcePcdDict
.keys()
476 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
478 # generate the SourcePcdDict and BinaryPcdDict
479 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
480 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
481 if BuildData
.Arch
!= Arch
:
483 if BuildData
.MetaFile
.Ext
== '.inf':
484 for key
in BuildData
.Pcds
:
485 if BuildData
.Pcds
[key
].Pending
:
486 if key
in Platform
.Pcds
:
487 PcdInPlatform
= Platform
.Pcds
[key
]
488 if PcdInPlatform
.Type
:
489 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
490 BuildData
.Pcds
[key
].Pending
= False
492 if BuildData
.MetaFile
in Platform
.Modules
:
493 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
494 if key
in PlatformModule
.Pcds
:
495 PcdInPlatform
= PlatformModule
.Pcds
[key
]
496 if PcdInPlatform
.Type
:
497 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
498 BuildData
.Pcds
[key
].Pending
= False
500 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
501 if BuildData
.Pcds
[key
].Pending
:
502 MGen
= ModuleAutoGen(self
, BuildData
.MetaFile
, Target
, Toolchain
, Arch
, self
.MetaFile
)
503 if MGen
and MGen
.IsLibrary
:
504 if MGen
in PGen
.LibraryAutoGenList
:
505 ReferenceModules
= MGen
.ReferenceModules
506 for ReferenceModule
in ReferenceModules
:
507 if ReferenceModule
.MetaFile
in Platform
.Modules
:
508 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
509 if key
in RefPlatformModule
.Pcds
:
510 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
511 if PcdInReferenceModule
.Type
:
512 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
513 BuildData
.Pcds
[key
].Pending
= False
516 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
517 if BuildData
.IsBinaryModule
:
518 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
520 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
522 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
523 if BuildData
.MetaFile
.Ext
== '.inf':
524 if BuildData
.IsBinaryModule
:
525 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
527 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
529 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
530 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
531 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
532 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
536 # A PCD can only use one type for all source modules
538 for i
in SourcePcdDict_Keys
:
539 for j
in SourcePcdDict_Keys
:
541 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
542 if len(Intersections
) > 0:
546 "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i
, j
),
547 ExtraData
='\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
551 # intersection the BinaryPCD for Mixed PCD
553 for i
in BinaryPcdDict_Keys
:
554 for j
in BinaryPcdDict_Keys
:
556 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
557 for item
in Intersections
:
558 NewPcd1
= (item
[0] + '_' + i
, item
[1])
559 NewPcd2
= (item
[0] + '_' + j
, item
[1])
560 if item
not in GlobalData
.MixedPcd
:
561 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
563 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
564 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
565 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
566 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
569 # intersection the SourcePCD and BinaryPCD for Mixed PCD
571 for i
in SourcePcdDict_Keys
:
572 for j
in BinaryPcdDict_Keys
:
574 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
575 for item
in Intersections
:
576 NewPcd1
= (item
[0] + '_' + i
, item
[1])
577 NewPcd2
= (item
[0] + '_' + j
, item
[1])
578 if item
not in GlobalData
.MixedPcd
:
579 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
581 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
582 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
583 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
584 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
586 for BuildData
in PGen
.BuildDatabase
._CACHE
_.values():
587 if BuildData
.Arch
!= Arch
:
589 for key
in BuildData
.Pcds
:
590 for SinglePcd
in GlobalData
.MixedPcd
:
591 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
592 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
593 Pcd_Type
= item
[0].split('_')[-1]
594 if (Pcd_Type
== BuildData
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_EX_TYPE_SET
) or \
595 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
596 Value
= BuildData
.Pcds
[key
]
597 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
599 newkey
= (Value
.TokenCName
, key
[1])
601 newkey
= (Value
.TokenCName
, key
[1], key
[2])
602 del BuildData
.Pcds
[key
]
603 BuildData
.Pcds
[newkey
] = Value
607 # handle the mixed pcd in FDF file
609 if key
in GlobalData
.MixedPcd
:
612 for item
in GlobalData
.MixedPcd
[key
]:
615 #Collect package set information from INF of FDF
617 for Inf
in ModuleList
:
618 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
619 if ModuleFile
in Platform
.Modules
:
621 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
622 PkgSet
.update(ModuleData
.Packages
)
623 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
628 DecPcds
.add((Pcd
[0], Pcd
[1]))
629 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
631 Platform
.SkuName
= self
.SkuId
632 for Name
, Guid
,Fileds
in PcdSet
:
633 if (Name
, Guid
) not in DecPcds
:
637 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
638 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
639 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
642 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
643 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
644 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
645 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
647 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
651 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
652 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
653 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
656 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
658 # Explicitly collect platform's dynamic PCDs
660 Pa
.CollectPlatformDynamicPcds()
661 Pa
.CollectFixedAtBuildPcds()
662 self
.AutoGenObjectList
.append(Pa
)
665 # Generate Package level hash value
667 GlobalData
.gPackageHash
[Arch
] = {}
668 if GlobalData
.gUseHashCache
:
670 self
._GenPkgLevelHash
(Pkg
)
673 # Check PCDs token value conflict in each DEC file.
675 self
._CheckAllPcdsTokenValueConflict
()
678 # Check PCD type and definition between DSC and DEC
680 self
._CheckPcdDefineAndType
()
683 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
685 content
= 'gCommandLineDefines: '
686 content
+= str(GlobalData
.gCommandLineDefines
)
687 content
+= os
.linesep
688 content
+= 'BuildOptionPcd: '
689 content
+= str(GlobalData
.BuildOptionPcd
)
690 content
+= os
.linesep
691 content
+= 'Active Platform: '
692 content
+= str(self
.Platform
)
693 content
+= os
.linesep
695 content
+= 'Flash Image Definition: '
696 content
+= str(self
.FdfFile
)
697 content
+= os
.linesep
698 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
701 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
703 PcdTokenNumber
= 'PcdTokenNumber: '
704 if Pa
.PcdTokenNumber
:
705 if Pa
.DynamicPcdList
:
706 for Pcd
in Pa
.DynamicPcdList
:
707 PcdTokenNumber
+= os
.linesep
708 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
709 PcdTokenNumber
+= ' : '
710 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
711 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
714 # Get set of workspace metafiles
716 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
719 # Retrieve latest modified time of all metafiles
722 for f
in AllWorkSpaceMetaFiles
:
723 if os
.stat(f
)[8] > SrcTimeStamp
:
724 SrcTimeStamp
= os
.stat(f
)[8]
725 self
._SrcTimeStamp
= SrcTimeStamp
727 if GlobalData
.gUseHashCache
:
729 for files
in AllWorkSpaceMetaFiles
:
730 if files
.endswith('.dec'):
736 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), True)
737 GlobalData
.gPlatformHash
= m
.hexdigest()
740 # Write metafile list to build directory
742 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
743 if os
.path
.exists (AutoGenFilePath
):
744 os
.remove(AutoGenFilePath
)
745 if not os
.path
.exists(self
.BuildDir
):
746 os
.makedirs(self
.BuildDir
)
747 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
748 for f
in AllWorkSpaceMetaFiles
:
752 def _GenPkgLevelHash(self
, Pkg
):
753 if Pkg
.PackageName
in GlobalData
.gPackageHash
[Pkg
.Arch
]:
756 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
757 CreateDirectory(PkgDir
)
758 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
760 # Get .dec file's hash value
761 f
= open(Pkg
.MetaFile
.Path
, 'r')
765 # Get include files hash value
767 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
768 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
769 for File
in sorted(Files
):
770 File_Path
= os
.path
.join(Root
, File
)
771 f
= open(File_Path
, 'r')
775 SaveFileOnChange(HashFile
, m
.hexdigest(), True)
776 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
778 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
779 AllWorkSpaceMetaFiles
= set()
784 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
785 for f
in GlobalData
.gFdfParser
.GetAllIncludedFile():
786 AllWorkSpaceMetaFiles
.add (f
.FileName
)
790 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
793 # add build_rule.txt & tools_def.txt
795 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
796 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
798 # add BuildOption metafile
800 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
802 # add PcdToken Number file for Dynamic/DynamicEx Pcd
804 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
806 for Arch
in self
.ArchList
:
810 for Package
in PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
).PackageList
:
811 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
816 for filePath
in self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]._RawData
.IncludedFiles
:
817 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
819 return AllWorkSpaceMetaFiles
821 def _CheckPcdDefineAndType(self
):
822 PcdTypeSet
= {TAB_PCDS_FIXED_AT_BUILD
,
823 TAB_PCDS_PATCHABLE_IN_MODULE
,
824 TAB_PCDS_FEATURE_FLAG
,
828 # This dict store PCDs which are not used by any modules with specified arches
829 UnusedPcd
= OrderedDict()
830 for Pa
in self
.AutoGenObjectList
:
831 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
832 for Pcd
in Pa
.Platform
.Pcds
:
833 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
835 # If no PCD type, this PCD comes from FDF
839 # Try to remove Hii and Vpd suffix
840 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
841 PcdType
= TAB_PCDS_DYNAMIC_EX
842 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
843 PcdType
= TAB_PCDS_DYNAMIC
845 for Package
in Pa
.PackageList
:
846 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
847 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
849 for Type
in PcdTypeSet
:
850 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
854 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
855 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
860 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
862 for Pcd
in UnusedPcd
:
865 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
866 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
867 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
872 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
874 ## Return the directory to store FV files
877 return path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
879 ## Return the directory to store all intermediate and final files built
882 return self
.AutoGenObjectList
[0].BuildDir
884 ## Return the build output directory platform specifies
887 return self
.Platform
.OutputDirectory
889 ## Return platform name
892 return self
.Platform
.PlatformName
894 ## Return meta-file GUID
897 return self
.Platform
.Guid
899 ## Return platform version
902 return self
.Platform
.Version
904 ## Return paths of tools
906 def ToolDefinition(self
):
907 return self
.AutoGenObjectList
[0].ToolDefinition
909 ## Return directory of platform makefile
911 # @retval string Makefile directory
914 def MakeFileDir(self
):
917 ## Return build command string
919 # @retval string Build command string
922 def BuildCommand(self
):
923 # BuildCommand should be all the same. So just get one from platform AutoGen
924 return self
.AutoGenObjectList
[0].BuildCommand
926 ## Check the PCDs token value conflict in each DEC file.
928 # Will cause build break and raise error message while two PCDs conflict.
932 def _CheckAllPcdsTokenValueConflict(self
):
933 for Pa
in self
.AutoGenObjectList
:
934 for Package
in Pa
.PackageList
:
935 PcdList
= Package
.Pcds
.values()
936 PcdList
.sort(key
=lambda x
: int(x
.TokenValue
, 0))
938 while (Count
< len(PcdList
) - 1) :
939 Item
= PcdList
[Count
]
940 ItemNext
= PcdList
[Count
+ 1]
942 # Make sure in the same token space the TokenValue should be unique
944 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
945 SameTokenValuePcdList
= []
946 SameTokenValuePcdList
.append(Item
)
947 SameTokenValuePcdList
.append(ItemNext
)
948 RemainPcdListLength
= len(PcdList
) - Count
- 2
949 for ValueSameCount
in range(RemainPcdListLength
):
950 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
951 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
955 # Sort same token value PCD list with TokenGuid and TokenCName
957 SameTokenValuePcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
958 SameTokenValuePcdListCount
= 0
959 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
961 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
962 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
964 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
965 for PcdItem
in GlobalData
.MixedPcd
:
966 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
967 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
973 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
974 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
977 SameTokenValuePcdListCount
+= 1
978 Count
+= SameTokenValuePcdListCount
981 PcdList
= Package
.Pcds
.values()
982 PcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
984 while (Count
< len(PcdList
) - 1) :
985 Item
= PcdList
[Count
]
986 ItemNext
= PcdList
[Count
+ 1]
988 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
990 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
994 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
995 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
999 ## Generate fds command
1001 def GenFdsCommand(self
):
1002 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1005 def GenFdsCommandDict(self
):
1007 LogLevel
= EdkLogger
.GetLevel()
1008 if LogLevel
== EdkLogger
.VERBOSE
:
1009 FdsCommandDict
["verbose"] = True
1010 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1011 FdsCommandDict
["debug"] = LogLevel
- 1
1012 elif LogLevel
== EdkLogger
.QUIET
:
1013 FdsCommandDict
["quiet"] = True
1015 if GlobalData
.gEnableGenfdsMultiThread
:
1016 FdsCommandDict
["GenfdsMultiThread"] = True
1017 if GlobalData
.gIgnoreSource
:
1018 FdsCommandDict
["IgnoreSources"] = True
1020 FdsCommandDict
["OptionPcd"] = []
1021 for pcd
in GlobalData
.BuildOptionPcd
:
1023 pcdname
= '.'.join(pcd
[0:3])
1025 pcdname
= '.'.join(pcd
[0:2])
1026 if pcd
[3].startswith('{'):
1027 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"')
1029 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + pcd
[3])
1032 # macros passed to GenFds
1034 MacroDict
.update(GlobalData
.gGlobalDefines
)
1035 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1036 for MacroName
in MacroDict
:
1037 if MacroDict
[MacroName
] != "":
1038 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1040 MacroList
.append('"%s"' % MacroName
)
1041 FdsCommandDict
["macro"] = MacroList
1043 FdsCommandDict
["fdf_file"] = [self
.FdfFile
]
1044 FdsCommandDict
["build_target"] = self
.BuildTarget
1045 FdsCommandDict
["toolchain_tag"] = self
.ToolChain
1046 FdsCommandDict
["active_platform"] = str(self
)
1048 FdsCommandDict
["conf_directory"] = GlobalData
.gConfDirectory
1049 FdsCommandDict
["build_architecture_list"] = ','.join(self
.ArchList
)
1050 FdsCommandDict
["platform_build_directory"] = self
.BuildDir
1052 FdsCommandDict
["fd"] = self
.FdTargetList
1053 FdsCommandDict
["fv"] = self
.FvTargetList
1054 FdsCommandDict
["cap"] = self
.CapTargetList
1055 return FdsCommandDict
1057 ## Create makefile for the platform and modules in it
1059 # @param CreateDepsMakeFile Flag indicating if the makefile for
1060 # modules will be created as well
1062 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1063 if not CreateDepsMakeFile
:
1065 for Pa
in self
.AutoGenObjectList
:
1066 Pa
.CreateMakeFile(True)
1068 ## Create autogen code for platform and modules
1070 # Since there's no autogen code for platform, this method will do nothing
1071 # if CreateModuleCodeFile is set to False.
1073 # @param CreateDepsCodeFile Flag indicating if creating module's
1074 # autogen code file or not
1076 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1077 if not CreateDepsCodeFile
:
1079 for Pa
in self
.AutoGenObjectList
:
1080 Pa
.CreateCodeFile(True)
1082 ## Create AsBuilt INF file the platform
1084 def CreateAsBuiltInf(self
):
1088 ## AutoGen class for platform
1090 # PlatformAutoGen class will process the original information in platform
1091 # file in order to generate makefile for platform.
1093 class PlatformAutoGen(AutoGen
):
1094 # call super().__init__ then call the worker function with different parameter count
1095 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1096 if not hasattr(self
, "_Init"):
1097 super(PlatformAutoGen
, self
).__init
__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
1098 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1101 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1102 # correct PCD database
1105 _NonDynaPcdList_
= []
1109 # The priority list while override build option
1111 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1112 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1113 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1114 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1115 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1116 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1117 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1118 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1119 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1120 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1121 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1122 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1123 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1124 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1125 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1126 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1128 ## Initialize PlatformAutoGen
1131 # @param Workspace WorkspaceAutoGen object
1132 # @param PlatformFile Platform file (DSC file)
1133 # @param Target Build target (DEBUG, RELEASE)
1134 # @param Toolchain Name of tool chain
1135 # @param Arch arch of the platform supports
1137 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1138 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1139 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1141 self
.MetaFile
= PlatformFile
1142 self
.Workspace
= Workspace
1143 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1144 self
.ToolChain
= Toolchain
1145 self
.BuildTarget
= Target
1147 self
.SourceDir
= PlatformFile
.SubDir
1148 self
.SourceOverrideDir
= None
1149 self
.FdTargetList
= self
.Workspace
.FdTargetList
1150 self
.FvTargetList
= self
.Workspace
.FvTargetList
1151 self
.AllPcdList
= []
1152 # get the original module/package/platform objects
1153 self
.BuildDatabase
= Workspace
.BuildDatabase
1154 self
.DscBuildDataObj
= Workspace
.Platform
1156 # flag indicating if the makefile/C-code file has been created or not
1157 self
.IsMakeFileCreated
= False
1159 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1160 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1162 self
._AsBuildInfList
= []
1163 self
._AsBuildModuleList
= []
1165 self
.VariableInfo
= None
1167 if GlobalData
.gFdfParser
is not None:
1168 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1169 for Inf
in self
._AsBuildInfList
:
1170 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1171 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1172 if not M
.IsBinaryModule
:
1174 self
._AsBuildModuleList
.append(InfClass
)
1175 # get library/modules for build
1176 self
.LibraryBuildDirectoryList
= []
1177 self
.ModuleBuildDirectoryList
= []
1181 @cached_class_function
1183 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1185 ## Create autogen code for platform and modules
1187 # Since there's no autogen code for platform, this method will do nothing
1188 # if CreateModuleCodeFile is set to False.
1190 # @param CreateModuleCodeFile Flag indicating if creating module's
1191 # autogen code file or not
1193 @cached_class_function
1194 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1195 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False
1196 if not CreateModuleCodeFile
:
1199 for Ma
in self
.ModuleAutoGenList
:
1200 Ma
.CreateCodeFile(True)
1202 ## Generate Fds Command
1204 def GenFdsCommand(self
):
1205 return self
.Workspace
.GenFdsCommand
1207 ## Create makefile for the platform and modules in it
1209 # @param CreateModuleMakeFile Flag indicating if the makefile for
1210 # modules will be created as well
1212 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1213 if CreateModuleMakeFile
:
1214 for Ma
in self
._MaList
:
1215 key
= (Ma
.MetaFile
.File
, self
.Arch
)
1216 if key
in FfsCommand
:
1217 Ma
.CreateMakeFile(True, FfsCommand
[key
])
1219 Ma
.CreateMakeFile(True)
1221 # no need to create makefile for the platform more than once
1222 if self
.IsMakeFileCreated
:
1225 # create library/module build dirs for platform
1226 Makefile
= GenMake
.PlatformMakefile(self
)
1227 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1228 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1230 self
.IsMakeFileCreated
= True
1232 ## Deal with Shared FixedAtBuild Pcds
1234 def CollectFixedAtBuildPcds(self
):
1235 for LibAuto
in self
.LibraryAutoGenList
:
1236 FixedAtBuildPcds
= {}
1237 ShareFixedAtBuildPcdsSameValue
= {}
1238 for Module
in LibAuto
.ReferenceModules
:
1239 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
1240 DefaultValue
= Pcd
.DefaultValue
1241 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
1242 if Pcd
in Module
.LibraryPcdList
:
1243 Index
= Module
.LibraryPcdList
.index(Pcd
)
1244 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
1245 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1246 if key
not in FixedAtBuildPcds
:
1247 ShareFixedAtBuildPcdsSameValue
[key
] = True
1248 FixedAtBuildPcds
[key
] = DefaultValue
1250 if FixedAtBuildPcds
[key
] != DefaultValue
:
1251 ShareFixedAtBuildPcdsSameValue
[key
] = False
1252 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1253 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1254 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1257 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
1258 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
1260 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1261 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
1263 def CollectVariables(self
, DynamicPcdSet
):
1266 if self
.Workspace
.FdfFile
:
1267 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1268 for FdRegion
in FdDict
.RegionList
:
1269 for item
in FdRegion
.RegionDataList
:
1270 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1271 VpdRegionSize
= FdRegion
.Size
1272 VpdRegionBase
= FdRegion
.Offset
1275 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
1276 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1277 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1279 for Pcd
in DynamicPcdSet
:
1280 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1281 for SkuName
in Pcd
.SkuInfoList
:
1282 Sku
= Pcd
.SkuInfoList
[SkuName
]
1284 if SkuId
is None or SkuId
== '':
1286 if len(Sku
.VariableName
) > 0:
1287 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
1289 VariableGuidStructure
= Sku
.VariableGuidValue
1290 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1291 for StorageName
in Sku
.DefaultStoreDict
:
1292 VariableInfo
.append_variable(var_info(Index
, pcdname
, StorageName
, SkuName
, StringToArray(Sku
.VariableName
), VariableGuid
, Sku
.VariableOffset
, Sku
.VariableAttribute
, Sku
.HiiDefaultValue
, Sku
.DefaultStoreDict
[StorageName
] if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
else StringToArray(Sku
.DefaultStoreDict
[StorageName
]), Pcd
.DatumType
, Pcd
.CustomAttribute
['DscPosition'], Pcd
.CustomAttribute
.get('IsStru',False)))
1296 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
1297 if self
.VariableInfo
:
1298 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1299 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1301 if PcdNvStoreDfBuffer
:
1302 if os
.path
.exists(VpdMapFilePath
):
1303 OrgVpdFile
.Read(VpdMapFilePath
)
1304 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1305 NvStoreOffset
= PcdItems
.values()[0].strip() if PcdItems
else '0'
1307 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1309 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1310 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1311 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1312 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1314 if var_data
and default_skuobj
:
1315 default_skuobj
.DefaultValue
= var_data
1316 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1317 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1318 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
1319 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1323 ## Collect dynamic PCDs
1325 # Gather dynamic PCDs list from each module and their settings from platform
1326 # This interface should be invoked explicitly when platform action is created.
1328 def CollectPlatformDynamicPcds(self
):
1329 for key
in self
.Platform
.Pcds
:
1330 for SinglePcd
in GlobalData
.MixedPcd
:
1331 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1332 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1333 Pcd_Type
= item
[0].split('_')[-1]
1334 if (Pcd_Type
== self
.Platform
.Pcds
[key
].Type
) or (Pcd_Type
== TAB_PCDS_DYNAMIC_EX
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_EX_TYPE_SET
) or \
1335 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
1336 Value
= self
.Platform
.Pcds
[key
]
1337 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1339 newkey
= (Value
.TokenCName
, key
[1])
1341 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1342 del self
.Platform
.Pcds
[key
]
1343 self
.Platform
.Pcds
[newkey
] = Value
1347 # for gathering error information
1348 NoDatumTypePcdList
= set()
1350 for InfName
in self
._AsBuildInfList
:
1351 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1352 FdfModuleList
.append(os
.path
.normpath(InfName
))
1353 for M
in self
._MaList
:
1354 # F is the Module for which M is the module autogen
1355 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1356 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1357 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1358 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
1360 # Check the PCD from Binary INF or Source INF
1361 if M
.IsBinaryModule
== True:
1362 PcdFromModule
.IsFromBinaryInf
= True
1364 # Check the PCD from DSC or not
1365 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
1367 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1368 if M
.MetaFile
.Path
not in FdfModuleList
:
1369 # If one of the Source built modules listed in the DSC is not listed
1370 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1371 # access method (it is only listed in the DEC file that declares the
1372 # PCD as PcdsDynamic), then build tool will report warning message
1373 # notify the PI that they are attempting to build a module that must
1374 # be included in a flash image in order to be functional. These Dynamic
1375 # PCD will not be added into the Database unless it is used by other
1376 # modules that are included in the FDF file.
1377 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
1378 PcdFromModule
.IsFromBinaryInf
== False:
1379 # Print warning message to let the developer make a determine.
1381 # If one of the Source built modules listed in the DSC is not listed in
1382 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1383 # access method (it is only listed in the DEC file that declares the
1384 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1385 # PCD to the Platform's PCD Database.
1386 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1389 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1390 # it should be stored in Pcd PEI database, If a dynamic only
1391 # used by DXE module, it should be stored in DXE PCD database.
1392 # The default Phase is DXE
1394 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1395 PcdFromModule
.Phase
= "PEI"
1396 if PcdFromModule
not in self
._DynaPcdList
_:
1397 self
._DynaPcdList
_.append(PcdFromModule
)
1398 elif PcdFromModule
.Phase
== 'PEI':
1399 # overwrite any the same PCD existing, if Phase is PEI
1400 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1401 self
._DynaPcdList
_[Index
] = PcdFromModule
1402 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1403 self
._NonDynaPcdList
_.append(PcdFromModule
)
1404 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1405 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1406 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1407 #The PCD from Binary INF will override the same one from source INF
1408 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1409 PcdFromModule
.Pending
= False
1410 self
._NonDynaPcdList
_.append (PcdFromModule
)
1411 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
1412 # add the PCD from modules that listed in FDF but not in DSC to Database
1413 for InfName
in FdfModuleList
:
1414 if InfName
not in DscModuleSet
:
1415 InfClass
= PathClass(InfName
)
1416 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1417 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1418 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1419 # For binary module, if in current arch, we need to list the PCDs into database.
1420 if not M
.IsBinaryModule
:
1422 # Override the module PCD setting by platform setting
1423 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1424 for PcdFromModule
in ModulePcdList
:
1425 PcdFromModule
.IsFromBinaryInf
= True
1426 PcdFromModule
.IsFromDsc
= False
1427 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1428 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1429 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1431 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1432 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1433 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1434 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1435 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1436 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1437 PcdFromModule
.Phase
= "PEI"
1438 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1439 self
._DynaPcdList
_.append(PcdFromModule
)
1440 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1441 self
._NonDynaPcdList
_.append(PcdFromModule
)
1442 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1443 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1444 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1445 # module & DXE module at a same time.
1446 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1447 # INF file as DynamicEx.
1448 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1449 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1450 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1451 for PcdFromModule
in self
._NonDynaPcdList
_:
1452 # If a PCD is not listed in the DSC file, but binary INF files used by
1453 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1454 # section, AND all source INF files used by this platform the build
1455 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1456 # section, then the tools must NOT add the PCD to the Platform's PCD
1457 # Database; the build must assign the access method for this PCD as
1458 # PcdsPatchableInModule.
1459 if PcdFromModule
not in self
._DynaPcdList
_:
1461 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1462 if PcdFromModule
.IsFromDsc
== False and \
1463 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1464 PcdFromModule
.IsFromBinaryInf
== True and \
1465 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1466 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1467 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1469 # print out error information and break the build, if error found
1470 if len(NoDatumTypePcdList
) > 0:
1471 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1472 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1474 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1475 % NoDatumTypePcdListString
)
1476 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1477 self
._DynamicPcdList
= self
._DynaPcdList
_
1479 # Sort dynamic PCD list to:
1480 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1481 # try to be put header of dynamicd List
1482 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1484 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1486 UnicodePcdArray
= set()
1488 OtherPcdArray
= set()
1490 VpdFile
= VpdInfoFile
.VpdInfoFile()
1491 NeedProcessVpdMapFile
= False
1493 for pcd
in self
.Platform
.Pcds
:
1494 if pcd
not in self
._PlatformPcds
:
1495 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1497 for item
in self
._PlatformPcds
:
1498 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1499 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
1501 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1502 for Pcd
in self
._DynamicPcdList
:
1503 # just pick the a value to determine whether is unicode string type
1504 Sku
= Pcd
.SkuInfoList
.values()[0]
1505 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1507 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1508 Pcd
.DatumType
= TAB_VOID
1510 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1511 # if found HII type PCD then insert to right of UnicodeIndex
1512 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1513 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1515 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1516 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
1517 if PcdNvStoreDfBuffer
:
1518 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1519 vardump
= self
.VariableInfo
.dump()
1522 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
1523 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
1524 #typedef UINT16 SIZE_INFO;
1525 #//SIZE_INFO SizeTable[];
1526 if len(vardump
.split(",")) > 0xffff:
1527 EdkLogger
.error("build", RESOURCE_OVERFLOW
, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer
.TokenSpaceGuidCName
,PcdNvStoreDfBuffer
.TokenCName
]) ,len(vardump
.split(","))))
1528 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1529 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1530 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1531 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1533 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
1534 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
1535 EdkLogger
.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self
.Platform
.MetaFile
.Path
)
1536 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
1538 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1541 for PcdKey
in PlatformPcds
:
1542 Pcd
= self
._PlatformPcds
[PcdKey
]
1543 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1544 PcdKey
in VpdPcdDict
:
1545 Pcd
= VpdPcdDict
[PcdKey
]
1547 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1549 PcdValue
= DefaultSku
.DefaultValue
1550 if PcdValue
not in SkuValueMap
:
1551 SkuValueMap
[PcdValue
] = []
1552 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
1553 SkuValueMap
[PcdValue
].append(DefaultSku
)
1555 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
1556 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1557 PcdValue
= Sku
.DefaultValue
1559 PcdValue
= Pcd
.DefaultValue
1560 if Sku
.VpdOffset
!= TAB_STAR
:
1561 if PcdValue
.startswith("{"):
1563 elif PcdValue
.startswith("L"):
1568 VpdOffset
= int(Sku
.VpdOffset
)
1571 VpdOffset
= int(Sku
.VpdOffset
, 16)
1573 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1574 if VpdOffset
% Alignment
!= 0:
1575 if PcdValue
.startswith("{"):
1576 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1578 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1579 if PcdValue
not in SkuValueMap
:
1580 SkuValueMap
[PcdValue
] = []
1581 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
1582 SkuValueMap
[PcdValue
].append(Sku
)
1583 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1584 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1585 NeedProcessVpdMapFile
= True
1586 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1587 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1588 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
1590 VpdSkuMap
[PcdKey
] = SkuValueMap
1592 # Fix the PCDs define in VPD PCD section that never referenced by module.
1593 # An example is PCD for signature usage.
1595 for DscPcd
in PlatformPcds
:
1596 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1597 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1598 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1600 for VpdPcd
in VpdFile
._VpdArray
:
1601 # This PCD has been referenced by module
1602 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1603 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1606 # Not found, it should be signature
1608 # just pick the a value to determine whether is unicode string type
1610 SkuObjList
= DscPcdEntry
.SkuInfoList
.items()
1611 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
1613 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
1614 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
1615 for (SkuName
, Sku
) in SkuObjList
:
1616 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1618 # Need to iterate DEC pcd information to get the value & datumtype
1619 for eachDec
in self
.PackageList
:
1620 for DecPcd
in eachDec
.Pcds
:
1621 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1622 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1623 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1624 # Print warning message to let the developer make a determine.
1625 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1626 File
=self
.MetaFile
, \
1627 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1628 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1630 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1631 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1632 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1633 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1634 # Only fix the value while no value provided in DSC file.
1635 if not Sku
.DefaultValue
:
1636 DscPcdEntry
.SkuInfoList
[DscPcdEntry
.SkuInfoList
.keys()[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1638 if DscPcdEntry
not in self
._DynamicPcdList
:
1639 self
._DynamicPcdList
.append(DscPcdEntry
)
1640 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1641 PcdValue
= Sku
.DefaultValue
1643 PcdValue
= DscPcdEntry
.DefaultValue
1644 if Sku
.VpdOffset
!= TAB_STAR
:
1645 if PcdValue
.startswith("{"):
1647 elif PcdValue
.startswith("L"):
1652 VpdOffset
= int(Sku
.VpdOffset
)
1655 VpdOffset
= int(Sku
.VpdOffset
, 16)
1657 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1658 if VpdOffset
% Alignment
!= 0:
1659 if PcdValue
.startswith("{"):
1660 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1662 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1663 if PcdValue
not in SkuValueMap
:
1664 SkuValueMap
[PcdValue
] = []
1665 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
1666 SkuValueMap
[PcdValue
].append(Sku
)
1667 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1668 NeedProcessVpdMapFile
= True
1669 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1670 UnicodePcdArray
.add(DscPcdEntry
)
1671 elif len(Sku
.VariableName
) > 0:
1672 HiiPcdArray
.add(DscPcdEntry
)
1674 OtherPcdArray
.add(DscPcdEntry
)
1676 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1677 VpdSkuMap
[DscPcd
] = SkuValueMap
1678 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1679 VpdFile
.GetCount() != 0:
1680 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1681 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1683 if VpdFile
.GetCount() != 0:
1685 self
.FixVpdOffset(VpdFile
)
1687 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1688 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1689 if PcdNvStoreDfBuffer
:
1690 PcdName
,PcdGuid
= PcdNvStoreDfBuffer
[0].TokenCName
, PcdNvStoreDfBuffer
[0].TokenSpaceGuidCName
1691 if (PcdName
,PcdGuid
) in VpdSkuMap
:
1692 DefaultSku
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1693 VpdSkuMap
[(PcdName
,PcdGuid
)] = {DefaultSku
.DefaultValue
:[DefaultSku
]}
1695 # Process VPD map file generated by third party BPDG tool
1696 if NeedProcessVpdMapFile
:
1697 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1698 if os
.path
.exists(VpdMapFilePath
):
1699 VpdFile
.Read(VpdMapFilePath
)
1701 # Fixup TAB_STAR offset
1702 for pcd
in VpdSkuMap
:
1703 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1705 # just pick the a value to determine whether is unicode string type
1707 for pcdvalue
in VpdSkuMap
[pcd
]:
1708 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1709 for item
in vpdinfo
:
1710 if item
[2] == pcdvalue
:
1711 sku
.VpdOffset
= item
[1]
1713 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1715 # Delete the DynamicPcdList At the last time enter into this function
1716 for Pcd
in self
._DynamicPcdList
:
1717 # just pick the a value to determine whether is unicode string type
1718 Sku
= Pcd
.SkuInfoList
.values()[0]
1719 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1721 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1722 Pcd
.DatumType
= TAB_VOID
1724 PcdValue
= Sku
.DefaultValue
1725 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1726 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1727 UnicodePcdArray
.add(Pcd
)
1728 elif len(Sku
.VariableName
) > 0:
1729 # if found HII type PCD then insert to right of UnicodeIndex
1730 HiiPcdArray
.add(Pcd
)
1732 OtherPcdArray
.add(Pcd
)
1733 del self
._DynamicPcdList
[:]
1734 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1735 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1736 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1737 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
1738 for pcd
in self
._DynamicPcdList
:
1739 if len(pcd
.SkuInfoList
) == 1:
1740 for (SkuName
, SkuId
) in allskuset
:
1741 if type(SkuId
) in (str, unicode) and eval(SkuId
) == 0 or SkuId
== 0:
1743 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
1744 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1745 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
1746 self
.AllPcdList
= self
._NonDynamicPcdList
+ self
._DynamicPcdList
1748 def FixVpdOffset(self
, VpdFile
):
1749 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
1750 if not os
.path
.exists(FvPath
):
1754 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1756 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1758 if VpdFile
.Write(VpdFilePath
):
1759 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1761 for ToolDef
in self
.ToolDefinition
.values():
1762 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
1763 if "PATH" not in ToolDef
:
1764 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1765 BPDGToolName
= ToolDef
["PATH"]
1767 # Call third party GUID BPDG tool.
1768 if BPDGToolName
is not None:
1769 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1771 EdkLogger
.error("Build", FILE_NOT_FOUND
, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
1773 ## Return the platform build data object
1776 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1778 ## Return platform name
1781 return self
.Platform
.PlatformName
1783 ## Return the meta file GUID
1786 return self
.Platform
.Guid
1788 ## Return the platform version
1791 return self
.Platform
.Version
1793 ## Return the FDF file name
1796 if self
.Workspace
.FdfFile
:
1797 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1802 ## Return the build output directory platform specifies
1804 def OutputDir(self
):
1805 return self
.Platform
.OutputDirectory
1807 ## Return the directory to store all intermediate and final files built
1810 if os
.path
.isabs(self
.OutputDir
):
1811 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1812 path
.abspath(self
.OutputDir
),
1813 self
.BuildTarget
+ "_" + self
.ToolChain
,
1816 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1819 self
.BuildTarget
+ "_" + self
.ToolChain
,
1823 ## Return directory of platform makefile
1825 # @retval string Makefile directory
1828 def MakeFileDir(self
):
1829 return path
.join(self
.BuildDir
, self
.Arch
)
1831 ## Return build command string
1833 # @retval string Build command string
1836 def BuildCommand(self
):
1838 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1839 RetVal
+= _SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1840 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1841 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1843 RetVal
+= _SplitOption(NewOption
)
1844 if "MAKE" in self
.EdkIIBuildOption
:
1845 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1846 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1847 if Flags
.startswith('='):
1848 RetVal
= [RetVal
[0]] + [Flags
[1:]]
1850 RetVal
.append(Flags
)
1853 ## Get tool chain definition
1855 # Get each tool defition for given tool chain from tools_def.txt and platform
1858 def ToolDefinition(self
):
1859 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1860 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1861 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1862 ExtraData
="[%s]" % self
.MetaFile
)
1865 for Def
in ToolDefinition
:
1866 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1867 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1870 Value
= ToolDefinition
[Def
]
1871 # don't record the DLL
1873 DllPathList
.add(Value
)
1876 if Tool
not in RetVal
:
1878 RetVal
[Tool
][Attr
] = Value
1881 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
1882 if "FLAGS" not in RetVal
["MAKE"]:
1883 RetVal
["MAKE"]["FLAGS"] = ""
1884 RetVal
["MAKE"]["FLAGS"] += " -s"
1887 for Attr
in RetVal
[Tool
]:
1888 Value
= RetVal
[Tool
][Attr
]
1889 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
1890 # check if override is indicated
1891 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
1892 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
1895 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1897 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1900 # Don't put MAKE definition in the file
1902 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1904 # Don't put MAKE definition in the file
1909 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1912 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
)
1913 for DllPath
in DllPathList
:
1914 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1915 os
.environ
["MAKE_FLAGS"] = MakeFlags
1919 ## Return the paths of tools
1921 def ToolDefinitionFile(self
):
1922 return os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1924 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1926 def ToolChainFamily(self
):
1927 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1928 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1929 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1930 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1931 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1933 RetVal
= TAB_COMPILER_MSFT
1935 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1939 def BuildRuleFamily(self
):
1940 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1941 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1942 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1943 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1944 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1946 return TAB_COMPILER_MSFT
1948 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1950 ## Return the build options specific for all modules in this platform
1952 def BuildOption(self
):
1953 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1955 def _BuildOptionWithToolDef(self
, ToolDef
):
1956 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
1958 ## Return the build options specific for EDK modules in this platform
1960 def EdkBuildOption(self
):
1961 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1963 ## Return the build options specific for EDKII modules in this platform
1965 def EdkIIBuildOption(self
):
1966 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1968 ## Parse build_rule.txt in Conf Directory.
1970 # @retval BuildRule object
1973 def BuildRule(self
):
1974 BuildRuleFile
= None
1975 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1976 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1977 if not BuildRuleFile
:
1978 BuildRuleFile
= gDefaultBuildRuleFile
1979 RetVal
= BuildRule(BuildRuleFile
)
1980 if RetVal
._FileVersion
== "":
1981 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
1983 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1984 # If Build Rule's version is less than the version number required by the tools, halting the build.
1985 EdkLogger
.error("build", AUTOGEN_ERROR
,
1986 ExtraData
="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
1987 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1990 ## Summarize the packages used by modules in this platform
1992 def PackageList(self
):
1994 for La
in self
.LibraryAutoGenList
:
1995 RetVal
.update(La
.DependentPackageList
)
1996 for Ma
in self
.ModuleAutoGenList
:
1997 RetVal
.update(Ma
.DependentPackageList
)
1998 #Collect package set information from INF of FDF
1999 for ModuleFile
in self
._AsBuildModuleList
:
2000 if ModuleFile
in self
.Platform
.Modules
:
2002 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2003 RetVal
.update(ModuleData
.Packages
)
2007 def NonDynamicPcdDict(self
):
2008 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
2010 ## Get list of non-dynamic PCDs
2012 def NonDynamicPcdList(self
):
2013 if not self
._NonDynamicPcdList
:
2014 self
.CollectPlatformDynamicPcds()
2015 return self
._NonDynamicPcdList
2017 ## Get list of dynamic PCDs
2019 def DynamicPcdList(self
):
2020 if not self
._DynamicPcdList
:
2021 self
.CollectPlatformDynamicPcds()
2022 return self
._DynamicPcdList
2024 ## Generate Token Number for all PCD
2026 def PcdTokenNumber(self
):
2027 RetVal
= OrderedDict()
2030 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2034 # TokenNumber 0 ~ 10
2036 # TokeNumber 11 ~ 20
2038 for Pcd
in self
.DynamicPcdList
:
2039 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2040 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2041 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2044 for Pcd
in self
.DynamicPcdList
:
2045 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2046 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2047 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2050 for Pcd
in self
.DynamicPcdList
:
2051 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2052 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2053 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2056 for Pcd
in self
.DynamicPcdList
:
2057 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2058 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2059 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2062 for Pcd
in self
.NonDynamicPcdList
:
2063 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2069 for ModuleFile
in self
.Platform
.Modules
:
2078 self
.Platform
.Modules
[ModuleFile
].M
= Ma
2079 return [x
.M
for x
in self
.Platform
.Modules
.values()]
2081 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2083 def ModuleAutoGenList(self
):
2085 for Ma
in self
._MaList
:
2086 if Ma
not in RetVal
:
2090 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2092 def LibraryAutoGenList(self
):
2094 for Ma
in self
._MaList
:
2095 for La
in Ma
.LibraryAutoGenList
:
2096 if La
not in RetVal
:
2098 if Ma
not in La
.ReferenceModules
:
2099 La
.ReferenceModules
.append(Ma
)
2102 ## Test if a module is supported by the platform
2104 # An error will be raised directly if the module or its arch is not supported
2105 # by the platform or current configuration
2107 def ValidModule(self
, Module
):
2108 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2109 or Module
in self
._AsBuildModuleList
2111 ## Resolve the library classes in a module to library instances
2113 # This method will not only resolve library classes but also sort the library
2114 # instances according to the dependency-ship.
2116 # @param Module The module from which the library classes will be resolved
2118 # @retval library_list List of library instances sorted
2120 def ApplyLibraryInstance(self
, Module
):
2121 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2122 if str(Module
) not in self
.Platform
.Modules
:
2125 return GetModuleLibInstances(Module
,
2134 ## Override PCD setting (type, value, ...)
2136 # @param ToPcd The PCD to be overrided
2137 # @param FromPcd The PCD overrideing from
2139 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2141 # in case there's PCDs coming from FDF file, which have no type given.
2142 # at this point, ToPcd.Type has the type found from dependent
2145 TokenCName
= ToPcd
.TokenCName
2146 for PcdItem
in GlobalData
.MixedPcd
:
2147 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2148 TokenCName
= PcdItem
[0]
2150 if FromPcd
is not None:
2151 if ToPcd
.Pending
and FromPcd
.Type
:
2152 ToPcd
.Type
= FromPcd
.Type
2153 elif ToPcd
.Type
and FromPcd
.Type\
2154 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
2155 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2156 ToPcd
.Type
= FromPcd
.Type
2157 elif ToPcd
.Type
and FromPcd
.Type \
2158 and ToPcd
.Type
!= FromPcd
.Type
:
2160 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2161 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2162 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2163 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2164 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2167 if FromPcd
.MaxDatumSize
:
2168 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2169 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2170 if FromPcd
.DefaultValue
:
2171 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2172 if FromPcd
.TokenValue
:
2173 ToPcd
.TokenValue
= FromPcd
.TokenValue
2174 if FromPcd
.DatumType
:
2175 ToPcd
.DatumType
= FromPcd
.DatumType
2176 if FromPcd
.SkuInfoList
:
2177 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2178 if FromPcd
.UserDefinedDefaultStoresFlag
:
2179 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
2180 # Add Flexible PCD format parse
2181 if ToPcd
.DefaultValue
:
2183 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Workspace
._GuidDict
)(True)
2184 except BadExpression
as Value
:
2185 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2188 # check the validation of datum
2189 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2191 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2192 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2193 ToPcd
.validateranges
= FromPcd
.validateranges
2194 ToPcd
.validlists
= FromPcd
.validlists
2195 ToPcd
.expressions
= FromPcd
.expressions
2196 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
2198 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2199 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2200 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2201 Value
= ToPcd
.DefaultValue
2203 ToPcd
.MaxDatumSize
= '1'
2204 elif Value
[0] == 'L':
2205 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2206 elif Value
[0] == '{':
2207 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2209 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2211 # apply default SKU for dynamic PCDS if specified one is not available
2212 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2213 and not ToPcd
.SkuInfoList
:
2214 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2215 SkuName
= self
.Platform
.SkuName
2217 SkuName
= TAB_DEFAULT
2218 ToPcd
.SkuInfoList
= {
2219 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2222 ## Apply PCD setting defined platform to a module
2224 # @param Module The module from which the PCD setting will be overrided
2226 # @retval PCD_list The list PCDs with settings from platform
2228 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2229 # for each PCD in module
2230 for Name
, Guid
in Pcds
:
2231 PcdInModule
= Pcds
[Name
, Guid
]
2232 # find out the PCD setting in platform
2233 if (Name
, Guid
) in self
.Platform
.Pcds
:
2234 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2236 PcdInPlatform
= None
2237 # then override the settings if any
2238 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2239 # resolve the VariableGuid value
2240 for SkuId
in PcdInModule
.SkuInfoList
:
2241 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2242 if Sku
.VariableGuid
== '': continue
2243 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2244 if Sku
.VariableGuidValue
is None:
2245 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2248 RESOURCE_NOT_AVAILABLE
,
2249 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2250 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2251 % (Guid
, Name
, str(Module
)),
2255 # override PCD settings with module specific setting
2256 if Module
in self
.Platform
.Modules
:
2257 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2258 for Key
in PlatformModule
.Pcds
:
2259 if GlobalData
.BuildOptionPcd
:
2260 for pcd
in GlobalData
.BuildOptionPcd
:
2261 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
2262 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
2263 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
2264 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
2270 elif Key
in GlobalData
.MixedPcd
:
2271 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2273 ToPcd
= Pcds
[PcdItem
]
2277 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2278 # use PCD value to calculate the MaxDatumSize when it is not specified
2279 for Name
, Guid
in Pcds
:
2280 Pcd
= Pcds
[Name
, Guid
]
2281 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2282 Pcd
.MaxSizeUserSet
= None
2283 Value
= Pcd
.DefaultValue
2285 Pcd
.MaxDatumSize
= '1'
2286 elif Value
[0] == 'L':
2287 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2288 elif Value
[0] == '{':
2289 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2291 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2292 return Pcds
.values()
2296 ## Calculate the priority value of the build option
2298 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2300 # @retval Value Priority value based on the priority list.
2302 def CalculatePriorityValue(self
, Key
):
2303 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2304 PriorityValue
= 0x11111
2305 if Target
== TAB_STAR
:
2306 PriorityValue
&= 0x01111
2307 if ToolChain
== TAB_STAR
:
2308 PriorityValue
&= 0x10111
2309 if Arch
== TAB_STAR
:
2310 PriorityValue
&= 0x11011
2311 if CommandType
== TAB_STAR
:
2312 PriorityValue
&= 0x11101
2313 if Attr
== TAB_STAR
:
2314 PriorityValue
&= 0x11110
2316 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2319 ## Expand * in build option key
2321 # @param Options Options to be expanded
2322 # @param ToolDef Use specified ToolDef instead of full version.
2323 # This is needed during initialization to prevent
2324 # infinite recursion betweeh BuildOptions,
2325 # ToolDefinition, and this function.
2327 # @retval options Options expanded
2329 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
2331 ToolDef
= self
.ToolDefinition
2338 # Construct a list contain the build options which need override.
2342 # Key[0] -- tool family
2343 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2345 if (Key
[0] == self
.BuildRuleFamily
and
2346 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2347 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2348 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
2349 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
2350 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
2351 Options
[Key
].startswith("="):
2353 if OverrideList
.get(Key
[1]) is not None:
2354 OverrideList
.pop(Key
[1])
2355 OverrideList
[Key
[1]] = Options
[Key
]
2358 # Use the highest priority value.
2360 if (len(OverrideList
) >= 2):
2361 KeyList
= OverrideList
.keys()
2362 for Index
in range(len(KeyList
)):
2363 NowKey
= KeyList
[Index
]
2364 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2365 for Index1
in range(len(KeyList
) - Index
- 1):
2366 NextKey
= KeyList
[Index1
+ Index
+ 1]
2368 # Compare two Key, if one is included by another, choose the higher priority one
2370 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2371 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
2372 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
2373 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
2374 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
2375 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
2377 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2378 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2379 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2381 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2382 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2385 if ModuleStyle
is not None and len (Key
) > 2:
2386 # Check Module style is EDK or EDKII.
2387 # Only append build option for the matched style module.
2388 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2390 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2393 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2394 # if tool chain family doesn't match, skip it
2395 if Tool
in ToolDef
and Family
!= "":
2396 FamilyIsNull
= False
2397 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2398 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2400 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2403 # expand any wildcard
2404 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2405 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2406 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2407 if Tool
not in BuildOptions
:
2408 BuildOptions
[Tool
] = {}
2409 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2410 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2412 # append options for the same tool except PATH
2414 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2416 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2417 # Build Option Family has been checked, which need't to be checked again for family.
2418 if FamilyMatch
or FamilyIsNull
:
2422 if ModuleStyle
is not None and len (Key
) > 2:
2423 # Check Module style is EDK or EDKII.
2424 # Only append build option for the matched style module.
2425 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2427 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2430 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2431 # if tool chain family doesn't match, skip it
2432 if Tool
not in ToolDef
or Family
== "":
2434 # option has been added before
2435 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2438 # expand any wildcard
2439 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2440 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2441 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2442 if Tool
not in BuildOptions
:
2443 BuildOptions
[Tool
] = {}
2444 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2445 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2447 # append options for the same tool except PATH
2449 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2451 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2454 ## Append build options in platform to a module
2456 # @param Module The module to which the build options will be appened
2458 # @retval options The options appended with build options in platform
2460 def ApplyBuildOption(self
, Module
):
2461 # Get the different options for the different style module
2462 PlatformOptions
= self
.EdkIIBuildOption
2463 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2464 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2465 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2466 if Module
in self
.Platform
.Modules
:
2467 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2468 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2470 PlatformModuleOptions
= {}
2472 BuildRuleOrder
= None
2473 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2474 for Tool
in Options
:
2475 for Attr
in Options
[Tool
]:
2476 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2477 BuildRuleOrder
= Options
[Tool
][Attr
]
2479 AllTools
= set(ModuleOptions
.keys() + PlatformOptions
.keys() +
2480 PlatformModuleOptions
.keys() + ModuleTypeOptions
.keys() +
2481 self
.ToolDefinition
.keys())
2482 BuildOptions
= defaultdict(lambda: defaultdict(str))
2483 for Tool
in AllTools
:
2484 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2485 if Tool
not in Options
:
2487 for Attr
in Options
[Tool
]:
2489 # Do not generate it in Makefile
2491 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2493 Value
= Options
[Tool
][Attr
]
2494 # check if override is indicated
2495 if Value
.startswith('='):
2496 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2499 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2501 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2503 return BuildOptions
, BuildRuleOrder
2506 # extend lists contained in a dictionary with lists stored in another dictionary
2507 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
2509 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
2510 for Key
in CopyFromDict
:
2511 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
2513 # Create a directory specified by a set of path elements and return the full path
2514 def _MakeDir(PathList
):
2515 RetVal
= path
.join(*PathList
)
2516 CreateDirectory(RetVal
)
2519 ## ModuleAutoGen class
2521 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2522 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2523 # to the [depex] section in module's inf file.
2525 class ModuleAutoGen(AutoGen
):
2526 # call super().__init__ then call the worker function with different parameter count
2527 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2528 if not hasattr(self
, "_Init"):
2529 super(ModuleAutoGen
, self
).__init
__(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2530 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2533 ## Cache the timestamps of metafiles of every module in a class attribute
2537 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2538 # check if this module is employed by active platform
2539 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2540 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2543 return super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2545 ## Initialize ModuleAutoGen
2547 # @param Workspace EdkIIWorkspaceBuild object
2548 # @param ModuleFile The path of module file
2549 # @param Target Build target (DEBUG, RELEASE)
2550 # @param Toolchain Name of tool chain
2551 # @param Arch The arch the module supports
2552 # @param PlatformFile Platform meta-file
2554 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2555 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2556 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2558 self
.Workspace
= Workspace
2559 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2560 self
.MetaFile
= ModuleFile
2561 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2563 self
.SourceDir
= self
.MetaFile
.SubDir
2564 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2566 self
.SourceOverrideDir
= None
2567 # use overrided path defined in DSC file
2568 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2569 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2571 self
.ToolChain
= Toolchain
2572 self
.BuildTarget
= Target
2574 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2575 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2577 self
.IsCodeFileCreated
= False
2578 self
.IsAsBuiltInfCreated
= False
2579 self
.DepexGenerated
= False
2581 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2582 self
.BuildRuleOrder
= None
2585 self
._PcdComments
= OrderedListDict()
2586 self
._GuidComments
= OrderedListDict()
2587 self
._ProtocolComments
= OrderedListDict()
2588 self
._PpiComments
= OrderedListDict()
2589 self
._BuildTargets
= None
2590 self
._IntroBuildTargetList
= None
2591 self
._FinalBuildTargetList
= None
2592 self
._FileTypes
= None
2594 self
.AutoGenDepSet
= set()
2595 self
.ReferenceModules
= []
2600 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2602 # Get FixedAtBuild Pcds of this Module
2604 def FixedAtBuildPcds(self
):
2606 for Pcd
in self
.ModulePcdList
:
2607 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2609 if Pcd
not in RetVal
:
2614 def FixedVoidTypePcds(self
):
2616 for Pcd
in self
.FixedAtBuildPcds
:
2617 if Pcd
.DatumType
== TAB_VOID
:
2618 if '{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) not in RetVal
:
2619 RetVal
['{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)] = Pcd
.DefaultValue
2623 def UniqueBaseName(self
):
2624 BaseName
= self
.Name
2625 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2626 if Module
.MetaFile
== self
.MetaFile
:
2628 if Module
.Name
== self
.Name
:
2629 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2630 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2631 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2632 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2635 # Macros could be used in build_rule.txt (also Makefile)
2638 return OrderedDict((
2639 ("WORKSPACE" ,self
.WorkspaceDir
),
2640 ("MODULE_NAME" ,self
.Name
),
2641 ("MODULE_NAME_GUID" ,self
.UniqueBaseName
),
2642 ("MODULE_GUID" ,self
.Guid
),
2643 ("MODULE_VERSION" ,self
.Version
),
2644 ("MODULE_TYPE" ,self
.ModuleType
),
2645 ("MODULE_FILE" ,str(self
.MetaFile
)),
2646 ("MODULE_FILE_BASE_NAME" ,self
.MetaFile
.BaseName
),
2647 ("MODULE_RELATIVE_DIR" ,self
.SourceDir
),
2648 ("MODULE_DIR" ,self
.SourceDir
),
2649 ("BASE_NAME" ,self
.Name
),
2650 ("ARCH" ,self
.Arch
),
2651 ("TOOLCHAIN" ,self
.ToolChain
),
2652 ("TOOLCHAIN_TAG" ,self
.ToolChain
),
2653 ("TOOL_CHAIN_TAG" ,self
.ToolChain
),
2654 ("TARGET" ,self
.BuildTarget
),
2655 ("BUILD_DIR" ,self
.PlatformInfo
.BuildDir
),
2656 ("BIN_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2657 ("LIB_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2658 ("MODULE_BUILD_DIR" ,self
.BuildDir
),
2659 ("OUTPUT_DIR" ,self
.OutputDir
),
2660 ("DEBUG_DIR" ,self
.DebugDir
),
2661 ("DEST_DIR_OUTPUT" ,self
.OutputDir
),
2662 ("DEST_DIR_DEBUG" ,self
.DebugDir
),
2663 ("PLATFORM_NAME" ,self
.PlatformInfo
.Name
),
2664 ("PLATFORM_GUID" ,self
.PlatformInfo
.Guid
),
2665 ("PLATFORM_VERSION" ,self
.PlatformInfo
.Version
),
2666 ("PLATFORM_RELATIVE_DIR" ,self
.PlatformInfo
.SourceDir
),
2667 ("PLATFORM_DIR" ,mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)),
2668 ("PLATFORM_OUTPUT_DIR" ,self
.PlatformInfo
.OutputDir
),
2669 ("FFS_OUTPUT_DIR" ,self
.FfsOutputDir
)
2672 ## Return the module build data object
2675 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2677 ## Return the module name
2680 return self
.Module
.BaseName
2682 ## Return the module DxsFile if exist
2685 return self
.Module
.DxsFile
2687 ## Return the module meta-file GUID
2691 # To build same module more than once, the module path with FILE_GUID overridden has
2692 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path
2693 # in DSC. The overridden GUID can be retrieved from file name
2695 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2697 # Length of GUID is 36
2699 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2700 return self
.Module
.Guid
2702 ## Return the module version
2705 return self
.Module
.Version
2707 ## Return the module type
2709 def ModuleType(self
):
2710 return self
.Module
.ModuleType
2712 ## Return the component type (for Edk.x style of module)
2714 def ComponentType(self
):
2715 return self
.Module
.ComponentType
2717 ## Return the build type
2719 def BuildType(self
):
2720 return self
.Module
.BuildType
2722 ## Return the PCD_IS_DRIVER setting
2724 def PcdIsDriver(self
):
2725 return self
.Module
.PcdIsDriver
2727 ## Return the autogen version, i.e. module meta-file version
2729 def AutoGenVersion(self
):
2730 return self
.Module
.AutoGenVersion
2732 ## Check if the module is library or not
2734 def IsLibrary(self
):
2735 return bool(self
.Module
.LibraryClass
)
2737 ## Check if the module is binary module or not
2739 def IsBinaryModule(self
):
2740 return self
.Module
.IsBinaryModule
2742 ## Return the directory to store intermediate files of the module
2746 self
.PlatformInfo
.BuildDir
,
2749 self
.MetaFile
.BaseName
2752 ## Return the directory to store the intermediate object files of the mdoule
2754 def OutputDir(self
):
2755 return _MakeDir((self
.BuildDir
, "OUTPUT"))
2757 ## Return the directory path to store ffs file
2759 def FfsOutputDir(self
):
2760 if GlobalData
.gFdfParser
:
2761 return path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2764 ## Return the directory to store auto-gened source files of the mdoule
2767 return _MakeDir((self
.BuildDir
, "DEBUG"))
2769 ## Return the path of custom file
2771 def CustomMakefile(self
):
2773 for Type
in self
.Module
.CustomMakefile
:
2774 MakeType
= gMakeTypeMap
[Type
] if Type
in gMakeTypeMap
else 'nmake'
2775 if self
.SourceOverrideDir
is not None:
2776 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2777 if not os
.path
.exists(File
):
2778 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2780 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2781 RetVal
[MakeType
] = File
2784 ## Return the directory of the makefile
2786 # @retval string The directory string of module's makefile
2789 def MakeFileDir(self
):
2790 return self
.BuildDir
2792 ## Return build command string
2794 # @retval string Build command string
2797 def BuildCommand(self
):
2798 return self
.PlatformInfo
.BuildCommand
2800 ## Get object list of all packages the module and its dependent libraries belong to
2802 # @retval list The list of package object
2805 def DerivedPackageList(self
):
2807 for M
in [self
.Module
] + self
.DependentLibraryList
:
2808 for Package
in M
.Packages
:
2809 if Package
in PackageList
:
2811 PackageList
.append(Package
)
2814 ## Get the depex string
2816 # @return : a string contain all depex expresion.
2817 def _GetDepexExpresionString(self
):
2820 ## DPX_SOURCE IN Define section.
2821 if self
.Module
.DxsFile
:
2823 for M
in [self
.Module
] + self
.DependentLibraryList
:
2824 Filename
= M
.MetaFile
.Path
2825 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2826 DepexExpresionList
= InfObj
.GetDepexExpresionList()
2827 for DepexExpresion
in DepexExpresionList
:
2828 for key
in DepexExpresion
:
2829 Arch
, ModuleType
= key
2830 DepexExpr
= [x
for x
in DepexExpresion
[key
] if not str(x
).startswith('#')]
2831 # the type of build module is USER_DEFINED.
2832 # All different DEPEX section tags would be copied into the As Built INF file
2833 # and there would be separate DEPEX section tags
2834 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2835 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2836 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2838 if Arch
.upper() == TAB_ARCH_COMMON
or \
2839 (Arch
.upper() == self
.Arch
.upper() and \
2840 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2841 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2843 #the type of build module is USER_DEFINED.
2844 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2845 for Depex
in DepexList
:
2847 DepexStr
+= '[Depex.%s.%s]\n' % key
2848 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
2851 return '[Depex.%s]\n' % self
.Arch
2854 #the type of build module not is USER_DEFINED.
2856 for Depex
in DepexList
:
2861 for D
in Depex
.values():
2862 DepexStr
+= ' '.join(val
for val
in D
)
2863 Index
= DepexStr
.find('END')
2864 if Index
> -1 and Index
== len(DepexStr
) - 3:
2865 DepexStr
= DepexStr
[:-3]
2866 DepexStr
= DepexStr
.strip()
2869 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2871 return '[Depex.%s]\n' % self
.Arch
2872 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2874 ## Merge dependency expression
2876 # @retval list The token list of the dependency expression after parsed
2879 def DepexList(self
):
2880 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2885 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2887 for M
in [self
.Module
] + self
.DependentLibraryList
:
2889 for D
in M
.Depex
[self
.Arch
, self
.ModuleType
]:
2891 DepexList
.append('AND')
2892 DepexList
.append('(')
2893 #replace D with value if D is FixedAtBuild PCD
2897 NewList
.append(item
)
2899 if item
not in self
.FixedVoidTypePcds
:
2900 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
2902 Value
= self
.FixedVoidTypePcds
[item
]
2903 if len(Value
.split(',')) != 16:
2904 EdkLogger
.error("build", FORMAT_INVALID
,
2905 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
2906 NewList
.append(Value
)
2907 DepexList
.extend(NewList
)
2908 if DepexList
[-1] == 'END': # no need of a END at this time
2910 DepexList
.append(')')
2913 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2914 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2916 if len(DepexList
) > 0:
2917 EdkLogger
.verbose('')
2918 return {self
.ModuleType
:DepexList
}
2920 ## Merge dependency expression
2922 # @retval list The token list of the dependency expression after parsed
2925 def DepexExpressionDict(self
):
2926 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2929 DepexExpressionString
= ''
2931 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2933 for M
in [self
.Module
] + self
.DependentLibraryList
:
2935 for D
in M
.DepexExpression
[self
.Arch
, self
.ModuleType
]:
2936 if DepexExpressionString
!= '':
2937 DepexExpressionString
+= ' AND '
2938 DepexExpressionString
+= '('
2939 DepexExpressionString
+= D
2940 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
2941 DepexExpressionString
+= ')'
2944 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
2945 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
2947 if len(DepexExpressionString
) > 0:
2948 EdkLogger
.verbose('')
2950 return {self
.ModuleType
:DepexExpressionString
}
2952 # Get the tiano core user extension, it is contain dependent library.
2953 # @retval: a list contain tiano core userextension.
2955 def _GetTianoCoreUserExtensionList(self
):
2956 TianoCoreUserExtentionList
= []
2957 for M
in [self
.Module
] + self
.DependentLibraryList
:
2958 Filename
= M
.MetaFile
.Path
2959 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2960 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
2961 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
2962 for Section
in TianoCoreUserExtent
:
2963 ItemList
= Section
.split(TAB_SPLIT
)
2965 if len(ItemList
) == 4:
2967 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
2969 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
2970 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
2971 TianoCoreList
.append('\n')
2972 TianoCoreUserExtentionList
.append(TianoCoreList
)
2974 return TianoCoreUserExtentionList
2976 ## Return the list of specification version required for the module
2978 # @retval list The list of specification defined in module file
2981 def Specification(self
):
2982 return self
.Module
.Specification
2984 ## Tool option for the module build
2986 # @param PlatformInfo The object of PlatformBuildInfo
2987 # @retval dict The dict containing valid options
2990 def BuildOption(self
):
2991 RetVal
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2992 if self
.BuildRuleOrder
:
2993 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
2996 ## Get include path list from tool option for the module build
2998 # @retval list The include path list
3001 def BuildOptionIncPathList(self
):
3003 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3004 # is the former use /I , the Latter used -I to specify include directories
3006 if self
.PlatformInfo
.ToolChainFamily
in (TAB_COMPILER_MSFT
):
3007 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3008 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3009 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3012 # New ToolChainFamily, don't known whether there is option to specify include directories
3017 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3019 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
3023 if self
.ToolChainFamily
!= 'RVCT':
3024 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3027 # RVCT may specify a list of directory seperated by commas
3030 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3031 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3032 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
3035 # EDK II modules must not reference header files outside of the packages they depend on or
3036 # within the module's directory tree. Report error if violation.
3038 for Path
in IncPathList
:
3039 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3040 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3041 EdkLogger
.error("build",
3044 File
=str(self
.MetaFile
))
3045 RetVal
+= IncPathList
3048 ## Return a list of files which can be built from source
3050 # What kind of files can be built is determined by build rules in
3051 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3054 def SourceFileList(self
):
3056 ToolChainTagSet
= {"", TAB_STAR
, self
.ToolChain
}
3057 ToolChainFamilySet
= {"", TAB_STAR
, self
.ToolChainFamily
, self
.BuildRuleFamily
}
3058 for F
in self
.Module
.Sources
:
3060 if F
.TagName
not in ToolChainTagSet
:
3061 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3062 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
3064 # match tool chain family or build rule family
3065 if F
.ToolChainFamily
not in ToolChainFamilySet
:
3068 "The file [%s] must be built by tools of [%s], " \
3069 "but current toolchain family is [%s], buildrule family is [%s]" \
3070 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3073 # add the file path into search path list for file including
3074 if F
.Dir
not in self
.IncludePathList
:
3075 self
.IncludePathList
.insert(0, F
.Dir
)
3078 self
._MatchBuildRuleOrder
(RetVal
)
3081 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3084 def _MatchBuildRuleOrder(self
, FileList
):
3087 for SingleFile
in FileList
:
3088 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3089 key
= SingleFile
.Path
.rsplit(SingleFile
.Ext
,1)[0]
3090 if key
in Order_Dict
:
3091 Order_Dict
[key
].append(SingleFile
.Ext
)
3093 Order_Dict
[key
] = [SingleFile
.Ext
]
3096 for F
in Order_Dict
:
3097 if len(Order_Dict
[F
]) > 1:
3098 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3099 for Ext
in Order_Dict
[F
][1:]:
3100 RemoveList
.append(F
+ Ext
)
3102 for item
in RemoveList
:
3103 FileList
.remove(item
)
3107 ## Return the list of unicode files
3109 def UnicodeFileList(self
):
3110 return self
.FileTypes
.get(TAB_UNICODE_FILE
,[])
3112 ## Return the list of vfr files
3114 def VfrFileList(self
):
3115 return self
.FileTypes
.get(TAB_VFR_FILE
, [])
3117 ## Return the list of Image Definition files
3119 def IdfFileList(self
):
3120 return self
.FileTypes
.get(TAB_IMAGE_FILE
,[])
3122 ## Return a list of files which can be built from binary
3124 # "Build" binary files are just to copy them to build directory.
3126 # @retval list The list of files which can be built later
3129 def BinaryFileList(self
):
3131 for F
in self
.Module
.Binaries
:
3132 if F
.Target
not in [TAB_ARCH_COMMON
, TAB_STAR
] and F
.Target
!= self
.BuildTarget
:
3135 self
._ApplyBuildRule
(F
, F
.Type
, BinaryFileList
=RetVal
)
3139 def BuildRules(self
):
3141 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3142 for Type
in BuildRuleDatabase
.FileTypeList
:
3143 #first try getting build rule by BuildRuleFamily
3144 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3146 # build type is always module type, but ...
3147 if self
.ModuleType
!= self
.BuildType
:
3148 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3149 #second try getting build rule by ToolChainFamily
3151 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3153 # build type is always module type, but ...
3154 if self
.ModuleType
!= self
.BuildType
:
3155 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3158 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3159 RetVal
[Type
] = RuleObject
3160 for Ext
in RuleObject
.SourceFileExtList
:
3161 RetVal
[Ext
] = RuleObject
3164 def _ApplyBuildRule(self
, File
, FileType
, BinaryFileList
=None):
3165 if self
._BuildTargets
is None:
3166 self
._IntroBuildTargetList
= set()
3167 self
._FinalBuildTargetList
= set()
3168 self
._BuildTargets
= defaultdict(set)
3169 self
._FileTypes
= defaultdict(set)
3171 if not BinaryFileList
:
3172 BinaryFileList
= self
.BinaryFileList
3174 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3175 if not os
.path
.exists(SubDirectory
):
3176 CreateDirectory(SubDirectory
)
3182 # Make sure to get build rule order value
3186 while Index
< len(SourceList
):
3187 Source
= SourceList
[Index
]
3191 CreateDirectory(Source
.Dir
)
3193 if File
.IsBinary
and File
== Source
and File
in BinaryFileList
:
3194 # Skip all files that are not binary libraries
3195 if not self
.IsLibrary
:
3197 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3198 elif FileType
in self
.BuildRules
:
3199 RuleObject
= self
.BuildRules
[FileType
]
3200 elif Source
.Ext
in self
.BuildRules
:
3201 RuleObject
= self
.BuildRules
[Source
.Ext
]
3203 # stop at no more rules
3205 self
._FinalBuildTargetList
.add(LastTarget
)
3208 FileType
= RuleObject
.SourceFileType
3209 self
._FileTypes
[FileType
].add(Source
)
3211 # stop at STATIC_LIBRARY for library
3212 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3214 self
._FinalBuildTargetList
.add(LastTarget
)
3217 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3220 self
._FinalBuildTargetList
.add(LastTarget
)
3222 elif not Target
.Outputs
:
3223 # Only do build for target with outputs
3224 self
._FinalBuildTargetList
.add(Target
)
3226 self
._BuildTargets
[FileType
].add(Target
)
3228 if not Source
.IsBinary
and Source
== File
:
3229 self
._IntroBuildTargetList
.add(Target
)
3231 # to avoid cyclic rule
3232 if FileType
in RuleChain
:
3235 RuleChain
.add(FileType
)
3236 SourceList
.extend(Target
.Outputs
)
3238 FileType
= TAB_UNKNOWN_FILE
3242 if self
._BuildTargets
is None:
3243 self
._IntroBuildTargetList
= set()
3244 self
._FinalBuildTargetList
= set()
3245 self
._BuildTargets
= defaultdict(set)
3246 self
._FileTypes
= defaultdict(set)
3248 #TRICK: call SourceFileList property to apply build rule for source files
3251 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3254 return self
._BuildTargets
3257 def IntroTargetList(self
):
3259 return self
._IntroBuildTargetList
3262 def CodaTargetList(self
):
3264 return self
._FinalBuildTargetList
3267 def FileTypes(self
):
3269 return self
._FileTypes
3271 ## Get the list of package object the module depends on
3273 # @retval list The package object list
3276 def DependentPackageList(self
):
3277 return self
.Module
.Packages
3279 ## Return the list of auto-generated code file
3281 # @retval list The list of auto-generated file
3284 def AutoGenFileList(self
):
3285 AutoGenUniIdf
= self
.BuildType
!= 'UEFI_HII'
3286 UniStringBinBuffer
= BytesIO()
3287 IdfGenBinBuffer
= BytesIO()
3289 AutoGenC
= TemplateString()
3290 AutoGenH
= TemplateString()
3291 StringH
= TemplateString()
3292 StringIdf
= TemplateString()
3293 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, AutoGenUniIdf
, UniStringBinBuffer
, StringIdf
, AutoGenUniIdf
, IdfGenBinBuffer
)
3295 # AutoGen.c is generated if there are library classes in inf, or there are object files
3297 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3298 or TAB_OBJECT_FILE
in self
.FileTypes
):
3299 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3300 RetVal
[AutoFile
] = str(AutoGenC
)
3301 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3302 if str(AutoGenH
) != "":
3303 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3304 RetVal
[AutoFile
] = str(AutoGenH
)
3305 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3306 if str(StringH
) != "":
3307 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3308 RetVal
[AutoFile
] = str(StringH
)
3309 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3310 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != "":
3311 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3312 RetVal
[AutoFile
] = UniStringBinBuffer
.getvalue()
3313 AutoFile
.IsBinary
= True
3314 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3315 if UniStringBinBuffer
is not None:
3316 UniStringBinBuffer
.close()
3317 if str(StringIdf
) != "":
3318 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3319 RetVal
[AutoFile
] = str(StringIdf
)
3320 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3321 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != "":
3322 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3323 RetVal
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3324 AutoFile
.IsBinary
= True
3325 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3326 if IdfGenBinBuffer
is not None:
3327 IdfGenBinBuffer
.close()
3330 ## Return the list of library modules explicitly or implicityly used by this module
3332 def DependentLibraryList(self
):
3333 # only merge library classes and PCD for non-library module
3336 return self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3338 ## Get the list of PCDs from current module
3340 # @retval list The list of PCD
3343 def ModulePcdList(self
):
3344 # apply PCD settings from platform
3345 RetVal
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3346 ExtendCopyDictionaryLists(self
._PcdComments
, self
.Module
.PcdComments
)
3349 ## Get the list of PCDs from dependent libraries
3351 # @retval list The list of PCD
3354 def LibraryPcdList(self
):
3359 # get PCDs from dependent libraries
3360 for Library
in self
.DependentLibraryList
:
3361 PcdsInLibrary
= OrderedDict()
3362 ExtendCopyDictionaryLists(self
._PcdComments
, Library
.PcdComments
)
3363 for Key
in Library
.Pcds
:
3364 # skip duplicated PCDs
3365 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3368 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3369 RetVal
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3372 ## Get the GUID value mapping
3374 # @retval dict The mapping between GUID cname and its value
3378 RetVal
= OrderedDict(self
.Module
.Guids
)
3379 for Library
in self
.DependentLibraryList
:
3380 RetVal
.update(Library
.Guids
)
3381 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
3382 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
3386 def GetGuidsUsedByPcd(self
):
3387 RetVal
= OrderedDict(self
.Module
.GetGuidsUsedByPcd())
3388 for Library
in self
.DependentLibraryList
:
3389 RetVal
.update(Library
.GetGuidsUsedByPcd())
3391 ## Get the protocol value mapping
3393 # @retval dict The mapping between protocol cname and its value
3396 def ProtocolList(self
):
3397 RetVal
= OrderedDict(self
.Module
.Protocols
)
3398 for Library
in self
.DependentLibraryList
:
3399 RetVal
.update(Library
.Protocols
)
3400 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
3401 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3404 ## Get the PPI value mapping
3406 # @retval dict The mapping between PPI cname and its value
3410 RetVal
= OrderedDict(self
.Module
.Ppis
)
3411 for Library
in self
.DependentLibraryList
:
3412 RetVal
.update(Library
.Ppis
)
3413 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
3414 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
3417 ## Get the list of include search path
3419 # @retval list The list path
3422 def IncludePathList(self
):
3424 RetVal
.append(self
.MetaFile
.Dir
)
3425 RetVal
.append(self
.DebugDir
)
3427 for Package
in self
.Module
.Packages
:
3428 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3429 if PackageDir
not in RetVal
:
3430 RetVal
.append(PackageDir
)
3431 IncludesList
= Package
.Includes
3432 if Package
._PrivateIncludes
:
3433 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3434 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3435 for Inc
in IncludesList
:
3436 if Inc
not in RetVal
:
3437 RetVal
.append(str(Inc
))
3441 def IncludePathLength(self
):
3442 return sum(len(inc
)+1 for inc
in self
.IncludePathList
)
3444 ## Get HII EX PCDs which maybe used by VFR
3446 # efivarstore used by VFR may relate with HII EX PCDs
3447 # Get the variable name and GUID from efivarstore and HII EX PCD
3448 # List the HII EX PCDs in As Built INF if both name and GUID match.
3450 # @retval list HII EX PCDs
3452 def _GetPcdsMaybeUsedByVfr(self
):
3453 if not self
.SourceFileList
:
3457 for SrcFile
in self
.SourceFileList
:
3458 if SrcFile
.Ext
.lower() != '.vfr':
3460 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3461 if not os
.path
.exists(Vfri
):
3463 VfriFile
= open(Vfri
, 'r')
3464 Content
= VfriFile
.read()
3466 Pos
= Content
.find('efivarstore')
3469 # Make sure 'efivarstore' is the start of efivarstore statement
3470 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3473 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3475 if Index
>= 0 and Content
[Index
] != ';':
3476 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3479 # 'efivarstore' must be followed by name and guid
3481 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3484 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3487 NameArray
= _ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3488 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3489 Pos
= Content
.find('efivarstore', Name
.end())
3493 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3494 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3496 for SkuInfo
in Pcd
.SkuInfoList
.values():
3497 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3500 Name
= _ConvertStringToByteArray(SkuInfo
.VariableName
)
3501 Guid
= GuidStructureStringToGuidString(Value
)
3502 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3503 HiiExPcds
.append(Pcd
)
3508 def _GenOffsetBin(self
):
3510 for SourceFile
in self
.Module
.Sources
:
3511 if SourceFile
.Type
.upper() == ".VFR" :
3513 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3515 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3516 elif SourceFile
.Type
.upper() == ".UNI" :
3518 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3520 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3522 if not VfrUniBaseName
:
3524 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3525 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3526 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, VfrUniBaseName
.values())
3527 if not VfrUniOffsetList
:
3530 OutputName
= '%sOffset.bin' % self
.Name
3531 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3534 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3536 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
3538 # Use a instance of BytesIO to cache data
3539 fStringIO
= BytesIO('')
3541 for Item
in VfrUniOffsetList
:
3542 if (Item
[0].find("Strings") != -1):
3544 # UNI offset in image.
3546 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3548 UniGuid
= [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]
3549 UniGuid
= [chr(ItemGuid
) for ItemGuid
in UniGuid
]
3550 fStringIO
.write(''.join(UniGuid
))
3551 UniValue
= pack ('Q', int (Item
[1], 16))
3552 fStringIO
.write (UniValue
)
3555 # VFR binary offset in image.
3557 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3559 VfrGuid
= [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]
3560 VfrGuid
= [chr(ItemGuid
) for ItemGuid
in VfrGuid
]
3561 fStringIO
.write(''.join(VfrGuid
))
3562 VfrValue
= pack ('Q', int (Item
[1], 16))
3563 fStringIO
.write (VfrValue
)
3565 # write data into file.
3568 fInputfile
.write (fStringIO
.getvalue())
3570 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3571 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
3577 ## Create AsBuilt INF file the module
3579 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3580 self
.OutputFile
= set()
3581 if IsOnlyCopy
and GlobalData
.gBinCacheDest
:
3582 self
.CopyModuleToCache()
3585 if self
.IsAsBuiltInfCreated
:
3588 # Skip the following code for libraries
3592 # Skip the following code for modules with no source files
3593 if not self
.SourceFileList
:
3596 # Skip the following code for modules without any binary files
3597 if self
.BinaryFileList
:
3600 ### TODO: How to handles mixed source and binary modules
3602 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3603 # Also find all packages that the DynamicEx PCDs depend on
3608 PcdTokenSpaceList
= []
3609 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3610 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3611 PatchablePcds
.append(Pcd
)
3612 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3613 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3616 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3617 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3618 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3619 GuidList
= OrderedDict(self
.GuidList
)
3620 for TokenSpace
in self
.GetGuidsUsedByPcd
:
3621 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3622 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3623 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3624 GuidList
.pop(TokenSpace
)
3625 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3626 for Package
in self
.DerivedPackageList
:
3627 if Package
in Packages
:
3629 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3631 for Index
in range(len(BeChecked
)):
3632 for Item
in CheckList
[Index
]:
3633 if Item
in BeChecked
[Index
]:
3634 Packages
.append(Package
)
3640 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3641 for Pkg
in self
.PlatformInfo
.PackageList
:
3644 for VfrPcd
in VfrPcds
:
3645 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3646 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3647 Packages
.append(Pkg
)
3650 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
3651 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
3653 MDefs
= self
.Module
.Defines
3656 'module_name' : self
.Name
,
3657 'module_guid' : Guid
,
3658 'module_module_type' : ModuleType
,
3659 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3660 'pcd_is_driver_string' : [],
3661 'module_uefi_specification_version' : [],
3662 'module_pi_specification_version' : [],
3663 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3664 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3665 'module_constructor' : self
.Module
.ConstructorList
,
3666 'module_destructor' : self
.Module
.DestructorList
,
3667 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3668 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3669 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3670 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3671 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3672 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3673 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3674 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3675 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3676 'module_arch' : self
.Arch
,
3677 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
3679 'patchablepcd_item' : [],
3681 'protocol_item' : [],
3685 'libraryclasses_item' : []
3688 if 'MODULE_UNI_FILE' in MDefs
:
3689 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3690 if os
.path
.isfile(UNIFile
):
3691 shutil
.copy2(UNIFile
, self
.OutputDir
)
3693 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3694 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3696 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3699 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
3701 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3702 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
3703 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3704 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
3706 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3707 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3708 for Item
in self
.CodaTargetList
:
3709 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3710 self
.OutputFile
.add(File
)
3711 if os
.path
.isabs(File
):
3712 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3713 if Item
.Target
.Ext
.lower() == '.aml':
3714 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
3715 elif Item
.Target
.Ext
.lower() == '.acpi':
3716 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
3717 elif Item
.Target
.Ext
.lower() == '.efi':
3718 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
3720 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
3721 if not self
.DepexGenerated
:
3722 DepexFile
= os
.path
.join(self
.OutputDir
, self
.Name
+ '.depex')
3723 if os
.path
.exists(DepexFile
):
3724 self
.DepexGenerated
= True
3725 if self
.DepexGenerated
:
3726 self
.OutputFile
.add(self
.Name
+ '.depex')
3727 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3728 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
3729 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3730 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
3731 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3732 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
3734 Bin
= self
._GenOffsetBin
()
3736 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
3737 self
.OutputFile
.add(Bin
)
3739 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3741 if File
.lower().endswith('.pdb'):
3742 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
3743 self
.OutputFile
.add(File
)
3744 HeaderComments
= self
.Module
.HeaderComments
3746 for Index
in range(len(HeaderComments
)):
3747 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3748 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3751 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3752 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3755 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3756 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3757 (GuidList
, self
._GuidComments
, 'guid_item')
3759 for Item
in GenList
:
3760 for CName
in Item
[0]:
3761 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
3762 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
3763 AsBuiltInfDict
[Item
[2]].append(Entry
)
3764 PatchList
= parsePcdInfoFromMapFile(
3765 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3766 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3769 for Pcd
in PatchablePcds
:
3770 TokenCName
= Pcd
.TokenCName
3771 for PcdItem
in GlobalData
.MixedPcd
:
3772 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3773 TokenCName
= PcdItem
[0]
3775 for PatchPcd
in PatchList
:
3776 if TokenCName
== PatchPcd
[0]:
3781 if Pcd
.DatumType
== 'BOOLEAN':
3782 BoolValue
= Pcd
.DefaultValue
.upper()
3783 if BoolValue
== 'TRUE':
3784 Pcd
.DefaultValue
= '1'
3785 elif BoolValue
== 'FALSE':
3786 Pcd
.DefaultValue
= '0'
3788 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3789 HexFormat
= '0x%02x'
3790 if Pcd
.DatumType
== TAB_UINT16
:
3791 HexFormat
= '0x%04x'
3792 elif Pcd
.DatumType
== TAB_UINT32
:
3793 HexFormat
= '0x%08x'
3794 elif Pcd
.DatumType
== TAB_UINT64
:
3795 HexFormat
= '0x%016x'
3796 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3798 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
3799 EdkLogger
.error("build", AUTOGEN_ERROR
,
3800 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3802 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3803 PcdValue
= Pcd
.DefaultValue
3804 if PcdValue
[0] != '{':
3806 if PcdValue
[0] == 'L':
3808 PcdValue
= PcdValue
.lstrip('L')
3809 PcdValue
= eval(PcdValue
)
3811 for Index
in range(0, len(PcdValue
)):
3813 CharVal
= ord(PcdValue
[Index
])
3814 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3815 + '0x%02x' % (CharVal
>> 8) + ', '
3817 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3820 Padding
= Padding
* 2
3821 ArraySize
= ArraySize
/ 2
3822 if ArraySize
< (len(PcdValue
) + 1):
3823 if Pcd
.MaxSizeUserSet
:
3824 EdkLogger
.error("build", AUTOGEN_ERROR
,
3825 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3828 ArraySize
= len(PcdValue
) + 1
3829 if ArraySize
> len(PcdValue
) + 1:
3830 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3831 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3832 elif len(PcdValue
.split(',')) <= ArraySize
:
3833 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3836 if Pcd
.MaxSizeUserSet
:
3837 EdkLogger
.error("build", AUTOGEN_ERROR
,
3838 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3841 ArraySize
= len(PcdValue
) + 1
3842 PcdItem
= '%s.%s|%s|0x%X' % \
3843 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3845 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3846 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3848 PcdItem
= PcdComments
+ '\n ' + PcdItem
3849 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3851 for Pcd
in Pcds
+ VfrPcds
:
3854 TokenCName
= Pcd
.TokenCName
3855 for PcdItem
in GlobalData
.MixedPcd
:
3856 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3857 TokenCName
= PcdItem
[0]
3859 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3860 for SkuName
in Pcd
.SkuInfoList
:
3861 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3862 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3864 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3865 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3869 for Index
, Comment
in enumerate(PcdCommentList
):
3870 for Usage
in UsageList
:
3871 if Comment
.find(Usage
) != -1:
3875 if UsageIndex
!= -1:
3876 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3878 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3879 PcdComments
= '\n '.join(PcdCommentList
)
3880 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
3882 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3883 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
3884 for Item
in self
.BuildOption
:
3885 if 'FLAGS' in self
.BuildOption
[Item
]:
3886 AsBuiltInfDict
['flags_item'].append('%s:%s_%s_%s_%s_FLAGS = %s' % (self
.ToolChainFamily
, self
.BuildTarget
, self
.ToolChain
, self
.Arch
, Item
, self
.BuildOption
[Item
]['FLAGS'].strip()))
3888 # Generated LibraryClasses section in comments.
3889 for Library
in self
.LibraryAutoGenList
:
3890 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
3892 # Generated UserExtensions TianoCore section.
3893 # All tianocore user extensions are copied.
3895 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
3896 UserExtStr
+= '\n'.join(TianoCore
)
3897 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
3898 if os
.path
.isfile(ExtensionFile
):
3899 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
3900 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
3902 # Generated depex expression section in comments.
3903 DepexExpresion
= self
._GetDepexExpresionString
()
3904 AsBuiltInfDict
['depexsection_item'] = DepexExpresion
if DepexExpresion
else ''
3906 AsBuiltInf
= TemplateString()
3907 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3909 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3911 self
.IsAsBuiltInfCreated
= True
3912 if GlobalData
.gBinCacheDest
:
3913 self
.CopyModuleToCache()
3915 def CopyModuleToCache(self
):
3916 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3917 CreateDirectory (FileDir
)
3918 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
3919 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
3920 if os
.path
.exists(HashFile
):
3921 shutil
.copy2(HashFile
, FileDir
)
3922 if os
.path
.exists(ModuleFile
):
3923 shutil
.copy2(ModuleFile
, FileDir
)
3924 if not self
.OutputFile
:
3925 Ma
= self
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
3926 self
.OutputFile
= Ma
.Binaries
3928 for File
in self
.OutputFile
:
3930 if not os
.path
.isabs(File
):
3931 File
= os
.path
.join(self
.OutputDir
, File
)
3932 if os
.path
.exists(File
):
3933 shutil
.copy2(File
, FileDir
)
3935 def AttemptModuleCacheCopy(self
):
3936 if self
.IsBinaryModule
:
3938 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3939 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
3940 if os
.path
.exists(HashFile
):
3941 f
= open(HashFile
, 'r')
3942 CacheHash
= f
.read()
3944 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3945 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3946 for root
, dir, files
in os
.walk(FileDir
):
3948 if self
.Name
+ '.hash' in f
:
3949 shutil
.copy2(HashFile
, self
.BuildDir
)
3951 File
= path
.join(root
, f
)
3952 shutil
.copy2(File
, self
.OutputDir
)
3953 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
3954 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3958 ## Create makefile for the module and its dependent libraries
3960 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3961 # dependent libraries will be created
3963 @cached_class_function
3964 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
3965 # nest this function inside it's only caller.
3966 def CreateTimeStamp():
3967 FileSet
= {self
.MetaFile
.Path
}
3969 for SourceFile
in self
.Module
.Sources
:
3970 FileSet
.add (SourceFile
.Path
)
3972 for Lib
in self
.DependentLibraryList
:
3973 FileSet
.add (Lib
.MetaFile
.Path
)
3975 for f
in self
.AutoGenDepSet
:
3976 FileSet
.add (f
.Path
)
3978 if os
.path
.exists (self
.TimeStampPath
):
3979 os
.remove (self
.TimeStampPath
)
3980 with
open(self
.TimeStampPath
, 'w+') as file:
3984 # Ignore generating makefile when it is a binary module
3985 if self
.IsBinaryModule
:
3988 self
.GenFfsList
= GenFfsList
3989 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3990 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3991 LibraryAutoGen
.CreateMakeFile()
3996 if len(self
.CustomMakefile
) == 0:
3997 Makefile
= GenMake
.ModuleMakefile(self
)
3999 Makefile
= GenMake
.CustomMakefile(self
)
4000 if Makefile
.Generate():
4001 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4002 (self
.Name
, self
.Arch
))
4004 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4005 (self
.Name
, self
.Arch
))
4009 def CopyBinaryFiles(self
):
4010 for File
in self
.Module
.Binaries
:
4012 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4013 CopyLongFilePath(SrcPath
, DstPath
)
4014 ## Create autogen code for the module and its dependent libraries
4016 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4017 # dependent libraries will be created
4019 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4020 if self
.IsCodeFileCreated
:
4023 # Need to generate PcdDatabase even PcdDriver is binarymodule
4024 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4025 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4027 if self
.IsBinaryModule
:
4029 self
.CopyBinaryFiles()
4032 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4033 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4034 LibraryAutoGen
.CreateCodeFile()
4040 IgoredAutoGenList
= []
4042 for File
in self
.AutoGenFileList
:
4043 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4044 AutoGenList
.append(str(File
))
4046 IgoredAutoGenList
.append(str(File
))
4049 for ModuleType
in self
.DepexList
:
4050 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
4051 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
4054 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4055 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4057 if len(Dpx
.PostfixNotation
) != 0:
4058 self
.DepexGenerated
= True
4060 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4061 AutoGenList
.append(str(DpxFile
))
4063 IgoredAutoGenList
.append(str(DpxFile
))
4065 if IgoredAutoGenList
== []:
4066 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4067 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4068 elif AutoGenList
== []:
4069 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4070 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4072 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4073 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4075 self
.IsCodeFileCreated
= True
4078 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4080 def LibraryAutoGenList(self
):
4082 for Library
in self
.DependentLibraryList
:
4089 self
.PlatformInfo
.MetaFile
4091 if La
not in RetVal
:
4093 for Lib
in La
.CodaTargetList
:
4094 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4097 def GenModuleHash(self
):
4098 if self
.Arch
not in GlobalData
.gModuleHash
:
4099 GlobalData
.gModuleHash
[self
.Arch
] = {}
4101 # Add Platform level hash
4102 m
.update(GlobalData
.gPlatformHash
)
4103 # Add Package level hash
4104 if self
.DependentPackageList
:
4105 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4106 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4107 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
])
4110 if self
.LibraryAutoGenList
:
4111 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4112 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4114 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
])
4117 f
= open(str(self
.MetaFile
), 'r')
4121 # Add Module's source files
4122 if self
.SourceFileList
:
4123 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4124 f
= open(str(File
), 'r')
4129 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4130 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4131 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4132 if GlobalData
.gBinCacheSource
:
4133 if self
.AttemptModuleCacheCopy():
4135 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), True)
4137 ## Decide whether we can skip the ModuleAutoGen process
4138 def CanSkipbyHash(self
):
4139 if GlobalData
.gUseHashCache
:
4140 return not self
.GenModuleHash()
4143 ## Decide whether we can skip the ModuleAutoGen process
4144 # If any source file is newer than the module than we cannot skip
4147 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
4149 if not os
.path
.exists(self
.TimeStampPath
):
4151 #last creation time of the module
4152 DstTimeStamp
= os
.stat(self
.TimeStampPath
)[8]
4154 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4155 if SrcTimeStamp
> DstTimeStamp
:
4158 with
open(self
.TimeStampPath
,'r') as f
:
4160 source
= source
.rstrip('\n')
4161 if not os
.path
.exists(source
):
4163 if source
not in ModuleAutoGen
.TimeDict
:
4164 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4165 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4167 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
4171 def TimeStampPath(self
):
4172 return os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')