Update to follow Tiano Coding style. Fix potential NULL memory copy Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chao Zhang <chao.b.zhang@intel.com> Reviewed-by: Qiu Shumin <shumin.qiu@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17474 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			439 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			439 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Esrt management implementation.
 | |
| 
 | |
| Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #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 ((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 (!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;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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;
 | |
|   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);
 | |
|   }
 | |
| }
 |