mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
Persist the attempted version and failure status in one FmpState write before calling the device writer. Abort without touching firmware when a variable read or write fails, including a full variable store. TEST=FmpDevicePkg host unit tests (7 passed) TEST=RELEASE_GCC X64 FmpDxe build with SMMSTORE capsule support Signed-off-by: Sean Rhodes <sean@starlabs.systems>
266 lines
9.5 KiB
C
266 lines
9.5 KiB
C
/** @file
|
|
UEFI variable support functions for Firmware Management Protocol based
|
|
firmware updates.
|
|
|
|
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
|
|
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#pragma once
|
|
|
|
///
|
|
/// Default values for FMP Controller State information
|
|
///
|
|
#define DEFAULT_VERSION 0x1
|
|
#define DEFAULT_LOWESTSUPPORTEDVERSION 0x0
|
|
#define DEFAULT_LASTATTEMPTSTATUS 0x0
|
|
#define DEFAULT_LASTATTEMPTVERSION 0x0
|
|
|
|
///
|
|
/// Base UEFI Variable names for FMP Controller State information stored in
|
|
/// separate variables.
|
|
///
|
|
#define VARNAME_VERSION L"FmpVersion"
|
|
#define VARNAME_LSV L"FmpLsv"
|
|
#define VARNAME_LASTATTEMPTSTATUS L"LastAttemptStatus"
|
|
#define VARNAME_LASTATTEMPTVERSION L"LastAttemptVersion"
|
|
|
|
///
|
|
/// Base UEFI Variable name for FMP Controller State information stored in a
|
|
/// merged UEFI Variable. If the separate UEFI Variables above are detected,
|
|
/// then they are merged into a single variable and the separate variables are
|
|
/// deleted.
|
|
///
|
|
#define VARNAME_FMPSTATE L"FmpState"
|
|
|
|
///
|
|
/// FMP Controller State structure that is used to store the state of
|
|
/// a controller in one combined UEFI Variable.
|
|
///
|
|
typedef struct {
|
|
BOOLEAN VersionValid;
|
|
BOOLEAN LsvValid;
|
|
BOOLEAN LastAttemptStatusValid;
|
|
BOOLEAN LastAttemptVersionValid;
|
|
UINT32 Version;
|
|
UINT32 Lsv;
|
|
UINT32 LastAttemptStatus;
|
|
UINT32 LastAttemptVersion;
|
|
} FMP_CONTROLLER_STATE;
|
|
|
|
/**
|
|
Generate the names of the UEFI Variables used to store state information for
|
|
a managed controller. The UEFI Variables names are a combination of a base
|
|
name and an optional hardware instance value as a 16 character hex value. If
|
|
the hardware instance value is 0, then the 16 character hex value is not
|
|
included. These storage for the UEFI Variable names are allocated using the
|
|
UEFI Boot Service AllocatePool() and the pointers are stored in the Private.
|
|
The following are examples of variable names produces for hardware instance
|
|
value 0 and value 0x1234567812345678.
|
|
|
|
FmpVersion
|
|
FmpLsv
|
|
LastAttemptStatus
|
|
LastAttemptVersion
|
|
FmpDxe
|
|
|
|
FmpVersion1234567812345678
|
|
FmpLsv1234567812345678
|
|
LastAttemptStatus1234567812345678
|
|
LastAttemptVersion1234567812345678
|
|
FmpDxe1234567812345678
|
|
|
|
@param[in,out] Private Private context structure for the managed controller.
|
|
**/
|
|
VOID
|
|
GenerateFmpVariableNames (
|
|
IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
|
|
);
|
|
|
|
/**
|
|
Retrieve the FMP Controller State UEFI Variable value. Return NULL if
|
|
the variable does not exist or if the size of the UEFI Variable is not the
|
|
size of FMP_CONTROLLER_STATE. The buffer for the UEFI Variable value
|
|
is allocated using the UEFI Boot Service AllocatePool(). Caller must free
|
|
the returned buffer with FreePool().
|
|
|
|
@param[in] Private Private context structure for the managed controller.
|
|
|
|
@return Pointer to the allocated FMP Controller State. Returns NULL
|
|
if the variable does not exist or is a different size than expected.
|
|
**/
|
|
FMP_CONTROLLER_STATE *
|
|
GetFmpControllerState (
|
|
IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
|
|
);
|
|
|
|
/**
|
|
Returns the value used to fill in the Version field of the
|
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
|
service of the Firmware Management Protocol. The value is extracted from the
|
|
provided FmpControllerState. If FmpControllerState is NULL or the Version
|
|
field is not valid, then a default version value is returned.
|
|
|
|
@param[in] FmpControllerState The cached FMP Controller State, or NULL if the
|
|
state could not be retrieved.
|
|
|
|
@return The version of the firmware image in the firmware device.
|
|
**/
|
|
UINT32
|
|
GetVersionFromFmpControllerState (
|
|
IN FMP_CONTROLLER_STATE *FmpControllerState
|
|
);
|
|
|
|
/**
|
|
Returns the value used to fill in the LowestSupportedVersion field of the
|
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
|
service of the Firmware Management Protocol. The value is extracted from the
|
|
provided FmpControllerState. If FmpControllerState is NULL or the Lsv field
|
|
is not valid, then a default lowest supported version value is returned.
|
|
|
|
@param[in] FmpControllerState The cached FMP Controller State, or NULL if the
|
|
state could not be retrieved.
|
|
|
|
@return The lowest supported version of the firmware image in the firmware
|
|
device.
|
|
**/
|
|
UINT32
|
|
GetLowestSupportedVersionFromFmpControllerState (
|
|
IN FMP_CONTROLLER_STATE *FmpControllerState
|
|
);
|
|
|
|
/**
|
|
Returns the value used to fill in the LastAttemptStatus field of the
|
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
|
service of the Firmware Management Protocol. The value is extracted from the
|
|
provided FmpControllerState. If FmpControllerState is NULL or the
|
|
LastAttemptStatus field is not valid, then a default last attempt status value
|
|
is returned.
|
|
|
|
@param[in] FmpControllerState The cached FMP Controller State, or NULL if the
|
|
state could not be retrieved.
|
|
|
|
@return The last attempt status value for the most recent capsule update.
|
|
**/
|
|
UINT32
|
|
GetLastAttemptStatusFromFmpControllerState (
|
|
IN FMP_CONTROLLER_STATE *FmpControllerState
|
|
);
|
|
|
|
/**
|
|
Returns the value used to fill in the LastAttemptVersion field of the
|
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
|
service of the Firmware Management Protocol. The value is extracted from the
|
|
provided FmpControllerState. If FmpControllerState is NULL or the
|
|
LastAttemptVersion field is not valid, then a default last attempt version
|
|
value is returned.
|
|
|
|
@param[in] FmpControllerState The cached FMP Controller State, or NULL if the
|
|
state could not be retrieved.
|
|
|
|
@return The last attempt version value for the most recent capsule update.
|
|
**/
|
|
UINT32
|
|
GetLastAttemptVersionFromFmpControllerState (
|
|
IN FMP_CONTROLLER_STATE *FmpControllerState
|
|
);
|
|
|
|
/**
|
|
Saves the version current of the firmware image in the firmware device to a
|
|
UEFI variable.
|
|
|
|
UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
|
|
|
|
@param[in] Private Private context structure for the managed controller.
|
|
@param[in] Version The version of the firmware image in the firmware device.
|
|
**/
|
|
VOID
|
|
SetVersionInVariable (
|
|
IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
|
|
IN UINT32 Version
|
|
);
|
|
|
|
/**
|
|
Saves the lowest supported version current of the firmware image in the
|
|
firmware device to a UEFI variable.
|
|
|
|
UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
|
|
|
|
@param[in] Private Private context structure for the managed
|
|
controller.
|
|
@param[in] LowestSupportedVersion The lowest supported version of the
|
|
firmware image in the firmware device.
|
|
**/
|
|
VOID
|
|
SetLowestSupportedVersionInVariable (
|
|
IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
|
|
IN UINT32 LowestSupportedVersion
|
|
);
|
|
|
|
/**
|
|
Saves the last attempt status value of the most recent FMP capsule update to a
|
|
UEFI variable.
|
|
|
|
UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
|
|
|
|
@param[in] Private Private context structure for the managed
|
|
controller.
|
|
@param[in] LastAttemptStatus The last attempt status of the most recent FMP
|
|
capsule update.
|
|
**/
|
|
VOID
|
|
SetLastAttemptStatusInVariable (
|
|
IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
|
|
IN UINT32 LastAttemptStatus
|
|
);
|
|
|
|
/**
|
|
Saves the last attempt version value of the most recent FMP capsule update to
|
|
a UEFI variable.
|
|
|
|
UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"
|
|
|
|
@param[in] Private Private context structure for the managed
|
|
controller.
|
|
@param[in] LastAttemptVersion The last attempt version value of the most
|
|
recent FMP capsule update.
|
|
**/
|
|
VOID
|
|
SetLastAttemptVersionInVariable (
|
|
IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
|
|
IN UINT32 LastAttemptVersion
|
|
);
|
|
|
|
/**
|
|
Records a durable failure checkpoint immediately before device update starts.
|
|
|
|
@param[in] Private Private context structure for the managed
|
|
controller.
|
|
@param[in] LastAttemptVersion Version of the firmware update being attempted.
|
|
|
|
@retval EFI_SUCCESS The checkpoint is durable.
|
|
@retval Other The checkpoint could not be persisted.
|
|
**/
|
|
EFI_STATUS
|
|
SetUpdateInProgressInVariable (
|
|
IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,
|
|
IN UINT32 LastAttemptVersion
|
|
);
|
|
|
|
/**
|
|
Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently
|
|
executing module.
|
|
|
|
@param[in] Private Private context structure for the managed controller.
|
|
|
|
@retval EFI_SUCCESS All UEFI variables are locked.
|
|
@retval EFI_UNSUPPORTED Variable Lock Protocol not found.
|
|
@retval Other One of the UEFI variables could not be locked.
|
|
**/
|
|
EFI_STATUS
|
|
LockAllFmpVariables (
|
|
IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
|
|
);
|