Build report add new report type 'HASH' to include the hash value for each output EFI image.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yonghong Zhu <[email protected]> --- BaseTools/Source/Python/build/BuildReport.py | 53 +++++++++++++++++++++++++++- BaseTools/Source/Python/build/build.py | 4 +-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py index aee50fb..27a5d97 100644 --- a/BaseTools/Source/Python/build/BuildReport.py +++ b/BaseTools/Source/Python/build/BuildReport.py @@ -22,19 +22,23 @@ import platform import textwrap import traceback import sys import time import struct +import hashlib +import subprocess +import threading from datetime import datetime from StringIO import StringIO from Common import EdkLogger from Common.Misc import SaveFileOnChange from Common.Misc import GuidStructureByteArrayToGuidString from Common.Misc import GuidStructureStringToGuidString from Common.InfClassObject import gComponentType2ModuleType from Common.BuildToolError import FILE_WRITE_FAILURE from Common.BuildToolError import CODE_ERROR +from Common.BuildToolError import COMMAND_FAILURE from Common.DataType import TAB_LINE_BREAK from Common.DataType import TAB_DEPEX from Common.DataType import TAB_SLASH from Common.DataType import TAB_SPACE_SPLIT from Common.DataType import TAB_BRG_PCD @@ -526,10 +530,11 @@ class ModuleReport(object): self.ModuleName = M.Module.BaseName self.ModuleInfPath = M.MetaFile.File self.FileGuid = M.Guid self.Size = 0 self.BuildTimeStamp = None + self.Hash = 0 self.DriverType = "" if not M.IsLibrary: ModuleType = M.ModuleType if not ModuleType: ModuleType = gComponentType2ModuleType.get(M.ComponentType, "") @@ -597,16 +602,50 @@ class ModuleReport(object): if Match: self.BuildTimeStamp = datetime.fromtimestamp(int(Match.group(1))) except IOError: EdkLogger.warn(None, "Fail to read report file", FwReportFileName) + if "HASH" in ReportType: + OutputDir = os.path.join(self._BuildDir, "OUTPUT") + DefaultEFIfile = os.path.join(OutputDir, self.ModuleName + ".efi") + if os.path.isfile(DefaultEFIfile): + Tempfile = os.path.join(OutputDir, self.ModuleName + "_hash.tmp") + # rebase the efi image since its base address may not zero + cmd = ["GenFw", "--rebase", str(0), "-o", Tempfile, DefaultEFIfile] + try: + PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + except Exception, X: + EdkLogger.error("GenFw", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0])) + EndOfProcedure = threading.Event() + EndOfProcedure.clear() + if PopenObject.stderr: + StdErrThread = threading.Thread(target=ReadMessage, args=(PopenObject.stderr, EdkLogger.quiet, EndOfProcedure)) + StdErrThread.setName("STDERR-Redirector") + StdErrThread.setDaemon(False) + StdErrThread.start() + # waiting for program exit + PopenObject.wait() + if PopenObject.stderr: + StdErrThread.join() + if PopenObject.returncode != 0: + EdkLogger.error("GenFw", COMMAND_FAILURE, "Failed to generate firmware hash image for %s" % (DefaultEFIfile)) + if os.path.isfile(Tempfile): + self.Hash = hashlib.sha1() + buf = open(Tempfile, 'rb').read() + if self.Hash.update(buf): + self.Hash = self.Hash.update(buf) + self.Hash = self.Hash.hexdigest() + os.remove(Tempfile) + FileWrite(File, "Module Summary") FileWrite(File, "Module Name: %s" % self.ModuleName) FileWrite(File, "Module INF Path: %s" % self.ModuleInfPath) FileWrite(File, "File GUID: %s" % self.FileGuid) if self.Size: FileWrite(File, "Size: 0x%X (%.2fK)" % (self.Size, self.Size / 1024.0)) + if self.Hash: + FileWrite(File, "SHA1 HASH: %s *%s" % (self.Hash, self.ModuleName + ".efi")) if self.BuildTimeStamp: FileWrite(File, "Build Time Stamp: %s" % self.BuildTimeStamp) if self.DriverType: FileWrite(File, "Driver Type: %s" % self.DriverType) if self.UefiSpecVersion: @@ -637,10 +676,22 @@ class ModuleReport(object): if "FIXED_ADDRESS" in ReportType and self.FileGuid: GlobalPredictionReport.GenerateReport(File, self.FileGuid) FileWrite(File, gSectionEnd) +def ReadMessage(From, To, ExitFlag): + while True: + # read one line a time + Line = From.readline() + # empty string means "end" + if Line != None and Line != "": + To(Line.rstrip()) + else: + break + if ExitFlag.isSet(): + break + ## # Reports platform and module PCD information # # This class reports the platform PCD section and module PCD subsection # in the build report file. @@ -1665,11 +1716,11 @@ class BuildReport(object): if ReportType: for ReportTypeItem in ReportType: if ReportTypeItem not in self.ReportType: self.ReportType.append(ReportTypeItem) else: - self.ReportType = ["PCD", "LIBRARY", "BUILD_FLAGS", "DEPEX", "FLASH", "FIXED_ADDRESS"] + self.ReportType = ["PCD", "LIBRARY", "BUILD_FLAGS", "DEPEX", "HASH", "FLASH", "FIXED_ADDRESS"] ## # Adds platform report to the list # # This function adds a platform report to the final report list. # diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py index 37afe52..37ce8e1 100644 --- a/BaseTools/Source/Python/build/build.py +++ b/BaseTools/Source/Python/build/build.py @@ -2103,12 +2103,12 @@ def MyOptionParser(): "and warning messages, etc.") Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.") Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".") Parser.add_option("-y", "--report-file", action="store", dest="ReportFile", help="Create/overwrite the report to the specified filename.") - Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD', 'LIBRARY', 'FLASH', 'DEPEX', 'BUILD_FLAGS', 'FIXED_ADDRESS', 'EXECUTION_ORDER'], dest="ReportType", default=[], - help="Flags that control the type of build report to generate. Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, EXECUTION_ORDER]. "\ + Parser.add_option("-Y", "--report-type", action="append", type="choice", choices=['PCD','LIBRARY','FLASH','DEPEX','BUILD_FLAGS','FIXED_ADDRESS','HASH','EXECUTION_ORDER'], dest="ReportType", default=[], + help="Flags that control the type of build report to generate. Must be one of: [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS, HASH, EXECUTION_ORDER]. "\ "To specify more than one flag, repeat this option on the command line and the default flag set is [PCD, LIBRARY, FLASH, DEPEX, BUILD_FLAGS, FIXED_ADDRESS]") Parser.add_option("-F", "--flag", action="store", type="string", dest="Flag", help="Specify the specific option to parse EDK UNI file. Must be one of: [-c, -s]. -c is for EDK framework UNI file, and -s is for EDK UEFI UNI file. "\ "This option can also be specified by setting *_*_*_BUILD_FLAGS in [BuildOptions] section of platform DSC. If they are both specified, this value "\ "will override the setting in [BuildOptions] section of platform DSC.") -- 2.6.1.windows.1 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

