]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
SecurityPkg: remove PE/COFF header workaround for ELILO on IPF
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / SecureBootConfigDxe / SecureBootConfigImpl.c
index f0a3f076378c5a9f43b07ffaddd015250734e832..f96325e978a5c5c390f21807b2488667633b33af 100644 (file)
@@ -1,20 +1,22 @@
 /** @file\r
   HII Config Access protocol implementation of SecureBoot configuration module.\r
 \r
-Copyright (c) 2011, 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
+Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
 **/\r
 \r
 #include "SecureBootConfigImpl.h"\r
+#include <Library/BaseCryptLib.h>\r
 \r
-CHAR16                          mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";\r
+CHAR16              mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";\r
 \r
 SECUREBOOT_CONFIG_PRIVATE_DATA         mSecureBootConfigPrivateDateTemplate = {\r
   SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,\r
@@ -40,15 +42,167 @@ HII_VENDOR_DEVICE_PATH          mSecureBootHiiVendorDevicePath = {
   {\r
     END_DEVICE_PATH_TYPE,\r
     END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-    { \r
+    {\r
       (UINT8) (END_DEVICE_PATH_LENGTH),\r
       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
     }\r
   }\r
 };\r
 \r
+\r
+BOOLEAN mIsEnterSecureBootForm = FALSE;\r
+\r
+//\r
+// OID ASN.1 Value for Hash Algorithms\r
+//\r
+UINT8 mHashOidValue[] = {\r
+  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,         // OBJ_md5\r
+  0x2B, 0x0E, 0x03, 0x02, 0x1A,                           // OBJ_sha1\r
+  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,   // OBJ_sha224\r
+  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,   // OBJ_sha256\r
+  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,   // OBJ_sha384\r
+  0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,   // OBJ_sha512\r
+  };\r
+\r
+HASH_TABLE mHash[] = {\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
+UINT32            mPeCoffHeaderOffset = 0;\r
+WIN_CERTIFICATE   *mCertificate = NULL;\r
+IMAGE_TYPE        mImageType;\r
+UINT8             *mImageBase = NULL;\r
+UINTN             mImageSize = 0;\r
+UINT8             mImageDigest[MAX_DIGEST_SIZE];\r
+UINTN             mImageDigestSize;\r
+EFI_GUID          mCertType;\r
+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
-  Save Secure Boot option to variable space.\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
 \r
   @param[in] VarValue              The option of Secure Boot.\r
 \r
@@ -62,184 +216,4048 @@ SaveSecureBootVariable (
   )\r
 {\r
   EFI_STATUS                       Status;\r
-  \r
+\r
   Status = gRT->SetVariable (\r
-             EFI_SECURE_BOOT_ENABLE_NAME, \r
+             EFI_SECURE_BOOT_ENABLE_NAME,\r
              &gEfiSecureBootEnableDisableGuid,\r
-             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, \r
-             sizeof (UINT8), \r
+             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+             sizeof (UINT8),\r
              &VarValue\r
              );\r
+  return Status;\r
+}\r
+\r
+/**\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
+  @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
+                                   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
+\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
+  @retval EFI_INVALID_PARAMETER    The parameter is invalid.\r
+  @retval Others                   Unexpected error happens.\r
+\r
+**/\r
+EFI_STATUS\r
+CreateTimeBasedPayload (\r
+  IN OUT UINTN            *DataSize,\r
+  IN OUT UINT8            **Data\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINT8                            *NewData;\r
+  UINT8                            *Payload;\r
+  UINTN                            PayloadSize;\r
+  EFI_VARIABLE_AUTHENTICATION_2    *DescriptorData;\r
+  UINTN                            DescriptorSize;\r
+  EFI_TIME                         Time;\r
+\r
+  if (Data == NULL || DataSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\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
+  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
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if ((Payload != NULL) && (PayloadSize != 0)) {\r
+    CopyMem (NewData + DescriptorSize, Payload, PayloadSize);\r
+  }\r
+\r
+  DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);\r
+\r
+  ZeroMem (&Time, sizeof (EFI_TIME));\r
+  Status = gRT->GetTime (&Time, NULL);\r
   if (EFI_ERROR (Status)) {\r
+    FreePool(NewData);\r
     return Status;\r
   }\r
-  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+  Time.Pad1       = 0;\r
+  Time.Nanosecond = 0;\r
+  Time.TimeZone   = 0;\r
+  Time.Daylight   = 0;\r
+  Time.Pad2       = 0;\r
+  CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));\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
+  if (Payload != NULL) {\r
+    FreePool(Payload);\r
+  }\r
+\r
+  *DataSize = DescriptorSize + PayloadSize;\r
+  *Data     = NewData;\r
   return EFI_SUCCESS;\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
+  Internal helper function to delete a Variable given its name and GUID, NO authentication\r
+  required.\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
+  @param[in]      VariableName            Name of the Variable.\r
+  @param[in]      VendorGuid              GUID of the Variable.\r
+\r
+  @retval EFI_SUCCESS              Variable deleted successfully.\r
+  @retval Others                   The driver failed to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteVariable (\r
+  IN  CHAR16                    *VariableName,\r
+  IN  EFI_GUID                  *VendorGuid\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  VOID*                   Variable;\r
+  UINT8                   *Data;\r
+  UINTN                   DataSize;\r
+  UINT32                  Attr;\r
+\r
+  GetVariable2 (VariableName, VendorGuid, &Variable, NULL);\r
+  if (Variable == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  FreePool (Variable);\r
+\r
+  Data     = NULL;\r
+  DataSize = 0;\r
+  Attr     = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS\r
+             | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r
+\r
+  Status = CreateTimeBasedPayload (&DataSize, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
+    return Status;\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VariableName,\r
+                  VendorGuid,\r
+                  Attr,\r
+                  DataSize,\r
+                  Data\r
+                  );\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
+  }\r
+  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
+  @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
+EFI_STATUS\r
+CreatePkX509SignatureList (\r
+  IN    EFI_FILE_HANDLE             X509File,\r
+  OUT   EFI_SIGNATURE_LIST          **PkCert\r
+  )\r
+{\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
+  Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (X509Data != NULL);\r
+\r
+  //\r
+  // Allocate space for PK certificate list and initialize it.\r
+  // Create PK database entry with SignatureHeaderSize equals 0.\r
+  //\r
+  *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool (\r
+              sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1\r
+              + X509DataSize\r
+              );\r
+  if (*PkCert == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\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
+                                                          + sizeof(EFI_SIGNATURE_LIST)\r
+                                                          + (*PkCert)->SignatureHeaderSize);\r
+  CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid);\r
+  //\r
+  // Fill the PK database with PKpub data from X509 certificate file.\r
+  //\r
+  CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize);\r
+\r
+ON_EXIT:\r
+\r
+  if (X509Data != NULL) {\r
+    FreePool (X509Data);\r
+  }\r
+\r
+  if (EFI_ERROR(Status) && *PkCert != NULL) {\r
+    FreePool (*PkCert);\r
+    *PkCert = NULL;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enroll new PK into the System without original PK's authentication.\r
+\r
+  The SignatureOwner GUID will be the same with PK's vendorguid.\r
+\r
+  @param[in] PrivateData     The module's private data.\r
+\r
+  @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
+EFI_STATUS\r
+EnrollPlatformKey (\r
+   IN  SECUREBOOT_CONFIG_PRIVATE_DATA*   Private\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINT32                          Attr;\r
+  UINTN                           DataSize;\r
+  EFI_SIGNATURE_LIST              *PkCert;\r
+  UINT16*                         FilePostFix;\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 DER encoded X.509 certificate files.\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
+    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
+  DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));\r
+\r
+  //\r
+  // Prase the selected PK file and generature PK certificate list.\r
+  //\r
+  Status = CreatePkX509SignatureList (\r
+            Private->FileContext->FHandle,\r
+            &PkCert\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (PkCert != NULL);\r
+\r
+  //\r
+  // Set Platform Key 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
+  DataSize = PkCert->SignatureListSize;\r
+  Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert);\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
+  Status = gRT->SetVariable(\r
+                  EFI_PLATFORM_KEY_NAME,\r
+                  &gEfiGlobalVariableGuid,\r
+                  Attr,\r
+                  DataSize,\r
+                  PkCert\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n"));\r
+    }\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+\r
+  if (PkCert != NULL) {\r
+    FreePool(PkCert);\r
+  }\r
+\r
+  CloseEnrolledFile(Private->FileContext);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Remove the PK variable.\r
+\r
+  @retval EFI_SUCCESS    Delete PK successfully.\r
+  @retval Others         Could not allow to delete PK.\r
+\r
+**/\r
+EFI_STATUS\r
+DeletePlatformKey (\r
+  VOID\r
+)\r
+{\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
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enroll a new KEK item from public key storing file (*.pbk).\r
+\r
+  @param[in] PrivateData           The module's private data.\r
+\r
+  @retval   EFI_SUCCESS            New KEK 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
+EnrollRsa2048ToKek (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINT32                          Attr;\r
+  UINTN                           DataSize;\r
+  EFI_SIGNATURE_LIST              *KekSigList;\r
+  UINTN                           KeyBlobSize;\r
+  UINT8                           *KeyBlob;\r
+  CPL_KEY_INFO                    *KeyInfo;\r
+  EFI_SIGNATURE_DATA              *KEKSigData;\r
+  UINTN                           KekSigListSize;\r
+  UINT8                           *KeyBuffer;\r
+  UINTN                           KeyLenInBytes;\r
+\r
+  Attr        = 0;\r
+  DataSize    = 0;\r
+  KeyBuffer   = NULL;\r
+  KeyBlobSize = 0;\r
+  KeyBlob     = NULL;\r
+  KeyInfo     = NULL;\r
+  KEKSigData  = NULL;\r
+  KekSigList  = NULL;\r
+  KekSigListSize = 0;\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
+  Status = ReadFileContent (\r
+             Private->FileContext->FHandle,\r
+             (VOID**) &KeyBlob,\r
+             &KeyBlobSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (KeyBlob != NULL);\r
+  KeyInfo = (CPL_KEY_INFO *) KeyBlob;\r
+  if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) {\r
+    DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n"));\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Convert the Public key to fix octet string format represented in RSA PKCS#1.\r
+  //\r
+  KeyLenInBytes = KeyInfo->KeyLengthInBits / 8;\r
+  KeyBuffer = AllocateZeroPool (KeyLenInBytes);\r
+  if (KeyBuffer == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+  Int2OctStr (\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
+  // Form an new EFI_SIGNATURE_LIST.\r
+  //\r
+  KekSigListSize = sizeof(EFI_SIGNATURE_LIST)\r
+                     + sizeof(EFI_SIGNATURE_DATA) - 1\r
+                     + WIN_CERT_UEFI_RSA2048_SIZE;\r
+\r
+  KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
+  if (KekSigList == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  KekSigList->SignatureListSize   = sizeof(EFI_SIGNATURE_LIST)\r
+                                  + sizeof(EFI_SIGNATURE_DATA) - 1\r
+                                  + WIN_CERT_UEFI_RSA2048_SIZE;\r
+  KekSigList->SignatureHeaderSize = 0;\r
+  KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;\r
+  CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid);\r
+\r
+  KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST));\r
+  CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
+  CopyMem (\r
+    KEKSigData->SignatureData,\r
+    KeyBlob + sizeof(CPL_KEY_INFO),\r
+    WIN_CERT_UEFI_RSA2048_SIZE\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
+  // new KEK to original 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 = 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
+  Status = gRT->GetVariable(\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
+  // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,\r
+  //\r
+  Status = gRT->SetVariable(\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
+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 (KeyBlob != NULL) {\r
+    FreePool (KeyBlob);\r
+  }\r
+  if (KeyBuffer != NULL) {\r
+    FreePool (KeyBuffer);\r
+  }\r
+  if (KekSigList != NULL) {\r
+    FreePool (KekSigList);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enroll a new KEK item from X509 certificate file.\r
+\r
+  @param[in] PrivateData           The module's private data.\r
+\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
+EnrollX509ToKek (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             X509DataSize;\r
+  VOID                              *X509Data;\r
+  EFI_SIGNATURE_DATA                *KEKSigData;\r
+  EFI_SIGNATURE_LIST                *KekSigList;\r
+  UINTN                             DataSize;\r
+  UINTN                             KekSigListSize;\r
+  UINT32                            Attr;\r
+\r
+  X509Data       = NULL;\r
+  X509DataSize   = 0;\r
+  KekSigList     = NULL;\r
+  KekSigListSize = 0;\r
+  DataSize       = 0;\r
+  KEKSigData     = NULL;\r
+\r
+  Status = ReadFileContent (\r
+             Private->FileContext->FHandle,\r
+             &X509Data,\r
+             &X509DataSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (X509Data != NULL);\r
+\r
+  KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
+  KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize);\r
+  if (KekSigList == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Fill Certificate Database parameters.\r
+  //\r
+  KekSigList->SignatureListSize   = (UINT32) KekSigListSize;\r
+  KekSigList->SignatureHeaderSize = 0;\r
+  KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
+  CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid);\r
+\r
+  KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST));\r
+  CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID);\r
+  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
+  // new kek to original 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 = 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
+  Status = gRT->GetVariable(\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
+  Status = gRT->SetVariable(\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
+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 (KekSigList != NULL) {\r
+    FreePool (KekSigList);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Enroll new KEK into the System without PK's authentication.\r
+  The SignatureOwner GUID will be Private->SignatureGUID.\r
+\r
+  @param[in] PrivateData     The module's private data.\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
+EFI_STATUS\r
+EnrollKeyExchangeKey (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private\r
+  )\r
+{\r
+  UINT16*     FilePostFix;\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 DER-encoded X509 certificate,\r
+  // and .pbk as RSA public key 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
+    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 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
+                             EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
+\r
+  @retval   EFI_SUCCESS            New X509 is enrolled successfully.\r
+  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EnrollX509toSigDB (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
+  IN CHAR16                         *VariableName\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             X509DataSize;\r
+  VOID                              *X509Data;\r
+  EFI_SIGNATURE_LIST                *SigDBCert;\r
+  EFI_SIGNATURE_DATA                *SigDBCertData;\r
+  VOID                              *Data;\r
+  UINTN                             DataSize;\r
+  UINTN                             SigDBSize;\r
+  UINT32                            Attr;\r
+\r
+  X509DataSize  = 0;\r
+  SigDBSize     = 0;\r
+  DataSize      = 0;\r
+  X509Data      = NULL;\r
+  SigDBCert     = NULL;\r
+  SigDBCertData = NULL;\r
+  Data          = NULL;\r
+\r
+  Status = ReadFileContent (\r
+             Private->FileContext->FHandle,\r
+             &X509Data,\r
+             &X509DataSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (X509Data != NULL);\r
+\r
+  SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;\r
+\r
+  Data = AllocateZeroPool (SigDBSize);\r
+  if (Data == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Fill Certificate Database parameters.\r
+  //\r
+  SigDBCert = (EFI_SIGNATURE_LIST*) Data;\r
+  SigDBCert->SignatureListSize   = (UINT32) SigDBSize;\r
+  SigDBCert->SignatureHeaderSize = 0;\r
+  SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);\r
+  CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid);\r
+\r
+  SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST));\r
+  CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID);\r
+  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
+  // new signature data to original 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 = 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
+  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
+  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 (X509Data != NULL) {\r
+    FreePool (X509Data);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Check whether signature is in specified database.\r
+\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
+BOOLEAN\r
+IsSignatureFoundInDatabase (\r
+  IN CHAR16             *VariableName,\r
+  IN UINT8              *Signature,\r
+  IN UINTN              SignatureSize\r
+  )\r
+{\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
+  //\r
+  // Read signature database variable.\r
+  //\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
+  Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Enumerate all signature data in SigDB to check if executable's signature exists.\r
+  //\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
+\r
+Done:\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
+  }\r
+\r
+  return IsFound;\r
+}\r
+\r
+/**\r
+  Calculate the hash of a certificate data with the specified hash algorithm.\r
+\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
+CalculateCertHash (\r
+  IN  UINT8                 *CertData,\r
+  IN  UINTN                 CertSize,\r
+  IN  UINT32                HashAlg,\r
+  OUT UINT8                 *CertHash\r
+  )\r
+{\r
+  BOOLEAN                   Status;\r
+  VOID                      *HashCtx;\r
+  UINTN                     CtxSize;\r
+  UINT8                     *TBSCert;\r
+  UINTN                     TBSCertSize;\r
+\r
+  HashCtx = NULL;\r
+  Status  = FALSE;\r
+\r
+  if (HashAlg >= HASHALG_MAX) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Retrieve the TBSCertificate for Hash Calculation.\r
+  //\r
+  if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // 1. Initialize context of hash.\r
+  //\r
+  CtxSize = mHash[HashAlg].GetContextSize ();\r
+  HashCtx = AllocatePool (CtxSize);\r
+  ASSERT (HashCtx != NULL);\r
+\r
+  //\r
+  // 2. Initialize a hash context.\r
+  //\r
+  Status = mHash[HashAlg].HashInit (HashCtx);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // 3. Calculate the hash.\r
+  //\r
+  Status  = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // 4. Get the hash result.\r
+  //\r
+  ZeroMem (CertHash, mHash[HashAlg].DigestLength);\r
+  Status  = mHash[HashAlg].HashFinal (HashCtx, CertHash);\r
+\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
+  // Read signature database variable.\r
+  //\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
+  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
+  // Check whether the certificate hash exists in the forbidden database.\r
+  //\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
+\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
+    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
+      // Iterate each Signature Data Node within this CertList for verify.\r
+      //\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
+    DataSize -= DbxList->SignatureListSize;\r
+    DbxList   = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
+  }\r
+\r
+Done:\r
+  if (Data != NULL) {\r
+    FreePool (Data);\r
+  }\r
+\r
+  return IsFound;\r
+}\r
+\r
+/**\r
+  Check whether the signature list exists in given variable data.\r
+\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
+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
+  EFI_SIGNATURE_LIST      *SigList;\r
+  UINTN                   SiglistSize;\r
+\r
+  if ((Database == NULL) || (DatabaseSize == 0)) {\r
+    *Offset = 0;\r
+    return FALSE;\r
+  }\r
+\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
+  *Offset = 0;\r
+  return FALSE;\r
+}\r
+\r
+/**\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] 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 X509 is 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
+EFI_STATUS\r
+EnrollX509HashtoSigDB (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\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
+  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
+  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
+  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
+  // Get the certificate from file and calculate its hash.\r
+  //\r
+  Status = ReadFileContent (\r
+             Private->FileContext->FHandle,\r
+             &X509Data,\r
+             &X509DataSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  ASSERT (X509Data != NULL);\r
+\r
+  if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) {\r
+    goto ON_EXIT;\r
+  }\r
+\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
+\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
+  // Allocate memory for Signature and fill the Signature\r
+  //\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
+  //\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
+  // 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
+  //\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
+    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
+    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 = gRT->SetVariable(\r
+                  EFI_IMAGE_SECURITY_DATABASE1,\r
+                  &gEfiImageSecurityDatabaseGuid,\r
+                  Attr,\r
+                  DataSize,\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 (SignatureData != NULL) {\r
+    FreePool (SignatureData);\r
+  }\r
+\r
+  if (X509Data != NULL) {\r
+    FreePool (X509Data);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\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_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
+BOOLEAN\r
+IsX509CertInDbx (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private,\r
+  IN CHAR16                         *VariableName\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  UINTN               X509DataSize;\r
+  VOID                *X509Data;\r
+  BOOLEAN             IsFound;\r
+\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
+  // Check the raw certificate.\r
+  //\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 IsFound;\r
+}\r
+\r
+/**\r
+  Reads contents of a PE/COFF image in memory buffer.\r
+\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
+  @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
+EFIAPI\r
+SecureBootConfigImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+{\r
+  UINTN               EndPosition;\r
+\r
+  if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  EndPosition = FileOffset + *ReadSize;\r
+  if (EndPosition > mImageSize) {\r
+    *ReadSize = (UINT32)(mImageSize - FileOffset);\r
+  }\r
+\r
+  if (FileOffset >= mImageSize) {\r
+    *ReadSize = 0;\r
+  }\r
+\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
+  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
+\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 (mNtHeader.Pe32->OptionalHeader.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 (mNtHeader.Pe32->OptionalHeader.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 (mNtHeader.Pe32->OptionalHeader.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 (mNtHeader.Pe32->OptionalHeader.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 (mNtHeader.Pe32->OptionalHeader.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
+  //\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
+  // Check SecureBootEnable & Pk status, fix the inconsistence.\r
+  // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
+  // Checkbox.\r
+  //\r
+  ConfigData->AttemptSecureBoot = FALSE;\r
+  GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, 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
+  } else {\r
+    ConfigData->HideSecureBoot = TRUE;\r
+  }\r
+\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 (SecureBootEnable != NULL) {\r
+    FreePool (SecureBootEnable);\r
+  }\r
+  if (SetupMode != NULL) {\r
+    FreePool (SetupMode);\r
+  }\r
+  if (SecureBootMode != NULL) {\r
+    FreePool (SecureBootMode);\r
+  }\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
+\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
+**/\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
+  )\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
+\r
+  if (Progress == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\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
+\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
+  // Free the allocated config request string.\r
+  //\r
+  if (AllocatedRequest) {\r
+    FreePool (ConfigRequest);\r
+  }\r
+\r
+  //\r
+  // Set Progress string to the original request string.\r
+  //\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
+  *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
+  // Get Configuration from Variable.\r
+  //\r
+  SecureBootExtractConfigFromVariable (PrivateData, &IfrNvData);\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
+    return Status;\r
+  }\r
+\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
+  *Progress = Configuration + StrLen (Configuration);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function to load signature list, the update the menu page.\r
+\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
+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
+  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
+  // 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
+  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
+  // 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        = 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
+  // Read Variable, the variable name save in the PrivateData->VariableName.\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
+      ListType = STRING_TOKEN (STR_LIST_TYPE_UNKNOWN);\r
+    }\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
+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
+  // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'.\r
+  //\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
+  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
+  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
+  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
+  AsciiStrToUnicodeStrS (CNBuffer, *BufferToReturn, 256);\r
+\r
+ON_EXIT:\r
+  SECUREBOOT_FREE_NON_NULL (CNBuffer);\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
+  return Status;\r
+}\r
+\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
 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
+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
-  EFI_STATUS                        Status;\r
-  UINTN                             BufferSize;\r
-  SECUREBOOT_CONFIGURATION          Configuration;\r
-  \r
-  EFI_STRING                        ConfigRequest;\r
-  UINT8                             *SecureBootEnable;\r
-  \r
-  if (Progress == NULL || Results == NULL) {\r
-    return EFI_INVALID_PARAMETER;\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
-  *Progress = Request;\r
-  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
-    return EFI_NOT_FOUND;\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
-  // Get the SecureBoot Variable\r
+  // Format GUID part.\r
   //\r
-  SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);  \r
-  \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 the SecureBoot Variable doesn't exist, hide the SecureBoot Enable/Disable\r
-  // Checkbox.\r
+  // Format content part, it depends on the type of signature list, hash value or CN.\r
   //\r
-  if (SecureBootEnable == NULL) {\r
-    Configuration.HideSecureBoot = 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
-    Configuration.HideSecureBoot = FALSE;\r
-    Configuration.SecureBootState = *SecureBootEnable;\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
-  BufferSize = sizeof (Configuration);\r
-  ConfigRequest = Request;\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
-  Status = gHiiConfigRouting->BlockToConfig (\r
-                                gHiiConfigRouting,\r
-                                ConfigRequest,\r
-                                (UINT8 *) &Configuration,\r
-                                BufferSize,\r
-                                Results,\r
-                                Progress\r
-                                );\r
-  \r
   //\r
-  // Set Progress string to the original request string.\r
+  // Format revocation time part.\r
   //\r
-  if (Request == NULL) {\r
-    *Progress = NULL;\r
-  } else if (StrStr (Request, L"OFFSET") == NULL) {\r
-    *Progress = Request + StrLen (Request);\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
+  *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 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
+  This functino to load signature data under the signature list.\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
+  @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
-SecureBootRouteConfig (\r
-  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
-  IN CONST EFI_STRING                          Configuration,\r
-       OUT EFI_STRING                          *Progress\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
-  SECUREBOOT_CONFIGURATION         SecureBootConfiguration;\r
-  UINT8                            *SecureBootEnable;\r
-    \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
-  if (Configuration == NULL || Progress == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
+  Status              = EFI_SUCCESS;\r
+  FormatNameString    = NULL;\r
+  StartOpCodeHandle   = NULL;\r
+  EndOpCodeHandle     = NULL;\r
+  Index               = 0;\r
+  VariableData        = 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
-  *Progress = Configuration;\r
-  if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) {\r
-    return EFI_NOT_FOUND;\r
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (EndOpCodeHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
   }\r
 \r
   //\r
-  // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
+  // Create Hii Extend Label OpCode.\r
   //\r
-  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
-  Status = gHiiConfigRouting->ConfigToBlock (\r
-                                gHiiConfigRouting,\r
-                                Configuration,\r
-                                (UINT8 *) &SecureBootConfiguration,\r
-                                &BufferSize,\r
-                                Progress\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
+  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
+  // Read Variable, the variable name save in the PrivateData->VariableName.\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
-    return Status;\r
+    goto ON_EXIT;\r
   }\r
 \r
-  SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);  \r
-  if (SecureBootEnable == NULL) {\r
-    return EFI_SUCCESS;\r
-  } \r
-  \r
-  if ((*SecureBootEnable) != SecureBootConfiguration.SecureBootState) {\r
+  RemainingSize = DataSize;\r
+  ListWalker = (EFI_SIGNATURE_LIST *)VariableData;\r
+\r
+  //\r
+  // Skip signature list.\r
+  //\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
+  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
-    // If the configure is changed, update the SecureBoot Variable.\r
+    // Format name buffer.\r
     //\r
-    SaveSecureBootVariable (SecureBootConfiguration.SecureBootState); \r
-  }  \r
-  return EFI_SUCCESS;\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
+    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
+    ZeroMem(NameBuffer, 100);\r
+    DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize);\r
+  }\r
+\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
+  SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle);\r
+  SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle);\r
+\r
+  SECUREBOOT_FREE_NON_NULL (VariableData);\r
+  SECUREBOOT_FREE_NON_NULL (FormatNameString);\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
-  This function processes the results of changes in configuration.\r
+  This function is called to provide results data to the driver.\r
 \r
   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
   @param[in]  Action             Specifies the type of action taken by the browser.\r
@@ -271,24 +4289,606 @@ SecureBootCallback (
      OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
   )\r
 {\r
-  BOOLEAN           SecureBootEnable;\r
-  \r
+  EFI_INPUT_KEY                   Key;\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
+  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
+  BOOLEAN                         GetBrowserDataResult;\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_CHANGING) || (QuestionId != KEY_SECURE_BOOT_ENABLE)) {\r
-    return EFI_UNSUPPORTED;\r
+  Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
+\r
+  gSecureBootPrivateData = Private;\r
+\r
+  //\r
+  // Retrieve uncommitted data from Browser\r
+  //\r
+  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
+  IfrNvData = AllocateZeroPool (BufferSize);\r
+  if (IfrNvData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
-  \r
-  if (NULL == GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid)) {\r
-    return EFI_SUCCESS;\r
+\r
+  GetBrowserDataResult = 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
+  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
+            &Key,\r
+            L"Only Physical Presence User could disable secure boot!",\r
+            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
+      }\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
+      ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid));\r
+      if (Private->SignatureGUID == NULL) {\r
+        Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));\r
+        if (Private->SignatureGUID == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\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
+\r
+      //\r
+      // Refresh selected file.\r
+      //\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 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
+      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
+      break;\r
+\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
+          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
+        EFI_KEY_EXCHANGE_KEY_NAME,\r
+        &gEfiGlobalVariableGuid,\r
+        LABEL_KEK_DELETE,\r
+        FORMID_DELETE_KEK_FORM,\r
+        OPTION_DEL_KEK_QUESTION_ID\r
+        );\r
+      break;\r
+\r
+    case SECUREBOOT_DELETE_SIGNATURE_FROM_DB:\r
+      UpdateDeletePage (\r
+        Private,\r
+        EFI_IMAGE_SECURITY_DATABASE,\r
+        &gEfiImageSecurityDatabaseGuid,\r
+        LABEL_DB_DELETE,\r
+        SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
+        OPTION_DEL_DB_QUESTION_ID\r
+        );\r
+       break;\r
+\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_DATABASE2,\r
+        &gEfiImageSecurityDatabaseGuid,\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
+      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 >= 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
+                 (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
+        DeleteSignature (\r
+          Private,\r
+          EFI_IMAGE_SECURITY_DATABASE,\r
+          &gEfiImageSecurityDatabaseGuid,\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_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_DATABASE2,\r
+          &gEfiImageSecurityDatabaseGuid,\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
+    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
+    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
+      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_FORM_APPLY;\r
+      break;\r
+    case KEY_SECURE_BOOT_MODE:\r
+      mIsEnterSecureBootForm = FALSE;\r
+      break;\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
+      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
+    case KEY_SECURE_BOOT_DELETE_PK:\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
+      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
-  SecureBootEnable = Value->u8;\r
-  SaveSecureBootVariable (Value->u8); \r
-  return EFI_SUCCESS;\r
 \r
+EXIT:\r
+\r
+  if (!EFI_ERROR (Status) && GetBrowserDataResult) {\r
+    BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
+    HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
+  }\r
+\r
+  FreePool (IfrNvData);\r
+\r
+  if (File != NULL){\r
+    FreePool(File);\r
+    File = NULL;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -296,7 +4896,7 @@ SecureBootCallback (
 \r
   @param[in, out]  PrivateData   Points to SecureBoot configuration private data.\r
 \r
-  @retval EFI_SUCCESS            HII Form is installed for this network device.\r
+  @retval EFI_SUCCESS            HII Form is installed successfully.\r
   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.\r
   @retval Others                 Other errors as indicated.\r
 \r
@@ -309,7 +4909,6 @@ InstallSecureBootConfigForm (
   EFI_STATUS                      Status;\r
   EFI_HII_HANDLE                  HiiHandle;\r
   EFI_HANDLE                      DriverHandle;\r
-\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
 \r
   DriverHandle = NULL;\r
@@ -346,13 +4945,58 @@ InstallSecureBootConfigForm (
            &gEfiHiiConfigAccessProtocolGuid,\r
            ConfigAccess,\r
            NULL\r
-           );  \r
-\r
+           );\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  \r
+\r
   PrivateData->HiiHandle = HiiHandle;\r
-  return EFI_SUCCESS;  \r
+\r
+  PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
+\r
+  if (PrivateData->FileContext == NULL) {\r
+    UninstallSecureBootConfigForm (PrivateData);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Init OpCode Handle and Allocate space for creation of Buffer\r
+  //\r
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (mStartOpCodeHandle == NULL) {\r
+    UninstallSecureBootConfigForm (PrivateData);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  mEndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (mEndOpCodeHandle == NULL) {\r
+    UninstallSecureBootConfigForm (PrivateData);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Create Hii Extend Label OpCode as the start opcode\r
+  //\r
+  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
+                                         mStartOpCodeHandle,\r
+                                         &gEfiIfrTianoGuid,\r
+                                         NULL,\r
+                                         sizeof (EFI_IFR_GUID_LABEL)\r
+                                         );\r
+  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+\r
+  //\r
+  // Create Hii Extend Label OpCode as the end opcode\r
+  //\r
+  mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
+                                       mEndOpCodeHandle,\r
+                                       &gEfiIfrTianoGuid,\r
+                                       NULL,\r
+                                       sizeof (EFI_IFR_GUID_LABEL)\r
+                                       );\r
+  mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+  mEndLabel->Number       = LABEL_END;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -388,6 +5032,22 @@ UninstallSecureBootConfigForm (
            );\r
     PrivateData->DriverHandle = NULL;\r
   }\r
-  \r
+\r
+  if (PrivateData->SignatureGUID != NULL) {\r
+    FreePool (PrivateData->SignatureGUID);\r
+  }\r
+\r
+  if (PrivateData->FileContext != NULL) {\r
+    FreePool (PrivateData->FileContext);\r
+  }\r
+\r
   FreePool (PrivateData);\r
+\r
+  if (mStartOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
+  }\r
+\r
+  if (mEndOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
+  }\r
 }\r