public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Liming Gao" <liming.gao@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"Jin, Eric" <eric.jin@intel.com>
Cc: "Feng, Bob C" <bob.c.feng@intel.com>,
	"Kinney, Michael D" <michael.d.kinney@intel.com>
Subject: Re: [edk2-devel] [PATCH v3 1/1] BaseTools/Capsule: Tool to Generate Windows Firmware Update Driver
Date: Thu, 13 Jun 2019 03:09:57 +0000	[thread overview]
Message-ID: <4A89E2EF3DFEDB4C8BFDE51014F606A14E4802CA@SHSMSX104.ccr.corp.intel.com> (raw)
In-Reply-To: <20190611062252.9124-1-eric.jin@intel.com>

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 Eric
>Jin
>Sent: Tuesday, June 11, 2019 2:23 PM
>To: devel@edk2.groups.io
>Cc: Feng, Bob C <bob.c.feng@intel.com>; Gao, Liming
><liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
>Subject: [edk2-devel] [PATCH v3 1/1] BaseTools/Capsule: Tool to Generate
>Windows Firmware Update Driver
>
>https://bugzilla.tianocore.org/show_bug.cgi?id=1837
>
>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_DOTSTRING]
>                      [--capsuleversion-hexstring CAPSULEVERSION_HEXSTRING]
>                      [--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 <bob.c.feng@intel.com>
>Cc: Liming Gao <liming.gao@intel.com>
>Cc: Kinney Michael D <michael.d.kinney@intel.com>
>Signed-off-by: Eric Jin <eric.jin@intel.com>
>---
> 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.<BR>
>+ # 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 = None
>+        try:
>+            if hasattr(self, '_Thread__target'):
>+                # Thread uses name mangling prior to Python 3.
>+                self.ret = self._Thread__target(*self._Thread__args,
>**self._Thread__kwargs)
>+            else:
>+                self.ret = self._target(*self._args, **self._kwargs)
>+        except BaseException as e:
>+            self.exc = e
>+    def join(self, timeout=None):
>+        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 = 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=True, workingdir=None,
>outfile=None, outstream=None, environ=None):
>+    cmd = cmd.strip('"\'')
>+    if " " in cmd:
>+        cmd = '"' + cmd + '"'
>+    if parameters is not None:
>+        parameters = parameters.strip()
>+        cmd += " " + parameters
>+    starttime = datetime.datetime.now()
>+    logging.info("Cmd to run is: " + cmd)
>+    logging.info("------------------------------------------------")
>+    logging.info("--------------Cmd Output Starting---------------")
>+    logging.info("------------------------------------------------")
>+    c = subprocess.Popen(cmd, stdout=subprocess.PIPE,
>stderr=subprocess.STDOUT, cwd=workingdir, shell=True, env=environ)
>+    if(capture):
>+        outr = PropagatingThread(target=reader, args=(outfile, outstream,
>c.stdout,))
>+        outr.start()
>+        outr.join()
>+    c.wait()
>+
>+    endtime = datetime.datetime.now()
>+    delta = 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 = {'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 = arch
>+        self.OperatingSystem = os
>+
>+    @property
>+    def Arch(self):
>+        return self._arch
>+
>+    @Arch.setter
>+    def Arch(self, value):
>+        value = value.lower()
>+        if(value == "x64") or (value == "amd64"):  # support amd64 value so INF
>and CAT tools can use same arch value
>+            self._arch = "X64"
>+        elif(value == "arm"):
>+            self._arch = "ARM"
>+        elif(value == "arm64") or (value == "aarch64"):  # support UEFI defined
>aarch64 value as well
>+            self._arch = "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 = value.lower()
>+        if(key not in CatGenerator.SUPPORTED_OS.keys()):
>+            logging.critical("Unsupported Operating System: %s", key)
>+            raise ValueError("Unsupported Operating System")
>+        self._operatingsystem = CatGenerator.SUPPORTED_OS[key]
>+
>+    def MakeCat(self, OutputCatFile, PathToInf2CatTool=None):
>+        # Find Inf2Cat tool
>+        if(PathToInf2CatTool is None):
>+            PathToInf2CatTool = 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 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 = '"' + PathToInf2CatTool + '"'
>+
>+        OutputFolder = os.path.dirname(OutputCatFile)
>+        # Make Cat file
>+        cmd = "/driver:. /os:" + self.OperatingSystem + "_" + self.Arch + "
>/verbose"
>+        ret = RunCmd(PathToInf2CatTool, cmd, workingdir=OutputFolder)
>+        if(ret != 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.<BR>
>+# 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__        = 'GenerateWindowsDriver'
>+__version__     = '0.0'
>+__copyright__   = 'Copyright (c) 2019, Intel Corporation. All rights reserved.'
>+__description__ = 'Generate Capsule Windows Driver.\n'
>+
>+
>+if __name__ == '__main__':
>+    def convert_arg_line_to_args(arg_line):
>+        for arg in arg_line.split():
>+            if not arg.strip():
>+                continue
>+            yield arg
>+
>+    parser = argparse.ArgumentParser (
>+                        prog = __prog__,
>+                        description = __description__ + __copyright__,
>+                        conflict_handler = 'resolve',
>+                        fromfile_prefix_chars = '@'
>+                        )
>+    parser.convert_arg_line_to_args = convert_arg_line_to_args
>+    parser.add_argument("--output-folder", dest = 'OutputFolder', help =
>"firmware resource update driver package output folder.")
>+    parser.add_argument("--product-fmp-guid", dest = 'ProductFmpGuid',
>help = "firmware GUID of resource update driver package")
>+    parser.add_argument("--capsuleversion-dotstring", dest =
>'CapsuleVersion_DotString', help = "firmware version with date on which
>update driver package is authored")
>+    parser.add_argument("--capsuleversion-hexstring", dest =
>'CapsuleVersion_HexString', help = "firmware version in Hex of update driver
>package")
>+    parser.add_argument("--product-fw-provider", dest =
>'ProductFwProvider', help = "vendor/provider of entire firmware resource
>update driver package")
>+    parser.add_argument("--product-fw-mfg-name", dest =
>'ProductFwMfgName', help = "manufacturer/vendor of firmware resource
>update driver package")
>+    parser.add_argument("--product-fw-desc", dest = "ProductFwDesc", help
>= "description about resource update driver")
>+    parser.add_argument("--capsule-file-name", dest = 'CapsuleFileName',
>help ="firmware resource image file")
>+    parser.add_argument("--pfx-file", dest = 'PfxFile', help = "pfx file path
>used to sign resource update driver")
>+    parser.add_argument("--arch", dest = 'Arch', help = "supported
>architecture:arm/x64/amd64/arm64/aarch64", default = 'amd64')
>+    parser.add_argument("--operating-system-string", dest =
>'OperatingSystemString', help = "supported operating
>system:win10/10/10_au/10_rs2/10_rs3/10_rs4/server10/server2016/serverrs
>2/serverrs3/serverrs4", default = "win10")
>+
>+    def ArgCheck(args):
>+        Version = args.CapsuleVersion_DotString.split('.')
>+
>+        if len(Version) != 4:
>+            logging.critical("Name invalid: '%s'", args.CapsuleVersion_DotString)
>+            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_DotString):
>+            logging.critical("Name invalid: '%s'", args.CapsuleVersion_DotString)
>+            raise ValueError("Name has invalid chars.")
>+
>+    def CapsuleGuidCheck(InputFile, Guid):
>+        TempCapDecode = 'TempCapDecode.txt'
>+        Command = '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 = str(line).split('= ')[1][:-5]
>+                    break
>+        os.remove(TempCapDecode)
>+        if (Guid != CapGuid):
>+            print('GenerateWindowsDriver error: Different Guid from Capsule')
>+            sys.exit(1)
>+
>+    args = parser.parse_args()
>+
>+    InputFile = os.path.join(args.OutputFolder, '') + args.CapsuleFileName
>+
>+    ProductName = args.CapsuleFileName.strip('.cap')
>+    WindowsDriver = WindowsCapsuleSupportHelper ()
>+
>+    ArgCheck(args)
>+    CapsuleGuidCheck(InputFile, args.ProductFmpGuid)
>+
>+    WindowsDriver.PackageWindowsCapsuleFiles (
>+                                                   args.OutputFolder,
>+                                                   ProductName,
>+                                                   args.ProductFmpGuid,
>+                                                   args.CapsuleVersion_DotString,
>+                                                   args.CapsuleVersion_HexString,
>+                                                   args.ProductFwProvider,
>+                                                   args.ProductFwMfgName,
>+                                                   args.ProductFwDesc,
>+                                                   args.CapsuleFileName,
>+                                                   args.PfxFile,
>+                                                   None,
>+                                                   None,
>+                                                   args.Arch,
>+                                                   args.OperatingSystemString
>+                                                   )
>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.<BR>
>+ # SPDX-License-Identifier: BSD-2-Clause-Patent
>+ ##
>+
>+import os
>+import logging
>+import datetime
>+import re
>+import uuid
>+
>+
>+#####
>+#
>+#####
>+class InfGenerator(object):
>+
>+    ### INF Template ###
>+    TEMPLATE = r""";
>+; {Name}.inf
>+; {DriverVersion}
>+; Copyright (C) 2019 Microsoft Corporation.  All Rights Reserved.
>+;
>+[Version]
>+Signature="$WINDOWS NT$"
>+Class=Firmware
>+ClassGuid={{f2e7dd72-6468-4e36-b6f1-6488f42c1b52}}
>+Provider=%Provider%
>+DriverVer={Date},{DriverVersion}
>+PnpLockdown=1
>+CatalogFile={Name}.cat
>+[Manufacturer]
>+%MfgName% = Firmware,NT{Arch}
>+[Firmware.NT{Arch}]
>+%FirmwareDesc% = Firmware_Install,UEFI\RES_{{{EsrtGuid}}}
>+[Firmware_Install.NT]
>+CopyFiles = Firmware_CopyFiles
>+{Rollback}
>+[Firmware_CopyFiles]
>+{FirmwareBinFile}
>+[Firmware_Install.NT.Hw]
>+AddReg = Firmware_AddReg
>+[Firmware_AddReg]
>+HKR,,FirmwareId,,{{{EsrtGuid}}}
>+HKR,,FirmwareVersion,%REG_DWORD%,{VersionHexString}
>+HKR,,FirmwareFilename,,{FirmwareBinFile}
>+[SourceDisksNames]
>+1 = %DiskName%
>+[SourceDisksFiles]
>+{FirmwareBinFile} = 1
>+[DestinationDirs]
>+DefaultDestDir = %DIRID_WINDOWS%,Firmware ; %SystemRoot%\Firmware
>+[Strings]
>+; localizable
>+Provider     = "{Provider}"
>+MfgName      = "{MfgName}"
>+FirmwareDesc = "{Description}"
>+DiskName     = "Firmware Update"
>+; non-localizable
>+DIRID_WINDOWS = 10
>+REG_DWORD     = 0x00010001
>+"""
>+
>+    ROLLBACKTEMPLATE = r"""AddReg    =
>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 = {'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 = name_string
>+        self.Provider = provider
>+        self.EsrtGuid = esrt_guid
>+        self.Arch = arch
>+        self.Description = description_string
>+        self.VersionString = version_string
>+        self.VersionHex = version_hex
>+        self._manufacturer = None  # default for optional feature
>+        self._date = 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 = value
>+
>+    @property
>+    def Provider(self):
>+        return self._provider
>+
>+    @Provider.setter
>+    def Provider(self, value):
>+        self._provider = value
>+
>+    @property
>+    def Manufacturer(self):
>+        if(self._manufacturer is None):
>+            return self.Provider
>+
>+        return self._manufacturer
>+
>+    @Manufacturer.setter
>+    def Manufacturer(self, value):
>+        self._manufacturer = value
>+
>+    @property
>+    def Description(self):
>+        return self._description
>+
>+    @Description.setter
>+    def Description(self, value):
>+        self._description = 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 = value
>+
>+    @property
>+    def VersionString(self):
>+        return self._versionstring
>+
>+    @VersionString.setter
>+    def VersionString(self, value):
>+        c = 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 = value
>+
>+    @property
>+    def VersionHex(self):
>+        return "0x%08X" % self._versionhex
>+
>+    @VersionHex.setter
>+    def VersionHex(self, value):
>+        a = 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 = a
>+
>+    @property
>+    def Arch(self):
>+        return self._arch
>+
>+    @Arch.setter
>+    def Arch(self, value):
>+        key = value.lower()
>+        if(key not in InfGenerator.SUPPORTED_ARCH.keys()):
>+            logging.critical("Arch invalid: '%s'", value)
>+            raise ValueError("Unsupported Architecture")
>+        self._arch = 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 = value
>+
>+    def MakeInf(self, OutputInfFilePath, FirmwareBinFileName,
>Rollback=False):
>+        RollbackString = ""
>+        if(Rollback):
>+            RollbackString =
>InfGenerator.ROLLBACKTEMPLATE.format(EsrtGuid=self.EsrtGuid)
>+
>+        binfilename = os.path.basename(FirmwareBinFileName)
>+
>+        Content = InfGenerator.TEMPLATE.format(
>+            Name=self.Name,
>+            Date=self.Date,
>+            Arch=self.Arch,
>+            DriverVersion=self.VersionString,
>+            EsrtGuid=self.EsrtGuid,
>+            FirmwareBinFile=binfilename,
>+            VersionHexString=self.VersionHex,
>+            Provider=self.Provider,
>+            MfgName=self.Manufacturer,
>+            Description=self.Description,
>+            Rollback=RollbackString)
>+
>+        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.<BR>
>+# 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=None):
>+    # 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 = '"' + SignToolPath + '"'
>+
>+    OutputDir = os.path.dirname(ToSignFilePath)
>+    # Signtool docs https://docs.microsoft.com/en-
>us/dotnet/framework/tools/signtool-exe
>+    # todo: link to catalog signing documentation
>+    params = "sign /a /fd SHA256 /f " + PfxFilePath
>+    if PfxPass is not None:
>+        # add password if set
>+        params = params + ' /p ' + PfxPass
>+    params = params + ' /debug /v "' + ToSignFilePath + '" '
>+    ret = RunCmd(SignToolPath, params, workingdir=OutputDir)
>+    if(ret != 0):
>+        logging.error("Signtool failed %d" % ret)
>+    return ret
>+
>+class WindowsCapsuleSupportHelper(object):
>+    @staticmethod
>+    def _LocateLatestWindowsKits():
>+        result = None
>+
>+        # Start with a base path and use it to start locating the ideal directory.
>+        base_path = os.path.join(os.getenv("ProgramFiles(x86)"), "Windows
>Kits")
>+
>+        # Check for Win 10 kits first.
>+        base_10_path = 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 = 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 = 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 = os.path.join(base_path, "8.1", "bin", "x64")
>+        return result
>+
>+    def RegisterHelpers(self, obj):
>+        fp = 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=None, PfxPass=None, Rollback=False, Arch='amd64',
>OperatingSystem_String='Win10'):
>+        logging.debug("CapsulePackage: Create Windows Capsule Files")
>+        #Make INF
>+        InfFilePath = os.path.join(OutputFolder, ProductName + ".inf")
>+        InfTool = InfGenerator(ProductName, ProductFwProvider,
>ProductFmpGuid, Arch, ProductFwDesc, CapsuleVersion_DotString,
>CapsuleVersion_HexString)
>+        InfTool.Manufacturer = ProductFwMfgName #optional
>+        ret = InfTool.MakeInf(InfFilePath, CapsuleFileName, Rollback)
>+        if(ret != 0):
>+            raise Exception("CreateWindowsInf Failed with errorcode %d" % ret)
>+        #Make CAT
>+        CatFilePath = os.path.realpath(os.path.join(OutputFolder, ProductName
>+ ".cat"))
>+        CatTool = CatGenerator(Arch, OperatingSystem_String)
>+        ret = CatTool.MakeCat(CatFilePath)
>+
>+        if(ret != 0):
>+            raise Exception("Creating Cat file Failed with errorcode %d" % ret)
>+        if(PfxFile is not None):
>+            #Find Signtool
>+            WinKitsPath =
>WindowsCapsuleSupportHelper._LocateLatestWindowsKits()
>+            SignToolPath = 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 = CatalogSignWithSignTool(SignToolPath, CatFilePath, PfxFile,
>PfxPass)
>+            if(ret != 0):
>+                raise Exception("Signing Cat file Failed with errorcode %d" % ret)
>+        return ret
>--
>2.20.1.windows.1
>
>
>


      reply	other threads:[~2019-06-13  3:10 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-11  6:22 [PATCH v3 1/1] BaseTools/Capsule: Tool to Generate Windows Firmware Update Driver Eric Jin
2019-06-13  3:09 ` Liming Gao [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A89E2EF3DFEDB4C8BFDE51014F606A14E4802CA@SHSMSX104.ccr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox