mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-07 19:45:07 +02:00
BaseTools/Capsule: Add Capsule Generation Tools
https://bugzilla.tianocore.org/show_bug.cgi?id=945 Based on content from the following branch https://github.com/Microsoft/MS_UEFI/tree/share/beta/CapsuleTools * Convert C tools to Python * Add common python modules to: BaseTools/Source/Python/Common/Uefi/Capsule BaseTools/Source/Python/Common/Edk2/Capsule * Add GenerateCapsule.py to BaseTools/Source/Python/Capsule * Add Windows and Posix wrappers for GenerateCapsule.py usage: GenerateCapsule [-h] [-o OUTPUTFILE] (-e | -d | --dump-info) [--capflag {PersistAcrossReset,PopulateSystemTable,InitiateReset}] [--capoemflag CAPSULEOEMFLAG] [--guid GUID] [--hardware-instance HARDWAREINSTANCE] [--monotonic-count MONOTONICCOUNT] [--fw-version FWVERSION] [--lsv LOWESTSUPPORTEDVERSION] [--pfx-file SIGNTOOLPFXFILE] [--signer-private-cert OPENSSLSIGNERPRIVATECERTFILE] [--other-public-cert OPENSSLOTHERPUBLICCERTFILE] [--trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE] [--signing-tool-path SIGNINGTOOLPATH] [--version] [-v] [-q] [--debug [0-9]] InputFile Generate a capsule. Copyright (c) 2018, Intel Corporation. All rights reserved. positional arguments: InputFile Input binary payload filename. optional arguments: -h, --help show this help message and exit -o OUTPUTFILE, --output OUTPUTFILE Output filename. -e, --encode Encode file -d, --decode Decode file --dump-info Display FMP Payload Header information --capflag {PersistAcrossReset,PopulateSystemTable,InitiateReset} Capsule flag can be PersistAcrossReset, or PopulateSystemTable or InitiateReset or not set --capoemflag CAPSULEOEMFLAG Capsule OEM Flag is an integer between 0x0000 and 0xffff. --guid GUID The FMP/ESRT GUID in registry format. Required for encode operations. --hardware-instance HARDWAREINSTANCE The 64-bit hardware instance. The default is 0x0000000000000000 --monotonic-count MONOTONICCOUNT 64-bit monotonic count value in header. Default is 0x0000000000000000. --fw-version FWVERSION The 32-bit version of the binary payload (e.g. 0x11223344 or 5678). --lsv LOWESTSUPPORTEDVERSION The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678). --pfx-file SIGNTOOLPFXFILE signtool PFX certificate filename. --signer-private-cert OPENSSLSIGNERPRIVATECERTFILE OpenSSL signer private certificate filename. --other-public-cert OPENSSLOTHERPUBLICCERTFILE OpenSSL other public certificate filename. --trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE OpenSSL trusted public certificate filename. --signing-tool-path SIGNINGTOOLPATH Path to signtool or OpenSSL tool. Optional if path to tools are already in PATH. --version show program's version number and exit -v, --verbose Turn on verbose output with informational messages printed, including capsule headers and warning messages. -q, --quiet Disable all messages except fatal errors. --debug [0-9] Set debug level Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Yonghong Zhu <yonghong.zhu@intel.com> Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
This commit is contained in:
parent
3a0c1bf64b
commit
8b63877aca
14
BaseTools/BinWrappers/PosixLike/GenerateCapsule
Normal file
14
BaseTools/BinWrappers/PosixLike/GenerateCapsule
Normal file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
#python `dirname $0`/RunToolFromSource.py `basename $0` $*
|
||||
|
||||
# If a python2 command is available, use it in preference to python
|
||||
if command -v python2 >/dev/null 2>&1; then
|
||||
python_exe=python2
|
||||
fi
|
||||
|
||||
full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
|
||||
dir=$(dirname "$full_cmd")
|
||||
cmd=${full_cmd##*/}
|
||||
|
||||
export PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYTHONPATH"}"
|
||||
exec "${python_exe:-python}" "$dir/../../Source/Python/Capsule/$cmd.py" "$@"
|
1
BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
Normal file
1
BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
Normal file
@ -0,0 +1 @@
|
||||
@%PYTHON_HOME%\python.exe %BASE_TOOLS_PATH%\Source\Python\Capsule\GenerateCapsule.py %*
|
522
BaseTools/Source/Python/Capsule/GenerateCapsule.py
Normal file
522
BaseTools/Source/Python/Capsule/GenerateCapsule.py
Normal file
@ -0,0 +1,522 @@
|
||||
## @file
|
||||
# Generate a capsule.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
GenerateCapsule
|
||||
'''
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import uuid
|
||||
import struct
|
||||
import subprocess
|
||||
import os
|
||||
import tempfile
|
||||
import shutil
|
||||
import platform
|
||||
from Common.Uefi.Capsule.UefiCapsuleHeader import UefiCapsuleHeaderClass
|
||||
from Common.Uefi.Capsule.FmpCapsuleHeader import FmpCapsuleHeaderClass
|
||||
from Common.Uefi.Capsule.FmpAuthHeader import FmpAuthHeaderClass
|
||||
from Common.Edk2.Capsule.FmpPayloadHeader import FmpPayloadHeaderClass
|
||||
|
||||
#
|
||||
# Globals for help information
|
||||
#
|
||||
__prog__ = 'GenerateCapsule'
|
||||
__version__ = '0.9'
|
||||
__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'
|
||||
__description__ = 'Generate a capsule.\n'
|
||||
|
||||
def SignPayloadSignTool (Payload, ToolPath, PfxFile):
|
||||
#
|
||||
# Create a temporary directory
|
||||
#
|
||||
TempDirectoryName = tempfile.mkdtemp()
|
||||
|
||||
#
|
||||
# Generate temp file name for the payload contents
|
||||
#
|
||||
TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')
|
||||
|
||||
#
|
||||
# Create temporary payload file for signing
|
||||
#
|
||||
try:
|
||||
File = open (TempFileName, mode='wb')
|
||||
File.write (Payload)
|
||||
File.close ()
|
||||
except:
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')
|
||||
|
||||
#
|
||||
# Build signtool command
|
||||
#
|
||||
if ToolPath is None:
|
||||
ToolPath = ''
|
||||
Command = ''
|
||||
Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'signtool.exe'))
|
||||
Command = Command + 'sign /fd sha256 /p7ce DetachedSignedData /p7co 1.2.840.113549.1.7.2 '
|
||||
Command = Command + '/p7 {TempDir} '.format (TempDir = TempDirectoryName)
|
||||
Command = Command + '/f {PfxFile} '.format (PfxFile = PfxFile)
|
||||
Command = Command + TempFileName
|
||||
|
||||
#
|
||||
# Sign the input file using the specified private key
|
||||
#
|
||||
try:
|
||||
Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
|
||||
Result = Process.communicate('')
|
||||
except:
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
raise ValueError ('GenerateCapsule: error: can not run signtool.')
|
||||
|
||||
if Process.returncode != 0:
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
print (Result[1].decode())
|
||||
raise ValueError ('GenerateCapsule: error: signtool failed.')
|
||||
|
||||
#
|
||||
# Read the signature from the generated output file
|
||||
#
|
||||
try:
|
||||
File = open (TempFileName + '.p7', mode='rb')
|
||||
Signature = File.read ()
|
||||
File.close ()
|
||||
except:
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
raise ValueError ('GenerateCapsule: error: can not read signature file.')
|
||||
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
return Signature
|
||||
|
||||
def VerifyPayloadSignTool (Payload, CertData, ToolPath, PfxFile):
|
||||
print ('signtool verify is not supported.')
|
||||
raise ValueError ('GenerateCapsule: error: signtool verify is not supported.')
|
||||
|
||||
def SignPayloadOpenSsl (Payload, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):
|
||||
#
|
||||
# Build openssl command
|
||||
#
|
||||
if ToolPath is None:
|
||||
ToolPath = ''
|
||||
Command = ''
|
||||
Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))
|
||||
Command = Command + 'smime -sign -binary -outform DER -md sha256 '
|
||||
Command = Command + '-signer "{Private}" -certfile "{Public}"'.format (Private = SignerPrivateCertFile, Public = OtherPublicCertFile)
|
||||
|
||||
#
|
||||
# Sign the input file using the specified private key and capture signature from STDOUT
|
||||
#
|
||||
try:
|
||||
Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
|
||||
Result = Process.communicate(input = Payload)
|
||||
Signature = Result[0]
|
||||
except:
|
||||
raise ValueError ('GenerateCapsule: error: can not run openssl.')
|
||||
|
||||
if Process.returncode != 0:
|
||||
print (Result[1].decode())
|
||||
raise ValueError ('GenerateCapsule: error: openssl failed.')
|
||||
|
||||
return Signature
|
||||
|
||||
def VerifyPayloadOpenSsl (Payload, CertData, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):
|
||||
#
|
||||
# Create a temporary directory
|
||||
#
|
||||
TempDirectoryName = tempfile.mkdtemp()
|
||||
|
||||
#
|
||||
# Generate temp file name for the payload contents
|
||||
#
|
||||
TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')
|
||||
|
||||
#
|
||||
# Create temporary payload file for verification
|
||||
#
|
||||
try:
|
||||
File = open (TempFileName, mode='wb')
|
||||
File.write (Payload)
|
||||
File.close ()
|
||||
except:
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')
|
||||
|
||||
#
|
||||
# Build openssl command
|
||||
#
|
||||
if ToolPath is None:
|
||||
ToolPath = ''
|
||||
Command = ''
|
||||
Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))
|
||||
Command = Command + 'smime -verify -inform DER '
|
||||
Command = Command + '-content {Content} -CAfile "{Public}"'.format (Content = TempFileName, Public = TrustedPublicCertFile)
|
||||
|
||||
#
|
||||
# Verify signature
|
||||
#
|
||||
try:
|
||||
Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
|
||||
Result = Process.communicate(input = CertData)
|
||||
except:
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
raise ValueError ('GenerateCapsule: error: can not run openssl.')
|
||||
|
||||
if Process.returncode != 0:
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
print (Result[1].decode())
|
||||
raise ValueError ('GenerateCapsule: error: openssl failed.')
|
||||
|
||||
shutil.rmtree (TempDirectoryName)
|
||||
return Payload
|
||||
|
||||
if __name__ == '__main__':
|
||||
def convert_arg_line_to_args(arg_line):
|
||||
for arg in arg_line.split():
|
||||
if not arg.strip():
|
||||
continue
|
||||
yield arg
|
||||
|
||||
def ValidateUnsignedInteger (Argument):
|
||||
try:
|
||||
Value = int (Argument, 0)
|
||||
except:
|
||||
Message = '{Argument} is not a valid integer value.'.format (Argument = Argument)
|
||||
raise argparse.ArgumentTypeError (Message)
|
||||
if Value < 0:
|
||||
Message = '{Argument} is a negative value.'.format (Argument = Argument)
|
||||
raise argparse.ArgumentTypeError (Message)
|
||||
return Value
|
||||
|
||||
def ValidateRegistryFormatGuid (Argument):
|
||||
try:
|
||||
Value = uuid.UUID (Argument)
|
||||
except:
|
||||
Message = '{Argument} is not a valid registry format GUID value.'.format (Argument = Argument)
|
||||
raise argparse.ArgumentTypeError (Message)
|
||||
return Value
|
||||
|
||||
#
|
||||
# Create command line argument parser object
|
||||
#
|
||||
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
|
||||
|
||||
#
|
||||
# Add input and output file arguments
|
||||
#
|
||||
parser.add_argument("InputFile", type = argparse.FileType('rb'),
|
||||
help = "Input binary payload filename.")
|
||||
parser.add_argument("-o", "--output", dest = 'OutputFile', type = argparse.FileType('wb'),
|
||||
help = "Output filename.")
|
||||
#
|
||||
# Add group for -e and -d flags that are mutually exclusive and required
|
||||
#
|
||||
group = parser.add_mutually_exclusive_group (required = True)
|
||||
group.add_argument ("-e", "--encode", dest = 'Encode', action = "store_true",
|
||||
help = "Encode file")
|
||||
group.add_argument ("-d", "--decode", dest = 'Decode', action = "store_true",
|
||||
help = "Decode file")
|
||||
group.add_argument ("--dump-info", dest = 'DumpInfo', action = "store_true",
|
||||
help = "Display FMP Payload Header information")
|
||||
#
|
||||
# Add optional arguments for this command
|
||||
#
|
||||
parser.add_argument ("--capflag", dest = 'CapsuleFlag', action='append', default = [],
|
||||
choices=['PersistAcrossReset', 'PopulateSystemTable', 'InitiateReset'],
|
||||
help = "Capsule flag can be PersistAcrossReset, or PopulateSystemTable or InitiateReset or not set")
|
||||
parser.add_argument ("--capoemflag", dest = 'CapsuleOemFlag', type = ValidateUnsignedInteger, default = 0x0000,
|
||||
help = "Capsule OEM Flag is an integer between 0x0000 and 0xffff.")
|
||||
|
||||
parser.add_argument ("--guid", dest = 'Guid', type = ValidateRegistryFormatGuid,
|
||||
help = "The FMP/ESRT GUID in registry format. Required for encode operations.")
|
||||
parser.add_argument ("--hardware-instance", dest = 'HardwareInstance', type = ValidateUnsignedInteger, default = 0x0000000000000000,
|
||||
help = "The 64-bit hardware instance. The default is 0x0000000000000000")
|
||||
|
||||
|
||||
parser.add_argument ("--monotonic-count", dest = 'MonotonicCount', type = ValidateUnsignedInteger, default = 0x0000000000000000,
|
||||
help = "64-bit monotonic count value in header. Default is 0x0000000000000000.")
|
||||
|
||||
parser.add_argument ("--fw-version", dest = 'FwVersion', type = ValidateUnsignedInteger,
|
||||
help = "The 32-bit version of the binary payload (e.g. 0x11223344 or 5678).")
|
||||
parser.add_argument ("--lsv", dest = 'LowestSupportedVersion', type = ValidateUnsignedInteger,
|
||||
help = "The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678).")
|
||||
|
||||
parser.add_argument ("--pfx-file", dest='SignToolPfxFile', type=argparse.FileType('rb'),
|
||||
help="signtool PFX certificate filename.")
|
||||
|
||||
parser.add_argument ("--signer-private-cert", dest='OpenSslSignerPrivateCertFile', type=argparse.FileType('rb'),
|
||||
help="OpenSSL signer private certificate filename.")
|
||||
parser.add_argument ("--other-public-cert", dest='OpenSslOtherPublicCertFile', type=argparse.FileType('rb'),
|
||||
help="OpenSSL other public certificate filename.")
|
||||
parser.add_argument ("--trusted-public-cert", dest='OpenSslTrustedPublicCertFile', type=argparse.FileType('rb'),
|
||||
help="OpenSSL trusted public certificate filename.")
|
||||
|
||||
parser.add_argument ("--signing-tool-path", dest = 'SigningToolPath',
|
||||
help = "Path to signtool or OpenSSL tool. Optional if path to tools are already in PATH.")
|
||||
|
||||
#
|
||||
# Add optional arguments common to all operations
|
||||
#
|
||||
parser.add_argument ('--version', action='version', version='%(prog)s ' + __version__)
|
||||
parser.add_argument ("-v", "--verbose", dest = 'Verbose', action = "store_true",
|
||||
help = "Turn on verbose output with informational messages printed, including capsule headers and warning messages.")
|
||||
parser.add_argument ("-q", "--quiet", dest = 'Quiet', action = "store_true",
|
||||
help = "Disable all messages except fatal errors.")
|
||||
parser.add_argument ("--debug", dest = 'Debug', type = int, metavar = '[0-9]', choices = range (0, 10), default = 0,
|
||||
help = "Set debug level")
|
||||
|
||||
#
|
||||
# Parse command line arguments
|
||||
#
|
||||
args = parser.parse_args()
|
||||
|
||||
#
|
||||
# Perform additional argument verification
|
||||
#
|
||||
if args.Encode:
|
||||
if args.Guid is None:
|
||||
parser.error ('the following option is required: --guid')
|
||||
if 'PersistAcrossReset' not in args.CapsuleFlag:
|
||||
if 'PopulateSystemTable' in args.CapsuleFlag:
|
||||
parser.error ('--capflag PopulateSystemTable also requires --capflag PersistAcrossReset')
|
||||
if 'InitiateReset' in args.CapsuleFlag:
|
||||
parser.error ('--capflag InitiateReset also requires --capflag PersistAcrossReset')
|
||||
|
||||
UseSignTool = args.SignToolPfxFile is not None
|
||||
UseOpenSsl = (args.OpenSslSignerPrivateCertFile is not None and
|
||||
args.OpenSslOtherPublicCertFile is not None and
|
||||
args.OpenSslTrustedPublicCertFile is not None)
|
||||
AnyOpenSsl = (args.OpenSslSignerPrivateCertFile is not None or
|
||||
args.OpenSslOtherPublicCertFile is not None or
|
||||
args.OpenSslTrustedPublicCertFile is not None)
|
||||
if args.Encode or args.Decode:
|
||||
if args.OutputFile is None:
|
||||
parser.error ('the following option is required for all encode and decode operations: --output')
|
||||
|
||||
if UseSignTool and AnyOpenSsl:
|
||||
parser.error ('Providing both signtool and OpenSSL options is not supported')
|
||||
if not UseSignTool and not UseOpenSsl and AnyOpenSsl:
|
||||
parser.error ('all the following options are required for OpenSSL: --signer-private-cert, --other-public-cert, --trusted-public-cert')
|
||||
if UseSignTool and platform.system() != 'Windows':
|
||||
parser.error ('Use of signtool is not supported on this operating system.')
|
||||
if args.Encode and (UseSignTool or UseOpenSsl):
|
||||
if args.FwVersion is None or args.LowestSupportedVersion is None:
|
||||
parser.error ('the following options are required: --fw-version, --lsv')
|
||||
|
||||
if UseSignTool:
|
||||
args.SignToolPfxFile.close()
|
||||
args.SignToolPfxFile = args.SignToolPfxFile.name
|
||||
if UseOpenSsl:
|
||||
args.OpenSslSignerPrivateCertFile.close()
|
||||
args.OpenSslOtherPublicCertFile.close()
|
||||
args.OpenSslTrustedPublicCertFile.close()
|
||||
args.OpenSslSignerPrivateCertFile = args.OpenSslSignerPrivateCertFile.name
|
||||
args.OpenSslOtherPublicCertFile = args.OpenSslOtherPublicCertFile.name
|
||||
args.OpenSslTrustedPublicCertFile = args.OpenSslTrustedPublicCertFile.name
|
||||
|
||||
#
|
||||
# Read binary input file
|
||||
#
|
||||
try:
|
||||
if args.Verbose:
|
||||
print ('Read binary input file {File}'.format (File = args.InputFile.name))
|
||||
Buffer = args.InputFile.read ()
|
||||
args.InputFile.close ()
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not read binary input file {File}'.format (File = args.InputFile.name))
|
||||
sys.exit (1)
|
||||
|
||||
#
|
||||
# Create objects
|
||||
#
|
||||
UefiCapsuleHeader = UefiCapsuleHeaderClass ()
|
||||
FmpCapsuleHeader = FmpCapsuleHeaderClass ()
|
||||
FmpAuthHeader = FmpAuthHeaderClass ()
|
||||
FmpPayloadHeader = FmpPayloadHeaderClass ()
|
||||
|
||||
if args.Encode:
|
||||
Result = Buffer
|
||||
if UseSignTool or UseOpenSsl:
|
||||
try:
|
||||
FmpPayloadHeader.FwVersion = args.FwVersion
|
||||
FmpPayloadHeader.LowestSupportedVersion = args.LowestSupportedVersion
|
||||
FmpPayloadHeader.Payload = Result
|
||||
Result = FmpPayloadHeader.Encode ()
|
||||
if args.Verbose:
|
||||
FmpPayloadHeader.DumpInfo ()
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not encode FMP Payload Header')
|
||||
sys.exit (1)
|
||||
|
||||
#
|
||||
# Sign image with 64-bit MonotonicCount appended to end of image
|
||||
#
|
||||
try:
|
||||
if UseSignTool:
|
||||
CertData = SignPayloadSignTool (
|
||||
Result + struct.pack ('<Q', args.MonotonicCount),
|
||||
args.SigningToolPath,
|
||||
args.SignToolPfxFile
|
||||
)
|
||||
else:
|
||||
CertData = SignPayloadOpenSsl (
|
||||
Result + struct.pack ('<Q', args.MonotonicCount),
|
||||
args.SigningToolPath,
|
||||
args.OpenSslSignerPrivateCertFile,
|
||||
args.OpenSslOtherPublicCertFile,
|
||||
args.OpenSslTrustedPublicCertFile
|
||||
)
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not sign payload')
|
||||
raise
|
||||
sys.exit (1)
|
||||
|
||||
try:
|
||||
FmpAuthHeader.MonotonicCount = args.MonotonicCount
|
||||
FmpAuthHeader.CertData = CertData
|
||||
FmpAuthHeader.Payload = Result
|
||||
Result = FmpAuthHeader.Encode ()
|
||||
if args.Verbose:
|
||||
FmpAuthHeader.DumpInfo ()
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not encode FMP Auth Header')
|
||||
sys.exit (1)
|
||||
|
||||
try:
|
||||
FmpCapsuleHeader.AddPayload (args.Guid, Result, HardwareInstance = args.HardwareInstance)
|
||||
Result = FmpCapsuleHeader.Encode ()
|
||||
if args.Verbose:
|
||||
FmpCapsuleHeader.DumpInfo ()
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not encode FMP Capsule Header')
|
||||
sys.exit (1)
|
||||
|
||||
try:
|
||||
UefiCapsuleHeader.OemFlags = args.CapsuleOemFlag
|
||||
UefiCapsuleHeader.PersistAcrossReset = 'PersistAcrossReset' in args.CapsuleFlag
|
||||
UefiCapsuleHeader.PopulateSystemTable = 'PopulateSystemTable' in args.CapsuleFlag
|
||||
UefiCapsuleHeader.InitiateReset = 'InitiateReset' in args.CapsuleFlag
|
||||
UefiCapsuleHeader.Payload = Result
|
||||
Result = UefiCapsuleHeader.Encode ()
|
||||
if args.Verbose:
|
||||
UefiCapsuleHeader.DumpInfo ()
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not encode UEFI Capsule Header')
|
||||
sys.exit (1)
|
||||
|
||||
elif args.Decode:
|
||||
try:
|
||||
Result = UefiCapsuleHeader.Decode (Buffer)
|
||||
FmpCapsuleHeader.Decode (Result)
|
||||
Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload
|
||||
if args.Verbose:
|
||||
print ('========')
|
||||
UefiCapsuleHeader.DumpInfo ()
|
||||
print ('--------')
|
||||
FmpCapsuleHeader.DumpInfo ()
|
||||
if UseSignTool or UseOpenSsl:
|
||||
Result = FmpAuthHeader.Decode (Result)
|
||||
|
||||
#
|
||||
# Verify Image with 64-bit MonotonicCount appended to end of image
|
||||
#
|
||||
try:
|
||||
if UseSignTool:
|
||||
CertData = VerifyPayloadSignTool (
|
||||
FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),
|
||||
FmpAuthHeader.CertData,
|
||||
args.SigningToolPath,
|
||||
args.SignToolPfxFile
|
||||
)
|
||||
else:
|
||||
CertData = VerifyPayloadOpenSsl (
|
||||
FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),
|
||||
FmpAuthHeader.CertData,
|
||||
args.SigningToolPath,
|
||||
args.OpenSslSignerPrivateCertFile,
|
||||
args.OpenSslOtherPublicCertFile,
|
||||
args.OpenSslTrustedPublicCertFile
|
||||
)
|
||||
except ValueError:
|
||||
print ('GenerateCapsule: warning: can not verify payload.')
|
||||
|
||||
Result = FmpPayloadHeader.Decode (Result)
|
||||
if args.Verbose:
|
||||
print ('--------')
|
||||
FmpAuthHeader.DumpInfo ()
|
||||
print ('--------')
|
||||
FmpPayloadHeader.DumpInfo ()
|
||||
else:
|
||||
if args.Verbose:
|
||||
print ('--------')
|
||||
print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')
|
||||
print ('--------')
|
||||
print ('No FMP_PAYLOAD_HEADER')
|
||||
if args.Verbose:
|
||||
print ('========')
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not decode capsule')
|
||||
raise
|
||||
sys.exit (1)
|
||||
|
||||
elif args.DumpInfo:
|
||||
try:
|
||||
Result = UefiCapsuleHeader.Decode (Buffer)
|
||||
FmpCapsuleHeader.Decode (Result)
|
||||
Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload
|
||||
print ('========')
|
||||
UefiCapsuleHeader.DumpInfo ()
|
||||
print ('--------')
|
||||
FmpCapsuleHeader.DumpInfo ()
|
||||
try:
|
||||
Result = FmpAuthHeader.Decode (Result)
|
||||
Result = FmpPayloadHeader.Decode (Result)
|
||||
print ('--------')
|
||||
FmpAuthHeader.DumpInfo ()
|
||||
print ('--------')
|
||||
FmpPayloadHeader.DumpInfo ()
|
||||
except:
|
||||
print ('--------')
|
||||
print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')
|
||||
print ('--------')
|
||||
print ('No FMP_PAYLOAD_HEADER')
|
||||
print ('========')
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not decode capsule')
|
||||
sys.exit (1)
|
||||
else:
|
||||
print('GenerateCapsule: error: invalid options')
|
||||
sys.exit (1)
|
||||
|
||||
#
|
||||
# Write binary output file
|
||||
#
|
||||
if args.OutputFile is not None:
|
||||
try:
|
||||
if args.Verbose:
|
||||
print ('Write binary output file {File}'.format (File = args.OutputFile.name))
|
||||
args.OutputFile.write (Result)
|
||||
args.OutputFile.close ()
|
||||
except:
|
||||
print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = args.OutputFile.name))
|
||||
sys.exit (1)
|
||||
|
||||
if args.Verbose:
|
||||
print('Success')
|
@ -0,0 +1,91 @@
|
||||
## @file
|
||||
# Module that encodes and decodes a FMP_PAYLOAD_HEADER with a payload.
|
||||
# The FMP_PAYLOAD_HEADER is processed by the FmpPayloadHeaderLib in the
|
||||
# FmpDevicePkg.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
FmpPayloadHeader
|
||||
'''
|
||||
|
||||
import struct
|
||||
|
||||
def _SIGNATURE_32 (A, B, C, D):
|
||||
return struct.unpack ('=I',bytearray (A + B + C + D, 'ascii'))[0]
|
||||
|
||||
def _SIGNATURE_32_TO_STRING (Signature):
|
||||
return struct.pack ("<I", Signature).decode ()
|
||||
|
||||
class FmpPayloadHeaderClass (object):
|
||||
#
|
||||
# typedef struct {
|
||||
# UINT32 Signature;
|
||||
# UINT32 HeaderSize;
|
||||
# UINT32 FwVersion;
|
||||
# UINT32 LowestSupportedVersion;
|
||||
# } FMP_PAYLOAD_HEADER;
|
||||
#
|
||||
# #define FMP_PAYLOAD_HEADER_SIGNATURE SIGNATURE_32 ('M', 'S', 'S', '1')
|
||||
#
|
||||
_StructFormat = '<IIII'
|
||||
_StructSize = struct.calcsize (_StructFormat)
|
||||
|
||||
_FMP_PAYLOAD_HEADER_SIGNATURE = _SIGNATURE_32 ('M', 'S', 'S', '1')
|
||||
|
||||
def __init__ (self):
|
||||
self._Valid = False
|
||||
self.Signature = self._FMP_PAYLOAD_HEADER_SIGNATURE
|
||||
self.HeaderSize = self._StructSize
|
||||
self.FwVersion = 0x00000000
|
||||
self.LowestSupportedVersion = 0x00000000
|
||||
self.Payload = b''
|
||||
|
||||
def Encode (self):
|
||||
FmpPayloadHeader = struct.pack (
|
||||
self._StructFormat,
|
||||
self.Signature,
|
||||
self.HeaderSize,
|
||||
self.FwVersion,
|
||||
self.LowestSupportedVersion
|
||||
)
|
||||
self._Valid = True
|
||||
return FmpPayloadHeader + self.Payload
|
||||
|
||||
def Decode (self, Buffer):
|
||||
if len (Buffer) < self._StructSize:
|
||||
raise ValueError
|
||||
(Signature, HeaderSize, FwVersion, LowestSupportedVersion) = \
|
||||
struct.unpack (
|
||||
self._StructFormat,
|
||||
Buffer[0:self._StructSize]
|
||||
)
|
||||
if Signature != self._FMP_PAYLOAD_HEADER_SIGNATURE:
|
||||
raise ValueError
|
||||
if HeaderSize < self._StructSize:
|
||||
raise ValueError
|
||||
self.Signature = Signature
|
||||
self.HeaderSize = HeaderSize
|
||||
self.FwVersion = FwVersion
|
||||
self.LowestSupportedVersion = LowestSupportedVersion
|
||||
self.Payload = Buffer[self.HeaderSize:]
|
||||
|
||||
self._Valid = True
|
||||
return self.Payload
|
||||
|
||||
def DumpInfo (self):
|
||||
if not self._Valid:
|
||||
raise ValueError
|
||||
print ('FMP_PAYLOAD_HEADER.Signature = {Signature:08X} ({SignatureString})'.format (Signature = self.Signature, SignatureString = _SIGNATURE_32_TO_STRING (self.Signature)))
|
||||
print ('FMP_PAYLOAD_HEADER.HeaderSize = {HeaderSize:08X}'.format (HeaderSize = self.HeaderSize))
|
||||
print ('FMP_PAYLOAD_HEADER.FwVersion = {FwVersion:08X}'.format (FwVersion = self.FwVersion))
|
||||
print ('FMP_PAYLOAD_HEADER.LowestSupportedVersion = {LowestSupportedVersion:08X}'.format (LowestSupportedVersion = self.LowestSupportedVersion))
|
||||
print ('sizeof (Payload) = {Size:08X}'.format (Size = len (self.Payload)))
|
15
BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
Normal file
15
BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
## @file
|
||||
# Python 'Common.Edk2.Capsule' package initialization file.
|
||||
#
|
||||
# This file is required to make Python interpreter treat the directory
|
||||
# as containing package.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
15
BaseTools/Source/Python/Common/Edk2/__init__.py
Normal file
15
BaseTools/Source/Python/Common/Edk2/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
## @file
|
||||
# Python 'Common.Edk2' package initialization file.
|
||||
#
|
||||
# This file is required to make Python interpreter treat the directory
|
||||
# as containing package.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
184
BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
Normal file
184
BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
Normal file
@ -0,0 +1,184 @@
|
||||
## @file
|
||||
# Module that encodes and decodes a EFI_FIRMWARE_IMAGE_AUTHENTICATION with
|
||||
# certificate data and payload data.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
FmpAuthHeader
|
||||
'''
|
||||
|
||||
import struct
|
||||
import uuid
|
||||
|
||||
class FmpAuthHeaderClass (object):
|
||||
# ///
|
||||
# /// Image Attribute -Authentication Required
|
||||
# ///
|
||||
# typedef struct {
|
||||
# ///
|
||||
# /// It is included in the signature of AuthInfo. It is used to ensure freshness/no replay.
|
||||
# /// It is incremented during each firmware image operation.
|
||||
# ///
|
||||
# UINT64 MonotonicCount;
|
||||
# ///
|
||||
# /// Provides the authorization for the firmware image operations. It is a signature across
|
||||
# /// the image data and the Monotonic Count value. Caller uses the private key that is
|
||||
# /// associated with a public key that has been provisioned via the key exchange.
|
||||
# /// Because this is defined as a signature, WIN_CERTIFICATE_UEFI_GUID.CertType must
|
||||
# /// be EFI_CERT_TYPE_PKCS7_GUID.
|
||||
# ///
|
||||
# WIN_CERTIFICATE_UEFI_GUID AuthInfo;
|
||||
# } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
|
||||
#
|
||||
# ///
|
||||
# /// Certificate which encapsulates a GUID-specific digital signature
|
||||
# ///
|
||||
# typedef struct {
|
||||
# ///
|
||||
# /// This is the standard WIN_CERTIFICATE header, where
|
||||
# /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID.
|
||||
# ///
|
||||
# WIN_CERTIFICATE Hdr;
|
||||
# ///
|
||||
# /// This is the unique id which determines the
|
||||
# /// format of the CertData. .
|
||||
# ///
|
||||
# EFI_GUID CertType;
|
||||
# ///
|
||||
# /// The following is the certificate data. The format of
|
||||
# /// the data is determined by the CertType.
|
||||
# /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
|
||||
# /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
|
||||
# ///
|
||||
# UINT8 CertData[1];
|
||||
# } WIN_CERTIFICATE_UEFI_GUID;
|
||||
#
|
||||
# ///
|
||||
# /// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
|
||||
# ///
|
||||
# typedef struct {
|
||||
# ///
|
||||
# /// The length of the entire certificate,
|
||||
# /// including the length of the header, in bytes.
|
||||
# ///
|
||||
# UINT32 dwLength;
|
||||
# ///
|
||||
# /// The revision level of the WIN_CERTIFICATE
|
||||
# /// structure. The current revision level is 0x0200.
|
||||
# ///
|
||||
# UINT16 wRevision;
|
||||
# ///
|
||||
# /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI
|
||||
# /// certificate types. The UEFI specification reserves the range of
|
||||
# /// certificate type values from 0x0EF0 to 0x0EFF.
|
||||
# ///
|
||||
# UINT16 wCertificateType;
|
||||
# ///
|
||||
# /// The following is the actual certificate. The format of
|
||||
# /// the certificate depends on wCertificateType.
|
||||
# ///
|
||||
# /// UINT8 bCertificate[ANYSIZE_ARRAY];
|
||||
# ///
|
||||
# } WIN_CERTIFICATE;
|
||||
#
|
||||
# #define WIN_CERT_TYPE_EFI_GUID 0x0EF1
|
||||
#
|
||||
# ///
|
||||
# /// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315]
|
||||
# /// SignedData value.
|
||||
# ///
|
||||
# #define EFI_CERT_TYPE_PKCS7_GUID \
|
||||
# { \
|
||||
# 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \
|
||||
# }
|
||||
|
||||
_StructFormat = '<QIHH16s'
|
||||
_StructSize = struct.calcsize (_StructFormat)
|
||||
|
||||
_MonotonicCountFormat = '<Q'
|
||||
_MonotonicCountSize = struct.calcsize (_MonotonicCountFormat)
|
||||
|
||||
_StructAuthInfoFormat = '<IHH16s'
|
||||
_StructAuthInfoSize = struct.calcsize (_StructAuthInfoFormat)
|
||||
|
||||
_WIN_CERT_REVISION = 0x0200
|
||||
_WIN_CERT_TYPE_EFI_GUID = 0x0EF1
|
||||
_EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID ('4aafd29d-68df-49ee-8aa9-347d375665a7')
|
||||
|
||||
def __init__ (self):
|
||||
self._Valid = False
|
||||
self.MonotonicCount = 0
|
||||
self.dwLength = self._StructAuthInfoSize
|
||||
self.wRevision = self._WIN_CERT_REVISION
|
||||
self.wCertificateType = self._WIN_CERT_TYPE_EFI_GUID
|
||||
self.CertType = self._EFI_CERT_TYPE_PKCS7_GUID
|
||||
self.CertData = b''
|
||||
self.Payload = b''
|
||||
|
||||
|
||||
def Encode (self):
|
||||
if self.wRevision != self._WIN_CERT_REVISION:
|
||||
raise ValueError
|
||||
if self.wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:
|
||||
raise ValueError
|
||||
if self.CertType != self._EFI_CERT_TYPE_PKCS7_GUID:
|
||||
raise ValueError
|
||||
self.dwLength = self._StructAuthInfoSize + len (self.CertData)
|
||||
|
||||
FmpAuthHeader = struct.pack (
|
||||
self._StructFormat,
|
||||
self.MonotonicCount,
|
||||
self.dwLength,
|
||||
self.wRevision,
|
||||
self.wCertificateType,
|
||||
self.CertType.bytes_le
|
||||
)
|
||||
self._Valid = True
|
||||
|
||||
return FmpAuthHeader + self.CertData + self.Payload
|
||||
|
||||
def Decode (self, Buffer):
|
||||
if len (Buffer) < self._StructSize:
|
||||
raise ValueError
|
||||
(MonotonicCount, dwLength, wRevision, wCertificateType, CertType) = \
|
||||
struct.unpack (
|
||||
self._StructFormat,
|
||||
Buffer[0:self._StructSize]
|
||||
)
|
||||
if dwLength < self._StructAuthInfoSize:
|
||||
raise ValueError
|
||||
if wRevision != self._WIN_CERT_REVISION:
|
||||
raise ValueError
|
||||
if wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:
|
||||
raise ValueError
|
||||
if CertType != self._EFI_CERT_TYPE_PKCS7_GUID.bytes_le:
|
||||
raise ValueError
|
||||
self.MonotonicCount = MonotonicCount
|
||||
self.dwLength = dwLength
|
||||
self.wRevision = wRevision
|
||||
self.wCertificateType = wCertificateType
|
||||
self.CertType = uuid.UUID (bytes = CertType)
|
||||
self.CertData = Buffer[self._StructSize:self._MonotonicCountSize + self.dwLength]
|
||||
self.Payload = Buffer[self._MonotonicCountSize + self.dwLength:]
|
||||
self._Valid = True
|
||||
return self.Payload
|
||||
|
||||
def DumpInfo (self):
|
||||
if not self._Valid:
|
||||
raise ValueError
|
||||
print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount = {MonotonicCount:016X}'.format (MonotonicCount = self.MonotonicCount))
|
||||
print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.dwLength = {dwLength:08X}'.format (dwLength = self.dwLength))
|
||||
print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wRevision = {wRevision:04X}'.format (wRevision = self.wRevision))
|
||||
print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wCertificateType = {wCertificateType:04X}'.format (wCertificateType = self.wCertificateType))
|
||||
print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertType = {Guid}'.format (Guid = str(self.CertType).upper()))
|
||||
print ('sizeof (EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertData) = {Size:08X}'.format (Size = len (self.CertData)))
|
||||
print ('sizeof (Payload) = {Size:08X}'.format (Size = len (self.Payload)))
|
302
BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
Normal file
302
BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
Normal file
@ -0,0 +1,302 @@
|
||||
## @file
|
||||
# Module that encodes and decodes a EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with
|
||||
# a payload.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
FmpCapsuleHeader
|
||||
'''
|
||||
|
||||
import struct
|
||||
import uuid
|
||||
|
||||
class FmpCapsuleImageHeaderClass (object):
|
||||
# typedef struct {
|
||||
# UINT32 Version;
|
||||
#
|
||||
# ///
|
||||
# /// Used to identify device firmware targeted by this update. This guid is matched by
|
||||
# /// system firmware against ImageTypeId field within a EFI_FIRMWARE_IMAGE_DESCRIPTOR
|
||||
# ///
|
||||
# EFI_GUID UpdateImageTypeId;
|
||||
#
|
||||
# ///
|
||||
# /// Passed as ImageIndex in call to EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage ()
|
||||
# ///
|
||||
# UINT8 UpdateImageIndex;
|
||||
# UINT8 reserved_bytes[3];
|
||||
#
|
||||
# ///
|
||||
# /// Size of the binary update image which immediately follows this structure
|
||||
# ///
|
||||
# UINT32 UpdateImageSize;
|
||||
#
|
||||
# ///
|
||||
# /// Size of the VendorCode bytes which optionally immediately follow binary update image in the capsule
|
||||
# ///
|
||||
# UINT32 UpdateVendorCodeSize;
|
||||
#
|
||||
# ///
|
||||
# /// The HardwareInstance to target with this update. If value is zero it means match all
|
||||
# /// HardwareInstances. This field allows update software to target only a single device in
|
||||
# /// cases where there are more than one device with the same ImageTypeId GUID.
|
||||
# /// This header is outside the signed data of the Authentication Info structure and
|
||||
# /// therefore can be modified without changing the Auth data.
|
||||
# ///
|
||||
# UINT64 UpdateHardwareInstance;
|
||||
# } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
|
||||
#
|
||||
# #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002
|
||||
|
||||
_StructFormat = '<I16sB3BIIQ'
|
||||
_StructSize = struct.calcsize (_StructFormat)
|
||||
|
||||
EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002
|
||||
|
||||
def __init__ (self):
|
||||
self._Valid = False
|
||||
self.Version = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
|
||||
self.UpdateImageTypeId = uuid.UUID ('00000000-0000-0000-0000-000000000000')
|
||||
self.UpdateImageIndex = 0
|
||||
self.UpdateImageSize = 0
|
||||
self.UpdateVendorCodeSize = 0
|
||||
self.UpdateHardwareInstance = 0x0000000000000000
|
||||
self.Payload = b''
|
||||
self.VendorCodeBytes = b''
|
||||
|
||||
def Encode (self):
|
||||
self.UpdateImageSize = len (self.Payload)
|
||||
self.UpdateVendorCodeSize = len (self.VendorCodeBytes)
|
||||
FmpCapsuleImageHeader = struct.pack (
|
||||
self._StructFormat,
|
||||
self.Version,
|
||||
self.UpdateImageTypeId.bytes_le,
|
||||
self.UpdateImageIndex,
|
||||
0,0,0,
|
||||
self.UpdateImageSize,
|
||||
self.UpdateVendorCodeSize,
|
||||
self.UpdateHardwareInstance
|
||||
)
|
||||
self._Valid = True
|
||||
return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes
|
||||
|
||||
def Decode (self, Buffer):
|
||||
if len (Buffer) < self._StructSize:
|
||||
raise ValueError
|
||||
(Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize, UpdateHardwareInstance) = \
|
||||
struct.unpack (
|
||||
self._StructFormat,
|
||||
Buffer[0:self._StructSize]
|
||||
)
|
||||
|
||||
if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION:
|
||||
raise ValueError
|
||||
if UpdateImageIndex < 1:
|
||||
raise ValueError
|
||||
if UpdateImageSize + UpdateVendorCodeSize != len (Buffer[self._StructSize:]):
|
||||
raise ValueError
|
||||
|
||||
self.Version = Version
|
||||
self.UpdateImageTypeId = uuid.UUID (bytes_le = UpdateImageTypeId)
|
||||
self.UpdateImageIndex = UpdateImageIndex
|
||||
self.UpdateImageSize = UpdateImageSize
|
||||
self.UpdateVendorCodeSize = UpdateVendorCodeSize
|
||||
self.UpdateHardwareInstance = UpdateHardwareInstance
|
||||
self.Payload = Buffer[self._StructSize:self._StructSize + UpdateImageSize]
|
||||
self.VendorCodeBytes = Buffer[self._StructSize + UpdateImageSize:]
|
||||
self._Valid = True
|
||||
return Buffer[self._StructSize:]
|
||||
|
||||
def DumpInfo (self):
|
||||
if not self._Valid:
|
||||
raise ValueError
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version = {Version:08X}'.format (Version = self.Version))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageTypeId = {UpdateImageTypeId}'.format (UpdateImageTypeId = str(self.UpdateImageTypeId).upper()))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageIndex = {UpdateImageIndex:08X}'.format (UpdateImageIndex = self.UpdateImageIndex))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize = {UpdateImageSize:08X}'.format (UpdateImageSize = self.UpdateImageSize))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize = {UpdateVendorCodeSize:08X}'.format (UpdateVendorCodeSize = self.UpdateVendorCodeSize))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance = {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))
|
||||
print ('sizeof (Payload) = {Size:08X}'.format (Size = len (self.Payload)))
|
||||
print ('sizeof (VendorCodeBytes) = {Size:08X}'.format (Size = len (self.VendorCodeBytes)))
|
||||
|
||||
class FmpCapsuleHeaderClass (object):
|
||||
# typedef struct {
|
||||
# UINT32 Version;
|
||||
#
|
||||
# ///
|
||||
# /// The number of drivers included in the capsule and the number of corresponding
|
||||
# /// offsets stored in ItemOffsetList array.
|
||||
# ///
|
||||
# UINT16 EmbeddedDriverCount;
|
||||
#
|
||||
# ///
|
||||
# /// The number of payload items included in the capsule and the number of
|
||||
# /// corresponding offsets stored in the ItemOffsetList array.
|
||||
# ///
|
||||
# UINT16 PayloadItemCount;
|
||||
#
|
||||
# ///
|
||||
# /// Variable length array of dimension [EmbeddedDriverCount + PayloadItemCount]
|
||||
# /// containing offsets of each of the drivers and payload items contained within the capsule
|
||||
# ///
|
||||
# // UINT64 ItemOffsetList[];
|
||||
# } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
|
||||
#
|
||||
# #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION 0x00000001
|
||||
_StructFormat = '<IHH'
|
||||
_StructSize = struct.calcsize (_StructFormat)
|
||||
|
||||
_ItemOffsetFormat = '<Q'
|
||||
_ItemOffsetSize = struct.calcsize (_ItemOffsetFormat)
|
||||
|
||||
EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001
|
||||
|
||||
def __init__ (self):
|
||||
self._Valid = False
|
||||
self.Version = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
|
||||
self.EmbeddedDriverCount = 0
|
||||
self.PayloadItemCount = 0
|
||||
self._ItemOffsetList = []
|
||||
self._EmbeddedDriverList = []
|
||||
self._PayloadList = []
|
||||
self._FmpCapsuleImageHeaderList = []
|
||||
|
||||
def AddEmbeddedDriver (self, EmbeddedDriver):
|
||||
self._EmbeddedDriverList.append (EmbeddedDriver)
|
||||
|
||||
def GetEmbeddedDriver (self, Index):
|
||||
if Index > len (self._EmbeddedDriverList):
|
||||
raise ValueError
|
||||
return self._EmbeddedDriverList[Index]
|
||||
|
||||
def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0):
|
||||
self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance))
|
||||
|
||||
def GetFmpCapsuleImageHeader (self, Index):
|
||||
if Index >= len (self._FmpCapsuleImageHeaderList):
|
||||
raise ValueError
|
||||
return self._FmpCapsuleImageHeaderList[Index]
|
||||
|
||||
def Encode (self):
|
||||
self.EmbeddedDriverCount = len (self._EmbeddedDriverList)
|
||||
self.PayloadItemCount = len (self._PayloadList)
|
||||
|
||||
FmpCapsuleHeader = struct.pack (
|
||||
self._StructFormat,
|
||||
self.Version,
|
||||
self.EmbeddedDriverCount,
|
||||
self.PayloadItemCount
|
||||
)
|
||||
|
||||
FmpCapsuleData = b''
|
||||
Offset = self._StructSize + (self.EmbeddedDriverCount + self.PayloadItemCount) * self._ItemOffsetSize
|
||||
for EmbeddedDriver in self._EmbeddedDriverList:
|
||||
FmpCapsuleData = FmpCapsuleData + EmbeddedDriver
|
||||
self._ItemOffsetList.append (Offset)
|
||||
Offset = Offset + len (EmbeddedDriver)
|
||||
Index = 1
|
||||
for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance) in self._PayloadList:
|
||||
FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
|
||||
FmpCapsuleImageHeader.UpdateImageTypeId = UpdateImageTypeId
|
||||
FmpCapsuleImageHeader.UpdateImageIndex = Index
|
||||
FmpCapsuleImageHeader.Payload = Payload
|
||||
FmpCapsuleImageHeader.VendorCodeBytes = VendorCodeBytes
|
||||
FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance
|
||||
FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()
|
||||
FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage
|
||||
|
||||
self._ItemOffsetList.append (Offset)
|
||||
self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
|
||||
|
||||
Offset = Offset + len (FmpCapsuleImage)
|
||||
Index = Index + 1
|
||||
|
||||
for Offset in self._ItemOffsetList:
|
||||
FmpCapsuleHeader = FmpCapsuleHeader + struct.pack (self._ItemOffsetFormat, Offset)
|
||||
|
||||
self._Valid = True
|
||||
return FmpCapsuleHeader + FmpCapsuleData
|
||||
|
||||
def Decode (self, Buffer):
|
||||
if len (Buffer) < self._StructSize:
|
||||
raise ValueError
|
||||
(Version, EmbeddedDriverCount, PayloadItemCount) = \
|
||||
struct.unpack (
|
||||
self._StructFormat,
|
||||
Buffer[0:self._StructSize]
|
||||
)
|
||||
if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION:
|
||||
raise ValueError
|
||||
|
||||
self.Version = Version
|
||||
self.EmbeddedDriverCount = EmbeddedDriverCount
|
||||
self.PayloadItemCount = PayloadItemCount
|
||||
self._ItemOffsetList = []
|
||||
self._EmbeddedDriverList = []
|
||||
self._PayloadList = []
|
||||
self._FmpCapsuleImageHeaderList = []
|
||||
|
||||
#
|
||||
# Parse the ItemOffsetList values
|
||||
#
|
||||
Offset = self._StructSize
|
||||
for Index in range (0, EmbeddedDriverCount + PayloadItemCount):
|
||||
ItemOffset = struct.unpack (self._ItemOffsetFormat, Buffer[Offset:Offset + self._ItemOffsetSize])[0]
|
||||
if ItemOffset >= len (Buffer):
|
||||
raise ValueError
|
||||
self._ItemOffsetList.append (ItemOffset)
|
||||
Offset = Offset + self._ItemOffsetSize
|
||||
Result = Buffer[Offset:]
|
||||
|
||||
#
|
||||
# Parse the EmbeddedDrivers
|
||||
#
|
||||
for Index in range (0, EmbeddedDriverCount):
|
||||
Offset = self._ItemOffsetList[Index]
|
||||
if Index < (len (self._ItemOffsetList) - 1):
|
||||
Length = self._ItemOffsetList[Index + 1] - Offset
|
||||
else:
|
||||
Length = len (Buffer) - Offset
|
||||
self.AddEmbeddedDriver (Buffer[Offset:Offset + Length])
|
||||
|
||||
#
|
||||
# Parse the Payloads that are FMP Capsule Images
|
||||
#
|
||||
for Index in range (EmbeddedDriverCount, EmbeddedDriverCount + PayloadItemCount):
|
||||
Offset = self._ItemOffsetList[Index]
|
||||
if Index < (len (self._ItemOffsetList) - 1):
|
||||
Length = self._ItemOffsetList[Index + 1] - Offset
|
||||
else:
|
||||
Length = len (Buffer) - Offset
|
||||
FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
|
||||
FmpCapsuleImageHeader.Decode (Buffer[Offset:Offset + Length])
|
||||
self.AddPayload (
|
||||
FmpCapsuleImageHeader.UpdateImageTypeId,
|
||||
FmpCapsuleImageHeader.Payload,
|
||||
FmpCapsuleImageHeader.VendorCodeBytes
|
||||
)
|
||||
self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
|
||||
|
||||
self._Valid = True
|
||||
return Result
|
||||
|
||||
def DumpInfo (self):
|
||||
if not self._Valid:
|
||||
raise ValueError
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version = {Version:08X}'.format (Version = self.Version))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format (EmbeddedDriverCount = self.EmbeddedDriverCount))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCount = {PayloadItemCount:08X}'.format (PayloadItemCount = self.PayloadItemCount))
|
||||
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList = ')
|
||||
for Offset in self._ItemOffsetList:
|
||||
print (' {Offset:016X}'.format (Offset = Offset))
|
||||
for FmpCapsuleImageHeader in self._FmpCapsuleImageHeaderList:
|
||||
FmpCapsuleImageHeader.DumpInfo ()
|
136
BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
Normal file
136
BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
Normal file
@ -0,0 +1,136 @@
|
||||
## @file
|
||||
# Module that encodes and decodes a EFI_CAPSULE_HEADER with a payload
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
'''
|
||||
UefiCapsuleHeader
|
||||
'''
|
||||
|
||||
import struct
|
||||
import uuid
|
||||
|
||||
class UefiCapsuleHeaderClass (object):
|
||||
# typedef struct {
|
||||
# ///
|
||||
# /// A GUID that defines the contents of a capsule.
|
||||
# ///
|
||||
# EFI_GUID CapsuleGuid;
|
||||
# ///
|
||||
# /// The size of the capsule header. This may be larger than the size of
|
||||
# /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply
|
||||
# /// extended header entries
|
||||
# ///
|
||||
# UINT32 HeaderSize;
|
||||
# ///
|
||||
# /// Bit-mapped list describing the capsule attributes. The Flag values
|
||||
# /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values
|
||||
# /// of 0x10000 - 0xFFFFFFFF are defined by this specification
|
||||
# ///
|
||||
# UINT32 Flags;
|
||||
# ///
|
||||
# /// Size in bytes of the capsule.
|
||||
# ///
|
||||
# UINT32 CapsuleImageSize;
|
||||
# } EFI_CAPSULE_HEADER;
|
||||
#
|
||||
# #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
|
||||
# #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000
|
||||
# #define CAPSULE_FLAGS_INITIATE_RESET 0x00040000
|
||||
#
|
||||
_StructFormat = '<16sIIII'
|
||||
_StructSize = struct.calcsize (_StructFormat)
|
||||
|
||||
EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID = uuid.UUID ('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')
|
||||
|
||||
_CAPSULE_FLAGS_PERSIST_ACROSS_RESET = 0x00010000
|
||||
_CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE = 0x00020000
|
||||
_CAPSULE_FLAGS_INITIATE_RESET = 0x00040000
|
||||
|
||||
def __init__ (self):
|
||||
self._Valid = False
|
||||
self.CapsuleGuid = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
|
||||
self.HeaderSize = self._StructSize
|
||||
self.OemFlags = 0x0000
|
||||
self.PersistAcrossReset = False
|
||||
self.PopulateSystemTable = False
|
||||
self.InitiateReset = False
|
||||
self.CapsuleImageSize = self.HeaderSize
|
||||
self.Payload = b''
|
||||
|
||||
def Encode (self):
|
||||
Flags = self.OemFlags
|
||||
if self.PersistAcrossReset:
|
||||
Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
|
||||
if self.PopulateSystemTable:
|
||||
Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
|
||||
if self.InitiateReset:
|
||||
Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET
|
||||
|
||||
self.CapsuleImageSize = self.HeaderSize + len (self.Payload)
|
||||
|
||||
UefiCapsuleHeader = struct.pack (
|
||||
self._StructFormat,
|
||||
self.CapsuleGuid.bytes_le,
|
||||
self.HeaderSize,
|
||||
Flags,
|
||||
self.CapsuleImageSize,
|
||||
0
|
||||
)
|
||||
self._Valid = True
|
||||
return UefiCapsuleHeader + self.Payload
|
||||
|
||||
def Decode (self, Buffer):
|
||||
if len (Buffer) < self._StructSize:
|
||||
raise ValueError
|
||||
(CapsuleGuid, HeaderSize, Flags, CapsuleImageSize, Reserved) = \
|
||||
struct.unpack (
|
||||
self._StructFormat,
|
||||
Buffer[0:self._StructSize]
|
||||
)
|
||||
if HeaderSize < self._StructSize:
|
||||
raise ValueError
|
||||
if CapsuleImageSize != len (Buffer):
|
||||
raise ValueError
|
||||
self.CapsuleGuid = uuid.UUID (bytes_le = CapsuleGuid)
|
||||
self.HeaderSize = HeaderSize
|
||||
self.OemFlags = Flags & 0xffff
|
||||
self.PersistAcrossReset = (Flags & self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0
|
||||
self.PopulateSystemTable = (Flags & self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0
|
||||
self.InitiateReset = (Flags & self._CAPSULE_FLAGS_INITIATE_RESET) != 0
|
||||
self.CapsuleImageSize = CapsuleImageSize
|
||||
self.Payload = Buffer[self.HeaderSize:]
|
||||
|
||||
self._Valid = True
|
||||
return self.Payload
|
||||
|
||||
def DumpInfo (self):
|
||||
if not self._Valid:
|
||||
raise ValueError
|
||||
Flags = self.OemFlags
|
||||
if self.PersistAcrossReset:
|
||||
Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
|
||||
if self.PopulateSystemTable:
|
||||
Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
|
||||
if self.InitiateReset:
|
||||
Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET
|
||||
print ('EFI_CAPSULE_HEADER.CapsuleGuid = {Guid}'.format (Guid = str(self.CapsuleGuid).upper()))
|
||||
print ('EFI_CAPSULE_HEADER.HeaderSize = {Size:08X}'.format (Size = self.HeaderSize))
|
||||
print ('EFI_CAPSULE_HEADER.Flags = {Flags:08X}'.format (Flags = Flags))
|
||||
print (' OEM Flags = {Flags:04X}'.format (Flags = self.OemFlags))
|
||||
if self.PersistAcrossReset:
|
||||
print (' CAPSULE_FLAGS_PERSIST_ACROSS_RESET')
|
||||
if self.PopulateSystemTable:
|
||||
print (' CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE')
|
||||
if self.InitiateReset:
|
||||
print (' CAPSULE_FLAGS_INITIATE_RESET')
|
||||
print ('EFI_CAPSULE_HEADER.CapsuleImageSize = {Size:08X}'.format (Size = self.CapsuleImageSize))
|
||||
print ('sizeof (Payload) = {Size:08X}'.format (Size = len (self.Payload)))
|
15
BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
Normal file
15
BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
## @file
|
||||
# Python 'Common.Uefi.Capsule' package initialization file.
|
||||
#
|
||||
# This file is required to make Python interpreter treat the directory
|
||||
# as containing package.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
15
BaseTools/Source/Python/Common/Uefi/__init__.py
Normal file
15
BaseTools/Source/Python/Common/Uefi/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
## @file
|
||||
# Python 'Common.Uefi' package initialization file.
|
||||
#
|
||||
# This file is required to make Python interpreter treat the directory
|
||||
# as containing package.
|
||||
#
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
Loading…
x
Reference in New Issue
Block a user