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