]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/UPT/InstallPkg.py
BaseTools:Update mailing list address in BaseTools error messages
[mirror_edk2.git] / BaseTools / Source / Python / UPT / InstallPkg.py
index 1c75dad80b1684cb5072fc3fe47affef61eaa0fb..e4c7565441ba1726066fc6c23ca13a01987d945a 100644 (file)
@@ -1,15 +1,9 @@
 ## @file\r
 # Install distribution package.\r
 #\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
 #\r
-# This program and the accompanying materials are licensed and made available \r
-# under the terms and conditions of the BSD License which accompanies this \r
-# distribution. The full text of the license may be found at \r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 """\r
 Install a distribution package\r
@@ -17,12 +11,14 @@ Install a distribution package
 ##\r
 # Import Modules\r
 #\r
+from Core.FileHook import __FileHookOpen__\r
 import os.path\r
 from os import chmod\r
 from os import SEEK_SET\r
 from os import SEEK_END\r
 import stat\r
-import md5\r
+from hashlib import md5\r
+import copy\r
 from sys import stdin\r
 from sys import platform\r
 from shutil import rmtree\r
@@ -42,7 +38,6 @@ from Logger.ToolError import FORMAT_INVALID
 from Logger.ToolError import FILE_TYPE_MISMATCH\r
 import Logger.Log as Logger\r
 \r
-from Library.Misc import CheckEnvVariable\r
 from Library.Misc import Sdict\r
 from Library.Misc import ConvertPath\r
 from Library.ParserValidate import IsValidInstallPath\r
@@ -83,7 +78,6 @@ def InstallNewPackage(WorkspaceDir, Path, CustomPath = False):
     Input = Input.replace('\r', '').replace('\n', '')\r
     return InstallNewPackage(WorkspaceDir, Input, False)\r
 \r
-\r
 ## InstallNewModule\r
 #\r
 # @param WorkspaceDir:   Workspace Directory\r
@@ -91,7 +85,7 @@ def InstallNewPackage(WorkspaceDir, Path, CustomPath = False):
 # @param PathList:       The already installed standalone module Path list\r
 #\r
 def InstallNewModule(WorkspaceDir, Path, PathList = None):\r
-    if PathList == None:\r
+    if PathList is None:\r
         PathList = []\r
     Path = ConvertPath(Path)\r
     Path = os.path.normpath(Path)\r
@@ -102,7 +96,7 @@ def InstallNewModule(WorkspaceDir, Path, PathList = None):
         Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%FullPath)\r
     else:\r
         return Path\r
-    \r
+\r
     Input = stdin.readline()\r
     Input = Input.replace('\r', '').replace('\n', '')\r
     if Input == '':\r
@@ -110,7 +104,7 @@ def InstallNewModule(WorkspaceDir, Path, PathList = None):
     Input = Input.replace('\r', '').replace('\n', '')\r
     return InstallNewModule(WorkspaceDir, Input, PathList)\r
 \r
-    \r
+\r
 ## InstallNewFile\r
 #\r
 # @param WorkspaceDir:   Workspace Direction\r
@@ -133,20 +127,19 @@ def InstallNewFile(WorkspaceDir, File):
 #\r
 # UnZipDp\r
 #\r
-def UnZipDp(WorkspaceDir, Options, DataBase):\r
+def UnZipDp(WorkspaceDir, DpPkgFileName, Index=1):\r
     ContentZipFile = None\r
     Logger.Quiet(ST.MSG_UZIP_PARSE_XML)\r
-    DpPkgFileName = Options.PackageFile\r
     DistFile = PackageFile(DpPkgFileName)\r
-    \r
+\r
     DpDescFileName, ContentFileName = GetDPFile(DistFile.GetZipFile())\r
-    \r
-    GlobalData.gUNPACK_DIR = os.path.normpath(os.path.join(WorkspaceDir, ".tmp"))\r
-    DistPkgFile = DistFile.UnpackFile(DpDescFileName,\r
-        os.path.normpath(os.path.join(GlobalData.gUNPACK_DIR, DpDescFileName)))\r
+\r
+    TempDir = os.path.normpath(os.path.join(WorkspaceDir, "Conf/.tmp%s" % str(Index)))\r
+    GlobalData.gUNPACK_DIR.append(TempDir)\r
+    DistPkgFile = DistFile.UnpackFile(DpDescFileName, os.path.normpath(os.path.join(TempDir, DpDescFileName)))\r
     if not DistPkgFile:\r
         Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_FILE_BROKEN %DpDescFileName)\r
-    \r
+\r
     #\r
     # Generate distpkg\r
     #\r
@@ -156,61 +149,34 @@ def UnZipDp(WorkspaceDir, Options, DataBase):
         DistPkg.Header.RePackage = False\r
     if DistPkg.Header.ReadOnly == '':\r
         DistPkg.Header.ReadOnly = False\r
-    \r
-    #\r
-    # prepare check dependency\r
-    #\r
-    Dep = DependencyRules(DataBase)\r
-    #\r
-    # Check distribution package installed or not\r
-    #\r
-    if Dep.CheckDpExists(DistPkg.Header.GetGuid(),\r
-        DistPkg.Header.GetVersion()):\r
-        Logger.Error("InstallPkg", UPT_ALREADY_INSTALLED_ERROR,\r
-            ST.WRN_DIST_PKG_INSTALLED)\r
-    #\r
-    # Check distribution dependency (all module dependency should be\r
-    # satisfied)\r
-    #\r
-    if not Dep.CheckDpDepexSatisfied(DistPkg):\r
-        Logger.Error("InstallPkg", UNKNOWN_ERROR,\r
-            ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY,\r
-            ExtraData=DistPkg.Header.Name)\r
+\r
     #\r
     # unzip contents.zip file\r
     #\r
-    ContentFile = DistFile.UnpackFile(ContentFileName,\r
-        os.path.normpath(os.path.join(GlobalData.gUNPACK_DIR, ContentFileName)))\r
+    ContentFile = DistFile.UnpackFile(ContentFileName, os.path.normpath(os.path.join(TempDir, ContentFileName)))\r
     if not ContentFile:\r
         Logger.Error("InstallPkg", FILE_NOT_FOUND,\r
             ST.ERR_FILE_BROKEN % ContentFileName)\r
 \r
-    FilePointer = open(ContentFile, "rb")\r
-    #\r
-    # Assume no archive comment.\r
-    #\r
-    FilePointer.seek(0, SEEK_SET)\r
-    FilePointer.seek(0, SEEK_END)\r
     #\r
     # Get file size\r
-    #                \r
-    FileSize = FilePointer.tell()\r
-    FilePointer.close()\r
-               \r
-    if FileSize != 0:        \r
+    #\r
+    FileSize = os.path.getsize(ContentFile)\r
+\r
+    if FileSize != 0:\r
         ContentZipFile = PackageFile(ContentFile)\r
 \r
     #\r
     # verify MD5 signature when existed\r
     #\r
     if DistPkg.Header.Signature != '':\r
-        Md5Sigature = md5.new(open(ContentFile, 'rb').read())\r
-        if DistPkg.Header.Signature != Md5Sigature.hexdigest():\r
+        Md5Signature = md5(__FileHookOpen__(ContentFile, 'rb').read())\r
+        if DistPkg.Header.Signature != Md5Signature.hexdigest():\r
             ContentZipFile.Close()\r
             Logger.Error("InstallPkg", FILE_CHECKSUM_FAILURE,\r
                 ExtraData=ContentFile)\r
 \r
-    return DistPkg, Dep, ContentZipFile, DpPkgFileName\r
+    return DistPkg, ContentZipFile, DpPkgFileName, DistFile\r
 \r
 ## GetPackageList\r
 #\r
@@ -222,15 +188,19 @@ def GetPackageList(DistPkg, Dep, WorkspaceDir, Options, ContentZipFile, ModuleLi
         PackagePath = Path\r
         Package = DistPkg.PackageSurfaceArea[Guid, Version, Path]\r
         Logger.Info(ST.MSG_INSTALL_PACKAGE % Package.GetName())\r
-        if Dep.CheckPackageExists(Guid, Version):\r
-            Logger.Info(ST.WRN_PACKAGE_EXISTED %(Guid, Version))\r
-        NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath, Options.CustomPath)\r
-        InstallPackageContent(PackagePath, NewPackagePath, Package, ContentZipFile, Dep, WorkspaceDir, ModuleList, \r
+#         if Dep.CheckPackageExists(Guid, Version):\r
+#             Logger.Info(ST.WRN_PACKAGE_EXISTED %(Guid, Version))\r
+        if Options.UseGuidedPkgPath:\r
+            GuidedPkgPath = "%s_%s_%s" % (Package.GetName(), Guid, Version)\r
+            NewPackagePath = InstallNewPackage(WorkspaceDir, GuidedPkgPath, Options.CustomPath)\r
+        else:\r
+            NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath, Options.CustomPath)\r
+        InstallPackageContent(PackagePath, NewPackagePath, Package, ContentZipFile, Dep, WorkspaceDir, ModuleList,\r
                               DistPkg.Header.ReadOnly)\r
         PackageList.append(Package)\r
-        \r
+\r
         NewDict[Guid, Version, Package.GetPackagePath()] = Package\r
-    \r
+\r
     #\r
     # Now generate meta-data files, first generate all dec for package\r
     # dec should be generated before inf, and inf should be generated after\r
@@ -238,12 +208,12 @@ def GetPackageList(DistPkg, Dep, WorkspaceDir, Options, ContentZipFile, ModuleLi
     # dependency (Hard to get the location of the newly installed package)\r
     #\r
     for Package in PackageList:\r
-        FilePath = PackageToDec(Package)\r
-        Md5Sigature = md5.new(open(str(FilePath), 'rb').read())\r
-        Md5Sum = Md5Sigature.hexdigest()\r
+        FilePath = PackageToDec(Package, DistPkg.Header)\r
+        Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read())\r
+        Md5Sum = Md5Signature.hexdigest()\r
         if (FilePath, Md5Sum) not in Package.FileList:\r
             Package.FileList.append((FilePath, Md5Sum))\r
-    \r
+\r
     return NewDict\r
 \r
 ## GetModuleList\r
@@ -253,18 +223,18 @@ def GetPackageList(DistPkg, Dep, WorkspaceDir, Options, ContentZipFile, ModuleLi
 def GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList):\r
     #\r
     # ModulePathList will keep track of the standalone module path that\r
-    # we just installed. If a new module's path in that list \r
-    # (only multiple INF in one directory will be so), we will \r
-    # install them directly. If not, we will try to create a new directory \r
+    # we just installed. If a new module's path in that list\r
+    # (only multiple INF in one directory will be so), we will\r
+    # install them directly. If not, we will try to create a new directory\r
     # for it.\r
     #\r
-    ModulePathList = []   \r
-    \r
+    ModulePathList = []\r
+\r
     #\r
     # Check module exist and install\r
     #\r
     Module = None\r
-    NewDict = Sdict()        \r
+    NewDict = Sdict()\r
     for Guid, Version, Name, Path in DistPkg.ModuleSurfaceArea:\r
         ModulePath = Path\r
         Module = DistPkg.ModuleSurfaceArea[Guid, Version, Name, Path]\r
@@ -283,32 +253,191 @@ def GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList):
             ModulePathList.append(NewModuleFullPath)\r
         else:\r
             NewModulePath = ModulePath\r
-        \r
-        InstallModuleContent(ModulePath, NewModulePath, '', Module, ContentZipFile, WorkspaceDir, ModuleList, None, \r
+\r
+        InstallModuleContent(ModulePath, NewModulePath, '', Module, ContentZipFile, WorkspaceDir, ModuleList, None,\r
                              DistPkg.Header.ReadOnly)\r
         #\r
         # Update module\r
         #\r
         Module.SetModulePath(Module.GetModulePath().replace(Path, NewModulePath, 1))\r
-        \r
+\r
         NewDict[Guid, Version, Name, Module.GetModulePath()] = Module\r
 \r
     #\r
     # generate all inf for modules\r
     #\r
     for (Module, Package) in ModuleList:\r
-        FilePath = ModuleToInf(Module)\r
-        Md5Sigature = md5.new(open(str(FilePath), 'rb').read())\r
-        Md5Sum = Md5Sigature.hexdigest()\r
+        CheckCNameInModuleRedefined(Module, DistPkg)\r
+        FilePath = ModuleToInf(Module, Package, DistPkg.Header)\r
+        Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read())\r
+        Md5Sum = Md5Signature.hexdigest()\r
         if Package:\r
             if (FilePath, Md5Sum) not in Package.FileList:\r
                 Package.FileList.append((FilePath, Md5Sum))\r
         else:\r
             if (FilePath, Md5Sum) not in Module.FileList:\r
                 Module.FileList.append((FilePath, Md5Sum))\r
-    \r
+        #\r
+        # append the module unicode files to Package FileList\r
+        #\r
+        for (FilePath, Md5Sum) in Module.FileList:\r
+            if str(FilePath).endswith('.uni') and Package and (FilePath, Md5Sum) not in Package.FileList:\r
+                Package.FileList.append((FilePath, Md5Sum))\r
+\r
     return NewDict\r
 \r
+##\r
+# Get all protocol/ppi/guid CNames and pcd name from all dependent DEC file\r
+#\r
+def GetDepProtocolPpiGuidPcdNames(DePackageObjList):\r
+    #\r
+    # [[Dec1Protocol1, Dec1Protocol2...], [Dec2Protocols...],...]\r
+    #\r
+    DependentProtocolCNames = []\r
+    DependentPpiCNames = []\r
+    DependentGuidCNames = []\r
+    DependentPcdNames = []\r
+\r
+    for PackageObj in DePackageObjList:\r
+        #\r
+        # Get protocol CName list from all dependent DEC file\r
+        #\r
+        ProtocolCNames = []\r
+        for Protocol in PackageObj.GetProtocolList():\r
+            if Protocol.GetCName() not in ProtocolCNames:\r
+                ProtocolCNames.append(Protocol.GetCName())\r
+\r
+        DependentProtocolCNames.append(ProtocolCNames)\r
+\r
+        #\r
+        # Get Ppi CName list from all dependent DEC file\r
+        #\r
+        PpiCNames = []\r
+        for Ppi in PackageObj.GetPpiList():\r
+            if Ppi.GetCName() not in PpiCNames:\r
+                PpiCNames.append(Ppi.GetCName())\r
+\r
+        DependentPpiCNames.append(PpiCNames)\r
+\r
+        #\r
+        # Get Guid CName list from all dependent DEC file\r
+        #\r
+        GuidCNames = []\r
+        for Guid in PackageObj.GetGuidList():\r
+            if Guid.GetCName() not in GuidCNames:\r
+                GuidCNames.append(Guid.GetCName())\r
+\r
+        DependentGuidCNames.append(GuidCNames)\r
+\r
+        #\r
+        # Get PcdName list from all dependent DEC file\r
+        #\r
+        PcdNames = []\r
+        for Pcd in PackageObj.GetPcdList():\r
+            PcdName = '.'.join([Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName()])\r
+            if PcdName not in PcdNames:\r
+                PcdNames.append(PcdName)\r
+\r
+        DependentPcdNames.append(PcdNames)\r
+\r
+\r
+    return DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames\r
+\r
+##\r
+# Check if protocol CName is redefined\r
+#\r
+def CheckProtoclCNameRedefined(Module, DependentProtocolCNames):\r
+    for ProtocolInModule in Module.GetProtocolList():\r
+        IsCNameDefined = False\r
+        for PackageProtocolCNames in DependentProtocolCNames:\r
+            if ProtocolInModule.GetCName() in PackageProtocolCNames:\r
+                if IsCNameDefined:\r
+                    Logger.Error("\nUPT", FORMAT_INVALID,\r
+                                 File = Module.GetFullPath(),\r
+                                 ExtraData = \\r
+                                 ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % ProtocolInModule.GetCName())\r
+                else:\r
+                    IsCNameDefined = True\r
+\r
+##\r
+# Check if Ppi CName is redefined\r
+#\r
+def CheckPpiCNameRedefined(Module, DependentPpiCNames):\r
+    for PpiInModule in Module.GetPpiList():\r
+        IsCNameDefined = False\r
+        for PackagePpiCNames in DependentPpiCNames:\r
+            if PpiInModule.GetCName() in PackagePpiCNames:\r
+                if IsCNameDefined:\r
+                    Logger.Error("\nUPT", FORMAT_INVALID,\r
+                                 File = Module.GetFullPath(),\r
+                                 ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PpiInModule.GetCName())\r
+                else:\r
+                    IsCNameDefined = True\r
+\r
+##\r
+# Check if Guid CName is redefined\r
+#\r
+def CheckGuidCNameRedefined(Module, DependentGuidCNames):\r
+    for GuidInModule in Module.GetGuidList():\r
+        IsCNameDefined = False\r
+        for PackageGuidCNames in DependentGuidCNames:\r
+            if GuidInModule.GetCName() in PackageGuidCNames:\r
+                if IsCNameDefined:\r
+                    Logger.Error("\nUPT", FORMAT_INVALID,\r
+                                 File = Module.GetFullPath(),\r
+                                 ExtraData = \\r
+                                 ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % GuidInModule.GetCName())\r
+                else:\r
+                    IsCNameDefined = True\r
+\r
+##\r
+# Check if PcdName is redefined\r
+#\r
+def CheckPcdNameRedefined(Module, DependentPcdNames):\r
+    PcdObjs = []\r
+    if not Module.GetBinaryFileList():\r
+        PcdObjs += Module.GetPcdList()\r
+    else:\r
+        Binary = Module.GetBinaryFileList()[0]\r
+        for AsBuild in Binary.GetAsBuiltList():\r
+            PcdObjs += AsBuild.GetPatchPcdList() + AsBuild.GetPcdExList()\r
+\r
+    for PcdObj in PcdObjs:\r
+        PcdName = '.'.join([PcdObj.GetTokenSpaceGuidCName(), PcdObj.GetCName()])\r
+        IsPcdNameDefined = False\r
+        for PcdNames in DependentPcdNames:\r
+            if PcdName in PcdNames:\r
+                if IsPcdNameDefined:\r
+                    Logger.Error("\nUPT", FORMAT_INVALID,\r
+                                 File = Module.GetFullPath(),\r
+                                 ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PcdName)\r
+                else:\r
+                    IsPcdNameDefined = True\r
+\r
+##\r
+# Check if any Protocol/Ppi/Guid and Pcd name is redefined in its dependent DEC files\r
+#\r
+def CheckCNameInModuleRedefined(Module, DistPkg):\r
+    DePackageObjList = []\r
+    #\r
+    # Get all dependent package objects\r
+    #\r
+    for Obj in Module.GetPackageDependencyList():\r
+        Guid = Obj.GetGuid()\r
+        Version = Obj.GetVersion()\r
+        for Key in DistPkg.PackageSurfaceArea:\r
+            if Key[0] == Guid and Key[1] == Version:\r
+                if DistPkg.PackageSurfaceArea[Key] not in DePackageObjList:\r
+                    DePackageObjList.append(DistPkg.PackageSurfaceArea[Key])\r
+\r
+    DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames = \\r
+    GetDepProtocolPpiGuidPcdNames(DePackageObjList)\r
+\r
+    CheckProtoclCNameRedefined(Module, DependentProtocolCNames)\r
+    CheckPpiCNameRedefined(Module, DependentPpiCNames)\r
+    CheckGuidCNameRedefined(Module, DependentGuidCNames)\r
+    CheckPcdNameRedefined(Module, DependentPcdNames)\r
+\r
 ## GenToolMisc\r
 #\r
 # GenToolMisc\r
@@ -322,7 +451,7 @@ def GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile):
     ToolFileNum = 0\r
     FileNum = 0\r
     RootDir = WorkspaceDir\r
-    \r
+\r
     #\r
     # FileList stores both tools files and misc files\r
     # Misc file list must be appended to FileList *AFTER* Tools file list\r
@@ -366,103 +495,135 @@ def GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile):
 # @param  Options: command Options\r
 #\r
 def Main(Options = None):\r
-    ContentZipFile, DistFile = None, None\r
-\r
     try:\r
-        DataBase = GlobalData.gDB        \r
-        CheckEnvVariable()\r
+        DataBase = GlobalData.gDB\r
         WorkspaceDir = GlobalData.gWORKSPACE\r
         if not Options.PackageFile:\r
             Logger.Error("InstallPkg", OPTION_MISSING, ExtraData=ST.ERR_SPECIFY_PACKAGE)\r
-        \r
-        #\r
-        # unzip dist.pkg file\r
-        #\r
-        DistPkg, Dep, ContentZipFile, DpPkgFileName = UnZipDp(WorkspaceDir, Options, DataBase)\r
 \r
-        #\r
-        # PackageList, ModuleList record the information for the meta-data\r
-        # files that need to be generated later\r
-        #\r
-        PackageList = []\r
-        ModuleList = []\r
-        DistPkg.PackageSurfaceArea = GetPackageList(DistPkg, Dep, WorkspaceDir, Options, \r
-                                                    ContentZipFile, ModuleList, PackageList)\r
-\r
-        DistPkg.ModuleSurfaceArea = GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList)       \r
-        \r
-        \r
-        GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile)\r
-        \r
-        #\r
-        # copy "Distribution File" to directory $(WORKSPACE)/conf/upt\r
-        #\r
-        DistFileName = os.path.split(DpPkgFileName)[1]\r
-        DestDir = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR))\r
-        CreateDirectory(DestDir)\r
-        DestFile = os.path.normpath(os.path.join(DestDir, DistFileName))\r
-        if os.path.exists(DestFile):\r
-            FileName, Ext = os.path.splitext(DistFileName)\r
-            NewFileName = FileName + '_' + DistPkg.Header.GetGuid() + '_' + DistPkg.Header.GetVersion() + '.' + Ext\r
-            DestFile = os.path.normpath(os.path.join(DestDir, NewFileName))\r
-            if os.path.exists(DestFile):\r
-                #\r
-                # ask for user input the new file name\r
-                #\r
-                Logger.Info( ST.MSG_NEW_FILE_NAME_FOR_DIST)\r
-                Input = stdin.readline()\r
-                Input = Input.replace('\r', '').replace('\n', '')\r
-                DestFile = os.path.normpath(os.path.join(DestDir, Input))\r
-        copyfile(DpPkgFileName, DestFile)\r
-        NewDpPkgFileName = DestFile[DestFile.find(DestDir) + len(DestDir) + 1:]\r
+        # Get all Dist Info\r
+        DistInfoList = []\r
+        DistPkgList = []\r
+        Index = 1\r
+        for ToBeInstalledDist in Options.PackageFile:\r
+            #\r
+            # unzip dist.pkg file\r
+            #\r
+            DistInfoList.append(UnZipDp(WorkspaceDir, ToBeInstalledDist, Index))\r
+            DistPkgList.append(DistInfoList[-1][0])\r
+            Index += 1\r
 \r
-        #\r
-        # update database\r
-        #\r
-        Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE)\r
-        DataBase.AddDPObject(DistPkg, NewDpPkgFileName, DistFileName, \r
-                       DistPkg.Header.RePackage)\r
-        \r
+            #\r
+            # Add dist\r
+            #\r
+            GlobalData.gTO_BE_INSTALLED_DIST_LIST.append(DistInfoList[-1][0])\r
+\r
+        # Check for dependency\r
+        Dep = DependencyRules(DataBase, DistPkgList)\r
+\r
+        for ToBeInstalledDist in DistInfoList:\r
+            CheckInstallDpx(Dep, ToBeInstalledDist[0], ToBeInstalledDist[2])\r
+\r
+            #\r
+            # Install distribution\r
+            #\r
+            InstallDp(ToBeInstalledDist[0], ToBeInstalledDist[2], ToBeInstalledDist[1],\r
+                      Options, Dep, WorkspaceDir, DataBase)\r
         ReturnCode = 0\r
-        \r
-    except FatalError, XExcept:\r
+\r
+    except FatalError as XExcept:\r
         ReturnCode = XExcept.args[0]\r
         if Logger.GetLevel() <= Logger.DEBUG_9:\r
-            Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),\r
-                platform) + format_exc())\r
+            Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())\r
+\r
     except KeyboardInterrupt:\r
         ReturnCode = ABORT_ERROR\r
         if Logger.GetLevel() <= Logger.DEBUG_9:\r
-            Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),\r
-                platform) + format_exc())\r
+            Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())\r
+\r
     except:\r
         ReturnCode = CODE_ERROR\r
         Logger.Error(\r
                     "\nInstallPkg",\r
                     CODE_ERROR,\r
                     ST.ERR_UNKNOWN_FATAL_INSTALL_ERR % Options.PackageFile,\r
-                    ExtraData=ST.MSG_SEARCH_FOR_HELP,\r
+                    ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR,\r
                     RaiseError=False\r
                     )\r
         Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),\r
             platform) + format_exc())\r
-\r
     finally:\r
         Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED)\r
-        if DistFile:\r
-            DistFile.Close()\r
-        if ContentZipFile:\r
-            ContentZipFile.Close()\r
-        if GlobalData.gUNPACK_DIR:\r
-            rmtree(GlobalData.gUNPACK_DIR)\r
-            GlobalData.gUNPACK_DIR = None\r
+        for ToBeInstalledDist in DistInfoList:\r
+            if ToBeInstalledDist[3]:\r
+                ToBeInstalledDist[3].Close()\r
+            if ToBeInstalledDist[1]:\r
+                ToBeInstalledDist[1].Close()\r
+        for TempDir in GlobalData.gUNPACK_DIR:\r
+            rmtree(TempDir)\r
+        GlobalData.gUNPACK_DIR = []\r
         Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE)\r
-\r
     if ReturnCode == 0:\r
         Logger.Quiet(ST.MSG_FINISH)\r
-    \r
     return ReturnCode\r
 \r
+# BackupDist method\r
+#\r
+# This method will backup the Distribution file into the $(WORKSPACE)/conf/upt, and rename it\r
+# if there is already a same-named distribution existed.\r
+#\r
+# @param DpPkgFileName: The distribution path\r
+# @param Guid:          The distribution Guid\r
+# @param Version:       The distribution Version\r
+# @param WorkspaceDir:  The workspace directory\r
+# @retval NewDpPkgFileName: The exact backup file name\r
+#\r
+def BackupDist(DpPkgFileName, Guid, Version, WorkspaceDir):\r
+    DistFileName = os.path.split(DpPkgFileName)[1]\r
+    DestDir = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR))\r
+    CreateDirectory(DestDir)\r
+    DestFile = os.path.normpath(os.path.join(DestDir, DistFileName))\r
+    if os.path.exists(DestFile):\r
+        FileName, Ext = os.path.splitext(DistFileName)\r
+        NewFileName = FileName + '_' + Guid + '_' + Version + Ext\r
+        DestFile = os.path.normpath(os.path.join(DestDir, NewFileName))\r
+        if os.path.exists(DestFile):\r
+            #\r
+            # ask for user input the new file name\r
+            #\r
+            Logger.Info( ST.MSG_NEW_FILE_NAME_FOR_DIST)\r
+            Input = stdin.readline()\r
+            Input = Input.replace('\r', '').replace('\n', '')\r
+            DestFile = os.path.normpath(os.path.join(DestDir, Input))\r
+    copyfile(DpPkgFileName, DestFile)\r
+    NewDpPkgFileName = DestFile[DestFile.find(DestDir) + len(DestDir) + 1:]\r
+    return NewDpPkgFileName\r
+\r
+## CheckInstallDpx method\r
+#\r
+#  check whether distribution could be installed\r
+#\r
+#   @param  Dep: the DependencyRules instance that used to check dependency\r
+#   @param  DistPkg: the distribution object\r
+#\r
+def CheckInstallDpx(Dep, DistPkg, DistPkgFileName):\r
+    #\r
+    # Check distribution package installed or not\r
+    #\r
+    if Dep.CheckDpExists(DistPkg.Header.GetGuid(),\r
+        DistPkg.Header.GetVersion()):\r
+        Logger.Error("InstallPkg",\r
+                     UPT_ALREADY_INSTALLED_ERROR,\r
+                     ST.WRN_DIST_PKG_INSTALLED % os.path.basename(DistPkgFileName))\r
+    #\r
+    # Check distribution dependency (all module dependency should be\r
+    # satisfied)\r
+    #\r
+    if not Dep.CheckInstallDpDepexSatisfied(DistPkg):\r
+        Logger.Error("InstallPkg", UNKNOWN_ERROR,\r
+            ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY,\r
+            ExtraData=DistPkg.Header.Name)\r
+\r
 ## InstallModuleContent method\r
 #\r
 # If this is standalone module, then Package should be none,\r
@@ -478,19 +639,19 @@ def Main(Options = None):
 #\r
 def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile,\r
     WorkspaceDir, ModuleList, Package = None, ReadOnly = False):\r
-    \r
+\r
     if NewPath.startswith("\\") or NewPath.startswith("/"):\r
         NewPath = NewPath[1:]\r
-    \r
+\r
     if not IsValidInstallPath(NewPath):\r
-        Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%NewPath) \r
-           \r
+        Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%NewPath)\r
+\r
     NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewPath,\r
         ConvertPath(ModulePath)))\r
     Module.SetFullPath(os.path.normpath(os.path.join(NewModuleFullPath,\r
         ConvertPath(Module.GetName()) + '.inf')))\r
     Module.FileList = []\r
-    \r
+\r
     for MiscFile in Module.GetMiscFileList():\r
         if not MiscFile:\r
             continue\r
@@ -498,12 +659,12 @@ def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile,
             File = Item.GetURI()\r
             if File.startswith("\\") or File.startswith("/"):\r
                 File = File[1:]\r
-            \r
+\r
             if not IsValidInstallPath(File):\r
                 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)\r
-                      \r
+\r
             FromFile = os.path.join(FromPath, ModulePath, File)\r
-            Executable = Item.GetExecutable()            \r
+            Executable = Item.GetExecutable()\r
             ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))\r
             Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable)\r
             if Package and ((ToFile, Md5Sum) not in Package.FileList):\r
@@ -516,10 +677,10 @@ def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile,
         File = Item.GetSourceFile()\r
         if File.startswith("\\") or File.startswith("/"):\r
             File = File[1:]\r
-            \r
+\r
         if not IsValidInstallPath(File):\r
-            Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File) \r
-                               \r
+            Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)\r
+\r
         FromFile = os.path.join(FromPath, ModulePath, File)\r
         ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))\r
         Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)\r
@@ -531,24 +692,24 @@ def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile,
             Module.FileList.append((ToFile, Md5Sum))\r
     for Item in Module.GetBinaryFileList():\r
         FileNameList = Item.GetFileNameList()\r
-        for FileName in FileNameList:              \r
-            File = FileName.GetFilename()          \r
+        for FileName in FileNameList:\r
+            File = FileName.GetFilename()\r
             if File.startswith("\\") or File.startswith("/"):\r
                 File = File[1:]\r
-                \r
+\r
             if not IsValidInstallPath(File):\r
                 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)\r
 \r
             FromFile = os.path.join(FromPath, ModulePath, File)\r
             ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))\r
-            Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)       \r
+            Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)\r
             if Package and ((ToFile, Md5Sum) not in Package.FileList):\r
                 Package.FileList.append((ToFile, Md5Sum))\r
             elif Package:\r
                 continue\r
             elif (ToFile, Md5Sum) not in Module.FileList:\r
                 Module.FileList.append((ToFile, Md5Sum))\r
-    \r
+\r
     InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly,\r
                                 ModuleList)\r
 \r
@@ -559,7 +720,7 @@ def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile,
 def InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly,\r
                                 ModuleList):\r
     #\r
-    # Extract other files under current module path in content Zip file but not listed in the description \r
+    # Extract other files under current module path in content Zip file but not listed in the description\r
     #\r
     if ContentZipFile:\r
         for FileName in ContentZipFile.GetZipFile().namelist():\r
@@ -568,14 +729,14 @@ def InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceD
             if FileUnderPath(FileName, CheckPath):\r
                 if FileName.startswith("\\") or FileName.startswith("/"):\r
                     FileName = FileName[1:]\r
-                    \r
+\r
                 if not IsValidInstallPath(FileName):\r
                     Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)\r
-                                                   \r
+\r
                 FromFile = FileName\r
-                ToFile = os.path.normpath(os.path.join(WorkspaceDir, \r
+                ToFile = os.path.normpath(os.path.join(WorkspaceDir,\r
                         ConvertPath(FileName.replace(FromPath, NewPath, 1))))\r
-                CheckList = Module.FileList\r
+                CheckList = copy.copy(Module.FileList)\r
                 if Package:\r
                     CheckList += Package.FileList\r
                 for Item in CheckList:\r
@@ -588,16 +749,16 @@ def InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceD
                     elif Package:\r
                         continue\r
                     elif (ToFile, Md5Sum) not in Module.FileList:\r
-                        Module.FileList.append((ToFile, Md5Sum))            \r
-    \r
+                        Module.FileList.append((ToFile, Md5Sum))\r
+\r
     ModuleList.append((Module, Package))\r
 \r
 ## FileUnderPath\r
-#  Check whether FileName started with directory specified by CheckPath \r
+#  Check whether FileName started with directory specified by CheckPath\r
 #\r
 # @param FileName: the FileName need to be checked\r
 # @param CheckPath: the path need to be checked against\r
-# @return:  True or False  \r
+# @return:  True or False\r
 #\r
 def FileUnderPath(FileName, CheckPath):\r
     FileName = FileName.replace('\\', '/')\r
@@ -610,32 +771,37 @@ def FileUnderPath(FileName, CheckPath):
             RemainingPath = RemainingPath[1:]\r
         if FileName == os.path.normpath(os.path.join(CheckPath, RemainingPath)):\r
             return True\r
-    \r
+\r
     return False\r
 \r
 ## InstallFile\r
 #  Extract File from Zipfile, set file attribute, and return the Md5Sum\r
 #\r
-# @return:  True or False  \r
+# @return:  True or False\r
 #\r
 def InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable=False):\r
-    if not ContentZipFile or not ContentZipFile.UnpackFile(FromFile, ToFile):\r
-        Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_INSTALL_FILE_FROM_EMPTY_CONTENT%FromFile)\r
+    if os.path.exists(os.path.normpath(ToFile)):\r
+        pass\r
+    else:\r
+        if not ContentZipFile or not ContentZipFile.UnpackFile(FromFile, ToFile):\r
+            Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_INSTALL_FILE_FROM_EMPTY_CONTENT % FromFile)\r
 \r
-    if ReadOnly:\r
-        if not Executable:\r
-            chmod(ToFile, stat.S_IREAD)\r
+        if ReadOnly:\r
+            if not Executable:\r
+                chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)\r
+            else:\r
+                chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)\r
+        elif Executable:\r
+            chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP |\r
+                  stat.S_IWOTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)\r
         else:\r
-            chmod(ToFile, stat.S_IREAD|stat.S_IEXEC)\r
-    elif Executable:\r
-        chmod(ToFile, stat.S_IREAD|stat.S_IWRITE|stat.S_IEXEC)\r
-    else:\r
-        chmod(ToFile, stat.S_IREAD|stat.S_IWRITE)\r
-                \r
-    Md5Sigature = md5.new(open(str(ToFile), 'rb').read())\r
-    Md5Sum = Md5Sigature.hexdigest()\r
+            chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)\r
+\r
+    Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read())\r
+    Md5Sum = Md5Signature.hexdigest()\r
+\r
     return Md5Sum\r
-        \r
+\r
 ## InstallPackageContent method\r
 #\r
 #   @param  FromPath: FromPath\r
@@ -651,44 +817,44 @@ def InstallPackageContent(FromPath, ToPath, Package, ContentZipFile, Dep,
     if Dep:\r
         pass\r
     Package.FileList = []\r
-    \r
+\r
     if ToPath.startswith("\\") or ToPath.startswith("/"):\r
         ToPath = ToPath[1:]\r
-    \r
+\r
     if not IsValidInstallPath(ToPath):\r
-        Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%ToPath)     \r
+        Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%ToPath)\r
 \r
     if FromPath.startswith("\\") or FromPath.startswith("/"):\r
         FromPath = FromPath[1:]\r
-    \r
+\r
     if not IsValidInstallPath(FromPath):\r
-        Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FromPath)   \r
-    \r
+        Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FromPath)\r
+\r
     PackageFullPath = os.path.normpath(os.path.join(WorkspaceDir, ToPath))\r
     for MiscFile in Package.GetMiscFileList():\r
         for Item in MiscFile.GetFileList():\r
             FileName = Item.GetURI()\r
             if FileName.startswith("\\") or FileName.startswith("/"):\r
                 FileName = FileName[1:]\r
-                \r
+\r
             if not IsValidInstallPath(FileName):\r
                 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)\r
-                            \r
+\r
             FromFile = os.path.join(FromPath, FileName)\r
             Executable = Item.GetExecutable()\r
             ToFile =  (os.path.join(PackageFullPath, ConvertPath(FileName)))\r
             Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable)\r
             if (ToFile, Md5Sum) not in Package.FileList:\r
                 Package.FileList.append((ToFile, Md5Sum))\r
-    PackageIncludeArchList = [] \r
+    PackageIncludeArchList = []\r
     for Item in Package.GetPackageIncludeFileList():\r
         FileName = Item.GetFilePath()\r
         if FileName.startswith("\\") or FileName.startswith("/"):\r
             FileName = FileName[1:]\r
-            \r
+\r
         if not IsValidInstallPath(FileName):\r
-            Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) \r
-                   \r
+            Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)\r
+\r
         FromFile = os.path.join(FromPath, FileName)\r
         ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName)))\r
         RetFile = ContentZipFile.UnpackFile(FromFile, ToFile)\r
@@ -701,23 +867,23 @@ def InstallPackageContent(FromPath, ToPath, Package, ContentZipFile, Dep,
             CreateDirectory(ToFile)\r
             continue\r
         if ReadOnly:\r
-            chmod(ToFile, stat.S_IREAD)\r
+            chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)\r
         else:\r
-            chmod(ToFile, stat.S_IREAD|stat.S_IWRITE)            \r
-        Md5Sigature = md5.new(open(str(ToFile), 'rb').read())\r
-        Md5Sum = Md5Sigature.hexdigest()\r
+            chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH)\r
+        Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read())\r
+        Md5Sum = Md5Signature.hexdigest()\r
         if (ToFile, Md5Sum) not in Package.FileList:\r
             Package.FileList.append((ToFile, Md5Sum))\r
     Package.SetIncludeArchList(PackageIncludeArchList)\r
-    \r
+\r
     for Item in Package.GetStandardIncludeFileList():\r
         FileName = Item.GetFilePath()\r
         if FileName.startswith("\\") or FileName.startswith("/"):\r
             FileName = FileName[1:]\r
-            \r
+\r
         if not IsValidInstallPath(FileName):\r
-            Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) \r
-                    \r
+            Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)\r
+\r
         FromFile = os.path.join(FromPath, FileName)\r
         ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName)))\r
         Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)\r
@@ -760,7 +926,7 @@ def GetDPFile(ZipFile):
                 continue\r
         else:\r
             continue\r
-        \r
+\r
         Logger.Error("PackagingTool", FILE_TYPE_MISMATCH,\r
             ExtraData=ST.ERR_DIST_FILE_TOOMANY)\r
     if not DescFile or not ContentFile:\r
@@ -768,3 +934,34 @@ def GetDPFile(ZipFile):
             ExtraData=ST.ERR_DIST_FILE_TOOFEW)\r
     return DescFile, ContentFile\r
 \r
+## InstallDp method\r
+#\r
+#   Install the distribution to current workspace\r
+#\r
+def InstallDp(DistPkg, DpPkgFileName, ContentZipFile, Options, Dep, WorkspaceDir, DataBase):\r
+    #\r
+    # PackageList, ModuleList record the information for the meta-data\r
+    # files that need to be generated later\r
+    #\r
+    PackageList = []\r
+    ModuleList = []\r
+    DistPkg.PackageSurfaceArea = GetPackageList(DistPkg, Dep, WorkspaceDir, Options,\r
+                                                ContentZipFile, ModuleList, PackageList)\r
+\r
+    DistPkg.ModuleSurfaceArea = GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList)\r
+\r
+    GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile)\r
+\r
+    #\r
+    # copy "Distribution File" to directory $(WORKSPACE)/conf/upt\r
+    #\r
+    DistFileName = os.path.split(DpPkgFileName)[1]\r
+    NewDpPkgFileName = BackupDist(DpPkgFileName, DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion(), WorkspaceDir)\r
+\r
+    #\r
+    # update database\r
+    #\r
+    Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE)\r
+    DataBase.AddDPObject(DistPkg, NewDpPkgFileName, DistFileName,\r
+                   DistPkg.Header.RePackage)\r
+\r