It provides a repository to cache ESRT info for FMP or Non-FMP instance.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chao Zhang <chao.b.zh...@intel.com>
---
 MdeModulePkg/MdeModulePkg.dsc                   |   1 +
 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c        | 652 ++++++++++++++++++++++++
 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf      |  70 +++
 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni      | Bin 0 -> 2510 bytes
 MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni | Bin 0 -> 1314 bytes
 MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c       | 438 ++++++++++++++++
 MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h       | 245 +++++++++
 7 files changed, 1406 insertions(+)
 create mode 100644 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c
 create mode 100644 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
 create mode 100644 MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni
 create mode 100644 MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni
 create mode 100644 MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
 create mode 100644 MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h

diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 16a6eb5..d0832bc 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -354,6 +354,7 @@
   }
 
   MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
 
 [Components.IA32, Components.X64, Components.IPF]  
   MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c 
b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c
new file mode 100644
index 0000000..8f76cea
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c
@@ -0,0 +1,652 @@
+/** @file
+  Esrt management module.
+
+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"
+
+
+//
+// Module globals.
+//
+
+ESRT_PRIVATE_DATA mPrivate;
+
+ESRT_MANAGEMENT_PROTOCOL  mEsrtManagementProtocolTemplate = { 
+                            EsrtDxeGetEsrtEntry,
+                            EsrtDxeUpdateEsrtEntry,
+                            EsrtDxeRegisterEsrtEntry,
+                            EsrtDxeUnRegisterEsrtEntry,
+                            EsrtDxeSyncFmp,
+                            EsrtDxeLockEsrtRepository
+                            };
+
+/**
+  Get ESRT entry from ESRT Cache by FwClass Guid 
+
+  @param[in]       FwClass                FwClass of Esrt entry to get  
+  @param[in out]  Entry                   Esrt entry returned 
+  
+  @retval EFI_SUCCESS                   The variable saving this Esrt Entry 
exists.
+  @retval EF_NOT_FOUND                  No correct variable found.
+  @retval EFI_WRITE_PROTECTED           ESRT Cache repository is locked
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeGetEsrtEntry(
+  IN     EFI_GUID                  *FwClass,
+  IN OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry
+  )
+{
+  EFI_STATUS                Status;
+
+  if (FwClass == NULL || Entry == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Find in Non-FMP Cached Esrt Repository
+  //
+  Status = GetEsrtEntry(
+             FwClass,
+             ESRT_FROM_NONFMP,
+             Entry
+             );
+
+  EfiReleaseLock(&mPrivate.NonFmpLock);
+
+  if (EFI_ERROR(Status)) {
+    Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Find in FMP Cached Esrt NV Variable
+    //
+    Status = GetEsrtEntry(
+               FwClass,
+               ESRT_FROM_FMP,
+               Entry
+               );
+
+    EfiReleaseLock(&mPrivate.FmpLock);
+  }
+
+  return Status;
+}
+
+/**
+  Update one ESRT entry in ESRT Cache.
+
+  @param[in]  Entry                         Esrt entry to be updated
+  
+  @retval EFI_SUCCESS                   Successfully update an ESRT entry in 
cache.
+  @retval EFI_INVALID_PARAMETER         Entry does't exist in ESRT Cache
+  @retval EFI_WRITE_PROTECTED           ESRT Cache repositoy is locked
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeUpdateEsrtEntry(
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry
+  )
+{
+  EFI_STATUS                Status;
+  
+  if (Entry == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = UpdateEsrtEntry(Entry, ESRT_FROM_FMP);
+
+  if (!EFI_ERROR(Status)) {
+    EfiReleaseLock(&mPrivate.FmpLock);
+    return Status;
+  }
+  EfiReleaseLock(&mPrivate.FmpLock);
+
+
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = UpdateEsrtEntry(Entry, ESRT_FROM_NONFMP);
+
+  EfiReleaseLock(&mPrivate.NonFmpLock);
+
+  return Status;
+}
+
+/**
+  Non-FMP instance to unregister Esrt Entry from ESRT Cache. 
+
+  @param[in]    FwClass                FwClass of Esrt entry to Unregister  
+  
+  @retval EFI_SUCCESS             Insert all entries Successfully 
+  @retval EFI_NOT_FOUND           Entry of FwClass does not exsit
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeUnRegisterEsrtEntry(
+  IN  EFI_GUID        *FwClass
+  )
+{
+  EFI_STATUS Status; 
+
+  if (FwClass == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = DeleteEsrtEntry(FwClass, ESRT_FROM_NONFMP);
+
+  EfiReleaseLock(&mPrivate.NonFmpLock);
+
+  return Status;
+}
+
+/**
+  Non-FMP instance to register one ESRT entry into ESRT Cache.
+
+  @param[in]  Entry                Esrt entry to be set
+
+  @retval EFI_SUCCESS              Successfully set a variable.
+  @retval EFI_INVALID_PARAMETER    ESRT Entry is already exist
+  @retval EFI_OUT_OF_RESOURCES     Non-FMP ESRT repository is full
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeRegisterEsrtEntry(
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry
+  )
+{
+  EFI_STATUS                Status;
+  EFI_SYSTEM_RESOURCE_ENTRY EsrtEntryTmp;
+
+  if (Entry == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = GetEsrtEntry(
+             &Entry->FwClass,
+             ESRT_FROM_NONFMP,
+             &EsrtEntryTmp
+             );
+
+  if (Status == EFI_NOT_FOUND) {
+    Status = InsertEsrtEntry(Entry, ESRT_FROM_NONFMP);
+  }
+
+  EfiReleaseLock(&mPrivate.NonFmpLock);
+
+  return Status;
+}
+
+/**
+  This function syn up Cached ESRT with data from FMP instances
+  Function should be called after Connect All in order to locate all FMP 
protocols
+  installed
+
+  @retval EFI_SUCCESS                      Successfully sync cache repository 
from FMP instances
+  @retval EFI_NOT_FOUND                   No FMP Instance are found
+  @retval EFI_OUT_OF_RESOURCES     Resource allocaton fail
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeSyncFmp(
+  VOID
+  ) 
+{
+  EFI_STATUS                                Status;
+  UINTN                                     Index1;
+  UINTN                                     Index2;
+  UINTN                                     Index3;
+  EFI_HANDLE                                *HandleBuffer;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL          **FmpBuf;
+  UINTN                                     NumberOfHandles;
+  UINTN                                     *DescriptorSizeBuf;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR             **FmpImageInfoBuf;  
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR             *TempFmpImageInfo;  
+  UINT8                                     *FmpImageInfoCountBuf;
+  UINT32                                    *FmpImageInfoDescriptorVerBuf;
+  UINTN                                     ImageInfoSize;
+  UINT32                                    PackageVersion;
+  CHAR16                                    *PackageVersionName;
+  EFI_SYSTEM_RESOURCE_ENTRY                 *EsrtRepositoryNew;
+  UINTN                                     EntryNumNew;
+
+  NumberOfHandles              = 0;
+  EntryNumNew                  = 0;
+  FmpBuf                       = NULL;
+  HandleBuffer                 = NULL;
+  FmpImageInfoBuf              = NULL;
+  FmpImageInfoCountBuf         = NULL;
+  PackageVersionName           = NULL;
+  DescriptorSizeBuf            = NULL;
+  FmpImageInfoDescriptorVerBuf = NULL;
+  EsrtRepositoryNew            = NULL;
+
+  //
+  // Get image information from all FMP protocol
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareManagementProtocolGuid,
+                  NULL,
+                  &NumberOfHandles,
+                  &HandleBuffer
+                  );
+
+ 
+  if (Status == EFI_NOT_FOUND) { 
+    EntryNumNew = 0;
+    goto UPDATE_REPOSITORY;
+  } else if (EFI_ERROR(Status)){ 
+    goto END;
+  }
+
+  //
+  // Allocate buffer to hold new FMP ESRT Cache repository
+  //
+  EsrtRepositoryNew = AllocateZeroPool(PcdGet32(PcdMaxFmpEsrtCacheNum) * 
sizeof(EFI_SYSTEM_RESOURCE_ENTRY));
+  if (EsrtRepositoryNew == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto END;
+  }
+
+  FmpBuf = AllocatePool(sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL *) * 
NumberOfHandles);
+  if (FmpBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto END;
+  }
+
+  FmpImageInfoBuf = AllocateZeroPool(sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * 
NumberOfHandles);
+  if (FmpImageInfoBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;    
+    goto END;
+  }
+
+  FmpImageInfoCountBuf = AllocateZeroPool(sizeof(UINT8) * NumberOfHandles);
+  if (FmpImageInfoCountBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto END;
+  }
+
+  DescriptorSizeBuf = AllocateZeroPool(sizeof(UINTN) * NumberOfHandles);
+  if (DescriptorSizeBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto END;
+  }
+
+  FmpImageInfoDescriptorVerBuf = AllocateZeroPool(sizeof(UINT32) * 
NumberOfHandles);
+   if (FmpImageInfoDescriptorVerBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto END;
+  }
+
+  //
+  // Get all FmpImageInfo Descriptor into FmpImageInfoBuf
+  //
+  for (Index1 = 0; Index1 < NumberOfHandles; Index1++){
+    Status = gBS->HandleProtocol(
+                    HandleBuffer[Index1],
+                    &gEfiFirmwareManagementProtocolGuid,
+                    &FmpBuf[Index1]
+                    );
+
+    if (EFI_ERROR(Status)) {
+      continue;
+    }
+
+    ImageInfoSize = 0;
+    Status = FmpBuf[Index1]->GetImageInfo (
+                               FmpBuf[Index1],
+                               &ImageInfoSize,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL
+                               );
+
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      FmpImageInfoBuf[Index1] = AllocateZeroPool(ImageInfoSize);
+      if (FmpImageInfoBuf[Index1] == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto END;
+      }
+    } else {
+      continue;
+    }
+
+    PackageVersionName = NULL;
+    Status = FmpBuf[Index1]->GetImageInfo (
+                               FmpBuf[Index1],
+                               &ImageInfoSize,
+                               FmpImageInfoBuf[Index1],
+                               &FmpImageInfoDescriptorVerBuf[Index1],
+                               &FmpImageInfoCountBuf[Index1],
+                               &DescriptorSizeBuf[Index1],
+                               &PackageVersion,
+                               &PackageVersionName
+                               );
+
+    //
+    // If FMP GetInformation interface failed, skip this resource
+    //
+    if (EFI_ERROR(Status)){
+      FmpImageInfoCountBuf[Index1] = 0;
+      continue;
+    }
+
+    if (PackageVersionName != NULL) {
+      FreePool(PackageVersionName);
+    }
+  }
+
+  //
+  // Create new FMP cache repository based on FmpImageInfoBuf
+  // 
+  for (Index2 = 0; Index2 < NumberOfHandles; Index2++){
+    TempFmpImageInfo = FmpImageInfoBuf[Index2];
+    for (Index3 = 0; Index3 < FmpImageInfoCountBuf[Index2]; Index3++){
+      if ((TempFmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE) != 
0 
+      && (TempFmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0){
+        //
+        // Always put the first smallest version of Image info into ESRT cache 
+        //
+        for(Index1 = 0; Index1 < EntryNumNew; Index1++) {
+          if (CompareGuid(&EsrtRepositoryNew[Index1].FwClass, 
&TempFmpImageInfo->ImageTypeId)) {
+            if(EsrtRepositoryNew[Index1].FwVersion > 
TempFmpImageInfo->Version) {
+              SetEsrtEntryFromFmpInfo(&EsrtRepositoryNew[Index1], 
TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);
+            }
+            break;
+          }
+        }
+        //
+        // New ImageTypeId can't be found in EsrtRepositoryNew. Create a new 
one
+        //
+        if (Index1 == EntryNumNew){
+          SetEsrtEntryFromFmpInfo(&EsrtRepositoryNew[EntryNumNew], 
TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);
+          EntryNumNew++; 
+          if (EntryNumNew >= PcdGet32(PcdMaxFmpEsrtCacheNum)) {
+            break;
+          }
+        }
+      }
+
+      //
+      // Use DescriptorSize to move ImageInfo Pointer to stay compatible with 
different ImageInfo version
+      //
+      TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 
*)TempFmpImageInfo + DescriptorSizeBuf[Index2]);
+    }
+  }
+
+UPDATE_REPOSITORY:
+
+  Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gRT->SetVariable(
+                  EFI_ESRT_FMP_VARIABLE_NAME,
+                  &gEfiCallerIdGuid,
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                  EntryNumNew * sizeof(EFI_SYSTEM_RESOURCE_ENTRY),
+                  EsrtRepositoryNew
+                  );
+
+  EfiReleaseLock(&mPrivate.FmpLock);
+
+END:
+  if (EsrtRepositoryNew != NULL) {
+    FreePool(EsrtRepositoryNew);
+  }
+
+  if (HandleBuffer != NULL) {
+    FreePool(HandleBuffer);
+  }
+
+  if (FmpBuf != NULL) {
+    FreePool(FmpBuf);
+  }
+
+  if (FmpImageInfoCountBuf != NULL) {
+    FreePool(FmpImageInfoCountBuf);
+  }
+
+  if (DescriptorSizeBuf != NULL) {
+    FreePool(DescriptorSizeBuf);
+  }
+
+  if (FmpImageInfoDescriptorVerBuf != NULL) {
+    FreePool(FmpImageInfoDescriptorVerBuf);
+  }
+
+  if (FmpImageInfoBuf != NULL) {
+    for (Index1 = 0; Index1 < NumberOfHandles; Index1++){
+      if (FmpImageInfoBuf[Index1] != NULL) {
+        FreePool(FmpImageInfoBuf[Index1]);
+      }
+    }
+    FreePool(FmpImageInfoBuf);
+  }
+
+  return Status;
+}
+
+/**
+  This function locks up Esrt repository to be readonly. It should be called 
+  before gEfiEndOfDxeEventGroupGuid event signaled
+
+  @retval EFI_SUCCESS              Locks up FMP Non-FMP repository 
successfully 
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeLockEsrtRepository(
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;
+  //
+  // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock 
protocol exists
+  //
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID 
**) &VariableLock);
+  if (!EFI_ERROR (Status)) {
+    Status = VariableLock->RequestToLock (VariableLock, 
EFI_ESRT_FMP_VARIABLE_NAME, &gEfiCallerIdGuid);
+    DEBUG((EFI_D_INFO, "EsrtDxe Lock EsrtFmp Variable Status 0x%x", Status));
+
+    Status = VariableLock->RequestToLock (VariableLock, 
EFI_ESRT_NONFMP_VARIABLE_NAME, &gEfiCallerIdGuid);
+    DEBUG((EFI_D_INFO, "EsrtDxe Lock EsrtNonFmp Variable Status 0x%x", 
Status));
+  }
+
+  return Status;
+}
+
+/**
+  Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used 
to
+  install the Esrt Table into system configuration table
+
+  @param[in]  Event   The Event that is being processed.
+  @param[in]  Context The Event Context.
+
+**/
+VOID
+EFIAPI
+EsrtReadyToBootEventNotify (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{  
+  EFI_STATUS                 Status;
+  EFI_SYSTEM_RESOURCE_TABLE  *EsrtTable;
+  EFI_SYSTEM_RESOURCE_ENTRY  *FmpEsrtRepository;
+  EFI_SYSTEM_RESOURCE_ENTRY  *NonFmpEsrtRepository;
+  UINTN                      FmpRepositorySize;
+  UINTN                      NonFmpRepositorySize;
+  
+
+  FmpEsrtRepository    = NULL;
+  NonFmpEsrtRepository = NULL;
+  FmpRepositorySize    = 0;
+  NonFmpRepositorySize = 0;
+
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  Status = GetVariable2 (
+             EFI_ESRT_NONFMP_VARIABLE_NAME,
+             &gEfiCallerIdGuid,
+             (VOID **) &NonFmpEsrtRepository,
+             &NonFmpRepositorySize
+             );
+
+  if (EFI_ERROR(Status)) {
+    NonFmpRepositorySize = 0;
+  }
+
+  if (NonFmpRepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
+    DEBUG((EFI_D_ERROR, "NonFmp Repository Corrupt. Need to rebuild NonFmp 
Repository.\n"));
+    NonFmpRepositorySize = 0;
+  }
+
+  EfiReleaseLock(&mPrivate.NonFmpLock);
+
+  Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);
+  Status = GetVariable2 (
+             EFI_ESRT_FMP_VARIABLE_NAME,
+             &gEfiCallerIdGuid,
+             (VOID **) &FmpEsrtRepository,
+             &FmpRepositorySize
+             );
+
+  if (EFI_ERROR(Status)) {
+    FmpRepositorySize = 0;
+  }
+
+  if (FmpRepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {
+    DEBUG((EFI_D_ERROR, "Fmp Repository Corrupt. Need to rebuild Fmp 
Repository.\n"));
+    FmpRepositorySize = 0;
+  }
+
+  EfiReleaseLock(&mPrivate.FmpLock);
+
+  //
+  // Skip ESRT table publish if no ESRT entry exists
+  //
+  if (NonFmpRepositorySize + FmpRepositorySize == 0) {
+    goto EXIT;
+  }
+
+  EsrtTable = AllocatePool(sizeof(EFI_SYSTEM_RESOURCE_TABLE) + 
NonFmpRepositorySize + FmpRepositorySize);
+  if (EsrtTable == NULL) {
+    DEBUG ((EFI_D_ERROR, "Esrt table memory allocation failure\n"));
+    goto EXIT;
+  }
+
+  EsrtTable->FwResourceVersion  = 
EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;                            
                
+  EsrtTable->FwResourceCount    = (UINT32)((NonFmpRepositorySize + 
FmpRepositorySize) / sizeof(EFI_SYSTEM_RESOURCE_ENTRY));  
+  EsrtTable->FwResourceCountMax = PcdGet32(PcdMaxNonFmpEsrtCacheNum) + 
PcdGet32(PcdMaxFmpEsrtCacheNum);
+
+  CopyMem(EsrtTable + 1, NonFmpEsrtRepository, NonFmpRepositorySize);
+  CopyMem((UINT8 *)(EsrtTable + 1) + NonFmpRepositorySize, FmpEsrtRepository, 
FmpRepositorySize);
+
+  //
+  // Publish Esrt to system config table
+  //
+  Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, 
EsrtTable);
+
+  //
+  // Only one successful install
+  //
+  gBS->CloseEvent(Event);
+
+EXIT:
+
+  if (FmpEsrtRepository != NULL) {
+    FreePool(FmpEsrtRepository);
+  }
+
+  if (NonFmpEsrtRepository != NULL) {
+    FreePool(NonFmpEsrtRepository);
+  }
+}
+
+
+EFI_STATUS
+EFIAPI
+EsrtDxeEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{  
+  EFI_STATUS                    Status;
+
+  EfiInitializeLock (&mPrivate.FmpLock,    TPL_CALLBACK);
+  EfiInitializeLock (&mPrivate.NonFmpLock, TPL_CALLBACK);
+
+  //
+  // Install Esrt management Protocol
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mPrivate.Handle,
+                  &gEsrtManagementProtocolGuid,
+                  &mEsrtManagementProtocolTemplate,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register notify function to install Esrt Table on ReadyToBoot Event.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  EsrtReadyToBootEventNotify,
+                  NULL,
+                  &gEfiEventReadyToBootGuid,
+                  &mPrivate.Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf 
b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
new file mode 100644
index 0000000..daadee6
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
@@ -0,0 +1,70 @@
+## @file
+#  Esrt DXE driver that manages cached ESRT repository & publishes ESRT table
+#
+#  This driver produces EsrtManagement protocol to manage cache ESRT 
repository for FMP/Non-FMP instances.
+#  ESRT table based on repository is published on gEfiEventReadyToBootGuid.
+#
+#  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.
+#  
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = EsrtDxe
+  FILE_GUID                      = 999BD818-7DF7-4A9A-A502-9B75033E6A0F
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = EsrtDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  EsrtImpl.c
+  EsrtDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  BaseMemoryLib
+  UefiLib
+  PcdLib
+  DebugLib
+  MemoryAllocationLib
+  DxeServicesTableLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  PrintLib
+
+[Guids]
+  gEfiSystemResourceTableGuid             ## PRODUCES
+  gEfiEventReadyToBootGuid                ## CONSUMES
+
+[Protocols]
+  gEfiFirmwareManagementProtocolGuid      ## SOMETIMES_CONSUMES
+  gEsrtManagementProtocolGuid             ## PRODUCES
+  gEdkiiVariableLockProtocolGuid          ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxFmpEsrtCacheNum                  ## 
CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxNonFmpEsrtCacheNum               ## 
CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## 
CONSUMES
+
+[Depex]
+  gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  EsrtDxeExtra.uni
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni 
b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni
new file mode 100644
index 
0000000000000000000000000000000000000000..029041531d47685014f49c780bad05595e5590b4
GIT binary patch
literal 2510
zcmdUxUuzRV6vgke;CC2O5S2Dj!50y+F<T9`P1z<?K`2Suqzla^Y_`>YdG&W@vY8~L
z=u1Hf+xd6r+%xCiJJVl38`dz#_ne=z_cpT3uI<tu+aqSRme|}1E9tfD3nOP2j5E8%
zs$f*wmG%Algf{0JvodF8NPo!cB|C(3YN>VU70k?RicQA8DdRh4pYYA>#s>J$SkpeC
z#C;`rT8-=?%P#iXwaIP<`V{{+Fsbmud5%`tPFTzR8G^l74f(FYQ{UO@*;Y@s%5VF*
zM(meP2X<s9D0<8|x4p&K!8(Vx&XzAY*4NapREwu~sL*Fm&{b&nX&MySR8`RkyT+)i
zh$lXpQXmDjk6w2~YHCfsDYGBZFJm?`i^_k%VurnPVoVg2DNi}cGul`7!d}{I+oj)z
zX9>DA)t<uVK!LZCo#InxWuJ9fL^Q=z%Ids@=P4d<;g;IFrBabk%!CljF}wQ2&+#|+
znW&7t^y8tA@&qPYyMss08A7zhRV@1OnJ@haMQj|inU9yE7a~#ND_1TS9&YKYqN>bw
zC@B`Pc7zptO+bn)m4C8SjRbwPIwfAA=CrR#O|@tb*SJJ2zWb_B4GMStv>6<PC^f3e
zQCs>`58zq(Ra_kT5L6qn5@ICQKd{<lwXRH1Qx!h&ny4Ov2I5q%D68BliNza#^C+uS
zm2+=jc&+R73nJ9mP=C(M0Lu&NYTbJslq<fdN$hp)6PfR*%G5gKcuMviF>a%(ZacMI
zX4~l8qnCKCdsJ|Xeu_<n5aZA$w-YQ*J#vSha$0|Dw89l?jkf8>8ttyIJ7Zm_9q-ZE
z8CI!hcFcSmRAF?y_mq*iYfe79*vdv;gVh1H^8S_fGb>`QT1*yR!YLB&^$I7VxBY!}
z=zX@fR=(bhhUYF#_3bS4C)82U?;NBKo_pkJV&^cDUQ%`+we%v~_uKK6Bdi;8MemC9
zIk5+pnAX7i_g<&kQj@>aL)mnS63VobWdyfr@@GBb?YI6)|DW$*b<0=nH|~R=?lyHE
fa!#4{kS}qS$J^iE_&)2u2i?mfUaR;D22Fkgg#d{f

literal 0
HcmV?d00001

diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni 
b/MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni
new file mode 100644
index 
0000000000000000000000000000000000000000..dc762dd93a7e250e5fa1a1282f8f9b5f9da7fcd8
GIT binary patch
literal 1314
zcmZXUTW=Ck6ovP*iT~k*zNl$IO?)xN2r}x#mLU{keQE}1=_Fj50o&q_SHHFA)?&z<
z%f76=&N`d(_fN+<7WiKA3--ybEwiOv*>ih_Rldl!mfOzy_JBRuscmd#DN&jI#xlot
zjz4F=wgu4v@7nF3iCyEn^0C6K=3w&Q+TL>)c0**a7ofjnervDojlHvD)^UllWUZW>
zER87{nb&CJ>B317Vp5=qOHTDIUv78KwrwA*XCwPqpRwUHhC}8jxFvoAifXJtsZO*b
zLMo)NoDs2tiG2I=^Z|=lsb0ov30i}nVpX=Zo3UCuGbvc%D|=p6xMQu`NNvifykBI<
zo3pN%6tz~)x<U~%MP{`=QewmHHhDd6t<V1S373ZJy=yUJ{QtBW9E2zig<h()Wv^3D
z;raMpf=O5Lzs6JCkyt+vb;#<eGKHFZqNZj3rqn>3c8`=*@9emX_ujSYszP1G=dN{|
z^XJ@X=Ro}}mMPrlc5>ipgL1=HX;RHP&o}-T!G`ovVqY1%cE&zN(}1d)$5>-JZNe&Y
zr6)FEj<7cf%`L=qc0|OvBPXoX(HdLK!WC+Zx#xTBj%#kge&83c#4BpwrIMHpu*aYZ
zBk}4ZcH%CZYL1CgjH(t<Ux-!aPv-A<#9aTxsH{?)BC?Abr$LX=Vn|=9X5ZR1$3{QB
zHXXOic2swc-VePd((bZUcL>U;KEWl}38)kBBVq=yJYy9c?T8!He_+9_r;O@3^}z}8
a;-_jYqKg+zH+A8;eeYYn4>^8CRo_1l?8*TE

literal 0
HcmV?d00001

diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c 
b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
new file mode 100644
index 0000000..95f6220
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
@@ -0,0 +1,438 @@
+/** @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) {
+      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]    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);
+  }
+}
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h 
b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h
new file mode 100644
index 0000000..227b9b3
--- /dev/null
+++ b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h
@@ -0,0 +1,245 @@
+/** @file
+  Esrt management implementation head file.
+
+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.
+
+**/
+
+#ifndef _DXE_ESRT_IMPL_H_
+#define _DXE_ESRT_IMPL_H_
+
+#include <Guid/EventGroup.h>
+#include <Guid/SystemResourceTable.h>
+
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/PrintLib.h>
+
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/EsrtManagement.h>
+#include <Protocol/VariableLock.h>
+
+//
+// Name of  Variable for Non-FMP ESRT Repository
+// 
+#define EFI_ESRT_NONFMP_VARIABLE_NAME    L"EsrtNonFmp"
+
+//
+// Name of Variable for FMP
+// 
+#define EFI_ESRT_FMP_VARIABLE_NAME       L"EsrtFmp"
+
+//
+// Attribute of Cached ESRT entry
+//
+#define ESRT_FROM_FMP                    0x00000001
+#define ESRT_FROM_NONFMP                 0x00000002
+
+typedef struct {
+  EFI_HANDLE            Handle;
+  //
+  // Ready to boot event
+  //
+  EFI_EVENT             Event;
+  
+  //
+  // Updates to Fmp storage must be locked.
+  //
+  EFI_LOCK              FmpLock;
+
+  //
+  // Update to Non-Fmp storage must be locked
+  //
+  EFI_LOCK              NonFmpLock;
+} ESRT_PRIVATE_DATA;
+
+
+/**
+  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
+  );
+
+/**
+  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
+  );
+
+/**
+  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
+  );
+
+/**
+  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
+  );
+
+/**
+  Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .
+
+  @param[in]    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
+  );
+
+/**
+  Get ESRT entry from ESRT Cache by FwClass Guid 
+
+  @param[in]       FwClass                FwClass of Esrt entry to get  
+  @param[in out]  Entry                   Esrt entry returned 
+  
+  @retval EFI_SUCCESS                   The variable saving this Esrt Entry 
exists.
+  @retval EF_NOT_FOUND                  No correct variable found.
+  @retval EFI_WRITE_PROTECTED           ESRT Cache repository is locked
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeGetEsrtEntry(
+  IN     EFI_GUID                  *FwClass,
+  IN OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry
+  );
+
+/**
+  Update one ESRT entry in ESRT Cache.
+
+  @param[in]  Entry                         Esrt entry to be updated
+  
+  @retval EFI_SUCCESS                   Successfully update an ESRT entry in 
cache.
+  @retval EFI_INVALID_PARAMETER  Entry does't exist in ESRT Cache
+  @retval EFI_WRITE_PROTECTED     ESRT Cache is locked
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeUpdateEsrtEntry(
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry
+  );
+
+/**
+  Non-FMP instance to unregister Esrt Entry from ESRT Cache. 
+
+  @param[in]    FwClass                FwClass of Esrt entry to Unregister  
+  
+  @retval EFI_SUCCESS             Insert all entries Successfully 
+  @retval EFI_NOT_FOUND           Entry of FwClass does not exsit
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeUnRegisterEsrtEntry(
+  IN  EFI_GUID        *FwClass
+  );
+
+/**
+  Non-FMP instance to register one ESRT entry into ESRT Cache.
+
+  @param[in]  Entry                Esrt entry to be set
+
+  @retval EFI_SUCCESS          Successfully set a variable.
+  @retval EFI_INVALID_PARAMETER  ESRT Entry is already exist
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeRegisterEsrtEntry(
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry
+  );
+
+/**
+  This function syn up Cached ESRT with data from FMP instances
+  Function should be called after Connect All in order to locate all FMP 
protocols
+  installed
+
+  @retval EFI_SUCCESS                      Successfully sync cache repository 
from FMP instances
+  @retval EFI_NOT_FOUND                   No FMP Instance are found
+  @retval EFI_OUT_OF_RESOURCES     Resource allocaton fail
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeSyncFmp(
+  VOID
+  );
+
+/**
+  This function locks up Esrt repository to be readonly. It should be called 
+  before gEfiEndOfDxeEventGroupGuid event signaled
+
+  @retval EFI_SUCCESS              Locks up FMP Non-FMP repository 
successfully 
+
+**/
+EFI_STATUS
+EFIAPI
+EsrtDxeLockEsrtRepository(
+  VOID
+  );
+
+#endif // #ifndef _EFI_ESRT_IMPL_H_
+
-- 
1.9.5.msysgit.1


------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud 
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to