]> git.proxmox.com Git - mirror_edk2.git/blob - FmpDevicePkg/FmpDxe/VariableSupport.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 UINTN Size;
151 CHAR16 *VariableName;
152
153 //
154 // Allocate Unicode string with room for BaseVariableName and a 16 digit
155 // hexadecimal value for the HardwareInstance value.
156 //
157 Size = StrSize (BaseVariableName) + 16 * sizeof (CHAR16);
158 VariableName = AllocateCopyPool (Size, BaseVariableName);
159 if (VariableName == NULL) {
160 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to generate variable name %s.\n", mImageIdName, BaseVariableName));
161 return VariableName;
162 }
163 if (HardwareInstance == 0) {
164 return VariableName;
165 }
166 UnicodeValueToStringS (
167 &VariableName[StrLen(BaseVariableName)],
168 Size,
169 PREFIX_ZERO | RADIX_HEX,
170 HardwareInstance,
171 16
172 );
173 return VariableName;
174 }
175
176 /**
177 Generate the names of the UEFI Variables used to store state information for
178 a managed controller. The UEFI Variables names are a combination of a base
179 name and an optional hardware instance value as a 16 character hex value. If
180 the hardware instance value is 0, then the 16 character hex value is not
181 included. These storage for the UEFI Variable names are allocated using the
182 UEFI Boot Service AllocatePool() and the pointers are stored in the Private.
183 The following are examples of variable names produces for hardware instance
184 value 0 and value 0x1234567812345678.
185
186 FmpVersion
187 FmpLsv
188 LastAttemptStatus
189 LastAttemptVersion
190 FmpState
191
192 FmpVersion1234567812345678
193 FmpLsv1234567812345678
194 LastAttemptStatus1234567812345678
195 LastAttemptVersion1234567812345678
196 FmpState1234567812345678
197
198 @param[in,out] Private Private context structure for the managed controller.
199 **/
200 VOID
201 GenerateFmpVariableNames (
202 IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
203 )
204 {
205 EFI_STATUS Status;
206 VOID *Buffer;
207 FMP_CONTROLLER_STATE FmpControllerState;
208
209 if (Private->VersionVariableName != NULL) {
210 FreePool (Private->VersionVariableName);
211 }
212 if (Private->LsvVariableName != NULL) {
213 FreePool (Private->LsvVariableName);
214 }
215 if (Private->LastAttemptStatusVariableName != NULL) {
216 FreePool (Private->LastAttemptStatusVariableName);
217 }
218 if (Private->LastAttemptVersionVariableName != NULL) {
219 FreePool (Private->LastAttemptVersionVariableName);
220 }
221 if (Private->FmpStateVariableName != NULL) {
222 FreePool (Private->FmpStateVariableName);
223 }
224
225 Private->VersionVariableName = GenerateFmpVariableName (
226 Private->Descriptor.HardwareInstance,
227 VARNAME_VERSION
228 );
229 Private->LsvVariableName = GenerateFmpVariableName (
230 Private->Descriptor.HardwareInstance,
231 VARNAME_LSV
232 );
233 Private->LastAttemptStatusVariableName = GenerateFmpVariableName (
234 Private->Descriptor.HardwareInstance,
235 VARNAME_LASTATTEMPTSTATUS
236 );
237 Private->LastAttemptVersionVariableName = GenerateFmpVariableName (
238 Private->Descriptor.HardwareInstance,
239 VARNAME_LASTATTEMPTVERSION
240 );
241 Private->FmpStateVariableName = GenerateFmpVariableName (
242 Private->Descriptor.HardwareInstance,
243 VARNAME_FMPSTATE
244 );
245
246 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->VersionVariableName));
247 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LsvVariableName));
248 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));
249 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));
250 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->FmpStateVariableName));
251
252 Buffer = GetFmpControllerState (Private);
253 if (Buffer != NULL) {
254 //
255 // FMP Controller State was found with correct size.
256 // Delete old variables if they exist.
257 //
258 FreePool (Buffer);
259 DeleteFmpVariable (Private->VersionVariableName);
260 DeleteFmpVariable (Private->LsvVariableName);
261 DeleteFmpVariable (Private->LastAttemptStatusVariableName);
262 DeleteFmpVariable (Private->LastAttemptVersionVariableName);
263 return;
264 }
265
266 //
267 // FMP Controller State was either not found or is wrong size.
268 // Create a new FMP Controller State variable with the correct size.
269 //
270 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Create controller state\n", mImageIdName));
271 GetFmpVariable (
272 Private->VersionVariableName,
273 &FmpControllerState.VersionValid,
274 &FmpControllerState.Version
275 );
276 GetFmpVariable (
277 Private->LsvVariableName,
278 &FmpControllerState.LsvValid,
279 &FmpControllerState.Lsv
280 );
281 GetFmpVariable (
282 Private->LastAttemptStatusVariableName,
283 &FmpControllerState.LastAttemptStatusValid,
284 &FmpControllerState.LastAttemptStatus
285 );
286 GetFmpVariable (
287 Private->LastAttemptVersionVariableName,
288 &FmpControllerState.LastAttemptVersionValid,
289 &FmpControllerState.LastAttemptVersion
290 );
291 Status = gRT->SetVariable (
292 Private->FmpStateVariableName,
293 &gEfiCallerIdGuid,
294 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
295 sizeof (FmpControllerState),
296 &FmpControllerState
297 );
298 if (EFI_ERROR (Status)) {
299 //
300 // Failed to create FMP Controller State. In this case, do not
301 // delete the individual variables. They can be used again on next boot
302 // to create the FMP Controller State.
303 //
304 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to create controller state. Status = %r\n", mImageIdName, Status));
305 } else {
306 DeleteFmpVariable (Private->VersionVariableName);
307 DeleteFmpVariable (Private->LsvVariableName);
308 DeleteFmpVariable (Private->LastAttemptStatusVariableName);
309 DeleteFmpVariable (Private->LastAttemptVersionVariableName);
310 }
311 }
312
313 /**
314 Returns the value used to fill in the Version field of the
315 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
316 service of the Firmware Management Protocol. The value is read from a UEFI
317 variable. If the UEFI variables does not exist, then a default version value
318 is returned.
319
320 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
321
322 @param[in] Private Private context structure for the managed controller.
323
324 @return The version of the firmware image in the firmware device.
325 **/
326 UINT32
327 GetVersionFromVariable (
328 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
329 )
330 {
331 FMP_CONTROLLER_STATE *FmpControllerState;
332 UINT32 Value;
333
334 Value = DEFAULT_VERSION;
335 FmpControllerState = GetFmpControllerState (Private);
336 if (FmpControllerState != NULL) {
337 if (FmpControllerState->VersionValid) {
338 Value = FmpControllerState->Version;
339 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s Version %08x\n",
340 mImageIdName,
341 &gEfiCallerIdGuid,
342 Private->FmpStateVariableName,
343 Value
344 ));
345 }
346 FreePool (FmpControllerState);
347 }
348 return Value;
349 }
350
351 /**
352 Returns the value used to fill in the LowestSupportedVersion field of the
353 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
354 service of the Firmware Management Protocol. The value is read from a UEFI
355 variable. If the UEFI variables does not exist, then a default lowest
356 supported version value is returned.
357
358 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
359
360 @param[in] Private Private context structure for the managed controller.
361
362 @return The lowest supported version of the firmware image in the firmware
363 device.
364 **/
365 UINT32
366 GetLowestSupportedVersionFromVariable (
367 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
368 )
369 {
370 FMP_CONTROLLER_STATE *FmpControllerState;
371 UINT32 Value;
372
373 Value = DEFAULT_LOWESTSUPPORTEDVERSION;
374 FmpControllerState = GetFmpControllerState (Private);
375 if (FmpControllerState != NULL) {
376 if (FmpControllerState->LsvValid) {
377 Value = FmpControllerState->Lsv;
378 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s LowestSupportedVersion %08x\n",
379 mImageIdName,
380 &gEfiCallerIdGuid,
381 Private->FmpStateVariableName,
382 Value
383 ));
384 }
385 FreePool (FmpControllerState);
386 }
387 return Value;
388 }
389
390 /**
391 Returns the value used to fill in the LastAttemptStatus field of the
392 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
393 service of the Firmware Management Protocol. The value is read from a UEFI
394 variable. If the UEFI variables does not exist, then a default last attempt
395 status value is returned.
396
397 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
398
399 @param[in] Private Private context structure for the managed controller.
400
401 @return The last attempt status value for the most recent capsule update.
402 **/
403 UINT32
404 GetLastAttemptStatusFromVariable (
405 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
406 )
407 {
408 FMP_CONTROLLER_STATE *FmpControllerState;
409 UINT32 Value;
410
411 Value = DEFAULT_LASTATTEMPTSTATUS;
412 FmpControllerState = GetFmpControllerState (Private);
413 if (FmpControllerState != NULL) {
414 if (FmpControllerState->LastAttemptStatusValid) {
415 Value = FmpControllerState->LastAttemptStatus;
416 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s LastAttemptStatus %08x\n",
417 mImageIdName,
418 &gEfiCallerIdGuid,
419 Private->FmpStateVariableName,
420 Value
421 ));
422 }
423 FreePool (FmpControllerState);
424 }
425 return Value;
426 }
427
428 /**
429 Returns the value used to fill in the LastAttemptVersion field of the
430 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
431 service of the Firmware Management Protocol. The value is read from a UEFI
432 variable. If the UEFI variables does not exist, then a default last attempt
433 version value is returned.
434
435 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
436
437 @param[in] Private Private context structure for the managed controller.
438
439 @return The last attempt version value for the most recent capsule update.
440 **/
441 UINT32
442 GetLastAttemptVersionFromVariable (
443 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
444 )
445 {
446 FMP_CONTROLLER_STATE *FmpControllerState;
447 UINT32 Value;
448
449 Value = DEFAULT_LASTATTEMPTVERSION;
450 FmpControllerState = GetFmpControllerState (Private);
451 if (FmpControllerState != NULL) {
452 if (FmpControllerState->LastAttemptVersionValid) {
453 Value = FmpControllerState->LastAttemptVersion;
454 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Get variable %g %s LastAttemptVersion %08x\n",
455 mImageIdName,
456 &gEfiCallerIdGuid,
457 Private->FmpStateVariableName,
458 Value
459 ));
460 }
461 FreePool (FmpControllerState);
462 }
463 return Value;
464 }
465
466 /**
467 Saves the version current of the firmware image in the firmware device to a
468 UEFI variable.
469
470 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
471
472 @param[in] Private Private context structure for the managed controller.
473 @param[in] Version The version of the firmware image in the firmware device.
474 **/
475 VOID
476 SetVersionInVariable (
477 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
478 IN UINT32 Version
479 )
480 {
481 EFI_STATUS Status;
482 FMP_CONTROLLER_STATE *FmpControllerState;
483 BOOLEAN Update;
484
485 FmpControllerState = GetFmpControllerState (Private);
486 if (FmpControllerState == NULL) {
487 //
488 // Can not update value if FMP Controller State does not exist.
489 // This variable is guaranteed to be created by GenerateFmpVariableNames().
490 //
491 return;
492 }
493
494 Update = FALSE;
495 if (!FmpControllerState->VersionValid) {
496 Update = TRUE;
497 }
498 if (FmpControllerState->Version != Version) {
499 Update = TRUE;
500 }
501 if (!Update) {
502 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
503 } else {
504 FmpControllerState->VersionValid = TRUE;
505 FmpControllerState->Version = Version;
506 Status = gRT->SetVariable (
507 Private->FmpStateVariableName,
508 &gEfiCallerIdGuid,
509 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
510 sizeof (*FmpControllerState),
511 FmpControllerState
512 );
513 if (EFI_ERROR (Status)) {
514 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
515 } else {
516 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s Version %08x\n",
517 mImageIdName,
518 &gEfiCallerIdGuid,
519 Private->FmpStateVariableName,
520 Version
521 ));
522 }
523 }
524 FreePool (FmpControllerState);
525 }
526
527 /**
528 Saves the lowest supported version current of the firmware image in the
529 firmware device to a UEFI variable.
530
531 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
532
533 @param[in] Private Private context structure for the managed
534 controller.
535 @param[in] LowestSupportedVersion The lowest supported version of the
536 firmware image in the firmware device.
537 **/
538 VOID
539 SetLowestSupportedVersionInVariable (
540 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
541 IN UINT32 LowestSupportedVersion
542 )
543 {
544 EFI_STATUS Status;
545 FMP_CONTROLLER_STATE *FmpControllerState;
546 BOOLEAN Update;
547
548 FmpControllerState = GetFmpControllerState (Private);
549 if (FmpControllerState == NULL) {
550 //
551 // Can not update value if FMP Controller State does not exist.
552 // This variable is guaranteed to be created by GenerateFmpVariableNames().
553 //
554 return;
555 }
556
557 Update = FALSE;
558 if (!FmpControllerState->LsvValid) {
559 Update = TRUE;
560 }
561 if (FmpControllerState->Lsv < LowestSupportedVersion) {
562 Update = TRUE;
563 }
564 if (!Update) {
565 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
566 } else {
567 FmpControllerState->LsvValid = TRUE;
568 FmpControllerState->Lsv = LowestSupportedVersion;
569 Status = gRT->SetVariable (
570 Private->FmpStateVariableName,
571 &gEfiCallerIdGuid,
572 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
573 sizeof (*FmpControllerState),
574 FmpControllerState
575 );
576 if (EFI_ERROR (Status)) {
577 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
578 } else {
579 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s LowestSupportedVersion %08x\n",
580 mImageIdName,
581 &gEfiCallerIdGuid,
582 Private->FmpStateVariableName,
583 LowestSupportedVersion
584 ));
585 }
586 }
587 FreePool (FmpControllerState);
588 }
589
590 /**
591 Saves the last attempt status value of the most recent FMP capsule update to a
592 UEFI variable.
593
594 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
595
596 @param[in] Private Private context structure for the managed
597 controller.
598 @param[in] LastAttemptStatus The last attempt status of the most recent FMP
599 capsule update.
600 **/
601 VOID
602 SetLastAttemptStatusInVariable (
603 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
604 IN UINT32 LastAttemptStatus
605 )
606 {
607 EFI_STATUS Status;
608 FMP_CONTROLLER_STATE *FmpControllerState;
609 BOOLEAN Update;
610
611 FmpControllerState = GetFmpControllerState (Private);
612 if (FmpControllerState == NULL) {
613 //
614 // Can not update value if FMP Controller State does not exist.
615 // This variable is guaranteed to be created by GenerateFmpVariableNames().
616 //
617 return;
618 }
619
620 Update = FALSE;
621 if (!FmpControllerState->LastAttemptStatusValid) {
622 Update = TRUE;
623 }
624 if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {
625 Update = TRUE;
626 }
627 if (!Update) {
628 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
629 } else {
630 FmpControllerState->LastAttemptStatusValid = TRUE;
631 FmpControllerState->LastAttemptStatus = LastAttemptStatus;
632 Status = gRT->SetVariable (
633 Private->FmpStateVariableName,
634 &gEfiCallerIdGuid,
635 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
636 sizeof (*FmpControllerState),
637 FmpControllerState
638 );
639 if (EFI_ERROR (Status)) {
640 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
641 } else {
642 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s LastAttemptStatus %08x\n",
643 mImageIdName,
644 &gEfiCallerIdGuid,
645 Private->FmpStateVariableName,
646 LastAttemptStatus
647 ));
648 }
649 }
650 FreePool (FmpControllerState);
651 }
652
653 /**
654 Saves the last attempt version value of the most recent FMP capsule update to
655 a UEFI variable.
656
657 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"
658
659 @param[in] Private Private context structure for the managed
660 controller.
661 @param[in] LastAttemptVersion The last attempt version value of the most
662 recent FMP capsule update.
663 **/
664 VOID
665 SetLastAttemptVersionInVariable (
666 IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
667 IN UINT32 LastAttemptVersion
668 )
669 {
670 EFI_STATUS Status;
671 FMP_CONTROLLER_STATE *FmpControllerState;
672 BOOLEAN Update;
673
674 FmpControllerState = GetFmpControllerState (Private);
675 if (FmpControllerState == NULL) {
676 //
677 // Can not update value if FMP Controller State does not exist.
678 // This variable is guaranteed to be created by GenerateFmpVariableNames().
679 //
680 return;
681 }
682
683 Update = FALSE;
684 if (!FmpControllerState->LastAttemptVersionValid) {
685 Update = TRUE;
686 }
687 if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {
688 Update = TRUE;
689 }
690 if (!Update) {
691 DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state. Same value as before.\n", mImageIdName));
692 } else {
693 FmpControllerState->LastAttemptVersionValid = TRUE;
694 FmpControllerState->LastAttemptVersion = LastAttemptVersion;
695 Status = gRT->SetVariable (
696 Private->FmpStateVariableName,
697 &gEfiCallerIdGuid,
698 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
699 sizeof (*FmpControllerState),
700 FmpControllerState
701 );
702 if (EFI_ERROR (Status)) {
703 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state. Status = %r\n", mImageIdName, Status));
704 } else {
705 DEBUG ((DEBUG_INFO, "FmpDxe(%s): Set variable %g %s LastAttemptVersion %08x\n",
706 mImageIdName,
707 &gEfiCallerIdGuid,
708 Private->FmpStateVariableName,
709 LastAttemptVersion
710 ));
711 }
712 }
713 FreePool (FmpControllerState);
714 }
715
716 /**
717 Attempts to lock a single UEFI Variable propagating the error state of the
718 first lock attempt that fails. Uses gEfiCallerIdGuid as the variable GUID.
719
720 @param[in] PreviousStatus The previous UEFI Variable lock attempt status.
721 @param[in] VariableLock The EDK II Variable Lock Protocol instance.
722 @param[in] VariableName The name of the UEFI Variable to lock.
723
724 @retval EFI_SUCCESS The UEFI Variable was locked and the previous variable
725 lock attempt also succeeded.
726 @retval Other The UEFI Variable could not be locked or the previous
727 variable lock attempt failed.
728 **/
729 static
730 EFI_STATUS
731 LockFmpVariable (
732 IN EFI_STATUS PreviousStatus,
733 IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock,
734 IN CHAR16 *VariableName
735 )
736 {
737 EFI_STATUS Status;
738
739 Status = VariableLock->RequestToLock (
740 VariableLock,
741 VariableName,
742 &gEfiCallerIdGuid
743 );
744 if (!EFI_ERROR (Status)) {
745 return PreviousStatus;
746 }
747
748 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to lock variable %g %s. Status = %r\n",
749 mImageIdName,
750 &gEfiCallerIdGuid,
751 VariableName,
752 Status
753 ));
754
755 if (EFI_ERROR (PreviousStatus)) {
756 return PreviousStatus;
757 }
758 return Status;
759 }
760
761 /**
762 Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently
763 executing module.
764
765 @param[in] Private Private context structure for the managed controller.
766
767 @retval EFI_SUCCESS All UEFI variables are locked.
768 @retval EFI_UNSUPPORTED Variable Lock Protocol not found.
769 @retval Other One of the UEFI variables could not be locked.
770 **/
771 EFI_STATUS
772 LockAllFmpVariables (
773 FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
774 )
775 {
776 EFI_STATUS Status;
777 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
778
779 VariableLock = NULL;
780 Status = gBS->LocateProtocol (
781 &gEdkiiVariableLockProtocolGuid,
782 NULL,
783 (VOID **)&VariableLock
784 );
785 if (EFI_ERROR (Status) || VariableLock == NULL) {
786 DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to locate Variable Lock Protocol (%r).\n", mImageIdName, Status));
787 return EFI_UNSUPPORTED;
788 }
789
790 Status = EFI_SUCCESS;
791 Status = LockFmpVariable (Status, VariableLock, Private->VersionVariableName);
792 Status = LockFmpVariable (Status, VariableLock, Private->LsvVariableName);
793 Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptStatusVariableName);
794 Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptVersionVariableName);
795 Status = LockFmpVariable (Status, VariableLock, Private->FmpStateVariableName);
796
797 return Status;
798 }