]> git.proxmox.com Git - mirror_edk2.git/blame - FmpDevicePkg/FmpDxe/VariableSupport.c
FmpDevicePkg/FmpDxe: Improve all DEBUG() messages
[mirror_edk2.git] / FmpDevicePkg / FmpDxe / VariableSupport.c
CommitLineData
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
26static\r
27VOID\r
28GetFmpVariable (\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
64static\r
65VOID\r
66DeleteFmpVariable (\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
96static\r
97FMP_CONTROLLER_STATE *\r
98GetFmpControllerState (\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
143static\r
144CHAR16 *\r
145GenerateFmpVariableName (\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
191VOID\r
192GenerateFmpVariableNames (\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
317UINT32\r
318GetVersionFromVariable (\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
356UINT32\r
357GetLowestSupportedVersionFromVariable (\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
394UINT32\r
395GetLastAttemptStatusFromVariable (\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
432UINT32\r
433GetLastAttemptVersionFromVariable (\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
466VOID\r
467SetVersionInVariable (\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
529VOID\r
530SetLowestSupportedVersionInVariable (\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
592VOID\r
593SetLastAttemptStatusInVariable (\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
655VOID\r
656SetLastAttemptVersionInVariable (\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
720static\r
721EFI_STATUS\r
722LockFmpVariable (\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
762EFI_STATUS\r
763LockAllFmpVariables (\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