]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
BaseTools/Capsule: Add Capsule Generation Tools
[mirror_edk2.git] / BaseTools / Source / Python / Common / Uefi / Capsule / FmpCapsuleHeader.py
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
new file mode 100644 (file)
index 0000000..2461fb5
--- /dev/null
@@ -0,0 +1,302 @@
+## @file\r
+# Module that encodes and decodes a EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with\r
+# a payload.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+'''\r
+FmpCapsuleHeader\r
+'''\r
+\r
+import struct\r
+import uuid\r
+\r
+class FmpCapsuleImageHeaderClass (object):\r
+    # typedef struct {\r
+    #   UINT32   Version;\r
+    #\r
+    #   ///\r
+    #   /// Used to identify device firmware targeted by this update. This guid is matched by\r
+    #   /// system firmware against ImageTypeId field within a EFI_FIRMWARE_IMAGE_DESCRIPTOR\r
+    #   ///\r
+    #   EFI_GUID UpdateImageTypeId;\r
+    #\r
+    #   ///\r
+    #   /// Passed as ImageIndex in call to EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage ()\r
+    #   ///\r
+    #   UINT8    UpdateImageIndex;\r
+    #   UINT8    reserved_bytes[3];\r
+    #\r
+    #   ///\r
+    #   /// Size of the binary update image which immediately follows this structure\r
+    #   ///\r
+    #   UINT32   UpdateImageSize;\r
+    #\r
+    #   ///\r
+    #   /// Size of the VendorCode bytes which optionally immediately follow binary update image in the capsule\r
+    #   ///\r
+    #   UINT32   UpdateVendorCodeSize;\r
+    #\r
+    #   ///\r
+    #   /// The HardwareInstance to target with this update. If value is zero it means match all\r
+    #   /// HardwareInstances. This field allows update software to target only a single device in\r
+    #   /// cases where there are more than one device with the same ImageTypeId GUID.\r
+    #   /// This header is outside the signed data of the Authentication Info structure and\r
+    #   /// therefore can be modified without changing the Auth data.\r
+    #   ///\r
+    #   UINT64   UpdateHardwareInstance;\r
+    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;\r
+    #\r
+    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002\r
+\r
+    _StructFormat = '<I16sB3BIIQ'\r
+    _StructSize   = struct.calcsize (_StructFormat)\r
+\r
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002\r
+\r
+    def __init__ (self):\r
+        self._Valid                 = False\r
+        self.Version                = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION\r
+        self.UpdateImageTypeId      = uuid.UUID ('00000000-0000-0000-0000-000000000000')\r
+        self.UpdateImageIndex       = 0\r
+        self.UpdateImageSize        = 0\r
+        self.UpdateVendorCodeSize   = 0\r
+        self.UpdateHardwareInstance = 0x0000000000000000\r
+        self.Payload                = b''\r
+        self.VendorCodeBytes        = b''\r
+\r
+    def Encode (self):\r
+        self.UpdateImageSize      = len (self.Payload)\r
+        self.UpdateVendorCodeSize = len (self.VendorCodeBytes)\r
+        FmpCapsuleImageHeader = struct.pack (\r
+                                         self._StructFormat,\r
+                                         self.Version,\r
+                                         self.UpdateImageTypeId.bytes_le,\r
+                                         self.UpdateImageIndex,\r
+                                         0,0,0,\r
+                                         self.UpdateImageSize,\r
+                                         self.UpdateVendorCodeSize,\r
+                                         self.UpdateHardwareInstance\r
+                                         )\r
+        self._Valid = True\r
+        return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes\r
+\r
+    def Decode (self, Buffer):\r
+        if len (Buffer) < self._StructSize:\r
+            raise ValueError\r
+        (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize, UpdateHardwareInstance) = \\r
+            struct.unpack (\r
+                     self._StructFormat,\r
+                     Buffer[0:self._StructSize]\r
+                     )\r
+\r
+        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION:\r
+            raise ValueError\r
+        if UpdateImageIndex < 1:\r
+            raise ValueError\r
+        if UpdateImageSize + UpdateVendorCodeSize != len (Buffer[self._StructSize:]):\r
+            raise ValueError\r
+\r
+        self.Version                = Version\r
+        self.UpdateImageTypeId      = uuid.UUID (bytes_le = UpdateImageTypeId)\r
+        self.UpdateImageIndex       = UpdateImageIndex\r
+        self.UpdateImageSize        = UpdateImageSize\r
+        self.UpdateVendorCodeSize   = UpdateVendorCodeSize\r
+        self.UpdateHardwareInstance = UpdateHardwareInstance\r
+        self.Payload                = Buffer[self._StructSize:self._StructSize + UpdateImageSize]\r
+        self.VendorCodeBytes        = Buffer[self._StructSize + UpdateImageSize:]\r
+        self._Valid                 = True\r
+        return Buffer[self._StructSize:]\r
+\r
+    def DumpInfo (self):\r
+        if not self._Valid:\r
+            raise ValueError\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version                = {Version:08X}'.format (Version = self.Version))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageTypeId      = {UpdateImageTypeId}'.format (UpdateImageTypeId = str(self.UpdateImageTypeId).upper()))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageIndex       = {UpdateImageIndex:08X}'.format (UpdateImageIndex = self.UpdateImageIndex))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize        = {UpdateImageSize:08X}'.format (UpdateImageSize = self.UpdateImageSize))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize   = {UpdateVendorCodeSize:08X}'.format (UpdateVendorCodeSize = self.UpdateVendorCodeSize))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance = {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))\r
+        print ('sizeof (Payload)                                                    = {Size:08X}'.format (Size = len (self.Payload)))\r
+        print ('sizeof (VendorCodeBytes)                                            = {Size:08X}'.format (Size = len (self.VendorCodeBytes)))\r
+\r
+class FmpCapsuleHeaderClass (object):\r
+    # typedef struct {\r
+    #   UINT32 Version;\r
+    #\r
+    #   ///\r
+    #   /// The number of drivers included in the capsule and the number of corresponding\r
+    #   /// offsets stored in ItemOffsetList array.\r
+    #   ///\r
+    #   UINT16 EmbeddedDriverCount;\r
+    #\r
+    #   ///\r
+    #   /// The number of payload items included in the capsule and the number of\r
+    #   /// corresponding offsets stored in the ItemOffsetList array.\r
+    #   ///\r
+    #   UINT16 PayloadItemCount;\r
+    #\r
+    #   ///\r
+    #   /// Variable length array of dimension [EmbeddedDriverCount + PayloadItemCount]\r
+    #   /// containing offsets of each of the drivers and payload items contained within the capsule\r
+    #   ///\r
+    #   // UINT64 ItemOffsetList[];\r
+    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;\r
+    #\r
+    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION       0x00000001\r
+    _StructFormat = '<IHH'\r
+    _StructSize   = struct.calcsize (_StructFormat)\r
+\r
+    _ItemOffsetFormat = '<Q'\r
+    _ItemOffsetSize   = struct.calcsize (_ItemOffsetFormat)\r
+\r
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001\r
+\r
+    def __init__ (self):\r
+        self._Valid                     = False\r
+        self.Version                    = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\r
+        self.EmbeddedDriverCount        = 0\r
+        self.PayloadItemCount           = 0\r
+        self._ItemOffsetList            = []\r
+        self._EmbeddedDriverList        = []\r
+        self._PayloadList               = []\r
+        self._FmpCapsuleImageHeaderList = []\r
+\r
+    def AddEmbeddedDriver (self, EmbeddedDriver):\r
+        self._EmbeddedDriverList.append (EmbeddedDriver)\r
+\r
+    def GetEmbeddedDriver (self, Index):\r
+        if Index > len (self._EmbeddedDriverList):\r
+            raise ValueError\r
+        return self._EmbeddedDriverList[Index]\r
+\r
+    def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0):\r
+        self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance))\r
+\r
+    def GetFmpCapsuleImageHeader (self, Index):\r
+        if Index >= len (self._FmpCapsuleImageHeaderList):\r
+            raise ValueError\r
+        return self._FmpCapsuleImageHeaderList[Index]\r
+\r
+    def Encode (self):\r
+        self.EmbeddedDriverCount = len (self._EmbeddedDriverList)\r
+        self.PayloadItemCount    = len (self._PayloadList)\r
+\r
+        FmpCapsuleHeader = struct.pack (\r
+                                    self._StructFormat,\r
+                                    self.Version,\r
+                                    self.EmbeddedDriverCount,\r
+                                    self.PayloadItemCount\r
+                                    )\r
+\r
+        FmpCapsuleData = b''\r
+        Offset = self._StructSize + (self.EmbeddedDriverCount + self.PayloadItemCount) * self._ItemOffsetSize\r
+        for EmbeddedDriver in self._EmbeddedDriverList:\r
+            FmpCapsuleData = FmpCapsuleData + EmbeddedDriver\r
+            self._ItemOffsetList.append (Offset)\r
+            Offset = Offset + len (EmbeddedDriver)\r
+        Index = 1\r
+        for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance) in self._PayloadList:\r
+            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()\r
+            FmpCapsuleImageHeader.UpdateImageTypeId      = UpdateImageTypeId\r
+            FmpCapsuleImageHeader.UpdateImageIndex       = Index\r
+            FmpCapsuleImageHeader.Payload                = Payload\r
+            FmpCapsuleImageHeader.VendorCodeBytes        = VendorCodeBytes\r
+            FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance\r
+            FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()\r
+            FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage\r
+\r
+            self._ItemOffsetList.append (Offset)\r
+            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)\r
+\r
+            Offset = Offset + len (FmpCapsuleImage)\r
+            Index = Index + 1\r
+\r
+        for Offset in self._ItemOffsetList:\r
+          FmpCapsuleHeader = FmpCapsuleHeader + struct.pack (self._ItemOffsetFormat, Offset)\r
+\r
+        self._Valid = True\r
+        return FmpCapsuleHeader + FmpCapsuleData\r
+\r
+    def Decode (self, Buffer):\r
+        if len (Buffer) < self._StructSize:\r
+            raise ValueError\r
+        (Version, EmbeddedDriverCount, PayloadItemCount) = \\r
+            struct.unpack (\r
+                     self._StructFormat,\r
+                     Buffer[0:self._StructSize]\r
+                     )\r
+        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION:\r
+            raise ValueError\r
+\r
+        self.Version                    = Version\r
+        self.EmbeddedDriverCount        = EmbeddedDriverCount\r
+        self.PayloadItemCount           = PayloadItemCount\r
+        self._ItemOffsetList            = []\r
+        self._EmbeddedDriverList        = []\r
+        self._PayloadList               = []\r
+        self._FmpCapsuleImageHeaderList = []\r
+\r
+        #\r
+        # Parse the ItemOffsetList values\r
+        #\r
+        Offset = self._StructSize\r
+        for Index in range (0, EmbeddedDriverCount + PayloadItemCount):\r
+            ItemOffset = struct.unpack (self._ItemOffsetFormat, Buffer[Offset:Offset + self._ItemOffsetSize])[0]\r
+            if ItemOffset >= len (Buffer):\r
+                raise ValueError\r
+            self._ItemOffsetList.append (ItemOffset)\r
+            Offset = Offset + self._ItemOffsetSize\r
+        Result = Buffer[Offset:]\r
+\r
+        #\r
+        # Parse the EmbeddedDrivers\r
+        #\r
+        for Index in range (0, EmbeddedDriverCount):\r
+            Offset = self._ItemOffsetList[Index]\r
+            if Index < (len (self._ItemOffsetList) - 1):\r
+                Length = self._ItemOffsetList[Index + 1] - Offset\r
+            else:\r
+                Length = len (Buffer) - Offset\r
+            self.AddEmbeddedDriver (Buffer[Offset:Offset + Length])\r
+\r
+        #\r
+        # Parse the Payloads that are FMP Capsule Images\r
+        #\r
+        for Index in range (EmbeddedDriverCount, EmbeddedDriverCount + PayloadItemCount):\r
+            Offset = self._ItemOffsetList[Index]\r
+            if Index < (len (self._ItemOffsetList) - 1):\r
+                Length = self._ItemOffsetList[Index + 1] - Offset\r
+            else:\r
+                Length = len (Buffer) - Offset\r
+            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()\r
+            FmpCapsuleImageHeader.Decode (Buffer[Offset:Offset + Length])\r
+            self.AddPayload (\r
+                   FmpCapsuleImageHeader.UpdateImageTypeId,\r
+                   FmpCapsuleImageHeader.Payload,\r
+                   FmpCapsuleImageHeader.VendorCodeBytes\r
+                   )\r
+            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)\r
+\r
+        self._Valid = True\r
+        return Result\r
+\r
+    def DumpInfo (self):\r
+        if not self._Valid:\r
+            raise ValueError\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version             = {Version:08X}'.format (Version = self.Version))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format (EmbeddedDriverCount = self.EmbeddedDriverCount))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCount    = {PayloadItemCount:08X}'.format (PayloadItemCount = self.PayloadItemCount))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList      = ')\r
+        for Offset in self._ItemOffsetList:\r
+            print ('  {Offset:016X}'.format (Offset = Offset))\r
+        for FmpCapsuleImageHeader in self._FmpCapsuleImageHeaderList:\r
+            FmpCapsuleImageHeader.DumpInfo ()\r