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 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
24 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <Library/DebugLib.h>
31 #include <Library/UefiBootServicesTableLib.h>
32 #include <Library/UefiRuntimeServicesTableLib.h>
33 #include <Library/UefiLib.h>
34 #include <Library/MemoryAllocationLib.h>
35 #include <Protocol/VariableLock.h>
36 #include "VariableSupport.h"
39 /// Array of UEFI variable names that are locked in LockAllFmpVariables().
41 const CHAR16
*mFmpVariableLockList
[] = {
44 VARNAME_LASTATTEMPTSTATUS
,
45 VARNAME_LASTATTEMPTVERSION
49 Returns the value used to fill in the Version field of the
50 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
51 service of the Firmware Management Protocol. The value is read from a UEFI
52 variable. If the UEFI variables does not exist, then a default version value
55 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
57 @return The version of the firmware image in the firmware device.
61 GetVersionFromVariable (
72 Version
= DEFAULT_VERSION
;
74 Status
= GetVariable2 (VARNAME_VERSION
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
75 if (EFI_ERROR (Status
)) {
76 DEBUG ((DEBUG_ERROR
, "Failed to get the Version from variable. Status = %r\n", Status
));
83 if (Size
== sizeof (*Value
)) {
90 // Return default since size was unknown
92 DEBUG ((DEBUG_ERROR
, "Getting version Variable returned a size different than expected. Size = 0x%x\n", Size
));
101 Returns the value used to fill in the LowestSupportedVersion field of the
102 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
103 service of the Firmware Management Protocol. The value is read from a UEFI
104 variable. If the UEFI variables does not exist, then a default lowest
105 supported version value is returned.
107 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
109 @return The lowest supported version of the firmware image in the firmware
114 GetLowestSupportedVersionFromVariable (
125 Version
= DEFAULT_LOWESTSUPPORTEDVERSION
;
127 Status
= GetVariable2 (VARNAME_LSV
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
128 if (EFI_ERROR (Status
)) {
129 DEBUG ((DEBUG_WARN
, "Warning: Failed to get the Lowest Supported Version from variable. Status = %r\n", Status
));
134 // No error from call
136 if (Size
== sizeof (*Value
)) {
143 // Return default since size was unknown
145 DEBUG ((DEBUG_ERROR
, "Getting LSV Variable returned a size different than expected. Size = 0x%x\n", Size
));
154 Returns the value used to fill in the LastAttemptStatus field of the
155 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
156 service of the Firmware Management Protocol. The value is read from a UEFI
157 variable. If the UEFI variables does not exist, then a default last attempt
158 status value is returned.
160 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
162 @return The last attempt status value for the most recent capsule update.
166 GetLastAttemptStatusFromVariable (
173 UINT32 LastAttemptStatus
;
177 LastAttemptStatus
= DEFAULT_LASTATTEMPT
;
179 Status
= GetVariable2 (VARNAME_LASTATTEMPTSTATUS
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
180 if (EFI_ERROR (Status
)) {
181 DEBUG ((DEBUG_WARN
, "Warning: Failed to get the Last Attempt Status from variable. Status = %r\n", Status
));
182 return LastAttemptStatus
;
186 // No error from call
188 if (Size
== sizeof (*Value
)) {
192 LastAttemptStatus
= *Value
;
195 // Return default since size was unknown
199 "Getting Last Attempt Status Variable returned a size different than expected. Size = 0x%x\n",
206 return LastAttemptStatus
;
210 Returns the value used to fill in the LastAttemptVersion field of the
211 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
212 service of the Firmware Management Protocol. The value is read from a UEFI
213 variable. If the UEFI variables does not exist, then a default last attempt
214 version value is returned.
216 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
218 @return The last attempt version value for the most recent capsule update.
222 GetLastAttemptVersionFromVariable (
233 Version
= DEFAULT_LASTATTEMPT
;
235 Status
= GetVariable2 (VARNAME_LASTATTEMPTVERSION
, &gEfiCallerIdGuid
, (VOID
**)&Value
, &Size
);
236 if (EFI_ERROR (Status
)) {
237 DEBUG ((DEBUG_WARN
, "Warning: Failed to get the Last Attempt Version from variable. Status = %r\n", Status
));
242 // No error from call
244 if (Size
== sizeof (*Value
)) {
251 // Return default since size was unknown
255 "Getting Last Attempt Version variable returned a size different than expected. Size = 0x%x\n",
267 Saves the version current of the firmware image in the firmware device to a
270 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"
272 @param[in] Version The version of the firmware image in the firmware device.
276 SetVersionInVariable (
283 Status
= EFI_SUCCESS
;
285 Current
= GetVersionFromVariable();
286 if (Current
!= Version
) {
287 Status
= gRT
->SetVariable (
290 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
294 if (EFI_ERROR (Status
)) {
295 DEBUG ((DEBUG_ERROR
, "Failed to set the Version into a variable. Status = %r\n", Status
));
298 DEBUG ((DEBUG_INFO
, "Version variable doesn't need to update. Same value as before.\n"));
303 Saves the lowest supported version current of the firmware image in the
304 firmware device to a UEFI variable.
306 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"
308 @param[in] LowestSupported The lowest supported version of the firmware image
309 in the firmware device.
313 SetLowestSupportedVersionInVariable (
314 UINT32 LowestSupportedVersion
320 Status
= EFI_SUCCESS
;
322 Current
= GetLowestSupportedVersionFromVariable();
323 if (LowestSupportedVersion
> Current
) {
324 Status
= gRT
->SetVariable (
327 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
328 sizeof (LowestSupportedVersion
), &LowestSupportedVersion
330 if (EFI_ERROR (Status
)) {
331 DEBUG ((DEBUG_ERROR
, "Failed to set the LSV into a variable. Status = %r\n", Status
));
334 DEBUG ((DEBUG_INFO
, "LSV variable doesn't need to update. Same value as before.\n"));
339 Saves the last attempt status value of the most recent FMP capsule update to a
342 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"
344 @param[in] LastAttemptStatus The last attempt status of the most recent FMP
349 SetLastAttemptStatusInVariable (
350 UINT32 LastAttemptStatus
356 Status
= EFI_SUCCESS
;
358 Current
= GetLastAttemptStatusFromVariable();
359 if (Current
!= LastAttemptStatus
) {
360 Status
= gRT
->SetVariable (
361 VARNAME_LASTATTEMPTSTATUS
,
363 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
364 sizeof (LastAttemptStatus
),
367 if (EFI_ERROR (Status
)) {
368 DEBUG ((DEBUG_ERROR
, "Failed to set the LastAttemptStatus into a variable. Status = %r\n", Status
));
371 DEBUG ((DEBUG_INFO
, "LastAttemptStatus variable doesn't need to update. Same value as before.\n"));
376 Saves the last attempt version value of the most recent FMP capsule update to
379 UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"
381 @param[in] LastAttemptVersion The last attempt version value of the most
382 recent FMP capsule update.
386 SetLastAttemptVersionInVariable (
387 UINT32 LastAttemptVersion
393 Status
= EFI_SUCCESS
;
395 Current
= GetLastAttemptVersionFromVariable();
396 if (Current
!= LastAttemptVersion
) {
397 Status
= gRT
->SetVariable (
398 VARNAME_LASTATTEMPTVERSION
,
400 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
401 sizeof (LastAttemptVersion
),
404 if (EFI_ERROR (Status
)) {
405 DEBUG ((DEBUG_ERROR
, "Failed to set the LastAttemptVersion into a variable. Status = %r\n", Status
));
408 DEBUG ((DEBUG_INFO
, "LastAttemptVersion variable doesn't need to update. Same value as before.\n"));
413 Locks all the UEFI Variables used by this module.
415 @retval EFI_SUCCESS All UEFI variables are locked.
416 @retval EFI_UNSUPPORTED Variable Lock Protocol not found.
417 @retval Other One of the UEFI variables could not be locked.
421 LockAllFmpVariables (
426 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
427 EFI_STATUS ReturnStatus
;
431 Status
= gBS
->LocateProtocol (
432 &gEdkiiVariableLockProtocolGuid
,
434 (VOID
**)&VariableLock
436 if (EFI_ERROR (Status
)) {
437 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to locate Variable Lock Protocol (%r).\n", Status
));
438 return EFI_UNSUPPORTED
;
441 ReturnStatus
= EFI_SUCCESS
;
442 for (Index
= 0; Index
< ARRAY_SIZE (mFmpVariableLockList
); Index
++) {
443 Status
= VariableLock
->RequestToLock (
445 (CHAR16
*)mFmpVariableLockList
[Index
],
448 if (EFI_ERROR (Status
)) {
449 DEBUG ((DEBUG_ERROR
, "FmpDxe: Failed to lock variable %g %s. Status = %r\n",
451 mFmpVariableLockList
[Index
],
454 if (!EFI_ERROR (ReturnStatus
)) {
455 ReturnStatus
= Status
;