Add support for the ImageCapsuleSupport field, introduced in version 3 of the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER structure. This structure member is used to indicate if the corresponding payload has support for authentication and dependency. Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Bob Feng <bob.c.feng@intel.com>
		
			
				
	
	
		
			311 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			311 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # Module that encodes and decodes a EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with
 | |
| # a payload.
 | |
| #
 | |
| # Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
| # SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| #
 | |
| 
 | |
| '''
 | |
| 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;
 | |
|     #
 | |
|     #   ///
 | |
|     #   /// Bits which indicate authentication and depex information for the image that follows this structure
 | |
|     #   ///
 | |
|     #   UINT64   ImageCapsuleSupport
 | |
|     # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
 | |
|     #
 | |
|     #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000003
 | |
| 
 | |
|     _StructFormat = '<I16sB3BIIQQ'
 | |
|     _StructSize   = struct.calcsize (_StructFormat)
 | |
| 
 | |
|     EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000003
 | |
| 
 | |
|     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.ImageCapsuleSupport    = 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.ImageCapsuleSupport
 | |
|                                          )
 | |
|         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, ImageCapsuleSupport) = \
 | |
|             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.ImageCapsuleSupport    = ImageCapsuleSupport
 | |
|         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 ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.ImageCapsuleSupport    = {ImageCapsuleSupport:016X}'.format (ImageCapsuleSupport = self.ImageCapsuleSupport))
 | |
|         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
 | |
|     CAPSULE_SUPPORT_AUTHENTICATION = 0x0000000000000001
 | |
|     CAPSULE_SUPPORT_DEPENDENCY     = 0x0000000000000002
 | |
| 
 | |
|     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, UpdateImageIndex = 1, CapsuleSupport = 0):
 | |
|         self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex, CapsuleSupport))
 | |
| 
 | |
|     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, UpdateImageIndex, CapsuleSupport) in self._PayloadList:
 | |
|             FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
 | |
|             FmpCapsuleImageHeader.UpdateImageTypeId      = UpdateImageTypeId
 | |
|             FmpCapsuleImageHeader.UpdateImageIndex       = UpdateImageIndex
 | |
|             FmpCapsuleImageHeader.Payload                = Payload
 | |
|             FmpCapsuleImageHeader.VendorCodeBytes        = VendorCodeBytes
 | |
|             FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance
 | |
|             FmpCapsuleImageHeader.ImageCapsuleSupport    = CapsuleSupport
 | |
|             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))
 | |
|         for EmbeddedDriver in self._EmbeddedDriverList:
 | |
|             print ('  sizeof (EmbeddedDriver)                                  = {Size:08X}'.format (Size = len (EmbeddedDriver)))
 | |
|         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 ()
 |