aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/edk2/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/edk2/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c')
-rw-r--r--roms/edk2/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c475
1 files changed, 475 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c b/roms/edk2/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
new file mode 100644
index 000000000..fff17b98f
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
@@ -0,0 +1,475 @@
+/** @file
+ Esrt management implementation.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "EsrtImpl.h"
+
+/**
+ Find Esrt Entry stored in ESRT repository.
+
+ @param[in] FwClass Firmware class guid in Esrt entry
+ @param[in] Attribute Esrt from Non FMP or FMP instance
+ @param[out] Entry Esrt entry returned
+
+ @retval EFI_SUCCESS Successfully find an Esrt entry
+ @retval EF_NOT_FOUND No Esrt entry found
+
+**/
+EFI_STATUS
+GetEsrtEntry (
+ IN EFI_GUID *FwClass,
+ IN UINTN Attribute,
+ OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *VariableName;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;
+ UINTN RepositorySize;
+ UINTN Index;
+ UINTN EsrtNum;
+
+ EsrtRepository = NULL;
+
+ //
+ // Get Esrt index buffer
+ //
+ if (Attribute == ESRT_FROM_FMP) {
+ VariableName = EFI_ESRT_FMP_VARIABLE_NAME;
+ } else {
+ VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;
+ }
+
+ Status = GetVariable2 (
+ VariableName,
+ &gEfiCallerIdGuid,
+ (VOID **) &EsrtRepository,
+ &RepositorySize
+ );
+
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+
+ if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
+ DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));
+ Status = EFI_ABORTED;
+ goto EXIT;
+ }
+
+ Status = EFI_NOT_FOUND;
+ EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);
+ for (Index = 0; Index < EsrtNum; Index++) {
+ if (CompareGuid(FwClass, &EsrtRepository[Index].FwClass)) {
+ CopyMem(Entry, &EsrtRepository[Index], sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+
+EXIT:
+ if (EsrtRepository != NULL) {
+ FreePool(EsrtRepository);
+ }
+
+ return Status;
+}
+
+/**
+ Insert a new ESRT entry into ESRT Cache repository.
+
+ @param[in] Entry Esrt entry to be set
+ @param[in] Attribute Esrt from Esrt private protocol or FMP instance
+
+ @retval EFI_SUCCESS Successfully set a variable.
+
+**/
+EFI_STATUS
+InsertEsrtEntry(
+ IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,
+ UINTN Attribute
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *VariableName;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;
+ UINTN RepositorySize;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepositoryNew;
+
+ EsrtRepository = NULL;
+ EsrtRepositoryNew = NULL;
+
+ //
+ // Get Esrt index buffer
+ //
+ if (Attribute == ESRT_FROM_FMP) {
+ VariableName = EFI_ESRT_FMP_VARIABLE_NAME;
+ } else {
+ VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;
+ }
+
+ Status = GetVariable2 (
+ VariableName,
+ &gEfiCallerIdGuid,
+ (VOID **) &EsrtRepository,
+ &RepositorySize
+ );
+
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // If not exist, create new Esrt cache repository
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(EFI_SYSTEM_RESOURCE_ENTRY),
+ Entry
+ );
+ return Status;
+
+ } else if (Status == EFI_SUCCESS) {
+ //
+ // if exist, update Esrt cache repository
+ //
+ if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
+ DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));
+ //
+ // Repository is corrupt. Clear Repository before insert new entry
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ EsrtRepository
+ );
+ FreePool(EsrtRepository);
+ RepositorySize = 0;
+ EsrtRepository = NULL;
+ }
+
+ //
+ // Check Repository size constraint
+ //
+ if ((Attribute == ESRT_FROM_FMP && RepositorySize >= PcdGet32(PcdMaxFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY))
+ ||(Attribute == ESRT_FROM_NONFMP && RepositorySize >= PcdGet32(PcdMaxNonFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) ) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ EsrtRepositoryNew = AllocatePool(RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
+ if (EsrtRepositoryNew == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ if (RepositorySize != 0 && EsrtRepository != NULL) {
+ CopyMem(EsrtRepositoryNew, EsrtRepository, RepositorySize);
+ }
+ CopyMem((UINT8 *)EsrtRepositoryNew + RepositorySize, Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
+
+ Status = gRT->SetVariable(
+ VariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY),
+ EsrtRepositoryNew
+ );
+ }
+
+EXIT:
+ if (EsrtRepository != NULL) {
+ FreePool(EsrtRepository);
+ }
+
+ if (EsrtRepositoryNew != NULL) {
+ FreePool(EsrtRepositoryNew);
+ }
+
+ return Status;
+}
+
+/**
+ Delete ESRT Entry from ESRT repository.
+
+ @param[in] FwClass FwClass of Esrt entry to delete
+ @param[in] Attribute Esrt from Esrt private protocol or FMP instance
+
+ @retval EFI_SUCCESS Insert all entries Successfully
+ @retval EFI_NOT_FOUND ESRT entry with FwClass doesn't exsit
+
+**/
+EFI_STATUS
+DeleteEsrtEntry(
+ IN EFI_GUID *FwClass,
+ IN UINTN Attribute
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *VariableName;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;
+ UINTN RepositorySize;
+ UINTN Index;
+ UINTN EsrtNum;
+
+ EsrtRepository = NULL;
+
+ //
+ // Get Esrt index buffer
+ //
+ if (Attribute == ESRT_FROM_FMP) {
+ VariableName = EFI_ESRT_FMP_VARIABLE_NAME;
+ } else {
+ VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;
+ }
+
+ Status = GetVariable2 (
+ VariableName,
+ &gEfiCallerIdGuid,
+ (VOID **) &EsrtRepository,
+ &RepositorySize
+ );
+
+ if (EFI_ERROR(Status)) {
+ goto EXIT;
+ }
+
+ if (EsrtRepository == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ if ((RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) != 0) {
+ DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));
+ //
+ // Repository is corrupt. Clear Repository before insert new entry
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ EsrtRepository
+ );
+ goto EXIT;
+ }
+
+ Status = EFI_NOT_FOUND;
+ EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);
+ for (Index = 0; Index < EsrtNum; Index++) {
+ //
+ // Delete Esrt entry if it is found in repository
+ //
+ if (CompareGuid(FwClass, &EsrtRepository[Index].FwClass)) {
+ //
+ // If delete Esrt entry is not at the rail
+ //
+ if (Index < EsrtNum - 1) {
+ CopyMem(&EsrtRepository[Index], &EsrtRepository[Index + 1], (EsrtNum - Index - 1) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
+ }
+
+ //
+ // Update New Repository
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ (EsrtNum - 1) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY),
+ EsrtRepository
+ );
+ break;
+ }
+ }
+
+EXIT:
+ if (EsrtRepository != NULL) {
+ FreePool(EsrtRepository);
+ }
+
+ return Status;
+
+}
+
+/**
+ Update one ESRT entry in ESRT repository
+
+ @param[in] Entry Esrt entry to be set
+ @param[in] Attribute Esrt from Non Esrt or FMP instance
+
+ @retval EFI_SUCCESS Successfully Update a variable.
+ @retval EFI_NOT_FOUND The Esrt enry doesn't exist
+
+**/
+EFI_STATUS
+UpdateEsrtEntry(
+ IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,
+ UINTN Attribute
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *VariableName;
+ EFI_SYSTEM_RESOURCE_ENTRY *EsrtRepository;
+ UINTN RepositorySize;
+ UINTN Index;
+ UINTN EsrtNum;
+
+ EsrtRepository = NULL;
+
+ //
+ // Get Esrt index buffer
+ //
+ if (Attribute == ESRT_FROM_FMP) {
+ VariableName = EFI_ESRT_FMP_VARIABLE_NAME;
+ } else {
+ VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;
+ }
+
+ Status = GetVariable2 (
+ VariableName,
+ &gEfiCallerIdGuid,
+ (VOID **) &EsrtRepository,
+ &RepositorySize
+ );
+
+ if (EsrtRepository == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // if exist, update Esrt cache repository
+ //
+ if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
+ DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));
+ //
+ // Repository is corrupt. Clear Repository before insert new entry
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ EsrtRepository
+ );
+ Status = EFI_NOT_FOUND;
+ goto EXIT;
+ }
+
+ Status = EFI_NOT_FOUND;
+ EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);
+ for (Index = 0; Index < EsrtNum; Index++) {
+ //
+ // Update Esrt entry if it is found in repository
+ //
+ if (CompareGuid(&Entry->FwClass, &EsrtRepository[Index].FwClass)) {
+
+ CopyMem(&EsrtRepository[Index], Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
+ //
+ // Update New Repository
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ RepositorySize,
+ EsrtRepository
+ );
+ break;
+ }
+ }
+ }
+
+EXIT:
+ if (EsrtRepository != NULL) {
+ FreePool(EsrtRepository);
+ }
+
+ return Status;
+}
+
+/**
+ Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+ @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
+
+ @return TRUE It is a system FMP.
+ @return FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmp (
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo
+ )
+{
+ GUID *Guid;
+ UINTN Count;
+ UINTN Index;
+
+ Guid = PcdGetPtr(PcdSystemFmpCapsuleImageTypeIdGuid);
+ Count = PcdGetSize(PcdSystemFmpCapsuleImageTypeIdGuid)/sizeof(GUID);
+
+ for (Index = 0; Index < Count; Index++, Guid++) {
+ if (CompareGuid(&FmpImageInfo->ImageTypeId, Guid)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .
+
+ @param[in, out] EsrtEntry Esrt entry to be Init
+ @param[in] FmpImageInfo FMP image info descriptor
+ @param[in] DescriptorVersion FMP Image info descriptor version
+
+**/
+VOID
+SetEsrtEntryFromFmpInfo (
+ IN OUT EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry,
+ IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo,
+ IN UINT32 DescriptorVersion
+ )
+{
+ EsrtEntry->FwVersion = FmpImageInfo->Version;
+ EsrtEntry->FwClass = FmpImageInfo->ImageTypeId;
+ if (IsSystemFmp(FmpImageInfo)) {
+ EsrtEntry->FwType = ESRT_FW_TYPE_SYSTEMFIRMWARE;
+ } else {
+ EsrtEntry->FwType = ESRT_FW_TYPE_DEVICEFIRMWARE;
+ }
+ EsrtEntry->LowestSupportedFwVersion = 0;
+ EsrtEntry->CapsuleFlags = 0;
+ EsrtEntry->LastAttemptVersion = 0;
+ EsrtEntry->LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+
+ if (DescriptorVersion >= 2) {
+ //
+ // LowestSupportedImageVersion only available in FMP V2 or higher
+ //
+ EsrtEntry->LowestSupportedFwVersion = FmpImageInfo->LowestSupportedImageVersion;
+ }
+
+ if (DescriptorVersion >= 3) {
+ //
+ // LastAttemptVersion & LastAttemptStatus only available in FMP V3 or higher
+ //
+ EsrtEntry->LastAttemptVersion = FmpImageInfo->LastAttemptVersion;
+ EsrtEntry->LastAttemptStatus = FmpImageInfo->LastAttemptStatus;
+ }
+
+ //
+ // Set capsule customized flag
+ //
+ if ((FmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0
+ && (FmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) {
+ EsrtEntry->CapsuleFlags = PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag);
+ }
+}