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