Index: Source/Python/Common/LongFilePathSupport.py
===================================================================
--- Source/Python/Common/LongFilePathSupport.py	(revision 17647)
+++ Source/Python/Common/LongFilePathSupport.py	(working copy)
@@ -1,7 +1,7 @@
 ## @file
 # Override built in function file.open to provide support for long file path
 #
-# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2015, 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
@@ -14,6 +14,7 @@
 import os
 import platform
 import shutil
+import codecs
 
 ##
 # OpenLongPath
@@ -37,6 +38,9 @@
 def OpenLongFilePath(FileName, Mode='r', Buffer= -1):
     return open(LongFilePath(FileName), Mode, Buffer)
 
+def CodecOpenLongFilePath(Filename, Mode='rb', Encoding=None, Errors='strict', Buffering=1):
+    return codecs.open(LongFilePath(Filename), Mode, Encoding, Errors, Buffering)
+
 ##
 # CopyLongFilePath
 # wrap copyfile to support copy a long file path
Index: Source/Python/Ecc/config.ini
===================================================================
--- Source/Python/Ecc/config.ini	(revision 17671)
+++ Source/Python/Ecc/config.ini	(working copy)
@@ -2,7 +2,7 @@
 # This file is used to set configuration of ECC tool
 # For the items listed below, 1 means valid, 0 means invalid
 #
-# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2015, 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
@@ -249,6 +249,15 @@
 MetaDataFileCheckModuleFileGuidDuplication = 1
 
 #
+# Uni File Processing Checking
+#
+UniCheckAll = 0
+# Check INF or DEC file whether defined the localized information in the associated UNI file.
+UniCheckHelpInfo = 1
+# Check PCD whether defined the prompt, help in the DEC file and localized information in the associated UNI file.
+UniCheckPCDInfo = 1
+
+#
 # The check points in this section are reserved
 #
 # GotoStatementCheckAll = 0
Index: Source/Python/Ecc/Configuration.py
===================================================================
--- Source/Python/Ecc/Configuration.py	(revision 17671)
+++ Source/Python/Ecc/Configuration.py	(working copy)
@@ -246,6 +246,13 @@
         self.MetaDataFileCheckModuleFilePpiFormat = 1
         # Check Pcd Format in INF files
         self.MetaDataFileCheckModuleFilePcdFormat = 1
+        
+        # Check UNI file
+        self.UniCheckAll = 0
+        # Check INF or DEC file whether defined the localized information in the associated UNI file.
+        self.UniCheckHelpInfo = 1
+        # Check PCD whether defined the prompt, help in the DEC file and localized information in the associated UNI file.
+        self.UniCheckPCDInfo = 1
 
         #
         # The check points in this section are reserved
Index: Source/Python/Ecc/Ecc.py
===================================================================
--- Source/Python/Ecc/Ecc.py	(revision 17671)
+++ Source/Python/Ecc/Ecc.py	(working copy)
@@ -251,7 +251,8 @@
                         Filename = os.path.normpath(os.path.join(Root, File))
                         EdkLogger.quiet("Parsing %s" % Filename)
                         Op.write("%s\r" % Filename)
-                        EccGlobalData.gDb.TblFile.InsertFile(Filename, MODEL_FILE_UNI)
+                        FileID = EccGlobalData.gDb.TblFile.InsertFile(Filename, MODEL_FILE_UNI)
+                        EccGlobalData.gDb.TblReport.UpdateBelongsToItemByFile(FileID, File)
                         continue
 
         Op.close()
Index: Source/Python/Ecc/EccToolError.py
===================================================================
--- Source/Python/Ecc/EccToolError.py	(revision 17671)
+++ Source/Python/Ecc/EccToolError.py	(working copy)
@@ -1,7 +1,7 @@
 ## @file
 # Standardized Error Hanlding infrastructures.
 #
-# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2008 - 2015, 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
@@ -21,6 +21,7 @@
 ERROR_GENERAL_CHECK_FILE_EXISTENCE = 1007
 ERROR_GENERAL_CHECK_NON_ACSII = 1008
 ERROR_GENERAL_CHECK_UNI = 1009
+ERROR_GENERAL_CHECK_UNI_HELP_INFO = 1010
 
 ERROR_SPACE_CHECK_ALL = 2000
 
@@ -114,6 +115,7 @@
     ERROR_GENERAL_CHECK_FILE_EXISTENCE : "File not found",
     ERROR_GENERAL_CHECK_NON_ACSII : "File has invalid Non-ACSII char",
     ERROR_GENERAL_CHECK_UNI : "File is not a valid UTF-16 UNI file",
+    ERROR_GENERAL_CHECK_UNI_HELP_INFO : "UNI file that is associated by INF or DEC file need define the prompt and help information.",
 
     ERROR_SPACE_CHECK_ALL : "",
 
Index: Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
===================================================================
--- Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py	(revision 17671)
+++ Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py	(working copy)
@@ -1,7 +1,7 @@
 ## @file
 # This file is used to parse meta files
 #
-# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2008 - 2015, 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
@@ -33,6 +33,7 @@
 from MetaFileTable import MetaFileStorage
 from GenFds.FdfParser import FdfParser
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.LongFilePathSupport import CodecOpenLongFilePath
 
 ## A decorator used to parse macro definition
 def ParseMacro(Parser):
@@ -174,6 +175,9 @@
         self._PostProcessed = False
         # Different version of meta-file has different way to parse.
         self._Version = 0
+        # UNI object and extra UNI object
+        self._UniObj = None
+        self._UniExtraObj = None
 
     ## Store the parsed data in table
     def _Store(self, *Args):
@@ -258,8 +262,16 @@
 
     ## Skip unsupported data
     def _Skip(self):
-        EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
-                        Line=self._LineIndex+1, ExtraData=self._CurrentLine);
+        if self._SectionName == TAB_USER_EXTENSIONS.upper() and self._CurrentLine.upper().endswith('.UNI'):
+            if EccGlobalData.gConfig.UniCheckHelpInfo == '1' or EccGlobalData.gConfig.UniCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
+                ExtraUni = self._CurrentLine.strip()
+                ExtraUniFile = os.path.join(os.path.dirname(self.MetaFile), ExtraUni)
+                IsModuleUni = self.MetaFile.upper().endswith('.INF')
+                self._UniExtraObj = UniParser(ExtraUniFile, IsExtraUni=True, IsModuleUni=IsModuleUni)
+                self._UniExtraObj.Start()
+        else:
+            EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
+                            Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
         self._ValueList[0:1] = [self._CurrentLine]
 
     ## Section header parser
@@ -328,7 +340,20 @@
             except:
                 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
                                 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
-
+        elif Name == 'MODULE_UNI_FILE':
+            UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)
+            if os.path.exists(UniFile):
+                self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=True)
+                self._UniObj.Start()
+            else:
+                EdkLogger.error('Parser', FILE_NOT_FOUND, "Module UNI file %s is missing." % Value,
+                                ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1,
+                                RaiseError=False)
+        elif Name == 'PACKAGE_UNI_FILE':
+            UniFile = os.path.join(os.path.dirname(self.MetaFile), Value)
+            if os.path.exists(UniFile):
+                self._UniObj = UniParser(UniFile, IsExtraUni=False, IsModuleUni=False)
+        
         if type(self) == InfParser and self._Version < 0x00010005:
             # EDK module allows using defines as macros
             self._FileLocalMacros[Name] = Value
@@ -1873,6 +1898,69 @@
                 BelongsToFile = self.InsertFile(FileName)
                 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
 
+class UniParser(object):
+    # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
+    # IsModuleUni defined the UNI file is Module UNI or Package UNI
+    def __init__(self, FilePath, IsExtraUni=False, IsModuleUni=True):
+        self.FilePath = FilePath
+        self.FileName = os.path.basename(FilePath)
+        self.IsExtraUni = IsExtraUni
+        self.IsModuleUni = IsModuleUni
+        self.FileIn = None
+        self.Missing = []
+        self.__read()
+    
+    def __read(self):
+        try:
+            self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode = 'rb', Encoding = 'utf_16').read()
+        except UnicodeError:
+            self.FileIn = CodecOpenLongFilePath(self.FilePath, Mode = 'rb', Encoding = 'utf_16_le').read()
+        except IOError:
+            self.FileIn = ""
+    
+    def Start(self):
+        if self.IsModuleUni:
+            if self.IsExtraUni:
+                ModuleName = self.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
+                self.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName)
+            else:
+                ModuleAbstract = self.CheckKeyValid('STR_MODULE_ABSTRACT')
+                self.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract)
+                ModuleDescription = self.CheckKeyValid('STR_MODULE_DESCRIPTION')
+                self.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription)
+        else:
+            if self.IsExtraUni:
+                PackageName = self.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
+                self.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName)
+            else:
+                PackageAbstract = self.CheckKeyValid('STR_PACKAGE_ABSTRACT')
+                self.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract)
+                PackageDescription = self.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
+                self.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription)
+                
+    def CheckKeyValid(self, Key, Contents=None):
+        if not Contents:
+            Contents = self.FileIn
+        KeyPattern = re.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key, re.S)
+        if KeyPattern.search(Contents):
+            return True
+        return False
+    
+    def CheckPcdInfo(self, PcdCName):
+        PromptKey = 'STR_%s_PROMPT' % PcdCName.replace('.', '_')
+        PcdPrompt = self.CheckKeyValid(PromptKey)
+        self.PrintLog(PromptKey, PcdPrompt)
+        HelpKey = 'STR_%s_HELP' % PcdCName.replace('.', '_')
+        PcdHelp = self.CheckKeyValid(HelpKey)
+        self.PrintLog(HelpKey, PcdHelp)
+    
+    def PrintLog(self, Key, Value):
+        if not Value and Key not in self.Missing:
+            Msg = '%s is missing in the %s file.' % (Key, self.FileName)
+            EdkLogger.warn('Parser', Msg)
+            EccGlobalData.gDb.TblReport.Insert(EccToolError.ERROR_GENERAL_CHECK_UNI_HELP_INFO, OtherMsg=Msg, BelongsToTable='File', BelongsToItem=-2)
+            self.Missing.append(Key)
+
 ##
 #
 # This acts like the main() function for the script, unless it is 'import'ed into another
Index: Source/Python/Table/TableReport.py
===================================================================
--- Source/Python/Table/TableReport.py	(revision 17647)
+++ Source/Python/Table/TableReport.py	(working copy)
@@ -1,7 +1,7 @@
 ## @file
 # This file is used to create/update/query/erase table for ECC reports
 #
-# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2008 - 2015, 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
@@ -85,6 +85,13 @@
                         where Enabled > -1 order by ErrorID, BelongsToItem""" % (self.Table)
         return self.Exec(SqlCommand)
 
+    ## Update table
+    #
+    def UpdateBelongsToItemByFile(self, ItemID=-1, File=""):
+        SqlCommand = """update Report set BelongsToItem=%s where BelongsToTable='File' and BelongsToItem=-2
+                        and OtherMsg like '%%%s%%'""" % (ItemID, File)
+        return self.Exec(SqlCommand)
+
     ## Convert to CSV
     #
     # Get all enabled records from table report and save them to a .csv file
