]> git.proxmox.com Git - mirror_edk2.git/blob - FmpDevicePkg/FmpDxe/VariableSupport.c
FmpDevicePkg/FmpDxe: Different variable for each FMP Descriptor
[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, "Failed to delete FMP Variable %s. Status = %r\n", VariableName, Status));
79 } else {
80 DEBUG ((DEBUG_INFO, "Deleted FMP Variable %s\n", 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, "Failed to get the FMP Controller State. Status = %r\n", Status));
116 } else {
117 if (Size == sizeof (*FmpControllerState)) {
118 return FmpControllerState;
119 }
120 DEBUG ((DEBUG_ERROR, "Getting FMP Controller State returned a size different than expected. Size = 0x%x\n", 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, "Failed to generate FMP variable name %s.\n", 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, "Failed to generate FMP variable name %s.\n", 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 Variable %g %s\n", &gEfiCallerIdGuid, Private->VersionVariableName));
238 DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LsvVariableName));
239 DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));
240 DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));
241 DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &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, "Create FMP Controller State\n"));
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, "Failed to create FMP Controller State. Status = %r\n", 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, "Get FMP Variable %g %s Version %08x\n",
331 &gEfiCallerIdGuid,
332 Private->FmpStateVariableName,
333 Value
334 ));
335 }
336 FreePool (FmpControllerState);
337 }
338 return Value;
339 }
340
341 /**
342 Returns the value used to fill in the LowestSupportedVersion field of the
343 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
344 service of the Firmware Management Protocol. The value is read from a UEFI
345 variable. If the UEFI variables does not exist, then a default lowest
346 supported version value is returned.
347
348 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
349
350 @param[in] Private Private context structure for the managed controller.
351
352 @return The lowest supported version of the firmware image in the firmware
353 device.
354 **/
355 UINT32
356 GetLowestSupportedVersionFromVariable (
357 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
358 )
359 {
360 FMP_CONTROLLER_STATE *FmpControllerState;
361 UINT32 Value;
362
363 Value = DEFAULT_LOWESTSUPPORTEDVERSION;
364 FmpControllerState = GetFmpControllerState (Private);
365 if (FmpControllerState != NULL) {
366 if (FmpControllerState->LsvValid) {
367 Value = FmpControllerState->Lsv;
368 DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LowestSupportedVersion %08x\n",
369 &gEfiCallerIdGuid,
370 Private->FmpStateVariableName,
371 Value
372 ));
373 }
374 FreePool (FmpControllerState);
375 }
376 return Value;
377 }
378
379 /**
380 Returns the value used to fill in the LastAttemptStatus field of the
381 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
382 service of the Firmware Management Protocol. The value is read from a UEFI
383 variable. If the UEFI variables does not exist, then a default last attempt
384 status value is returned.
385
386 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
387
388 @param[in] Private Private context structure for the managed controller.
389
390 @return The last attempt status value for the most recent capsule update.
391 **/
392 UINT32
393 GetLastAttemptStatusFromVariable (
394 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
395 )
396 {
397 FMP_CONTROLLER_STATE *FmpControllerState;
398 UINT32 Value;
399
400 Value = DEFAULT_LASTATTEMPTSTATUS;
401 FmpControllerState = GetFmpControllerState (Private);
402 if (FmpControllerState != NULL) {
403 if (FmpControllerState->LastAttemptStatusValid) {
404 Value = FmpControllerState->LastAttemptStatus;
405 DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LastAttemptStatus %08x\n",
406 &gEfiCallerIdGuid,
407 Private->FmpStateVariableName,
408 Value
409 ));
410 }
411 FreePool (FmpControllerState);
412 }
413 return Value;
414 }
415
416 /**
417 Returns the value used to fill in the LastAttemptVersion field of the
418 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
419 service of the Firmware Management Protocol. The value is read from a UEFI
420 variable. If the UEFI variables does not exist, then a default last attempt
421 version value is returned.
422
423 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
424
425 @param[in] Private Private context structure for the managed controller.
426
427 @return The last attempt version value for the most recent capsule update.
428 **/
429 UINT32
430 GetLastAttemptVersionFromVariable (
431 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
432 )
433 {
434 FMP_CONTROLLER_STATE *FmpControllerState;
435 UINT32 Value;
436
437 Value = DEFAULT_LASTATTEMPTVERSION;
438 FmpControllerState = GetFmpControllerState (Private);
439 if (FmpControllerState != NULL) {
440 if (FmpControllerState->LastAttemptVersionValid) {
441 Value = FmpControllerState->LastAttemptVersion;
442 DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LastAttemptVersion %08x\n",
443 &gEfiCallerIdGuid,
444 Private->FmpStateVariableName,
445 Value
446 ));
447 }
448 FreePool (FmpControllerState);
449 }
450 return Value;
451 }
452
453 /**
454 Saves the version current of the firmware image in the firmware device to a
455 UEFI variable.
456
457 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
458
459 @param[in] Private Private context structure for the managed controller.
460 @param[in] Version The version of the firmware image in the firmware device.
461 **/
462 VOID
463 SetVersionInVariable (
464 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
465 IN UINT32 Version
466 )
467 {
468 EFI_STATUS Status;
469 FMP_CONTROLLER_STATE *FmpControllerState;
470 BOOLEAN Update;
471
472 FmpControllerState = GetFmpControllerState (Private);
473 if (FmpControllerState == NULL) {
474 //
475 // Can not update value if FMP Controller State does not exist.
476 // This variable is guaranteed to be created by GenerateFmpVariableNames().
477 //
478 return;
479 }
480
481 Update = FALSE;
482 if (!FmpControllerState->VersionValid) {
483 Update = TRUE;
484 }
485 if (FmpControllerState->Version != Version) {
486 Update = TRUE;
487 }
488 if (!Update) {
489 DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
490 } else {
491 FmpControllerState->VersionValid = TRUE;
492 FmpControllerState->Version = Version;
493 Status = gRT->SetVariable (
494 Private->FmpStateVariableName,
495 &gEfiCallerIdGuid,
496 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
497 sizeof (*FmpControllerState),
498 FmpControllerState
499 );
500 if (EFI_ERROR (Status)) {
501 DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
502 } else {
503 DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s Version %08x\n",
504 &gEfiCallerIdGuid,
505 Private->FmpStateVariableName,
506 Version
507 ));
508 }
509 }
510 FreePool (FmpControllerState);
511 }
512
513 /**
514 Saves the lowest supported version current of the firmware image in the
515 firmware device to a UEFI variable.
516
517 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
518
519 @param[in] Private Private context structure for the managed
520 controller.
521 @param[in] LowestSupportedVersion The lowest supported version of the
522 firmware image in the firmware device.
523 **/
524 VOID
525 SetLowestSupportedVersionInVariable (
526 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
527 IN UINT32 LowestSupportedVersion
528 )
529 {
530 EFI_STATUS Status;
531 FMP_CONTROLLER_STATE *FmpControllerState;
532 BOOLEAN Update;
533
534 FmpControllerState = GetFmpControllerState (Private);
535 if (FmpControllerState == NULL) {
536 //
537 // Can not update value if FMP Controller State does not exist.
538 // This variable is guaranteed to be created by GenerateFmpVariableNames().
539 //
540 return;
541 }
542
543 Update = FALSE;
544 if (!FmpControllerState->LsvValid) {
545 Update = TRUE;
546 }
547 if (FmpControllerState->Lsv < LowestSupportedVersion) {
548 Update = TRUE;
549 }
550 if (!Update) {
551 DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
552 } else {
553 FmpControllerState->LsvValid = TRUE;
554 FmpControllerState->Lsv = LowestSupportedVersion;
555 Status = gRT->SetVariable (
556 Private->FmpStateVariableName,
557 &gEfiCallerIdGuid,
558 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
559 sizeof (*FmpControllerState),
560 FmpControllerState
561 );
562 if (EFI_ERROR (Status)) {
563 DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
564 } else {
565 DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LowestSupportedVersion %08x\n",
566 &gEfiCallerIdGuid,
567 Private->FmpStateVariableName,
568 LowestSupportedVersion
569 ));
570 }
571 }
572 FreePool (FmpControllerState);
573 }
574
575 /**
576 Saves the last attempt status value of the most recent FMP capsule update to a
577 UEFI variable.
578
579 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
580
581 @param[in] Private Private context structure for the managed
582 controller.
583 @param[in] LastAttemptStatus The last attempt status of the most recent FMP
584 capsule update.
585 **/
586 VOID
587 SetLastAttemptStatusInVariable (
588 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
589 IN UINT32 LastAttemptStatus
590 )
591 {
592 EFI_STATUS Status;
593 FMP_CONTROLLER_STATE *FmpControllerState;
594 BOOLEAN Update;
595
596 FmpControllerState = GetFmpControllerState (Private);
597 if (FmpControllerState == NULL) {
598 //
599 // Can not update value if FMP Controller State does not exist.
600 // This variable is guaranteed to be created by GenerateFmpVariableNames().
601 //
602 return;
603 }
604
605 Update = FALSE;
606 if (!FmpControllerState->LastAttemptStatusValid) {
607 Update = TRUE;
608 }
609 if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {
610 Update = TRUE;
611 }
612 if (!Update) {
613 DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
614 } else {
615 FmpControllerState->LastAttemptStatusValid = TRUE;
616 FmpControllerState->LastAttemptStatus = LastAttemptStatus;
617 Status = gRT->SetVariable (
618 Private->FmpStateVariableName,
619 &gEfiCallerIdGuid,
620 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
621 sizeof (*FmpControllerState),
622 FmpControllerState
623 );
624 if (EFI_ERROR (Status)) {
625 DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
626 } else {
627 DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LastAttemptStatus %08x\n",
628 &gEfiCallerIdGuid,
629 Private->FmpStateVariableName,
630 LastAttemptStatus
631 ));
632 }
633 }
634 FreePool (FmpControllerState);
635 }
636
637 /**
638 Saves the last attempt version value of the most recent FMP capsule update to
639 a UEFI variable.
640
641 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
642
643 @param[in] Private Private context structure for the managed
644 controller.
645 @param[in] LastAttemptVersion The last attempt version value of the most
646 recent FMP capsule update.
647 **/
648 VOID
649 SetLastAttemptVersionInVariable (
650 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
651 IN UINT32 LastAttemptVersion
652 )
653 {
654 EFI_STATUS Status;
655 FMP_CONTROLLER_STATE *FmpControllerState;
656 BOOLEAN Update;
657
658 FmpControllerState = GetFmpControllerState (Private);
659 if (FmpControllerState == NULL) {
660 //
661 // Can not update value if FMP Controller State does not exist.
662 // This variable is guaranteed to be created by GenerateFmpVariableNames().
663 //
664 return;
665 }
666
667 Update = FALSE;
668 if (!FmpControllerState->LastAttemptVersionValid) {
669 Update = TRUE;
670 }
671 if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {
672 Update = TRUE;
673 }
674 if (!Update) {
675 DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));
676 } else {
677 FmpControllerState->LastAttemptVersionValid = TRUE;
678 FmpControllerState->LastAttemptVersion = LastAttemptVersion;
679 Status = gRT->SetVariable (
680 Private->FmpStateVariableName,
681 &gEfiCallerIdGuid,
682 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
683 sizeof (*FmpControllerState),
684 FmpControllerState
685 );
686 if (EFI_ERROR (Status)) {
687 DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));
688 } else {
689 DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LastAttemptVersion %08x\n",
690 &gEfiCallerIdGuid,
691 Private->FmpStateVariableName,
692 LastAttemptVersion
693 ));
694 }
695 }
696 FreePool (FmpControllerState);
697 }
698
699 /**
700 Attempts to lock a single UEFI Variable propagating the error state of the
701 first lock attempt that fails. Uses gEfiCallerIdGuid as the variable GUID.
702
703 @param[in] PreviousStatus The previous UEFI Variable lock attempt status.
704 @param[in] VariableLock The EDK II Variable Lock Protocol instance.
705 @param[in] VariableName The name of the UEFI Variable to lock.
706
707 @retval EFI_SUCCESS The UEFI Variable was locked and the previous variable
708 lock attempt also succeeded.
709 @retval Other The UEFI Variable could not be locked or the previous
710 variable lock attempt failed.
711 **/
712 static
713 EFI_STATUS
714 LockFmpVariable (
715 IN EFI_STATUS PreviousStatus,
716 IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock,
717 IN CHAR16 *VariableName
718 )
719 {
720 EFI_STATUS Status;
721
722 Status = VariableLock->RequestToLock (
723 VariableLock,
724 VariableName,
725 &gEfiCallerIdGuid
726 );
727 if (!EFI_ERROR (Status)) {
728 return PreviousStatus;
729 }
730
731 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variable %g %s. Status = %r\n",
732 &gEfiCallerIdGuid,
733 VariableName,
734 Status
735 ));
736
737 if (EFI_ERROR (PreviousStatus)) {
738 return PreviousStatus;
739 }
740 return Status;
741 }
742
743 /**
744 Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently
745 executing module.
746
747 @param[in] Private Private context structure for the managed controller.
748
749 @retval EFI_SUCCESS All UEFI variables are locked.
750 @retval EFI_UNSUPPORTED Variable Lock Protocol not found.
751 @retval Other One of the UEFI variables could not be locked.
752 **/
753 EFI_STATUS
754 LockAllFmpVariables (
755 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
756 )
757 {
758 EFI_STATUS Status;
759 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
760
761 VariableLock = NULL;
762 Status = gBS->LocateProtocol (
763 &gEdkiiVariableLockProtocolGuid,
764 NULL,
765 (VOID **)&VariableLock
766 );
767 if (EFI_ERROR (Status) || VariableLock == NULL) {
768 DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to locate Variable Lock Protocol (%r).\n", Status));
769 return EFI_UNSUPPORTED;
770 }
771
772 Status = EFI_SUCCESS;
773 Status = LockFmpVariable (Status, VariableLock, Private->VersionVariableName);
774 Status = LockFmpVariable (Status, VariableLock, Private->LsvVariableName);
775 Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptStatusVariableName);
776 Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptVersionVariableName);
777 Status = LockFmpVariable (Status, VariableLock, Private->FmpStateVariableName);
778
779 return Status;
780 }