]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Add ESRT management module.
authorChao Zhang <chao.b.zhang@intel.com>
Wed, 13 May 2015 08:30:45 +0000 (08:30 +0000)
committerczhang46 <czhang46@Edk2>
Wed, 13 May 2015 08:30:45 +0000 (08:30 +0000)
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.zhang@intel.com>
Reviewed-by: Gao Liming <liming.gao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17426 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c [new file with mode: 0644]
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni [new file with mode: 0644]
MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni [new file with mode: 0644]
MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c [new file with mode: 0644]
MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h [new file with mode: 0644]

index 16a6eb57749420b17bc37e345bcbc474cea5955c..d0832bc21561025f715c3ceee1f56a29a6f379ba 100644 (file)
   }\r
 \r
   MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf\r
   }\r
 \r
   MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf\r
+  MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf\r
 \r
 [Components.IA32, Components.X64, Components.IPF]  \r
   MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf\r
 \r
 [Components.IA32, Components.X64, Components.IPF]  \r
   MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf\r
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.c
new file mode 100644 (file)
index 0000000..742abde
--- /dev/null
@@ -0,0 +1,652 @@
+/** @file\r
+  Esrt management module.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "EsrtImpl.h"\r
+\r
+\r
+//\r
+// Module globals.\r
+//\r
+\r
+ESRT_PRIVATE_DATA mPrivate;\r
+\r
+ESRT_MANAGEMENT_PROTOCOL  mEsrtManagementProtocolTemplate = { \r
+                            EsrtDxeGetEsrtEntry,\r
+                            EsrtDxeUpdateEsrtEntry,\r
+                            EsrtDxeRegisterEsrtEntry,\r
+                            EsrtDxeUnRegisterEsrtEntry,\r
+                            EsrtDxeSyncFmp,\r
+                            EsrtDxeLockEsrtRepository\r
+                            };\r
+\r
+/**\r
+  Get ESRT entry from ESRT Cache by FwClass Guid \r
+\r
+  @param[in]       FwClass                FwClass of Esrt entry to get  \r
+  @param[in out]  Entry                   Esrt entry returned \r
+  \r
+  @retval EFI_SUCCESS                   The variable saving this Esrt Entry exists.\r
+  @retval EF_NOT_FOUND                  No correct variable found.\r
+  @retval EFI_WRITE_PROTECTED           ESRT Cache repository is locked\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeGetEsrtEntry(\r
+  IN     EFI_GUID                  *FwClass,\r
+  IN OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  if (FwClass == NULL || Entry == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Find in Non-FMP Cached Esrt Repository\r
+  //\r
+  Status = GetEsrtEntry(\r
+             FwClass,\r
+             ESRT_FROM_NONFMP,\r
+             Entry\r
+             );\r
+\r
+  EfiReleaseLock(&mPrivate.NonFmpLock);\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Find in FMP Cached Esrt NV Variable\r
+    //\r
+    Status = GetEsrtEntry(\r
+               FwClass,\r
+               ESRT_FROM_FMP,\r
+               Entry\r
+               );\r
+\r
+    EfiReleaseLock(&mPrivate.FmpLock);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Update one ESRT entry in ESRT Cache.\r
+\r
+  @param[in]  Entry                         Esrt entry to be updated\r
+  \r
+  @retval EFI_SUCCESS                   Successfully update an ESRT entry in cache.\r
+  @retval EFI_INVALID_PARAMETER         Entry does't exist in ESRT Cache\r
+  @retval EFI_WRITE_PROTECTED           ESRT Cache repositoy is locked\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeUpdateEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  \r
+  if (Entry == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = UpdateEsrtEntry(Entry, ESRT_FROM_FMP);\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    EfiReleaseLock(&mPrivate.FmpLock);\r
+    return Status;\r
+  }\r
+  EfiReleaseLock(&mPrivate.FmpLock);\r
+\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = UpdateEsrtEntry(Entry, ESRT_FROM_NONFMP);\r
+\r
+  EfiReleaseLock(&mPrivate.NonFmpLock);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Non-FMP instance to unregister Esrt Entry from ESRT Cache. \r
+\r
+  @param[in]    FwClass                FwClass of Esrt entry to Unregister  \r
+  \r
+  @retval EFI_SUCCESS             Insert all entries Successfully \r
+  @retval EFI_NOT_FOUND           Entry of FwClass does not exsit\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeUnRegisterEsrtEntry(\r
+  IN  EFI_GUID        *FwClass\r
+  )\r
+{\r
+  EFI_STATUS Status; \r
+\r
+  if (FwClass == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = DeleteEsrtEntry(FwClass, ESRT_FROM_NONFMP);\r
+\r
+  EfiReleaseLock(&mPrivate.NonFmpLock);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Non-FMP instance to register one ESRT entry into ESRT Cache.\r
+\r
+  @param[in]  Entry                Esrt entry to be set\r
+\r
+  @retval EFI_SUCCESS              Successfully set a variable.\r
+  @retval EFI_INVALID_PARAMETER    ESRT Entry is already exist\r
+  @retval EFI_OUT_OF_RESOURCES     Non-FMP ESRT repository is full\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeRegisterEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_SYSTEM_RESOURCE_ENTRY EsrtEntryTmp;\r
+\r
+  if (Entry == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = GetEsrtEntry(\r
+             &Entry->FwClass,\r
+             ESRT_FROM_NONFMP,\r
+             &EsrtEntryTmp\r
+             );\r
+\r
+  if (Status == EFI_NOT_FOUND) {\r
+    Status = InsertEsrtEntry(Entry, ESRT_FROM_NONFMP);\r
+  }\r
+\r
+  EfiReleaseLock(&mPrivate.NonFmpLock);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function syn up Cached ESRT with data from FMP instances\r
+  Function should be called after Connect All in order to locate all FMP protocols\r
+  installed\r
+\r
+  @retval EFI_SUCCESS                      Successfully sync cache repository from FMP instances\r
+  @retval EFI_NOT_FOUND                   No FMP Instance are found\r
+  @retval EFI_OUT_OF_RESOURCES     Resource allocaton fail\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeSyncFmp(\r
+  VOID\r
+  ) \r
+{\r
+  EFI_STATUS                                Status;\r
+  UINTN                                     Index1;\r
+  UINTN                                     Index2;\r
+  UINTN                                     Index3;\r
+  EFI_HANDLE                                *HandleBuffer;\r
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL          **FmpBuf;\r
+  UINTN                                     NumberOfHandles;\r
+  UINTN                                     *DescriptorSizeBuf;\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR             **FmpImageInfoBuf;  \r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR             *TempFmpImageInfo;  \r
+  UINT8                                     *FmpImageInfoCountBuf;\r
+  UINT32                                    *FmpImageInfoDescriptorVerBuf;\r
+  UINTN                                     ImageInfoSize;\r
+  UINT32                                    PackageVersion;\r
+  CHAR16                                    *PackageVersionName;\r
+  EFI_SYSTEM_RESOURCE_ENTRY                 *EsrtRepositoryNew;\r
+  UINTN                                     EntryNumNew;\r
+\r
+  NumberOfHandles              = 0;\r
+  EntryNumNew                  = 0;\r
+  FmpBuf                       = NULL;\r
+  HandleBuffer                 = NULL;\r
+  FmpImageInfoBuf              = NULL;\r
+  FmpImageInfoCountBuf         = NULL;\r
+  PackageVersionName           = NULL;\r
+  DescriptorSizeBuf            = NULL;\r
+  FmpImageInfoDescriptorVerBuf = NULL;\r
+  EsrtRepositoryNew            = NULL;\r
+\r
+  //\r
+  // Get image information from all FMP protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiFirmwareManagementProtocolGuid,\r
+                  NULL,\r
+                  &NumberOfHandles,\r
+                  &HandleBuffer\r
+                  );\r
+\r
\r
+  if (Status == EFI_NOT_FOUND) { \r
+    EntryNumNew = 0;\r
+    goto UPDATE_REPOSITORY;\r
+  } else if (EFI_ERROR(Status)){ \r
+    goto END;\r
+  }\r
+\r
+  //\r
+  // Allocate buffer to hold new FMP ESRT Cache repository\r
+  //\r
+  EsrtRepositoryNew = AllocateZeroPool(PcdGet32(PcdMaxFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
+  if (EsrtRepositoryNew == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto END;\r
+  }\r
+\r
+  FmpBuf = AllocatePool(sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL *) * NumberOfHandles);\r
+  if (FmpBuf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto END;\r
+  }\r
+\r
+  FmpImageInfoBuf = AllocateZeroPool(sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfHandles);\r
+  if (FmpImageInfoBuf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;    \r
+    goto END;\r
+  }\r
+\r
+  FmpImageInfoCountBuf = AllocateZeroPool(sizeof(UINT8) * NumberOfHandles);\r
+  if (FmpImageInfoCountBuf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto END;\r
+  }\r
+\r
+  DescriptorSizeBuf = AllocateZeroPool(sizeof(UINTN) * NumberOfHandles);\r
+  if (DescriptorSizeBuf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto END;\r
+  }\r
+\r
+  FmpImageInfoDescriptorVerBuf = AllocateZeroPool(sizeof(UINT32) * NumberOfHandles);\r
+   if (FmpImageInfoDescriptorVerBuf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto END;\r
+  }\r
+\r
+  //\r
+  // Get all FmpImageInfo Descriptor into FmpImageInfoBuf\r
+  //\r
+  for (Index1 = 0; Index1 < NumberOfHandles; Index1++){\r
+    Status = gBS->HandleProtocol(\r
+                    HandleBuffer[Index1],\r
+                    &gEfiFirmwareManagementProtocolGuid,\r
+                    (VOID **)&FmpBuf[Index1]\r
+                    );\r
+\r
+    if (EFI_ERROR(Status)) {\r
+      continue;\r
+    }\r
+\r
+    ImageInfoSize = 0;\r
+    Status = FmpBuf[Index1]->GetImageInfo (\r
+                               FmpBuf[Index1],\r
+                               &ImageInfoSize,\r
+                               NULL,\r
+                               NULL,\r
+                               NULL,\r
+                               NULL,\r
+                               NULL,\r
+                               NULL\r
+                               );\r
+\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      FmpImageInfoBuf[Index1] = AllocateZeroPool(ImageInfoSize);\r
+      if (FmpImageInfoBuf[Index1] == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto END;\r
+      }\r
+    } else {\r
+      continue;\r
+    }\r
+\r
+    PackageVersionName = NULL;\r
+    Status = FmpBuf[Index1]->GetImageInfo (\r
+                               FmpBuf[Index1],\r
+                               &ImageInfoSize,\r
+                               FmpImageInfoBuf[Index1],\r
+                               &FmpImageInfoDescriptorVerBuf[Index1],\r
+                               &FmpImageInfoCountBuf[Index1],\r
+                               &DescriptorSizeBuf[Index1],\r
+                               &PackageVersion,\r
+                               &PackageVersionName\r
+                               );\r
+\r
+    //\r
+    // If FMP GetInformation interface failed, skip this resource\r
+    //\r
+    if (EFI_ERROR(Status)){\r
+      FmpImageInfoCountBuf[Index1] = 0;\r
+      continue;\r
+    }\r
+\r
+    if (PackageVersionName != NULL) {\r
+      FreePool(PackageVersionName);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Create new FMP cache repository based on FmpImageInfoBuf\r
+  // \r
+  for (Index2 = 0; Index2 < NumberOfHandles; Index2++){\r
+    TempFmpImageInfo = FmpImageInfoBuf[Index2];\r
+    for (Index3 = 0; Index3 < FmpImageInfoCountBuf[Index2]; Index3++){\r
+      if ((TempFmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE) != 0 \r
+      && (TempFmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0){\r
+        //\r
+        // Always put the first smallest version of Image info into ESRT cache \r
+        //\r
+        for(Index1 = 0; Index1 < EntryNumNew; Index1++) {\r
+          if (CompareGuid(&EsrtRepositoryNew[Index1].FwClass, &TempFmpImageInfo->ImageTypeId)) {\r
+            if(EsrtRepositoryNew[Index1].FwVersion > TempFmpImageInfo->Version) {\r
+              SetEsrtEntryFromFmpInfo(&EsrtRepositoryNew[Index1], TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);\r
+            }\r
+            break;\r
+          }\r
+        }\r
+        //\r
+        // New ImageTypeId can't be found in EsrtRepositoryNew. Create a new one\r
+        //\r
+        if (Index1 == EntryNumNew){\r
+          SetEsrtEntryFromFmpInfo(&EsrtRepositoryNew[EntryNumNew], TempFmpImageInfo, FmpImageInfoDescriptorVerBuf[Index2]);\r
+          EntryNumNew++; \r
+          if (EntryNumNew >= PcdGet32(PcdMaxFmpEsrtCacheNum)) {\r
+            break;\r
+          }\r
+        }\r
+      }\r
+\r
+      //\r
+      // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version\r
+      //\r
+      TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSizeBuf[Index2]);\r
+    }\r
+  }\r
+\r
+UPDATE_REPOSITORY:\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gRT->SetVariable(\r
+                  EFI_ESRT_FMP_VARIABLE_NAME,\r
+                  &gEfiCallerIdGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                  EntryNumNew * sizeof(EFI_SYSTEM_RESOURCE_ENTRY),\r
+                  EsrtRepositoryNew\r
+                  );\r
+\r
+  EfiReleaseLock(&mPrivate.FmpLock);\r
+\r
+END:\r
+  if (EsrtRepositoryNew != NULL) {\r
+    FreePool(EsrtRepositoryNew);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool(HandleBuffer);\r
+  }\r
+\r
+  if (FmpBuf != NULL) {\r
+    FreePool(FmpBuf);\r
+  }\r
+\r
+  if (FmpImageInfoCountBuf != NULL) {\r
+    FreePool(FmpImageInfoCountBuf);\r
+  }\r
+\r
+  if (DescriptorSizeBuf != NULL) {\r
+    FreePool(DescriptorSizeBuf);\r
+  }\r
+\r
+  if (FmpImageInfoDescriptorVerBuf != NULL) {\r
+    FreePool(FmpImageInfoDescriptorVerBuf);\r
+  }\r
+\r
+  if (FmpImageInfoBuf != NULL) {\r
+    for (Index1 = 0; Index1 < NumberOfHandles; Index1++){\r
+      if (FmpImageInfoBuf[Index1] != NULL) {\r
+        FreePool(FmpImageInfoBuf[Index1]);\r
+      }\r
+    }\r
+    FreePool(FmpImageInfoBuf);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function locks up Esrt repository to be readonly. It should be called \r
+  before gEfiEndOfDxeEventGroupGuid event signaled\r
+\r
+  @retval EFI_SUCCESS              Locks up FMP Non-FMP repository successfully \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeLockEsrtRepository(\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;\r
+  //\r
+  // Mark ACPI_GLOBAL_VARIABLE variable to read-only if the Variable Lock protocol exists\r
+  //\r
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = VariableLock->RequestToLock (VariableLock, EFI_ESRT_FMP_VARIABLE_NAME, &gEfiCallerIdGuid);\r
+    DEBUG((EFI_D_INFO, "EsrtDxe Lock EsrtFmp Variable Status 0x%x", Status));\r
+\r
+    Status = VariableLock->RequestToLock (VariableLock, EFI_ESRT_NONFMP_VARIABLE_NAME, &gEfiCallerIdGuid);\r
+    DEBUG((EFI_D_INFO, "EsrtDxe Lock EsrtNonFmp Variable Status 0x%x", Status));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to\r
+  install the Esrt Table into system configuration table\r
+\r
+  @param[in]  Event   The Event that is being processed.\r
+  @param[in]  Context The Event Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EsrtReadyToBootEventNotify (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{  \r
+  EFI_STATUS                 Status;\r
+  EFI_SYSTEM_RESOURCE_TABLE  *EsrtTable;\r
+  EFI_SYSTEM_RESOURCE_ENTRY  *FmpEsrtRepository;\r
+  EFI_SYSTEM_RESOURCE_ENTRY  *NonFmpEsrtRepository;\r
+  UINTN                      FmpRepositorySize;\r
+  UINTN                      NonFmpRepositorySize;\r
+  \r
+\r
+  FmpEsrtRepository    = NULL;\r
+  NonFmpEsrtRepository = NULL;\r
+  FmpRepositorySize    = 0;\r
+  NonFmpRepositorySize = 0;\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.NonFmpLock);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  Status = GetVariable2 (\r
+             EFI_ESRT_NONFMP_VARIABLE_NAME,\r
+             &gEfiCallerIdGuid,\r
+             (VOID **) &NonFmpEsrtRepository,\r
+             &NonFmpRepositorySize\r
+             );\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    NonFmpRepositorySize = 0;\r
+  }\r
+\r
+  if (NonFmpRepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
+    DEBUG((EFI_D_ERROR, "NonFmp Repository Corrupt. Need to rebuild NonFmp Repository.\n"));\r
+    NonFmpRepositorySize = 0;\r
+  }\r
+\r
+  EfiReleaseLock(&mPrivate.NonFmpLock);\r
+\r
+  Status = EfiAcquireLockOrFail (&mPrivate.FmpLock);\r
+  Status = GetVariable2 (\r
+             EFI_ESRT_FMP_VARIABLE_NAME,\r
+             &gEfiCallerIdGuid,\r
+             (VOID **) &FmpEsrtRepository,\r
+             &FmpRepositorySize\r
+             );\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    FmpRepositorySize = 0;\r
+  }\r
+\r
+  if (FmpRepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
+    DEBUG((EFI_D_ERROR, "Fmp Repository Corrupt. Need to rebuild Fmp Repository.\n"));\r
+    FmpRepositorySize = 0;\r
+  }\r
+\r
+  EfiReleaseLock(&mPrivate.FmpLock);\r
+\r
+  //\r
+  // Skip ESRT table publish if no ESRT entry exists\r
+  //\r
+  if (NonFmpRepositorySize + FmpRepositorySize == 0) {\r
+    goto EXIT;\r
+  }\r
+\r
+  EsrtTable = AllocatePool(sizeof(EFI_SYSTEM_RESOURCE_TABLE) + NonFmpRepositorySize + FmpRepositorySize);\r
+  if (EsrtTable == NULL) {\r
+    DEBUG ((EFI_D_ERROR, "Esrt table memory allocation failure\n"));\r
+    goto EXIT;\r
+  }\r
+\r
+  EsrtTable->FwResourceVersion  = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;                                            \r
+  EsrtTable->FwResourceCount    = (UINT32)((NonFmpRepositorySize + FmpRepositorySize) / sizeof(EFI_SYSTEM_RESOURCE_ENTRY));  \r
+  EsrtTable->FwResourceCountMax = PcdGet32(PcdMaxNonFmpEsrtCacheNum) + PcdGet32(PcdMaxFmpEsrtCacheNum);\r
+\r
+  CopyMem(EsrtTable + 1, NonFmpEsrtRepository, NonFmpRepositorySize);\r
+  CopyMem((UINT8 *)(EsrtTable + 1) + NonFmpRepositorySize, FmpEsrtRepository, FmpRepositorySize);\r
+\r
+  //\r
+  // Publish Esrt to system config table\r
+  //\r
+  Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, EsrtTable);\r
+\r
+  //\r
+  // Only one successful install\r
+  //\r
+  gBS->CloseEvent(Event);\r
+\r
+EXIT:\r
+\r
+  if (FmpEsrtRepository != NULL) {\r
+    FreePool(FmpEsrtRepository);\r
+  }\r
+\r
+  if (NonFmpEsrtRepository != NULL) {\r
+    FreePool(NonFmpEsrtRepository);\r
+  }\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeEntryPoint (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{  \r
+  EFI_STATUS                    Status;\r
+\r
+  EfiInitializeLock (&mPrivate.FmpLock,    TPL_CALLBACK);\r
+  EfiInitializeLock (&mPrivate.NonFmpLock, TPL_CALLBACK);\r
+\r
+  //\r
+  // Install Esrt management Protocol\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mPrivate.Handle,\r
+                  &gEsrtManagementProtocolGuid,\r
+                  &mEsrtManagementProtocolTemplate,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Register notify function to install Esrt Table on ReadyToBoot Event.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  EsrtReadyToBootEventNotify,\r
+                  NULL,\r
+                  &gEfiEventReadyToBootGuid,\r
+                  &mPrivate.Event\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf
new file mode 100644 (file)
index 0000000..573f8cd
--- /dev/null
@@ -0,0 +1,70 @@
+## @file\r
+#  Esrt DXE driver that manages cached ESRT repository & publishes ESRT table\r
+#\r
+#  This driver produces EsrtManagement protocol to manage cache ESRT repository for FMP/Non-FMP instances.\r
+#  ESRT table based on repository is published on gEfiEventReadyToBootGuid.\r
+#\r
+#  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#  \r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = EsrtDxe\r
+  FILE_GUID                      = 999BD818-7DF7-4A9A-A502-9B75033E6A0F\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = EsrtDxeEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  EsrtImpl.c\r
+  EsrtDxe.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  UefiLib\r
+  PcdLib\r
+  DebugLib\r
+  MemoryAllocationLib\r
+  DxeServicesTableLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  PrintLib\r
+\r
+[Guids]\r
+  gEfiSystemResourceTableGuid             ## PRODUCES\r
+  gEfiEventReadyToBootGuid                ## CONSUMES\r
+\r
+[Protocols]\r
+  gEfiFirmwareManagementProtocolGuid      ## SOMETIMES_CONSUMES\r
+  gEsrtManagementProtocolGuid             ## PRODUCES\r
+  gEdkiiVariableLockProtocolGuid          ## CONSUMES\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxFmpEsrtCacheNum                  ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxNonFmpEsrtCacheNum               ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES\r
+\r
+[Depex]\r
+  gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid\r
+\r
+[UserExtensions.TianoCore."ExtraFiles"]\r
+  EsrtDxeExtra.uni\r
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni
new file mode 100644 (file)
index 0000000..0290415
Binary files /dev/null and b/MdeModulePkg/Universal/EsrtDxe/EsrtDxe.uni differ
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni b/MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni
new file mode 100644 (file)
index 0000000..dc762dd
Binary files /dev/null and b/MdeModulePkg/Universal/EsrtDxe/EsrtDxeExtra.uni differ
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.c
new file mode 100644 (file)
index 0000000..09255bd
--- /dev/null
@@ -0,0 +1,438 @@
+/** @file\r
+  Esrt management implementation.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "EsrtImpl.h"\r
+\r
+/**\r
+  Find Esrt Entry stored in ESRT repository. \r
+\r
+  @param[in]     FwClass           Firmware class guid in Esrt entry\r
+  @param[in]     Attribute         Esrt from Non FMP or FMP instance\r
+  @param[out]    Entry             Esrt entry returned\r
+  \r
+  @retval EFI_SUCCESS            Successfully find an Esrt entry\r
+  @retval EF_NOT_FOUND           No Esrt entry found\r
+\r
+**/\r
+EFI_STATUS\r
+GetEsrtEntry (\r
+  IN  EFI_GUID              *FwClass,\r
+  IN  UINTN                 Attribute,\r
+  OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  CHAR16                     *VariableName;\r
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtRepository;\r
+  UINTN                      RepositorySize;\r
+  UINTN                      Index;\r
+  UINTN                      EsrtNum;\r
+\r
+  EsrtRepository = NULL;\r
+\r
+  //\r
+  // Get Esrt index buffer\r
+  //\r
+  if (Attribute == ESRT_FROM_FMP) {\r
+    VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
+  } else {\r
+    VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
+  }\r
+  \r
+  Status = GetVariable2 (\r
+             VariableName,\r
+             &gEfiCallerIdGuid,\r
+             (VOID **) &EsrtRepository,\r
+             &RepositorySize\r
+             );\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    goto EXIT;\r
+  }\r
+\r
+  if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
+    DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
+    Status = EFI_ABORTED;\r
+    goto EXIT;\r
+  }\r
+\r
+  Status  = EFI_NOT_FOUND;\r
+  EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);\r
+  for (Index = 0; Index < EsrtNum; Index++) {\r
+    if (CompareGuid(FwClass, &EsrtRepository[Index].FwClass)) {\r
+      CopyMem(Entry, &EsrtRepository[Index], sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+  }\r
+\r
+EXIT:\r
+  if (EsrtRepository != NULL) {\r
+    FreePool(EsrtRepository);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Insert a new ESRT entry into ESRT Cache repository.\r
+\r
+  @param[in]  Entry                Esrt entry to be set\r
+  @param[in]  Attribute            Esrt from Esrt private protocol or FMP instance\r
+  \r
+  @retval EFI_SUCCESS          Successfully set a variable.\r
+\r
+**/\r
+EFI_STATUS\r
+InsertEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,\r
+  UINTN                        Attribute\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  CHAR16                     *VariableName;\r
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtRepository;\r
+  UINTN                      RepositorySize;\r
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtRepositoryNew;\r
+\r
+  EsrtRepository    = NULL;\r
+  EsrtRepositoryNew = NULL;\r
+\r
+  //\r
+  // Get Esrt index buffer\r
+  //\r
+  if (Attribute == ESRT_FROM_FMP) {\r
+    VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
+  } else {\r
+    VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
+  }\r
+\r
+  Status = GetVariable2 (\r
+             VariableName,\r
+             &gEfiCallerIdGuid,\r
+             (VOID **) &EsrtRepository,\r
+             &RepositorySize\r
+             );\r
+\r
+  if (Status == EFI_NOT_FOUND) {\r
+    //\r
+    // If not exist, create new Esrt cache repository\r
+    //\r
+    Status = gRT->SetVariable(\r
+                    VariableName,\r
+                    &gEfiCallerIdGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                    sizeof(EFI_SYSTEM_RESOURCE_ENTRY),\r
+                    Entry\r
+                    );\r
+    return Status;\r
+\r
+  } else if (Status == EFI_SUCCESS) {\r
+    //\r
+    // if exist, update Esrt cache repository\r
+    //\r
+    if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
+      DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
+      //\r
+      // Repository is corrupt. Clear Repository before insert new entry\r
+      //\r
+      Status = gRT->SetVariable(\r
+                      VariableName,\r
+                      &gEfiCallerIdGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                      0,\r
+                      EsrtRepository\r
+                      );\r
+      FreePool(EsrtRepository);\r
+      RepositorySize = 0;\r
+      EsrtRepository = NULL;\r
+    }\r
+\r
+    //\r
+    // Check Repository size constraint\r
+    //\r
+    if ((Attribute == ESRT_FROM_FMP && RepositorySize >= PcdGet32(PcdMaxFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY))\r
+      ||(Attribute == ESRT_FROM_NONFMP && RepositorySize >= PcdGet32(PcdMaxNonFmpEsrtCacheNum) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) ) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto EXIT;\r
+    }\r
+\r
+    EsrtRepositoryNew = AllocatePool(RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
+    if (EsrtRepositoryNew == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto EXIT;\r
+    }\r
+\r
+    if (RepositorySize != 0) {\r
+      CopyMem(EsrtRepositoryNew, EsrtRepository, RepositorySize);\r
+    }\r
+    CopyMem((UINT8 *)EsrtRepositoryNew + RepositorySize, Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
+\r
+    Status = gRT->SetVariable(\r
+                    VariableName,\r
+                    &gEfiCallerIdGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                    RepositorySize + sizeof(EFI_SYSTEM_RESOURCE_ENTRY),\r
+                    EsrtRepositoryNew\r
+                    );\r
+  }\r
+\r
+EXIT:\r
+  if (EsrtRepository != NULL) {\r
+    FreePool(EsrtRepository);\r
+  }\r
+\r
+  if (EsrtRepositoryNew != NULL) {\r
+    FreePool(EsrtRepositoryNew);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Delete ESRT Entry from ESRT repository. \r
+\r
+  @param[in]    FwClass              FwClass of Esrt entry to delete  \r
+  @param[in]    Attribute            Esrt from Esrt private protocol or FMP instance\r
+  \r
+  @retval EFI_SUCCESS         Insert all entries Successfully \r
+  @retval EFI_NOT_FOUND       ESRT entry with FwClass doesn't exsit\r
+  \r
+**/\r
+EFI_STATUS\r
+DeleteEsrtEntry(\r
+  IN  EFI_GUID        *FwClass,\r
+  IN  UINTN           Attribute\r
+  )\r
+{  \r
+  EFI_STATUS                 Status;\r
+  CHAR16                     *VariableName;\r
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtRepository;\r
+  UINTN                      RepositorySize;\r
+  UINTN                      Index;\r
+  UINTN                      EsrtNum;\r
+\r
+  EsrtRepository = NULL;\r
+  \r
+  //\r
+  // Get Esrt index buffer\r
+  //\r
+  if (Attribute == ESRT_FROM_FMP) {\r
+    VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
+  } else {\r
+    VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
+  }\r
+  \r
+  Status = GetVariable2 (\r
+             VariableName,\r
+             &gEfiCallerIdGuid,\r
+             (VOID **) &EsrtRepository,\r
+             &RepositorySize\r
+             );\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    goto EXIT;\r
+  }\r
+\r
+  if ((RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY)) != 0) {\r
+    DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
+    //\r
+    // Repository is corrupt. Clear Repository before insert new entry\r
+    //\r
+    Status = gRT->SetVariable(\r
+                    VariableName,\r
+                    &gEfiCallerIdGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                    0,\r
+                    EsrtRepository\r
+                    );\r
+    goto EXIT;\r
+  }\r
+\r
+  Status = EFI_NOT_FOUND;\r
+  EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);\r
+  for (Index = 0; Index < EsrtNum; Index++) {\r
+    //\r
+    // Delete Esrt entry if it is found in repository\r
+    //\r
+    if (CompareGuid(FwClass, &EsrtRepository[Index].FwClass)) {\r
+      //\r
+      // If delete Esrt entry is not at the rail\r
+      //\r
+      if (Index < EsrtNum - 1) {\r
+        CopyMem(&EsrtRepository[Index], &EsrtRepository[Index + 1], (EsrtNum - Index - 1) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
+      }\r
+\r
+      //\r
+      // Update New Repository\r
+      //\r
+      Status = gRT->SetVariable(\r
+                      VariableName,\r
+                      &gEfiCallerIdGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                      (EsrtNum - 1) * sizeof(EFI_SYSTEM_RESOURCE_ENTRY),\r
+                      EsrtRepository\r
+                      );\r
+      break;\r
+    }\r
+  }\r
+\r
+EXIT:\r
+  if (EsrtRepository != NULL) {\r
+    FreePool(EsrtRepository);\r
+  }\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  Update one ESRT entry in ESRT repository\r
+\r
+  @param[in]    Entry                Esrt entry to be set\r
+  @param[in]    Attribute            Esrt from Non Esrt or FMP instance\r
+  \r
+  @retval EFI_SUCCESS          Successfully Update a variable.\r
+  @retval EFI_NOT_FOUND        The Esrt enry doesn't exist\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,\r
+  UINTN                        Attribute\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  CHAR16                     *VariableName;\r
+  EFI_SYSTEM_RESOURCE_ENTRY  *EsrtRepository;\r
+  UINTN                      RepositorySize;\r
+  UINTN                      Index;\r
+  UINTN                      EsrtNum;\r
+\r
+  EsrtRepository    = NULL;\r
+\r
+  //\r
+  // Get Esrt index buffer\r
+  //\r
+  if (Attribute == ESRT_FROM_FMP) {\r
+    VariableName = EFI_ESRT_FMP_VARIABLE_NAME;\r
+  } else {\r
+    VariableName = EFI_ESRT_NONFMP_VARIABLE_NAME;\r
+  }\r
+\r
+  Status = GetVariable2 (\r
+             VariableName,\r
+             &gEfiCallerIdGuid,\r
+             (VOID **) &EsrtRepository,\r
+             &RepositorySize\r
+             );\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    //\r
+    // if exist, update Esrt cache repository\r
+    //\r
+    if (RepositorySize % sizeof(EFI_SYSTEM_RESOURCE_ENTRY) != 0) {\r
+      DEBUG((EFI_D_ERROR, "Repository Corrupt. Need to rebuild Repository.\n"));\r
+      //\r
+      // Repository is corrupt. Clear Repository before insert new entry\r
+      //\r
+      Status = gRT->SetVariable(\r
+                      VariableName,\r
+                      &gEfiCallerIdGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                      0,\r
+                      EsrtRepository\r
+                      );\r
+      Status = EFI_NOT_FOUND;\r
+      goto EXIT;\r
+    }\r
+\r
+    Status = EFI_NOT_FOUND;\r
+    EsrtNum = RepositorySize/sizeof(EFI_SYSTEM_RESOURCE_ENTRY);\r
+    for (Index = 0; Index < EsrtNum; Index++) {\r
+      //\r
+      // Update Esrt entry if it is found in repository\r
+      //\r
+      if (CompareGuid(&Entry->FwClass, &EsrtRepository[Index].FwClass)) {\r
+\r
+        CopyMem(&EsrtRepository[Index], Entry, sizeof(EFI_SYSTEM_RESOURCE_ENTRY));\r
+        //\r
+        // Update New Repository\r
+        //\r
+        Status = gRT->SetVariable(\r
+                        VariableName,\r
+                        &gEfiCallerIdGuid,\r
+                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                        RepositorySize,\r
+                        EsrtRepository\r
+                        );\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+EXIT:\r
+  if (EsrtRepository != NULL) {\r
+    FreePool(EsrtRepository);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .\r
+\r
+  @param[in]    EsrtEntry                Esrt entry to be Init\r
+  @param[in]    FmpImageInfo        FMP image info descriptor\r
+  @param[in]   DescriptorVersion    FMP Image info descriptor version\r
+  \r
+**/\r
+VOID \r
+SetEsrtEntryFromFmpInfo (\r
+  IN OUT EFI_SYSTEM_RESOURCE_ENTRY   *EsrtEntry,\r
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *FmpImageInfo,\r
+  IN UINT32                          DescriptorVersion\r
+  )\r
+{\r
+  EsrtEntry->FwVersion                = FmpImageInfo->Version;\r
+  EsrtEntry->FwClass                  = FmpImageInfo->ImageTypeId;\r
+  EsrtEntry->FwType                   = ESRT_FW_TYPE_DEVICEFIRMWARE;\r
+  EsrtEntry->LowestSupportedFwVersion = 0;\r
+  EsrtEntry->CapsuleFlags             = 0;\r
+  EsrtEntry->LastAttemptVersion       = 0;\r
+  EsrtEntry->LastAttemptStatus        = LAST_ATTEMPT_STATUS_SUCCESS;\r
+\r
+  if (DescriptorVersion >= 2) {\r
+    //\r
+    // LowestSupportedImageVersion only available in FMP V2 or higher\r
+    //\r
+    EsrtEntry->LowestSupportedFwVersion = FmpImageInfo->LowestSupportedImageVersion;\r
+  } \r
+\r
+  if (DescriptorVersion >= 3) {\r
+    //\r
+    // LastAttemptVersion & LastAttemptStatus only available in FMP V3 or higher\r
+    //\r
+    EsrtEntry->LastAttemptVersion = FmpImageInfo->LastAttemptVersion;\r
+    EsrtEntry->LastAttemptStatus  = FmpImageInfo->LastAttemptStatus;\r
+  } \r
+\r
+  //\r
+  // Set capsule customized flag\r
+  //\r
+  if ((FmpImageInfo->AttributesSupported & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0\r
+   && (FmpImageInfo->AttributesSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) {\r
+    EsrtEntry->CapsuleFlags = PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag);\r
+  }\r
+}\r
diff --git a/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h b/MdeModulePkg/Universal/EsrtDxe/EsrtImpl.h
new file mode 100644 (file)
index 0000000..b26cbd2
--- /dev/null
@@ -0,0 +1,245 @@
+/** @file\r
+  Esrt management implementation head file.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DXE_ESRT_IMPL_H_\r
+#define _DXE_ESRT_IMPL_H_\r
+\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/SystemResourceTable.h>\r
+\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/CapsuleLib.h>\r
+#include <Library/PrintLib.h>\r
+\r
+#include <Protocol/FirmwareManagement.h>\r
+#include <Protocol/EsrtManagement.h>\r
+#include <Protocol/VariableLock.h>\r
+\r
+//\r
+// Name of  Variable for Non-FMP ESRT Repository\r
+// \r
+#define EFI_ESRT_NONFMP_VARIABLE_NAME    L"EsrtNonFmp"\r
+\r
+//\r
+// Name of Variable for FMP\r
+// \r
+#define EFI_ESRT_FMP_VARIABLE_NAME       L"EsrtFmp"\r
+\r
+//\r
+// Attribute of Cached ESRT entry\r
+//\r
+#define ESRT_FROM_FMP                    0x00000001\r
+#define ESRT_FROM_NONFMP                 0x00000002\r
+\r
+typedef struct {\r
+  EFI_HANDLE            Handle;\r
+  //\r
+  // Ready to boot event\r
+  //\r
+  EFI_EVENT             Event;\r
+  \r
+  //\r
+  // Updates to Fmp storage must be locked.\r
+  //\r
+  EFI_LOCK              FmpLock;\r
+\r
+  //\r
+  // Update to Non-Fmp storage must be locked\r
+  //\r
+  EFI_LOCK              NonFmpLock;\r
+} ESRT_PRIVATE_DATA;\r
+\r
+\r
+/**\r
+  Find Esrt Entry stored in ESRT repository. \r
+\r
+  @param[in]     FwClass           Firmware class guid in Esrt entry\r
+  @param[in]     Attribute         Esrt from Non FMP or FMP instance\r
+  @param[out]    Entry             Esrt entry returned\r
+  \r
+  @retval EFI_SUCCESS            Successfully find an Esrt entry\r
+  @retval EF_NOT_FOUND           No Esrt entry found\r
+\r
+**/\r
+EFI_STATUS\r
+GetEsrtEntry (\r
+  IN  EFI_GUID              *FwClass,\r
+  IN  UINTN                 Attribute,\r
+  OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  );\r
+\r
+/**\r
+  Insert a new ESRT entry into ESRT Cache repository.\r
+\r
+  @param[in]  Entry                Esrt entry to be set\r
+  @param[in]  Attribute            Esrt from Esrt private protocol or FMP instance\r
+  \r
+  @retval EFI_SUCCESS          Successfully set a variable.\r
+\r
+**/\r
+EFI_STATUS\r
+InsertEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,\r
+  UINTN                        Attribute\r
+  );\r
+\r
+/**\r
+  Delete ESRT Entry from ESRT repository. \r
+\r
+  @param[in]    FwClass              FwClass of Esrt entry to delete  \r
+  @param[in]    Attribute            Esrt from Esrt private protocol or FMP instance\r
+  \r
+  @retval EFI_SUCCESS         Insert all entries Successfully \r
+  @retval EFI_NOT_FOUND       ESRT entry with FwClass doesn't exsit\r
+  \r
+**/\r
+EFI_STATUS\r
+DeleteEsrtEntry(\r
+  IN  EFI_GUID        *FwClass,\r
+  IN  UINTN           Attribute\r
+  );\r
+\r
+/**\r
+  Update one ESRT entry in ESRT repository\r
+\r
+  @param[in]    Entry                Esrt entry to be set\r
+  @param[in]    Attribute            Esrt from Non Esrt or FMP instance\r
+  \r
+  @retval EFI_SUCCESS          Successfully Update a variable.\r
+  @retval EFI_NOT_FOUND        The Esrt enry doesn't exist\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry,\r
+  UINTN                        Attribute\r
+  );\r
+\r
+/**\r
+  Init one ESRT entry according to input FmpImageInfo (V1, V2, V3) .\r
+\r
+  @param[in]    EsrtEntry                Esrt entry to be Init\r
+  @param[in]    FmpImageInfo        FMP image info descriptor\r
+  @param[in]   DescriptorVersion    FMP Image info descriptor version\r
+  \r
+**/\r
+VOID \r
+SetEsrtEntryFromFmpInfo (\r
+  IN OUT EFI_SYSTEM_RESOURCE_ENTRY   *EsrtEntry,\r
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR   *FmpImageInfo,\r
+  IN UINT32                          DescriptorVersion\r
+  );\r
+\r
+/**\r
+  Get ESRT entry from ESRT Cache by FwClass Guid \r
+\r
+  @param[in]       FwClass                FwClass of Esrt entry to get  \r
+  @param[in out]  Entry                   Esrt entry returned \r
+  \r
+  @retval EFI_SUCCESS                   The variable saving this Esrt Entry exists.\r
+  @retval EF_NOT_FOUND                  No correct variable found.\r
+  @retval EFI_WRITE_PROTECTED           ESRT Cache repository is locked\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeGetEsrtEntry(\r
+  IN     EFI_GUID                  *FwClass,\r
+  IN OUT EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  );\r
+\r
+/**\r
+  Update one ESRT entry in ESRT Cache.\r
+\r
+  @param[in]  Entry                         Esrt entry to be updated\r
+  \r
+  @retval EFI_SUCCESS                   Successfully update an ESRT entry in cache.\r
+  @retval EFI_INVALID_PARAMETER  Entry does't exist in ESRT Cache\r
+  @retval EFI_WRITE_PROTECTED     ESRT Cache is locked\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeUpdateEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  );\r
+\r
+/**\r
+  Non-FMP instance to unregister Esrt Entry from ESRT Cache. \r
+\r
+  @param[in]    FwClass                FwClass of Esrt entry to Unregister  \r
+  \r
+  @retval EFI_SUCCESS             Insert all entries Successfully \r
+  @retval EFI_NOT_FOUND           Entry of FwClass does not exsit\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeUnRegisterEsrtEntry(\r
+  IN  EFI_GUID        *FwClass\r
+  );\r
+\r
+/**\r
+  Non-FMP instance to register one ESRT entry into ESRT Cache.\r
+\r
+  @param[in]  Entry                Esrt entry to be set\r
+\r
+  @retval EFI_SUCCESS          Successfully set a variable.\r
+  @retval EFI_INVALID_PARAMETER  ESRT Entry is already exist\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeRegisterEsrtEntry(\r
+  IN EFI_SYSTEM_RESOURCE_ENTRY *Entry\r
+  );\r
+\r
+/**\r
+  This function syn up Cached ESRT with data from FMP instances\r
+  Function should be called after Connect All in order to locate all FMP protocols\r
+  installed\r
+\r
+  @retval EFI_SUCCESS                      Successfully sync cache repository from FMP instances\r
+  @retval EFI_NOT_FOUND                   No FMP Instance are found\r
+  @retval EFI_OUT_OF_RESOURCES     Resource allocaton fail\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeSyncFmp(\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function locks up Esrt repository to be readonly. It should be called \r
+  before gEfiEndOfDxeEventGroupGuid event signaled\r
+\r
+  @retval EFI_SUCCESS              Locks up FMP Non-FMP repository successfully \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EsrtDxeLockEsrtRepository(\r
+  VOID\r
+  );\r
+\r
+#endif // #ifndef _EFI_ESRT_IMPL_H_\r
+\r