From nobody Sat Apr 27 13:09:17 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41454+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41454+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559027621; cv=none; d=zoho.com; s=zohoarc; b=ZvgTJF9lavghXtbvpl4jReMP4JtIFJzLQrwKZFFEtJ9N+QOSStPVBXhz27Utu4/0nRJR9hQGT8uvkJoK6GL31EGBTxcMZO/Jyy/3F7TuAl5XGjJeLroSd9rhPHDngNjG5wheD3PwdiOV+pg6RxGlwgD3aLuKhoBVcxvQicCAtKw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559027621; h=Content-Transfer-Encoding:Cc:Date:From:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To:ARC-Authentication-Results; bh=gg00gqnVyJNTuJLvb/RoTumRIZeYcLUvCs92TlEWggE=; b=RSQ6GVv/JjEff4ZoKEBaphOLcEdv2S8f3ctU0gtNFNVO/uAFZ4D1VkqEpzE8TookbIU+j/S9TpNDMA2zhiUP/w7erSyJyx9ElGzigoIkU7MZT6wUH4VXb5rjxRM1GyiGZiGmMkHLk8t2VzPqAJKXxMMBj3l+eHiHEWNRoQExYyg= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41454+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1559027621084816.2605289974665; Tue, 28 May 2019 00:13:41 -0700 (PDT) Return-Path: X-Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by groups.io with SMTP; Tue, 28 May 2019 00:13:39 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 May 2019 00:13:39 -0700 X-ExtLoop1: 1 X-Received: from jjin9-mobl.ccr.corp.intel.com ([10.239.192.131]) by orsmga004.jf.intel.com with ESMTP; 28 May 2019 00:13:37 -0700 From: "Eric Jin" To: devel@edk2.groups.io Cc: Bob Feng , Liming Gao , Kinney Michael D Subject: [edk2-devel] [PATCH] BaseTools/Capsule: Tool to Generate Windows Firmware Update Driver Date: Tue, 28 May 2019 15:10:57 +0800 Message-Id: <20190528071057.1196-1-eric.jin@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,eric.jin@intel.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559027620; bh=rPg2GS8Fk18CEsvCbKiXoimDmirwX5m+GZv1G762gmA=; h=Cc:Date:From:Reply-To:Subject:To; b=UPI7jtZIBszfJDc6SrFuPK+LX4EKcZFSYNjKWqOCDzgpJEwbicPH7wiQ+CzQt4qSCN7 bldXaiMf4FIK2Rrsic2oRLklCNDEi4WMct9nZ3hwPnbsX6FYmIqhMNE3QlunHSTKCuhQF ZSWEWto0VmnGu01mYh2tWXas4F8EuZm5O8M= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" https://bugzilla.tianocore.org/show_bug.cgi?id=3D1837 The tool is designed to generate Windows Firmware Update Drivers, the input is one drivername.cap with related parameters, the output Windows Driver package are composed by drivername.cap, drivername.inf and drivername.cat to update the single payload in device. usage: GenerateWindowsDriver [-h] [--output-folder OUTPUTFOLDER] [--product-fmp-guid PRODUCTFMPGUID] [--capsuleversion-dotstring CAPSULEVERSION_DOT= STRING] [--capsuleversion-hexstring CAPSULEVERSION_HEX= STRING] [--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 OPERATINGSYSTEMSTRI= NG] 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/So= urce/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 inf f= ile + # + # 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, **s= elf._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=3DN= one, 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=3Dsubproc= ess.STDOUT, cwd=3Dworkingdir, shell=3DTrue, env=3Denviron) + if(capture): + outr =3D PropagatingThread(target=3Dreader, args=3D(outfile, outst= ream, c.stdout,)) + outr.start() + outr.join() + c.wait() + else: + c.wait() + =20 + 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 amd64= 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"): # support= 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(x86= )"), "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 i= nstall 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/Bas= eTools/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 res= erved.' +__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', h= elp =3D "firmware GUID of resource update driver package") + parser.add_argument("--capsuleversion-dotstring", dest =3D 'CapsuleVer= sion_DotString', help =3D "firmware version with date on which update drive= r package is authored") + parser.add_argument("--capsuleversion-hexstring", dest =3D 'CapsuleVer= sion_HexString', help =3D "firmware version in Hex of update driver package= ") + parser.add_argument("--product-fw-provider", dest =3D 'ProductFwProvid= er', help =3D "vendor/provider of entire firmware resource update driver pa= ckage") + parser.add_argument("--product-fw-mfg-name", dest =3D 'ProductFwMfgNam= e', help =3D "manufacturer/vendor of firmware resource update driver packag= e") + parser.add_argument("--product-fw-desc", dest =3D "ProductFwDesc", hel= p =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 fi= le path used to sign resource update driver") + parser.add_argument("--arch", dest =3D 'Arch', help =3D "supported arc= hitecture:arm/x64/amd64/arm64/aarch64", default =3D 'amd64') + parser.add_argument("--operating-system-string", dest =3D 'OperatingSy= stemString', help =3D "supported operating system:win10/10/10_au/10_rs2/10_= rs3/10_rs4/server10/server2016/serverrs2/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_Dot= String) + raise ValueError("Name invalid.") + for sub in Version: + if int(sub) > 65536: + logging.critical("Name invalid: '%s'", args.CapsuleVersion= _DotString) + raise ValueError("Name exceed limit 65536.") + + if not (re.compile(r'[0-9.]*$')).match(args.CapsuleVersion_DotStri= ng): + logging.critical("Name invalid: '%s'", args.CapsuleVersion_Dot= String) + 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 Ca= psule') + sys.exit(1) + + args =3D parser.parse_args() + + InputFile =3D os.path.join(args.OutputFolder, '') + args.CapsuleFileNa= me + + ProductName =3D args.CapsuleFileName.strip('.cap') + WindowsDriver =3D WindowsCapsuleSupportHelper () + + ArgCheck(args) + CapsuleGuidCheck(InputFile, args.ProductFmpGuid) + + WindowsDriver.PackageWindowsCapsuleFiles ( + args.OutputFolder, + ProductName, + args.ProductFmpGuid, + args.CapsuleVersion_Dot= String, + args.CapsuleVersion_Hex= String, + args.ProductFwProvider, + args.ProductFwMfgName, + args.ProductFwDesc, + args.CapsuleFileName, + args.PfxFile, + None, + None, + args.Arch, + args.OperatingSystemStr= ing + ) diff --git a/BaseTools/Source/Python/Capsule/InfGenerator.py b/BaseTools/So= urce/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 TEMPLATE a= nd + # supplied information (Name, Version, ESRT Guid, Rollback, etc.) + # + # 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 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 +[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_Addreg + ;override firmware resource update policy to allow downgrade to lower ve= rsion + [Firmware_DowngradePolicy_Addreg] + HKLM,SYSTEM\CurrentControlSet\Control\FirmwareResources\{{{EsrtGuid}}},P= olicy,%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, description= _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 e= xception + # 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 range= 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=3DF= alse): + RollbackString =3D "" + if(Rollback): + RollbackString =3D InfGenerator.ROLLBACKTEMPLATE.format(EsrtGu= id=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.py= 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 +# Windows Firmware Update Platform spec. +# Creates INF, Cat, and then signs it +# +# +# Copyright (c) 2018, Microsoft Corporation +# Copyright (c) 2019, Intel 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, Pfx= Pass=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/tool= s/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 + =20 + # Start with a base path and use it to start locating the ideal di= rectory. + base_path =3D os.path.join(os.getenv("ProgramFiles(x86)"), "Window= s Kits") + =20 + # 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.jo= in(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, "x6= 4")): + 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", WindowsCapsuleSupportHe= lper.PackageWindowsCapsuleFiles, fp) + + + @staticmethod + def PackageWindowsCapsuleFiles(OutputFolder, ProductName, ProductFmpGu= id, CapsuleVersion_DotString,CapsuleVersion_HexString, ProductFwProvider, P= roductFwMfgName, ProductFwDesc, CapsuleFileName, PfxFile=3DNone, PfxPass=3D= None, 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, ProductFm= pGuid, Arch, ProductFwDesc, CapsuleVersion_DotString, CapsuleVersion_HexStr= ing) + 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, Produc= tName + ".cat")) + CatTool =3D CatGenerator(Arch, OperatingSystem_String) + ret =3D CatTool.MakeCat(CatFilePath) + =20 + if(ret !=3D 0): + raise Exception("Creating Cat file Failed with errorcode %d" %= ret) + if(PfxFile is not None): + #Find Signtool + WinKitsPath =3D WindowsCapsuleSupportHelper._LocateLatestWindo= wsKits() + 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, Pfx= File, PfxPass) + if(ret !=3D 0): + raise Exception("Signing Cat file Failed with errorcode %d= " % ret) + return ret --=20 2.20.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41454): https://edk2.groups.io/g/devel/message/41454 Mute This Topic: https://groups.io/mt/31819358/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-