TianoCore EDK2 master
Loading...
Searching...
No Matches
VariableSupport.c
Go to the documentation of this file.
1
12#include "FmpDxe.h"
13#include "VariableSupport.h"
14
26static
27VOID
28GetFmpVariable (
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
53 if (Buffer != NULL) {
54 FreePool (Buffer);
55 }
56}
57
65static
66VOID
67DeleteFmpVariable (
68 IN CHAR16 *VariableName
69 )
70{
71 EFI_STATUS Status;
72 BOOLEAN Valid;
73 UINT32 Value;
74
75 GetFmpVariable (VariableName, &Valid, &Value);
76 if (Valid) {
77 Status = gRT->SetVariable (VariableName, &gEfiCallerIdGuid, 0, 0, NULL);
78 if (EFI_ERROR (Status)) {
79 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to delete variable %s. Status = %r\n", mImageIdName, VariableName, Status));
80 } else {
81 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Deleted variable %s\n", mImageIdName, VariableName));
82 }
83 }
84}
85
97static
99GetFmpControllerState (
101 )
102{
103 EFI_STATUS Status;
104 FMP_CONTROLLER_STATE *FmpControllerState;
105 UINTN Size;
106
107 FmpControllerState = NULL;
108 Size = 0;
109 Status = GetVariable2 (
110 Private->FmpStateVariableName,
111 &gEfiCallerIdGuid,
112 (VOID **)&FmpControllerState,
113 &Size
114 );
115 if (EFI_ERROR (Status) || (FmpControllerState == NULL)) {
116 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to get the controller state. Status = %r\n", mImageIdName, Status));
117 } else {
118 if (Size == sizeof (*FmpControllerState)) {
119 return FmpControllerState;
120 }
121
122 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Getting controller state returned a size different than expected. Size = 0x%x\n", mImageIdName, Size));
123 }
124
125 if (FmpControllerState != NULL) {
126 FreePool (FmpControllerState);
127 }
128
129 return NULL;
130}
131
147static
148CHAR16 *
149GenerateFmpVariableName (
150 IN UINT64 HardwareInstance,
151 IN CHAR16 *BaseVariableName
152 )
153{
154 UINTN Size;
155 CHAR16 *VariableName;
156
157 //
158 // Allocate Unicode string with room for BaseVariableName and a 16 digit
159 // hexadecimal value for the HardwareInstance value.
160 //
161 Size = StrSize (BaseVariableName) + 16 * sizeof (CHAR16);
162 VariableName = AllocateCopyPool (Size, BaseVariableName);
163 if (VariableName == NULL) {
164 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to generate variable name %s.\n", mImageIdName, BaseVariableName));
165 return VariableName;
166 }
167
168 if (HardwareInstance == 0) {
169 return VariableName;
170 }
171
173 &VariableName[StrLen (BaseVariableName)],
174 Size,
175 PREFIX_ZERO | RADIX_HEX,
176 HardwareInstance,
177 16
178 );
179 return VariableName;
180}
181
206VOID
209 )
210{
211 EFI_STATUS Status;
212 VOID *Buffer;
213 FMP_CONTROLLER_STATE FmpControllerState;
214
215 if (Private->VersionVariableName != NULL) {
216 FreePool (Private->VersionVariableName);
217 }
218
219 if (Private->LsvVariableName != NULL) {
220 FreePool (Private->LsvVariableName);
221 }
222
223 if (Private->LastAttemptStatusVariableName != NULL) {
224 FreePool (Private->LastAttemptStatusVariableName);
225 }
226
227 if (Private->LastAttemptVersionVariableName != NULL) {
228 FreePool (Private->LastAttemptVersionVariableName);
229 }
230
231 if (Private->FmpStateVariableName != NULL) {
232 FreePool (Private->FmpStateVariableName);
233 }
234
235 Private->VersionVariableName = GenerateFmpVariableName (
236 Private->Descriptor.HardwareInstance,
238 );
239 Private->LsvVariableName = GenerateFmpVariableName (
240 Private->Descriptor.HardwareInstance,
241 VARNAME_LSV
242 );
243 Private->LastAttemptStatusVariableName = GenerateFmpVariableName (
244 Private->Descriptor.HardwareInstance,
245 VARNAME_LASTATTEMPTSTATUS
246 );
247 Private->LastAttemptVersionVariableName = GenerateFmpVariableName (
248 Private->Descriptor.HardwareInstance,
249 VARNAME_LASTATTEMPTVERSION
250 );
251 Private->FmpStateVariableName = GenerateFmpVariableName (
252 Private->Descriptor.HardwareInstance,
254 );
255
256 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->VersionVariableName));
257 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LsvVariableName));
258 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));
259 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));
260 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->FmpStateVariableName));
261
262 Buffer = GetFmpControllerState (Private);
263 if (Buffer != NULL) {
264 //
265 // FMP Controller State was found with correct size.
266 // Delete old variables if they exist.
267 //
268 FreePool (Buffer);
269 DeleteFmpVariable (Private->VersionVariableName);
270 DeleteFmpVariable (Private->LsvVariableName);
271 DeleteFmpVariable (Private->LastAttemptStatusVariableName);
272 DeleteFmpVariable (Private->LastAttemptVersionVariableName);
273 return;
274 }
275
276 //
277 // FMP Controller State was either not found or is wrong size.
278 // Create a new FMP Controller State variable with the correct size.
279 //
280 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Create controller state\n", mImageIdName));
281 GetFmpVariable (
282 Private->VersionVariableName,
283 &FmpControllerState.VersionValid,
284 &FmpControllerState.Version
285 );
286 GetFmpVariable (
287 Private->LsvVariableName,
288 &FmpControllerState.LsvValid,
289 &FmpControllerState.Lsv
290 );
291 GetFmpVariable (
292 Private->LastAttemptStatusVariableName,
293 &FmpControllerState.LastAttemptStatusValid,
294 &FmpControllerState.LastAttemptStatus
295 );
296 GetFmpVariable (
297 Private->LastAttemptVersionVariableName,
298 &FmpControllerState.LastAttemptVersionValid,
299 &FmpControllerState.LastAttemptVersion
300 );
301 Status = gRT->SetVariable (
302 Private->FmpStateVariableName,
303 &gEfiCallerIdGuid,
304 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
305 sizeof (FmpControllerState),
306 &FmpControllerState
307 );
308 if (EFI_ERROR (Status)) {
309 //
310 // Failed to create FMP Controller State. In this case, do not
311 // delete the individual variables. They can be used again on next boot
312 // to create the FMP Controller State.
313 //
314 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to create controller state. Status = %r\n", mImageIdName, Status));
315 } else {
316 DeleteFmpVariable (Private->VersionVariableName);
317 DeleteFmpVariable (Private->LsvVariableName);
318 DeleteFmpVariable (Private->LastAttemptStatusVariableName);
319 DeleteFmpVariable (Private->LastAttemptVersionVariableName);
320 }
321}
322
336UINT32
339 )
340{
341 FMP_CONTROLLER_STATE *FmpControllerState;
342 UINT32 Value;
343
344 Value = DEFAULT_VERSION;
345 FmpControllerState = GetFmpControllerState (Private);
346 if (FmpControllerState != NULL) {
347 if (FmpControllerState->VersionValid) {
348 Value = FmpControllerState->Version;
349 DEBUG ((
350 DEBUG_INFO,
351 "FmpDxe(%s): Get variable %g %s Version %08x\n",
353 &gEfiCallerIdGuid,
354 Private->FmpStateVariableName,
355 Value
356 ));
357 }
358
359 FreePool (FmpControllerState);
360 }
361
362 return Value;
363}
364
379UINT32
382 )
383{
384 FMP_CONTROLLER_STATE *FmpControllerState;
385 UINT32 Value;
386
387 Value = DEFAULT_LOWESTSUPPORTEDVERSION;
388 FmpControllerState = GetFmpControllerState (Private);
389 if (FmpControllerState != NULL) {
390 if (FmpControllerState->LsvValid) {
391 Value = FmpControllerState->Lsv;
392 DEBUG ((
393 DEBUG_INFO,
394 "FmpDxe(%s): Get variable %g %s LowestSupportedVersion %08x\n",
396 &gEfiCallerIdGuid,
397 Private->FmpStateVariableName,
398 Value
399 ));
400 }
401
402 FreePool (FmpControllerState);
403 }
404
405 return Value;
406}
407
421UINT32
424 )
425{
426 FMP_CONTROLLER_STATE *FmpControllerState;
427 UINT32 Value;
428
429 Value = DEFAULT_LASTATTEMPTSTATUS;
430 FmpControllerState = GetFmpControllerState (Private);
431 if (FmpControllerState != NULL) {
432 if (FmpControllerState->LastAttemptStatusValid) {
433 Value = FmpControllerState->LastAttemptStatus;
434 DEBUG ((
435 DEBUG_INFO,
436 "FmpDxe(%s): Get variable %g %s LastAttemptStatus %08x\n",
438 &gEfiCallerIdGuid,
439 Private->FmpStateVariableName,
440 Value
441 ));
442 }
443
444 FreePool (FmpControllerState);
445 }
446
447 return Value;
448}
449
463UINT32
466 )
467{
468 FMP_CONTROLLER_STATE *FmpControllerState;
469 UINT32 Value;
470
471 Value = DEFAULT_LASTATTEMPTVERSION;
472 FmpControllerState = GetFmpControllerState (Private);
473 if (FmpControllerState != NULL) {
474 if (FmpControllerState->LastAttemptVersionValid) {
475 Value = FmpControllerState->LastAttemptVersion;
476 DEBUG ((
477 DEBUG_INFO,
478 "FmpDxe(%s): Get variable %g %s LastAttemptVersion %08x\n",
480 &gEfiCallerIdGuid,
481 Private->FmpStateVariableName,
482 Value
483 ));
484 }
485
486 FreePool (FmpControllerState);
487 }
488
489 return Value;
490}
491
501VOID
504 IN UINT32 Version
505 )
506{
507 EFI_STATUS Status;
508 FMP_CONTROLLER_STATE *FmpControllerState;
509 BOOLEAN Update;
510
511 FmpControllerState = GetFmpControllerState (Private);
512 if (FmpControllerState == NULL) {
513 //
514 // Can not update value if FMP Controller State does not exist.
515 // This variable is guaranteed to be created by GenerateFmpVariableNames().
516 //
517 return;
518 }
519
520 Update = FALSE;
521 if (!FmpControllerState->VersionValid) {
522 Update = TRUE;
523 }
524
525 if (FmpControllerState->Version != Version) {
526 Update = TRUE;
527 }
528
529 if (!Update) {
530 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
531 } else {
532 FmpControllerState->VersionValid = TRUE;
533 FmpControllerState->Version = Version;
534 Status = gRT->SetVariable (
535 Private->FmpStateVariableName,
536 &gEfiCallerIdGuid,
537 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
538 sizeof (*FmpControllerState),
539 FmpControllerState
540 );
541 if (EFI_ERROR (Status)) {
542 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
543 } else {
544 DEBUG ((
545 DEBUG_INFO,
546 "FmpDxe(%s): Set variable %g %s Version %08x\n",
548 &gEfiCallerIdGuid,
549 Private->FmpStateVariableName,
550 Version
551 ));
552 }
553 }
554
555 FreePool (FmpControllerState);
556}
557
569VOID
572 IN UINT32 LowestSupportedVersion
573 )
574{
575 EFI_STATUS Status;
576 FMP_CONTROLLER_STATE *FmpControllerState;
577 BOOLEAN Update;
578
579 FmpControllerState = GetFmpControllerState (Private);
580 if (FmpControllerState == NULL) {
581 //
582 // Can not update value if FMP Controller State does not exist.
583 // This variable is guaranteed to be created by GenerateFmpVariableNames().
584 //
585 return;
586 }
587
588 Update = FALSE;
589 if (!FmpControllerState->LsvValid) {
590 Update = TRUE;
591 }
592
593 if (FmpControllerState->Lsv < LowestSupportedVersion) {
594 Update = TRUE;
595 }
596
597 if (!Update) {
598 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
599 } else {
600 FmpControllerState->LsvValid = TRUE;
601 FmpControllerState->Lsv = LowestSupportedVersion;
602 Status = gRT->SetVariable (
603 Private->FmpStateVariableName,
604 &gEfiCallerIdGuid,
605 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
606 sizeof (*FmpControllerState),
607 FmpControllerState
608 );
609 if (EFI_ERROR (Status)) {
610 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
611 } else {
612 DEBUG ((
613 DEBUG_INFO,
614 "FmpDxe(%s): Set variable %g %s LowestSupportedVersion %08x\n",
616 &gEfiCallerIdGuid,
617 Private->FmpStateVariableName,
618 LowestSupportedVersion
619 ));
620 }
621 }
622
623 FreePool (FmpControllerState);
624}
625
637VOID
640 IN UINT32 LastAttemptStatus
641 )
642{
643 EFI_STATUS Status;
644 FMP_CONTROLLER_STATE *FmpControllerState;
645 BOOLEAN Update;
646
647 FmpControllerState = GetFmpControllerState (Private);
648 if (FmpControllerState == NULL) {
649 //
650 // Can not update value if FMP Controller State does not exist.
651 // This variable is guaranteed to be created by GenerateFmpVariableNames().
652 //
653 return;
654 }
655
656 Update = FALSE;
657 if (!FmpControllerState->LastAttemptStatusValid) {
658 Update = TRUE;
659 }
660
661 if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {
662 Update = TRUE;
663 }
664
665 if (!Update) {
666 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
667 } else {
668 FmpControllerState->LastAttemptStatusValid = TRUE;
669 FmpControllerState->LastAttemptStatus = LastAttemptStatus;
670 Status = gRT->SetVariable (
671 Private->FmpStateVariableName,
672 &gEfiCallerIdGuid,
673 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
674 sizeof (*FmpControllerState),
675 FmpControllerState
676 );
677 if (EFI_ERROR (Status)) {
678 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
679 } else {
680 DEBUG ((
681 DEBUG_INFO,
682 "FmpDxe(%s): Set variable %g %s LastAttemptStatus %08x\n",
684 &gEfiCallerIdGuid,
685 Private->FmpStateVariableName,
686 LastAttemptStatus
687 ));
688 }
689 }
690
691 FreePool (FmpControllerState);
692}
693
705VOID
708 IN UINT32 LastAttemptVersion
709 )
710{
711 EFI_STATUS Status;
712 FMP_CONTROLLER_STATE *FmpControllerState;
713 BOOLEAN Update;
714
715 FmpControllerState = GetFmpControllerState (Private);
716 if (FmpControllerState == NULL) {
717 //
718 // Can not update value if FMP Controller State does not exist.
719 // This variable is guaranteed to be created by GenerateFmpVariableNames().
720 //
721 return;
722 }
723
724 Update = FALSE;
725 if (!FmpControllerState->LastAttemptVersionValid) {
726 Update = TRUE;
727 }
728
729 if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {
730 Update = TRUE;
731 }
732
733 if (!Update) {
734 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
735 } else {
736 FmpControllerState->LastAttemptVersionValid = TRUE;
737 FmpControllerState->LastAttemptVersion = LastAttemptVersion;
738 Status = gRT->SetVariable (
739 Private->FmpStateVariableName,
740 &gEfiCallerIdGuid,
741 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
742 sizeof (*FmpControllerState),
743 FmpControllerState
744 );
745 if (EFI_ERROR (Status)) {
746 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
747 } else {
748 DEBUG ((
749 DEBUG_INFO,
750 "FmpDxe(%s): Set variable %g %s LastAttemptVersion %08x\n",
752 &gEfiCallerIdGuid,
753 Private->FmpStateVariableName,
754 LastAttemptVersion
755 ));
756 }
757 }
758
759 FreePool (FmpControllerState);
760}
761
775static
777LockFmpVariable (
778 IN EFI_STATUS PreviousStatus,
779 IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
780 IN CHAR16 *VariableName
781 )
782{
783 EFI_STATUS Status;
784
785 // If success, go ahead and set the policies to protect the target variables.
786 Status = RegisterBasicVariablePolicy (
787 VariablePolicy,
788 &gEfiCallerIdGuid,
789 VariableName,
790 VARIABLE_POLICY_NO_MIN_SIZE,
791 VARIABLE_POLICY_NO_MAX_SIZE,
792 VARIABLE_POLICY_NO_MUST_ATTR,
793 VARIABLE_POLICY_NO_CANT_ATTR,
794 VARIABLE_POLICY_TYPE_LOCK_NOW
795 );
796 if (EFI_ERROR (Status)) {
797 DEBUG ((
798 DEBUG_ERROR,
799 "FmpDxe(%s): Failed to lock variable %g %s. Status = %r\n",
801 &gEfiCallerIdGuid,
802 VariableName,
803 Status
804 ));
805 }
806
807 if (EFI_ERROR (PreviousStatus)) {
808 return PreviousStatus;
809 }
810
811 return Status;
812}
813
827 )
828{
829 EFI_STATUS Status;
830 EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;
831
832 // Locate the VariablePolicy protocol.
833 Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);
834 if (EFI_ERROR (Status)) {
835 DEBUG ((DEBUG_ERROR, "FmpDxe %a - Could not locate VariablePolicy protocol! %r\n", __func__, Status));
836 return Status;
837 }
838
839 Status = EFI_SUCCESS;
840 Status = LockFmpVariable (Status, VariablePolicy, Private->VersionVariableName);
841 Status = LockFmpVariable (Status, VariablePolicy, Private->LsvVariableName);
842 Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptStatusVariableName);
843 Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptVersionVariableName);
844 Status = LockFmpVariable (Status, VariablePolicy, Private->FmpStateVariableName);
845
846 return Status;
847}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
CHAR16 * mImageIdName
Definition: FmpDxe.c:101
RETURN_STATUS EFIAPI UnicodeValueToStringS(IN OUT CHAR16 *Buffer, IN UINTN BufferSize, IN UINTN Flags, IN INT64 Value, IN UINTN Width)
Definition: PrintLib.c:652
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI GetVariable2(IN CONST CHAR16 *Name, IN CONST EFI_GUID *Guid, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1317
#define EFI_VARIABLE_NON_VOLATILE
UINT32 GetLastAttemptStatusFromVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private)
VOID SetVersionInVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private, IN UINT32 Version)
UINT32 GetLastAttemptVersionFromVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private)
UINT32 GetLowestSupportedVersionFromVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private)
VOID SetLowestSupportedVersionInVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private, IN UINT32 LowestSupportedVersion)
VOID GenerateFmpVariableNames(IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private)
UINT32 GetVersionFromVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private)
VOID SetLastAttemptStatusInVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private, IN UINT32 LastAttemptStatus)
EFI_STATUS LockAllFmpVariables(FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private)
VOID SetLastAttemptVersionInVariable(IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private, IN UINT32 LastAttemptVersion)
#define DEFAULT_VERSION
#define VARNAME_VERSION
#define VARNAME_FMPSTATE