From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.115, mailfrom: eric.jin@intel.com) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by groups.io with SMTP; Sun, 02 Jun 2019 21:46:31 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Jun 2019 21:46:31 -0700 X-ExtLoop1: 1 Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by fmsmga004.fm.intel.com with ESMTP; 02 Jun 2019 21:46:31 -0700 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.408.0; Sun, 2 Jun 2019 21:46:30 -0700 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.120]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.187]) with mapi id 14.03.0415.000; Mon, 3 Jun 2019 12:46:29 +0800 From: "Eric Jin" To: "Feng, Bob C" , "devel@edk2.groups.io" , "Jin, Eric" CC: "Gao, Liming" , "Kinney, Michael D" Subject: Re: [edk2-devel] [PATCH] BaseTools/Capsule: Tool to Generate Windows Firmware Update Driver Thread-Topic: [edk2-devel] [PATCH] BaseTools/Capsule: Tool to Generate Windows Firmware Update Driver Thread-Index: AQHVFSTl33YPThNlaEueZKPdNY3IzKaBqZ0wgAe6S4A= Date: Mon, 3 Jun 2019 04:46:27 +0000 Message-ID: References: <20190528071057.1196-1-eric.jin@intel.com> <08650203BA1BD64D8AD9B6D5D74A85D160117618@SHSMSX101.ccr.corp.intel.com> In-Reply-To: <08650203BA1BD64D8AD9B6D5D74A85D160117618@SHSMSX101.ccr.corp.intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMTg0YzdiMzAtNDg1Mi00NGMxLWJlN2EtOGY5OWY0ZDMzODkxIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiMmhpTWo4YllUVWVVWGtNcXc2NitnSVdoSUc2bFJcLytGMklRZ0N2SkR0OEgwMzFwd3VVanhQOUF2Nkg4VDgwVWIifQ== x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.600.7 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: eric.jin@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Bob, Thank for comment. V2 has been sent out to fix this. Best Regards Eric -----Original Message----- From: Feng, Bob C=20 Sent: Wednesday, May 29, 2019 2:47 PM To: devel@edk2.groups.io; Jin, Eric Cc: Gao, Liming ; Kinney, Michael D Subject: RE: [edk2-devel] [PATCH] BaseTools/Capsule: Tool to Generate Wind= ows Firmware Update Driver Hi Eric, Please use "with" statement for the open() calls. For example, Replace: Fd =3D open("file","w") Do something Fd.close To: With open("file","w") as fd: Do something Thanks, Bob -----Original Message----- From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Eric= Jin Sent: Tuesday, May 28, 2019 3:11 PM To: devel@edk2.groups.io Cc: Feng, Bob C ; Gao, Liming = ; Kinney, Michael D Subject: [edk2-devel] [PATCH] BaseTools/Capsule: Tool to Generate Windows = Firmware Update Driver https://bugzilla.tianocore.org/show_bug.cgi?id=3D1837 The tool is designed to generate Windows Firmware Update Drivers, the inpu= t is one drivername.cap with related parameters, the output Windows Driver = package are composed by drivername.cap, drivername.inf and drivername.cat t= o update the single payload in device. usage: GenerateWindowsDriver [-h] [--output-folder OUTPUTFOLDER] [--product-fmp-guid PRODUCTFMPGUID] [--capsuleversion-dotstring CAPSULEVERSION_DO= TSTRING] [--capsuleversion-hexstring CAPSULEVERSION_HE= XSTRING] [--product-fw-provider PRODUCTFWPROVIDER] [--product-fw-mfg-name PRODUCTFWMFGNAME] [--product-fw-desc PRODUCTFWDESC] [--capsule-file-name CAPSULEFILENAME] [--pfx-file PFXFILE] [--arch ARCH] [--operating-system-string OPERATINGSYSTEMSTR= ING] Cc: Bob Feng Cc: Liming Gao Cc: Kinney Michael D Signed-off-by: Eric Jin --- BaseTools/Source/Python/Capsule/CatGenerator.py | 155 ++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= + BaseTools/Source/Python/Capsule/GenerateWindowsDriver.py | 115 ++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++ BaseTools/Source/Python/Capsule/InfGenerator.py | 210 ++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BaseTools/Source/Python/Capsule/WindowsCapsuleSupportHelper.py | 102 ++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++ 4 files changed, 582 insertions(+) diff --git a/BaseTools/Source/Python/Capsule/CatGenerator.py b/BaseTools/S= ource/Python/Capsule/CatGenerator.py new file mode 100644 index 0000000000..737387c296 --- /dev/null +++ b/BaseTools/Source/Python/Capsule/CatGenerator.py @@ -0,0 +1,155 @@ +## @file + # Script to generate Cat files for capsule update based on supplied=20 +inf file # # Copyright (c) 2019, Microsoft Corporation # Copyright +(c) 2019, Intel Corporation. All rights reserved.
# +SPDX-License-Identifier: BSD-2-Clause-Patent # ## + +import os +import logging +import datetime +import subprocess +import threading + +class PropagatingThread(threading.Thread): + def run(self): + self.exc =3D None + try: + if hasattr(self, '_Thread__target'): + # Thread uses name mangling prior to Python 3. + self.ret =3D self._Thread__target(*self._Thread__args, **= self._Thread__kwargs) + else: + self.ret =3D self._target(*self._args, **self._kwargs) + except BaseException as e: + self.exc =3D e + def join(self, timeout=3DNone): + super(PropagatingThread, self).join() + if self.exc: + raise self.exc + return self.ret +def reader(filepath, outstream, stream): + f =3D None + # open file if caller provided path + if(filepath): + f =3D open(filepath, "w") + while True: + s =3D stream.readline().decode() + if not s: + stream.close() + break + if(f is not None): + # write to file if caller provided file + f.write(s) + if(outstream is not None): + # write to stream object if caller provided object + outstream.write(s) + logging.info(s.rstrip()) + if(f is not None): + f.close() +def RunCmd(cmd, parameters, capture=3DTrue, workingdir=3DNone, outfile=3D= None, outstream=3DNone, environ=3DNone): + cmd =3D cmd.strip('"\'') + if " " in cmd: + cmd =3D '"' + cmd + '"' + if parameters is not None: + parameters =3D parameters.strip() + cmd +=3D " " + parameters + starttime =3D datetime.datetime.now() + logging.info("Cmd to run is: " + cmd)=20 + logging.info("------------------------------------------------") + logging.info("--------------Cmd Output Starting---------------") + logging.info("------------------------------------------------") + c =3D subprocess.Popen(cmd, stdout=3Dsubprocess.PIPE, stderr=3Dsubpro= cess.STDOUT, cwd=3Dworkingdir, shell=3DTrue, env=3Denviron) + if(capture): + outr =3D PropagatingThread(target=3Dreader, args=3D(outfile, outs= tream, c.stdout,)) + outr.start() + outr.join() + c.wait() + else: + c.wait() + + endtime =3D datetime.datetime.now() + delta =3D endtime - starttime + logging.info("------------------------------------------------") + logging.info("--------------Cmd Output Finished---------------") + logging.info("--------- Running Time (mm:ss): {0[0]:02}:{0[1]:02} ---= -------".format(divmod(delta.seconds, 60))) + logging.info("------------------------------------------------") + return c.returncode + +class CatGenerator(object): + SUPPORTED_OS =3D {'win10': '10', + '10': '10', + '10_au': '10_AU', + '10_rs2': '10_RS2', + '10_rs3': '10_RS3', + '10_rs4': '10_RS4', + 'server10': 'Server10', + 'server2016': 'Server2016', + 'serverrs2': 'ServerRS2', + 'serverrs3': 'ServerRS3', + 'serverrs4': 'ServerRS4' + } + + def __init__(self, arch, os): + self.Arch =3D arch + self.OperatingSystem =3D os + + @property + def Arch(self): + return self._arch + + @Arch.setter + def Arch(self, value): + value =3D value.lower() + if(value =3D=3D "x64") or (value =3D=3D "amd64"): # support amd6= 4 value so INF and CAT tools can use same arch value + self._arch =3D "X64" + elif(value =3D=3D "arm"): + self._arch =3D "ARM" + elif(value =3D=3D "arm64") or (value =3D=3D "aarch64"): # suppor= t UEFI defined aarch64 value as well + self._arch =3D "ARM64" + else: + logging.critical("Unsupported Architecture: %s", value) + raise ValueError("Unsupported Architecture") + + @property + def OperatingSystem(self): + return self._operatingsystem + + @OperatingSystem.setter + def OperatingSystem(self, value): + key =3D value.lower() + if(key not in CatGenerator.SUPPORTED_OS.keys()): + logging.critical("Unsupported Operating System: %s", key) + raise ValueError("Unsupported Operating System") + self._operatingsystem =3D CatGenerator.SUPPORTED_OS[key] + + def MakeCat(self, OutputCatFile, PathToInf2CatTool=3DNone): + # Find Inf2Cat tool + if(PathToInf2CatTool is None): + PathToInf2CatTool =3D os.path.join(os.getenv("ProgramFiles(x8= 6)"), "Windows Kits", "10", + "bin", "x86", "Inf2Cat.exe") + if not os.path.exists(PathToInf2CatTool): + logging.debug("Windows Kit 10 not Found....trying 8.1") + # Try 8.1 kit + PathToInf2CatTool.replace("10", "8.1") + + # check if exists + if not os.path.exists(PathToInf2CatTool): + raise Exception("Can't find Inf2Cat on this machine. Please = install the Windows 10 WDK - " + + "https://developer.microsoft.com/en-us/windows/hardware/windows-driver + -kit") + + # Adjust for spaces in the path (when calling the command). + if " " in PathToInf2CatTool: + PathToInf2CatTool =3D '"' + PathToInf2CatTool + '"' + + OutputFolder =3D os.path.dirname(OutputCatFile) + # Make Cat file + cmd =3D "/driver:. /os:" + self.OperatingSystem + "_" + self.Arch= + " /verbose" + ret =3D RunCmd(PathToInf2CatTool, cmd, workingdir=3DOutputFolder) + if(ret !=3D 0): + raise Exception("Creating Cat file Failed with errorcode %d" = % ret) + if(not os.path.isfile(OutputCatFile)): + raise Exception("CAT file (%s) not created" % + OutputCatFile) + + return 0 diff --git a/BaseTools/Source/Python/Capsule/GenerateWindowsDriver.py b/Ba= seTools/Source/Python/Capsule/GenerateWindowsDriver.py new file mode 100644 index 0000000000..1d543b3fca --- /dev/null +++ b/BaseTools/Source/Python/Capsule/GenerateWindowsDriver.py @@ -0,0 +1,115 @@ +## @file +# Generate a capsule windows driver. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
# +SPDX-License-Identifier: BSD-2-Clause-Patent # + +''' +GenerateWindowsDriver +''' + +import sys +import argparse +import uuid +import struct +import subprocess +import os +import tempfile +import shutil +import platform +import re +import logging +from WindowsCapsuleSupportHelper import WindowsCapsuleSupportHelper + +# +# Globals for help information +# +__prog__ =3D 'GenerateWindowsDriver' +__version__ =3D '0.0' +__copyright__ =3D 'Copyright (c) 2019, Intel Corporation. All rights re= served.' +__description__ =3D 'Generate Capsule Windows Driver.\n' + + +if __name__ =3D=3D '__main__': + def convert_arg_line_to_args(arg_line): + for arg in arg_line.split(): + if not arg.strip(): + continue + yield arg + + parser =3D argparse.ArgumentParser ( + prog =3D __prog__, + description =3D __description__ + __copyright__, + conflict_handler =3D 'resolve', + fromfile_prefix_chars =3D '@' + ) + parser.convert_arg_line_to_args =3D convert_arg_line_to_args + parser.add_argument("--output-folder", dest =3D 'OutputFolder', help = = =3D "firmware resource update driver package output folder.") + parser.add_argument("--product-fmp-guid", dest =3D 'ProductFmpGuid', = help =3D "firmware GUID of resource update driver package") + parser.add_argument("--capsuleversion-dotstring", dest =3D 'CapsuleVe= rsion_DotString', help =3D "firmware version with date on which update driv= er package is authored") + parser.add_argument("--capsuleversion-hexstring", dest =3D 'CapsuleVe= rsion_HexString', help =3D "firmware version in Hex of update driver packag= e") + parser.add_argument("--product-fw-provider", dest =3D 'ProductFwProvi= der', help =3D "vendor/provider of entire firmware resource update driver p= ackage") + parser.add_argument("--product-fw-mfg-name", dest =3D 'ProductFwMfgNa= me', help =3D "manufacturer/vendor of firmware resource update driver packa= ge") + parser.add_argument("--product-fw-desc", dest =3D "ProductFwDesc", he= lp =3D "description about resource update driver") + parser.add_argument("--capsule-file-name", dest =3D 'CapsuleFileName'= , help =3D"firmware resource image file") + parser.add_argument("--pfx-file", dest =3D 'PfxFile', help =3D "pfx f= ile path used to sign resource update driver") + parser.add_argument("--arch", dest =3D 'Arch', help =3D "supported ar= chitecture:arm/x64/amd64/arm64/aarch64", default =3D 'amd64') + parser.add_argument("--operating-system-string", dest =3D=20 + 'OperatingSystemString', help =3D "supported operating=20 + system:win10/10/10_au/10_rs2/10_rs3/10_rs4/server10/server2016/serverr + s2/serverrs3/serverrs4", default =3D "win10") + + def ArgCheck(args): + Version =3D args.CapsuleVersion_DotString.split('.') + + if len(Version) !=3D 4: + logging.critical("Name invalid: '%s'", args.CapsuleVersion_Do= tString) + raise ValueError("Name invalid.") + for sub in Version: + if int(sub) > 65536: + logging.critical("Name invalid: '%s'", args.CapsuleVersio= n_DotString) + raise ValueError("Name exceed limit 65536.") + + if not (re.compile(r'[0-9.]*$')).match(args.CapsuleVersion_DotStr= ing): + logging.critical("Name invalid: '%s'", args.CapsuleVersion_Do= tString) + raise ValueError("Name has invalid chars.") + + def CapsuleGuidCheck(InputFile, Guid): + TempCapDecode =3D 'TempCapDecode.txt' + Command =3D 'python GenerateCapsule.py "' + InputFile + '" --dump= -info >' + TempCapDecode + os.system (Command) + with open(TempCapDecode, 'rb') as f: + for line in f: + if re.search(b'UpdateImageTypeId', line, re.M|re.I): + CapGuid =3D str(line).split('=3D ')[1][:-5] + break + f.close() + os.remove(TempCapDecode) + if (Guid !=3D CapGuid): + print('GenerateWindowsDriver error: Different Guid from C= apsule') + sys.exit(1) + + args =3D parser.parse_args() + + InputFile =3D os.path.join(args.OutputFolder, '') +=20 + args.CapsuleFileName + + ProductName =3D args.CapsuleFileName.strip('.cap') + WindowsDriver =3D WindowsCapsuleSupportHelper () + + ArgCheck(args) + CapsuleGuidCheck(InputFile, args.ProductFmpGuid) + + WindowsDriver.PackageWindowsCapsuleFiles ( + args.OutputFolder, + ProductName, + args.ProductFmpGuid, + args.CapsuleVersion_Do= tString, + args.CapsuleVersion_He= xString, + args.ProductFwProvider= , + args.ProductFwMfgName, + args.ProductFwDesc, + args.CapsuleFileName, + args.PfxFile, + None, + None, + args.Arch, + args.OperatingSystemSt= ring + ) diff --git a/BaseTools/Source/Python/Capsule/InfGenerator.py b/BaseTools/S= ource/Python/Capsule/InfGenerator.py new file mode 100644 index 0000000000..508bbed0ef --- /dev/null +++ b/BaseTools/Source/Python/Capsule/InfGenerator.py @@ -0,0 +1,210 @@ +## @file + # Script to generate inf files for capsule update based on INF=20 +TEMPLATE and # supplied information (Name, Version, ESRT Guid,=20 +Rollback, etc.) # # Copyright (c) 2019, Microsoft Corporation #=20 +Copyright (c) 2019, Intel Corporation. All rights reserved.
# +SPDX-License-Identifier: BSD-2-Clause-Patent ## + +import os +import logging +import datetime +import re +import uuid + + +##### +# +##### +class InfGenerator(object): + + ### INF Template ### + TEMPLATE =3D r"""; +; {Name}.inf +; {DriverVersion} +; Copyright (C) 2019 Microsoft Corporation. All Rights Reserved. +; +[Version] +Signature=3D"$WINDOWS NT$" +Class=3DFirmware +ClassGuid=3D{{f2e7dd72-6468-4e36-b6f1-6488f42c1b52}} +Provider=3D%Provider% +DriverVer=3D{Date},{DriverVersion} +PnpLockdown=3D1 +CatalogFile=3D{Name}.cat +[Manufacturer] +%MfgName% =3D Firmware,NT{Arch} +[Firmware.NT{Arch}] +%FirmwareDesc% =3D Firmware_Install,UEFI\RES_{{{EsrtGuid}}} +[Firmware_Install.NT] +CopyFiles =3D Firmware_CopyFiles +{Rollback} +[Firmware_CopyFiles] +{FirmwareBinFile} +[Firmware_Install.NT.Hw] +AddReg =3D Firmware_AddReg +[Firmware_AddReg] +HKR,,FirmwareId,,{{{EsrtGuid}}} +HKR,,FirmwareVersion,%REG_DWORD%,{VersionHexString} +HKR,,FirmwareFilename,,{FirmwareBinFile} +[SourceDisksNames] +1 =3D %DiskName% +[SourceDisksFiles] +{FirmwareBinFile} =3D 1 +[DestinationDirs] +DefaultDestDir =3D %DIRID_WINDOWS%,Firmware ; %SystemRoot%\Firmware=20 +[Strings] ; localizable +Provider =3D "{Provider}" +MfgName =3D "{MfgName}" +FirmwareDesc =3D "{Description}" +DiskName =3D "Firmware Update" +; non-localizable +DIRID_WINDOWS =3D 10 +REG_DWORD =3D 0x00010001 +""" + + ROLLBACKTEMPLATE =3D r"""AddReg =3D Firmware_DowngradePolicy_Addre= g + ;override firmware resource update policy to allow downgrade to lower= =20 + version [Firmware_DowngradePolicy_Addreg] + + HKLM,SYSTEM\CurrentControlSet\Control\FirmwareResources\{{{EsrtGuid}}} + ,Policy,%REG_DWORD%,1 + """ + + SUPPORTED_ARCH =3D {'amd64': 'amd64', + 'x64': 'amd64', + 'arm': 'arm', + 'arm64': 'ARM64', + 'aarch64': 'ARM64' + } + + def __init__(self, name_string, provider, esrt_guid, arch, descriptio= n_string, version_string, version_hex): + self.Name =3D name_string + self.Provider =3D provider + self.EsrtGuid =3D esrt_guid + self.Arch =3D arch + self.Description =3D description_string + self.VersionString =3D version_string + self.VersionHex =3D version_hex + self._manufacturer =3D None # default for optional feature + self._date =3D datetime.date.today() + + @property + def Name(self): + return self._name + + @Name.setter + def Name(self, value): + # test here for invalid chars + if not (re.compile(r'[\w-]*$')).match(value): + logging.critical("Name invalid: '%s'", value) + raise ValueError("Name has invalid chars.") + self._name =3D value + + @property + def Provider(self): + return self._provider + + @Provider.setter + def Provider(self, value): + self._provider =3D value + + @property + def Manufacturer(self): + if(self._manufacturer is None): + return self.Provider + + return self._manufacturer + + @Manufacturer.setter + def Manufacturer(self, value): + self._manufacturer =3D value + + @property + def Description(self): + return self._description + + @Description.setter + def Description(self, value): + self._description =3D value + + @property + def EsrtGuid(self): + return self._esrtguid + + @EsrtGuid.setter + def EsrtGuid(self, value): + uuid.UUID(value) # if this works it is valid...otherwise throws = exception + # todo - make sure it is formatted exactly right + self._esrtguid =3D value + + @property + def VersionString(self): + return self._versionstring + + @VersionString.setter + def VersionString(self, value): + c =3D value.count(".") + if(c < 1) or (c > 3): + logging.critical("Version string in invalid format.") + raise ValueError("VersionString must be in format of xx.xx ->= xx.xx.xx.xx") + self._versionstring =3D value + + @property + def VersionHex(self): + return "0x%08X" % self._versionhex + + @VersionHex.setter + def VersionHex(self, value): + a =3D int(value, 0) + if(a > 0xFFFFFFFF): + logging.critical("VersionHex invalid: '%s'", value) + raise ValueError("VersionHex must fit within 32bit value rang= e for unsigned integer") + self._versionhex =3D a + + @property + def Arch(self): + return self._arch + + @Arch.setter + def Arch(self, value): + key =3D value.lower() + if(key not in InfGenerator.SUPPORTED_ARCH.keys()): + logging.critical("Arch invalid: '%s'", value) + raise ValueError("Unsupported Architecture") + self._arch =3D InfGenerator.SUPPORTED_ARCH[key] + + @property + def Date(self): + return self._date.strftime("%m/%d/%Y") + + @Date.setter + def Date(self, value): + if(not isinstance(value, datetime.date)): + raise ValueError("Date must be a datetime.date object") + self._date =3D value + + def MakeInf(self, OutputInfFilePath, FirmwareBinFileName, Rollback=3D= False): + RollbackString =3D "" + if(Rollback): + RollbackString =3D + InfGenerator.ROLLBACKTEMPLATE.format(EsrtGuid=3Dself.EsrtGuid) + + binfilename =3D os.path.basename(FirmwareBinFileName) + + Content =3D InfGenerator.TEMPLATE.format( + Name=3Dself.Name, + Date=3Dself.Date, + Arch=3Dself.Arch, + DriverVersion=3Dself.VersionString, + EsrtGuid=3Dself.EsrtGuid, + FirmwareBinFile=3Dbinfilename, + VersionHexString=3Dself.VersionHex, + Provider=3Dself.Provider, + MfgName=3Dself.Manufacturer, + Description=3Dself.Description, + Rollback=3DRollbackString) + + with open(OutputInfFilePath, "w") as f: + f.write(Content) + + return 0 diff --git a/BaseTools/Source/Python/Capsule/WindowsCapsuleSupportHelper.p= y b/BaseTools/Source/Python/Capsule/WindowsCapsuleSupportHelper.py new file mode 100644 index 0000000000..69992e2c08 --- /dev/null +++ b/BaseTools/Source/Python/Capsule/WindowsCapsuleSupportHelper.py @@ -0,0 +1,102 @@ +## +# UefiBuild Plugin that supports Window Capsule files based on the #=20 +Windows Firmware Update Platform spec. +# Creates INF, Cat, and then signs it +# +# +# Copyright (c) 2018, Microsoft Corporation # Copyright (c) 2019, Intel= =20 +Corporation. All rights reserved.
# SPDX-License-Identifier: +BSD-2-Clause-Patent ## + +import sys +import re +import datetime +import os +import logging +from CatGenerator import CatGenerator +from InfGenerator import InfGenerator +from CatGenerator import RunCmd + +def CatalogSignWithSignTool(SignToolPath, ToSignFilePath, PfxFilePath, Pf= xPass=3DNone): + # check signtool path + if not os.path.exists(SignToolPath): + logging.error("Path to signtool invalid. %s" % SignToolPath) + return -1 + + # Adjust for spaces in the path (when calling the command). + if " " in SignToolPath: + SignToolPath =3D '"' + SignToolPath + '"' + + OutputDir =3D os.path.dirname(ToSignFilePath) + # Signtool docs https://docs.microsoft.com/en-us/dotnet/framework/too= ls/signtool-exe + # todo: link to catalog signing documentation + params =3D "sign /a /fd SHA256 /f " + PfxFilePath + if PfxPass is not None: + # add password if set + params =3D params + ' /p ' + PfxPass + params =3D params + ' /debug /v "' + ToSignFilePath + '" ' + ret =3D RunCmd(SignToolPath, params, workingdir=3DOutputDir) + if(ret !=3D 0): + logging.error("Signtool failed %d" % ret) + return ret + +class WindowsCapsuleSupportHelper(object): + @staticmethod + def _LocateLatestWindowsKits(): + result =3D None + + # Start with a base path and use it to start locating the ideal d= irectory. + base_path =3D os.path.join(os.getenv("ProgramFiles(x86)"), + "Windows Kits") + + # Check for Win 10 kits first. + base_10_path =3D os.path.join(base_path, "10", "bin") + if os.path.isdir(base_10_path): + # If you can find one of the new kit paths, use it. + # Walk backwards to test the most recent kit first. + for sub_path in reversed(os.listdir(base_10_path)): + if sub_path.startswith("10.") and os.path.isdir(os.path.j= oin(base_10_path, sub_path, "x64")): + result =3D os.path.join(base_10_path, sub_path, "x64"= ) + break + + # Otherwise, fall back to the legacy path. + if not result and os.path.isdir(os.path.join(base_10_path, "x= 64")): + result =3D os.path.join(base_10_path, "x64") + # If not, fall back to Win 8.1. + elif os.path.isdir(os.path.join(base_path, "8.1", "bin", "x64")): + result =3D os.path.join(base_path, "8.1", "bin", "x64") + return result + + def RegisterHelpers(self, obj): + fp =3D os.path.abspath(__file__) + obj.Register("PackageWindowsCapsuleFiles", + WindowsCapsuleSupportHelper.PackageWindowsCapsuleFiles, fp) + + + @staticmethod + def PackageWindowsCapsuleFiles(OutputFolder, ProductName, ProductFmpG= uid, CapsuleVersion_DotString,CapsuleVersion_HexString, ProductFwProvider, = ProductFwMfgName, ProductFwDesc, CapsuleFileName, PfxFile=3DNone, PfxPass= =3DNone, Rollback=3DFalse, Arch=3D'amd64', OperatingSystem_String=3D'Win10= '): + logging.debug("CapsulePackage: Create Windows Capsule Files") + #Make INF + InfFilePath =3D os.path.join(OutputFolder, ProductName + ".inf") + InfTool =3D InfGenerator(ProductName, ProductFwProvider, ProductF= mpGuid, Arch, ProductFwDesc, CapsuleVersion_DotString, CapsuleVersion_HexSt= ring) + InfTool.Manufacturer =3D ProductFwMfgName #optional + ret =3D InfTool.MakeInf(InfFilePath, CapsuleFileName, Rollback) + if(ret !=3D 0): + raise Exception("CreateWindowsInf Failed with errorcode %d" %= ret) + #Make CAT + CatFilePath =3D os.path.realpath(os.path.join(OutputFolder, Produ= ctName + ".cat")) + CatTool =3D CatGenerator(Arch, OperatingSystem_String) + ret =3D CatTool.MakeCat(CatFilePath) + + if(ret !=3D 0): + raise Exception("Creating Cat file Failed with errorcode %d" = % ret) + if(PfxFile is not None): + #Find Signtool + WinKitsPath =3D WindowsCapsuleSupportHelper._LocateLatestWind= owsKits() + SignToolPath =3D os.path.join(WinKitsPath, "signtool.exe") + if not os.path.exists(SignToolPath): + raise Exception("Can't find signtool on this machine.") + #dev sign the cat file + ret =3D CatalogSignWithSignTool(SignToolPath, CatFilePath, Pf= xFile, PfxPass) + if(ret !=3D 0): + raise Exception("Signing Cat file Failed with errorcode %= d" % ret) + return ret -- 2.20.1.windows.1