]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / Python / Common / Uefi / Capsule / FmpCapsuleHeader.py
1 ## @file
2 # Module that encodes and decodes a EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with
3 # a payload.
4 #
5 # Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 '''
10 FmpCapsuleHeader
11 '''
12
13 import struct
14 import uuid
15
16 class FmpCapsuleImageHeaderClass (object):
17 # typedef struct {
18 # UINT32 Version;
19 #
20 # ///
21 # /// Used to identify device firmware targeted by this update. This guid is matched by
22 # /// system firmware against ImageTypeId field within a EFI_FIRMWARE_IMAGE_DESCRIPTOR
23 # ///
24 # EFI_GUID UpdateImageTypeId;
25 #
26 # ///
27 # /// Passed as ImageIndex in call to EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage ()
28 # ///
29 # UINT8 UpdateImageIndex;
30 # UINT8 reserved_bytes[3];
31 #
32 # ///
33 # /// Size of the binary update image which immediately follows this structure
34 # ///
35 # UINT32 UpdateImageSize;
36 #
37 # ///
38 # /// Size of the VendorCode bytes which optionally immediately follow binary update image in the capsule
39 # ///
40 # UINT32 UpdateVendorCodeSize;
41 #
42 # ///
43 # /// The HardwareInstance to target with this update. If value is zero it means match all
44 # /// HardwareInstances. This field allows update software to target only a single device in
45 # /// cases where there are more than one device with the same ImageTypeId GUID.
46 # /// This header is outside the signed data of the Authentication Info structure and
47 # /// therefore can be modified without changing the Auth data.
48 # ///
49 # UINT64 UpdateHardwareInstance;
50 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
51 #
52 # #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002
53
54 _StructFormat = '<I16sB3BIIQ'
55 _StructSize = struct.calcsize (_StructFormat)
56
57 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002
58
59 def __init__ (self):
60 self._Valid = False
61 self.Version = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
62 self.UpdateImageTypeId = uuid.UUID ('00000000-0000-0000-0000-000000000000')
63 self.UpdateImageIndex = 0
64 self.UpdateImageSize = 0
65 self.UpdateVendorCodeSize = 0
66 self.UpdateHardwareInstance = 0x0000000000000000
67 self.Payload = b''
68 self.VendorCodeBytes = b''
69
70 def Encode (self):
71 self.UpdateImageSize = len (self.Payload)
72 self.UpdateVendorCodeSize = len (self.VendorCodeBytes)
73 FmpCapsuleImageHeader = struct.pack (
74 self._StructFormat,
75 self.Version,
76 self.UpdateImageTypeId.bytes_le,
77 self.UpdateImageIndex,
78 0,0,0,
79 self.UpdateImageSize,
80 self.UpdateVendorCodeSize,
81 self.UpdateHardwareInstance
82 )
83 self._Valid = True
84 return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes
85
86 def Decode (self, Buffer):
87 if len (Buffer) < self._StructSize:
88 raise ValueError
89 (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize, UpdateHardwareInstance) = \
90 struct.unpack (
91 self._StructFormat,
92 Buffer[0:self._StructSize]
93 )
94
95 if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION:
96 raise ValueError
97 if UpdateImageIndex < 1:
98 raise ValueError
99 if UpdateImageSize + UpdateVendorCodeSize != len (Buffer[self._StructSize:]):
100 raise ValueError
101
102 self.Version = Version
103 self.UpdateImageTypeId = uuid.UUID (bytes_le = UpdateImageTypeId)
104 self.UpdateImageIndex = UpdateImageIndex
105 self.UpdateImageSize = UpdateImageSize
106 self.UpdateVendorCodeSize = UpdateVendorCodeSize
107 self.UpdateHardwareInstance = UpdateHardwareInstance
108 self.Payload = Buffer[self._StructSize:self._StructSize + UpdateImageSize]
109 self.VendorCodeBytes = Buffer[self._StructSize + UpdateImageSize:]
110 self._Valid = True
111 return Buffer[self._StructSize:]
112
113 def DumpInfo (self):
114 if not self._Valid:
115 raise ValueError
116 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version = {Version:08X}'.format (Version = self.Version))
117 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageTypeId = {UpdateImageTypeId}'.format (UpdateImageTypeId = str(self.UpdateImageTypeId).upper()))
118 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageIndex = {UpdateImageIndex:08X}'.format (UpdateImageIndex = self.UpdateImageIndex))
119 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize = {UpdateImageSize:08X}'.format (UpdateImageSize = self.UpdateImageSize))
120 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize = {UpdateVendorCodeSize:08X}'.format (UpdateVendorCodeSize = self.UpdateVendorCodeSize))
121 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance = {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))
122 print ('sizeof (Payload) = {Size:08X}'.format (Size = len (self.Payload)))
123 print ('sizeof (VendorCodeBytes) = {Size:08X}'.format (Size = len (self.VendorCodeBytes)))
124
125 class FmpCapsuleHeaderClass (object):
126 # typedef struct {
127 # UINT32 Version;
128 #
129 # ///
130 # /// The number of drivers included in the capsule and the number of corresponding
131 # /// offsets stored in ItemOffsetList array.
132 # ///
133 # UINT16 EmbeddedDriverCount;
134 #
135 # ///
136 # /// The number of payload items included in the capsule and the number of
137 # /// corresponding offsets stored in the ItemOffsetList array.
138 # ///
139 # UINT16 PayloadItemCount;
140 #
141 # ///
142 # /// Variable length array of dimension [EmbeddedDriverCount + PayloadItemCount]
143 # /// containing offsets of each of the drivers and payload items contained within the capsule
144 # ///
145 # // UINT64 ItemOffsetList[];
146 # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
147 #
148 # #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION 0x00000001
149 _StructFormat = '<IHH'
150 _StructSize = struct.calcsize (_StructFormat)
151
152 _ItemOffsetFormat = '<Q'
153 _ItemOffsetSize = struct.calcsize (_ItemOffsetFormat)
154
155 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001
156
157 def __init__ (self):
158 self._Valid = False
159 self.Version = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
160 self.EmbeddedDriverCount = 0
161 self.PayloadItemCount = 0
162 self._ItemOffsetList = []
163 self._EmbeddedDriverList = []
164 self._PayloadList = []
165 self._FmpCapsuleImageHeaderList = []
166
167 def AddEmbeddedDriver (self, EmbeddedDriver):
168 self._EmbeddedDriverList.append (EmbeddedDriver)
169
170 def GetEmbeddedDriver (self, Index):
171 if Index > len (self._EmbeddedDriverList):
172 raise ValueError
173 return self._EmbeddedDriverList[Index]
174
175 def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0):
176 self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance))
177
178 def GetFmpCapsuleImageHeader (self, Index):
179 if Index >= len (self._FmpCapsuleImageHeaderList):
180 raise ValueError
181 return self._FmpCapsuleImageHeaderList[Index]
182
183 def Encode (self):
184 self.EmbeddedDriverCount = len (self._EmbeddedDriverList)
185 self.PayloadItemCount = len (self._PayloadList)
186
187 FmpCapsuleHeader = struct.pack (
188 self._StructFormat,
189 self.Version,
190 self.EmbeddedDriverCount,
191 self.PayloadItemCount
192 )
193
194 FmpCapsuleData = b''
195 Offset = self._StructSize + (self.EmbeddedDriverCount + self.PayloadItemCount) * self._ItemOffsetSize
196 for EmbeddedDriver in self._EmbeddedDriverList:
197 FmpCapsuleData = FmpCapsuleData + EmbeddedDriver
198 self._ItemOffsetList.append (Offset)
199 Offset = Offset + len (EmbeddedDriver)
200 Index = 1
201 for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance) in self._PayloadList:
202 FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
203 FmpCapsuleImageHeader.UpdateImageTypeId = UpdateImageTypeId
204 FmpCapsuleImageHeader.UpdateImageIndex = Index
205 FmpCapsuleImageHeader.Payload = Payload
206 FmpCapsuleImageHeader.VendorCodeBytes = VendorCodeBytes
207 FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance
208 FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()
209 FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage
210
211 self._ItemOffsetList.append (Offset)
212 self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
213
214 Offset = Offset + len (FmpCapsuleImage)
215 Index = Index + 1
216
217 for Offset in self._ItemOffsetList:
218 FmpCapsuleHeader = FmpCapsuleHeader + struct.pack (self._ItemOffsetFormat, Offset)
219
220 self._Valid = True
221 return FmpCapsuleHeader + FmpCapsuleData
222
223 def Decode (self, Buffer):
224 if len (Buffer) < self._StructSize:
225 raise ValueError
226 (Version, EmbeddedDriverCount, PayloadItemCount) = \
227 struct.unpack (
228 self._StructFormat,
229 Buffer[0:self._StructSize]
230 )
231 if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION:
232 raise ValueError
233
234 self.Version = Version
235 self.EmbeddedDriverCount = EmbeddedDriverCount
236 self.PayloadItemCount = PayloadItemCount
237 self._ItemOffsetList = []
238 self._EmbeddedDriverList = []
239 self._PayloadList = []
240 self._FmpCapsuleImageHeaderList = []
241
242 #
243 # Parse the ItemOffsetList values
244 #
245 Offset = self._StructSize
246 for Index in range (0, EmbeddedDriverCount + PayloadItemCount):
247 ItemOffset = struct.unpack (self._ItemOffsetFormat, Buffer[Offset:Offset + self._ItemOffsetSize])[0]
248 if ItemOffset >= len (Buffer):
249 raise ValueError
250 self._ItemOffsetList.append (ItemOffset)
251 Offset = Offset + self._ItemOffsetSize
252 Result = Buffer[Offset:]
253
254 #
255 # Parse the EmbeddedDrivers
256 #
257 for Index in range (0, EmbeddedDriverCount):
258 Offset = self._ItemOffsetList[Index]
259 if Index < (len (self._ItemOffsetList) - 1):
260 Length = self._ItemOffsetList[Index + 1] - Offset
261 else:
262 Length = len (Buffer) - Offset
263 self.AddEmbeddedDriver (Buffer[Offset:Offset + Length])
264
265 #
266 # Parse the Payloads that are FMP Capsule Images
267 #
268 for Index in range (EmbeddedDriverCount, EmbeddedDriverCount + PayloadItemCount):
269 Offset = self._ItemOffsetList[Index]
270 if Index < (len (self._ItemOffsetList) - 1):
271 Length = self._ItemOffsetList[Index + 1] - Offset
272 else:
273 Length = len (Buffer) - Offset
274 FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
275 FmpCapsuleImageHeader.Decode (Buffer[Offset:Offset + Length])
276 self.AddPayload (
277 FmpCapsuleImageHeader.UpdateImageTypeId,
278 FmpCapsuleImageHeader.Payload,
279 FmpCapsuleImageHeader.VendorCodeBytes
280 )
281 self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
282
283 self._Valid = True
284 return Result
285
286 def DumpInfo (self):
287 if not self._Valid:
288 raise ValueError
289 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version = {Version:08X}'.format (Version = self.Version))
290 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format (EmbeddedDriverCount = self.EmbeddedDriverCount))
291 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCount = {PayloadItemCount:08X}'.format (PayloadItemCount = self.PayloadItemCount))
292 print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList = ')
293 for Offset in self._ItemOffsetList:
294 print (' {Offset:016X}'.format (Offset = Offset))
295 for FmpCapsuleImageHeader in self._FmpCapsuleImageHeaderList:
296 FmpCapsuleImageHeader.DumpInfo ()