]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Add custom SecureBootConfigDxe that doesn't reset
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 15 Aug 2012 00:03:59 +0000 (00:03 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 15 Aug 2012 00:03:59 +0000 (00:03 +0000)
We don't force a platform reset for OVMF when PK is changed in
custom mode setup.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Lee Rosenbaum <lee.g.rosenbaum@intel.com>
Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13635 6f19259b-4bc3-4df7-8a09-765794883524

16 files changed:
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32.fdf
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgIa32X64.fdf
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/OvmfPkgX64.fdf
OvmfPkg/SecureBootConfigDxe/SecureBootConfig.vfr [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigDevicePath.c [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigDriver.c [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigFileExplorer.c [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigImpl.c [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigImpl.h [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigMisc.c [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigNvData.h [new file with mode: 0644]
OvmfPkg/SecureBootConfigDxe/SecureBootConfigStrings.uni [new file with mode: 0644]

index 453a5788cb43062fa2adc45b354ae6467199d580..232e010e12708c1fe018814209732f867063fc90 100644 (file)
       BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
       OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
   }\r
       BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
       OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
   }\r
-  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
+  OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
 !endif\r
 !endif\r
index f31d002192f63b22c799561551db0ad9329b6e0d..f819e6b59bbd6b8a367ed116673c03a10a62269e 100644 (file)
@@ -170,7 +170,7 @@ INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
 \r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf\r
 \r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf\r
-  INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
+  INF  OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
 !else\r
   INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf\r
 !endif\r
 !else\r
   INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf\r
 !endif\r
@@ -356,7 +356,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
-  \r
+\r
 [Rule.Common.UEFI_APPLICATION]\r
   FILE APPLICATION = $(NAMED_GUID) {\r
     PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi\r
 [Rule.Common.UEFI_APPLICATION]\r
   FILE APPLICATION = $(NAMED_GUID) {\r
     PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi\r
@@ -370,7 +370,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
-  \r
+\r
 [Rule.Common.USER_DEFINED.ACPITABLE]\r
   FILE FREEFORM = $(NAMED_GUID) {\r
     RAW ACPI               |.acpi\r
 [Rule.Common.USER_DEFINED.ACPITABLE]\r
   FILE FREEFORM = $(NAMED_GUID) {\r
     RAW ACPI               |.acpi\r
index 73e8c987b5e3ec594260cc3f07a3fb2f4178cb93..c095df935d7f7e47f3739701771b0e19706f8259 100644 (file)
       BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
       OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
   }\r
       BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
       OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
   }\r
-  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
+  OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
 !endif\r
 !endif\r
index 71c9b981f0365df642be1c8267812784fb22e84c..399f01321c4e1a2434b3f2c161cfe5cd252367b0 100644 (file)
@@ -170,7 +170,7 @@ INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
 \r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf\r
 \r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf\r
-  INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
+  INF  OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
 !else\r
   INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf\r
 !endif\r
 !else\r
   INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf\r
 !endif\r
@@ -356,7 +356,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
-  \r
+\r
 [Rule.Common.UEFI_APPLICATION]\r
   FILE APPLICATION = $(NAMED_GUID) {\r
     PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi\r
 [Rule.Common.UEFI_APPLICATION]\r
   FILE APPLICATION = $(NAMED_GUID) {\r
     PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi\r
@@ -370,7 +370,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
-  \r
+\r
 [Rule.Common.USER_DEFINED.ACPITABLE]\r
   FILE FREEFORM = $(NAMED_GUID) {\r
     RAW ACPI               |.acpi\r
 [Rule.Common.USER_DEFINED.ACPITABLE]\r
   FILE FREEFORM = $(NAMED_GUID) {\r
     RAW ACPI               |.acpi\r
index 1c2aec0cdc8d32fea2e13795b34f383b720b93bd..d742c1cae128b1fa1c845ceb0e8fd6b50b336dbf 100644 (file)
       BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
       OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
   }\r
       BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf\r
       OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf\r
   }\r
-  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
+  OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
 !endif\r
 !endif\r
index e234f4fdae7ba38e605118ed42928aced1c650f3..6a5bcb6fad56e7d6c79a548650268472ae710eab 100644 (file)
@@ -170,7 +170,7 @@ INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
 \r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf\r
 \r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf\r
-  INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
+  INF  OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf\r
 !else\r
   INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf\r
 !endif\r
 !else\r
   INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf\r
 !endif\r
@@ -356,7 +356,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
-  \r
+\r
 [Rule.Common.UEFI_APPLICATION]\r
   FILE APPLICATION = $(NAMED_GUID) {\r
     PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi\r
 [Rule.Common.UEFI_APPLICATION]\r
   FILE APPLICATION = $(NAMED_GUID) {\r
     PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi\r
@@ -370,7 +370,7 @@ FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
     UI        STRING="$(MODULE_NAME)" Optional\r
     VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)\r
   }\r
-  \r
+\r
 [Rule.Common.USER_DEFINED.ACPITABLE]\r
   FILE FREEFORM = $(NAMED_GUID) {\r
     RAW ACPI               |.acpi\r
 [Rule.Common.USER_DEFINED.ACPITABLE]\r
   FILE FREEFORM = $(NAMED_GUID) {\r
     RAW ACPI               |.acpi\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfig.vfr b/OvmfPkg/SecureBootConfigDxe/SecureBootConfig.vfr
new file mode 100644 (file)
index 0000000..22c03c1
--- /dev/null
@@ -0,0 +1,495 @@
+/** @file\r
+  VFR file used by the SecureBoot configuration component.\r
+\r
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SecureBootConfigNvData.h"\r
+\r
+formset\r
+  guid      = SECUREBOOT_CONFIG_FORM_SET_GUID,\r
+  title     = STRING_TOKEN(STR_SECUREBOOT_TITLE),\r
+  help      = STRING_TOKEN(STR_SECUREBOOT_HELP),\r
+  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,\r
+\r
+  varstore SECUREBOOT_CONFIGURATION,\r
+    varid = SECUREBOOT_CONFIGURATION_VARSTORE_ID,\r
+    name  = SECUREBOOT_CONFIGURATION,\r
+    guid  = SECUREBOOT_CONFIG_FORM_SET_GUID;\r
+  \r
+  //\r
+  // ##1 Form "Secure Boot Configuration"\r
+  //\r
+  form formid = SECUREBOOT_CONFIGURATION_FORM_ID,\r
+    title = STRING_TOKEN(STR_SECUREBOOT_TITLE);\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+    //\r
+    // Define of Check Box: Attempt Secure Boot\r
+    //\r
+    suppressif TRUE;\r
+      checkbox varid   = SECUREBOOT_CONFIGURATION.HideSecureBoot,\r
+              prompt   = STRING_TOKEN(STR_NULL),\r
+              help     = STRING_TOKEN(STR_NULL),\r
+      endcheckbox;\r
+    endif;  \r
+    \r
+    //\r
+    // Display of Check Box: Attempt Secure Boot\r
+    //\r
+    grayoutif ideqval SECUREBOOT_CONFIGURATION.HideSecureBoot == 1;\r
+    checkbox varid = SECUREBOOT_CONFIGURATION.SecureBootState,\r
+          questionid = KEY_SECURE_BOOT_ENABLE,\r
+          prompt = STRING_TOKEN(STR_SECURE_BOOT_PROMPT),\r
+          help   = STRING_TOKEN(STR_SECURE_BOOT_HELP),\r
+          flags  = INTERACTIVE,\r
+    endcheckbox;\r
+    endif;\r
+    \r
+    //\r
+    // Display of Oneof: 'Secure Boot Mode'\r
+    //\r
+    oneof varid  = SECUREBOOT_CONFIGURATION.SecureBootMode,\r
+          questionid = KEY_SECURE_BOOT_MODE,      \r
+          prompt = STRING_TOKEN(STR_SECURE_BOOT_MODE_PROMPT),\r
+          help   = STRING_TOKEN(STR_SECURE_BOOT_MODE_HELP),\r
+          flags  = INTERACTIVE,\r
+          option text = STRING_TOKEN(STR_STANDARD_MODE),    value = SECURE_BOOT_MODE_STANDARD, flags = DEFAULT;\r
+          option text = STRING_TOKEN(STR_CUSTOM_MODE),      value = SECURE_BOOT_MODE_CUSTOM,   flags = 0;\r
+    endoneof;\r
+    \r
+    //\r
+    //\r
+    // Display of 'Current Secure Boot Mode'\r
+    //\r
+    suppressif ideqval SECUREBOOT_CONFIGURATION.SecureBootMode == SECURE_BOOT_MODE_STANDARD;\r
+      grayoutif NOT ideqval SECUREBOOT_CONFIGURATION.PhysicalPresent == 1;\r
+      goto FORMID_SECURE_BOOT_OPTION_FORM,\r
+           prompt = STRING_TOKEN(STR_SECURE_BOOT_OPTION),\r
+           help   = STRING_TOKEN(STR_SECURE_BOOT_OPTION_HELP),\r
+           flags  = INTERACTIVE,\r
+           key    = KEY_SECURE_BOOT_OPTION;\r
+      endif;\r
+    endif;\r
+  endform;\r
+  \r
+  //\r
+  // ##2 Form: 'Custom Secure Boot Options'\r
+  //\r
+  form formid = FORMID_SECURE_BOOT_OPTION_FORM,\r
+    title  = STRING_TOKEN(STR_SECURE_BOOT_OPTION_TITLE);\r
+    \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+    goto FORMID_SECURE_BOOT_PK_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION),\r
+         help   = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION_HELP),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_SECURE_BOOT_PK_OPTION;\r
+        \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+    goto FORMID_SECURE_BOOT_KEK_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_SECURE_BOOT_KEK_OPTION),\r
+         help   = STRING_TOKEN(STR_SECURE_BOOT_KEK_OPTION_HELP),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_SECURE_BOOT_KEK_OPTION;\r
+        \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+    goto FORMID_SECURE_BOOT_DB_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_SECURE_BOOT_DB_OPTION),\r
+         help   = STRING_TOKEN(STR_SECURE_BOOT_DB_OPTION_HELP),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_SECURE_BOOT_DB_OPTION;\r
+    \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+    goto FORMID_SECURE_BOOT_DBX_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_SECURE_BOOT_DBX_OPTION),\r
+         help   = STRING_TOKEN(STR_SECURE_BOOT_DBX_OPTION_HELP),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_SECURE_BOOT_DBX_OPTION;\r
+\r
+  endform;\r
+  \r
+  //\r
+  // ##3 Form: 'PK Options'\r
+  //\r
+  form formid = FORMID_SECURE_BOOT_PK_OPTION_FORM,\r
+    title  = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION);\r
+    \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+    //\r
+    // Define of Check Box: 'Delete PK'\r
+    //\r
+    suppressif TRUE;\r
+      checkbox varid   = SECUREBOOT_CONFIGURATION.DeletePk,\r
+               prompt   = STRING_TOKEN(STR_NULL),\r
+               help     = STRING_TOKEN(STR_NULL),\r
+      endcheckbox;\r
+    endif;\r
+    \r
+    grayoutif ideqval SECUREBOOT_CONFIGURATION.HasPk == 1;\r
+    goto FORMID_ENROLL_PK_FORM,\r
+         prompt = STRING_TOKEN(STR_ENROLL_PK),\r
+         help   = STRING_TOKEN(STR_ENROLL_PK_HELP),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_ENROLL_PK;\r
+    endif;\r
+    \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+   \r
+    //\r
+    // Display of Check Box: 'Delete Pk' \r
+    //\r
+    grayoutif ideqval SECUREBOOT_CONFIGURATION.HideSecureBoot == 1;\r
+    checkbox varid = SECUREBOOT_CONFIGURATION.DeletePk,\r
+          questionid = KEY_SECURE_BOOT_DELETE_PK,\r
+          prompt = STRING_TOKEN(STR_DELETE_PK),          \r
+          help   = STRING_TOKEN(STR_DELETE_PK_HELP),\r
+          flags  = INTERACTIVE,\r
+    endcheckbox;\r
+    endif;\r
+  endform;\r
+  \r
+  //\r
+  // ##4 Form: 'Enroll PK'\r
+  //\r
+  form formid = FORMID_ENROLL_PK_FORM,\r
+    title  = STRING_TOKEN(STR_ENROLL_PK);\r
+    \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto FORM_FILE_EXPLORER_ID_PK,\r
+         prompt = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_PK_FILE),\r
+         help = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_PK_FILE),\r
+         flags = INTERACTIVE,\r
+         key = SECUREBOOT_ADD_PK_FILE_FORM_ID;\r
+  endform;\r
+  \r
+  //\r
+  // ##5 Form: 'KEK Options'\r
+  //\r
+  form formid = FORMID_SECURE_BOOT_KEK_OPTION_FORM,\r
+    title  = STRING_TOKEN(STR_SECURE_BOOT_KEK_OPTION);\r
+\r
+    //\r
+    // Display of 'Enroll KEK' \r
+    //\r
+    goto FORMID_ENROLL_KEK_FORM,\r
+         prompt = STRING_TOKEN(STR_ENROLL_KEK),\r
+         help   = STRING_TOKEN(STR_ENROLL_KEK_HELP),\r
+         flags  = INTERACTIVE;\r
+    \r
+    subtitle text = STRING_TOKEN(STR_NULL);     \r
+   \r
+    //\r
+    // Display of 'Delete KEK' \r
+    //\r
+    goto FORMID_DELETE_KEK_FORM,\r
+         prompt = STRING_TOKEN(STR_DELETE_KEK),\r
+         help   = STRING_TOKEN(STR_DELETE_KEK_HELP),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_DELETE_KEK;\r
+  \r
+    subtitle text = STRING_TOKEN(STR_NULL);    \r
+  endform;\r
+\r
+  //\r
+  // ##6 Form: 'Enroll KEK' \r
+  //\r
+  form formid = FORMID_ENROLL_KEK_FORM,\r
+    title = STRING_TOKEN(STR_ENROLL_KEK_TITLE);\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto FORM_FILE_EXPLORER_ID_KEK,\r
+         prompt = STRING_TOKEN(STR_FORM_ENROLL_KEK_FROM_FILE_TITLE),\r
+         help   = STRING_TOKEN(STR_FORM_ENROLL_KEK_FROM_FILE_TITLE_HELP),\r
+         flags  = INTERACTIVE,\r
+         key    = FORMID_ENROLL_KEK_FORM;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    label FORMID_ENROLL_KEK_FORM;\r
+    label LABEL_END;\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    string  varid   = SECUREBOOT_CONFIGURATION.SignatureGuid,\r
+            prompt  = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID),\r
+            help    = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID_HELP),\r
+            flags   = INTERACTIVE,\r
+            key     = KEY_SECURE_BOOT_KEK_GUID,\r
+            minsize = SECURE_BOOT_GUID_SIZE,\r
+            maxsize = SECURE_BOOT_GUID_SIZE,\r
+    endstring;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto FORMID_SECURE_BOOT_OPTION_FORM,\r
+      prompt = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+      help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+      flags  = INTERACTIVE,\r
+      key    = KEY_VALUE_SAVE_AND_EXIT_KEK;\r
\r
+    goto FORMID_SECURE_BOOT_OPTION_FORM,\r
+      prompt = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+      help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+      flags  = INTERACTIVE,\r
+      key    = KEY_VALUE_NO_SAVE_AND_EXIT_KEK;\r
+\r
+  endform;\r
+\r
+  //\r
+  // ##7 Form: 'Delete KEK'\r
+  //  \r
+  form formid = FORMID_DELETE_KEK_FORM,\r
+    title  = STRING_TOKEN(STR_DELETE_KEK_TITLE);\r
+\r
+    label LABEL_KEK_DELETE;\r
+    label LABEL_END;\r
+         \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+  endform;\r
+\r
+  //\r
+  // ##8 Form: 'DB Options'\r
+  //\r
+  form formid = FORMID_SECURE_BOOT_DB_OPTION_FORM,\r
+    title = STRING_TOKEN(STR_SECURE_BOOT_DB_OPTION);\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto SECUREBOOT_ENROLL_SIGNATURE_TO_DB,\r
+    prompt = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE),\r
+    help   = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE),\r
+    flags  = 0;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
+    prompt = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE),\r
+    help   = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE),\r
+    flags  = INTERACTIVE,\r
+    key    = SECUREBOOT_DELETE_SIGNATURE_FROM_DB;\r
+    \r
+  endform;\r
+\r
+  //\r
+  // ##9 Form: 'DBX Options'\r
+  //\r
+  form formid = FORMID_SECURE_BOOT_DBX_OPTION_FORM,\r
+    title = STRING_TOKEN(STR_SECURE_BOOT_DBX_OPTION);\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto SECUREBOOT_ENROLL_SIGNATURE_TO_DBX,\r
+    prompt = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE),\r
+    help   = STRING_TOKEN (STR_SECURE_BOOT_ENROLL_SIGNATURE),\r
+    flags  = 0;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
+    prompt = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE),\r
+    help   = STRING_TOKEN (STR_SECURE_BOOT_DELETE_SIGNATURE),\r
+    flags  = INTERACTIVE,\r
+    key    = SECUREBOOT_DELETE_SIGNATURE_FROM_DBX;\r
+\r
+  endform;\r
+\r
+  //\r
+  // Form: 'Delete Signature' for DB Options.\r
+  //\r
+  form formid = SECUREBOOT_DELETE_SIGNATURE_FROM_DB,\r
+    title  = STRING_TOKEN(STR_SECURE_BOOT_DELETE_SIGNATURE);\r
+\r
+    label LABEL_DB_DELETE;\r
+    label LABEL_END;\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+  endform;\r
+\r
+  //\r
+  // Form: 'Delete Signature' for DBX Options.\r
+  //\r
+  form formid = SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
+    title  = STRING_TOKEN(STR_SECURE_BOOT_DELETE_SIGNATURE);\r
+\r
+    label LABEL_DBX_DELETE;\r
+    label LABEL_END;\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+  endform;\r
+\r
+  //\r
+  // Form: 'Enroll Signature' for DB options.\r
+  //\r
+  form formid = SECUREBOOT_ENROLL_SIGNATURE_TO_DB,\r
+    title = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_SIGNATURE);\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto FORM_FILE_EXPLORER_ID_DB,\r
+         prompt = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE),\r
+         help = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE),\r
+         flags = INTERACTIVE,\r
+         key = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    label SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
+    label LABEL_END;\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    string  varid   = SECUREBOOT_CONFIGURATION.SignatureGuid,\r
+            prompt  = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID),\r
+            help    = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID_HELP),\r
+            flags   = INTERACTIVE,\r
+            key     = KEY_SECURE_BOOT_SIGNATURE_GUID_DB,\r
+            minsize = SECURE_BOOT_GUID_SIZE,\r
+            maxsize = SECURE_BOOT_GUID_SIZE,\r
+    endstring;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto FORMID_SECURE_BOOT_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT_DB;\r
\r
+    goto FORMID_SECURE_BOOT_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT_DB;\r
+\r
+  endform;\r
+\r
+  //\r
+  // Form: 'Enroll Signature' for DBX options.\r
+  //\r
+  form formid = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX,\r
+    title = STRING_TOKEN(STR_SECURE_BOOT_ENROLL_SIGNATURE);\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto FORM_FILE_EXPLORER_ID_DBX,\r
+         prompt = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE),\r
+         help = STRING_TOKEN(STR_SECURE_BOOT_ADD_SIGNATURE_FILE),\r
+         flags = INTERACTIVE,\r
+         key = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    label SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
+    label LABEL_END;\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    string  varid   = SECUREBOOT_CONFIGURATION.SignatureGuid,\r
+            prompt  = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID),\r
+            help    = STRING_TOKEN(STR_SECURE_BOOT_SIGNATURE_GUID_HELP),\r
+            flags   = INTERACTIVE,\r
+            key     = KEY_SECURE_BOOT_SIGNATURE_GUID_DBX,\r
+            minsize = SECURE_BOOT_GUID_SIZE,\r
+            maxsize = SECURE_BOOT_GUID_SIZE,\r
+    endstring;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+    goto FORMID_SECURE_BOOT_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT_DBX;\r
\r
+    goto FORMID_SECURE_BOOT_OPTION_FORM,\r
+         prompt = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT_DBX;\r
+\r
+  endform;\r
+\r
+  //\r
+  // File Explorer for PK\r
+  //\r
+  form formid = FORM_FILE_EXPLORER_ID_PK,\r
+       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+       label FORM_FILE_EXPLORER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+  \r
+  //\r
+  // File Explorer for KEK\r
+  //\r
+  form formid = FORM_FILE_EXPLORER_ID_KEK,\r
+       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+       label FORM_FILE_EXPLORER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  //\r
+  // File Explorer for DB\r
+  //\r
+  form formid = FORM_FILE_EXPLORER_ID_DB,\r
+       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+       label FORM_FILE_EXPLORER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  //\r
+  // File Explorer for DBX\r
+  //\r
+  form formid = FORM_FILE_EXPLORER_ID_DBX,\r
+       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+       label FORM_FILE_EXPLORER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+\r
+  //\r
+  // Enroll Pk from File Commit Form\r
+  //\r
+  form formid = SECUREBOOT_ADD_PK_FILE_FORM_ID,\r
+    title = STRING_TOKEN(STR_SAVE_PK_FILE);\r
+\r
+    label SECUREBOOT_ADD_PK_FILE_FORM_ID;\r
+    label LABEL_END;\r
+    \r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+\r
+     text\r
+       help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+       text   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+       text   = STRING_TOKEN(STR_NULL),\r
+       flags  = INTERACTIVE,\r
+       key    = KEY_VALUE_SAVE_AND_EXIT_PK;\r
+\r
+     text\r
+       help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+       text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+       text   = STRING_TOKEN(STR_NULL),\r
+       flags  = INTERACTIVE,\r
+       key    = KEY_VALUE_NO_SAVE_AND_EXIT_PK;\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigDevicePath.c b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigDevicePath.c
new file mode 100644 (file)
index 0000000..ae44626
--- /dev/null
@@ -0,0 +1,1537 @@
+/** @file\r
+  Internal function defines the default device path string for SecureBoot configuration module.\r
+\r
+Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SecureBootConfigImpl.h"\r
+\r
+/**\r
+  Concatenates a formatted unicode string to allocated pool.\r
+  The caller must free the resulting buffer.\r
+\r
+  @param[in, out]  Str      Tracks the allocated pool, size in use, and amount of pool allocated.\r
+  @param[in]       Fmt      The format string\r
+  @param[in]       ...      The data will be printed.\r
+\r
+  @return Allocated buffer with the formatted string printed in it.\r
+          The caller must free the allocated buffer.\r
+          The buffer allocation is not packed.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+CatPrint (\r
+  IN OUT POOL_PRINT   *Str,\r
+  IN CHAR16           *Fmt,\r
+  ...\r
+  )\r
+{\r
+  UINT16  *AppendStr;\r
+  VA_LIST Args;\r
+  UINTN   StringSize;\r
+\r
+  AppendStr = AllocateZeroPool (0x1000);\r
+  if (AppendStr == NULL) {\r
+    return Str->Str;\r
+  }\r
+\r
+  VA_START (Args, Fmt);\r
+  UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);\r
+  VA_END (Args);\r
+  if (NULL == Str->Str) {\r
+    StringSize   = StrSize (AppendStr);\r
+    Str->Str  = AllocateZeroPool (StringSize);\r
+    ASSERT (Str->Str != NULL);\r
+  } else {\r
+    StringSize = StrSize (AppendStr);\r
+    StringSize += (StrSize (Str->Str) - sizeof (UINT16));\r
+\r
+    Str->Str = ReallocatePool (\r
+                StrSize (Str->Str),\r
+                StringSize,\r
+                Str->Str\r
+                );\r
+    ASSERT (Str->Str != NULL);\r
+  }\r
+\r
+  Str->Maxlen = MAX_CHAR * sizeof (UINT16);\r
+  if (StringSize < Str->Maxlen) {\r
+    StrCat (Str->Str, AppendStr);\r
+    Str->Len = StringSize - sizeof (UINT16);\r
+  }\r
+\r
+  FreePool (AppendStr);\r
+  return Str->Str;\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathPci (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  PCI_DEVICE_PATH *Pci;\r
+\r
+  Pci = DevPath;\r
+  CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathPccard (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  PCCARD_DEVICE_PATH  *Pccard;\r
+\r
+  Pccard = DevPath;\r
+  CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMemMap (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEMMAP_DEVICE_PATH  *MemMap;\r
+\r
+  MemMap = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"MemMap(%d:%lx-%lx)",\r
+    (UINTN) MemMap->MemoryType,\r
+    MemMap->StartingAddress,\r
+    MemMap->EndingAddress\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathController (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CONTROLLER_DEVICE_PATH  *Controller;\r
+\r
+  Controller = DevPath;\r
+  CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber);\r
+}\r
+\r
+\r
+/**\r
+  Convert Vendor device path to device name.\r
+\r
+  @param[in, out]  Str      The buffer store device name\r
+  @param[in]       DevPath  Pointer to vendor device path\r
+\r
+**/\r
+VOID\r
+DevPathVendor (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  VENDOR_DEVICE_PATH  *Vendor;\r
+  CHAR16              *Type;\r
+  UINTN               DataLength;\r
+  UINTN               Index;\r
+  UINT32              FlowControlMap;\r
+\r
+  UINT16              Info;\r
+\r
+  Vendor  = DevPath;\r
+\r
+  switch (DevicePathType (&Vendor->Header)) {\r
+  case HARDWARE_DEVICE_PATH:\r
+    Type = L"Hw";\r
+    break;\r
+\r
+  case MESSAGING_DEVICE_PATH:\r
+    Type = L"Msg";\r
+    if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {\r
+      CatPrint (Str, L"VenPcAnsi()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {\r
+      CatPrint (Str, L"VenVt100()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {\r
+      CatPrint (Str, L"VenVt100Plus()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {\r
+      CatPrint (Str, L"VenUft8()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid     )) {\r
+      FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);\r
+      switch (FlowControlMap & 0x00000003) {\r
+      case 0:\r
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"None");\r
+        break;\r
+\r
+      case 1:\r
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");\r
+        break;\r
+\r
+      case 2:\r
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      return ;\r
+\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {\r
+      CatPrint (\r
+        Str,\r
+        L"SAS(%lx,%lx,%x,",\r
+        ((SAS_DEVICE_PATH *) Vendor)->SasAddress,\r
+        ((SAS_DEVICE_PATH *) Vendor)->Lun,\r
+        (UINTN) ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort\r
+        );\r
+      Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);\r
+      if ((Info & 0x0f) == 0) {\r
+        CatPrint (Str, L"NoTopology,0,0,0,");\r
+      } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {\r
+        CatPrint (\r
+          Str,\r
+          L"%s,%s,%s,",\r
+          ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",\r
+          ((Info & (0x1 << 5)) != 0) ? L"External" : L"Internal",\r
+          ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"\r
+          );\r
+        if ((Info & 0x0f) == 1) {\r
+          CatPrint (Str, L"0,");\r
+        } else {\r
+          CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));\r
+        }\r
+      } else {\r
+        CatPrint (Str, L"0,0,0,0,");\r
+      }\r
+\r
+      CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);\r
+      return ;\r
+\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {\r
+      CatPrint (Str, L"DebugPort()");\r
+      return ;\r
+    }\r
+    break;\r
+\r
+  case MEDIA_DEVICE_PATH:\r
+    Type = L"Media";\r
+    break;\r
+\r
+  default:\r
+    Type = L"?";\r
+    break;\r
+  }\r
+\r
+  CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);\r
+  DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);\r
+  if (DataLength > 0) {\r
+    CatPrint (Str, L",");\r
+    for (Index = 0; Index < DataLength; Index++) {\r
+      CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);\r
+    }\r
+  }\r
+  CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAcpi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ACPI_HID_DEVICE_PATH  *Acpi;\r
+\r
+  Acpi = DevPath;\r
+  if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+    CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN)  EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);\r
+  } else {\r
+    CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);\r
+  }\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathExtendedAcpi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ACPI_EXTENDED_HID_DEVICE_PATH   *ExtendedAcpi;\r
+  \r
+  //\r
+  // Index for HID, UID and CID strings, 0 for non-exist\r
+  //\r
+  UINT16                          HIDSTRIdx;\r
+  UINT16                          UIDSTRIdx;\r
+  UINT16                          CIDSTRIdx;\r
+  UINT16                          Index;\r
+  UINT16                          Length;\r
+  UINT16                          Anchor;\r
+  CHAR8                           *AsChar8Array;\r
+\r
+  HIDSTRIdx    = 0;\r
+  UIDSTRIdx    = 0;\r
+  CIDSTRIdx    = 0;\r
+  ExtendedAcpi = DevPath;\r
+  Length       = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);\r
+\r
+  AsChar8Array = (CHAR8 *) ExtendedAcpi;\r
+\r
+  //\r
+  // find HIDSTR\r
+  //\r
+  Anchor = 16;\r
+  for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+    ;\r
+  }\r
+  if (Index > Anchor) {\r
+    HIDSTRIdx = Anchor;\r
+  }\r
+  //\r
+  // find UIDSTR\r
+  //\r
+  Anchor = (UINT16) (Index + 1);\r
+  for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+    ;\r
+  }\r
+  if (Index > Anchor) {\r
+    UIDSTRIdx = Anchor;\r
+  }\r
+  //\r
+  // find CIDSTR\r
+  //\r
+  Anchor = (UINT16) (Index + 1);\r
+  for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+    ;\r
+  }\r
+  if (Index > Anchor) {\r
+    CIDSTRIdx = Anchor;\r
+  }\r
+\r
+  if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) {\r
+    CatPrint (Str, L"AcpiExp(");\r
+    if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+    }\r
+    if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN)  ExtendedAcpi->CID);\r
+    }\r
+    if (UIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\")");\r
+    }\r
+  } else {\r
+    CatPrint (Str, L"AcpiEx(");\r
+    if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+    }\r
+    if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);\r
+    }\r
+    CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);\r
+\r
+    if (HIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\",");\r
+    }\r
+    if (CIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\",");\r
+    }\r
+    if (UIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\")");\r
+    }\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAdrAcpi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ACPI_ADR_DEVICE_PATH    *AcpiAdr;\r
+  UINT16                  Index;\r
+  UINT16                  Length;\r
+  UINT16                  AdditionalAdrCount;\r
+\r
+  AcpiAdr            = DevPath;\r
+  Length             = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);\r
+  AdditionalAdrCount = (UINT16) ((Length - 8) / 4);\r
+\r
+  CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);\r
+  for (Index = 0; Index < AdditionalAdrCount; Index++) {\r
+    CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));\r
+  }\r
+  CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAtapi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ATAPI_DEVICE_PATH *Atapi;\r
+\r
+  Atapi = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Ata(%s,%s)",\r
+    (Atapi->PrimarySecondary != 0)? L"Secondary" : L"Primary",\r
+    (Atapi->SlaveMaster != 0)? L"Slave" : L"Master"\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathScsi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  SCSI_DEVICE_PATH  *Scsi;\r
+\r
+  Scsi = DevPath;\r
+  CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+  \r
+**/\r
+VOID\r
+DevPathFibre (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  FIBRECHANNEL_DEVICE_PATH  *Fibre;\r
+\r
+  Fibre = DevPath;\r
+  CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPath1394 (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  F1394_DEVICE_PATH *F1394Path;\r
+\r
+  F1394Path = DevPath;\r
+  CatPrint (Str, L"1394(%lx)", &F1394Path->Guid);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+  \r
+**/\r
+VOID\r
+DevPathUsb (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  USB_DEVICE_PATH *Usb;\r
+\r
+  Usb = DevPath;\r
+  CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsbWWID (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  USB_WWID_DEVICE_PATH  *UsbWWId;\r
+\r
+  UsbWWId = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"UsbWwid(%x,%x,%x,\"WWID\")",\r
+    (UINTN) UsbWWId->VendorId,\r
+    (UINTN) UsbWWId->ProductId,\r
+    (UINTN) UsbWWId->InterfaceNumber\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathLogicalUnit (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;\r
+\r
+  LogicalUnit = DevPath;\r
+  CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsbClass (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  USB_CLASS_DEVICE_PATH *UsbClass;\r
+\r
+  UsbClass = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Usb Class(%x,%x,%x,%x,%x)",\r
+    (UINTN) UsbClass->VendorId,\r
+    (UINTN) UsbClass->ProductId,\r
+    (UINTN) UsbClass->DeviceClass,\r
+    (UINTN) UsbClass->DeviceSubClass,\r
+    (UINTN) UsbClass->DeviceProtocol\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathSata (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  SATA_DEVICE_PATH *Sata;\r
+\r
+  Sata = DevPath;\r
+  if ((Sata->PortMultiplierPortNumber & SATA_HBA_DIRECT_CONNECT_FLAG) != 0) {\r
+    CatPrint (\r
+      Str,\r
+      L"Sata(%x,%x)",\r
+      (UINTN) Sata->HBAPortNumber,\r
+      (UINTN) Sata->Lun\r
+      );\r
+  } else {\r
+    CatPrint (\r
+      Str,\r
+      L"Sata(%x,%x,%x)",\r
+      (UINTN) Sata->HBAPortNumber,\r
+      (UINTN) Sata->PortMultiplierPortNumber,\r
+      (UINTN) Sata->Lun\r
+      );\r
+  }\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathI2O (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  I2O_DEVICE_PATH *I2OPath;\r
+\r
+  I2OPath = DevPath;\r
+  CatPrint (Str, L"I2O(%x)", (UINTN) I2OPath->Tid);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMacAddr (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MAC_ADDR_DEVICE_PATH  *MACDevPath;\r
+  UINTN                 HwAddressSize;\r
+  UINTN                 Index;\r
+\r
+  MACDevPath           = DevPath;\r
+\r
+  HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
+  if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) {\r
+    HwAddressSize = 6;\r
+  }\r
+\r
+  CatPrint (Str, L"Mac(");\r
+\r
+  for (Index = 0; Index < HwAddressSize; Index++) {\r
+    CatPrint (Str, L"%02x", (UINTN) MACDevPath->MacAddress.Addr[Index]);\r
+  }\r
+\r
+  CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathIPv4 (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  IPv4_DEVICE_PATH  *IPDevPath;\r
+\r
+  IPDevPath = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"IPv4(%d.%d.%d.%d:%d)",\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[0],\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[1],\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[2],\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[3],\r
+    (UINTN) IPDevPath->RemotePort\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathIPv6 (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  IPv6_DEVICE_PATH  *IPv6DevPath;\r
+\r
+  IPv6DevPath = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[0],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[1],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[2],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[3],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[4],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[5],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[6],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[7],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[8],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[9],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[10],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[11],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[12],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[13],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[14],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[15]\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathInfiniBand (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  INFINIBAND_DEVICE_PATH  *InfiniBand;\r
+\r
+  InfiniBand = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Infiniband(%x,%g,%lx,%lx,%lx)",\r
+    (UINTN) InfiniBand->ResourceFlags,\r
+    InfiniBand->PortGid,\r
+    InfiniBand->ServiceId,\r
+    InfiniBand->TargetPortId,\r
+    InfiniBand->DeviceId\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUart (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  UART_DEVICE_PATH  *Uart;\r
+  CHAR8             Parity;\r
+\r
+  Uart = DevPath;\r
+  switch (Uart->Parity) {\r
+  case 0:\r
+    Parity = 'D';\r
+    break;\r
+\r
+  case 1:\r
+    Parity = 'N';\r
+    break;\r
+\r
+  case 2:\r
+    Parity = 'E';\r
+    break;\r
+\r
+  case 3:\r
+    Parity = 'O';\r
+    break;\r
+\r
+  case 4:\r
+    Parity = 'M';\r
+    break;\r
+\r
+  case 5:\r
+    Parity = 'S';\r
+    break;\r
+\r
+  default:\r
+    Parity = 'x';\r
+    break;\r
+  }\r
+\r
+  if (Uart->BaudRate == 0) {\r
+    CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);\r
+  } else {\r
+    CatPrint (Str, L"Uart(%ld,%c,", Uart->BaudRate, Parity);\r
+  }\r
+\r
+  if (Uart->DataBits == 0) {\r
+    CatPrint (Str, L"D,");\r
+  } else {\r
+    CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);\r
+  }\r
+\r
+  switch (Uart->StopBits) {\r
+  case 0:\r
+    CatPrint (Str, L"D)");\r
+    break;\r
+\r
+  case 1:\r
+    CatPrint (Str, L"1)");\r
+    break;\r
+\r
+  case 2:\r
+    CatPrint (Str, L"1.5)");\r
+    break;\r
+\r
+  case 3:\r
+    CatPrint (Str, L"2)");\r
+    break;\r
+\r
+  default:\r
+    CatPrint (Str, L"x)");\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathiSCSI (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ISCSI_DEVICE_PATH_WITH_NAME *IScsi;\r
+  UINT16                      Options;\r
+\r
+  IScsi = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"iSCSI(%a,%x,%lx,",\r
+    IScsi->TargetName,\r
+    (UINTN) IScsi->TargetPortalGroupTag,\r
+    IScsi->Lun\r
+    );\r
+\r
+  Options = IScsi->LoginOption;\r
+  CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None");\r
+  CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None");\r
+  if (((Options >> 11) & 0x0001) != 0) {\r
+    CatPrint (Str, L"%s,", L"None");\r
+  } else if (((Options >> 12) & 0x0001) != 0) {\r
+    CatPrint (Str, L"%s,", L"CHAP_UNI");\r
+  } else {\r
+    CatPrint (Str, L"%s,", L"CHAP_BI");\r
+\r
+  }\r
+\r
+  CatPrint (Str, L"%s)", (IScsi->NetworkProtocol == 0) ? L"TCP" : L"reserved");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathVlan (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  VLAN_DEVICE_PATH  *Vlan;\r
+\r
+  Vlan = DevPath;\r
+  CatPrint (Str, L"Vlan(%d)", (UINTN) Vlan->VlanId);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathHardDrive (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  HARDDRIVE_DEVICE_PATH *Hd;\r
+\r
+  Hd = DevPath;\r
+  switch (Hd->SignatureType) {\r
+  case SIGNATURE_TYPE_MBR:\r
+    CatPrint (\r
+      Str,\r
+      L"HD(Part%d,Sig%08x)",\r
+      (UINTN) Hd->PartitionNumber,\r
+      (UINTN) *((UINT32 *) (&(Hd->Signature[0])))\r
+      );\r
+    break;\r
+\r
+  case SIGNATURE_TYPE_GUID:\r
+    CatPrint (\r
+      Str,\r
+      L"HD(Part%d,Sig%g)",\r
+      (UINTN) Hd->PartitionNumber,\r
+      (EFI_GUID *) &(Hd->Signature[0])\r
+      );\r
+    break;\r
+\r
+  default:\r
+    CatPrint (\r
+      Str,\r
+      L"HD(Part%d,MBRType=%02x,SigType=%02x)",\r
+      (UINTN) Hd->PartitionNumber,\r
+      (UINTN) Hd->MBRType,\r
+      (UINTN) Hd->SignatureType\r
+      );\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathCDROM (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CDROM_DEVICE_PATH *Cd;\r
+\r
+  Cd = DevPath;\r
+  CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFilePath (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  FILEPATH_DEVICE_PATH  *Fp;\r
+\r
+  Fp = DevPath;\r
+  CatPrint (Str, L"%s", Fp->PathName);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMediaProtocol (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;\r
+\r
+  MediaProt = DevPath;\r
+  CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFvFilePath (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
+\r
+  FvFilePath = DevPath;\r
+  CatPrint (Str, L"%g", &FvFilePath->FvFileName);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathRelativeOffsetRange (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;\r
+\r
+  Offset = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Offset(%lx,%lx)",\r
+    Offset->StartingOffset,\r
+    Offset->EndingOffset\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathBssBss (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  BBS_BBS_DEVICE_PATH *Bbs;\r
+  CHAR16              *Type;\r
+\r
+  Bbs = DevPath;\r
+  switch (Bbs->DeviceType) {\r
+  case BBS_TYPE_FLOPPY:\r
+    Type = L"Floppy";\r
+    break;\r
+\r
+  case BBS_TYPE_HARDDRIVE:\r
+    Type = L"Harddrive";\r
+    break;\r
+\r
+  case BBS_TYPE_CDROM:\r
+    Type = L"CDROM";\r
+    break;\r
+\r
+  case BBS_TYPE_PCMCIA:\r
+    Type = L"PCMCIA";\r
+    break;\r
+\r
+  case BBS_TYPE_USB:\r
+    Type = L"Usb";\r
+    break;\r
+\r
+  case BBS_TYPE_EMBEDDED_NETWORK:\r
+    Type = L"Net";\r
+    break;\r
+\r
+  case BBS_TYPE_BEV:\r
+    Type = L"BEV";\r
+    break;\r
+\r
+  default:\r
+    Type = L"?";\r
+    break;\r
+  }\r
+  CatPrint (Str, L"Legacy-%s", Type);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathEndInstance (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CatPrint (Str, L",");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathNodeUnknown (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CatPrint (Str, L"?");\r
+}\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param[in, out] Str           The buffer holding the output string.\r
+                                This buffer contains the length of the string and \r
+                                the maixmum length reserved for the string buffer.\r
+  @param[in]      DevPath       The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFvPath (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEDIA_FW_VOL_DEVICE_PATH *FvPath;\r
+\r
+  FvPath = DevPath;\r
+  CatPrint (Str, L"Fv(%g)", &FvPath->FvName);\r
+}\r
+\r
+DEVICE_PATH_STRING_TABLE  DevPathTable[] = {\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_PCI_DP,\r
+    DevPathPci\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_PCCARD_DP,\r
+    DevPathPccard\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_MEMMAP_DP,\r
+    DevPathMemMap\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_VENDOR_DP,\r
+    DevPathVendor\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_CONTROLLER_DP,\r
+    DevPathController\r
+  },\r
+  {\r
+    ACPI_DEVICE_PATH,\r
+    ACPI_DP,\r
+    DevPathAcpi\r
+  },\r
+  {\r
+    ACPI_DEVICE_PATH,\r
+    ACPI_EXTENDED_DP,\r
+    DevPathExtendedAcpi\r
+  },\r
+  {\r
+    ACPI_DEVICE_PATH,\r
+    ACPI_ADR_DP,\r
+    DevPathAdrAcpi\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_ATAPI_DP,\r
+    DevPathAtapi\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_SCSI_DP,\r
+    DevPathScsi\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_FIBRECHANNEL_DP,\r
+    DevPathFibre\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_1394_DP,\r
+    DevPath1394\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_USB_DP,\r
+    DevPathUsb\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_USB_WWID_DP,\r
+    DevPathUsbWWID\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_DEVICE_LOGICAL_UNIT_DP,\r
+    DevPathLogicalUnit\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_USB_CLASS_DP,\r
+    DevPathUsbClass\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_SATA_DP,\r
+    DevPathSata\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_I2O_DP,\r
+    DevPathI2O\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_MAC_ADDR_DP,\r
+    DevPathMacAddr\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_IPv4_DP,\r
+    DevPathIPv4\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_IPv6_DP,\r
+    DevPathIPv6\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_INFINIBAND_DP,\r
+    DevPathInfiniBand\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_UART_DP,\r
+    DevPathUart\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_VENDOR_DP,\r
+    DevPathVendor\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_ISCSI_DP,\r
+    DevPathiSCSI\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_VLAN_DP,\r
+    DevPathVlan\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_HARDDRIVE_DP,\r
+    DevPathHardDrive\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_CDROM_DP,\r
+    DevPathCDROM\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_VENDOR_DP,\r
+    DevPathVendor\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_FILEPATH_DP,\r
+    DevPathFilePath\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_PROTOCOL_DP,\r
+    DevPathMediaProtocol\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_PIWG_FW_VOL_DP,\r
+    DevPathFvPath,\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_PIWG_FW_FILE_DP,\r
+    DevPathFvFilePath\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_RELATIVE_OFFSET_RANGE_DP,\r
+    DevPathRelativeOffsetRange,\r
+  },\r
+  {\r
+    BBS_DEVICE_PATH,\r
+    BBS_BBS_DP,\r
+    DevPathBssBss\r
+  },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_INSTANCE_DEVICE_PATH_SUBTYPE,\r
+    DevPathEndInstance\r
+  },\r
+  {\r
+    0,\r
+    0,\r
+    NULL\r
+  }\r
+};\r
+\r
+\r
+/**\r
+  This function converts an input device structure to a Unicode string.\r
+\r
+  @param[in] DevPath                  A pointer to the device path structure.\r
+\r
+  @return A new allocated Unicode string that represents the device path.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+DevicePathToStr (\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  )\r
+{\r
+  POOL_PRINT                Str;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;\r
+  VOID (*DumpNode) (POOL_PRINT *, VOID *);\r
+\r
+  UINTN Index;\r
+  UINTN NewSize;\r
+\r
+  EFI_STATUS                       Status;\r
+  CHAR16                           *ToText;\r
+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
+\r
+  ZeroMem (&Str, sizeof (Str));\r
+\r
+  if (DevPath == NULL) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDevicePathToTextProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &DevPathToText\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    ToText = DevPathToText->ConvertDevicePathToText (\r
+                              DevPath,\r
+                              FALSE,\r
+                              TRUE\r
+                              );\r
+    ASSERT (ToText != NULL);\r
+    return ToText;\r
+  }\r
+\r
+  //\r
+  // Process each device path node\r
+  //\r
+  DevPathNode = DevPath;\r
+  while (!IsDevicePathEnd (DevPathNode)) {\r
+    //\r
+    // Find the handler to dump this device path node\r
+    //\r
+    DumpNode = NULL;\r
+    for (Index = 0; DevPathTable[Index].Function != NULL; Index += 1) {\r
+\r
+      if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&\r
+          DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType\r
+          ) {\r
+        DumpNode = DevPathTable[Index].Function;\r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // If not found, use a generic function\r
+    //\r
+    if (!DumpNode) {\r
+      DumpNode = DevPathNodeUnknown;\r
+    }\r
+    //\r
+    //  Put a path seperator in if needed\r
+    //\r
+    if ((Str.Len != 0) && (DumpNode != DevPathEndInstance)) {\r
+      CatPrint (&Str, L"/");\r
+    }\r
+    //\r
+    // Print this node of the device path\r
+    //\r
+    DumpNode (&Str, DevPathNode);\r
+\r
+    //\r
+    // Next device path node\r
+    //\r
+    DevPathNode = NextDevicePathNode (DevPathNode);\r
+  }\r
+\r
+Done:\r
+  NewSize = (Str.Len + 1) * sizeof (CHAR16);\r
+  Str.Str = ReallocatePool (NewSize, NewSize, Str.Str);\r
+  ASSERT (Str.Str != NULL);\r
+  Str.Str[Str.Len] = 0;\r
+  return Str.Str;\r
+}\r
+\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigDriver.c b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigDriver.c
new file mode 100644 (file)
index 0000000..1d6c4ac
--- /dev/null
@@ -0,0 +1,133 @@
+/** @file\r
+  The module entry point for 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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SecureBootConfigImpl.h"\r
+\r
+/**\r
+  The entry point for SecureBoot configuration driver.\r
+\r
+  @param[in]  ImageHandle        The image handle of the driver.\r
+  @param[in]  SystemTable        The system table.\r
+\r
+  @retval EFI_ALREADY_STARTED    The driver already exists in system.\r
+  @retval EFI_OUT_OF_RESOURCES   Fail to execute entry point due to lack of resources.\r
+  @retval EFI_SUCCES             All the related protocols are installed on the driver.\r
+  @retval Others                 Fail to get the SecureBootEnable variable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SecureBootConfigDriverEntryPoint (\r
+  IN EFI_HANDLE          ImageHandle,\r
+  IN EFI_SYSTEM_TABLE    *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData;\r
+  \r
+  //\r
+  // If already started, return.\r
+  //\r
+    Status = gBS->OpenProtocol (\r
+                  ImageHandle,\r
+                  &gEfiCallerIdGuid,\r
+                  NULL,\r
+                  ImageHandle,\r
+                  ImageHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+  \r
+  //\r
+  // Create a private data structure.\r
+  //\r
+  PrivateData = AllocateCopyPool (sizeof (SECUREBOOT_CONFIG_PRIVATE_DATA), &mSecureBootConfigPrivateDateTemplate);\r
+  if (PrivateData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+    \r
+  //\r
+  // Install SecureBoot configuration form\r
+  //\r
+  Status = InstallSecureBootConfigForm (PrivateData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
+  //\r
+  // Install private GUID.\r
+  //    \r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ImageHandle,\r
+                  &gEfiCallerIdGuid,\r
+                  PrivateData,\r
+                  NULL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+  if (PrivateData != NULL) {\r
+    UninstallSecureBootConfigForm (PrivateData);\r
+  }  \r
+  \r
+  return Status;\r
+}\r
+\r
+/**\r
+  Unload the SecureBoot configuration form.\r
+\r
+  @param[in]  ImageHandle         The driver's image handle.\r
+\r
+  @retval     EFI_SUCCESS         The SecureBoot configuration form is unloaded.\r
+  @retval     Others              Failed to unload the form.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SecureBootConfigDriverUnload (\r
+  IN EFI_HANDLE  ImageHandle\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  ImageHandle,\r
+                  &gEfiCallerIdGuid,\r
+                  (VOID **) &PrivateData\r
+                  );  \r
+  if (EFI_ERROR (Status)) {\r
+    return Status;  \r
+  }\r
+  \r
+  ASSERT (PrivateData->Signature == SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE);\r
+\r
+  gBS->UninstallMultipleProtocolInterfaces (\r
+         &ImageHandle,\r
+         &gEfiCallerIdGuid,\r
+         PrivateData,\r
+         NULL\r
+         );\r
+  \r
+  UninstallSecureBootConfigForm (PrivateData);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigDxe.inf
new file mode 100644 (file)
index 0000000..44b15b8
--- /dev/null
@@ -0,0 +1,105 @@
+## @file\r
+# Component name for SecureBoot configuration module for OVMF.\r
+#\r
+# Need custom SecureBootConfigDxe for OVMF that does not force\r
+# resets after PK changes since OVMF doesn't have persistent variables\r
+#\r
+# Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SecureBootConfigDxe\r
+  FILE_GUID                      = F0E6A44F-7195-41c3-AC64-54F202CD0A21\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SecureBootConfigDriverEntryPoint\r
+  UNLOAD_IMAGE                   = SecureBootConfigDriverUnload\r
+\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  SecureBootConfigDriver.c\r
+  SecureBootConfigImpl.c\r
+  SecureBootConfigFileExplorer.c\r
+  SecureBootConfigDevicePath.c\r
+  SecureBootConfigMisc.c\r
+  SecureBootConfigImpl.h\r
+  SecureBootConfig.vfr\r
+  SecureBootConfigStrings.uni\r
+  SecureBootConfigNvData.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  BaseCryptLib\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiDriverEntryPoint\r
+  UefiHiiServicesLib\r
+  DebugLib\r
+  HiiLib\r
+  PlatformSecureLib  \r
+\r
+[Guids]\r
+  gEfiIfrTianoGuid\r
+  gEfiCustomModeEnableGuid\r
+  gEfiSecureBootEnableDisableGuid\r
+  gSecureBootConfigFormSetGuid\r
+  gEfiCertPkcs7Guid\r
+  gEfiCertRsa2048Guid                           ## CONSUMES\r
+  gEfiCertX509Guid                              ## CONSUMES\r
+  gEfiCertSha1Guid                              ## CONSUMES\r
+  gEfiCertSha256Guid                            ## CONSUMES\r
+  gEfiCertTypeRsa2048Sha256Guid                 ## CONSUMES\r
+  gEfiImageSecurityDatabaseGuid                 ## CONSUMES\r
+  gEfiFileSystemVolumeLabelInfoIdGuid           ## CONSUMES\r
+  gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid\r
+  gEfiVT100PlusGuid                             ## CONSUMES ## GUID (The type of terminal)\r
+  gEfiVT100Guid                                 ## CONSUMES ## GUID (The type of terminal)\r
+                                                ## CONSUMES ## GUID HOB (The hob holding memory type information)\r
+  gEfiVTUTF8Guid                                ## CONSUMES ## GUID (The type of terminal)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"BootXX" (Boot option variable)\r
+                                                ## CONSUMES           ## Variable:L"Timeout" (The time out value in second of showing progress bar)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"DriverOrder" (The driver order list)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ConIn" (The device path of console in device)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ConOut" (The device path of console out device)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"ErrOut" (The device path of error out device)\r
+  gEfiFileInfoGuid                              ## CONSUMES ## GUID\r
+  gEfiPcAnsiGuid                                ## CONSUMES ## GUID (The type of terminal)\r
+  gEfiUartDevicePathGuid                        ## CONSUMES ## GUID (Identify the device path for UARD device)\r
+  gEfiSasDevicePathGuid                         ## CONSUMES ## GUID (Identify the device path for SAS device)\r
+\r
+[Protocols]\r
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES\r
+  gEfiHiiConfigRoutingProtocolGuid              ## CONSUMES\r
+  gEfiSimpleFileSystemProtocolGuid              ## PROTOCOL CONSUMES\r
+  gEfiLoadFileProtocolGuid                      ## PROTOCOL CONSUMES\r
+  gEfiBlockIoProtocolGuid                       ## PROTOCOL CONSUMES\r
+  gEfiDevicePathProtocolGuid                    ## PROTOCOL CONSUMES\r
+  gEfiDevicePathToTextProtocolGuid\r
+  gEfiDebugPortProtocolGuid\r
+\r
+[Depex]\r
+  gEfiHiiConfigRoutingProtocolGuid  AND\r
+  gEfiHiiDatabaseProtocolGuid       AND\r
+  gEfiVariableArchProtocolGuid      AND\r
+  gEfiVariableWriteArchProtocolGuid\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigFileExplorer.c b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigFileExplorer.c
new file mode 100644 (file)
index 0000000..deff87b
--- /dev/null
@@ -0,0 +1,1227 @@
+/** @file\r
+  Internal file explorer functions for SecureBoot configuration module.\r
+\r
+Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SecureBootConfigImpl.h"\r
+\r
+///\r
+/// File system selection menu\r
+///\r
+SECUREBOOT_MENU_OPTION      FsOptionMenu = {\r
+  SECUREBOOT_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Files and sub-directories in current directory menu\r
+///\r
+SECUREBOOT_MENU_OPTION      DirectoryMenu = {\r
+  SECUREBOOT_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+VOID                  *mStartOpCodeHandle = NULL;\r
+VOID                  *mEndOpCodeHandle = NULL;\r
+EFI_IFR_GUID_LABEL    *mStartLabel = NULL;\r
+EFI_IFR_GUID_LABEL    *mEndLabel = NULL;\r
+\r
+/**\r
+  Duplicate a string.\r
+\r
+  @param[in]    Src             The source string.\r
+\r
+  @return      A new string which is duplicated copy of the source,\r
+               or NULL if there is not enough memory.\r
+\r
+**/\r
+CHAR16 *\r
+StrDuplicate (\r
+  IN CHAR16   *Src\r
+  )\r
+{\r
+  CHAR16  *Dest;\r
+  UINTN   Size;\r
+\r
+  Size  = StrSize (Src);\r
+  Dest  = AllocateZeroPool (Size);\r
+  ASSERT (Dest != NULL);\r
+  if (Dest != NULL) {\r
+    CopyMem (Dest, Src, Size);\r
+  }\r
+\r
+  return Dest;\r
+}\r
+\r
+/**\r
+  Helper function called as part of the code needed to allocate \r
+  the proper sized buffer for various EFI interfaces.\r
+\r
+  @param[in, out]   Status          Current status\r
+  @param[in, out]   Buffer          Current allocated buffer, or NULL\r
+  @param[in]        BufferSize      Current buffer size needed\r
+\r
+  @retval  TRUE         If the buffer was reallocated and the caller\r
+                        should try the API again.\r
+  @retval  FALSE        The caller should not call this function again.\r
+\r
+**/\r
+BOOLEAN\r
+GrowBuffer (\r
+  IN OUT EFI_STATUS   *Status,\r
+  IN OUT VOID         **Buffer,\r
+  IN UINTN            BufferSize\r
+  )\r
+{\r
+  BOOLEAN TryAgain;\r
+\r
+  //\r
+  // If this is an initial request, buffer will be null with a new buffer size\r
+  //\r
+  if ((*Buffer == NULL) && (BufferSize != 0)) {\r
+    *Status = EFI_BUFFER_TOO_SMALL;\r
+  }\r
+  //\r
+  // If the status code is "buffer too small", resize the buffer\r
+  //\r
+  TryAgain = FALSE;\r
+  if (*Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+    if (*Buffer != NULL) {\r
+      FreePool (*Buffer);\r
+    }\r
+\r
+    *Buffer = AllocateZeroPool (BufferSize);\r
+\r
+    if (*Buffer != NULL) {\r
+      TryAgain = TRUE;\r
+    } else {\r
+      *Status = EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+  //\r
+  // If there's an error, free the buffer\r
+  //\r
+  if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {\r
+    FreePool (*Buffer);\r
+    *Buffer = NULL;\r
+  }\r
+\r
+  return TryAgain;\r
+}\r
+\r
+/**\r
+  Append file name to existing file name, and allocate a new buffer \r
+  to hold the appended result.\r
+\r
+  @param[in]  Str1  The existing file name\r
+  @param[in]  Str2  The file name to be appended\r
+\r
+  @return      A new string with appended result.\r
+\r
+**/\r
+CHAR16 *\r
+AppendFileName (\r
+  IN  CHAR16  *Str1,\r
+  IN  CHAR16  *Str2\r
+  )\r
+{\r
+  UINTN   Size1;\r
+  UINTN   Size2;\r
+  CHAR16  *Str;\r
+  CHAR16  *TmpStr;\r
+  CHAR16  *Ptr;\r
+  CHAR16  *LastSlash;\r
+\r
+  Size1 = StrSize (Str1);\r
+  Size2 = StrSize (Str2);\r
+  Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
+  ASSERT (Str != NULL);\r
+\r
+  TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); \r
+  ASSERT (TmpStr != NULL);\r
+\r
+  StrCat (Str, Str1);\r
+  if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
+    StrCat (Str, L"\\");\r
+  }\r
+\r
+  StrCat (Str, Str2);\r
+\r
+  Ptr       = Str;\r
+  LastSlash = Str;\r
+  while (*Ptr != 0) {\r
+    if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {\r
+      //\r
+      // Convert "\Name\..\" to "\"\r
+      // DO NOT convert the .. if it is at the end of the string. This will\r
+      // break the .. behavior in changing directories.\r
+      //\r
+\r
+      //\r
+      // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
+      // that overlap.\r
+      //\r
+      StrCpy (TmpStr, Ptr + 3);\r
+      StrCpy (LastSlash, TmpStr);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
+      //\r
+      // Convert a "\.\" to a "\"\r
+      //\r
+\r
+      //\r
+      // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
+      // that overlap.\r
+      //\r
+      StrCpy (TmpStr, Ptr + 2);\r
+      StrCpy (Ptr, TmpStr);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\') {\r
+      LastSlash = Ptr;\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+\r
+  FreePool (TmpStr);\r
+  \r
+  return Str;\r
+}\r
+\r
+/**\r
+  Create a SECUREBOOT_MENU_ENTRY, and stores it in a buffer allocated from the pool.\r
+\r
+  @return           The new menu entry or NULL of error happens.\r
+\r
+**/\r
+SECUREBOOT_MENU_ENTRY *\r
+CreateMenuEntry (\r
+  VOID\r
+  )\r
+{\r
+  SECUREBOOT_MENU_ENTRY *MenuEntry;\r
+  UINTN                 ContextSize;\r
+\r
+  //\r
+  // Create new menu entry\r
+  //\r
+  MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));\r
+  if (MenuEntry == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  ContextSize = sizeof (SECUREBOOT_FILE_CONTEXT);\r
+  MenuEntry->FileContext = AllocateZeroPool (ContextSize);\r
+  if (MenuEntry->FileContext == NULL) {\r
+    FreePool (MenuEntry);\r
+    return NULL;\r
+  }\r
+\r
+  MenuEntry->Signature = SECUREBOOT_MENU_ENTRY_SIGNATURE;\r
+\r
+  return MenuEntry;\r
+}\r
+\r
+/**\r
+  Get Menu Entry from the Menu Entry List by MenuNumber.\r
+\r
+  If MenuNumber is great or equal to the number of Menu\r
+  Entry in the list, then ASSERT.\r
+\r
+  @param[in]  MenuOption      The Menu Entry List to read the menu entry.\r
+  @param[in]  MenuNumber      The index of Menu Entry.\r
+\r
+  @return     The Menu Entry.\r
+\r
+**/\r
+SECUREBOOT_MENU_ENTRY *\r
+GetMenuEntry (\r
+  IN  SECUREBOOT_MENU_OPTION      *MenuOption,\r
+  IN  UINTN                       MenuNumber\r
+  )\r
+{\r
+  SECUREBOOT_MENU_ENTRY       *NewMenuEntry;\r
+  UINTN                       Index;\r
+  LIST_ENTRY                  *List;\r
+\r
+  ASSERT (MenuNumber < MenuOption->MenuNumber);\r
+\r
+  List = MenuOption->Head.ForwardLink;\r
+  for (Index = 0; Index < MenuNumber; Index++) {\r
+    List = List->ForwardLink;\r
+  }\r
+\r
+  NewMenuEntry = CR (List, SECUREBOOT_MENU_ENTRY, Link, SECUREBOOT_MENU_ENTRY_SIGNATURE);\r
+\r
+  return NewMenuEntry;\r
+}\r
+\r
+/**\r
+  Create string tokens for a menu from its help strings and display strings.\r
+\r
+  @param[in] HiiHandle          Hii Handle of the package to be updated.\r
+  @param[in] MenuOption         The Menu whose string tokens need to be created.\r
+\r
+**/\r
+VOID\r
+CreateMenuStringToken (\r
+  IN EFI_HII_HANDLE                          HiiHandle,\r
+  IN SECUREBOOT_MENU_OPTION                  *MenuOption\r
+  )\r
+{\r
+  SECUREBOOT_MENU_ENTRY *NewMenuEntry;\r
+  UINTN         Index;\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry = GetMenuEntry (MenuOption, Index);\r
+\r
+    NewMenuEntry->DisplayStringToken = HiiSetString (\r
+                                         HiiHandle,\r
+                                         0,\r
+                                         NewMenuEntry->DisplayString,\r
+                                         NULL\r
+                                         );\r
+\r
+    if (NewMenuEntry->HelpString == NULL) {\r
+      NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
+    } else {\r
+      NewMenuEntry->HelpStringToken = HiiSetString (\r
+                                        HiiHandle,\r
+                                        0,\r
+                                        NewMenuEntry->HelpString,\r
+                                        NULL\r
+                                        );\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Free up all resources allocated for a SECUREBOOT_MENU_ENTRY.\r
+\r
+  @param[in, out]  MenuEntry   A pointer to SECUREBOOT_MENU_ENTRY.\r
+\r
+**/\r
+VOID\r
+DestroyMenuEntry (\r
+  IN OUT SECUREBOOT_MENU_ENTRY         *MenuEntry\r
+  )\r
+{\r
+  SECUREBOOT_FILE_CONTEXT           *FileContext;\r
+\r
+\r
+  FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;\r
+\r
+  if (!FileContext->IsRoot) {\r
+    FreePool (FileContext->DevicePath);\r
+  } else {\r
+    if (FileContext->FHandle != NULL) {\r
+      FileContext->FHandle->Close (FileContext->FHandle);\r
+    }\r
+  }\r
+\r
+  if (FileContext->FileName != NULL) {\r
+    FreePool (FileContext->FileName);\r
+  }\r
+  if (FileContext->Info != NULL) {\r
+    FreePool (FileContext->Info);\r
+  }\r
+\r
+  FreePool (FileContext);\r
+\r
+  FreePool (MenuEntry->DisplayString);\r
+  if (MenuEntry->HelpString != NULL) {\r
+    FreePool (MenuEntry->HelpString);\r
+  }\r
+\r
+  FreePool (MenuEntry);\r
+}\r
+\r
+/**\r
+  Free resources allocated in Allocate Rountine.\r
+\r
+  @param[in, out]  MenuOption        Menu to be freed\r
+  \r
+**/\r
+VOID\r
+FreeMenu (\r
+  IN OUT SECUREBOOT_MENU_OPTION        *MenuOption\r
+  )\r
+{\r
+  SECUREBOOT_MENU_ENTRY      *MenuEntry;\r
+  while (!IsListEmpty (&MenuOption->Head)) {\r
+    MenuEntry = CR (\r
+                  MenuOption->Head.ForwardLink,\r
+                  SECUREBOOT_MENU_ENTRY,\r
+                  Link,\r
+                  SECUREBOOT_MENU_ENTRY_SIGNATURE\r
+                  );\r
+    RemoveEntryList (&MenuEntry->Link);\r
+    DestroyMenuEntry (MenuEntry);\r
+  }\r
+  MenuOption->MenuNumber = 0;\r
+}\r
+\r
+/**\r
+  This function gets the file information from an open file descriptor, and stores it\r
+  in a buffer allocated from pool.\r
+\r
+  @param[in]  FHand           File Handle.\r
+\r
+  @return    A pointer to a buffer with file information or NULL is returned\r
+\r
+**/\r
+EFI_FILE_INFO *\r
+FileInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_FILE_INFO *Buffer;\r
+  UINTN         BufferSize;\r
+\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileInfoGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  This function gets the file system information from an open file descriptor,\r
+  and stores it in a buffer allocated from pool.\r
+\r
+  @param[in] FHand       The file handle.\r
+\r
+  @return                A pointer to a buffer with file information.\r
+  @retval                NULL is returned if failed to get Vaolume Label Info.\r
+\r
+**/\r
+EFI_FILE_SYSTEM_VOLUME_LABEL *\r
+FileSystemVolumeLabelInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL      *Buffer;\r
+  UINTN                             BufferSize;\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileSystemVolumeLabelInfoIdGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  This function will open a file or directory referenced by DevicePath.\r
+\r
+  This function opens a file with the open mode according to the file path. The\r
+  Attributes is valid only for EFI_FILE_MODE_CREATE.\r
+\r
+  @param[in, out]  FilePath        On input, the device path to the file.  \r
+                                   On output, the remaining device path.\r
+  @param[out]      FileHandle      Pointer to the file handle.\r
+  @param[in]       OpenMode        The mode to open the file with.\r
+  @param[in]       Attributes      The file's file attributes.\r
+\r
+  @retval EFI_SUCCESS              The information was set.\r
+  @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.\r
+  @retval EFI_UNSUPPORTED          Could not open the file path.\r
+  @retval EFI_NOT_FOUND            The specified file could not be found on the\r
+                                   device or the file system could not be found on\r
+                                   the device.\r
+  @retval EFI_NO_MEDIA             The device has no medium.\r
+  @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the\r
+                                   medium is no longer supported.\r
+  @retval EFI_DEVICE_ERROR         The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED      The file or medium is write protected.\r
+  @retval EFI_ACCESS_DENIED        The file was opened read only.\r
+  @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the\r
+                                   file.\r
+  @retval EFI_VOLUME_FULL          The volume is full.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OpenFileByDevicePath(\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,\r
+  OUT EFI_FILE_HANDLE                 *FileHandle,\r
+  IN UINT64                           OpenMode,\r
+  IN UINT64                           Attributes\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
+  EFI_FILE_PROTOCOL               *Handle1;\r
+  EFI_FILE_PROTOCOL               *Handle2;\r
+  EFI_HANDLE                      DeviceHandle; \r
+\r
+  if ((FilePath == NULL || FileHandle == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  FilePath,\r
+                  &DeviceHandle\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol(\r
+                  DeviceHandle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  (VOID**)&EfiSimpleFileSystemProtocol,\r
+                  gImageHandle,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);\r
+  if (EFI_ERROR (Status)) {\r
+    FileHandle = NULL;\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // go down directories one node at a time.\r
+  //\r
+  while (!IsDevicePathEnd (*FilePath)) {\r
+    //\r
+    // For file system access each node should be a file path component\r
+    //\r
+    if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||\r
+        DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
+       ) {\r
+      FileHandle = NULL;\r
+      return (EFI_INVALID_PARAMETER);\r
+    }\r
+    //\r
+    // Open this file path node\r
+    //\r
+    Handle2  = Handle1;\r
+    Handle1 = NULL;\r
+\r
+    //\r
+    // Try to test opening an existing file\r
+    //\r
+    Status = Handle2->Open (\r
+                          Handle2,\r
+                          &Handle1,\r
+                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
+                          OpenMode &~EFI_FILE_MODE_CREATE,\r
+                          0\r
+                         );\r
+\r
+    //\r
+    // see if the error was that it needs to be created\r
+    //\r
+    if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
+      Status = Handle2->Open (\r
+                            Handle2,\r
+                            &Handle1,\r
+                            ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
+                            OpenMode,\r
+                            Attributes\r
+                           );\r
+    }\r
+    //\r
+    // Close the last node\r
+    //\r
+    Handle2->Close (Handle2);\r
+\r
+    if (EFI_ERROR(Status)) {\r
+      return (Status);\r
+    }\r
+\r
+    //\r
+    // Get the next node\r
+    //\r
+    *FilePath = NextDevicePathNode (*FilePath);\r
+  }\r
+\r
+  //\r
+  // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!\r
+  //\r
+  *FileHandle = (VOID*)Handle1;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Function opens and returns a file handle to the root directory of a volume.\r
+\r
+  @param[in]   DeviceHandle    A handle for a device\r
+\r
+  @return      A valid file handle or NULL if error happens.\r
+\r
+**/\r
+EFI_FILE_HANDLE\r
+OpenRoot (\r
+  IN EFI_HANDLE                   DeviceHandle\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+  EFI_FILE_HANDLE                 File;\r
+\r
+  File = NULL;\r
+\r
+  //\r
+  // File the file system interface to the device\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  DeviceHandle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  (VOID *) &Volume\r
+                  );\r
+\r
+  //\r
+  // Open the root directory of the volume\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = Volume->OpenVolume (\r
+                      Volume,\r
+                      &File\r
+                      );\r
+  }\r
+  //\r
+  // Done\r
+  //\r
+  return EFI_ERROR (Status) ? NULL : File;\r
+}\r
+\r
+/**\r
+  This function builds the FsOptionMenu list which records all\r
+  available file system in the system. They include all instances\r
+  of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM\r
+  and all type of legacy boot device.\r
+\r
+  @retval  EFI_SUCCESS             Success find the file system\r
+  @retval  EFI_OUT_OF_RESOURCES    Can not create menu entry\r
+\r
+**/\r
+EFI_STATUS\r
+FindFileSystem (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                     NoBlkIoHandles;\r
+  UINTN                     NoSimpleFsHandles;\r
+  UINTN                     NoLoadFileHandles;\r
+  EFI_HANDLE                *BlkIoHandle;\r
+  EFI_HANDLE                *SimpleFsHandle;\r
+  UINT16                    *VolumeLabel;\r
+  EFI_BLOCK_IO_PROTOCOL     *BlkIo;\r
+  UINTN                     Index;\r
+  EFI_STATUS                Status;\r
+  SECUREBOOT_MENU_ENTRY     *MenuEntry;\r
+  SECUREBOOT_FILE_CONTEXT   *FileContext;\r
+  UINT16                    *TempStr;\r
+  UINTN                     OptionNumber;\r
+  VOID                      *Buffer;\r
+\r
+  BOOLEAN                   RemovableMedia;\r
+\r
+\r
+  NoSimpleFsHandles = 0;\r
+  NoLoadFileHandles = 0;\r
+  OptionNumber      = 0;\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+\r
+  //\r
+  // Locate Handles that support BlockIo protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  NULL,\r
+                  &NoBlkIoHandles,\r
+                  &BlkIoHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    for (Index = 0; Index < NoBlkIoHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      BlkIoHandle[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media\r
+      //\r
+      if (BlkIo->Media->RemovableMedia) {\r
+        Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);\r
+        if (NULL == Buffer) {\r
+          FreePool (BlkIoHandle);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        BlkIo->ReadBlocks (\r
+                BlkIo,\r
+                BlkIo->Media->MediaId,\r
+                0,\r
+                BlkIo->Media->BlockSize,\r
+                Buffer\r
+                );\r
+        FreePool (Buffer);\r
+      }\r
+    }\r
+    FreePool (BlkIoHandle);\r
+  }\r
+\r
+  //\r
+  // Locate Handles that support Simple File System protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  NULL,\r
+                  &NoSimpleFsHandles,\r
+                  &SimpleFsHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Find all the instances of the File System prototocol\r
+    //\r
+    for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      SimpleFsHandle[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // If no block IO exists assume it's NOT a removable media\r
+        //\r
+        RemovableMedia = FALSE;\r
+      } else {\r
+        //\r
+        // If block IO exists check to see if it's remobable media\r
+        //\r
+        RemovableMedia = BlkIo->Media->RemovableMedia;\r
+      }\r
+\r
+      //\r
+      // Allocate pool for this instance.\r
+      //\r
+      MenuEntry = CreateMenuEntry ();\r
+      if (NULL == MenuEntry) {\r
+        FreePool (SimpleFsHandle);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;\r
+\r
+      FileContext->Handle     = SimpleFsHandle[Index];\r
+      MenuEntry->OptionNumber = Index;\r
+      FileContext->FHandle    = OpenRoot (FileContext->Handle);\r
+      if (FileContext->FHandle == NULL) {\r
+        DestroyMenuEntry (MenuEntry);\r
+        continue;\r
+      }\r
+\r
+      MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
+      FileContext->Info = FileSystemVolumeLabelInfo (FileContext->FHandle);\r
+      FileContext->FileName = StrDuplicate (L"\\");\r
+      FileContext->DevicePath = FileDevicePath (\r
+                                  FileContext->Handle,\r
+                                  FileContext->FileName\r
+                                  );\r
+      FileContext->IsDir            = TRUE;\r
+      FileContext->IsRoot           = TRUE;\r
+      FileContext->IsRemovableMedia = RemovableMedia;\r
+      FileContext->IsLoadFile       = FALSE;\r
+\r
+      //\r
+      // Get current file system's Volume Label\r
+      //\r
+      if (FileContext->Info == NULL) {\r
+        VolumeLabel = L"NO FILE SYSTEM INFO";\r
+      } else {\r
+        if (FileContext->Info->VolumeLabel == NULL) {\r
+          VolumeLabel = L"NULL VOLUME LABEL";\r
+        } else {\r
+          VolumeLabel = FileContext->Info->VolumeLabel;\r
+          if (*VolumeLabel == 0x0000) {\r
+            VolumeLabel = L"NO VOLUME LABEL";\r
+          }\r
+        }\r
+      }\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"%s, [%s]",\r
+        VolumeLabel,\r
+        TempStr\r
+        );\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  if (NoSimpleFsHandles != 0) {\r
+    FreePool (SimpleFsHandle);\r
+  }\r
+  \r
+  //\r
+  // Remember how many file system options are here\r
+  //\r
+  FsOptionMenu.MenuNumber = OptionNumber;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Find files under the current directory. All files and sub-directories \r
+  in current directory will be stored in DirectoryMenu for future use.\r
+\r
+  @param[in] MenuEntry     The Menu Entry.\r
+\r
+  @retval EFI_SUCCESS      Get files from current dir successfully.\r
+  @return Other            Can't get files from current dir.\r
+\r
+**/\r
+EFI_STATUS\r
+FindFiles (\r
+  IN SECUREBOOT_MENU_ENTRY              *MenuEntry\r
+  )\r
+{\r
+  EFI_FILE_HANDLE           NewDir;\r
+  EFI_FILE_HANDLE           Dir;\r
+  EFI_FILE_INFO             *DirInfo;\r
+  UINTN                     BufferSize;\r
+  UINTN                     DirBufferSize;\r
+  SECUREBOOT_MENU_ENTRY     *NewMenuEntry;\r
+  SECUREBOOT_FILE_CONTEXT   *FileContext;\r
+  SECUREBOOT_FILE_CONTEXT   *NewFileContext;\r
+  UINTN                     Pass;\r
+  EFI_STATUS                Status;\r
+  UINTN                     OptionNumber;\r
+\r
+  FileContext   = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;\r
+  Dir           = FileContext->FHandle;\r
+  OptionNumber  = 0;\r
+  //\r
+  // Open current directory to get files from it\r
+  //\r
+  Status = Dir->Open (\r
+                  Dir,\r
+                  &NewDir,\r
+                  FileContext->FileName,\r
+                  EFI_FILE_READ_ONLY,\r
+                  0\r
+                  );\r
+  if (!FileContext->IsRoot) {\r
+    Dir->Close (Dir);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DirInfo = FileInfo (NewDir);\r
+  if (DirInfo == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FileContext->DevicePath = FileDevicePath (\r
+                              FileContext->Handle,\r
+                              FileContext->FileName\r
+                              );\r
+\r
+  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
+  DirInfo       = AllocateZeroPool (DirBufferSize);\r
+  if (DirInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  //\r
+  // Get all files in current directory\r
+  // Pass 1 to get Directories\r
+  // Pass 2 to get files that are EFI images\r
+  //\r
+  for (Pass = 1; Pass <= 2; Pass++) {\r
+    NewDir->SetPosition (NewDir, 0);\r
+    for (;;) {\r
+      BufferSize  = DirBufferSize;\r
+      Status      = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
+      if (EFI_ERROR (Status) || BufferSize == 0) {\r
+        break;\r
+      }\r
+\r
+      if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||\r
+          ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)\r
+          ) {\r
+        //\r
+        // Pass 1 is for Directories\r
+        // Pass 2 is for file names\r
+        //\r
+        continue;\r
+      }\r
+\r
+      NewMenuEntry = CreateMenuEntry ();\r
+      if (NULL == NewMenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewFileContext          = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext;\r
+      NewFileContext->Handle  = FileContext->Handle;\r
+      NewFileContext->FileName = AppendFileName (\r
+                                  FileContext->FileName,\r
+                                  DirInfo->FileName\r
+                                  );\r
+      NewFileContext->FHandle = NewDir;\r
+      NewFileContext->DevicePath = FileDevicePath (\r
+                                    NewFileContext->Handle,\r
+                                    NewFileContext->FileName\r
+                                    );\r
+      NewMenuEntry->HelpString = NULL;\r
+      \r
+      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
+      if (NewFileContext->IsDir) {\r
+        BufferSize = StrLen (DirInfo->FileName) * 2 + 6;\r
+        NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);\r
+\r
+        UnicodeSPrint (\r
+          NewMenuEntry->DisplayString,\r
+          BufferSize,\r
+          L"<%s>",\r
+          DirInfo->FileName\r
+          );\r
+\r
+      } else {\r
+        NewMenuEntry->DisplayString = StrDuplicate (DirInfo->FileName);\r
+      }\r
+\r
+      NewFileContext->IsRoot            = FALSE;\r
+      NewFileContext->IsLoadFile        = FALSE;\r
+      NewFileContext->IsRemovableMedia  = FALSE;\r
+\r
+      NewMenuEntry->OptionNumber        = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  DirectoryMenu.MenuNumber = OptionNumber;\r
+  FreePool (DirInfo);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Refresh the global UpdateData structure.\r
+\r
+**/\r
+VOID\r
+RefreshUpdateData (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Free current updated date\r
+  //  \r
+  if (mStartOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
+  }\r
+\r
+  //\r
+  // Create new OpCode Handle\r
+  //\r
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();\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
+/**\r
+  Update the File Explore page.\r
+\r
+  @param[in] HiiHandle          Hii Handle of the package to be updated.\r
+  @param[in] MenuOption         The Menu whose string tokens need to be updated.\r
+  @param[in] FeCurrentState     Current file explorer state.\r
+\r
+**/\r
+VOID\r
+UpdateFileExplorePage (\r
+  IN EFI_HII_HANDLE               HiiHandle,\r
+  IN SECUREBOOT_MENU_OPTION       *MenuOption,\r
+  IN FILE_EXPLORER_STATE          FeCurrentState\r
+  )\r
+{\r
+  UINTN                   Index;\r
+  SECUREBOOT_MENU_ENTRY   *NewMenuEntry;\r
+  SECUREBOOT_FILE_CONTEXT *NewFileContext;\r
+  EFI_FORM_ID             FormId;\r
+  EFI_FORM_ID             FileFormId;\r
+\r
+  if (FeCurrentState == FileExplorerStateEnrollPkFile) {\r
+    FormId     = SECUREBOOT_ADD_PK_FILE_FORM_ID;\r
+    FileFormId = FORM_FILE_EXPLORER_ID_PK;\r
+  } else if (FeCurrentState == FileExplorerStateEnrollKekFile) {\r
+    FormId     = FORMID_ENROLL_KEK_FORM;\r
+    FileFormId = FORM_FILE_EXPLORER_ID_KEK;\r
+  } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDb) {\r
+    FormId     = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
+    FileFormId = FORM_FILE_EXPLORER_ID_DB;\r
+  } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) {\r
+    FormId     = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
+    FileFormId = FORM_FILE_EXPLORER_ID_DBX;\r
+  } else {\r
+    return;\r
+  }\r
+\r
+  NewMenuEntry    = NULL;\r
+  NewFileContext  = NULL;\r
+\r
+  RefreshUpdateData ();\r
+  mStartLabel->Number = FORM_FILE_EXPLORER_ID;\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry    = GetMenuEntry (MenuOption, Index);\r
+    NewFileContext  = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext;\r
+\r
+    if (NewFileContext->IsDir) {\r
+      //\r
+      // Create Text opcode for directory.\r
+      //\r
+      HiiCreateActionOpCode (\r
+        mStartOpCodeHandle,\r
+        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        0\r
+        );\r
+    } else {\r
+\r
+      //\r
+      // Create Goto opcode for file.\r
+      //\r
+      HiiCreateGotoOpCode (\r
+        mStartOpCodeHandle,\r
+        FormId,\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        (UINT16) (FILE_OPTION_OFFSET + Index)\r
+        );\r
+    }\r
+  }\r
+\r
+  HiiUpdateForm (\r
+    HiiHandle,\r
+    &gSecureBootConfigFormSetGuid,\r
+    FileFormId,\r
+    mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID\r
+    mEndOpCodeHandle    // LABEL_END\r
+    );\r
+}\r
+\r
+/**\r
+  Update the file explorer page with the refreshed file system.\r
+\r
+  @param[in] PrivateData     Module private data.\r
+  @param[in] KeyValue        Key value to identify the type of data to expect.\r
+\r
+  @retval  TRUE           Inform the caller to create a callback packet to exit file explorer.\r
+  @retval  FALSE          Indicate that there is no need to exit file explorer.\r
+\r
+**/\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
+  IN UINT16                           KeyValue\r
+  )\r
+{\r
+  UINT16                              FileOptionMask;\r
+  SECUREBOOT_MENU_ENTRY               *NewMenuEntry;\r
+  SECUREBOOT_FILE_CONTEXT             *NewFileContext;\r
+  EFI_FORM_ID                         FormId;\r
+  BOOLEAN                             ExitFileExplorer;\r
+  EFI_STATUS                          Status;\r
+  EFI_DEVICE_PATH_PROTOCOL            *TmpDevicePath;\r
+\r
+  NewMenuEntry      = NULL;\r
+  NewFileContext    = NULL;\r
+  ExitFileExplorer  = FALSE;\r
+  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+\r
+  if (PrivateData->FeDisplayContext == FileExplorerDisplayUnknown) {\r
+    //\r
+    // First in, display file system.\r
+    //\r
+    FreeMenu (&FsOptionMenu);\r
+    FindFileSystem ();\r
+    \r
+    CreateMenuStringToken (PrivateData->HiiHandle, &FsOptionMenu);\r
+    UpdateFileExplorePage (PrivateData->HiiHandle, &FsOptionMenu, PrivateData->FeCurrentState);\r
+\r
+    PrivateData->FeDisplayContext = FileExplorerDisplayFileSystem;\r
+  } else {\r
+    if (PrivateData->FeDisplayContext == FileExplorerDisplayFileSystem) {\r
+      NewMenuEntry = GetMenuEntry (&FsOptionMenu, FileOptionMask);\r
+    } else if (PrivateData->FeDisplayContext == FileExplorerDisplayDirectory) {\r
+      NewMenuEntry = GetMenuEntry (&DirectoryMenu, FileOptionMask);\r
+    }\r
+\r
+    NewFileContext = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext;\r
+\r
+    if (NewFileContext->IsDir ) {\r
+      PrivateData->FeDisplayContext = FileExplorerDisplayDirectory;\r
+\r
+      RemoveEntryList (&NewMenuEntry->Link);\r
+      FreeMenu (&DirectoryMenu);\r
+      Status = FindFiles (NewMenuEntry);\r
+       if (EFI_ERROR (Status)) {\r
+         ExitFileExplorer = TRUE;\r
+         goto OnExit;\r
+       }\r
+      CreateMenuStringToken (PrivateData->HiiHandle, &DirectoryMenu);\r
+      DestroyMenuEntry (NewMenuEntry);\r
+\r
+      UpdateFileExplorePage (PrivateData->HiiHandle, &DirectoryMenu, PrivateData->FeCurrentState);\r
+\r
+    } else {\r
+      if (PrivateData->FeCurrentState == FileExplorerStateEnrollPkFile) {\r
+        FormId = SECUREBOOT_ADD_PK_FILE_FORM_ID;\r
+      } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollKekFile) {\r
+        FormId = FORMID_ENROLL_KEK_FORM;\r
+      } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDb) {\r
+        FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;\r
+      } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) {\r
+        FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;\r
+      } else {\r
+        return FALSE;\r
+      }\r
+\r
+      PrivateData->MenuEntry = NewMenuEntry;\r
+      PrivateData->FileContext->FileName = NewFileContext->FileName;\r
+      \r
+      TmpDevicePath = NewFileContext->DevicePath;\r
+      OpenFileByDevicePath (\r
+        &TmpDevicePath,\r
+        &PrivateData->FileContext->FHandle,\r
+        EFI_FILE_MODE_READ,\r
+        0\r
+        );\r
+\r
+      //\r
+      // Create Subtitle op-code for the display string of the option.\r
+      //\r
+      RefreshUpdateData ();\r
+      mStartLabel->Number = FormId;\r
+\r
+      HiiCreateSubTitleOpCode (\r
+        mStartOpCodeHandle,\r
+        NewMenuEntry->DisplayStringToken,\r
+        0,\r
+        0,\r
+        0\r
+        );\r
+\r
+      HiiUpdateForm (\r
+        PrivateData->HiiHandle,\r
+        &gSecureBootConfigFormSetGuid,\r
+        FormId,\r
+        mStartOpCodeHandle, // Label FormId\r
+        mEndOpCodeHandle    // LABEL_END\r
+        );\r
+    }\r
+  }\r
+\r
+OnExit:\r
+  return ExitFileExplorer;\r
+}\r
+\r
+/**\r
+  Clean up the dynamic opcode at label and form specified by both LabelId. \r
+\r
+  @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.\r
+  @param[in] PrivateData     Module private data.\r
+\r
+**/\r
+VOID\r
+CleanUpPage (\r
+  IN UINT16                           LabelId,\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData\r
+  )\r
+{\r
+  RefreshUpdateData ();\r
+\r
+  //\r
+  // Remove all op-codes from dynamic page\r
+  //\r
+  mStartLabel->Number = LabelId;\r
+  HiiUpdateForm (\r
+    PrivateData->HiiHandle,\r
+    &gSecureBootConfigFormSetGuid,\r
+    LabelId,\r
+    mStartOpCodeHandle, // Label LabelId\r
+    mEndOpCodeHandle    // LABEL_END\r
+    );\r
+}\r
+\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigImpl.c b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigImpl.c
new file mode 100644 (file)
index 0000000..c82c0f4
--- /dev/null
@@ -0,0 +1,2804 @@
+/** @file\r
+  HII Config Access protocol implementation of SecureBoot configuration module.\r
+\r
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SecureBootConfigImpl.h"\r
+\r
+CHAR16              mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";\r
+\r
+SECUREBOOT_CONFIG_PRIVATE_DATA         mSecureBootConfigPrivateDateTemplate = {\r
+  SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,  \r
+  {\r
+    SecureBootExtractConfig,\r
+    SecureBootRouteConfig,\r
+    SecureBootCallback\r
+  }\r
+};\r
+\r
+HII_VENDOR_DEVICE_PATH          mSecureBootHiiVendorDevicePath = {\r
+  {\r
+    {\r
+      HARDWARE_DEVICE_PATH,\r
+      HW_VENDOR_DP,\r
+      {\r
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
+      }\r
+    },\r
+    SECUREBOOT_CONFIG_FORM_SET_GUID\r
+  },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    {\r
+      (UINT8) (END_DEVICE_PATH_LENGTH),\r
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
+    }\r
+  }\r
+};\r
+\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"SHA1",   20, &mHashOidValue[8],  5, Sha1GetContextSize,  Sha1Init,   Sha1Update,    Sha1Final  },\r
+  { L"SHA224", 28, &mHashOidValue[13], 9, NULL,                NULL,       NULL,          NULL       },\r
+  { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize,Sha256Init, Sha256Update,  Sha256Final},\r
+  { L"SHA384", 48, &mHashOidValue[31], 9, NULL,                NULL,       NULL,          NULL       },\r
+  { L"SHA512", 64, &mHashOidValue[40], 9, NULL,                NULL,       NULL,          NULL       }\r
+};\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
+/**\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
+  Set Secure Boot option into variable space.\r
+\r
+  @param[in] VarValue              The option of Secure Boot.\r
+\r
+  @retval    EFI_SUCCESS           The operation is finished successfully.\r
+  @retval    Others                Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+SaveSecureBootVariable (\r
+  IN UINT8                         VarValue\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+\r
+  Status = gRT->SetVariable (\r
+             EFI_SECURE_BOOT_ENABLE_NAME,\r
+             &gEfiSecureBootEnableDisableGuid,\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
+  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
+  Internal helper function to delete a Variable given its name and GUID, NO authentication\r
+  required.\r
+\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
+\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
+  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
+  \r
+  if (Private->FileContext->FileName == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PkCert = NULL;\r
+\r
+  //\r
+  // Parse the file's postfix. Only support DER encoded X.509 certificate files.\r
+  //\r
+  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
+  if (!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
+  if (Private->FileContext->FHandle != NULL) {\r
+    CloseFile (Private->FileContext->FHandle);\r
+    Private->FileContext->FHandle = NULL;\r
+  }\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 = 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
+  CloseFile (Private->FileContext->FHandle);\r
+  Private->FileContext->FHandle = NULL;\r
+  Private->FileContext->FileName = NULL;\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
+  CloseFile (Private->FileContext->FHandle);\r
+  Private->FileContext->FileName = NULL;\r
+  Private->FileContext->FHandle = NULL;\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
+  \r
+  if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Parse the file's postfix. Supports DER-encoded X509 certificate, \r
+  // and .pbk as RSA public key file.\r
+  //\r
+  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
+  if (IsDerEncodeCertificate(FilePostFix)) {\r
+    return EnrollX509ToKek (Private);\r
+  } else if (CompareMem (FilePostFix, L".pbk",4) == 0) {\r
+    return EnrollRsa2048ToKek (Private);\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+}\r
+\r
+/**\r
+  Enroll a new X509 certificate into Signature Database (DB or DBX) without\r
+  KEK's authentication.\r
+\r
+  @param[in] PrivateData     The module's private data.\r
+  @param[in] VariableName    Variable name of signature database, must be \r
+                             EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.\r
+  \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
+  CloseFile (Private->FileContext->FHandle);\r
+  Private->FileContext->FileName = NULL;\r
+  Private->FileContext->FHandle = NULL;\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
+  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
+\r
+  NtHeader32 = NULL;\r
+  NtHeader64 = NULL;\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
+    //\r
+    // IA-32 Architecture\r
+    //\r
+    mImageType = ImageType_IA32;\r
+    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
+  }\r
+  else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)\r
+          || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)) {\r
+    //\r
+    // 64-bits Architecture\r
+    //\r
+    mImageType = ImageType_X64;\r
+    NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset);\r
+    mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\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
+  @param[in]    HashAlg   Hash algorithm type.\r
\r
+  @retval TRUE            Successfully hash image.\r
+  @retval FALSE           Fail in hash image.\r
+\r
+**/\r
+BOOLEAN \r
+HashPeImage (\r
+  IN  UINT32                HashAlg\r
+  )\r
+{\r
+  BOOLEAN                   Status;\r
+  UINT16                    Magic;\r
+  EFI_IMAGE_SECTION_HEADER  *Section;\r
+  VOID                      *HashCtx;\r
+  UINTN                     CtxSize;\r
+  UINT8                     *HashBase;\r
+  UINTN                     HashSize;\r
+  UINTN                     SumOfBytesHashed;\r
+  EFI_IMAGE_SECTION_HEADER  *SectionHeader;\r
+  UINTN                     Index;\r
+  UINTN                     Pos;\r
+\r
+  HashCtx       = NULL;\r
+  SectionHeader = NULL;\r
+  Status        = FALSE;\r
+\r
+  if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
+    return FALSE;\r
+  }\r
+  \r
+  //\r
+  // Initialize context of hash.\r
+  //\r
+  ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
+\r
+  if (HashAlg == HASHALG_SHA1) {\r
+    mImageDigestSize  = SHA1_DIGEST_SIZE;\r
+    mCertType         = gEfiCertSha1Guid;    \r
+  } else if (HashAlg == HASHALG_SHA256) {\r
+    mImageDigestSize  = SHA256_DIGEST_SIZE;\r
+    mCertType         = gEfiCertSha256Guid;\r
+  }\r
+\r
+  CtxSize   = mHash[HashAlg].GetContextSize();\r
+  \r
+  HashCtx = AllocatePool (CtxSize);\r
+  ASSERT (HashCtx != NULL);\r
+\r
+  // 1.  Load the image header into memory.\r
+\r
+  // 2.  Initialize a SHA hash context.\r
+  Status = mHash[HashAlg].HashInit(HashCtx);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Measuring PE/COFF Image Header;\r
+  // But CheckSum field and SECURITY data directory (certificate) are excluded\r
+  //\r
+  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
+    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+    //\r
+    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+  } else {\r
+    //\r
+    // Get the magic value from the PE/COFF Optional Header\r
+    //\r
+    Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+  }\r
+  \r
+  //\r
+  // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
+  // 4.  Hash the image header from its base to beginning of the image checksum.\r
+  //\r
+  HashBase = mImageBase;\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset.\r
+    //\r
+    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //\r
+    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // 5.  Skip over the image checksum (it occupies a single ULONG).\r
+  // 6.  Get the address of the beginning of the Cert Directory.\r
+  // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
+  //\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset.\r
+    //\r
+    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //    \r
+    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
+  // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
+  //\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset\r
+    //\r
+    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+    HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //\r
+    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+    HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+  if (!Status) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
+  //\r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Use PE32 offset.\r
+    //\r
+    SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;\r
+  } else {\r
+    //\r
+    // Use PE32+ offset\r
+    //\r
+    SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
+  }\r
+\r
+  //\r
+  // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
+  //     structures in the image. The 'NumberOfSections' field of the image\r
+  //     header indicates how big the table should be. Do not include any\r
+  //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
+  ASSERT (SectionHeader != NULL);\r
+  //\r
+  // 12.  Using the 'PointerToRawData' in the referenced section headers as\r
+  //      a key, arrange the elements in the table in ascending order. In other\r
+  //      words, sort the section headers according to the disk-file offset of\r
+  //      the section.\r
+  //\r
+  Section = (EFI_IMAGE_SECTION_HEADER *) (\r
+               mImageBase +\r
+               mPeCoffHeaderOffset +\r
+               sizeof (UINT32) +\r
+               sizeof (EFI_IMAGE_FILE_HEADER) +\r
+               mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
+               );\r
+  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
+    Pos = Index;\r
+    while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
+      CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER));\r
+      Pos--;\r
+    }\r
+    CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER));\r
+    Section += 1;\r
+  }\r
+\r
+  //\r
+  // 13.  Walk through the sorted table, bring the corresponding section\r
+  //      into memory, and hash the entire section (using the 'SizeOfRawData'\r
+  //      field in the section header to determine the amount of data to hash).\r
+  // 14.  Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .\r
+  // 15.  Repeat steps 13 and 14 for all the sections in the sorted table.\r
+  //\r
+  for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
+    Section = &SectionHeader[Index];\r
+    if (Section->SizeOfRawData == 0) {\r
+      continue;\r
+    }\r
+    HashBase  = mImageBase + Section->PointerToRawData;\r
+    HashSize  = (UINTN) Section->SizeOfRawData;\r
+\r
+    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+    if (!Status) {\r
+      goto Done;\r
+    }\r
+\r
+    SumOfBytesHashed += HashSize;\r
+  }\r
+\r
+  //\r
+  // 16.  If the file size is greater than SUM_OF_BYTES_HASHED, there is extra\r
+  //      data in the file that needs to be added to the hash. This data begins\r
+  //      at file offset SUM_OF_BYTES_HASHED and its length is:\r
+  //             FileSize  -  (CertDirectory->Size)\r
+  //\r
+  if (mImageSize > SumOfBytesHashed) {\r
+    HashBase = mImageBase + SumOfBytesHashed;\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset.\r
+      //\r
+      HashSize = (UINTN)(\r
+                 mImageSize -\r
+                 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+                 SumOfBytesHashed);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset.\r
+      //\r
+      HashSize = (UINTN)(\r
+                 mImageSize -\r
+                 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
+                 SumOfBytesHashed);      \r
+    }\r
+\r
+    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+    if (!Status) {\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  Status  = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
+\r
+Done:\r
+  if (HashCtx != NULL) {\r
+    FreePool (HashCtx);\r
+  }\r
+  if (SectionHeader != NULL) {\r
+    FreePool (SectionHeader);\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Recognize the Hash algorithm in PE/COFF Authenticode and caculate 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 or EFI_IMAGE_SECURITY_DATABASE1.\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
+  //\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
+  CloseFile (Private->FileContext->FHandle);\r
+  Private->FileContext->FHandle = NULL;\r
+  Private->FileContext->FileName = NULL;\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 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
+\r
+  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Parse the file's postfix. \r
+  //\r
+  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
+  if (IsDerEncodeCertificate(FilePostFix)) {\r
+    //\r
+    // Supports DER-encoded X509 certificate.\r
+    //\r
+    return EnrollX509toSigDB (Private, VariableName);\r
+  }\r
+\r
+  return EnrollImageSignatureToSigDB (Private, VariableName);\r
+}\r
+\r
+/**\r
+  List all signatures in specified signature database (e.g. KEK/DB/DBX)\r
+  by GUID in the page for user to select and delete as needed.\r
+\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 {\r
+      //\r
+      // The signature type is not supported in current implementation.\r
+      //\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
+  //\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_ERROR, "       CertCount = %x\n", CertCount));\r
+    if (CertCount != 0) {\r
+      CopyMem (OldData + Offset, CertList, CertList->SignatureListSize);\r
+      Offset += CertList->SignatureListSize;\r
+    }    \r
+    KekDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+  DataSize = Offset;\r
+  if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    Status = CreateTimeBasedPayload (&DataSize, &OldData);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status));\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+\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 siganture 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 siganture successfully.\r
+  @retval   EFI_NOT_FOUND           Can't find the signature item,\r
+  @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.\r
+**/\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
+  //\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
+        ) {\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_ERROR, "       CertCount = %x\n", CertCount));\r
+    if (CertCount != 0) {\r
+      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);\r
+      Offset += CertList->SignatureListSize;\r
+    }    \r
+    ItemDataSize -= CertList->SignatureListSize;\r
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\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 extracts configuration from variable.\r
+  \r
+  @param[in, out]  ConfigData   Point to SecureBoot configuration private data.\r
+\r
+**/\r
+VOID\r
+SecureBootExtractConfigFromVariable (\r
+  IN OUT SECUREBOOT_CONFIGURATION    *ConfigData\r
+  ) \r
+{\r
+  UINT8   *SecureBootEnable;\r
+  UINT8   *SetupMode;\r
+  UINT8   *SecureBoot;\r
+  UINT8   *SecureBootMode;\r
+\r
+  SecureBootEnable = NULL;\r
+  SetupMode        = NULL;\r
+  SecureBoot       = NULL;\r
+  SecureBootMode   = NULL;\r
+  \r
+  //\r
+  // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
+  // Checkbox.\r
+  //\r
+  GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
+  if (SecureBootEnable == NULL) {\r
+    ConfigData->HideSecureBoot = TRUE;\r
+  } else {\r
+    ConfigData->HideSecureBoot = FALSE;\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
+  // If the value of SecureBoot variable is 1, the platform is operating in secure boot mode.\r
+  //\r
+  GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
+  if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
+    ConfigData->SecureBootState = TRUE;\r
+  } else {\r
+    ConfigData->SecureBootState = FALSE;\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
+}\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
+  //\r
+  // Get Configuration from Variable.\r
+  //\r
+  SecureBootExtractConfigFromVariable (&Configuration);\r
+  \r
+  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
+  ConfigRequest = Request;\r
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
+    //\r
+    // Request is set to NULL or OFFSET is NULL, construct full request string.\r
+    //\r
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
+    //\r
+    ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle);\r
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
+    ConfigRequest = AllocateZeroPool (Size);\r
+    ASSERT (ConfigRequest != NULL);\r
+    AllocatedRequest = TRUE;\r
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
+    FreePool (ConfigRequestHdr);\r
+    ConfigRequestHdr = NULL;\r
+  }\r
+\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
+  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
+  *Progress = Configuration + StrLen (Configuration);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\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
+  @param[in]  QuestionId         A unique value which is sent to the original\r
+                                 exporting driver so that it can identify the type\r
+                                 of data to expect.\r
+  @param[in]  Type               The type of value for the question.\r
+  @param[in]  Value              A pointer to the data being sent to the original\r
+                                 exporting driver.\r
+  @param[out] ActionRequest      On return, points to the action requested by the\r
+                                 callback function.\r
+\r
+  @retval EFI_SUCCESS            The callback successfully handled the action.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
+                                 variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
+                                 callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SecureBootCallback (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
+  IN     EFI_BROWSER_ACTION                    Action,\r
+  IN     EFI_QUESTION_ID                       QuestionId,\r
+  IN     UINT8                                 Type,\r
+  IN     EFI_IFR_TYPE_VALUE                    *Value,\r
+     OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
+  )\r
+{\r
+  EFI_INPUT_KEY                   Key;\r
+  EFI_STATUS                      Status;  \r
+  SECUREBOOT_CONFIG_PRIVATE_DATA  *Private;\r
+  UINTN                           BufferSize;\r
+  SECUREBOOT_CONFIGURATION        *IfrNvData;\r
+  UINT16                          LabelId;\r
+  UINT8                           *SecureBootEnable;\r
+  CHAR16                          PromptString[100];\r
+\r
+  SecureBootEnable = NULL;\r
+\r
+  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
+\r
+  //\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
+  Status = EFI_SUCCESS;\r
+\r
+  HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);\r
+  \r
+  if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
+\r
+    switch (QuestionId) {\r
+    case KEY_SECURE_BOOT_ENABLE:\r
+      GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
+      if (NULL != SecureBootEnable) {\r
+        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
+        }\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; \r
+      }\r
+      break;\r
+\r
+    case KEY_SECURE_BOOT_OPTION:\r
+      FreeMenu (&DirectoryMenu);\r
+      FreeMenu (&FsOptionMenu);\r
+      break;\r
+\r
+    case KEY_SECURE_BOOT_KEK_OPTION:\r
+    case KEY_SECURE_BOOT_DB_OPTION:\r
+    case KEY_SECURE_BOOT_DBX_OPTION:\r
+      //\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
+      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 {\r
+        LabelId = FORMID_ENROLL_KEK_FORM;\r
+      }\r
+\r
+      //\r
+      // Refresh selected file.\r
+      //\r
+      CleanUpPage (LabelId, Private);    \r
+      break;\r
+  \r
+    case SECUREBOOT_ADD_PK_FILE_FORM_ID:\r
+    case FORMID_ENROLL_KEK_FORM:\r
+    case SECUREBOOT_ENROLL_SIGNATURE_TO_DB:\r
+    case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX:\r
+      if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) {\r
+        Private->FeCurrentState = FileExplorerStateEnrollPkFile;\r
+      } else if (QuestionId == FORMID_ENROLL_KEK_FORM) {\r
+        Private->FeCurrentState = FileExplorerStateEnrollKekFile;\r
+      } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) {\r
+        Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb;\r
+      } else {\r
+        Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx;\r
+      }\r
+\r
+      Private->FeDisplayContext = FileExplorerDisplayUnknown;\r
+      CleanUpPage (FORM_FILE_EXPLORER_ID, Private);\r
+      UpdateFileExplorer (Private, 0);\r
+      break;\r
+\r
+    case KEY_SECURE_BOOT_DELETE_PK: \r
+        if (Value->u8) {\r
+          Status = DeletePlatformKey ();\r
+          *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\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
+    case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX:\r
+      UpdateDeletePage (\r
+        Private,\r
+        EFI_IMAGE_SECURITY_DATABASE1,\r
+        &gEfiImageSecurityDatabaseGuid,\r
+        LABEL_DBX_DELETE,\r
+        SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
+        OPTION_DEL_DBX_QUESTION_ID\r
+        );\r
+\r
+      break;\r
+\r
+    case KEY_VALUE_SAVE_AND_EXIT_KEK:\r
+      Status = EnrollKeyExchangeKey (Private);\r
+      break;\r
+\r
+    case KEY_VALUE_SAVE_AND_EXIT_DB:\r
+      Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE);\r
+      break;\r
+\r
+    case KEY_VALUE_SAVE_AND_EXIT_DBX:\r
+      Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1);\r
+      break;\r
+\r
+    default:\r
+      if (QuestionId >= FILE_OPTION_OFFSET) {\r
+        UpdateFileExplorer (Private, QuestionId);\r
+      } else 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_DEL_DBX_QUESTION_ID) &&\r
+                 (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) {\r
+        DeleteSignature (\r
+          Private,\r
+          EFI_IMAGE_SECURITY_DATABASE1,\r
+          &gEfiImageSecurityDatabaseGuid,\r
+          LABEL_DBX_DELETE,   \r
+          SECUREBOOT_DELETE_SIGNATURE_FROM_DBX,\r
+          OPTION_DEL_DBX_QUESTION_ID,\r
+          QuestionId - OPTION_DEL_DBX_QUESTION_ID\r
+          );\r
+      }\r
+      break;\r
+    }\r
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+    switch (QuestionId) {\r
+    case KEY_SECURE_BOOT_ENABLE:\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;      \r
+      break;  \r
+    case KEY_VALUE_SAVE_AND_EXIT_PK:\r
+      Status = EnrollPlatformKey (Private);\r
+      UnicodeSPrint (\r
+        PromptString,\r
+        sizeof (PromptString),\r
+        L"Only DER encoded certificate file (%s) is supported.",\r
+        mSupportX509Suffix\r
+        );\r
+      if (EFI_ERROR (Status)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"ERROR: Unsupported file type!",\r
+          PromptString,\r
+          NULL\r
+          );\r
+      } else {\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+      }        \r
+      break;\r
+\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
+      if (Private->FileContext->FHandle != NULL) {\r
+        CloseFile (Private->FileContext->FHandle);\r
+        Private->FileContext->FHandle = NULL;\r
+        Private->FileContext->FileName = NULL;\r
+      }\r
+   \r
+      if (Private->SignatureGUID != NULL) {\r
+        FreePool (Private->SignatureGUID);\r
+        Private->SignatureGUID = NULL;\r
+      }\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+      break;\r
+      \r
+    case KEY_SECURE_BOOT_MODE:\r
+      GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootEnable, NULL);\r
+      if (NULL != SecureBootEnable) {\r
+        Status = gRT->SetVariable (                          \r
+                        EFI_CUSTOM_MODE_NAME,\r
+                        &gEfiCustomModeEnableGuid,\r
+                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                        sizeof (UINT8),\r
+                        &Value->u8\r
+                        );\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
+        IfrNvData->SecureBootMode = Value->u8;\r
+      }        \r
+      break;\r
+\r
+    case KEY_SECURE_BOOT_KEK_GUID:\r
+    case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
+    case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
+      ASSERT (Private->SignatureGUID != NULL);\r
+      Status = StringToGuid (\r
+                 IfrNvData->SignatureGuid,\r
+                 StrLen (IfrNvData->SignatureGuid),\r
+                 Private->SignatureGUID\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
+      break;\r
+\r
+    case KEY_SECURE_BOOT_DELETE_PK:\r
+      if (Value->u8) {\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+      }\r
+      break;  \r
+    }\r
+  }\r
+  \r
+  if (!EFI_ERROR (Status)) {\r
+    BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
+    HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8*) IfrNvData, NULL);\r
+  }\r
+  FreePool (IfrNvData);\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function publish the SecureBoot configuration Form.\r
+\r
+  @param[in, out]  PrivateData   Points to SecureBoot configuration private data.\r
+\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
+**/\r
+EFI_STATUS\r
+InstallSecureBootConfigForm (\r
+  IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
+\r
+  DriverHandle = NULL;\r
+  ConfigAccess = &PrivateData->ConfigAccess;\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &DriverHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  &mSecureBootHiiVendorDevicePath,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  ConfigAccess,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  PrivateData->DriverHandle = DriverHandle;\r
+\r
+  //\r
+  // Publish the HII package list\r
+  //\r
+  HiiHandle = HiiAddPackages (\r
+                &gSecureBootConfigFormSetGuid,\r
+                DriverHandle,\r
+                SecureBootConfigDxeStrings,\r
+                SecureBootConfigBin,\r
+                NULL\r
+                );\r
+  if (HiiHandle == NULL) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           DriverHandle,\r
+           &gEfiDevicePathProtocolGuid,\r
+           &mSecureBootHiiVendorDevicePath,\r
+           &gEfiHiiConfigAccessProtocolGuid,\r
+           ConfigAccess,\r
+           NULL\r
+           );\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  PrivateData->HiiHandle = HiiHandle;\r
+\r
+  PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT));\r
+  PrivateData->MenuEntry   = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));\r
+  \r
+  if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) {\r
+    UninstallSecureBootConfigForm (PrivateData);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  PrivateData->FeCurrentState = FileExplorerStateInActive;\r
+  PrivateData->FeDisplayContext = FileExplorerDisplayUnknown;\r
+  \r
+  InitializeListHead (&FsOptionMenu.Head);\r
+  InitializeListHead (&DirectoryMenu.Head);\r
+\r
+  //\r
+  // Init OpCode Handle and Allocate space for creation of Buffer\r
+  //\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
+  This function removes SecureBoot configuration Form.\r
+\r
+  @param[in, out]  PrivateData   Points to SecureBoot configuration private data.\r
+\r
+**/\r
+VOID\r
+UninstallSecureBootConfigForm (\r
+  IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData\r
+  )\r
+{\r
+  //\r
+  // Uninstall HII package list\r
+  //\r
+  if (PrivateData->HiiHandle != NULL) {\r
+    HiiRemovePackages (PrivateData->HiiHandle);\r
+    PrivateData->HiiHandle = NULL;\r
+  }\r
+\r
+  //\r
+  // Uninstall HII Config Access Protocol\r
+  //\r
+  if (PrivateData->DriverHandle != NULL) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           PrivateData->DriverHandle,\r
+           &gEfiDevicePathProtocolGuid,\r
+           &mSecureBootHiiVendorDevicePath,\r
+           &gEfiHiiConfigAccessProtocolGuid,\r
+           &PrivateData->ConfigAccess,\r
+           NULL\r
+           );\r
+    PrivateData->DriverHandle = NULL;\r
+  }\r
+\r
+  if (PrivateData->SignatureGUID != NULL) {\r
+    FreePool (PrivateData->SignatureGUID);\r
+  }\r
+\r
+  if (PrivateData->MenuEntry != NULL) {\r
+    FreePool (PrivateData->MenuEntry);\r
+  }\r
+\r
+  if (PrivateData->FileContext != NULL) {\r
+    FreePool (PrivateData->FileContext);\r
+  }\r
+\r
+  FreePool (PrivateData);\r
+\r
+  FreeMenu (&DirectoryMenu);\r
+  FreeMenu (&FsOptionMenu);\r
+\r
+  if (mStartOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);\r
+  }\r
+\r
+  if (mEndOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (mEndOpCodeHandle);\r
+  }\r
+}\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigImpl.h b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigImpl.h
new file mode 100644 (file)
index 0000000..5a5ac12
--- /dev/null
@@ -0,0 +1,614 @@
+/** @file\r
+  The header file of HII Config Access protocol implementation of SecureBoot\r
+  configuration module.\r
+\r
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __SECUREBOOT_CONFIG_IMPL_H__\r
+#define __SECUREBOOT_CONFIG_IMPL_H__\r
+\r
+#include <Uefi.h>\r
+\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/DevicePathToText.h>\r
+#include <Protocol/DebugPort.h>\r
+#include <Protocol/LoadFile.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiHiiServicesLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/PlatformSecureLib.h>\r
+#include <Library/BaseCryptLib.h>\r
+#include <Guid/MdeModuleHii.h>\r
+#include <Guid/AuthenticatedVariableFormat.h>\r
+#include <Guid/FileSystemVolumeLabelInfo.h>\r
+#include <Guid/ImageAuthentication.h>\r
+#include <Guid/FileInfo.h>\r
+\r
+#include "SecureBootConfigNvData.h"\r
+\r
+//\r
+// Tool generated IFR binary data and String package data\r
+//\r
+extern  UINT8                      SecureBootConfigBin[];\r
+extern  UINT8                      SecureBootConfigDxeStrings[];\r
+\r
+//\r
+// Shared IFR form update data\r
+//\r
+extern  VOID                       *mStartOpCodeHandle;\r
+extern  VOID                       *mEndOpCodeHandle;\r
+extern  EFI_IFR_GUID_LABEL         *mStartLabel;\r
+extern  EFI_IFR_GUID_LABEL         *mEndLabel;\r
+\r
+#define MAX_CHAR              480\r
+#define TWO_BYTE_ENCODE       0x82\r
+\r
+//\r
+// SHA-1 digest size in bytes.\r
+//\r
+#define SHA1_DIGEST_SIZE    20\r
+//\r
+// SHA-256 digest size in bytes\r
+//\r
+#define SHA256_DIGEST_SIZE  32\r
+//\r
+// Set max digest size as SHA256 Output (32 bytes) by far\r
+//\r
+#define MAX_DIGEST_SIZE    SHA256_DIGEST_SIZE\r
+\r
+#define WIN_CERT_UEFI_RSA2048_SIZE               256\r
+\r
+//\r
+// Support hash types\r
+//\r
+#define HASHALG_SHA1                           0x00000000\r
+#define HASHALG_SHA224                         0x00000001\r
+#define HASHALG_SHA256                         0x00000002\r
+#define HASHALG_SHA384                         0x00000003\r
+#define HASHALG_SHA512                         0x00000004\r
+#define HASHALG_MAX                            0x00000005\r
+\r
+\r
+#define SECUREBOOT_MENU_OPTION_SIGNATURE   SIGNATURE_32 ('S', 'b', 'M', 'u')\r
+#define SECUREBOOT_MENU_ENTRY_SIGNATURE    SIGNATURE_32 ('S', 'b', 'M', 'r')\r
+\r
+typedef struct {\r
+  EFI_DEVICE_PATH_PROTOCOL  Header;\r
+  EFI_GUID                  Guid;\r
+  UINT8                     VendorDefinedData[1];\r
+} VENDOR_DEVICE_PATH_WITH_DATA;\r
+\r
+typedef struct {\r
+  EFI_DEVICE_PATH_PROTOCOL  Header;\r
+  UINT16                    NetworkProtocol;\r
+  UINT16                    LoginOption;\r
+  UINT64                    Lun;\r
+  UINT16                    TargetPortalGroupTag;\r
+  CHAR16                    TargetName[1];\r
+} ISCSI_DEVICE_PATH_WITH_NAME;\r
+\r
+typedef enum _FILE_EXPLORER_DISPLAY_CONTEXT {\r
+  FileExplorerDisplayFileSystem,\r
+  FileExplorerDisplayDirectory,\r
+  FileExplorerDisplayUnknown\r
+} FILE_EXPLORER_DISPLAY_CONTEXT;\r
+\r
+typedef enum _FILE_EXPLORER_STATE {\r
+  FileExplorerStateInActive                      = 0,\r
+  FileExplorerStateEnrollPkFile,\r
+  FileExplorerStateEnrollKekFile,\r
+  FileExplorerStateEnrollSignatureFileToDb,\r
+  FileExplorerStateEnrollSignatureFileToDbx,\r
+  FileExplorerStateUnknown\r
+} FILE_EXPLORER_STATE;\r
+\r
+typedef struct {\r
+  CHAR16  *Str;\r
+  UINTN   Len;\r
+  UINTN   Maxlen;\r
+} POOL_PRINT;\r
+\r
+typedef\r
+VOID\r
+(*DEV_PATH_FUNCTION) (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  );\r
+\r
+typedef struct {\r
+  UINT8             Type;\r
+  UINT8             SubType;\r
+  DEV_PATH_FUNCTION Function;\r
+} DEVICE_PATH_STRING_TABLE;\r
+\r
+typedef struct {\r
+  UINTN             Signature;\r
+  LIST_ENTRY        Head;\r
+  UINTN             MenuNumber;\r
+} SECUREBOOT_MENU_OPTION;\r
+\r
+extern  SECUREBOOT_MENU_OPTION     FsOptionMenu;\r
+extern  SECUREBOOT_MENU_OPTION     DirectoryMenu;\r
+\r
+typedef struct {\r
+  UINTN             Signature;\r
+  LIST_ENTRY        Link;\r
+  UINTN             OptionNumber;\r
+  UINT16            *DisplayString;\r
+  UINT16            *HelpString;\r
+  EFI_STRING_ID     DisplayStringToken;\r
+  EFI_STRING_ID     HelpStringToken;\r
+  VOID              *FileContext;\r
+} SECUREBOOT_MENU_ENTRY;\r
+\r
+typedef struct {\r
+  EFI_HANDLE                        Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+  EFI_FILE_HANDLE                   FHandle;\r
+  UINT16                            *FileName;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL      *Info;\r
+\r
+  BOOLEAN                           IsRoot;\r
+  BOOLEAN                           IsDir;\r
+  BOOLEAN                           IsRemovableMedia;\r
+  BOOLEAN                           IsLoadFile;\r
+  BOOLEAN                           IsBootLegacy;\r
+} SECUREBOOT_FILE_CONTEXT;\r
+\r
+\r
+//\r
+// We define another format of 5th directory entry: security directory\r
+//\r
+typedef struct {\r
+  UINT32               Offset;      // Offset of certificate\r
+  UINT32               SizeOfCert;  // size of certificate appended\r
+} EFI_IMAGE_SECURITY_DATA_DIRECTORY;\r
+\r
+typedef enum{\r
+  ImageType_IA32,\r
+  ImageType_X64\r
+} IMAGE_TYPE;\r
+\r
+///\r
+/// HII specific Vendor Device Path definition.\r
+///\r
+typedef struct {\r
+  VENDOR_DEVICE_PATH                VendorDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL          End;\r
+} HII_VENDOR_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  UINTN                             Signature;\r
+\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;\r
+  EFI_HII_HANDLE                    HiiHandle;\r
+  EFI_HANDLE                        DriverHandle;\r
+\r
+  FILE_EXPLORER_STATE               FeCurrentState;\r
+  FILE_EXPLORER_DISPLAY_CONTEXT     FeDisplayContext;\r
+\r
+  SECUREBOOT_MENU_ENTRY             *MenuEntry;\r
+  SECUREBOOT_FILE_CONTEXT           *FileContext;\r
+\r
+  EFI_GUID                          *SignatureGUID;\r
+} SECUREBOOT_CONFIG_PRIVATE_DATA;\r
+\r
+extern SECUREBOOT_CONFIG_PRIVATE_DATA      mSecureBootConfigPrivateDateTemplate;\r
+\r
+#define SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE     SIGNATURE_32 ('S', 'E', 'C', 'B')\r
+#define SECUREBOOT_CONFIG_PRIVATE_FROM_THIS(a)  CR (a, SECUREBOOT_CONFIG_PRIVATE_DATA, ConfigAccess, SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE)\r
+\r
+//\r
+// Cryptograhpic Key Information\r
+//\r
+#pragma pack(1)\r
+typedef struct _CPL_KEY_INFO {\r
+  UINT32        KeyLengthInBits;    // Key Length In Bits\r
+  UINT32        BlockSize;          // Operation Block Size in Bytes\r
+  UINT32        CipherBlockSize;    // Output Cipher Block Size in Bytes\r
+  UINT32        KeyType;            // Key Type\r
+  UINT32        CipherMode;         // Cipher Mode for Symmetric Algorithm\r
+  UINT32        Flags;              // Additional Key Property Flags\r
+} CPL_KEY_INFO;\r
+#pragma pack()\r
+\r
+\r
+/**\r
+  Retrieves the size, in bytes, of the context buffer required for hash operations.\r
+\r
+  @return  The size, in bytes, of the context buffer required for hash operations.\r
+\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *HASH_GET_CONTEXT_SIZE)(\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Initializes user-supplied memory pointed by HashContext as hash context for\r
+  subsequent use.\r
+\r
+  If HashContext is NULL, then ASSERT().\r
+\r
+  @param[in, out]  HashContext  Pointer to  Context being initialized.\r
+\r
+  @retval TRUE   HASH context initialization succeeded.\r
+  @retval FALSE  HASH context initialization failed.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_INIT)(\r
+  IN OUT  VOID  *HashContext\r
+  );\r
+\r
+\r
+/**\r
+  Performs digest on a data buffer of the specified length. This function can\r
+  be called multiple times to compute the digest of long or discontinuous data streams.\r
+\r
+  If HashContext is NULL, then ASSERT().\r
+\r
+  @param[in, out]  HashContext  Pointer to the MD5 context.\r
+  @param[in]       Data        Pointer to the buffer containing the data to be hashed.\r
+  @param[in]       DataLength  Length of Data buffer in bytes.\r
+\r
+  @retval TRUE   HASH data digest succeeded.\r
+  @retval FALSE  Invalid HASH context. After HashFinal function has been called, the\r
+                 HASH context cannot be reused.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_UPDATE)(\r
+  IN OUT  VOID        *HashContext,\r
+  IN      CONST VOID  *Data,\r
+  IN      UINTN       DataLength\r
+  );\r
+\r
+/**\r
+  Completes hash computation and retrieves the digest value into the specified\r
+  memory. After this function has been called, the context cannot be used again.\r
+\r
+  If HashContext is NULL, then ASSERT().\r
+  If HashValue is NULL, then ASSERT().\r
+\r
+  @param[in, out]  HashContext  Pointer to the MD5 context\r
+  @param[out]      HashValue   Pointer to a buffer that receives the HASH digest\r
+                               value (16 bytes).\r
+\r
+  @retval TRUE   HASH digest computation succeeded.\r
+  @retval FALSE  HASH digest computation failed.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *HASH_FINAL)(\r
+  IN OUT  VOID   *HashContext,\r
+  OUT     UINT8  *HashValue\r
+  );\r
+\r
+//\r
+// Hash Algorithm Table\r
+//\r
+typedef struct {\r
+  CHAR16                   *Name;           ///< Name for Hash Algorithm\r
+  UINTN                    DigestLength;    ///< Digest Length\r
+  UINT8                    *OidValue;       ///< Hash Algorithm OID ASN.1 Value \r
+  UINTN                    OidLength;       ///< Length of Hash OID Value\r
+  HASH_GET_CONTEXT_SIZE    GetContextSize;  ///< Pointer to Hash GetContentSize function\r
+  HASH_INIT                HashInit;        ///< Pointer to Hash Init function\r
+  HASH_UPDATE              HashUpdate;      ///< Pointer to Hash Update function\r
+  HASH_FINAL               HashFinal;       ///< Pointer to Hash Final function\r
+} HASH_TABLE;\r
+\r
+typedef struct {\r
+  WIN_CERTIFICATE Hdr;\r
+  UINT8           CertData[1];\r
+} WIN_CERTIFICATE_EFI_PKCS;\r
+\r
+\r
+/**\r
+  This function publish the SecureBoot configuration Form.\r
+\r
+  @param[in, out]  PrivateData   Points to SecureBoot configuration private data.\r
+\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
+**/\r
+EFI_STATUS\r
+InstallSecureBootConfigForm (\r
+  IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData\r
+  );\r
+\r
+\r
+/**\r
+  This function removes SecureBoot configuration Form.\r
+\r
+  @param[in, out]  PrivateData   Points to SecureBoot configuration private data.\r
+\r
+**/\r
+VOID\r
+UninstallSecureBootConfigForm (\r
+  IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData\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
+\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
+\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]  Action             Specifies the type of action taken by the browser.\r
+  @param[in]  QuestionId         A unique value which is sent to the original\r
+                                 exporting driver so that it can identify the type\r
+                                 of data to expect.\r
+  @param[in]  Type               The type of value for the question.\r
+  @param[in]  Value              A pointer to the data being sent to the original\r
+                                 exporting driver.\r
+  @param[out] ActionRequest      On return, points to the action requested by the\r
+                                 callback function.\r
+\r
+  @retval EFI_SUCCESS            The callback successfully handled the action.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
+                                 variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
+                                 callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SecureBootCallback (\r
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,\r
+  IN     EFI_BROWSER_ACTION                    Action,\r
+  IN     EFI_QUESTION_ID                       QuestionId,\r
+  IN     UINT8                                 Type,\r
+  IN     EFI_IFR_TYPE_VALUE                    *Value,\r
+     OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
+  );\r
+\r
+\r
+/**\r
+  This function converts an input device structure to a Unicode string.\r
+\r
+  @param[in] DevPath                  A pointer to the device path structure.\r
+\r
+  @return A new allocated Unicode string that represents the device path.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+DevicePathToStr (\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  );\r
+\r
+\r
+/**\r
+  Clean up the dynamic opcode at label and form specified by both LabelId. \r
+\r
+  @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.\r
+  @param[in] PrivateData     Module private data.\r
+\r
+**/\r
+VOID\r
+CleanUpPage (\r
+  IN UINT16                           LabelId,\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData\r
+  );\r
+\r
+\r
+/**\r
+  Update the file explorer page with the refreshed file system.\r
+\r
+  @param[in] PrivateData     Module private data.\r
+  @param[in] KeyValue        Key value to identify the type of data to expect.\r
+\r
+  @retval  TRUE           Inform the caller to create a callback packet to exit file explorer.\r
+  @retval  FALSE          Indicate that there is no need to exit file explorer.\r
+\r
+**/\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,\r
+  IN UINT16                           KeyValue\r
+  );\r
+\r
+\r
+/**\r
+  Free resources allocated in Allocate Rountine.\r
+\r
+  @param[in, out]  MenuOption        Menu to be freed\r
+  \r
+**/\r
+VOID\r
+FreeMenu (\r
+  IN OUT SECUREBOOT_MENU_OPTION        *MenuOption\r
+  );\r
+\r
+\r
+/**\r
+  Read file content into BufferPtr, the size of the allocate buffer \r
+  is *FileSize plus AddtionAllocateSize.\r
+\r
+  @param[in]       FileHandle            The file to be read.\r
+  @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.\r
+  @param[out]      FileSize              Size of input file\r
+  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated. \r
+                                         In case the buffer need to contain others besides the file content.\r
+  \r
+  @retval   EFI_SUCCESS                  The file was read into the buffer.\r
+  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.\r
+  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.\r
+  @retval   others                       Unexpected error.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadFileContent (\r
+  IN      EFI_FILE_HANDLE           FileHandle,\r
+  IN OUT  VOID                      **BufferPtr,\r
+     OUT  UINTN                     *FileSize,\r
+  IN      UINTN                     AddtionAllocateSize\r
+  );\r
+\r
+\r
+/**\r
+  Close an open file handle.\r
+\r
+  @param[in] FileHandle           The file handle to close.\r
+  \r
+**/\r
+VOID\r
+CloseFile (\r
+  IN EFI_FILE_HANDLE   FileHandle\r
+  );\r
+\r
+\r
+/**\r
+  Converts a nonnegative integer to an octet string of a specified length.\r
+\r
+  @param[in]   Integer          Pointer to the nonnegative integer to be converted\r
+  @param[in]   IntSizeInWords   Length of integer buffer in words\r
+  @param[out]  OctetString      Converted octet string of the specified length \r
+  @param[in]   OSSizeInBytes    Intended length of resulting octet string in bytes\r
+\r
+Returns:\r
+\r
+  @retval   EFI_SUCCESS            Data conversion successfully\r
+  @retval   EFI_BUFFER_TOOL_SMALL  Buffer is too small for output string\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Int2OctStr (\r
+  IN     CONST UINTN       *Integer,\r
+  IN     UINTN             IntSizeInWords,\r
+     OUT UINT8             *OctetString,\r
+  IN     UINTN             OSSizeInBytes\r
+  );\r
+\r
+\r
+/**\r
+  Convert a String to Guid Value.\r
+\r
+  @param[in]   Str        Specifies the String to be converted.\r
+  @param[in]   StrLen     Number of Unicode Characters of String (exclusive \0)\r
+  @param[out]  Guid       Return the result Guid value.\r
+\r
+  @retval    EFI_SUCCESS           The operation is finished successfully.\r
+  @retval    EFI_NOT_FOUND         Invalid string.\r
+\r
+**/\r
+EFI_STATUS\r
+StringToGuid (\r
+  IN   CHAR16           *Str, \r
+  IN   UINTN            StrLen, \r
+  OUT  EFI_GUID         *Guid\r
+  );\r
+\r
+\r
+/**\r
+  Worker function that prints an EFI_GUID into specified Buffer.\r
+\r
+  @param[in]     Guid          Pointer to GUID to print.\r
+  @param[in]     Buffer        Buffer to print Guid into.\r
+  @param[in]     BufferSize    Size of Buffer.\r
+  \r
+  @retval    Number of characters printed.\r
+\r
+**/\r
+UINTN\r
+GuidToString (\r
+  IN  EFI_GUID  *Guid,\r
+  IN  CHAR16    *Buffer,\r
+  IN  UINTN     BufferSize\r
+  );\r
+\r
+#endif\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigMisc.c b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigMisc.c
new file mode 100644 (file)
index 0000000..13c7c27
--- /dev/null
@@ -0,0 +1,334 @@
+/** @file\r
+  Helper functions for SecureBoot configuration module.\r
+\r
+Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SecureBootConfigImpl.h"\r
+\r
+/**\r
+  Read file content into BufferPtr, the size of the allocate buffer \r
+  is *FileSize plus AddtionAllocateSize.\r
+\r
+  @param[in]       FileHandle            The file to be read.\r
+  @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.\r
+  @param[out]      FileSize              Size of input file\r
+  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated. \r
+                                         In case the buffer need to contain others besides the file content.\r
+  \r
+  @retval   EFI_SUCCESS                  The file was read into the buffer.\r
+  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.\r
+  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.\r
+  @retval   others                       Unexpected error.\r
+\r
+**/\r
+EFI_STATUS\r
+ReadFileContent (\r
+  IN      EFI_FILE_HANDLE           FileHandle,\r
+  IN OUT  VOID                      **BufferPtr,\r
+     OUT  UINTN                     *FileSize,\r
+  IN      UINTN                     AddtionAllocateSize\r
+  )\r
+\r
+{\r
+  UINTN      BufferSize;\r
+  UINT64     SourceFileSize;\r
+  VOID       *Buffer;\r
+  EFI_STATUS Status;\r
+\r
+  if ((FileHandle == NULL) || (FileSize == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Buffer = NULL;\r
+\r
+  //\r
+  // Get the file size\r
+  //\r
+  Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  \r
+  Status = FileHandle->SetPosition (FileHandle, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;\r
+  Buffer =  AllocateZeroPool(BufferSize);\r
+  if (Buffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  BufferSize = (UINTN) SourceFileSize;\r
+  *FileSize  = BufferSize;\r
+\r
+  Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);\r
+  if (EFI_ERROR (Status) || BufferSize != *FileSize) {\r
+    FreePool (Buffer);\r
+    Buffer = NULL;\r
+    Status  = EFI_BAD_BUFFER_SIZE;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+  \r
+  *BufferPtr = Buffer;\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Close an open file handle.\r
+\r
+  @param[in] FileHandle           The file handle to close.\r
+  \r
+**/\r
+VOID\r
+CloseFile (\r
+  IN EFI_FILE_HANDLE   FileHandle\r
+  )\r
+{\r
+  if (FileHandle != NULL) {\r
+    FileHandle->Close (FileHandle);  \r
+  }\r
+}\r
+\r
+/**\r
+  Convert a nonnegative integer to an octet string of a specified length.\r
+\r
+  @param[in]   Integer          Pointer to the nonnegative integer to be converted\r
+  @param[in]   IntSizeInWords   Length of integer buffer in words\r
+  @param[out]  OctetString      Converted octet string of the specified length \r
+  @param[in]   OSSizeInBytes    Intended length of resulting octet string in bytes\r
+\r
+Returns:\r
+\r
+  @retval   EFI_SUCCESS            Data conversion successfully\r
+  @retval   EFI_BUFFER_TOOL_SMALL  Buffer is too small for output string\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Int2OctStr (\r
+  IN     CONST UINTN                *Integer,\r
+  IN     UINTN                      IntSizeInWords,\r
+     OUT UINT8                      *OctetString,\r
+  IN     UINTN                      OSSizeInBytes\r
+  )\r
+{\r
+  CONST UINT8  *Ptr1;\r
+  UINT8        *Ptr2;\r
+\r
+  for (Ptr1 = (CONST UINT8 *)Integer, Ptr2 = OctetString + OSSizeInBytes - 1;\r
+       Ptr1 < (UINT8 *)(Integer + IntSizeInWords) && Ptr2 >= OctetString;\r
+       Ptr1++, Ptr2--) {\r
+    *Ptr2 = *Ptr1;\r
+  }\r
+       \r
+  for (; Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords) && *Ptr1 == 0; Ptr1++);\r
+  \r
+  if (Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords)) {\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+  \r
+  if (Ptr2 >= OctetString) {\r
+    ZeroMem (OctetString, Ptr2 - OctetString + 1);\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Convert a String to Guid Value.\r
+\r
+  @param[in]   Str        Specifies the String to be converted.\r
+  @param[in]   StrLen     Number of Unicode Characters of String (exclusive \0)\r
+  @param[out]  Guid       Return the result Guid value.\r
+\r
+  @retval    EFI_SUCCESS           The operation is finished successfully.\r
+  @retval    EFI_NOT_FOUND         Invalid string.\r
+\r
+**/\r
+EFI_STATUS\r
+StringToGuid (\r
+  IN   CHAR16           *Str, \r
+  IN   UINTN            StrLen, \r
+  OUT  EFI_GUID         *Guid\r
+  )\r
+{\r
+  CHAR16             *PtrBuffer;\r
+  CHAR16             *PtrPosition;\r
+  UINT16             *Buffer;\r
+  UINTN              Data;\r
+  UINTN              Index;\r
+  UINT16             Digits[3];\r
+\r
+  Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1));\r
+  if (Buffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  StrCpy (Buffer, Str);\r
+\r
+  //\r
+  // Data1\r
+  //\r
+  PtrBuffer       = Buffer;\r
+  PtrPosition     = PtrBuffer; \r
+  while (*PtrBuffer != L'\0') {\r
+    if (*PtrBuffer == L'-') {\r
+      break;\r
+    }\r
+    PtrBuffer++;\r
+  }\r
+  if (*PtrBuffer == L'\0') {\r
+    FreePool (Buffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  *PtrBuffer      = L'\0';\r
+  Data            = StrHexToUintn (PtrPosition);\r
+  Guid->Data1     = (UINT32)Data;\r
+\r
+  //\r
+  // Data2\r
+  //\r
+  PtrBuffer++;\r
+  PtrPosition     = PtrBuffer;\r
+  while (*PtrBuffer != L'\0') {\r
+    if (*PtrBuffer == L'-') {\r
+      break;\r
+    }\r
+    PtrBuffer++;\r
+  }\r
+  if (*PtrBuffer == L'\0') {\r
+    FreePool (Buffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  *PtrBuffer      = L'\0';\r
+  Data            = StrHexToUintn (PtrPosition);\r
+  Guid->Data2     = (UINT16)Data;\r
+\r
+  //\r
+  // Data3\r
+  //\r
+  PtrBuffer++;\r
+  PtrPosition     = PtrBuffer;\r
+  while (*PtrBuffer != L'\0') {\r
+    if (*PtrBuffer == L'-') {\r
+      break;\r
+    }\r
+    PtrBuffer++;\r
+  }\r
+  if (*PtrBuffer == L'\0') {\r
+    FreePool (Buffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  *PtrBuffer      = L'\0';\r
+  Data            = StrHexToUintn (PtrPosition);\r
+  Guid->Data3     = (UINT16)Data;\r
+\r
+  //\r
+  // Data4[0..1]\r
+  //\r
+  for ( Index = 0 ; Index < 2 ; Index++) {\r
+    PtrBuffer++;\r
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {\r
+      FreePool (Buffer);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+    Digits[0]     = *PtrBuffer;\r
+    PtrBuffer++;\r
+    Digits[1]     = *PtrBuffer;\r
+    Digits[2]     = L'\0';\r
+    Data          = StrHexToUintn (Digits);\r
+    Guid->Data4[Index] = (UINT8)Data;\r
+  }\r
+\r
+  //\r
+  // skip the '-'\r
+  //\r
+  PtrBuffer++;\r
+  if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Data4[2..7]\r
+  //\r
+  for ( ; Index < 8; Index++) {\r
+    PtrBuffer++;\r
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {\r
+      FreePool (Buffer);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+    Digits[0]     = *PtrBuffer;\r
+    PtrBuffer++;\r
+    Digits[1]     = *PtrBuffer;\r
+    Digits[2]     = L'\0';\r
+    Data          = StrHexToUintn (Digits);\r
+    Guid->Data4[Index] = (UINT8)Data;\r
+  }\r
+\r
+  FreePool (Buffer);\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Worker function that prints an EFI_GUID into specified Buffer.\r
+\r
+  @param[in]     Guid          Pointer to GUID to print.\r
+  @param[in]     Buffer        Buffer to print Guid into.\r
+  @param[in]     BufferSize    Size of Buffer.\r
+  \r
+  @retval    Number of characters printed.\r
+\r
+**/\r
+UINTN\r
+GuidToString (\r
+  IN  EFI_GUID  *Guid,\r
+  IN  CHAR16    *Buffer,\r
+  IN  UINTN     BufferSize\r
+  )\r
+{\r
+  UINTN Size;\r
+\r
+  Size = UnicodeSPrint (\r
+            Buffer,\r
+            BufferSize, \r
+            L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
+            (UINTN)Guid->Data1,                    \r
+            (UINTN)Guid->Data2,\r
+            (UINTN)Guid->Data3,\r
+            (UINTN)Guid->Data4[0],\r
+            (UINTN)Guid->Data4[1],\r
+            (UINTN)Guid->Data4[2],\r
+            (UINTN)Guid->Data4[3],\r
+            (UINTN)Guid->Data4[4],\r
+            (UINTN)Guid->Data4[5],\r
+            (UINTN)Guid->Data4[6],\r
+            (UINTN)Guid->Data4[7]\r
+            );\r
+\r
+  //\r
+  // SPrint will null terminate the string. The -1 skips the null\r
+  //\r
+  return Size - 1;\r
+}\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigNvData.h b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigNvData.h
new file mode 100644 (file)
index 0000000..6015dd6
--- /dev/null
@@ -0,0 +1,118 @@
+/** @file\r
+  Header file for NV data structure definition.\r
+\r
+Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution.  The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __SECUREBOOT_CONFIG_NV_DATA_H__\r
+#define __SECUREBOOT_CONFIG_NV_DATA_H__\r
+\r
+#include <Guid/HiiPlatformSetupFormset.h>\r
+#include <Guid/SecureBootConfigHii.h>\r
+\r
+//\r
+// Used by VFR for form or button identification\r
+//\r
+#define SECUREBOOT_CONFIGURATION_VARSTORE_ID  0x0001\r
+#define SECUREBOOT_CONFIGURATION_FORM_ID      0x01\r
+#define FORMID_SECURE_BOOT_OPTION_FORM        0x02\r
+#define FORMID_SECURE_BOOT_PK_OPTION_FORM     0x03\r
+#define FORMID_SECURE_BOOT_KEK_OPTION_FORM    0x04\r
+#define FORMID_SECURE_BOOT_DB_OPTION_FORM     0x05\r
+#define FORMID_SECURE_BOOT_DBX_OPTION_FORM    0x06\r
+#define FORMID_ENROLL_PK_FORM                 0x07\r
+#define SECUREBOOT_ADD_PK_FILE_FORM_ID        0x08\r
+#define FORMID_ENROLL_KEK_FORM                0x09\r
+#define FORMID_DELETE_KEK_FORM                0x0a\r
+#define SECUREBOOT_ENROLL_SIGNATURE_TO_DB     0x0b\r
+#define SECUREBOOT_DELETE_SIGNATURE_FROM_DB   0x0c\r
+#define SECUREBOOT_ENROLL_SIGNATURE_TO_DBX    0x0d\r
+#define SECUREBOOT_DELETE_SIGNATURE_FROM_DBX  0x0e\r
+#define FORM_FILE_EXPLORER_ID                 0x0f\r
+#define FORM_FILE_EXPLORER_ID_PK              0x10\r
+#define FORM_FILE_EXPLORER_ID_KEK             0x11\r
+#define FORM_FILE_EXPLORER_ID_DB              0x12\r
+#define FORM_FILE_EXPLORER_ID_DBX             0x13\r
+\r
+#define SECURE_BOOT_MODE_CUSTOM               0x01\r
+#define SECURE_BOOT_MODE_STANDARD             0x00\r
+\r
+#define KEY_SECURE_BOOT_ENABLE                0x1000\r
+#define KEY_SECURE_BOOT_MODE                  0x1001\r
+#define KEY_VALUE_SAVE_AND_EXIT_DB            0x1002\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DB         0x1003\r
+#define KEY_VALUE_SAVE_AND_EXIT_PK            0x1004\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_PK         0x1005\r
+#define KEY_VALUE_SAVE_AND_EXIT_KEK           0x1008\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_KEK        0x1009\r
+#define KEY_VALUE_SAVE_AND_EXIT_DBX           0x100a\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DBX        0x100b\r
+\r
+#define KEY_SECURE_BOOT_OPTION                0x1100\r
+#define KEY_SECURE_BOOT_PK_OPTION             0x1101\r
+#define KEY_SECURE_BOOT_KEK_OPTION            0x1102\r
+#define KEY_SECURE_BOOT_DB_OPTION             0x1103\r
+#define KEY_SECURE_BOOT_DBX_OPTION            0x1104\r
+#define KEY_SECURE_BOOT_DELETE_PK             0x1105\r
+#define KEY_ENROLL_PK                         0x1106\r
+#define KEY_ENROLL_KEK                        0x1107\r
+#define KEY_DELETE_KEK                        0x1108\r
+#define KEY_SECURE_BOOT_KEK_GUID              0x110a\r
+#define KEY_SECURE_BOOT_SIGNATURE_GUID_DB     0x110b\r
+#define KEY_SECURE_BOOT_SIGNATURE_GUID_DBX    0x110c\r
+\r
+#define LABEL_KEK_DELETE                      0x1200\r
+#define LABEL_DB_DELETE                       0x1201\r
+#define LABEL_DBX_DELETE                      0x1202\r
+#define LABEL_END                             0xffff\r
+\r
+#define SECURE_BOOT_MAX_ATTEMPTS_NUM          255\r
+\r
+#define CONFIG_OPTION_OFFSET                  0x2000\r
+\r
+#define OPTION_CONFIG_QUESTION_ID             0x2000\r
+#define OPTION_CONFIG_RANGE                   0x1000\r
+\r
+//\r
+// Question ID 0x2000 ~ 0x2FFF is for KEK\r
+//\r
+#define OPTION_DEL_KEK_QUESTION_ID            0x2000\r
+//\r
+// Question ID 0x3000 ~ 0x3FFF is for DB\r
+//\r
+#define OPTION_DEL_DB_QUESTION_ID             0x3000\r
+//\r
+// Question ID 0x4000 ~ 0x4FFF is for DBX\r
+//\r
+#define OPTION_DEL_DBX_QUESTION_ID            0x4000 \r
+\r
+\r
+#define FILE_OPTION_OFFSET                    0x8000\r
+#define FILE_OPTION_MASK                      0x7FFF\r
+\r
+#define SECURE_BOOT_GUID_SIZE                 36\r
+#define SECURE_BOOT_GUID_STORAGE_SIZE         37\r
+\r
+\r
+//\r
+// Nv Data structure referenced by IFR\r
+//\r
+typedef struct {\r
+  BOOLEAN SecureBootState; //Secure Boot Disable/Enable;\r
+  BOOLEAN HideSecureBoot;  //Hiden Attempt Secure Boot\r
+  CHAR16  SignatureGuid[SECURE_BOOT_GUID_STORAGE_SIZE];\r
+  BOOLEAN PhysicalPresent; //If a Physical Present User;\r
+  UINT8   SecureBootMode;  //Secure Boot Mode: Standard Or Custom\r
+  BOOLEAN DeletePk; \r
+  BOOLEAN HasPk;           //If Pk is existed it is true;\r
+} SECUREBOOT_CONFIGURATION;\r
+\r
+#endif\r
diff --git a/OvmfPkg/SecureBootConfigDxe/SecureBootConfigStrings.uni b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigStrings.uni
new file mode 100644 (file)
index 0000000..ed4db13
Binary files /dev/null and b/OvmfPkg/SecureBootConfigDxe/SecureBootConfigStrings.uni differ