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