| ## @file | |
| # Module that encodes and decodes a EFI_CAPSULE_HEADER with a payload | |
| # | |
| # Copyright (c) 2018, Intel Corporation. All rights reserved.<BR> | |
| # SPDX-License-Identifier: BSD-2-Clause-Patent | |
| # | |
| ''' | |
| 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("HeaderSize of {0} doesn't match _StructSize of {1}".format(HeaderSize, self._StructSize)) | |
| if CapsuleImageSize != len (Buffer): | |
| raise ValueError("CapsuleImageSize of {0} doesn't match buffer length of {1}".format(CapsuleImageSize, len(Buffer))) | |
| 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))) |