]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1. Remove “Force clear PK” feature in AuthVarialbe driver.
authorsfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 27 Mar 2012 08:17:23 +0000 (08:17 +0000)
committersfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 27 Mar 2012 08:17:23 +0000 (08:17 +0000)
2. Update API ForceClearPK() to UserPhysicalPresent() in PlatformSecureLib.
2. Update SecureBootConfigDxe driver and AuthVariable driver to support Custom Secure Boot Mode feature.
3. Fix some bugs in AuthVariable driver.

Signed-off-by: sfu5
Reviewed-by: tye
Reviewed-by: gdong1
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13144 6f19259b-4bc3-4df7-8a09-765794883524

19 files changed:
SecurityPkg/Include/Guid/AuthenticatedVariableFormat.h
SecurityPkg/Include/Library/PlatformSecureLib.h
SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.c
SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
SecurityPkg/SecurityPkg.dec
SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDevicePath.c [new file with mode: 0644]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c [new file with mode: 0644]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigMisc.c [new file with mode: 0644]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni

index 7ff469779c05a070ad84b779e1a9e6ecb3891f55..7e543ee9116cdd1e735627be0aa1cb125f3ca517 100644 (file)
@@ -4,7 +4,7 @@
   AuthenticatedVariableFormat.h defines variable data headers \r
   and variable storage region headers.\r
 \r
   AuthenticatedVariableFormat.h defines variable data headers \r
   and variable storage region headers.\r
 \r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 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
 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
@@ -35,6 +35,20 @@ extern EFI_GUID gEfiSecureBootEnableDisableGuid;
 #define SECURE_BOOT_ENABLE               1\r
 #define SECURE_BOOT_DISABLE              0\r
 \r
 #define SECURE_BOOT_ENABLE               1\r
 #define SECURE_BOOT_DISABLE              0\r
 \r
+extern EFI_GUID gEfiCustomModeEnableGuid;\r
+\r
+///\r
+///  "CustomMode" variable for two Secure Boot modes feature: "Custom" and "Standard".\r
+///  Standard Secure Boot mode is the default mode as UEFI Spec's description.\r
+///  Custom Secure Boot mode allows for more flexibility as specified in the following:\r
+///    Can enroll or delete PK without existing PK's private key.\r
+///    Can enroll or delete KEK without existing PK's private key.\r
+///    Can enroll or delete signature from DB/DBX without KEK's private key.\r
+///\r
+#define EFI_CUSTOM_MODE_NAME          L"CustomMode"\r
+#define CUSTOM_SECURE_BOOT_MODE       1\r
+#define STANDARD_SECURE_BOOT_MODE     0\r
+\r
 ///\r
 /// Alignment of variable name and data, according to the architecture:\r
 /// * For IA-32 and Intel(R) 64 architectures: 1.\r
 ///\r
 /// Alignment of variable name and data, according to the architecture:\r
 /// * For IA-32 and Intel(R) 64 architectures: 1.\r
index c544719ba21ec18628c87a522e59f51f51a81e3e..6a4cb147a6bce836016dd26022e48790b05dbc55 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 /** @file\r
-  Provides a secure platform-specific method to clear PK(Platform Key).\r
+  Provides a secure platform-specific method to detect physically present user.\r
 \r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -18,25 +18,25 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 /**\r
 \r
 \r
 /**\r
 \r
-  This function detects whether a secure platform-specific method to clear PK(Platform Key)\r
-  is configured by platform owner. This method is provided for users force to clear PK \r
-  in case incorrect enrollment mis-haps.\r
-  \r
-  UEFI231 spec chapter 27.5.2 stipulates: The platform key may also be cleared using \r
-  a secure platform-specific method. In  this case, the global variable SetupMode \r
-  must also be updated to 1.\r
+  This function provides a platform-specific method to detect whether the platform\r
+  is operating by a physically present user. \r
+\r
+  Programmatic changing of platform security policy (such as disable Secure Boot,\r
+  or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during\r
+  Boot Services or after exiting EFI Boot Services. Only a physically present user\r
+  is allowed to perform these operations.\r
 \r
   NOTE THAT: This function cannot depend on any EFI Variable Service since they are\r
   not available when this function is called in AuthenticateVariable driver.\r
   \r
 \r
   NOTE THAT: This function cannot depend on any EFI Variable Service since they are\r
   not available when this function is called in AuthenticateVariable driver.\r
   \r
-  @retval  TRUE       The Platform owner wants to force clear PK.\r
-  @retval  FALSE      The Platform owner doesn't want to force clear PK. \r
+  @retval  TRUE       The platform is operated by a physically present user.\r
+  @retval  FALSE      The platform is NOT operated by a physically present user.\r
 \r
 **/\r
 BOOLEAN\r
 EFIAPI\r
 \r
 **/\r
 BOOLEAN\r
 EFIAPI\r
-ForceClearPK (\r
+UserPhysicalPresent (\r
   VOID\r
   );\r
 \r
   VOID\r
   );\r
 \r
-#endif
\ No newline at end of file
+#endif\r
index f085d62b7795facd5c3f3d060b1f6dcfa7201f56..cfce97e2844d34c7051325974a7e0b063ae71c24 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 /** @file\r
-  Provides a secure platform-specific method to clear PK(Platform Key).\r
+  Provides a secure platform-specific method to detect physically present user.\r
 \r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -14,24 +14,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 /**\r
 \r
 \r
 /**\r
 \r
-  This function detects whether a secure platform-specific method to clear PK(Platform Key)\r
-  is configured by platform owner. This method is provided for users force to clear PK \r
-  in case incorrect enrollment mis-haps.\r
-  \r
-  UEFI231 spec chapter 27.5.2 stipulates: The platform key may also be cleared using \r
-  a secure platform-specific method. In  this case, the global variable SetupMode \r
-  must also be updated to 1.\r
-  \r
+  This function provides a platform-specific method to detect whether the platform\r
+  is operating by a physically present user. \r
+\r
+  Programmatic changing of platform security policy (such as disable Secure Boot,\r
+  or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during\r
+  Boot Services or after exiting EFI Boot Services. Only a physically present user\r
+  is allowed to perform these operations.\r
+\r
   NOTE THAT: This function cannot depend on any EFI Variable Service since they are\r
   not available when this function is called in AuthenticateVariable driver.\r
   NOTE THAT: This function cannot depend on any EFI Variable Service since they are\r
   not available when this function is called in AuthenticateVariable driver.\r
-\r
-  @retval  TRUE       The Platform owner wants to force clear PK.\r
-  @retval  FALSE      The Platform owner doesn't want to force clear PK. \r
+  \r
+  @retval  TRUE       The platform is operated by a physically present user.\r
+  @retval  FALSE      The platform is NOT operated by a physically present user.\r
 \r
 **/\r
 BOOLEAN\r
 EFIAPI\r
 \r
 **/\r
 BOOLEAN\r
 EFIAPI\r
-ForceClearPK (\r
+UserPhysicalPresent (\r
   VOID\r
   )\r
 {\r
   VOID\r
   )\r
 {\r
index dc119f2b1ca841de2c824049d7a1f7311ee0f222..ce0b2cebcf78c1ad9bbca260236c9531a1044200 100644 (file)
@@ -1,5 +1,5 @@
 ## @file\r
 ## @file\r
-#  Provides a secure platform-specific method to clear PK(Platform Key).\r
+#  Provides a secure platform-specific method to detect physically present user.\r
 #\r
 # Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 #\r
 # Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
index f9382788fccefed997b34d275da7ef52006757ab..e5471778ee21a6282139be8753732da98d7900c4 100644 (file)
@@ -2,7 +2,7 @@
 #  This package includes the security drivers, defintions(including PPIs/PROTOCOLs/GUIDs  \r
 #  and library classes) and libraries instances.\r
 #\r
 #  This package includes the security drivers, defintions(including PPIs/PROTOCOLs/GUIDs  \r
 #  and library classes) and libraries instances.\r
 #\r
-# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials are licensed and made available under\r
 # the terms and conditions of the BSD License which accompanies this distribution.\r
 # The full text of the license may be found at\r
 # This program and the accompanying materials are licensed and made available under\r
 # the terms and conditions of the BSD License which accompanies this distribution.\r
 # The full text of the license may be found at\r
@@ -37,6 +37,9 @@
 \r
   #  Include/Guid/AuthenticatedVariableFormat.h\r
   gEfiSecureBootEnableDisableGuid = { 0xf0a30bc7, 0xaf08, 0x4556, { 0x99, 0xc4, 0x0, 0x10, 0x9, 0xc9, 0x3a, 0x44 } }\r
 \r
   #  Include/Guid/AuthenticatedVariableFormat.h\r
   gEfiSecureBootEnableDisableGuid = { 0xf0a30bc7, 0xaf08, 0x4556, { 0x99, 0xc4, 0x0, 0x10, 0x9, 0xc9, 0x3a, 0x44 } }\r
+\r
+  #  Include/Guid/AuthenticatedVariableFormat.h\r
+  gEfiCustomModeEnableGuid           = { 0xc076ec0c, 0x7028, 0x4399, { 0xa0, 0x72, 0x71, 0xee, 0x5c, 0x44, 0x8b, 0x9f } }\r
   \r
   ## Include/Guid/TcgEventHob.h\r
   gTcgEventEntryHobGuid              = { 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 }}\r
   \r
   ## Include/Guid/TcgEventHob.h\r
   gTcgEventEntryHobGuid              = { 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f, 0x50 }}\r
index f7a9888ce1be840643f85b70e90cfd269185132b..4036885570a04c737fca4273ceb109c3361f10c7 100644 (file)
@@ -2,7 +2,7 @@
   Implement authentication services for the authenticated variable\r
   service in UEFI2.2.\r
 \r
   Implement authentication services for the authenticated variable\r
   service in UEFI2.2.\r
 \r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 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
 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
@@ -65,6 +65,53 @@ EFI_SIGNATURE_ITEM mSupportSigItem[] = {
   {EFI_CERT_SHA512_GUID,          0,               64           }\r
 };\r
 \r
   {EFI_CERT_SHA512_GUID,          0,               64           }\r
 };\r
 \r
+/**\r
+  Determine whether this operation needs a physical present user.\r
+\r
+  @param[in]      VariableName            Name of the Variable.\r
+  @param[in]      VendorGuid              GUID of the Variable.\r
+\r
+  @retval TRUE      This variable is protected, only a physical present user could set this variable.\r
+  @retval FALSE     This variable is not protected.\r
+  \r
+**/\r
+BOOLEAN\r
+NeedPhysicallyPresent(\r
+  IN     CHAR16         *VariableName,\r
+  IN     EFI_GUID       *VendorGuid\r
+  )\r
+{\r
+  if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))\r
+    || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {\r
+    return TRUE;\r
+  }\r
+  \r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Determine whether the platform is operating in Custom Secure Boot mode.\r
+\r
+  @retval TRUE           The platform is operating in Custom mode.\r
+  @retval FALSE          The platform is operating in Standard mode.\r
+\r
+**/\r
+BOOLEAN\r
+InCustomMode (\r
+  VOID\r
+  )\r
+{\r
+  VARIABLE_POINTER_TRACK  Variable;\r
+\r
+  FindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+  if (Variable.CurrPtr != NULL && *(GetVariableDataPtr (Variable.CurrPtr)) == CUSTOM_SECURE_BOOT_MODE) {\r
+    return TRUE;\r
+  }\r
+  \r
+  return FALSE;\r
+}\r
+\r
+\r
 /**\r
   Internal function to delete a Variable given its name and GUID, no authentication\r
   required.\r
 /**\r
   Internal function to delete a Variable given its name and GUID, no authentication\r
   required.\r
@@ -85,7 +132,7 @@ DeleteVariable (
   EFI_STATUS              Status;\r
   VARIABLE_POINTER_TRACK  Variable;\r
 \r
   EFI_STATUS              Status;\r
   VARIABLE_POINTER_TRACK  Variable;\r
 \r
-  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_SUCCESS;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     return EFI_SUCCESS;\r
   }\r
@@ -116,6 +163,7 @@ AutenticatedVariableServiceInitialize (
   UINTN                   CtxSize;\r
   UINT8                   SecureBootMode;\r
   UINT8                   SecureBootEnable;\r
   UINTN                   CtxSize;\r
   UINT8                   SecureBootMode;\r
   UINT8                   SecureBootEnable;\r
+  UINT8                   CustomMode;\r
 \r
   //\r
   // Initialize hash context.\r
 \r
   //\r
   // Initialize hash context.\r
@@ -151,7 +199,8 @@ AutenticatedVariableServiceInitialize (
              AUTHVAR_KEYDB_NAME,\r
              &gEfiAuthenticatedVariableGuid,\r
              &Variable,\r
              AUTHVAR_KEYDB_NAME,\r
              &gEfiAuthenticatedVariableGuid,\r
              &Variable,\r
-             &mVariableModuleGlobal->VariableGlobal\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
              );\r
 \r
   if (Variable.CurrPtr == NULL) {\r
              );\r
 \r
   if (Variable.CurrPtr == NULL) {\r
@@ -183,7 +232,7 @@ AutenticatedVariableServiceInitialize (
     mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);\r
   }\r
 \r
     mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);\r
   }\r
 \r
-  FindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, &PkVariable, &mVariableModuleGlobal->VariableGlobal);\r
+  FindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, &PkVariable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (PkVariable.CurrPtr == NULL) {\r
     DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME));\r
   } else {\r
   if (PkVariable.CurrPtr == NULL) {\r
     DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME));\r
   } else {\r
@@ -199,7 +248,8 @@ AutenticatedVariableServiceInitialize (
              EFI_SETUP_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
              EFI_SETUP_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
-             &mVariableModuleGlobal->VariableGlobal\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
              );\r
 \r
   if (Variable.CurrPtr == NULL) {\r
              );\r
 \r
   if (Variable.CurrPtr == NULL) {\r
@@ -235,7 +285,8 @@ AutenticatedVariableServiceInitialize (
              EFI_SIGNATURE_SUPPORT_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
              EFI_SIGNATURE_SUPPORT_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
-             &mVariableModuleGlobal->VariableGlobal\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
              );\r
 \r
   if (Variable.CurrPtr == NULL) {\r
              );\r
 \r
   if (Variable.CurrPtr == NULL) {\r
@@ -259,7 +310,7 @@ AutenticatedVariableServiceInitialize (
   // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.\r
   //\r
   SecureBootEnable = SECURE_BOOT_MODE_DISABLE;\r
   // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.\r
   //\r
   SecureBootEnable = SECURE_BOOT_MODE_DISABLE;\r
-  FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+  FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (Variable.CurrPtr != NULL) {\r
     SecureBootEnable = *(GetVariableDataPtr (Variable.CurrPtr));\r
   } else if (mPlatformMode == USER_MODE) {\r
   if (Variable.CurrPtr != NULL) {\r
     SecureBootEnable = *(GetVariableDataPtr (Variable.CurrPtr));\r
   } else if (mPlatformMode == USER_MODE) {\r
@@ -288,7 +339,7 @@ AutenticatedVariableServiceInitialize (
   } else {\r
     SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
   }\r
   } else {\r
     SecureBootMode = SECURE_BOOT_MODE_DISABLE;\r
   }\r
-  FindVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+  FindVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   Status = UpdateVariable (\r
              EFI_SECURE_BOOT_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
   Status = UpdateVariable (\r
              EFI_SECURE_BOOT_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
@@ -309,33 +360,33 @@ AutenticatedVariableServiceInitialize (
   DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable));\r
 \r
   //\r
   DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable));\r
 \r
   //\r
-  // Detect whether a secure platform-specific method to clear PK(Platform Key)\r
-  // is configured by platform owner. This method is provided for users force to clear PK\r
-  // in case incorrect enrollment mis-haps.\r
+  // Check "CustomMode" variable's existence.\r
   //\r
   //\r
-  if (ForceClearPK ()) {\r
-    DEBUG ((EFI_D_INFO, "Variable PK/KEK/DB/DBX will be cleared in clear PK mode.\n"));\r
-\r
+  FindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+  if (Variable.CurrPtr != NULL) {\r
+    CustomMode = *(GetVariableDataPtr (Variable.CurrPtr));\r
+  } else {\r
     //\r
     //\r
-    // 1. Clear PK.\r
+    // "CustomMode" not exist, initialize it in STANDARD_SECURE_BOOT_MODE.\r
     //\r
     //\r
-    Status = DeleteVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid);\r
+    CustomMode = STANDARD_SECURE_BOOT_MODE;\r
+    Status = UpdateVariable (\r
+               EFI_CUSTOM_MODE_NAME,\r
+               &gEfiCustomModeEnableGuid,\r
+               &CustomMode,\r
+               sizeof (UINT8),\r
+               EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+               0,\r
+               0,\r
+               &Variable,\r
+               NULL\r
+               );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-\r
-    //\r
-    // 2. Update "SetupMode" variable to SETUP_MODE.\r
-    //\r
-    UpdatePlatformMode (SETUP_MODE);\r
-\r
-    //\r
-    // 3. Clear KEK, DB and DBX.\r
-    //\r
-    DeleteVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid);\r
-    DeleteVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid);\r
-    DeleteVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid);\r
   }\r
   }\r
+  \r
+  DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode));\r
 \r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
@@ -367,7 +418,8 @@ AddPubKeyInStore (
              AUTHVAR_KEYDB_NAME,\r
              &gEfiAuthenticatedVariableGuid,\r
              &Variable,\r
              AUTHVAR_KEYDB_NAME,\r
              &gEfiAuthenticatedVariableGuid,\r
              &Variable,\r
-             &mVariableModuleGlobal->VariableGlobal\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
   //\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
   //\r
@@ -551,7 +603,8 @@ UpdatePlatformMode (
              EFI_SETUP_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
              EFI_SETUP_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
-             &mVariableModuleGlobal->VariableGlobal\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
              );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
              );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -592,7 +645,8 @@ UpdatePlatformMode (
              EFI_SECURE_BOOT_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
              EFI_SECURE_BOOT_MODE_NAME,\r
              &gEfiGlobalVariableGuid,\r
              &Variable,\r
-             &mVariableModuleGlobal->VariableGlobal\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
              );\r
   //\r
   // If "SecureBoot" variable exists, then check "SetupMode" variable update.\r
              );\r
   //\r
   // If "SecureBoot" variable exists, then check "SetupMode" variable update.\r
@@ -634,7 +688,8 @@ UpdatePlatformMode (
              EFI_SECURE_BOOT_ENABLE_NAME,\r
              &gEfiSecureBootEnableDisableGuid,\r
              &Variable,\r
              EFI_SECURE_BOOT_ENABLE_NAME,\r
              &gEfiSecureBootEnableDisableGuid,\r
              &Variable,\r
-             &mVariableModuleGlobal->VariableGlobal\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
              );\r
 \r
   if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) {\r
              );\r
 \r
   if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) {\r
@@ -811,7 +866,7 @@ ProcessVarWithPk (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (mPlatformMode == USER_MODE) {\r
+  if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {\r
 \r
     if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
       //\r
 \r
     if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
       //\r
@@ -860,7 +915,8 @@ ProcessVarWithPk (
                  EFI_PLATFORM_KEY_NAME,\r
                  &gEfiGlobalVariableGuid,\r
                  &PkVariable,\r
                  EFI_PLATFORM_KEY_NAME,\r
                  &gEfiGlobalVariableGuid,\r
                  &PkVariable,\r
-                 &mVariableModuleGlobal->VariableGlobal\r
+                 &mVariableModuleGlobal->VariableGlobal,\r
+                 FALSE\r
                  );\r
       ASSERT_EFI_ERROR (Status);\r
 \r
                  );\r
       ASSERT_EFI_ERROR (Status);\r
 \r
@@ -901,7 +957,7 @@ ProcessVarWithPk (
     }\r
   } else {\r
     //\r
     }\r
   } else {\r
     //\r
-    // Process PK or KEK in Setup mode.\r
+    // Process PK or KEK in Setup mode or Custom Secure Boot mode.\r
     //\r
     if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
       //\r
     //\r
     if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
       //\r
@@ -945,12 +1001,20 @@ ProcessVarWithPk (
                Variable,\r
                TimeStamp\r
                );\r
                Variable,\r
                TimeStamp\r
                );\r
-    //\r
-    // If enroll PK in setup mode, need change to user mode.\r
-    //\r
-    if ((DataSize != 0) && IsPk) {\r
-      Status = UpdatePlatformMode (USER_MODE);\r
-    }\r
+\r
+    if (IsPk) {\r
+      if (PayloadSize != 0) {\r
+        //\r
+        // If enroll PK in setup mode, need change to user mode.\r
+        //\r
+        Status = UpdatePlatformMode (USER_MODE);\r
+      } else {\r
+        //\r
+        // If delete PK in custom mode, need change to setup mode.\r
+        //\r
+        UpdatePlatformMode (SETUP_MODE);\r
+      }\r
+    }   \r
   }\r
 \r
   return Status;\r
   }\r
 \r
   return Status;\r
@@ -996,85 +1060,116 @@ ProcessVarWithKek (
   UINT8                           *Payload;\r
   UINTN                           PayloadSize;\r
   UINT64                          MonotonicCount;\r
   UINT8                           *Payload;\r
   UINTN                           PayloadSize;\r
   UINT64                          MonotonicCount;\r
+  EFI_TIME                        *TimeStamp;\r
+\r
+  if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
+    //\r
+    // DB and DBX should set EFI_VARIABLE_NON_VOLATILE attribute.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
 \r
-  if (mPlatformMode == USER_MODE) {\r
-    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {\r
+  Status = EFI_SUCCESS;\r
+  if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {\r
+    if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) &&\r
+        ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0)){\r
       //\r
       //\r
-      // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.\r
+      // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS or\r
+      // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute.\r
       //\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
       //\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;\r
-    CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);\r
-    if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) {\r
+    if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
       //\r
       //\r
-      // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.\r
+      // Time-based, verify against X509 Cert KEK.\r
       //\r
       //\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
-    //\r
-    // Get KEK database from variable.\r
-    //\r
-    Status = FindVariable (\r
-               EFI_KEY_EXCHANGE_KEY_NAME,\r
-               &gEfiGlobalVariableGuid,\r
-               &KekVariable,\r
-               &mVariableModuleGlobal->VariableGlobal\r
-               );\r
-    ASSERT_EFI_ERROR (Status);\r
+      return VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, FALSE, NULL);\r
+    } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+      //\r
+      // Counter-based, verify against RSA2048 Cert KEK.\r
+      //\r
+      CertData  = (EFI_VARIABLE_AUTHENTICATION *) Data;\r
+      CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);\r
+      if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) {\r
+        //\r
+        // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.\r
+        //\r
+        return EFI_SECURITY_VIOLATION;\r
+      }\r
+      //\r
+      // Get KEK database from variable.\r
+      //\r
+      Status = FindVariable (\r
+                 EFI_KEY_EXCHANGE_KEY_NAME,\r
+                 &gEfiGlobalVariableGuid,\r
+                 &KekVariable,\r
+                 &mVariableModuleGlobal->VariableGlobal,\r
+                 FALSE\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
 \r
 \r
-    KekDataSize = KekVariable.CurrPtr->DataSize;\r
-    KekList     = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr);\r
+      KekDataSize = KekVariable.CurrPtr->DataSize;\r
+      KekList     = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr);\r
 \r
 \r
-    //\r
-    // Enumerate all Kek items in this list to verify the variable certificate data.\r
-    // If anyone is authenticated successfully, it means the variable is correct!\r
-    //\r
-    IsFound   = FALSE;\r
-    while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {\r
-      if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {\r
-        KekItem   = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);\r
-        KekCount  = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;\r
-        for (Index = 0; Index < KekCount; Index++) {\r
-          if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
-            IsFound = TRUE;\r
-            break;\r
+      //\r
+      // Enumerate all Kek items in this list to verify the variable certificate data.\r
+      // If anyone is authenticated successfully, it means the variable is correct!\r
+      //\r
+      IsFound   = FALSE;\r
+      while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {\r
+        if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {\r
+          KekItem   = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);\r
+          KekCount  = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;\r
+          for (Index = 0; Index < KekCount; Index++) {\r
+            if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
+              IsFound = TRUE;\r
+              break;\r
+            }\r
+            KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);\r
           }\r
           }\r
-          KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);\r
         }\r
         }\r
+        KekDataSize -= KekList->SignatureListSize;\r
+        KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);\r
       }\r
       }\r
-      KekDataSize -= KekList->SignatureListSize;\r
-      KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);\r
-    }\r
 \r
 \r
-    if (!IsFound) {\r
-      return EFI_SECURITY_VIOLATION;\r
-    }\r
+      if (!IsFound) {\r
+        return EFI_SECURITY_VIOLATION;\r
+      }\r
 \r
 \r
-    Status = VerifyCounterBasedPayload (Data, DataSize, CertBlock->PublicKey);\r
-    if (!EFI_ERROR (Status)) {\r
-      Status = UpdateVariable (\r
-                 VariableName,\r
-                 VendorGuid,\r
-                 (UINT8*)Data + AUTHINFO_SIZE,\r
-                 DataSize - AUTHINFO_SIZE,\r
-                 Attributes,\r
-                 0,\r
-                 CertData->MonotonicCount,\r
-                 Variable,\r
-                 NULL\r
-                 );\r
+      Status = VerifyCounterBasedPayload (Data, DataSize, CertBlock->PublicKey);\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = UpdateVariable (\r
+                   VariableName,\r
+                   VendorGuid,\r
+                   (UINT8*)Data + AUTHINFO_SIZE,\r
+                   DataSize - AUTHINFO_SIZE,\r
+                   Attributes,\r
+                   0,\r
+                   CertData->MonotonicCount,\r
+                   Variable,\r
+                   NULL\r
+                   );\r
+      }\r
     }\r
   } else {\r
     //\r
     }\r
   } else {\r
     //\r
-    // If in setup mode, no authentication needed.\r
+    // If in setup mode or custom secure boot mode, no authentication needed.\r
     //\r
     //\r
-    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+    if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
+      //\r
+      // Time-based Authentication descriptor.\r
+      //\r
+      MonotonicCount = 0;\r
+      TimeStamp = &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp;\r
+      Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);\r
+      PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
+    } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {\r
       //\r
       // Counter-based Authentication descriptor.\r
       //\r
       MonotonicCount = ((EFI_VARIABLE_AUTHENTICATION *) Data)->MonotonicCount;\r
       //\r
       // Counter-based Authentication descriptor.\r
       //\r
       MonotonicCount = ((EFI_VARIABLE_AUTHENTICATION *) Data)->MonotonicCount;\r
+      TimeStamp = NULL;\r
       Payload = (UINT8*) Data + AUTHINFO_SIZE;\r
       PayloadSize = DataSize - AUTHINFO_SIZE;\r
     } else {\r
       Payload = (UINT8*) Data + AUTHINFO_SIZE;\r
       PayloadSize = DataSize - AUTHINFO_SIZE;\r
     } else {\r
@@ -1082,6 +1177,7 @@ ProcessVarWithKek (
       // No Authentication descriptor.\r
       //\r
       MonotonicCount = 0;\r
       // No Authentication descriptor.\r
       //\r
       MonotonicCount = 0;\r
+      TimeStamp = NULL;\r
       Payload = Data;\r
       PayloadSize = DataSize;\r
     }\r
       Payload = Data;\r
       PayloadSize = DataSize;\r
     }\r
@@ -1095,7 +1191,7 @@ ProcessVarWithKek (
                0,\r
                MonotonicCount,\r
                Variable,\r
                0,\r
                MonotonicCount,\r
                Variable,\r
-               NULL\r
+               TimeStamp\r
                );\r
   }\r
 \r
                );\r
   }\r
 \r
@@ -1148,6 +1244,13 @@ ProcessVariable (
   PubKey      = NULL;\r
   IsDeletion  = FALSE;\r
 \r
   PubKey      = NULL;\r
   IsDeletion  = FALSE;\r
 \r
+  if (NeedPhysicallyPresent(VariableName, VendorGuid) && !UserPhysicalPresent()) {\r
+    //\r
+    // This variable is protected, only physical present user could modify its value.\r
+    //\r
+    return EFI_SECURITY_VIOLATION;\r
+  }\r
+  \r
   //\r
   // Process Time-based Authenticated variable.\r
   //\r
   //\r
   // Process Time-based Authenticated variable.\r
   //\r
@@ -1538,7 +1641,8 @@ VerifyTimeBasedPayload (
                EFI_PLATFORM_KEY_NAME,\r
                &gEfiGlobalVariableGuid,\r
                &PkVariable,\r
                EFI_PLATFORM_KEY_NAME,\r
                &gEfiGlobalVariableGuid,\r
                &PkVariable,\r
-               &mVariableModuleGlobal->VariableGlobal\r
+               &mVariableModuleGlobal->VariableGlobal,\r
+               FALSE\r
                );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
                );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
@@ -1571,7 +1675,8 @@ VerifyTimeBasedPayload (
                EFI_KEY_EXCHANGE_KEY_NAME,\r
                &gEfiGlobalVariableGuid,\r
                &KekVariable,\r
                EFI_KEY_EXCHANGE_KEY_NAME,\r
                &gEfiGlobalVariableGuid,\r
                &KekVariable,\r
-               &mVariableModuleGlobal->VariableGlobal\r
+               &mVariableModuleGlobal->VariableGlobal,\r
+               FALSE\r
                );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
                );\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
index c84a2f62d3d70c6aa43f7df96c41fac631b59004..22ded16819077a34b5b1a7927fc751ca9c349a48 100644 (file)
@@ -718,17 +718,19 @@ Reclaim (
 /**\r
   Find the variable in the specified variable store.\r
 \r
 /**\r
   Find the variable in the specified variable store.\r
 \r
-  @param  VariableName        Name of the variable to be found\r
-  @param  VendorGuid          Vendor GUID to be found.\r
-  @param  PtrTrack            Variable Track Pointer structure that contains Variable Information.\r
+  @param[in]       VariableName        Name of the variable to be found\r
+  @param[in]       VendorGuid          Vendor GUID to be found.\r
+  @param[in]       IgnoreRtAttribute   Ignore RUNTIME_ACCESS attribute when searching variable.\r
+  @param[in, out]  PtrTrack            Variable Track Pointer structure that contains Variable Information.\r
 \r
 \r
-  @retval  EFI_SUCCESS            Variable found successfully\r
-  @retval  EFI_NOT_FOUND          Variable not found\r
+  @retval          EFI_SUCCESS         Variable found successfully\r
+  @retval          EFI_NOT_FOUND       Variable not found\r
 **/\r
 EFI_STATUS\r
 FindVariableEx (\r
   IN     CHAR16                  *VariableName,\r
   IN     EFI_GUID                *VendorGuid,\r
 **/\r
 EFI_STATUS\r
 FindVariableEx (\r
   IN     CHAR16                  *VariableName,\r
   IN     EFI_GUID                *VendorGuid,\r
+  IN     BOOLEAN                 IgnoreRtAttribute,\r
   IN OUT VARIABLE_POINTER_TRACK  *PtrTrack\r
   )\r
 {\r
   IN OUT VARIABLE_POINTER_TRACK  *PtrTrack\r
   )\r
 {\r
@@ -747,7 +749,7 @@ FindVariableEx (
     if (PtrTrack->CurrPtr->State == VAR_ADDED ||\r
         PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
        ) {\r
     if (PtrTrack->CurrPtr->State == VAR_ADDED ||\r
         PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
        ) {\r
-      if (!AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {\r
+      if (IgnoreRtAttribute || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {\r
         if (VariableName[0] == 0) {\r
           if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
             InDeletedVariable   = PtrTrack->CurrPtr;\r
         if (VariableName[0] == 0) {\r
           if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
             InDeletedVariable   = PtrTrack->CurrPtr;\r
@@ -783,15 +785,18 @@ FindVariableEx (
   This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
   If VariableName is an empty string, then we just return the first\r
   qualified variable without comparing VariableName and VendorGuid.\r
   This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
   If VariableName is an empty string, then we just return the first\r
   qualified variable without comparing VariableName and VendorGuid.\r
-  Otherwise, VariableName and VendorGuid are compared.\r
+  If IgnoreRtAttribute is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS Attribute\r
+  when searching existing variable, only VariableName and VendorGuid are compared.\r
+  Otherwise, variables with EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime.\r
 \r
 \r
-  @param  VariableName                Name of the variable to be found.\r
-  @param  VendorGuid                  Vendor GUID to be found.\r
-  @param  PtrTrack                    VARIABLE_POINTER_TRACK structure for output,\r
+  @param[in]   VariableName           Name of the variable to be found.\r
+  @param[in]   VendorGuid             Vendor GUID to be found.\r
+  @param[out]  PtrTrack               VARIABLE_POINTER_TRACK structure for output,\r
                                       including the range searched and the target position.\r
                                       including the range searched and the target position.\r
-  @param  Global                      Pointer to VARIABLE_GLOBAL structure, including\r
+  @param[in]   Global                 Pointer to VARIABLE_GLOBAL structure, including\r
                                       base of volatile variable storage area, base of\r
                                       NV variable storage area, and a lock.\r
                                       base of volatile variable storage area, base of\r
                                       NV variable storage area, and a lock.\r
+  @param[in]   IgnoreRtAttribute      Ignore RUNTIME_ACCESS attribute when searching variable.\r
 \r
   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
                                       VendorGuid is NULL.\r
 \r
   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
                                       VendorGuid is NULL.\r
@@ -804,7 +809,8 @@ FindVariable (
   IN  CHAR16                  *VariableName,\r
   IN  EFI_GUID                *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
   IN  CHAR16                  *VariableName,\r
   IN  EFI_GUID                *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
-  IN  VARIABLE_GLOBAL         *Global\r
+  IN  VARIABLE_GLOBAL         *Global,\r
+  IN  BOOLEAN                 IgnoreRtAttribute\r
   )\r
 {\r
   EFI_STATUS              Status;\r
   )\r
 {\r
   EFI_STATUS              Status;\r
@@ -836,7 +842,7 @@ FindVariable (
     PtrTrack->EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);\r
     PtrTrack->Volatile = (BOOLEAN) (Type == VariableStoreTypeVolatile);\r
 \r
     PtrTrack->EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);\r
     PtrTrack->Volatile = (BOOLEAN) (Type == VariableStoreTypeVolatile);\r
 \r
-    Status = FindVariableEx (VariableName, VendorGuid, PtrTrack);\r
+    Status = FindVariableEx (VariableName, VendorGuid, IgnoreRtAttribute, PtrTrack);\r
     if (!EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
     if (!EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -1238,7 +1244,7 @@ AutoUpdateLangVariable (
     // Update Lang if PlatformLang is already set\r
     // Update PlatformLang if Lang is already set\r
     //\r
     // Update Lang if PlatformLang is already set\r
     // Update PlatformLang if Lang is already set\r
     //\r
-    Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+    Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
     if (!EFI_ERROR (Status)) {\r
       //\r
       // Update Lang\r
     if (!EFI_ERROR (Status)) {\r
       //\r
       // Update Lang\r
@@ -1247,7 +1253,7 @@ AutoUpdateLangVariable (
       Data         = GetVariableDataPtr (Variable.CurrPtr);\r
       DataSize     = Variable.CurrPtr->DataSize;\r
     } else {\r
       Data         = GetVariableDataPtr (Variable.CurrPtr);\r
       DataSize     = Variable.CurrPtr->DataSize;\r
     } else {\r
-      Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+      Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
       if (!EFI_ERROR (Status)) {\r
         //\r
         // Update PlatformLang\r
       if (!EFI_ERROR (Status)) {\r
         //\r
         // Update PlatformLang\r
@@ -1292,7 +1298,7 @@ AutoUpdateLangVariable (
         //\r
         // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.\r
         //\r
         //\r
         // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.\r
         //\r
-        FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+        FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
 \r
         Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,\r
                                  ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL);\r
 \r
         Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,\r
                                  ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL);\r
@@ -1326,7 +1332,7 @@ AutoUpdateLangVariable (
         //\r
         // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.\r
         //\r
         //\r
         // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.\r
         //\r
-        FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+        FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
 \r
         Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,\r
                                  AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL);\r
 \r
         Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,\r
                                  AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL);\r
@@ -1456,6 +1462,14 @@ UpdateVariable (
         Status = EFI_INVALID_PARAMETER;\r
         goto Done;\r
       }\r
         Status = EFI_INVALID_PARAMETER;\r
         goto Done;\r
       }\r
+      \r
+      //\r
+      // Only variable that have RT attributes can be updated/deleted in Runtime.\r
+      //\r
+      if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
     }\r
 \r
     //\r
     }\r
 \r
     //\r
@@ -1905,7 +1919,7 @@ VariableServiceGetVariable (
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
-  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
@@ -1980,7 +1994,7 @@ VariableServiceGetNextVariableName (
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
-  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
+  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
@@ -2057,6 +2071,7 @@ VariableServiceGetNextVariableName (
           Status = FindVariableEx (\r
                      GetVariableNamePtr (Variable.CurrPtr),\r
                      &Variable.CurrPtr->VendorGuid,\r
           Status = FindVariableEx (\r
                      GetVariableNamePtr (Variable.CurrPtr),\r
                      &Variable.CurrPtr->VendorGuid,\r
+                     FALSE,\r
                      &VariableInHob\r
                      );\r
           if (!EFI_ERROR (Status)) {\r
                      &VariableInHob\r
                      );\r
           if (!EFI_ERROR (Status)) {\r
@@ -2220,8 +2235,13 @@ VariableServiceSetVariable (
   //\r
   // Check whether the input variable is already existed.\r
   //\r
   //\r
   // Check whether the input variable is already existed.\r
   //\r
-  FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);\r
-\r
+  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE);\r
+  if (!EFI_ERROR (Status)) {\r
+    if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {\r
+      return EFI_WRITE_PROTECTED;\r
+    }\r
+  }\r
+  \r
   //\r
   // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.\r
   //\r
   //\r
   // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang.\r
   //\r
@@ -2233,7 +2253,8 @@ VariableServiceSetVariable (
     Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, TRUE);\r
   } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {\r
     Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, FALSE);\r
     Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, TRUE);\r
   } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {\r
     Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes, FALSE);\r
-  } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0)) {\r
+  } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) && \r
+          ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) {\r
     Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);\r
   } else {\r
     Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);\r
     Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);\r
   } else {\r
     Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);\r
index 58d1e5a8cdab4fe2bcef7bdfeb7fe4b79de2a7a8..d58203739fb5e3a613caa55c71314388ed59dbad 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file includes the common header files, defines\r
   internal structure and functions used by Variable modules.\r
 \r
   The internal header file includes the common header files, defines\r
   internal structure and functions used by Variable modules.\r
 \r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 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
 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
@@ -120,20 +120,23 @@ FtwVariableSpace (
   This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
   If VariableName is an empty string, then we just return the first\r
   qualified variable without comparing VariableName and VendorGuid.\r
   This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
   If VariableName is an empty string, then we just return the first\r
   qualified variable without comparing VariableName and VendorGuid.\r
-  Otherwise, VariableName and VendorGuid are compared.\r
+  If IgnoreRtAttribute is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS Attribute\r
+  when searching existing variable, only VariableName and VendorGuid are compared.\r
+  Otherwise, variables with EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime.\r
 \r
 \r
-  @param  VariableName                Name of the variable to be found.\r
-  @param  VendorGuid                  Vendor GUID to be found.\r
-  @param  PtrTrack                    VARIABLE_POINTER_TRACK structure for output,\r
+  @param[in]   VariableName           Name of the variable to be found.\r
+  @param[in]   VendorGuid             Vendor GUID to be found.\r
+  @param[out]  PtrTrack               VARIABLE_POINTER_TRACK structure for output,\r
                                       including the range searched and the target position.\r
                                       including the range searched and the target position.\r
-  @param  Global                      Pointer to VARIABLE_GLOBAL structure, including\r
+  @param[in]   Global                 Pointer to VARIABLE_GLOBAL structure, including\r
                                       base of volatile variable storage area, base of\r
                                       NV variable storage area, and a lock.\r
                                       base of volatile variable storage area, base of\r
                                       NV variable storage area, and a lock.\r
+  @param[in]   IgnoreRtAttribute      Ignore RUNTIME_ACCESS attribute when searching variable.\r
 \r
   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
                                       VendorGuid is NULL.\r
   @retval EFI_SUCCESS                 Variable successfully found.\r
 \r
   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
                                       VendorGuid is NULL.\r
   @retval EFI_SUCCESS                 Variable successfully found.\r
-  @retval EFI_INVALID_PARAMETER       Variable not found.\r
+  @retval EFI_NOT_FOUND               Variable not found\r
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
@@ -141,7 +144,8 @@ FindVariable (
   IN  CHAR16                  *VariableName,\r
   IN  EFI_GUID                *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
   IN  CHAR16                  *VariableName,\r
   IN  EFI_GUID                *VendorGuid,\r
   OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
-  IN  VARIABLE_GLOBAL         *Global\r
+  IN  VARIABLE_GLOBAL         *Global,\r
+  IN  BOOLEAN                 IgnoreRtAttribute\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
index 70717c457331424114e99638fe86def236708dbe..abe14abab30dbd791fdffe984f2c5d61d8947a5b 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Component description file for Authenticated Variable module.\r
 #\r
 ## @file\r
 #  Component description file for Authenticated Variable module.\r
 #\r
-# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2009 - 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
 # 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
@@ -73,6 +73,7 @@
   gEfiCertPkcs7Guid\r
   gEfiCertRsa2048Guid\r
   gEfiSecureBootEnableDisableGuid\r
   gEfiCertPkcs7Guid\r
   gEfiCertRsa2048Guid\r
   gEfiSecureBootEnableDisableGuid\r
+  gEfiCustomModeEnableGuid\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
 \r
 [Pcd]\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
 \r
 [Pcd]\r
index 84762dc406a73389792cabbd2430b8db0081f64f..cd6457f8f488963c93b4feabfec88c8759ec503b 100644 (file)
@@ -9,7 +9,7 @@
 #  SMM Runtime DXE module would install variable arch protocol and variable\r
 #  write arch protocol based on SMM variable module.\r
 #\r
 #  SMM Runtime DXE module would install variable arch protocol and variable\r
 #  write arch protocol based on SMM variable module.\r
 #\r
-# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2010 - 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
 # 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
@@ -78,6 +78,7 @@
   gEfiCertPkcs7Guid\r
   gEfiCertRsa2048Guid\r
   gEfiSecureBootEnableDisableGuid\r
   gEfiCertPkcs7Guid\r
   gEfiCertRsa2048Guid\r
   gEfiSecureBootEnableDisableGuid\r
+  gEfiCustomModeEnableGuid\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
 \r
 [Pcd]\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES\r
 \r
 [Pcd]\r
index fbf5e2eae1a743d85c7f9ad433afb1dbf0de220f..22c03c1288b72a04ad31619495d76fc65e6d674c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   VFR file used by the SecureBoot configuration component.\r
 \r
 /** @file\r
   VFR file used by the SecureBoot configuration component.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -24,26 +24,471 @@ formset
     varid = SECUREBOOT_CONFIGURATION_VARSTORE_ID,\r
     name  = SECUREBOOT_CONFIGURATION,\r
     guid  = SECUREBOOT_CONFIG_FORM_SET_GUID;\r
     varid = SECUREBOOT_CONFIGURATION_VARSTORE_ID,\r
     name  = SECUREBOOT_CONFIGURATION,\r
     guid  = SECUREBOOT_CONFIG_FORM_SET_GUID;\r
-\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
   form formid = SECUREBOOT_CONFIGURATION_FORM_ID,\r
     title = STRING_TOKEN(STR_SECUREBOOT_TITLE);\r
 \r
     subtitle text = STRING_TOKEN(STR_NULL);\r
-\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
     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
+    endif;  \r
     \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
     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
     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
 \r
   endform;\r
 \r
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDevicePath.c b/SecurityPkg/VariableAuthenticated/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
index b0254da30e374f92b1eb3dff870da5043c662d4b..a6a207efe674c6dc3021d06e09972b81ac46c08e 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 #  Component name for SecureBoot configuration module.\r
 #\r
 ## @file\r
 #  Component name for SecureBoot configuration module.\r
 #\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
 # 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
@@ -27,6 +27,9 @@
 [Sources]\r
   SecureBootConfigDriver.c\r
   SecureBootConfigImpl.c\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
   SecureBootConfigImpl.h\r
   SecureBootConfig.vfr\r
   SecureBootConfigStrings.uni\r
   MdePkg/MdePkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
   SecurityPkg/SecurityPkg.dec\r
   MdePkg/MdePkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
   SecurityPkg/SecurityPkg.dec\r
+  CryptoPkg/CryptoPkg.dec\r
 \r
 [LibraryClasses]\r
   BaseLib\r
   BaseMemoryLib\r
 \r
 [LibraryClasses]\r
   BaseLib\r
   BaseMemoryLib\r
+  BaseCryptLib\r
   MemoryAllocationLib\r
   UefiLib\r
   UefiBootServicesTableLib\r
   MemoryAllocationLib\r
   UefiLib\r
   UefiBootServicesTableLib\r
   UefiHiiServicesLib\r
   DebugLib\r
   HiiLib\r
   UefiHiiServicesLib\r
   DebugLib\r
   HiiLib\r
+  PlatformSecureLib  \r
 \r
 [Guids]\r
   gEfiIfrTianoGuid\r
 \r
 [Guids]\r
   gEfiIfrTianoGuid\r
+  gEfiCustomModeEnableGuid\r
   gEfiSecureBootEnableDisableGuid\r
   gSecureBootConfigFormSetGuid\r
   gEfiSecureBootEnableDisableGuid\r
   gSecureBootConfigFormSetGuid\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
 \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
 \r
 [Depex]\r
   gEfiHiiConfigRoutingProtocolGuid  AND\r
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigFileExplorer.c b/SecurityPkg/VariableAuthenticated/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
index f846a72ca95b5b9b4af7ea3b8489b697210b6a79..63dffd76bcd1237307b8117d0b890bea9fd7e7d5 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   HII Config Access protocol implementation of SecureBoot configuration module.\r
 \r
 /** @file\r
   HII Config Access protocol implementation of SecureBoot configuration module.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -14,10 +14,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "SecureBootConfigImpl.h"\r
 \r
 \r
 #include "SecureBootConfigImpl.h"\r
 \r
-CHAR16                          mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";\r
+CHAR16              mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION";\r
 \r
 SECUREBOOT_CONFIG_PRIVATE_DATA         mSecureBootConfigPrivateDateTemplate = {\r
 \r
 SECUREBOOT_CONFIG_PRIVATE_DATA         mSecureBootConfigPrivateDateTemplate = {\r
-  SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,\r
+  SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,  \r
   {\r
     SecureBootExtractConfig,\r
     SecureBootRouteConfig,\r
   {\r
     SecureBootExtractConfig,\r
     SecureBootRouteConfig,\r
@@ -47,34 +47,2035 @@ HII_VENDOR_DEVICE_PATH          mSecureBootHiiVendorDevicePath = {
   }\r
 };\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
+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
+/**\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
+  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
+\r
+  Variable = GetVariable (VariableName, VendorGuid);\r
+  if (Variable == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status =   gRT->SetVariable (\r
+                    VariableName,\r
+                    VendorGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                    0,\r
+                    NULL\r
+                    );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Generate a PK signature list from the public key storing file (*.pbk).\r
+\r
+  @param[in]   PkKeyFile             FileHandle of the public key 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
+CreatePkRsaSignatureList (\r
+  IN    EFI_FILE_HANDLE             PkKeyFile, \r
+  OUT   EFI_SIGNATURE_LIST          **PkCert \r
+  )\r
+{\r
+  EFI_STATUS                      Status;  \r
+  UINTN                           KeyBlobSize;\r
+  VOID                            *KeyBlob;\r
+  CPL_KEY_INFO                    *KeyInfo;\r
+  EFI_SIGNATURE_DATA              *PkCertData;\r
+  VOID                            *KeyBuffer;  \r
+  UINTN                           KeyLenInBytes;\r
+\r
+  PkCertData = NULL;\r
+  KeyBlob = NULL;\r
+  KeyBuffer = NULL;\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Get key from PK key file\r
+  //                           \r
+  Status = ReadFileContent (PkKeyFile, &KeyBlob, &KeyBlobSize, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Can't Open the file for PK enrolling.\n"));\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  KeyInfo = (CPL_KEY_INFO *)KeyBlob;\r
+  if (KeyInfo->KeyLengthInBits/8 != WIN_CERT_UEFI_RSA2048_SIZE) {\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
+  Status = Int2OctStr (\r
+              (UINTN*) ((UINTN)KeyBlob + sizeof(CPL_KEY_INFO)), \r
+              KeyLenInBytes / sizeof (UINTN), \r
+              (UINT8*)KeyBuffer, \r
+              KeyLenInBytes\r
+              );\r
+  if (EFI_ERROR(Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  // Allocate space for PK certificate list and initialize the list.\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
+            + WIN_CERT_UEFI_RSA2048_SIZE\r
+            );\r
+  \r
+  if (*PkCert == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  (*PkCert)->SignatureListSize   = sizeof(EFI_SIGNATURE_LIST) \r
+                                  + sizeof(EFI_SIGNATURE_DATA) - 1\r
+                                  + WIN_CERT_UEFI_RSA2048_SIZE;\r
+  (*PkCert)->SignatureSize       = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE;\r
+  (*PkCert)->SignatureHeaderSize = 0;\r
+  CopyGuid (&(*PkCert)->SignatureType, &gEfiCertRsa2048Guid);\r
+\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 PKKeyFile.\r
+  //               \r
+  CopyMem (&(PkCertData->SignatureData[0]), KeyBuffer, WIN_CERT_UEFI_RSA2048_SIZE);\r
+\r
+ON_EXIT:\r
+  \r
+  if (KeyBlob != NULL) {\r
+    FreePool (KeyBlob);\r
+  }\r
+  \r
+  if (EFI_ERROR(Status) && *PkCert != NULL) {\r
+    FreePool (*PkCert);\r
+    *PkCert = NULL;\r
+  }\r
+  \r
+  if (KeyBuffer != NULL) {\r
+    FreePool (KeyBuffer);\r
+  }\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, &X509Data, &X509DataSize, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\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 *.pbk(RSA2048) and *.cer(X509) files.\r
+  //\r
+  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
+  if (CompareMem (FilePostFix, L".pbk",4) && CompareMem (FilePostFix, L".cer",4)) {\r
+    DEBUG ((EFI_D_ERROR, "Don't support the file, only *.pbk or *.cer.\n is supported."));\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
+  if (!CompareMem (FilePostFix, L".pbk",4)) {\r
+    Status = CreatePkRsaSignatureList (\r
+              Private->FileContext->FHandle, \r
+              &PkCert \r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_EXIT;\r
+    }\r
+  } else if (!CompareMem (FilePostFix, L".cer",4)) {\r
+    Status = CreatePkX509SignatureList (\r
+              Private->FileContext->FHandle, \r
+              &PkCert \r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+                         \r
+  //\r
+  // Set Platform Key variable.\r
+  // \r
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
+          | EFI_VARIABLE_BOOTSERVICE_ACCESS;\r
+  DataSize = PkCert->SignatureListSize;\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 (EFI_PLATFORM_KEY_NAME, &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
+             &KeyBlob,\r
+             &KeyBlobSize,\r
+             0\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\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 | EFI_VARIABLE_BOOTSERVICE_ACCESS;\r
+  DataSize = 0;\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
+\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;\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 .cer and .der file as X509 certificate, \r
+  // and .pbk as RSA public key file.\r
+  //\r
+  FilePostFix = Private->FileContext->FileName + StrLen (Private->FileContext->FileName) - 4;\r
+  if ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) {\r
+    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
+\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;\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
+  Magic = mNtHeader.Pe32->OptionalHeader.Magic;\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
+  Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS \r
+          | EFI_VARIABLE_BOOTSERVICE_ACCESS;\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
+\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
+  //\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 ((CompareMem (FilePostFix, L".cer",4) == 0) || (CompareMem (FilePostFix, L".der",4) == 0)) {\r
+    //\r
+    // Supports .cer and .der file as X509 certificate.\r
+    //\r
+    return EnrollX509toSigDB (Private, VariableName);\r
+  }\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
 /**\r
-  Save Secure Boot option to variable space.\r
+  Delete a KEK entry from KEK database. \r
 \r
 \r
-  @param[in] VarValue              The option of Secure Boot.\r
+  @param[in]    PrivateData         Module's private data.\r
+  @param[in]    QuestionId          Question id of the KEK item to delete.\r
 \r
 \r
-  @retval    EFI_SUCCESS           The operation is finished successfully.\r
-  @retval    Others                Other errors as indicated.\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
+  CertList = (EFI_SIGNATURE_LIST*) OldData;\r
+  DataSize = Offset;\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
 \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
 **/\r
 EFI_STATUS\r
-SaveSecureBootVariable (\r
-  IN UINT8                         VarValue\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
   )\r
 {\r
-  EFI_STATUS                       Status;\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
 \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
+  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
+  CertList = (EFI_SIGNATURE_LIST*) OldData;\r
+  DataSize = Offset;\r
+\r
+  Status = gRT->SetVariable(\r
+                  VariableName, \r
+                  VendorGuid, \r
+                  Attr, \r
+                  DataSize, \r
+                  OldData\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));\r
+    goto ON_EXIT;\r
   }\r
   }\r
-  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
-  return EFI_SUCCESS;\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   *SecureBootMode;\r
+\r
+  SecureBootEnable = NULL;\r
+  SetupMode        = NULL;\r
+  SecureBootMode   = NULL;\r
+  \r
+  //\r
+  // Get the SecureBootEnable Variable\r
+  //\r
+  SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);\r
+\r
+  //\r
+  // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable\r
+  // Checkbox.\r
+  //\r
+  if (SecureBootEnable == NULL) {\r
+    ConfigData->HideSecureBoot = TRUE;\r
+  } else {\r
+    ConfigData->HideSecureBoot = FALSE;\r
+    ConfigData->SecureBootState = *SecureBootEnable;\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
+  SetupMode = GetVariable (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid);\r
+  if (SetupMode == NULL || (*SetupMode) == 1) {\r
+    ConfigData->HasPk = FALSE;\r
+  } else  {\r
+    ConfigData->HasPk = TRUE;\r
+  }\r
+\r
+  //\r
+  // Get the SecureBootMode from CustomMode variable.\r
+  //\r
+  SecureBootMode = GetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid);\r
+  if (SecureBootMode == NULL) {\r
+    ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE;\r
+  } else {\r
+    ConfigData->SecureBootMode = *(SecureBootMode);\r
+  }\r
+  \r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -116,16 +2117,15 @@ SecureBootExtractConfig (
   UINTN                             BufferSize;\r
   UINTN                             Size;\r
   SECUREBOOT_CONFIGURATION          Configuration;\r
   UINTN                             BufferSize;\r
   UINTN                             Size;\r
   SECUREBOOT_CONFIGURATION          Configuration;\r
-\r
   EFI_STRING                        ConfigRequest;\r
   EFI_STRING                        ConfigRequestHdr;\r
   EFI_STRING                        ConfigRequest;\r
   EFI_STRING                        ConfigRequestHdr;\r
-  UINT8                             *SecureBootEnable;\r
   SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData;\r
   BOOLEAN                           AllocatedRequest;\r
 \r
   if (Progress == NULL || Results == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\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
   AllocatedRequest = FALSE;\r
   ConfigRequestHdr = NULL;\r
   ConfigRequest    = NULL;\r
@@ -139,30 +2139,16 @@ SecureBootExtractConfig (
     return EFI_NOT_FOUND;\r
   }\r
 \r
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  \r
-  //\r
-  // Get the SecureBoot Variable\r
-  //\r
-  SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);\r
-\r
   //\r
   //\r
-  // If the SecureBoot Variable doesn't exist, hide the SecureBoot Enable/Disable\r
-  // Checkbox.\r
+  // Get Configuration from Variable.\r
   //\r
   //\r
-  if (SecureBootEnable == NULL) {\r
-    Configuration.HideSecureBoot = TRUE;\r
-  } else {\r
-    Configuration.HideSecureBoot = FALSE;\r
-    Configuration.SecureBootState = *SecureBootEnable;\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
   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
-\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
     // 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
@@ -231,12 +2217,6 @@ SecureBootRouteConfig (
        OUT EFI_STRING                          *Progress\r
   )\r
 {\r
        OUT EFI_STRING                          *Progress\r
   )\r
 {\r
-  EFI_STATUS                       Status;\r
-  UINTN                            BufferSize;\r
-  SECUREBOOT_CONFIGURATION         SecureBootConfiguration;\r
-  UINT8                            *SecureBootEnable;\r
-\r
-\r
   if (Configuration == NULL || Progress == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if (Configuration == NULL || Progress == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -246,37 +2226,12 @@ SecureBootRouteConfig (
     return EFI_NOT_FOUND;\r
   }\r
 \r
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  //\r
-  // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
-  //\r
-  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
-  Status = gHiiConfigRouting->ConfigToBlock (\r
-                                gHiiConfigRouting,\r
-                                Configuration,\r
-                                (UINT8 *) &SecureBootConfiguration,\r
-                                &BufferSize,\r
-                                Progress\r
-                                );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);\r
-  if (SecureBootEnable == NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if ((*SecureBootEnable) != SecureBootConfiguration.SecureBootState) {\r
-    //\r
-    // If the configure is changed, update the SecureBoot Variable.\r
-    //\r
-    SaveSecureBootVariable (SecureBootConfiguration.SecureBootState);\r
-  }\r
+  *Progress = Configuration + StrLen (Configuration);\r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  This function processes the results of changes in configuration.\r
+  This function is called to provide results data to the driver.\r
 \r
   @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
   @param[in]  Action             Specifies the type of action taken by the browser.\r
 \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
@@ -308,24 +2263,271 @@ SecureBootCallback (
      OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
   )\r
 {\r
      OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
   )\r
 {\r
-  BOOLEAN           SecureBootEnable;\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
 \r
   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
 \r
   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((Action != EFI_BROWSER_ACTION_CHANGED) || (QuestionId != KEY_SECURE_BOOT_ENABLE)) {\r
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
     return EFI_UNSUPPORTED;\r
   }\r
+  \r
+  Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
 \r
 \r
-  if (NULL == GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid)) {\r
-    return EFI_SUCCESS;\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
   }\r
 \r
-  SecureBootEnable = Value->u8;\r
-  SaveSecureBootVariable (Value->u8);\r
-  return EFI_SUCCESS;\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
+      if (NULL != GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid)) {\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
 \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
+      if (EFI_ERROR (Status)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"ERROR: The File Type is neither *.cer nor *.pbk!",\r
+          NULL\r
+          );\r
+      } else {\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; \r
+      }        \r
+      break;\r
+\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_PK:\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_KEK:\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_DB:\r
+    case KEY_VALUE_NO_SAVE_AND_EXIT_DBX:\r
+      if (Private->FileContext->FHandle != NULL) {\r
+        CloseFile (Private->FileContext->FHandle);\r
+        Private->FileContext->FHandle = NULL;\r
+        Private->FileContext->FileName = NULL;\r
+      }\r
+   \r
+      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
+      if (NULL != GetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid)) {\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
 }\r
 \r
 /**\r
@@ -333,7 +2535,7 @@ SecureBootCallback (
 \r
   @param[in, out]  PrivateData   Points to SecureBoot configuration private data.\r
 \r
 \r
   @param[in, out]  PrivateData   Points to SecureBoot configuration private data.\r
 \r
-  @retval EFI_SUCCESS            HII Form is installed for this network device.\r
+  @retval EFI_SUCCESS            HII Form is installed successfully.\r
   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.\r
   @retval Others                 Other errors as indicated.\r
 \r
   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.\r
   @retval Others                 Other errors as indicated.\r
 \r
@@ -346,7 +2548,6 @@ InstallSecureBootConfigForm (
   EFI_STATUS                      Status;\r
   EFI_HII_HANDLE                  HiiHandle;\r
   EFI_HANDLE                      DriverHandle;\r
   EFI_STATUS                      Status;\r
   EFI_HII_HANDLE                  HiiHandle;\r
   EFI_HANDLE                      DriverHandle;\r
-\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
 \r
   DriverHandle = NULL;\r
   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;\r
 \r
   DriverHandle = NULL;\r
@@ -384,11 +2585,63 @@ InstallSecureBootConfigForm (
            ConfigAccess,\r
            NULL\r
            );\r
            ConfigAccess,\r
            NULL\r
            );\r
-\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   PrivateData->HiiHandle = HiiHandle;\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
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -426,5 +2679,28 @@ UninstallSecureBootConfigForm (
     PrivateData->DriverHandle = NULL;\r
   }\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
   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
 }\r
index 603044d26e33745d6671f49aa466495568b3ae51..789150363134ed46b0178550736438000f260bbe 100644 (file)
@@ -2,7 +2,7 @@
   The header file of HII Config Access protocol implementation of SecureBoot\r
   configuration module.\r
 \r
   The header file of HII Config Access protocol implementation of SecureBoot\r
   configuration module.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -20,6 +20,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Protocol/HiiConfigAccess.h>\r
 #include <Protocol/HiiConfigRouting.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
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
@@ -32,17 +38,158 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/HiiLib.h>\r
 #include <Library/DevicePathLib.h>\r
 #include <Library/PrintLib.h>\r
 #include <Library/HiiLib.h>\r
 #include <Library/DevicePathLib.h>\r
 #include <Library/PrintLib.h>\r
-\r
+#include <Library/PlatformSecureLib.h>\r
+#include <Library/BaseCryptLib.h>\r
 #include <Guid/MdeModuleHii.h>\r
 #include <Guid/AuthenticatedVariableFormat.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
 \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
+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
 ///\r
 /// HII specific Vendor Device Path definition.\r
@@ -59,6 +206,13 @@ typedef struct {
   EFI_HII_HANDLE                    HiiHandle;\r
   EFI_HANDLE                        DriverHandle;\r
 \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
 } SECUREBOOT_CONFIG_PRIVATE_DATA;\r
 \r
 extern SECUREBOOT_CONFIG_PRIVATE_DATA      mSecureBootConfigPrivateDateTemplate;\r
@@ -66,13 +220,123 @@ extern SECUREBOOT_CONFIG_PRIVATE_DATA      mSecureBootConfigPrivateDateTemplate;
 #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
 #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 (push, 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 (pop)\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
 \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 for this network device.\r
+  @retval EFI_SUCCESS            HII Form is installed successfully.\r
   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.\r
   @retval Others                 Other errors as indicated.\r
 \r
   @retval EFI_OUT_OF_RESOURCES   Not enough resource for HII Form installation.\r
   @retval Others                 Other errors as indicated.\r
 \r
@@ -82,6 +346,7 @@ InstallSecureBootConfigForm (
   IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData\r
   );\r
 \r
   IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA  *PrivateData\r
   );\r
 \r
+\r
 /**\r
   This function removes SecureBoot configuration Form.\r
 \r
 /**\r
   This function removes SecureBoot configuration Form.\r
 \r
@@ -93,6 +358,7 @@ UninstallSecureBootConfigForm (
   IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData\r
   );\r
 \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
   This function allows a caller to extract the current configuration for one\r
   or more named elements from the target driver.\r
@@ -128,6 +394,7 @@ SecureBootExtractConfig (
        OUT EFI_STRING                            *Results\r
   );\r
 \r
        OUT EFI_STRING                            *Results\r
   );\r
 \r
+\r
 /**\r
   This function processes the results of changes in configuration.\r
 \r
 /**\r
   This function processes the results of changes in configuration.\r
 \r
@@ -154,6 +421,7 @@ SecureBootRouteConfig (
        OUT EFI_STRING                          *Progress\r
   );\r
 \r
        OUT EFI_STRING                          *Progress\r
   );\r
 \r
+\r
 /**\r
   This function processes the results of changes in configuration.\r
 \r
 /**\r
   This function processes the results of changes in configuration.\r
 \r
@@ -187,4 +455,160 @@ SecureBootCallback (
      OUT EFI_BROWSER_ACTION_REQUEST            *ActionRequest\r
   );\r
 \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
 #endif\r
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigMisc.c b/SecurityPkg/VariableAuthenticated/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
index 278066e87ffa795d0d4f93d1a0e9c64b23e5928b..6015dd636dd49d1f738b8f632215432ae3f7a62a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for NV data structure definition.\r
 \r
 /** @file\r
   Header file for NV data structure definition.\r
 \r
-Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -18,17 +18,101 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Guid/HiiPlatformSetupFormset.h>\r
 #include <Guid/SecureBootConfigHii.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_VARSTORE_ID  0x0001\r
-#define SECUREBOOT_CONFIGURATION_FORM_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
-#define KEY_SECURE_BOOT_ENABLE         0x5000\r
\r
 //\r
 // Nv Data structure referenced by IFR\r
 //\r
 typedef struct {\r
 //\r
 // Nv Data structure referenced by IFR\r
 //\r
 typedef struct {\r
-  BOOLEAN SecureBootState;\r
-  BOOLEAN HideSecureBoot;\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
 } SECUREBOOT_CONFIGURATION;\r
 \r
 #endif\r
index 99f728ead0cab465ce0195f57dfc2fde4ec4716d..ed4db131e9b0dd8547b4cf22e3915a25fee3abd1 100644 (file)
Binary files a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni and b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni differ