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