]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
SecurityPkg: SecureBootConfigDxe: Enhance secure boot string update logic
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / SecureBootConfigDxe / SecureBootConfigImpl.c
index 1d730dc288fc8a76ffa9e39dba6c21deed80178d..aafb3b374ade7b591745bd42ee3cfb99dd76f3a3 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   HII Config Access protocol implementation of SecureBoot configuration module.\r
 \r
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2016, 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
@@ -49,6 +49,8 @@ HII_VENDOR_DEVICE_PATH          mSecureBootHiiVendorDevicePath = {
 \r
 \r
 BOOLEAN mIsEnterSecureBootForm = FALSE;\r
+BOOLEAN mIsSelectedSecureBootModeForm = FALSE;\r
+BOOLEAN mIsSecureBootModeChanged = FALSE;\r
 \r
 //\r
 // OID ASN.1 Value for Hash Algorithms\r
@@ -1643,15 +1645,17 @@ LoadPeImage (
   // Note the size of FileHeader field is constant for both IA32 and X64 arch\r
   //\r
   if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32)\r
-      || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)) {\r
+      || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC)\r
+      || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)) {\r
     //\r
-    // IA-32 Architecture\r
+    // 32-bits Architecture\r
     //\r
     mImageType = ImageType_IA32;\r
     mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]);\r
   }\r
   else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64)\r
-          || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)) {\r
+          || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64)\r
+          || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64)) {\r
     //\r
     // 64-bits Architecture\r
     //\r
@@ -2806,6 +2810,308 @@ ON_EXIT:
            );\r
 }\r
 \r
+/**\r
+  Perform secure boot mode transition from User Mode by setting AuditMode \r
+  or DeployedMode variable.\r
+\r
+  @param[in]  NewMode          New secure boot mode.\r
+\r
+  @retval   EFI_SUCCESS        Secure Boot mode transition is successful.\r
+**/\r
+EFI_STATUS\r
+TransitionFromUserMode(\r
+  IN  UINT8 NewMode\r
+  )\r
+{\r
+  UINT8      Data;\r
+  EFI_STATUS Status;\r
+\r
+  if (NewMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
+    Data = 1;\r
+    Status = gRT->SetVariable(\r
+                    EFI_AUDIT_MODE_NAME,\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    sizeof(UINT8),\r
+                    &Data\r
+                    );\r
+    return Status;\r
+  } else if (NewMode == SECURE_BOOT_MODE_DEPLOYED_MODE) {\r
+    Data = 1;\r
+    Status = gRT->SetVariable(\r
+                    EFI_DEPLOYED_MODE_NAME,\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    sizeof(UINT8),\r
+                    &Data\r
+                    );\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Other case do nothing here. May Goto enroll PK page.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Perform secure boot mode transition from Setup Mode by setting AuditMode \r
+  variable.\r
+\r
+  @param[in]  NewMode          New secure boot mode.\r
+\r
+  @retval   EFI_SUCCESS        Secure Boot mode transition is successful.\r
+**/\r
+EFI_STATUS\r
+TransitionFromSetupMode(\r
+  IN UINT8 NewMode\r
+  )\r
+{\r
+  UINT8      Data;\r
+  EFI_STATUS Status;\r
+\r
+  Status = EFI_INVALID_PARAMETER;\r
+\r
+  if (NewMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
+    Data = 1;\r
+    Status = gRT->SetVariable(\r
+                    EFI_AUDIT_MODE_NAME,\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    sizeof(UINT8),\r
+                    &Data\r
+                    );\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Other case do nothing here. May Goto enroll PK page.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Perform secure boot mode transition from Audit Mode. Nothing is done here,\r
+  should goto enroll PK page.\r
+\r
+  @param[in]  NewMode          New secure boot mode.\r
+\r
+  @retval   EFI_SUCCESS        Secure Boot mode transition is successful.\r
+**/\r
+EFI_STATUS\r
+TransitionFromAuditMode(\r
+  IN UINT8 NewMode\r
+  )\r
+{\r
+  //\r
+  // Other case do nothing here. Should Goto enroll PK page.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+   Perform secure boot mode transition from Deployed Mode by setting Deployed Mode\r
+   variable to 0.\r
+\r
+  @param[in]  NewMode          New secure boot mode.\r
+\r
+  @retval   EFI_SUCCESS        Secure Boot mode transition is successful.\r
+**/\r
+EFI_STATUS\r
+TransitionFromDeployedMode(\r
+  IN UINT8 NewMode\r
+  )\r
+{\r
+  UINT8      Data;\r
+  EFI_STATUS Status;\r
+\r
+  //\r
+  // Platform specific logic. when physical presence,  Allow to set DeployedMode =:0\r
+  // to switch back to UserMode\r
+  //\r
+  if (NewMode == SECURE_BOOT_MODE_USER_MODE) {\r
+    Data = 0;\r
+    Status = gRT->SetVariable(\r
+                    EFI_DEPLOYED_MODE_NAME,\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    sizeof(UINT8),\r
+                    &Data\r
+                    );\r
+    DEBUG((EFI_D_INFO, "DeployedMode Status %x\n", Status));\r
+    return Status;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+   Perform main secure boot mode transition.\r
+\r
+  @param[in]  CurMode          New secure boot mode.\r
+  @param[in]  NewMode          New secure boot mode.\r
+\r
+  @retval   EFI_SUCCESS        Secure Boot mode transition is successful.\r
+**/\r
+EFI_STATUS\r
+SecureBootModeTransition(\r
+  IN  UINT8  CurMode,\r
+  IN  UINT8  NewMode\r
+  )\r
+{\r
+  EFI_STATUS                         Status;\r
+\r
+  //\r
+  // Set platform to be customized mode to ensure platform specific mode switch sucess\r
+  //\r
+  Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // SecureBootMode transition\r
+  //\r
+  switch (CurMode) {\r
+    case SECURE_BOOT_MODE_USER_MODE:\r
+      Status = TransitionFromUserMode(NewMode);\r
+      break;\r
+\r
+    case SECURE_BOOT_MODE_SETUP_MODE:\r
+      Status = TransitionFromSetupMode(NewMode);\r
+      break;\r
+\r
+    case SECURE_BOOT_MODE_AUDIT_MODE:\r
+      Status = TransitionFromAuditMode(NewMode);\r
+      break;\r
+\r
+    case SECURE_BOOT_MODE_DEPLOYED_MODE:\r
+      Status = TransitionFromDeployedMode(NewMode);\r
+      break;\r
+\r
+    default:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      ASSERT(FALSE);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+   Get current secure boot mode by retrieve data from SetupMode/AuditMode/DeployedMode.\r
+\r
+  @param[out]  SecureBootMode                Current secure boot mode.\r
+\r
+**/\r
+VOID\r
+ExtractSecureBootModeFromVariable(\r
+  OUT UINT8      *SecureBootMode\r
+  )\r
+{\r
+  UINT8     *SetupMode;\r
+  UINT8     *AuditMode;\r
+  UINT8     *DeployedMode;\r
+\r
+  SetupMode        = NULL;\r
+  AuditMode        = NULL;\r
+  DeployedMode     = NULL;\r
+\r
+  //\r
+  // Get AuditMode/DeployedMode from variable\r
+  //\r
+  GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
+  GetVariable2 (EFI_AUDIT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&AuditMode, NULL);\r
+  GetVariable2 (EFI_DEPLOYED_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&DeployedMode, NULL);\r
+  if (SetupMode != NULL && AuditMode != NULL && DeployedMode != NULL) {\r
+    if (*SetupMode == 0 && *AuditMode == 0 && *DeployedMode == 0) {\r
+      //\r
+      // User Mode\r
+      //\r
+      *SecureBootMode = SECURE_BOOT_MODE_USER_MODE;\r
+    } else if (*SetupMode == 1 && *AuditMode == 0 && *DeployedMode == 0) {\r
+      //\r
+      // Setup Mode\r
+      //\r
+      *SecureBootMode = SECURE_BOOT_MODE_SETUP_MODE;\r
+    } else if (*SetupMode == 1 && *AuditMode == 1 && *DeployedMode == 0) {\r
+      //\r
+      // Audit Mode\r
+      //\r
+      *SecureBootMode = SECURE_BOOT_MODE_AUDIT_MODE;\r
+    } else if (*SetupMode == 0 && *AuditMode == 0 && *DeployedMode == 1) {\r
+      //\r
+      // Deployed Mode\r
+      //\r
+      *SecureBootMode = SECURE_BOOT_MODE_DEPLOYED_MODE;\r
+    } else {\r
+      ASSERT(FALSE);\r
+    }\r
+  }else {\r
+    ASSERT(FALSE);\r
+  }\r
+\r
+  if (SetupMode != NULL) {\r
+    FreePool (SetupMode);\r
+  }\r
+  if (DeployedMode != NULL) {\r
+    FreePool (DeployedMode);\r
+  }\r
+  if (AuditMode != NULL) {\r
+    FreePool (AuditMode);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT\r
+ and STR_CUR_SECURE_BOOT_MODE_CONTENT.\r
+\r
+  @param[in]    PrivateData         Module's private data.\r
+\r
+  @return EFI_SUCCESS              Update secure boot strings successfully.\r
+  @return other                          Fail to update secure boot strings.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateSecureBootString(\r
+  IN SECUREBOOT_CONFIG_PRIVATE_DATA  *Private\r
+  ) {\r
+  EFI_STATUS  Status;\r
+  UINT8       CurSecureBootMode;\r
+  UINT8       *SecureBoot;\r
+\r
+  //\r
+  // Get current secure boot state.\r
+  //\r
+  Status = GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);\r
+  } else {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);\r
+  }\r
+  //\r
+  // Get current secure boot mode.\r
+  //\r
+  ExtractSecureBootModeFromVariable(&CurSecureBootMode);\r
+  \r
+  if (CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE) {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"UserMode", NULL);\r
+  } else if (CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE) {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"SetupMode", NULL);\r
+  } else if (CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"AuditMode", NULL);\r
+  } else if (CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) {\r
+    HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"DeployedMode", NULL);\r
+  }\r
+\r
+  FreePool(SecureBoot);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   This function extracts configuration from variable.\r
 \r
@@ -2818,12 +3124,10 @@ SecureBootExtractConfigFromVariable (
   )\r
 {\r
   UINT8     *SecureBootEnable;\r
-  UINT8     *SetupMode;\r
   UINT8     *SecureBootMode;\r
   EFI_TIME  CurrTime;\r
 \r
   SecureBootEnable = NULL;\r
-  SetupMode        = NULL;\r
   SecureBootMode   = NULL;\r
 \r
   //\r
@@ -2863,16 +3167,6 @@ SecureBootExtractConfigFromVariable (
     ConfigData->PhysicalPresent = FALSE;\r
   }\r
 \r
-  //\r
-  // If there is no PK then the Delete Pk button will be gray.\r
-  //\r
-  GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
-  if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
-    ConfigData->HasPk = FALSE;\r
-  } else  {\r
-    ConfigData->HasPk = TRUE;\r
-  }\r
-\r
   //\r
   // Get the SecureBootMode from CustomMode variable.\r
   //\r
@@ -2883,12 +3177,24 @@ SecureBootExtractConfigFromVariable (
     ConfigData->SecureBootMode = *(SecureBootMode);\r
   }\r
 \r
+  //\r
+  // Extact current Secure Boot Mode\r
+  //\r
+  ExtractSecureBootModeFromVariable(&ConfigData->CurSecureBootMode);\r
+\r
+  //\r
+  // If there is no PK then the Delete Pk button will be gray.\r
+  //\r
+  if (ConfigData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE || ConfigData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) {\r
+    ConfigData->HasPk = FALSE;\r
+  } else  {\r
+    ConfigData->HasPk = TRUE;\r
+  }\r
+\r
   if (SecureBootEnable != NULL) {\r
     FreePool (SecureBootEnable);\r
   }\r
-  if (SetupMode != NULL) {\r
-    FreePool (SetupMode);\r
-  }\r
+\r
   if (SecureBootMode != NULL) {\r
     FreePool (SecureBootMode);\r
   }\r
@@ -2937,7 +3243,6 @@ SecureBootExtractConfig (
   EFI_STRING                        ConfigRequestHdr;\r
   SECUREBOOT_CONFIG_PRIVATE_DATA    *PrivateData;\r
   BOOLEAN                           AllocatedRequest;\r
-  UINT8                             *SecureBoot;\r
 \r
   if (Progress == NULL || Results == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -2947,7 +3252,6 @@ SecureBootExtractConfig (
   ConfigRequestHdr = NULL;\r
   ConfigRequest    = NULL;\r
   Size             = 0;\r
-  SecureBoot       = NULL;\r
 \r
   ZeroMem (&Configuration, sizeof (Configuration));\r
   PrivateData      = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
@@ -2962,19 +3266,6 @@ SecureBootExtractConfig (
   //\r
   SecureBootExtractConfigFromVariable (&Configuration);\r
 \r
-  //\r
-  // Update current secure boot state.\r
-  //\r
-  GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL);\r
-  if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) {\r
-    HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL);\r
-  } else {\r
-    HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL);\r
-  }\r
-  if (SecureBoot != NULL) {\r
-    FreePool (SecureBoot);\r
-  }\r
-\r
   BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
   ConfigRequest = Request;\r
   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
@@ -3140,23 +3431,45 @@ SecureBootCallback (
   UINT16                          LabelId;\r
   UINT8                           *SecureBootEnable;\r
   UINT8                           *SecureBootMode;\r
-  UINT8                           *SetupMode;\r
   CHAR16                          PromptString[100];\r
+  UINT8                           CurSecureBootMode;\r
 \r
+  Status           = EFI_SUCCESS;\r
   SecureBootEnable = NULL;\r
   SecureBootMode   = NULL;\r
-  SetupMode        = NULL;\r
 \r
   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+  Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
+\r
+  //\r
+  // Retrieve uncommitted data from Browser\r
+  //\r
+  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
+  IfrNvData = AllocateZeroPool (BufferSize);\r
+  if (IfrNvData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);\r
 \r
   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
     if (QuestionId == KEY_SECURE_BOOT_MODE) {\r
+      //\r
+      // Update secure boot strings when opening this form\r
+      //\r
+      Status = UpdateSecureBootString(Private);\r
       mIsEnterSecureBootForm = TRUE;\r
+    } else if (QuestionId == KEY_TRANS_SECURE_BOOT_MODE){\r
+      //\r
+      // Secure Boot Policy variable changes after tranistion. Re-sync CurSecureBootMode\r
+      //\r
+      ExtractSecureBootModeFromVariable(&IfrNvData->CurSecureBootMode);\r
+      mIsSelectedSecureBootModeForm = TRUE;\r
+      mIsSecureBootModeChanged = FALSE;\r
     }\r
-\r
-    return EFI_SUCCESS;\r
+    goto EXIT;\r
   }\r
 \r
   if (Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
@@ -3166,32 +3479,23 @@ SecureBootCallback (
         Value->u8 = SECURE_BOOT_MODE_STANDARD;\r
         Status = EFI_SUCCESS;\r
       }\r
+    } else if (QuestionId == KEY_TRANS_SECURE_BOOT_MODE) {\r
+      if (mIsSelectedSecureBootModeForm) {\r
+        Value->u8 = IfrNvData->CurSecureBootMode;\r
+        Status = EFI_SUCCESS;\r
+      }\r
     }\r
-    return Status;\r
+    goto EXIT;\r
   }\r
 \r
   if ((Action != EFI_BROWSER_ACTION_CHANGED) &&\r
       (Action != EFI_BROWSER_ACTION_CHANGING) &&\r
       (Action != EFI_BROWSER_ACTION_FORM_CLOSE) &&\r
       (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This);\r
-\r
-  //\r
-  // Retrieve uncommitted data from Browser\r
-  //\r
-  BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
-  IfrNvData = AllocateZeroPool (BufferSize);\r
-  if (IfrNvData == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = EFI_UNSUPPORTED;\r
+    goto EXIT;\r
   }\r
 \r
-  Status = EFI_SUCCESS;\r
-\r
-  HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData);\r
-\r
   if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
 \r
     switch (QuestionId) {\r
@@ -3417,6 +3721,56 @@ SecureBootCallback (
           );\r
       }\r
       break;\r
+    case KEY_TRANS_SECURE_BOOT_MODE:\r
+      //\r
+      // Pop up to alert user want to change secure boot mode \r
+      //\r
+      if ((IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE && \r
+           (Value->u8 == SECURE_BOOT_MODE_AUDIT_MODE || Value->u8 == SECURE_BOOT_MODE_DEPLOYED_MODE))\r
+        ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE && \r
+           Value->u8 == SECURE_BOOT_MODE_AUDIT_MODE)\r
+        ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE && \r
+          Value->u8 == SECURE_BOOT_MODE_USER_MODE && IfrNvData->PhysicalPresent == 1)){\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Are you sure you want to switch secure boot mode?",\r
+          L"Press 'Y' to switch secure boot mode, 'N' to discard change and return",\r
+          NULL\r
+          );\r
+        if (Key.UnicodeChar != 'y' && Key.UnicodeChar != 'Y') {\r
+          //\r
+          // If not 'Y'/''y' restore to defualt secure boot mode\r
+          //\r
+          Value->u8 = IfrNvData->CurSecureBootMode;\r
+          goto EXIT;\r
+        }\r
+      } else if ((IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE && Value->u8 == SECURE_BOOT_MODE_USER_MODE)\r
+               ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE && Value->u8 == SECURE_BOOT_MODE_SETUP_MODE)\r
+               ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE && Value->u8 == SECURE_BOOT_MODE_DEPLOYED_MODE)\r
+               ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE && Value->u8 == SECURE_BOOT_MODE_SETUP_MODE)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Secure boot mode tranistion requires PK change",\r
+          L"Please go to link below to update PK",\r
+          NULL\r
+          );\r
+      } else {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto EXIT;\r
+      }\r
+\r
+      Status = SecureBootModeTransition(IfrNvData->CurSecureBootMode, Value->u8);\r
+      //\r
+      // Secure Boot Policy variable may change after tranistion. Re-sync CurSecureBootMode\r
+      //\r
+      ExtractSecureBootModeFromVariable(&CurSecureBootMode);\r
+      if (IfrNvData->CurSecureBootMode != CurSecureBootMode) {\r
+        IfrNvData->CurSecureBootMode = CurSecureBootMode;\r
+        mIsSecureBootModeChanged = TRUE;\r
+      }\r
+      break;\r
 \r
     default:\r
       if (QuestionId >= FILE_OPTION_GOTO_OFFSET) {\r
@@ -3507,7 +3861,13 @@ SecureBootCallback (
     case KEY_SECURE_BOOT_MODE:\r
       mIsEnterSecureBootForm = FALSE;\r
       break;\r
-\r
+    case KEY_TRANS_SECURE_BOOT_MODE:\r
+      mIsSelectedSecureBootModeForm = FALSE;\r
+      if (mIsSecureBootModeChanged) {\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
+      }\r
+      mIsSecureBootModeChanged = FALSE;\r
+      break;\r
     case KEY_SECURE_BOOT_KEK_GUID:\r
     case KEY_SECURE_BOOT_SIGNATURE_GUID_DB:\r
     case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX:\r
@@ -3526,8 +3886,7 @@ SecureBootCallback (
       break;\r
 \r
     case KEY_SECURE_BOOT_DELETE_PK:\r
-      GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL);\r
-      if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) {\r
+      if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE || IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) {\r
         IfrNvData->DeletePk = TRUE;\r
         IfrNvData->HasPk    = FALSE;\r
         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
@@ -3536,9 +3895,6 @@ SecureBootCallback (
         IfrNvData->HasPk    = TRUE;\r
         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
       }\r
-      if (SetupMode != NULL) {\r
-        FreePool (SetupMode);\r
-      }\r
       break;\r
     default:\r
       if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) {\r
@@ -3573,10 +3929,13 @@ SecureBootCallback (
     }\r
   }\r
 \r
+EXIT:\r
+\r
   if (!EFI_ERROR (Status)) {\r
     BufferSize = sizeof (SECUREBOOT_CONFIGURATION);\r
     HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL);\r
   }\r
+\r
   FreePool (IfrNvData);\r
 \r
   return EFI_SUCCESS;\r