]>
Commit | Line | Data |
---|---|---|
a6d73269 | 1 | /** @file\r |
b0bacc00 KM |
2 | UEFI variable support functions for Firmware Management Protocol based\r |
3 | firmware updates.\r | |
4 | \r | |
5 | Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r | |
67c1e5ee | 6 | Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r |
b0bacc00 | 7 | \r |
bcef758c | 8 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
b0bacc00 KM |
9 | \r |
10 | **/\r | |
11 | \r | |
67c1e5ee | 12 | #include "FmpDxe.h"\r |
b0bacc00 KM |
13 | #include "VariableSupport.h"\r |
14 | \r | |
67c1e5ee EJ |
15 | /**\r |
16 | Retrieve the value of a 32-bit UEFI Variable specified by VariableName and\r | |
17 | a GUID of gEfiCallerIdGuid.\r | |
18 | \r | |
19 | @param[in] VariableName Pointer to the UEFI Variable name to retrieve.\r | |
20 | @param[out] Valid Set to TRUE if UEFI Variable is present and the size\r | |
21 | of the UEFI Variable value is 32-bits. Otherwise\r | |
22 | FALSE.\r | |
23 | @param[out] Value If Valid is set to TRUE, then the 32-bit value of\r | |
24 | the UEFI Variable. Otherwise 0.\r | |
25 | **/\r | |
26 | static\r | |
27 | VOID\r | |
28 | GetFmpVariable (\r | |
29 | IN CHAR16 *VariableName,\r | |
30 | OUT BOOLEAN *Valid,\r | |
31 | OUT UINT32 *Value\r | |
32 | )\r | |
33 | {\r | |
34 | EFI_STATUS Status;\r | |
35 | UINTN Size;\r | |
36 | UINT32 *Buffer;\r | |
37 | \r | |
38 | *Valid = FALSE;\r | |
39 | *Value = 0;\r | |
40 | Size = 0;\r | |
41 | Buffer = NULL;\r | |
42 | Status = GetVariable2 (\r | |
43 | VariableName,\r | |
44 | &gEfiCallerIdGuid,\r | |
45 | (VOID **)&Buffer,\r | |
46 | &Size\r | |
47 | );\r | |
48 | if (!EFI_ERROR (Status) && Size == sizeof (*Value) && Buffer != NULL) {\r | |
49 | *Valid = TRUE;\r | |
50 | *Value = *Buffer;\r | |
51 | }\r | |
52 | if (Buffer != NULL) {\r | |
53 | FreePool (Buffer);\r | |
54 | }\r | |
55 | }\r | |
b0bacc00 KM |
56 | \r |
57 | /**\r | |
67c1e5ee EJ |
58 | Delete the UEFI Variable with name specified by VariableName and GUID of\r |
59 | gEfiCallerIdGuid. If the variable can not be deleted, then print a\r | |
60 | DEBUG_ERROR message.\r | |
b0bacc00 | 61 | \r |
67c1e5ee EJ |
62 | @param[in] VariableName Pointer to the UEFI Variable name to delete.\r |
63 | **/\r | |
64 | static\r | |
65 | VOID\r | |
66 | DeleteFmpVariable (\r | |
67 | IN CHAR16 *VariableName\r | |
68 | )\r | |
69 | {\r | |
70 | EFI_STATUS Status;\r | |
71 | BOOLEAN Valid;\r | |
72 | UINT32 Value;\r | |
b0bacc00 | 73 | \r |
67c1e5ee EJ |
74 | GetFmpVariable (VariableName, &Valid, &Value);\r |
75 | if (Valid) {\r | |
76 | Status = gRT->SetVariable (VariableName, &gEfiCallerIdGuid, 0, 0, NULL);\r | |
77 | if (EFI_ERROR (Status)) {\r | |
e0961677 | 78 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to delete variable %s. Status = %r\n", mImageIdName, VariableName, Status));\r |
67c1e5ee | 79 | } else {\r |
e0961677 | 80 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Deleted variable %s\n", mImageIdName, VariableName));\r |
67c1e5ee EJ |
81 | }\r |
82 | }\r | |
83 | }\r | |
84 | \r | |
85 | /**\r | |
86 | Retrieve the FMP Controller State UEFI Variable value. Return NULL if\r | |
87 | the variable does not exist or if the size of the UEFI Variable is not the\r | |
88 | size of FMP_CONTROLLER_STATE. The buffer for the UEFI Variable value\r | |
89 | if allocated using the UEFI Boot Service AllocatePool().\r | |
b0bacc00 | 90 | \r |
67c1e5ee EJ |
91 | @param[in] Private Private context structure for the managed controller.\r |
92 | \r | |
93 | @return Pointer to the allocated FMP Controller State. Returns NULL\r | |
94 | if the variable does not exist or is a different size than expected.\r | |
b0bacc00 | 95 | **/\r |
67c1e5ee EJ |
96 | static\r |
97 | FMP_CONTROLLER_STATE *\r | |
98 | GetFmpControllerState (\r | |
99 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
b0bacc00 KM |
100 | )\r |
101 | {\r | |
67c1e5ee EJ |
102 | EFI_STATUS Status;\r |
103 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
104 | UINTN Size;\r | |
105 | \r | |
106 | FmpControllerState = NULL;\r | |
107 | Size = 0;\r | |
108 | Status = GetVariable2 (\r | |
109 | Private->FmpStateVariableName,\r | |
110 | &gEfiCallerIdGuid,\r | |
111 | (VOID **)&FmpControllerState,\r | |
112 | &Size\r | |
113 | );\r | |
114 | if (EFI_ERROR (Status) || FmpControllerState == NULL) {\r | |
e0961677 | 115 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to get the controller state. Status = %r\n", mImageIdName, Status));\r |
67c1e5ee EJ |
116 | } else {\r |
117 | if (Size == sizeof (*FmpControllerState)) {\r | |
118 | return FmpControllerState;\r | |
119 | }\r | |
e0961677 | 120 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Getting controller state returned a size different than expected. Size = 0x%x\n", mImageIdName, Size));\r |
67c1e5ee EJ |
121 | }\r |
122 | if (FmpControllerState != NULL) {\r | |
123 | FreePool (FmpControllerState);\r | |
124 | }\r | |
125 | return NULL;\r | |
126 | }\r | |
b0bacc00 | 127 | \r |
67c1e5ee EJ |
128 | /**\r |
129 | Generates a Null-terminated Unicode string UEFI Variable name from a base name\r | |
130 | and a hardware instance. If the hardware instance value is 0, then the base\r | |
131 | name is returned. If the hardware instance value is non-zero, then the 64-bit\r | |
132 | hardware instance value is converted to a 16 character hex string and appended\r | |
133 | to base name. The UEFI Variable name returned is allocated using the UEFI\r | |
134 | Boot Service AllocatePool().\r | |
135 | \r | |
136 | @param[in] HardwareInstance 64-bit hardware instance value.\r | |
137 | @param[in] BaseVariableName Null-terminated Unicode string that is the base\r | |
138 | name of the UEFI Variable.\r | |
139 | \r | |
140 | @return Pointer to the allocated UEFI Variable name. Returns NULL if the\r | |
141 | UEFI Variable can not be allocated.\r | |
142 | **/\r | |
143 | static\r | |
144 | CHAR16 *\r | |
145 | GenerateFmpVariableName (\r | |
146 | IN UINT64 HardwareInstance,\r | |
147 | IN CHAR16 *BaseVariableName\r | |
148 | )\r | |
149 | {\r | |
150 | CHAR16 *VariableName;\r | |
151 | \r | |
152 | VariableName = CatSPrint (NULL, BaseVariableName);\r | |
153 | if (VariableName == NULL) {\r | |
e0961677 | 154 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to generate variable name %s.\n", mImageIdName, BaseVariableName));\r |
67c1e5ee EJ |
155 | return VariableName;\r |
156 | }\r | |
157 | if (HardwareInstance == 0) {\r | |
158 | return VariableName;\r | |
159 | }\r | |
160 | VariableName = CatSPrint (VariableName, L"%016lx", HardwareInstance);\r | |
161 | if (VariableName == NULL) {\r | |
e0961677 | 162 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to generate variable name %s.\n", mImageIdName, BaseVariableName));\r |
67c1e5ee EJ |
163 | }\r |
164 | return VariableName;\r | |
165 | }\r | |
166 | \r | |
167 | /**\r | |
168 | Generate the names of the UEFI Variables used to store state information for\r | |
169 | a managed controller. The UEFI Variables names are a combination of a base\r | |
170 | name and an optional hardware instance value as a 16 character hex value. If\r | |
171 | the hardware instance value is 0, then the 16 character hex value is not\r | |
172 | included. These storage for the UEFI Variable names are allocated using the\r | |
173 | UEFI Boot Service AllocatePool() and the pointers are stored in the Private.\r | |
174 | The following are examples of variable names produces for hardware instance\r | |
175 | value 0 and value 0x1234567812345678.\r | |
176 | \r | |
177 | FmpVersion\r | |
178 | FmpLsv\r | |
179 | LastAttemptStatus\r | |
180 | LastAttemptVersion\r | |
181 | FmpState\r | |
182 | \r | |
183 | FmpVersion1234567812345678\r | |
184 | FmpLsv1234567812345678\r | |
185 | LastAttemptStatus1234567812345678\r | |
186 | LastAttemptVersion1234567812345678\r | |
187 | FmpState1234567812345678\r | |
188 | \r | |
189 | @param[in,out] Private Private context structure for the managed controller.\r | |
190 | **/\r | |
191 | VOID\r | |
192 | GenerateFmpVariableNames (\r | |
193 | IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
194 | )\r | |
195 | {\r | |
196 | EFI_STATUS Status;\r | |
197 | VOID *Buffer;\r | |
198 | FMP_CONTROLLER_STATE FmpControllerState;\r | |
199 | \r | |
200 | if (Private->VersionVariableName != NULL) {\r | |
201 | FreePool (Private->VersionVariableName);\r | |
202 | }\r | |
203 | if (Private->LsvVariableName != NULL) {\r | |
204 | FreePool (Private->LsvVariableName);\r | |
205 | }\r | |
206 | if (Private->LastAttemptStatusVariableName != NULL) {\r | |
207 | FreePool (Private->LastAttemptStatusVariableName);\r | |
208 | }\r | |
209 | if (Private->LastAttemptVersionVariableName != NULL) {\r | |
210 | FreePool (Private->LastAttemptVersionVariableName);\r | |
211 | }\r | |
212 | if (Private->FmpStateVariableName != NULL) {\r | |
213 | FreePool (Private->FmpStateVariableName);\r | |
214 | }\r | |
b0bacc00 | 215 | \r |
67c1e5ee EJ |
216 | Private->VersionVariableName = GenerateFmpVariableName (\r |
217 | Private->Descriptor.HardwareInstance,\r | |
218 | VARNAME_VERSION\r | |
219 | );\r | |
220 | Private->LsvVariableName = GenerateFmpVariableName (\r | |
221 | Private->Descriptor.HardwareInstance,\r | |
222 | VARNAME_LSV\r | |
223 | );\r | |
224 | Private->LastAttemptStatusVariableName = GenerateFmpVariableName (\r | |
225 | Private->Descriptor.HardwareInstance,\r | |
226 | VARNAME_LASTATTEMPTSTATUS\r | |
227 | );\r | |
228 | Private->LastAttemptVersionVariableName = GenerateFmpVariableName (\r | |
229 | Private->Descriptor.HardwareInstance,\r | |
230 | VARNAME_LASTATTEMPTVERSION\r | |
231 | );\r | |
232 | Private->FmpStateVariableName = GenerateFmpVariableName (\r | |
233 | Private->Descriptor.HardwareInstance,\r | |
234 | VARNAME_FMPSTATE\r | |
235 | );\r | |
236 | \r | |
e0961677 EJ |
237 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->VersionVariableName));\r |
238 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LsvVariableName));\r | |
239 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));\r | |
240 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));\r | |
241 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->FmpStateVariableName));\r | |
67c1e5ee EJ |
242 | \r |
243 | Buffer = GetFmpControllerState (Private);\r | |
244 | if (Buffer != NULL) {\r | |
245 | //\r | |
246 | // FMP Controller State was found with correct size.\r | |
247 | // Delete old variables if they exist.\r | |
248 | //\r | |
249 | FreePool (Buffer);\r | |
250 | DeleteFmpVariable (Private->VersionVariableName);\r | |
251 | DeleteFmpVariable (Private->LsvVariableName);\r | |
252 | DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r | |
253 | DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r | |
254 | return;\r | |
b0bacc00 KM |
255 | }\r |
256 | \r | |
257 | //\r | |
67c1e5ee EJ |
258 | // FMP Controller State was either not found or is wrong size.\r |
259 | // Create a new FMP Controller State variable with the correct size.\r | |
b0bacc00 | 260 | //\r |
e0961677 | 261 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Create controller state\n", mImageIdName));\r |
67c1e5ee EJ |
262 | GetFmpVariable (\r |
263 | Private->VersionVariableName,\r | |
264 | &FmpControllerState.VersionValid,\r | |
265 | &FmpControllerState.Version\r | |
266 | );\r | |
267 | GetFmpVariable (\r | |
268 | Private->LsvVariableName,\r | |
269 | &FmpControllerState.LsvValid,\r | |
270 | &FmpControllerState.Lsv\r | |
271 | );\r | |
272 | GetFmpVariable (\r | |
273 | Private->LastAttemptStatusVariableName,\r | |
274 | &FmpControllerState.LastAttemptStatusValid,\r | |
275 | &FmpControllerState.LastAttemptStatus\r | |
276 | );\r | |
277 | GetFmpVariable (\r | |
278 | Private->LastAttemptVersionVariableName,\r | |
279 | &FmpControllerState.LastAttemptVersionValid,\r | |
280 | &FmpControllerState.LastAttemptVersion\r | |
281 | );\r | |
282 | Status = gRT->SetVariable (\r | |
283 | Private->FmpStateVariableName,\r | |
284 | &gEfiCallerIdGuid,\r | |
285 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
286 | sizeof (FmpControllerState),\r | |
287 | &FmpControllerState\r | |
288 | );\r | |
289 | if (EFI_ERROR (Status)) {\r | |
b0bacc00 | 290 | //\r |
67c1e5ee EJ |
291 | // Failed to create FMP Controller State. In this case, do not\r |
292 | // delete the individual variables. They can be used again on next boot\r | |
293 | // to create the FMP Controller State.\r | |
b0bacc00 | 294 | //\r |
e0961677 | 295 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to create controller state. Status = %r\n", mImageIdName, Status));\r |
b0bacc00 | 296 | } else {\r |
67c1e5ee EJ |
297 | DeleteFmpVariable (Private->VersionVariableName);\r |
298 | DeleteFmpVariable (Private->LsvVariableName);\r | |
299 | DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r | |
300 | DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r | |
b0bacc00 | 301 | }\r |
67c1e5ee | 302 | }\r |
b0bacc00 | 303 | \r |
67c1e5ee EJ |
304 | /**\r |
305 | Returns the value used to fill in the Version field of the\r | |
306 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
307 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
308 | variable. If the UEFI variables does not exist, then a default version value\r | |
309 | is returned.\r | |
310 | \r | |
311 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r | |
b0bacc00 | 312 | \r |
67c1e5ee EJ |
313 | @param[in] Private Private context structure for the managed controller.\r |
314 | \r | |
315 | @return The version of the firmware image in the firmware device.\r | |
316 | **/\r | |
317 | UINT32\r | |
318 | GetVersionFromVariable (\r | |
319 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r | |
320 | )\r | |
321 | {\r | |
322 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
323 | UINT32 Value;\r | |
324 | \r | |
325 | Value = DEFAULT_VERSION;\r | |
326 | FmpControllerState = GetFmpControllerState (Private);\r | |
327 | if (FmpControllerState != NULL) {\r | |
328 | if (FmpControllerState->VersionValid) {\r | |
329 | Value = FmpControllerState->Version;\r | |
e0961677 EJ |
330 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s Version %08x\n",\r |
331 | mImageIdName,\r | |
67c1e5ee EJ |
332 | &gEfiCallerIdGuid,\r |
333 | Private->FmpStateVariableName,\r | |
334 | Value\r | |
335 | ));\r | |
336 | }\r | |
337 | FreePool (FmpControllerState);\r | |
338 | }\r | |
339 | return Value;\r | |
b0bacc00 KM |
340 | }\r |
341 | \r | |
342 | /**\r | |
343 | Returns the value used to fill in the LowestSupportedVersion field of the\r | |
344 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
345 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
346 | variable. If the UEFI variables does not exist, then a default lowest\r | |
347 | supported version value is returned.\r | |
348 | \r | |
67c1e5ee EJ |
349 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r |
350 | \r | |
351 | @param[in] Private Private context structure for the managed controller.\r | |
b0bacc00 KM |
352 | \r |
353 | @return The lowest supported version of the firmware image in the firmware\r | |
354 | device.\r | |
b0bacc00 KM |
355 | **/\r |
356 | UINT32\r | |
357 | GetLowestSupportedVersionFromVariable (\r | |
67c1e5ee | 358 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r |
b0bacc00 KM |
359 | )\r |
360 | {\r | |
67c1e5ee EJ |
361 | FMP_CONTROLLER_STATE *FmpControllerState;\r |
362 | UINT32 Value;\r | |
363 | \r | |
364 | Value = DEFAULT_LOWESTSUPPORTEDVERSION;\r | |
365 | FmpControllerState = GetFmpControllerState (Private);\r | |
366 | if (FmpControllerState != NULL) {\r | |
367 | if (FmpControllerState->LsvValid) {\r | |
368 | Value = FmpControllerState->Lsv;\r | |
e0961677 EJ |
369 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s LowestSupportedVersion %08x\n",\r |
370 | mImageIdName,\r | |
67c1e5ee EJ |
371 | &gEfiCallerIdGuid,\r |
372 | Private->FmpStateVariableName,\r | |
373 | Value\r | |
374 | ));\r | |
375 | }\r | |
376 | FreePool (FmpControllerState);\r | |
b0bacc00 | 377 | }\r |
67c1e5ee | 378 | return Value;\r |
b0bacc00 KM |
379 | }\r |
380 | \r | |
381 | /**\r | |
382 | Returns the value used to fill in the LastAttemptStatus field of the\r | |
383 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
384 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
385 | variable. If the UEFI variables does not exist, then a default last attempt\r | |
386 | status value is returned.\r | |
387 | \r | |
67c1e5ee | 388 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r |
b0bacc00 | 389 | \r |
67c1e5ee | 390 | @param[in] Private Private context structure for the managed controller.\r |
b0bacc00 | 391 | \r |
67c1e5ee | 392 | @return The last attempt status value for the most recent capsule update.\r |
b0bacc00 KM |
393 | **/\r |
394 | UINT32\r | |
395 | GetLastAttemptStatusFromVariable (\r | |
67c1e5ee | 396 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r |
b0bacc00 KM |
397 | )\r |
398 | {\r | |
67c1e5ee EJ |
399 | FMP_CONTROLLER_STATE *FmpControllerState;\r |
400 | UINT32 Value;\r | |
401 | \r | |
402 | Value = DEFAULT_LASTATTEMPTSTATUS;\r | |
403 | FmpControllerState = GetFmpControllerState (Private);\r | |
404 | if (FmpControllerState != NULL) {\r | |
405 | if (FmpControllerState->LastAttemptStatusValid) {\r | |
406 | Value = FmpControllerState->LastAttemptStatus;\r | |
e0961677 EJ |
407 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s LastAttemptStatus %08x\n",\r |
408 | mImageIdName,\r | |
67c1e5ee EJ |
409 | &gEfiCallerIdGuid,\r |
410 | Private->FmpStateVariableName,\r | |
411 | Value\r | |
412 | ));\r | |
413 | }\r | |
414 | FreePool (FmpControllerState);\r | |
b0bacc00 | 415 | }\r |
67c1e5ee | 416 | return Value;\r |
b0bacc00 KM |
417 | }\r |
418 | \r | |
419 | /**\r | |
420 | Returns the value used to fill in the LastAttemptVersion field of the\r | |
421 | EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r | |
422 | service of the Firmware Management Protocol. The value is read from a UEFI\r | |
423 | variable. If the UEFI variables does not exist, then a default last attempt\r | |
424 | version value is returned.\r | |
425 | \r | |
67c1e5ee | 426 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r |
b0bacc00 | 427 | \r |
67c1e5ee | 428 | @param[in] Private Private context structure for the managed controller.\r |
b0bacc00 | 429 | \r |
67c1e5ee | 430 | @return The last attempt version value for the most recent capsule update.\r |
b0bacc00 KM |
431 | **/\r |
432 | UINT32\r | |
433 | GetLastAttemptVersionFromVariable (\r | |
67c1e5ee | 434 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r |
b0bacc00 KM |
435 | )\r |
436 | {\r | |
67c1e5ee EJ |
437 | FMP_CONTROLLER_STATE *FmpControllerState;\r |
438 | UINT32 Value;\r | |
439 | \r | |
440 | Value = DEFAULT_LASTATTEMPTVERSION;\r | |
441 | FmpControllerState = GetFmpControllerState (Private);\r | |
442 | if (FmpControllerState != NULL) {\r | |
443 | if (FmpControllerState->LastAttemptVersionValid) {\r | |
444 | Value = FmpControllerState->LastAttemptVersion;\r | |
e0961677 EJ |
445 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s LastAttemptVersion %08x\n",\r |
446 | mImageIdName,\r | |
67c1e5ee EJ |
447 | &gEfiCallerIdGuid,\r |
448 | Private->FmpStateVariableName,\r | |
449 | Value\r | |
450 | ));\r | |
451 | }\r | |
452 | FreePool (FmpControllerState);\r | |
b0bacc00 | 453 | }\r |
67c1e5ee | 454 | return Value;\r |
b0bacc00 KM |
455 | }\r |
456 | \r | |
b0bacc00 KM |
457 | /**\r |
458 | Saves the version current of the firmware image in the firmware device to a\r | |
459 | UEFI variable.\r | |
460 | \r | |
67c1e5ee | 461 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r |
b0bacc00 | 462 | \r |
67c1e5ee | 463 | @param[in] Private Private context structure for the managed controller.\r |
b0bacc00 | 464 | @param[in] Version The version of the firmware image in the firmware device.\r |
b0bacc00 KM |
465 | **/\r |
466 | VOID\r | |
467 | SetVersionInVariable (\r | |
67c1e5ee EJ |
468 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r |
469 | IN UINT32 Version\r | |
b0bacc00 KM |
470 | )\r |
471 | {\r | |
67c1e5ee EJ |
472 | EFI_STATUS Status;\r |
473 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
474 | BOOLEAN Update;\r | |
b0bacc00 | 475 | \r |
67c1e5ee EJ |
476 | FmpControllerState = GetFmpControllerState (Private);\r |
477 | if (FmpControllerState == NULL) {\r | |
478 | //\r | |
479 | // Can not update value if FMP Controller State does not exist.\r | |
480 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
481 | //\r | |
482 | return;\r | |
483 | }\r | |
b0bacc00 | 484 | \r |
67c1e5ee EJ |
485 | Update = FALSE;\r |
486 | if (!FmpControllerState->VersionValid) {\r | |
487 | Update = TRUE;\r | |
488 | }\r | |
489 | if (FmpControllerState->Version != Version) {\r | |
490 | Update = TRUE;\r | |
491 | }\r | |
492 | if (!Update) {\r | |
e0961677 | 493 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r |
67c1e5ee EJ |
494 | } else {\r |
495 | FmpControllerState->VersionValid = TRUE;\r | |
496 | FmpControllerState->Version = Version;\r | |
b0bacc00 | 497 | Status = gRT->SetVariable (\r |
67c1e5ee | 498 | Private->FmpStateVariableName,\r |
b0bacc00 KM |
499 | &gEfiCallerIdGuid,\r |
500 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
67c1e5ee EJ |
501 | sizeof (*FmpControllerState),\r |
502 | FmpControllerState\r | |
b0bacc00 KM |
503 | );\r |
504 | if (EFI_ERROR (Status)) {\r | |
e0961677 | 505 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r |
67c1e5ee | 506 | } else {\r |
e0961677 EJ |
507 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s Version %08x\n",\r |
508 | mImageIdName,\r | |
67c1e5ee EJ |
509 | &gEfiCallerIdGuid,\r |
510 | Private->FmpStateVariableName,\r | |
511 | Version\r | |
512 | ));\r | |
b0bacc00 | 513 | }\r |
b0bacc00 | 514 | }\r |
67c1e5ee | 515 | FreePool (FmpControllerState);\r |
b0bacc00 KM |
516 | }\r |
517 | \r | |
518 | /**\r | |
519 | Saves the lowest supported version current of the firmware image in the\r | |
520 | firmware device to a UEFI variable.\r | |
521 | \r | |
67c1e5ee | 522 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r |
b0bacc00 | 523 | \r |
67c1e5ee EJ |
524 | @param[in] Private Private context structure for the managed\r |
525 | controller.\r | |
526 | @param[in] LowestSupportedVersion The lowest supported version of the\r | |
527 | firmware image in the firmware device.\r | |
b0bacc00 KM |
528 | **/\r |
529 | VOID\r | |
530 | SetLowestSupportedVersionInVariable (\r | |
67c1e5ee EJ |
531 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r |
532 | IN UINT32 LowestSupportedVersion\r | |
b0bacc00 KM |
533 | )\r |
534 | {\r | |
67c1e5ee EJ |
535 | EFI_STATUS Status;\r |
536 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
537 | BOOLEAN Update;\r | |
b0bacc00 | 538 | \r |
67c1e5ee EJ |
539 | FmpControllerState = GetFmpControllerState (Private);\r |
540 | if (FmpControllerState == NULL) {\r | |
541 | //\r | |
542 | // Can not update value if FMP Controller State does not exist.\r | |
543 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
544 | //\r | |
545 | return;\r | |
546 | }\r | |
b0bacc00 | 547 | \r |
67c1e5ee EJ |
548 | Update = FALSE;\r |
549 | if (!FmpControllerState->LsvValid) {\r | |
550 | Update = TRUE;\r | |
551 | }\r | |
552 | if (FmpControllerState->Lsv < LowestSupportedVersion) {\r | |
553 | Update = TRUE;\r | |
554 | }\r | |
555 | if (!Update) {\r | |
e0961677 | 556 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r |
67c1e5ee EJ |
557 | } else {\r |
558 | FmpControllerState->LsvValid = TRUE;\r | |
559 | FmpControllerState->Lsv = LowestSupportedVersion;\r | |
b0bacc00 | 560 | Status = gRT->SetVariable (\r |
67c1e5ee | 561 | Private->FmpStateVariableName,\r |
b0bacc00 KM |
562 | &gEfiCallerIdGuid,\r |
563 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
67c1e5ee EJ |
564 | sizeof (*FmpControllerState),\r |
565 | FmpControllerState\r | |
b0bacc00 KM |
566 | );\r |
567 | if (EFI_ERROR (Status)) {\r | |
e0961677 | 568 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r |
67c1e5ee | 569 | } else {\r |
e0961677 EJ |
570 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s LowestSupportedVersion %08x\n",\r |
571 | mImageIdName,\r | |
67c1e5ee EJ |
572 | &gEfiCallerIdGuid,\r |
573 | Private->FmpStateVariableName,\r | |
574 | LowestSupportedVersion\r | |
575 | ));\r | |
b0bacc00 | 576 | }\r |
b0bacc00 | 577 | }\r |
67c1e5ee | 578 | FreePool (FmpControllerState);\r |
b0bacc00 KM |
579 | }\r |
580 | \r | |
581 | /**\r | |
582 | Saves the last attempt status value of the most recent FMP capsule update to a\r | |
583 | UEFI variable.\r | |
584 | \r | |
67c1e5ee | 585 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r |
b0bacc00 | 586 | \r |
67c1e5ee EJ |
587 | @param[in] Private Private context structure for the managed\r |
588 | controller.\r | |
b0bacc00 KM |
589 | @param[in] LastAttemptStatus The last attempt status of the most recent FMP\r |
590 | capsule update.\r | |
b0bacc00 KM |
591 | **/\r |
592 | VOID\r | |
593 | SetLastAttemptStatusInVariable (\r | |
67c1e5ee EJ |
594 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r |
595 | IN UINT32 LastAttemptStatus\r | |
b0bacc00 KM |
596 | )\r |
597 | {\r | |
67c1e5ee EJ |
598 | EFI_STATUS Status;\r |
599 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
600 | BOOLEAN Update;\r | |
b0bacc00 | 601 | \r |
67c1e5ee EJ |
602 | FmpControllerState = GetFmpControllerState (Private);\r |
603 | if (FmpControllerState == NULL) {\r | |
604 | //\r | |
605 | // Can not update value if FMP Controller State does not exist.\r | |
606 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
607 | //\r | |
608 | return;\r | |
609 | }\r | |
b0bacc00 | 610 | \r |
67c1e5ee EJ |
611 | Update = FALSE;\r |
612 | if (!FmpControllerState->LastAttemptStatusValid) {\r | |
613 | Update = TRUE;\r | |
614 | }\r | |
615 | if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {\r | |
616 | Update = TRUE;\r | |
617 | }\r | |
618 | if (!Update) {\r | |
e0961677 | 619 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r |
67c1e5ee EJ |
620 | } else {\r |
621 | FmpControllerState->LastAttemptStatusValid = TRUE;\r | |
622 | FmpControllerState->LastAttemptStatus = LastAttemptStatus;\r | |
b0bacc00 | 623 | Status = gRT->SetVariable (\r |
67c1e5ee | 624 | Private->FmpStateVariableName,\r |
b0bacc00 KM |
625 | &gEfiCallerIdGuid,\r |
626 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
67c1e5ee EJ |
627 | sizeof (*FmpControllerState),\r |
628 | FmpControllerState\r | |
b0bacc00 KM |
629 | );\r |
630 | if (EFI_ERROR (Status)) {\r | |
e0961677 | 631 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r |
67c1e5ee | 632 | } else {\r |
e0961677 EJ |
633 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s LastAttemptStatus %08x\n",\r |
634 | mImageIdName,\r | |
67c1e5ee EJ |
635 | &gEfiCallerIdGuid,\r |
636 | Private->FmpStateVariableName,\r | |
637 | LastAttemptStatus\r | |
638 | ));\r | |
b0bacc00 | 639 | }\r |
b0bacc00 | 640 | }\r |
67c1e5ee | 641 | FreePool (FmpControllerState);\r |
b0bacc00 KM |
642 | }\r |
643 | \r | |
644 | /**\r | |
645 | Saves the last attempt version value of the most recent FMP capsule update to\r | |
646 | a UEFI variable.\r | |
647 | \r | |
67c1e5ee | 648 | UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r |
b0bacc00 | 649 | \r |
67c1e5ee EJ |
650 | @param[in] Private Private context structure for the managed\r |
651 | controller.\r | |
b0bacc00 KM |
652 | @param[in] LastAttemptVersion The last attempt version value of the most\r |
653 | recent FMP capsule update.\r | |
b0bacc00 KM |
654 | **/\r |
655 | VOID\r | |
656 | SetLastAttemptVersionInVariable (\r | |
67c1e5ee EJ |
657 | IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r |
658 | IN UINT32 LastAttemptVersion\r | |
b0bacc00 KM |
659 | )\r |
660 | {\r | |
67c1e5ee EJ |
661 | EFI_STATUS Status;\r |
662 | FMP_CONTROLLER_STATE *FmpControllerState;\r | |
663 | BOOLEAN Update;\r | |
b0bacc00 | 664 | \r |
67c1e5ee EJ |
665 | FmpControllerState = GetFmpControllerState (Private);\r |
666 | if (FmpControllerState == NULL) {\r | |
667 | //\r | |
668 | // Can not update value if FMP Controller State does not exist.\r | |
669 | // This variable is guaranteed to be created by GenerateFmpVariableNames().\r | |
670 | //\r | |
671 | return;\r | |
672 | }\r | |
b0bacc00 | 673 | \r |
67c1e5ee EJ |
674 | Update = FALSE;\r |
675 | if (!FmpControllerState->LastAttemptVersionValid) {\r | |
676 | Update = TRUE;\r | |
677 | }\r | |
678 | if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {\r | |
679 | Update = TRUE;\r | |
680 | }\r | |
681 | if (!Update) {\r | |
e0961677 | 682 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));\r |
67c1e5ee EJ |
683 | } else {\r |
684 | FmpControllerState->LastAttemptVersionValid = TRUE;\r | |
685 | FmpControllerState->LastAttemptVersion = LastAttemptVersion;\r | |
b0bacc00 | 686 | Status = gRT->SetVariable (\r |
67c1e5ee | 687 | Private->FmpStateVariableName,\r |
b0bacc00 KM |
688 | &gEfiCallerIdGuid,\r |
689 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r | |
67c1e5ee EJ |
690 | sizeof (*FmpControllerState),\r |
691 | FmpControllerState\r | |
b0bacc00 KM |
692 | );\r |
693 | if (EFI_ERROR (Status)) {\r | |
e0961677 | 694 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));\r |
67c1e5ee | 695 | } else {\r |
e0961677 EJ |
696 | DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s LastAttemptVersion %08x\n",\r |
697 | mImageIdName,\r | |
67c1e5ee EJ |
698 | &gEfiCallerIdGuid,\r |
699 | Private->FmpStateVariableName,\r | |
700 | LastAttemptVersion\r | |
701 | ));\r | |
b0bacc00 | 702 | }\r |
b0bacc00 | 703 | }\r |
67c1e5ee | 704 | FreePool (FmpControllerState);\r |
b0bacc00 KM |
705 | }\r |
706 | \r | |
707 | /**\r | |
67c1e5ee EJ |
708 | Attempts to lock a single UEFI Variable propagating the error state of the\r |
709 | first lock attempt that fails. Uses gEfiCallerIdGuid as the variable GUID.\r | |
710 | \r | |
711 | @param[in] PreviousStatus The previous UEFI Variable lock attempt status.\r | |
712 | @param[in] VariableLock The EDK II Variable Lock Protocol instance.\r | |
713 | @param[in] VariableName The name of the UEFI Variable to lock.\r | |
714 | \r | |
715 | @retval EFI_SUCCESS The UEFI Variable was locked and the previous variable\r | |
716 | lock attempt also succeeded.\r | |
717 | @retval Other The UEFI Variable could not be locked or the previous\r | |
718 | variable lock attempt failed.\r | |
719 | **/\r | |
720 | static\r | |
721 | EFI_STATUS\r | |
722 | LockFmpVariable (\r | |
723 | IN EFI_STATUS PreviousStatus,\r | |
724 | IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock,\r | |
725 | IN CHAR16 *VariableName\r | |
726 | )\r | |
727 | {\r | |
728 | EFI_STATUS Status;\r | |
729 | \r | |
730 | Status = VariableLock->RequestToLock (\r | |
731 | VariableLock,\r | |
732 | VariableName,\r | |
733 | &gEfiCallerIdGuid\r | |
734 | );\r | |
735 | if (!EFI_ERROR (Status)) {\r | |
736 | return PreviousStatus;\r | |
737 | }\r | |
738 | \r | |
e0961677 EJ |
739 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to lock variable %g %s. Status = %r\n",\r |
740 | mImageIdName,\r | |
67c1e5ee EJ |
741 | &gEfiCallerIdGuid,\r |
742 | VariableName,\r | |
743 | Status\r | |
744 | ));\r | |
745 | \r | |
746 | if (EFI_ERROR (PreviousStatus)) {\r | |
747 | return PreviousStatus;\r | |
748 | }\r | |
749 | return Status;\r | |
750 | }\r | |
751 | \r | |
752 | /**\r | |
753 | Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently\r | |
754 | executing module.\r | |
755 | \r | |
756 | @param[in] Private Private context structure for the managed controller.\r | |
b0bacc00 KM |
757 | \r |
758 | @retval EFI_SUCCESS All UEFI variables are locked.\r | |
759 | @retval EFI_UNSUPPORTED Variable Lock Protocol not found.\r | |
760 | @retval Other One of the UEFI variables could not be locked.\r | |
b0bacc00 KM |
761 | **/\r |
762 | EFI_STATUS\r | |
763 | LockAllFmpVariables (\r | |
67c1e5ee | 764 | FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r |
b0bacc00 KM |
765 | )\r |
766 | {\r | |
767 | EFI_STATUS Status;\r | |
768 | EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r | |
b0bacc00 KM |
769 | \r |
770 | VariableLock = NULL;\r | |
771 | Status = gBS->LocateProtocol (\r | |
772 | &gEdkiiVariableLockProtocolGuid,\r | |
773 | NULL,\r | |
774 | (VOID **)&VariableLock\r | |
775 | );\r | |
67c1e5ee | 776 | if (EFI_ERROR (Status) || VariableLock == NULL) {\r |
e0961677 | 777 | DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to locate Variable Lock Protocol (%r).\n", mImageIdName, Status));\r |
b0bacc00 KM |
778 | return EFI_UNSUPPORTED;\r |
779 | }\r | |
780 | \r | |
67c1e5ee EJ |
781 | Status = EFI_SUCCESS;\r |
782 | Status = LockFmpVariable (Status, VariableLock, Private->VersionVariableName);\r | |
783 | Status = LockFmpVariable (Status, VariableLock, Private->LsvVariableName);\r | |
784 | Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptStatusVariableName);\r | |
785 | Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptVersionVariableName);\r | |
786 | Status = LockFmpVariable (Status, VariableLock, Private->FmpStateVariableName);\r | |
b0bacc00 | 787 | \r |
67c1e5ee | 788 | return Status;\r |
b0bacc00 | 789 | }\r |