2 UEFI variable support functions for Firmware Management Protocol based
5 Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
6 Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/DebugLib.h>
14 #include <Library/UefiBootServicesTableLib.h>
15 #include <Library/UefiRuntimeServicesTableLib.h>
16 #include <Library/UefiLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Protocol/VariableLock.h>
19 #include "VariableSupport.h"
22 /// Array of UEFI variable names that are locked in LockAllFmpVariables().
24 const CHAR16
*mFmpVariableLockList
[] = {
27 VARNAME_LASTATTEMPTSTATUS
,
28 VARNAME_LASTATTEMPTVERSION
32 Returns the value used to fill in the Version field of the
33 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
34 service of the Firmware Management Protocol. The value is read from a UEFI
35 variable. If the UEFI variables does not exist, then a default version value
38 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
40 @return The version of the firmware image in the firmware device.
44 GetVersionFromVariable (
55 Version
= DEFAULT_VERSION
;
57 Status
= GetVariable2 (VARNAME_VERSION
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
58 if (EFI_ERROR (Status
) || (Value
== NULL
)) {
59 DEBUG ((DEBUG_ERROR
, "Failed to get the Version from variable. Status = %r\n", Status
));
66 if (Size
== sizeof (*Value
)) {
73 // Return default since size was unknown
75 DEBUG ((DEBUG_ERROR
, "Getting version Variable returned a size different than expected. Size = 0x%x\n", Size
));
84 Returns the value used to fill in the LowestSupportedVersion field of the
85 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
86 service of the Firmware Management Protocol. The value is read from a UEFI
87 variable. If the UEFI variables does not exist, then a default lowest
88 supported version value is returned.
90 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
92 @return The lowest supported version of the firmware image in the firmware
97 GetLowestSupportedVersionFromVariable (
108 Version
= DEFAULT_LOWESTSUPPORTEDVERSION
;
110 Status
= GetVariable2 (VARNAME_LSV
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
111 if (EFI_ERROR (Status
) || (Value
== NULL
)) {
112 DEBUG ((DEBUG_WARN
, "Warning: Failed to get the Lowest Supported Version from variable. Status = %r\n", Status
));
117 // No error from call
119 if (Size
== sizeof (*Value
)) {
126 // Return default since size was unknown
128 DEBUG ((DEBUG_ERROR
, "Getting LSV Variable returned a size different than expected. Size = 0x%x\n", Size
));
137 Returns the value used to fill in the LastAttemptStatus field of the
138 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
139 service of the Firmware Management Protocol. The value is read from a UEFI
140 variable. If the UEFI variables does not exist, then a default last attempt
141 status value is returned.
143 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
145 @return The last attempt status value for the most recent capsule update.
149 GetLastAttemptStatusFromVariable (
156 UINT32 LastAttemptStatus
;
160 LastAttemptStatus
= DEFAULT_LASTATTEMPT
;
162 Status
= GetVariable2 (VARNAME_LASTATTEMPTSTATUS
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
163 if (EFI_ERROR (Status
) || (Value
== NULL
)) {
164 DEBUG ((DEBUG_WARN
, "Warning: Failed to get the Last Attempt Status from variable. Status = %r\n", Status
));
165 return LastAttemptStatus
;
169 // No error from call
171 if (Size
== sizeof (*Value
)) {
175 LastAttemptStatus
= *Value
;
178 // Return default since size was unknown
182 "Getting Last Attempt Status Variable returned a size different than expected. Size = 0x%x\n",
189 return LastAttemptStatus
;
193 Returns the value used to fill in the LastAttemptVersion field of the
194 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
195 service of the Firmware Management Protocol. The value is read from a UEFI
196 variable. If the UEFI variables does not exist, then a default last attempt
197 version value is returned.
199 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
201 @return The last attempt version value for the most recent capsule update.
205 GetLastAttemptVersionFromVariable (
216 Version
= DEFAULT_LASTATTEMPT
;
218 Status
= GetVariable2 (VARNAME_LASTATTEMPTVERSION
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
219 if (EFI_ERROR (Status
) || (Value
== NULL
)) {
220 DEBUG ((DEBUG_WARN
, "Warning: Failed to get the Last Attempt Version from variable. Status = %r\n", Status
));
225 // No error from call
227 if (Size
== sizeof (*Value
)) {
234 // Return default since size was unknown
238 "Getting Last Attempt Version variable returned a size different than expected. Size = 0x%x\n",
250 Saves the version current of the firmware image in the firmware device to a
253 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
255 @param[in] Version The version of the firmware image in the firmware device.
259 SetVersionInVariable (
266 Status
= EFI_SUCCESS
;
268 Current
= GetVersionFromVariable();
269 if (Current
!= Version
) {
270 Status
= gRT
->SetVariable (
273 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
277 if (EFI_ERROR (Status
)) {
278 DEBUG ((DEBUG_ERROR
, "Failed to set the Version into a variable. Status = %r\n", Status
));
281 DEBUG ((DEBUG_INFO
, "Version variable doesn't need to update. Same value as before.\n"));
286 Saves the lowest supported version current of the firmware image in the
287 firmware device to a UEFI variable.
289 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
291 @param[in] LowestSupportedVersion The lowest supported version of the firmware image
292 in the firmware device.
296 SetLowestSupportedVersionInVariable (
297 UINT32 LowestSupportedVersion
303 Status
= EFI_SUCCESS
;
305 Current
= GetLowestSupportedVersionFromVariable();
306 if (LowestSupportedVersion
> Current
) {
307 Status
= gRT
->SetVariable (
310 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
311 sizeof (LowestSupportedVersion
), &LowestSupportedVersion
313 if (EFI_ERROR (Status
)) {
314 DEBUG ((DEBUG_ERROR
, "Failed to set the LSV into a variable. Status = %r\n", Status
));
317 DEBUG ((DEBUG_INFO
, "LSV variable doesn't need to update. Same value as before.\n"));
322 Saves the last attempt status value of the most recent FMP capsule update to a
325 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
327 @param[in] LastAttemptStatus The last attempt status of the most recent FMP
332 SetLastAttemptStatusInVariable (
333 UINT32 LastAttemptStatus
339 Status
= EFI_SUCCESS
;
341 Current
= GetLastAttemptStatusFromVariable();
342 if (Current
!= LastAttemptStatus
) {
343 Status
= gRT
->SetVariable (
344 VARNAME_LASTATTEMPTSTATUS
,
346 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
347 sizeof (LastAttemptStatus
),
350 if (EFI_ERROR (Status
)) {
351 DEBUG ((DEBUG_ERROR
, "Failed to set the LastAttemptStatus into a variable. Status = %r\n", Status
));
354 DEBUG ((DEBUG_INFO
, "LastAttemptStatus variable doesn't need to update. Same value as before.\n"));
359 Saves the last attempt version value of the most recent FMP capsule update to
362 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
364 @param[in] LastAttemptVersion The last attempt version value of the most
365 recent FMP capsule update.
369 SetLastAttemptVersionInVariable (
370 UINT32 LastAttemptVersion
376 Status
= EFI_SUCCESS
;
378 Current
= GetLastAttemptVersionFromVariable();
379 if (Current
!= LastAttemptVersion
) {
380 Status
= gRT
->SetVariable (
381 VARNAME_LASTATTEMPTVERSION
,
383 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
384 sizeof (LastAttemptVersion
),
387 if (EFI_ERROR (Status
)) {
388 DEBUG ((DEBUG_ERROR
, "Failed to set the LastAttemptVersion into a variable. Status = %r\n", Status
));
391 DEBUG ((DEBUG_INFO
, "LastAttemptVersion variable doesn't need to update. Same value as before.\n"));
396 Locks all the UEFI Variables used by this module.
398 @retval EFI_SUCCESS All UEFI variables are locked.
399 @retval EFI_UNSUPPORTED Variable Lock Protocol not found.
400 @retval Other One of the UEFI variables could not be locked.
404 LockAllFmpVariables (
409 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
410 EFI_STATUS ReturnStatus
;
414 Status
= gBS
->LocateProtocol (
415 &gEdkiiVariableLockProtocolGuid
,
417 (VOID
**)&VariableLock
419 if (EFI_ERROR (Status
)) {
420 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to locate Variable Lock Protocol (%r).\n", Status
));
421 return EFI_UNSUPPORTED
;
424 ReturnStatus
= EFI_SUCCESS
;
425 for (Index
= 0; Index
< ARRAY_SIZE (mFmpVariableLockList
); Index
++) {
426 Status
= VariableLock
->RequestToLock (
428 (CHAR16
*)mFmpVariableLockList
[Index
],
431 if (EFI_ERROR (Status
)) {
432 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to lock variable %g %s. Status = %r\n",
434 mFmpVariableLockList
[Index
],
437 if (!EFI_ERROR (ReturnStatus
)) {
438 ReturnStatus
= Status
;