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.151, mailfrom: liming.gao@intel.com) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by groups.io with SMTP; Wed, 12 Jun 2019 20:10:01 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Jun 2019 20:10:00 -0700 X-ExtLoop1: 1 Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by orsmga008.jf.intel.com with ESMTP; 12 Jun 2019 20:09:59 -0700 Received: from fmsmsx152.amr.corp.intel.com (10.18.125.5) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 12 Jun 2019 20:09:59 -0700 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by FMSMSX152.amr.corp.intel.com (10.18.125.5) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 12 Jun 2019 20:09:59 -0700 Received: from shsmsx104.ccr.corp.intel.com ([169.254.5.185]) by shsmsx102.ccr.corp.intel.com ([169.254.2.33]) with mapi id 14.03.0439.000; Thu, 13 Jun 2019 11:09:57 +0800 From: "Liming Gao" To: "devel@edk2.groups.io" , "Jin, Eric" CC: "Feng, Bob C" , "Kinney, Michael D" Subject: Re: [edk2-devel] [PATCH v3 1/1] BaseTools/Capsule: Tool to Generate Windows Firmware Update Driver Thread-Topic: [edk2-devel] [PATCH v3 1/1] BaseTools/Capsule: Tool to Generate Windows Firmware Update Driver Thread-Index: AQHVIB4lG4qYQrDQqU6pi081EgSv8KaY5+Wg Date: Thu, 13 Jun 2019 03:09:57 +0000 Message-ID: <4A89E2EF3DFEDB4C8BFDE51014F606A14E4802CA@SHSMSX104.ccr.corp.intel.com> References: <20190611062252.9124-1-eric.jin@intel.com> In-Reply-To: <20190611062252.9124-1-eric.jin@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: liming.gao@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Eric: Can you help post link for Windows Firmware Update Drivers? Thanks Liming >-----Original Message----- >From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Eri= c >Jin >Sent: Tuesday, June 11, 2019 2:23 PM >To: devel@edk2.groups.io >Cc: Feng, Bob C ; Gao, Liming >; Kinney, Michael D >Subject: [edk2-devel] [PATCH v3 1/1] 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 >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_DOTSTRIN= G] > [--capsuleversion-hexstring CAPSULEVERSION_HEXSTRIN= G] > [--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 OPERATINGSYSTEMSTRING] > >Cc: Bob Feng >Cc: Liming Gao >Cc: Kinney Michael D >Signed-off-by: Eric Jin >--- > BaseTools/Source/Python/Capsule/CatGenerator.py | 159 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >+++++++++++++++++++++++++++++++++++++++++ > BaseTools/Source/Python/Capsule/GenerateWindowsDriver.py | 114 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >+++++++++++++++++++++++++++++++++++++++++++++++++++++++ > BaseTools/Source/Python/Capsule/InfGenerator.py | 210 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >+++++++++++++++++++++++++++++++++ > BaseTools/Source/Python/Capsule/WindowsCapsuleSupportHelper.py | 102 >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >+++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 585 insertions(+) > >diff --git a/BaseTools/Source/Python/Capsule/CatGenerator.py >b/BaseTools/Source/Python/Capsule/CatGenerator.py >new file mode 100644 >index 0000000000..5f7fefa788 >--- /dev/null >+++ b/BaseTools/Source/Python/Capsule/CatGenerator.py >@@ -0,0 +1,159 @@ >+## @file >+ # Script to generate Cat files for capsule update based on supplied 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): >+ if filepath: >+ try: >+ with open(filepath, "w") as f: >+ print("The file is" + filepath) >+ except FileNotFoundError: >+ print("Sorry, the file" + filepath + "does not exist.") >+ >+ while True: >+ s =3D stream.readline().decode() >+ if not s: >+ stream.close() >+ break >+ # write to file if caller provideds file >+ if filepath: >+ try: >+ with open(filepath, "a") as f: >+ f.write(s) >+ except FileNotFoundError: >+ print("Sorry, the file" + filepath + "does not exist.") >+ if(outstream is not None): >+ # write to stream object if caller provided object >+ outstream.write(s) >+ logging.info(s.rstrip()) >+ >+def RunCmd(cmd, parameters, capture=3DTrue, workingdir=3DNone, >outfile=3DNone, 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) >+ logging.info("------------------------------------------------") >+ logging.info("--------------Cmd Output Starting---------------") >+ logging.info("------------------------------------------------") >+ c =3D subprocess.Popen(cmd, stdout=3Dsubprocess.PIPE, >stderr=3Dsubprocess.STDOUT, cwd=3Dworkingdir, shell=3DTrue, env=3Denviron= ) >+ if(capture): >+ outr =3D PropagatingThread(target=3Dreader, args=3D(outfile, out= stream, >c.stdout,)) >+ outr.start() >+ outr.join() >+ 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 amd= 64 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"): # suppo= rt 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(x= 86)"), >"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.Arc= h + " >/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/BaseTools/Source/Python/Capsule/GenerateWindowsDriver.py >new file mode 100644 >index 0000000000..83546f69fb >--- /dev/null >+++ b/BaseTools/Source/Python/Capsule/GenerateWindowsDriver.py >@@ -0,0 +1,114 @@ >+## @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 r= eserved.' >+__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 >'CapsuleVersion_DotString', help =3D "firmware version with date on which >update driver package is authored") >+ parser.add_argument("--capsuleversion-hexstring", dest =3D >'CapsuleVersion_HexString', help =3D "firmware version in Hex of update d= river >package") >+ parser.add_argument("--product-fw-provider", dest =3D >'ProductFwProvider', help =3D "vendor/provider of entire firmware resourc= e >update driver package") >+ parser.add_argument("--product-fw-mfg-name", dest =3D >'ProductFwMfgName', help =3D "manufacturer/vendor of firmware resource >update driver package") >+ parser.add_argument("--product-fw-desc", dest =3D "ProductFwDesc", h= elp >=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 = file path >used to sign resource update driver") >+ parser.add_argument("--arch", dest =3D 'Arch', help =3D "supported >architecture:arm/x64/amd64/arm64/aarch64", default =3D 'amd64') >+ parser.add_argument("--operating-system-string", dest =3D >'OperatingSystemString', help =3D "supported operating >system:win10/10/10_au/10_rs2/10_rs3/10_rs4/server10/server2016/serverrs >2/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_D= otString) >+ raise ValueError("Name invalid.") >+ for sub in Version: >+ if int(sub) > 65536: >+ logging.critical("Name invalid: '%s'", args.CapsuleVersi= on_DotString) >+ raise ValueError("Name exceed limit 65536.") >+ >+ if not (re.compile(r'[0-9.]*$')).match(args.CapsuleVersion_DotSt= ring): >+ logging.critical("Name invalid: '%s'", args.CapsuleVersion_D= otString) >+ raise ValueError("Name has invalid chars.") >+ >+ def CapsuleGuidCheck(InputFile, Guid): >+ TempCapDecode =3D 'TempCapDecode.txt' >+ Command =3D 'python GenerateCapsule.py "' + InputFile + '" --dum= p- >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 >+ os.remove(TempCapDecode) >+ if (Guid !=3D CapGuid): >+ print('GenerateWindowsDriver error: Different Guid from Caps= ule') >+ sys.exit(1) >+ >+ args =3D parser.parse_args() >+ >+ InputFile =3D os.path.join(args.OutputFolder, '') + args.CapsuleFile= Name >+ >+ ProductName =3D args.CapsuleFileName.strip('.cap') >+ WindowsDriver =3D WindowsCapsuleSupportHelper () >+ >+ ArgCheck(args) >+ CapsuleGuidCheck(InputFile, args.ProductFmpGuid) >+ >+ WindowsDriver.PackageWindowsCapsuleFiles ( >+ args.OutputFolder, >+ ProductName, >+ args.ProductFmpGuid, >+ args.CapsuleVersion_D= otString, >+ args.CapsuleVersion_H= exString, >+ args.ProductFwProvide= r, >+ args.ProductFwMfgName= , >+ args.ProductFwDesc, >+ args.CapsuleFileName, >+ args.PfxFile, >+ None, >+ None, >+ args.Arch, >+ args.OperatingSystemS= tring >+ ) >diff --git a/BaseTools/Source/Python/Capsule/InfGenerator.py >b/BaseTools/Source/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= and >+ # 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 >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, >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= 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 ran= ge 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=3DFalse): >+ 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.py >b/BaseTools/Source/Python/Capsule/WindowsCapsuleSupportHelper.py >new file mode 100644 >index 0000000000..8abac3e31d >--- /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, >PfxPass=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/tools/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 = directory. >+ base_path =3D os.path.join(os.getenv("ProgramFiles(x86)"), "Wind= ows >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.join(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, "= x64")): >+ 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, >ProductFmpGuid, 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, >ProductFmpGuid, Arch, ProductFwDesc, CapsuleVersion_DotString, >CapsuleVersion_HexString) >+ 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, Prod= uctName >+ ".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._LocateLatestWindowsKits() >+ 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, P= fxFile, >PfxPass) >+ if(ret !=3D 0): >+ raise Exception("Signing Cat file Failed with errorcode = %d" % ret) >+ return ret >-- >2.20.1.windows.1 > > >