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
)
275 # The file path of platform file will be used to represent hash value of this object
277 # @retval int Hash value of the file path of platform file
280 return hash(self
.MetaFile
)
284 # The file path of platform file will be used to represent this object
286 # @retval string String of platform file path
289 return str(self
.MetaFile
)
292 def __eq__(self
, Other
):
293 return Other
and self
.MetaFile
== Other
295 ## Workspace AutoGen class
297 # This class is used mainly to control the whole platform build for different
298 # architecture. This class will generate top level makefile.
300 class WorkspaceAutoGen(AutoGen
):
301 # call super().__init__ then call the worker function with different parameter count
302 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
303 if not hasattr(self
, "_Init"):
304 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
307 ## Initialize WorkspaceAutoGen
309 # @param WorkspaceDir Root directory of workspace
310 # @param ActivePlatform Meta-file of active platform
311 # @param Target Build target
312 # @param Toolchain Tool chain name
313 # @param ArchList List of architecture of current build
314 # @param MetaFileDb Database containing meta-files
315 # @param BuildConfig Configuration of build
316 # @param ToolDefinition Tool chain definitions
317 # @param FlashDefinitionFile File of flash definition
318 # @param Fds FD list to be generated
319 # @param Fvs FV list to be generated
320 # @param Caps Capsule list to be generated
321 # @param SkuId SKU id from command line
323 def _InitWorker(self
, WorkspaceDir
, ActivePlatform
, Target
, Toolchain
, ArchList
, MetaFileDb
,
324 BuildConfig
, ToolDefinition
, FlashDefinitionFile
='', Fds
=None, Fvs
=None, Caps
=None, SkuId
='', UniFlag
=None,
325 Progress
=None, BuildModule
=None):
326 self
.BuildDatabase
= MetaFileDb
327 self
.MetaFile
= ActivePlatform
328 self
.WorkspaceDir
= WorkspaceDir
329 self
.Platform
= self
.BuildDatabase
[self
.MetaFile
, TAB_ARCH_COMMON
, Target
, Toolchain
]
330 GlobalData
.gActivePlatform
= self
.Platform
331 self
.BuildTarget
= Target
332 self
.ToolChain
= Toolchain
333 self
.ArchList
= ArchList
335 self
.UniFlag
= UniFlag
337 self
.TargetTxt
= BuildConfig
338 self
.ToolDef
= ToolDefinition
339 self
.FdfFile
= FlashDefinitionFile
340 self
.FdTargetList
= Fds
if Fds
else []
341 self
.FvTargetList
= Fvs
if Fvs
else []
342 self
.CapTargetList
= Caps
if Caps
else []
343 self
.AutoGenObjectList
= []
346 # there's many relative directory operations, so ...
347 os
.chdir(self
.WorkspaceDir
)
352 if not self
.ArchList
:
353 ArchList
= set(self
.Platform
.SupArchList
)
355 ArchList
= set(self
.ArchList
) & set(self
.Platform
.SupArchList
)
357 EdkLogger
.error("build", PARAMETER_INVALID
,
358 ExtraData
= "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self
.Platform
.SupArchList
)))
359 elif self
.ArchList
and len(ArchList
) != len(self
.ArchList
):
360 SkippedArchList
= set(self
.ArchList
).symmetric_difference(set(self
.Platform
.SupArchList
))
361 EdkLogger
.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
362 % (" ".join(SkippedArchList
), " ".join(self
.Platform
.SupArchList
)))
363 self
.ArchList
= tuple(ArchList
)
365 # Validate build target
366 if self
.BuildTarget
not in self
.Platform
.BuildTargets
:
367 EdkLogger
.error("build", PARAMETER_INVALID
,
368 ExtraData
="Build target [%s] is not supported by the platform. [Valid target: %s]"
369 % (self
.BuildTarget
, " ".join(self
.Platform
.BuildTargets
)))
372 # parse FDF file to get PCDs in it, if any
374 self
.FdfFile
= self
.Platform
.FlashDefinition
378 EdkLogger
.info('%-16s = %s' % ("Architecture(s)", ' '.join(self
.ArchList
)))
379 EdkLogger
.info('%-16s = %s' % ("Build target", self
.BuildTarget
))
380 EdkLogger
.info('%-16s = %s' % ("Toolchain", self
.ToolChain
))
382 EdkLogger
.info('\n%-24s = %s' % ("Active Platform", self
.Platform
))
384 EdkLogger
.info('%-24s = %s' % ("Active Module", BuildModule
))
387 EdkLogger
.info('%-24s = %s' % ("Flash Image Definition", self
.FdfFile
))
389 EdkLogger
.verbose("\nFLASH_DEFINITION = %s" % self
.FdfFile
)
392 Progress
.Start("\nProcessing meta-data")
396 # Mark now build in AutoGen Phase
398 GlobalData
.gAutoGenPhase
= True
399 Fdf
= FdfParser(self
.FdfFile
.Path
)
401 GlobalData
.gFdfParser
= Fdf
402 GlobalData
.gAutoGenPhase
= False
403 PcdSet
= Fdf
.Profile
.PcdDict
404 if Fdf
.CurrentFdName
and Fdf
.CurrentFdName
in Fdf
.Profile
.FdDict
:
405 FdDict
= Fdf
.Profile
.FdDict
[Fdf
.CurrentFdName
]
406 for FdRegion
in FdDict
.RegionList
:
407 if str(FdRegion
.RegionType
) is 'FILE' and self
.Platform
.VpdToolGuid
in str(FdRegion
.RegionDataList
):
408 if int(FdRegion
.Offset
) % 8 != 0:
409 EdkLogger
.error("build", FORMAT_INVALID
, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion
.Offset
))
410 ModuleList
= Fdf
.Profile
.InfList
411 self
.FdfProfile
= Fdf
.Profile
412 for fvname
in self
.FvTargetList
:
413 if fvname
.upper() not in self
.FdfProfile
.FvDict
:
414 EdkLogger
.error("build", OPTION_VALUE_INVALID
,
415 "No such an FV in FDF file: %s" % fvname
)
417 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
418 # but the path (self.MetaFile.Path) is the real path
419 for key
in self
.FdfProfile
.InfDict
:
421 MetaFile_cache
= defaultdict(set)
422 for Arch
in self
.ArchList
:
423 Current_Platform_cache
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
424 for Pkey
in Current_Platform_cache
.Modules
:
425 MetaFile_cache
[Arch
].add(Current_Platform_cache
.Modules
[Pkey
].MetaFile
)
426 for Inf
in self
.FdfProfile
.InfDict
[key
]:
427 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
428 for Arch
in self
.ArchList
:
429 if ModuleFile
in MetaFile_cache
[Arch
]:
432 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
433 if not ModuleData
.IsBinaryModule
:
434 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
437 for Arch
in self
.ArchList
:
439 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
441 for Pkey
in Platform
.Modules
:
442 MetaFileList
.add(Platform
.Modules
[Pkey
].MetaFile
)
443 for Inf
in self
.FdfProfile
.InfDict
[key
]:
444 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
445 if ModuleFile
in MetaFileList
:
447 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
448 if not ModuleData
.IsBinaryModule
:
449 EdkLogger
.error('build', PARSER_ERROR
, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile
)
454 self
.FdfProfile
= None
455 if self
.FdTargetList
:
456 EdkLogger
.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self
.FdTargetList
))
457 self
.FdTargetList
= []
458 if self
.FvTargetList
:
459 EdkLogger
.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self
.FvTargetList
))
460 self
.FvTargetList
= []
461 if self
.CapTargetList
:
462 EdkLogger
.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self
.CapTargetList
))
463 self
.CapTargetList
= []
465 # apply SKU and inject PCDs from Flash Definition file
466 for Arch
in self
.ArchList
:
467 Platform
= self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]
468 PlatformPcds
= Platform
.Pcds
469 self
._GuidDict
= Platform
._GuidDict
470 SourcePcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set(),TAB_PCDS_DYNAMIC
:set(),TAB_PCDS_FIXED_AT_BUILD
:set()}
471 BinaryPcdDict
= {TAB_PCDS_DYNAMIC_EX
:set(), TAB_PCDS_PATCHABLE_IN_MODULE
:set()}
472 SourcePcdDict_Keys
= SourcePcdDict
.keys()
473 BinaryPcdDict_Keys
= BinaryPcdDict
.keys()
475 # generate the SourcePcdDict and BinaryPcdDict
476 PGen
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
477 for BuildData
in list(PGen
.BuildDatabase
._CACHE
_.values()):
478 if BuildData
.Arch
!= Arch
:
480 if BuildData
.MetaFile
.Ext
== '.inf':
481 for key
in BuildData
.Pcds
:
482 if BuildData
.Pcds
[key
].Pending
:
483 if key
in Platform
.Pcds
:
484 PcdInPlatform
= Platform
.Pcds
[key
]
485 if PcdInPlatform
.Type
:
486 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
487 BuildData
.Pcds
[key
].Pending
= False
489 if BuildData
.MetaFile
in Platform
.Modules
:
490 PlatformModule
= Platform
.Modules
[str(BuildData
.MetaFile
)]
491 if key
in PlatformModule
.Pcds
:
492 PcdInPlatform
= PlatformModule
.Pcds
[key
]
493 if PcdInPlatform
.Type
:
494 BuildData
.Pcds
[key
].Type
= PcdInPlatform
.Type
495 BuildData
.Pcds
[key
].Pending
= False
497 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
498 if BuildData
.Pcds
[key
].Pending
:
499 MGen
= ModuleAutoGen(self
, BuildData
.MetaFile
, Target
, Toolchain
, Arch
, self
.MetaFile
)
500 if MGen
and MGen
.IsLibrary
:
501 if MGen
in PGen
.LibraryAutoGenList
:
502 ReferenceModules
= MGen
.ReferenceModules
503 for ReferenceModule
in ReferenceModules
:
504 if ReferenceModule
.MetaFile
in Platform
.Modules
:
505 RefPlatformModule
= Platform
.Modules
[str(ReferenceModule
.MetaFile
)]
506 if key
in RefPlatformModule
.Pcds
:
507 PcdInReferenceModule
= RefPlatformModule
.Pcds
[key
]
508 if PcdInReferenceModule
.Type
:
509 BuildData
.Pcds
[key
].Type
= PcdInReferenceModule
.Type
510 BuildData
.Pcds
[key
].Pending
= False
513 if TAB_PCDS_DYNAMIC_EX
in BuildData
.Pcds
[key
].Type
:
514 if BuildData
.IsBinaryModule
:
515 BinaryPcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
517 SourcePcdDict
[TAB_PCDS_DYNAMIC_EX
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
519 elif TAB_PCDS_PATCHABLE_IN_MODULE
in BuildData
.Pcds
[key
].Type
:
520 if BuildData
.MetaFile
.Ext
== '.inf':
521 if BuildData
.IsBinaryModule
:
522 BinaryPcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
524 SourcePcdDict
[TAB_PCDS_PATCHABLE_IN_MODULE
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
526 elif TAB_PCDS_DYNAMIC
in BuildData
.Pcds
[key
].Type
:
527 SourcePcdDict
[TAB_PCDS_DYNAMIC
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
528 elif TAB_PCDS_FIXED_AT_BUILD
in BuildData
.Pcds
[key
].Type
:
529 SourcePcdDict
[TAB_PCDS_FIXED_AT_BUILD
].add((BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
))
533 # A PCD can only use one type for all source modules
535 for i
in SourcePcdDict_Keys
:
536 for j
in SourcePcdDict_Keys
:
538 Intersections
= SourcePcdDict
[i
].intersection(SourcePcdDict
[j
])
539 if len(Intersections
) > 0:
543 "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
),
544 ExtraData
='\n\t'.join(str(P
[1]+'.'+P
[0]) for P
in Intersections
)
548 # intersection the BinaryPCD for Mixed PCD
550 for i
in BinaryPcdDict_Keys
:
551 for j
in BinaryPcdDict_Keys
:
553 Intersections
= BinaryPcdDict
[i
].intersection(BinaryPcdDict
[j
])
554 for item
in Intersections
:
555 NewPcd1
= (item
[0] + '_' + i
, item
[1])
556 NewPcd2
= (item
[0] + '_' + j
, item
[1])
557 if item
not in GlobalData
.MixedPcd
:
558 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
560 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
561 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
562 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
563 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
566 # intersection the SourcePCD and BinaryPCD for Mixed PCD
568 for i
in SourcePcdDict_Keys
:
569 for j
in BinaryPcdDict_Keys
:
571 Intersections
= SourcePcdDict
[i
].intersection(BinaryPcdDict
[j
])
572 for item
in Intersections
:
573 NewPcd1
= (item
[0] + '_' + i
, item
[1])
574 NewPcd2
= (item
[0] + '_' + j
, item
[1])
575 if item
not in GlobalData
.MixedPcd
:
576 GlobalData
.MixedPcd
[item
] = [NewPcd1
, NewPcd2
]
578 if NewPcd1
not in GlobalData
.MixedPcd
[item
]:
579 GlobalData
.MixedPcd
[item
].append(NewPcd1
)
580 if NewPcd2
not in GlobalData
.MixedPcd
[item
]:
581 GlobalData
.MixedPcd
[item
].append(NewPcd2
)
583 for BuildData
in list(PGen
.BuildDatabase
._CACHE
_.values()):
584 if BuildData
.Arch
!= Arch
:
586 for key
in BuildData
.Pcds
:
587 for SinglePcd
in GlobalData
.MixedPcd
:
588 if (BuildData
.Pcds
[key
].TokenCName
, BuildData
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
589 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
590 Pcd_Type
= item
[0].split('_')[-1]
591 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 \
592 (Pcd_Type
== TAB_PCDS_DYNAMIC
and BuildData
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
593 Value
= BuildData
.Pcds
[key
]
594 Value
.TokenCName
= BuildData
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
596 newkey
= (Value
.TokenCName
, key
[1])
598 newkey
= (Value
.TokenCName
, key
[1], key
[2])
599 del BuildData
.Pcds
[key
]
600 BuildData
.Pcds
[newkey
] = Value
604 # handle the mixed pcd in FDF file
606 if key
in GlobalData
.MixedPcd
:
609 for item
in GlobalData
.MixedPcd
[key
]:
612 #Collect package set information from INF of FDF
614 for Inf
in ModuleList
:
615 ModuleFile
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, Arch
)
616 if ModuleFile
in Platform
.Modules
:
618 ModuleData
= self
.BuildDatabase
[ModuleFile
, Arch
, Target
, Toolchain
]
619 PkgSet
.update(ModuleData
.Packages
)
620 Pkgs
= list(PkgSet
) + list(PGen
.PackageList
)
625 DecPcds
.add((Pcd
[0], Pcd
[1]))
626 DecPcdsKey
.add((Pcd
[0], Pcd
[1], Pcd
[2]))
628 Platform
.SkuName
= self
.SkuId
629 for Name
, Guid
,Fileds
in PcdSet
:
630 if (Name
, Guid
) not in DecPcds
:
634 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid
, Name
),
635 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
636 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
639 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
640 if (Name
, Guid
, TAB_PCDS_FIXED_AT_BUILD
) in DecPcdsKey \
641 or (Name
, Guid
, TAB_PCDS_PATCHABLE_IN_MODULE
) in DecPcdsKey \
642 or (Name
, Guid
, TAB_PCDS_FEATURE_FLAG
) in DecPcdsKey
:
644 elif (Name
, Guid
, TAB_PCDS_DYNAMIC
) in DecPcdsKey
or (Name
, Guid
, TAB_PCDS_DYNAMIC_EX
) in DecPcdsKey
:
648 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid
, Name
),
649 File
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][0],
650 Line
= self
.FdfProfile
.PcdFileLineDict
[Name
, Guid
, Fileds
][1]
653 Pa
= PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
)
655 # Explicitly collect platform's dynamic PCDs
657 Pa
.CollectPlatformDynamicPcds()
658 Pa
.CollectFixedAtBuildPcds()
659 self
.AutoGenObjectList
.append(Pa
)
662 # Generate Package level hash value
664 GlobalData
.gPackageHash
[Arch
] = {}
665 if GlobalData
.gUseHashCache
:
667 self
._GenPkgLevelHash
(Pkg
)
670 # Check PCDs token value conflict in each DEC file.
672 self
._CheckAllPcdsTokenValueConflict
()
675 # Check PCD type and definition between DSC and DEC
677 self
._CheckPcdDefineAndType
()
680 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
682 content
= 'gCommandLineDefines: '
683 content
+= str(GlobalData
.gCommandLineDefines
)
684 content
+= TAB_LINE_BREAK
685 content
+= 'BuildOptionPcd: '
686 content
+= str(GlobalData
.BuildOptionPcd
)
687 content
+= TAB_LINE_BREAK
688 content
+= 'Active Platform: '
689 content
+= str(self
.Platform
)
690 content
+= TAB_LINE_BREAK
692 content
+= 'Flash Image Definition: '
693 content
+= str(self
.FdfFile
)
694 content
+= TAB_LINE_BREAK
695 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'BuildOptions'), content
, False)
698 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
700 PcdTokenNumber
= 'PcdTokenNumber: '
701 if Pa
.PcdTokenNumber
:
702 if Pa
.DynamicPcdList
:
703 for Pcd
in Pa
.DynamicPcdList
:
704 PcdTokenNumber
+= TAB_LINE_BREAK
705 PcdTokenNumber
+= str((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
))
706 PcdTokenNumber
+= ' : '
707 PcdTokenNumber
+= str(Pa
.PcdTokenNumber
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
])
708 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'), PcdTokenNumber
, False)
711 # Get set of workspace metafiles
713 AllWorkSpaceMetaFiles
= self
._GetMetaFiles
(Target
, Toolchain
, Arch
)
716 # Retrieve latest modified time of all metafiles
719 for f
in AllWorkSpaceMetaFiles
:
720 if os
.stat(f
)[8] > SrcTimeStamp
:
721 SrcTimeStamp
= os
.stat(f
)[8]
722 self
._SrcTimeStamp
= SrcTimeStamp
724 if GlobalData
.gUseHashCache
:
726 for files
in AllWorkSpaceMetaFiles
:
727 if files
.endswith('.dec'):
729 f
= open(files
, 'rb')
733 SaveFileOnChange(os
.path
.join(self
.BuildDir
, 'AutoGen.hash'), m
.hexdigest(), False)
734 GlobalData
.gPlatformHash
= m
.hexdigest()
737 # Write metafile list to build directory
739 AutoGenFilePath
= os
.path
.join(self
.BuildDir
, 'AutoGen')
740 if os
.path
.exists (AutoGenFilePath
):
741 os
.remove(AutoGenFilePath
)
742 if not os
.path
.exists(self
.BuildDir
):
743 os
.makedirs(self
.BuildDir
)
744 with
open(os
.path
.join(self
.BuildDir
, 'AutoGen'), 'w+') as file:
745 for f
in AllWorkSpaceMetaFiles
:
749 def _GenPkgLevelHash(self
, Pkg
):
750 if Pkg
.PackageName
in GlobalData
.gPackageHash
[Pkg
.Arch
]:
753 PkgDir
= os
.path
.join(self
.BuildDir
, Pkg
.Arch
, Pkg
.PackageName
)
754 CreateDirectory(PkgDir
)
755 HashFile
= os
.path
.join(PkgDir
, Pkg
.PackageName
+ '.hash')
757 # Get .dec file's hash value
758 f
= open(Pkg
.MetaFile
.Path
, 'rb')
762 # Get include files hash value
764 for inc
in sorted(Pkg
.Includes
, key
=lambda x
: str(x
)):
765 for Root
, Dirs
, Files
in os
.walk(str(inc
)):
766 for File
in sorted(Files
):
767 File_Path
= os
.path
.join(Root
, File
)
768 f
= open(File_Path
, 'rb')
772 SaveFileOnChange(HashFile
, m
.hexdigest(), False)
773 GlobalData
.gPackageHash
[Pkg
.Arch
][Pkg
.PackageName
] = m
.hexdigest()
775 def _GetMetaFiles(self
, Target
, Toolchain
, Arch
):
776 AllWorkSpaceMetaFiles
= set()
781 AllWorkSpaceMetaFiles
.add (self
.FdfFile
.Path
)
782 for f
in GlobalData
.gFdfParser
.GetAllIncludedFile():
783 AllWorkSpaceMetaFiles
.add (f
.FileName
)
787 AllWorkSpaceMetaFiles
.add(self
.MetaFile
.Path
)
790 # add build_rule.txt & tools_def.txt
792 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultBuildRuleFile
))
793 AllWorkSpaceMetaFiles
.add(os
.path
.join(GlobalData
.gConfDirectory
, gDefaultToolsDefFile
))
795 # add BuildOption metafile
797 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'BuildOptions'))
799 # add PcdToken Number file for Dynamic/DynamicEx Pcd
801 AllWorkSpaceMetaFiles
.add(os
.path
.join(self
.BuildDir
, 'PcdTokenNumber'))
803 for Arch
in self
.ArchList
:
807 for Package
in PlatformAutoGen(self
, self
.MetaFile
, Target
, Toolchain
, Arch
).PackageList
:
808 AllWorkSpaceMetaFiles
.add(Package
.MetaFile
.Path
)
813 for filePath
in self
.BuildDatabase
[self
.MetaFile
, Arch
, Target
, Toolchain
]._RawData
.IncludedFiles
:
814 AllWorkSpaceMetaFiles
.add(filePath
.Path
)
816 return AllWorkSpaceMetaFiles
818 def _CheckPcdDefineAndType(self
):
819 PcdTypeSet
= {TAB_PCDS_FIXED_AT_BUILD
,
820 TAB_PCDS_PATCHABLE_IN_MODULE
,
821 TAB_PCDS_FEATURE_FLAG
,
825 # This dict store PCDs which are not used by any modules with specified arches
826 UnusedPcd
= OrderedDict()
827 for Pa
in self
.AutoGenObjectList
:
828 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
829 for Pcd
in Pa
.Platform
.Pcds
:
830 PcdType
= Pa
.Platform
.Pcds
[Pcd
].Type
832 # If no PCD type, this PCD comes from FDF
836 # Try to remove Hii and Vpd suffix
837 if PcdType
.startswith(TAB_PCDS_DYNAMIC_EX
):
838 PcdType
= TAB_PCDS_DYNAMIC_EX
839 elif PcdType
.startswith(TAB_PCDS_DYNAMIC
):
840 PcdType
= TAB_PCDS_DYNAMIC
842 for Package
in Pa
.PackageList
:
843 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
844 if (Pcd
[0], Pcd
[1], PcdType
) in Package
.Pcds
:
846 for Type
in PcdTypeSet
:
847 if (Pcd
[0], Pcd
[1], Type
) in Package
.Pcds
:
851 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
852 % (Pa
.Platform
.Pcds
[Pcd
].Type
, Pcd
[1], Pcd
[0], Type
),
857 UnusedPcd
.setdefault(Pcd
, []).append(Pa
.Arch
)
859 for Pcd
in UnusedPcd
:
862 "The PCD was not specified by any INF module in the platform for the given architecture.\n"
863 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
864 % (Pcd
[1], Pcd
[0], os
.path
.basename(str(self
.MetaFile
)), str(UnusedPcd
[Pcd
])),
869 return "%s [%s]" % (self
.MetaFile
, ", ".join(self
.ArchList
))
871 ## Return the directory to store FV files
874 return path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
876 ## Return the directory to store all intermediate and final files built
879 return self
.AutoGenObjectList
[0].BuildDir
881 ## Return the build output directory platform specifies
884 return self
.Platform
.OutputDirectory
886 ## Return platform name
889 return self
.Platform
.PlatformName
891 ## Return meta-file GUID
894 return self
.Platform
.Guid
896 ## Return platform version
899 return self
.Platform
.Version
901 ## Return paths of tools
903 def ToolDefinition(self
):
904 return self
.AutoGenObjectList
[0].ToolDefinition
906 ## Return directory of platform makefile
908 # @retval string Makefile directory
911 def MakeFileDir(self
):
914 ## Return build command string
916 # @retval string Build command string
919 def BuildCommand(self
):
920 # BuildCommand should be all the same. So just get one from platform AutoGen
921 return self
.AutoGenObjectList
[0].BuildCommand
923 ## Check the PCDs token value conflict in each DEC file.
925 # Will cause build break and raise error message while two PCDs conflict.
929 def _CheckAllPcdsTokenValueConflict(self
):
930 for Pa
in self
.AutoGenObjectList
:
931 for Package
in Pa
.PackageList
:
932 PcdList
= list(Package
.Pcds
.values())
933 PcdList
.sort(key
=lambda x
: int(x
.TokenValue
, 0))
935 while (Count
< len(PcdList
) - 1) :
936 Item
= PcdList
[Count
]
937 ItemNext
= PcdList
[Count
+ 1]
939 # Make sure in the same token space the TokenValue should be unique
941 if (int(Item
.TokenValue
, 0) == int(ItemNext
.TokenValue
, 0)):
942 SameTokenValuePcdList
= []
943 SameTokenValuePcdList
.append(Item
)
944 SameTokenValuePcdList
.append(ItemNext
)
945 RemainPcdListLength
= len(PcdList
) - Count
- 2
946 for ValueSameCount
in range(RemainPcdListLength
):
947 if int(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
].TokenValue
, 0) == int(Item
.TokenValue
, 0):
948 SameTokenValuePcdList
.append(PcdList
[len(PcdList
) - RemainPcdListLength
+ ValueSameCount
])
952 # Sort same token value PCD list with TokenGuid and TokenCName
954 SameTokenValuePcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
955 SameTokenValuePcdListCount
= 0
956 while (SameTokenValuePcdListCount
< len(SameTokenValuePcdList
) - 1):
958 TemListItem
= SameTokenValuePcdList
[SameTokenValuePcdListCount
]
959 TemListItemNext
= SameTokenValuePcdList
[SameTokenValuePcdListCount
+ 1]
961 if (TemListItem
.TokenSpaceGuidCName
== TemListItemNext
.TokenSpaceGuidCName
) and (TemListItem
.TokenCName
!= TemListItemNext
.TokenCName
):
962 for PcdItem
in GlobalData
.MixedPcd
:
963 if (TemListItem
.TokenCName
, TemListItem
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
] or \
964 (TemListItemNext
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
970 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
971 % (TemListItem
.TokenValue
, TemListItem
.TokenSpaceGuidCName
, TemListItem
.TokenCName
, TemListItemNext
.TokenSpaceGuidCName
, TemListItemNext
.TokenCName
, Package
),
974 SameTokenValuePcdListCount
+= 1
975 Count
+= SameTokenValuePcdListCount
978 PcdList
= list(Package
.Pcds
.values())
979 PcdList
.sort(key
=lambda x
: "%s.%s" % (x
.TokenSpaceGuidCName
, x
.TokenCName
))
981 while (Count
< len(PcdList
) - 1) :
982 Item
= PcdList
[Count
]
983 ItemNext
= PcdList
[Count
+ 1]
985 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
987 if (Item
.TokenSpaceGuidCName
== ItemNext
.TokenSpaceGuidCName
) and (Item
.TokenCName
== ItemNext
.TokenCName
) and (int(Item
.TokenValue
, 0) != int(ItemNext
.TokenValue
, 0)):
991 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
992 % (Item
.TokenValue
, Item
.TokenSpaceGuidCName
, Item
.TokenCName
, Package
),
996 ## Generate fds command
998 def GenFdsCommand(self
):
999 return (GenMake
.TopLevelMakefile(self
)._TEMPLATE
_.Replace(GenMake
.TopLevelMakefile(self
)._TemplateDict
)).strip()
1002 def GenFdsCommandDict(self
):
1004 LogLevel
= EdkLogger
.GetLevel()
1005 if LogLevel
== EdkLogger
.VERBOSE
:
1006 FdsCommandDict
["verbose"] = True
1007 elif LogLevel
<= EdkLogger
.DEBUG_9
:
1008 FdsCommandDict
["debug"] = LogLevel
- 1
1009 elif LogLevel
== EdkLogger
.QUIET
:
1010 FdsCommandDict
["quiet"] = True
1012 if GlobalData
.gEnableGenfdsMultiThread
:
1013 FdsCommandDict
["GenfdsMultiThread"] = True
1014 if GlobalData
.gIgnoreSource
:
1015 FdsCommandDict
["IgnoreSources"] = True
1017 FdsCommandDict
["OptionPcd"] = []
1018 for pcd
in GlobalData
.BuildOptionPcd
:
1020 pcdname
= '.'.join(pcd
[0:3])
1022 pcdname
= '.'.join(pcd
[0:2])
1023 if pcd
[3].startswith('{'):
1024 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + 'H' + '"' + pcd
[3] + '"')
1026 FdsCommandDict
["OptionPcd"].append(pcdname
+ '=' + pcd
[3])
1029 # macros passed to GenFds
1031 MacroDict
.update(GlobalData
.gGlobalDefines
)
1032 MacroDict
.update(GlobalData
.gCommandLineDefines
)
1033 for MacroName
in MacroDict
:
1034 if MacroDict
[MacroName
] != "":
1035 MacroList
.append('"%s=%s"' % (MacroName
, MacroDict
[MacroName
].replace('\\', '\\\\')))
1037 MacroList
.append('"%s"' % MacroName
)
1038 FdsCommandDict
["macro"] = MacroList
1040 FdsCommandDict
["fdf_file"] = [self
.FdfFile
]
1041 FdsCommandDict
["build_target"] = self
.BuildTarget
1042 FdsCommandDict
["toolchain_tag"] = self
.ToolChain
1043 FdsCommandDict
["active_platform"] = str(self
)
1045 FdsCommandDict
["conf_directory"] = GlobalData
.gConfDirectory
1046 FdsCommandDict
["build_architecture_list"] = ','.join(self
.ArchList
)
1047 FdsCommandDict
["platform_build_directory"] = self
.BuildDir
1049 FdsCommandDict
["fd"] = self
.FdTargetList
1050 FdsCommandDict
["fv"] = self
.FvTargetList
1051 FdsCommandDict
["cap"] = self
.CapTargetList
1052 return FdsCommandDict
1054 ## Create makefile for the platform and modules in it
1056 # @param CreateDepsMakeFile Flag indicating if the makefile for
1057 # modules will be created as well
1059 def CreateMakeFile(self
, CreateDepsMakeFile
=False):
1060 if not CreateDepsMakeFile
:
1062 for Pa
in self
.AutoGenObjectList
:
1063 Pa
.CreateMakeFile(True)
1065 ## Create autogen code for platform and modules
1067 # Since there's no autogen code for platform, this method will do nothing
1068 # if CreateModuleCodeFile is set to False.
1070 # @param CreateDepsCodeFile Flag indicating if creating module's
1071 # autogen code file or not
1073 def CreateCodeFile(self
, CreateDepsCodeFile
=False):
1074 if not CreateDepsCodeFile
:
1076 for Pa
in self
.AutoGenObjectList
:
1077 Pa
.CreateCodeFile(True)
1079 ## Create AsBuilt INF file the platform
1081 def CreateAsBuiltInf(self
):
1085 ## AutoGen class for platform
1087 # PlatformAutoGen class will process the original information in platform
1088 # file in order to generate makefile for platform.
1090 class PlatformAutoGen(AutoGen
):
1091 # call super().__init__ then call the worker function with different parameter count
1092 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
1093 if not hasattr(self
, "_Init"):
1094 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
)
1097 # Used to store all PCDs for both PEI and DXE phase, in order to generate
1098 # correct PCD database
1101 _NonDynaPcdList_
= []
1105 # The priority list while override build option
1107 PrioList
= {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
1108 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
1109 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1110 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
1111 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1112 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
1113 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
1114 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
1115 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1116 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
1117 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
1118 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
1119 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
1120 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
1121 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
1122 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
1124 ## Initialize PlatformAutoGen
1127 # @param Workspace WorkspaceAutoGen object
1128 # @param PlatformFile Platform file (DSC file)
1129 # @param Target Build target (DEBUG, RELEASE)
1130 # @param Toolchain Name of tool chain
1131 # @param Arch arch of the platform supports
1133 def _InitWorker(self
, Workspace
, PlatformFile
, Target
, Toolchain
, Arch
):
1134 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen platform [%s] [%s]" % (PlatformFile
, Arch
))
1135 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (PlatformFile
, Arch
, Toolchain
, Target
)
1137 self
.MetaFile
= PlatformFile
1138 self
.Workspace
= Workspace
1139 self
.WorkspaceDir
= Workspace
.WorkspaceDir
1140 self
.ToolChain
= Toolchain
1141 self
.BuildTarget
= Target
1143 self
.SourceDir
= PlatformFile
.SubDir
1144 self
.SourceOverrideDir
= None
1145 self
.FdTargetList
= self
.Workspace
.FdTargetList
1146 self
.FvTargetList
= self
.Workspace
.FvTargetList
1147 # get the original module/package/platform objects
1148 self
.BuildDatabase
= Workspace
.BuildDatabase
1149 self
.DscBuildDataObj
= Workspace
.Platform
1151 # flag indicating if the makefile/C-code file has been created or not
1152 self
.IsMakeFileCreated
= False
1154 self
._DynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1155 self
._NonDynamicPcdList
= None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
1157 self
._AsBuildInfList
= []
1158 self
._AsBuildModuleList
= []
1160 self
.VariableInfo
= None
1162 if GlobalData
.gFdfParser
is not None:
1163 self
._AsBuildInfList
= GlobalData
.gFdfParser
.Profile
.InfList
1164 for Inf
in self
._AsBuildInfList
:
1165 InfClass
= PathClass(NormPath(Inf
), GlobalData
.gWorkspace
, self
.Arch
)
1166 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1167 if not M
.IsBinaryModule
:
1169 self
._AsBuildModuleList
.append(InfClass
)
1170 # get library/modules for build
1171 self
.LibraryBuildDirectoryList
= []
1172 self
.ModuleBuildDirectoryList
= []
1176 @cached_class_function
1178 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
1180 ## Create autogen code for platform and modules
1182 # Since there's no autogen code for platform, this method will do nothing
1183 # if CreateModuleCodeFile is set to False.
1185 # @param CreateModuleCodeFile Flag indicating if creating module's
1186 # autogen code file or not
1188 @cached_class_function
1189 def CreateCodeFile(self
, CreateModuleCodeFile
=False):
1190 # only module has code to be created, so do nothing if CreateModuleCodeFile is False
1191 if not CreateModuleCodeFile
:
1194 for Ma
in self
.ModuleAutoGenList
:
1195 Ma
.CreateCodeFile(True)
1197 ## Generate Fds Command
1199 def GenFdsCommand(self
):
1200 return self
.Workspace
.GenFdsCommand
1202 ## Create makefile for the platform and modules in it
1204 # @param CreateModuleMakeFile Flag indicating if the makefile for
1205 # modules will be created as well
1207 def CreateMakeFile(self
, CreateModuleMakeFile
=False, FfsCommand
= {}):
1208 if CreateModuleMakeFile
:
1209 for Ma
in self
._MaList
:
1210 key
= (Ma
.MetaFile
.File
, self
.Arch
)
1211 if key
in FfsCommand
:
1212 Ma
.CreateMakeFile(True, FfsCommand
[key
])
1214 Ma
.CreateMakeFile(True)
1216 # no need to create makefile for the platform more than once
1217 if self
.IsMakeFileCreated
:
1220 # create library/module build dirs for platform
1221 Makefile
= GenMake
.PlatformMakefile(self
)
1222 self
.LibraryBuildDirectoryList
= Makefile
.GetLibraryBuildDirectoryList()
1223 self
.ModuleBuildDirectoryList
= Makefile
.GetModuleBuildDirectoryList()
1225 self
.IsMakeFileCreated
= True
1228 def AllPcdList(self
):
1229 return self
.DynamicPcdList
+ self
.NonDynamicPcdList
1230 ## Deal with Shared FixedAtBuild Pcds
1232 def CollectFixedAtBuildPcds(self
):
1233 for LibAuto
in self
.LibraryAutoGenList
:
1234 FixedAtBuildPcds
= {}
1235 ShareFixedAtBuildPcdsSameValue
= {}
1236 for Module
in LibAuto
.ReferenceModules
:
1237 for Pcd
in set(Module
.FixedAtBuildPcds
+ LibAuto
.FixedAtBuildPcds
):
1238 DefaultValue
= Pcd
.DefaultValue
1239 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
1240 if Pcd
in Module
.LibraryPcdList
:
1241 Index
= Module
.LibraryPcdList
.index(Pcd
)
1242 DefaultValue
= Module
.LibraryPcdList
[Index
].DefaultValue
1243 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1244 if key
not in FixedAtBuildPcds
:
1245 ShareFixedAtBuildPcdsSameValue
[key
] = True
1246 FixedAtBuildPcds
[key
] = DefaultValue
1248 if FixedAtBuildPcds
[key
] != DefaultValue
:
1249 ShareFixedAtBuildPcdsSameValue
[key
] = False
1250 for Pcd
in LibAuto
.FixedAtBuildPcds
:
1251 key
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1252 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) not in self
.NonDynamicPcdDict
:
1255 DscPcd
= self
.NonDynamicPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)]
1256 if DscPcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
1258 if key
in ShareFixedAtBuildPcdsSameValue
and ShareFixedAtBuildPcdsSameValue
[key
]:
1259 LibAuto
.ConstPcd
[key
] = FixedAtBuildPcds
[key
]
1261 def CollectVariables(self
, DynamicPcdSet
):
1264 if self
.Workspace
.FdfFile
:
1265 FdDict
= self
.Workspace
.FdfProfile
.FdDict
[GlobalData
.gFdfParser
.CurrentFdName
]
1266 for FdRegion
in FdDict
.RegionList
:
1267 for item
in FdRegion
.RegionDataList
:
1268 if self
.Platform
.VpdToolGuid
.strip() and self
.Platform
.VpdToolGuid
in item
:
1269 VpdRegionSize
= FdRegion
.Size
1270 VpdRegionBase
= FdRegion
.Offset
1273 VariableInfo
= VariableMgr(self
.DscBuildDataObj
._GetDefaultStores
(), self
.DscBuildDataObj
.SkuIds
)
1274 VariableInfo
.SetVpdRegionMaxSize(VpdRegionSize
)
1275 VariableInfo
.SetVpdRegionOffset(VpdRegionBase
)
1277 for Pcd
in DynamicPcdSet
:
1278 pcdname
= ".".join((Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1279 for SkuName
in Pcd
.SkuInfoList
:
1280 Sku
= Pcd
.SkuInfoList
[SkuName
]
1282 if SkuId
is None or SkuId
== '':
1284 if len(Sku
.VariableName
) > 0:
1285 if Sku
.VariableAttribute
and 'NV' not in Sku
.VariableAttribute
:
1287 VariableGuidStructure
= Sku
.VariableGuidValue
1288 VariableGuid
= GuidStructureStringToGuidString(VariableGuidStructure
)
1289 for StorageName
in Sku
.DefaultStoreDict
:
1290 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)))
1294 def UpdateNVStoreMaxSize(self
, OrgVpdFile
):
1295 if self
.VariableInfo
:
1296 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1297 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1299 if PcdNvStoreDfBuffer
:
1300 if os
.path
.exists(VpdMapFilePath
):
1301 OrgVpdFile
.Read(VpdMapFilePath
)
1302 PcdItems
= OrgVpdFile
.GetOffset(PcdNvStoreDfBuffer
[0])
1303 NvStoreOffset
= list(PcdItems
.values())[0].strip() if PcdItems
else '0'
1305 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1307 NvStoreOffset
= int(NvStoreOffset
, 16) if NvStoreOffset
.upper().startswith("0X") else int(NvStoreOffset
)
1308 default_skuobj
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1309 maxsize
= self
.VariableInfo
.VpdRegionSize
- NvStoreOffset
if self
.VariableInfo
.VpdRegionSize
else len(default_skuobj
.DefaultValue
.split(","))
1310 var_data
= self
.VariableInfo
.PatchNVStoreDefaultMaxSize(maxsize
)
1312 if var_data
and default_skuobj
:
1313 default_skuobj
.DefaultValue
= var_data
1314 PcdNvStoreDfBuffer
[0].DefaultValue
= var_data
1315 PcdNvStoreDfBuffer
[0].SkuInfoList
.clear()
1316 PcdNvStoreDfBuffer
[0].SkuInfoList
[TAB_DEFAULT
] = default_skuobj
1317 PcdNvStoreDfBuffer
[0].MaxDatumSize
= str(len(default_skuobj
.DefaultValue
.split(",")))
1321 ## Collect dynamic PCDs
1323 # Gather dynamic PCDs list from each module and their settings from platform
1324 # This interface should be invoked explicitly when platform action is created.
1326 def CollectPlatformDynamicPcds(self
):
1327 for key
in self
.Platform
.Pcds
:
1328 for SinglePcd
in GlobalData
.MixedPcd
:
1329 if (self
.Platform
.Pcds
[key
].TokenCName
, self
.Platform
.Pcds
[key
].TokenSpaceGuidCName
) == SinglePcd
:
1330 for item
in GlobalData
.MixedPcd
[SinglePcd
]:
1331 Pcd_Type
= item
[0].split('_')[-1]
1332 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 \
1333 (Pcd_Type
== TAB_PCDS_DYNAMIC
and self
.Platform
.Pcds
[key
].Type
in PCD_DYNAMIC_TYPE_SET
):
1334 Value
= self
.Platform
.Pcds
[key
]
1335 Value
.TokenCName
= self
.Platform
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
1337 newkey
= (Value
.TokenCName
, key
[1])
1339 newkey
= (Value
.TokenCName
, key
[1], key
[2])
1340 del self
.Platform
.Pcds
[key
]
1341 self
.Platform
.Pcds
[newkey
] = Value
1345 # for gathering error information
1346 NoDatumTypePcdList
= set()
1348 for InfName
in self
._AsBuildInfList
:
1349 InfName
= mws
.join(self
.WorkspaceDir
, InfName
)
1350 FdfModuleList
.append(os
.path
.normpath(InfName
))
1351 for M
in self
._MaList
:
1352 # F is the Module for which M is the module autogen
1353 for PcdFromModule
in M
.ModulePcdList
+ M
.LibraryPcdList
:
1354 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1355 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1356 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, M
.MetaFile
))
1358 # Check the PCD from Binary INF or Source INF
1359 if M
.IsBinaryModule
== True:
1360 PcdFromModule
.IsFromBinaryInf
= True
1362 # Check the PCD from DSC or not
1363 PcdFromModule
.IsFromDsc
= (PcdFromModule
.TokenCName
, PcdFromModule
.TokenSpaceGuidCName
) in self
.Platform
.Pcds
1365 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
or PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1366 if M
.MetaFile
.Path
not in FdfModuleList
:
1367 # If one of the Source built modules listed in the DSC is not listed
1368 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
1369 # access method (it is only listed in the DEC file that declares the
1370 # PCD as PcdsDynamic), then build tool will report warning message
1371 # notify the PI that they are attempting to build a module that must
1372 # be included in a flash image in order to be functional. These Dynamic
1373 # PCD will not be added into the Database unless it is used by other
1374 # modules that are included in the FDF file.
1375 if PcdFromModule
.Type
in PCD_DYNAMIC_TYPE_SET
and \
1376 PcdFromModule
.IsFromBinaryInf
== False:
1377 # Print warning message to let the developer make a determine.
1379 # If one of the Source built modules listed in the DSC is not listed in
1380 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
1381 # access method (it is only listed in the DEC file that declares the
1382 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
1383 # PCD to the Platform's PCD Database.
1384 if PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1387 # If a dynamic PCD used by a PEM module/PEI module & DXE module,
1388 # it should be stored in Pcd PEI database, If a dynamic only
1389 # used by DXE module, it should be stored in DXE PCD database.
1390 # The default Phase is DXE
1392 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1393 PcdFromModule
.Phase
= "PEI"
1394 if PcdFromModule
not in self
._DynaPcdList
_:
1395 self
._DynaPcdList
_.append(PcdFromModule
)
1396 elif PcdFromModule
.Phase
== 'PEI':
1397 # overwrite any the same PCD existing, if Phase is PEI
1398 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1399 self
._DynaPcdList
_[Index
] = PcdFromModule
1400 elif PcdFromModule
not in self
._NonDynaPcdList
_:
1401 self
._NonDynaPcdList
_.append(PcdFromModule
)
1402 elif PcdFromModule
in self
._NonDynaPcdList
_ and PcdFromModule
.IsFromBinaryInf
== True:
1403 Index
= self
._NonDynaPcdList
_.index(PcdFromModule
)
1404 if self
._NonDynaPcdList
_[Index
].IsFromBinaryInf
== False:
1405 #The PCD from Binary INF will override the same one from source INF
1406 self
._NonDynaPcdList
_.remove (self
._NonDynaPcdList
_[Index
])
1407 PcdFromModule
.Pending
= False
1408 self
._NonDynaPcdList
_.append (PcdFromModule
)
1409 DscModuleSet
= {os
.path
.normpath(ModuleInf
.Path
) for ModuleInf
in self
.Platform
.Modules
}
1410 # add the PCD from modules that listed in FDF but not in DSC to Database
1411 for InfName
in FdfModuleList
:
1412 if InfName
not in DscModuleSet
:
1413 InfClass
= PathClass(InfName
)
1414 M
= self
.BuildDatabase
[InfClass
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1415 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
1416 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
1417 # For binary module, if in current arch, we need to list the PCDs into database.
1418 if not M
.IsBinaryModule
:
1420 # Override the module PCD setting by platform setting
1421 ModulePcdList
= self
.ApplyPcdSetting(M
, M
.Pcds
)
1422 for PcdFromModule
in ModulePcdList
:
1423 PcdFromModule
.IsFromBinaryInf
= True
1424 PcdFromModule
.IsFromDsc
= False
1425 # Only allow the DynamicEx and Patchable PCD in AsBuild INF
1426 if PcdFromModule
.Type
not in PCD_DYNAMIC_EX_TYPE_SET
and PcdFromModule
.Type
not in TAB_PCDS_PATCHABLE_IN_MODULE
:
1427 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1429 ExtraData
="\n\tExisted %s PCD %s in:\n\t\t%s\n"
1430 % (PcdFromModule
.Type
, PcdFromModule
.TokenCName
, InfName
))
1431 # make sure that the "VOID*" kind of datum has MaxDatumSize set
1432 if PcdFromModule
.DatumType
== TAB_VOID
and not PcdFromModule
.MaxDatumSize
:
1433 NoDatumTypePcdList
.add("%s.%s [%s]" % (PcdFromModule
.TokenSpaceGuidCName
, PcdFromModule
.TokenCName
, InfName
))
1434 if M
.ModuleType
in SUP_MODULE_SET_PEI
:
1435 PcdFromModule
.Phase
= "PEI"
1436 if PcdFromModule
not in self
._DynaPcdList
_ and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1437 self
._DynaPcdList
_.append(PcdFromModule
)
1438 elif PcdFromModule
not in self
._NonDynaPcdList
_ and PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
:
1439 self
._NonDynaPcdList
_.append(PcdFromModule
)
1440 if PcdFromModule
in self
._DynaPcdList
_ and PcdFromModule
.Phase
== 'PEI' and PcdFromModule
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
1441 # Overwrite the phase of any the same PCD existing, if Phase is PEI.
1442 # It is to solve the case that a dynamic PCD used by a PEM module/PEI
1443 # module & DXE module at a same time.
1444 # Overwrite the type of the PCDs in source INF by the type of AsBuild
1445 # INF file as DynamicEx.
1446 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1447 self
._DynaPcdList
_[Index
].Phase
= PcdFromModule
.Phase
1448 self
._DynaPcdList
_[Index
].Type
= PcdFromModule
.Type
1449 for PcdFromModule
in self
._NonDynaPcdList
_:
1450 # If a PCD is not listed in the DSC file, but binary INF files used by
1451 # this platform all (that use this PCD) list the PCD in a [PatchPcds]
1452 # section, AND all source INF files used by this platform the build
1453 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
1454 # section, then the tools must NOT add the PCD to the Platform's PCD
1455 # Database; the build must assign the access method for this PCD as
1456 # PcdsPatchableInModule.
1457 if PcdFromModule
not in self
._DynaPcdList
_:
1459 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1460 if PcdFromModule
.IsFromDsc
== False and \
1461 PcdFromModule
.Type
in TAB_PCDS_PATCHABLE_IN_MODULE
and \
1462 PcdFromModule
.IsFromBinaryInf
== True and \
1463 self
._DynaPcdList
_[Index
].IsFromBinaryInf
== False:
1464 Index
= self
._DynaPcdList
_.index(PcdFromModule
)
1465 self
._DynaPcdList
_.remove (self
._DynaPcdList
_[Index
])
1467 # print out error information and break the build, if error found
1468 if len(NoDatumTypePcdList
) > 0:
1469 NoDatumTypePcdListString
= "\n\t\t".join(NoDatumTypePcdList
)
1470 EdkLogger
.error("build", AUTOGEN_ERROR
, "PCD setting error",
1472 ExtraData
="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
1473 % NoDatumTypePcdListString
)
1474 self
._NonDynamicPcdList
= self
._NonDynaPcdList
_
1475 self
._DynamicPcdList
= self
._DynaPcdList
_
1477 # Sort dynamic PCD list to:
1478 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
1479 # try to be put header of dynamicd List
1480 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
1482 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
1484 UnicodePcdArray
= set()
1486 OtherPcdArray
= set()
1488 VpdFile
= VpdInfoFile
.VpdInfoFile()
1489 NeedProcessVpdMapFile
= False
1491 for pcd
in self
.Platform
.Pcds
:
1492 if pcd
not in self
._PlatformPcds
:
1493 self
._PlatformPcds
[pcd
] = self
.Platform
.Pcds
[pcd
]
1495 for item
in self
._PlatformPcds
:
1496 if self
._PlatformPcds
[item
].DatumType
and self
._PlatformPcds
[item
].DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1497 self
._PlatformPcds
[item
].DatumType
= TAB_VOID
1499 if (self
.Workspace
.ArchList
[-1] == self
.Arch
):
1500 for Pcd
in self
._DynamicPcdList
:
1501 # just pick the a value to determine whether is unicode string type
1502 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1503 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1505 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1506 Pcd
.DatumType
= TAB_VOID
1508 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1509 # if found HII type PCD then insert to right of UnicodeIndex
1510 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1511 VpdPcdDict
[(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
)] = Pcd
1513 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
1514 PcdNvStoreDfBuffer
= VpdPcdDict
.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
1515 if PcdNvStoreDfBuffer
:
1516 self
.VariableInfo
= self
.CollectVariables(self
._DynamicPcdList
)
1517 vardump
= self
.VariableInfo
.dump()
1520 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
1521 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
1522 #typedef UINT16 SIZE_INFO;
1523 #//SIZE_INFO SizeTable[];
1524 if len(vardump
.split(",")) > 0xffff:
1525 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(","))))
1526 PcdNvStoreDfBuffer
.DefaultValue
= vardump
1527 for skuname
in PcdNvStoreDfBuffer
.SkuInfoList
:
1528 PcdNvStoreDfBuffer
.SkuInfoList
[skuname
].DefaultValue
= vardump
1529 PcdNvStoreDfBuffer
.MaxDatumSize
= str(len(vardump
.split(",")))
1531 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
1532 if [Pcd
for Pcd
in self
._DynamicPcdList
if Pcd
.UserDefinedDefaultStoresFlag
]:
1533 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
)
1534 PlatformPcds
= sorted(self
._PlatformPcds
.keys())
1536 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
1539 for PcdKey
in PlatformPcds
:
1540 Pcd
= self
._PlatformPcds
[PcdKey
]
1541 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
] and \
1542 PcdKey
in VpdPcdDict
:
1543 Pcd
= VpdPcdDict
[PcdKey
]
1545 DefaultSku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1547 PcdValue
= DefaultSku
.DefaultValue
1548 if PcdValue
not in SkuValueMap
:
1549 SkuValueMap
[PcdValue
] = []
1550 VpdFile
.Add(Pcd
, TAB_DEFAULT
, DefaultSku
.VpdOffset
)
1551 SkuValueMap
[PcdValue
].append(DefaultSku
)
1553 for (SkuName
, Sku
) in Pcd
.SkuInfoList
.items():
1554 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1555 PcdValue
= Sku
.DefaultValue
1557 PcdValue
= Pcd
.DefaultValue
1558 if Sku
.VpdOffset
!= TAB_STAR
:
1559 if PcdValue
.startswith("{"):
1561 elif PcdValue
.startswith("L"):
1566 VpdOffset
= int(Sku
.VpdOffset
)
1569 VpdOffset
= int(Sku
.VpdOffset
, 16)
1571 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
))
1572 if VpdOffset
% Alignment
!= 0:
1573 if PcdValue
.startswith("{"):
1574 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
), File
=self
.MetaFile
)
1576 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
, Alignment
))
1577 if PcdValue
not in SkuValueMap
:
1578 SkuValueMap
[PcdValue
] = []
1579 VpdFile
.Add(Pcd
, SkuName
, Sku
.VpdOffset
)
1580 SkuValueMap
[PcdValue
].append(Sku
)
1581 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1582 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1583 NeedProcessVpdMapFile
= True
1584 if self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== '':
1585 EdkLogger
.error("Build", FILE_NOT_FOUND
, \
1586 "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.")
1588 VpdSkuMap
[PcdKey
] = SkuValueMap
1590 # Fix the PCDs define in VPD PCD section that never referenced by module.
1591 # An example is PCD for signature usage.
1593 for DscPcd
in PlatformPcds
:
1594 DscPcdEntry
= self
._PlatformPcds
[DscPcd
]
1595 if DscPcdEntry
.Type
in [TAB_PCDS_DYNAMIC_VPD
, TAB_PCDS_DYNAMIC_EX_VPD
]:
1596 if not (self
.Platform
.VpdToolGuid
is None or self
.Platform
.VpdToolGuid
== ''):
1598 for VpdPcd
in VpdFile
._VpdArray
:
1599 # This PCD has been referenced by module
1600 if (VpdPcd
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1601 (VpdPcd
.TokenCName
== DscPcdEntry
.TokenCName
):
1604 # Not found, it should be signature
1606 # just pick the a value to determine whether is unicode string type
1608 SkuObjList
= list(DscPcdEntry
.SkuInfoList
.items())
1609 DefaultSku
= DscPcdEntry
.SkuInfoList
.get(TAB_DEFAULT
)
1611 defaultindex
= SkuObjList
.index((TAB_DEFAULT
, DefaultSku
))
1612 SkuObjList
[0], SkuObjList
[defaultindex
] = SkuObjList
[defaultindex
], SkuObjList
[0]
1613 for (SkuName
, Sku
) in SkuObjList
:
1614 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1616 # Need to iterate DEC pcd information to get the value & datumtype
1617 for eachDec
in self
.PackageList
:
1618 for DecPcd
in eachDec
.Pcds
:
1619 DecPcdEntry
= eachDec
.Pcds
[DecPcd
]
1620 if (DecPcdEntry
.TokenSpaceGuidCName
== DscPcdEntry
.TokenSpaceGuidCName
) and \
1621 (DecPcdEntry
.TokenCName
== DscPcdEntry
.TokenCName
):
1622 # Print warning message to let the developer make a determine.
1623 EdkLogger
.warn("build", "Unreferenced vpd pcd used!",
1624 File
=self
.MetaFile
, \
1625 ExtraData
= "PCD: %s.%s used in the DSC file %s is unreferenced." \
1626 %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, self
.Platform
.MetaFile
.Path
))
1628 DscPcdEntry
.DatumType
= DecPcdEntry
.DatumType
1629 DscPcdEntry
.DefaultValue
= DecPcdEntry
.DefaultValue
1630 DscPcdEntry
.TokenValue
= DecPcdEntry
.TokenValue
1631 DscPcdEntry
.TokenSpaceGuidValue
= eachDec
.Guids
[DecPcdEntry
.TokenSpaceGuidCName
]
1632 # Only fix the value while no value provided in DSC file.
1633 if not Sku
.DefaultValue
:
1634 DscPcdEntry
.SkuInfoList
[list(DscPcdEntry
.SkuInfoList
.keys())[0]].DefaultValue
= DecPcdEntry
.DefaultValue
1636 if DscPcdEntry
not in self
._DynamicPcdList
:
1637 self
._DynamicPcdList
.append(DscPcdEntry
)
1638 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1639 PcdValue
= Sku
.DefaultValue
1641 PcdValue
= DscPcdEntry
.DefaultValue
1642 if Sku
.VpdOffset
!= TAB_STAR
:
1643 if PcdValue
.startswith("{"):
1645 elif PcdValue
.startswith("L"):
1650 VpdOffset
= int(Sku
.VpdOffset
)
1653 VpdOffset
= int(Sku
.VpdOffset
, 16)
1655 EdkLogger
.error("build", FORMAT_INVALID
, "Invalid offset value %s for PCD %s.%s." % (Sku
.VpdOffset
, DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
))
1656 if VpdOffset
% Alignment
!= 0:
1657 if PcdValue
.startswith("{"):
1658 EdkLogger
.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
), File
=self
.MetaFile
)
1660 EdkLogger
.error("build", FORMAT_INVALID
, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry
.TokenSpaceGuidCName
, DscPcdEntry
.TokenCName
, Alignment
))
1661 if PcdValue
not in SkuValueMap
:
1662 SkuValueMap
[PcdValue
] = []
1663 VpdFile
.Add(DscPcdEntry
, SkuName
, Sku
.VpdOffset
)
1664 SkuValueMap
[PcdValue
].append(Sku
)
1665 if not NeedProcessVpdMapFile
and Sku
.VpdOffset
== TAB_STAR
:
1666 NeedProcessVpdMapFile
= True
1667 if DscPcdEntry
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1668 UnicodePcdArray
.add(DscPcdEntry
)
1669 elif len(Sku
.VariableName
) > 0:
1670 HiiPcdArray
.add(DscPcdEntry
)
1672 OtherPcdArray
.add(DscPcdEntry
)
1674 # if the offset of a VPD is *, then it need to be fixed up by third party tool.
1675 VpdSkuMap
[DscPcd
] = SkuValueMap
1676 if (self
.Platform
.FlashDefinition
is None or self
.Platform
.FlashDefinition
== '') and \
1677 VpdFile
.GetCount() != 0:
1678 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
1679 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self
.Platform
.MetaFile
))
1681 if VpdFile
.GetCount() != 0:
1683 self
.FixVpdOffset(VpdFile
)
1685 self
.FixVpdOffset(self
.UpdateNVStoreMaxSize(VpdFile
))
1686 PcdNvStoreDfBuffer
= [item
for item
in self
._DynamicPcdList
if item
.TokenCName
== "PcdNvStoreDefaultValueBuffer" and item
.TokenSpaceGuidCName
== "gEfiMdeModulePkgTokenSpaceGuid"]
1687 if PcdNvStoreDfBuffer
:
1688 PcdName
,PcdGuid
= PcdNvStoreDfBuffer
[0].TokenCName
, PcdNvStoreDfBuffer
[0].TokenSpaceGuidCName
1689 if (PcdName
,PcdGuid
) in VpdSkuMap
:
1690 DefaultSku
= PcdNvStoreDfBuffer
[0].SkuInfoList
.get(TAB_DEFAULT
)
1691 VpdSkuMap
[(PcdName
,PcdGuid
)] = {DefaultSku
.DefaultValue
:[SkuObj
for SkuObj
in PcdNvStoreDfBuffer
[0].SkuInfoList
.values() ]}
1693 # Process VPD map file generated by third party BPDG tool
1694 if NeedProcessVpdMapFile
:
1695 VpdMapFilePath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
, "%s.map" % self
.Platform
.VpdToolGuid
)
1696 if os
.path
.exists(VpdMapFilePath
):
1697 VpdFile
.Read(VpdMapFilePath
)
1699 # Fixup TAB_STAR offset
1700 for pcd
in VpdSkuMap
:
1701 vpdinfo
= VpdFile
.GetVpdInfo(pcd
)
1703 # just pick the a value to determine whether is unicode string type
1705 for pcdvalue
in VpdSkuMap
[pcd
]:
1706 for sku
in VpdSkuMap
[pcd
][pcdvalue
]:
1707 for item
in vpdinfo
:
1708 if item
[2] == pcdvalue
:
1709 sku
.VpdOffset
= item
[1]
1711 EdkLogger
.error("build", FILE_READ_FAILURE
, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath
)
1713 # Delete the DynamicPcdList At the last time enter into this function
1714 for Pcd
in self
._DynamicPcdList
:
1715 # just pick the a value to determine whether is unicode string type
1716 Sku
= Pcd
.SkuInfoList
.get(TAB_DEFAULT
)
1717 Sku
.VpdOffset
= Sku
.VpdOffset
.strip()
1719 if Pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
1720 Pcd
.DatumType
= TAB_VOID
1722 PcdValue
= Sku
.DefaultValue
1723 if Pcd
.DatumType
== TAB_VOID
and PcdValue
.startswith("L"):
1724 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
1725 UnicodePcdArray
.add(Pcd
)
1726 elif len(Sku
.VariableName
) > 0:
1727 # if found HII type PCD then insert to right of UnicodeIndex
1728 HiiPcdArray
.add(Pcd
)
1730 OtherPcdArray
.add(Pcd
)
1731 del self
._DynamicPcdList
[:]
1732 self
._DynamicPcdList
.extend(list(UnicodePcdArray
))
1733 self
._DynamicPcdList
.extend(list(HiiPcdArray
))
1734 self
._DynamicPcdList
.extend(list(OtherPcdArray
))
1735 allskuset
= [(SkuName
, Sku
.SkuId
) for pcd
in self
._DynamicPcdList
for (SkuName
, Sku
) in pcd
.SkuInfoList
.items()]
1736 for pcd
in self
._DynamicPcdList
:
1737 if len(pcd
.SkuInfoList
) == 1:
1738 for (SkuName
, SkuId
) in allskuset
:
1739 if isinstance(SkuId
, str) and eval(SkuId
) == 0 or SkuId
== 0:
1741 pcd
.SkuInfoList
[SkuName
] = copy
.deepcopy(pcd
.SkuInfoList
[TAB_DEFAULT
])
1742 pcd
.SkuInfoList
[SkuName
].SkuId
= SkuId
1743 pcd
.SkuInfoList
[SkuName
].SkuIdName
= SkuName
1745 def FixVpdOffset(self
, VpdFile
):
1746 FvPath
= os
.path
.join(self
.BuildDir
, TAB_FV_DIRECTORY
)
1747 if not os
.path
.exists(FvPath
):
1751 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Fail to create FV folder under %s" % self
.BuildDir
)
1753 VpdFilePath
= os
.path
.join(FvPath
, "%s.txt" % self
.Platform
.VpdToolGuid
)
1755 if VpdFile
.Write(VpdFilePath
):
1756 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
1758 for ToolDef
in self
.ToolDefinition
.values():
1759 if TAB_GUID
in ToolDef
and ToolDef
[TAB_GUID
] == self
.Platform
.VpdToolGuid
:
1760 if "PATH" not in ToolDef
:
1761 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self
.Platform
.VpdToolGuid
)
1762 BPDGToolName
= ToolDef
["PATH"]
1764 # Call third party GUID BPDG tool.
1765 if BPDGToolName
is not None:
1766 VpdInfoFile
.CallExtenalBPDGTool(BPDGToolName
, VpdFilePath
)
1768 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.")
1770 ## Return the platform build data object
1773 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
1775 ## Return platform name
1778 return self
.Platform
.PlatformName
1780 ## Return the meta file GUID
1783 return self
.Platform
.Guid
1785 ## Return the platform version
1788 return self
.Platform
.Version
1790 ## Return the FDF file name
1793 if self
.Workspace
.FdfFile
:
1794 RetVal
= mws
.join(self
.WorkspaceDir
, self
.Workspace
.FdfFile
)
1799 ## Return the build output directory platform specifies
1801 def OutputDir(self
):
1802 return self
.Platform
.OutputDirectory
1804 ## Return the directory to store all intermediate and final files built
1807 if os
.path
.isabs(self
.OutputDir
):
1808 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1809 path
.abspath(self
.OutputDir
),
1810 self
.BuildTarget
+ "_" + self
.ToolChain
,
1813 GlobalData
.gBuildDirectory
= RetVal
= path
.join(
1816 self
.BuildTarget
+ "_" + self
.ToolChain
,
1820 ## Return directory of platform makefile
1822 # @retval string Makefile directory
1825 def MakeFileDir(self
):
1826 return path
.join(self
.BuildDir
, self
.Arch
)
1828 ## Return build command string
1830 # @retval string Build command string
1833 def BuildCommand(self
):
1835 if "MAKE" in self
.ToolDefinition
and "PATH" in self
.ToolDefinition
["MAKE"]:
1836 RetVal
+= _SplitOption(self
.ToolDefinition
["MAKE"]["PATH"])
1837 if "FLAGS" in self
.ToolDefinition
["MAKE"]:
1838 NewOption
= self
.ToolDefinition
["MAKE"]["FLAGS"].strip()
1840 RetVal
+= _SplitOption(NewOption
)
1841 if "MAKE" in self
.EdkIIBuildOption
:
1842 if "FLAGS" in self
.EdkIIBuildOption
["MAKE"]:
1843 Flags
= self
.EdkIIBuildOption
["MAKE"]["FLAGS"]
1844 if Flags
.startswith('='):
1845 RetVal
= [RetVal
[0]] + [Flags
[1:]]
1847 RetVal
.append(Flags
)
1850 ## Get tool chain definition
1852 # Get each tool definition for given tool chain from tools_def.txt and platform
1855 def ToolDefinition(self
):
1856 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDictionary
1857 if TAB_TOD_DEFINES_COMMAND_TYPE
not in self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
:
1858 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No tools found in configuration",
1859 ExtraData
="[%s]" % self
.MetaFile
)
1862 for Def
in ToolDefinition
:
1863 Target
, Tag
, Arch
, Tool
, Attr
= Def
.split("_")
1864 if Target
!= self
.BuildTarget
or Tag
!= self
.ToolChain
or Arch
!= self
.Arch
:
1867 Value
= ToolDefinition
[Def
]
1868 # don't record the DLL
1870 DllPathList
.add(Value
)
1873 if Tool
not in RetVal
:
1875 RetVal
[Tool
][Attr
] = Value
1878 if GlobalData
.gOptions
.SilentMode
and "MAKE" in RetVal
:
1879 if "FLAGS" not in RetVal
["MAKE"]:
1880 RetVal
["MAKE"]["FLAGS"] = ""
1881 RetVal
["MAKE"]["FLAGS"] += " -s"
1884 for Attr
in RetVal
[Tool
]:
1885 Value
= RetVal
[Tool
][Attr
]
1886 if Tool
in self
._BuildOptionWithToolDef
(RetVal
) and Attr
in self
._BuildOptionWithToolDef
(RetVal
)[Tool
]:
1887 # check if override is indicated
1888 if self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
].startswith('='):
1889 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
][1:]
1892 Value
+= " " + self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1894 Value
= self
._BuildOptionWithToolDef
(RetVal
)[Tool
][Attr
]
1897 # Don't put MAKE definition in the file
1899 ToolsDef
+= "%s = %s\n" % (Tool
, Value
)
1901 # Don't put MAKE definition in the file
1906 ToolsDef
+= "%s_%s = %s\n" % (Tool
, Attr
, Value
)
1909 SaveFileOnChange(self
.ToolDefinitionFile
, ToolsDef
, False)
1910 for DllPath
in DllPathList
:
1911 os
.environ
["PATH"] = DllPath
+ os
.pathsep
+ os
.environ
["PATH"]
1912 os
.environ
["MAKE_FLAGS"] = MakeFlags
1916 ## Return the paths of tools
1918 def ToolDefinitionFile(self
):
1919 return os
.path
.join(self
.MakeFileDir
, "TOOLS_DEF." + self
.Arch
)
1921 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
1923 def ToolChainFamily(self
):
1924 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1925 if TAB_TOD_DEFINES_FAMILY
not in ToolDefinition \
1926 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_FAMILY
] \
1927 or not ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]:
1928 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1930 RetVal
= TAB_COMPILER_MSFT
1932 RetVal
= ToolDefinition
[TAB_TOD_DEFINES_FAMILY
][self
.ToolChain
]
1936 def BuildRuleFamily(self
):
1937 ToolDefinition
= self
.Workspace
.ToolDef
.ToolsDefTxtDatabase
1938 if TAB_TOD_DEFINES_BUILDRULEFAMILY
not in ToolDefinition \
1939 or self
.ToolChain
not in ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
1940 or not ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]:
1941 EdkLogger
.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
1943 return TAB_COMPILER_MSFT
1945 return ToolDefinition
[TAB_TOD_DEFINES_BUILDRULEFAMILY
][self
.ToolChain
]
1947 ## Return the build options specific for all modules in this platform
1949 def BuildOption(self
):
1950 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
)
1952 def _BuildOptionWithToolDef(self
, ToolDef
):
1953 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, ToolDef
=ToolDef
)
1955 ## Return the build options specific for EDK modules in this platform
1957 def EdkBuildOption(self
):
1958 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDK_NAME
)
1960 ## Return the build options specific for EDKII modules in this platform
1962 def EdkIIBuildOption(self
):
1963 return self
._ExpandBuildOption
(self
.Platform
.BuildOptions
, EDKII_NAME
)
1965 ## Parse build_rule.txt in Conf Directory.
1967 # @retval BuildRule object
1970 def BuildRule(self
):
1971 BuildRuleFile
= None
1972 if TAB_TAT_DEFINES_BUILD_RULE_CONF
in self
.Workspace
.TargetTxt
.TargetTxtDictionary
:
1973 BuildRuleFile
= self
.Workspace
.TargetTxt
.TargetTxtDictionary
[TAB_TAT_DEFINES_BUILD_RULE_CONF
]
1974 if not BuildRuleFile
:
1975 BuildRuleFile
= gDefaultBuildRuleFile
1976 RetVal
= BuildRule(BuildRuleFile
)
1977 if RetVal
._FileVersion
== "":
1978 RetVal
._FileVersion
= AutoGenReqBuildRuleVerNum
1980 if RetVal
._FileVersion
< AutoGenReqBuildRuleVerNum
:
1981 # If Build Rule's version is less than the version number required by the tools, halting the build.
1982 EdkLogger
.error("build", AUTOGEN_ERROR
,
1983 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])"\
1984 % (RetVal
._FileVersion
, AutoGenReqBuildRuleVerNum
))
1987 ## Summarize the packages used by modules in this platform
1989 def PackageList(self
):
1991 for La
in self
.LibraryAutoGenList
:
1992 RetVal
.update(La
.DependentPackageList
)
1993 for Ma
in self
.ModuleAutoGenList
:
1994 RetVal
.update(Ma
.DependentPackageList
)
1995 #Collect package set information from INF of FDF
1996 for ModuleFile
in self
._AsBuildModuleList
:
1997 if ModuleFile
in self
.Platform
.Modules
:
1999 ModuleData
= self
.BuildDatabase
[ModuleFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2000 RetVal
.update(ModuleData
.Packages
)
2004 def NonDynamicPcdDict(self
):
2005 return {(Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
):Pcd
for Pcd
in self
.NonDynamicPcdList
}
2007 ## Get list of non-dynamic PCDs
2009 def NonDynamicPcdList(self
):
2010 if not self
._NonDynamicPcdList
:
2011 self
.CollectPlatformDynamicPcds()
2012 return self
._NonDynamicPcdList
2014 ## Get list of dynamic PCDs
2016 def DynamicPcdList(self
):
2017 if not self
._DynamicPcdList
:
2018 self
.CollectPlatformDynamicPcds()
2019 return self
._DynamicPcdList
2021 ## Generate Token Number for all PCD
2023 def PcdTokenNumber(self
):
2024 RetVal
= OrderedDict()
2027 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
2031 # TokenNumber 0 ~ 10
2033 # TokeNumber 11 ~ 20
2035 for Pcd
in self
.DynamicPcdList
:
2036 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2037 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2038 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2041 for Pcd
in self
.DynamicPcdList
:
2042 if Pcd
.Phase
== "PEI" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2043 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2044 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2047 for Pcd
in self
.DynamicPcdList
:
2048 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_TYPE_SET
:
2049 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2050 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2053 for Pcd
in self
.DynamicPcdList
:
2054 if Pcd
.Phase
== "DXE" and Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
2055 EdkLogger
.debug(EdkLogger
.DEBUG_5
, "%s %s (%s) -> %d" % (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, Pcd
.Phase
, TokenNumber
))
2056 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2059 for Pcd
in self
.NonDynamicPcdList
:
2060 RetVal
[Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
] = TokenNumber
2066 for ModuleFile
in self
.Platform
.Modules
:
2075 self
.Platform
.Modules
[ModuleFile
].M
= Ma
2076 return [x
.M
for x
in self
.Platform
.Modules
.values()]
2078 ## Summarize ModuleAutoGen objects of all modules to be built for this platform
2080 def ModuleAutoGenList(self
):
2082 for Ma
in self
._MaList
:
2083 if Ma
not in RetVal
:
2087 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2089 def LibraryAutoGenList(self
):
2091 for Ma
in self
._MaList
:
2092 for La
in Ma
.LibraryAutoGenList
:
2093 if La
not in RetVal
:
2095 if Ma
not in La
.ReferenceModules
:
2096 La
.ReferenceModules
.append(Ma
)
2099 ## Test if a module is supported by the platform
2101 # An error will be raised directly if the module or its arch is not supported
2102 # by the platform or current configuration
2104 def ValidModule(self
, Module
):
2105 return Module
in self
.Platform
.Modules
or Module
in self
.Platform
.LibraryInstances \
2106 or Module
in self
._AsBuildModuleList
2108 ## Resolve the library classes in a module to library instances
2110 # This method will not only resolve library classes but also sort the library
2111 # instances according to the dependency-ship.
2113 # @param Module The module from which the library classes will be resolved
2115 # @retval library_list List of library instances sorted
2117 def ApplyLibraryInstance(self
, Module
):
2118 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
2119 if str(Module
) not in self
.Platform
.Modules
:
2122 return GetModuleLibInstances(Module
,
2131 ## Override PCD setting (type, value, ...)
2133 # @param ToPcd The PCD to be overridden
2134 # @param FromPcd The PCD overriding from
2136 def _OverridePcd(self
, ToPcd
, FromPcd
, Module
="", Msg
="", Library
=""):
2138 # in case there's PCDs coming from FDF file, which have no type given.
2139 # at this point, ToPcd.Type has the type found from dependent
2142 TokenCName
= ToPcd
.TokenCName
2143 for PcdItem
in GlobalData
.MixedPcd
:
2144 if (ToPcd
.TokenCName
, ToPcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
2145 TokenCName
= PcdItem
[0]
2147 if FromPcd
is not None:
2148 if ToPcd
.Pending
and FromPcd
.Type
:
2149 ToPcd
.Type
= FromPcd
.Type
2150 elif ToPcd
.Type
and FromPcd
.Type\
2151 and ToPcd
.Type
!= FromPcd
.Type
and ToPcd
.Type
in FromPcd
.Type
:
2152 if ToPcd
.Type
.strip() == TAB_PCDS_DYNAMIC_EX
:
2153 ToPcd
.Type
= FromPcd
.Type
2154 elif ToPcd
.Type
and FromPcd
.Type \
2155 and ToPcd
.Type
!= FromPcd
.Type
:
2157 Module
= str(Module
) + " 's library file (" + str(Library
) + ")"
2158 EdkLogger
.error("build", OPTION_CONFLICT
, "Mismatched PCD type",
2159 ExtraData
="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
2160 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
,
2161 ToPcd
.Type
, Module
, FromPcd
.Type
, Msg
),
2164 if FromPcd
.MaxDatumSize
:
2165 ToPcd
.MaxDatumSize
= FromPcd
.MaxDatumSize
2166 ToPcd
.MaxSizeUserSet
= FromPcd
.MaxDatumSize
2167 if FromPcd
.DefaultValue
:
2168 ToPcd
.DefaultValue
= FromPcd
.DefaultValue
2169 if FromPcd
.TokenValue
:
2170 ToPcd
.TokenValue
= FromPcd
.TokenValue
2171 if FromPcd
.DatumType
:
2172 ToPcd
.DatumType
= FromPcd
.DatumType
2173 if FromPcd
.SkuInfoList
:
2174 ToPcd
.SkuInfoList
= FromPcd
.SkuInfoList
2175 if FromPcd
.UserDefinedDefaultStoresFlag
:
2176 ToPcd
.UserDefinedDefaultStoresFlag
= FromPcd
.UserDefinedDefaultStoresFlag
2177 # Add Flexible PCD format parse
2178 if ToPcd
.DefaultValue
:
2180 ToPcd
.DefaultValue
= ValueExpressionEx(ToPcd
.DefaultValue
, ToPcd
.DatumType
, self
.Workspace
._GuidDict
)(True)
2181 except BadExpression
as Value
:
2182 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(ToPcd
.TokenSpaceGuidCName
, ToPcd
.TokenCName
, ToPcd
.DefaultValue
, Value
),
2185 # check the validation of datum
2186 IsValid
, Cause
= CheckPcdDatum(ToPcd
.DatumType
, ToPcd
.DefaultValue
)
2188 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, File
=self
.MetaFile
,
2189 ExtraData
="%s.%s" % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2190 ToPcd
.validateranges
= FromPcd
.validateranges
2191 ToPcd
.validlists
= FromPcd
.validlists
2192 ToPcd
.expressions
= FromPcd
.expressions
2193 ToPcd
.CustomAttribute
= FromPcd
.CustomAttribute
2195 if FromPcd
is not None and ToPcd
.DatumType
== TAB_VOID
and not ToPcd
.MaxDatumSize
:
2196 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "No MaxDatumSize specified for PCD %s.%s" \
2197 % (ToPcd
.TokenSpaceGuidCName
, TokenCName
))
2198 Value
= ToPcd
.DefaultValue
2200 ToPcd
.MaxDatumSize
= '1'
2201 elif Value
[0] == 'L':
2202 ToPcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2203 elif Value
[0] == '{':
2204 ToPcd
.MaxDatumSize
= str(len(Value
.split(',')))
2206 ToPcd
.MaxDatumSize
= str(len(Value
) - 1)
2208 # apply default SKU for dynamic PCDS if specified one is not available
2209 if (ToPcd
.Type
in PCD_DYNAMIC_TYPE_SET
or ToPcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
) \
2210 and not ToPcd
.SkuInfoList
:
2211 if self
.Platform
.SkuName
in self
.Platform
.SkuIds
:
2212 SkuName
= self
.Platform
.SkuName
2214 SkuName
= TAB_DEFAULT
2215 ToPcd
.SkuInfoList
= {
2216 SkuName
: SkuInfoClass(SkuName
, self
.Platform
.SkuIds
[SkuName
][0], '', '', '', '', '', ToPcd
.DefaultValue
)
2219 ## Apply PCD setting defined platform to a module
2221 # @param Module The module from which the PCD setting will be overridden
2223 # @retval PCD_list The list PCDs with settings from platform
2225 def ApplyPcdSetting(self
, Module
, Pcds
, Library
=""):
2226 # for each PCD in module
2227 for Name
, Guid
in Pcds
:
2228 PcdInModule
= Pcds
[Name
, Guid
]
2229 # find out the PCD setting in platform
2230 if (Name
, Guid
) in self
.Platform
.Pcds
:
2231 PcdInPlatform
= self
.Platform
.Pcds
[Name
, Guid
]
2233 PcdInPlatform
= None
2234 # then override the settings if any
2235 self
._OverridePcd
(PcdInModule
, PcdInPlatform
, Module
, Msg
="DSC PCD sections", Library
=Library
)
2236 # resolve the VariableGuid value
2237 for SkuId
in PcdInModule
.SkuInfoList
:
2238 Sku
= PcdInModule
.SkuInfoList
[SkuId
]
2239 if Sku
.VariableGuid
== '': continue
2240 Sku
.VariableGuidValue
= GuidValue(Sku
.VariableGuid
, self
.PackageList
, self
.MetaFile
.Path
)
2241 if Sku
.VariableGuidValue
is None:
2242 PackageList
= "\n\t".join(str(P
) for P
in self
.PackageList
)
2245 RESOURCE_NOT_AVAILABLE
,
2246 "Value of GUID [%s] is not found in" % Sku
.VariableGuid
,
2247 ExtraData
=PackageList
+ "\n\t(used with %s.%s from module %s)" \
2248 % (Guid
, Name
, str(Module
)),
2252 # override PCD settings with module specific setting
2253 if Module
in self
.Platform
.Modules
:
2254 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2255 for Key
in PlatformModule
.Pcds
:
2256 if GlobalData
.BuildOptionPcd
:
2257 for pcd
in GlobalData
.BuildOptionPcd
:
2258 (TokenSpaceGuidCName
, TokenCName
, FieldName
, pcdvalue
, _
) = pcd
2259 if (TokenCName
, TokenSpaceGuidCName
) == Key
and FieldName
=="":
2260 PlatformModule
.Pcds
[Key
].DefaultValue
= pcdvalue
2261 PlatformModule
.Pcds
[Key
].PcdValueFromComm
= pcdvalue
2267 elif Key
in GlobalData
.MixedPcd
:
2268 for PcdItem
in GlobalData
.MixedPcd
[Key
]:
2270 ToPcd
= Pcds
[PcdItem
]
2274 self
._OverridePcd
(ToPcd
, PlatformModule
.Pcds
[Key
], Module
, Msg
="DSC Components Module scoped PCD section", Library
=Library
)
2275 # use PCD value to calculate the MaxDatumSize when it is not specified
2276 for Name
, Guid
in Pcds
:
2277 Pcd
= Pcds
[Name
, Guid
]
2278 if Pcd
.DatumType
== TAB_VOID
and not Pcd
.MaxDatumSize
:
2279 Pcd
.MaxSizeUserSet
= None
2280 Value
= Pcd
.DefaultValue
2282 Pcd
.MaxDatumSize
= '1'
2283 elif Value
[0] == 'L':
2284 Pcd
.MaxDatumSize
= str((len(Value
) - 2) * 2)
2285 elif Value
[0] == '{':
2286 Pcd
.MaxDatumSize
= str(len(Value
.split(',')))
2288 Pcd
.MaxDatumSize
= str(len(Value
) - 1)
2289 return list(Pcds
.values())
2293 ## Calculate the priority value of the build option
2295 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2297 # @retval Value Priority value based on the priority list.
2299 def CalculatePriorityValue(self
, Key
):
2300 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
.split('_')
2301 PriorityValue
= 0x11111
2302 if Target
== TAB_STAR
:
2303 PriorityValue
&= 0x01111
2304 if ToolChain
== TAB_STAR
:
2305 PriorityValue
&= 0x10111
2306 if Arch
== TAB_STAR
:
2307 PriorityValue
&= 0x11011
2308 if CommandType
== TAB_STAR
:
2309 PriorityValue
&= 0x11101
2310 if Attr
== TAB_STAR
:
2311 PriorityValue
&= 0x11110
2313 return self
.PrioList
["0x%0.5x" % PriorityValue
]
2316 ## Expand * in build option key
2318 # @param Options Options to be expanded
2319 # @param ToolDef Use specified ToolDef instead of full version.
2320 # This is needed during initialization to prevent
2321 # infinite recursion betweeh BuildOptions,
2322 # ToolDefinition, and this function.
2324 # @retval options Options expanded
2326 def _ExpandBuildOption(self
, Options
, ModuleStyle
=None, ToolDef
=None):
2328 ToolDef
= self
.ToolDefinition
2335 # Construct a list contain the build options which need override.
2339 # Key[0] -- tool family
2340 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
2342 if (Key
[0] == self
.BuildRuleFamily
and
2343 (ModuleStyle
is None or len(Key
) < 3 or (len(Key
) > 2 and Key
[2] == ModuleStyle
))):
2344 Target
, ToolChain
, Arch
, CommandType
, Attr
= Key
[1].split('_')
2345 if (Target
== self
.BuildTarget
or Target
== TAB_STAR
) and\
2346 (ToolChain
== self
.ToolChain
or ToolChain
== TAB_STAR
) and\
2347 (Arch
== self
.Arch
or Arch
== TAB_STAR
) and\
2348 Options
[Key
].startswith("="):
2350 if OverrideList
.get(Key
[1]) is not None:
2351 OverrideList
.pop(Key
[1])
2352 OverrideList
[Key
[1]] = Options
[Key
]
2355 # Use the highest priority value.
2357 if (len(OverrideList
) >= 2):
2358 KeyList
= list(OverrideList
.keys())
2359 for Index
in range(len(KeyList
)):
2360 NowKey
= KeyList
[Index
]
2361 Target1
, ToolChain1
, Arch1
, CommandType1
, Attr1
= NowKey
.split("_")
2362 for Index1
in range(len(KeyList
) - Index
- 1):
2363 NextKey
= KeyList
[Index1
+ Index
+ 1]
2365 # Compare two Key, if one is included by another, choose the higher priority one
2367 Target2
, ToolChain2
, Arch2
, CommandType2
, Attr2
= NextKey
.split("_")
2368 if (Target1
== Target2
or Target1
== TAB_STAR
or Target2
== TAB_STAR
) and\
2369 (ToolChain1
== ToolChain2
or ToolChain1
== TAB_STAR
or ToolChain2
== TAB_STAR
) and\
2370 (Arch1
== Arch2
or Arch1
== TAB_STAR
or Arch2
== TAB_STAR
) and\
2371 (CommandType1
== CommandType2
or CommandType1
== TAB_STAR
or CommandType2
== TAB_STAR
) and\
2372 (Attr1
== Attr2
or Attr1
== TAB_STAR
or Attr2
== TAB_STAR
):
2374 if self
.CalculatePriorityValue(NowKey
) > self
.CalculatePriorityValue(NextKey
):
2375 if Options
.get((self
.BuildRuleFamily
, NextKey
)) is not None:
2376 Options
.pop((self
.BuildRuleFamily
, NextKey
))
2378 if Options
.get((self
.BuildRuleFamily
, NowKey
)) is not None:
2379 Options
.pop((self
.BuildRuleFamily
, NowKey
))
2382 if ModuleStyle
is not None and len (Key
) > 2:
2383 # Check Module style is EDK or EDKII.
2384 # Only append build option for the matched style module.
2385 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2387 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2390 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2391 # if tool chain family doesn't match, skip it
2392 if Tool
in ToolDef
and Family
!= "":
2393 FamilyIsNull
= False
2394 if ToolDef
[Tool
].get(TAB_TOD_DEFINES_BUILDRULEFAMILY
, "") != "":
2395 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_BUILDRULEFAMILY
]:
2397 elif Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2400 # expand any wildcard
2401 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2402 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2403 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2404 if Tool
not in BuildOptions
:
2405 BuildOptions
[Tool
] = {}
2406 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2407 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2409 # append options for the same tool except PATH
2411 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2413 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2414 # Build Option Family has been checked, which need't to be checked again for family.
2415 if FamilyMatch
or FamilyIsNull
:
2419 if ModuleStyle
is not None and len (Key
) > 2:
2420 # Check Module style is EDK or EDKII.
2421 # Only append build option for the matched style module.
2422 if ModuleStyle
== EDK_NAME
and Key
[2] != EDK_NAME
:
2424 elif ModuleStyle
== EDKII_NAME
and Key
[2] != EDKII_NAME
:
2427 Target
, Tag
, Arch
, Tool
, Attr
= Key
[1].split("_")
2428 # if tool chain family doesn't match, skip it
2429 if Tool
not in ToolDef
or Family
== "":
2431 # option has been added before
2432 if Family
!= ToolDef
[Tool
][TAB_TOD_DEFINES_FAMILY
]:
2435 # expand any wildcard
2436 if Target
== TAB_STAR
or Target
== self
.BuildTarget
:
2437 if Tag
== TAB_STAR
or Tag
== self
.ToolChain
:
2438 if Arch
== TAB_STAR
or Arch
== self
.Arch
:
2439 if Tool
not in BuildOptions
:
2440 BuildOptions
[Tool
] = {}
2441 if Attr
!= "FLAGS" or Attr
not in BuildOptions
[Tool
] or Options
[Key
].startswith('='):
2442 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2444 # append options for the same tool except PATH
2446 BuildOptions
[Tool
][Attr
] += " " + Options
[Key
]
2448 BuildOptions
[Tool
][Attr
] = Options
[Key
]
2451 ## Append build options in platform to a module
2453 # @param Module The module to which the build options will be appended
2455 # @retval options The options appended with build options in platform
2457 def ApplyBuildOption(self
, Module
):
2458 # Get the different options for the different style module
2459 PlatformOptions
= self
.EdkIIBuildOption
2460 ModuleTypeOptions
= self
.Platform
.GetBuildOptionsByModuleType(EDKII_NAME
, Module
.ModuleType
)
2461 ModuleTypeOptions
= self
._ExpandBuildOption
(ModuleTypeOptions
)
2462 ModuleOptions
= self
._ExpandBuildOption
(Module
.BuildOptions
)
2463 if Module
in self
.Platform
.Modules
:
2464 PlatformModule
= self
.Platform
.Modules
[str(Module
)]
2465 PlatformModuleOptions
= self
._ExpandBuildOption
(PlatformModule
.BuildOptions
)
2467 PlatformModuleOptions
= {}
2469 BuildRuleOrder
= None
2470 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2471 for Tool
in Options
:
2472 for Attr
in Options
[Tool
]:
2473 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2474 BuildRuleOrder
= Options
[Tool
][Attr
]
2476 AllTools
= set(list(ModuleOptions
.keys()) + list(PlatformOptions
.keys()) +
2477 list(PlatformModuleOptions
.keys()) + list(ModuleTypeOptions
.keys()) +
2478 list(self
.ToolDefinition
.keys()))
2479 BuildOptions
= defaultdict(lambda: defaultdict(str))
2480 for Tool
in AllTools
:
2481 for Options
in [self
.ToolDefinition
, ModuleOptions
, PlatformOptions
, ModuleTypeOptions
, PlatformModuleOptions
]:
2482 if Tool
not in Options
:
2484 for Attr
in Options
[Tool
]:
2486 # Do not generate it in Makefile
2488 if Attr
== TAB_TOD_DEFINES_BUILDRULEORDER
:
2490 Value
= Options
[Tool
][Attr
]
2491 # check if override is indicated
2492 if Value
.startswith('='):
2493 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
[1:])
2496 BuildOptions
[Tool
][Attr
] += " " + mws
.handleWsMacro(Value
)
2498 BuildOptions
[Tool
][Attr
] = mws
.handleWsMacro(Value
)
2500 return BuildOptions
, BuildRuleOrder
2503 # extend lists contained in a dictionary with lists stored in another dictionary
2504 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
2506 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
2507 for Key
in CopyFromDict
:
2508 CopyToDict
[Key
].extend(CopyFromDict
[Key
])
2510 # Create a directory specified by a set of path elements and return the full path
2511 def _MakeDir(PathList
):
2512 RetVal
= path
.join(*PathList
)
2513 CreateDirectory(RetVal
)
2516 ## ModuleAutoGen class
2518 # This class encapsules the AutoGen behaviors for the build tools. In addition to
2519 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
2520 # to the [depex] section in module's inf file.
2522 class ModuleAutoGen(AutoGen
):
2523 # call super().__init__ then call the worker function with different parameter count
2524 def __init__(self
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2525 if not hasattr(self
, "_Init"):
2526 self
._InitWorker
(Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
)
2529 ## Cache the timestamps of metafiles of every module in a class attribute
2533 def __new__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
):
2534 # check if this module is employed by active platform
2535 if not PlatformAutoGen(Workspace
, args
[0], Target
, Toolchain
, Arch
).ValidModule(MetaFile
):
2536 EdkLogger
.verbose("Module [%s] for [%s] is not employed by active platform\n" \
2539 return super(ModuleAutoGen
, cls
).__new
__(cls
, Workspace
, MetaFile
, Target
, Toolchain
, Arch
, *args
, **kwargs
)
2541 ## Initialize ModuleAutoGen
2543 # @param Workspace EdkIIWorkspaceBuild object
2544 # @param ModuleFile The path of module file
2545 # @param Target Build target (DEBUG, RELEASE)
2546 # @param Toolchain Name of tool chain
2547 # @param Arch The arch the module supports
2548 # @param PlatformFile Platform meta-file
2550 def _InitWorker(self
, Workspace
, ModuleFile
, Target
, Toolchain
, Arch
, PlatformFile
):
2551 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "AutoGen module [%s] [%s]" % (ModuleFile
, Arch
))
2552 GlobalData
.gProcessingFile
= "%s [%s, %s, %s]" % (ModuleFile
, Arch
, Toolchain
, Target
)
2554 self
.Workspace
= Workspace
2555 self
.WorkspaceDir
= Workspace
.WorkspaceDir
2556 self
.MetaFile
= ModuleFile
2557 self
.PlatformInfo
= PlatformAutoGen(Workspace
, PlatformFile
, Target
, Toolchain
, Arch
)
2559 self
.SourceDir
= self
.MetaFile
.SubDir
2560 self
.SourceDir
= mws
.relpath(self
.SourceDir
, self
.WorkspaceDir
)
2562 self
.SourceOverrideDir
= None
2563 # use overridden path defined in DSC file
2564 if self
.MetaFile
.Key
in GlobalData
.gOverrideDir
:
2565 self
.SourceOverrideDir
= GlobalData
.gOverrideDir
[self
.MetaFile
.Key
]
2567 self
.ToolChain
= Toolchain
2568 self
.BuildTarget
= Target
2570 self
.ToolChainFamily
= self
.PlatformInfo
.ToolChainFamily
2571 self
.BuildRuleFamily
= self
.PlatformInfo
.BuildRuleFamily
2573 self
.IsCodeFileCreated
= False
2574 self
.IsAsBuiltInfCreated
= False
2575 self
.DepexGenerated
= False
2577 self
.BuildDatabase
= self
.Workspace
.BuildDatabase
2578 self
.BuildRuleOrder
= None
2581 self
._PcdComments
= OrderedListDict()
2582 self
._GuidComments
= OrderedListDict()
2583 self
._ProtocolComments
= OrderedListDict()
2584 self
._PpiComments
= OrderedListDict()
2585 self
._BuildTargets
= None
2586 self
._IntroBuildTargetList
= None
2587 self
._FinalBuildTargetList
= None
2588 self
._FileTypes
= None
2590 self
.AutoGenDepSet
= set()
2591 self
.ReferenceModules
= []
2596 return "%s [%s]" % (self
.MetaFile
, self
.Arch
)
2598 # Get FixedAtBuild Pcds of this Module
2600 def FixedAtBuildPcds(self
):
2602 for Pcd
in self
.ModulePcdList
:
2603 if Pcd
.Type
!= TAB_PCDS_FIXED_AT_BUILD
:
2605 if Pcd
not in RetVal
:
2610 def FixedVoidTypePcds(self
):
2612 for Pcd
in self
.FixedAtBuildPcds
:
2613 if Pcd
.DatumType
== TAB_VOID
:
2614 if '{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) not in RetVal
:
2615 RetVal
['{}.{}'.format(Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
)] = Pcd
.DefaultValue
2619 def UniqueBaseName(self
):
2620 BaseName
= self
.Name
2621 for Module
in self
.PlatformInfo
.ModuleAutoGenList
:
2622 if Module
.MetaFile
== self
.MetaFile
:
2624 if Module
.Name
== self
.Name
:
2625 if uuid
.UUID(Module
.Guid
) == uuid
.UUID(self
.Guid
):
2626 EdkLogger
.error("build", FILE_DUPLICATED
, 'Modules have same BaseName and FILE_GUID:\n'
2627 ' %s\n %s' % (Module
.MetaFile
, self
.MetaFile
))
2628 BaseName
= '%s_%s' % (self
.Name
, self
.Guid
)
2631 # Macros could be used in build_rule.txt (also Makefile)
2634 return OrderedDict((
2635 ("WORKSPACE" ,self
.WorkspaceDir
),
2636 ("MODULE_NAME" ,self
.Name
),
2637 ("MODULE_NAME_GUID" ,self
.UniqueBaseName
),
2638 ("MODULE_GUID" ,self
.Guid
),
2639 ("MODULE_VERSION" ,self
.Version
),
2640 ("MODULE_TYPE" ,self
.ModuleType
),
2641 ("MODULE_FILE" ,str(self
.MetaFile
)),
2642 ("MODULE_FILE_BASE_NAME" ,self
.MetaFile
.BaseName
),
2643 ("MODULE_RELATIVE_DIR" ,self
.SourceDir
),
2644 ("MODULE_DIR" ,self
.SourceDir
),
2645 ("BASE_NAME" ,self
.Name
),
2646 ("ARCH" ,self
.Arch
),
2647 ("TOOLCHAIN" ,self
.ToolChain
),
2648 ("TOOLCHAIN_TAG" ,self
.ToolChain
),
2649 ("TOOL_CHAIN_TAG" ,self
.ToolChain
),
2650 ("TARGET" ,self
.BuildTarget
),
2651 ("BUILD_DIR" ,self
.PlatformInfo
.BuildDir
),
2652 ("BIN_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2653 ("LIB_DIR" ,os
.path
.join(self
.PlatformInfo
.BuildDir
, self
.Arch
)),
2654 ("MODULE_BUILD_DIR" ,self
.BuildDir
),
2655 ("OUTPUT_DIR" ,self
.OutputDir
),
2656 ("DEBUG_DIR" ,self
.DebugDir
),
2657 ("DEST_DIR_OUTPUT" ,self
.OutputDir
),
2658 ("DEST_DIR_DEBUG" ,self
.DebugDir
),
2659 ("PLATFORM_NAME" ,self
.PlatformInfo
.Name
),
2660 ("PLATFORM_GUID" ,self
.PlatformInfo
.Guid
),
2661 ("PLATFORM_VERSION" ,self
.PlatformInfo
.Version
),
2662 ("PLATFORM_RELATIVE_DIR" ,self
.PlatformInfo
.SourceDir
),
2663 ("PLATFORM_DIR" ,mws
.join(self
.WorkspaceDir
, self
.PlatformInfo
.SourceDir
)),
2664 ("PLATFORM_OUTPUT_DIR" ,self
.PlatformInfo
.OutputDir
),
2665 ("FFS_OUTPUT_DIR" ,self
.FfsOutputDir
)
2668 ## Return the module build data object
2671 return self
.BuildDatabase
[self
.MetaFile
, self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
2673 ## Return the module name
2676 return self
.Module
.BaseName
2678 ## Return the module DxsFile if exist
2681 return self
.Module
.DxsFile
2683 ## Return the module meta-file GUID
2687 # To build same module more than once, the module path with FILE_GUID overridden has
2688 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
2689 # in DSC. The overridden GUID can be retrieved from file name
2691 if os
.path
.basename(self
.MetaFile
.File
) != os
.path
.basename(self
.MetaFile
.Path
):
2693 # Length of GUID is 36
2695 return os
.path
.basename(self
.MetaFile
.Path
)[:36]
2696 return self
.Module
.Guid
2698 ## Return the module version
2701 return self
.Module
.Version
2703 ## Return the module type
2705 def ModuleType(self
):
2706 return self
.Module
.ModuleType
2708 ## Return the component type (for Edk.x style of module)
2710 def ComponentType(self
):
2711 return self
.Module
.ComponentType
2713 ## Return the build type
2715 def BuildType(self
):
2716 return self
.Module
.BuildType
2718 ## Return the PCD_IS_DRIVER setting
2720 def PcdIsDriver(self
):
2721 return self
.Module
.PcdIsDriver
2723 ## Return the autogen version, i.e. module meta-file version
2725 def AutoGenVersion(self
):
2726 return self
.Module
.AutoGenVersion
2728 ## Check if the module is library or not
2730 def IsLibrary(self
):
2731 return bool(self
.Module
.LibraryClass
)
2733 ## Check if the module is binary module or not
2735 def IsBinaryModule(self
):
2736 return self
.Module
.IsBinaryModule
2738 ## Return the directory to store intermediate files of the module
2742 self
.PlatformInfo
.BuildDir
,
2745 self
.MetaFile
.BaseName
2748 ## Return the directory to store the intermediate object files of the module
2750 def OutputDir(self
):
2751 return _MakeDir((self
.BuildDir
, "OUTPUT"))
2753 ## Return the directory path to store ffs file
2755 def FfsOutputDir(self
):
2756 if GlobalData
.gFdfParser
:
2757 return path
.join(self
.PlatformInfo
.BuildDir
, TAB_FV_DIRECTORY
, "Ffs", self
.Guid
+ self
.Name
)
2760 ## Return the directory to store auto-gened source files of the module
2763 return _MakeDir((self
.BuildDir
, "DEBUG"))
2765 ## Return the path of custom file
2767 def CustomMakefile(self
):
2769 for Type
in self
.Module
.CustomMakefile
:
2770 MakeType
= gMakeTypeMap
[Type
] if Type
in gMakeTypeMap
else 'nmake'
2771 if self
.SourceOverrideDir
is not None:
2772 File
= os
.path
.join(self
.SourceOverrideDir
, self
.Module
.CustomMakefile
[Type
])
2773 if not os
.path
.exists(File
):
2774 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2776 File
= os
.path
.join(self
.SourceDir
, self
.Module
.CustomMakefile
[Type
])
2777 RetVal
[MakeType
] = File
2780 ## Return the directory of the makefile
2782 # @retval string The directory string of module's makefile
2785 def MakeFileDir(self
):
2786 return self
.BuildDir
2788 ## Return build command string
2790 # @retval string Build command string
2793 def BuildCommand(self
):
2794 return self
.PlatformInfo
.BuildCommand
2796 ## Get object list of all packages the module and its dependent libraries belong to
2798 # @retval list The list of package object
2801 def DerivedPackageList(self
):
2803 for M
in [self
.Module
] + self
.DependentLibraryList
:
2804 for Package
in M
.Packages
:
2805 if Package
in PackageList
:
2807 PackageList
.append(Package
)
2810 ## Get the depex string
2812 # @return : a string contain all depex expression.
2813 def _GetDepexExpresionString(self
):
2816 ## DPX_SOURCE IN Define section.
2817 if self
.Module
.DxsFile
:
2819 for M
in [self
.Module
] + self
.DependentLibraryList
:
2820 Filename
= M
.MetaFile
.Path
2821 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2822 DepexExpressionList
= InfObj
.GetDepexExpresionList()
2823 for DepexExpression
in DepexExpressionList
:
2824 for key
in DepexExpression
:
2825 Arch
, ModuleType
= key
2826 DepexExpr
= [x
for x
in DepexExpression
[key
] if not str(x
).startswith('#')]
2827 # the type of build module is USER_DEFINED.
2828 # All different DEPEX section tags would be copied into the As Built INF file
2829 # and there would be separate DEPEX section tags
2830 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2831 if (Arch
.upper() == self
.Arch
.upper()) and (ModuleType
.upper() != TAB_ARCH_COMMON
):
2832 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2834 if Arch
.upper() == TAB_ARCH_COMMON
or \
2835 (Arch
.upper() == self
.Arch
.upper() and \
2836 ModuleType
.upper() in [TAB_ARCH_COMMON
, self
.ModuleType
.upper()]):
2837 DepexList
.append({(Arch
, ModuleType
): DepexExpr
})
2839 #the type of build module is USER_DEFINED.
2840 if self
.ModuleType
.upper() == SUP_MODULE_USER_DEFINED
:
2841 for Depex
in DepexList
:
2843 DepexStr
+= '[Depex.%s.%s]\n' % key
2844 DepexStr
+= '\n'.join('# '+ val
for val
in Depex
[key
])
2847 return '[Depex.%s]\n' % self
.Arch
2850 #the type of build module not is USER_DEFINED.
2852 for Depex
in DepexList
:
2857 for D
in Depex
.values():
2858 DepexStr
+= ' '.join(val
for val
in D
)
2859 Index
= DepexStr
.find('END')
2860 if Index
> -1 and Index
== len(DepexStr
) - 3:
2861 DepexStr
= DepexStr
[:-3]
2862 DepexStr
= DepexStr
.strip()
2865 DepexStr
= DepexStr
.lstrip('(').rstrip(')').strip()
2867 return '[Depex.%s]\n' % self
.Arch
2868 return '[Depex.%s]\n# ' % self
.Arch
+ DepexStr
2870 ## Merge dependency expression
2872 # @retval list The token list of the dependency expression after parsed
2875 def DepexList(self
):
2876 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2881 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
2883 for M
in [self
.Module
] + self
.DependentLibraryList
:
2885 for D
in M
.Depex
[self
.Arch
, self
.ModuleType
]:
2887 DepexList
.append('AND')
2888 DepexList
.append('(')
2889 #replace D with value if D is FixedAtBuild PCD
2893 NewList
.append(item
)
2895 FixedVoidTypePcds
= {}
2896 if item
in self
.FixedVoidTypePcds
:
2897 FixedVoidTypePcds
= self
.FixedVoidTypePcds
2898 elif M
in self
.PlatformInfo
.LibraryAutoGenList
:
2899 Index
= self
.PlatformInfo
.LibraryAutoGenList
.index(M
)
2900 FixedVoidTypePcds
= self
.PlatformInfo
.LibraryAutoGenList
[Index
].FixedVoidTypePcds
2901 if item
not in FixedVoidTypePcds
:
2902 EdkLogger
.error("build", FORMAT_INVALID
, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item
))
2904 Value
= FixedVoidTypePcds
[item
]
2905 if len(Value
.split(',')) != 16:
2906 EdkLogger
.error("build", FORMAT_INVALID
,
2907 "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item
))
2908 NewList
.append(Value
)
2909 DepexList
.extend(NewList
)
2910 if DepexList
[-1] == 'END': # no need of a END at this time
2912 DepexList
.append(')')
2915 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexList
))
2916 if 'BEFORE' in DepexList
or 'AFTER' in DepexList
:
2918 if len(DepexList
) > 0:
2919 EdkLogger
.verbose('')
2920 return {self
.ModuleType
:DepexList
}
2922 ## Merge dependency expression
2924 # @retval list The token list of the dependency expression after parsed
2927 def DepexExpressionDict(self
):
2928 if self
.DxsFile
or self
.IsLibrary
or TAB_DEPENDENCY_EXPRESSION_FILE
in self
.FileTypes
:
2931 DepexExpressionString
= ''
2933 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
2935 for M
in [self
.Module
] + self
.DependentLibraryList
:
2937 for D
in M
.DepexExpression
[self
.Arch
, self
.ModuleType
]:
2938 if DepexExpressionString
!= '':
2939 DepexExpressionString
+= ' AND '
2940 DepexExpressionString
+= '('
2941 DepexExpressionString
+= D
2942 DepexExpressionString
= DepexExpressionString
.rstrip('END').strip()
2943 DepexExpressionString
+= ')'
2946 EdkLogger
.verbose("DEPEX[%s] (+%s) = %s" % (self
.Name
, M
.BaseName
, DepexExpressionString
))
2947 if 'BEFORE' in DepexExpressionString
or 'AFTER' in DepexExpressionString
:
2949 if len(DepexExpressionString
) > 0:
2950 EdkLogger
.verbose('')
2952 return {self
.ModuleType
:DepexExpressionString
}
2954 # Get the tiano core user extension, it is contain dependent library.
2955 # @retval: a list contain tiano core userextension.
2957 def _GetTianoCoreUserExtensionList(self
):
2958 TianoCoreUserExtentionList
= []
2959 for M
in [self
.Module
] + self
.DependentLibraryList
:
2960 Filename
= M
.MetaFile
.Path
2961 InfObj
= InfSectionParser
.InfSectionParser(Filename
)
2962 TianoCoreUserExtenList
= InfObj
.GetUserExtensionTianoCore()
2963 for TianoCoreUserExtent
in TianoCoreUserExtenList
:
2964 for Section
in TianoCoreUserExtent
:
2965 ItemList
= Section
.split(TAB_SPLIT
)
2967 if len(ItemList
) == 4:
2969 if Arch
.upper() == TAB_ARCH_COMMON
or Arch
.upper() == self
.Arch
.upper():
2971 TianoCoreList
.extend([TAB_SECTION_START
+ Section
+ TAB_SECTION_END
])
2972 TianoCoreList
.extend(TianoCoreUserExtent
[Section
][:])
2973 TianoCoreList
.append('\n')
2974 TianoCoreUserExtentionList
.append(TianoCoreList
)
2976 return TianoCoreUserExtentionList
2978 ## Return the list of specification version required for the module
2980 # @retval list The list of specification defined in module file
2983 def Specification(self
):
2984 return self
.Module
.Specification
2986 ## Tool option for the module build
2988 # @param PlatformInfo The object of PlatformBuildInfo
2989 # @retval dict The dict containing valid options
2992 def BuildOption(self
):
2993 RetVal
, self
.BuildRuleOrder
= self
.PlatformInfo
.ApplyBuildOption(self
.Module
)
2994 if self
.BuildRuleOrder
:
2995 self
.BuildRuleOrder
= ['.%s' % Ext
for Ext
in self
.BuildRuleOrder
.split()]
2998 ## Get include path list from tool option for the module build
3000 # @retval list The include path list
3003 def BuildOptionIncPathList(self
):
3005 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
3006 # is the former use /I , the Latter used -I to specify include directories
3008 if self
.PlatformInfo
.ToolChainFamily
in (TAB_COMPILER_MSFT
):
3009 BuildOptIncludeRegEx
= gBuildOptIncludePatternMsft
3010 elif self
.PlatformInfo
.ToolChainFamily
in ('INTEL', 'GCC', 'RVCT'):
3011 BuildOptIncludeRegEx
= gBuildOptIncludePatternOther
3014 # New ToolChainFamily, don't known whether there is option to specify include directories
3019 for Tool
in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
3021 FlagOption
= self
.BuildOption
[Tool
]['FLAGS']
3025 if self
.ToolChainFamily
!= 'RVCT':
3026 IncPathList
= [NormPath(Path
, self
.Macros
) for Path
in BuildOptIncludeRegEx
.findall(FlagOption
)]
3029 # RVCT may specify a list of directory seperated by commas
3032 for Path
in BuildOptIncludeRegEx
.findall(FlagOption
):
3033 PathList
= GetSplitList(Path
, TAB_COMMA_SPLIT
)
3034 IncPathList
.extend(NormPath(PathEntry
, self
.Macros
) for PathEntry
in PathList
)
3037 # EDK II modules must not reference header files outside of the packages they depend on or
3038 # within the module's directory tree. Report error if violation.
3040 if GlobalData
.gDisableIncludePathCheck
== False:
3041 for Path
in IncPathList
:
3042 if (Path
not in self
.IncludePathList
) and (CommonPath([Path
, self
.MetaFile
.Dir
]) != self
.MetaFile
.Dir
):
3043 ErrMsg
= "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path
, Tool
, FlagOption
)
3044 EdkLogger
.error("build",
3047 File
=str(self
.MetaFile
))
3048 RetVal
+= IncPathList
3051 ## Return a list of files which can be built from source
3053 # What kind of files can be built is determined by build rules in
3054 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
3057 def SourceFileList(self
):
3059 ToolChainTagSet
= {"", TAB_STAR
, self
.ToolChain
}
3060 ToolChainFamilySet
= {"", TAB_STAR
, self
.ToolChainFamily
, self
.BuildRuleFamily
}
3061 for F
in self
.Module
.Sources
:
3063 if F
.TagName
not in ToolChainTagSet
:
3064 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "The toolchain [%s] for processing file [%s] is found, "
3065 "but [%s] is currently used" % (F
.TagName
, str(F
), self
.ToolChain
))
3067 # match tool chain family or build rule family
3068 if F
.ToolChainFamily
not in ToolChainFamilySet
:
3071 "The file [%s] must be built by tools of [%s], " \
3072 "but current toolchain family is [%s], buildrule family is [%s]" \
3073 % (str(F
), F
.ToolChainFamily
, self
.ToolChainFamily
, self
.BuildRuleFamily
))
3076 # add the file path into search path list for file including
3077 if F
.Dir
not in self
.IncludePathList
:
3078 self
.IncludePathList
.insert(0, F
.Dir
)
3081 self
._MatchBuildRuleOrder
(RetVal
)
3084 self
._ApplyBuildRule
(F
, TAB_UNKNOWN_FILE
)
3087 def _MatchBuildRuleOrder(self
, FileList
):
3090 for SingleFile
in FileList
:
3091 if self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRuleOrder
and SingleFile
.Ext
in self
.BuildRules
:
3092 key
= SingleFile
.Path
.rsplit(SingleFile
.Ext
,1)[0]
3093 if key
in Order_Dict
:
3094 Order_Dict
[key
].append(SingleFile
.Ext
)
3096 Order_Dict
[key
] = [SingleFile
.Ext
]
3099 for F
in Order_Dict
:
3100 if len(Order_Dict
[F
]) > 1:
3101 Order_Dict
[F
].sort(key
=lambda i
: self
.BuildRuleOrder
.index(i
))
3102 for Ext
in Order_Dict
[F
][1:]:
3103 RemoveList
.append(F
+ Ext
)
3105 for item
in RemoveList
:
3106 FileList
.remove(item
)
3110 ## Return the list of unicode files
3112 def UnicodeFileList(self
):
3113 return self
.FileTypes
.get(TAB_UNICODE_FILE
,[])
3115 ## Return the list of vfr files
3117 def VfrFileList(self
):
3118 return self
.FileTypes
.get(TAB_VFR_FILE
, [])
3120 ## Return the list of Image Definition files
3122 def IdfFileList(self
):
3123 return self
.FileTypes
.get(TAB_IMAGE_FILE
,[])
3125 ## Return a list of files which can be built from binary
3127 # "Build" binary files are just to copy them to build directory.
3129 # @retval list The list of files which can be built later
3132 def BinaryFileList(self
):
3134 for F
in self
.Module
.Binaries
:
3135 if F
.Target
not in [TAB_ARCH_COMMON
, TAB_STAR
] and F
.Target
!= self
.BuildTarget
:
3138 self
._ApplyBuildRule
(F
, F
.Type
, BinaryFileList
=RetVal
)
3142 def BuildRules(self
):
3144 BuildRuleDatabase
= self
.PlatformInfo
.BuildRule
3145 for Type
in BuildRuleDatabase
.FileTypeList
:
3146 #first try getting build rule by BuildRuleFamily
3147 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.BuildRuleFamily
]
3149 # build type is always module type, but ...
3150 if self
.ModuleType
!= self
.BuildType
:
3151 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.BuildRuleFamily
]
3152 #second try getting build rule by ToolChainFamily
3154 RuleObject
= BuildRuleDatabase
[Type
, self
.BuildType
, self
.Arch
, self
.ToolChainFamily
]
3156 # build type is always module type, but ...
3157 if self
.ModuleType
!= self
.BuildType
:
3158 RuleObject
= BuildRuleDatabase
[Type
, self
.ModuleType
, self
.Arch
, self
.ToolChainFamily
]
3161 RuleObject
= RuleObject
.Instantiate(self
.Macros
)
3162 RetVal
[Type
] = RuleObject
3163 for Ext
in RuleObject
.SourceFileExtList
:
3164 RetVal
[Ext
] = RuleObject
3167 def _ApplyBuildRule(self
, File
, FileType
, BinaryFileList
=None):
3168 if self
._BuildTargets
is None:
3169 self
._IntroBuildTargetList
= set()
3170 self
._FinalBuildTargetList
= set()
3171 self
._BuildTargets
= defaultdict(set)
3172 self
._FileTypes
= defaultdict(set)
3174 if not BinaryFileList
:
3175 BinaryFileList
= self
.BinaryFileList
3177 SubDirectory
= os
.path
.join(self
.OutputDir
, File
.SubDir
)
3178 if not os
.path
.exists(SubDirectory
):
3179 CreateDirectory(SubDirectory
)
3185 # Make sure to get build rule order value
3189 while Index
< len(SourceList
):
3190 Source
= SourceList
[Index
]
3194 CreateDirectory(Source
.Dir
)
3196 if File
.IsBinary
and File
== Source
and File
in BinaryFileList
:
3197 # Skip all files that are not binary libraries
3198 if not self
.IsLibrary
:
3200 RuleObject
= self
.BuildRules
[TAB_DEFAULT_BINARY_FILE
]
3201 elif FileType
in self
.BuildRules
:
3202 RuleObject
= self
.BuildRules
[FileType
]
3203 elif Source
.Ext
in self
.BuildRules
:
3204 RuleObject
= self
.BuildRules
[Source
.Ext
]
3206 # stop at no more rules
3208 self
._FinalBuildTargetList
.add(LastTarget
)
3211 FileType
= RuleObject
.SourceFileType
3212 self
._FileTypes
[FileType
].add(Source
)
3214 # stop at STATIC_LIBRARY for library
3215 if self
.IsLibrary
and FileType
== TAB_STATIC_LIBRARY
:
3217 self
._FinalBuildTargetList
.add(LastTarget
)
3220 Target
= RuleObject
.Apply(Source
, self
.BuildRuleOrder
)
3223 self
._FinalBuildTargetList
.add(LastTarget
)
3225 elif not Target
.Outputs
:
3226 # Only do build for target with outputs
3227 self
._FinalBuildTargetList
.add(Target
)
3229 self
._BuildTargets
[FileType
].add(Target
)
3231 if not Source
.IsBinary
and Source
== File
:
3232 self
._IntroBuildTargetList
.add(Target
)
3234 # to avoid cyclic rule
3235 if FileType
in RuleChain
:
3238 RuleChain
.add(FileType
)
3239 SourceList
.extend(Target
.Outputs
)
3241 FileType
= TAB_UNKNOWN_FILE
3245 if self
._BuildTargets
is None:
3246 self
._IntroBuildTargetList
= set()
3247 self
._FinalBuildTargetList
= set()
3248 self
._BuildTargets
= defaultdict(set)
3249 self
._FileTypes
= defaultdict(set)
3251 #TRICK: call SourceFileList property to apply build rule for source files
3254 #TRICK: call _GetBinaryFileList to apply build rule for binary files
3257 return self
._BuildTargets
3260 def IntroTargetList(self
):
3262 return self
._IntroBuildTargetList
3265 def CodaTargetList(self
):
3267 return self
._FinalBuildTargetList
3270 def FileTypes(self
):
3272 return self
._FileTypes
3274 ## Get the list of package object the module depends on
3276 # @retval list The package object list
3279 def DependentPackageList(self
):
3280 return self
.Module
.Packages
3282 ## Return the list of auto-generated code file
3284 # @retval list The list of auto-generated file
3287 def AutoGenFileList(self
):
3288 AutoGenUniIdf
= self
.BuildType
!= 'UEFI_HII'
3289 UniStringBinBuffer
= BytesIO()
3290 IdfGenBinBuffer
= BytesIO()
3292 AutoGenC
= TemplateString()
3293 AutoGenH
= TemplateString()
3294 StringH
= TemplateString()
3295 StringIdf
= TemplateString()
3296 GenC
.CreateCode(self
, AutoGenC
, AutoGenH
, StringH
, AutoGenUniIdf
, UniStringBinBuffer
, StringIdf
, AutoGenUniIdf
, IdfGenBinBuffer
)
3298 # AutoGen.c is generated if there are library classes in inf, or there are object files
3300 if str(AutoGenC
) != "" and (len(self
.Module
.LibraryClasses
) > 0
3301 or TAB_OBJECT_FILE
in self
.FileTypes
):
3302 AutoFile
= PathClass(gAutoGenCodeFileName
, self
.DebugDir
)
3303 RetVal
[AutoFile
] = str(AutoGenC
)
3304 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3305 if str(AutoGenH
) != "":
3306 AutoFile
= PathClass(gAutoGenHeaderFileName
, self
.DebugDir
)
3307 RetVal
[AutoFile
] = str(AutoGenH
)
3308 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3309 if str(StringH
) != "":
3310 AutoFile
= PathClass(gAutoGenStringFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3311 RetVal
[AutoFile
] = str(StringH
)
3312 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3313 if UniStringBinBuffer
is not None and UniStringBinBuffer
.getvalue() != b
"":
3314 AutoFile
= PathClass(gAutoGenStringFormFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3315 RetVal
[AutoFile
] = UniStringBinBuffer
.getvalue()
3316 AutoFile
.IsBinary
= True
3317 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3318 if UniStringBinBuffer
is not None:
3319 UniStringBinBuffer
.close()
3320 if str(StringIdf
) != "":
3321 AutoFile
= PathClass(gAutoGenImageDefFileName
% {"module_name":self
.Name
}, self
.DebugDir
)
3322 RetVal
[AutoFile
] = str(StringIdf
)
3323 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3324 if IdfGenBinBuffer
is not None and IdfGenBinBuffer
.getvalue() != b
"":
3325 AutoFile
= PathClass(gAutoGenIdfFileName
% {"module_name":self
.Name
}, self
.OutputDir
)
3326 RetVal
[AutoFile
] = IdfGenBinBuffer
.getvalue()
3327 AutoFile
.IsBinary
= True
3328 self
._ApplyBuildRule
(AutoFile
, TAB_UNKNOWN_FILE
)
3329 if IdfGenBinBuffer
is not None:
3330 IdfGenBinBuffer
.close()
3333 ## Return the list of library modules explicitly or implicitly used by this module
3335 def DependentLibraryList(self
):
3336 # only merge library classes and PCD for non-library module
3339 return self
.PlatformInfo
.ApplyLibraryInstance(self
.Module
)
3341 ## Get the list of PCDs from current module
3343 # @retval list The list of PCD
3346 def ModulePcdList(self
):
3347 # apply PCD settings from platform
3348 RetVal
= self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, self
.Module
.Pcds
)
3349 ExtendCopyDictionaryLists(self
._PcdComments
, self
.Module
.PcdComments
)
3352 ## Get the list of PCDs from dependent libraries
3354 # @retval list The list of PCD
3357 def LibraryPcdList(self
):
3362 # get PCDs from dependent libraries
3363 for Library
in self
.DependentLibraryList
:
3364 PcdsInLibrary
= OrderedDict()
3365 ExtendCopyDictionaryLists(self
._PcdComments
, Library
.PcdComments
)
3366 for Key
in Library
.Pcds
:
3367 # skip duplicated PCDs
3368 if Key
in self
.Module
.Pcds
or Key
in Pcds
:
3371 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
3372 RetVal
.extend(self
.PlatformInfo
.ApplyPcdSetting(self
.Module
, PcdsInLibrary
, Library
=Library
))
3375 ## Get the GUID value mapping
3377 # @retval dict The mapping between GUID cname and its value
3381 RetVal
= OrderedDict(self
.Module
.Guids
)
3382 for Library
in self
.DependentLibraryList
:
3383 RetVal
.update(Library
.Guids
)
3384 ExtendCopyDictionaryLists(self
._GuidComments
, Library
.GuidComments
)
3385 ExtendCopyDictionaryLists(self
._GuidComments
, self
.Module
.GuidComments
)
3389 def GetGuidsUsedByPcd(self
):
3390 RetVal
= OrderedDict(self
.Module
.GetGuidsUsedByPcd())
3391 for Library
in self
.DependentLibraryList
:
3392 RetVal
.update(Library
.GetGuidsUsedByPcd())
3394 ## Get the protocol value mapping
3396 # @retval dict The mapping between protocol cname and its value
3399 def ProtocolList(self
):
3400 RetVal
= OrderedDict(self
.Module
.Protocols
)
3401 for Library
in self
.DependentLibraryList
:
3402 RetVal
.update(Library
.Protocols
)
3403 ExtendCopyDictionaryLists(self
._ProtocolComments
, Library
.ProtocolComments
)
3404 ExtendCopyDictionaryLists(self
._ProtocolComments
, self
.Module
.ProtocolComments
)
3407 ## Get the PPI value mapping
3409 # @retval dict The mapping between PPI cname and its value
3413 RetVal
= OrderedDict(self
.Module
.Ppis
)
3414 for Library
in self
.DependentLibraryList
:
3415 RetVal
.update(Library
.Ppis
)
3416 ExtendCopyDictionaryLists(self
._PpiComments
, Library
.PpiComments
)
3417 ExtendCopyDictionaryLists(self
._PpiComments
, self
.Module
.PpiComments
)
3420 ## Get the list of include search path
3422 # @retval list The list path
3425 def IncludePathList(self
):
3427 RetVal
.append(self
.MetaFile
.Dir
)
3428 RetVal
.append(self
.DebugDir
)
3430 for Package
in self
.Module
.Packages
:
3431 PackageDir
= mws
.join(self
.WorkspaceDir
, Package
.MetaFile
.Dir
)
3432 if PackageDir
not in RetVal
:
3433 RetVal
.append(PackageDir
)
3434 IncludesList
= Package
.Includes
3435 if Package
._PrivateIncludes
:
3436 if not self
.MetaFile
.Path
.startswith(PackageDir
):
3437 IncludesList
= list(set(Package
.Includes
).difference(set(Package
._PrivateIncludes
)))
3438 for Inc
in IncludesList
:
3439 if Inc
not in RetVal
:
3440 RetVal
.append(str(Inc
))
3444 def IncludePathLength(self
):
3445 return sum(len(inc
)+1 for inc
in self
.IncludePathList
)
3447 ## Get HII EX PCDs which maybe used by VFR
3449 # efivarstore used by VFR may relate with HII EX PCDs
3450 # Get the variable name and GUID from efivarstore and HII EX PCD
3451 # List the HII EX PCDs in As Built INF if both name and GUID match.
3453 # @retval list HII EX PCDs
3455 def _GetPcdsMaybeUsedByVfr(self
):
3456 if not self
.SourceFileList
:
3460 for SrcFile
in self
.SourceFileList
:
3461 if SrcFile
.Ext
.lower() != '.vfr':
3463 Vfri
= os
.path
.join(self
.OutputDir
, SrcFile
.BaseName
+ '.i')
3464 if not os
.path
.exists(Vfri
):
3466 VfriFile
= open(Vfri
, 'r')
3467 Content
= VfriFile
.read()
3469 Pos
= Content
.find('efivarstore')
3472 # Make sure 'efivarstore' is the start of efivarstore statement
3473 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
3476 while Index
>= 0 and Content
[Index
] in ' \t\r\n':
3478 if Index
>= 0 and Content
[Index
] != ';':
3479 Pos
= Content
.find('efivarstore', Pos
+ len('efivarstore'))
3482 # 'efivarstore' must be followed by name and guid
3484 Name
= gEfiVarStoreNamePattern
.search(Content
, Pos
)
3487 Guid
= gEfiVarStoreGuidPattern
.search(Content
, Pos
)
3490 NameArray
= _ConvertStringToByteArray('L"' + Name
.group(1) + '"')
3491 NameGuids
.add((NameArray
, GuidStructureStringToGuidString(Guid
.group(1))))
3492 Pos
= Content
.find('efivarstore', Name
.end())
3496 for Pcd
in self
.PlatformInfo
.Platform
.Pcds
.values():
3497 if Pcd
.Type
!= TAB_PCDS_DYNAMIC_EX_HII
:
3499 for SkuInfo
in Pcd
.SkuInfoList
.values():
3500 Value
= GuidValue(SkuInfo
.VariableGuid
, self
.PlatformInfo
.PackageList
, self
.MetaFile
.Path
)
3503 Name
= _ConvertStringToByteArray(SkuInfo
.VariableName
)
3504 Guid
= GuidStructureStringToGuidString(Value
)
3505 if (Name
, Guid
) in NameGuids
and Pcd
not in HiiExPcds
:
3506 HiiExPcds
.append(Pcd
)
3511 def _GenOffsetBin(self
):
3513 for SourceFile
in self
.Module
.Sources
:
3514 if SourceFile
.Type
.upper() == ".VFR" :
3516 # search the .map file to find the offset of vfr binary in the PE32+/TE file.
3518 VfrUniBaseName
[SourceFile
.BaseName
] = (SourceFile
.BaseName
+ "Bin")
3519 elif SourceFile
.Type
.upper() == ".UNI" :
3521 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
3523 VfrUniBaseName
["UniOffsetName"] = (self
.Name
+ "Strings")
3525 if not VfrUniBaseName
:
3527 MapFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".map")
3528 EfiFileName
= os
.path
.join(self
.OutputDir
, self
.Name
+ ".efi")
3529 VfrUniOffsetList
= GetVariableOffset(MapFileName
, EfiFileName
, list(VfrUniBaseName
.values()))
3530 if not VfrUniOffsetList
:
3533 OutputName
= '%sOffset.bin' % self
.Name
3534 UniVfrOffsetFileName
= os
.path
.join( self
.OutputDir
, OutputName
)
3537 fInputfile
= open(UniVfrOffsetFileName
, "wb+", 0)
3539 EdkLogger
.error("build", FILE_OPEN_FAILURE
, "File open failed for %s" % UniVfrOffsetFileName
, None)
3541 # Use a instance of BytesIO to cache data
3542 fStringIO
= BytesIO()
3544 for Item
in VfrUniOffsetList
:
3545 if (Item
[0].find("Strings") != -1):
3547 # UNI offset in image.
3549 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
3551 UniGuid
= b
'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
3552 fStringIO
.write(UniGuid
)
3553 UniValue
= pack ('Q', int (Item
[1], 16))
3554 fStringIO
.write (UniValue
)
3557 # VFR binary offset in image.
3559 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
3561 VfrGuid
= b
'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
3562 fStringIO
.write(VfrGuid
)
3563 VfrValue
= pack ('Q', int (Item
[1], 16))
3564 fStringIO
.write (VfrValue
)
3566 # write data into file.
3569 fInputfile
.write (fStringIO
.getvalue())
3571 EdkLogger
.error("build", FILE_WRITE_FAILURE
, "Write data to file %s failed, please check whether the "
3572 "file been locked or using by other applications." %UniVfrOffsetFileName
, None)
3578 ## Create AsBuilt INF file the module
3580 def CreateAsBuiltInf(self
, IsOnlyCopy
= False):
3581 self
.OutputFile
= set()
3582 if IsOnlyCopy
and GlobalData
.gBinCacheDest
:
3583 self
.CopyModuleToCache()
3586 if self
.IsAsBuiltInfCreated
:
3589 # Skip the following code for libraries
3593 # Skip the following code for modules with no source files
3594 if not self
.SourceFileList
:
3597 # Skip the following code for modules without any binary files
3598 if self
.BinaryFileList
:
3601 ### TODO: How to handles mixed source and binary modules
3603 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
3604 # Also find all packages that the DynamicEx PCDs depend on
3609 PcdTokenSpaceList
= []
3610 for Pcd
in self
.ModulePcdList
+ self
.LibraryPcdList
:
3611 if Pcd
.Type
== TAB_PCDS_PATCHABLE_IN_MODULE
:
3612 PatchablePcds
.append(Pcd
)
3613 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_PATCHABLE_IN_MODULE
))
3614 elif Pcd
.Type
in PCD_DYNAMIC_EX_TYPE_SET
:
3617 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
))
3618 PcdCheckList
.append((Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
))
3619 PcdTokenSpaceList
.append(Pcd
.TokenSpaceGuidCName
)
3620 GuidList
= OrderedDict(self
.GuidList
)
3621 for TokenSpace
in self
.GetGuidsUsedByPcd
:
3622 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
3623 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
3624 if TokenSpace
not in PcdTokenSpaceList
and TokenSpace
in GuidList
:
3625 GuidList
.pop(TokenSpace
)
3626 CheckList
= (GuidList
, self
.PpiList
, self
.ProtocolList
, PcdCheckList
)
3627 for Package
in self
.DerivedPackageList
:
3628 if Package
in Packages
:
3630 BeChecked
= (Package
.Guids
, Package
.Ppis
, Package
.Protocols
, Package
.Pcds
)
3632 for Index
in range(len(BeChecked
)):
3633 for Item
in CheckList
[Index
]:
3634 if Item
in BeChecked
[Index
]:
3635 Packages
.append(Package
)
3641 VfrPcds
= self
._GetPcdsMaybeUsedByVfr
()
3642 for Pkg
in self
.PlatformInfo
.PackageList
:
3645 for VfrPcd
in VfrPcds
:
3646 if ((VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC_EX
) in Pkg
.Pcds
or
3647 (VfrPcd
.TokenCName
, VfrPcd
.TokenSpaceGuidCName
, TAB_PCDS_DYNAMIC
) in Pkg
.Pcds
):
3648 Packages
.append(Pkg
)
3651 ModuleType
= SUP_MODULE_DXE_DRIVER
if self
.ModuleType
== SUP_MODULE_UEFI_DRIVER
and self
.DepexGenerated
else self
.ModuleType
3652 DriverType
= self
.PcdIsDriver
if self
.PcdIsDriver
else ''
3654 MDefs
= self
.Module
.Defines
3657 'module_name' : self
.Name
,
3658 'module_guid' : Guid
,
3659 'module_module_type' : ModuleType
,
3660 'module_version_string' : [MDefs
['VERSION_STRING']] if 'VERSION_STRING' in MDefs
else [],
3661 'pcd_is_driver_string' : [],
3662 'module_uefi_specification_version' : [],
3663 'module_pi_specification_version' : [],
3664 'module_entry_point' : self
.Module
.ModuleEntryPointList
,
3665 'module_unload_image' : self
.Module
.ModuleUnloadImageList
,
3666 'module_constructor' : self
.Module
.ConstructorList
,
3667 'module_destructor' : self
.Module
.DestructorList
,
3668 'module_shadow' : [MDefs
['SHADOW']] if 'SHADOW' in MDefs
else [],
3669 'module_pci_vendor_id' : [MDefs
['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs
else [],
3670 'module_pci_device_id' : [MDefs
['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs
else [],
3671 'module_pci_class_code' : [MDefs
['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs
else [],
3672 'module_pci_revision' : [MDefs
['PCI_REVISION']] if 'PCI_REVISION' in MDefs
else [],
3673 'module_build_number' : [MDefs
['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs
else [],
3674 'module_spec' : [MDefs
['SPEC']] if 'SPEC' in MDefs
else [],
3675 'module_uefi_hii_resource_section' : [MDefs
['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs
else [],
3676 'module_uni_file' : [MDefs
['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs
else [],
3677 'module_arch' : self
.Arch
,
3678 'package_item' : [Package
.MetaFile
.File
.replace('\\', '/') for Package
in Packages
],
3680 'patchablepcd_item' : [],
3682 'protocol_item' : [],
3686 'libraryclasses_item' : []
3689 if 'MODULE_UNI_FILE' in MDefs
:
3690 UNIFile
= os
.path
.join(self
.MetaFile
.Dir
, MDefs
['MODULE_UNI_FILE'])
3691 if os
.path
.isfile(UNIFile
):
3692 shutil
.copy2(UNIFile
, self
.OutputDir
)
3694 if self
.AutoGenVersion
> int(gInfSpecVersion
, 0):
3695 AsBuiltInfDict
['module_inf_version'] = '0x%08x' % self
.AutoGenVersion
3697 AsBuiltInfDict
['module_inf_version'] = gInfSpecVersion
3700 AsBuiltInfDict
['pcd_is_driver_string'].append(DriverType
)
3702 if 'UEFI_SPECIFICATION_VERSION' in self
.Specification
:
3703 AsBuiltInfDict
['module_uefi_specification_version'].append(self
.Specification
['UEFI_SPECIFICATION_VERSION'])
3704 if 'PI_SPECIFICATION_VERSION' in self
.Specification
:
3705 AsBuiltInfDict
['module_pi_specification_version'].append(self
.Specification
['PI_SPECIFICATION_VERSION'])
3707 OutputDir
= self
.OutputDir
.replace('\\', '/').strip('/')
3708 DebugDir
= self
.DebugDir
.replace('\\', '/').strip('/')
3709 for Item
in self
.CodaTargetList
:
3710 File
= Item
.Target
.Path
.replace('\\', '/').strip('/').replace(DebugDir
, '').replace(OutputDir
, '').strip('/')
3711 self
.OutputFile
.add(File
)
3712 if os
.path
.isabs(File
):
3713 File
= File
.replace('\\', '/').strip('/').replace(OutputDir
, '').strip('/')
3714 if Item
.Target
.Ext
.lower() == '.aml':
3715 AsBuiltInfDict
['binary_item'].append('ASL|' + File
)
3716 elif Item
.Target
.Ext
.lower() == '.acpi':
3717 AsBuiltInfDict
['binary_item'].append('ACPI|' + File
)
3718 elif Item
.Target
.Ext
.lower() == '.efi':
3719 AsBuiltInfDict
['binary_item'].append('PE32|' + self
.Name
+ '.efi')
3721 AsBuiltInfDict
['binary_item'].append('BIN|' + File
)
3722 if not self
.DepexGenerated
:
3723 DepexFile
= os
.path
.join(self
.OutputDir
, self
.Name
+ '.depex')
3724 if os
.path
.exists(DepexFile
):
3725 self
.DepexGenerated
= True
3726 if self
.DepexGenerated
:
3727 self
.OutputFile
.add(self
.Name
+ '.depex')
3728 if self
.ModuleType
in [SUP_MODULE_PEIM
]:
3729 AsBuiltInfDict
['binary_item'].append('PEI_DEPEX|' + self
.Name
+ '.depex')
3730 elif self
.ModuleType
in [SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_RUNTIME_DRIVER
, SUP_MODULE_DXE_SAL_DRIVER
, SUP_MODULE_UEFI_DRIVER
]:
3731 AsBuiltInfDict
['binary_item'].append('DXE_DEPEX|' + self
.Name
+ '.depex')
3732 elif self
.ModuleType
in [SUP_MODULE_DXE_SMM_DRIVER
]:
3733 AsBuiltInfDict
['binary_item'].append('SMM_DEPEX|' + self
.Name
+ '.depex')
3735 Bin
= self
._GenOffsetBin
()
3737 AsBuiltInfDict
['binary_item'].append('BIN|%s' % Bin
)
3738 self
.OutputFile
.add(Bin
)
3740 for Root
, Dirs
, Files
in os
.walk(OutputDir
):
3742 if File
.lower().endswith('.pdb'):
3743 AsBuiltInfDict
['binary_item'].append('DISPOSABLE|' + File
)
3744 self
.OutputFile
.add(File
)
3745 HeaderComments
= self
.Module
.HeaderComments
3747 for Index
in range(len(HeaderComments
)):
3748 if HeaderComments
[Index
].find('@BinaryHeader') != -1:
3749 HeaderComments
[Index
] = HeaderComments
[Index
].replace('@BinaryHeader', '@file')
3752 AsBuiltInfDict
['header_comments'] = '\n'.join(HeaderComments
[StartPos
:]).replace(':#', '://')
3753 AsBuiltInfDict
['tail_comments'] = '\n'.join(self
.Module
.TailComments
)
3756 (self
.ProtocolList
, self
._ProtocolComments
, 'protocol_item'),
3757 (self
.PpiList
, self
._PpiComments
, 'ppi_item'),
3758 (GuidList
, self
._GuidComments
, 'guid_item')
3760 for Item
in GenList
:
3761 for CName
in Item
[0]:
3762 Comments
= '\n '.join(Item
[1][CName
]) if CName
in Item
[1] else ''
3763 Entry
= Comments
+ '\n ' + CName
if Comments
else CName
3764 AsBuiltInfDict
[Item
[2]].append(Entry
)
3765 PatchList
= parsePcdInfoFromMapFile(
3766 os
.path
.join(self
.OutputDir
, self
.Name
+ '.map'),
3767 os
.path
.join(self
.OutputDir
, self
.Name
+ '.efi')
3770 for Pcd
in PatchablePcds
:
3771 TokenCName
= Pcd
.TokenCName
3772 for PcdItem
in GlobalData
.MixedPcd
:
3773 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3774 TokenCName
= PcdItem
[0]
3776 for PatchPcd
in PatchList
:
3777 if TokenCName
== PatchPcd
[0]:
3782 if Pcd
.DatumType
== 'BOOLEAN':
3783 BoolValue
= Pcd
.DefaultValue
.upper()
3784 if BoolValue
== 'TRUE':
3785 Pcd
.DefaultValue
= '1'
3786 elif BoolValue
== 'FALSE':
3787 Pcd
.DefaultValue
= '0'
3789 if Pcd
.DatumType
in TAB_PCD_NUMERIC_TYPES
:
3790 HexFormat
= '0x%02x'
3791 if Pcd
.DatumType
== TAB_UINT16
:
3792 HexFormat
= '0x%04x'
3793 elif Pcd
.DatumType
== TAB_UINT32
:
3794 HexFormat
= '0x%08x'
3795 elif Pcd
.DatumType
== TAB_UINT64
:
3796 HexFormat
= '0x%016x'
3797 PcdValue
= HexFormat
% int(Pcd
.DefaultValue
, 0)
3799 if Pcd
.MaxDatumSize
is None or Pcd
.MaxDatumSize
== '':
3800 EdkLogger
.error("build", AUTOGEN_ERROR
,
3801 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3803 ArraySize
= int(Pcd
.MaxDatumSize
, 0)
3804 PcdValue
= Pcd
.DefaultValue
3805 if PcdValue
[0] != '{':
3807 if PcdValue
[0] == 'L':
3809 PcdValue
= PcdValue
.lstrip('L')
3810 PcdValue
= eval(PcdValue
)
3812 for Index
in range(0, len(PcdValue
)):
3814 CharVal
= ord(PcdValue
[Index
])
3815 NewValue
= NewValue
+ '0x%02x' % (CharVal
& 0x00FF) + ', ' \
3816 + '0x%02x' % (CharVal
>> 8) + ', '
3818 NewValue
= NewValue
+ '0x%02x' % (ord(PcdValue
[Index
]) % 0x100) + ', '
3821 Padding
= Padding
* 2
3822 ArraySize
= ArraySize
// 2
3823 if ArraySize
< (len(PcdValue
) + 1):
3824 if Pcd
.MaxSizeUserSet
:
3825 EdkLogger
.error("build", AUTOGEN_ERROR
,
3826 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3829 ArraySize
= len(PcdValue
) + 1
3830 if ArraySize
> len(PcdValue
) + 1:
3831 NewValue
= NewValue
+ Padding
* (ArraySize
- len(PcdValue
) - 1)
3832 PcdValue
= NewValue
+ Padding
.strip().rstrip(',') + '}'
3833 elif len(PcdValue
.split(',')) <= ArraySize
:
3834 PcdValue
= PcdValue
.rstrip('}') + ', 0x00' * (ArraySize
- len(PcdValue
.split(',')))
3837 if Pcd
.MaxSizeUserSet
:
3838 EdkLogger
.error("build", AUTOGEN_ERROR
,
3839 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd
.TokenSpaceGuidCName
, TokenCName
)
3842 ArraySize
= len(PcdValue
) + 1
3843 PcdItem
= '%s.%s|%s|0x%X' % \
3844 (Pcd
.TokenSpaceGuidCName
, TokenCName
, PcdValue
, PatchPcd
[1])
3846 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3847 PcdComments
= '\n '.join(self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
])
3849 PcdItem
= PcdComments
+ '\n ' + PcdItem
3850 AsBuiltInfDict
['patchablepcd_item'].append(PcdItem
)
3852 for Pcd
in Pcds
+ VfrPcds
:
3855 TokenCName
= Pcd
.TokenCName
3856 for PcdItem
in GlobalData
.MixedPcd
:
3857 if (Pcd
.TokenCName
, Pcd
.TokenSpaceGuidCName
) in GlobalData
.MixedPcd
[PcdItem
]:
3858 TokenCName
= PcdItem
[0]
3860 if Pcd
.Type
== TAB_PCDS_DYNAMIC_EX_HII
:
3861 for SkuName
in Pcd
.SkuInfoList
:
3862 SkuInfo
= Pcd
.SkuInfoList
[SkuName
]
3863 HiiInfo
= '## %s|%s|%s' % (SkuInfo
.VariableName
, SkuInfo
.VariableGuid
, SkuInfo
.VariableOffset
)
3865 if (Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
) in self
._PcdComments
:
3866 PcdCommentList
= self
._PcdComments
[Pcd
.TokenSpaceGuidCName
, Pcd
.TokenCName
][:]
3870 for Index
, Comment
in enumerate(PcdCommentList
):
3871 for Usage
in UsageList
:
3872 if Comment
.find(Usage
) != -1:
3876 if UsageIndex
!= -1:
3877 PcdCommentList
[UsageIndex
] = '## %s %s %s' % (UsageStr
, HiiInfo
, PcdCommentList
[UsageIndex
].replace(UsageStr
, ''))
3879 PcdCommentList
.append('## UNDEFINED ' + HiiInfo
)
3880 PcdComments
= '\n '.join(PcdCommentList
)
3881 PcdEntry
= Pcd
.TokenSpaceGuidCName
+ '.' + TokenCName
3883 PcdEntry
= PcdComments
+ '\n ' + PcdEntry
3884 AsBuiltInfDict
['pcd_item'].append(PcdEntry
)
3885 for Item
in self
.BuildOption
:
3886 if 'FLAGS' in self
.BuildOption
[Item
]:
3887 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()))
3889 # Generated LibraryClasses section in comments.
3890 for Library
in self
.LibraryAutoGenList
:
3891 AsBuiltInfDict
['libraryclasses_item'].append(Library
.MetaFile
.File
.replace('\\', '/'))
3893 # Generated UserExtensions TianoCore section.
3894 # All tianocore user extensions are copied.
3896 for TianoCore
in self
._GetTianoCoreUserExtensionList
():
3897 UserExtStr
+= '\n'.join(TianoCore
)
3898 ExtensionFile
= os
.path
.join(self
.MetaFile
.Dir
, TianoCore
[1])
3899 if os
.path
.isfile(ExtensionFile
):
3900 shutil
.copy2(ExtensionFile
, self
.OutputDir
)
3901 AsBuiltInfDict
['userextension_tianocore_item'] = UserExtStr
3903 # Generated depex expression section in comments.
3904 DepexExpression
= self
._GetDepexExpresionString
()
3905 AsBuiltInfDict
['depexsection_item'] = DepexExpression
if DepexExpression
else ''
3907 AsBuiltInf
= TemplateString()
3908 AsBuiltInf
.Append(gAsBuiltInfHeaderString
.Replace(AsBuiltInfDict
))
3910 SaveFileOnChange(os
.path
.join(self
.OutputDir
, self
.Name
+ '.inf'), str(AsBuiltInf
), False)
3912 self
.IsAsBuiltInfCreated
= True
3913 if GlobalData
.gBinCacheDest
:
3914 self
.CopyModuleToCache()
3916 def CopyModuleToCache(self
):
3917 FileDir
= path
.join(GlobalData
.gBinCacheDest
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3918 CreateDirectory (FileDir
)
3919 HashFile
= path
.join(self
.BuildDir
, self
.Name
+ '.hash')
3920 ModuleFile
= path
.join(self
.OutputDir
, self
.Name
+ '.inf')
3921 if os
.path
.exists(HashFile
):
3922 shutil
.copy2(HashFile
, FileDir
)
3923 if os
.path
.exists(ModuleFile
):
3924 shutil
.copy2(ModuleFile
, FileDir
)
3925 if not self
.OutputFile
:
3926 Ma
= self
.BuildDatabase
[PathClass(ModuleFile
), self
.Arch
, self
.BuildTarget
, self
.ToolChain
]
3927 self
.OutputFile
= Ma
.Binaries
3929 for File
in self
.OutputFile
:
3931 if not os
.path
.isabs(File
):
3932 File
= os
.path
.join(self
.OutputDir
, File
)
3933 if os
.path
.exists(File
):
3934 shutil
.copy2(File
, FileDir
)
3936 def AttemptModuleCacheCopy(self
):
3937 if self
.IsBinaryModule
:
3939 FileDir
= path
.join(GlobalData
.gBinCacheSource
, self
.Arch
, self
.SourceDir
, self
.MetaFile
.BaseName
)
3940 HashFile
= path
.join(FileDir
, self
.Name
+ '.hash')
3941 if os
.path
.exists(HashFile
):
3942 f
= open(HashFile
, 'r')
3943 CacheHash
= f
.read()
3945 if GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3946 if CacheHash
== GlobalData
.gModuleHash
[self
.Arch
][self
.Name
]:
3947 for root
, dir, files
in os
.walk(FileDir
):
3949 if self
.Name
+ '.hash' in f
:
3950 shutil
.copy2(HashFile
, self
.BuildDir
)
3952 File
= path
.join(root
, f
)
3953 shutil
.copy2(File
, self
.OutputDir
)
3954 if self
.Name
== "PcdPeim" or self
.Name
== "PcdDxe":
3955 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
3959 ## Create makefile for the module and its dependent libraries
3961 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
3962 # dependent libraries will be created
3964 @cached_class_function
3965 def CreateMakeFile(self
, CreateLibraryMakeFile
=True, GenFfsList
= []):
3966 # nest this function inside it's only caller.
3967 def CreateTimeStamp():
3968 FileSet
= {self
.MetaFile
.Path
}
3970 for SourceFile
in self
.Module
.Sources
:
3971 FileSet
.add (SourceFile
.Path
)
3973 for Lib
in self
.DependentLibraryList
:
3974 FileSet
.add (Lib
.MetaFile
.Path
)
3976 for f
in self
.AutoGenDepSet
:
3977 FileSet
.add (f
.Path
)
3979 if os
.path
.exists (self
.TimeStampPath
):
3980 os
.remove (self
.TimeStampPath
)
3981 with
open(self
.TimeStampPath
, 'w+') as file:
3985 # Ignore generating makefile when it is a binary module
3986 if self
.IsBinaryModule
:
3989 self
.GenFfsList
= GenFfsList
3990 if not self
.IsLibrary
and CreateLibraryMakeFile
:
3991 for LibraryAutoGen
in self
.LibraryAutoGenList
:
3992 LibraryAutoGen
.CreateMakeFile()
3997 if len(self
.CustomMakefile
) == 0:
3998 Makefile
= GenMake
.ModuleMakefile(self
)
4000 Makefile
= GenMake
.CustomMakefile(self
)
4001 if Makefile
.Generate():
4002 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated makefile for module %s [%s]" %
4003 (self
.Name
, self
.Arch
))
4005 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of makefile for module %s [%s]" %
4006 (self
.Name
, self
.Arch
))
4010 def CopyBinaryFiles(self
):
4011 for File
in self
.Module
.Binaries
:
4013 DstPath
= os
.path
.join(self
.OutputDir
, os
.path
.basename(SrcPath
))
4014 CopyLongFilePath(SrcPath
, DstPath
)
4015 ## Create autogen code for the module and its dependent libraries
4017 # @param CreateLibraryCodeFile Flag indicating if or not the code of
4018 # dependent libraries will be created
4020 def CreateCodeFile(self
, CreateLibraryCodeFile
=True):
4021 if self
.IsCodeFileCreated
:
4024 # Need to generate PcdDatabase even PcdDriver is binarymodule
4025 if self
.IsBinaryModule
and self
.PcdIsDriver
!= '':
4026 CreatePcdDatabaseCode(self
, TemplateString(), TemplateString())
4028 if self
.IsBinaryModule
:
4030 self
.CopyBinaryFiles()
4033 if not self
.IsLibrary
and CreateLibraryCodeFile
:
4034 for LibraryAutoGen
in self
.LibraryAutoGenList
:
4035 LibraryAutoGen
.CreateCodeFile()
4041 IgoredAutoGenList
= []
4043 for File
in self
.AutoGenFileList
:
4044 if GenC
.Generate(File
.Path
, self
.AutoGenFileList
[File
], File
.IsBinary
):
4045 AutoGenList
.append(str(File
))
4047 IgoredAutoGenList
.append(str(File
))
4050 for ModuleType
in self
.DepexList
:
4051 # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
4052 if len(self
.DepexList
[ModuleType
]) == 0 or ModuleType
== SUP_MODULE_USER_DEFINED
:
4055 Dpx
= GenDepex
.DependencyExpression(self
.DepexList
[ModuleType
], ModuleType
, True)
4056 DpxFile
= gAutoGenDepexFileName
% {"module_name" : self
.Name
}
4058 if len(Dpx
.PostfixNotation
) != 0:
4059 self
.DepexGenerated
= True
4061 if Dpx
.Generate(path
.join(self
.OutputDir
, DpxFile
)):
4062 AutoGenList
.append(str(DpxFile
))
4064 IgoredAutoGenList
.append(str(DpxFile
))
4066 if IgoredAutoGenList
== []:
4067 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] files for module %s [%s]" %
4068 (" ".join(AutoGenList
), self
.Name
, self
.Arch
))
4069 elif AutoGenList
== []:
4070 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Skipped the generation of [%s] files for module %s [%s]" %
4071 (" ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4073 EdkLogger
.debug(EdkLogger
.DEBUG_9
, "Generated [%s] (skipped %s) files for module %s [%s]" %
4074 (" ".join(AutoGenList
), " ".join(IgoredAutoGenList
), self
.Name
, self
.Arch
))
4076 self
.IsCodeFileCreated
= True
4079 ## Summarize the ModuleAutoGen objects of all libraries used by this module
4081 def LibraryAutoGenList(self
):
4083 for Library
in self
.DependentLibraryList
:
4090 self
.PlatformInfo
.MetaFile
4092 if La
not in RetVal
:
4094 for Lib
in La
.CodaTargetList
:
4095 self
._ApplyBuildRule
(Lib
.Target
, TAB_UNKNOWN_FILE
)
4098 def GenModuleHash(self
):
4099 if self
.Arch
not in GlobalData
.gModuleHash
:
4100 GlobalData
.gModuleHash
[self
.Arch
] = {}
4102 # Add Platform level hash
4103 m
.update(GlobalData
.gPlatformHash
.encode('utf-8'))
4104 # Add Package level hash
4105 if self
.DependentPackageList
:
4106 for Pkg
in sorted(self
.DependentPackageList
, key
=lambda x
: x
.PackageName
):
4107 if Pkg
.PackageName
in GlobalData
.gPackageHash
[self
.Arch
]:
4108 m
.update(GlobalData
.gPackageHash
[self
.Arch
][Pkg
.PackageName
].encode('utf-8'))
4111 if self
.LibraryAutoGenList
:
4112 for Lib
in sorted(self
.LibraryAutoGenList
, key
=lambda x
: x
.Name
):
4113 if Lib
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4115 m
.update(GlobalData
.gModuleHash
[self
.Arch
][Lib
.Name
].encode('utf-8'))
4118 f
= open(str(self
.MetaFile
), 'rb')
4122 # Add Module's source files
4123 if self
.SourceFileList
:
4124 for File
in sorted(self
.SourceFileList
, key
=lambda x
: str(x
)):
4125 f
= open(str(File
), 'rb')
4130 ModuleHashFile
= path
.join(self
.BuildDir
, self
.Name
+ ".hash")
4131 if self
.Name
not in GlobalData
.gModuleHash
[self
.Arch
]:
4132 GlobalData
.gModuleHash
[self
.Arch
][self
.Name
] = m
.hexdigest()
4133 if GlobalData
.gBinCacheSource
:
4134 if self
.AttemptModuleCacheCopy():
4136 return SaveFileOnChange(ModuleHashFile
, m
.hexdigest(), False)
4138 ## Decide whether we can skip the ModuleAutoGen process
4139 def CanSkipbyHash(self
):
4140 if GlobalData
.gUseHashCache
:
4141 return not self
.GenModuleHash()
4144 ## Decide whether we can skip the ModuleAutoGen process
4145 # If any source file is newer than the module than we cannot skip
4148 if self
.MakeFileDir
in GlobalData
.gSikpAutoGenCache
:
4150 if not os
.path
.exists(self
.TimeStampPath
):
4152 #last creation time of the module
4153 DstTimeStamp
= os
.stat(self
.TimeStampPath
)[8]
4155 SrcTimeStamp
= self
.Workspace
._SrcTimeStamp
4156 if SrcTimeStamp
> DstTimeStamp
:
4159 with
open(self
.TimeStampPath
,'r') as f
:
4161 source
= source
.rstrip('\n')
4162 if not os
.path
.exists(source
):
4164 if source
not in ModuleAutoGen
.TimeDict
:
4165 ModuleAutoGen
.TimeDict
[source
] = os
.stat(source
)[8]
4166 if ModuleAutoGen
.TimeDict
[source
] > DstTimeStamp
:
4168 GlobalData
.gSikpAutoGenCache
.add(self
.MakeFileDir
)
4172 def TimeStampPath(self
):
4173 return os
.path
.join(self
.MakeFileDir
, 'AutoGenTimeStamp')