]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
SecurityPkg: Convert source file to DOS format
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / SecureBootConfigDxe / SecureBootConfigImpl.c
index 904a210338f386de8b287aededadfab36ed722b5..e3066f77be37766c75bc7efdb0f7f1f34d4f890a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   HII Config Access protocol implementation of SecureBoot configuration module.\r
 \r
-Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2017, 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
@@ -13,11 +13,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "SecureBootConfigImpl.h"\r
+#include <Library/BaseCryptLib.h>\r
 \r
 CHAR16              mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";\r
 \r
 SECUREBOOT_CONFIG_PRIVATE_DATA         mSecureBootConfigPrivateDateTemplate = {\r
-  SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,  \r
+  SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,\r
   {\r
     SecureBootExtractConfig,\r
     SecureBootRouteConfig,\r
@@ -48,6 +49,8 @@ HII_VENDOR_DEVICE_PATH          mSecureBootHiiVendorDevicePath = {
 };\r
 \r
 \r
+BOOLEAN mIsEnterSecureBootForm = FALSE;\r
+\r
 //\r
 // OID ASN.1 Value for Hash Algorithms\r
 //\r
@@ -61,15 +64,15 @@ UINT8 mHashOidValue[] = {
   };\r
 \r
 HASH_TABLE mHash[] = {\r
-  { L"SHA1",   20, &mHashOidValue[8],  5, Sha1GetContextSize,  Sha1Init,   Sha1Update,    Sha1Final  },\r
-  { L"SHA224", 28, &mHashOidValue[13], 9, NULL,                NULL,       NULL,          NULL       },\r
-  { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update,  Sha256Final},\r
-  { L"SHA384", 48, &mHashOidValue[31], 9, NULL,                NULL,       NULL,          NULL       },\r
-  { L"SHA512", 64, &mHashOidValue[40], 9, NULL,                NULL,       NULL,          NULL       }\r
+  { L"SHA224", 28, &mHashOidValue[13], 9, NULL,                 NULL,       NULL,         NULL       },\r
+  { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},\r
+  { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},\r
+  { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}\r
 };\r
 \r
-\r
-// Variable Definitions                                           \r
+//\r
+// Variable Definitions\r
+//\r
 UINT32            mPeCoffHeaderOffset = 0;\r
 WIN_CERTIFICATE   *mCertificate = NULL;\r
 IMAGE_TYPE        mImageType;\r
@@ -81,6 +84,121 @@ EFI_GUID          mCertType;
 EFI_IMAGE_SECURITY_DATA_DIRECTORY    *mSecDataDir = NULL;\r
 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  mNtHeader;\r
 \r
+//\r
+// Possible DER-encoded certificate file suffixes, end with NULL pointer.\r
+//\r
+CHAR16* mDerEncodedSuffix[] = {\r
+  L".cer",\r
+  L".der",\r
+  L".crt",\r
+  NULL\r
+};\r
+CHAR16* mSupportX509Suffix = L"*.cer/der/crt";\r
+\r
+SECUREBOOT_CONFIG_PRIVATE_DATA  *gSecureBootPrivateData = NULL;\r
+\r
+/**\r
+  This code cleans up enrolled file by closing file & free related resources attached to\r
+  enrolled file.\r
+\r
+  @param[in] FileContext            FileContext cached in SecureBootConfig driver\r
+\r
+**/\r
+VOID\r
+CloseEnrolledFile(\r
+  IN SECUREBOOT_FILE_CONTEXT *FileContext\r
+)\r
+{\r
+  if (FileContext->FHandle != NULL) {\r
+    CloseFile (FileContext->FHandle);\r
+    FileContext->FHandle = NULL;\r
+  }\r
+\r
+  if (FileContext->FileName != NULL){\r
+    FreePool(FileContext->FileName);\r
+    FileContext->FileName = NULL;\r
+  }\r
+  FileContext->FileType = UNKNOWN_FILE_TYPE;\r
+\r
+}\r
+\r
+/**\r
+  This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.\r
+\r
+  @param[in] FileSuffix            The suffix of the input certificate file\r
+\r
+  @retval    TRUE           It's a DER-encoded certificate.\r
+  @retval    FALSE          It's NOT a DER-encoded certificate.\r
+\r
+**/\r
+BOOLEAN\r
+IsDerEncodeCertificate (\r
+  IN CONST CHAR16         *FileSuffix\r
+)\r
+{\r
+  UINTN     Index;\r
+  for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) {\r
+    if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) {\r
+      return TRUE;\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format\r
+The function reads file content but won't open/close given FileHandle.\r
+\r
+  @param[in] FileHandle            The FileHandle to be checked\r
+\r
+  @retval    TRUE            The content is EFI_VARIABLE_AUTHENTICATION_2 format.\r
+  @retval    FALSE          The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format.\r
+\r
+**/\r
+BOOLEAN\r
+IsAuthentication2Format (\r
+  IN   EFI_FILE_HANDLE    FileHandle\r
+)\r
+{\r
+  EFI_STATUS                     Status;\r
+  EFI_VARIABLE_AUTHENTICATION_2  *Auth2;\r
+  BOOLEAN                        IsAuth2Format;\r
+\r
+  IsAuth2Format = FALSE;\r
+\r
+  //\r
+  // Read the whole file content\r
+  //\r
+  Status = ReadFileContent(\r
+             FileHandle,\r
+             (VOID **) &mImageBase,\r
+             &mImageSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Auth2 = (EFI_VARIABLE_AUTHENTICATION_2 *)mImageBase;\r
+  if (Auth2->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (CompareGuid(&gEfiCertPkcs7Guid, &Auth2->AuthInfo.CertType)) {\r
+    IsAuth2Format = TRUE;\r
+  }\r
+\r
+ON_EXIT:\r
+  //\r
+  // Do not close File. simply check file content\r
+  //\r
+  if (mImageBase != NULL) {\r
+    FreePool (mImageBase);\r
+    mImageBase = NULL;\r
+  }\r
+\r
+  return IsAuth2Format;\r
+}\r
 \r
 /**\r
   Set Secure Boot option into variable space.\r
@@ -111,14 +229,14 @@ SaveSecureBootVariable (
 /**\r
   Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2\r
   descriptor with the input data. NO authentication is required in this function.\r
-  \r
+\r
   @param[in, out]   DataSize       On input, the size of Data buffer in bytes.\r
                                    On output, the size of data returned in Data\r
                                    buffer in bytes.\r
-  @param[in, out]   Data           On input, Pointer to data buffer to be wrapped or \r
+  @param[in, out]   Data           On input, Pointer to data buffer to be wrapped or\r
                                    pointer to NULL to wrap an empty payload.\r
                                    On output, Pointer to the new payload date buffer allocated from pool,\r
-                                   it's caller's responsibility to free the memory when finish using it. \r
+                                   it's caller's responsibility to free the memory when finish using it.\r
 \r
   @retval EFI_SUCCESS              Create time based payload successfully.\r
   @retval EFI_OUT_OF_RESOURCES     There are not enough memory resourses to create time based payload.\r
@@ -139,20 +257,20 @@ CreateTimeBasedPayload (
   EFI_VARIABLE_AUTHENTICATION_2    *DescriptorData;\r
   UINTN                            DescriptorSize;\r
   EFI_TIME                         Time;\r
-  \r
+\r
   if (Data == NULL || DataSize == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
   //\r
-  // In Setup mode or Custom mode, the variable does not need to be signed but the \r
+  // In Setup mode or Custom mode, the variable does not need to be signed but the\r
   // parameters to the SetVariable() call still need to be prepared as authenticated\r
   // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate\r
   // data in it.\r
   //\r
   Payload     = *Data;\r
   PayloadSize = *DataSize;\r
-  \r
+\r
   DescriptorSize    = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
   NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);\r
   if (NewData == NULL) {\r
@@ -177,16 +295,16 @@ CreateTimeBasedPayload (
   Time.Daylight   = 0;\r
   Time.Pad2       = 0;\r
   CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));\r
\r
+\r
   DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);\r
   DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;\r
   DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
   CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);\r
-  \r
+\r
   if (Payload != NULL) {\r
     FreePool(Payload);\r
   }\r
-  \r
+\r
   *DataSize = DescriptorSize + PayloadSize;\r
   *Data     = NewData;\r
   return EFI_SUCCESS;\r
@@ -219,6 +337,7 @@ DeleteVariable (
   if (Variable == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
+  FreePool (Variable);\r
 \r
   Data     = NULL;\r
   DataSize = 0;\r
@@ -244,31 +363,56 @@ DeleteVariable (
   return Status;\r
 }\r
 \r
+/**\r
+\r
+  Set the platform secure boot mode into "Custom" or "Standard" mode.\r
+\r
+  @param[in]   SecureBootMode        New secure boot mode: STANDARD_SECURE_BOOT_MODE or\r
+                                     CUSTOM_SECURE_BOOT_MODE.\r
+\r
+  @return EFI_SUCCESS                The platform has switched to the special mode successfully.\r
+  @return other                      Fail to operate the secure boot mode.\r
+\r
+**/\r
+EFI_STATUS\r
+SetSecureBootMode (\r
+  IN     UINT8         SecureBootMode\r
+  )\r
+{\r
+  return gRT->SetVariable (\r
+                EFI_CUSTOM_MODE_NAME,\r
+                &gEfiCustomModeEnableGuid,\r
+                EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                sizeof (UINT8),\r
+                &SecureBootMode\r
+                );\r
+}\r
+\r
 /**\r
   Generate the PK signature list from the X509 Certificate storing file (.cer)\r
 \r
   @param[in]   X509File              FileHandle of X509 Certificate storing file.\r
   @param[out]  PkCert                Point to the data buffer to store the signature list.\r
-  \r
+\r
   @return EFI_UNSUPPORTED            Unsupported Key Length.\r
   @return EFI_OUT_OF_RESOURCES       There are not enough memory resourses to form the signature list.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 CreatePkX509SignatureList (\r
-  IN    EFI_FILE_HANDLE             X509File, \r
-  OUT   EFI_SIGNATURE_LIST          **PkCert \r
+  IN    EFI_FILE_HANDLE             X509File,\r
+  OUT   EFI_SIGNATURE_LIST          **PkCert\r
   )\r
 {\r
-  EFI_STATUS              Status;  \r
+  EFI_STATUS              Status;\r
   UINT8                   *X509Data;\r
   UINTN                   X509DataSize;\r
   EFI_SIGNATURE_DATA      *PkCertData;\r
 \r
   X509Data = NULL;\r
   PkCertData = NULL;\r
-  X509DataSize = 0;  \r
-  \r
+  X509DataSize = 0;\r
+\r
   Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
@@ -288,32 +432,32 @@ CreatePkX509SignatureList (
     goto ON_EXIT;\r
   }\r
 \r
-  (*PkCert)->SignatureListSize   = (UINT32) (sizeof(EFI_SIGNATURE_LIST) \r
+  (*PkCert)->SignatureListSize   = (UINT32) (sizeof(EFI_SIGNATURE_LIST)\r
                                     + sizeof(EFI_SIGNATURE_DATA) - 1\r
                                     + X509DataSize);\r
   (*PkCert)->SignatureSize       = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
   (*PkCert)->SignatureHeaderSize = 0;\r
   CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid);\r
-  PkCertData                     = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert) \r
+  PkCertData                     = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert)\r
                                                           + sizeof(EFI_SIGNATURE_LIST)\r
                                                           + (*PkCert)->SignatureHeaderSize);\r
-  CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);   \r
+  CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);\r
   //\r
   // Fill the PK database with PKpub data from X509 certificate file.\r
-  //  \r
+  //\r
   CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);\r
-  \r
+\r
 ON_EXIT:\r
-  \r
+\r
   if (X509Data != NULL) {\r
     FreePool (X509Data);\r
   }\r
-  \r
+\r
   if (EFI_ERROR(Status) && *PkCert != NULL) {\r
     FreePool (*PkCert);\r
     *PkCert = NULL;\r
   }\r
-  \r
+\r
   return Status;\r
 }\r
 \r
@@ -327,31 +471,41 @@ ON_EXIT:
   @retval   EFI_SUCCESS            New PK enrolled successfully.\r
   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EnrollPlatformKey (\r
    IN  SECUREBOOT_CONFIG_PRIVATE_DATA*   Private\r
-  )                       \r
+  )\r
 {\r
   EFI_STATUS                      Status;\r
   UINT32                          Attr;\r
   UINTN                           DataSize;\r
   EFI_SIGNATURE_LIST              *PkCert;\r
   UINT16*                         FilePostFix;\r
-  \r
+  UINTN                           NameLength;\r
+\r
   if (Private->FileContext->FileName == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   PkCert = NULL;\r
 \r
+  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   //\r
-  // Parse the file's postfix. Only support *.cer(X509) files.\r
+  // Parse the file's postfix. Only support DER encoded X.509 certificate files.\r
   //\r
-  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
-  if (CompareMem (FilePostFix, L".cer",4)) {\r
-    DEBUG ((EFI_D_ERROR, "Don't support the file, only *.cer is supported."));\r
+  NameLength = StrLen (Private->FileContext->FileName);\r
+  if (NameLength <= 4) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
+  if (!IsDerEncodeCertificate(FilePostFix)) {\r
+    DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));\r
@@ -361,18 +515,18 @@ EnrollPlatformKey (
   // Prase the selected PK file and generature PK certificate list.\r
   //\r
   Status = CreatePkX509SignatureList (\r
-            Private->FileContext->FHandle, \r
-            &PkCert \r
+            Private->FileContext->FHandle,\r
+            &PkCert\r
             );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }\r
   ASSERT (PkCert != NULL);\r
-                         \r
+\r
   //\r
   // Set Platform Key variable.\r
-  // \r
-  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
+  //\r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
   DataSize = PkCert->SignatureListSize;\r
   Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);\r
@@ -380,12 +534,12 @@ EnrollPlatformKey (
     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
     goto ON_EXIT;\r
   }\r
-  \r
+\r
   Status = gRT->SetVariable(\r
-                  EFI_PLATFORM_KEY_NAME, \r
-                  &gEfiGlobalVariableGuid, \r
-                  Attr, \r
-                  DataSize, \r
+                  EFI_PLATFORM_KEY_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  Attr,\r
+                  DataSize,\r
                   PkCert\r
                   );\r
   if (EFI_ERROR (Status)) {\r
@@ -394,17 +548,14 @@ EnrollPlatformKey (
     }\r
     goto ON_EXIT;\r
   }\r
-  \r
+\r
 ON_EXIT:\r
 \r
   if (PkCert != NULL) {\r
     FreePool(PkCert);\r
   }\r
-  \r
-  if (Private->FileContext->FHandle != NULL) {\r
-    CloseFile (Private->FileContext->FHandle);\r
-    Private->FileContext->FHandle = NULL;\r
-  }\r
+\r
+  CloseEnrolledFile(Private->FileContext);\r
 \r
   return Status;\r
 }\r
@@ -414,7 +565,7 @@ ON_EXIT:
 \r
   @retval EFI_SUCCESS    Delete PK successfully.\r
   @retval Others         Could not allow to delete PK.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 DeletePlatformKey (\r
@@ -423,6 +574,11 @@ DeletePlatformKey (
 {\r
   EFI_STATUS Status;\r
 \r
+  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Status = DeleteVariable (\r
              EFI_PLATFORM_KEY_NAME,\r
              &gEfiGlobalVariableGuid\r
@@ -455,7 +611,7 @@ EnrollRsa2048ToKek (
   CPL_KEY_INFO                    *KeyInfo;\r
   EFI_SIGNATURE_DATA              *KEKSigData;\r
   UINTN                           KekSigListSize;\r
-  UINT8                           *KeyBuffer;  \r
+  UINT8                           *KeyBuffer;\r
   UINTN                           KeyLenInBytes;\r
 \r
   Attr        = 0;\r
@@ -467,11 +623,11 @@ EnrollRsa2048ToKek (
   KEKSigData  = NULL;\r
   KekSigList  = NULL;\r
   KekSigListSize = 0;\r
-  \r
+\r
   //\r
   // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.\r
   // First, We have to parse out public key data from the pbk key file.\r
-  //                \r
+  //\r
   Status = ReadFileContent (\r
              Private->FileContext->FHandle,\r
              (VOID**) &KeyBlob,\r
@@ -488,10 +644,10 @@ EnrollRsa2048ToKek (
     Status = EFI_UNSUPPORTED;\r
     goto ON_EXIT;\r
   }\r
-  \r
+\r
   //\r
   // Convert the Public key to fix octet string format represented in RSA PKCS#1.\r
-  // \r
+  //\r
   KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;\r
   KeyBuffer = AllocateZeroPool (KeyLenInBytes);\r
   if (KeyBuffer == NULL) {\r
@@ -499,13 +655,13 @@ EnrollRsa2048ToKek (
     goto ON_EXIT;\r
   }\r
   Int2OctStr (\r
-    (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)), \r
-    KeyLenInBytes / sizeof (UINTN), \r
-    KeyBuffer, \r
+    (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)),\r
+    KeyLenInBytes / sizeof (UINTN),\r
+    KeyBuffer,\r
     KeyLenInBytes\r
     );\r
   CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes);\r
-  \r
+\r
   //\r
   // Form an new EFI_SIGNATURE_LIST.\r
   //\r
@@ -525,7 +681,7 @@ EnrollRsa2048ToKek (
   KekSigList->SignatureHeaderSize = 0;\r
   KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;\r
   CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);\r
-  \r
+\r
   KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));\r
   CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
   CopyMem (\r
@@ -533,13 +689,13 @@ EnrollRsa2048ToKek (
     KeyBlob + sizeof(CPL_KEY_INFO),\r
     WIN_CERT_UEFI_RSA2048_SIZE\r
     );\r
-  \r
+\r
   //\r
-  // Check if KEK entry has been already existed. \r
-  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
+  // Check if KEK entry has been already existed.\r
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
   // new KEK to original variable.\r
-  //            \r
-  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
+  //\r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
          | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
   Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
   if (EFI_ERROR (Status)) {\r
@@ -548,10 +704,10 @@ EnrollRsa2048ToKek (
   }\r
 \r
   Status = gRT->GetVariable(\r
-                  EFI_KEY_EXCHANGE_KEY_NAME, \r
-                  &gEfiGlobalVariableGuid, \r
-                  NULL, \r
-                  &DataSize, \r
+                  EFI_KEY_EXCHANGE_KEY_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &DataSize,\r
                   NULL\r
                   );\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
@@ -559,26 +715,24 @@ EnrollRsa2048ToKek (
   } else if (Status != EFI_NOT_FOUND) {\r
     goto ON_EXIT;\r
   }\r
-  \r
+\r
   //\r
   // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,\r
-  //             \r
+  //\r
   Status = gRT->SetVariable(\r
-                  EFI_KEY_EXCHANGE_KEY_NAME, \r
-                  &gEfiGlobalVariableGuid, \r
-                  Attr, \r
-                  KekSigListSize, \r
+                  EFI_KEY_EXCHANGE_KEY_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  Attr,\r
+                  KekSigListSize,\r
                   KekSigList\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }\r
-  \r
+\r
 ON_EXIT:\r
 \r
-  CloseFile (Private->FileContext->FHandle);\r
-  Private->FileContext->FHandle = NULL;\r
-  Private->FileContext->FileName = NULL;\r
+  CloseEnrolledFile(Private->FileContext);\r
 \r
   if (Private->SignatureGUID != NULL) {\r
     FreePool (Private->SignatureGUID);\r
@@ -594,7 +748,7 @@ ON_EXIT:
   if (KekSigList != NULL) {\r
     FreePool (KekSigList);\r
   }\r
-  \r
+\r
   return Status;\r
 }\r
 \r
@@ -612,7 +766,7 @@ ON_EXIT:
 EFI_STATUS\r
 EnrollX509ToKek (\r
   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
-  ) \r
+  )\r
 {\r
   EFI_STATUS                        Status;\r
   UINTN                             X509DataSize;\r
@@ -650,7 +804,7 @@ EnrollX509ToKek (
 \r
   //\r
   // Fill Certificate Database parameters.\r
-  // \r
+  //\r
   KekSigList->SignatureListSize   = (UINT32) KekSigListSize;\r
   KekSigList->SignatureHeaderSize = 0;\r
   KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
@@ -661,35 +815,35 @@ EnrollX509ToKek (
   CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize);\r
 \r
   //\r
-  // Check if KEK been already existed. \r
-  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
+  // Check if KEK been already existed.\r
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
   // new kek to original variable\r
-  //    \r
-  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
+  //\r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
   Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList);\r
   if (EFI_ERROR (Status)) {\r
     DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
     goto ON_EXIT;\r
   }\r
-  \r
+\r
   Status = gRT->GetVariable(\r
-                  EFI_KEY_EXCHANGE_KEY_NAME, \r
-                  &gEfiGlobalVariableGuid, \r
-                  NULL, \r
-                  &DataSize, \r
+                  EFI_KEY_EXCHANGE_KEY_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &DataSize,\r
                   NULL\r
                   );\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     Attr |= EFI_VARIABLE_APPEND_WRITE;\r
   } else if (Status != EFI_NOT_FOUND) {\r
     goto ON_EXIT;\r
-  }  \r
+  }\r
 \r
   Status = gRT->SetVariable(\r
-                  EFI_KEY_EXCHANGE_KEY_NAME, \r
-                  &gEfiGlobalVariableGuid, \r
-                  Attr, \r
+                  EFI_KEY_EXCHANGE_KEY_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  Attr,\r
                   KekSigListSize,\r
                   KekSigList\r
                   );\r
@@ -699,9 +853,7 @@ EnrollX509ToKek (
 \r
 ON_EXIT:\r
 \r
-  CloseFile (Private->FileContext->FHandle);\r
-  Private->FileContext->FileName = NULL;\r
-  Private->FileContext->FHandle = NULL;\r
+  CloseEnrolledFile(Private->FileContext);\r
 \r
   if (Private->SignatureGUID != NULL) {\r
     FreePool (Private->SignatureGUID);\r
@@ -718,47 +870,63 @@ ON_EXIT:
 /**\r
   Enroll new KEK into the System without PK's authentication.\r
   The SignatureOwner GUID will be Private->SignatureGUID.\r
-  \r
+\r
   @param[in] PrivateData     The module's private data.\r
-  \r
+\r
   @retval   EFI_SUCCESS            New KEK enrolled successful.\r
   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
   @retval   others                 Fail to enroll KEK data.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EnrollKeyExchangeKey (\r
   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
-  ) \r
+  )\r
 {\r
   UINT16*     FilePostFix;\r
-  \r
-  if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {\r
+  EFI_STATUS  Status;\r
+  UINTN       NameLength;\r
+\r
+  if ((Private->FileContext->FHandle == NULL) || (Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   //\r
-  // Parse the file's postfix. Supports .cer and .der file as X509 certificate, \r
+  // Parse the file's postfix. Supports DER-encoded X509 certificate,\r
   // and .pbk as RSA public key file.\r
   //\r
-  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
-  if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) {\r
+  NameLength = StrLen (Private->FileContext->FileName);\r
+  if (NameLength <= 4) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
+  if (IsDerEncodeCertificate(FilePostFix)) {\r
     return EnrollX509ToKek (Private);\r
   } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {\r
     return EnrollRsa2048ToKek (Private);\r
   } else {\r
+    //\r
+    // File type is wrong, simply close it\r
+    //\r
+    CloseEnrolledFile(Private->FileContext);\r
+\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 }\r
 \r
 /**\r
-  Enroll a new X509 certificate into Signature Database (DB or DBX) without\r
+  Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without\r
   KEK's authentication.\r
 \r
   @param[in] PrivateData     The module's private data.\r
-  @param[in] VariableName    Variable name of signature database, must be \r
+  @param[in] VariableName    Variable name of signature database, must be\r
                              EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
-  \r
+\r
   @retval   EFI_SUCCESS            New X509 is enrolled successfully.\r
   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
 \r
@@ -767,7 +935,7 @@ EFI_STATUS
 EnrollX509toSigDB (\r
   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
   IN CHAR16                         *VariableName\r
-  ) \r
+  )\r
 {\r
   EFI_STATUS                        Status;\r
   UINTN                             X509DataSize;\r
@@ -808,7 +976,7 @@ EnrollX509toSigDB (
 \r
   //\r
   // Fill Certificate Database parameters.\r
-  // \r
+  //\r
   SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
   SigDBCert->SignatureListSize   = (UINT32) SigDBSize;\r
   SigDBCert->SignatureHeaderSize = 0;\r
@@ -820,11 +988,11 @@ EnrollX509toSigDB (
   CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize);\r
 \r
   //\r
-  // Check if signature database entry has been already existed. \r
-  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
+  // Check if signature database entry has been already existed.\r
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
   // new signature data to original variable\r
-  //    \r
-  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
+  //\r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
           | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
   Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
   if (EFI_ERROR (Status)) {\r
@@ -833,22 +1001,22 @@ EnrollX509toSigDB (
   }\r
 \r
   Status = gRT->GetVariable(\r
-                  VariableName, \r
-                  &gEfiImageSecurityDatabaseGuid, \r
-                  NULL, \r
-                  &DataSize, \r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  NULL,\r
+                  &DataSize,\r
                   NULL\r
                   );\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     Attr |= EFI_VARIABLE_APPEND_WRITE;\r
   } else if (Status != EFI_NOT_FOUND) {\r
     goto ON_EXIT;\r
-  }  \r
+  }\r
 \r
   Status = gRT->SetVariable(\r
-                  VariableName, \r
-                  &gEfiImageSecurityDatabaseGuid, \r
-                  Attr, \r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  Attr,\r
                   SigDBSize,\r
                   Data\r
                   );\r
@@ -858,9 +1026,7 @@ EnrollX509toSigDB (
 \r
 ON_EXIT:\r
 \r
-  CloseFile (Private->FileContext->FHandle);\r
-  Private->FileContext->FileName = NULL;\r
-  Private->FileContext->FHandle = NULL;\r
+  CloseEnrolledFile(Private->FileContext);\r
 \r
   if (Private->SignatureGUID != NULL) {\r
     FreePool (Private->SignatureGUID);\r
@@ -879,538 +1045,538 @@ ON_EXIT:
 }\r
 \r
 /**\r
-  Load PE/COFF image information into internal buffer and check its validity.\r
+  Check whether signature is in specified database.\r
 \r
-  @retval   EFI_SUCCESS         Successful\r
-  @retval   EFI_UNSUPPORTED     Invalid PE/COFF file\r
-  @retval   EFI_ABORTED         Serious error occurs, like file I/O error etc.\r
+  @param[in]  VariableName        Name of database variable that is searched in.\r
+  @param[in]  Signature           Pointer to signature that is searched for.\r
+  @param[in]  SignatureSize       Size of Signature.\r
+\r
+  @return TRUE                    Found the signature in the variable database.\r
+  @return FALSE                   Not found the signature in the variable database.\r
 \r
 **/\r
-EFI_STATUS\r
-LoadPeImage (\r
-  VOID \r
-  )   \r
+BOOLEAN\r
+IsSignatureFoundInDatabase (\r
+  IN CHAR16             *VariableName,\r
+  IN UINT8              *Signature,\r
+  IN UINTN              SignatureSize\r
+  )\r
 {\r
-  EFI_IMAGE_DOS_HEADER                  *DosHdr;\r
-  EFI_IMAGE_NT_HEADERS32                *NtHeader32;\r
-  EFI_IMAGE_NT_HEADERS64                *NtHeader64;\r
+  EFI_STATUS          Status;\r
+  EFI_SIGNATURE_LIST  *CertList;\r
+  EFI_SIGNATURE_DATA  *Cert;\r
+  UINTN               DataSize;\r
+  UINT8               *Data;\r
+  UINTN               Index;\r
+  UINTN               CertCount;\r
+  BOOLEAN             IsFound;\r
 \r
-  NtHeader32 = NULL;\r
-  NtHeader64 = NULL;\r
   //\r
-  // Read the Dos header\r
+  // Read signature database variable.\r
   //\r
-  DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);\r
-  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)\r
-  {\r
-    //\r
-    // DOS image header is present, \r
-    // So read the PE header after the DOS image header\r
-    //\r
-    mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
-  }\r
-  else\r
-  {\r
-    mPeCoffHeaderOffset = 0;\r
+  IsFound   = FALSE;\r
+  Data      = NULL;\r
+  DataSize  = 0;\r
+  Status    = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return FALSE;\r
   }\r
 \r
-  //\r
-  // Read PE header and check the signature validity and machine compatibility\r
-  //\r
-  NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);\r
-  if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)\r
-  {\r
-    return EFI_UNSUPPORTED;\r
+  Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    return FALSE;\r
   }\r
 \r
-  mNtHeader.Pe32 = NtHeader32;\r
+  Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
 \r
   //\r
-  // Check the architecture field of PE header and get the Certificate Data Directory data\r
-  // Note the size of FileHeader field is constant for both IA32 and X64 arch\r
+  // Enumerate all signature data in SigDB to check if executable's signature exists.\r
   //\r
-  if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) \r
-      || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)) {\r
-    //\r
-    // IA-32 Architecture\r
-    //\r
-    mImageType = ImageType_IA32;\r
-    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
+  CertList = (EFI_SIGNATURE_LIST *) Data;\r
+  while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
+    CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+    Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+    if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) {\r
+      for (Index = 0; Index < CertCount; Index++) {\r
+        if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {\r
+          //\r
+          // Find the signature in database.\r
+          //\r
+          IsFound = TRUE;\r
+          break;\r
+        }\r
+        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+      }\r
+\r
+      if (IsFound) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    DataSize -= CertList->SignatureListSize;\r
+    CertList  = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
   }\r
-  else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)\r
-          || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)) {\r
-    //\r
-    // 64-bits Architecture\r
-    //\r
-    mImageType = ImageType_X64;\r
-    NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);\r
-    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
-  } else {\r
-    return EFI_UNSUPPORTED;\r
+\r
+Done:\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  return IsFound;\r
 }\r
 \r
 /**\r
-  Calculate hash of Pe/Coff image based on the authenticode image hashing in\r
-  PE/COFF Specification 8.0 Appendix A\r
+  Calculate the hash of a certificate data with the specified hash algorithm.\r
 \r
-  @param[in]    HashAlg   Hash algorithm type.\r
\r
-  @retval TRUE            Successfully hash image.\r
-  @retval FALSE           Fail in hash image.\r
+  @param[in]    CertData  The certificate data to be hashed.\r
+  @param[in]    CertSize  The certificate size in bytes.\r
+  @param[in]    HashAlg   The specified hash algorithm.\r
+  @param[out]   CertHash  The output digest of the certificate\r
+\r
+  @retval TRUE            Successfully got the hash of the CertData.\r
+  @retval FALSE           Failed to get the hash of CertData.\r
 \r
 **/\r
-BOOLEAN \r
-HashPeImage (\r
-  IN  UINT32                HashAlg\r
+BOOLEAN\r
+CalculateCertHash (\r
+  IN  UINT8                 *CertData,\r
+  IN  UINTN                 CertSize,\r
+  IN  UINT32                HashAlg,\r
+  OUT UINT8                 *CertHash\r
   )\r
 {\r
   BOOLEAN                   Status;\r
-  UINT16                    Magic;\r
-  EFI_IMAGE_SECTION_HEADER  *Section;\r
   VOID                      *HashCtx;\r
   UINTN                     CtxSize;\r
-  UINT8                     *HashBase;\r
-  UINTN                     HashSize;\r
-  UINTN                     SumOfBytesHashed;\r
-  EFI_IMAGE_SECTION_HEADER  *SectionHeader;\r
-  UINTN                     Index;\r
-  UINTN                     Pos;\r
+  UINT8                     *TBSCert;\r
+  UINTN                     TBSCertSize;\r
 \r
-  HashCtx       = NULL;\r
-  SectionHeader = NULL;\r
-  Status        = FALSE;\r
+  HashCtx = NULL;\r
+  Status  = FALSE;\r
 \r
-  if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
+  if (HashAlg >= HASHALG_MAX) {\r
     return FALSE;\r
   }\r
-  \r
+\r
   //\r
-  // Initialize context of hash.\r
+  // Retrieve the TBSCertificate for Hash Calculation.\r
   //\r
-  ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
-\r
-  if (HashAlg == HASHALG_SHA1) {\r
-    mImageDigestSize  = SHA1_DIGEST_SIZE;\r
-    mCertType         = gEfiCertSha1Guid;    \r
-  } else if (HashAlg == HASHALG_SHA256) {\r
-    mImageDigestSize  = SHA256_DIGEST_SIZE;\r
-    mCertType         = gEfiCertSha256Guid;\r
+  if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) {\r
+    return FALSE;\r
   }\r
 \r
-  CtxSize   = mHash[HashAlg].GetContextSize();\r
-  \r
+  //\r
+  // 1. Initialize context of hash.\r
+  //\r
+  CtxSize = mHash[HashAlg].GetContextSize ();\r
   HashCtx = AllocatePool (CtxSize);\r
   ASSERT (HashCtx != NULL);\r
 \r
-  // 1.  Load the image header into memory.\r
-\r
-  // 2.  Initialize a SHA hash context.\r
-  Status = mHash[HashAlg].HashInit(HashCtx);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // Measuring PE/COFF Image Header;\r
-  // But CheckSum field and SECURITY data directory (certificate) are excluded\r
   //\r
-  Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+  // 2. Initialize a hash context.\r
   //\r
-  // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
-  // 4.  Hash the image header from its base to beginning of the image checksum.\r
-  //\r
-  HashBase = mImageBase;\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // Use PE32 offset.\r
-    //\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
-  } else {\r
-    //\r
-    // Use PE32+ offset.\r
-    //\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
-  }\r
-\r
-  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  Status = mHash[HashAlg].HashInit (HashCtx);\r
   if (!Status) {\r
     goto Done;\r
   }\r
+\r
   //\r
-  // 5.  Skip over the image checksum (it occupies a single ULONG).\r
-  // 6.  Get the address of the beginning of the Cert Directory.\r
-  // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
+  // 3. Calculate the hash.\r
   //\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // Use PE32 offset.\r
-    //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
-  } else {\r
-    //\r
-    // Use PE32+ offset.\r
-    //    \r
-    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
-  }\r
-\r
-  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  Status  = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
   if (!Status) {\r
     goto Done;\r
   }\r
+\r
   //\r
-  // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
-  // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
+  // 4. Get the hash result.\r
   //\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // Use PE32 offset\r
-    //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
-  } else {\r
-    //\r
-    // Use PE32+ offset.\r
-    //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
-  }\r
+  ZeroMem (CertHash, mHash[HashAlg].DigestLength);\r
+  Status  = mHash[HashAlg].HashFinal (HashCtx, CertHash);\r
 \r
-  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-  if (!Status) {\r
-    goto Done;\r
+Done:\r
+  if (HashCtx != NULL) {\r
+    FreePool (HashCtx);\r
   }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Check whether the hash of an X.509 certificate is in forbidden database (DBX).\r
+\r
+  @param[in]  Certificate       Pointer to X.509 Certificate that is searched for.\r
+  @param[in]  CertSize          Size of X.509 Certificate.\r
+\r
+  @return TRUE               Found the certificate hash in the forbidden database.\r
+  @return FALSE              Certificate hash is Not found in the forbidden database.\r
+\r
+**/\r
+BOOLEAN\r
+IsCertHashFoundInDbx (\r
+  IN  UINT8               *Certificate,\r
+  IN  UINTN               CertSize\r
+  )\r
+{\r
+  BOOLEAN                 IsFound;\r
+  EFI_STATUS              Status;\r
+  EFI_SIGNATURE_LIST      *DbxList;\r
+  EFI_SIGNATURE_DATA      *CertHash;\r
+  UINTN                   CertHashCount;\r
+  UINTN                   Index;\r
+  UINT32                  HashAlg;\r
+  UINT8                   CertDigest[MAX_DIGEST_SIZE];\r
+  UINT8                   *DbxCertHash;\r
+  UINTN                   SiglistHeaderSize;\r
+  UINT8                   *Data;\r
+  UINTN                   DataSize;\r
+\r
+  IsFound  = FALSE;\r
+  HashAlg  = HASHALG_MAX;\r
+  Data     = NULL;\r
+\r
   //\r
-  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
+  // Read signature database variable.\r
   //\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // Use PE32 offset.\r
-    //\r
-    SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
-  } else {\r
-    //\r
-    // Use PE32+ offset\r
-    //\r
-    SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
+  DataSize  = 0;\r
+  Status    = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return FALSE;\r
   }\r
 \r
-  //\r
-  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
-  //     structures in the image. The 'NumberOfSections' field of the image\r
-  //     header indicates how big the table should be. Do not include any\r
-  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
-  //\r
-  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
-  ASSERT (SectionHeader != NULL);\r
-  //\r
-  // 12.  Using the 'PointerToRawData' in the referenced section headers as\r
-  //      a key, arrange the elements in the table in ascending order. In other\r
-  //      words, sort the section headers according to the disk-file offset of\r
-  //      the section.\r
-  //\r
-  Section = (EFI_IMAGE_SECTION_HEADER *) (\r
-               mImageBase +\r
-               mPeCoffHeaderOffset +\r
-               sizeof (UINT32) +\r
-               sizeof (EFI_IMAGE_FILE_HEADER) +\r
-               mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
-               );\r
-  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
-    Pos = Index;\r
-    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
-      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
-      Pos--;\r
-    }\r
-    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
-    Section += 1;\r
+  Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
   }\r
 \r
   //\r
-  // 13.  Walk through the sorted table, bring the corresponding section\r
-  //      into memory, and hash the entire section (using the 'SizeOfRawData'\r
-  //      field in the section header to determine the amount of data to hash).\r
-  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
-  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.\r
+  // Check whether the certificate hash exists in the forbidden database.\r
   //\r
-  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
-    Section = &SectionHeader[Index];\r
-    if (Section->SizeOfRawData == 0) {\r
+  DbxList = (EFI_SIGNATURE_LIST *) Data;\r
+  while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) {\r
+    //\r
+    // Determine Hash Algorithm of Certificate in the forbidden database.\r
+    //\r
+    if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
+      HashAlg = HASHALG_SHA256;\r
+    } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
+      HashAlg = HASHALG_SHA384;\r
+    } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
+      HashAlg = HASHALG_SHA512;\r
+    } else {\r
+      DataSize -= DbxList->SignatureListSize;\r
+      DbxList   = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
       continue;\r
     }\r
-    HashBase  = mImageBase + Section->PointerToRawData;\r
-    HashSize  = (UINTN) Section->SizeOfRawData;\r
 \r
-    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-    if (!Status) {\r
+    //\r
+    // Calculate the hash value of current db certificate for comparision.\r
+    //\r
+    if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) {\r
       goto Done;\r
     }\r
 \r
-    SumOfBytesHashed += HashSize;\r
-  }\r
-\r
-  //\r
-  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
-  //      data in the file that needs to be added to the hash. This data begins\r
-  //      at file offset SUM_OF_BYTES_HASHED and its length is:\r
-  //             FileSize  -  (CertDirectory->Size)\r
-  //\r
-  if (mImageSize > SumOfBytesHashed) {\r
-    HashBase = mImageBase + SumOfBytesHashed;\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-      //\r
-      // Use PE32 offset.\r
-      //\r
-      HashSize = (UINTN)(\r
-                 mImageSize -\r
-                 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);\r
-    } else {\r
+    SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;\r
+    CertHash          = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);\r
+    CertHashCount     = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;\r
+    for (Index = 0; Index < CertHashCount; Index++) {\r
       //\r
-      // Use PE32+ offset.\r
+      // Iterate each Signature Data Node within this CertList for verify.\r
       //\r
-      HashSize = (UINTN)(\r
-                 mImageSize -\r
-                 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);      \r
+      DbxCertHash = CertHash->SignatureData;\r
+      if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {\r
+        //\r
+        // Hash of Certificate is found in forbidden database.\r
+        //\r
+        IsFound = TRUE;\r
+        goto Done;\r
+      }\r
+      CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);\r
     }\r
 \r
-    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-    if (!Status) {\r
-      goto Done;\r
-    }\r
+    DataSize -= DbxList->SignatureListSize;\r
+    DbxList   = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
   }\r
 \r
-  Status  = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
-\r
 Done:\r
-  if (HashCtx != NULL) {\r
-    FreePool (HashCtx);\r
-  }\r
-  if (SectionHeader != NULL) {\r
-    FreePool (SectionHeader);\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
   }\r
-  return Status;\r
+\r
+  return IsFound;\r
 }\r
 \r
 /**\r
-  Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of \r
-  Pe/Coff image based on the authenticated image hashing in PE/COFF Specification \r
-  8.0 Appendix A\r
+  Check whether the signature list exists in given variable data.\r
 \r
-  @retval EFI_UNSUPPORTED             Hash algorithm is not supported.\r
-  @retval EFI_SUCCESS                 Hash successfully.\r
+  It searches the signature list for the ceritificate hash by CertType.\r
+  If the signature list is found, get the offset of Database for the\r
+  next hash of a certificate.\r
 \r
+  @param[in]  Database      Variable data to save signature list.\r
+  @param[in]  DatabaseSize  Variable size.\r
+  @param[in]  SignatureType The type of the signature.\r
+  @param[out] Offset        The offset to save a new hash of certificate.\r
+\r
+  @return TRUE       The signature list is found in the forbidden database.\r
+  @return FALSE      The signature list is not found in the forbidden database.\r
 **/\r
-EFI_STATUS \r
-HashPeImageByType (\r
-  VOID\r
+BOOLEAN\r
+GetSignaturelistOffset (\r
+  IN  EFI_SIGNATURE_LIST  *Database,\r
+  IN  UINTN               DatabaseSize,\r
+  IN  EFI_GUID            *SignatureType,\r
+  OUT UINTN               *Offset\r
   )\r
 {\r
-  UINT8                     Index;\r
-  WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;\r
-\r
-  PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);\r
-\r
-  for (Index = 0; Index < HASHALG_MAX; Index++) {  \r
-    //\r
-    // Check the Hash algorithm in PE/COFF Authenticode.\r
-    //    According to PKCS#7 Definition: \r
-    //        SignedData ::= SEQUENCE {\r
-    //            version Version,\r
-    //            digestAlgorithms DigestAlgorithmIdentifiers,\r
-    //            contentInfo ContentInfo,\r
-    //            .... }\r
-    //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
-    //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
-    //    Fixed offset (+32) is calculated based on two bytes of length encoding.\r
-     //\r
-    if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
-      //\r
-      // Only support two bytes of Long Form of Length Encoding.\r
-      //\r
-      continue;\r
-    }\r
-\r
-    //    \r
-    if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
-      break;\r
-    }\r
-  }\r
+  EFI_SIGNATURE_LIST      *SigList;\r
+  UINTN                   SiglistSize;\r
 \r
-  if (Index == HASHALG_MAX) {\r
-    return EFI_UNSUPPORTED;\r
+  if ((Database == NULL) || (DatabaseSize == 0)) {\r
+    *Offset = 0;\r
+    return FALSE;\r
   }\r
 \r
-  //\r
-  // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
-  //\r
-  if (!HashPeImage(Index)) {\r
-    return EFI_UNSUPPORTED;\r
+  SigList     = Database;\r
+  SiglistSize = DatabaseSize;\r
+  while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) {\r
+    if (CompareGuid (&SigList->SignatureType, SignatureType)) {\r
+      *Offset = DatabaseSize - SiglistSize;\r
+      return TRUE;\r
+    }\r
+    SiglistSize -= SigList->SignatureListSize;\r
+    SigList      = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);\r
   }\r
-\r
-  return EFI_SUCCESS;\r
+  *Offset = 0;\r
+  return FALSE;\r
 }\r
 \r
 /**\r
-  Enroll a new executable's signature into Signature Database. \r
+  Enroll a new X509 certificate hash into Signature Database (dbx) without\r
+  KEK's authentication.\r
 \r
-  @param[in] PrivateData     The module's private data.\r
-  @param[in] VariableName    Variable name of signature database, must be \r
-                             EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
+  @param[in] PrivateData      The module's private data.\r
+  @param[in] HashAlg          The hash algorithm to enroll the certificate.\r
+  @param[in] RevocationDate   The revocation date of the certificate.\r
+  @param[in] RevocationTime   The revocation time of the certificate.\r
+  @param[in] AlwaysRevocation Indicate whether the certificate is always revoked.\r
 \r
-  @retval   EFI_SUCCESS            New signature is enrolled successfully.\r
+  @retval   EFI_SUCCESS            New X509 is enrolled successfully.\r
   @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
-  @retval   EFI_UNSUPPORTED        Unsupported command.\r
   @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
 \r
 **/\r
 EFI_STATUS\r
-EnrollImageSignatureToSigDB (\r
+EnrollX509HashtoSigDB (\r
   IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
-  IN CHAR16                         *VariableName\r
+  IN UINT32                         HashAlg,\r
+  IN EFI_HII_DATE                   *RevocationDate,\r
+  IN EFI_HII_TIME                   *RevocationTime,\r
+  IN BOOLEAN                        AlwaysRevocation\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  EFI_SIGNATURE_LIST                *SigDBCert;\r
-  EFI_SIGNATURE_DATA                *SigDBCertData;\r
-  VOID                              *Data;\r
-  UINTN                             DataSize;\r
-  UINTN                             SigDBSize;\r
-  UINT32                            Attr;\r
-  WIN_CERTIFICATE_UEFI_GUID         *GuidCertData;\r
+  EFI_STATUS          Status;\r
+  UINTN               X509DataSize;\r
+  VOID                *X509Data;\r
+  EFI_SIGNATURE_LIST  *SignatureList;\r
+  UINTN               SignatureListSize;\r
+  UINT8               *Data;\r
+  UINT8               *NewData;\r
+  UINTN               DataSize;\r
+  UINTN               DbSize;\r
+  UINT32              Attr;\r
+  EFI_SIGNATURE_DATA  *SignatureData;\r
+  UINTN               SignatureSize;\r
+  EFI_GUID            SignatureType;\r
+  UINTN               Offset;\r
+  UINT8               CertHash[MAX_DIGEST_SIZE];\r
+  UINT16*             FilePostFix;\r
+  UINTN               NameLength;\r
+  EFI_TIME            *Time;\r
 \r
-  Data = NULL;\r
-  GuidCertData = NULL;\r
+  X509DataSize  = 0;\r
+  DbSize        = 0;\r
+  X509Data      = NULL;\r
+  SignatureData = NULL;\r
+  SignatureList = NULL;\r
+  Data          = NULL;\r
+  NewData       = NULL;\r
 \r
+  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Parse the file's postfix.\r
   //\r
-  // Form the SigDB certificate list.\r
-  // Format the data item into EFI_SIGNATURE_LIST type.\r
-  //\r
-  // We need to parse executable's signature data from specified signed executable file.\r
-  // In current implementation, we simply trust the pass-in signed executable file.\r
-  // In reality, it's OS's responsibility to verify the signed executable file.\r
-  //\r
+  NameLength = StrLen (Private->FileContext->FileName);\r
+  if (NameLength <= 4) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
+  if (!IsDerEncodeCertificate(FilePostFix)) {\r
+    //\r
+    // Only supports DER-encoded X509 certificate.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   //\r
-  // Read the whole file content\r
+  // Get the certificate from file and calculate its hash.\r
   //\r
-  Status = ReadFileContent(\r
+  Status = ReadFileContent (\r
              Private->FileContext->FHandle,\r
-             (VOID **) &mImageBase, \r
-             &mImageSize, \r
+             &X509Data,\r
+             &X509DataSize,\r
              0\r
              );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
-  }  \r
-  ASSERT (mImageBase != NULL);\r
+  }\r
+  ASSERT (X509Data != NULL);\r
 \r
-  Status = LoadPeImage ();\r
-  if (EFI_ERROR (Status)) {\r
+  if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {\r
     goto ON_EXIT;\r
   }\r
 \r
-  if (mSecDataDir->SizeOfCert == 0) {\r
-    if (!HashPeImage (HASHALG_SHA256)) {\r
-      Status =  EFI_SECURITY_VIOLATION;\r
-      goto ON_EXIT;\r
+  //\r
+  // Get the variable for enrollment.\r
+  //\r
+  DataSize = 0;\r
+  Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+    if (Data == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
     }\r
-  } else {\r
-  \r
-    //\r
-    // Read the certificate data\r
-    //\r
-    mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);\r
-\r
-    if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
-      GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;\r
-      if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {\r
-        Status = EFI_ABORTED;\r
-        goto ON_EXIT;\r
-      }\r
-\r
-      if (!HashPeImage (HASHALG_SHA256)) {\r
-        Status = EFI_ABORTED;\r
-        goto ON_EXIT;;\r
-      }\r
-    \r
-    } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
 \r
-      Status = HashPeImageByType ();\r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_EXIT;;\r
-      }\r
-    } else {\r
-      Status = EFI_ABORTED;\r
+    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
+    if (EFI_ERROR (Status)) {\r
       goto ON_EXIT;\r
     }\r
   }\r
 \r
   //\r
-  // Create a new SigDB entry.\r
+  // Allocate memory for Signature and fill the Signature\r
   //\r
-  SigDBSize = sizeof(EFI_SIGNATURE_LIST) \r
-              + sizeof(EFI_SIGNATURE_DATA) - 1\r
-              + (UINT32) mImageDigestSize;\r
+  SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength;\r
+  SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize);\r
+  if (SignatureData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID);\r
+  CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength);\r
 \r
-  Data = (UINT8*) AllocateZeroPool (SigDBSize);\r
-  if (Data == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
+  //\r
+  // Fill the time.\r
+  //\r
+  if (!AlwaysRevocation) {\r
+    Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength);\r
+    Time->Year   = RevocationDate->Year;\r
+    Time->Month  = RevocationDate->Month;\r
+    Time->Day    = RevocationDate->Day;\r
+    Time->Hour   = RevocationTime->Hour;\r
+    Time->Minute = RevocationTime->Minute;\r
+    Time->Second = RevocationTime->Second;\r
   }\r
-  \r
+\r
   //\r
-  // Adjust the Certificate Database parameters.\r
-  // \r
-  SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
-  SigDBCert->SignatureListSize   = (UINT32) SigDBSize;\r
-  SigDBCert->SignatureHeaderSize = 0;\r
-  SigDBCert->SignatureSize       = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;\r
-  CopyGuid (&SigDBCert->SignatureType, &mCertType);\r
+  // Determine the GUID for certificate hash.\r
+  //\r
+  switch (HashAlg) {\r
+  case HASHALG_SHA256:\r
+    SignatureType = gEfiCertX509Sha256Guid;\r
+    break;\r
+  case HASHALG_SHA384:\r
+    SignatureType = gEfiCertX509Sha384Guid;\r
+    break;\r
+  case HASHALG_SHA512:\r
+    SignatureType = gEfiCertX509Sha512Guid;\r
+    break;\r
+  default:\r
+    return FALSE;\r
+  }\r
 \r
-  SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));\r
-  CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
-  CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);\r
+  //\r
+  // Add signature into the new variable data buffer\r
+  //\r
+  if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) {\r
+    //\r
+    // Add the signature to the found signaturelist.\r
+    //\r
+    DbSize  = DataSize + SignatureSize;\r
+    NewData = AllocateZeroPool (DbSize);\r
+    if (NewData == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_EXIT;\r
+    }\r
 \r
-  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
-          | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
-  Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
+    SignatureList     = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
+    SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize);\r
+    CopyMem (NewData, Data, Offset + SignatureListSize);\r
+\r
+    SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset);\r
+    WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize));\r
+\r
+    Offset += SignatureListSize;\r
+    CopyMem (NewData + Offset, SignatureData, SignatureSize);\r
+    CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset);\r
+\r
+    FreePool (Data);\r
+    Data     = NewData;\r
+    DataSize = DbSize;\r
+  } else {\r
+    //\r
+    // Create a new signaturelist, and add the signature into the signaturelist.\r
+    //\r
+    DbSize  = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize;\r
+    NewData = AllocateZeroPool (DbSize);\r
+    if (NewData == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_EXIT;\r
+    }\r
+    //\r
+    // Fill Certificate Database parameters.\r
+    //\r
+    SignatureList     = (EFI_SIGNATURE_LIST*) (NewData + DataSize);\r
+    SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize;\r
+    WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize);\r
+    WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize);\r
+    CopyGuid (&SignatureList->SignatureType, &SignatureType);\r
+    CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize);\r
+    if ((DataSize != 0) && (Data != NULL)) {\r
+      CopyMem (NewData, Data, DataSize);\r
+      FreePool (Data);\r
+    }\r
+    Data     = NewData;\r
+    DataSize = DbSize;\r
+  }\r
+\r
+  Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
     goto ON_EXIT;\r
   }\r
-  \r
-  //\r
-  // Check if SigDB variable has been already existed. \r
-  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the \r
-  // new signature data to original variable\r
-  //    \r
-  DataSize = 0;\r
-  Status = gRT->GetVariable(\r
-                  VariableName, \r
-                  &gEfiImageSecurityDatabaseGuid, \r
-                  NULL, \r
-                  &DataSize, \r
-                  NULL\r
-                  );\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    Attr |= EFI_VARIABLE_APPEND_WRITE;\r
-  } else if (Status != EFI_NOT_FOUND) {\r
-    goto ON_EXIT;\r
-  }  \r
 \r
-  //\r
-  // Enroll the variable.\r
-  //\r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
+          | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
   Status = gRT->SetVariable(\r
-                  VariableName, \r
-                  &gEfiImageSecurityDatabaseGuid, \r
-                  Attr, \r
-                  SigDBSize, \r
+                  EFI_IMAGE_SECURITY_DATABASE1,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  Attr,\r
+                  DataSize,\r
                   Data\r
                   );\r
   if (EFI_ERROR (Status)) {\r
@@ -1419,9 +1585,7 @@ EnrollImageSignatureToSigDB (
 \r
 ON_EXIT:\r
 \r
-  CloseFile (Private->FileContext->FHandle);\r
-  Private->FileContext->FHandle = NULL;\r
-  Private->FileContext->FileName = NULL;\r
+  CloseEnrolledFile(Private->FileContext);\r
 \r
   if (Private->SignatureGUID != NULL) {\r
     FreePool (Private->SignatureGUID);\r
@@ -1432,831 +1596,2678 @@ ON_EXIT:
     FreePool (Data);\r
   }\r
 \r
-  if (mImageBase != NULL) {\r
-    FreePool (mImageBase);\r
-    mImageBase = NULL;\r
+  if (SignatureData != NULL) {\r
+    FreePool (SignatureData);\r
+  }\r
+\r
+  if (X509Data != NULL) {\r
+    FreePool (X509Data);\r
   }\r
 \r
   return Status;\r
 }\r
 \r
 /**\r
-  Enroll signature into DB/DBX without KEK's authentication.\r
-  The SignatureOwner GUID will be Private->SignatureGUID.\r
-  \r
+  Check whether a certificate from a file exists in dbx.\r
+\r
   @param[in] PrivateData     The module's private data.\r
-  @param[in] VariableName    Variable name of signature database, must be \r
-                             EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
-  \r
-  @retval   EFI_SUCCESS            New signature enrolled successfully.\r
-  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
-  @retval   others                 Fail to enroll signature data.\r
-  \r
+  @param[in] VariableName    Variable name of signature database, must be\r
+                             EFI_IMAGE_SECURITY_DATABASE1.\r
+\r
+  @retval   TRUE             The X509 certificate is found in dbx successfully.\r
+  @retval   FALSE            The X509 certificate is not found in dbx.\r
 **/\r
-EFI_STATUS\r
-EnrollSignatureDatabase (\r
-  IN SECUREBOOT_CONFIG_PRIVATE_DATA     *Private,\r
-  IN CHAR16                             *VariableName\r
-  ) \r
+BOOLEAN\r
+IsX509CertInDbx (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
+  IN CHAR16                         *VariableName\r
+  )\r
 {\r
-  UINT16*      FilePostFix;\r
+  EFI_STATUS          Status;\r
+  UINTN               X509DataSize;\r
+  VOID                *X509Data;\r
+  BOOLEAN             IsFound;\r
 \r
-  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
+  //\r
+  //  Read the certificate from file\r
+  //\r
+  X509DataSize  = 0;\r
+  X509Data      = NULL;\r
+  Status = ReadFileContent (\r
+             Private->FileContext->FHandle,\r
+             &X509Data,\r
+             &X509DataSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
   }\r
 \r
   //\r
-  // Parse the file's postfix. \r
+  // Check the raw certificate.\r
   //\r
-  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
-  if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) {\r
-    //\r
-    // Supports .cer and .der file as X509 certificate.\r
-    //\r
-    return EnrollX509toSigDB (Private, VariableName);\r
+  IsFound = FALSE;\r
+  if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) {\r
+    IsFound = TRUE;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Check the hash of certificate.\r
+  //\r
+  if (IsCertHashFoundInDbx (X509Data, X509DataSize)) {\r
+    IsFound = TRUE;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+  if (X509Data != NULL) {\r
+    FreePool (X509Data);\r
   }\r
 \r
-  return EnrollImageSignatureToSigDB (Private, VariableName);\r
+  return IsFound;\r
 }\r
 \r
 /**\r
-  List all signatures in specified signature database (e.g. KEK/DB/DBX)\r
-  by GUID in the page for user to select and delete as needed.\r
+  Reads contents of a PE/COFF image in memory buffer.\r
 \r
-  @param[in]    PrivateData         Module's private data.\r
-  @param[in]    VariableName        The variable name of the vendor's signature database.\r
-  @param[in]    VendorGuid          A unique identifier for the vendor.\r
-  @param[in]    LabelNumber         Label number to insert opcodes.\r
-  @param[in]    FormId              Form ID of current page.\r
-  @param[in]    QuestionIdBase      Base question id of the signature list.\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
 \r
-  @retval   EFI_SUCCESS             Success to update the signature list page\r
-  @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.\r
-  \r
+  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.\r
+  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.\r
+  @param  ReadSize        On input, the size in bytes of the requested read operation.\r
+                          On output, the number of bytes actually read.\r
+  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.\r
+\r
+  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size\r
 **/\r
 EFI_STATUS\r
-UpdateDeletePage (\r
-  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
-  IN CHAR16                           *VariableName,\r
-  IN EFI_GUID                         *VendorGuid,\r
-  IN UINT16                           LabelNumber,\r
-  IN EFI_FORM_ID                      FormId,\r
-  IN EFI_QUESTION_ID                  QuestionIdBase\r
+EFIAPI\r
+SecureBootConfigImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINT32                      Index;\r
-  UINTN                       CertCount;\r
-  UINTN                       GuidIndex;\r
-  VOID                        *StartOpCodeHandle;\r
-  VOID                        *EndOpCodeHandle;\r
-  EFI_IFR_GUID_LABEL          *StartLabel;\r
-  EFI_IFR_GUID_LABEL          *EndLabel;  \r
-  UINTN                       DataSize;\r
-  UINT8                       *Data;\r
-  EFI_SIGNATURE_LIST          *CertList;\r
-  EFI_SIGNATURE_DATA          *Cert;\r
-  UINT32                      ItemDataSize;\r
-  CHAR16                      *GuidStr;\r
-  EFI_STRING_ID               GuidID;\r
-  EFI_STRING_ID               Help;\r
+  UINTN               EndPosition;\r
 \r
-  Data     = NULL;\r
-  CertList = NULL;\r
-  Cert     = NULL;\r
-  GuidStr  = NULL;\r
-  StartOpCodeHandle = NULL;\r
-  EndOpCodeHandle   = NULL;\r
-  \r
-  //\r
-  // Initialize the container for dynamic opcodes.\r
-  //\r
-  StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
-  if (StartOpCodeHandle == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT; \r
+  if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
-  if (EndOpCodeHandle == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT; \r
+  if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  //\r
-  // Create Hii Extend Label OpCode.\r
-  //\r
-  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
-                                        StartOpCodeHandle,\r
-                                        &gEfiIfrTianoGuid,\r
-                                        NULL,\r
-                                        sizeof (EFI_IFR_GUID_LABEL)\r
-                                        );\r
-  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
-  StartLabel->Number        = LabelNumber;\r
-\r
-  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
-                                      EndOpCodeHandle,\r
-                                      &gEfiIfrTianoGuid,\r
-                                      NULL,\r
-                                      sizeof (EFI_IFR_GUID_LABEL)\r
-                                      );\r
-  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
-  EndLabel->Number        = LABEL_END;\r
-\r
-  //\r
-  // Read Variable.\r
-  //\r
-  DataSize = 0;\r
-  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);  \r
-  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
-    goto ON_EXIT;\r
+  EndPosition = FileOffset + *ReadSize;\r
+  if (EndPosition > mImageSize) {\r
+    *ReadSize = (UINT32)(mImageSize - FileOffset);\r
   }\r
 \r
-  Data = (UINT8 *) AllocateZeroPool (DataSize);\r
-  if (Data == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
+  if (FileOffset >= mImageSize) {\r
+    *ReadSize = 0;\r
   }\r
 \r
-  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
+  CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Load PE/COFF image information into internal buffer and check its validity.\r
+\r
+  @retval   EFI_SUCCESS         Successful\r
+  @retval   EFI_UNSUPPORTED     Invalid PE/COFF file\r
+  @retval   EFI_ABORTED         Serious error occurs, like file I/O error etc.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadPeImage (\r
+  VOID\r
+  )\r
+{\r
+  EFI_IMAGE_DOS_HEADER                  *DosHdr;\r
+  EFI_IMAGE_NT_HEADERS32                *NtHeader32;\r
+  EFI_IMAGE_NT_HEADERS64                *NtHeader64;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  EFI_STATUS                            Status;\r
+\r
+  NtHeader32 = NULL;\r
+  NtHeader64 = NULL;\r
+\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+  ImageContext.Handle    = (VOID *) mImageBase;\r
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecureBootConfigImageRead;\r
+\r
+  //\r
+  // Get information about the image being loaded\r
+  //\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // The information can't be got from the invalid PeImage\r
+    //\r
+    DEBUG ((DEBUG_INFO, "SecureBootConfigDxe: PeImage invalid. \n"));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Read the Dos header\r
+  //\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase);\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)\r
+  {\r
+    //\r
+    // DOS image header is present,\r
+    // So read the PE header after the DOS image header\r
+    //\r
+    mPeCoffHeaderOffset = DosHdr->e_lfanew;\r
+  }\r
+  else\r
+  {\r
+    mPeCoffHeaderOffset = 0;\r
+  }\r
+\r
+  //\r
+  // Read PE header and check the signature validity and machine compatibility\r
+  //\r
+  NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset);\r
+  if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE)\r
+  {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  mNtHeader.Pe32 = NtHeader32;\r
+\r
+  //\r
+  // Check the architecture field of PE header and get the Certificate Data Directory data\r
+  // Note the size of FileHeader field is constant for both IA32 and X64 arch\r
+  //\r
+  if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)\r
+      || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)\r
+      || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)) {\r
+    //\r
+    // 32-bits Architecture\r
+    //\r
+    mImageType = ImageType_IA32;\r
+    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
+  }\r
+  else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)\r
+          || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)\r
+          || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64)) {\r
+    //\r
+    // 64-bits Architecture\r
+    //\r
+    mImageType = ImageType_X64;\r
+    NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);\r
+    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Calculate hash of Pe/Coff image based on the authenticode image hashing in\r
+  PE/COFF Specification 8.0 Appendix A\r
+\r
+  Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in \r
+  the function LoadPeImage ().\r
+\r
+  @param[in]    HashAlg   Hash algorithm type.\r
+\r
+  @retval TRUE            Successfully hash image.\r
+  @retval FALSE           Fail in hash image.\r
+\r
+**/\r
+BOOLEAN\r
+HashPeImage (\r
+  IN  UINT32                HashAlg\r
+  )\r
+{\r
+  BOOLEAN                   Status;\r
+  UINT16                    Magic;\r
+  EFI_IMAGE_SECTION_HEADER  *Section;\r
+  VOID                      *HashCtx;\r
+  UINTN                     CtxSize;\r
+  UINT8                     *HashBase;\r
+  UINTN                     HashSize;\r
+  UINTN                     SumOfBytesHashed;\r
+  EFI_IMAGE_SECTION_HEADER  *SectionHeader;\r
+  UINTN                     Index;\r
+  UINTN                     Pos;\r
+\r
+  HashCtx       = NULL;\r
+  SectionHeader = NULL;\r
+  Status        = FALSE;\r
+\r
+  if (HashAlg != HASHALG_SHA256) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Initialize context of hash.\r
+  //\r
+  ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
+\r
+  mImageDigestSize  = SHA256_DIGEST_SIZE;\r
+  mCertType         = gEfiCertSha256Guid;\r
+\r
+  CtxSize   = mHash[HashAlg].GetContextSize();\r
+\r
+  HashCtx = AllocatePool (CtxSize);\r
+  ASSERT (HashCtx != NULL);\r
+\r
+  // 1.  Load the image header into memory.\r
+\r
+  // 2.  Initialize a SHA hash context.\r
+  Status = mHash[HashAlg].HashInit(HashCtx);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Measuring PE/COFF Image Header;\r
+  // But CheckSum field and SECURITY data directory (certificate) are excluded\r
+  //\r
+  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
+    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
+    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+    //\r
+    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+  } else {\r
+    //\r
+    // Get the magic value from the PE/COFF Optional Header\r
+    //\r
+    Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+  }\r
+\r
+  //\r
+  // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
+  // 4.  Hash the image header from its base to beginning of the image checksum.\r
+  //\r
+  HashBase = mImageBase;\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset.\r
+    //\r
+    HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //\r
+    HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // 5.  Skip over the image checksum (it occupies a single ULONG).\r
+  // 6.  Get the address of the beginning of the Cert Directory.\r
+  // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
+  //\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset.\r
+    //\r
+    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+    HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //\r
+    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+    HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
+  // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
+  //\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset\r
+    //\r
+    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+    HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase);\r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //\r
+    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+    HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase);\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
+  //\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset.\r
+    //\r
+    SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
+  } else {\r
+    //\r
+    // Use PE32+ offset\r
+    //\r
+    SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
+  }\r
+\r
+  //\r
+  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
+  //     structures in the image. The 'NumberOfSections' field of the image\r
+  //     header indicates how big the table should be. Do not include any\r
+  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
+  ASSERT (SectionHeader != NULL);\r
+  //\r
+  // 12.  Using the 'PointerToRawData' in the referenced section headers as\r
+  //      a key, arrange the elements in the table in ascending order. In other\r
+  //      words, sort the section headers according to the disk-file offset of\r
+  //      the section.\r
+  //\r
+  Section = (EFI_IMAGE_SECTION_HEADER *) (\r
+               mImageBase +\r
+               mPeCoffHeaderOffset +\r
+               sizeof (UINT32) +\r
+               sizeof (EFI_IMAGE_FILE_HEADER) +\r
+               mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
+               );\r
+  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
+    Pos = Index;\r
+    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
+      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
+      Pos--;\r
+    }\r
+    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
+    Section += 1;\r
+  }\r
+\r
+  //\r
+  // 13.  Walk through the sorted table, bring the corresponding section\r
+  //      into memory, and hash the entire section (using the 'SizeOfRawData'\r
+  //      field in the section header to determine the amount of data to hash).\r
+  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
+  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.\r
+  //\r
+  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
+    Section = &SectionHeader[Index];\r
+    if (Section->SizeOfRawData == 0) {\r
+      continue;\r
+    }\r
+    HashBase  = mImageBase + Section->PointerToRawData;\r
+    HashSize  = (UINTN) Section->SizeOfRawData;\r
+\r
+    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+    if (!Status) {\r
+      goto Done;\r
+    }\r
+\r
+    SumOfBytesHashed += HashSize;\r
+  }\r
+\r
+  //\r
+  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
+  //      data in the file that needs to be added to the hash. This data begins\r
+  //      at file offset SUM_OF_BYTES_HASHED and its length is:\r
+  //             FileSize  -  (CertDirectory->Size)\r
+  //\r
+  if (mImageSize > SumOfBytesHashed) {\r
+    HashBase = mImageBase + SumOfBytesHashed;\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset.\r
+      //\r
+      HashSize = (UINTN)(\r
+                 mImageSize -\r
+                 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+                 SumOfBytesHashed);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset.\r
+      //\r
+      HashSize = (UINTN)(\r
+                 mImageSize -\r
+                 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+                 SumOfBytesHashed);\r
+    }\r
+\r
+    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+    if (!Status) {\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
+\r
+Done:\r
+  if (HashCtx != NULL) {\r
+    FreePool (HashCtx);\r
+  }\r
+  if (SectionHeader != NULL) {\r
+    FreePool (SectionHeader);\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of\r
+  Pe/Coff image based on the authenticated image hashing in PE/COFF Specification\r
+  8.0 Appendix A\r
+\r
+  @retval EFI_UNSUPPORTED             Hash algorithm is not supported.\r
+  @retval EFI_SUCCESS                 Hash successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+HashPeImageByType (\r
+  VOID\r
+  )\r
+{\r
+  UINT8                     Index;\r
+  WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;\r
+\r
+  PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset);\r
+\r
+  for (Index = 0; Index < HASHALG_MAX; Index++) {\r
+    //\r
+    // Check the Hash algorithm in PE/COFF Authenticode.\r
+    //    According to PKCS#7 Definition:\r
+    //        SignedData ::= SEQUENCE {\r
+    //            version Version,\r
+    //            digestAlgorithms DigestAlgorithmIdentifiers,\r
+    //            contentInfo ContentInfo,\r
+    //            .... }\r
+    //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
+    //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
+    //    Fixed offset (+32) is calculated based on two bytes of length encoding.\r
+     //\r
+    if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
+      //\r
+      // Only support two bytes of Long Form of Length Encoding.\r
+      //\r
+      continue;\r
+    }\r
+\r
+    //\r
+    if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index == HASHALG_MAX) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.\r
+  //\r
+  if (!HashPeImage(Index)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Enroll a new executable's signature into Signature Database.\r
+\r
+  @param[in] PrivateData     The module's private data.\r
+  @param[in] VariableName    Variable name of signature database, must be\r
+                             EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1\r
+                             or EFI_IMAGE_SECURITY_DATABASE2.\r
+\r
+  @retval   EFI_SUCCESS            New signature is enrolled successfully.\r
+  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
+  @retval   EFI_UNSUPPORTED        Unsupported command.\r
+  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EnrollAuthentication2Descriptor (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
+  IN CHAR16                         *VariableName\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  VOID                              *Data;\r
+  UINTN                             DataSize;\r
+  UINT32                            Attr;\r
+\r
+  Data = NULL;\r
+\r
+  //\r
+  // DBT only support DER-X509 Cert Enrollment\r
+  //\r
+  if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Read the whole file content\r
+  //\r
+  Status = ReadFileContent(\r
+             Private->FileContext->FHandle,\r
+             (VOID **) &mImageBase,\r
+             &mImageSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (mImageBase != NULL);\r
+\r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
+         | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
+\r
+  //\r
+  // Check if SigDB variable has been already existed.\r
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
+  // new signature data to original variable\r
+  //\r
+  DataSize = 0;\r
+  Status = gRT->GetVariable(\r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  NULL\r
+                  );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    Attr |= EFI_VARIABLE_APPEND_WRITE;\r
+  } else if (Status != EFI_NOT_FOUND) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Diretly set AUTHENTICATION_2 data to SetVariable\r
+  //\r
+  Status = gRT->SetVariable(\r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  Attr,\r
+                  mImageSize,\r
+                  mImageBase\r
+                  );\r
+\r
+  DEBUG((DEBUG_INFO, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName, Status));\r
+\r
+ON_EXIT:\r
+\r
+  CloseEnrolledFile(Private->FileContext);\r
+\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
+  }\r
+\r
+  if (mImageBase != NULL) {\r
+    FreePool (mImageBase);\r
+    mImageBase = NULL;\r
+  }\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Enroll a new executable's signature into Signature Database.\r
+\r
+  @param[in] PrivateData     The module's private data.\r
+  @param[in] VariableName    Variable name of signature database, must be\r
+                             EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1\r
+                             or EFI_IMAGE_SECURITY_DATABASE2.\r
+\r
+  @retval   EFI_SUCCESS            New signature is enrolled successfully.\r
+  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
+  @retval   EFI_UNSUPPORTED        Unsupported command.\r
+  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EnrollImageSignatureToSigDB (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
+  IN CHAR16                         *VariableName\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_SIGNATURE_LIST                *SigDBCert;\r
+  EFI_SIGNATURE_DATA                *SigDBCertData;\r
+  VOID                              *Data;\r
+  UINTN                             DataSize;\r
+  UINTN                             SigDBSize;\r
+  UINT32                            Attr;\r
+  WIN_CERTIFICATE_UEFI_GUID         *GuidCertData;\r
+\r
+  Data = NULL;\r
+  GuidCertData = NULL;\r
+\r
+  if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Form the SigDB certificate list.\r
+  // Format the data item into EFI_SIGNATURE_LIST type.\r
+  //\r
+  // We need to parse executable's signature data from specified signed executable file.\r
+  // In current implementation, we simply trust the pass-in signed executable file.\r
+  // In reality, it's OS's responsibility to verify the signed executable file.\r
+  //\r
+\r
+  //\r
+  // Read the whole file content\r
+  //\r
+  Status = ReadFileContent(\r
+             Private->FileContext->FHandle,\r
+             (VOID **) &mImageBase,\r
+             &mImageSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (mImageBase != NULL);\r
+\r
+  Status = LoadPeImage ();\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (mSecDataDir->SizeOfCert == 0) {\r
+    if (!HashPeImage (HASHALG_SHA256)) {\r
+      Status =  EFI_SECURITY_VIOLATION;\r
+      goto ON_EXIT;\r
+    }\r
+  } else {\r
+\r
+    //\r
+    // Read the certificate data\r
+    //\r
+    mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset);\r
+\r
+    if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
+      GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate;\r
+      if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) {\r
+        Status = EFI_ABORTED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      if (!HashPeImage (HASHALG_SHA256)) {\r
+        Status = EFI_ABORTED;\r
+        goto ON_EXIT;;\r
+      }\r
+\r
+    } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
+\r
+      Status = HashPeImageByType ();\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_EXIT;;\r
+      }\r
+    } else {\r
+      Status = EFI_ABORTED;\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Create a new SigDB entry.\r
+  //\r
+  SigDBSize = sizeof(EFI_SIGNATURE_LIST)\r
+              + sizeof(EFI_SIGNATURE_DATA) - 1\r
+              + (UINT32) mImageDigestSize;\r
+\r
+  Data = (UINT8*) AllocateZeroPool (SigDBSize);\r
+  if (Data == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Adjust the Certificate Database parameters.\r
+  //\r
+  SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
+  SigDBCert->SignatureListSize   = (UINT32) SigDBSize;\r
+  SigDBCert->SignatureHeaderSize = 0;\r
+  SigDBCert->SignatureSize       = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize;\r
+  CopyGuid (&SigDBCert->SignatureType, &mCertType);\r
+\r
+  SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST));\r
+  CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
+  CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize);\r
+\r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS\r
+          | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
+  Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Check if SigDB variable has been already existed.\r
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the\r
+  // new signature data to original variable\r
+  //\r
+  DataSize = 0;\r
+  Status = gRT->GetVariable(\r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  NULL,\r
+                  &DataSize,\r
+                  NULL\r
+                  );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    Attr |= EFI_VARIABLE_APPEND_WRITE;\r
+  } else if (Status != EFI_NOT_FOUND) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Enroll the variable.\r
+  //\r
+  Status = gRT->SetVariable(\r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  Attr,\r
+                  SigDBSize,\r
+                  Data\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+\r
+  CloseEnrolledFile(Private->FileContext);\r
+\r
+  if (Private->SignatureGUID != NULL) {\r
+    FreePool (Private->SignatureGUID);\r
+    Private->SignatureGUID = NULL;\r
+  }\r
+\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
+  }\r
+\r
+  if (mImageBase != NULL) {\r
+    FreePool (mImageBase);\r
+    mImageBase = NULL;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enroll signature into DB/DBX/DBT without KEK's authentication.\r
+  The SignatureOwner GUID will be Private->SignatureGUID.\r
+\r
+  @param[in] PrivateData     The module's private data.\r
+  @param[in] VariableName    Variable name of signature database, must be\r
+                             EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
+\r
+  @retval   EFI_SUCCESS            New signature enrolled successfully.\r
+  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.\r
+  @retval   others                 Fail to enroll signature data.\r
+\r
+**/\r
+EFI_STATUS\r
+EnrollSignatureDatabase (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA     *Private,\r
+  IN CHAR16                             *VariableName\r
+  )\r
+{\r
+  UINT16*      FilePostFix;\r
+  EFI_STATUS   Status;\r
+  UINTN        NameLength;\r
+\r
+  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Parse the file's postfix.\r
+  //\r
+  NameLength = StrLen (Private->FileContext->FileName);\r
+  if (NameLength <= 4) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
+  if (IsDerEncodeCertificate (FilePostFix)) {\r
+    //\r
+    // Supports DER-encoded X509 certificate.\r
+    //\r
+    return EnrollX509toSigDB (Private, VariableName);\r
+  } else if (IsAuthentication2Format(Private->FileContext->FHandle)){\r
+    return EnrollAuthentication2Descriptor(Private, VariableName);\r
+  } else {\r
+    return EnrollImageSignatureToSigDB (Private, VariableName);\r
+  }\r
+}\r
+\r
+/**\r
+  List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT)\r
+  by GUID in the page for user to select and delete as needed.\r
+\r
+  @param[in]    PrivateData         Module's private data.\r
+  @param[in]    VariableName        The variable name of the vendor's signature database.\r
+  @param[in]    VendorGuid          A unique identifier for the vendor.\r
+  @param[in]    LabelNumber         Label number to insert opcodes.\r
+  @param[in]    FormId              Form ID of current page.\r
+  @param[in]    QuestionIdBase      Base question id of the signature list.\r
+\r
+  @retval   EFI_SUCCESS             Success to update the signature list page\r
+  @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateDeletePage (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
+  IN CHAR16                           *VariableName,\r
+  IN EFI_GUID                         *VendorGuid,\r
+  IN UINT16                           LabelNumber,\r
+  IN EFI_FORM_ID                      FormId,\r
+  IN EFI_QUESTION_ID                  QuestionIdBase\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINT32                      Index;\r
+  UINTN                       CertCount;\r
+  UINTN                       GuidIndex;\r
+  VOID                        *StartOpCodeHandle;\r
+  VOID                        *EndOpCodeHandle;\r
+  EFI_IFR_GUID_LABEL          *StartLabel;\r
+  EFI_IFR_GUID_LABEL          *EndLabel;\r
+  UINTN                       DataSize;\r
+  UINT8                       *Data;\r
+  EFI_SIGNATURE_LIST          *CertList;\r
+  EFI_SIGNATURE_DATA          *Cert;\r
+  UINT32                      ItemDataSize;\r
+  CHAR16                      *GuidStr;\r
+  EFI_STRING_ID               GuidID;\r
+  EFI_STRING_ID               Help;\r
+\r
+  Data     = NULL;\r
+  CertList = NULL;\r
+  Cert     = NULL;\r
+  GuidStr  = NULL;\r
+  StartOpCodeHandle = NULL;\r
+  EndOpCodeHandle   = NULL;\r
+\r
+  //\r
+  // Initialize the container for dynamic opcodes.\r
+  //\r
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (StartOpCodeHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (EndOpCodeHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Create Hii Extend Label OpCode.\r
+  //\r
+  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
+                                        StartOpCodeHandle,\r
+                                        &gEfiIfrTianoGuid,\r
+                                        NULL,\r
+                                        sizeof (EFI_IFR_GUID_LABEL)\r
+                                        );\r
+  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
+  StartLabel->Number        = LabelNumber;\r
+\r
+  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
+                                      EndOpCodeHandle,\r
+                                      &gEfiIfrTianoGuid,\r
+                                      NULL,\r
+                                      sizeof (EFI_IFR_GUID_LABEL)\r
+                                      );\r
+  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
+  EndLabel->Number        = LABEL_END;\r
+\r
+  //\r
+  // Read Variable.\r
+  //\r
+  DataSize = 0;\r
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  GuidStr = AllocateZeroPool (100);\r
+  if (GuidStr == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Enumerate all KEK pub data.\r
+  //\r
+  ItemDataSize = (UINT32) DataSize;\r
+  CertList = (EFI_SIGNATURE_LIST *) Data;\r
+  GuidIndex = 0;\r
+\r
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
+\r
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {\r
+      Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);\r
+    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+      Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);\r
+    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {\r
+      Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);\r
+    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {\r
+      Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);\r
+    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
+      Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID);\r
+    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
+      Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID);\r
+    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
+      Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID);\r
+    } else {\r
+      //\r
+      // The signature type is not supported in current implementation.\r
+      //\r
+      ItemDataSize -= CertList->SignatureListSize;\r
+      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+      continue;\r
+    }\r
+\r
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+    for (Index = 0; Index < CertCount; Index++) {\r
+      Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList\r
+                                              + sizeof (EFI_SIGNATURE_LIST)\r
+                                              + CertList->SignatureHeaderSize\r
+                                              + Index * CertList->SignatureSize);\r
+      //\r
+      // Display GUID and help\r
+      //\r
+      GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
+      GuidID  = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);\r
+      HiiCreateCheckBoxOpCode (\r
+        StartOpCodeHandle,\r
+        (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
+        0,\r
+        0,\r
+        GuidID,\r
+        Help,\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        0,\r
+        NULL\r
+        );\r
+    }\r
+\r
+    ItemDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+ON_EXIT:\r
+  HiiUpdateForm (\r
+    PrivateData->HiiHandle,\r
+    &gSecureBootConfigFormSetGuid,\r
+    FormId,\r
+    StartOpCodeHandle,\r
+    EndOpCodeHandle\r
+    );\r
+\r
+  if (StartOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (StartOpCodeHandle);\r
+  }\r
+\r
+  if (EndOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (EndOpCodeHandle);\r
+  }\r
+\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
+  }\r
+\r
+  if (GuidStr != NULL) {\r
+    FreePool (GuidStr);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Delete a KEK entry from KEK database.\r
+\r
+  @param[in]    PrivateData         Module's private data.\r
+  @param[in]    QuestionId          Question id of the KEK item to delete.\r
+\r
+  @retval   EFI_SUCCESS            Delete kek item successfully.\r
+  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteKeyExchangeKey (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
+  IN EFI_QUESTION_ID                  QuestionId\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINTN                       DataSize;\r
+  UINT8                       *Data;\r
+  UINT8                       *OldData;\r
+  UINT32                      Attr;\r
+  UINT32                      Index;\r
+  EFI_SIGNATURE_LIST          *CertList;\r
+  EFI_SIGNATURE_LIST          *NewCertList;\r
+  EFI_SIGNATURE_DATA          *Cert;\r
+  UINTN                       CertCount;\r
+  UINT32                      Offset;\r
+  BOOLEAN                     IsKEKItemFound;\r
+  UINT32                      KekDataSize;\r
+  UINTN                       DeleteKekIndex;\r
+  UINTN                       GuidIndex;\r
+\r
+  Data            = NULL;\r
+  OldData         = NULL;\r
+  CertList        = NULL;\r
+  Cert            = NULL;\r
+  Attr            = 0;\r
+  DeleteKekIndex  = QuestionId - OPTION_DEL_KEK_QUESTION_ID;\r
+\r
+  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get original KEK variable.\r
+  //\r
+  DataSize = 0;\r
+  Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
+  if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  OldData = (UINT8*)AllocateZeroPool(DataSize);\r
+  if (OldData == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);\r
+  if (EFI_ERROR(Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Allocate space for new variable.\r
+  //\r
+  Data = (UINT8*) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    Status  =  EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Enumerate all KEK pub data and erasing the target item.\r
+  //\r
+  IsKEKItemFound = FALSE;\r
+  KekDataSize = (UINT32) DataSize;\r
+  CertList = (EFI_SIGNATURE_LIST *) OldData;\r
+  Offset = 0;\r
+  GuidIndex = 0;\r
+  while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
+        CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
+      NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
+      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+      Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+      CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+      for (Index = 0; Index < CertCount; Index++) {\r
+        if (GuidIndex == DeleteKekIndex ) {\r
+          //\r
+          // Find it! Skip it!\r
+          //\r
+          NewCertList->SignatureListSize -= CertList->SignatureSize;\r
+          IsKEKItemFound = TRUE;\r
+        } else {\r
+          //\r
+          // This item doesn't match. Copy it to the Data buffer.\r
+          //\r
+          CopyMem (Data + Offset, Cert, CertList->SignatureSize);\r
+          Offset += CertList->SignatureSize;\r
+        }\r
+        GuidIndex++;\r
+        Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);\r
+      }\r
+    } else {\r
+      //\r
+      // This List doesn't match. Copy it to the Data buffer.\r
+      //\r
+      CopyMem (Data + Offset, CertList, CertList->SignatureListSize);\r
+      Offset += CertList->SignatureListSize;\r
+    }\r
+\r
+    KekDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+  if (!IsKEKItemFound) {\r
+    //\r
+    // Doesn't find the Kek Item!\r
+    //\r
+    Status = EFI_NOT_FOUND;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Delete the Signature header if there is no signature in the list.\r
+  //\r
+  KekDataSize = Offset;\r
+  CertList = (EFI_SIGNATURE_LIST*) Data;\r
+  Offset = 0;\r
+  ZeroMem (OldData, KekDataSize);\r
+  while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));\r
+    if (CertCount != 0) {\r
+      CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
+      Offset += CertList->SignatureListSize;\r
+    }\r
+    KekDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+  DataSize = Offset;\r
+  if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+\r
+  Status = gRT->SetVariable(\r
+                  EFI_KEY_EXCHANGE_KEY_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  Attr,\r
+                  DataSize,\r
+                  OldData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+  if (Data != NULL) {\r
+    FreePool(Data);\r
+  }\r
+\r
+  if (OldData != NULL) {\r
+    FreePool(OldData);\r
+  }\r
+\r
+  return UpdateDeletePage (\r
+           PrivateData,\r
+           EFI_KEY_EXCHANGE_KEY_NAME,\r
+           &gEfiGlobalVariableGuid,\r
+           LABEL_KEK_DELETE,\r
+           FORMID_DELETE_KEK_FORM,\r
+           OPTION_DEL_KEK_QUESTION_ID\r
+           );\r
+}\r
+\r
+/**\r
+  Delete a signature entry from signature database.\r
+\r
+  @param[in]    PrivateData         Module's private data.\r
+  @param[in]    VariableName        The variable name of the vendor's signature database.\r
+  @param[in]    VendorGuid          A unique identifier for the vendor.\r
+  @param[in]    LabelNumber         Label number to insert opcodes.\r
+  @param[in]    FormId              Form ID of current page.\r
+  @param[in]    QuestionIdBase      Base question id of the signature list.\r
+  @param[in]    DeleteIndex         Signature index to delete.\r
+\r
+  @retval   EFI_SUCCESS             Delete signature successfully.\r
+  @retval   EFI_NOT_FOUND           Can't find the signature item,\r
+  @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.\r
+**/\r
+EFI_STATUS\r
+DeleteSignature (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
+  IN CHAR16                           *VariableName,\r
+  IN EFI_GUID                         *VendorGuid,\r
+  IN UINT16                           LabelNumber,\r
+  IN EFI_FORM_ID                      FormId,\r
+  IN EFI_QUESTION_ID                  QuestionIdBase,\r
+  IN UINTN                            DeleteIndex\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINTN                       DataSize;\r
+  UINT8                       *Data;\r
+  UINT8                       *OldData;\r
+  UINT32                      Attr;\r
+  UINT32                      Index;\r
+  EFI_SIGNATURE_LIST          *CertList;\r
+  EFI_SIGNATURE_LIST          *NewCertList;\r
+  EFI_SIGNATURE_DATA          *Cert;\r
+  UINTN                       CertCount;\r
+  UINT32                      Offset;\r
+  BOOLEAN                     IsItemFound;\r
+  UINT32                      ItemDataSize;\r
+  UINTN                       GuidIndex;\r
+\r
+  Data            = NULL;\r
+  OldData         = NULL;\r
+  CertList        = NULL;\r
+  Cert            = NULL;\r
+  Attr            = 0;\r
+\r
+  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get original signature list data.\r
+  //\r
+  DataSize = 0;\r
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
+  if (OldData == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
+  if (EFI_ERROR(Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Allocate space for new variable.\r
+  //\r
+  Data = (UINT8*) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    Status  =  EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
   }\r
 \r
-  GuidStr = AllocateZeroPool (100);\r
-  if (GuidStr == NULL) {\r
+  //\r
+  // Enumerate all signature data and erasing the target item.\r
+  //\r
+  IsItemFound = FALSE;\r
+  ItemDataSize = (UINT32) DataSize;\r
+  CertList = (EFI_SIGNATURE_LIST *) OldData;\r
+  Offset = 0;\r
+  GuidIndex = 0;\r
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
+        CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||\r
+        CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||\r
+        CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) ||\r
+        CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) ||\r
+        CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) ||\r
+        CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)\r
+        ) {\r
+      //\r
+      // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
+      //\r
+      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
+      NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
+      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+      Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+      CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+      for (Index = 0; Index < CertCount; Index++) {\r
+        if (GuidIndex == DeleteIndex) {\r
+          //\r
+          // Find it! Skip it!\r
+          //\r
+          NewCertList->SignatureListSize -= CertList->SignatureSize;\r
+          IsItemFound = TRUE;\r
+        } else {\r
+          //\r
+          // This item doesn't match. Copy it to the Data buffer.\r
+          //\r
+          CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
+          Offset += CertList->SignatureSize;\r
+        }\r
+        GuidIndex++;\r
+        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+      }\r
+    } else {\r
+      //\r
+      // This List doesn't match. Just copy it to the Data buffer.\r
+      //\r
+      CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
+      Offset += CertList->SignatureListSize;\r
+    }\r
+\r
+    ItemDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+  if (!IsItemFound) {\r
+    //\r
+    // Doesn't find the signature Item!\r
+    //\r
+    Status = EFI_NOT_FOUND;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
+  //\r
+  ItemDataSize = Offset;\r
+  CertList = (EFI_SIGNATURE_LIST *) Data;\r
+  Offset = 0;\r
+  ZeroMem (OldData, ItemDataSize);\r
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));\r
+    if (CertCount != 0) {\r
+      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
+      Offset += CertList->SignatureListSize;\r
+    }\r
+    ItemDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+  DataSize = Offset;\r
+  if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+\r
+  Status = gRT->SetVariable(\r
+                  VariableName,\r
+                  VendorGuid,\r
+                  Attr,\r
+                  DataSize,\r
+                  OldData\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+  if (Data != NULL) {\r
+    FreePool(Data);\r
+  }\r
+\r
+  if (OldData != NULL) {\r
+    FreePool(OldData);\r
+  }\r
+\r
+  return UpdateDeletePage (\r
+           PrivateData,\r
+           VariableName,\r
+           VendorGuid,\r
+           LabelNumber,\r
+           FormId,\r
+           QuestionIdBase\r
+           );\r
+}\r
+\r
+/**\r
+  This function to delete signature list or data, according by DelType.\r
+\r
+  @param[in]  PrivateData           Module's private data.\r
+  @param[in]  DelType               Indicate delete signature list or data.\r
+  @param[in]  CheckedCount          Indicate how many signature data have\r
+                                    been checked in current signature list.\r
+\r
+  @retval   EFI_SUCCESS             Success to update the signature list page\r
+  @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.\r
+**/\r
+EFI_STATUS\r
+DeleteSignatureEx (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
+  IN SIGNATURE_DELETE_TYPE            DelType,\r
+  IN UINT32                           CheckedCount\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  EFI_SIGNATURE_LIST  *ListWalker;\r
+  EFI_SIGNATURE_LIST  *NewCertList;\r
+  EFI_SIGNATURE_DATA  *DataWalker;\r
+  CHAR16              VariableName[BUFFER_MAX_SIZE];\r
+  UINT32              VariableAttr;\r
+  UINTN               VariableDataSize;\r
+  UINTN               RemainingSize;\r
+  UINTN               ListIndex;\r
+  UINTN               Index;\r
+  UINTN               Offset;\r
+  UINT8               *VariableData;\r
+  UINT8               *NewVariableData;\r
+\r
+  Status              = EFI_SUCCESS;\r
+  VariableAttr        = 0;\r
+  VariableDataSize    = 0;\r
+  ListIndex           = 0;\r
+  Offset              = 0;\r
+  VariableData        = NULL;\r
+  NewVariableData     = NULL;\r
+\r
+  if (PrivateData->VariableName == Variable_DB) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);\r
+  } else if (PrivateData->VariableName == Variable_DBX) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);\r
+  } else if (PrivateData->VariableName == Variable_DBT) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);\r
+  } else {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gRT->GetVariable (\r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  &VariableAttr,\r
+                  &VariableDataSize,\r
+                  VariableData\r
+                );\r
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  VariableData = AllocateZeroPool (VariableDataSize);\r
+  if (VariableData == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gRT->GetVariable (\r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  &VariableAttr,\r
+                  &VariableDataSize,\r
+                  VariableData\r
+                );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  NewVariableData = AllocateZeroPool (VariableDataSize);\r
+  if (NewVariableData == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
   }\r
 \r
+  RemainingSize = VariableDataSize;\r
+  ListWalker = (EFI_SIGNATURE_LIST *)(VariableData);\r
+  if (DelType == Delete_Signature_List_All) {\r
+    VariableDataSize = 0;\r
+  } else {\r
+    //\r
+    //  Traverse to target EFI_SIGNATURE_LIST but others will be skipped.\r
+    //\r
+    while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex < PrivateData->ListIndex) {\r
+      CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, ListWalker->SignatureListSize);\r
+      Offset += ListWalker->SignatureListSize;\r
+\r
+      RemainingSize -= ListWalker->SignatureListSize;\r
+      ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
+      ListIndex++;\r
+    }\r
+\r
+    //\r
+    //  Handle the target EFI_SIGNATURE_LIST.\r
+    //  If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One\r
+    //  it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST.\r
+    //\r
+    if (CheckedCount < SIGNATURE_DATA_COUNTS (ListWalker) && DelType == Delete_Signature_Data) {\r
+      NewCertList = (EFI_SIGNATURE_LIST *)(NewVariableData + Offset);\r
+      //\r
+      // Copy header.\r
+      //\r
+      CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);\r
+      Offset += sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize;\r
+\r
+      DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof(EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);\r
+      for (Index = 0; Index < SIGNATURE_DATA_COUNTS(ListWalker); Index = Index + 1) {\r
+        if (PrivateData->CheckArray[Index]) {\r
+          //\r
+          // Delete checked signature data, and update the size of whole signature list.\r
+          //\r
+          NewCertList->SignatureListSize -= NewCertList->SignatureSize;\r
+        } else {\r
+          //\r
+          // Remain the unchecked signature data.\r
+          //\r
+          CopyMem ((UINT8 *)NewVariableData + Offset, DataWalker, ListWalker->SignatureSize);\r
+          Offset += ListWalker->SignatureSize;\r
+        }\r
+        DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);\r
+      }\r
+    }\r
+\r
+    RemainingSize -= ListWalker->SignatureListSize;\r
+    ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
+\r
+    //\r
+    // Copy remaining data, maybe 0.\r
+    //\r
+    CopyMem((UINT8 *)NewVariableData + Offset, ListWalker, RemainingSize);\r
+    Offset += RemainingSize;\r
+\r
+    VariableDataSize = Offset;\r
+  }\r
+\r
+  if ((VariableAttr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    Status = CreateTimeBasedPayload (&VariableDataSize, &NewVariableData);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VariableName,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  VariableAttr,\r
+                  VariableDataSize,\r
+                  NewVariableData\r
+                );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r", Status));\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+  SECUREBOOT_FREE_NON_NULL (VariableData);\r
+  SECUREBOOT_FREE_NON_NULL (NewVariableData);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT\r
+ and STR_CUR_SECURE_BOOT_MODE_CONTENT.\r
+\r
+  @param[in]    PrivateData         Module's private data.\r
+\r
+  @return EFI_SUCCESS              Update secure boot strings successfully.\r
+  @return other                          Fail to update secure boot strings.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateSecureBootString(\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  UINT8       *SecureBoot;\r
+\r
+  SecureBoot = NULL;\r
+\r
+  //\r
+  // Get current secure boot state.\r
+  //\r
+  GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
+  if (SecureBoot == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);\r
+  } else {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);\r
+  }\r
+\r
+  FreePool(SecureBoot);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function extracts configuration from variable.\r
+\r
+  @param[in]       Private      Point to SecureBoot configuration driver private data.\r
+  @param[in, out]  ConfigData   Point to SecureBoot configuration private data.\r
+\r
+**/\r
+VOID\r
+SecureBootExtractConfigFromVariable (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA  *Private,\r
+  IN OUT SECUREBOOT_CONFIGURATION    *ConfigData\r
+  )\r
+{\r
+  UINT8     *SecureBootEnable;\r
+  UINT8     *SetupMode;\r
+  UINT8     *SecureBootMode;\r
+  EFI_TIME  CurrTime;\r
+\r
+  SecureBootEnable = NULL;\r
+  SetupMode        = NULL;\r
+  SecureBootMode   = NULL;\r
+\r
+  //\r
+  // Initilize the Date and Time using system time.\r
+  //\r
+  ConfigData->CertificateFormat = HASHALG_RAW;\r
+  ConfigData->AlwaysRevocation = TRUE;\r
+  gRT->GetTime (&CurrTime, NULL);\r
+  ConfigData->RevocationDate.Year   = CurrTime.Year;\r
+  ConfigData->RevocationDate.Month  = CurrTime.Month;\r
+  ConfigData->RevocationDate.Day    = CurrTime.Day;\r
+  ConfigData->RevocationTime.Hour   = CurrTime.Hour;\r
+  ConfigData->RevocationTime.Minute = CurrTime.Minute;\r
+  ConfigData->RevocationTime.Second = 0;\r
+  if (Private->FileContext->FHandle != NULL) {\r
+    ConfigData->FileEnrollType = Private->FileContext->FileType;\r
+  } else {\r
+    ConfigData->FileEnrollType = UNKNOWN_FILE_TYPE;\r
+  }\r
+\r
+  //\r
+  // If it is Physical Presence User, set the PhysicalPresent to true.\r
+  //\r
+  if (UserPhysicalPresent()) {\r
+    ConfigData->PhysicalPresent = TRUE;\r
+  } else {\r
+    ConfigData->PhysicalPresent = FALSE;\r
+  }\r
+\r
+  //\r
+  // If there is no PK then the Delete Pk button will be gray.\r
+  //\r
+  GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
+  if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
+    ConfigData->HasPk = FALSE;\r
+  } else  {\r
+    ConfigData->HasPk = TRUE;\r
+  }\r
+\r
   //\r
-  // Enumerate all KEK pub data.\r
+  // Check SecureBootEnable & Pk status, fix the inconsistence. \r
+  // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
+  // Checkbox.\r
   //\r
-  ItemDataSize = (UINT32) DataSize;\r
-  CertList = (EFI_SIGNATURE_LIST *) Data;\r
-  GuidIndex = 0;\r
-\r
-  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
-\r
-    if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) {\r
-      Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID);\r
-    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
-      Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID);\r
-    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) {\r
-      Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID);\r
-    } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) {\r
-      Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID);\r
-    } else {\r
-      //\r
-      // The signature type is not supported in current implementation.\r
-      //\r
-      continue;\r
-    }\r
+  ConfigData->AttemptSecureBoot = FALSE;\r
+  GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);  \r
 \r
-    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
-    for (Index = 0; Index < CertCount; Index++) {\r
-      Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList \r
-                                              + sizeof (EFI_SIGNATURE_LIST) \r
-                                              + CertList->SignatureHeaderSize \r
-                                              + Index * CertList->SignatureSize);\r
-      //\r
-      // Display GUID and help \r
-      //\r
-      GuidToString (&Cert->SignatureOwner, GuidStr, 100);\r
-      GuidID  = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL);\r
-      HiiCreateCheckBoxOpCode (\r
-        StartOpCodeHandle,\r
-        (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),\r
-        0, \r
-        0, \r
-        GuidID, \r
-        Help,\r
-        EFI_IFR_FLAG_CALLBACK,\r
-        0,\r
-        NULL\r
-        );       \r
+  //\r
+  // Fix Pk, SecureBootEnable inconsistence\r
+  //\r
+  if ((SetupMode != NULL) && (*SetupMode) == USER_MODE) {\r
+    ConfigData->HideSecureBoot = FALSE;\r
+    if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) {\r
+      ConfigData->AttemptSecureBoot = TRUE;\r
     }\r
-\r
-    ItemDataSize -= CertList->SignatureListSize;\r
-    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  } else {\r
+    ConfigData->HideSecureBoot = TRUE;\r
   }\r
 \r
-ON_EXIT:\r
-  HiiUpdateForm (\r
-    PrivateData->HiiHandle,\r
-    &gSecureBootConfigFormSetGuid,\r
-    FormId,\r
-    StartOpCodeHandle,\r
-    EndOpCodeHandle\r
-    );\r
-\r
-  if (StartOpCodeHandle != NULL) {\r
-    HiiFreeOpCodeHandle (StartOpCodeHandle);\r
+  //\r
+  // Get the SecureBootMode from CustomMode variable.\r
+  //\r
+  GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
+  if (SecureBootMode == NULL) {\r
+    ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
+  } else {\r
+    ConfigData->SecureBootMode = *(SecureBootMode);\r
   }\r
 \r
-  if (EndOpCodeHandle != NULL) {\r
-    HiiFreeOpCodeHandle (EndOpCodeHandle);\r
+  if (SecureBootEnable != NULL) {\r
+    FreePool (SecureBootEnable);\r
   }\r
-  \r
-  if (Data != NULL) {\r
-    FreePool (Data);\r
+  if (SetupMode != NULL) {\r
+    FreePool (SetupMode);\r
   }\r
-\r
-  if (GuidStr != NULL) {\r
-    FreePool (GuidStr);\r
+  if (SecureBootMode != NULL) {\r
+    FreePool (SecureBootMode);\r
   }\r
-\r
-  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Delete a KEK entry from KEK database. \r
+  This function allows a caller to extract the current configuration for one\r
+  or more named elements from the target driver.\r
 \r
-  @param[in]    PrivateData         Module's private data.\r
-  @param[in]    QuestionId          Question id of the KEK item to delete.\r
+  @param[in]   This              Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]   Request           A null-terminated Unicode string in\r
+                                 <ConfigRequest> format.\r
+  @param[out]  Progress          On return, points to a character in the Request\r
+                                 string. Points to the string's null terminator if\r
+                                 request was successful. Points to the most recent\r
+                                 '&' before the first failing name/value pair (or\r
+                                 the beginning of the string if the failure is in\r
+                                 the first name/value pair) if the request was not\r
+                                 successful.\r
+  @param[out]  Results           A null-terminated Unicode string in\r
+                                 <ConfigAltResp> format which has all values filled\r
+                                 in for the names in the Request string. String to\r
+                                 be allocated by the called function.\r
+\r
+  @retval EFI_SUCCESS            The Results is filled with the requested values.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
+  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
 \r
-  @retval   EFI_SUCCESS            Delete kek item successfully.\r
-  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
-  \r
 **/\r
 EFI_STATUS\r
-DeleteKeyExchangeKey (\r
-  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
-  IN EFI_QUESTION_ID                  QuestionId\r
+EFIAPI\r
+SecureBootExtractConfig (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL        *This,\r
+  IN CONST EFI_STRING                            Request,\r
+       OUT EFI_STRING                            *Progress,\r
+       OUT EFI_STRING                            *Results\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINTN                       DataSize;\r
-  UINT8                       *Data;\r
-  UINT8                       *OldData;\r
-  UINT32                      Attr;\r
-  UINT32                      Index;\r
-  EFI_SIGNATURE_LIST          *CertList;\r
-  EFI_SIGNATURE_LIST          *NewCertList;\r
-  EFI_SIGNATURE_DATA          *Cert;\r
-  UINTN                       CertCount;\r
-  UINT32                      Offset;\r
-  BOOLEAN                     IsKEKItemFound;\r
-  UINT32                      KekDataSize;\r
-  UINTN                       DeleteKekIndex;\r
-  UINTN                       GuidIndex;\r
+  EFI_STATUS                        Status;\r
+  UINTN                             BufferSize;\r
+  UINTN                             Size;\r
+  SECUREBOOT_CONFIGURATION          Configuration;\r
+  EFI_STRING                        ConfigRequest;\r
+  EFI_STRING                        ConfigRequestHdr;\r
+  SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData;\r
+  BOOLEAN                           AllocatedRequest;\r
 \r
-  Data            = NULL;\r
-  OldData         = NULL;\r
-  CertList        = NULL;\r
-  Cert            = NULL;\r
-  Attr            = 0;   \r
-  DeleteKekIndex  = QuestionId - OPTION_DEL_KEK_QUESTION_ID;\r
-  \r
-  //\r
-  // Get original KEK variable.\r
-  //                           \r
-  DataSize = 0;  \r
-  Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
-  if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
-    goto ON_EXIT;\r
+  if (Progress == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  OldData = (UINT8*)AllocateZeroPool(DataSize);\r
-  if (OldData == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;  \r
-    goto ON_EXIT;\r
+  AllocatedRequest = FALSE;\r
+  ConfigRequestHdr = NULL;\r
+  ConfigRequest    = NULL;\r
+  Size             = 0;\r
+\r
+  ZeroMem (&Configuration, sizeof (Configuration));\r
+  PrivateData      = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
+  *Progress        = Request;\r
+\r
+  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
-  Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData);\r
-  if (EFI_ERROR(Status)) {\r
-    goto ON_EXIT;\r
+  ZeroMem(&Configuration, sizeof(SECUREBOOT_CONFIGURATION));\r
+\r
+  //\r
+  // Get Configuration from Variable.\r
+  //\r
+  SecureBootExtractConfigFromVariable (PrivateData, &Configuration);\r
+\r
+  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
+  ConfigRequest = Request;\r
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
+    //\r
+    // Request is set to NULL or OFFSET is NULL, construct full request string.\r
+    //\r
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
+    //\r
+    ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
+    ConfigRequest = AllocateZeroPool (Size);\r
+    ASSERT (ConfigRequest != NULL);\r
+    AllocatedRequest = TRUE;\r
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
+    FreePool (ConfigRequestHdr);\r
+    ConfigRequestHdr = NULL;\r
   }\r
 \r
+  Status = gHiiConfigRouting->BlockToConfig (\r
+                                gHiiConfigRouting,\r
+                                ConfigRequest,\r
+                                (UINT8 *) &Configuration,\r
+                                BufferSize,\r
+                                Results,\r
+                                Progress\r
+                                );\r
+\r
   //\r
-  // Allocate space for new variable.  \r
+  // Free the allocated config request string.\r
   //\r
-  Data = (UINT8*) AllocateZeroPool (DataSize);\r
-  if (Data == NULL) {\r
-    Status  =  EFI_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
+  if (AllocatedRequest) {\r
+    FreePool (ConfigRequest);\r
   }\r
 \r
   //\r
-  // Enumerate all KEK pub data and erasing the target item.\r
+  // Set Progress string to the original request string.\r
   //\r
-  IsKEKItemFound = FALSE;\r
-  KekDataSize = (UINT32) DataSize;\r
-  CertList = (EFI_SIGNATURE_LIST *) OldData;\r
-  Offset = 0;\r
-  GuidIndex = 0;\r
-  while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
-    if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
-        CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
-      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
-      NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);\r
-      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-      Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-      CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
-      for (Index = 0; Index < CertCount; Index++) {\r
-        if (GuidIndex == DeleteKekIndex ) {\r
-          //\r
-          // Find it! Skip it!\r
-          //\r
-          NewCertList->SignatureListSize -= CertList->SignatureSize;\r
-          IsKEKItemFound = TRUE;          \r
-        } else {\r
-          //\r
-          // This item doesn't match. Copy it to the Data buffer.\r
-          //\r
-          CopyMem (Data + Offset, Cert, CertList->SignatureSize);\r
-          Offset += CertList->SignatureSize;\r
-        }\r
-        GuidIndex++;\r
-        Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize);\r
-      }\r
-    } else {\r
-      //\r
-      // This List doesn't match. Copy it to the Data buffer.\r
-      //\r
-      CopyMem (Data + Offset, CertList, CertList->SignatureListSize);\r
-      Offset += CertList->SignatureListSize;\r
-    }\r
-      \r
-    KekDataSize -= CertList->SignatureListSize;\r
-    CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize);\r
+  if (Request == NULL) {\r
+    *Progress = NULL;\r
+  } else if (StrStr (Request, L"OFFSET") == NULL) {\r
+    *Progress = Request + StrLen (Request);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]  Configuration      A null-terminated Unicode string in <ConfigResp>\r
+                                 format.\r
+  @param[out] Progress           A pointer to a string filled in with the offset of\r
+                                 the most recent '&' before the first failing\r
+                                 name/value pair (or the beginning of the string if\r
+                                 the failure is in the first name/value pair) or\r
+                                 the terminating NULL if all was successful.\r
+\r
+  @retval EFI_SUCCESS            The Results is processed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
+  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
+                                 driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SecureBootRouteConfig (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
+  IN CONST EFI_STRING                          Configuration,\r
+       OUT EFI_STRING                          *Progress\r
+  )\r
+{\r
+  SECUREBOOT_CONFIGURATION          IfrNvData;\r
+  UINTN                             BufferSize;\r
+  SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData;\r
+  EFI_STATUS                        Status;\r
+\r
+  if (Configuration == NULL || Progress == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (!IsKEKItemFound) {\r
-    //\r
-    // Doesn't find the Kek Item!\r
-    //\r
-    Status = EFI_NOT_FOUND;\r
-    goto ON_EXIT;\r
+  *Progress = Configuration;\r
+  if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
+  PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
+\r
   //\r
-  // Delete the Signature header if there is no signature in the list.\r
+  // Get Configuration from Variable.\r
   //\r
-  KekDataSize = Offset;\r
-  CertList = (EFI_SIGNATURE_LIST*) Data;\r
-  Offset = 0;\r
-  ZeroMem (OldData, KekDataSize);\r
-  while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {\r
-    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
-    DEBUG ((DEBUG_ERROR, "       CertCount = %x\n", CertCount));\r
-    if (CertCount != 0) {\r
-      CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
-      Offset += CertList->SignatureListSize;\r
-    }    \r
-    KekDataSize -= CertList->SignatureListSize;\r
-    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
-  }\r
-\r
-  DataSize = Offset;\r
-  if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
-    Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
-      goto ON_EXIT;\r
-    }\r
-  }\r
+  SecureBootExtractConfigFromVariable (PrivateData, &IfrNvData);\r
 \r
-  Status = gRT->SetVariable(\r
-                  EFI_KEY_EXCHANGE_KEY_NAME, \r
-                  &gEfiGlobalVariableGuid, \r
-                  Attr, \r
-                  DataSize, \r
-                  OldData\r
-                  );\r
+  //\r
+  // Map the Configuration to the configuration block.\r
+  //\r
+  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
+  Status = gHiiConfigRouting->ConfigToBlock (\r
+                                gHiiConfigRouting,\r
+                                Configuration,\r
+                                (UINT8 *)&IfrNvData,\r
+                                &BufferSize,\r
+                                Progress\r
+                                );\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
-    goto ON_EXIT;\r
-  }\r
\r
-ON_EXIT:\r
-  if (Data != NULL) {\r
-    FreePool(Data);\r
+    return Status;\r
   }\r
 \r
-  if (OldData != NULL) {\r
-    FreePool(OldData);\r
+  //\r
+  // Store Buffer Storage back to EFI variable if needed\r
+  //\r
+  if (!IfrNvData.HideSecureBoot) {\r
+    Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
-  return UpdateDeletePage (\r
-           PrivateData, \r
-           EFI_KEY_EXCHANGE_KEY_NAME,\r
-           &gEfiGlobalVariableGuid,\r
-           LABEL_KEK_DELETE,\r
-           FORMID_DELETE_KEK_FORM,\r
-           OPTION_DEL_KEK_QUESTION_ID\r
-           );\r
+  *Progress = Configuration + StrLen (Configuration);\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Delete a signature entry from siganture database.\r
+  This function to load signature list, the update the menu page.\r
 \r
-  @param[in]    PrivateData         Module's private data.\r
-  @param[in]    VariableName        The variable name of the vendor's signature database.\r
-  @param[in]    VendorGuid          A unique identifier for the vendor.\r
-  @param[in]    LabelNumber         Label number to insert opcodes.\r
-  @param[in]    FormId              Form ID of current page.\r
-  @param[in]    QuestionIdBase      Base question id of the signature list.\r
-  @param[in]    DeleteIndex         Signature index to delete.\r
-  \r
-  @retval   EFI_SUCCESS             Delete siganture successfully.\r
-  @retval   EFI_NOT_FOUND           Can't find the signature item,\r
-  @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.\r
+  @param[in]  PrivateData         Module's private data.\r
+  @param[in]  LabelId             Label number to insert opcodes.\r
+  @param[in]  FormId              Form ID of current page.\r
+  @param[in]  QuestionIdBase      Base question id of the signature list.\r
+\r
+  @retval   EFI_SUCCESS           Success to update the signature list page\r
+  @retval   EFI_OUT_OF_RESOURCES  Unable to allocate required resources.\r
 **/\r
 EFI_STATUS\r
-DeleteSignature (\r
-  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
-  IN CHAR16                           *VariableName,\r
-  IN EFI_GUID                         *VendorGuid,\r
-  IN UINT16                           LabelNumber,\r
-  IN EFI_FORM_ID                      FormId,\r
-  IN EFI_QUESTION_ID                  QuestionIdBase,\r
-  IN UINTN                            DeleteIndex\r
+LoadSignatureList (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
+  IN UINT16                         LabelId,\r
+  IN EFI_FORM_ID                    FormId,\r
+  IN EFI_QUESTION_ID                QuestionIdBase\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINTN                       DataSize;\r
-  UINT8                       *Data;\r
-  UINT8                       *OldData;\r
-  UINT32                      Attr;\r
-  UINT32                      Index;\r
-  EFI_SIGNATURE_LIST          *CertList;\r
-  EFI_SIGNATURE_LIST          *NewCertList;\r
-  EFI_SIGNATURE_DATA          *Cert;\r
-  UINTN                       CertCount;\r
-  UINT32                      Offset;\r
-  BOOLEAN                     IsItemFound;\r
-  UINT32                      ItemDataSize;\r
-  UINTN                       GuidIndex;\r
-\r
-  Data            = NULL;\r
-  OldData         = NULL;\r
-  CertList        = NULL;\r
-  Cert            = NULL;\r
-  Attr            = 0; \r
+  EFI_STATUS            Status;\r
+  EFI_STRING_ID         ListType;\r
+  EFI_STRING            FormatNameString;\r
+  EFI_STRING            FormatHelpString;\r
+  EFI_STRING            FormatTypeString;\r
+  EFI_SIGNATURE_LIST    *ListWalker;\r
+  EFI_IFR_GUID_LABEL    *StartLabel;\r
+  EFI_IFR_GUID_LABEL    *EndLabel;\r
+  EFI_IFR_GUID_LABEL    *StartGoto;\r
+  EFI_IFR_GUID_LABEL    *EndGoto;\r
+  EFI_FORM_ID           DstFormId;\r
+  VOID                  *StartOpCodeHandle;\r
+  VOID                  *EndOpCodeHandle;\r
+  VOID                  *StartGotoHandle;\r
+  VOID                  *EndGotoHandle;\r
+  UINTN                 DataSize;\r
+  UINTN                 RemainingSize;\r
+  UINT16                Index;\r
+  UINT8                 *VariableData;\r
+  CHAR16                VariableName[BUFFER_MAX_SIZE];\r
+  CHAR16                NameBuffer[BUFFER_MAX_SIZE];\r
+  CHAR16                HelpBuffer[BUFFER_MAX_SIZE];\r
+\r
+  Status                = EFI_SUCCESS;\r
+  FormatNameString      = NULL;\r
+  FormatHelpString      = NULL;\r
+  StartOpCodeHandle     = NULL;\r
+  EndOpCodeHandle       = NULL;\r
+  StartGotoHandle       = NULL;\r
+  EndGotoHandle         = NULL;\r
+  Index                 = 0;\r
+  VariableData          = NULL;\r
 \r
   //\r
-  // Get original signature list data.\r
-  //                           \r
-  DataSize = 0;\r
-  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
-  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+  // Initialize the container for dynamic opcodes.\r
+  //\r
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (StartOpCodeHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
   }\r
 \r
-  OldData = (UINT8 *) AllocateZeroPool (DataSize);\r
-  if (OldData == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;  \r
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (EndOpCodeHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
   }\r
 \r
-  Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);\r
-  if (EFI_ERROR(Status)) {\r
+  StartGotoHandle = HiiAllocateOpCodeHandle ();\r
+  if (StartGotoHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  EndGotoHandle = HiiAllocateOpCodeHandle ();\r
+  if (EndGotoHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
-  } \r
+  }\r
 \r
   //\r
-  // Allocate space for new variable.  \r
+  // Create Hii Extend Label OpCode.\r
   //\r
-  Data = (UINT8*) AllocateZeroPool (DataSize);\r
-  if (Data == NULL) {\r
-    Status  =  EFI_OUT_OF_RESOURCES;\r
+  StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
+                                       StartOpCodeHandle,\r
+                                       &gEfiIfrTianoGuid,\r
+                                       NULL,\r
+                                       sizeof (EFI_IFR_GUID_LABEL)\r
+                                     );\r
+  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
+  StartLabel->Number        = LabelId;\r
+\r
+  EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
+                                     EndOpCodeHandle,\r
+                                     &gEfiIfrTianoGuid,\r
+                                     NULL,\r
+                                     sizeof (EFI_IFR_GUID_LABEL)\r
+                                   );\r
+  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
+  EndLabel->Number        = LABEL_END;\r
+\r
+  StartGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode(\r
+                                      StartGotoHandle,\r
+                                      &gEfiIfrTianoGuid,\r
+                                      NULL,\r
+                                      sizeof(EFI_IFR_GUID_LABEL)\r
+                                    );\r
+  StartGoto->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
+  StartGoto->Number        = LABEL_DELETE_ALL_LIST_BUTTON;\r
+\r
+  EndGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode(\r
+                                    EndGotoHandle,\r
+                                    &gEfiIfrTianoGuid,\r
+                                    NULL,\r
+                                    sizeof(EFI_IFR_GUID_LABEL)\r
+                                  );\r
+  EndGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+  EndGoto->Number = LABEL_END;\r
+\r
+  if (PrivateData->VariableName == Variable_DB) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);\r
+    DstFormId = FORMID_SECURE_BOOT_DB_OPTION_FORM;\r
+  } else if (PrivateData->VariableName == Variable_DBX) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);\r
+    DstFormId = FORMID_SECURE_BOOT_DBX_OPTION_FORM;\r
+  } else if (PrivateData->VariableName == Variable_DBT) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);\r
+    DstFormId = FORMID_SECURE_BOOT_DBT_OPTION_FORM;\r
+  } else {\r
     goto ON_EXIT;\r
   }\r
 \r
+  HiiCreateGotoOpCode (\r
+    StartGotoHandle,\r
+    DstFormId,\r
+    STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),\r
+    STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST),\r
+    EFI_IFR_FLAG_CALLBACK,\r
+    KEY_SECURE_BOOT_DELETE_ALL_LIST\r
+  );\r
+\r
   //\r
-  // Enumerate all signature data and erasing the target item.\r
+  // Read Variable, the variable name save in the PrivateData->VariableName.\r
   //\r
-  IsItemFound = FALSE;\r
-  ItemDataSize = (UINT32) DataSize;\r
-  CertList = (EFI_SIGNATURE_LIST *) OldData;\r
-  Offset = 0;\r
-  GuidIndex = 0;\r
-  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
-    if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) ||\r
-        CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) ||\r
-        CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) ||\r
-        CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)\r
-        ) {\r
-      //\r
-      // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.\r
-      //\r
-      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));\r
-      NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);\r
-      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-      Cert      = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
-      CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
-      for (Index = 0; Index < CertCount; Index++) {\r
-        if (GuidIndex == DeleteIndex) {\r
-          //\r
-          // Find it! Skip it!\r
-          //\r
-          NewCertList->SignatureListSize -= CertList->SignatureSize;\r
-          IsItemFound = TRUE;          \r
-        } else {\r
-          //\r
-          // This item doesn't match. Copy it to the Data buffer.\r
-          //\r
-          CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);\r
-          Offset += CertList->SignatureSize;\r
-        }\r
-        GuidIndex++;\r
-        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
-      }\r
+  DataSize = 0;\r
+  Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  VariableData = AllocateZeroPool (DataSize);\r
+  if (VariableData == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+  Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT), NULL);\r
+  FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT), NULL);\r
+  if (FormatNameString == NULL || FormatHelpString == NULL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  RemainingSize = DataSize;\r
+  ListWalker    = (EFI_SIGNATURE_LIST *)VariableData;\r
+  while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) {\r
+    if (CompareGuid (&ListWalker->SignatureType, &gEfiCertRsa2048Guid)) {\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256);\r
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Guid)) {\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_X509);\r
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha1Guid)) {\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_SHA1);\r
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha256Guid)) {\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_SHA256);\r
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha256Guid)) {\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256);\r
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha384Guid)) {\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA384);\r
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha512Guid)) {\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA512);\r
     } else {\r
-      //\r
-      // This List doesn't match. Just copy it to the Data buffer.\r
-      //\r
-      CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
-      Offset += CertList->SignatureListSize;\r
+      ListType = STRING_TOKEN (STR_LIST_TYPE_UNKNOWN);\r
     }\r
-      \r
-    ItemDataSize -= CertList->SignatureListSize;\r
-    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+    FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListType, NULL);\r
+    if (FormatTypeString == NULL) {\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    ZeroMem (NameBuffer, sizeof (NameBuffer));\r
+    UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);\r
+\r
+    ZeroMem (HelpBuffer, sizeof (HelpBuffer));\r
+    UnicodeSPrint (HelpBuffer,\r
+      sizeof (HelpBuffer),\r
+      FormatHelpString,\r
+      FormatTypeString,\r
+      SIGNATURE_DATA_COUNTS (ListWalker)\r
+    );\r
+    SECUREBOOT_FREE_NON_NULL (FormatTypeString);\r
+    FormatTypeString = NULL;\r
+\r
+    HiiCreateGotoOpCode (\r
+      StartOpCodeHandle,\r
+      SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,\r
+      HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),\r
+      HiiSetString (PrivateData->HiiHandle, 0, HelpBuffer, NULL),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      QuestionIdBase + Index++\r
+    );\r
+\r
+    RemainingSize -= ListWalker->SignatureListSize;\r
+    ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
   }\r
 \r
-  if (!IsItemFound) {\r
-    //\r
-    // Doesn't find the signature Item!\r
-    //\r
-    Status = EFI_NOT_FOUND;\r
-    goto ON_EXIT;\r
+ON_EXIT:\r
+  HiiUpdateForm (\r
+    PrivateData->HiiHandle,\r
+    &gSecureBootConfigFormSetGuid,\r
+    FormId,\r
+    StartOpCodeHandle,\r
+    EndOpCodeHandle\r
+  );\r
+\r
+  HiiUpdateForm (\r
+    PrivateData->HiiHandle,\r
+    &gSecureBootConfigFormSetGuid,\r
+    FormId,\r
+    StartGotoHandle,\r
+    EndGotoHandle\r
+  );\r
+\r
+  SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);\r
+  SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);\r
+  SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle);\r
+  SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle);\r
+\r
+  SECUREBOOT_FREE_NON_NULL (VariableData);\r
+  SECUREBOOT_FREE_NON_NULL (FormatNameString);\r
+  SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
+\r
+  PrivateData->ListCount = Index;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array.\r
+  The buffer is callee allocated and should be freed by the caller.\r
+\r
+  @param[in]    ListEntry                 The pointer point to the signature list.\r
+  @param[in]    DataEntry                 The signature data we are processing.\r
+  @param[out]   BufferToReturn            Buffer to save the hash value.\r
+\r
+  @retval       EFI_INVALID_PARAMETER     Invalid List or Data or Buffer.\r
+  @retval       EFI_OUT_OF_RESOURCES      A memory allocation failed.\r
+  @retval       EFI_SUCCESS               Operation success.\r
+**/\r
+EFI_STATUS\r
+ParseHashValue (\r
+  IN     EFI_SIGNATURE_LIST    *ListEntry,\r
+  IN     EFI_SIGNATURE_DATA    *DataEntry,\r
+     OUT CHAR16                **BufferToReturn\r
+  )\r
+{\r
+  UINTN       Index;\r
+  UINTN       BufferIndex;\r
+  UINTN       TotalSize;\r
+  UINTN       DataSize;\r
+  UINTN       Line;\r
+  UINTN       OneLineBytes;\r
+\r
+  //\r
+  //  Assume that, display 8 bytes in one line.\r
+  //\r
+  OneLineBytes = 8;\r
+\r
+  if (ListEntry == NULL || DataEntry == NULL || BufferToReturn == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);\r
+  Line = (DataSize + OneLineBytes - 1) / OneLineBytes;\r
+\r
   //\r
-  // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.\r
+  // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.\r
   //\r
-  ItemDataSize = Offset;\r
-  CertList = (EFI_SIGNATURE_LIST *) Data;\r
-  Offset = 0;\r
-  ZeroMem (OldData, ItemDataSize);\r
-  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {\r
-    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
-    DEBUG ((DEBUG_ERROR, "       CertCount = %x\n", CertCount));\r
-    if (CertCount != 0) {\r
-      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
-      Offset += CertList->SignatureListSize;\r
-    }    \r
-    ItemDataSize -= CertList->SignatureListSize;\r
-    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  TotalSize = ((DataSize + Line) * 2 * sizeof(CHAR16));\r
+\r
+  *BufferToReturn = AllocateZeroPool(TotalSize);\r
+  if (*BufferToReturn == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  DataSize = Offset;\r
-  if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
-    Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
-      goto ON_EXIT;\r
+  for (Index = 0, BufferIndex = 0; Index < DataSize; Index = Index + 1) {\r
+    if ((Index > 0) && (Index % OneLineBytes == 0)) {\r
+      BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"\n");\r
     }\r
+    BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"%02x", DataEntry->SignatureData[Index]);\r
   }\r
+  BufferIndex += UnicodeSPrint(&(*BufferToReturn)[BufferIndex], TotalSize - sizeof(CHAR16) * BufferIndex, L"\n");\r
 \r
-  Status = gRT->SetVariable(\r
-                  VariableName, \r
-                  VendorGuid, \r
-                  Attr, \r
-                  DataSize, \r
-                  OldData\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Function to get the common name from the X509 format certificate.\r
+  The buffer is callee allocated and should be freed by the caller.\r
+\r
+  @param[in]    ListEntry                 The pointer point to the signature list.\r
+  @param[in]    DataEntry                 The signature data we are processing.\r
+  @param[out]   BufferToReturn            Buffer to save the CN of X509 certificate.\r
+\r
+  @retval       EFI_INVALID_PARAMETER     Invalid List or Data or Buffer.\r
+  @retval       EFI_OUT_OF_RESOURCES      A memory allocation failed.\r
+  @retval       EFI_SUCCESS               Operation success.\r
+  @retval       EFI_NOT_FOUND             Not found CN field in the X509 certificate.\r
+**/\r
+EFI_STATUS\r
+GetCommonNameFromX509 (\r
+  IN     EFI_SIGNATURE_LIST    *ListEntry,\r
+  IN     EFI_SIGNATURE_DATA    *DataEntry,\r
+     OUT CHAR16                **BufferToReturn\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  CHAR8           *CNBuffer;\r
+  UINTN           CNBufferSize;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  CNBuffer      = NULL;\r
+\r
+  CNBuffer = AllocateZeroPool(256);\r
+  if (CNBuffer == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
   }\r
\r
-ON_EXIT:\r
-  if (Data != NULL) {\r
-    FreePool(Data);\r
-  }\r
 \r
-  if (OldData != NULL) {\r
-    FreePool(OldData);\r
+  CNBufferSize = 256;\r
+  X509GetCommonName (\r
+    (UINT8 *)DataEntry + sizeof(EFI_GUID),\r
+    ListEntry->SignatureSize - sizeof(EFI_GUID),\r
+    CNBuffer,\r
+    &CNBufferSize\r
+  );\r
+\r
+  *BufferToReturn = AllocateZeroPool(256 * sizeof(CHAR16));\r
+  if (*BufferToReturn == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
   }\r
 \r
-  return UpdateDeletePage (\r
-           PrivateData, \r
-           VariableName,\r
-           VendorGuid,\r
-           LabelNumber,\r
-           FormId,\r
-           QuestionIdBase\r
-           );\r
+  AsciiStrToUnicodeStrS (CNBuffer, *BufferToReturn, 256);\r
+\r
+ON_EXIT:\r
+  SECUREBOOT_FREE_NON_NULL (CNBuffer);\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
-  This function extracts configuration from variable.\r
-  \r
-  @param[in, out]  ConfigData   Point to SecureBoot configuration private data.\r
-\r
+  Format the help info for the signature data, each help info contain 3 parts.\r
+  1. Onwer Guid.\r
+  2. Content, depends on the type of the signature list.\r
+  3. Revocation time.\r
+\r
+  @param[in]      PrivateData             Module's private data.\r
+  @param[in]      ListEntry               Point to the signature list.\r
+  @param[in]      DataEntry               Point to the signature data we are processing.\r
+  @param[out]     StringId                Save the string id of help info.\r
+\r
+  @retval         EFI_SUCCESS             Operation success.\r
+  @retval         EFI_OUT_OF_RESOURCES    Unable to allocate required resources.\r
 **/\r
-VOID\r
-SecureBootExtractConfigFromVariable (\r
-  IN OUT SECUREBOOT_CONFIGURATION    *ConfigData\r
-  ) \r
+EFI_STATUS\r
+FormatHelpInfo (\r
+  IN     SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
+  IN     EFI_SIGNATURE_LIST               *ListEntry,\r
+  IN     EFI_SIGNATURE_DATA               *DataEntry,\r
+     OUT EFI_STRING_ID                    *StringId\r
+  )\r
 {\r
-  UINT8   *SecureBootEnable;\r
-  UINT8   *SetupMode;\r
-  UINT8   *SecureBootMode;\r
+  EFI_STATUS      Status;\r
+  EFI_TIME        *Time;\r
+  EFI_STRING_ID   ListTypeId;\r
+  EFI_STRING      FormatHelpString;\r
+  EFI_STRING      FormatTypeString;\r
+  UINTN           DataSize;\r
+  UINTN           HelpInfoIndex;\r
+  UINTN           TotalSize;\r
+  CHAR16          GuidString[BUFFER_MAX_SIZE];\r
+  CHAR16          TimeString[BUFFER_MAX_SIZE];\r
+  CHAR16          *DataString;\r
+  CHAR16          *HelpInfoString;\r
+  BOOLEAN         IsCert;\r
+\r
+  Status            = EFI_SUCCESS;\r
+  Time              = NULL;\r
+  FormatTypeString  = NULL;\r
+  HelpInfoIndex     = 0;\r
+  DataString        = NULL;\r
+  HelpInfoString    = NULL;\r
+  IsCert            = FALSE;\r
+\r
+  if (CompareGuid(&ListEntry->SignatureType, &gEfiCertRsa2048Guid)) {\r
+    ListTypeId = STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256);\r
+    DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);\r
+    IsCert = TRUE;\r
+  } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Guid)) {\r
+    ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509);\r
+    DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID);\r
+    IsCert = TRUE;\r
+  } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha1Guid)) {\r
+    ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA1);\r
+    DataSize = 20;\r
+  } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha256Guid)) {\r
+    ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA256);\r
+    DataSize = 32;\r
+  } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha256Guid)) {\r
+    ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA256);\r
+    DataSize = 32;\r
+    Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);\r
+  } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha384Guid)) {\r
+    ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA384);\r
+    DataSize = 48;\r
+    Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);\r
+  } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Sha512Guid)) {\r
+    ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA512);\r
+    DataSize = 64;\r
+    Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize);\r
+  } else {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_EXIT;\r
+  }\r
 \r
-  SecureBootEnable = NULL;\r
-  SetupMode        = NULL;\r
-  SecureBootMode   = NULL;\r
-  \r
-  //\r
-  // Get the SecureBootEnable Variable\r
-  //\r
-  GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
+  FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListTypeId, NULL);\r
+  if (FormatTypeString == NULL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  TotalSize = 1024;\r
+  HelpInfoString = AllocateZeroPool (TotalSize);\r
+  if (HelpInfoString == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
 \r
   //\r
-  // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
-  // Checkbox.\r
+  // Format GUID part.\r
   //\r
-  if (SecureBootEnable == NULL) {\r
-    ConfigData->HideSecureBoot = TRUE;\r
-  } else {\r
-    ConfigData->HideSecureBoot = FALSE;\r
-    ConfigData->SecureBootState = *SecureBootEnable;\r
+  ZeroMem (GuidString, sizeof (GuidString));\r
+  GuidToString(&DataEntry->SignatureOwner, GuidString, BUFFER_MAX_SIZE);\r
+  FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID), NULL);\r
+  if (FormatHelpString == NULL) {\r
+    goto ON_EXIT;\r
   }\r
+  HelpInfoIndex += UnicodeSPrint (\r
+                     &HelpInfoString[HelpInfoIndex],\r
+                     TotalSize - sizeof(CHAR16) * HelpInfoIndex,\r
+                     FormatHelpString,\r
+                     GuidString\r
+                   );\r
+  SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
+  FormatHelpString = NULL;\r
+\r
   //\r
-  // If it is Physical Presence User, set the PhysicalPresent to true.\r
+  // Format content part, it depends on the type of signature list, hash value or CN.\r
   //\r
-  if (UserPhysicalPresent()) {\r
-    ConfigData->PhysicalPresent = TRUE;\r
+  if (IsCert) {\r
+    GetCommonNameFromX509 (ListEntry, DataEntry, &DataString);\r
+    FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN), NULL);\r
   } else {\r
-    ConfigData->PhysicalPresent = FALSE;\r
+    //\r
+    //  Format hash value for each signature data entry.\r
+    //\r
+    ParseHashValue (ListEntry, DataEntry, &DataString);\r
+    FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH), NULL);\r
   }\r
-  \r
-  //\r
-  // If there is no PK then the Delete Pk button will be gray.\r
-  //\r
-  GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
-  if (SetupMode == NULL || (*SetupMode) == 1) {\r
-    ConfigData->HasPk = FALSE;\r
-  } else  {\r
-    ConfigData->HasPk = TRUE;\r
+  if (FormatHelpString == NULL) {\r
+    goto ON_EXIT;\r
   }\r
+  HelpInfoIndex += UnicodeSPrint (\r
+                     &HelpInfoString[HelpInfoIndex],\r
+                     TotalSize - sizeof (CHAR16) * HelpInfoIndex,\r
+                     FormatHelpString,\r
+                     FormatTypeString,\r
+                     DataSize,\r
+                     DataString\r
+                   );\r
+  SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
+  FormatHelpString = NULL;\r
 \r
   //\r
-  // Get the SecureBootMode from CustomMode variable.\r
+  // Format revocation time part.\r
   //\r
-  GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
-  if (SecureBootMode == NULL) {\r
-    ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
-  } else {\r
-    ConfigData->SecureBootMode = *(SecureBootMode);\r
+  if (Time != NULL) {\r
+    ZeroMem (TimeString, sizeof (TimeString));\r
+    UnicodeSPrint (\r
+      TimeString,\r
+      sizeof (TimeString),\r
+      L"%d-%d-%d %d:%d:%d",\r
+      Time->Year,\r
+      Time->Month,\r
+      Time->Day,\r
+      Time->Hour,\r
+      Time->Minute,\r
+      Time->Second\r
+    );\r
+    FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME), NULL);\r
+    if (FormatHelpString == NULL) {\r
+      goto ON_EXIT;\r
+    }\r
+    UnicodeSPrint (\r
+      &HelpInfoString[HelpInfoIndex],\r
+      TotalSize - sizeof (CHAR16) * HelpInfoIndex,\r
+      FormatHelpString,\r
+      TimeString\r
+    );\r
+    SECUREBOOT_FREE_NON_NULL (FormatHelpString);\r
+    FormatHelpString = NULL;\r
   }\r
-  \r
+\r
+  *StringId = HiiSetString (PrivateData->HiiHandle, 0, HelpInfoString, NULL);\r
+ON_EXIT:\r
+  SECUREBOOT_FREE_NON_NULL (DataString);\r
+  SECUREBOOT_FREE_NON_NULL (HelpInfoString);\r
+\r
+  SECUREBOOT_FREE_NON_NULL (FormatTypeString);\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
-  This function allows a caller to extract the current configuration for one\r
-  or more named elements from the target driver.\r
-\r
-  @param[in]   This              Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
-  @param[in]   Request           A null-terminated Unicode string in\r
-                                 <ConfigRequest> format.\r
-  @param[out]  Progress          On return, points to a character in the Request\r
-                                 string. Points to the string's null terminator if\r
-                                 request was successful. Points to the most recent\r
-                                 '&' before the first failing name/value pair (or\r
-                                 the beginning of the string if the failure is in\r
-                                 the first name/value pair) if the request was not\r
-                                 successful.\r
-  @param[out]  Results           A null-terminated Unicode string in\r
-                                 <ConfigAltResp> format which has all values filled\r
-                                 in for the names in the Request string. String to\r
-                                 be allocated by the called function.\r
+  This functino to load signature data under the signature list.\r
 \r
-  @retval EFI_SUCCESS            The Results is filled with the requested values.\r
-  @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
-  @retval EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.\r
-  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
-                                 driver.\r
+  @param[in]  PrivateData         Module's private data.\r
+  @param[in]  LabelId             Label number to insert opcodes.\r
+  @param[in]  FormId              Form ID of current page.\r
+  @param[in]  QuestionIdBase      Base question id of the signature list.\r
+  @param[in]  ListIndex           Indicate to load which signature list.\r
 \r
+  @retval   EFI_SUCCESS           Success to update the signature list page\r
+  @retval   EFI_OUT_OF_RESOURCES  Unable to allocate required resources.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-SecureBootExtractConfig (\r
-  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL        *This,\r
-  IN CONST EFI_STRING                            Request,\r
-       OUT EFI_STRING                            *Progress,\r
-       OUT EFI_STRING                            *Results\r
+LoadSignatureData (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData,\r
+  IN UINT16                         LabelId,\r
+  IN EFI_FORM_ID                    FormId,\r
+  IN EFI_QUESTION_ID                QuestionIdBase,\r
+  IN UINT16                         ListIndex\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  UINTN                             BufferSize;\r
-  UINTN                             Size;\r
-  SECUREBOOT_CONFIGURATION          Configuration;\r
-  EFI_STRING                        ConfigRequest;\r
-  EFI_STRING                        ConfigRequestHdr;\r
-  SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData;\r
-  BOOLEAN                           AllocatedRequest;\r
+  EFI_STATUS            Status;\r
+  EFI_SIGNATURE_LIST    *ListWalker;\r
+  EFI_SIGNATURE_DATA    *DataWalker;\r
+  EFI_IFR_GUID_LABEL    *StartLabel;\r
+  EFI_IFR_GUID_LABEL    *EndLabel;\r
+  EFI_STRING_ID         HelpStringId;\r
+  EFI_STRING            FormatNameString;\r
+  VOID                  *StartOpCodeHandle;\r
+  VOID                  *EndOpCodeHandle;\r
+  UINTN                 DataSize;\r
+  UINTN                 RemainingSize;\r
+  UINT16                Index;\r
+  UINT8                 *VariableData;\r
+  CHAR16                VariableName[BUFFER_MAX_SIZE];\r
+  CHAR16                NameBuffer[BUFFER_MAX_SIZE];\r
+\r
+  Status              = EFI_SUCCESS;\r
+  FormatNameString    = NULL;\r
+  StartOpCodeHandle   = NULL;\r
+  EndOpCodeHandle     = NULL;\r
+  Index               = 0;\r
+  VariableData        = NULL;\r
 \r
-  if (Progress == NULL || Results == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
+  //\r
+  // Initialize the container for dynamic opcodes.\r
+  //\r
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (StartOpCodeHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
   }\r
-  \r
-  AllocatedRequest = FALSE;\r
-  ConfigRequestHdr = NULL;\r
-  ConfigRequest    = NULL;\r
-  Size             = 0;\r
-  \r
-  ZeroMem (&Configuration, sizeof (Configuration));\r
-  PrivateData      = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
-  *Progress        = Request;\r
-  \r
-  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
-    return EFI_NOT_FOUND;\r
+\r
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (EndOpCodeHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
   }\r
 \r
   //\r
-  // Get Configuration from Variable.\r
+  // Create Hii Extend Label OpCode.\r
   //\r
-  SecureBootExtractConfigFromVariable (&Configuration);\r
-  \r
-  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
-  ConfigRequest = Request;\r
-  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
-    //\r
-    // Request is set to NULL or OFFSET is NULL, construct full request string.\r
-    //\r
-    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
-    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
-    //\r
-    ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
-    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
-    ConfigRequest = AllocateZeroPool (Size);\r
-    ASSERT (ConfigRequest != NULL);\r
-    AllocatedRequest = TRUE;\r
-    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
-    FreePool (ConfigRequestHdr);\r
-    ConfigRequestHdr = NULL;\r
-  }\r
+  StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
+                                       StartOpCodeHandle,\r
+                                       &gEfiIfrTianoGuid,\r
+                                       NULL,\r
+                                       sizeof (EFI_IFR_GUID_LABEL)\r
+                                     );\r
+  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
+  StartLabel->Number        = LabelId;\r
+\r
+  EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (\r
+                                     EndOpCodeHandle,\r
+                                     &gEfiIfrTianoGuid,\r
+                                     NULL,\r
+                                     sizeof (EFI_IFR_GUID_LABEL)\r
+                                   );\r
+  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;\r
+  EndLabel->Number        = LABEL_END;\r
 \r
-  Status = gHiiConfigRouting->BlockToConfig (\r
-                                gHiiConfigRouting,\r
-                                ConfigRequest,\r
-                                (UINT8 *) &Configuration,\r
-                                BufferSize,\r
-                                Results,\r
-                                Progress\r
-                                );\r
+  if (PrivateData->VariableName == Variable_DB) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE);\r
+  } else if (PrivateData->VariableName == Variable_DBX) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1);\r
+  } else if (PrivateData->VariableName == Variable_DBT) {\r
+    UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2);\r
+  } else {\r
+    goto ON_EXIT;\r
+  }\r
 \r
   //\r
-  // Free the allocated config request string.\r
+  // Read Variable, the variable name save in the PrivateData->VariableName.\r
   //\r
-  if (AllocatedRequest) {\r
-    FreePool (ConfigRequest);\r
+  DataSize = 0;\r
+  Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  VariableData = AllocateZeroPool (DataSize);\r
+  if (VariableData == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+  Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
   }\r
 \r
+  RemainingSize = DataSize;\r
+  ListWalker = (EFI_SIGNATURE_LIST *)VariableData;\r
+\r
   //\r
-  // Set Progress string to the original request string.\r
+  // Skip signature list.\r
   //\r
-  if (Request == NULL) {\r
-    *Progress = NULL;\r
-  } else if (StrStr (Request, L"OFFSET") == NULL) {\r
-    *Progress = Request + StrLen (Request);\r
+  while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex-- > 0) {\r
+    RemainingSize -= ListWalker->SignatureListSize;\r
+    ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize);\r
   }\r
 \r
-  return Status;\r
-}\r
+  FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT), NULL);\r
+  if (FormatNameString == NULL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof(EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize);\r
+  for (Index = 0; Index < SIGNATURE_DATA_COUNTS(ListWalker); Index = Index + 1) {\r
+    //\r
+    // Format name buffer.\r
+    //\r
+    ZeroMem (NameBuffer, sizeof (NameBuffer));\r
+    UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1);\r
+\r
+    //\r
+    // Format help info buffer.\r
+    //\r
+    Status = FormatHelpInfo (PrivateData, ListWalker, DataWalker, &HelpStringId);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_EXIT;\r
+    }\r
 \r
-/**\r
-  This function processes the results of changes in configuration.\r
+    HiiCreateCheckBoxOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(QuestionIdBase + Index),\r
+      0,\r
+      0,\r
+      HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL),\r
+      HelpStringId,\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      0,\r
+      NULL\r
+    );\r
 \r
-  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
-  @param[in]  Configuration      A null-terminated Unicode string in <ConfigResp>\r
-                                 format.\r
-  @param[out] Progress           A pointer to a string filled in with the offset of\r
-                                 the most recent '&' before the first failing\r
-                                 name/value pair (or the beginning of the string if\r
-                                 the failure is in the first name/value pair) or\r
-                                 the terminating NULL if all was successful.\r
+    ZeroMem(NameBuffer, 100);\r
+    DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);\r
+  }\r
 \r
-  @retval EFI_SUCCESS            The Results is processed successfully.\r
-  @retval EFI_INVALID_PARAMETER  Configuration is NULL.\r
-  @retval EFI_NOT_FOUND          Routing data doesn't match any storage in this\r
-                                 driver.\r
+  //\r
+  // Allocate a buffer to record which signature data will be checked.\r
+  // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.\r
+  //\r
+  PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker) * sizeof (BOOLEAN));\r
+ON_EXIT:\r
+  HiiUpdateForm (\r
+    PrivateData->HiiHandle,\r
+    &gSecureBootConfigFormSetGuid,\r
+    FormId,\r
+    StartOpCodeHandle,\r
+    EndOpCodeHandle\r
+  );\r
 \r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SecureBootRouteConfig (\r
-  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
-  IN CONST EFI_STRING                          Configuration,\r
-       OUT EFI_STRING                          *Progress\r
-  )\r
-{\r
-  if (Configuration == NULL || Progress == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);\r
+  SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);\r
 \r
-  *Progress = Configuration;\r
-  if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
+  SECUREBOOT_FREE_NON_NULL (VariableData);\r
+  SECUREBOOT_FREE_NON_NULL (FormatNameString);\r
 \r
-  *Progress = Configuration + StrLen (Configuration);\r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -2293,25 +4304,36 @@ SecureBootCallback (
   )\r
 {\r
   EFI_INPUT_KEY                   Key;\r
-  EFI_STATUS                      Status;  \r
+  EFI_STATUS                      Status;\r
+  RETURN_STATUS                   RStatus;\r
   SECUREBOOT_CONFIG_PRIVATE_DATA  *Private;\r
   UINTN                           BufferSize;\r
   SECUREBOOT_CONFIGURATION        *IfrNvData;\r
   UINT16                          LabelId;\r
   UINT8                           *SecureBootEnable;\r
-\r
+  UINT8                           *Pk;\r
+  UINT8                           *SecureBootMode;\r
+  UINT8                           *SetupMode;\r
+  CHAR16                          PromptString[100];\r
+  EFI_DEVICE_PATH_PROTOCOL        *File;\r
+  UINTN                           NameLength;\r
+  UINT16                          *FilePostFix;\r
+  SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData;\r
+\r
+  Status           = EFI_SUCCESS;\r
   SecureBootEnable = NULL;\r
+  SecureBootMode   = NULL;\r
+  SetupMode        = NULL;\r
+  File             = NULL;\r
 \r
   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-  \r
   Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
 \r
+  gSecureBootPrivateData = Private;\r
+\r
   //\r
   // Retrieve uncommitted data from Browser\r
   //\r
@@ -2321,16 +4343,65 @@ SecureBootCallback (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Status = EFI_SUCCESS;\r
+  HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);\r
+\r
+  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
+    if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
+      //\r
+      // Update secure boot strings when opening this form\r
+      //\r
+      Status = UpdateSecureBootString(Private);\r
+      SecureBootExtractConfigFromVariable (Private, IfrNvData);\r
+      mIsEnterSecureBootForm = TRUE;\r
+    } else {\r
+      //\r
+      // When entering SecureBoot OPTION Form\r
+      // always close opened file & free resource\r
+      //\r
+      if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION) ||\r
+          (QuestionId == KEY_SECURE_BOOT_KEK_OPTION) ||\r
+          (QuestionId == KEY_SECURE_BOOT_DB_OPTION) ||\r
+          (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) ||\r
+          (QuestionId == KEY_SECURE_BOOT_DBT_OPTION)) {\r
+        CloseEnrolledFile(Private->FileContext);\r
+      } else if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_LIST) {\r
+        //\r
+        // Update ListCount field in varstore\r
+        // Button "Delete All Signature List" is\r
+        // enable when ListCount is greater than 0.\r
+        //\r
+        IfrNvData->ListCount = Private->ListCount;\r
+      }\r
+    }\r
+    goto EXIT;\r
+  }\r
+\r
+  if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+    Status = EFI_UNSUPPORTED;\r
+    if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
+      if (mIsEnterSecureBootForm) {\r
+        Value->u8 = SECURE_BOOT_MODE_STANDARD;\r
+        Status = EFI_SUCCESS;\r
+      }\r
+    } \r
+    goto EXIT;\r
+  }\r
+\r
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) &&\r
+      (Action != EFI_BROWSER_ACTION_CHANGING) &&\r
+      (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&\r
+      (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto EXIT;\r
+  }\r
 \r
-  HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);\r
-  \r
   if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
 \r
     switch (QuestionId) {\r
     case KEY_SECURE_BOOT_ENABLE:\r
       GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
       if (NULL != SecureBootEnable) {\r
+        FreePool (SecureBootEnable);\r
         if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) {\r
           CreatePopUp (\r
             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
@@ -2339,19 +4410,22 @@ SecureBootCallback (
             NULL\r
             );\r
           Status = EFI_UNSUPPORTED;\r
+        } else {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Configuration changed, please reset the platform to take effect!",\r
+            NULL\r
+            );\r
         }\r
-        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; \r
       }\r
       break;\r
 \r
-    case KEY_SECURE_BOOT_OPTION:\r
-      FreeMenu (&DirectoryMenu);\r
-      FreeMenu (&FsOptionMenu);\r
-      break;\r
-\r
     case KEY_SECURE_BOOT_KEK_OPTION:\r
     case KEY_SECURE_BOOT_DB_OPTION:\r
     case KEY_SECURE_BOOT_DBX_OPTION:\r
+    case KEY_SECURE_BOOT_DBT_OPTION:\r
+      PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
       //\r
       // Clear Signature GUID.\r
       //\r
@@ -2363,10 +4437,17 @@ SecureBootCallback (
         }\r
       }\r
 \r
+      //\r
+      // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page\r
+      //\r
+      SecureBootExtractConfigFromVariable (PrivateData, IfrNvData);\r
+\r
       if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) {\r
         LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
       } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) {\r
         LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
+      } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) {\r
+        LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT;\r
       } else {\r
         LabelId = FORMID_ENROLL_KEK_FORM;\r
       }\r
@@ -2374,47 +4455,103 @@ SecureBootCallback (
       //\r
       // Refresh selected file.\r
       //\r
-      CleanUpPage (LabelId, Private);    \r
+      CleanUpPage (LabelId, Private);\r
+      break;\r
+    case KEY_SECURE_BOOT_PK_OPTION:\r
+      LabelId = FORMID_ENROLL_PK_FORM;\r
+      //\r
+      // Refresh selected file.\r
+      //\r
+      CleanUpPage (LabelId, Private);\r
+      break;\r
+\r
+    case FORMID_ENROLL_PK_FORM:\r
+      ChooseFile (NULL, NULL, UpdatePKFromFile, &File);\r
       break;\r
-  \r
-    case SECUREBOOT_ADD_PK_FILE_FORM_ID:\r
+\r
     case FORMID_ENROLL_KEK_FORM:\r
+      ChooseFile (NULL, NULL, UpdateKEKFromFile, &File);\r
+      break;\r
+\r
     case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:\r
+      ChooseFile (NULL, NULL, UpdateDBFromFile, &File);\r
+      break;\r
+\r
     case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:\r
-      if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) {\r
-        Private->FeCurrentState = FileExplorerStateEnrollPkFile;\r
-      } else if (QuestionId == FORMID_ENROLL_KEK_FORM) {\r
-        Private->FeCurrentState = FileExplorerStateEnrollKekFile;\r
-      } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) {\r
-        Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb;\r
-      } else {\r
-        Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx;\r
+      ChooseFile (NULL, NULL, UpdateDBXFromFile, &File);\r
+\r
+      if (Private->FileContext->FHandle != NULL) {\r
+        //\r
+        // Parse the file's postfix.\r
+        //\r
+        NameLength = StrLen (Private->FileContext->FileName);\r
+        if (NameLength <= 4) {\r
+          return FALSE;\r
+        }\r
+        FilePostFix = Private->FileContext->FileName + NameLength - 4;\r
+\r
+        if (IsDerEncodeCertificate (FilePostFix)) {\r
+          //\r
+          // Supports DER-encoded X509 certificate.\r
+          //\r
+          IfrNvData->FileEnrollType = X509_CERT_FILE_TYPE;\r
+        } else if (IsAuthentication2Format(Private->FileContext->FHandle)){\r
+          IfrNvData->FileEnrollType = AUTHENTICATION_2_FILE_TYPE;\r
+        } else {\r
+          IfrNvData->FileEnrollType = PE_IMAGE_FILE_TYPE;\r
+        }\r
+        Private->FileContext->FileType = IfrNvData->FileEnrollType;\r
+\r
+        //\r
+        // Clean up Certificate Format if File type is not X509 DER\r
+        //\r
+        if (IfrNvData->FileEnrollType != X509_CERT_FILE_TYPE) {\r
+          IfrNvData->CertificateFormat = HASHALG_RAW;\r
+        }\r
+        DEBUG((DEBUG_ERROR, "IfrNvData->FileEnrollType %d\n", Private->FileContext->FileType));\r
       }\r
 \r
-      Private->FeDisplayContext = FileExplorerDisplayUnknown;\r
-      CleanUpPage (FORM_FILE_EXPLORER_ID, Private);\r
-      UpdateFileExplorer (Private, 0);\r
       break;\r
 \r
-    case KEY_SECURE_BOOT_DELETE_PK: \r
-        if (Value->u8) {\r
+    case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT:\r
+      ChooseFile (NULL, NULL, UpdateDBTFromFile, &File);\r
+      break;\r
+\r
+    case KEY_SECURE_BOOT_DELETE_PK:\r
+      if (Value->u8) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Are you sure you want to delete PK? Secure boot will be disabled!",\r
+          L"Press 'Y' to delete PK and exit, 'N' to discard change and return",\r
+          NULL\r
+          );\r
+        if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {\r
           Status = DeletePlatformKey ();\r
-          *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
+          if (EFI_ERROR (Status)) {\r
+            CreatePopUp (\r
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+              &Key,\r
+              L"Only Physical Presence User could delete PK in custom mode!",\r
+              NULL\r
+              );\r
+          }\r
         }\r
+      }\r
       break;\r
 \r
     case KEY_DELETE_KEK:\r
       UpdateDeletePage (\r
-        Private, \r
+        Private,\r
         EFI_KEY_EXCHANGE_KEY_NAME,\r
         &gEfiGlobalVariableGuid,\r
         LABEL_KEK_DELETE,\r
         FORMID_DELETE_KEK_FORM,\r
-        OPTION_DEL_KEK_QUESTION_ID          \r
+        OPTION_DEL_KEK_QUESTION_ID\r
         );\r
       break;\r
 \r
-    case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:        \r
+    case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:\r
       UpdateDeletePage (\r
         Private,\r
         EFI_IMAGE_SECURITY_DATABASE,\r
@@ -2425,34 +4562,200 @@ SecureBootCallback (
         );\r
        break;\r
 \r
-    case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:\r
+    //\r
+    // From DBX option to the level-1 form, display signature list.\r
+    //\r
+    case KEY_VALUE_FROM_DBX_TO_LIST_FORM:\r
+      Private->VariableName = Variable_DBX;\r
+      LoadSignatureList (\r
+        Private,\r
+        LABEL_SIGNATURE_LIST_START,\r
+        SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
+        OPTION_SIGNATURE_LIST_QUESTION_ID\r
+      );\r
+      break;\r
+\r
+      //\r
+      // Delete all signature list and reload.\r
+      //\r
+    case KEY_SECURE_BOOT_DELETE_ALL_LIST:\r
+      CreatePopUp(\r
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+        &Key,\r
+        L"Press 'Y' to delete signature list.",\r
+        L"Press other key to cancel and exit.",\r
+        NULL\r
+      );\r
+\r
+      if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
+        DeleteSignatureEx (Private, Delete_Signature_List_All, IfrNvData->CheckedDataCount);\r
+      }\r
+\r
+      LoadSignatureList (\r
+        Private,\r
+        LABEL_SIGNATURE_LIST_START,\r
+        SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
+        OPTION_SIGNATURE_LIST_QUESTION_ID\r
+      );\r
+      break;\r
+\r
+      //\r
+      // Delete one signature list and reload.\r
+      //\r
+    case KEY_SECURE_BOOT_DELETE_ALL_DATA:\r
+      CreatePopUp(\r
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+        &Key,\r
+        L"Press 'Y' to delete signature data.",\r
+        L"Press other key to cancel and exit.",\r
+        NULL\r
+      );\r
+\r
+      if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
+        DeleteSignatureEx (Private, Delete_Signature_List_One, IfrNvData->CheckedDataCount);\r
+      }\r
+\r
+      LoadSignatureList (\r
+        Private,\r
+        LABEL_SIGNATURE_LIST_START,\r
+        SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
+        OPTION_SIGNATURE_LIST_QUESTION_ID\r
+      );\r
+      break;\r
+\r
+      //\r
+      // Delete checked signature data and reload.\r
+      //\r
+    case KEY_SECURE_BOOT_DELETE_CHECK_DATA:\r
+      CreatePopUp(\r
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+        &Key,\r
+        L"Press 'Y' to delete signature data.",\r
+        L"Press other key to cancel and exit.",\r
+        NULL\r
+      );\r
+\r
+      if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
+        DeleteSignatureEx (Private, Delete_Signature_Data, IfrNvData->CheckedDataCount);\r
+      }\r
+\r
+      LoadSignatureList (\r
+        Private,\r
+        LABEL_SIGNATURE_LIST_START,\r
+        SECUREBOOT_DELETE_SIGNATURE_LIST_FORM,\r
+        OPTION_SIGNATURE_LIST_QUESTION_ID\r
+      );\r
+      break;\r
+\r
+    case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT:\r
       UpdateDeletePage (\r
         Private,\r
-        EFI_IMAGE_SECURITY_DATABASE1,\r
+        EFI_IMAGE_SECURITY_DATABASE2,\r
         &gEfiImageSecurityDatabaseGuid,\r
-        LABEL_DBX_DELETE,\r
-        SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
-        OPTION_DEL_DBX_QUESTION_ID\r
+        LABEL_DBT_DELETE,\r
+        SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
+        OPTION_DEL_DBT_QUESTION_ID\r
         );\r
 \r
       break;\r
 \r
     case KEY_VALUE_SAVE_AND_EXIT_KEK:\r
       Status = EnrollKeyExchangeKey (Private);\r
+      if (EFI_ERROR (Status)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"ERROR: Unsupported file type!",\r
+          L"Only supports DER-encoded X509 certificate",\r
+          NULL\r
+          );\r
+      }\r
       break;\r
 \r
     case KEY_VALUE_SAVE_AND_EXIT_DB:\r
       Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);\r
+      if (EFI_ERROR (Status)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"ERROR: Unsupported file type!",\r
+          L"Only supports DER-encoded X509 certificate and executable EFI image",\r
+          NULL\r
+          );\r
+      }\r
       break;\r
 \r
     case KEY_VALUE_SAVE_AND_EXIT_DBX:\r
-      Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
+      if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Enrollment failed! Same certificate had already been in the dbx!",\r
+          NULL\r
+          );\r
+\r
+        //\r
+        // Cert already exists in DBX. Close opened file before exit.\r
+        //\r
+        CloseEnrolledFile(Private->FileContext);\r
+        break;\r
+      }\r
+\r
+      if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) {\r
+        Status = EnrollX509HashtoSigDB (\r
+                   Private,\r
+                   IfrNvData->CertificateFormat,\r
+                   &IfrNvData->RevocationDate,\r
+                   &IfrNvData->RevocationTime,\r
+                   IfrNvData->AlwaysRevocation\r
+                   );\r
+        IfrNvData->CertificateFormat = HASHALG_RAW;\r
+      } else {\r
+        Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
+      }\r
+      if (EFI_ERROR (Status)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"ERROR: Unsupported file type!",\r
+          L"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image",\r
+          NULL\r
+          );\r
+      }\r
       break;\r
 \r
+    case KEY_VALUE_SAVE_AND_EXIT_DBT:\r
+      Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2);\r
+      if (EFI_ERROR (Status)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"ERROR: Unsupported file type!",\r
+          L"Only supports DER-encoded X509 certificate.",\r
+          NULL\r
+          );\r
+      }\r
+      break;\r
+    case KEY_VALUE_SAVE_AND_EXIT_PK:\r
+      Status = EnrollPlatformKey (Private);\r
+      if (EFI_ERROR (Status)) {\r
+        UnicodeSPrint (\r
+          PromptString,\r
+          sizeof (PromptString),\r
+          L"Only DER encoded certificate file (%s) is supported.",\r
+          mSupportX509Suffix\r
+          );\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"ERROR: Unsupported file type!",\r
+          PromptString,\r
+          NULL\r
+          );\r
+      }\r
+      break;\r
     default:\r
-      if (QuestionId >= FILE_OPTION_OFFSET) {\r
-        UpdateFileExplorer (Private, QuestionId);\r
-      } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&\r
+      if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) &&\r
                  (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
         DeleteKeyExchangeKey (Private, QuestionId);\r
       } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) &&\r
@@ -2461,106 +4764,143 @@ SecureBootCallback (
           Private,\r
           EFI_IMAGE_SECURITY_DATABASE,\r
           &gEfiImageSecurityDatabaseGuid,\r
-          LABEL_DB_DELETE,   \r
+          LABEL_DB_DELETE,\r
           SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
           OPTION_DEL_DB_QUESTION_ID,\r
           QuestionId - OPTION_DEL_DB_QUESTION_ID\r
           );\r
-      } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) &&\r
-                 (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
+      } else if ((QuestionId >= OPTION_SIGNATURE_LIST_QUESTION_ID) &&\r
+                 (QuestionId < (OPTION_SIGNATURE_LIST_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
+        LoadSignatureData (\r
+          Private,\r
+          LABEL_SIGNATURE_DATA_START,\r
+          SECUREBOOT_DELETE_SIGNATURE_DATA_FORM,\r
+          OPTION_SIGNATURE_DATA_QUESTION_ID,\r
+          QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID\r
+        );\r
+        Private->ListIndex = QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID;\r
+      } else if ((QuestionId >= OPTION_SIGNATURE_DATA_QUESTION_ID) &&\r
+                 (QuestionId < (OPTION_SIGNATURE_DATA_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
+        if (Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID]) {\r
+          IfrNvData->CheckedDataCount--;\r
+          Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = FALSE;\r
+        } else {\r
+          IfrNvData->CheckedDataCount++;\r
+          Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = TRUE;\r
+        }\r
+      } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) &&\r
+                 (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
         DeleteSignature (\r
           Private,\r
-          EFI_IMAGE_SECURITY_DATABASE1,\r
+          EFI_IMAGE_SECURITY_DATABASE2,\r
           &gEfiImageSecurityDatabaseGuid,\r
-          LABEL_DBX_DELETE,   \r
-          SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
-          OPTION_DEL_DBX_QUESTION_ID,\r
-          QuestionId - OPTION_DEL_DBX_QUESTION_ID\r
+          LABEL_DBT_DELETE,\r
+          SECUREBOOT_DELETE_SIGNATURE_FROM_DBT,\r
+          OPTION_DEL_DBT_QUESTION_ID,\r
+          QuestionId - OPTION_DEL_DBT_QUESTION_ID\r
           );\r
       }\r
       break;\r
-    }\r
-  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
-    switch (QuestionId) {\r
-    case KEY_SECURE_BOOT_ENABLE:\r
-      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;      \r
-      break;  \r
-    case KEY_VALUE_SAVE_AND_EXIT_PK:\r
-      Status = EnrollPlatformKey (Private);\r
-      if (EFI_ERROR (Status)) {\r
-        CreatePopUp (\r
-          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
-          &Key,\r
-          L"ERROR: Unsupported file type, only *.cer is supported!",\r
-          NULL\r
-          );\r
-      } else {\r
-        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; \r
-      }        \r
-      break;\r
 \r
     case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
     case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
     case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
     case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
-      if (Private->FileContext->FHandle != NULL) {\r
-        CloseFile (Private->FileContext->FHandle);\r
-        Private->FileContext->FHandle = NULL;\r
-        Private->FileContext->FileName = NULL;\r
-      }\r
-   \r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_DBT:\r
+      CloseEnrolledFile(Private->FileContext);\r
+\r
       if (Private->SignatureGUID != NULL) {\r
         FreePool (Private->SignatureGUID);\r
         Private->SignatureGUID = NULL;\r
       }\r
-      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
       break;\r
-      \r
+    }\r
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+    switch (QuestionId) {\r
+    case KEY_SECURE_BOOT_ENABLE:\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
+      break;\r
     case KEY_SECURE_BOOT_MODE:\r
-      GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootEnable, NULL);\r
-      if (NULL != SecureBootEnable) {\r
-        Status = gRT->SetVariable (                          \r
-                        EFI_CUSTOM_MODE_NAME,\r
-                        &gEfiCustomModeEnableGuid,\r
-                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                        sizeof (UINT8),\r
-                        &Value->u8\r
-                        );\r
-        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
-        IfrNvData->SecureBootMode = Value->u8;\r
-      }        \r
+      mIsEnterSecureBootForm = FALSE;\r
       break;\r
-\r
     case KEY_SECURE_BOOT_KEK_GUID:\r
     case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
     case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
+    case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT:\r
       ASSERT (Private->SignatureGUID != NULL);\r
-      Status = StringToGuid (\r
-                 IfrNvData->SignatureGuid,\r
-                 StrLen (IfrNvData->SignatureGuid),\r
-                 Private->SignatureGUID\r
-                 );\r
-      if (EFI_ERROR (Status)) {\r
+      RStatus = StrToGuid (IfrNvData->SignatureGuid, Private->SignatureGUID);\r
+      if (RETURN_ERROR (RStatus) || (IfrNvData->SignatureGuid[GUID_STRING_LENGTH] != L'\0')) {\r
+        Status = EFI_INVALID_PARAMETER;\r
         break;\r
       }\r
 \r
       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
       break;\r
-\r
     case KEY_SECURE_BOOT_DELETE_PK:\r
-      if (Value->u8) {\r
+      GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
+      if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
+        IfrNvData->DeletePk = TRUE;\r
+        IfrNvData->HasPk    = FALSE;\r
         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+      } else  {\r
+        IfrNvData->DeletePk = FALSE;\r
+        IfrNvData->HasPk    = TRUE;\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
+      }\r
+      if (SetupMode != NULL) {\r
+        FreePool (SetupMode);\r
+      }\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+  } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) {\r
+    if (QuestionId == KEY_HIDE_SECURE_BOOT) {\r
+      GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID**)&Pk, NULL);\r
+      if (Pk == NULL) {\r
+        IfrNvData->HideSecureBoot = TRUE;\r
+      } else {\r
+        FreePool (Pk);\r
+        IfrNvData->HideSecureBoot = FALSE;\r
       }\r
-      break;  \r
+      Value->b = IfrNvData->HideSecureBoot;\r
+    }\r
+  } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {\r
+    //\r
+    // Force the platform back to Standard Mode once user leave the setup screen.\r
+    //\r
+    GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL);\r
+    if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) {\r
+      IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
+      SetSecureBootMode(STANDARD_SECURE_BOOT_MODE);\r
+    }\r
+    if (SecureBootMode != NULL) {\r
+      FreePool (SecureBootMode);\r
+    }\r
+\r
+    if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_DATA) {\r
+      //\r
+      // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form.\r
+      //\r
+      SECUREBOOT_FREE_NON_NULL (Private->CheckArray);\r
+      IfrNvData->CheckedDataCount = 0;\r
     }\r
   }\r
-  \r
+\r
+EXIT:\r
+\r
   if (!EFI_ERROR (Status)) {\r
     BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
-    HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8*) IfrNvData, NULL);\r
+    HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
   }\r
+\r
   FreePool (IfrNvData);\r
-  \r
+\r
+  if (File != NULL){\r
+    FreePool(File);\r
+    File = NULL;\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -2625,18 +4965,11 @@ InstallSecureBootConfigForm (
   PrivateData->HiiHandle = HiiHandle;\r
 \r
   PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
-  PrivateData->MenuEntry   = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));\r
-  \r
-  if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) {\r
+\r
+  if (PrivateData->FileContext == NULL) {\r
     UninstallSecureBootConfigForm (PrivateData);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  \r
-  PrivateData->FeCurrentState = FileExplorerStateInActive;\r
-  PrivateData->FeDisplayContext = FileExplorerDisplayUnknown;\r
-  \r
-  InitializeListHead (&FsOptionMenu.Head);\r
-  InitializeListHead (&DirectoryMenu.Head);\r
 \r
   //\r
   // Init OpCode Handle and Allocate space for creation of Buffer\r
@@ -2675,7 +5008,7 @@ InstallSecureBootConfigForm (
                                        );\r
   mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
   mEndLabel->Number       = LABEL_END;\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -2717,19 +5050,12 @@ UninstallSecureBootConfigForm (
     FreePool (PrivateData->SignatureGUID);\r
   }\r
 \r
-  if (PrivateData->MenuEntry != NULL) {\r
-    FreePool (PrivateData->MenuEntry);\r
-  }\r
-\r
   if (PrivateData->FileContext != NULL) {\r
     FreePool (PrivateData->FileContext);\r
   }\r
 \r
   FreePool (PrivateData);\r
 \r
-  FreeMenu (&DirectoryMenu);\r
-  FreeMenu (&FsOptionMenu);\r
-\r
   if (mStartOpCodeHandle != NULL) {\r
     HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
   }\r