1## @file
2# This file is used to create a database used by build tool
3#
4# Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>
5# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6# SPDX-License-Identifier: BSD-2-Clause-Patent
7#
8
9## Platform build information from DSC file
10#
11#  This class is used to retrieve information stored in database and convert them
12# into PlatformBuildClassObject form for easier use for AutoGen.
13#
14from __future__ import print_function
15from __future__ import absolute_import
16from Common.StringUtils import *
17from Common.DataType import *
18from Common.Misc import *
19from types import *
20from Common.Expression import *
21from CommonDataClass.CommonClass import SkuInfoClass
22from Common.TargetTxtClassObject import TargetTxtDict
23from Common.ToolDefClassObject import ToolDefDict
24from .MetaDataTable import *
25from .MetaFileTable import *
26from .MetaFileParser import *
27
28from .WorkspaceCommon import GetDeclaredPcd
29from Common.Misc import AnalyzeDscPcd
30from Common.Misc import ProcessDuplicatedInf,RemoveCComments,ArrayIndex
31import re
32from Common.Parsing import IsValidWord
33from Common.VariableAttributes import VariableAttributes
34import Common.GlobalData as GlobalData
35import subprocess
36from functools import reduce
37from Common.Misc import SaveFileOnChange
38from Workspace.BuildClassObject import PlatformBuildClassObject, StructurePcd, PcdClassObject, ModuleBuildClassObject
39from collections import OrderedDict, defaultdict
40
41def _IsFieldValueAnArray (Value):
42    Value = Value.strip()
43    if Value.startswith(TAB_GUID) and Value.endswith(')'):
44        return True
45    if Value.startswith('L"') and Value.endswith('"')  and len(list(Value[2:-1])) > 1:
46        return True
47    if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
48        return True
49    if Value[0] == '{' and Value[-1] == '}':
50        return True
51    if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
52        return True
53    if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
54        return True
55    return False
56
57PcdValueInitName = 'PcdValueInit'
58PcdValueCommonName = 'PcdValueCommon'
59
60PcdMainCHeader = '''
61/**
62  DO NOT EDIT
63  FILE auto-generated
64**/
65
66#include <stdio.h>
67#include <stdlib.h>
68#include <string.h>
69#include <PcdValueCommon.h>
70'''
71
72PcdMainCEntry = '''
73int
74main (
75  int   argc,
76  char  *argv[]
77  )
78{
79  return PcdValueMain (argc, argv);
80}
81'''
82
83PcdMakefileHeader = '''
84#
85# DO NOT EDIT
86# This file is auto-generated by build utility
87#
88
89'''
90
91WindowsCFLAGS = 'CFLAGS = $(CFLAGS) /wd4200 /wd4034 /wd4101 '
92LinuxCFLAGS = 'BUILD_CFLAGS += -Wno-pointer-to-int-cast -Wno-unused-variable '
93PcdMakefileEnd = '''
94!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common
95!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app
96'''
97
98AppTarget = '''
99all: $(APPFILE)
100$(APPFILE): $(OBJECTS)
101%s
102'''
103
104PcdGccMakefile = '''
105MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C
106LIBS = -lCommon
107'''
108
109variablePattern = re.compile(r'[\t\s]*0[xX][a-fA-F0-9]+$')
110SkuIdPattern = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$')
111## regular expressions for finding decimal and hex numbers
112Pattern = re.compile('^[1-9]\d*|0$')
113HexPattern = re.compile(r'0[xX][0-9a-fA-F]+$')
114## Regular expression for finding header file inclusions
115from AutoGen.GenMake import gIncludePattern
116
117## Find dependencies for one source file
118#
119#  By searching recursively "#include" directive in file, find out all the
120#  files needed by given source file. The dependecies will be only searched
121#  in given search path list.
122#
123#   @param      SearchPathList  The list of search path
124#
125#   @retval     list            The list of files the given source file depends on
126#
127def GetDependencyList(FileStack, SearchPathList):
128    DepDb = dict()
129    DependencySet = set(FileStack)
130    while len(FileStack) > 0:
131        F = FileStack.pop()
132        FullPathDependList = []
133        CurrentFileDependencyList = []
134        if F in DepDb:
135            CurrentFileDependencyList = DepDb[F]
136        else:
137            try:
138                Fd = open(F, 'r')
139                FileContent = Fd.read()
140            except BaseException as X:
141                EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F + "\n\t" + str(X))
142            finally:
143                if "Fd" in dir(locals()):
144                    Fd.close()
145
146            if len(FileContent) == 0:
147                continue
148
149            try:
150                if FileContent[0] == 0xff or FileContent[0] == 0xfe:
151                    FileContent = FileContent.decode('utf-16')
152                else:
153                    FileContent = FileContent.decode()
154            except:
155                # The file is not txt file. for example .mcb file
156                continue
157            IncludedFileList = gIncludePattern.findall(FileContent)
158
159            for Inc in IncludedFileList:
160                Inc = Inc.strip()
161                Inc = os.path.normpath(Inc)
162                CurrentFileDependencyList.append(Inc)
163            DepDb[F] = CurrentFileDependencyList
164
165        CurrentFilePath = os.path.dirname(F)
166        PathList = [CurrentFilePath] + SearchPathList
167        for Inc in CurrentFileDependencyList:
168            for SearchPath in PathList:
169                FilePath = os.path.join(SearchPath, Inc)
170                if not os.path.exists(FilePath):
171                    continue
172                if FilePath not in DependencySet:
173                    FileStack.append(FilePath)
174                    FullPathDependList.append(FilePath)
175                break
176        DependencySet.update(FullPathDependList)
177    DependencyList = list(DependencySet)  # remove duplicate ones
178
179    return DependencyList
180
181class DscBuildData(PlatformBuildClassObject):
182    # dict used to convert PCD type in database to string used by build tool
183    _PCD_TYPE_STRING_ = {
184        MODEL_PCD_FIXED_AT_BUILD        :   TAB_PCDS_FIXED_AT_BUILD,
185        MODEL_PCD_PATCHABLE_IN_MODULE   :   TAB_PCDS_PATCHABLE_IN_MODULE,
186        MODEL_PCD_FEATURE_FLAG          :   TAB_PCDS_FEATURE_FLAG,
187        MODEL_PCD_DYNAMIC               :   TAB_PCDS_DYNAMIC,
188        MODEL_PCD_DYNAMIC_DEFAULT       :   TAB_PCDS_DYNAMIC,
189        MODEL_PCD_DYNAMIC_HII           :   TAB_PCDS_DYNAMIC_HII,
190        MODEL_PCD_DYNAMIC_VPD           :   TAB_PCDS_DYNAMIC_VPD,
191        MODEL_PCD_DYNAMIC_EX            :   TAB_PCDS_DYNAMIC_EX,
192        MODEL_PCD_DYNAMIC_EX_DEFAULT    :   TAB_PCDS_DYNAMIC_EX,
193        MODEL_PCD_DYNAMIC_EX_HII        :   TAB_PCDS_DYNAMIC_EX_HII,
194        MODEL_PCD_DYNAMIC_EX_VPD        :   TAB_PCDS_DYNAMIC_EX_VPD,
195    }
196
197    # dict used to convert part of [Defines] to members of DscBuildData directly
198    _PROPERTY_ = {
199        #
200        # Required Fields
201        #
202        TAB_DSC_DEFINES_PLATFORM_NAME           :   "_PlatformName",
203        TAB_DSC_DEFINES_PLATFORM_GUID           :   "_Guid",
204        TAB_DSC_DEFINES_PLATFORM_VERSION        :   "_Version",
205        TAB_DSC_DEFINES_DSC_SPECIFICATION       :   "_DscSpecification",
206        # TAB_DSC_DEFINES_OUTPUT_DIRECTORY        :   "_OutputDirectory",
207        # TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES :   "_SupArchList",
208        # TAB_DSC_DEFINES_BUILD_TARGETS           :   "_BuildTargets",
209        TAB_DSC_DEFINES_SKUID_IDENTIFIER        :   "_SkuName",
210        # TAB_DSC_DEFINES_FLASH_DEFINITION        :   "_FlashDefinition",
211        TAB_DSC_DEFINES_BUILD_NUMBER            :   "_BuildNumber",
212        TAB_DSC_DEFINES_MAKEFILE_NAME           :   "_MakefileName",
213        TAB_DSC_DEFINES_BS_BASE_ADDRESS         :   "_BsBaseAddress",
214        TAB_DSC_DEFINES_RT_BASE_ADDRESS         :   "_RtBaseAddress",
215        # TAB_DSC_DEFINES_RFC_LANGUAGES           :   "_RFCLanguages",
216        # TAB_DSC_DEFINES_ISO_LANGUAGES           :   "_ISOLanguages",
217    }
218
219    # used to compose dummy library class name for those forced library instances
220    _NullLibraryNumber = 0
221
222    ## Constructor of DscBuildData
223    #
224    #  Initialize object of DscBuildData
225    #
226    #   @param      FilePath        The path of platform description file
227    #   @param      RawData         The raw data of DSC file
228    #   @param      BuildDataBase   Database used to retrieve module/package information
229    #   @param      Arch            The target architecture
230    #   @param      Platform        (not used for DscBuildData)
231    #   @param      Macros          Macros used for replacement in DSC file
232    #
233    def __init__(self, FilePath, RawData, BuildDataBase, Arch=TAB_ARCH_COMMON, Target=None, Toolchain=None):
234        self.MetaFile = FilePath
235        self._RawData = RawData
236        self._Bdb = BuildDataBase
237        self._Arch = Arch
238        self._Target = Target
239        self._Toolchain = Toolchain
240        self._ToolChainFamily = None
241        self._Clear()
242        self.WorkspaceDir = os.getenv("WORKSPACE") if os.getenv("WORKSPACE") else ""
243        self.DefaultStores = None
244        self.SkuIdMgr = SkuClass(self.SkuName, self.SkuIds)
245
246    @property
247    def OutputPath(self):
248        if os.getenv("WORKSPACE"):
249            return os.path.join(os.getenv("WORKSPACE"), self.OutputDirectory, self._Target + "_" + self._Toolchain, PcdValueInitName)
250        else:
251            return os.path.dirname(self.DscFile)
252
253    ## XXX[key] = value
254    def __setitem__(self, key, value):
255        self.__dict__[self._PROPERTY_[key]] = value
256
257    ## value = XXX[key]
258    def __getitem__(self, key):
259        return self.__dict__[self._PROPERTY_[key]]
260
261    ## "in" test support
262    def __contains__(self, key):
263        return key in self._PROPERTY_
264
265    ## Set all internal used members of DscBuildData to None
266    def _Clear(self):
267        self._Header            = None
268        self._PlatformName      = None
269        self._Guid              = None
270        self._Version           = None
271        self._DscSpecification  = None
272        self._OutputDirectory   = None
273        self._SupArchList       = None
274        self._BuildTargets      = None
275        self._SkuName           = None
276        self._PcdInfoFlag       = None
277        self._VarCheckFlag      = None
278        self._FlashDefinition   = None
279        self._Prebuild          = None
280        self._Postbuild         = None
281        self._BuildNumber       = None
282        self._MakefileName      = None
283        self._BsBaseAddress     = None
284        self._RtBaseAddress     = None
285        self._SkuIds            = None
286        self._Modules           = None
287        self._LibraryInstances  = None
288        self._LibraryClasses    = None
289        self._Pcds              = None
290        self._DecPcds           = None
291        self._BuildOptions      = None
292        self._ModuleTypeOptions = None
293        self._LoadFixAddress    = None
294        self._RFCLanguages      = None
295        self._ISOLanguages      = None
296        self._VpdToolGuid       = None
297        self._MacroDict         = None
298        self.DefaultStores      = None
299
300    ## Get current effective macros
301    @property
302    def _Macros(self):
303        if self._MacroDict is None:
304            self._MacroDict = {}
305            self._MacroDict.update(GlobalData.gPlatformDefines)
306            self._MacroDict.update(GlobalData.gGlobalDefines)
307            self._MacroDict.update(GlobalData.gCommandLineDefines)
308        return self._MacroDict
309
310    ## Get architecture
311    @property
312    def Arch(self):
313        return self._Arch
314    @property
315    def Dir(self):
316        return self.MetaFile.Dir
317
318    ## Retrieve all information in [Defines] section
319    #
320    #   (Retrieving all [Defines] information in one-shot is just to save time.)
321    #
322    def _GetHeaderInfo(self):
323        RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
324        for Record in RecordList:
325            Name = Record[1]
326            # items defined _PROPERTY_ don't need additional processing
327
328            # some special items in [Defines] section need special treatment
329            if Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:
330                self._OutputDirectory = NormPath(Record[2], self._Macros)
331                if ' ' in self._OutputDirectory:
332                    EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY",
333                                    File=self.MetaFile, Line=Record[-1],
334                                    ExtraData=self._OutputDirectory)
335            elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:
336                self._FlashDefinition = PathClass(NormPath(Record[2], self._Macros), GlobalData.gWorkspace)
337                ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf')
338                if ErrorCode != 0:
339                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1],
340                                    ExtraData=ErrorInfo)
341            elif Name == TAB_DSC_PREBUILD:
342                PrebuildValue = Record[2]
343                if Record[2][0] == '"':
344                    if Record[2][-1] != '"':
345                        EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_PREBUILD,
346                                    File=self.MetaFile, Line=Record[-1])
347                    PrebuildValue = Record[2][1:-1]
348                self._Prebuild = PrebuildValue
349            elif Name == TAB_DSC_POSTBUILD:
350                PostbuildValue = Record[2]
351                if Record[2][0] == '"':
352                    if Record[2][-1] != '"':
353                        EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_POSTBUILD,
354                                    File=self.MetaFile, Line=Record[-1])
355                    PostbuildValue = Record[2][1:-1]
356                self._Postbuild = PostbuildValue
357            elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:
358                self._SupArchList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
359            elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:
360                self._BuildTargets = GetSplitValueList(Record[2])
361            elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:
362                if self._SkuName is None:
363                    self._SkuName = Record[2]
364                if GlobalData.gSKUID_CMD:
365                    self._SkuName = GlobalData.gSKUID_CMD
366            elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION:
367                self._PcdInfoFlag = Record[2]
368            elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION:
369                self._VarCheckFlag = Record[2]
370            elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:
371                try:
372                    self._LoadFixAddress = int (Record[2], 0)
373                except:
374                    EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (Record[2]))
375            elif Name == TAB_DSC_DEFINES_RFC_LANGUAGES:
376                if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
377                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for RFC_LANGUAGES must have double quotes around it, for example: RFC_LANGUAGES = "en-us;zh-hans"',
378                                    File=self.MetaFile, Line=Record[-1])
379                LanguageCodes = Record[2][1:-1]
380                if not LanguageCodes:
381                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more RFC4646 format language code must be provided for RFC_LANGUAGES statement',
382                                    File=self.MetaFile, Line=Record[-1])
383                LanguageList = GetSplitValueList(LanguageCodes, TAB_SEMI_COLON_SPLIT)
384                # check whether there is empty entries in the list
385                if None in LanguageList:
386                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more empty language code is in RFC_LANGUAGES statement',
387                                    File=self.MetaFile, Line=Record[-1])
388                self._RFCLanguages = LanguageList
389            elif Name == TAB_DSC_DEFINES_ISO_LANGUAGES:
390                if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
391                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for ISO_LANGUAGES must have double quotes around it, for example: ISO_LANGUAGES = "engchn"',
392                                    File=self.MetaFile, Line=Record[-1])
393                LanguageCodes = Record[2][1:-1]
394                if not LanguageCodes:
395                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more ISO639-2 format language code must be provided for ISO_LANGUAGES statement',
396                                    File=self.MetaFile, Line=Record[-1])
397                if len(LanguageCodes) % 3:
398                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'bad ISO639-2 format for ISO_LANGUAGES',
399                                    File=self.MetaFile, Line=Record[-1])
400                LanguageList = []
401                for i in range(0, len(LanguageCodes), 3):
402                    LanguageList.append(LanguageCodes[i:i + 3])
403                self._ISOLanguages = LanguageList
404            elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID:
405                #
406                # try to convert GUID to a real UUID value to see whether the GUID is format
407                # for VPD_TOOL_GUID is correct.
408                #
409                try:
410                    uuid.UUID(Record[2])
411                except:
412                    EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile)
413                self._VpdToolGuid = Record[2]
414            elif Name in self:
415                self[Name] = Record[2]
416        # set _Header to non-None in order to avoid database re-querying
417        self._Header = 'DUMMY'
418
419    ## Retrieve platform name
420    @property
421    def PlatformName(self):
422        if self._PlatformName is None:
423            if self._Header is None:
424                self._GetHeaderInfo()
425            if self._PlatformName is None:
426                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)
427        return self._PlatformName
428
429    @property
430    def Platform(self):
431        return self.PlatformName
432
433    ## Retrieve file guid
434    @property
435    def Guid(self):
436        if self._Guid is None:
437            if self._Header is None:
438                self._GetHeaderInfo()
439            if self._Guid is None:
440                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_GUID", File=self.MetaFile)
441        return self._Guid
442
443    ## Retrieve platform version
444    @property
445    def Version(self):
446        if self._Version is None:
447            if self._Header is None:
448                self._GetHeaderInfo()
449            if self._Version is None:
450                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_VERSION", File=self.MetaFile)
451        return self._Version
452
453    ## Retrieve platform description file version
454    @property
455    def DscSpecification(self):
456        if self._DscSpecification is None:
457            if self._Header is None:
458                self._GetHeaderInfo()
459            if self._DscSpecification is None:
460                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No DSC_SPECIFICATION", File=self.MetaFile)
461        return self._DscSpecification
462
463    ## Retrieve OUTPUT_DIRECTORY
464    @property
465    def OutputDirectory(self):
466        if self._OutputDirectory is None:
467            if self._Header is None:
468                self._GetHeaderInfo()
469            if self._OutputDirectory is None:
470                self._OutputDirectory = os.path.join("Build", self._PlatformName)
471        return self._OutputDirectory
472
473    ## Retrieve SUPPORTED_ARCHITECTURES
474    @property
475    def SupArchList(self):
476        if self._SupArchList is None:
477            if self._Header is None:
478                self._GetHeaderInfo()
479            if self._SupArchList is None:
480                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No SUPPORTED_ARCHITECTURES", File=self.MetaFile)
481        return self._SupArchList
482
483    ## Retrieve BUILD_TARGETS
484    @property
485    def BuildTargets(self):
486        if self._BuildTargets is None:
487            if self._Header is None:
488                self._GetHeaderInfo()
489            if self._BuildTargets is None:
490                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BUILD_TARGETS", File=self.MetaFile)
491        return self._BuildTargets
492
493    @property
494    def PcdInfoFlag(self):
495        if self._PcdInfoFlag is None or self._PcdInfoFlag.upper() == 'FALSE':
496            return False
497        elif self._PcdInfoFlag.upper() == 'TRUE':
498            return True
499        else:
500            return False
501
502    @property
503    def VarCheckFlag(self):
504        if self._VarCheckFlag is None or self._VarCheckFlag.upper() == 'FALSE':
505            return False
506        elif self._VarCheckFlag.upper() == 'TRUE':
507            return True
508        else:
509            return False
510
511    # # Retrieve SKUID_IDENTIFIER
512    @property
513    def SkuName(self):
514        if self._SkuName is None:
515            if self._Header is None:
516                self._GetHeaderInfo()
517            if self._SkuName is None:
518                self._SkuName = TAB_DEFAULT
519        return self._SkuName
520
521    ## Override SKUID_IDENTIFIER
522    @SkuName.setter
523    def SkuName(self, Value):
524        self._SkuName = Value
525
526    @property
527    def FlashDefinition(self):
528        if self._FlashDefinition is None:
529            if self._Header is None:
530                self._GetHeaderInfo()
531            if self._FlashDefinition is None:
532                self._FlashDefinition = ''
533        return self._FlashDefinition
534
535    @property
536    def Prebuild(self):
537        if self._Prebuild is None:
538            if self._Header is None:
539                self._GetHeaderInfo()
540            if self._Prebuild is None:
541                self._Prebuild = ''
542        return self._Prebuild
543
544    @property
545    def Postbuild(self):
546        if self._Postbuild is None:
547            if self._Header is None:
548                self._GetHeaderInfo()
549            if self._Postbuild is None:
550                self._Postbuild = ''
551        return self._Postbuild
552
553    ## Retrieve FLASH_DEFINITION
554    @property
555    def BuildNumber(self):
556        if self._BuildNumber is None:
557            if self._Header is None:
558                self._GetHeaderInfo()
559            if self._BuildNumber is None:
560                self._BuildNumber = ''
561        return self._BuildNumber
562
563    ## Retrieve MAKEFILE_NAME
564    @property
565    def MakefileName(self):
566        if self._MakefileName is None:
567            if self._Header is None:
568                self._GetHeaderInfo()
569            if self._MakefileName is None:
570                self._MakefileName = ''
571        return self._MakefileName
572
573    ## Retrieve BsBaseAddress
574    @property
575    def BsBaseAddress(self):
576        if self._BsBaseAddress is None:
577            if self._Header is None:
578                self._GetHeaderInfo()
579            if self._BsBaseAddress is None:
580                self._BsBaseAddress = ''
581        return self._BsBaseAddress
582
583    ## Retrieve RtBaseAddress
584    @property
585    def RtBaseAddress(self):
586        if self._RtBaseAddress is None:
587            if self._Header is None:
588                self._GetHeaderInfo()
589            if self._RtBaseAddress is None:
590                self._RtBaseAddress = ''
591        return self._RtBaseAddress
592
593    ## Retrieve the top address for the load fix address
594    @property
595    def LoadFixAddress(self):
596        if self._LoadFixAddress is None:
597            if self._Header is None:
598                self._GetHeaderInfo()
599
600            if self._LoadFixAddress is None:
601                self._LoadFixAddress = self._Macros.get(TAB_FIX_LOAD_TOP_MEMORY_ADDRESS, '0')
602
603            try:
604                self._LoadFixAddress = int (self._LoadFixAddress, 0)
605            except:
606                EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (self._LoadFixAddress))
607
608        #
609        # If command line defined, should override the value in DSC file.
610        #
611        if 'FIX_LOAD_TOP_MEMORY_ADDRESS' in GlobalData.gCommandLineDefines:
612            try:
613                self._LoadFixAddress = int(GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS'], 0)
614            except:
615                EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS']))
616
617        if self._LoadFixAddress < 0:
618            EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid negative value 0x%x" % (self._LoadFixAddress))
619        if self._LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self._LoadFixAddress % 0x1000 != 0:
620            EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid unaligned 4K value 0x%x" % (self._LoadFixAddress))
621
622        return self._LoadFixAddress
623
624    ## Retrieve RFCLanguage filter
625    @property
626    def RFCLanguages(self):
627        if self._RFCLanguages is None:
628            if self._Header is None:
629                self._GetHeaderInfo()
630            if self._RFCLanguages is None:
631                self._RFCLanguages = []
632        return self._RFCLanguages
633
634    ## Retrieve ISOLanguage filter
635    @property
636    def ISOLanguages(self):
637        if self._ISOLanguages is None:
638            if self._Header is None:
639                self._GetHeaderInfo()
640            if self._ISOLanguages is None:
641                self._ISOLanguages = []
642        return self._ISOLanguages
643
644    ## Retrieve the GUID string for VPD tool
645    @property
646    def VpdToolGuid(self):
647        if self._VpdToolGuid is None:
648            if self._Header is None:
649                self._GetHeaderInfo()
650            if self._VpdToolGuid is None:
651                self._VpdToolGuid = ''
652        return self._VpdToolGuid
653
654    ## Retrieve [SkuIds] section information
655    @property
656    def SkuIds(self):
657        if self._SkuIds is None:
658            self._SkuIds = OrderedDict()
659            RecordList = self._RawData[MODEL_EFI_SKU_ID, self._Arch]
660            for Record in RecordList:
661                if not Record[0]:
662                    EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',
663                                    File=self.MetaFile, Line=Record[-1])
664                if not Record[1]:
665                    EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',
666                                    File=self.MetaFile, Line=Record[-1])
667                if not Pattern.match(Record[0]) and not HexPattern.match(Record[0]):
668                    EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID number is invalid. It only support Integer and HexNumber",
669                                    File=self.MetaFile, Line=Record[-1])
670                if not SkuIdPattern.match(Record[1]) or (Record[2] and not SkuIdPattern.match(Record[2])):
671                    EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID name is invalid. The correct format is '(a-zA-Z_)(a-zA-Z0-9_)*'",
672                                    File=self.MetaFile, Line=Record[-1])
673                self._SkuIds[Record[1].upper()] = (str(DscBuildData.ToInt(Record[0])), Record[1].upper(), Record[2].upper())
674            if TAB_DEFAULT not in self._SkuIds:
675                self._SkuIds[TAB_DEFAULT] = ("0", TAB_DEFAULT, TAB_DEFAULT)
676            if TAB_COMMON not in self._SkuIds:
677                self._SkuIds[TAB_COMMON] = ("0", TAB_DEFAULT, TAB_DEFAULT)
678        return self._SkuIds
679
680    @staticmethod
681    def ToInt(intstr):
682        return int(intstr, 16) if intstr.upper().startswith("0X") else int(intstr)
683
684    def _GetDefaultStores(self):
685        if self.DefaultStores is None:
686            self.DefaultStores = OrderedDict()
687            RecordList = self._RawData[MODEL_EFI_DEFAULT_STORES, self._Arch]
688            for Record in RecordList:
689                if not Record[0]:
690                    EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID number',
691                                    File=self.MetaFile, Line=Record[-1])
692                if not Record[1]:
693                    EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID name',
694                                    File=self.MetaFile, Line=Record[-1])
695                if not Pattern.match(Record[0]) and not HexPattern.match(Record[0]):
696                    EdkLogger.error('build', FORMAT_INVALID, "The format of the DefaultStores ID number is invalid. It only support Integer and HexNumber",
697                                    File=self.MetaFile, Line=Record[-1])
698                if not IsValidWord(Record[1]):
699                    EdkLogger.error('build', FORMAT_INVALID, "The format of the DefaultStores ID name is invalid. The correct format is '(a-zA-Z0-9_)(a-zA-Z0-9_-.)*'",
700                                    File=self.MetaFile, Line=Record[-1])
701                self.DefaultStores[Record[1].upper()] = (DscBuildData.ToInt(Record[0]), Record[1].upper())
702            if TAB_DEFAULT_STORES_DEFAULT not in self.DefaultStores:
703                self.DefaultStores[TAB_DEFAULT_STORES_DEFAULT] = (0, TAB_DEFAULT_STORES_DEFAULT)
704            GlobalData.gDefaultStores = sorted(self.DefaultStores.keys())
705        return self.DefaultStores
706
707    def OverrideDuplicateModule(self):
708        RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
709        Macros = self._Macros
710        Components = {}
711        for Record in RecordList:
712            ModuleId = Record[6]
713            file_guid = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]
714            file_guid_str = file_guid[0][2] if file_guid else "NULL"
715            ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
716            if self._Arch != TAB_ARCH_COMMON and (file_guid_str,str(ModuleFile)) in Components:
717                self._RawData.DisableOverrideComponent(Components[(file_guid_str,str(ModuleFile))])
718            Components[(file_guid_str,str(ModuleFile))] = ModuleId
719        self._RawData._PostProcessed = False
720
721    ## Retrieve packages this Platform depends on
722    @cached_property
723    def Packages(self):
724        RetVal = set()
725        RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch]
726        Macros = self._Macros
727        for Record in RecordList:
728            File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
729            # check the file validation
730            ErrorCode, ErrorInfo = File.Validate('.dec')
731            if ErrorCode != 0:
732                LineNo = Record[-1]
733                EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
734            # parse this package now. we need it to get protocol/ppi/guid value
735            RetVal.add(self._Bdb[File, self._Arch, self._Target, self._Toolchain])
736        return RetVal
737
738    ## Retrieve [Components] section information
739    @property
740    def Modules(self):
741        if self._Modules is not None:
742            return self._Modules
743        self.OverrideDuplicateModule()
744        self._Modules = OrderedDict()
745        RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
746        Macros = self._Macros
747        for Record in RecordList:
748            ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
749            ModuleId = Record[6]
750            LineNo = Record[7]
751
752            # check the file validation
753            ErrorCode, ErrorInfo = ModuleFile.Validate('.inf')
754            if ErrorCode != 0:
755                EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
756                                ExtraData=ErrorInfo)
757
758            Module = ModuleBuildClassObject()
759            Module.MetaFile = ModuleFile
760
761            # get module private library instance
762            RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]
763            for Record in RecordList:
764                LibraryClass = Record[0]
765                LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch)
766                LineNo = Record[-1]
767
768                # check the file validation
769                ErrorCode, ErrorInfo = LibraryPath.Validate('.inf')
770                if ErrorCode != 0:
771                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
772                                    ExtraData=ErrorInfo)
773
774                if LibraryClass == '' or LibraryClass == 'NULL':
775                    self._NullLibraryNumber += 1
776                    LibraryClass = 'NULL%d' % self._NullLibraryNumber
777                    EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))
778                Module.LibraryClasses[LibraryClass] = LibraryPath
779                if LibraryPath not in self.LibraryInstances:
780                    self.LibraryInstances.append(LibraryPath)
781
782            # get module private PCD setting
783            for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \
784                         MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:
785                RecordList = self._RawData[Type, self._Arch, None, ModuleId]
786                for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
787                    TokenList = GetSplitValueList(Setting)
788                    DefaultValue = TokenList[0]
789                    # the format is PcdName| Value | VOID* | MaxDatumSize
790                    if len(TokenList) > 2:
791                        MaxDatumSize = TokenList[2]
792                    else:
793                        MaxDatumSize = ''
794                    TypeString = self._PCD_TYPE_STRING_[Type]
795                    Pcd = PcdClassObject(
796                            PcdCName,
797                            TokenSpaceGuid,
798                            TypeString,
799                            '',
800                            DefaultValue,
801                            '',
802                            MaxDatumSize,
803                            {},
804                            False,
805                            None
806                            )
807                    Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd
808
809            # get module private build options
810            RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]
811            for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
812                if (ToolChainFamily, ToolChain) not in Module.BuildOptions:
813                    Module.BuildOptions[ToolChainFamily, ToolChain] = Option
814                else:
815                    OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]
816                    Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
817
818            RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]
819            if RecordList:
820                if len(RecordList) != 1:
821                    EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in <Defines> section.',
822                                    File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
823                ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace)
824                ModuleFile.Arch = self._Arch
825
826            self._Modules[ModuleFile] = Module
827        return self._Modules
828
829    ## Retrieve all possible library instances used in this platform
830    @property
831    def LibraryInstances(self):
832        if self._LibraryInstances is None:
833            self.LibraryClasses
834        return self._LibraryInstances
835
836    ## Retrieve [LibraryClasses] information
837    @property
838    def LibraryClasses(self):
839        if self._LibraryClasses is None:
840            self._LibraryInstances = []
841            #
842            # tdict is a special dict kind of type, used for selecting correct
843            # library instance for given library class and module type
844            #
845            LibraryClassDict = tdict(True, 3)
846            # track all library class names
847            LibraryClassSet = set()
848            RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, -1]
849            Macros = self._Macros
850            for Record in RecordList:
851                LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, Dummy, LineNo = Record
852                if LibraryClass == '' or LibraryClass == 'NULL':
853                    self._NullLibraryNumber += 1
854                    LibraryClass = 'NULL%d' % self._NullLibraryNumber
855                    EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass))
856                LibraryClassSet.add(LibraryClass)
857                LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch)
858                # check the file validation
859                ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf')
860                if ErrorCode != 0:
861                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
862                                    ExtraData=ErrorInfo)
863
864                if ModuleType != TAB_COMMON and ModuleType not in SUP_MODULE_LIST:
865                    EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType,
866                                    File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo)
867                LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance
868                if LibraryInstance not in self._LibraryInstances:
869                    self._LibraryInstances.append(LibraryInstance)
870
871            # resolve the specific library instance for each class and each module type
872            self._LibraryClasses = tdict(True)
873            for LibraryClass in LibraryClassSet:
874                # try all possible module types
875                for ModuleType in SUP_MODULE_LIST:
876                    LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]
877                    if LibraryInstance is None:
878                        continue
879                    self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance
880
881            RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]
882            for Record in RecordList:
883                File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
884                LineNo = Record[-1]
885                # check the file validation
886                ErrorCode, ErrorInfo = File.Validate('.inf')
887                if ErrorCode != 0:
888                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
889                                    ExtraData=ErrorInfo)
890                if File not in self._LibraryInstances:
891                    self._LibraryInstances.append(File)
892                #
893                # we need the module name as the library class name, so we have
894                # to parse it here. (self._Bdb[] will trigger a file parse if it
895                # hasn't been parsed)
896                #
897                Library = self._Bdb[File, self._Arch, self._Target, self._Toolchain]
898                self._LibraryClasses[Library.BaseName, ':dummy:'] = Library
899        return self._LibraryClasses
900
901    def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo):
902        if not self._DecPcds:
903
904            FdfInfList = []
905            if GlobalData.gFdfParser:
906                FdfInfList = GlobalData.gFdfParser.Profile.InfList
907
908            PkgSet = set()
909            for Inf in FdfInfList:
910                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
911                if ModuleFile in self._Modules:
912                    continue
913                ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
914                PkgSet.update(ModuleData.Packages)
915            if self.Packages:
916                PkgSet.update(self.Packages)
917            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain, PkgSet)
918            self._GuidDict.update(GlobalData.gPlatformPcds)
919
920        if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
921            EdkLogger.error('build', PARSER_ERROR,
922                            "Pcd (%s.%s) defined in DSC is not declared in DEC files referenced in INF files in FDF. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),
923                            File=self.MetaFile, Line=LineNo)
924        ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType)
925        if not IsValid:
926            if PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
927                EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,
928                                ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
929            else:
930                if ValueList[2] == '-1':
931                    EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,
932                                ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
933        if ValueList[Index]:
934            DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
935            if "{CODE(" not in ValueList[Index]:
936                try:
937                    ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
938                except BadExpression as Value:
939                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
940                                    ExtraData="PCD [%s.%s] Value \"%s\" " % (
941                                    TokenSpaceGuid, PcdCName, ValueList[Index]))
942                except EvaluationException as Excpt:
943                    if hasattr(Excpt, 'Pcd'):
944                        if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
945                            EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
946                                            " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
947                                            " of the DSC file" % Excpt.Pcd,
948                                            File=self.MetaFile, Line=LineNo)
949                        else:
950                            EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
951                                            File=self.MetaFile, Line=LineNo)
952                    else:
953                        EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
954                                        File=self.MetaFile, Line=LineNo)
955
956        if ValueList[Index]:
957            Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
958            if not Valid:
959                EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
960                                ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
961            if PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
962                if self._DecPcds[PcdCName, TokenSpaceGuid].DatumType.strip() != ValueList[1].strip():
963                    DecPcd = self._DecPcds[PcdCName, TokenSpaceGuid]
964                    EdkLogger.error('build', FORMAT_INVALID,
965                                    "Pcd datumtype used in DSC file is not the same as its declaration. DatumType:%s"%DecPcd.DatumType,
966                                    File=self.MetaFile, Line=LineNo,
967                                    ExtraData="Dsc:%s.%s|%s\n    Dec:%s.%s|%s|%s|%s" % (TokenSpaceGuid, PcdCName, Setting, TokenSpaceGuid, \
968                                    PcdCName, DecPcd.DefaultValue, DecPcd.DatumType, DecPcd.TokenValue))
969        if (TokenSpaceGuid + '.' + PcdCName) in GlobalData.gPlatformPcds:
970            if GlobalData.gPlatformPcds[TokenSpaceGuid + '.' + PcdCName] != ValueList[Index]:
971                GlobalData.gPlatformPcds[TokenSpaceGuid + '.' + PcdCName] = ValueList[Index]
972        return ValueList
973
974    def _FilterPcdBySkuUsage(self, Pcds):
975        available_sku = self.SkuIdMgr.AvailableSkuIdSet
976        sku_usage = self.SkuIdMgr.SkuUsageType
977        if sku_usage == SkuClass.SINGLE:
978            for pcdname in Pcds:
979                pcd = Pcds[pcdname]
980                Pcds[pcdname].SkuInfoList = {TAB_DEFAULT:pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
981                if isinstance(pcd, StructurePcd) and pcd.SkuOverrideValues:
982                    Pcds[pcdname].SkuOverrideValues = {TAB_DEFAULT:pcd.SkuOverrideValues[skuid] for skuid in pcd.SkuOverrideValues if skuid in available_sku}
983        else:
984            for pcdname in Pcds:
985                pcd = Pcds[pcdname]
986                Pcds[pcdname].SkuInfoList = {skuid:pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
987                if isinstance(pcd, StructurePcd) and pcd.SkuOverrideValues:
988                    Pcds[pcdname].SkuOverrideValues = {skuid:pcd.SkuOverrideValues[skuid] for skuid in pcd.SkuOverrideValues if skuid in available_sku}
989        return Pcds
990
991    def CompleteHiiPcdsDefaultStores(self, Pcds):
992        HiiPcd = [Pcds[pcd] for pcd in Pcds if Pcds[pcd].Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]]
993        DefaultStoreMgr = DefaultStore(self.DefaultStores)
994        for pcd in HiiPcd:
995            for skuid in pcd.SkuInfoList:
996                skuobj = pcd.SkuInfoList.get(skuid)
997                if TAB_DEFAULT_STORES_DEFAULT not in skuobj.DefaultStoreDict:
998                    PcdDefaultStoreSet = set(defaultstorename  for defaultstorename in skuobj.DefaultStoreDict)
999                    mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)
1000                    skuobj.DefaultStoreDict[TAB_DEFAULT_STORES_DEFAULT] = skuobj.DefaultStoreDict[mindefaultstorename]
1001        return Pcds
1002
1003    def RecoverCommandLinePcd(self):
1004        def UpdateCommandLineValue(pcd):
1005            if pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
1006                                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
1007                pcd.PcdValueFromComm = pcd.DefaultValue
1008            elif pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
1009                pcd.PcdValueFromComm = pcd.SkuInfoList.get(TAB_DEFAULT).HiiDefaultValue
1010            else:
1011                pcd.PcdValueFromComm = pcd.SkuInfoList.get(TAB_DEFAULT).DefaultValue
1012        for pcd in self._Pcds:
1013            if isinstance(self._Pcds[pcd], StructurePcd) and (self._Pcds[pcd].PcdValueFromComm or self._Pcds[pcd].PcdFieldValueFromComm):
1014                UpdateCommandLineValue(self._Pcds[pcd])
1015
1016    def __ParsePcdFromCommandLine(self):
1017        if GlobalData.BuildOptionPcd:
1018            for i, pcd in enumerate(GlobalData.BuildOptionPcd):
1019                if isinstance(pcd, tuple):
1020                    continue
1021                (pcdname, pcdvalue) = pcd.split('=')
1022                if not pcdvalue:
1023                    EdkLogger.error('build', AUTOGEN_ERROR, "No Value specified for the PCD %s." % (pcdname))
1024                if '.' in pcdname:
1025                    (Name1, Name2) = pcdname.split('.', 1)
1026                    if "." in Name2:
1027                        (Name3, FieldName) = Name2.split(".", 1)
1028                        if ((Name3, Name1)) in self.DecPcds:
1029                            HasTokenSpace = True
1030                            TokenCName = Name3
1031                            TokenSpaceGuidCName = Name1
1032                        else:
1033                            FieldName = Name2
1034                            TokenCName = Name1
1035                            TokenSpaceGuidCName = ''
1036                            HasTokenSpace = False
1037                    else:
1038                        if ((Name2, Name1)) in self.DecPcds:
1039                            HasTokenSpace = True
1040                            TokenCName = Name2
1041                            TokenSpaceGuidCName = Name1
1042                            FieldName =""
1043                        else:
1044                            FieldName = Name2
1045                            TokenCName = Name1
1046                            TokenSpaceGuidCName = ''
1047                            HasTokenSpace = False
1048                else:
1049                    FieldName = ""
1050                    TokenCName = pcdname
1051                    TokenSpaceGuidCName = ''
1052                    HasTokenSpace = False
1053                TokenSpaceGuidCNameList = []
1054                FoundFlag = False
1055                PcdDatumType = ''
1056                DisplayName = TokenCName
1057                if FieldName:
1058                    DisplayName = TokenCName + '.' + FieldName
1059                if not HasTokenSpace:
1060                    for key in self.DecPcds:
1061                        PcdItem = self.DecPcds[key]
1062                        if TokenCName == PcdItem.TokenCName:
1063                            if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
1064                                if len (TokenSpaceGuidCNameList) < 1:
1065                                    TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
1066                                    TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
1067                                    PcdDatumType = PcdItem.DatumType
1068                                    FoundFlag = True
1069                                else:
1070                                    EdkLogger.error(
1071                                            'build',
1072                                             AUTOGEN_ERROR,
1073                                            "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (DisplayName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
1074                                            )
1075                else:
1076                    if (TokenCName, TokenSpaceGuidCName) in self.DecPcds:
1077                        PcdDatumType = self.DecPcds[(TokenCName, TokenSpaceGuidCName)].DatumType
1078                        FoundFlag = True
1079                if not FoundFlag:
1080                    if HasTokenSpace:
1081                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, DisplayName))
1082                    else:
1083                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (DisplayName))
1084                pcdvalue = pcdvalue.replace("\\\\\\'", '\\\\\\"').replace('\\\'', '\'').replace('\\\\\\"', "\\'")
1085                if FieldName:
1086                    pcdvalue = DscBuildData.HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, pcdvalue, PcdDatumType, self._GuidDict, FieldName)
1087                else:
1088                    pcdvalue = DscBuildData.HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, pcdvalue, PcdDatumType, self._GuidDict)
1089                    IsValid, Cause = CheckPcdDatum(PcdDatumType, pcdvalue)
1090                    if not IsValid:
1091                        EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))
1092                GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, ("build command options", 1))
1093
1094        if GlobalData.BuildOptionPcd:
1095            inf_objs = [item for item in self._Bdb._CACHE_.values() if item.Arch == self.Arch and item.MetaFile.Ext.lower() == '.inf']
1096            for pcd in GlobalData.BuildOptionPcd:
1097                (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
1098                for BuildData in inf_objs:
1099                    for key in BuildData.Pcds:
1100                        PcdItem = BuildData.Pcds[key]
1101                        if (TokenSpaceGuidCName, TokenCName) == (PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName) and FieldName =="":
1102                            PcdItem.DefaultValue = pcdvalue
1103                            PcdItem.PcdValueFromComm = pcdvalue
1104        #In command line, the latter full assign value in commandLine should override the former field assign value.
1105        #For example, --pcd Token.pcd.field="" --pcd Token.pcd=H"{}"
1106        delete_assign = []
1107        field_assign = {}
1108        if GlobalData.BuildOptionPcd:
1109            for pcdTuple in GlobalData.BuildOptionPcd:
1110                TokenSpaceGuid, Token, Field = pcdTuple[0], pcdTuple[1], pcdTuple[2]
1111                if Field:
1112                    if (TokenSpaceGuid, Token) not in field_assign:
1113                        field_assign[TokenSpaceGuid, Token] = []
1114                    field_assign[TokenSpaceGuid, Token].append(pcdTuple)
1115                else:
1116                    if (TokenSpaceGuid, Token) in field_assign:
1117                        delete_assign.extend(field_assign[TokenSpaceGuid, Token])
1118                        field_assign[TokenSpaceGuid, Token] = []
1119            for item in delete_assign:
1120                GlobalData.BuildOptionPcd.remove(item)
1121
1122    @staticmethod
1123    def HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, PcdValue, PcdDatumType, GuidDict, FieldName=''):
1124        if FieldName:
1125            IsArray = False
1126            TokenCName += '.' + FieldName
1127        if PcdValue.startswith('H'):
1128            if FieldName and _IsFieldValueAnArray(PcdValue[1:]):
1129                PcdDatumType = TAB_VOID
1130                IsArray = True
1131            if FieldName and not IsArray:
1132                return PcdValue
1133            try:
1134                PcdValue = ValueExpressionEx(PcdValue[1:], PcdDatumType, GuidDict)(True)
1135            except BadExpression as Value:
1136                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
1137                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
1138        elif PcdValue.startswith("L'") or PcdValue.startswith("'"):
1139            if FieldName and _IsFieldValueAnArray(PcdValue):
1140                PcdDatumType = TAB_VOID
1141                IsArray = True
1142            if FieldName and not IsArray:
1143                return PcdValue
1144            try:
1145                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
1146            except BadExpression as Value:
1147                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
1148                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
1149        elif PcdValue.startswith('L'):
1150            PcdValue = 'L"' + PcdValue[1:] + '"'
1151            if FieldName and _IsFieldValueAnArray(PcdValue):
1152                PcdDatumType = TAB_VOID
1153                IsArray = True
1154            if FieldName and not IsArray:
1155                return PcdValue
1156            try:
1157                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
1158            except BadExpression as Value:
1159                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
1160                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
1161        else:
1162            if PcdValue.upper() == 'FALSE':
1163                PcdValue = str(0)
1164            if PcdValue.upper() == 'TRUE':
1165                PcdValue = str(1)
1166            if not FieldName:
1167                if PcdDatumType not in TAB_PCD_NUMERIC_TYPES:
1168                    PcdValue = '"' + PcdValue + '"'
1169                elif not PcdValue.isdigit() and not PcdValue.upper().startswith('0X'):
1170                    PcdValue = '"' + PcdValue + '"'
1171            else:
1172                IsArray = False
1173                Base = 10
1174                if PcdValue.upper().startswith('0X'):
1175                    Base = 16
1176                try:
1177                    Num = int(PcdValue, Base)
1178                except:
1179                    PcdValue = '"' + PcdValue + '"'
1180                if _IsFieldValueAnArray(PcdValue):
1181                    PcdDatumType = TAB_VOID
1182                    IsArray = True
1183                if not IsArray:
1184                    return PcdValue
1185            try:
1186                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
1187            except BadExpression as Value:
1188                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
1189                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
1190        return PcdValue
1191
1192    ## Retrieve all PCD settings in platform
1193    @property
1194    def Pcds(self):
1195        if self._Pcds is None:
1196            self._Pcds = OrderedDict()
1197            self.__ParsePcdFromCommandLine()
1198            self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
1199            self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
1200            self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
1201            self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))
1202            self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))
1203            self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))
1204            self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))
1205            self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))
1206            self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))
1207
1208            self._Pcds = self.CompletePcdValues(self._Pcds)
1209            self._Pcds = self.OverrideByFdfOverAll(self._Pcds)
1210            self._Pcds = self.OverrideByCommOverAll(self._Pcds)
1211            self._Pcds = self.UpdateStructuredPcds(MODEL_PCD_TYPE_LIST, self._Pcds)
1212            self._Pcds = self.CompleteHiiPcdsDefaultStores(self._Pcds)
1213            self._Pcds = self._FilterPcdBySkuUsage(self._Pcds)
1214
1215            self.RecoverCommandLinePcd()
1216        return self._Pcds
1217
1218    ## Retrieve [BuildOptions]
1219    @property
1220    def BuildOptions(self):
1221        if self._BuildOptions is None:
1222            self._BuildOptions = OrderedDict()
1223            #
1224            # Retrieve build option for EDKII and EDK style module
1225            #
1226            for CodeBase in (EDKII_NAME, EDK_NAME):
1227                RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, CodeBase]
1228                for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
1229                    if Dummy3.upper() != TAB_COMMON:
1230                        continue
1231                    CurKey = (ToolChainFamily, ToolChain, CodeBase)
1232                    #
1233                    # Only flags can be appended
1234                    #
1235                    if CurKey not in self._BuildOptions or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
1236                        self._BuildOptions[CurKey] = Option
1237                    else:
1238                        if ' ' + Option not in self._BuildOptions[CurKey]:
1239                            self._BuildOptions[CurKey] += ' ' + Option
1240        return self._BuildOptions
1241    def GetBuildOptionsByPkg(self, Module, ModuleType):
1242
1243        local_pkg = os.path.split(Module.LocalPkg())[0]
1244        if self._ModuleTypeOptions is None:
1245            self._ModuleTypeOptions = OrderedDict()
1246        if ModuleType not in self._ModuleTypeOptions:
1247            options = OrderedDict()
1248            self._ModuleTypeOptions[ ModuleType] = options
1249            RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch]
1250            for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
1251                if Dummy2 not in (TAB_COMMON,local_pkg.upper(),"EDKII"):
1252                    continue
1253                Type = Dummy3
1254                if Type.upper() == ModuleType.upper():
1255                    Key = (ToolChainFamily, ToolChain)
1256                    if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
1257                        options[Key] = Option
1258                    else:
1259                        if ' ' + Option not in options[Key]:
1260                            options[Key] += ' ' + Option
1261        return self._ModuleTypeOptions[ModuleType]
1262    def GetBuildOptionsByModuleType(self, Edk, ModuleType):
1263        if self._ModuleTypeOptions is None:
1264            self._ModuleTypeOptions = OrderedDict()
1265        if (Edk, ModuleType) not in self._ModuleTypeOptions:
1266            options = OrderedDict()
1267            self._ModuleTypeOptions[Edk, ModuleType] = options
1268            DriverType = '%s.%s' % (Edk, ModuleType)
1269            CommonDriverType = '%s.%s' % (TAB_COMMON, ModuleType)
1270            RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch]
1271            for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
1272                Type = Dummy2 + '.' + Dummy3
1273                if Type.upper() == DriverType.upper() or Type.upper() == CommonDriverType.upper():
1274                    Key = (ToolChainFamily, ToolChain, Edk)
1275                    if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
1276                        options[Key] = Option
1277                    else:
1278                        if ' ' + Option not in options[Key]:
1279                            options[Key] += ' ' + Option
1280        return self._ModuleTypeOptions[Edk, ModuleType]
1281
1282    @staticmethod
1283    def GetStructurePcdInfo(PcdSet):
1284        structure_pcd_data = defaultdict(list)
1285        for item in PcdSet:
1286            structure_pcd_data[(item[0], item[1])].append(item)
1287
1288        return structure_pcd_data
1289
1290    @staticmethod
1291    def OverrideByFdf(StruPcds,workspace):
1292        if GlobalData.gFdfParser is None:
1293            return StruPcds
1294        StructurePcdInFdf = OrderedDict()
1295        fdfpcd = GlobalData.gFdfParser.Profile.PcdDict
1296        fdfpcdlocation = GlobalData.gFdfParser.Profile.PcdLocalDict
1297        for item in fdfpcd :
1298            if len(item[2]) and (item[0],item[1]) in StruPcds:
1299                StructurePcdInFdf[(item[1],item[0],item[2] )] = fdfpcd[item]
1300        GlobalPcds = {(item[0],item[1]) for item in StructurePcdInFdf}
1301        for Pcd in StruPcds.values():
1302            if (Pcd.TokenSpaceGuidCName,Pcd.TokenCName) not in GlobalPcds:
1303                continue
1304            FieldValues = OrderedDict()
1305            for item in StructurePcdInFdf:
1306                if (Pcd.TokenSpaceGuidCName,Pcd.TokenCName) == (item[0],item[1]) and item[2]:
1307                    FieldValues[item[2]] = StructurePcdInFdf[item]
1308            for field in FieldValues:
1309                if field not in Pcd.PcdFieldValueFromFdf:
1310                    Pcd.PcdFieldValueFromFdf[field] = ["","",""]
1311                Pcd.PcdFieldValueFromFdf[field][0] = FieldValues[field]
1312                Pcd.PcdFieldValueFromFdf[field][1] = os.path.relpath(fdfpcdlocation[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName,field)][0],workspace)
1313                Pcd.PcdFieldValueFromFdf[field][2] = fdfpcdlocation[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName,field)][1]
1314
1315        return StruPcds
1316
1317    @staticmethod
1318    def OverrideByComm(StruPcds):
1319        StructurePcdInCom = OrderedDict()
1320        for item in GlobalData.BuildOptionPcd:
1321            if len(item) == 5 and (item[1], item[0]) in StruPcds:
1322                StructurePcdInCom[(item[0], item[1], item[2] )] = (item[3], item[4])
1323        GlobalPcds = {(item[0], item[1]) for item in StructurePcdInCom}
1324        for Pcd in StruPcds.values():
1325            if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) not in GlobalPcds:
1326                continue
1327            FieldValues = OrderedDict()
1328            for item in StructurePcdInCom:
1329                if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (item[0], item[1]) and item[2]:
1330                    FieldValues[item[2]] = StructurePcdInCom[item]
1331            for field in FieldValues:
1332                if field not in Pcd.PcdFieldValueFromComm:
1333                    Pcd.PcdFieldValueFromComm[field] = ["", "", ""]
1334                Pcd.PcdFieldValueFromComm[field][0] = FieldValues[field][0]
1335                Pcd.PcdFieldValueFromComm[field][1] = FieldValues[field][1][0]
1336                Pcd.PcdFieldValueFromComm[field][2] = FieldValues[field][1][1]
1337        return StruPcds
1338
1339    def OverrideByCommOverAll(self,AllPcds):
1340        def CheckStructureInComm(commpcds):
1341            if not commpcds:
1342                return False
1343            if len(commpcds[0]) == 5:
1344                return True
1345            return False
1346        NoFiledValues = OrderedDict()
1347        if CheckStructureInComm(GlobalData.BuildOptionPcd):
1348            StructurePcdInCom = OrderedDict()
1349            for item in GlobalData.BuildOptionPcd:
1350                StructurePcdInCom[(item[0], item[1], item[2] )] = (item[3], item[4])
1351            for item in StructurePcdInCom:
1352                if not item[2]:
1353                    NoFiledValues[(item[0], item[1])] = StructurePcdInCom[item]
1354        else:
1355            for item in GlobalData.BuildOptionPcd:
1356                NoFiledValues[(item[0], item[1])] = [item[2]]
1357        for Guid, Name in NoFiledValues:
1358            if (Name, Guid) in AllPcds:
1359                Pcd = AllPcds.get((Name, Guid))
1360                if isinstance(self._DecPcds.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName), None), StructurePcd):
1361                    self._DecPcds.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName)).PcdValueFromComm = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
1362                else:
1363                    Pcd.PcdValueFromComm = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
1364                    Pcd.DefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
1365                    for sku in Pcd.SkuInfoList:
1366                        SkuInfo = Pcd.SkuInfoList[sku]
1367                        if SkuInfo.DefaultValue:
1368                            SkuInfo.DefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
1369                        else:
1370                            SkuInfo.HiiDefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
1371                            for defaultstore in SkuInfo.DefaultStoreDict:
1372                                SkuInfo.DefaultStoreDict[defaultstore] = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
1373                    if Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII]]:
1374                        if Pcd.DatumType == TAB_VOID:
1375                            if not Pcd.MaxDatumSize:
1376                                Pcd.MaxDatumSize = '0'
1377                            CurrentSize = int(Pcd.MaxDatumSize, 16) if Pcd.MaxDatumSize.upper().startswith("0X") else int(Pcd.MaxDatumSize)
1378                            OptionSize = len((StringToArray(Pcd.PcdValueFromComm)).split(","))
1379                            MaxSize = max(CurrentSize, OptionSize)
1380                            Pcd.MaxDatumSize = str(MaxSize)
1381            else:
1382                PcdInDec = self.DecPcds.get((Name, Guid))
1383                if PcdInDec:
1384                    PcdInDec.PcdValueFromComm = NoFiledValues[(Guid, Name)][0]
1385                    if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
1386                                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE],
1387                                        self._PCD_TYPE_STRING_[MODEL_PCD_FEATURE_FLAG],
1388                                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC],
1389                                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX]]:
1390                        self._Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
1391                        self._Pcds[Name, Guid].DefaultValue = NoFiledValues[( Guid, Name)][0]
1392                    if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC],
1393                                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX]]:
1394                        self._Pcds[Name, Guid].SkuInfoList = {TAB_DEFAULT:SkuInfoClass(TAB_DEFAULT, self.SkuIds[TAB_DEFAULT][0], '', '', '', '', '', NoFiledValues[( Guid, Name)][0])}
1395        return AllPcds
1396
1397    def OverrideByFdfOverAll(self,AllPcds):
1398
1399        if GlobalData.gFdfParser is None:
1400            return AllPcds
1401        NoFiledValues = GlobalData.gFdfParser.Profile.PcdDict
1402        for Name,Guid,Field in NoFiledValues:
1403            if len(Field):
1404                continue
1405            Value = NoFiledValues[(Name,Guid,Field)]
1406            if (Name,Guid) in AllPcds:
1407                Pcd = AllPcds.get((Name,Guid))
1408                if isinstance(self._DecPcds.get((Pcd.TokenCName,Pcd.TokenSpaceGuidCName), None),StructurePcd):
1409                    self._DecPcds.get((Pcd.TokenCName,Pcd.TokenSpaceGuidCName)).PcdValueFromComm = Value
1410                else:
1411                    Pcd.PcdValueFromComm = Value
1412                    Pcd.DefaultValue = Value
1413                    for sku in Pcd.SkuInfoList:
1414                        SkuInfo = Pcd.SkuInfoList[sku]
1415                        if SkuInfo.DefaultValue:
1416                            SkuInfo.DefaultValue = Value
1417                        else:
1418                            SkuInfo.HiiDefaultValue = Value
1419                            for defaultstore in SkuInfo.DefaultStoreDict:
1420                                SkuInfo.DefaultStoreDict[defaultstore] = Value
1421                    if Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII]]:
1422                        if Pcd.DatumType == TAB_VOID:
1423                            if not Pcd.MaxDatumSize:
1424                                Pcd.MaxDatumSize = '0'
1425                            CurrentSize = int(Pcd.MaxDatumSize,16) if Pcd.MaxDatumSize.upper().startswith("0X") else int(Pcd.MaxDatumSize)
1426                            OptionSize = len((StringToArray(Pcd.PcdValueFromComm)).split(","))
1427                            MaxSize = max(CurrentSize, OptionSize)
1428                            Pcd.MaxDatumSize = str(MaxSize)
1429            else:
1430                PcdInDec = self.DecPcds.get((Name,Guid))
1431                if PcdInDec:
1432                    PcdInDec.PcdValueFromFdf = Value
1433                    if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
1434                                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE],
1435                                        self._PCD_TYPE_STRING_[MODEL_PCD_FEATURE_FLAG]]:
1436                        self._Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
1437                        self._Pcds[Name, Guid].DefaultValue = Value
1438        return AllPcds
1439
1440    def ParsePcdNameStruct(self,NamePart1,NamePart2):
1441        TokenSpaceCName = PcdCName = DimensionAttr = Field = ""
1442        if "." in NamePart1:
1443            TokenSpaceCName, TempPcdCName = NamePart1.split(".")
1444            if "[" in TempPcdCName:
1445                PcdCName = TempPcdCName[:TempPcdCName.index("[")]
1446                DimensionAttr = TempPcdCName[TempPcdCName.index("["):]
1447            else:
1448                PcdCName = TempPcdCName
1449            Field = NamePart2
1450        else:
1451            TokenSpaceCName = NamePart1
1452            if "[" in NamePart2:
1453                PcdCName = NamePart2[:NamePart2.index("[")]
1454                DimensionAttr = NamePart2[NamePart2.index("["):]
1455            else:
1456                PcdCName = NamePart2
1457
1458        return TokenSpaceCName,PcdCName,DimensionAttr,Field
1459
1460    def UpdateStructuredPcds(self, TypeList, AllPcds):
1461
1462        DynamicPcdType = [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
1463                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
1464                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
1465                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
1466                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
1467                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]
1468
1469        Pcds = AllPcds
1470        DefaultStoreMgr = DefaultStore(self.DefaultStores)
1471        SkuIds = self.SkuIds
1472        self.SkuIdMgr.AvailableSkuIdSet.update({TAB_DEFAULT:0})
1473        DefaultStores = {storename for pcdobj in AllPcds.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict}
1474        DefaultStores.add(TAB_DEFAULT_STORES_DEFAULT)
1475
1476        S_PcdSet = []
1477        # Find out all possible PCD candidates for self._Arch
1478        RecordList = []
1479
1480        for Type in TypeList:
1481            RecordList.extend(self._RawData[Type, self._Arch])
1482
1483        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, default_store, Dummy4, Dummy5 in RecordList:
1484            SkuName = SkuName.upper()
1485            default_store = default_store.upper()
1486            SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
1487            if SkuName not in SkuIds:
1488                continue
1489            TCName,PCName,DimensionAttr,Field = self.ParsePcdNameStruct(TokenSpaceGuid, PcdCName)
1490            pcd_in_dec = self._DecPcds.get((PCName,TCName), None)
1491            if pcd_in_dec is None:
1492                EdkLogger.error('build', PARSER_ERROR,
1493                            "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TCName, PCName, self._Arch),
1494                            File=self.MetaFile, Line = Dummy5)
1495            if SkuName in SkuIds and ("." in TokenSpaceGuid or "[" in PcdCName):
1496                if not isinstance (pcd_in_dec, StructurePcd):
1497                    EdkLogger.error('build', PARSER_ERROR,
1498                                "Pcd (%s.%s) is not declared as Structure PCD in DEC files. Arch: ['%s']" % (TCName, PCName, self._Arch),
1499                                File=self.MetaFile, Line = Dummy5)
1500
1501                S_PcdSet.append([ TCName,PCName,DimensionAttr,Field, SkuName, default_store, Dummy5, AnalyzePcdExpression(Setting)[0]])
1502
1503        # handle pcd value override
1504        StrPcdSet = DscBuildData.GetStructurePcdInfo(S_PcdSet)
1505        S_pcd_set = OrderedDict()
1506        for str_pcd in StrPcdSet:
1507            str_pcd_obj = Pcds.get((str_pcd[1], str_pcd[0]), None)
1508            str_pcd_dec = self._DecPcds.get((str_pcd[1], str_pcd[0]), None)
1509            str_pcd_obj_str = StructurePcd()
1510            str_pcd_obj_str.copy(str_pcd_dec)
1511            if str_pcd_obj:
1512                str_pcd_obj_str.copy(str_pcd_obj)
1513                if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
1514                    str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
1515                else:
1516                    str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].DefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
1517            for str_pcd_data in StrPcdSet[str_pcd]:
1518                if str_pcd_data[4] in SkuIds:
1519                    str_pcd_obj_str.AddOverrideValue(str_pcd_data[3], str(str_pcd_data[7]), TAB_DEFAULT if str_pcd_data[4] == TAB_COMMON else str_pcd_data[4], TAB_DEFAULT_STORES_DEFAULT if str_pcd_data[5] == TAB_COMMON else str_pcd_data[5], self.MetaFile.File if self.WorkspaceDir not in self.MetaFile.File else self.MetaFile.File[len(self.WorkspaceDir) if self.WorkspaceDir.endswith(os.path.sep) else len(self.WorkspaceDir)+1:], LineNo=str_pcd_data[6],DimensionAttr = str_pcd_data[2])
1520            S_pcd_set[str_pcd[1], str_pcd[0]] = str_pcd_obj_str
1521
1522        # Add the Structure PCD that only defined in DEC, don't have override in DSC file
1523        for Pcd in self.DecPcds:
1524            if isinstance(self._DecPcds[Pcd], StructurePcd):
1525                if Pcd not in S_pcd_set:
1526                    str_pcd_obj_str = StructurePcd()
1527                    str_pcd_obj_str.copy(self._DecPcds[Pcd])
1528                    str_pcd_obj = Pcds.get(Pcd, None)
1529                    if str_pcd_obj:
1530                        str_pcd_obj_str.copy(str_pcd_obj)
1531                        if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
1532                            str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
1533                        else:
1534                            str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].DefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
1535                    S_pcd_set[Pcd] = str_pcd_obj_str
1536        if S_pcd_set:
1537            GlobalData.gStructurePcd[self.Arch] = S_pcd_set.copy()
1538        self.FilterStrcturePcd(S_pcd_set)
1539        for stru_pcd in S_pcd_set.values():
1540            for skuid in SkuIds:
1541                if skuid in stru_pcd.SkuOverrideValues:
1542                    continue
1543                nextskuid = self.SkuIdMgr.GetNextSkuId(skuid)
1544                NoDefault = False
1545                if skuid not in stru_pcd.SkuOverrideValues:
1546                    while nextskuid not in stru_pcd.SkuOverrideValues:
1547                        if nextskuid == TAB_DEFAULT:
1548                            NoDefault = True
1549                            break
1550                        nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
1551                    stru_pcd.SkuOverrideValues[skuid] = copy.deepcopy(stru_pcd.SkuOverrideValues[nextskuid]) if not NoDefault else copy.deepcopy({defaultstorename: stru_pcd.DefaultValues for defaultstorename in DefaultStores} if DefaultStores else {}) #{TAB_DEFAULT_STORES_DEFAULT:stru_pcd.DefaultValues})
1552                    if not NoDefault:
1553                        stru_pcd.ValueChain.add((skuid, ''))
1554                if 'DEFAULT' in stru_pcd.SkuOverrideValues and not GlobalData.gPcdSkuOverrides.get((stru_pcd.TokenCName, stru_pcd.TokenSpaceGuidCName)):
1555                    GlobalData.gPcdSkuOverrides.update(
1556                        {(stru_pcd.TokenCName, stru_pcd.TokenSpaceGuidCName): {'DEFAULT':stru_pcd.SkuOverrideValues['DEFAULT']}})
1557            if stru_pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
1558                for skuid in SkuIds:
1559                    nextskuid = skuid
1560                    NoDefault = False
1561                    if skuid not in stru_pcd.SkuOverrideValues:
1562                        while nextskuid not in stru_pcd.SkuOverrideValues:
1563                            if nextskuid == TAB_DEFAULT:
1564                                NoDefault = True
1565                                break
1566                            nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
1567                    if NoDefault:
1568                        continue
1569                    PcdDefaultStoreSet = set(defaultstorename  for defaultstorename in stru_pcd.SkuOverrideValues[nextskuid])
1570                    mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)
1571
1572                    for defaultstoreid in DefaultStores:
1573                        if defaultstoreid not in stru_pcd.SkuOverrideValues[skuid]:
1574                            stru_pcd.SkuOverrideValues[skuid][defaultstoreid] = CopyDict(stru_pcd.SkuOverrideValues[nextskuid][mindefaultstorename])
1575                            stru_pcd.ValueChain.add((skuid, defaultstoreid))
1576        S_pcd_set = DscBuildData.OverrideByFdf(S_pcd_set,self.WorkspaceDir)
1577        S_pcd_set = DscBuildData.OverrideByComm(S_pcd_set)
1578        Str_Pcd_Values = self.GenerateByteArrayValue(S_pcd_set)
1579        if Str_Pcd_Values:
1580            for (skuname, StoreName, PcdGuid, PcdName, PcdValue) in Str_Pcd_Values:
1581                str_pcd_obj = S_pcd_set.get((PcdName, PcdGuid))
1582                if str_pcd_obj is None:
1583                    print(PcdName, PcdGuid)
1584                    raise
1585                if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
1586                                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
1587                    if skuname not in str_pcd_obj.SkuInfoList:
1588                        str_pcd_obj.SkuInfoList[skuname] = SkuInfoClass(SkuIdName=skuname, SkuId=self.SkuIds[skuname][0], HiiDefaultValue=PcdValue, DefaultStore = {StoreName:PcdValue})
1589                    else:
1590                        str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue = PcdValue
1591                        str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.update({StoreName:PcdValue})
1592                elif str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
1593                                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
1594                    if skuname in (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT, TAB_COMMON):
1595                        str_pcd_obj.DefaultValue = PcdValue
1596                else:
1597                    if skuname not in str_pcd_obj.SkuInfoList:
1598                        nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
1599                        NoDefault = False
1600                        while nextskuid not in str_pcd_obj.SkuInfoList:
1601                            if nextskuid == TAB_DEFAULT:
1602                                NoDefault = True
1603                                break
1604                            nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
1605                        str_pcd_obj.SkuInfoList[skuname] = copy.deepcopy(str_pcd_obj.SkuInfoList[nextskuid]) if not NoDefault else SkuInfoClass(SkuIdName=skuname, SkuId=self.SkuIds[skuname][0], DefaultValue=PcdValue)
1606                        str_pcd_obj.SkuInfoList[skuname].SkuId = self.SkuIds[skuname][0]
1607                        str_pcd_obj.SkuInfoList[skuname].SkuIdName = skuname
1608                    else:
1609                        str_pcd_obj.SkuInfoList[skuname].DefaultValue = PcdValue
1610            for str_pcd_obj in S_pcd_set.values():
1611                if str_pcd_obj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
1612                                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
1613                    continue
1614                PcdDefaultStoreSet = set(defaultstorename for skuobj in str_pcd_obj.SkuInfoList.values() for defaultstorename in skuobj.DefaultStoreDict)
1615                DefaultStoreObj = DefaultStore(self._GetDefaultStores())
1616                mindefaultstorename = DefaultStoreObj.GetMin(PcdDefaultStoreSet)
1617                str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].HiiDefaultValue = str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].DefaultStoreDict[mindefaultstorename]
1618
1619            for str_pcd_obj in S_pcd_set.values():
1620
1621                str_pcd_obj.MaxDatumSize = DscBuildData.GetStructurePcdMaxSize(str_pcd_obj)
1622                Pcds[str_pcd_obj.TokenCName, str_pcd_obj.TokenSpaceGuidCName] = str_pcd_obj
1623                Pcds[str_pcd_obj.TokenCName, str_pcd_obj.TokenSpaceGuidCName].CustomAttribute['IsStru']=True
1624
1625            for pcdkey in Pcds:
1626                pcd = Pcds[pcdkey]
1627                if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
1628                    pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
1629                    del pcd.SkuInfoList[TAB_COMMON]
1630                elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
1631                    del pcd.SkuInfoList[TAB_COMMON]
1632
1633        list(map(self.FilterSkuSettings, [Pcds[pcdkey] for pcdkey in Pcds if Pcds[pcdkey].Type in DynamicPcdType]))
1634        return Pcds
1635    @cached_property
1636    def PlatformUsedPcds(self):
1637        FdfInfList = []
1638        if GlobalData.gFdfParser:
1639            FdfInfList = GlobalData.gFdfParser.Profile.InfList
1640        FdfModuleList = [PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch) for Inf in FdfInfList]
1641        AllModulePcds = set()
1642        ModuleSet = set(list(self._Modules.keys()) + FdfModuleList)
1643        for ModuleFile in ModuleSet:
1644            ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
1645            AllModulePcds = AllModulePcds | ModuleData.PcdsName
1646        for ModuleFile in self.LibraryInstances:
1647            ModuleData = self._Bdb.CreateBuildObject(ModuleFile, self._Arch, self._Target, self._Toolchain)
1648            AllModulePcds = AllModulePcds | ModuleData.PcdsName
1649        return AllModulePcds
1650
1651    #Filter the StrucutrePcd that is not used by any module in dsc file and fdf file.
1652    def FilterStrcturePcd(self, S_pcd_set):
1653        UnusedStruPcds = set(S_pcd_set.keys()) - self.PlatformUsedPcds
1654        for (Token, TokenSpaceGuid) in UnusedStruPcds:
1655            del S_pcd_set[(Token, TokenSpaceGuid)]
1656
1657    ## Retrieve non-dynamic PCD settings
1658    #
1659    #   @param  Type    PCD type
1660    #
1661    #   @retval a dict object contains settings of given PCD type
1662    #
1663    def _GetPcd(self, Type):
1664        Pcds = OrderedDict()
1665        #
1666        # tdict is a special dict kind of type, used for selecting correct
1667        # PCD settings for certain ARCH
1668        #
1669        AvailableSkuIdSet = copy.copy(self.SkuIds)
1670
1671        PcdDict = tdict(True, 4)
1672        PcdList = []
1673        # Find out all possible PCD candidates for self._Arch
1674        RecordList = self._RawData[Type, self._Arch]
1675        PcdValueDict = OrderedDict()
1676        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4, Dummy5 in RecordList:
1677            SkuName = SkuName.upper()
1678            SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
1679            if SkuName not in AvailableSkuIdSet:
1680                EdkLogger.error('build ', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
1681                                            File=self.MetaFile, Line=Dummy5)
1682            if SkuName in (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT, TAB_COMMON):
1683                if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, Dummy5) not in PcdList:
1684                    PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
1685                PcdDict[Arch, PcdCName, TokenSpaceGuid, SkuName] = Setting
1686
1687        for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
1688            Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid, SkuName]
1689            if Setting is None:
1690                continue
1691            PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
1692            if MaxDatumSize:
1693                if int(MaxDatumSize, 0) > 0xFFFF:
1694                    EdkLogger.error('build', FORMAT_INVALID, "The size value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)),
1695                                    File=self.MetaFile, Line=Dummy4)
1696                if int(MaxDatumSize, 0) < 0:
1697                    EdkLogger.error('build', FORMAT_INVALID, "The size value can't be set to negative value for %s." % ".".join((TokenSpaceGuid, PcdCName)),
1698                                    File=self.MetaFile, Line=Dummy4)
1699            if (PcdCName, TokenSpaceGuid) in PcdValueDict:
1700                PcdValueDict[PcdCName, TokenSpaceGuid][SkuName] = (PcdValue, DatumType, MaxDatumSize,Dummy4)
1701            else:
1702                PcdValueDict[PcdCName, TokenSpaceGuid] = {SkuName:(PcdValue, DatumType, MaxDatumSize,Dummy4)}
1703
1704        for ((PcdCName, TokenSpaceGuid), PcdSetting) in PcdValueDict.items():
1705            if self.SkuIdMgr.SystemSkuId in PcdSetting:
1706                PcdValue, DatumType, MaxDatumSize,_ = PcdSetting[self.SkuIdMgr.SystemSkuId]
1707            elif TAB_DEFAULT in PcdSetting:
1708                PcdValue, DatumType, MaxDatumSize,_  = PcdSetting[TAB_DEFAULT]
1709            elif TAB_COMMON in PcdSetting:
1710                PcdValue, DatumType, MaxDatumSize,_  = PcdSetting[TAB_COMMON]
1711            else:
1712                PcdValue = None
1713                DatumType = None
1714                MaxDatumSize = None
1715
1716            Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
1717                                                PcdCName,
1718                                                TokenSpaceGuid,
1719                                                self._PCD_TYPE_STRING_[Type],
1720                                                DatumType,
1721                                                PcdValue,
1722                                                '',
1723                                                MaxDatumSize,
1724                                                {},
1725                                                False,
1726                                                None,
1727                                                IsDsc=True)
1728            for SkuName in PcdValueDict[PcdCName, TokenSpaceGuid]:
1729                Settings = PcdValueDict[PcdCName, TokenSpaceGuid][SkuName]
1730                if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
1731                    Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
1732                    Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
1733                Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][TAB_DEFAULT_STORES_DEFAULT] = Settings[0]
1734                Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][TAB_DEFAULT_STORES_DEFAULT] = (self.MetaFile.File,Settings[3])
1735        return Pcds
1736
1737    @staticmethod
1738    def GetStructurePcdMaxSize(str_pcd):
1739        pcd_default_value = str_pcd.DefaultValue
1740        sku_values = [skuobj.HiiDefaultValue if str_pcd.Type in [DscBuildData._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], DscBuildData._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]] else skuobj.DefaultValue for skuobj in str_pcd.SkuInfoList.values()]
1741        sku_values.append(pcd_default_value)
1742
1743        def get_length(value):
1744            Value = value.strip()
1745            if len(value) > 1:
1746                if Value.startswith(TAB_GUID) and Value.endswith(')'):
1747                    return 16
1748                if Value.startswith('L"') and Value.endswith('"'):
1749                    return len(Value[2:-1])
1750                if Value[0] == '"' and Value[-1] == '"':
1751                    return len(Value) - 2
1752                if Value.strip().startswith("{CODE("):
1753                    tmpValue = RemoveCComments(Value)
1754                    return len(tmpValue.split(","))
1755                if (Value[0] == '{' and Value[-1] == '}'):
1756                    return len(Value.split(","))
1757                if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
1758                    return  len(list(Value[2:-1]))
1759                if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
1760                    return len(Value) - 2
1761            return len(Value)
1762
1763        return str(max(get_length(item) for item in sku_values))
1764
1765    @staticmethod
1766    def ExecuteCommand (Command):
1767        try:
1768            Process = subprocess.Popen(Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
1769        except:
1770            EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s' % Command)
1771        Result = Process.communicate()
1772        return Process.returncode, Result[0].decode(errors='ignore'), Result[1].decode(errors='ignore')
1773
1774    @staticmethod
1775    def IntToCString(Value, ValueSize):
1776        Result = '"'
1777        if not isinstance (Value, str):
1778            for Index in range(0, ValueSize):
1779                Result = Result + '\\x%02x' % (Value & 0xff)
1780                Value = Value >> 8
1781        Result = Result + '"'
1782        return Result
1783
1784    def GenerateSizeFunction(self, Pcd):
1785        CApp = "// Default Value in Dec \n"
1786        CApp = CApp + "void Cal_%s_%s_Size(UINT32 *Size){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
1787
1788        if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
1789            CApp += "  *Size = (sizeof (%s) > *Size ? sizeof (%s) : *Size);\n" % (Pcd.DatumType,Pcd.DatumType)
1790        else:
1791            if "{CODE(" in Pcd.DefaultValueFromDec:
1792                CApp += "  *Size = (sizeof (%s_%s_INIT_Value) > *Size ? sizeof (%s_%s_INIT_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,Pcd.TokenSpaceGuidCName,Pcd.TokenCName)
1793            if Pcd.Type in PCD_DYNAMIC_TYPE_SET | PCD_DYNAMIC_EX_TYPE_SET:
1794                for skuname in Pcd.SkuInfoList:
1795                    skuobj = Pcd.SkuInfoList[skuname]
1796                    if skuobj.VariableName:
1797                        for defaultstore in skuobj.DefaultStoreDict:
1798                            pcddef = self.GetPcdDscRawDefaultValue(Pcd,skuname,defaultstore)
1799                            if pcddef:
1800                                if "{CODE(" in pcddef:
1801                                    CApp += "  *Size = (sizeof (%s_%s_%s_%s_Value) > *Size ? sizeof (%s_%s_%s_%s_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,defaultstore,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,defaultstore)
1802                                else:
1803                                    CApp += "  *Size = %s > *Size ? %s : *Size;\n" % (self.GetStructurePcdMaxSize(Pcd),self.GetStructurePcdMaxSize(Pcd))
1804                    else:
1805                        pcddef = self.GetPcdDscRawDefaultValue(Pcd,skuname,TAB_DEFAULT_STORES_DEFAULT)
1806                        if pcddef:
1807                            if  "{CODE(" in pcddef:
1808                                CApp += "  *Size = (sizeof (%s_%s_%s_%s_Value) > *Size ? sizeof (%s_%s_%s_%s_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,TAB_DEFAULT_STORES_DEFAULT,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,TAB_DEFAULT_STORES_DEFAULT)
1809                            else:
1810                                CApp += "  *Size = %s > *Size ? %s : *Size;\n" % (self.GetStructurePcdMaxSize(Pcd),self.GetStructurePcdMaxSize(Pcd))
1811            else:
1812                pcddef = self.GetPcdDscRawDefaultValue(Pcd,TAB_DEFAULT,TAB_DEFAULT_STORES_DEFAULT)
1813                if pcddef:
1814                    if "{CODE(" in pcddef:
1815                        CApp += "  *Size = (sizeof (%s_%s_%s_%s_Value) > *Size ? sizeof (%s_%s_%s_%s_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,TAB_DEFAULT,TAB_DEFAULT_STORES_DEFAULT,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,TAB_DEFAULT,TAB_DEFAULT_STORES_DEFAULT)
1816                    else:
1817                        CApp += "  *Size = %s > *Size ? %s : *Size;\n" % (self.GetStructurePcdMaxSize(Pcd),self.GetStructurePcdMaxSize(Pcd))
1818        ActualCap = []
1819        for index in Pcd.DefaultValues:
1820            if index:
1821                ActualCap.append(index)
1822            FieldList = Pcd.DefaultValues[index]
1823            if not FieldList:
1824                continue
1825            for FieldName in FieldList:
1826                FieldName = "." + FieldName
1827                IsArray = _IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
1828                if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
1829                    try:
1830                        Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
1831                    except BadExpression:
1832                        EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
1833                                        (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2]))
1834                    Value, ValueSize = ParseFieldValue(Value)
1835                    if not Pcd.IsArray():
1836                        CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0));  // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2], FieldList[FieldName.strip(".")][0]);
1837                else:
1838                    NewFieldName = ''
1839                    FieldName_ori = FieldName.strip('.')
1840                    while '[' in  FieldName:
1841                        NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
1842                        Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
1843                        FieldName = FieldName.split(']', 1)[1]
1844                    FieldName = NewFieldName + FieldName
1845                    while '[' in FieldName and not Pcd.IsArray():
1846                        FieldName = FieldName.rsplit('[', 1)[0]
1847                        CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2], FieldList[FieldName_ori][0])
1848        for skuname in Pcd.SkuOverrideValues:
1849            if skuname == TAB_COMMON:
1850                continue
1851            for defaultstorenameitem in Pcd.SkuOverrideValues[skuname]:
1852                CApp = CApp + "// SkuName: %s,  DefaultStoreName: %s \n" % (skuname, defaultstorenameitem)
1853                for index in Pcd.SkuOverrideValues[skuname][defaultstorenameitem]:
1854                    if index:
1855                        ActualCap.append(index)
1856                    for FieldList in [Pcd.SkuOverrideValues[skuname][defaultstorenameitem][index]]:
1857                        if not FieldList:
1858                            continue
1859                        for FieldName in FieldList:
1860                            FieldName = "." + FieldName
1861                            IsArray = _IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
1862                            if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
1863                                try:
1864                                    Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
1865                                except BadExpression:
1866                                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
1867                                                    (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2]))
1868                                Value, ValueSize = ParseFieldValue(Value)
1869                                if not Pcd.IsArray():
1870                                    CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0)); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2], FieldList[FieldName.strip(".")][0]);
1871                            else:
1872                                NewFieldName = ''
1873                                FieldName_ori = FieldName.strip('.')
1874                                while '[' in  FieldName:
1875                                    NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
1876                                    Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
1877                                    FieldName = FieldName.split(']', 1)[1]
1878                                FieldName = NewFieldName + FieldName
1879                                while '[' in FieldName and not Pcd.IsArray():
1880                                    FieldName = FieldName.rsplit('[', 1)[0]
1881                                    CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2], FieldList[FieldName_ori][0])
1882        if Pcd.PcdFieldValueFromFdf:
1883            CApp = CApp + "// From fdf \n"
1884        for FieldName in Pcd.PcdFieldValueFromFdf:
1885            FieldName = "." + FieldName
1886            IsArray = _IsFieldValueAnArray(Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0])
1887            if IsArray and not (Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0].startswith('{GUID') and Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0].endswith('}')):
1888                try:
1889                    Value = ValueExpressionEx(Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
1890                except BadExpression:
1891                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
1892                                    (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][1], Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][2]))
1893                Value, ValueSize = ParseFieldValue(Value)
1894                if not Pcd.IsArray():
1895                    CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0)); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][1], Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][2], Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0]);
1896            else:
1897                NewFieldName = ''
1898                FieldName_ori = FieldName.strip('.')
1899                while '[' in  FieldName:
1900                    NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
1901                    Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
1902                    FieldName = FieldName.split(']', 1)[1]
1903                FieldName = NewFieldName + FieldName
1904                while '[' in FieldName:
1905                    FieldName = FieldName.rsplit('[', 1)[0]
1906                    CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %s Value %s \n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, Pcd.PcdFieldValueFromFdf[FieldName_ori][1], Pcd.PcdFieldValueFromFdf[FieldName_ori][2], Pcd.PcdFieldValueFromFdf[FieldName_ori][0])
1907        if Pcd.PcdFieldValueFromComm:
1908            CApp = CApp + "// From Command Line \n"
1909        for FieldName in Pcd.PcdFieldValueFromComm:
1910            FieldName = "." + FieldName
1911            IsArray = _IsFieldValueAnArray(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0])
1912            if IsArray and not (Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].startswith('{GUID') and Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].endswith('}')):
1913                try:
1914                    Value = ValueExpressionEx(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
1915                except BadExpression:
1916                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
1917                                    (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), Pcd.PcdFieldValueFromComm[FieldName.strip(".")][1], Pcd.PcdFieldValueFromComm[FieldName.strip(".")][2]))
1918                Value, ValueSize = ParseFieldValue(Value)
1919                if not Pcd.IsArray():
1920                    CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0)); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), Pcd.PcdFieldValueFromComm[FieldName.strip(".")][1], Pcd.PcdFieldValueFromComm[FieldName.strip(".")][2], Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0]);
1921            else:
1922                NewFieldName = ''
1923                FieldName_ori = FieldName.strip('.')
1924                while '[' in  FieldName:
1925                    NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
1926                    Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
1927                    FieldName = FieldName.split(']', 1)[1]
1928                FieldName = NewFieldName + FieldName
1929                while '[' in FieldName and not Pcd.IsArray():
1930                    FieldName = FieldName.rsplit('[', 1)[0]
1931                    CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, Pcd.PcdFieldValueFromComm[FieldName_ori][1], Pcd.PcdFieldValueFromComm[FieldName_ori][2], Pcd.PcdFieldValueFromComm[FieldName_ori][0])
1932        if Pcd.GetPcdMaxSize():
1933            CApp = CApp + "  *Size = (%d > *Size ? %d : *Size); // The Pcd maxsize is %d \n" % (Pcd.GetPcdMaxSize(), Pcd.GetPcdMaxSize(), Pcd.GetPcdMaxSize())
1934        ArraySizeByAssign = self.CalculateActualCap(ActualCap)
1935        if ArraySizeByAssign > 1:
1936            CApp = CApp + "  *Size = (%d > *Size ? %d : *Size); \n" % (ArraySizeByAssign, ArraySizeByAssign)
1937        CApp = CApp + "}\n"
1938        return CApp
1939    def CalculateActualCap(self,ActualCap):
1940        if not ActualCap:
1941            return 1
1942        maxsize = 1
1943        for item in ActualCap:
1944            index_elements = ArrayIndex.findall(item)
1945            rt = 1
1946            for index_e in index_elements:
1947                index_num = index_e.lstrip("[").rstrip("]").strip()
1948                if not index_num:
1949                    # Not support flexiable pcd array assignment
1950                    return 1
1951                index_num = int(index_num,16) if index_num.startswith(("0x","0X")) else int(index_num)
1952                rt = rt * (index_num+1)
1953            if rt  >maxsize:
1954                maxsize = rt
1955
1956        return maxsize
1957
1958    @staticmethod
1959    def GenerateSizeStatments(Pcd,skuname,defaultstorename):
1960        if Pcd.IsArray():
1961            r_datatype = [Pcd.BaseDatumType]
1962            lastoneisEmpty = False
1963            for dem in Pcd.Capacity:
1964                if lastoneisEmpty:
1965                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s.  " %
1966                                        (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))))
1967                if dem == '0' or dem == "-1":
1968                    r_datatype.append("[1]")
1969                    lastoneisEmpty = True
1970                else:
1971                    r_datatype.append("[" + dem + "]")
1972
1973            if Pcd.Type in [MODEL_PCD_DYNAMIC_EX_HII, MODEL_PCD_DYNAMIC_HII]:
1974                PcdDefValue = Pcd.SkuInfoList.get(skuname).DefaultStoreDict.get(defaultstorename)
1975            elif Pcd.Type in [MODEL_PCD_DYNAMIC_EX_DEFAULT,MODEL_PCD_DYNAMIC_VPD,MODEL_PCD_DYNAMIC_DEFAULT,MODEL_PCD_DYNAMIC_EX_VPD]:
1976                PcdDefValue = Pcd.SkuInfoList.get(skuname).DefaultValue
1977            else:
1978                PcdDefValue = Pcd.DefaultValue
1979            if lastoneisEmpty:
1980                if "{CODE(" not in PcdDefValue:
1981                    sizebasevalue_plus = "(%s / sizeof(%s) + 1)" % ((DscBuildData.GetStructurePcdMaxSize(Pcd), Pcd.BaseDatumType))
1982                    sizebasevalue = "(%s / sizeof(%s))" % ((DscBuildData.GetStructurePcdMaxSize(Pcd), Pcd.BaseDatumType))
1983                    sizeof = "sizeof(%s)" % Pcd.BaseDatumType
1984                    CApp = '  int ArraySize = %s %% %s ? %s : %s ;\n' % ( (DscBuildData.GetStructurePcdMaxSize(Pcd), sizeof, sizebasevalue_plus, sizebasevalue))
1985                    CApp += '  Size = ArraySize * sizeof(%s); \n' % Pcd.BaseDatumType
1986                else:
1987                    CApp = "  Size = 0;\n"
1988            else:
1989                CApp = '  Size = sizeof(%s);\n' % ("".join(r_datatype) )
1990        else:
1991            CApp = '  Size = sizeof(%s);\n' % (Pcd.DatumType)
1992        CApp = CApp + '  Cal_%s_%s_Size(&Size);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
1993        return CApp
1994
1995    def GetIndicator(self,index,FieldName,Pcd):
1996        def cleanupindex(indexstr):
1997            return indexstr.strip("[").strip("]").strip()
1998        index_elements = ArrayIndex.findall(index)
1999        pcd_capacity = Pcd.Capacity
2000        if index:
2001            indicator = "(Pcd"
2002            if len(pcd_capacity)>2:
2003                for i in range(0,len(index_elements)):
2004                    index_ele = index_elements[i]
2005                    index_num = index_ele.strip("[").strip("]").strip()
2006                    if i == len(index_elements) -2:
2007                        indicator += "+ %d*Size/sizeof(%s)/%d + %s)" %(int(cleanupindex(index_elements[i+1])),Pcd.BaseDatumType,reduce(lambda x,y: int(x)*int(y),pcd_capacity[:-1]), cleanupindex(index_elements[i]))
2008                        break
2009                    else:
2010                        indicator += " + %d*%s*Size/sizeof(%s)/%d" %(int(cleanupindex(index_elements[i])),reduce(lambda x,y: int(x)*int(y),pcd_capacity[i+1:-1]),Pcd.BaseDatumType,reduce(lambda x,y: int(x)*int(y),pcd_capacity[:-1]))
2011            elif len(pcd_capacity) == 2:
2012                indicator += "+ %d*Size/sizeof(%s)/%d + %s)" %(int(cleanupindex(index_elements[0])),Pcd.BaseDatumType,int(pcd_capacity[0]), index_elements[1].strip("[").strip("]").strip())
2013            elif len(pcd_capacity) == 1:
2014                index_ele = index_elements[0]
2015                index_num = index_ele.strip("[").strip("]").strip()
2016                indicator += " + %s)" % (index_num)
2017        else:
2018            indicator = "Pcd"
2019        if FieldName:
2020            indicator += "->" + FieldName
2021        return indicator
2022
2023    def GetStarNum(self,Pcd):
2024        if not Pcd.IsArray():
2025            return 1
2026        elif Pcd.IsSimpleTypeArray():
2027            return len(Pcd.Capacity)
2028        else:
2029            return len(Pcd.Capacity) + 1
2030    def GenerateDefaultValueAssignFunction(self, Pcd):
2031        CApp = "// Default value in Dec \n"
2032        CApp = CApp + "void Assign_%s_%s_Default_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.BaseDatumType)
2033        CApp = CApp + '  UINT32  FieldSize;\n'
2034        CApp = CApp + '  CHAR8   *Value;\n'
2035        CApp = CApp + ' UINT32 PcdArraySize;\n'
2036        DefaultValueFromDec = Pcd.DefaultValueFromDec
2037        IsArray = _IsFieldValueAnArray(Pcd.DefaultValueFromDec)
2038        if IsArray:
2039            try:
2040                DefaultValueFromDec = ValueExpressionEx(Pcd.DefaultValueFromDec, TAB_VOID)(True)
2041            except BadExpression:
2042                EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DEC: %s" %
2043                                (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValueFromDec))
2044        DefaultValueFromDec = StringToArray(DefaultValueFromDec)
2045        Value, ValueSize = ParseFieldValue (DefaultValueFromDec)
2046        if IsArray:
2047            #
2048            # Use memcpy() to copy value into field
2049            #
2050            if Pcd.IsArray():
2051                pcdarraysize = Pcd.PcdArraySize()
2052                if "{CODE(" in Pcd.DefaultValueFromDec:
2053                    if Pcd.Capacity[-1] != "-1":
2054                        CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_INIT_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dec exceed the array capability %s"); // From  %s Line %s \n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,Pcd.DefaultValueFromDecInfo[0],Pcd.DefaultValueFromDecInfo[1])
2055                    CApp = CApp + ' PcdArraySize = sizeof(%s_%s_INIT_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2056                    CApp = CApp + '  memcpy (Pcd, %s_%s_INIT_Value,PcdArraySize);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2057                else:
2058                    if Pcd.Capacity[-1] != "-1":
2059                        CApp = CApp + '__STATIC_ASSERT(%d < %d * sizeof(%s), "Pcd %s.%s Value in Dec exceed the array capability %s"); // From %s Line %s \n' % (ValueSize,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,Pcd.DefaultValueFromDecInfo[0],Pcd.DefaultValueFromDecInfo[1])
2060                    CApp = CApp + ' PcdArraySize = %d;\n' % ValueSize
2061                    CApp = CApp + '  Value     = %s; // From DEC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultValueFromDec)
2062                    CApp = CApp + '  memcpy (Pcd, Value, PcdArraySize);\n'
2063            else:
2064                if "{CODE(" in Pcd.DefaultValueFromDec:
2065                    CApp = CApp + '  PcdArraySize = sizeof(%s_%s_INIT_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2066                    CApp = CApp + '  memcpy (Pcd, &%s_%s_INIT_Value,PcdArraySize);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2067                else:
2068                    CApp = CApp + '  Value     = %s; // From DEC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultValueFromDec)
2069                    CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
2070        elif isinstance(Value, str):
2071            CApp = CApp + '  Pcd = %s; // From DEC Default Value %s\n' % (Value, Pcd.DefaultValueFromDec)
2072        for index in Pcd.DefaultValues:
2073            FieldList = Pcd.DefaultValues[index]
2074            if not FieldList:
2075                continue
2076            for FieldName in FieldList:
2077                IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
2078                if IsArray:
2079                    try:
2080                        FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
2081                    except BadExpression:
2082                        EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
2083                                        (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
2084
2085                try:
2086                    Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
2087                except Exception:
2088                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
2089
2090                indicator = self.GetIndicator(index, FieldName,Pcd)
2091                if IsArray:
2092                    #
2093                    # Use memcpy() to copy value into field
2094                    #
2095                    CApp = CApp + '  FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
2096                    CApp = CApp + '  Value     = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2097                    CApp = CApp + '  __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2098                    CApp = CApp + '  memcpy (&%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (indicator, ValueSize, ValueSize)
2099                elif isinstance(Value, str):
2100                    CApp = CApp + '  %s = %s; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2101                else:
2102                    if '[' in FieldName and ']' in FieldName:
2103                        Index = int(FieldName.split('[')[1].split(']')[0])
2104                        CApp = CApp + '  __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
2105                    if ValueSize > 4:
2106                        CApp = CApp + '  %s = %dULL; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2107                    else:
2108                        CApp = CApp + '  %s = %d; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2109        CApp = CApp + "}\n"
2110        return CApp
2111
2112    @staticmethod
2113    def GenerateDefaultValueAssignStatement(Pcd):
2114        CApp = '  Assign_%s_%s_Default_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2115        return CApp
2116
2117    def GetPcdDscRawDefaultValue(self,Pcd, SkuName,DefaultStoreName):
2118        if Pcd.Type in PCD_DYNAMIC_TYPE_SET or Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
2119            if (SkuName, DefaultStoreName) == (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT):
2120                pcddefaultvalue = Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT) if Pcd.DefaultFromDSC else None
2121            else:
2122                pcddefaultvalue = Pcd.DscRawValue.get(SkuName, {}).get(DefaultStoreName)
2123        else:
2124            pcddefaultvalue = Pcd.DscRawValue.get(SkuName, {}).get(TAB_DEFAULT_STORES_DEFAULT)
2125
2126        return pcddefaultvalue
2127    def GetPcdDscRawValueInfo(self,Pcd, SkuName,DefaultStoreName):
2128        DscValueInfo = Pcd.DscRawValueInfo.get(SkuName, {}).get(DefaultStoreName)
2129        if DscValueInfo:
2130            dscfilepath,lineno = DscValueInfo
2131        else:
2132            dscfilepath = self.MetaFile.File
2133            lineno = ""
2134        return dscfilepath,lineno
2135
2136    def GenerateInitValueFunction(self, Pcd, SkuName, DefaultStoreName):
2137        CApp = "// Value in Dsc for Sku: %s, DefaultStore %s\n" % (SkuName, DefaultStoreName)
2138        CApp = CApp + "void Assign_%s_%s_%s_%s_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, SkuName, DefaultStoreName, Pcd.BaseDatumType)
2139        CApp = CApp + '  UINT32  FieldSize;\n'
2140        CApp = CApp + '  CHAR8   *Value;\n'
2141        CApp = CApp + ' UINT32 PcdArraySize;\n'
2142
2143        CApp = CApp + "// SkuName: %s,  DefaultStoreName: %s \n" % (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT)
2144        inherit_OverrideValues = Pcd.SkuOverrideValues[SkuName]
2145        dscfilepath,lineno = self.GetPcdDscRawValueInfo(Pcd, SkuName, DefaultStoreName)
2146        if lineno:
2147            valuefrom = "%s Line %s" % (dscfilepath,str(lineno))
2148        else:
2149            valuefrom = dscfilepath
2150
2151        pcddefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, SkuName, DefaultStoreName)
2152        if pcddefaultvalue:
2153            FieldList = pcddefaultvalue
2154            IsArray = _IsFieldValueAnArray(FieldList)
2155            if IsArray:
2156                if "{CODE(" not in FieldList:
2157                    try:
2158                        FieldList = ValueExpressionEx(FieldList, TAB_VOID)(True)
2159                    except BadExpression:
2160                        EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DSC: %s" %
2161                                        (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
2162            Value, ValueSize = ParseFieldValue (FieldList)
2163
2164            if (SkuName, DefaultStoreName) == (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT):
2165                if isinstance(Value, str):
2166                    if "{CODE(" in Value:
2167                        if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
2168                            pcdarraysize = Pcd.PcdArraySize()
2169                            CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType, valuefrom)
2170                        CApp = CApp+ ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2171                        CApp = CApp + '  memcpy (Pcd, &%s_%s_%s_%s_Value,PcdArraySize);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2172                    else:
2173                        CApp = CApp + '  Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
2174                elif IsArray:
2175                    #
2176                    # Use memcpy() to copy value into field
2177                    #
2178                    if Pcd.IsArray():
2179                        pcdarraysize = Pcd.PcdArraySize()
2180                        if "{CODE(" in pcddefaultvalue:
2181                            if Pcd.Capacity[-1] != "-1":
2182                                CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From  %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
2183                            CApp = CApp + ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2184                            CApp = CApp + '  memcpy (Pcd, %s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2185                        else:
2186                            if Pcd.Capacity[-1] != "-1":
2187                                CApp = CApp + '__STATIC_ASSERT(%d < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From  %s \n' % (ValueSize,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
2188                            CApp = CApp + ' PcdArraySize = %d;\n' % ValueSize
2189                            CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
2190                            CApp = CApp + '  memcpy (Pcd, Value, PcdArraySize);\n'
2191                    else:
2192                        if "{CODE(" in pcddefaultvalue:
2193                            CApp = CApp + '  PcdArraySize = %d < sizeof(%s) * %d ? %d: sizeof(%s) * %d;\n ' % (ValueSize,Pcd.BaseDatumType,pcdarraysize,ValueSize,Pcd.BaseDatumType,pcdarraysize)
2194                            CApp = CApp + '  memcpy (Pcd, &%s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2195                        else:
2196                            CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
2197                            CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
2198            else:
2199                if isinstance(Value, str):
2200                    if "{CODE(" in Value:
2201                        if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
2202                            pcdarraysize = Pcd.PcdArraySize()
2203                            CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
2204                        CApp = CApp + ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n '% (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2205                        CApp = CApp + '  memcpy (Pcd, &%s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2206                    else:
2207                        CApp = CApp + '  Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DscRawValue.get(SkuName, {}).get(DefaultStoreName))
2208                elif IsArray:
2209                    #
2210                    # Use memcpy() to copy value into field
2211                    #
2212                    if Pcd.IsArray():
2213                        pcdarraysize = Pcd.PcdArraySize()
2214                        if "{CODE(" in pcddefaultvalue:
2215                            if Pcd.Capacity[-1] != "-1":
2216                                CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From  %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
2217                            CApp + ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2218                            CApp = CApp + '  memcpy (Pcd, %s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2219                        else:
2220                            if Pcd.Capacity[-1] != "-1":
2221                                CApp = CApp + '__STATIC_ASSERT(%d < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From  %s \n' % (ValueSize,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
2222                            CApp = CApp + ' PcdArraySize = %d;\n' % ValueSize
2223                            CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DscRawValue.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
2224                            CApp = CApp + '  memcpy (Pcd, Value, PcdArraySize);\n'
2225                    else:
2226                        if "{CODE(" in pcddefaultvalue:
2227                            CApp = CApp + '  PcdArraySize = %d < sizeof(%s) * %d ? %d: sizeof(%s) * %d;\n ' % (ValueSize,Pcd.BaseDatumType,pcdarraysize,ValueSize,Pcd.BaseDatumType,pcdarraysize)
2228                            CApp = CApp + '  memcpy (Pcd, &%s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
2229                        else:
2230                            CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DscRawValue.get(SkuName, {}).get(DefaultStoreName))
2231                            CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
2232
2233        inheritvalue = inherit_OverrideValues.get(DefaultStoreName)
2234        if not inheritvalue:
2235            inheritvalue = []
2236        for index in inheritvalue:
2237            FieldList = inheritvalue[index]
2238            if not FieldList:
2239                continue
2240            if (SkuName, DefaultStoreName) == (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT) or (( (SkuName, '') not in Pcd.ValueChain) and ( (SkuName, DefaultStoreName) not in Pcd.ValueChain )):
2241                for FieldName in FieldList:
2242                    indicator = self.GetIndicator(index, FieldName,Pcd)
2243                    IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
2244                    if IsArray:
2245                        try:
2246                            FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
2247                        except BadExpression:
2248                            EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
2249                                            (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
2250                    try:
2251                        Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
2252                    except Exception:
2253                        EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
2254                    if isinstance(Value, str):
2255                        CApp = CApp + '  Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2256                    elif IsArray:
2257                    #
2258                    # Use memcpy() to copy value into field
2259                    #
2260                        CApp = CApp + '  FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
2261                        CApp = CApp + '  Value     = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2262                        CApp = CApp + '  __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2263                        CApp = CApp + '  memcpy (&%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (indicator, ValueSize, ValueSize)
2264                    else:
2265                        if '[' in FieldName and ']' in FieldName:
2266                            Index = int(FieldName.split('[')[1].split(']')[0])
2267                            CApp = CApp + '  __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
2268                        if ValueSize > 4:
2269                            CApp = CApp + '  %s = %dULL; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2270                        else:
2271                            CApp = CApp + '  %s = %d; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2272        CApp = CApp + "}\n"
2273        return CApp
2274
2275    @staticmethod
2276    def GenerateInitValueStatement(Pcd, SkuName, DefaultStoreName):
2277        CApp = '  Assign_%s_%s_%s_%s_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, SkuName, DefaultStoreName)
2278        return CApp
2279
2280    def GenerateCommandLineValue(self, Pcd):
2281        CApp = "// Value in CommandLine\n"
2282        CApp = CApp + "void Assign_%s_%s_CommandLine_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.BaseDatumType)
2283        CApp = CApp + '  UINT32  FieldSize;\n'
2284        CApp = CApp + '  CHAR8   *Value;\n'
2285
2286        pcddefaultvalue = Pcd.PcdValueFromComm
2287        for FieldList in [pcddefaultvalue, Pcd.PcdFieldValueFromComm]:
2288            if not FieldList:
2289                continue
2290            if pcddefaultvalue and FieldList == pcddefaultvalue:
2291                IsArray = _IsFieldValueAnArray(FieldList)
2292                if IsArray:
2293                    try:
2294                        FieldList = ValueExpressionEx(FieldList, TAB_VOID)(True)
2295                    except BadExpression:
2296                        EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from Command: %s" %
2297                                        (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
2298                Value, ValueSize = ParseFieldValue (FieldList)
2299
2300                if isinstance(Value, str):
2301                    CApp = CApp + '  Pcd = %s; // From Command Line \n' % (Value)
2302                elif IsArray:
2303                #
2304                # Use memcpy() to copy value into field
2305                #
2306                    CApp = CApp + '  Value     = %s; // From Command Line.\n' % (DscBuildData.IntToCString(Value, ValueSize))
2307                    CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
2308                continue
2309            for FieldName in FieldList:
2310                IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
2311                if IsArray:
2312                    try:
2313                        FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
2314                    except BadExpression:
2315                        EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
2316                                        (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
2317                    except:
2318                        print("error")
2319                try:
2320                    Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
2321                except Exception:
2322                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
2323                if isinstance(Value, str):
2324                    CApp = CApp + '  Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2325                elif IsArray:
2326                #
2327                # Use memcpy() to copy value into field
2328                #
2329                    CApp = CApp + '  FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
2330                    CApp = CApp + '  Value     = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2331                    CApp = CApp + '  __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2332                    CApp = CApp + '  memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
2333                else:
2334                    if '[' in FieldName and ']' in FieldName:
2335                        Index = int(FieldName.split('[')[1].split(']')[0])
2336                        CApp = CApp + '  __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
2337                    if ValueSize > 4:
2338                        CApp = CApp + '  Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2339                    else:
2340                        CApp = CApp + '  Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2341        CApp = CApp + "}\n"
2342        return CApp
2343
2344    @staticmethod
2345    def GenerateCommandLineValueStatement(Pcd):
2346        CApp = '  Assign_%s_%s_CommandLine_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2347        return CApp
2348    def GenerateFdfValue(self,Pcd):
2349        CApp = "// Value in Fdf\n"
2350        CApp = CApp + "void Assign_%s_%s_Fdf_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.BaseDatumType)
2351        CApp = CApp + '  UINT32  FieldSize;\n'
2352        CApp = CApp + '  CHAR8   *Value;\n'
2353
2354        pcddefaultvalue = Pcd.PcdValueFromFdf
2355        for FieldList in [pcddefaultvalue,Pcd.PcdFieldValueFromFdf]:
2356            if not FieldList:
2357                continue
2358            if pcddefaultvalue and FieldList == pcddefaultvalue:
2359                IsArray = _IsFieldValueAnArray(FieldList)
2360                if IsArray:
2361                    try:
2362                        FieldList = ValueExpressionEx(FieldList, TAB_VOID)(True)
2363                    except BadExpression:
2364                        EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from Fdf: %s" %
2365                                        (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
2366                Value, ValueSize = ParseFieldValue (FieldList)
2367
2368                if isinstance(Value, str):
2369                    CApp = CApp + '  Pcd = %s; // From Fdf \n' % (Value)
2370                elif IsArray:
2371                #
2372                # Use memcpy() to copy value into field
2373                #
2374                    CApp = CApp + '  Value     = %s; // From Fdf .\n' % (DscBuildData.IntToCString(Value, ValueSize))
2375                    CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
2376                continue
2377            for FieldName in FieldList:
2378                IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
2379                if IsArray:
2380                    try:
2381                        FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
2382                    except BadExpression:
2383                        EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
2384                                        (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
2385                    except:
2386                        print("error")
2387                try:
2388                    Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
2389                except Exception:
2390                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName,FieldName)),FieldList[FieldName][1], FieldList[FieldName][2]))
2391                if isinstance(Value, str):
2392                    CApp = CApp + '  Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2393                elif IsArray:
2394                #
2395                # Use memcpy() to copy value into field
2396                #
2397                    CApp = CApp + '  FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
2398                    CApp = CApp + '  Value     = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2399                    CApp = CApp + '  __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2400                    CApp = CApp + '  memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
2401                else:
2402                    if '[' in FieldName and ']' in FieldName:
2403                        Index = int(FieldName.split('[')[1].split(']')[0])
2404                        CApp = CApp + '  __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
2405                    if ValueSize > 4:
2406                        CApp = CApp + '  Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2407                    else:
2408                        CApp = CApp + '  Pcd->%s = %d; // From %s Line %s Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
2409        CApp = CApp + "}\n"
2410        return CApp
2411
2412    @staticmethod
2413    def GenerateFdfValueStatement(Pcd):
2414        CApp = '  Assign_%s_%s_Fdf_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2415        return CApp
2416
2417    def GenerateInitializeFunc(self, SkuName, DefaultStore, Pcd, InitByteValue, CApp):
2418        OverrideValues = {DefaultStore:{}}
2419        if Pcd.SkuOverrideValues:
2420            OverrideValues = Pcd.SkuOverrideValues[SkuName]
2421        if not OverrideValues:
2422            OverrideValues = {TAB_DEFAULT_STORES_DEFAULT:Pcd.DefaultValues}
2423        for DefaultStoreName in OverrideValues:
2424            CApp = CApp + 'void\n'
2425            CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2426            CApp = CApp + '  void\n'
2427            CApp = CApp + '  )\n'
2428            CApp = CApp + '{\n'
2429            CApp = CApp + '  UINT32  Size;\n'
2430            CApp = CApp + '  UINT32  FieldSize;\n'
2431            CApp = CApp + '  CHAR8   *Value;\n'
2432            CApp = CApp + '  UINT32  OriginalSize;\n'
2433            CApp = CApp + '  VOID    *OriginalPcd;\n'
2434
2435            CApp = CApp + '  %s      *Pcd;  // From %s Line %d \n' % (Pcd.BaseDatumType,Pcd.PkgPath, Pcd.PcdDefineLineNo)
2436
2437            CApp = CApp + '\n'
2438
2439            PcdDefaultValue = StringToArray(Pcd.DefaultValueFromDec.strip())
2440
2441            InitByteValue += '%s.%s.%s.%s|%s|%s\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DatumType, PcdDefaultValue)
2442
2443            #
2444            # Get current PCD value and size
2445            #
2446            CApp = CApp + '  OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2447
2448            #
2449            # Determine the size of the PCD.  For simple structures, sizeof(TYPE) provides
2450            # the correct value.  For structures with a flexible array member, the flexible
2451            # array member is detected, and the size is based on the highest index used with
2452            # the flexible array member.  The flexible array member must be the last field
2453            # in a structure.  The size formula for this case is:
2454            # OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1)
2455            #
2456            CApp = CApp + DscBuildData.GenerateSizeStatments(Pcd,SkuName,DefaultStoreName)
2457            if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
2458                CApp = CApp + '  OriginalSize = OriginalSize < sizeof(%s) * %d? OriginalSize:sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize(),Pcd.BaseDatumType,Pcd.PcdArraySize())
2459                CApp = CApp + '  Size = sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize())
2460
2461            #
2462            # Allocate and zero buffer for the PCD
2463            # Must handle cases where current value is smaller, larger, or same size
2464            # Always keep that larger one as the current size
2465            #
2466            CApp = CApp + '  Size = (OriginalSize > Size ? OriginalSize : Size);\n'
2467            CApp = CApp + '  Pcd     = (%s *)malloc (Size);\n' % (Pcd.BaseDatumType,)
2468            CApp = CApp + '  memset (Pcd, 0, Size);\n'
2469
2470            #
2471            # Copy current PCD value into allocated buffer.
2472            #
2473            CApp = CApp + '  memcpy (Pcd, OriginalPcd, OriginalSize);\n'
2474
2475            #
2476            # Assign field values in PCD
2477            #
2478            CApp = CApp + DscBuildData.GenerateDefaultValueAssignStatement(Pcd)
2479            if Pcd.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
2480                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
2481                for skuname in self.SkuIdMgr.GetSkuChain(SkuName):
2482                    storeset = [DefaultStoreName] if DefaultStoreName == TAB_DEFAULT_STORES_DEFAULT else [TAB_DEFAULT_STORES_DEFAULT, DefaultStoreName]
2483                    for defaultstorenameitem in storeset:
2484                        CApp = CApp + "// SkuName: %s,  DefaultStoreName: %s \n" % (skuname, defaultstorenameitem)
2485                        CApp = CApp + DscBuildData.GenerateInitValueStatement(Pcd, skuname, defaultstorenameitem)
2486                    if skuname == SkuName:
2487                        break
2488            else:
2489                CApp = CApp + "// SkuName: %s,  DefaultStoreName: STANDARD \n" % self.SkuIdMgr.SystemSkuId
2490                CApp = CApp + DscBuildData.GenerateInitValueStatement(Pcd, self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT)
2491            CApp = CApp + DscBuildData.GenerateFdfValueStatement(Pcd)
2492            CApp = CApp + DscBuildData.GenerateCommandLineValueStatement(Pcd)
2493            #
2494            # Set new PCD value and size
2495            #
2496            CApp = CApp + '  PcdSetPtr (%s, %s, %s, %s, Size, (void *)Pcd);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2497
2498            #
2499            # Free PCD
2500            #
2501            CApp = CApp + '  free (Pcd);\n'
2502            CApp = CApp + '}\n'
2503            CApp = CApp + '\n'
2504        return InitByteValue, CApp
2505
2506    def GenerateArrayAssignment(self, Pcd):
2507        CApp = ""
2508        if not Pcd:
2509            return CApp
2510        Demesion = ""
2511        for d in Pcd.Capacity:
2512            Demesion += "[]"
2513
2514        Value = Pcd.DefaultValueFromDec
2515        if "{CODE(" in Pcd.DefaultValueFromDec:
2516            realvalue = Pcd.DefaultValueFromDec.strip()[6:-2] # "{CODE(").rstrip(")}"
2517            CApp += "static %s %s_%s_INIT_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,Demesion,realvalue)
2518
2519        if Pcd.Type in PCD_DYNAMIC_TYPE_SET | PCD_DYNAMIC_EX_TYPE_SET:
2520            for skuname in Pcd.SkuInfoList:
2521                skuinfo = Pcd.SkuInfoList[skuname]
2522                if skuinfo.VariableName:
2523                    for defaultstore in skuinfo.DefaultStoreDict:
2524                        pcddscrawdefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, skuname, defaultstore)
2525                        if pcddscrawdefaultvalue:
2526                            Value = skuinfo.DefaultStoreDict[defaultstore]
2527                            if "{CODE(" in Value:
2528                                realvalue = Value.strip()[6:-2] # "{CODE(").rstrip(")}"
2529                                CApp += "static %s %s_%s_%s_%s_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,defaultstore,Demesion,realvalue)
2530                else:
2531                    pcddscrawdefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, skuname, TAB_DEFAULT_STORES_DEFAULT)
2532                    if pcddscrawdefaultvalue:
2533                        Value = skuinfo.DefaultValue
2534                        if "{CODE(" in Value:
2535                            realvalue = Value.strip()[6:-2] # "{CODE(").rstrip(")}"
2536                            CApp += "static %s %s_%s_%s_%s_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,TAB_DEFAULT_STORES_DEFAULT,Demesion,realvalue)
2537        else:
2538            pcddscrawdefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT)
2539            if pcddscrawdefaultvalue:
2540                if "{CODE(" in Pcd.DefaultValue:
2541                    realvalue = Pcd.DefaultValue.strip()[6:-2] # "{CODE(").rstrip(")}"
2542                    CApp += "static %s %s_%s_DEFAULT_STANDARD_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,Demesion,realvalue)
2543
2544        return CApp
2545
2546    def SkuOverrideValuesEmpty(self,OverrideValues):
2547        if not OverrideValues:
2548            return True
2549        for key in OverrideValues:
2550            if OverrideValues[key]:
2551                return False
2552        return True
2553
2554    def ParseCCFlags(self, ccflag):
2555        ccflags = set()
2556        ccflaglist = ccflag.split(" ")
2557        i = 0
2558        while i < len(ccflaglist):
2559            item = ccflaglist[i].strip()
2560            if item in (r"/D", r"/U","-D","-U"):
2561                ccflags.add(" ".join((ccflaglist[i],ccflaglist[i+1])))
2562                i = i+1
2563            elif item.startswith((r"/D", r"/U","-D","-U")):
2564                ccflags.add(item)
2565            i +=1
2566        return ccflags
2567    def GenerateByteArrayValue (self, StructuredPcds):
2568        #
2569        # Generate/Compile/Run C application to determine if there are any flexible array members
2570        #
2571        if not StructuredPcds:
2572            return
2573
2574        InitByteValue = ""
2575        CApp = PcdMainCHeader
2576
2577        IncludeFiles = set()
2578        for PcdName in StructuredPcds:
2579            Pcd = StructuredPcds[PcdName]
2580            for IncludeFile in Pcd.StructuredPcdIncludeFile:
2581                if IncludeFile not in IncludeFiles:
2582                    IncludeFiles.add(IncludeFile)
2583                    CApp = CApp + '#include <%s>\n' % (IncludeFile)
2584        CApp = CApp + '\n'
2585        for Pcd in StructuredPcds.values():
2586            CApp = CApp + self.GenerateArrayAssignment(Pcd)
2587        for PcdName in StructuredPcds:
2588            Pcd = StructuredPcds[PcdName]
2589            CApp = CApp + self.GenerateSizeFunction(Pcd)
2590            CApp = CApp + self.GenerateDefaultValueAssignFunction(Pcd)
2591            CApp = CApp + self.GenerateFdfValue(Pcd)
2592            CApp = CApp + self.GenerateCommandLineValue(Pcd)
2593            if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
2594                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
2595                CApp = CApp + self.GenerateInitValueFunction(Pcd, self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT)
2596            else:
2597                for SkuName in self.SkuIdMgr.SkuOverrideOrder():
2598                    if SkuName not in Pcd.SkuOverrideValues:
2599                        continue
2600                    for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
2601                        CApp = CApp + self.GenerateInitValueFunction(Pcd, SkuName, DefaultStoreName)
2602            if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
2603                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
2604                InitByteValue, CApp = self.GenerateInitializeFunc(self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT, Pcd, InitByteValue, CApp)
2605            else:
2606                for SkuName in self.SkuIdMgr.SkuOverrideOrder():
2607                    if SkuName not in Pcd.SkuOverrideValues:
2608                        continue
2609                    for DefaultStoreName in Pcd.DefaultStoreName:
2610                        Pcd = StructuredPcds[PcdName]
2611                        InitByteValue, CApp = self.GenerateInitializeFunc(SkuName, DefaultStoreName, Pcd, InitByteValue, CApp)
2612
2613        CApp = CApp + 'VOID\n'
2614        CApp = CApp + 'PcdEntryPoint(\n'
2615        CApp = CApp + '  VOID\n'
2616        CApp = CApp + '  )\n'
2617        CApp = CApp + '{\n'
2618        for Pcd in StructuredPcds.values():
2619            if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD], self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
2620                CApp = CApp + '  Initialize_%s_%s_%s_%s();\n' % (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2621            else:
2622                for SkuName in self.SkuIdMgr.SkuOverrideOrder():
2623                    if SkuName not in self.SkuIdMgr.AvailableSkuIdSet:
2624                        continue
2625                    for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
2626                        CApp = CApp + '  Initialize_%s_%s_%s_%s();\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
2627        CApp = CApp + '}\n'
2628
2629        CApp = CApp + PcdMainCEntry + '\n'
2630
2631        if not os.path.exists(self.OutputPath):
2632            os.makedirs(self.OutputPath)
2633        CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
2634        SaveFileOnChange(CAppBaseFileName + '.c', CApp, False)
2635
2636        MakeApp = PcdMakefileHeader
2637        if sys.platform == "win32":
2638            MakeApp = MakeApp + 'APPFILE = %s\%s.exe\n' % (self.OutputPath, PcdValueInitName) + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s\%s.obj %s.obj\n' % (self.OutputPath, PcdValueInitName, os.path.join(self.OutputPath, PcdValueCommonName)) + 'INC = '
2639        else:
2640            MakeApp = MakeApp + PcdGccMakefile
2641            MakeApp = MakeApp + 'APPFILE = %s/%s\n' % (self.OutputPath, PcdValueInitName) + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s/%s.o %s.o\n' % (self.OutputPath, PcdValueInitName, os.path.join(self.OutputPath, PcdValueCommonName)) + \
2642                      'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'INCLUDE +='
2643
2644        IncSearchList = []
2645        PlatformInc = OrderedDict()
2646        for Cache in self._Bdb._CACHE_.values():
2647            if Cache.MetaFile.Ext.lower() != '.dec':
2648                continue
2649            if Cache.Includes:
2650                if str(Cache.MetaFile.Path) not in PlatformInc:
2651                    PlatformInc[str(Cache.MetaFile.Path)] = []
2652                    PlatformInc[str(Cache.MetaFile.Path)].append (os.path.dirname(Cache.MetaFile.Path))
2653                    PlatformInc[str(Cache.MetaFile.Path)].extend (Cache.CommonIncludes)
2654
2655        PcdDependDEC = []
2656        for Pcd in StructuredPcds.values():
2657            for PackageDec in Pcd.PackageDecs:
2658                Package = os.path.normpath(mws.join(GlobalData.gWorkspace, PackageDec))
2659                if not os.path.exists(Package):
2660                    EdkLogger.error('Build', RESOURCE_NOT_AVAILABLE, "The dependent Package %s of PCD %s.%s is not exist." % (PackageDec, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
2661                if Package not in PcdDependDEC:
2662                    PcdDependDEC.append(Package)
2663
2664        if PlatformInc and PcdDependDEC:
2665            for pkg in PcdDependDEC:
2666                if pkg in PlatformInc:
2667                    for inc in PlatformInc[pkg]:
2668                        #
2669                        # Get list of files in potential -I include path
2670                        #
2671                        FileList = os.listdir (str(inc))
2672                        #
2673                        # Skip -I include path if one of the include files required
2674                        # by PcdValueInit.c are present in the include paths from
2675                        # the DEC file.  PcdValueInit.c must use the standard include
2676                        # files from the host compiler.
2677                        #
2678                        if 'stdio.h' in FileList:
2679                          continue
2680                        if 'stdlib.h' in FileList:
2681                          continue
2682                        if 'string.h' in FileList:
2683                          continue
2684                        MakeApp += '-I'  + str(inc) + ' '
2685                        IncSearchList.append(inc)
2686        MakeApp = MakeApp + '\n'
2687
2688        CC_FLAGS = LinuxCFLAGS
2689        if sys.platform == "win32":
2690            CC_FLAGS = WindowsCFLAGS
2691        BuildOptions = OrderedDict()
2692        for Options in self.BuildOptions:
2693            if Options[2] != EDKII_NAME:
2694                continue
2695            Family = Options[0]
2696            if Family and Family != self.ToolChainFamily:
2697                continue
2698            Target, Tag, Arch, Tool, Attr = Options[1].split("_")
2699            if Tool != 'CC':
2700                continue
2701            if Attr != "FLAGS":
2702                continue
2703            if Target == TAB_STAR or Target == self._Target:
2704                if Tag == TAB_STAR or Tag == self._Toolchain:
2705                    if 'COMMON' not in BuildOptions:
2706                        BuildOptions['COMMON'] = set()
2707                    if Arch == TAB_STAR:
2708                        BuildOptions['COMMON']|= self.ParseCCFlags(self.BuildOptions[Options])
2709                    if Arch in self.SupArchList:
2710                        if Arch not in BuildOptions:
2711                            BuildOptions[Arch] = set()
2712                        BuildOptions[Arch] |= self.ParseCCFlags(self.BuildOptions[Options])
2713
2714        if BuildOptions:
2715            ArchBuildOptions = {arch:flags for arch,flags in BuildOptions.items() if arch != 'COMMON'}
2716            if len(ArchBuildOptions.keys()) == 1:
2717                BuildOptions['COMMON'] |= (list(ArchBuildOptions.values())[0])
2718            elif len(ArchBuildOptions.keys()) > 1:
2719                CommonBuildOptions = reduce(lambda x,y: x&y, ArchBuildOptions.values())
2720                BuildOptions['COMMON'] |= CommonBuildOptions
2721            ValueList = [item for item in BuildOptions['COMMON'] if item.startswith((r"/U","-U"))]
2722            ValueList.extend([item for item in BuildOptions['COMMON'] if item.startswith((r"/D", "-D"))])
2723            CC_FLAGS += " ".join(ValueList)
2724        MakeApp += CC_FLAGS
2725
2726        if sys.platform == "win32":
2727            MakeApp = MakeApp + PcdMakefileEnd
2728            MakeApp = MakeApp + AppTarget % ("""\tcopy $(APPLICATION) $(APPFILE) /y """)
2729        else:
2730            MakeApp = MakeApp + AppTarget % ("""\tcp $(APPLICATION) $(APPFILE) """)
2731        MakeApp = MakeApp + '\n'
2732        IncludeFileFullPaths = []
2733        for includefile in IncludeFiles:
2734            for includepath in IncSearchList:
2735                includefullpath = os.path.join(str(includepath), includefile)
2736                if os.path.exists(includefullpath):
2737                    IncludeFileFullPaths.append(os.path.normpath(includefullpath))
2738                    break
2739        SearchPathList = []
2740        SearchPathList.append(os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "BaseTools/Source/C/Include")))
2741        SearchPathList.append(os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "BaseTools/Source/C/Common")))
2742        SearchPathList.extend(str(item) for item in IncSearchList)
2743        IncFileList = GetDependencyList(IncludeFileFullPaths, SearchPathList)
2744        for include_file in IncFileList:
2745            MakeApp += "$(OBJECTS) : %s\n" % include_file
2746        if sys.platform == "win32":
2747            PcdValueCommonPath = os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "Source\C\Common\PcdValueCommon.c"))
2748            MakeApp = MakeApp + '%s\PcdValueCommon.c : %s\n' % (self.OutputPath, PcdValueCommonPath)
2749            MakeApp = MakeApp + '\tcopy /y %s $@\n' % (PcdValueCommonPath)
2750        else:
2751            PcdValueCommonPath = os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "Source/C/Common/PcdValueCommon.c"))
2752            MakeApp = MakeApp + '%s/PcdValueCommon.c : %s\n' % (self.OutputPath, PcdValueCommonPath)
2753            MakeApp = MakeApp + '\tcp -f %s %s/PcdValueCommon.c\n' % (PcdValueCommonPath, self.OutputPath)
2754        MakeFileName = os.path.join(self.OutputPath, 'Makefile')
2755        MakeApp += "$(OBJECTS) : %s\n" % MakeFileName
2756        SaveFileOnChange(MakeFileName, MakeApp, False)
2757
2758        InputValueFile = os.path.join(self.OutputPath, 'Input.txt')
2759        OutputValueFile = os.path.join(self.OutputPath, 'Output.txt')
2760        SaveFileOnChange(InputValueFile, InitByteValue, False)
2761
2762        Dest_PcdValueInitExe = PcdValueInitName
2763        if not sys.platform == "win32":
2764            Dest_PcdValueInitExe = os.path.join(self.OutputPath, PcdValueInitName)
2765        else:
2766            Dest_PcdValueInitExe = os.path.join(self.OutputPath, PcdValueInitName) +".exe"
2767        Messages = ''
2768        if sys.platform == "win32":
2769            MakeCommand = 'nmake -f %s' % (MakeFileName)
2770            returncode, StdOut, StdErr = DscBuildData.ExecuteCommand (MakeCommand)
2771            Messages = StdOut
2772        else:
2773            MakeCommand = 'make -f %s' % (MakeFileName)
2774            returncode, StdOut, StdErr = DscBuildData.ExecuteCommand (MakeCommand)
2775            Messages = StdErr
2776
2777        EdkLogger.verbose ('%s\n%s\n%s' % (MakeCommand, StdOut, StdErr))
2778        Messages = Messages.split('\n')
2779        MessageGroup = []
2780        if returncode != 0:
2781            CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
2782            File = open (CAppBaseFileName + '.c', 'r')
2783            FileData = File.readlines()
2784            File.close()
2785            for Message in Messages:
2786                if " error" in Message or "warning" in Message:
2787                    try:
2788                        FileInfo = Message.strip().split('(')
2789                        if len (FileInfo) > 1:
2790                            FileName = FileInfo [0]
2791                            FileLine = FileInfo [1].split (')')[0]
2792                        else:
2793                            FileInfo = Message.strip().split(':')
2794                            if len(FileInfo) < 2:
2795                                continue
2796                            FileName = FileInfo [0]
2797                            FileLine = FileInfo [1]
2798                    except:
2799                        continue
2800                    if "PcdValueInit.c" not in FileName:
2801                        continue
2802                    if FileLine.isdigit():
2803                        error_line = FileData[int (FileLine) - 1]
2804                        if r"//" in error_line:
2805                            c_line, dsc_line = error_line.split(r"//")
2806                        else:
2807                            dsc_line = error_line
2808                        message_itmes = Message.split(":")
2809                        Index = 0
2810                        if "PcdValueInit.c" not in Message:
2811                            if not MessageGroup:
2812                                MessageGroup.append(Message)
2813                            break
2814                        else:
2815                            for item in message_itmes:
2816                                if "PcdValueInit.c" in item:
2817                                    Index = message_itmes.index(item)
2818                                    message_itmes[Index] = dsc_line.strip()
2819                                    break
2820                            MessageGroup.append(":".join(message_itmes[Index:]).strip())
2821                            continue
2822                    else:
2823                        MessageGroup.append(Message)
2824            if MessageGroup:
2825                EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "\n".join(MessageGroup) )
2826            else:
2827                EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s\n%s\n%s' % (MakeCommand, StdOut, StdErr))
2828
2829        if DscBuildData.NeedUpdateOutput(OutputValueFile, Dest_PcdValueInitExe, InputValueFile):
2830            Command = Dest_PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile)
2831            returncode, StdOut, StdErr = DscBuildData.ExecuteCommand (Command)
2832            EdkLogger.verbose ('%s\n%s\n%s' % (Command, StdOut, StdErr))
2833            if returncode != 0:
2834                EdkLogger.warn('Build', COMMAND_FAILURE, 'Can not collect output from command: %s\n%s\n' % (Command, StdOut, StdErr))
2835
2836        File = open (OutputValueFile, 'r')
2837        FileBuffer = File.readlines()
2838        File.close()
2839
2840        StructurePcdSet = []
2841        for Pcd in FileBuffer:
2842            PcdValue = Pcd.split ('|')
2843            PcdInfo = PcdValue[0].split ('.')
2844            StructurePcdSet.append((PcdInfo[0], PcdInfo[1], PcdInfo[2], PcdInfo[3], PcdValue[2].strip()))
2845        return StructurePcdSet
2846
2847    @staticmethod
2848    def NeedUpdateOutput(OutputFile, ValueCFile, StructureInput):
2849        if not os.path.exists(OutputFile):
2850            return True
2851        if os.stat(OutputFile).st_mtime <= os.stat(ValueCFile).st_mtime:
2852            return True
2853        if os.stat(OutputFile).st_mtime <= os.stat(StructureInput).st_mtime:
2854            return True
2855        return False
2856
2857    ## Retrieve dynamic PCD settings
2858    #
2859    #   @param  Type    PCD type
2860    #
2861    #   @retval a dict object contains settings of given PCD type
2862    #
2863    def _GetDynamicPcd(self, Type):
2864
2865
2866        Pcds = OrderedDict()
2867        #
2868        # tdict is a special dict kind of type, used for selecting correct
2869        # PCD settings for certain ARCH and SKU
2870        #
2871        PcdDict = tdict(True, 4)
2872        PcdList = []
2873        # Find out all possible PCD candidates for self._Arch
2874        RecordList = self._RawData[Type, self._Arch]
2875        AvailableSkuIdSet = copy.copy(self.SkuIds)
2876
2877
2878        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4, Dummy5 in RecordList:
2879            SkuName = SkuName.upper()
2880            SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
2881            if SkuName not in AvailableSkuIdSet:
2882                EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
2883                                            File=self.MetaFile, Line=Dummy5)
2884            if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, Dummy5) not in PcdList:
2885                PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
2886            PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
2887
2888        # Remove redundant PCD candidates, per the ARCH and SKU
2889        for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
2890
2891            Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
2892            if Setting is None:
2893                continue
2894
2895            PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
2896            if MaxDatumSize:
2897                if int(MaxDatumSize, 0) > 0xFFFF:
2898                    EdkLogger.error('build', FORMAT_INVALID, "The size value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)),
2899                                    File=self.MetaFile, Line=Dummy4)
2900                if int(MaxDatumSize, 0) < 0:
2901                    EdkLogger.error('build', FORMAT_INVALID, "The size value can't be set to negative value for %s." % ".".join((TokenSpaceGuid, PcdCName)),
2902                                    File=self.MetaFile, Line=Dummy4)
2903            SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', '', PcdValue)
2904            if (PcdCName, TokenSpaceGuid) in Pcds:
2905                pcdObject = Pcds[PcdCName, TokenSpaceGuid]
2906                pcdObject.SkuInfoList[SkuName] = SkuInfo
2907                if MaxDatumSize.strip():
2908                    CurrentMaxSize = int(MaxDatumSize.strip(), 0)
2909                else:
2910                    CurrentMaxSize = 0
2911                if pcdObject.MaxDatumSize:
2912                    PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
2913                else:
2914                    PcdMaxSize = 0
2915                if CurrentMaxSize > PcdMaxSize:
2916                    pcdObject.MaxDatumSize = str(CurrentMaxSize)
2917            else:
2918                Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
2919                                                    PcdCName,
2920                                                    TokenSpaceGuid,
2921                                                    self._PCD_TYPE_STRING_[Type],
2922                                                    DatumType,
2923                                                    PcdValue,
2924                                                    '',
2925                                                    MaxDatumSize,
2926                                                    OrderedDict({SkuName : SkuInfo}),
2927                                                    False,
2928                                                    None,
2929                                                    IsDsc=True)
2930
2931            if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
2932                Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
2933                Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
2934            Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][TAB_DEFAULT_STORES_DEFAULT] = PcdValue
2935            Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][TAB_DEFAULT_STORES_DEFAULT] = (self.MetaFile.File,Dummy4)
2936
2937        for pcd in Pcds.values():
2938            pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
2939            # Only fix the value while no value provided in DSC file.
2940            for sku in pcd.SkuInfoList.values():
2941                if not sku.DefaultValue:
2942                    sku.DefaultValue = pcdDecObject.DefaultValue
2943            if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON not in pcd.SkuInfoList:
2944                valuefromDec = pcdDecObject.DefaultValue
2945                SkuInfo = SkuInfoClass(TAB_DEFAULT, '0', '', '', '', '', '', valuefromDec)
2946                pcd.SkuInfoList[TAB_DEFAULT] = SkuInfo
2947            elif TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
2948                pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
2949                del pcd.SkuInfoList[TAB_COMMON]
2950            elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
2951                del pcd.SkuInfoList[TAB_COMMON]
2952
2953        list(map(self.FilterSkuSettings, Pcds.values()))
2954
2955        return Pcds
2956
2957    def FilterSkuSettings(self, PcdObj):
2958
2959        if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE:
2960            if TAB_DEFAULT in PcdObj.SkuInfoList and self.SkuIdMgr.SystemSkuId not in PcdObj.SkuInfoList:
2961                PcdObj.SkuInfoList[self.SkuIdMgr.SystemSkuId] = PcdObj.SkuInfoList[TAB_DEFAULT]
2962            PcdObj.SkuInfoList = {TAB_DEFAULT:PcdObj.SkuInfoList[self.SkuIdMgr.SystemSkuId]}
2963            PcdObj.SkuInfoList[TAB_DEFAULT].SkuIdName = TAB_DEFAULT
2964            PcdObj.SkuInfoList[TAB_DEFAULT].SkuId = '0'
2965
2966        elif self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.DEFAULT:
2967            PcdObj.SkuInfoList = {TAB_DEFAULT:PcdObj.SkuInfoList[TAB_DEFAULT]}
2968
2969        return PcdObj
2970
2971    @staticmethod
2972    def CompareVarAttr(Attr1, Attr2):
2973        if not Attr1 or not Attr2:  # for empty string
2974            return True
2975        Attr1s = [attr.strip() for attr in Attr1.split(",")]
2976        Attr1Set = set(Attr1s)
2977        Attr2s = [attr.strip() for attr in Attr2.split(",")]
2978        Attr2Set = set(Attr2s)
2979        if Attr2Set == Attr1Set:
2980            return True
2981        else:
2982            return False
2983
2984    def CompletePcdValues(self, PcdSet):
2985        Pcds = OrderedDict()
2986        DefaultStoreObj = DefaultStore(self._GetDefaultStores())
2987        SkuIds = {skuname:skuid for skuname, skuid in self.SkuIdMgr.AvailableSkuIdSet.items() if skuname != TAB_COMMON}
2988        DefaultStores = set(storename for pcdobj in PcdSet.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict)
2989        for PcdCName, TokenSpaceGuid in PcdSet:
2990            PcdObj = PcdSet[(PcdCName, TokenSpaceGuid)]
2991
2992            if PcdObj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
2993                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
2994                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
2995                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
2996                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
2997                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]:
2998                Pcds[PcdCName, TokenSpaceGuid]= PcdObj
2999                continue
3000            PcdType = PcdObj.Type
3001            if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
3002                for skuid in PcdObj.SkuInfoList:
3003                    skuobj = PcdObj.SkuInfoList[skuid]
3004                    mindefaultstorename = DefaultStoreObj.GetMin(set(defaultstorename for defaultstorename in skuobj.DefaultStoreDict))
3005                    for defaultstorename in DefaultStores:
3006                        if defaultstorename not in skuobj.DefaultStoreDict:
3007                            skuobj.DefaultStoreDict[defaultstorename] = skuobj.DefaultStoreDict[mindefaultstorename]
3008                    skuobj.HiiDefaultValue = skuobj.DefaultStoreDict[mindefaultstorename]
3009            for skuname, skuid in SkuIds.items():
3010                if skuname not in PcdObj.SkuInfoList:
3011                    nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
3012                    while nextskuid not in PcdObj.SkuInfoList:
3013                        nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
3014                    PcdObj.SkuInfoList[skuname] = copy.deepcopy(PcdObj.SkuInfoList[nextskuid])
3015                    PcdObj.SkuInfoList[skuname].SkuId = skuid
3016                    PcdObj.SkuInfoList[skuname].SkuIdName = skuname
3017            if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
3018                PcdObj.DefaultValue = list(PcdObj.SkuInfoList.values())[0].HiiDefaultValue if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE else PcdObj.SkuInfoList[TAB_DEFAULT].HiiDefaultValue
3019            Pcds[PcdCName, TokenSpaceGuid]= PcdObj
3020        return Pcds
3021    ## Retrieve dynamic HII PCD settings
3022    #
3023    #   @param  Type    PCD type
3024    #
3025    #   @retval a dict object contains settings of given PCD type
3026    #
3027    def _GetDynamicHiiPcd(self, Type):
3028
3029        VariableAttrs = {}
3030
3031        Pcds = OrderedDict()
3032        UserDefinedDefaultStores = []
3033        #
3034        # tdict is a special dict kind of type, used for selecting correct
3035        # PCD settings for certain ARCH and SKU
3036        #
3037        PcdDict = tdict(True, 5)
3038        PcdList = []
3039        RecordList = self._RawData[Type, self._Arch]
3040        # Find out all possible PCD candidates for self._Arch
3041        AvailableSkuIdSet = copy.copy(self.SkuIds)
3042        DefaultStoresDefine = self._GetDefaultStores()
3043
3044        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, DefaultStore, Dummy4, Dummy5 in RecordList:
3045            SkuName = SkuName.upper()
3046            SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
3047            DefaultStore = DefaultStore.upper()
3048            if DefaultStore == TAB_COMMON:
3049                DefaultStore = TAB_DEFAULT_STORES_DEFAULT
3050            else:
3051                #The end user define [DefaultStores] and [SKUID_IDENTIFIER.Menufacturing] in DSC
3052                UserDefinedDefaultStores.append((PcdCName, TokenSpaceGuid))
3053            if SkuName not in AvailableSkuIdSet:
3054                EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
3055                                            File=self.MetaFile, Line=Dummy5)
3056            if DefaultStore not in DefaultStoresDefine:
3057                EdkLogger.error('build', PARAMETER_INVALID, 'DefaultStores %s is not defined in [DefaultStores] section' % DefaultStore,
3058                                            File=self.MetaFile, Line=Dummy5)
3059            if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, DefaultStore, Dummy5) not in PcdList:
3060                PcdList.append((PcdCName, TokenSpaceGuid, SkuName, DefaultStore, Dummy5))
3061            PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid, DefaultStore] = Setting
3062
3063
3064        # Remove redundant PCD candidates, per the ARCH and SKU
3065        for index,(PcdCName, TokenSpaceGuid, SkuName, DefaultStore, Dummy4) in enumerate(PcdList):
3066
3067            Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid, DefaultStore]
3068            if Setting is None:
3069                continue
3070            VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
3071
3072            rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute)
3073            if not rt:
3074                EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg),
3075                        ExtraData="[%s]" % VarAttribute)
3076            ExceedMax = False
3077            FormatCorrect = True
3078            if VariableOffset.isdigit():
3079                if int(VariableOffset, 10) > 0xFFFF:
3080                    ExceedMax = True
3081            elif variablePattern.match(VariableOffset):
3082                if int(VariableOffset, 16) > 0xFFFF:
3083                    ExceedMax = True
3084            # For Offset written in "A.B"
3085            elif VariableOffset.find('.') > -1:
3086                VariableOffsetList = VariableOffset.split(".")
3087                if not (len(VariableOffsetList) == 2
3088                        and IsValidWord(VariableOffsetList[0])
3089                        and IsValidWord(VariableOffsetList[1])):
3090                    FormatCorrect = False
3091            else:
3092                FormatCorrect = False
3093            if not FormatCorrect:
3094                EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid, PcdCName)))
3095
3096            if ExceedMax:
3097                EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)))
3098            if (VariableName, VariableGuid) not in VariableAttrs:
3099                VariableAttrs[(VariableName, VariableGuid)] = VarAttribute
3100            else:
3101                if not DscBuildData.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute):
3102                    EdkLogger.error('Build', PCD_VARIABLE_ATTRIBUTES_CONFLICT_ERROR, "The variable %s.%s for DynamicHii PCDs has conflicting attributes [%s] and [%s] " % (VariableGuid, VariableName, VarAttribute, VariableAttrs[(VariableName, VariableGuid)]))
3103
3104            pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid]
3105            if (PcdCName, TokenSpaceGuid) in Pcds:
3106                pcdObject = Pcds[PcdCName, TokenSpaceGuid]
3107                if SkuName in pcdObject.SkuInfoList:
3108                    Skuitem = pcdObject.SkuInfoList[SkuName]
3109                    Skuitem.DefaultStoreDict.update({DefaultStore:DefaultValue})
3110                else:
3111                    SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute, DefaultStore={DefaultStore:DefaultValue})
3112                    pcdObject.SkuInfoList[SkuName] = SkuInfo
3113            else:
3114                SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute, DefaultStore={DefaultStore:DefaultValue})
3115                PcdClassObj = PcdClassObject(
3116                                                PcdCName,
3117                                                TokenSpaceGuid,
3118                                                self._PCD_TYPE_STRING_[Type],
3119                                                '',
3120                                                DefaultValue,
3121                                                '',
3122                                                '',
3123                                                OrderedDict({SkuName : SkuInfo}),
3124                                                False,
3125                                                None,
3126                                                pcdDecObject.validateranges,
3127                                                pcdDecObject.validlists,
3128                                                pcdDecObject.expressions,
3129                                                IsDsc=True)
3130                if (PcdCName, TokenSpaceGuid) in UserDefinedDefaultStores:
3131                    PcdClassObj.UserDefinedDefaultStoresFlag = True
3132                Pcds[PcdCName, TokenSpaceGuid] = PcdClassObj
3133
3134                Pcds[PcdCName, TokenSpaceGuid].CustomAttribute['DscPosition'] = index
3135            if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
3136                Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
3137                Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
3138            Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][DefaultStore] = DefaultValue
3139            Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][DefaultStore] = (self.MetaFile.File,Dummy4)
3140        for pcd in Pcds.values():
3141            pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
3142            pcd.DatumType = pcdDecObject.DatumType
3143            # Only fix the value while no value provided in DSC file.
3144            for sku in pcd.SkuInfoList.values():
3145                if (sku.HiiDefaultValue == "" or sku.HiiDefaultValue is None):
3146                    sku.HiiDefaultValue = pcdDecObject.DefaultValue
3147                    for default_store in sku.DefaultStoreDict:
3148                        sku.DefaultStoreDict[default_store]=pcdDecObject.DefaultValue
3149                    pcd.DefaultValue = pcdDecObject.DefaultValue
3150            if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON not in pcd.SkuInfoList:
3151                SkuInfoObj = list(pcd.SkuInfoList.values())[0]
3152                valuefromDec = pcdDecObject.DefaultValue
3153                SkuInfo = SkuInfoClass(TAB_DEFAULT, '0', SkuInfoObj.VariableName, SkuInfoObj.VariableGuid, SkuInfoObj.VariableOffset, valuefromDec, VariableAttribute=SkuInfoObj.VariableAttribute, DefaultStore={DefaultStore:valuefromDec})
3154                pcd.SkuInfoList[TAB_DEFAULT] = SkuInfo
3155            elif TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
3156                pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
3157                del pcd.SkuInfoList[TAB_COMMON]
3158            elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
3159                del pcd.SkuInfoList[TAB_COMMON]
3160
3161            if pcd.MaxDatumSize.strip():
3162                MaxSize = int(pcd.MaxDatumSize, 0)
3163            else:
3164                MaxSize = 0
3165            if pcd.DatumType not in TAB_PCD_NUMERIC_TYPES:
3166                for (_, skuobj) in pcd.SkuInfoList.items():
3167                    datalen = 0
3168                    skuobj.HiiDefaultValue = StringToArray(skuobj.HiiDefaultValue)
3169                    datalen = len(skuobj.HiiDefaultValue.split(","))
3170                    if datalen > MaxSize:
3171                        MaxSize = datalen
3172                    for defaultst in skuobj.DefaultStoreDict:
3173                        skuobj.DefaultStoreDict[defaultst] = StringToArray(skuobj.DefaultStoreDict[defaultst])
3174                pcd.DefaultValue = StringToArray(pcd.DefaultValue)
3175                pcd.MaxDatumSize = str(MaxSize)
3176        rt, invalidhii = DscBuildData.CheckVariableNameAssignment(Pcds)
3177        if not rt:
3178            invalidpcd = ",".join(invalidhii)
3179            EdkLogger.error('build', PCD_VARIABLE_INFO_ERROR, Message='The same HII PCD must map to the same EFI variable for all SKUs', File=self.MetaFile, ExtraData=invalidpcd)
3180
3181        list(map(self.FilterSkuSettings, Pcds.values()))
3182
3183        return Pcds
3184
3185    @staticmethod
3186    def CheckVariableNameAssignment(Pcds):
3187        invalidhii = []
3188        for pcdname in Pcds:
3189            pcd = Pcds[pcdname]
3190            varnameset = set(sku.VariableName for (skuid, sku) in pcd.SkuInfoList.items())
3191            if len(varnameset) > 1:
3192                invalidhii.append(".".join((pcdname[1], pcdname[0])))
3193        if len(invalidhii):
3194            return False, invalidhii
3195        else:
3196            return True, []
3197    ## Retrieve dynamic VPD PCD settings
3198    #
3199    #   @param  Type    PCD type
3200    #
3201    #   @retval a dict object contains settings of given PCD type
3202    #
3203    def _GetDynamicVpdPcd(self, Type):
3204
3205
3206        Pcds = OrderedDict()
3207        #
3208        # tdict is a special dict kind of type, used for selecting correct
3209        # PCD settings for certain ARCH and SKU
3210        #
3211        PcdDict = tdict(True, 4)
3212        PcdList = []
3213
3214        # Find out all possible PCD candidates for self._Arch
3215        RecordList = self._RawData[Type, self._Arch]
3216        AvailableSkuIdSet = copy.copy(self.SkuIds)
3217
3218        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4, Dummy5 in RecordList:
3219            SkuName = SkuName.upper()
3220            SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
3221            if SkuName not in AvailableSkuIdSet:
3222                EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
3223                                            File=self.MetaFile, Line=Dummy5)
3224            if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, Dummy5) not in PcdList:
3225                PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
3226            PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
3227
3228        # Remove redundant PCD candidates, per the ARCH and SKU
3229        for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
3230            Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
3231            if Setting is None:
3232                continue
3233            #
3234            # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue
3235            # For the Integer & Boolean type, the optional data can only be InitialValue.
3236            # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype
3237            # until the DEC parser has been called.
3238            #
3239            VpdOffset, MaxDatumSize, InitialValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
3240            if MaxDatumSize:
3241                if int(MaxDatumSize, 0) > 0xFFFF:
3242                    EdkLogger.error('build', FORMAT_INVALID, "The size value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)),
3243                                    File=self.MetaFile, Line=Dummy4)
3244                if int(MaxDatumSize, 0) < 0:
3245                    EdkLogger.error('build', FORMAT_INVALID, "The size value can't be set to negative value for %s." % ".".join((TokenSpaceGuid, PcdCName)),
3246                                    File=self.MetaFile, Line=Dummy4)
3247            SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', VpdOffset, InitialValue)
3248            if (PcdCName, TokenSpaceGuid) in Pcds:
3249                pcdObject = Pcds[PcdCName, TokenSpaceGuid]
3250                pcdObject.SkuInfoList[SkuName] = SkuInfo
3251                if MaxDatumSize.strip():
3252                    CurrentMaxSize = int(MaxDatumSize.strip(), 0)
3253                else:
3254                    CurrentMaxSize = 0
3255                if pcdObject.MaxDatumSize:
3256                    PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
3257                else:
3258                    PcdMaxSize = 0
3259                if CurrentMaxSize > PcdMaxSize:
3260                    pcdObject.MaxDatumSize = str(CurrentMaxSize)
3261            else:
3262                Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
3263                                                PcdCName,
3264                                                TokenSpaceGuid,
3265                                                self._PCD_TYPE_STRING_[Type],
3266                                                '',
3267                                                InitialValue,
3268                                                '',
3269                                                MaxDatumSize,
3270                                                OrderedDict({SkuName : SkuInfo}),
3271                                                False,
3272                                                None,
3273                                                IsDsc=True)
3274
3275            if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
3276                Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
3277                Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
3278            Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][TAB_DEFAULT_STORES_DEFAULT] = InitialValue
3279            Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][TAB_DEFAULT_STORES_DEFAULT] = (self.MetaFile.File,Dummy4)
3280        for pcd in Pcds.values():
3281            pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
3282            pcd.DatumType = pcdDecObject.DatumType
3283            # Only fix the value while no value provided in DSC file.
3284            for sku in pcd.SkuInfoList.values():
3285                if not sku.DefaultValue:
3286                    sku.DefaultValue = pcdDecObject.DefaultValue
3287            if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON not in pcd.SkuInfoList:
3288                SkuInfoObj = list(pcd.SkuInfoList.values())[0]
3289                valuefromDec = pcdDecObject.DefaultValue
3290                SkuInfo = SkuInfoClass(TAB_DEFAULT, '0', '', '', '', '', SkuInfoObj.VpdOffset, valuefromDec)
3291                pcd.SkuInfoList[TAB_DEFAULT] = SkuInfo
3292            elif TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
3293                pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
3294                del pcd.SkuInfoList[TAB_COMMON]
3295            elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
3296                del pcd.SkuInfoList[TAB_COMMON]
3297
3298        #For the same one VOID* pcd, if the default value type of one SKU is "Unicode string",
3299        #the other SKUs are "OtherVOID*"(ASCII string or byte array),Then convert "Unicode string" to "byte array".
3300        for pcd in Pcds.values():
3301            PcdValueTypeSet = set()
3302            for sku in pcd.SkuInfoList.values():
3303                PcdValueTypeSet.add("UnicodeString" if sku.DefaultValue.startswith(('L"',"L'")) else "OtherVOID*")
3304            if len(PcdValueTypeSet) > 1:
3305                for sku in pcd.SkuInfoList.values():
3306                    sku.DefaultValue = StringToArray(sku.DefaultValue) if sku.DefaultValue.startswith(('L"',"L'")) else sku.DefaultValue
3307
3308        list(map(self.FilterSkuSettings, Pcds.values()))
3309        return Pcds
3310
3311    ## Add external modules
3312    #
3313    #   The external modules are mostly those listed in FDF file, which don't
3314    # need "build".
3315    #
3316    #   @param  FilePath    The path of module description file
3317    #
3318    def AddModule(self, FilePath):
3319        FilePath = NormPath(FilePath)
3320        if FilePath not in self.Modules:
3321            Module = ModuleBuildClassObject()
3322            Module.MetaFile = FilePath
3323            self.Modules.append(Module)
3324
3325    @property
3326    def ToolChainFamily(self):
3327        self._ToolChainFamily = TAB_COMPILER_MSFT
3328        TargetObj = TargetTxtDict()
3329        TargetTxt = TargetObj.Target
3330        BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, "target.txt"))
3331        if os.path.isfile(BuildConfigurationFile) == True:
3332            ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
3333            if ToolDefinitionFile == '':
3334                ToolDefinitionFile = "tools_def.txt"
3335                ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))
3336            if os.path.isfile(ToolDefinitionFile) == True:
3337                ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
3338                ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase
3339                if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
3340                   or self._Toolchain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
3341                   or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self._Toolchain]:
3342                    self._ToolChainFamily = TAB_COMPILER_MSFT
3343                else:
3344                    self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self._Toolchain]
3345        return self._ToolChainFamily
3346
3347    ## Add external PCDs
3348    #
3349    #   The external PCDs are mostly those listed in FDF file to specify address
3350    # or offset information.
3351    #
3352    #   @param  Name    Name of the PCD
3353    #   @param  Guid    Token space guid of the PCD
3354    #   @param  Value   Value of the PCD
3355    #
3356    def AddPcd(self, Name, Guid, Value):
3357        if (Name, Guid) not in self.Pcds:
3358            self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
3359        self.Pcds[Name, Guid].DefaultValue = Value
3360
3361    @property
3362    def DecPcds(self):
3363        if self._DecPcds is None:
3364            FdfInfList = []
3365            if GlobalData.gFdfParser:
3366                FdfInfList = GlobalData.gFdfParser.Profile.InfList
3367            PkgSet = set()
3368            for Inf in FdfInfList:
3369                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
3370                if ModuleFile in self._Modules:
3371                    continue
3372                ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
3373                PkgSet.update(ModuleData.Packages)
3374            if self.Packages:
3375                PkgSet.update(self.Packages)
3376            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain, PkgSet)
3377            self._GuidDict.update(GlobalData.gPlatformPcds)
3378        return self._DecPcds
3379