]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Workspace/MetaFileParser.py
Sync BaseTool trunk (version r2601) into EDKII BaseTools.
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
index d907b11ba11ac07053fe9c1688deee8eeb1ddf64..34000b5e8829d76b90e22c3ebe4c752f45a162f7 100644 (file)
@@ -1,7 +1,7 @@
 ## @file
 # This file is used to parse meta files
 #
-# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<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
@@ -25,7 +25,7 @@ import Common.GlobalData as GlobalData
 from CommonDataClass.DataClass import *
 from Common.DataType import *
 from Common.String import *
-from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData
+from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd
 from Common.Expression import *
 from CommonDataClass.Exceptions import *
 
@@ -44,7 +44,7 @@ def ParseMacro(Parser):
         # Syntax check
         if not TokenList[0]:
             EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         if len(TokenList) < 2:
             TokenList.append('')
 
@@ -53,34 +53,46 @@ def ParseMacro(Parser):
         # Global macros can be only defined via environment variable
         if Name in GlobalData.gGlobalDefines:
             EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         # Only upper case letters, digit and '_' are allowed
         if not gMacroNamePattern.match(Name):
             EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
 
-        self._ItemType = self.DataType[Type]
+        Value = ReplaceMacro(Value, self._Macros)
+        if Type in self.DataType:
+            self._ItemType = self.DataType[Type]
+        else:
+            self._ItemType = MODEL_META_DATA_DEFINE
         # DEFINE defined macros
-        if self._ItemType == MODEL_META_DATA_DEFINE:
-            if self._SectionType == MODEL_META_DATA_HEADER:
-                self._FileLocalMacros[Name] = Value
+        if Type == TAB_DSC_DEFINES_DEFINE:
+            #
+            # First judge whether this DEFINE is in conditional directive statements or not.
+            #
+            if type(self) == DscParser and self._InDirective > -1:
+                pass
             else:
-                SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
-                if SectionDictKey not in self._SectionsMacroDict:
-                    self._SectionsMacroDict[SectionDictKey] = {}
-                SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
-                SectionLocalMacros[Name] = Value
+                if type(self) == DecParser:
+                    if MODEL_META_DATA_HEADER in self._SectionType:
+                        self._FileLocalMacros[Name] = Value
+                    else:
+                        self._ConstructSectionMacroDict(Name, Value)
+                elif self._SectionType == MODEL_META_DATA_HEADER:
+                    self._FileLocalMacros[Name] = Value
+                else:
+                    self._ConstructSectionMacroDict(Name, Value)
+
         # EDK_GLOBAL defined macros
         elif type(self) != DscParser:
             EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         elif self._SectionType != MODEL_META_DATA_HEADER:
             EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
             EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-            
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
         self._ValueList = [Type, Name, Value]
 
     return MacroParser
@@ -134,7 +146,7 @@ class MetaFileParser(object):
     #   @param      Owner           Owner ID (for sub-section parsing)
     #   @param      From            ID from which the data comes (for !INCLUDE directive)
     #
-    def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
+    def __init__(self, FilePath, FileType, Table, Owner= -1, From= -1):
         self._Table = Table
         self._RawTable = Table
         self._FileType = FileType
@@ -250,7 +262,7 @@ class MetaFileParser(object):
     ## Skip unsupported data
     def _Skip(self):
         EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
-                        Line=self._LineIndex+1, ExtraData=self._CurrentLine);
+                        Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
         self._ValueList[0:1] = [self._CurrentLine]
 
     ## Section header parser
@@ -270,20 +282,27 @@ class MetaFileParser(object):
             # different section should not mix in one section
             if self._SectionName != '' and self._SectionName != ItemList[0].upper():
                 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
-                                File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
+                                File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
             self._SectionName = ItemList[0].upper()
             if self._SectionName in self.DataType:
                 self._SectionType = self.DataType[self._SectionName]
+                # Check if the section name is valid
+                if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH and len(ItemList) > 2:
+                    EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
+                                    self.MetaFile, self._LineIndex + 1, self._CurrentLine)
+            elif self._Version >= 0x00010005:
+                EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
+                                self.MetaFile, self._LineIndex + 1, self._CurrentLine)
             else:
                 self._SectionType = MODEL_UNKNOWN
-                EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
-                                Line=self._LineIndex+1, ExtraData=self._CurrentLine)
+
             # S1 is always Arch
             if len(ItemList) > 1:
                 S1 = ItemList[1].upper()
             else:
                 S1 = 'COMMON'
             ArchList.add(S1)
+
             # S2 may be Platform or ModuleType
             if len(ItemList) > 2:
                 S2 = ItemList[2].upper()
@@ -294,7 +313,7 @@ class MetaFileParser(object):
         # 'COMMON' must not be used with specific ARCHs at the same section
         if 'COMMON' in ArchList and len(ArchList) > 1:
             EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
-                            File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
+                            File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
         # If the section information is needed later, it should be stored in database
         self._ValueList[0] = self._SectionName
 
@@ -305,11 +324,12 @@ class MetaFileParser(object):
         self._ValueList[1:len(TokenList)] = TokenList
         if not self._ValueList[1]:
             EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         if not self._ValueList[2]:
             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
 
+        self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
         Name, Value = self._ValueList[1], self._ValueList[2]
         # Sometimes, we need to make differences between EDK and EDK2 modules 
         if Name == 'INF_VERSION':
@@ -317,9 +337,8 @@ class MetaFileParser(object):
                 self._Version = int(Value, 0)
             except:
                 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
-                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
 
-        Value = ReplaceMacro(Value, self._Macros)
         if type(self) == InfParser and self._Version < 0x00010005:
             # EDK module allows using defines as macros
             self._FileLocalMacros[Name] = Value
@@ -328,6 +347,7 @@ class MetaFileParser(object):
     ## [BuildOptions] section parser
     @ParseMacro
     def _BuildOptionParser(self):
+        self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
         if len(TokenList2) == 2:
@@ -345,7 +365,7 @@ class MetaFileParser(object):
                 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
                 ExtraData=self._CurrentLine,
                 File=self.MetaFile,
-                Line=self._LineIndex+1
+                Line=self._LineIndex + 1
                 )
 
     def _GetMacros(self):
@@ -354,21 +374,65 @@ class MetaFileParser(object):
         Macros.update(self._GetApplicableSectionMacro())
         return Macros
 
+    ## Construct section Macro dict 
+    def _ConstructSectionMacroDict(self, Name, Value):
+        ScopeKey = [(Scope[0], Scope[1]) for Scope in self._Scope]
+        ScopeKey = tuple(ScopeKey)
+        SectionDictKey = self._SectionType, ScopeKey
+        #
+        # DecParser SectionType is a list, will contain more than one item only in Pcd Section
+        # As Pcd section macro usage is not alllowed, so here it is safe
+        #
+        if type(self) == DecParser:
+            SectionDictKey = self._SectionType[0], ScopeKey
+        if SectionDictKey not in self._SectionsMacroDict:
+            self._SectionsMacroDict[SectionDictKey] = {}
+        SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
+        SectionLocalMacros[Name] = Value
 
     ## Get section Macros that are applicable to current line, which may come from other sections 
     ## that share the same name while scope is wider
     def _GetApplicableSectionMacro(self):
         Macros = {}
 
-        for SectionType, Scope1, Scope2 in self._SectionsMacroDict:
-            if (SectionType == self._SectionType) and (Scope1 == self._Scope[0][0] or Scope1 == "COMMON") and (Scope2 == self._Scope[0][1] or Scope2 == "COMMON"):
-                Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])
+        ComComMacroDict = {}
+        ComSpeMacroDict = {}
+        SpeSpeMacroDict = {}
+
+        ActiveSectionType = self._SectionType
+        if type(self) == DecParser:
+            ActiveSectionType = self._SectionType[0]
+
+        for (SectionType, Scope) in self._SectionsMacroDict:
+            if SectionType != ActiveSectionType:
+                continue
+
+            for ActiveScope in self._Scope:
+                Scope0, Scope1 = ActiveScope[0], ActiveScope[1]
+                if(Scope0, Scope1) not in Scope:
+                    break
+            else:
+                SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
+
+            for ActiveScope in self._Scope:
+                Scope0, Scope1 = ActiveScope[0], ActiveScope[1]
+                if(Scope0, Scope1) not in Scope and (Scope0, "COMMON") not in Scope and ("COMMON", Scope1) not in Scope:
+                    break
+            else:
+                ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
+
+            if ("COMMON", "COMMON") in Scope:
+                ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
+
+        Macros.update(ComComMacroDict)
+        Macros.update(ComSpeMacroDict)
+        Macros.update(SpeSpeMacroDict)
 
         return Macros
 
-    _SectionParser  = {}
-    Finished        = property(_GetFinished, _SetFinished)
-    _Macros         = property(_GetMacros)
+    _SectionParser = {}
+    Finished = property(_GetFinished, _SetFinished)
+    _Macros = property(_GetMacros)
 
 
 ## INF file parser class
@@ -418,6 +482,7 @@ class InfParser(MetaFileParser):
         if hasattr(self, "_Table"):
             return
         MetaFileParser.__init__(self, FilePath, FileType, Table)
+        self.PcdsDict = {}
 
     ## Parser starter
     def Start(self):
@@ -470,13 +535,13 @@ class InfParser(MetaFileParser):
                                              MODEL_META_DATA_USER_EXTENSION]:
                         EdkLogger.error('Parser', FORMAT_INVALID,
                                         "Section [%s] is not allowed in inf file without version" % (self._SectionName),
-                                        ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                                        ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
                 elif self._SectionType in [MODEL_EFI_INCLUDE,
                                            MODEL_EFI_LIBRARY_INSTANCE,
                                            MODEL_META_DATA_NMAKE]:
                     EdkLogger.error('Parser', FORMAT_INVALID,
                                     "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
-                                    ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                                    ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
                 continue
             # merge two lines specified by '\' in section NMAKE
             elif self._SectionType == MODEL_META_DATA_NMAKE:
@@ -496,10 +561,11 @@ class InfParser(MetaFileParser):
                     NmakeLine = ''
 
             # section content
-            self._ValueList = ['','','']
+            self._ValueList = ['', '', '']
             # parse current line, result will be put in self._ValueList
             self._SectionParser[self._SectionType](self)
-            if self._ValueList == None:
+            if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
+                self._ItemType = -1
                 continue
             #
             # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
@@ -513,14 +579,14 @@ class InfParser(MetaFileParser):
                             Arch,
                             Platform,
                             self._Owner[-1],
-                            self._LineIndex+1,
-                            -1,
-                            self._LineIndex+1,
-                            -1,
+                            self._LineIndex + 1,
+                            - 1,
+                            self._LineIndex + 1,
+                            - 1,
                             0
                             )
         if IsFindBlockComment:
-            EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */", 
+            EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
                             File=self.MetaFile)
         self._Done()
 
@@ -578,15 +644,15 @@ class InfParser(MetaFileParser):
         if len(TokenList) < 2:
             EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if not TokenList[0]:
             EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if not TokenList[1]:
             EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
                             ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         self._ValueList[0:len(TokenList)] = TokenList
         self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
 
@@ -607,14 +673,14 @@ class InfParser(MetaFileParser):
         if len(ValueList) != 2:
             EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         self._ValueList[0:1] = ValueList
         if len(TokenList) > 1:
             self._ValueList[2] = TokenList[1]
         if self._ValueList[0] == '' or self._ValueList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
 
         # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
         if self._ValueList[2] != '':
@@ -623,6 +689,12 @@ class InfParser(MetaFileParser):
                 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
             elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
                 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
+        if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
+            self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
+        elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
+            EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
+                            ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
+                            File=self.MetaFile, Line=self._LineIndex + 1)
 
     ## [depex] section parser
     @ParseMacro
@@ -633,11 +705,11 @@ class InfParser(MetaFileParser):
         MODEL_UNKNOWN                   :   MetaFileParser._Skip,
         MODEL_META_DATA_HEADER          :   MetaFileParser._DefineParser,
         MODEL_META_DATA_BUILD_OPTION    :   MetaFileParser._BuildOptionParser,
-        MODEL_EFI_INCLUDE               :   _IncludeParser,                 # for Edk.x modules
-        MODEL_EFI_LIBRARY_INSTANCE      :   MetaFileParser._CommonParser,   # for Edk.x modules
+        MODEL_EFI_INCLUDE               :   _IncludeParser, # for Edk.x modules
+        MODEL_EFI_LIBRARY_INSTANCE      :   MetaFileParser._CommonParser, # for Edk.x modules
         MODEL_EFI_LIBRARY_CLASS         :   MetaFileParser._PathParser,
         MODEL_META_DATA_PACKAGE         :   MetaFileParser._PathParser,
-        MODEL_META_DATA_NMAKE           :   _NmakeParser,                   # for Edk.x modules
+        MODEL_META_DATA_NMAKE           :   _NmakeParser, # for Edk.x modules
         MODEL_PCD_FIXED_AT_BUILD        :   _PcdParser,
         MODEL_PCD_PATCHABLE_IN_MODULE   :   _PcdParser,
         MODEL_PCD_FEATURE_FLAG          :   _PcdParser,
@@ -723,7 +795,7 @@ class DscParser(MetaFileParser):
     #   @param      Owner           Owner ID (for sub-section parsing)
     #   @param      From            ID from which the data comes (for !INCLUDE directive)
     #
-    def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
+    def __init__(self, FilePath, FileType, Table, Owner= -1, From= -1):
         # prevent re-initialization
         if hasattr(self, "_Table"):
             return
@@ -734,6 +806,11 @@ class DscParser(MetaFileParser):
         self._DirectiveEvalStack = []
         self._Enabled = 1
 
+        #
+        # Specify whether current line is in uncertain condition
+        #
+        self._InDirective = -1
+
         # Final valid replacable symbols
         self._Symbols = {}
         #
@@ -750,6 +827,7 @@ class DscParser(MetaFileParser):
         except:
             EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
 
+        OwnerId = {}
         for Index in range(0, len(Content)):
             Line = CleanString(Content[Index])
             # skip empty line
@@ -760,7 +838,7 @@ class DscParser(MetaFileParser):
             self._LineIndex = Index
             if self._InSubsection and self._Owner[-1] == -1:
                 self._Owner.append(self._LastItem)
-            
+
             # section header
             if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
                 self._SectionType = MODEL_META_DATA_SECTION_HEADER
@@ -770,6 +848,7 @@ class DscParser(MetaFileParser):
                 self._SubsectionType = MODEL_UNKNOWN
                 self._SubsectionName = ''
                 self._Owner[-1] = -1
+                OwnerId = {}
                 continue
             # subsection header
             elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
@@ -794,6 +873,9 @@ class DscParser(MetaFileParser):
             # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
             #
             for Arch, ModuleType in self._Scope:
+                Owner = self._Owner[-1]
+                if self._SubsectionType != MODEL_UNKNOWN:
+                    Owner = OwnerId[Arch]
                 self._LastItem = self._Store(
                                         self._ItemType,
                                         self._ValueList[0],
@@ -801,14 +883,16 @@ class DscParser(MetaFileParser):
                                         self._ValueList[2],
                                         Arch,
                                         ModuleType,
-                                        self._Owner[-1],
+                                        Owner,
                                         self._From,
-                                        self._LineIndex+1,
-                                        -1,
-                                        self._LineIndex+1,
-                                        -1,
+                                        self._LineIndex + 1,
+                                        - 1,
+                                        self._LineIndex + 1,
+                                        - 1,
                                         self._Enabled
                                         )
+                if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
+                    OwnerId[Arch] = self._LastItem
 
         if self._DirectiveStack:
             Type, Line, Text = self._DirectiveStack[-1]
@@ -824,12 +908,12 @@ class DscParser(MetaFileParser):
         else:
             self._SubsectionType = MODEL_UNKNOWN
             EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
-                           Line=self._LineIndex+1, ExtraData=self._CurrentLine)
+                           Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
         self._ValueList[0] = self._SubsectionName
 
     ## Directive statement parser
     def _DirectiveParser(self):
-        self._ValueList = ['','','']
+        self._ValueList = ['', '', '']
         TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
         self._ValueList[0:len(TokenList)] = TokenList
 
@@ -837,13 +921,23 @@ class DscParser(MetaFileParser):
         DirectiveName = self._ValueList[0].upper()
         if DirectiveName not in self.DataType:
             EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
+
+        if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
+            self._InDirective += 1
+
+        if DirectiveName in ['!ENDIF']:
+            self._InDirective -= 1
+
         if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
             EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
-                            File=self.MetaFile, Line=self._LineIndex+1,
+                            File=self.MetaFile, Line=self._LineIndex + 1,
                             ExtraData=self._CurrentLine)
 
         ItemType = self.DataType[DirectiveName]
+        Scope = [['COMMON', 'COMMON']]
+        if ItemType == MODEL_META_DATA_INCLUDE:
+            Scope = self._Scope
         if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
             # Remove all directives between !if and !endif, including themselves
             while self._DirectiveStack:
@@ -855,7 +949,7 @@ class DscParser(MetaFileParser):
                     break
             else:
                 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
-                                File=self.MetaFile, Line=self._LineIndex+1,
+                                File=self.MetaFile, Line=self._LineIndex + 1,
                                 ExtraData=self._CurrentLine)
         elif ItemType != MODEL_META_DATA_INCLUDE:
             # Break if there's a !else is followed by a !elseif
@@ -863,34 +957,35 @@ class DscParser(MetaFileParser):
                self._DirectiveStack and \
                self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
                 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
-                                File=self.MetaFile, Line=self._LineIndex+1,
+                                File=self.MetaFile, Line=self._LineIndex + 1,
                                 ExtraData=self._CurrentLine)
-            self._DirectiveStack.append((ItemType, self._LineIndex+1, self._CurrentLine))
+            self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
         elif self._From > 0:
             EdkLogger.error('Parser', FORMAT_INVALID,
                             "No '!include' allowed in included file",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, 
-                            Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile,
+                            Line=self._LineIndex + 1)
 
         #
         # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
         # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
         #
-        self._LastItem = self._Store(
-                                ItemType,
-                                self._ValueList[0],
-                                self._ValueList[1],
-                                self._ValueList[2],
-                                'COMMON',
-                                'COMMON',
-                                self._Owner[-1],
-                                self._From,
-                                self._LineIndex+1,
-                                -1,
-                                self._LineIndex+1,
-                                -1,
-                                0
-                                )
+        for Arch, ModuleType in Scope:
+            self._LastItem = self._Store(
+                                    ItemType,
+                                    self._ValueList[0],
+                                    self._ValueList[1],
+                                    self._ValueList[2],
+                                    Arch,
+                                    ModuleType,
+                                    self._Owner[-1],
+                                    self._From,
+                                    self._LineIndex + 1,
+                                    - 1,
+                                    self._LineIndex + 1,
+                                    - 1,
+                                    0
+                                    )
 
     ## [defines] section parser
     @ParseMacro
@@ -901,16 +996,16 @@ class DscParser(MetaFileParser):
         # Syntax check
         if not self._ValueList[1]:
             EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         if not self._ValueList[2]:
             EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         if not self._ValueList[1] in self.DefineKeywords:
             EdkLogger.error('Parser', FORMAT_INVALID,
                             "Unknown keyword found: %s. "
                             "If this is a macro you must "
                             "add it as a DEFINE in the DSC" % self._ValueList[1],
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         self._Defines[self._ValueList[1]] = self._ValueList[2]
         self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
 
@@ -919,10 +1014,11 @@ class DscParser(MetaFileParser):
         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
         if len(TokenList) != 2:
             EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
-                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
         self._ValueList[0:len(TokenList)] = TokenList
 
     ## Parse Edk style of library modules
+    @ParseMacro
     def _LibraryInstanceParser(self):
         self._ValueList[0] = self._CurrentLine
 
@@ -949,11 +1045,24 @@ class DscParser(MetaFileParser):
         if self._ValueList[0] == '' or self._ValueList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if self._ValueList[2] == '':
+            #
+            # The PCD values are optional for FIXEDATBUILD and PATCHABLEINMODULE
+            #
+            if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
+                return
             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
                             ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
+
+        # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
+        ValueList = GetSplitValueList(self._ValueList[2])
+        if len(ValueList) > 1 and ValueList[1] != TAB_VOID \
+                              and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
+            EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
         # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
         DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
         if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
@@ -961,6 +1070,7 @@ class DscParser(MetaFileParser):
         elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
             self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
 
+
     ## [components] section parser
     @ParseMacro
     def _ComponentParser(self):
@@ -977,15 +1087,15 @@ class DscParser(MetaFileParser):
         if len(TokenList) < 2:
             EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if TokenList[0] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if TokenList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
                             ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
 
         self._ValueList[0:len(TokenList)] = TokenList
 
@@ -995,6 +1105,7 @@ class DscParser(MetaFileParser):
     ## [BuildOptions] section parser
     @ParseMacro
     def _BuildOptionParser(self):
+        self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
         TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
         TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
         if len(TokenList2) == 2:
@@ -1012,7 +1123,7 @@ class DscParser(MetaFileParser):
                 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
                 ExtraData=self._CurrentLine,
                 File=self.MetaFile,
-                Line=self._LineIndex+1
+                Line=self._LineIndex + 1
                 )
 
     ## Override parent's method since we'll do all macro replacements in parser
@@ -1084,6 +1195,21 @@ class DscParser(MetaFileParser):
             self._ContentIndex += 1
 
             self._Scope = [[S1, S2]]
+            #
+            # For !include directive, handle it specially,
+            # merge arch and module type in case of duplicate items
+            #
+            while self._ItemType == MODEL_META_DATA_INCLUDE:
+                if self._ContentIndex >= len(self._Content):
+                    break
+                Record = self._Content[self._ContentIndex]
+                if LineStart == Record[9] and LineEnd == Record[11]:
+                    if [Record[5], Record[6]] not in self._Scope:
+                        self._Scope.append([Record[5], Record[6]])
+                    self._ContentIndex += 1
+                else:
+                    break
+
             self._LineIndex = LineStart - 1
             self._ValueList = [V1, V2, V3]
 
@@ -1094,16 +1220,30 @@ class DscParser(MetaFileParser):
                 # Only catch expression evaluation error here. We need to report
                 # the precise number of line on which the error occurred
                 #
-                EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
-                                File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
-                                Line=self._LineIndex+1)
+                if hasattr(Excpt, 'Pcd'):
+                    if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
+                        Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
+                        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, and it is currently defined in this section:"
+                                        " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
+                                    File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+                                    Line=self._LineIndex + 1)
+                    else:
+                        EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
+                                    File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+                                    Line=self._LineIndex + 1)
+                else:
+                    EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
+                                    File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+                                    Line=self._LineIndex + 1)
             except MacroException, Excpt:
                 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
-                                File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
-                                Line=self._LineIndex+1)
+                                File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+                                Line=self._LineIndex + 1)
 
             if self._ValueList == None:
-                continue 
+                continue
 
             NewOwner = self._IdMapping.get(Owner, -1)
             self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
@@ -1116,10 +1256,10 @@ class DscParser(MetaFileParser):
                                 S2,
                                 NewOwner,
                                 self._From,
-                                self._LineIndex+1,
-                                -1,
-                                self._LineIndex+1,
-                                -1,
+                                self._LineIndex + 1,
+                                - 1,
+                                self._LineIndex + 1,
+                                - 1,
                                 self._Enabled
                                 )
             self._IdMapping[Id] = self._LastItem
@@ -1143,31 +1283,31 @@ class DscParser(MetaFileParser):
             self._SubsectionType = MODEL_UNKNOWN
 
     def __RetrievePcdValue(self):
-        Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)
-        for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
-            Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
-            # Only use PCD whose value is straitforward (no macro and PCD)
-            if self.SymbolPattern.findall(Value):
-                continue
+        Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem= -1.0)
+        for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
+            Name = TokenSpaceGuid + '.' + PcdName
+            ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FEATURE_FLAG)
+            self._Symbols[Name] = ValList[Index]
+
+        Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem= -1.0)
+        for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
             Name = TokenSpaceGuid + '.' + PcdName
-            # Don't use PCD with different values.
-            if Name in self._Symbols and self._Symbols[Name] != Value:
-                self._Symbols.pop(Name)
-                continue 
-            self._Symbols[Name] = Value
-
-        Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)
-        for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
-            Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
-            # Only use PCD whose value is straitforward (no macro and PCD)
-            if self.SymbolPattern.findall(Value):
-                continue 
-            Name = TokenSpaceGuid+'.'+PcdName
-            # Don't use PCD with different values.
-            if Name in self._Symbols and self._Symbols[Name] != Value:
-                self._Symbols.pop(Name)
-                continue 
-            self._Symbols[Name] = Value
+            ValList, Valid, Index = AnalyzeDscPcd(Value, MODEL_PCD_FIXED_AT_BUILD)
+            self._Symbols[Name] = ValList[Index]
+
+        Content = open(str(self.MetaFile), 'r').readlines()
+        GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
+        for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
+                        MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
+                        MODEL_PCD_DYNAMIC_EX_VPD):
+            Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
+            for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, ID, Line in Records:
+                Name = TokenSpaceGuid + '.' + PcdName
+                if Name not in GlobalData.gPlatformOtherPcds:
+                    PcdLine = Line
+                    while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
+                        Line -= 1
+                    GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
 
     def __ProcessDefine(self):
         if not self._Enabled:
@@ -1179,20 +1319,16 @@ class DscParser(MetaFileParser):
             if self._SectionType == MODEL_META_DATA_HEADER:
                 self._FileLocalMacros[Name] = Value
             else:
-                SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
-                if SectionDictKey not in self._SectionsMacroDict:
-                    self._SectionsMacroDict[SectionDictKey] = {}
-                SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
-                SectionLocalMacros[Name] = Value
+                self._ConstructSectionMacroDict(Name, Value)
         elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
             GlobalData.gEdkGlobal[Name] = Value
-        
+
         #
         # Keyword in [Defines] section can be used as Macros
         #
         if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
             self._FileLocalMacros[Name] = Value
-            
+
         self._ValueList = [Type, Name, Value]
 
     def __ProcessDirective(self):
@@ -1212,8 +1348,8 @@ class DscParser(MetaFileParser):
                 # the precise number of line and return the evaluation result
                 #
                 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
-                                File=self._FileWithError, ExtraData=' '.join(self._ValueList), 
-                                Line=self._LineIndex+1)
+                                File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+                                Line=self._LineIndex + 1)
                 Result = Excpt.result
 
         if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
@@ -1234,8 +1370,9 @@ class DscParser(MetaFileParser):
             self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
             self._DirectiveEvalStack.append(bool(Result))
         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
-            self._DirectiveStack[-1] = self._ItemType
+            self._DirectiveStack.append(self._ItemType)
             self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
+            self._DirectiveEvalStack.append(True)
         elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
             # Back to the nearest !if/!ifdef/!ifndef
             while self._DirectiveStack:
@@ -1243,7 +1380,6 @@ class DscParser(MetaFileParser):
                 Directive = self._DirectiveStack.pop()
                 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
                                  MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
-                                 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
                                  MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
                     break
         elif self._ItemType == MODEL_META_DATA_INCLUDE:
@@ -1267,7 +1403,7 @@ class DscParser(MetaFileParser):
             # Allow using MACROs comes from [Defines] section to keep compatible. 
             #
             __IncludeMacros.update(self._Macros)
-            
+
             IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
             #
             # First search the include file under the same directory as DSC file
@@ -1281,14 +1417,14 @@ class DscParser(MetaFileParser):
                 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
                 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
                 if ErrorCode != 0:
-                    EdkLogger.error('parser', ErrorCode, File=self._FileWithError, 
-                                    Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2)
+                    EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
+                                    Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
 
             self._FileWithError = IncludedFile1
 
             IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, False)
-            Owner = self._Content[self._ContentIndex-1][0]
-            Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable, 
+            Owner = self._Content[self._ContentIndex - 1][0]
+            Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,
                                Owner=Owner, From=Owner)
 
             # set the parser status with current status
@@ -1302,17 +1438,17 @@ class DscParser(MetaFileParser):
             # update current status with sub-parser's status
             self._SectionName = Parser._SectionName
             self._SectionType = Parser._SectionType
-            self._Scope       = Parser._Scope
-            self._Enabled     = Parser._Enabled
+            self._Scope = Parser._Scope
+            self._Enabled = Parser._Enabled
 
             # Insert all records in the table for the included file into dsc file table
             Records = IncludedFileTable.GetAll()
             if Records:
                 self._Content[self._ContentIndex:self._ContentIndex] = Records
-                self._Content.pop(self._ContentIndex-1)
+                self._Content.pop(self._ContentIndex - 1)
                 self._ValueList = None
                 self._ContentIndex -= 1
-                
+
     def __ProcessSkuId(self):
         self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
                            for Value in self._ValueList]
@@ -1324,15 +1460,28 @@ class DscParser(MetaFileParser):
         self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
 
     def __ProcessPcd(self):
-        ValueList = GetSplitValueList(self._ValueList[2])
-        if len(ValueList) > 1 and ValueList[1] == 'VOID*':
-            PcdValue = ValueList[0]
-            ValueList[0] = ReplaceMacro(PcdValue, self._Macros)
-        else:
-            PcdValue = ValueList[-1]
-            ValueList[-1] = ReplaceMacro(PcdValue, self._Macros)
+        if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
+            self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
+            return
+
+        ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
+        if not Valid:
+            EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex+1,
+                            ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
+        PcdValue = ValList[Index]
+        if PcdValue:
+            try:
+                ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
+            except WrnExpression, Value:
+                ValList[Index] = Value.result
 
-        self._ValueList[2] = '|'.join(ValueList)
+        if ValList[Index] == 'True':
+            ValList[Index] = '1'
+        if ValList[Index] == 'False':
+            ValList[Index] = '0'
+
+        GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
+        self._ValueList[2] = '|'.join(ValList)
 
     def __ProcessComponent(self):
         self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
@@ -1367,7 +1516,7 @@ class DscParser(MetaFileParser):
         MODEL_META_DATA_SUBSECTION_HEADER               :   _SubsectionHeaderParser,
     }
 
-    _Macros     = property(_GetMacros)
+    _Macros = property(_GetMacros)
 
 ## DEC file parser class
 #
@@ -1380,6 +1529,7 @@ class DecParser(MetaFileParser):
     # DEC file supported data types (one type per section)
     DataType = {
         TAB_DEC_DEFINES.upper()                     :   MODEL_META_DATA_HEADER,
+        TAB_DSC_DEFINES_DEFINE                      :   MODEL_META_DATA_DEFINE,
         TAB_INCLUDES.upper()                        :   MODEL_EFI_INCLUDE,
         TAB_LIBRARY_CLASSES.upper()                 :   MODEL_EFI_LIBRARY_CLASS,
         TAB_GUIDS.upper()                           :   MODEL_EFI_GUID,
@@ -1408,6 +1558,7 @@ class DecParser(MetaFileParser):
         MetaFileParser.__init__(self, FilePath, FileType, Table, -1)
         self._Comments = []
         self._Version = 0x00010005  # Only EDK2 dec file is supported
+        self._AllPCDs = [] # Only for check duplicate PCD
 
     ## Parser starter
     def Start(self):
@@ -1424,7 +1575,7 @@ class DecParser(MetaFileParser):
 
             # save comment for later use
             if Comment:
-                self._Comments.append((Comment, self._LineIndex+1))
+                self._Comments.append((Comment, self._LineIndex + 1))
             # skip empty line
             if Line == '':
                 continue
@@ -1439,9 +1590,10 @@ class DecParser(MetaFileParser):
                 continue
 
             # section content
-            self._ValueList = ['','','']
+            self._ValueList = ['', '', '']
             self._SectionParser[self._SectionType[0]](self)
-            if self._ValueList == None:
+            if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
+                self._ItemType = -1
                 self._Comments = []
                 continue
 
@@ -1458,10 +1610,10 @@ class DecParser(MetaFileParser):
                     Arch,
                     ModuleType,
                     self._Owner[-1],
-                    self._LineIndex+1,
-                    -1,
-                    self._LineIndex+1,
-                    -1,
+                    self._LineIndex + 1,
+                    - 1,
+                    self._LineIndex + 1,
+                    - 1,
                     0
                     )
                 for Comment, LineNo in self._Comments:
@@ -1474,14 +1626,15 @@ class DecParser(MetaFileParser):
                         ModuleType,
                         self._LastItem,
                         LineNo,
-                        -1,
+                        - 1,
                         LineNo,
-                        -1,
+                        - 1,
                         0
                         )
             self._Comments = []
         self._Done()
 
+
     ## Section header parser
     #
     #   The section header is always in following format:
@@ -1493,10 +1646,13 @@ class DecParser(MetaFileParser):
         self._SectionName = ''
         self._SectionType = []
         ArchList = set()
-        for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
+        Line = self._CurrentLine.replace("%s%s" % (TAB_COMMA_SPLIT, TAB_SPACE_SPLIT), TAB_COMMA_SPLIT)
+        for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
             if Item == '':
-                continue
-            ItemList = GetSplitValueList(Item, TAB_SPLIT)
+                EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
+                                "section name can NOT be empty or incorrectly use separator comma",
+                                self.MetaFile, self._LineIndex + 1, self._CurrentLine)
+            ItemList = Item.split(TAB_SPLIT)
 
             # different types of PCD are permissible in one section
             self._SectionName = ItemList[0].upper()
@@ -1504,9 +1660,8 @@ class DecParser(MetaFileParser):
                 if self.DataType[self._SectionName] not in self._SectionType:
                     self._SectionType.append(self.DataType[self._SectionName])
             else:
-                EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
-                                Line=self._LineIndex+1, ExtraData=self._CurrentLine)
-                continue
+                EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
+                                self.MetaFile, self._LineIndex + 1, self._CurrentLine)
 
             if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
                 EdkLogger.error(
@@ -1514,7 +1669,7 @@ class DecParser(MetaFileParser):
                             FORMAT_INVALID,
                             "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
                             File=self.MetaFile,
-                            Line=self._LineIndex+1,
+                            Line=self._LineIndex + 1,
                             ExtraData=self._CurrentLine
                             )
             # S1 is always Arch
@@ -1534,7 +1689,7 @@ class DecParser(MetaFileParser):
         # 'COMMON' must not be used with specific ARCHs at the same section
         if 'COMMON' in ArchList and len(ArchList) > 1:
             EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
-                            File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
+                            File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
 
     ## [guids], [ppis] and [protocols] section parser
     @ParseMacro
@@ -1543,20 +1698,20 @@ class DecParser(MetaFileParser):
         if len(TokenList) < 2:
             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if TokenList[0] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if TokenList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
                             ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
                             ExtraData=self._CurrentLine + \
                                       " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         self._ValueList[0] = TokenList[0]
         self._ValueList[1] = TokenList[1]
 
@@ -1572,67 +1727,88 @@ class DecParser(MetaFileParser):
     def _PcdParser(self):
         TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
         self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
+        ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
         # check PCD information
         if self._ValueList[0] == '' or self._ValueList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
                             ExtraData=self._CurrentLine + \
                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
+        # check format of token space GUID CName
+        if not ValueRe.match(self._ValueList[0]):
+            EdkLogger.error('Parser', FORMAT_INVALID, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
+                            ExtraData=self._CurrentLine + \
+                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+                            File=self.MetaFile, Line=self._LineIndex + 1)
+        # check format of PCD CName
+        if not ValueRe.match(self._ValueList[1]):
+            EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
+                            ExtraData=self._CurrentLine + \
+                                      " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         # check PCD datum information
         if len(TokenList) < 2 or TokenList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
                             ExtraData=self._CurrentLine + \
                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
+
 
-        
-        ValueRe  = re.compile(r'^\s*L?\".*\|.*\"')
+        ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
         PtrValue = ValueRe.findall(TokenList[1])
-        
+
         # Has VOID* type string, may contain "|" character in the string. 
         if len(PtrValue) != 0:
             ptrValueList = re.sub(ValueRe, '', TokenList[1])
-            ValueList    = GetSplitValueList(ptrValueList)
+            ValueList = GetSplitValueList(ptrValueList)
             ValueList[0] = PtrValue[0]
         else:
             ValueList = GetSplitValueList(TokenList[1])
-            
-        
+
+
         # check if there's enough datum information given
         if len(ValueList) != 3:
             EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
                             ExtraData=self._CurrentLine + \
                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         # check default value
         if ValueList[0] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
                             ExtraData=self._CurrentLine + \
                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         # check datum type
         if ValueList[1] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
                             ExtraData=self._CurrentLine + \
                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         # check token of the PCD
         if ValueList[2] == '':
             EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
                             ExtraData=self._CurrentLine + \
                                       " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
         # check format of default value against the datum type
         IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
         if not IsValid:
             EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
-                            File=self.MetaFile, Line=self._LineIndex+1)
+                            File=self.MetaFile, Line=self._LineIndex + 1)
 
         if ValueList[0] in ['True', 'true', 'TRUE']:
             ValueList[0] = '1'
         elif ValueList[0] in ['False', 'false', 'FALSE']:
             ValueList[0] = '0'
 
+        # check for duplicate PCD definition
+        if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
+            EdkLogger.error('Parser', FORMAT_INVALID,
+                            "The same PCD name and GUID have been already defined",
+                            ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+        else:
+            self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
+
         self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
 
     _SectionParser = {