]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/build/BuildReport.py
BaseTools: Update python tool to call external tools with shell true mode
[mirror_edk2.git] / BaseTools / Source / Python / build / BuildReport.py
index aee50fb3a2940da050676103ceaef647756eb097..4c57754b3b1eea42fe9ae0c5e24a26702fe91a0d 100644 (file)
@@ -24,6 +24,9 @@ import traceback
 import sys\r
 import time\r
 import struct\r
+import hashlib\r
+import subprocess\r
+import threading\r
 from datetime import datetime\r
 from StringIO import StringIO\r
 from Common import EdkLogger\r
@@ -33,6 +36,7 @@ from Common.Misc import GuidStructureStringToGuidString
 from Common.InfClassObject import gComponentType2ModuleType\r
 from Common.BuildToolError import FILE_WRITE_FAILURE\r
 from Common.BuildToolError import CODE_ERROR\r
+from Common.BuildToolError import COMMAND_FAILURE\r
 from Common.DataType import TAB_LINE_BREAK\r
 from Common.DataType import TAB_DEPEX\r
 from Common.DataType import TAB_SLASH\r
@@ -43,6 +47,9 @@ from Common.DataType import TAB_BACK_SLASH
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 import Common.GlobalData as GlobalData\r
+from AutoGen.AutoGen import ModuleAutoGen\r
+from Common.Misc import PathClass\r
+from Common.String import NormPath\r
 \r
 ## Pattern to extract contents in EDK DXS files\r
 gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)\r
@@ -528,6 +535,7 @@ class ModuleReport(object):
         self.FileGuid = M.Guid\r
         self.Size = 0\r
         self.BuildTimeStamp = None\r
+        self.Hash = 0\r
         self.DriverType = ""\r
         if not M.IsLibrary:\r
             ModuleType = M.ModuleType\r
@@ -599,12 +607,46 @@ class ModuleReport(object):
             except IOError:\r
                 EdkLogger.warn(None, "Fail to read report file", FwReportFileName)\r
 \r
+        if "HASH" in ReportType:\r
+            OutputDir = os.path.join(self._BuildDir, "OUTPUT")\r
+            DefaultEFIfile = os.path.join(OutputDir, self.ModuleName + ".efi")\r
+            if os.path.isfile(DefaultEFIfile):\r
+                Tempfile = os.path.join(OutputDir, self.ModuleName + "_hash.tmp")\r
+                # rebase the efi image since its base address may not zero\r
+                cmd = ["GenFw", "--rebase", str(0), "-o", Tempfile, DefaultEFIfile]\r
+                try:\r
+                    PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)\r
+                except Exception, X:\r
+                    EdkLogger.error("GenFw", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))\r
+                EndOfProcedure = threading.Event()\r
+                EndOfProcedure.clear()\r
+                if PopenObject.stderr:\r
+                    StdErrThread = threading.Thread(target=ReadMessage, args=(PopenObject.stderr, EdkLogger.quiet, EndOfProcedure))\r
+                    StdErrThread.setName("STDERR-Redirector")\r
+                    StdErrThread.setDaemon(False)\r
+                    StdErrThread.start()\r
+                # waiting for program exit\r
+                PopenObject.wait()\r
+                if PopenObject.stderr:\r
+                    StdErrThread.join()\r
+                if PopenObject.returncode != 0:\r
+                    EdkLogger.error("GenFw", COMMAND_FAILURE, "Failed to generate firmware hash image for %s" % (DefaultEFIfile))\r
+                if os.path.isfile(Tempfile):\r
+                    self.Hash = hashlib.sha1()\r
+                    buf = open(Tempfile, 'rb').read()\r
+                    if self.Hash.update(buf):\r
+                        self.Hash = self.Hash.update(buf)\r
+                    self.Hash = self.Hash.hexdigest()\r
+                    os.remove(Tempfile)\r
+\r
         FileWrite(File, "Module Summary")\r
         FileWrite(File, "Module Name:          %s" % self.ModuleName)\r
         FileWrite(File, "Module INF Path:      %s" % self.ModuleInfPath)\r
         FileWrite(File, "File GUID:            %s" % self.FileGuid)\r
         if self.Size:\r
             FileWrite(File, "Size:                 0x%X (%.2fK)" % (self.Size, self.Size / 1024.0))\r
+        if self.Hash:\r
+            FileWrite(File, "SHA1 HASH:            %s *%s" % (self.Hash, self.ModuleName + ".efi"))\r
         if self.BuildTimeStamp:\r
             FileWrite(File, "Build Time Stamp:     %s" % self.BuildTimeStamp)\r
         if self.DriverType:\r
@@ -639,6 +681,18 @@ class ModuleReport(object):
 \r
         FileWrite(File, gSectionEnd)\r
 \r
+def ReadMessage(From, To, ExitFlag):\r
+    while True:\r
+        # read one line a time\r
+        Line = From.readline()\r
+        # empty string means "end"\r
+        if Line != None and Line != "":\r
+            To(Line.rstrip())\r
+        else:\r
+            break\r
+        if ExitFlag.isSet():\r
+            break\r
+\r
 ##\r
 # Reports platform and module PCD information\r
 #\r
@@ -1596,8 +1650,21 @@ class PlatformReport(object):
         else:\r
             self._IsModuleBuild = False\r
             for Pa in Wa.AutoGenObjectList:\r
+                ModuleAutoGenList = []\r
                 for ModuleKey in Pa.Platform.Modules:\r
-                    self.ModuleReportList.append(ModuleReport(Pa.Platform.Modules[ModuleKey].M, ReportType))\r
+                    ModuleAutoGenList.append(Pa.Platform.Modules[ModuleKey].M)\r
+                if GlobalData.gFdfParser != None:\r
+                    if Pa.Arch in GlobalData.gFdfParser.Profile.InfDict:\r
+                        INFList = GlobalData.gFdfParser.Profile.InfDict[Pa.Arch]\r
+                        for InfName in INFList:\r
+                            InfClass = PathClass(NormPath(InfName), Wa.WorkspaceDir, Pa.Arch)\r
+                            Ma = ModuleAutoGen(Wa, InfClass, Pa.BuildTarget, Pa.ToolChain, Pa.Arch, Wa.MetaFile)\r
+                            if Ma == None:\r
+                                continue\r
+                            if Ma not in ModuleAutoGenList:\r
+                                ModuleAutoGenList.append(Ma)\r
+                for MGen in ModuleAutoGenList:\r
+                    self.ModuleReportList.append(ModuleReport(MGen, ReportType))\r
 \r
 \r
 \r
@@ -1625,6 +1692,14 @@ class PlatformReport(object):
         FileWrite(File, "Build Duration:       %s" % BuildDuration)\r
         FileWrite(File, "Report Content:       %s" % ", ".join(ReportType))\r
 \r
+        if GlobalData.MixedPcd:\r
+            FileWrite(File, gSectionStart)\r
+            FileWrite(File, "The following PCDs use different access methods:")\r
+            FileWrite(File, gSectionSep)\r
+            for PcdItem in GlobalData.MixedPcd:\r
+                FileWrite(File, "%s.%s" % (str(PcdItem[1]), str(PcdItem[0])))\r
+            FileWrite(File, gSectionEnd)\r
+\r
         if not self._IsModuleBuild:\r
             if "PCD" in ReportType:\r
                 self.PcdReport.GenerateReport(File, None)\r
@@ -1667,7 +1742,7 @@ class BuildReport(object):
                     if ReportTypeItem not in self.ReportType:\r
                         self.ReportType.append(ReportTypeItem)\r
             else:\r
-                self.ReportType = ["PCD", "LIBRARY", "BUILD_FLAGS", "DEPEX", "FLASH", "FIXED_ADDRESS"]\r
+                self.ReportType = ["PCD", "LIBRARY", "BUILD_FLAGS", "DEPEX", "HASH", "FLASH", "FIXED_ADDRESS"]\r
     ##\r
     # Adds platform report to the list\r
     #\r