X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2Fbuild%2FBuildReport.py;h=4c57754b3b1eea42fe9ae0c5e24a26702fe91a0d;hb=71f5913eb9127305dc6ec63936c3c283975d86c0;hp=2dc02c2c4e056ecf792e3c0dbd0573440aa40c32;hpb=763e8edf610b2ccf422986c81ee36b4733560cdb;p=mirror_edk2.git diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py index 2dc02c2c4e..4c57754b3b 100644 --- a/BaseTools/Source/Python/build/BuildReport.py +++ b/BaseTools/Source/Python/build/BuildReport.py @@ -24,6 +24,9 @@ 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 @@ -33,6 +36,7 @@ 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 @@ -43,6 +47,9 @@ from Common.DataType import TAB_BACK_SLASH from Common.LongFilePathSupport import OpenLongFilePath as open from Common.MultipleWorkspace import MultipleWorkspace as mws import Common.GlobalData as GlobalData +from AutoGen.AutoGen import ModuleAutoGen +from Common.Misc import PathClass +from Common.String import NormPath ## Pattern to extract contents in EDK DXS files gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL) @@ -528,6 +535,7 @@ class ModuleReport(object): self.FileGuid = M.Guid self.Size = 0 self.BuildTimeStamp = None + self.Hash = 0 self.DriverType = "" if not M.IsLibrary: ModuleType = M.ModuleType @@ -599,12 +607,46 @@ class ModuleReport(object): 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: @@ -639,6 +681,18 @@ class ModuleReport(object): 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 # @@ -658,6 +712,8 @@ class PcdReport(object): # def __init__(self, Wa): self.AllPcds = {} + self.UnusedPcds = {} + self.ConditionalPcds = {} self.MaxLen = 0 if Wa.FdfProfile: self.FdfPcdSet = Wa.FdfProfile.PcdDict @@ -676,6 +732,63 @@ class PcdReport(object): PcdList.append(Pcd) if len(Pcd.TokenCName) > self.MaxLen: self.MaxLen = len(Pcd.TokenCName) + # + # Collect the PCD defined in DSC/FDF file, but not used in module + # + UnusedPcdFullList = [] + for item in Pa.Platform.Pcds: + Pcd = Pa.Platform.Pcds[item] + if not Pcd.Type: + PcdTypeFlag = False + for package in Pa.PackageList: + for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]: + if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, T) in package.Pcds: + Pcd.Type = T + PcdTypeFlag = True + if not Pcd.DatumType: + Pcd.DatumType = package.Pcds[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName, T)].DatumType + break + if PcdTypeFlag: + break + if not Pcd.DatumType: + PcdType = Pcd.Type + # Try to remove Hii and Vpd suffix + if PcdType.startswith("DynamicEx"): + PcdType = "DynamicEx" + elif PcdType.startswith("Dynamic"): + PcdType = "Dynamic" + for package in Pa.PackageList: + if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, PcdType) in package.Pcds: + Pcd.DatumType = package.Pcds[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName, PcdType)].DatumType + break + + PcdList = self.AllPcds.setdefault(Pcd.TokenSpaceGuidCName, {}).setdefault(Pcd.Type, []) + if Pcd not in PcdList and Pcd not in UnusedPcdFullList: + UnusedPcdFullList.append(Pcd) + if len(Pcd.TokenCName) > self.MaxLen: + self.MaxLen = len(Pcd.TokenCName) + + if GlobalData.gConditionalPcds: + for PcdItem in GlobalData.gConditionalPcds: + if '.' in PcdItem: + (TokenSpaceGuidCName, TokenCName) = PcdItem.split('.') + if (TokenCName, TokenSpaceGuidCName) in Pa.Platform.Pcds.keys(): + Pcd = Pa.Platform.Pcds[(TokenCName, TokenSpaceGuidCName)] + PcdList = self.ConditionalPcds.setdefault(Pcd.TokenSpaceGuidCName, {}).setdefault(Pcd.Type, []) + if Pcd not in PcdList: + PcdList.append(Pcd) + + UnusedPcdList = [] + if UnusedPcdFullList: + for Pcd in UnusedPcdFullList: + if Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName in GlobalData.gConditionalPcds: + continue + UnusedPcdList.append(Pcd) + + for Pcd in UnusedPcdList: + PcdList = self.UnusedPcds.setdefault(Pcd.TokenSpaceGuidCName, {}).setdefault(Pcd.Type, []) + if Pcd not in PcdList: + PcdList.append(Pcd) for Module in Pa.Platform.Modules.values(): # @@ -709,6 +822,13 @@ class PcdReport(object): if DscDefaultValue: self.DscPcdDefault[(TokenCName, TokenSpaceGuidCName)] = DscDefaultValue + def GenerateReport(self, File, ModulePcdSet): + if self.ConditionalPcds: + self.GenerateReportDetail(File, ModulePcdSet, 1) + if self.UnusedPcds: + self.GenerateReportDetail(File, ModulePcdSet, 2) + self.GenerateReportDetail(File, ModulePcdSet) + ## # Generate report for PCD information # @@ -719,39 +839,52 @@ class PcdReport(object): # @param File The file object for report # @param ModulePcdSet Set of all PCDs referenced by module or None for # platform PCD report + # @param ReportySubType 0 means platform/module PCD report, 1 means Conditional + # directives section report, 2 means Unused Pcds section report # @param DscOverridePcds Module DSC override PCDs set # - def GenerateReport(self, File, ModulePcdSet): + def GenerateReportDetail(self, File, ModulePcdSet, ReportSubType = 0): + PcdDict = self.AllPcds + if ReportSubType == 1: + PcdDict = self.ConditionalPcds + elif ReportSubType == 2: + PcdDict = self.UnusedPcds + if ModulePcdSet == None: - # - # For platform global PCD section - # FileWrite(File, gSectionStart) - FileWrite(File, "Platform Configuration Database Report") + if ReportSubType == 1: + FileWrite(File, "Conditional Directives used by the build system") + elif ReportSubType == 2: + FileWrite(File, "PCDs not used by modules or in conditional directives") + else: + FileWrite(File, "Platform Configuration Database Report") + FileWrite(File, " *B - PCD override in the build option") FileWrite(File, " *P - Platform scoped PCD override in DSC file") FileWrite(File, " *F - Platform scoped PCD override in FDF file") - FileWrite(File, " *M - Module scoped PCD override") + if not ReportSubType: + FileWrite(File, " *M - Module scoped PCD override") FileWrite(File, gSectionSep) else: - # - # For module PCD sub-section - # - FileWrite(File, gSubSectionStart) - FileWrite(File, TAB_BRG_PCD) - FileWrite(File, gSubSectionSep) + if not ReportSubType: + # + # For module PCD sub-section + # + FileWrite(File, gSubSectionStart) + FileWrite(File, TAB_BRG_PCD) + FileWrite(File, gSubSectionSep) - for Key in self.AllPcds: + for Key in PcdDict: # # Group PCD by their token space GUID C Name # First = True - for Type in self.AllPcds[Key]: + for Type in PcdDict[Key]: # # Group PCD by their usage type # TypeName, DecType = gPcdTypeMap.get(Type, ("", Type)) - for Pcd in self.AllPcds[Key][Type]: + for Pcd in PcdDict[Key][Type]: # # Get PCD default value and their override relationship # @@ -869,7 +1002,8 @@ class PcdReport(object): if ModulePcdSet == None: FileWrite(File, gSectionEnd) else: - FileWrite(File, gSubSectionEnd) + if not ReportSubType: + FileWrite(File, gSubSectionEnd) @@ -1516,8 +1650,21 @@ class PlatformReport(object): else: self._IsModuleBuild = False for Pa in Wa.AutoGenObjectList: + ModuleAutoGenList = [] for ModuleKey in Pa.Platform.Modules: - self.ModuleReportList.append(ModuleReport(Pa.Platform.Modules[ModuleKey].M, ReportType)) + ModuleAutoGenList.append(Pa.Platform.Modules[ModuleKey].M) + if GlobalData.gFdfParser != None: + if Pa.Arch in GlobalData.gFdfParser.Profile.InfDict: + INFList = GlobalData.gFdfParser.Profile.InfDict[Pa.Arch] + for InfName in INFList: + InfClass = PathClass(NormPath(InfName), Wa.WorkspaceDir, Pa.Arch) + Ma = ModuleAutoGen(Wa, InfClass, Pa.BuildTarget, Pa.ToolChain, Pa.Arch, Wa.MetaFile) + if Ma == None: + continue + if Ma not in ModuleAutoGenList: + ModuleAutoGenList.append(Ma) + for MGen in ModuleAutoGenList: + self.ModuleReportList.append(ModuleReport(MGen, ReportType)) @@ -1545,6 +1692,14 @@ class PlatformReport(object): FileWrite(File, "Build Duration: %s" % BuildDuration) FileWrite(File, "Report Content: %s" % ", ".join(ReportType)) + if GlobalData.MixedPcd: + FileWrite(File, gSectionStart) + FileWrite(File, "The following PCDs use different access methods:") + FileWrite(File, gSectionSep) + for PcdItem in GlobalData.MixedPcd: + FileWrite(File, "%s.%s" % (str(PcdItem[1]), str(PcdItem[0]))) + FileWrite(File, gSectionEnd) + if not self._IsModuleBuild: if "PCD" in ReportType: self.PcdReport.GenerateReport(File, None) @@ -1587,7 +1742,7 @@ class BuildReport(object): 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 #