## @file
# This file is used to create a database used by build tool
#
# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution.  The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#

## Platform build information from DSC file
#
#  This class is used to retrieve information stored in database and convert them
# into PlatformBuildClassObject form for easier use for AutoGen.
#
from Common.String import *
from Common.DataType import *
from Common.Misc import *
from types import *

from CommonDataClass.CommonClass import SkuInfoClass
from Common.TargetTxtClassObject import *
from Common.ToolDefClassObject import *
from MetaDataTable import *
from MetaFileTable import *
from MetaFileParser import *

from WorkspaceCommon import GetDeclaredPcd
from Common.Misc import AnalyzeDscPcd
from Common.Misc import ProcessDuplicatedInf
import re
from Common.Parsing import IsValidWord
from Common.VariableAttributes import VariableAttributes
import Common.GlobalData as GlobalData
import subprocess
from Common.Misc import SaveFileOnChange
from Workspace.BuildClassObject import PlatformBuildClassObject, StructurePcd, PcdClassObject, ModuleBuildClassObject
from collections import OrderedDict

#
# Treat CHAR16 as a synonym for UINT16.  CHAR16 support is required for VFR C structs
#
PcdValueInitName = 'PcdValueInit'
PcdSupportedBaseTypes = ['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64', 'CHAR16']
PcdSupportedBaseTypeWidth = {'BOOLEAN':8, 'UINT8':8, 'UINT16':16, 'UINT32':32, 'UINT64':64}
PcdUnsupportedBaseTypes = ['INT8', 'INT16', 'INT32', 'INT64', 'CHAR8', 'UINTN', 'INTN', 'VOID']

PcdMainCHeader = '''
/**
  DO NOT EDIT
  FILE auto-generated
**/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <PcdValueCommon.h>
'''

PcdMainCEntry = '''
int
main (
  int   argc,
  char  *argv[]
  )
{
  return PcdValueMain (argc, argv);
}
'''

PcdMakefileHeader = '''
#
# DO NOT EDIT
# This file is auto-generated by build utility
#

'''

WindowsCFLAGS = 'CFLAGS = $(CFLAGS) /wd4200 /wd4034 /wd4101 '
LinuxCFLAGS = 'BUILD_CFLAGS += -Wno-pointer-to-int-cast -Wno-unused-variable '
PcdMakefileEnd = '''
!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common

LIBS = $(LIB_PATH)\Common.lib

!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app
'''

PcdGccMakefile = '''
MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C
LIBS = -lCommon
'''

class DscBuildData(PlatformBuildClassObject):
    # dict used to convert PCD type in database to string used by build tool
    _PCD_TYPE_STRING_ = {
        MODEL_PCD_FIXED_AT_BUILD        :   "FixedAtBuild",
        MODEL_PCD_PATCHABLE_IN_MODULE   :   "PatchableInModule",
        MODEL_PCD_FEATURE_FLAG          :   "FeatureFlag",
        MODEL_PCD_DYNAMIC               :   "Dynamic",
        MODEL_PCD_DYNAMIC_DEFAULT       :   "Dynamic",
        MODEL_PCD_DYNAMIC_HII           :   "DynamicHii",
        MODEL_PCD_DYNAMIC_VPD           :   "DynamicVpd",
        MODEL_PCD_DYNAMIC_EX            :   "DynamicEx",
        MODEL_PCD_DYNAMIC_EX_DEFAULT    :   "DynamicEx",
        MODEL_PCD_DYNAMIC_EX_HII        :   "DynamicExHii",
        MODEL_PCD_DYNAMIC_EX_VPD        :   "DynamicExVpd",
    }

    # dict used to convert part of [Defines] to members of DscBuildData directly
    _PROPERTY_ = {
        #
        # Required Fields
        #
        TAB_DSC_DEFINES_PLATFORM_NAME           :   "_PlatformName",
        TAB_DSC_DEFINES_PLATFORM_GUID           :   "_Guid",
        TAB_DSC_DEFINES_PLATFORM_VERSION        :   "_Version",
        TAB_DSC_DEFINES_DSC_SPECIFICATION       :   "_DscSpecification",
        # TAB_DSC_DEFINES_OUTPUT_DIRECTORY        :   "_OutputDirectory",
        # TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES :   "_SupArchList",
        # TAB_DSC_DEFINES_BUILD_TARGETS           :   "_BuildTargets",
        TAB_DSC_DEFINES_SKUID_IDENTIFIER        :   "_SkuName",
        # TAB_DSC_DEFINES_FLASH_DEFINITION        :   "_FlashDefinition",
        TAB_DSC_DEFINES_BUILD_NUMBER            :   "_BuildNumber",
        TAB_DSC_DEFINES_MAKEFILE_NAME           :   "_MakefileName",
        TAB_DSC_DEFINES_BS_BASE_ADDRESS         :   "_BsBaseAddress",
        TAB_DSC_DEFINES_RT_BASE_ADDRESS         :   "_RtBaseAddress",
        # TAB_DSC_DEFINES_RFC_LANGUAGES           :   "_RFCLanguages",
        # TAB_DSC_DEFINES_ISO_LANGUAGES           :   "_ISOLanguages",
    }

    # used to compose dummy library class name for those forced library instances
    _NullLibraryNumber = 0

    ## Constructor of DscBuildData
    #
    #  Initialize object of DscBuildData
    #
    #   @param      FilePath        The path of platform description file
    #   @param      RawData         The raw data of DSC file
    #   @param      BuildDataBase   Database used to retrieve module/package information
    #   @param      Arch            The target architecture
    #   @param      Platform        (not used for DscBuildData)
    #   @param      Macros          Macros used for replacement in DSC file
    #
    def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Target=None, Toolchain=None):
        self.MetaFile = FilePath
        self._RawData = RawData
        self._Bdb = BuildDataBase
        self._Arch = Arch
        self._Target = Target
        self._Toolchain = Toolchain
        self._ToolChainFamily = None
        self._Clear()
        self._HandleOverridePath()
        self.WorkspaceDir = os.getenv("WORKSPACE") if os.getenv("WORKSPACE") else ""
        self.DefaultStores = None
        self.SkuIdMgr = SkuClass(self.SkuName, self.SkuIds)
    @property
    def OutputPath(self):
        if os.getenv("WORKSPACE"):
            return os.path.join(os.getenv("WORKSPACE"), self.OutputDirectory, self._Target + "_" + self._Toolchain,PcdValueInitName)
        else:
            return os.path.dirname(self.DscFile)

    ## XXX[key] = value
    def __setitem__(self, key, value):
        self.__dict__[self._PROPERTY_[key]] = value

    ## value = XXX[key]
    def __getitem__(self, key):
        return self.__dict__[self._PROPERTY_[key]]

    ## "in" test support
    def __contains__(self, key):
        return key in self._PROPERTY_

    ## Set all internal used members of DscBuildData to None
    def _Clear(self):
        self._Header            = None
        self._PlatformName      = None
        self._Guid              = None
        self._Version           = None
        self._DscSpecification  = None
        self._OutputDirectory   = None
        self._SupArchList       = None
        self._BuildTargets      = None
        self._SkuName           = None
        self._PcdInfoFlag       = None
        self._VarCheckFlag      = None
        self._FlashDefinition   = None
        self._Prebuild          = None
        self._Postbuild         = None
        self._BuildNumber       = None
        self._MakefileName      = None
        self._BsBaseAddress     = None
        self._RtBaseAddress     = None
        self._SkuIds            = None
        self._Modules           = None
        self._LibraryInstances  = None
        self._LibraryClasses    = None
        self._Pcds              = None
        self._DecPcds           = None
        self._BuildOptions      = None
        self._ModuleTypeOptions = None
        self._LoadFixAddress    = None
        self._RFCLanguages      = None
        self._ISOLanguages      = None
        self._VpdToolGuid       = None
        self.__Macros           = None
        self.DefaultStores      = None


    ## handle Override Path of Module
    def _HandleOverridePath(self):
        RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
        Macros = self._Macros
        Macros["EDK_SOURCE"] = GlobalData.gEcpSource
        for Record in RecordList:
            ModuleId = Record[6]
            LineNo = Record[7]
            ModuleFile = PathClass(NormPath(Record[0]), GlobalData.gWorkspace, Arch=self._Arch)
            RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId]
            if RecordList != []:
                SourceOverridePath = mws.join(GlobalData.gWorkspace, NormPath(RecordList[0][0]))

                # Check if the source override path exists
                if not os.path.isdir(SourceOverridePath):
                    EdkLogger.error('build', FILE_NOT_FOUND, Message='Source override path does not exist:', File=self.MetaFile, ExtraData=SourceOverridePath, Line=LineNo)

                # Add to GlobalData Variables
                GlobalData.gOverrideDir[ModuleFile.Key] = SourceOverridePath

    ## Get current effective macros
    def _GetMacros(self):
        if self.__Macros == None:
            self.__Macros = {}
            self.__Macros.update(GlobalData.gPlatformDefines)
            self.__Macros.update(GlobalData.gGlobalDefines)
            self.__Macros.update(GlobalData.gCommandLineDefines)
        return self.__Macros

    ## Get architecture
    def _GetArch(self):
        return self._Arch

    ## Set architecture
    #
    #   Changing the default ARCH to another may affect all other information
    # because all information in a platform may be ARCH-related. That's
    # why we need to clear all internal used members, in order to cause all
    # information to be re-retrieved.
    #
    #   @param  Value   The value of ARCH
    #
    def _SetArch(self, Value):
        if self._Arch == Value:
            return
        self._Arch = Value
        self._Clear()

    ## Retrieve all information in [Defines] section
    #
    #   (Retriving all [Defines] information in one-shot is just to save time.)
    #
    def _GetHeaderInfo(self):
        RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
        for Record in RecordList:
            Name = Record[1]
            # items defined _PROPERTY_ don't need additional processing

            # some special items in [Defines] section need special treatment
            if Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:
                self._OutputDirectory = NormPath(Record[2], self._Macros)
                if ' ' in self._OutputDirectory:
                    EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY",
                                    File=self.MetaFile, Line=Record[-1],
                                    ExtraData=self._OutputDirectory)
            elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:
                self._FlashDefinition = PathClass(NormPath(Record[2], self._Macros), GlobalData.gWorkspace)
                ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf')
                if ErrorCode != 0:
                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1],
                                    ExtraData=ErrorInfo)
            elif Name == TAB_DSC_PREBUILD:
                PrebuildValue = Record[2]
                if Record[2][0] == '"':
                    if Record[2][-1] != '"':
                        EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_PREBUILD,
                                    File=self.MetaFile, Line=Record[-1])
                    PrebuildValue = Record[2][1:-1]
                self._Prebuild = PrebuildValue
            elif Name == TAB_DSC_POSTBUILD:
                PostbuildValue = Record[2]
                if Record[2][0] == '"':
                    if Record[2][-1] != '"':
                        EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_POSTBUILD,
                                    File=self.MetaFile, Line=Record[-1])
                    PostbuildValue = Record[2][1:-1]
                self._Postbuild = PostbuildValue
            elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:
                self._SupArchList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
            elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:
                self._BuildTargets = GetSplitValueList(Record[2])
            elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:
                if self._SkuName == None:
                    self._SkuName = Record[2]
                if GlobalData.gSKUID_CMD:
                    self._SkuName = GlobalData.gSKUID_CMD
            elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION:
                self._PcdInfoFlag = Record[2]
            elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION:
                self._VarCheckFlag = Record[2]
            elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:
                try:
                    self._LoadFixAddress = int (Record[2], 0)
                except:
                    EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (Record[2]))
            elif Name == TAB_DSC_DEFINES_RFC_LANGUAGES:
                if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
                    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"',
                                    File=self.MetaFile, Line=Record[-1])
                LanguageCodes = Record[2][1:-1]
                if not LanguageCodes:
                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more RFC4646 format language code must be provided for RFC_LANGUAGES statement',
                                    File=self.MetaFile, Line=Record[-1])
                LanguageList = GetSplitValueList(LanguageCodes, TAB_SEMI_COLON_SPLIT)
                # check whether there is empty entries in the list
                if None in LanguageList:
                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more empty language code is in RFC_LANGUAGES statement',
                                    File=self.MetaFile, Line=Record[-1])
                self._RFCLanguages = LanguageList
            elif Name == TAB_DSC_DEFINES_ISO_LANGUAGES:
                if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for ISO_LANGUAGES must have double quotes around it, for example: ISO_LANGUAGES = "engchn"',
                                    File=self.MetaFile, Line=Record[-1])
                LanguageCodes = Record[2][1:-1]
                if not LanguageCodes:
                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more ISO639-2 format language code must be provided for ISO_LANGUAGES statement',
                                    File=self.MetaFile, Line=Record[-1])
                if len(LanguageCodes) % 3:
                    EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'bad ISO639-2 format for ISO_LANGUAGES',
                                    File=self.MetaFile, Line=Record[-1])
                LanguageList = []
                for i in range(0, len(LanguageCodes), 3):
                    LanguageList.append(LanguageCodes[i:i + 3])
                self._ISOLanguages = LanguageList
            elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID:
                #
                # try to convert GUID to a real UUID value to see whether the GUID is format
                # for VPD_TOOL_GUID is correct.
                #
                try:
                    uuid.UUID(Record[2])
                except:
                    EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile)
                self._VpdToolGuid = Record[2]
            elif Name in self:
                self[Name] = Record[2]
        # set _Header to non-None in order to avoid database re-querying
        self._Header = 'DUMMY'

    ## Retrieve platform name
    def _GetPlatformName(self):
        if self._PlatformName == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._PlatformName == None:
                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)
        return self._PlatformName

    ## Retrieve file guid
    def _GetFileGuid(self):
        if self._Guid == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._Guid == None:
                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_GUID", File=self.MetaFile)
        return self._Guid

    ## Retrieve platform version
    def _GetVersion(self):
        if self._Version == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._Version == None:
                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_VERSION", File=self.MetaFile)
        return self._Version

    ## Retrieve platform description file version
    def _GetDscSpec(self):
        if self._DscSpecification == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._DscSpecification == None:
                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No DSC_SPECIFICATION", File=self.MetaFile)
        return self._DscSpecification

    ## Retrieve OUTPUT_DIRECTORY
    def _GetOutpuDir(self):
        if self._OutputDirectory == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._OutputDirectory == None:
                self._OutputDirectory = os.path.join("Build", self._PlatformName)
        return self._OutputDirectory

    ## Retrieve SUPPORTED_ARCHITECTURES
    def _GetSupArch(self):
        if self._SupArchList == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._SupArchList == None:
                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No SUPPORTED_ARCHITECTURES", File=self.MetaFile)
        return self._SupArchList

    ## Retrieve BUILD_TARGETS
    def _GetBuildTarget(self):
        if self._BuildTargets == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._BuildTargets == None:
                EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BUILD_TARGETS", File=self.MetaFile)
        return self._BuildTargets

    def _GetPcdInfoFlag(self):
        if self._PcdInfoFlag == None or self._PcdInfoFlag.upper() == 'FALSE':
            return False
        elif self._PcdInfoFlag.upper() == 'TRUE':
            return True
        else:
            return False
    def _GetVarCheckFlag(self):
        if self._VarCheckFlag == None or self._VarCheckFlag.upper() == 'FALSE':
            return False
        elif self._VarCheckFlag.upper() == 'TRUE':
            return True
        else:
            return False

    # # Retrieve SKUID_IDENTIFIER
    def _GetSkuName(self):
        if self._SkuName == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._SkuName == None:
                self._SkuName = 'DEFAULT'
        return self._SkuName

    ## Override SKUID_IDENTIFIER
    def _SetSkuName(self, Value):
        self._SkuName = Value

    def _GetFdfFile(self):
        if self._FlashDefinition == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._FlashDefinition == None:
                self._FlashDefinition = ''
        return self._FlashDefinition

    def _GetPrebuild(self):
        if self._Prebuild == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._Prebuild == None:
                self._Prebuild = ''
        return self._Prebuild

    def _GetPostbuild(self):
        if self._Postbuild == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._Postbuild == None:
                self._Postbuild = ''
        return self._Postbuild

    ## Retrieve FLASH_DEFINITION
    def _GetBuildNumber(self):
        if self._BuildNumber == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._BuildNumber == None:
                self._BuildNumber = ''
        return self._BuildNumber

    ## Retrieve MAKEFILE_NAME
    def _GetMakefileName(self):
        if self._MakefileName == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._MakefileName == None:
                self._MakefileName = ''
        return self._MakefileName

    ## Retrieve BsBaseAddress
    def _GetBsBaseAddress(self):
        if self._BsBaseAddress == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._BsBaseAddress == None:
                self._BsBaseAddress = ''
        return self._BsBaseAddress

    ## Retrieve RtBaseAddress
    def _GetRtBaseAddress(self):
        if self._RtBaseAddress == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._RtBaseAddress == None:
                self._RtBaseAddress = ''
        return self._RtBaseAddress

    ## Retrieve the top address for the load fix address
    def _GetLoadFixAddress(self):
        if self._LoadFixAddress == None:
            if self._Header == None:
                self._GetHeaderInfo()

            if self._LoadFixAddress == None:
                self._LoadFixAddress = self._Macros.get(TAB_FIX_LOAD_TOP_MEMORY_ADDRESS, '0')

            try:
                self._LoadFixAddress = int (self._LoadFixAddress, 0)
            except:
                EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (self._LoadFixAddress))

        #
        # If command line defined, should override the value in DSC file.
        #
        if 'FIX_LOAD_TOP_MEMORY_ADDRESS' in GlobalData.gCommandLineDefines.keys():
            try:
                self._LoadFixAddress = int(GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS'], 0)
            except:
                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']))

        if self._LoadFixAddress < 0:
            EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid negative value 0x%x" % (self._LoadFixAddress))
        if self._LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self._LoadFixAddress % 0x1000 != 0:
            EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid unaligned 4K value 0x%x" % (self._LoadFixAddress))

        return self._LoadFixAddress

    ## Retrieve RFCLanguage filter
    def _GetRFCLanguages(self):
        if self._RFCLanguages == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._RFCLanguages == None:
                self._RFCLanguages = []
        return self._RFCLanguages

    ## Retrieve ISOLanguage filter
    def _GetISOLanguages(self):
        if self._ISOLanguages == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._ISOLanguages == None:
                self._ISOLanguages = []
        return self._ISOLanguages
    ## Retrieve the GUID string for VPD tool
    def _GetVpdToolGuid(self):
        if self._VpdToolGuid == None:
            if self._Header == None:
                self._GetHeaderInfo()
            if self._VpdToolGuid == None:
                self._VpdToolGuid = ''
        return self._VpdToolGuid

    ## Retrieve [SkuIds] section information
    def _GetSkuIds(self):
        if self._SkuIds == None:
            self._SkuIds = sdict()
            RecordList = self._RawData[MODEL_EFI_SKU_ID, self._Arch]
            for Record in RecordList:
                if Record[0] in [None, '']:
                    EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',
                                    File=self.MetaFile, Line=Record[-1])
                if Record[1] in [None, '']:
                    EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',
                                    File=self.MetaFile, Line=Record[-1])
                Pattern = re.compile('^[1-9]\d*|0$')
                HexPattern = re.compile(r'0[xX][0-9a-fA-F]+$')
                if Pattern.match(Record[0]) == None and HexPattern.match(Record[0]) == None:
                    EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID number is invalid. It only support Integer and HexNumber",
                                    File=self.MetaFile, Line=Record[-1])
                if not IsValidWord(Record[1]):
                    EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID name is invalid. The correct format is '(a-zA-Z0-9_)(a-zA-Z0-9_-.)*'",
                                    File=self.MetaFile, Line=Record[-1])
                self._SkuIds[Record[1].upper()] = (str(self.ToInt(Record[0])), Record[1].upper(), Record[2].upper())
            if 'DEFAULT' not in self._SkuIds:
                self._SkuIds['DEFAULT'] = ("0","DEFAULT","DEFAULT")
            if 'COMMON' not in self._SkuIds:
                self._SkuIds['COMMON'] = ("0","DEFAULT","DEFAULT")
        return self._SkuIds
    def ToInt(self,intstr):
        return int(intstr,16) if intstr.upper().startswith("0X") else int(intstr)
    def _GetDefaultStores(self):
        if self.DefaultStores == None:
            self.DefaultStores = sdict()
            RecordList = self._RawData[MODEL_EFI_DEFAULT_STORES, self._Arch]
            for Record in RecordList:
                if Record[0] in [None, '']:
                    EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID number',
                                    File=self.MetaFile, Line=Record[-1])
                if Record[1] in [None, '']:
                    EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID name',
                                    File=self.MetaFile, Line=Record[-1])
                Pattern = re.compile('^[1-9]\d*|0$')
                HexPattern = re.compile(r'0[xX][0-9a-fA-F]+$')
                if Pattern.match(Record[0]) == None and HexPattern.match(Record[0]) == None:
                    EdkLogger.error('build', FORMAT_INVALID, "The format of the DefaultStores ID number is invalid. It only support Integer and HexNumber",
                                    File=self.MetaFile, Line=Record[-1])
                if not IsValidWord(Record[1]):
                    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_-.)*'",
                                    File=self.MetaFile, Line=Record[-1])
                self.DefaultStores[Record[1].upper()] = (self.ToInt(Record[0]),Record[1].upper())
            if TAB_DEFAULT_STORES_DEFAULT not in self.DefaultStores:
                self.DefaultStores[TAB_DEFAULT_STORES_DEFAULT] = (0,TAB_DEFAULT_STORES_DEFAULT)
            GlobalData.gDefaultStores = self.DefaultStores.keys()
            if GlobalData.gDefaultStores:
                GlobalData.gDefaultStores.sort()
        return self.DefaultStores

    ## Retrieve [Components] section information
    def _GetModules(self):
        if self._Modules != None:
            return self._Modules

        self._Modules = sdict()
        RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
        Macros = self._Macros
        Macros["EDK_SOURCE"] = GlobalData.gEcpSource
        for Record in RecordList:
            DuplicatedFile = False

            ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
            ModuleId = Record[6]
            LineNo = Record[7]

            # check the file validation
            ErrorCode, ErrorInfo = ModuleFile.Validate('.inf')
            if ErrorCode != 0:
                EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
                                ExtraData=ErrorInfo)
            # Check duplication
            # If arch is COMMON, no duplicate module is checked since all modules in all component sections are selected
            if self._Arch != 'COMMON' and ModuleFile in self._Modules:
                DuplicatedFile = True

            Module = ModuleBuildClassObject()
            Module.MetaFile = ModuleFile

            # get module private library instance
            RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]
            for Record in RecordList:
                LibraryClass = Record[0]
                LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch)
                LineNo = Record[-1]

                # check the file validation
                ErrorCode, ErrorInfo = LibraryPath.Validate('.inf')
                if ErrorCode != 0:
                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
                                    ExtraData=ErrorInfo)

                if LibraryClass == '' or LibraryClass == 'NULL':
                    self._NullLibraryNumber += 1
                    LibraryClass = 'NULL%d' % self._NullLibraryNumber
                    EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))
                Module.LibraryClasses[LibraryClass] = LibraryPath
                if LibraryPath not in self.LibraryInstances:
                    self.LibraryInstances.append(LibraryPath)

            # get module private PCD setting
            for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \
                         MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:
                RecordList = self._RawData[Type, self._Arch, None, ModuleId]
                for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4,Dummy5 in RecordList:
                    TokenList = GetSplitValueList(Setting)
                    DefaultValue = TokenList[0]
                    # the format is PcdName| Value | VOID* | MaxDatumSize
                    if len(TokenList) > 2:
                        MaxDatumSize = TokenList[2]
                    else:
                        MaxDatumSize = ''
                    TypeString = self._PCD_TYPE_STRING_[Type]
                    Pcd = PcdClassObject(
                            PcdCName,
                            TokenSpaceGuid,
                            TypeString,
                            '',
                            DefaultValue,
                            '',
                            MaxDatumSize,
                            {},
                            False,
                            None
                            )
                    Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd

            # get module private build options
            RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]
            for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4,Dummy5 in RecordList:
                if (ToolChainFamily, ToolChain) not in Module.BuildOptions:
                    Module.BuildOptions[ToolChainFamily, ToolChain] = Option
                else:
                    OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]
                    Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option

            RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]
            if DuplicatedFile and not RecordList:
                EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
            if RecordList:
                if len(RecordList) != 1:
                    EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in <Defines> section.',
                                    File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
                ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace)
                ModuleFile.Arch = self._Arch

            self._Modules[ModuleFile] = Module
        return self._Modules

    ## Retrieve all possible library instances used in this platform
    def _GetLibraryInstances(self):
        if self._LibraryInstances == None:
            self._GetLibraryClasses()
        return self._LibraryInstances

    ## Retrieve [LibraryClasses] information
    def _GetLibraryClasses(self):
        if self._LibraryClasses == None:
            self._LibraryInstances = []
            #
            # tdict is a special dict kind of type, used for selecting correct
            # library instance for given library class and module type
            #
            LibraryClassDict = tdict(True, 3)
            # track all library class names
            LibraryClassSet = set()
            RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, -1]
            Macros = self._Macros
            for Record in RecordList:
                LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy,Dummy, LineNo = Record
                if LibraryClass == '' or LibraryClass == 'NULL':
                    self._NullLibraryNumber += 1
                    LibraryClass = 'NULL%d' % self._NullLibraryNumber
                    EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass))
                LibraryClassSet.add(LibraryClass)
                LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch)
                # check the file validation
                ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf')
                if ErrorCode != 0:
                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
                                    ExtraData=ErrorInfo)

                if ModuleType != 'COMMON' and ModuleType not in SUP_MODULE_LIST:
                    EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType,
                                    File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo)
                LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance
                if LibraryInstance not in self._LibraryInstances:
                    self._LibraryInstances.append(LibraryInstance)

            # resolve the specific library instance for each class and each module type
            self._LibraryClasses = tdict(True)
            for LibraryClass in LibraryClassSet:
                # try all possible module types
                for ModuleType in SUP_MODULE_LIST:
                    LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]
                    if LibraryInstance == None:
                        continue
                    self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance

            # for Edk style library instances, which are listed in different section
            Macros["EDK_SOURCE"] = GlobalData.gEcpSource
            RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]
            for Record in RecordList:
                File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
                LineNo = Record[-1]
                # check the file validation
                ErrorCode, ErrorInfo = File.Validate('.inf')
                if ErrorCode != 0:
                    EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
                                    ExtraData=ErrorInfo)
                if File not in self._LibraryInstances:
                    self._LibraryInstances.append(File)
                #
                # we need the module name as the library class name, so we have
                # to parse it here. (self._Bdb[] will trigger a file parse if it
                # hasn't been parsed)
                #
                Library = self._Bdb[File, self._Arch, self._Target, self._Toolchain]
                self._LibraryClasses[Library.BaseName, ':dummy:'] = Library
        return self._LibraryClasses

    def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo):
        if self._DecPcds == None:

            FdfInfList = []
            if GlobalData.gFdfParser:
                FdfInfList = GlobalData.gFdfParser.Profile.InfList

            PkgSet = set()
            for Inf in FdfInfList:
                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
                if ModuleFile in self._Modules:
                    continue
                ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
                PkgSet.update(ModuleData.Packages)

            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
            self._GuidDict.update(GlobalData.gPlatformPcds)

        if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
            EdkLogger.error('build', PARSER_ERROR,
                            "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),
                            File=self.MetaFile, Line=LineNo)
        ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType)
        if not IsValid:
            if PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
                EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,
                                ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
            else:
                if ValueList[2] == '-1':
                    EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,
                                ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
        if ValueList[Index]:
            DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
            try:
                ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
            except BadExpression, Value:
                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
                                ExtraData="PCD [%s.%s] Value \"%s\" " % (
                                TokenSpaceGuid, PcdCName, ValueList[Index]))
            except EvaluationException, Excpt:
                if hasattr(Excpt, 'Pcd'):
                    if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
                        EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
                                        " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
                                        " of the DSC file" % Excpt.Pcd,
                                        File=self.MetaFile, Line=LineNo)
                    else:
                        EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
                                        File=self.MetaFile, Line=LineNo)
                else:
                    EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
                                    File=self.MetaFile, Line=LineNo)

        if ValueList[Index]:
            Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
            if not Valid:
                EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
                                ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
            if PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
                if self._DecPcds[PcdCName, TokenSpaceGuid].DatumType.strip() != ValueList[1].strip():
                    EdkLogger.error('build', FORMAT_INVALID, "Pcd datumtype used in DSC file is not the same as its declaration in DEC file." , File=self.MetaFile, Line=LineNo,
                                ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
        if (TokenSpaceGuid + '.' + PcdCName) in GlobalData.gPlatformPcds:
            if GlobalData.gPlatformPcds[TokenSpaceGuid + '.' + PcdCName] != ValueList[Index]:
                GlobalData.gPlatformPcds[TokenSpaceGuid + '.' + PcdCName] = ValueList[Index]
        return ValueList

    def _FilterPcdBySkuUsage(self,Pcds):
        available_sku = self.SkuIdMgr.AvailableSkuIdSet
        sku_usage = self.SkuIdMgr.SkuUsageType
        if sku_usage == SkuClass.SINGLE:
            for pcdname in Pcds:
                pcd = Pcds[pcdname]
                Pcds[pcdname].SkuInfoList = {"DEFAULT":pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
                if type(pcd) is StructurePcd and pcd.SkuOverrideValues:
                    Pcds[pcdname].SkuOverrideValues = {"DEFAULT":pcd.SkuOverrideValues[skuid] for skuid in pcd.SkuOverrideValues if skuid in available_sku}
        else:
            for pcdname in Pcds:
                pcd = Pcds[pcdname]
                Pcds[pcdname].SkuInfoList = {skuid:pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
                if type(pcd) is StructurePcd and pcd.SkuOverrideValues:
                    Pcds[pcdname].SkuOverrideValues = {skuid:pcd.SkuOverrideValues[skuid] for skuid in pcd.SkuOverrideValues if skuid in available_sku}
        return Pcds
    def CompleteHiiPcdsDefaultStores(self,Pcds):
        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]]]
        DefaultStoreMgr = DefaultStore(self.DefaultStores)
        for pcd in HiiPcd:
            for skuid in pcd.SkuInfoList:
                skuobj = pcd.SkuInfoList.get(skuid)
                if "STANDARD" not in skuobj.DefaultStoreDict:
                    PcdDefaultStoreSet = set([defaultstorename  for defaultstorename in skuobj.DefaultStoreDict])
                    mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)
                    skuobj.DefaultStoreDict['STANDARD'] = copy.deepcopy(skuobj.DefaultStoreDict[mindefaultstorename])
        return Pcds

    def RecoverCommandLinePcd(self):
        pcdset = []
        if GlobalData.BuildOptionPcd:
            for pcd in GlobalData.BuildOptionPcd:
                if pcd[2] == "":
                    pcdset.append((pcd[0],pcd[1],pcd[3]))
                else:
                    if (pcd[1],pcd[0]) not in self._Pcds:
                        pcdvalue = pcd[3] if len(pcd) == 4 else pcd[2]
                        pcdset.append((pcd[0],pcd[1],pcdvalue))
                    #else:
                        # remove the settings from command line since it has been handled.
        GlobalData.BuildOptionPcd = pcdset
    def GetFieldValueFromComm(self,ValueStr,TokenSpaceGuidCName, TokenCName, FieldName):
        PredictedFieldType = "VOID*"
        if ValueStr.startswith('L'):
            if not ValueStr[1]:
                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
            ValueStr = ValueStr[0] + '"' + ValueStr[1:] + '"'
            PredictedFieldType = "VOID*"
        elif ValueStr.startswith('H') or ValueStr.startswith('{'):
            EdkLogger.error("build", FORMAT_INVALID, 'Currently we do not support assign H"{...}" format for Pcd field.', ExtraData="%s.%s.%s from command line" % (TokenSpaceGuidCName, TokenCName, FieldName))
            ValueStr = ValueStr[1:]
            PredictedFieldType = "VOID*"
        elif ValueStr.upper() in ['TRUE', '0X1', '0X01', '1', 'FALSE', '0X0', '0X00', '0']:
            PredictedFieldType = "BOOLEAN"
        elif ValueStr.isdigit() or ValueStr.upper().startswith('0X'):
            PredictedFieldType = TAB_UINT16
        else:
            if not ValueStr[0]:
                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
            ValueStr = '"' + ValueStr + '"'
            PredictedFieldType = "VOID*"
        IsValid, Cause = CheckPcdDatum(PredictedFieldType, ValueStr)
        if not IsValid:
            EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s.%s from command line" % (TokenSpaceGuidCName, TokenCName, FieldName))
        if PredictedFieldType == 'BOOLEAN':
            ValueStr = ValueStr.upper()
            if ValueStr == 'TRUE' or ValueStr == '1':
                ValueStr = '1'
            elif ValueStr == 'FALSE' or ValueStr == '0':
                ValueStr = '0'
        return  ValueStr
    def __ParsePcdFromCommandLine(self):
        if GlobalData.BuildOptionPcd:
            for i, pcd in enumerate(GlobalData.BuildOptionPcd):
                if type(pcd) is tuple:
                    continue
                (pcdname, pcdvalue) = pcd.split('=')
                if not pcdvalue:
                    EdkLogger.error('build', AUTOGEN_ERROR, "No Value specified for the PCD %s." % (pcdname))
                if '.' in pcdname:
                    (Name1, Name2) = pcdname.split('.',1)
                    if "." in Name2:
                        (Name3, FieldName) = Name2.split(".",1)
                        if ((Name3,Name1)) in self.DecPcds:
                            HasTokenSpace = True
                            TokenCName = Name3
                            TokenSpaceGuidCName = Name1
                        else:
                            FieldName = Name2
                            TokenCName = Name1
                            TokenSpaceGuidCName = ''
                            HasTokenSpace = False
                    else:
                        if ((Name2,Name1)) in self.DecPcds:
                            HasTokenSpace = True
                            TokenCName = Name2
                            TokenSpaceGuidCName = Name1
                            FieldName =""
                        else:
                            FieldName = Name2
                            TokenCName = Name1
                            TokenSpaceGuidCName = ''
                            HasTokenSpace = False
                else:
                    FieldName = ""
                    TokenCName = pcdname
                    TokenSpaceGuidCName = ''
                    HasTokenSpace = False
                TokenSpaceGuidCNameList = []
                FoundFlag = False
                PcdDatumType = ''
                NewValue = ''
                if not HasTokenSpace:
                    for key in self.DecPcds:
                        if TokenCName == key[0]:
                            if TokenSpaceGuidCName:
                                EdkLogger.error(
                                                'build',
                                                 AUTOGEN_ERROR,
                                                "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, TokenSpaceGuidCName, key[1])
                                                )
                            else:
                                TokenSpaceGuidCName = key[1]
                                FoundFlag = True
                else:
                    if (TokenCName, TokenSpaceGuidCName) in self.DecPcds:
                        FoundFlag = True
                if FieldName:
                    NewValue = self.GetFieldValueFromComm(pcdvalue, TokenSpaceGuidCName, TokenCName, FieldName)
                    GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, FieldName,NewValue,("build command options",1))
                else:
                    # Replace \' to ', \\\' to \'
                    pcdvalue = pcdvalue.replace("\\\\\\'", '\\\\\\"').replace('\\\'', '\'').replace('\\\\\\"', "\\'")
                    for key in self.DecPcds:
                        PcdItem = self.DecPcds[key]
                        if HasTokenSpace:
                            if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
                                PcdDatumType = PcdItem.DatumType
                                if pcdvalue.startswith('H'):
                                    try:
                                        pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
                                    except BadExpression, Value:
                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
                                        pcdvalue = 'H' + pcdvalue
                                elif pcdvalue.startswith("L'"):
                                    try:
                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
                                    except BadExpression, Value:
                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
                                        pcdvalue = 'H' + pcdvalue
                                elif pcdvalue.startswith("'"):
                                    try:
                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
                                    except BadExpression, Value:
                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
                                        pcdvalue = 'H' + pcdvalue
                                elif pcdvalue.startswith('L'):
                                    pcdvalue = 'L"' + pcdvalue[1:] + '"'
                                    try:
                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
                                    except BadExpression, Value:
                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                else:
                                    try:
                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
                                    except BadExpression, Value:
                                        try:
                                            pcdvalue = '"' + pcdvalue + '"'
                                            pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
                                        except BadExpression, Value:
                                            EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                            (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
                                FoundFlag = True
                        else:
                            if PcdItem.TokenCName == TokenCName:
                                if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
                                    if len (TokenSpaceGuidCNameList) < 1:
                                        TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
                                        PcdDatumType = PcdItem.DatumType
                                        TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
                                        if pcdvalue.startswith('H'):
                                            try:
                                                pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
                                            except BadExpression, Value:
                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64,'BOOLEAN']:
                                                pcdvalue = 'H' + pcdvalue
                                        elif pcdvalue.startswith("L'"):
                                            try:
                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(
                                                    True)
                                            except BadExpression, Value:
                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
                                                pcdvalue = 'H' + pcdvalue
                                        elif pcdvalue.startswith("'"):
                                            try:
                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(
                                                    True)
                                            except BadExpression, Value:
                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
                                                pcdvalue = 'H' + pcdvalue
                                        elif pcdvalue.startswith('L'):
                                            pcdvalue = 'L"' + pcdvalue[1:] + '"'
                                            try:
                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(
                                                    True)
                                            except BadExpression, Value:
                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                        else:
                                            try:
                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
                                            except BadExpression, Value:
                                                try:
                                                    pcdvalue = '"' + pcdvalue + '"'
                                                    pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
                                                except BadExpression, Value:
                                                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
                                                                    (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
                                        NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
                                        FoundFlag = True
                                    else:
                                        EdkLogger.error(
                                                'build',
                                                 AUTOGEN_ERROR,
                                                "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
                                                )
                    GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, FieldName,NewValue,("build command options",1))
                if not FoundFlag:
                    if HasTokenSpace:
                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, TokenCName))
                    else:
                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (TokenCName))
                for BuildData in self._Bdb._CACHE_.values():
                    if BuildData.MetaFile.Ext == '.dec' or BuildData.MetaFile.Ext == '.dsc':
                        continue
                    for key in BuildData.Pcds:
                        PcdItem = BuildData.Pcds[key]
                        if (TokenSpaceGuidCName, TokenCName) == (PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName) and FieldName =="":
                            PcdItem.DefaultValue = NewValue
    ## Retrieve all PCD settings in platform
    def _GetPcds(self):
        if self._Pcds == None:
            self._Pcds = sdict()
            self.__ParsePcdFromCommandLine()
            self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
            self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
            self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
            self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))
            self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))
            self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))
            self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))
            self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))
            self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))

            self._Pcds = self.CompletePcdValues(self._Pcds)
            self._Pcds = self.OverrideByFdfCommOverAll(self._Pcds)
            self._Pcds = self.UpdateStructuredPcds(MODEL_PCD_TYPE_LIST, self._Pcds)
            self._Pcds = self.CompleteHiiPcdsDefaultStores(self._Pcds)
            self._Pcds = self._FilterPcdBySkuUsage(self._Pcds)

            self.RecoverCommandLinePcd()
        return self._Pcds

    def _dumpPcdInfo(self,Pcds):
        for pcd in Pcds:
            pcdobj = Pcds[pcd]
            if not pcdobj.TokenCName.startswith("Test"):
                continue
            for skuid in pcdobj.SkuInfoList:
                if pcdobj.Type in (self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]):
                    for storename in pcdobj.SkuInfoList[skuid].DefaultStoreDict:
                        print "PcdCName: %s, SkuName: %s, StoreName: %s, Value: %s" % (".".join((pcdobj.TokenSpaceGuidCName, pcdobj.TokenCName)), skuid,storename,str(pcdobj.SkuInfoList[skuid].DefaultStoreDict[storename]))
                else:
                    print "PcdCName: %s, SkuName: %s, Value: %s" % (".".join((pcdobj.TokenSpaceGuidCName, pcdobj.TokenCName)), skuid,str(pcdobj.SkuInfoList[skuid].DefaultValue))
    ## Retrieve [BuildOptions]
    def _GetBuildOptions(self):
        if self._BuildOptions == None:
            self._BuildOptions = sdict()
            #
            # Retrieve build option for EDKII and EDK style module
            #
            for CodeBase in (EDKII_NAME, EDK_NAME):
                RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, CodeBase]
                for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4,Dummy5 in RecordList:
                    if Dummy3.upper() != 'COMMON':
                        continue
                    CurKey = (ToolChainFamily, ToolChain, CodeBase)
                    #
                    # Only flags can be appended
                    #
                    if CurKey not in self._BuildOptions or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
                        self._BuildOptions[CurKey] = Option
                    else:
                        if ' ' + Option not in self._BuildOptions[CurKey]:
                            self._BuildOptions[CurKey] += ' ' + Option
        return self._BuildOptions

    def GetBuildOptionsByModuleType(self, Edk, ModuleType):
        if self._ModuleTypeOptions == None:
            self._ModuleTypeOptions = sdict()
        if (Edk, ModuleType) not in self._ModuleTypeOptions:
            options = sdict()
            self._ModuleTypeOptions[Edk, ModuleType] = options
            DriverType = '%s.%s' % (Edk, ModuleType)
            CommonDriverType = '%s.%s' % ('COMMON', ModuleType)
            RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch]
            for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4,Dummy5 in RecordList:
                Type = Dummy2 + '.' + Dummy3
                if Type.upper() == DriverType.upper() or Type.upper() == CommonDriverType.upper():
                    Key = (ToolChainFamily, ToolChain, Edk)
                    if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
                        options[Key] = Option
                    else:
                        if ' ' + Option not in options[Key]:
                            options[Key] += ' ' + Option
        return self._ModuleTypeOptions[Edk, ModuleType]

    def GetStructurePcdInfo(self, PcdSet):
        structure_pcd_data = {}
        for item in PcdSet:
            if (item[0],item[1]) not in structure_pcd_data:
                structure_pcd_data[(item[0],item[1])] = []
            structure_pcd_data[(item[0],item[1])].append(item)

        return structure_pcd_data
    def OverrideByFdfComm(self,StruPcds):
        StructurePcdInCom = OrderedDict()
        for item in GlobalData.BuildOptionPcd:
            if len(item) == 5 and (item[1],item[0]) in StruPcds:
                StructurePcdInCom[(item[0],item[1],item[2] )] = (item[3],item[4])
        GlobalPcds = set([(item[0],item[1]) for item in StructurePcdInCom.keys()])
        for Pcd in StruPcds.values():
            if (Pcd.TokenSpaceGuidCName,Pcd.TokenCName) not in GlobalPcds:
                continue
            FieldValues = OrderedDict()
            for item in StructurePcdInCom:
                if (Pcd.TokenSpaceGuidCName,Pcd.TokenCName) == (item[0],item[1]) and item[2]:
                    FieldValues[item[2]] = StructurePcdInCom[item]
            for field in FieldValues:
                if field not in Pcd.PcdFieldValueFromComm:
                    Pcd.PcdFieldValueFromComm[field] = ["","",""]
                Pcd.PcdFieldValueFromComm[field][0] = FieldValues[field][0]
                Pcd.PcdFieldValueFromComm[field][1] = FieldValues[field][1][0]
                Pcd.PcdFieldValueFromComm[field][2] = FieldValues[field][1][1]
        return StruPcds
    def OverrideByFdfCommOverAll(self,AllPcds):
        def CheckStructureInComm(commpcds):
            if not commpcds:
                return False
            if len(commpcds[0]) == 5:
                return True
            return False

        if CheckStructureInComm(GlobalData.BuildOptionPcd):
            StructurePcdInCom = {(item[0],item[1],item[2] ):(item[3],item[4]) for item in GlobalData.BuildOptionPcd } if GlobalData.BuildOptionPcd else {}
            NoFiledValues = {(item[0],item[1]):StructurePcdInCom[item] for item in StructurePcdInCom if not item[2]}
        else:
            NoFiledValues = {(item[0],item[1]):[item[2]] for item in GlobalData.BuildOptionPcd}
        for Guid,Name in NoFiledValues:
            if (Name,Guid) in AllPcds:
                Pcd = AllPcds.get((Name,Guid))
                if isinstance(self._DecPcds.get((Pcd.TokenCName,Pcd.TokenSpaceGuidCName), None),StructurePcd):
                    self._DecPcds.get((Pcd.TokenCName,Pcd.TokenSpaceGuidCName)).PcdValueFromComm = NoFiledValues[(Pcd.TokenSpaceGuidCName,Pcd.TokenCName)][0]
                else:
                    Pcd.DefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName,Pcd.TokenCName)][0]
                    for sku in Pcd.SkuInfoList:
                        SkuInfo = Pcd.SkuInfoList[sku]
                        if SkuInfo.DefaultValue:
                            SkuInfo.DefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName,Pcd.TokenCName)][0]
                        else:
                            SkuInfo.HiiDefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName,Pcd.TokenCName)][0]
                            for defaultstore in SkuInfo.DefaultStoreDict:
                                SkuInfo.DefaultStoreDict[defaultstore] = NoFiledValues[(Pcd.TokenSpaceGuidCName,Pcd.TokenCName)][0]
                    if Pcd.DatumType == "VOID*":
                        if Pcd.MaxDatumSize is None:
                            Pcd.MaxDatumSize = '0'
                        MaxSize = int(Pcd.MaxDatumSize,10)
                        if Pcd.DefaultValue.startswith("{") and Pcd.DefaultValue.endswith("}"):
                            MaxSize = max([len(Pcd.DefaultValue.split(",")),MaxSize])
                        elif Pcd.DefaultValue.startswith("\"") or Pcd.DefaultValue.startswith("\'"):
                            MaxSize = max([len(Pcd.DefaultValue)-2+1,MaxSize])
                        elif Pcd.DefaultValue.startswith("L\""):
                            MaxSize = max([2*(len(Pcd.DefaultValue)-3+1),MaxSize])
                        else:
                            MaxSize = max([len(Pcd.DefaultValue),MaxSize])
                        Pcd.MaxDatumSize = str(MaxSize)
            else:
                PcdInDec = self.DecPcds.get((Name,Guid))
                if isinstance(PcdInDec,StructurePcd):
                    PcdInDec.PcdValueFromComm = NoFiledValues[(Guid,Name)][0]
                if PcdInDec:
                    if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
                                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
                        self.Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
                        self.Pcds[Name, Guid].DefaultValue = NoFiledValues[( Guid,Name)][0]
        return AllPcds
    def UpdateStructuredPcds(self, TypeList, AllPcds):

        DynamicPcdType = [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]

        Pcds = AllPcds
        DefaultStoreMgr = DefaultStore(self.DefaultStores)
        SkuIds = self.SkuIdMgr.AvailableSkuIdSet
        SkuIds.update({'DEFAULT':0})
        DefaultStores = set([storename for pcdobj in AllPcds.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict.keys()])

        S_PcdSet = []
        # Find out all possible PCD candidates for self._Arch
        RecordList = []

        for Type in TypeList:
            RecordList.extend(self._RawData[Type, self._Arch])

        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, default_store, Dummy4,Dummy5 in RecordList:
            SkuName = SkuName.upper()
            default_store = default_store.upper()
            SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
            if SkuName not in SkuIds:
                continue

            if SkuName in SkuIds and "." in TokenSpaceGuid:
                S_PcdSet.append([ TokenSpaceGuid.split(".")[0],TokenSpaceGuid.split(".")[1], PcdCName,SkuName, default_store,Dummy5, AnalyzePcdExpression(Setting)[0]])

        # handle pcd value override
        StrPcdSet = self.GetStructurePcdInfo(S_PcdSet)
        S_pcd_set = OrderedDict()
        for str_pcd in StrPcdSet:
            str_pcd_obj = Pcds.get((str_pcd[1], str_pcd[0]), None)
            str_pcd_dec = self._DecPcds.get((str_pcd[1], str_pcd[0]), None)
            if not isinstance (str_pcd_dec, StructurePcd):
                EdkLogger.error('build', PARSER_ERROR,
                            "Pcd (%s.%s) is not declared as Structure PCD in DEC files. Arch: ['%s']" % (str_pcd[0], str_pcd[1], self._Arch),
                            File=self.MetaFile,Line = StrPcdSet[str_pcd][0][5])
            if str_pcd_dec:
                str_pcd_obj_str = StructurePcd()
                str_pcd_obj_str.copy(str_pcd_dec)
                if str_pcd_obj:
                    str_pcd_obj_str.copy(str_pcd_obj)
                    if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                        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}
                    else:
                        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}
                for str_pcd_data in StrPcdSet[str_pcd]:
                    if str_pcd_data[3] in SkuIds:
                        str_pcd_obj_str.AddOverrideValue(str_pcd_data[2], str(str_pcd_data[6]), 'DEFAULT' if str_pcd_data[3] == 'COMMON' else str_pcd_data[3],'STANDARD' if str_pcd_data[4] == 'COMMON' else str_pcd_data[4], 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[5])
                S_pcd_set[str_pcd[1], str_pcd[0]] = str_pcd_obj_str
            else:
                EdkLogger.error('build', PARSER_ERROR,
                            "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (str_pcd[0], str_pcd[1], self._Arch),
                            File=self.MetaFile,Line = StrPcdSet[str_pcd][0][5])
        # Add the Structure PCD that only defined in DEC, don't have override in DSC file
        for Pcd in self.DecPcds:
            if type (self._DecPcds[Pcd]) is StructurePcd:
                if Pcd not in S_pcd_set:
                    str_pcd_obj_str = StructurePcd()
                    str_pcd_obj_str.copy(self._DecPcds[Pcd])
                    str_pcd_obj = Pcds.get(Pcd, None)
                    if str_pcd_obj:
                        str_pcd_obj_str.copy(str_pcd_obj)
                        if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                            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}
                        else:
                            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}
                    S_pcd_set[Pcd] = str_pcd_obj_str
        if S_pcd_set:
            GlobalData.gStructurePcd[self.Arch] = S_pcd_set
        for stru_pcd in S_pcd_set.values():
            for skuid in SkuIds:
                if skuid in stru_pcd.SkuOverrideValues:
                    continue
                nextskuid = self.SkuIdMgr.GetNextSkuId(skuid)
                NoDefault = False
                if skuid not in stru_pcd.SkuOverrideValues:
                    while nextskuid not in stru_pcd.SkuOverrideValues:
                        if nextskuid == "DEFAULT":
                            NoDefault = True
                            break
                        nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
                    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 {'STANDARD':stru_pcd.DefaultValues})
                    if not NoDefault:
                        stru_pcd.ValueChain[(skuid,'')]= (nextskuid,'')
            if stru_pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                for skuid in SkuIds:
                    nextskuid = skuid
                    NoDefault = False
                    if skuid not in stru_pcd.SkuOverrideValues:
                        while nextskuid not in stru_pcd.SkuOverrideValues:
                            if nextskuid == "DEFAULT":
                                NoDefault = True
                                break
                            nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
                    if NoDefault:
                        continue
                    PcdDefaultStoreSet = set([defaultstorename  for defaultstorename in stru_pcd.SkuOverrideValues[nextskuid]])
                    mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)

                    for defaultstoreid in DefaultStores:
                        if defaultstoreid not in stru_pcd.SkuOverrideValues[skuid]:
                            stru_pcd.SkuOverrideValues[skuid][defaultstoreid] = copy.deepcopy(stru_pcd.SkuOverrideValues[nextskuid][mindefaultstorename])
                            stru_pcd.ValueChain[(skuid,defaultstoreid)]= (nextskuid,mindefaultstorename)
        S_pcd_set = self.OverrideByFdfComm(S_pcd_set)
        Str_Pcd_Values = self.GenerateByteArrayValue(S_pcd_set)
        if Str_Pcd_Values:
            for (skuname,StoreName,PcdGuid,PcdName,PcdValue) in Str_Pcd_Values:
                str_pcd_obj = S_pcd_set.get((PcdName, PcdGuid))
                if str_pcd_obj is None:
                    print PcdName, PcdGuid
                    raise
                if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
                                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                    if skuname not in str_pcd_obj.SkuInfoList:
                        str_pcd_obj.SkuInfoList[skuname] = SkuInfoClass(SkuIdName=skuname, SkuId=self.SkuIds[skuname][0], HiiDefaultValue=PcdValue, DefaultStore = {StoreName:PcdValue})
                    else:
                        str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue = PcdValue
                        str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.update({StoreName:PcdValue})
                elif str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
                                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
                    if skuname in (self.SkuIdMgr.SystemSkuId, 'DEFAULT', 'COMMON'):
                        str_pcd_obj.DefaultValue = PcdValue
                else:
                    if skuname not in str_pcd_obj.SkuInfoList:
                        nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
                        NoDefault = False
                        while nextskuid not in str_pcd_obj.SkuInfoList:
                            if nextskuid == "DEFAULT":
                                NoDefault = True
                                break
                            nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
                        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)
                        str_pcd_obj.SkuInfoList[skuname].SkuId = self.SkuIds[skuname][0]
                        str_pcd_obj.SkuInfoList[skuname].SkuIdName = skuname
                    else:
                        str_pcd_obj.SkuInfoList[skuname].DefaultValue = PcdValue
            for str_pcd_obj in S_pcd_set.values():
                if str_pcd_obj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
                                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                    continue
                PcdDefaultStoreSet = set([defaultstorename  for skuobj in str_pcd_obj.SkuInfoList.values() for defaultstorename in skuobj.DefaultStoreDict])
                DefaultStoreObj = DefaultStore(self._GetDefaultStores())
                mindefaultstorename = DefaultStoreObj.GetMin(PcdDefaultStoreSet)
                str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].HiiDefaultValue = str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].DefaultStoreDict[mindefaultstorename]

            for str_pcd_obj in S_pcd_set.values():

                str_pcd_obj.MaxDatumSize = self.GetStructurePcdMaxSize(str_pcd_obj)
                Pcds[str_pcd_obj.TokenCName, str_pcd_obj.TokenSpaceGuidCName] = str_pcd_obj

            for pcdkey in Pcds:
                pcd = Pcds[pcdkey]
                if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                    pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
                    del(pcd.SkuInfoList['COMMON'])
                elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                    del(pcd.SkuInfoList['COMMON'])

        map(self.FilterSkuSettings,[Pcds[pcdkey] for pcdkey in Pcds if Pcds[pcdkey].Type in DynamicPcdType])
        return Pcds

    ## Retrieve non-dynamic PCD settings
    #
    #   @param  Type    PCD type
    #
    #   @retval a dict object contains settings of given PCD type
    #
    def _GetPcd(self, Type):
        Pcds = sdict()
        #
        # tdict is a special dict kind of type, used for selecting correct
        # PCD settings for certain ARCH
        #
        AvailableSkuIdSet = copy.copy(self.SkuIds)

        PcdDict = tdict(True, 3)
        PcdSet = set()
        # Find out all possible PCD candidates for self._Arch
        RecordList = self._RawData[Type, self._Arch]
        PcdValueDict = sdict()
        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4,Dummy5 in RecordList:
            SkuName = SkuName.upper()
            SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
            if SkuName not in AvailableSkuIdSet:
                EdkLogger.error('build ', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
                                            File=self.MetaFile, Line=Dummy5)
            if SkuName in (self.SkuIdMgr.SystemSkuId, 'DEFAULT', 'COMMON'):
                if "." not in TokenSpaceGuid:
                    PcdSet.add((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
                PcdDict[Arch, PcdCName, TokenSpaceGuid, SkuName] = Setting

        for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdSet:
            Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid, SkuName]
            if Setting == None:
                continue
            PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
            if (PcdCName, TokenSpaceGuid) in PcdValueDict:
                PcdValueDict[PcdCName, TokenSpaceGuid][SkuName] = (PcdValue, DatumType, MaxDatumSize)
            else:
                PcdValueDict[PcdCName, TokenSpaceGuid] = {SkuName:(PcdValue, DatumType, MaxDatumSize)}

        PcdsKeys = PcdValueDict.keys()
        for PcdCName, TokenSpaceGuid in PcdsKeys:

            PcdSetting = PcdValueDict[PcdCName, TokenSpaceGuid]
            PcdValue = None
            DatumType = None
            MaxDatumSize = None
            if 'COMMON' in PcdSetting:
                PcdValue, DatumType, MaxDatumSize = PcdSetting['COMMON']
            if 'DEFAULT' in PcdSetting:
                PcdValue, DatumType, MaxDatumSize = PcdSetting['DEFAULT']
            if self.SkuIdMgr.SystemSkuId in PcdSetting:
                PcdValue, DatumType, MaxDatumSize = PcdSetting[self.SkuIdMgr.SystemSkuId]

            Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
                                                PcdCName,
                                                TokenSpaceGuid,
                                                self._PCD_TYPE_STRING_[Type],
                                                DatumType,
                                                PcdValue,
                                                '',
                                                MaxDatumSize,
                                                {},
                                                False,
                                                None,
                                                IsDsc=True)


        return Pcds

    def __UNICODE2OCTList(self,Value):
        Value = Value.strip()
        Value = Value[2:-1]
        List = []
        for Item in Value:
            Temp = '%04X' % ord(Item)
            List.append('0x' + Temp[2:4])
            List.append('0x' + Temp[0:2])
        List.append('0x00')
        List.append('0x00')
        return List
    def __STRING2OCTList(self,Value):
        OCTList = []
        Value = Value.strip('"')
        for char in Value:
            Temp = '%02X' % ord(char)
            OCTList.append('0x' + Temp)
        OCTList.append('0x00')
        return OCTList

    def GetStructurePcdMaxSize(self, str_pcd):
        pcd_default_value = str_pcd.DefaultValue
        sku_values = [skuobj.HiiDefaultValue if str_pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]] else skuobj.DefaultValue for skuobj in str_pcd.SkuInfoList.values()]
        sku_values.append(pcd_default_value)

        def get_length(value):
            Value = value.strip()
            if len(value) > 1:
                if Value.startswith('GUID') and Value.endswith(')'):
                    return 16
                if Value.startswith('L"') and Value.endswith('"'):
                    return len(Value[2:-1])
                if Value[0] == '"' and Value[-1] == '"':
                    return len(Value) - 2
                if Value[0] == '{' and Value[-1] == '}':
                    return len(Value.split(","))
                if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
                    return  len(list(Value[2:-1]))
                if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
                    return len(Value) - 2
            return len(Value)

        return str(max([pcd_size for pcd_size in [get_length(item) for item in sku_values]]))

    def IsFieldValueAnArray (self, Value):
        Value = Value.strip()
        if Value.startswith('GUID') and Value.endswith(')'):
            return True
        if Value.startswith('L"') and Value.endswith('"')  and len(list(Value[2:-1])) > 1:
            return True
        if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
            return True
        if Value[0] == '{' and Value[-1] == '}':
            return True
        if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
            return True
        if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
            return True
        return False

    def ExecuteCommand (self, Command):
        try:
            Process = subprocess.Popen(Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        except:
            EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s' % Command)
        Result = Process.communicate()
        return Process.returncode, Result[0], Result[1]

    def IntToCString(self, Value, ValueSize):
        Result = '"'
        if not isinstance (Value, str):
            for Index in range(0, ValueSize):
                Result = Result + '\\x%02x' % (Value & 0xff)
                Value = Value >> 8
        Result = Result + '"'
        return Result

    def GetPcdMaxSize(self,Pcd):
        MaxSize = int(Pcd.MaxDatumSize,10) if Pcd.MaxDatumSize else 0
        if Pcd.DatumType not in ['BOOLEAN','UINT8','UINT16','UINT32','UINT64']:
            if Pcd.PcdValueFromComm:
                if Pcd.PcdValueFromComm.startswith("{") and Pcd.PcdValueFromComm.endswith("}"):
                    MaxSize = max([len(Pcd.PcdValueFromComm.split(",")),MaxSize])
                elif Pcd.PcdValueFromComm.startswith("\"") or Pcd.PcdValueFromComm.startswith("\'"):
                    MaxSize = max([len(Pcd.PcdValueFromComm)-2+1,MaxSize])
                elif Pcd.PcdValueFromComm.startswith("L\""):
                    MaxSize = max([2*(len(Pcd.PcdValueFromComm)-3+1),MaxSize])
                else:
                    MaxSize = max([len(Pcd.PcdValueFromComm),MaxSize])
        elif Pcd.DatumType not in ['BOOLEAN','UINT8']:
            MaxSize = 1
        elif Pcd.DatumType  == 'UINT16':
            MaxSize = 2
        elif Pcd.DatumType  == 'UINT32':
            MaxSize = 4
        elif Pcd.DatumType  == 'UINT64':
            MaxSize = 8
        return MaxSize
    def GenerateSizeFunction(self,Pcd):
        CApp = "// Default Value in Dec \n"
        CApp = CApp + "void Cal_%s_%s_Size(UINT32 *Size){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
        for FieldList in [Pcd.DefaultValues]:
            if not FieldList:
                continue
            for FieldName in FieldList:
                FieldName = "." + FieldName
                IsArray = self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
                if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
                    try:
                        Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], "VOID*", self._GuidDict)(True)
                    except BadExpression:
                        EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
                                        (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2]))
                    Value, ValueSize = ParseFieldValue(Value)
                    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]);
                else:
                    NewFieldName = ''
                    FieldName_ori = FieldName.strip('.')
                    while '[' in  FieldName:
                        NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
                        ArrayIndex = int(FieldName.split('[', 1)[1].split(']', 1)[0])
                        FieldName = FieldName.split(']', 1)[1]
                    FieldName = NewFieldName + FieldName
                    while '[' in FieldName:
                        FieldName = FieldName.rsplit('[', 1)[0]
                        CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), ArrayIndex + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2], FieldList[FieldName_ori][0])
        for skuname in Pcd.SkuOverrideValues:
            if skuname == "COMMON":
                continue
            for defaultstorenameitem in Pcd.SkuOverrideValues[skuname]:
                CApp = CApp + "// SkuName: %s,  DefaultStoreName: %s \n" % (skuname, defaultstorenameitem)
                for FieldList in [Pcd.SkuOverrideValues[skuname].get(defaultstorenameitem)]:
                    if not FieldList:
                        continue
                    for FieldName in FieldList:
                        FieldName = "." + FieldName
                        IsArray = self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
                        if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
                            try:
                                Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], "VOID*", self._GuidDict)(True)
                            except BadExpression:
                                EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
                                                (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2]))
                            Value, ValueSize = ParseFieldValue(Value)
                            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]);
                        else:
                            NewFieldName = ''
                            FieldName_ori = FieldName.strip('.')
                            while '[' in  FieldName:
                                NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
                                ArrayIndex = int(FieldName.split('[', 1)[1].split(']', 1)[0])
                                FieldName = FieldName.split(']', 1)[1]
                            FieldName = NewFieldName + FieldName
                            while '[' in FieldName:
                                FieldName = FieldName.rsplit('[', 1)[0]
                                CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), ArrayIndex + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2], FieldList[FieldName_ori][0])
        if Pcd.PcdFieldValueFromComm:
            CApp = CApp + "// From Command Line \n"
        for FieldName in Pcd.PcdFieldValueFromComm:
            FieldName = "." + FieldName
            IsArray = self.IsFieldValueAnArray(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0])
            if IsArray and not (Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].startswith('{GUID') and Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].endswith('}')):
                try:
                    Value = ValueExpressionEx(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0], "VOID*", self._GuidDict)(True)
                except BadExpression:
                    EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
                                    (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), Pcd.PcdFieldValueFromComm[FieldName.strip(".")][1], Pcd.PcdFieldValueFromComm[FieldName.strip(".")][2]))
                Value, ValueSize = ParseFieldValue(Value)
                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]);
            else:
                NewFieldName = ''
                FieldName_ori = FieldName.strip('.')
                while '[' in  FieldName:
                    NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
                    ArrayIndex = int(FieldName.split('[', 1)[1].split(']', 1)[0])
                    FieldName = FieldName.split(']', 1)[1]
                FieldName = NewFieldName + FieldName
                while '[' in FieldName:
                    FieldName = FieldName.rsplit('[', 1)[0]
                    CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), ArrayIndex + 1, Pcd.PcdFieldValueFromComm[FieldName_ori][1], Pcd.PcdFieldValueFromComm[FieldName_ori][2], Pcd.PcdFieldValueFromComm[FieldName_ori][0])
        CApp = CApp + "  *Size = (%d > *Size ? %d : *Size); // The Pcd maxsize is %d \n" % (self.GetPcdMaxSize(Pcd),self.GetPcdMaxSize(Pcd),self.GetPcdMaxSize(Pcd))
        CApp = CApp + "}\n"
        return CApp
    def GenerateSizeStatments(self,Pcd):
        CApp = '  Size = sizeof(%s);\n' % (Pcd.DatumType)
        CApp = CApp + '  Cal_%s_%s_Size(&Size);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
        return CApp
    def GenerateDefaultValueAssignFunction(self,Pcd):
        CApp = "// Default value in Dec \n"
        CApp = CApp + "void Assign_%s_%s_Default_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType)
        CApp = CApp + '  UINT32  FieldSize;\n'
        CApp = CApp + '  CHAR8   *Value;\n'
        DefaultValueFromDec = Pcd.DefaultValueFromDec
        IsArray = self.IsFieldValueAnArray(Pcd.DefaultValueFromDec)
        if IsArray:
            try:
                DefaultValueFromDec = ValueExpressionEx(Pcd.DefaultValueFromDec, "VOID*")(True)
            except BadExpression:
                EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DEC: %s" %
                                (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValueFromDec))
        Value, ValueSize = ParseFieldValue (DefaultValueFromDec)
        if isinstance(Value, str):
            CApp = CApp + '  Pcd = %s; // From DEC Default Value %s\n' % (Value, Pcd.DefaultValueFromDec)
        elif IsArray:
        #
        # Use memcpy() to copy value into field
        #
            CApp = CApp + '  Value     = %s; // From DEC Default Value %s\n' % (self.IntToCString(Value, ValueSize), Pcd.DefaultValueFromDec)
            CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
        for FieldList in [Pcd.DefaultValues]:
            if not FieldList:
                continue
            for FieldName in FieldList:
                IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
                if IsArray:
                    try:
                        FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
                    except BadExpression:
                        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]))

                try:
                    Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
                except Exception:
                    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]))
                if isinstance(Value, str):
                    CApp = CApp + '  Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                elif IsArray:
                    #
                    # Use memcpy() to copy value into field
                    #
                    CApp = CApp + '  FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.DatumType, FieldName)
                    CApp = CApp + '  Value     = %s; // From %s Line %d Value %s\n' % (self.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                    CApp = CApp + '  memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
                else:
                    if ValueSize > 4:
                        CApp = CApp + '  Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                    else:
                        CApp = CApp + '  Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
        CApp = CApp + "}\n"
        return CApp
    def GenerateDefaultValueAssignStatement(self,Pcd):
        CApp = '  Assign_%s_%s_Default_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
        return CApp
    def GenerateInitValueFunction(self,Pcd,SkuName,DefaultStoreName):
        CApp = "// Value in Dsc for Sku: %s, DefaultStore %s\n" % (SkuName,DefaultStoreName)
        CApp = CApp + "void Assign_%s_%s_%s_%s_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName,DefaultStoreName,Pcd.DatumType)
        CApp = CApp + '  UINT32  FieldSize;\n'
        CApp = CApp + '  CHAR8   *Value;\n'

        CApp = CApp + "// SkuName: %s,  DefaultStoreName: %s \n" % ('DEFAULT', 'STANDARD')
        inherit_OverrideValues = Pcd.SkuOverrideValues[SkuName]
        if (SkuName,DefaultStoreName) == ('DEFAULT','STANDARD'):
            pcddefaultvalue = Pcd.DefaultFromDSC.get('DEFAULT',{}).get('STANDARD', Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue
        else:
            if not Pcd.DscRawValue:
                # handle the case that structure pcd is not appear in DSC
                self.CopyDscRawValue(Pcd)
            pcddefaultvalue = Pcd.DscRawValue.get(SkuName,{}).get(DefaultStoreName)
        for FieldList in [pcddefaultvalue,inherit_OverrideValues.get(DefaultStoreName)]:
            if not FieldList:
                continue
            if pcddefaultvalue and FieldList == pcddefaultvalue:
                IsArray = self.IsFieldValueAnArray(FieldList)
                if IsArray:
                    try:
                        FieldList = ValueExpressionEx(FieldList, "VOID*")(True)
                    except BadExpression:
                        EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DSC: %s" %
                                        (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
                Value, ValueSize = ParseFieldValue (FieldList)

                if (SkuName,DefaultStoreName) == ('DEFAULT','STANDARD'):
                    if isinstance(Value, str):
                        CApp = CApp + '  Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DefaultFromDSC.get('DEFAULT',{}).get('STANDARD', Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
                    elif IsArray:
                    #
                    # Use memcpy() to copy value into field
                    #
                        CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' % (self.IntToCString(Value, ValueSize), Pcd.DefaultFromDSC.get('DEFAULT',{}).get('STANDARD', Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
                        CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
                else:
                    if isinstance(Value, str):
                        CApp = CApp + '  Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DscRawValue.get(SkuName,{}).get(DefaultStoreName))
                    elif IsArray:
                    #
                    # Use memcpy() to copy value into field
                    #
                        CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' % (self.IntToCString(Value, ValueSize), Pcd.DscRawValue.get(SkuName,{}).get(DefaultStoreName))
                        CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
                continue
            if (SkuName,DefaultStoreName) == ('DEFAULT','STANDARD') or (( (SkuName,'') not in Pcd.ValueChain) and ( (SkuName,DefaultStoreName) not in Pcd.ValueChain )):
                for FieldName in FieldList:
                    IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
                    if IsArray:
                        try:
                            FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
                        except BadExpression:
                            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]))
                    try:
                        Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
                    except Exception:
                        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]))
                    if isinstance(Value, str):
                        CApp = CApp + '  Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                    elif IsArray:
                    #
                    # Use memcpy() to copy value into field
                    #
                        CApp = CApp + '  FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.DatumType, FieldName)
                        CApp = CApp + '  Value     = %s; // From %s Line %d Value %s\n' % (self.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                        CApp = CApp + '  memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
                    else:
                        if ValueSize > 4:
                            CApp = CApp + '  Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                        else:
                            CApp = CApp + '  Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
        CApp = CApp + "}\n"
        return CApp
    def GenerateInitValueStatement(self,Pcd,SkuName,DefaultStoreName):
        CApp = '  Assign_%s_%s_%s_%s_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName,DefaultStoreName)
        return CApp
    def GenerateCommandLineValue(self,Pcd):
        CApp = "// Value in CommandLine\n"
        CApp = CApp + "void Assign_%s_%s_CommandLine_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType)
        CApp = CApp + '  UINT32  FieldSize;\n'
        CApp = CApp + '  CHAR8   *Value;\n'

        pcddefaultvalue = Pcd.PcdValueFromComm
        for FieldList in [pcddefaultvalue,Pcd.PcdFieldValueFromComm]:
            if not FieldList:
                continue
            if pcddefaultvalue and FieldList == pcddefaultvalue:
                IsArray = self.IsFieldValueAnArray(FieldList)
                if IsArray:
                    try:
                        FieldList = ValueExpressionEx(FieldList, "VOID*")(True)
                    except BadExpression:
                        EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DSC: %s" %
                                        (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
                Value, ValueSize = ParseFieldValue (FieldList)

                if isinstance(Value, str):
                    CApp = CApp + '  Pcd = %s; // From Command Line \n' % (Value)
                elif IsArray:
                #
                # Use memcpy() to copy value into field
                #
                    CApp = CApp + '  Value     = %s; // From Command Line.\n' % (self.IntToCString(Value, ValueSize))
                    CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
                continue
            for FieldName in FieldList:
                IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
                if IsArray:
                    try:
                        FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
                    except BadExpression:
                        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]))
                    except:
                        print "error"
                try:
                    Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
                except Exception:
                    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]))
                if isinstance(Value, str):
                    CApp = CApp + '  Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                elif IsArray:
                #
                # Use memcpy() to copy value into field
                #
                    CApp = CApp + '  FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.DatumType, FieldName)
                    CApp = CApp + '  Value     = %s; // From %s Line %d Value %s\n' % (self.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                    CApp = CApp + '  memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
                else:
                    if ValueSize > 4:
                        CApp = CApp + '  Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
                    else:
                        CApp = CApp + '  Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
        CApp = CApp + "}\n"
        return CApp
    def GenerateCommandLineValueStatement(self,Pcd):
        CApp = '  Assign_%s_%s_CommandLine_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
        return CApp
    def GenerateInitializeFunc(self, SkuName, DefaultStore, Pcd, InitByteValue, CApp):
        OverrideValues = {DefaultStore:""}
        if Pcd.SkuOverrideValues:
            OverrideValues = Pcd.SkuOverrideValues[SkuName]
        for DefaultStoreName in OverrideValues.keys():
            CApp = CApp + 'void\n'
            CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
            CApp = CApp + '  void\n'
            CApp = CApp + '  )\n'
            CApp = CApp + '{\n'
            CApp = CApp + '  UINT32  Size;\n'
            CApp = CApp + '  UINT32  FieldSize;\n'
            CApp = CApp + '  CHAR8   *Value;\n'
            CApp = CApp + '  UINT32  OriginalSize;\n'
            CApp = CApp + '  VOID    *OriginalPcd;\n'
            CApp = CApp + '  %s      *Pcd;  // From %s Line %d \n' % (Pcd.DatumType, Pcd.PkgPath, Pcd.PcdDefineLineNo)
            CApp = CApp + '\n'

            if SkuName in Pcd.SkuInfoList:
                DefaultValue = Pcd.SkuInfoList[SkuName].DefaultStoreDict.get(DefaultStoreName,Pcd.SkuInfoList[SkuName].HiiDefaultValue if Pcd.SkuInfoList[SkuName].HiiDefaultValue  else Pcd.SkuInfoList[SkuName].DefaultValue)
            else:
                DefaultValue = Pcd.DefaultValue
            PcdDefaultValue = StringToArray(DefaultValue.strip())

            InitByteValue += '%s.%s.%s.%s|%s|%s\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DatumType, PcdDefaultValue)

            #
            # Get current PCD value and size
            #
            CApp = CApp + '  OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)

            #
            # Determine the size of the PCD.  For simple structures, sizeof(TYPE) provides
            # the correct value.  For structures with a flexible array member, the flexible
            # array member is detected, and the size is based on the highest index used with
            # the flexible array member.  The flexible array member must be the last field
            # in a structure.  The size formula for this case is:
            # OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1)
            #
            CApp = CApp + self.GenerateSizeStatments(Pcd)

            #
            # Allocate and zero buffer for the PCD
            # Must handle cases where current value is smaller, larger, or same size
            # Always keep that larger one as the current size
            #
            CApp = CApp + '  Size = (OriginalSize > Size ? OriginalSize : Size);\n'
            CApp = CApp + '  Pcd     = (%s *)malloc (Size);\n' % (Pcd.DatumType)
            CApp = CApp + '  memset (Pcd, 0, Size);\n'

            #
            # Copy current PCD value into allocated buffer.
            #
            CApp = CApp + '  memcpy (Pcd, OriginalPcd, OriginalSize);\n'

            #
            # Assign field values in PCD
            #
            CApp = CApp + self.GenerateDefaultValueAssignStatement(Pcd)
            if Pcd.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
                for skuname in self.SkuIdMgr.GetSkuChain(SkuName):
                    storeset = [DefaultStoreName] if DefaultStoreName == 'STANDARD' else ['STANDARD', DefaultStoreName]
                    for defaultstorenameitem in storeset:
                        CApp = CApp + "// SkuName: %s,  DefaultStoreName: %s \n" % (skuname, defaultstorenameitem)
                        CApp = CApp + self.GenerateInitValueStatement(Pcd,skuname,defaultstorenameitem)
                    if skuname == SkuName:
                        break
            else:
                CApp = CApp + "// SkuName: %s,  DefaultStoreName: STANDARD \n" % self.SkuIdMgr.SystemSkuId
                CApp = CApp + self.GenerateInitValueStatement(Pcd,self.SkuIdMgr.SystemSkuId,"STANDARD")
            CApp = CApp + self.GenerateCommandLineValueStatement(Pcd)
            #
            # Set new PCD value and size
            #
            CApp = CApp + '  PcdSetPtr (%s, %s, %s, %s, Size, (UINT8 *)Pcd);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)

            #
            # Free PCD
            #
            CApp = CApp + '  free (Pcd);\n'
            CApp = CApp + '}\n'
            CApp = CApp + '\n'
        return InitByteValue, CApp

    def GenerateByteArrayValue (self, StructuredPcds):
        #
        # Generate/Compile/Run C application to determine if there are any flexible array members
        #
        if not StructuredPcds:
            return

        InitByteValue = ""
        CApp = PcdMainCHeader

        Includes = {}
        for PcdName in StructuredPcds:
            Pcd = StructuredPcds[PcdName]
            for IncludeFile in Pcd.StructuredPcdIncludeFile:
                if IncludeFile not in Includes:
                    Includes[IncludeFile] = True
                    CApp = CApp + '#include <%s>\n' % (IncludeFile)
        CApp = CApp + '\n'
        for PcdName in StructuredPcds:
            Pcd = StructuredPcds[PcdName]
            CApp = CApp + self.GenerateSizeFunction(Pcd)
            CApp = CApp + self.GenerateDefaultValueAssignFunction(Pcd)
            CApp = CApp + self.GenerateCommandLineValue(Pcd)
            if not Pcd.SkuOverrideValues or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
                CApp = CApp + self.GenerateInitValueFunction(Pcd,self.SkuIdMgr.SystemSkuId, 'STANDARD')
            else:
                for SkuName in self.SkuIdMgr.SkuOverrideOrder():
                    if SkuName not in Pcd.SkuOverrideValues:
                        continue
                    for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
                        CApp = CApp + self.GenerateInitValueFunction(Pcd,SkuName,DefaultStoreName)
            if not Pcd.SkuOverrideValues or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
                        self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
                InitByteValue, CApp = self.GenerateInitializeFunc(self.SkuIdMgr.SystemSkuId, 'STANDARD', Pcd, InitByteValue, CApp)
            else:
                for SkuName in self.SkuIdMgr.SkuOverrideOrder():
                    if SkuName not in Pcd.SkuOverrideValues:
                        continue
                    for DefaultStoreName in Pcd.DefaultStoreName:
                        Pcd = StructuredPcds[PcdName]
                        InitByteValue, CApp = self.GenerateInitializeFunc(SkuName, DefaultStoreName, Pcd, InitByteValue, CApp)

        CApp = CApp + 'VOID\n'
        CApp = CApp + 'PcdEntryPoint(\n'
        CApp = CApp + '  VOID\n'
        CApp = CApp + '  )\n'
        CApp = CApp + '{\n'
        for Pcd in StructuredPcds.values():
            if not Pcd.SkuOverrideValues or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
                CApp = CApp + '  Initialize_%s_%s_%s_%s();\n' % (self.SkuIdMgr.SystemSkuId, 'STANDARD', Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
            else:
                for SkuName in self.SkuIdMgr.SkuOverrideOrder():
                    if SkuName not in Pcd.SkuOverrideValues:
                        continue
                    for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
                        CApp = CApp + '  Initialize_%s_%s_%s_%s();\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
        CApp = CApp + '}\n'

        CApp = CApp + PcdMainCEntry + '\n'

        if not os.path.exists(self.OutputPath):
            os.makedirs(self.OutputPath)
        CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
        SaveFileOnChange(CAppBaseFileName + '.c', CApp, False)

        MakeApp = PcdMakefileHeader
        if sys.platform == "win32":
            MakeApp = MakeApp + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s\%s.obj\n' % (self.OutputPath, PcdValueInitName) + 'INC = '
        else:
            MakeApp = MakeApp + PcdGccMakefile
            MakeApp = MakeApp + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s/%s.o\n' % (self.OutputPath, PcdValueInitName) + \
                      'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'INCLUDE +='

        PlatformInc = {}
        for Cache in self._Bdb._CACHE_.values():
            if Cache.MetaFile.Ext.lower() != '.dec':
                continue
            if Cache.Includes:
                if str(Cache.MetaFile.Path) not in PlatformInc:
                    PlatformInc[str(Cache.MetaFile.Path)] = Cache.CommonIncludes

        PcdDependDEC = []
        for Pcd in StructuredPcds.values():
            for PackageDec in Pcd.PackageDecs:
                Package = os.path.normpath(mws.join(GlobalData.gWorkspace, PackageDec))
                if not os.path.exists(Package):
                    EdkLogger.error('Build', RESOURCE_NOT_AVAILABLE, "The dependent Package %s of PCD %s.%s is not exist." % (PackageDec, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
                if Package not in PcdDependDEC:
                    PcdDependDEC.append(Package)

        if PlatformInc and PcdDependDEC:
            for pkg in PcdDependDEC:
                if pkg in PlatformInc:
                    for inc in PlatformInc[pkg]:
                        MakeApp += '-I'  + str(inc) + ' '
        MakeApp = MakeApp + '\n'

        CC_FLAGS = LinuxCFLAGS
        if sys.platform == "win32":
            CC_FLAGS = WindowsCFLAGS
        BuildOptions = {}
        for Options in self.BuildOptions:
            if Options[2] != EDKII_NAME:
                continue
            Family = Options[0]
            if Family and Family != self.ToolChainFamily:
                continue
            Target, Tag, Arch, Tool, Attr = Options[1].split("_")
            if Tool != 'CC':
                continue

            if Target == "*" or Target == self._Target:
                if Tag == "*" or Tag == self._Toolchain:
                    if Arch == "*" or Arch == self.Arch:
                        if Tool not in BuildOptions:
                            BuildOptions[Tool] = {}
                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or self.BuildOptions[Options].startswith('='):
                            BuildOptions[Tool][Attr] = self.BuildOptions[Options]
                        else:
                            # append options for the same tool except PATH
                            if Attr != 'PATH':
                                BuildOptions[Tool][Attr] += " " + self.BuildOptions[Options]
                            else:
                                BuildOptions[Tool][Attr] = self.BuildOptions[Options]
        if BuildOptions:
            for Tool in BuildOptions:
                for Attr in BuildOptions[Tool]:
                    if Attr == "FLAGS":
                        Value = BuildOptions[Tool][Attr]
                        ValueList = Value.split()
                        if ValueList:
                            for Id, Item in enumerate(ValueList):
                                if Item == '-D' or Item == '/D':
                                    CC_FLAGS += ' ' + Item
                                    if Id + 1 < len(ValueList):
                                        CC_FLAGS += ' ' + ValueList[Id + 1]
                                elif Item.startswith('/D') or Item.startswith('-D'):
                                    CC_FLAGS += ' ' + Item
        MakeApp += CC_FLAGS

        if sys.platform == "win32":
            MakeApp = MakeApp + PcdMakefileEnd
        MakeFileName = os.path.join(self.OutputPath, 'Makefile')
        SaveFileOnChange(MakeFileName, MakeApp, False)

        InputValueFile = os.path.join(self.OutputPath, 'Input.txt')
        OutputValueFile = os.path.join(self.OutputPath, 'Output.txt')
        SaveFileOnChange(InputValueFile, InitByteValue, False)

        PcdValueInitExe = PcdValueInitName
        if not sys.platform == "win32":
            PcdValueInitExe = os.path.join(os.getenv("EDK_TOOLS_PATH"), 'Source', 'C', 'bin', PcdValueInitName)
        else:
            PcdValueInitExe = os.path.join(os.getenv("EDK_TOOLS_PATH"), 'Bin', 'Win32', PcdValueInitName) +".exe"
        if not os.path.exists(PcdValueInitExe) or self.NeedUpdateOutput(OutputValueFile, CAppBaseFileName + '.c',MakeFileName,InputValueFile):
            Messages = ''
            if sys.platform == "win32":
                MakeCommand = 'nmake clean & nmake -f %s' % (MakeFileName)
                returncode, StdOut, StdErr = self.ExecuteCommand (MakeCommand)
                Messages = StdOut
            else:
                MakeCommand = 'make clean & make -f %s' % (MakeFileName)
                returncode, StdOut, StdErr = self.ExecuteCommand (MakeCommand)
                Messages = StdErr
            Messages = Messages.split('\n')
            MessageGroup = []
            if returncode <>0:
                CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
                File = open (CAppBaseFileName + '.c', 'r')
                FileData = File.readlines()
                File.close()
                for Message in Messages:
                    if " error" in Message or "warning" in Message:
                        FileInfo = Message.strip().split('(')
                        if len (FileInfo) > 1:
                            FileName = FileInfo [0]
                            FileLine = FileInfo [1].split (')')[0]
                        else:
                            FileInfo = Message.strip().split(':')
                            FileName = FileInfo [0]
                            FileLine = FileInfo [1]
                        if FileLine.isdigit():
                            error_line = FileData[int (FileLine) - 1]
                            if r"//" in error_line:
                                c_line,dsc_line = error_line.split(r"//")
                            else:
                                dsc_line = error_line
                            message_itmes = Message.split(":")
                            Index = 0
                            if "PcdValueInit.c" not in Message:
                                if not MessageGroup:
                                    MessageGroup.append(Message)
                                break
                            else:
                                for item in message_itmes:
                                    if "PcdValueInit.c" in item:
                                        Index = message_itmes.index(item)
                                        message_itmes[Index] = dsc_line.strip()
                                        break
                                MessageGroup.append(":".join(message_itmes[Index:]).strip())
                                continue
                        else:
                            MessageGroup.append(Message)
                if MessageGroup:
                    EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "\n".join(MessageGroup) )
                else:
                    EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s' % MakeCommand)
            Command = PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile)
            returncode, StdOut, StdErr = self.ExecuteCommand (Command)
            if returncode <> 0:
                EdkLogger.warn('Build', COMMAND_FAILURE, 'Can not collect output from command: %s' % Command)

        File = open (OutputValueFile, 'r')
        FileBuffer = File.readlines()
        File.close()

        StructurePcdSet = []
        for Pcd in FileBuffer:
            PcdValue = Pcd.split ('|')
            PcdInfo = PcdValue[0].split ('.')
            StructurePcdSet.append((PcdInfo[0],PcdInfo[1], PcdInfo[2], PcdInfo[3], PcdValue[2].strip()))
        return StructurePcdSet

    def NeedUpdateOutput(self,OutputFile, ValueCFile, MakeFile, StructureInput):
        if not os.path.exists(OutputFile):
            return True
        if os.stat(OutputFile).st_mtime <= os.stat(ValueCFile).st_mtime:
            return True
        if os.stat(OutputFile).st_mtime <= os.stat(MakeFile).st_mtime:
            return True
        if os.stat(OutputFile).st_mtime <= os.stat(StructureInput).st_mtime:
            return True
        return False

    ## Retrieve dynamic PCD settings
    #
    #   @param  Type    PCD type
    #
    #   @retval a dict object contains settings of given PCD type
    #
    def _GetDynamicPcd(self, Type):


        Pcds = sdict()
        #
        # tdict is a special dict kind of type, used for selecting correct
        # PCD settings for certain ARCH and SKU
        #
        PcdDict = tdict(True, 4)
        PcdList = []
        # Find out all possible PCD candidates for self._Arch
        RecordList = self._RawData[Type, self._Arch]
        AvailableSkuIdSet = copy.copy(self.SkuIds)


        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4,Dummy5 in RecordList:
            SkuName = SkuName.upper()
            SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
            if SkuName not in AvailableSkuIdSet:
                EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
                                            File=self.MetaFile, Line=Dummy5)
            if "." not in TokenSpaceGuid:
                PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
            PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting

        # Remove redundant PCD candidates, per the ARCH and SKU
        for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:

            Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
            if Setting == None:
                continue

            PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
            SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', '', PcdValue)
            if (PcdCName, TokenSpaceGuid) in Pcds.keys():
                pcdObject = Pcds[PcdCName, TokenSpaceGuid]
                pcdObject.SkuInfoList[SkuName] = SkuInfo
                if MaxDatumSize.strip():
                    CurrentMaxSize = int(MaxDatumSize.strip(), 0)
                else:
                    CurrentMaxSize = 0
                if pcdObject.MaxDatumSize:
                    PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
                else:
                    PcdMaxSize = 0
                if CurrentMaxSize > PcdMaxSize:
                    pcdObject.MaxDatumSize = str(CurrentMaxSize)
            else:
                Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
                                                    PcdCName,
                                                    TokenSpaceGuid,
                                                    self._PCD_TYPE_STRING_[Type],
                                                    DatumType,
                                                    PcdValue,
                                                    '',
                                                    MaxDatumSize,
                                                    {SkuName : SkuInfo},
                                                    False,
                                                    None,
                                                    IsDsc=True)

        for pcd in Pcds.values():
            pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
            # Only fix the value while no value provided in DSC file.
            for sku in pcd.SkuInfoList.values():
                if (sku.DefaultValue == "" or sku.DefaultValue==None):
                    sku.DefaultValue = pcdDecObject.DefaultValue
            if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
                valuefromDec = pcdDecObject.DefaultValue
                SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '', '', '', valuefromDec)
                pcd.SkuInfoList['DEFAULT'] = SkuInfo
            elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
                del(pcd.SkuInfoList['COMMON'])
            elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                del(pcd.SkuInfoList['COMMON'])

        map(self.FilterSkuSettings,Pcds.values())

        return Pcds

    def FilterSkuSettings(self, PcdObj):

        if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE:
            if 'DEFAULT' in PcdObj.SkuInfoList.keys() and self.SkuIdMgr.SystemSkuId not in PcdObj.SkuInfoList.keys():
                PcdObj.SkuInfoList[self.SkuIdMgr.SystemSkuId] = PcdObj.SkuInfoList['DEFAULT']
            PcdObj.SkuInfoList = {'DEFAULT':PcdObj.SkuInfoList[self.SkuIdMgr.SystemSkuId]}
            PcdObj.SkuInfoList['DEFAULT'].SkuIdName = 'DEFAULT'
            PcdObj.SkuInfoList['DEFAULT'].SkuId = '0'

        elif self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.DEFAULT:
            PcdObj.SkuInfoList = {'DEFAULT':PcdObj.SkuInfoList['DEFAULT']}

        return PcdObj


    def CompareVarAttr(self, Attr1, Attr2):
        if not Attr1 or not Attr2:  # for empty string
            return True
        Attr1s = [attr.strip() for attr in Attr1.split(",")]
        Attr1Set = set(Attr1s)
        Attr2s = [attr.strip() for attr in Attr2.split(",")]
        Attr2Set = set(Attr2s)
        if Attr2Set == Attr1Set:
            return True
        else:
            return False
    def CopyDscRawValue(self,Pcd):
        if Pcd.DscRawValue is None:
            Pcd.DscRawValue = dict()
        if Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD], self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
            if self.SkuIdMgr.SystemSkuId not in Pcd.DscRawValue:
                Pcd.DscRawValue[self.SkuIdMgr.SystemSkuId] = {}
            Pcd.DscRawValue[self.SkuIdMgr.SystemSkuId]['STANDARD'] = Pcd.DefaultValue
        for skuname in Pcd.SkuInfoList:
            Pcd.DscRawValue[skuname] = {}
            if Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                for defaultstore in Pcd.SkuInfoList[skuname].DefaultStoreDict:
                    Pcd.DscRawValue[skuname][defaultstore] = Pcd.SkuInfoList[skuname].DefaultStoreDict[defaultstore]
            else:
                Pcd.DscRawValue[skuname]['STANDARD'] = Pcd.SkuInfoList[skuname].DefaultValue
    def CompletePcdValues(self,PcdSet):
        Pcds = {}
        DefaultStoreObj = DefaultStore(self._GetDefaultStores())
        SkuIds = {skuname:skuid for skuname,skuid in self.SkuIdMgr.AvailableSkuIdSet.items() if skuname !='COMMON'}
        DefaultStores = set([storename for pcdobj in PcdSet.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict.keys()])
        for PcdCName, TokenSpaceGuid in PcdSet:
            PcdObj = PcdSet[(PcdCName, TokenSpaceGuid)]
            self.CopyDscRawValue(PcdObj)
            if PcdObj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
                        self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]:
                Pcds[PcdCName, TokenSpaceGuid]= PcdObj
                continue
            PcdType = PcdObj.Type
            if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                for skuid in PcdObj.SkuInfoList:
                    skuobj = PcdObj.SkuInfoList[skuid]
                    mindefaultstorename = DefaultStoreObj.GetMin(set([defaultstorename  for defaultstorename in skuobj.DefaultStoreDict]))
                    for defaultstorename in DefaultStores:
                        if defaultstorename not in skuobj.DefaultStoreDict:
                            skuobj.DefaultStoreDict[defaultstorename] = copy.deepcopy(skuobj.DefaultStoreDict[mindefaultstorename])
                    skuobj.HiiDefaultValue = skuobj.DefaultStoreDict[mindefaultstorename]
            for skuname,skuid in SkuIds.items():
                if skuname not in PcdObj.SkuInfoList:
                    nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
                    while nextskuid not in PcdObj.SkuInfoList:
                        nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
                    PcdObj.SkuInfoList[skuname] = copy.deepcopy(PcdObj.SkuInfoList[nextskuid])
                    PcdObj.SkuInfoList[skuname].SkuId = skuid
                    PcdObj.SkuInfoList[skuname].SkuIdName = skuname
            if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
                PcdObj.DefaultValue = PcdObj.SkuInfoList.values()[0].HiiDefaultValue if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE else PcdObj.SkuInfoList["DEFAULT"].HiiDefaultValue
            Pcds[PcdCName, TokenSpaceGuid]= PcdObj
        return Pcds
    ## Retrieve dynamic HII PCD settings
    #
    #   @param  Type    PCD type
    #
    #   @retval a dict object contains settings of given PCD type
    #
    def _GetDynamicHiiPcd(self, Type):

        VariableAttrs = {}

        Pcds = sdict()
        #
        # tdict is a special dict kind of type, used for selecting correct
        # PCD settings for certain ARCH and SKU
        #
        PcdDict = tdict(True, 5)
        PcdSet = set()
        RecordList = self._RawData[Type, self._Arch]
        # Find out all possible PCD candidates for self._Arch
        AvailableSkuIdSet = copy.copy(self.SkuIds)
        DefaultStoresDefine = self._GetDefaultStores()

        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, DefaultStore, Dummy4,Dummy5 in RecordList:
            SkuName = SkuName.upper()
            SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
            DefaultStore = DefaultStore.upper()
            if DefaultStore == "COMMON":
                DefaultStore = "STANDARD"
            if SkuName not in AvailableSkuIdSet:
                EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
                                            File=self.MetaFile, Line=Dummy5)
            if DefaultStore not in DefaultStoresDefine:
                EdkLogger.error('build', PARAMETER_INVALID, 'DefaultStores %s is not defined in [DefaultStores] section' % DefaultStore,
                                            File=self.MetaFile, Line=Dummy5)
            if "." not in TokenSpaceGuid:
                PcdSet.add((PcdCName, TokenSpaceGuid, SkuName,DefaultStore, Dummy5))
            PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid,DefaultStore] = Setting


        # Remove redundant PCD candidates, per the ARCH and SKU
        for PcdCName, TokenSpaceGuid, SkuName,DefaultStore, Dummy4 in PcdSet:

            Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid,DefaultStore]
            if Setting == None:
                continue
            VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)

            rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute)
            if not rt:
                EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg),
                        ExtraData="[%s]" % VarAttribute)
            ExceedMax = False
            FormatCorrect = True
            if VariableOffset.isdigit():
                if int(VariableOffset, 10) > 0xFFFF:
                    ExceedMax = True
            elif re.match(r'[\t\s]*0[xX][a-fA-F0-9]+$', VariableOffset):
                if int(VariableOffset, 16) > 0xFFFF:
                    ExceedMax = True
            # For Offset written in "A.B"
            elif VariableOffset.find('.') > -1:
                VariableOffsetList = VariableOffset.split(".")
                if not (len(VariableOffsetList) == 2
                        and IsValidWord(VariableOffsetList[0])
                        and IsValidWord(VariableOffsetList[1])):
                    FormatCorrect = False
            else:
                FormatCorrect = False
            if not FormatCorrect:
                EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid, PcdCName)))

            if ExceedMax:
                EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)))
            if (VariableName, VariableGuid) not in VariableAttrs:
                VariableAttrs[(VariableName, VariableGuid)] = VarAttribute
            else:
                if not self.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute):
                    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)]))

            pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid]
            if (PcdCName, TokenSpaceGuid) in Pcds.keys():
                pcdObject = Pcds[PcdCName, TokenSpaceGuid]
                if SkuName in pcdObject.SkuInfoList:
                    Skuitem = pcdObject.SkuInfoList[SkuName]
                    Skuitem.DefaultStoreDict.update({DefaultStore:DefaultValue})
                else:
                    SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute,DefaultStore={DefaultStore:DefaultValue})
                    pcdObject.SkuInfoList[SkuName] = SkuInfo
            else:
                SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute,DefaultStore={DefaultStore:DefaultValue})
                Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
                                                PcdCName,
                                                TokenSpaceGuid,
                                                self._PCD_TYPE_STRING_[Type],
                                                '',
                                                DefaultValue,
                                                '',
                                                '',
                                                {SkuName : SkuInfo},
                                                False,
                                                None,
                                                pcdDecObject.validateranges,
                                                pcdDecObject.validlists,
                                                pcdDecObject.expressions,
                                                IsDsc=True)


        for pcd in Pcds.values():
            SkuInfoObj = pcd.SkuInfoList.values()[0]
            pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
            pcd.DatumType = pcdDecObject.DatumType
            # Only fix the value while no value provided in DSC file.
            for sku in pcd.SkuInfoList.values():
                if (sku.HiiDefaultValue == "" or sku.HiiDefaultValue == None):
                    sku.HiiDefaultValue = pcdDecObject.DefaultValue
                    for default_store in sku.DefaultStoreDict:
                        sku.DefaultStoreDict[default_store]=pcdDecObject.DefaultValue
                    pcd.DefaultValue = pcdDecObject.DefaultValue
            if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
                valuefromDec = pcdDecObject.DefaultValue
                SkuInfo = SkuInfoClass('DEFAULT', '0', SkuInfoObj.VariableName, SkuInfoObj.VariableGuid, SkuInfoObj.VariableOffset, valuefromDec,VariableAttribute=SkuInfoObj.VariableAttribute,DefaultStore={DefaultStore:valuefromDec})
                pcd.SkuInfoList['DEFAULT'] = SkuInfo
            elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
                del(pcd.SkuInfoList['COMMON'])
            elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                del(pcd.SkuInfoList['COMMON'])

            if pcd.MaxDatumSize.strip():
                MaxSize = int(pcd.MaxDatumSize, 0)
            else:
                MaxSize = 0
            if pcd.DatumType not in ['BOOLEAN','UINT8','UINT16','UINT32','UINT64']:
                for (_, skuobj) in pcd.SkuInfoList.items():
                    datalen = 0
                    skuobj.HiiDefaultValue = StringToArray(skuobj.HiiDefaultValue)
                    datalen = len(skuobj.HiiDefaultValue.split(","))
                    if datalen > MaxSize:
                        MaxSize = datalen
                    for defaultst in skuobj.DefaultStoreDict:
                        skuobj.DefaultStoreDict[defaultst] = StringToArray(skuobj.DefaultStoreDict[defaultst])
                pcd.DefaultValue = StringToArray(pcd.DefaultValue)
                pcd.MaxDatumSize = str(MaxSize)
        rt, invalidhii = self.CheckVariableNameAssignment(Pcds)
        if not rt:
            invalidpcd = ",".join(invalidhii)
            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)

        map(self.FilterSkuSettings,Pcds.values())

        return Pcds

    def CheckVariableNameAssignment(self,Pcds):
        invalidhii = []
        for pcdname in Pcds:
            pcd = Pcds[pcdname]
            varnameset = set([sku.VariableName for (skuid,sku) in pcd.SkuInfoList.items()])
            if len(varnameset) > 1:
                invalidhii.append(".".join((pcdname[1],pcdname[0])))
        if len(invalidhii):
            return False,invalidhii
        else:
            return True, []
    ## Retrieve dynamic VPD PCD settings
    #
    #   @param  Type    PCD type
    #
    #   @retval a dict object contains settings of given PCD type
    #
    def _GetDynamicVpdPcd(self, Type):


        Pcds = sdict()
        #
        # tdict is a special dict kind of type, used for selecting correct
        # PCD settings for certain ARCH and SKU
        #
        PcdDict = tdict(True, 4)
        PcdList = []

        # Find out all possible PCD candidates for self._Arch
        RecordList = self._RawData[Type, self._Arch]
        AvailableSkuIdSet = copy.copy(self.SkuIds)

        for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4,Dummy5 in RecordList:
            SkuName = SkuName.upper()
            SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName
            if SkuName not in AvailableSkuIdSet:
                EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
                                            File=self.MetaFile, Line=Dummy5)
            if "." not in TokenSpaceGuid:
                PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
            PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting

        # Remove redundant PCD candidates, per the ARCH and SKU
        for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
            Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
            if Setting == None:
                continue
            #
            # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue
            # For the Integer & Boolean type, the optional data can only be InitialValue.
            # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype
            # until the DEC parser has been called.
            #
            VpdOffset, MaxDatumSize, InitialValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
            SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', VpdOffset, InitialValue)
            if (PcdCName, TokenSpaceGuid) in Pcds.keys():
                pcdObject = Pcds[PcdCName, TokenSpaceGuid]
                pcdObject.SkuInfoList[SkuName] = SkuInfo
                if MaxDatumSize.strip():
                    CurrentMaxSize = int(MaxDatumSize.strip(), 0)
                else:
                    CurrentMaxSize = 0
                if pcdObject.MaxDatumSize:
                    PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
                else:
                    PcdMaxSize = 0
                if CurrentMaxSize > PcdMaxSize:
                    pcdObject.MaxDatumSize = str(CurrentMaxSize)
            else:
                Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
                                                PcdCName,
                                                TokenSpaceGuid,
                                                self._PCD_TYPE_STRING_[Type],
                                                '',
                                                InitialValue,
                                                '',
                                                MaxDatumSize,
                                                {SkuName : SkuInfo},
                                                False,
                                                None,
                                                IsDsc=True)
        for pcd in Pcds.values():
            SkuInfoObj = pcd.SkuInfoList.values()[0]
            pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
            pcd.DatumType = pcdDecObject.DatumType
            # Only fix the value while no value provided in DSC file.
            for sku in pcd.SkuInfoList.values():
                if (sku.DefaultValue == "" or sku.DefaultValue==None):
                    sku.DefaultValue = pcdDecObject.DefaultValue
            if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
                valuefromDec = pcdDecObject.DefaultValue
                SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '', '', SkuInfoObj.VpdOffset, valuefromDec)
                pcd.SkuInfoList['DEFAULT'] = SkuInfo
            elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
                del(pcd.SkuInfoList['COMMON'])
            elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
                del(pcd.SkuInfoList['COMMON'])


        map(self.FilterSkuSettings,Pcds.values())
        return Pcds

    ## Add external modules
    #
    #   The external modules are mostly those listed in FDF file, which don't
    # need "build".
    #
    #   @param  FilePath    The path of module description file
    #
    def AddModule(self, FilePath):
        FilePath = NormPath(FilePath)
        if FilePath not in self.Modules:
            Module = ModuleBuildClassObject()
            Module.MetaFile = FilePath
            self.Modules.append(Module)

    def _GetToolChainFamily(self):
        self._ToolChainFamily = "MSFT"
        BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, "target.txt"))
        if os.path.isfile(BuildConfigurationFile) == True:
            TargetTxt      = TargetTxtClassObject()
            TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
            ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
            if ToolDefinitionFile == '':
                ToolDefinitionFile = "tools_def.txt"
                ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))
            if os.path.isfile(ToolDefinitionFile) == True:
                ToolDef        = ToolDefClassObject()
                ToolDef.LoadToolDefFile(ToolDefinitionFile)
                ToolDefinition = ToolDef.ToolsDefTxtDatabase
                if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
                   or self._Toolchain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
                   or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self._Toolchain]:
                    self._ToolChainFamily = "MSFT"
                else:
                    self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self._Toolchain]
        return self._ToolChainFamily

    ## Add external PCDs
    #
    #   The external PCDs are mostly those listed in FDF file to specify address
    # or offset information.
    #
    #   @param  Name    Name of the PCD
    #   @param  Guid    Token space guid of the PCD
    #   @param  Value   Value of the PCD
    #
    def AddPcd(self, Name, Guid, Value):
        if (Name, Guid) not in self.Pcds:
            self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
        self.Pcds[Name, Guid].DefaultValue = Value
    @property
    def DecPcds(self):
        if self._DecPcds == None:
            FdfInfList = []
            if GlobalData.gFdfParser:
                FdfInfList = GlobalData.gFdfParser.Profile.InfList
            PkgSet = set()
            for Inf in FdfInfList:
                ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
                if ModuleFile in self._Modules:
                    continue
                ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
                PkgSet.update(ModuleData.Packages)
            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
        return self._DecPcds
    _Macros             = property(_GetMacros)
    Arch                = property(_GetArch, _SetArch)
    Platform            = property(_GetPlatformName)
    PlatformName        = property(_GetPlatformName)
    Guid                = property(_GetFileGuid)
    Version             = property(_GetVersion)
    DscSpecification    = property(_GetDscSpec)
    OutputDirectory     = property(_GetOutpuDir)
    SupArchList         = property(_GetSupArch)
    BuildTargets        = property(_GetBuildTarget)
    SkuName             = property(_GetSkuName, _SetSkuName)
    PcdInfoFlag         = property(_GetPcdInfoFlag)
    VarCheckFlag        = property(_GetVarCheckFlag)
    FlashDefinition     = property(_GetFdfFile)
    Prebuild            = property(_GetPrebuild)
    Postbuild           = property(_GetPostbuild)
    BuildNumber         = property(_GetBuildNumber)
    MakefileName        = property(_GetMakefileName)
    BsBaseAddress       = property(_GetBsBaseAddress)
    RtBaseAddress       = property(_GetRtBaseAddress)
    LoadFixAddress      = property(_GetLoadFixAddress)
    RFCLanguages        = property(_GetRFCLanguages)
    ISOLanguages        = property(_GetISOLanguages)
    VpdToolGuid         = property(_GetVpdToolGuid)
    SkuIds              = property(_GetSkuIds)
    Modules             = property(_GetModules)
    LibraryInstances    = property(_GetLibraryInstances)
    LibraryClasses      = property(_GetLibraryClasses)
    Pcds                = property(_GetPcds)
    BuildOptions        = property(_GetBuildOptions)
    ToolChainFamily     = property(_GetToolChainFamily)