/** @file
Copyright (c) 2024, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
- Platform Security Firmware Update for the A-profile Specification 1.0
(https://developer.arm.com/documentation/den0118/latest)
@par Glossary:
- FW - Firmware
- FWU - Firmware Update
- FWS - Firmware Storage
- PSA - Platform Security update for the A-profile specification
- IFD - Image File Data
- IF - Image File
- IMG - Image
- MM - Management Mode
- PROP - Property
- Bkup, Bkp - Backup
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "DiskGpt.h"
#include "FwsMetadata.h"
/**
Validate loaded Metadata version 2
@param [in] Metadata Firmware update storage metadata version 2.
@retval TRUE Valid.
@retval FALSE
**/
STATIC
BOOLEAN
EFIAPI
ValidateMetadataV2 (
IN PSA_MM_FWU_METADATA_V2 *Metadata
)
{
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
PSA_MM_FWU_IMAGE_PROPERTIES *ImageBankInfo;
UINT8 BankIdx;
UINT16 ImgIdx;
UINT32 Crc32;
UINT32 MetadataSize;
UINT32 ImageEntrySize;
if (Metadata->DescriptorOffset == 0x00) {
DEBUG ((
DEBUG_ERROR,
"%a: Metadata's DescriptorOffset shouldn't be zero...\n",
__func__
));
return FALSE;
}
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (Metadata);
if ((FwFwsDesc->NumBanks > FWU_METADATA_V2_MAX_NUM_BANKS) ||
(FwFwsDesc->NumBanks > FWU_NUMBER_OF_BANKS))
{
DEBUG ((
DEBUG_ERROR,
"%a: NumBanks should be <= %d... Current:%d.\n",
__func__,
MIN (FWU_NUMBER_OF_BANKS, FWU_METADATA_V2_MAX_NUM_BANKS),
FwFwsDesc->NumBanks
));
return FALSE;
}
if ((Metadata->Header.ActiveIndex >= FwFwsDesc->NumBanks) ||
(Metadata->Header.PreviousActiveIndex >= FwFwsDesc->NumBanks))
{
DEBUG ((
DEBUG_ERROR,
"%a: Active or Previous Index over bank count...\n",
__func__
));
return FALSE;
}
if (FwFwsDesc->BankInfoEntrySize != sizeof (PSA_MM_FWU_IMAGE_PROPERTIES)) {
DEBUG ((
DEBUG_ERROR,
"%a: BankInfoEntrySize should be %d... Current:%d.\n",
__func__,
sizeof (PSA_MM_FWU_IMAGE_PROPERTIES),
FwFwsDesc->BankInfoEntrySize
));
return FALSE;
}
ImageEntrySize = (FwFwsDesc->NumImages *
(sizeof (PSA_MM_FWU_IMAGE_ENTRY_V2) +
(FwFwsDesc->NumBanks * sizeof (PSA_MM_FWU_IMAGE_PROPERTIES))));
if (ImageEntrySize != FwFwsDesc->ImageEntrySize) {
DEBUG ((
DEBUG_ERROR,
"%a: ImageEntrySize should be %d... Current:%d.\n",
__func__,
ImageEntrySize,
FwFwsDesc->ImageEntrySize
));
return FALSE;
}
MetadataSize = sizeof (PSA_MM_FWU_METADATA_V2) +
sizeof (PSA_MM_FWU_FW_STORE_DESC_V2) + FwFwsDesc->ImageEntrySize;
if (MetadataSize != Metadata->MetadataSize) {
DEBUG ((
DEBUG_ERROR,
"%a: MetadataSize should be %d... Current:%d.\n",
__func__,
MetadataSize,
Metadata->MetadataSize
));
return FALSE;
}
for (BankIdx = 0; BankIdx < FwFwsDesc->NumBanks; BankIdx++) {
if ((Metadata->BankState[BankIdx] != FWU_BANK_STATE_VALID) &&
(Metadata->BankState[BankIdx] != FWU_BANK_STATE_ACCEPTED) &&
(Metadata->BankState[BankIdx] != FWU_BANK_STATE_INVALID))
{
DEBUG ((
DEBUG_ERROR,
"%a: BankState[%d] is Invalid: 0x%x...\n",
__func__,
BankIdx,
Metadata->BankState[BankIdx]
));
return FALSE;
}
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
ImageBankInfo = GET_FWU_IMAGE_BANK_INFO_V2 (ImageEntry, BankIdx);
if ((ImageBankInfo->Accepted == FWU_IMAGE_UNACCEPTED) &&
(Metadata->BankState[BankIdx] == FWU_BANK_STATE_ACCEPTED))
{
DEBUG ((
DEBUG_ERROR,
"%a: BankState[%d] should be VALID(0x%x) not ACCEPTED...\n",
__func__,
BankIdx,
FWU_BANK_STATE_VALID
));
return FALSE;
}
}
}
for (BankIdx = FwFwsDesc->NumBanks; BankIdx < FWU_METADATA_V2_MAX_NUM_BANKS; BankIdx++) {
if (Metadata->BankState[BankIdx] != FWU_BANK_STATE_INVALID) {
DEBUG ((
DEBUG_ERROR,
"%a: BankState[%d] should be Invalid...\n",
__func__
));
return FALSE;
}
}
Crc32 = CalculateCrc32 (
(VOID *)Metadata + sizeof (Metadata->Header.Crc32),
Metadata->MetadataSize - sizeof (Metadata->Header.Crc32)
);
if (Crc32 != Metadata->Header.Crc32) {
DEBUG ((
DEBUG_ERROR,
"%a: Crc32 value should be 0x%lx... Current:0x%lx.\n",
__func__,
Crc32,
Metadata->Header.Crc32
));
return FALSE;
}
return TRUE;
}
/**
Loaded Metadata version 2 from GPT partition.
@param [in] GptHandle Gpt partition handle.
@param [in] PartitionKey Key to find out gpt partition saving metadata.
@param [out] StartLba Start LBA of metadata gpt partition.
@param [out] Metadata Loaded metadata.
@retval EFI_SUCCESS
@retval Others Failed to read gpt partition.
**/
STATIC
EFI_STATUS
EFIAPI
GetMetadataV2 (
IN GPT_PARTITION_HANDLE *GptHandle,
IN VOID *PartitionKey,
OUT EFI_LBA *StartLba,
OUT PSA_MM_FWU_METADATA_V2 **Metadata
)
{
EFI_STATUS Status;
PSA_MM_FWU_METADATA_V2 *Meta;
PSA_MM_FWU_METADATA_V2 TmpHeader;
Meta = NULL;
/// Find out Metadata Partition.
Status = GptGetMatchedPartitionStats (
GptHandle,
MatchedMetaDataPartition,
PartitionKey,
StartLba,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Fail to get Metadata Partition LBA...\n", __func__));
goto ErrorHandler;
}
Status = GptReadPartition (
GptHandle,
(VOID *)&TmpHeader,
sizeof (PSA_MM_FWU_METADATA_V2),
0,
*StartLba
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Fail to read Tmp Header...\n", __func__));
goto ErrorHandler;
}
if (TmpHeader.Header.Version != FWS_METADATA_FORMAT_V2) {
Status = EFI_INVALID_PARAMETER;
DEBUG ((
DEBUG_ERROR,
"%a: Invalid Metadata Version: %d...\n",
__func__,
TmpHeader.Header.Version
));
goto ErrorHandler;
}
Meta = AllocateRuntimePool (TmpHeader.MetadataSize);
if (Meta == NULL) {
Status = EFI_OUT_OF_RESOURCES;
DEBUG ((DEBUG_ERROR, "%a: Out of Memory...\n", __func__));
goto ErrorHandler;
}
Status = GptReadPartition (
GptHandle,
(VOID *)Meta,
TmpHeader.MetadataSize,
0,
*StartLba
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Fail to read Metadata Header...\n", __func__));
goto ErrorHandler;
}
*Metadata = Meta;
return EFI_SUCCESS;
ErrorHandler:
if (Meta != NULL) {
FreePool (Meta);
}
*StartLba = 0;
return Status;
}
/**
Initialize and Load Firmware Update Store Metadata version 2.
@param [in] GptHandle GptHandle
@param [out] FwsMetadata Firmware Update Store Metadata.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
@retval EFI_OUT_OF_RESOURCES
@retval EFI_ABORTED Metadata is invalid.
@retval Others Failed to get metadata from gpt partition.
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2Init (
IN GPT_PARTITION_HANDLE *GptHandle,
OUT FWS_METADATA **FwsMetadata
)
{
EFI_STATUS Status;
FWS_METADATA *FwsMeta;
EFI_LBA ActiveLba;
EFI_LBA BackupLba;
PSA_MM_FWU_METADATA_V2 *ActiveMeta;
PSA_MM_FWU_METADATA_V2 *BackupMeta;
BOOLEAN IsActiveValid;
BOOLEAN IsBackupValid;
ActiveMeta = NULL;
BackupMeta = NULL;
Status = GetMetadataV2 (
GptHandle,
(VOID *)FWU_METADATA_PARTITION_NAME,
&ActiveLba,
&ActiveMeta
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"%a: Fail to get Active Metadata: %r\n",
__func__,
Status
));
goto ErrorHandler;
}
Status = GetMetadataV2 (
GptHandle,
(VOID *)FWU_BKUP_METADATA_PARTITION_NAME,
&BackupLba,
&BackupMeta
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"%a: Fail to get Backup Metadata: %r\n",
__func__,
Status
));
goto ErrorHandler;
}
IsActiveValid = ValidateMetadataV2 (ActiveMeta);
IsBackupValid = ValidateMetadataV2 (BackupMeta);
if (!IsActiveValid && !IsBackupValid) {
Status = EFI_ABORTED;
DEBUG ((
DEBUG_ERROR,
"%a: Both of metadata are invalid. Error!\n",
__func__,
Status
));
goto ErrorHandler;
}
if (!IsActiveValid) {
Status = GptWritePartition (
GptHandle,
(VOID *)BackupMeta,
BackupMeta->MetadataSize,
0,
ActiveLba
);
FreePool (ActiveMeta);
ActiveMeta = BackupMeta;
BackupMeta = NULL;
} else {
if (!IsBackupValid) {
Status = GptWritePartition (
GptHandle,
(VOID *)ActiveMeta,
ActiveMeta->MetadataSize,
0,
BackupLba
);
}
FreePool (BackupMeta);
BackupMeta = NULL;
}
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
"%a: Fail to overwrite metadata from %a to %a failure(%r)..!\n",
__func__,
(!IsActiveValid) ? "Backup" : "Active",
(!IsActiveValid) ? "Active" : "Backup",
Status
));
goto ErrorHandler;
}
FwsMeta = AllocateRuntimePool (sizeof (FWS_METADATA));
if (FwsMeta == NULL) {
DEBUG ((DEBUG_ERROR, "%a: Out of memory...\n", __func__));
goto ErrorHandler;
}
FwsMeta->GptHandle = GptHandle;
FwsMeta->ActiveLba = ActiveLba;
FwsMeta->BackupLba = BackupLba;
FwsMeta->Metadata = (VOID *)ActiveMeta;
FwsMeta->MetadataSize = ActiveMeta->MetadataSize;
FwsMeta->FwsMetadataOps = &gFwsMetadataV2Ops;
*FwsMetadata = FwsMeta;
return EFI_SUCCESS;
ErrorHandler:
if (BackupMeta != NULL) {
FreePool (BackupMeta);
}
if (ActiveMeta != NULL) {
FreePool (ActiveMeta);
}
return Status;
}
/**
Cleanup Loaded Firmware Update Store Metadata version 2.
@param [in] FwsMetadata Firmware Update Store Metadata.
**/
STATIC
VOID
EFIAPI
FwsMetadataV2Exit (
IN FWS_METADATA *FwsMetadata
)
{
if (FwsMetadata != NULL) {
if (FwsMetadata->Metadata != NULL) {
FreePool (FwsMetadata->Metadata);
}
FreePool (FwsMetadata);
}
}
/**
Get the number of banks.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [out] NumBanks Number of banks.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2GetNumBanks (
IN FWS_METADATA *FwsMetadata,
OUT UINT8 *NumBanks
)
{
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (FwsMetadata->Metadata);
*NumBanks = FwFwsDesc->NumBanks;
return EFI_SUCCESS;
}
/**
Get the number of images per bank.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [out] NumImages Number of images per bank.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2GetNumImages (
IN FWS_METADATA *FwsMetadata,
OUT UINT16 *NumImages
)
{
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (FwsMetadata->Metadata);
*NumImages = FwFwsDesc->NumImages;
return EFI_SUCCESS;
}
/**
Check trial state.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [out] TrialRunState If true, current is in the trial state.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2CheckTrialRunState (
IN FWS_METADATA *FwsMetadata,
OUT BOOLEAN *TrialRunState
)
{
PSA_MM_FWU_METADATA_V2 *Metadata;
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
UINT8 BankIdx;
Metadata = (PSA_MM_FWU_METADATA_V2 *)FwsMetadata->Metadata;
BankIdx = Metadata->Header.ActiveIndex;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (Metadata);
if (Metadata->BankState[BankIdx] == FWU_BANK_STATE_VALID) {
*TrialRunState = TRUE;
} else {
*TrialRunState = FALSE;
}
return EFI_SUCCESS;
}
/**
Get all image type guids.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [out] ImageTypeGuids Image type guid array.
@param [in,out] Size Byte size of @ImageTypeGuids.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
@retval EFI_BUFFER_TOO_SMALL Size of @ImageTypeGuids is too small to
contain all image type guids manged by
firmware update store.
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2GetImageTypeGuids (
IN FWS_METADATA *FwsMetadata,
OUT EFI_GUID *ImageTypeGuids,
IN OUT UINT32 *Size
)
{
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
UINT16 ImgIdx;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (FwsMetadata->Metadata);
if (*Size < (FwFwsDesc->NumImages * sizeof (EFI_GUID))) {
*Size = FwFwsDesc->NumImages * sizeof (EFI_GUID);
DEBUG ((DEBUG_ERROR, "%a: Buffer is too small...\n", __func__));
return EFI_BUFFER_TOO_SMALL;
}
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
CopyGuid (&ImageTypeGuids[ImgIdx], &ImageEntry->Header.ImageTypeGuid);
}
return EFI_SUCCESS;
}
/**
Get location guid of image type guid.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [in] ImageTypeGuid Image type guid.
@param [out] LocationGuid Location Guids.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2GetLocationGuid (
IN FWS_METADATA *FwsMetadata,
IN CONST EFI_GUID *ImageTypeGuid,
OUT EFI_GUID *LocationGuid
)
{
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
UINT16 ImgIdx;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (FwsMetadata->Metadata);
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
if (CompareGuid (&ImageEntry->Header.ImageTypeGuid, ImageTypeGuid)) {
CopyGuid (LocationGuid, &ImageEntry->Header.LocationGuid);
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/**
Get image guid of image type guid.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [in] ImageTypeGuid Image type guid.
@param [in] BankIdx Bank Index.
@param [out] ImageGuid Image Guids.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2GetImageGuid (
IN FWS_METADATA *FwsMetadata,
IN CONST EFI_GUID *ImageTypeGuid,
IN UINT32 BankIdx,
OUT EFI_GUID *ImageGuid
)
{
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
PSA_MM_FWU_IMAGE_PROPERTIES *ImageBankInfo;
UINT16 ImgIdx;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (FwsMetadata->Metadata);
if (BankIdx >= FwFwsDesc->NumBanks) {
DEBUG ((DEBUG_ERROR, "%a: Invalid arguments...\n", __func__));
return EFI_INVALID_PARAMETER;
}
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
if (CompareGuid (&ImageEntry->Header.ImageTypeGuid, ImageTypeGuid)) {
ImageBankInfo = GET_FWU_IMAGE_BANK_INFO_V2 (ImageEntry, BankIdx);
CopyGuid (ImageGuid, &ImageBankInfo->ImageGuid);
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/**
Get accept state of image type guid.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [in] ImageTypeGuid Image type guid.
@param [in] BankIdx Bank Index
@param [out] AcceptState If true, @ImageTypeGuid in the @BankIdx
is accepted.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2GetAcceptState (
IN FWS_METADATA *FwsMetadata,
IN CONST EFI_GUID *ImageTypeGuid,
IN UINT32 BankIdx,
OUT BOOLEAN *AcceptState
)
{
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
PSA_MM_FWU_IMAGE_PROPERTIES *ImageBankInfo;
UINT16 ImgIdx;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (FwsMetadata->Metadata);
if (BankIdx >= FwFwsDesc->NumBanks) {
DEBUG ((DEBUG_ERROR, "%a: Invalid arguments...\n", __func__));
return EFI_INVALID_PARAMETER;
}
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
if (!CompareGuid (&ImageEntry->Header.ImageTypeGuid, ImageTypeGuid)) {
continue;
}
ImageBankInfo = GET_FWU_IMAGE_BANK_INFO_V2 (ImageEntry, BankIdx);
if (ImageBankInfo->Accepted == FWU_IMAGE_ACCEPTED) {
*AcceptState = TRUE;
} else {
*AcceptState = FALSE;
}
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
/**
Set accept state of image type guid.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [in] ImageTypeGuid Image type guid.
@param [in] BankIdx Bank Index
@param [in] AcceptReq Type of request.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2SetAcceptState (
IN FWS_METADATA *FwsMetadata,
IN CONST EFI_GUID *ImageTypeGuid,
IN UINT32 BankIdx,
IN FWS_ACCEPT_REQ AcceptReq
)
{
PSA_MM_FWU_METADATA_V2 *Metadata;
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
PSA_MM_FWU_IMAGE_PROPERTIES *ImageBankInfo;
UINT16 ImgIdx;
Metadata = (PSA_MM_FWU_METADATA_V2 *)FwsMetadata->Metadata;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (Metadata);
if (BankIdx >= FwFwsDesc->NumBanks) {
DEBUG ((DEBUG_ERROR, "%a: Invalid arguments...\n", __func__));
return EFI_INVALID_PARAMETER;
}
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
if (!CompareGuid (&ImageEntry->Header.ImageTypeGuid, ImageTypeGuid)) {
continue;
}
ImageBankInfo = GET_FWU_IMAGE_BANK_INFO_V2 (ImageEntry, BankIdx);
if (AcceptReq == FwsImageAcceptReq) {
ImageBankInfo->Accepted = FWU_IMAGE_ACCEPTED;
} else {
ImageBankInfo->Accepted = FWU_IMAGE_UNACCEPTED;
if (AcceptReq == FwsImageWriteUnAcceptReq) {
Metadata->BankState[BankIdx] = FWU_BANK_STATE_INVALID;
}
}
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
/**
Update bank state.
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [in] BankIdx Bank Index
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2UpdateBankState (
IN FWS_METADATA *FwsMetadata,
IN UINT32 BankIdx
)
{
PSA_MM_FWU_METADATA_V2 *Metadata;
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
PSA_MM_FWU_IMAGE_PROPERTIES *ImageBankInfo;
UINT16 ImgIdx;
UINT8 BankState;
Metadata = (PSA_MM_FWU_METADATA_V2 *)FwsMetadata->Metadata;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (Metadata);
if (BankIdx >= FwFwsDesc->NumBanks) {
DEBUG ((DEBUG_ERROR, "%a: Invalid arguments...\n", __func__));
return EFI_INVALID_PARAMETER;
}
BankState = FWU_BANK_STATE_ACCEPTED;
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
ImageBankInfo = GET_FWU_IMAGE_BANK_INFO_V2 (ImageEntry, BankIdx);
if (ImageBankInfo->Accepted != FWU_IMAGE_ACCEPTED) {
BankState = FWU_BANK_STATE_VALID;
break;
}
}
Metadata->BankState[BankIdx] = BankState;
return EFI_SUCCESS;
}
/**
Rollback metadata from @BackupIdx's one to @@TargetIdx's one
@param [in] FwsMetadata Firmware Update Store Metadata.
@param [in] BackupIdx Backup Bank Index
@param [in] TargetIdx Target Bank Index
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
**/
STATIC
EFI_STATUS
EFIAPI
FwsMetadataV2RollBack (
IN FWS_METADATA *FwsMetadata,
IN UINT32 BackupIdx,
IN UINT32 TargetIdx
)
{
PSA_MM_FWU_METADATA_V2 *Metadata;
PSA_MM_FWU_FW_STORE_DESC_V2 *FwFwsDesc;
PSA_MM_FWU_IMAGE_ENTRY_V2 *ImageEntry;
PSA_MM_FWU_IMAGE_PROPERTIES *BkpImageBankInfo;
PSA_MM_FWU_IMAGE_PROPERTIES *TgtImageBankInfo;
UINT16 ImgIdx;
Metadata = (PSA_MM_FWU_METADATA_V2 *)FwsMetadata->Metadata;
FwFwsDesc = GET_FWU_FW_STORE_DESC_V2 (Metadata);
if ((BackupIdx >= FwFwsDesc->NumBanks) ||
(TargetIdx >= FwFwsDesc->NumBanks))
{
DEBUG ((DEBUG_ERROR, "%a: Invalid arguments...\n", __func__));
return EFI_INVALID_PARAMETER;
}
if (Metadata->BankState[BackupIdx] != FWU_BANK_STATE_ACCEPTED) {
DEBUG ((
DEBUG_ERROR,
"%a: Backup Bank(%d) State(0x%x) isn't accepted state\n",
__func__,
BackupIdx,
Metadata->BankState[BackupIdx]
));
return EFI_INVALID_PARAMETER;
}
for (ImgIdx = 0; ImgIdx < FwFwsDesc->NumImages; ImgIdx++) {
ImageEntry = GET_FWU_IMAGE_ENTRY_V2 (FwFwsDesc, ImgIdx);
BkpImageBankInfo = GET_FWU_IMAGE_BANK_INFO_V2 (ImageEntry, BackupIdx);
TgtImageBankInfo = GET_FWU_IMAGE_BANK_INFO_V2 (ImageEntry, TargetIdx);
CopyMem (TgtImageBankInfo, BkpImageBankInfo, sizeof (PSA_MM_FWU_IMAGE_PROPERTIES));
}
Metadata->BankState[TargetIdx] = Metadata->BankState[BackupIdx];
return EFI_SUCCESS;
}
FWS_METADATA_OPS gFwsMetadataV2Ops = {
FwsMetadataV2Init,
FwsMetadataV2Exit,
FwsMetadataV2GetNumBanks,
FwsMetadataV2GetNumImages,
FwsMetadataV2CheckTrialRunState,
FwsMetadataV2GetImageTypeGuids,
FwsMetadataV2GetLocationGuid,
FwsMetadataV2GetImageGuid,
FwsMetadataV2GetAcceptState,
FwsMetadataV2SetAcceptState,
FwsMetadataV2UpdateBankState,
FwsMetadataV2RollBack,
};