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