summaryrefslogtreecommitdiffstats
path: root/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
diff options
context:
space:
mode:
authorKinney, Michael D <michael.d.kinney@intel.com>2018-05-01 20:54:46 -0700
committerKinney, Michael D <michael.d.kinney@intel.com>2018-08-02 14:35:20 -0700
commit8b63877aca1e5a3576b7275439c494a6d40ed1b5 (patch)
tree0463caba8f91441a0f136310527f9540f36810ec /BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
parent3a0c1bf64b5deaa4e227b311cc43aa1513beae5e (diff)
downloadedk2-8b63877aca1e5a3576b7275439c494a6d40ed1b5.tar.gz
edk2-8b63877aca1e5a3576b7275439c494a6d40ed1b5.tar.bz2
edk2-8b63877aca1e5a3576b7275439c494a6d40ed1b5.zip
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>
Diffstat (limited to 'BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py')
-rw-r--r--BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py302
1 files changed, 302 insertions, 0 deletions
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
new file mode 100644
index 0000000000..2461fb5068
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
@@ -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 ()