[edk2] [Patch][edk2-platforms/devel-MinnowBoard3-UDK2017] Security of Setup Variable

Guo, Mang posted 1 patch 6 years, 9 months ago
Failed in applying to current master (apply log)
Platform/BroxtonPlatformPkg/BuildBios.bat          |  11 +-
.../PlatformPreMemPei/MultiPlatSupport.h           | 201 ++++++++++++++++++++
.../PlatformPreMemPei/PlatformInitPreMem.c         | 207 +++++++++++++++++++++
.../PlatformPreMemPei/PlatformInitPreMem.h         |   4 +
.../PlatformSetupDxe/PlatformSetupDxe.c            |  38 ++++
.../PlatformSettings/PlatformSetupDxe/Vfr.vfr      |  10 +-
6 files changed, 465 insertions(+), 6 deletions(-)
create mode 100644 Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/MultiPlatSupport.h
[edk2] [Patch][edk2-platforms/devel-MinnowBoard3-UDK2017] Security of Setup Variable
Posted by Guo, Mang 6 years, 9 months ago
System can still boot to shell and OS successfully after EFI variable deletion/corruption.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Guo Mang <mang.guo@intel.com>
---
 Platform/BroxtonPlatformPkg/BuildBios.bat          |  11 +-
 .../PlatformPreMemPei/MultiPlatSupport.h           | 201 ++++++++++++++++++++
 .../PlatformPreMemPei/PlatformInitPreMem.c         | 207 +++++++++++++++++++++
 .../PlatformPreMemPei/PlatformInitPreMem.h         |   4 +
 .../PlatformSetupDxe/PlatformSetupDxe.c            |  38 ++++
 .../PlatformSettings/PlatformSetupDxe/Vfr.vfr      |  10 +-
 6 files changed, 465 insertions(+), 6 deletions(-)
 create mode 100644 Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/MultiPlatSupport.h

diff --git a/Platform/BroxtonPlatformPkg/BuildBios.bat b/Platform/BroxtonPlatformPkg/BuildBios.bat
index f656876..2ecc28d 100644
--- a/Platform/BroxtonPlatformPkg/BuildBios.bat
+++ b/Platform/BroxtonPlatformPkg/BuildBios.bat
@@ -387,10 +387,15 @@ if not exist "%AutoGenPath%" (
 findstr /L "_PCD_VALUE_" %AutoGenPath% > %STITCH_PATH%\FlashMap.h
 
 echo Running FCE...
+copy /b %BUILD_PATH%\FV\FvIBBM.fv + /b %BUILD_PATH%\FV\Soc.fd /b %BUILD_PATH%\FV\Temp.fd
 :: Extract Hii data from build and store a copy in HiiDefaultData.txt
-fce.exe read -i %BUILD_PATH%\FV\Soc.fd > %BUILD_PATH%\FV\HiiDefaultData.txt 2>>EDK2.log
+:: UQI 0006 005C 0078 0030 0031 0030 0031 is for question prompt(STR_IPU_ENABLED)
+:: First 0006 is the length of string; Next six byte values are mapped to STR_IPU_ENABLED string value defined in Platform\BroxtonPlatformPkg\Common\PlatformSettings\PlatformSetupDxe\VfrStrings.uni.
+fce.exe read -i %BUILD_PATH%\FV\Temp.fd 0006 005C 0078 0030 0031 0030 0031 > %BUILD_PATH%\FV\HiiDefaultData.txt 2>>EDK2.log
 :: Generate the Setup variable and save changes to BxtXXX.fd
-fce.exe update -i %BUILD_PATH%\FV\Soc.fd -s %BUILD_PATH%\FV\HiiDefaultData.txt -o %BUILD_PATH%\FV\Bxt%Arch%.fd  1>>EDK2.log 2>&1
+:: B73FE497-B92E-416e-8326-45AD0D270091 is the GUID of IBBM FV
+fce.exe update -i %BUILD_PATH%\FV\Temp.fd -s %BUILD_PATH%\FV\HiiDefaultData.txt -o %BUILD_PATH%\FV\Bxt%Arch%.fd  -g B73FE497-B92E-416e-8326-45AD0D270091 -a 1>>EDK2.log 2>&1
+split -f %BUILD_PATH%\FV\Bxt%Arch%.fd -s 0x35000 -o %BUILD_PATH%\FV\FvIBBM.fv
 
 if ErrorLevel 1 goto BldFail
 
@@ -401,7 +406,7 @@ if "%BUILD_TYPE%"=="R" set BUILD_TYPE=R
 
 echo Copy BIOS...
 set BIOS_Name=%BOARD_ID%_%Arch%_%BUILD_TYPE%_%VERSION_MAJOR%_%VERSION_MINOR%
-copy /y/b %BUILD_PATH%\FV\Bxt%Arch%.fd  %STITCH_PATH%\%BIOS_Name%.ROM >nul
+copy /y/b %BUILD_PATH%\FV\Soc.fd          %STITCH_PATH%\%BIOS_Name%.ROM >nul
 copy /y   %STITCH_PATH%\FlashMap.h        %STITCH_PATH%\%BIOS_Name%.map >nul
 
 set Storage_Folder=%STITCH_PATH%\%BIOS_Name%
diff --git a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/MultiPlatSupport.h b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/MultiPlatSupport.h
new file mode 100644
index 0000000..7f21da2
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/MultiPlatSupport.h
@@ -0,0 +1,201 @@
+/**@file
+
+Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __MULTI_PLATFORM_SUPPORT_H__
+#define __MULTI_PLATFORM_SUPPORT_H__
+
+extern EFI_GUID gDefaultDataOptSizeFileGuid;
+
+///
+/// Alignment of variable name and data, according to the architecture:
+/// * For IA-32 and Intel(R) 64 architectures: 1.
+/// * For IA-64 architecture: 8.
+///
+#if defined (MDE_CPU_IPF)
+#define ALIGNMENT         8
+#else
+#define ALIGNMENT         1
+#endif
+
+//
+// GET_PAD_SIZE calculates the miminal pad bytes needed to make the current pad size satisfy the alignment requirement.
+//
+#if (ALIGNMENT == 1)
+#define GET_PAD_SIZE(a) (0)
+#else
+#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1))
+#endif
+
+///
+/// Alignment of Variable Data Header in Variable Store region.
+///
+#define HEADER_ALIGNMENT  4
+#define HEADER_ALIGN(Header)  (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1)))
+
+///
+/// Status of Variable Store Region.
+///
+/*typedef enum {
+  EfiRaw,
+  EfiValid,
+  EfiInvalid,
+  EfiUnknown
+} VARIABLE_STORE_STATUS;*/
+
+#pragma pack(1)
+
+///
+/// Variable Store Header Format and State.
+///
+#define VARIABLE_STORE_FORMATTED          0x5a
+#define VARIABLE_STORE_HEALTHY            0xfe
+
+///
+/// Variable Store region header.
+///
+/*typedef struct {
+  ///
+  /// Variable store region signature.
+  ///
+  EFI_GUID  Signature;
+  ///
+  /// Size of entire variable store, 
+  /// including size of variable store header but not including the size of FvHeader.
+  ///
+  UINT32  Size;
+  ///
+  /// Variable region format state.
+  ///
+  UINT8   Format;
+  ///
+  /// Variable region healthy state.
+  ///
+  UINT8   State;
+  UINT16  Reserved;
+  UINT32  Reserved1;
+} VARIABLE_STORE_HEADER;*/
+
+///
+/// Variable data start flag.
+///
+#define VARIABLE_DATA                     0x55AA
+
+///
+/// Variable State flags.
+///
+#define VAR_IN_DELETED_TRANSITION     0xfe  ///< Variable is in obsolete transition.
+#define VAR_DELETED                   0xfd  ///< Variable is obsolete.
+#define VAR_HEADER_VALID_ONLY         0x7f  ///< Variable header has been valid.
+#define VAR_ADDED                     0x3f  ///< Variable has been completely added.
+
+///
+/// Single Variable Data Header Structure.
+///
+/*typedef struct {
+  ///
+  /// Variable Data Start Flag.
+  ///
+  UINT16      StartId;
+  ///
+  /// Variable State defined above.
+  ///
+  UINT8       State;
+  UINT8       Reserved;
+  ///
+  /// Attributes of variable defined in UEFI specification.
+  ///
+  UINT32      Attributes;
+  ///
+  /// Size of variable null-terminated Unicode string name.
+  ///
+  UINT32      NameSize;
+  ///
+  /// Size of the variable data without this header.
+  ///
+  UINT32      DataSize;
+  ///
+  /// A unique identifier for the vendor that produces and consumes this varaible.
+  ///
+  EFI_GUID    VendorGuid;
+} VARIABLE_HEADER;*/
+
+///
+/// Single Variable Data Header Structure for Auth variable.
+///
+/*typedef struct {
+  ///
+  /// Variable Data Start Flag.
+  ///
+  UINT16      StartId;
+  ///
+  /// Variable State defined above.
+  ///
+  UINT8       State;
+  UINT8       Reserved;
+  ///
+  /// Attributes of variable defined in UEFI specification.
+  ///
+  UINT32      Attributes;
+  ///
+  /// Associated monotonic count value against replay attack.
+  ///
+  UINT64      MonotonicCount;
+  ///
+  /// Associated TimeStamp value against replay attack. 
+  ///
+  EFI_TIME    TimeStamp;
+  ///
+  /// Index of associated public key in database.
+  ///
+  UINT32      PubKeyIndex;
+  ///
+  /// Size of variable null-terminated Unicode string name.
+  ///
+  UINT32      NameSize;
+  ///
+  /// Size of the variable data without this header.
+  ///
+  UINT32      DataSize;
+  ///
+  /// A unique identifier for the vendor that produces and consumes this varaible.
+  ///
+  EFI_GUID    VendorGuid;
+} AUTHENTICATED_VARIABLE_HEADER;*/
+
+typedef struct {
+  UINT16 DefaultId;
+  UINT16 BoardId;
+} DEFAULT_INFO;
+
+typedef struct {
+  UINT16 Offset;
+  UINT8  Value;
+} DATA_DELTA;
+
+typedef struct {
+  //
+  // HeaderSize includes HeaderSize fields and DefaultInfo arrays
+  //
+  UINT16 HeaderSize;
+  //
+  // DefaultInfo arrays those have the same default setting.
+  //
+  DEFAULT_INFO DefaultInfo[1];
+  //
+  // Default data is stored as variable storage or the array of DATA_DELTA. 
+  //
+} DEFAULT_DATA;
+
+#pragma pack()
+
+#endif
diff --git a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.c b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.c
index fe454bf..49121ae 100644
--- a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.c
+++ b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.c
@@ -75,6 +75,15 @@
 #include <Library/PlatformSecLib.h>
 #include <Library/TimerLib.h>
 
+#include <PiPei.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <MultiPlatSupport.h>
+
+//
+// GUID used in FCE. FCE generate ffs file with this GUID.
+//
+EFI_GUID gDefaultDataOptSizeFileGuid = { 0x003e7b41, 0x98a2, 0x4be2, { 0xb2, 0x7a, 0x6c, 0x30, 0xc7, 0x65, 0x52, 0x25 }};
+
 #if (ENBDT_PF_ENABLE == 1)
 //
 //SSC
@@ -913,6 +922,7 @@ PlatformInitPreMemEntryPoint (
   PEI_BOARD_PRE_MEM_INIT_PPI       *BoardPreMemInitPpi;
   UINTN                            Instance;
   UINT64                           AcpiVariableSetCompatibility;
+  UINTN                            VarSize;
 
   Status = (*PeiServices)->RegisterForShadow (FileHandle);
 
@@ -1116,6 +1126,29 @@ PlatformInitPreMemEntryPoint (
     Tick = CarMap->IbblPerfRecord4;
     PERF_END_EX (NULL, "IBBMVer", "IBBL", Tick, 0x1041);
 
+
+    VarSize = sizeof (SYSTEM_CONFIGURATION);
+    Status = VariableServices->GetVariable (
+                    VariableServices,
+                    L"Setup",
+                    &gEfiSetupVariableGuid,
+                    NULL,
+                    &VarSize,
+                    &SystemConfiguration
+                    );
+    if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
+      Status = PlatformCreateDefaultVariableHob (EFI_HII_DEFAULT_CLASS_STANDARD);
+      ASSERT_EFI_ERROR (Status);
+    }
+    Status = VariableServices->GetVariable (
+                    VariableServices,
+                    L"Setup",
+                    &gEfiSetupVariableGuid,
+                    NULL,
+                    &VarSize,
+                    &SystemConfiguration
+                    );
+    ASSERT_EFI_ERROR (Status);
     //
     // Normal boot - build Hob for SEC performance data.
     //
@@ -1372,3 +1405,177 @@ ReadBxtIPlatformIds (
   return EFI_SUCCESS;
 }
 
+
+/**
+Description:
+
+  This function finds the matched default data and create GUID hob for it. 
+
+Arguments:
+
+  DefaultId - Specifies the type of defaults to retrieve.
+
+Returns:
+
+  EFI_SUCCESS - The matched default data is found.
+  EFI_NOT_FOUND - The matched default data is not found.
+  EFI_OUT_OF_RESOURCES - No enough resource to create HOB.
+
+**/
+EFI_STATUS
+PlatformCreateDefaultVariableHob (
+  IN UINT16  DefaultId
+  )
+
+{
+  UINTN                      FvInstance;
+  EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+  EFI_FFS_FILE_HEADER        *FfsHeader;
+  UINT32                     FileSize;
+  EFI_COMMON_SECTION_HEADER  *Section;
+  UINT32                     SectionLength;
+  BOOLEAN                    DefaultSettingIsFound;
+  DEFAULT_DATA               *DefaultData;
+  DEFAULT_INFO               *DefaultInfo;
+  VARIABLE_STORE_HEADER      *VarStoreHeader;
+  VARIABLE_STORE_HEADER      *VarStoreHeaderHob;
+  UINT8                      *VarHobPtr;
+  UINT8                      *VarPtr;
+  UINT32                     VarDataOffset;
+  UINT32                     VarHobDataOffset;
+  BOOLEAN                    IsFirstSection;
+  DATA_DELTA                 *DataDelta;
+  UINTN                      DataDeltaSize;
+  UINTN                      Index;
+  CONST EFI_PEI_SERVICES     **PeiServices;
+
+  //
+  // Get PeiService pointer
+  //
+  PeiServices = GetPeiServicesTablePointer ();
+
+  //
+  // Find the FFS file that stores all default data.
+  //
+  DefaultSettingIsFound = FALSE;
+  FvInstance            = 0;
+  FfsHeader             = NULL;
+  while (((*PeiServices)->FfsFindNextVolume (PeiServices, FvInstance, (VOID **) &FvHeader) == EFI_SUCCESS) &&
+         (!DefaultSettingIsFound)) {
+    FfsHeader = NULL;
+    while ((*PeiServices)->FfsFindNextFile (PeiServices, EFI_FV_FILETYPE_FREEFORM, FvHeader, (VOID **) &FfsHeader) == EFI_SUCCESS) {
+      if (CompareGuid ((EFI_GUID *) FfsHeader, &gDefaultDataOptSizeFileGuid)) {
+        DefaultSettingIsFound = TRUE;
+        break;
+      }
+    }
+    FvInstance ++;
+  }
+
+  //
+  // FFS file is not found.
+  //
+  if (!DefaultSettingIsFound) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Find the matched default data for the input default ID and plat ID.
+  //
+  DefaultSettingIsFound = FALSE;
+  VarStoreHeaderHob     = NULL;
+  VarHobPtr      = NULL;
+  DataDelta      = NULL;
+  DataDeltaSize  = 0;
+  IsFirstSection = TRUE;
+  VarStoreHeader = NULL;
+  Section  = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);
+  FileSize = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;
+  while (((UINTN) Section < (UINTN) FfsHeader + FileSize) && !DefaultSettingIsFound) {
+    DefaultData = (DEFAULT_DATA *) (Section + 1);
+    DefaultInfo   = &(DefaultData->DefaultInfo[0]);
+    SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
+
+    if (IsFirstSection) {
+      //
+      // Create HOB to store default data so that Variable driver can use it.
+      // Allocate more data for header alignment.
+      //
+      VarStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) DefaultData + DefaultData->HeaderSize);
+      VarStoreHeaderHob = (VARIABLE_STORE_HEADER *) BuildGuidHob (&VarStoreHeader->Signature, VarStoreHeader->Size + HEADER_ALIGNMENT - 1);
+      if (VarStoreHeaderHob == NULL) {
+        //
+        // No enough hob resource.
+        //
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      //
+      // Copy variable storage header.
+      //
+      CopyMem (VarStoreHeaderHob, VarStoreHeader, sizeof (VARIABLE_STORE_HEADER));
+      //
+      // Copy variable data.
+      //
+      VarPtr           = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeader + 1));
+      VarDataOffset    = (UINT32) ((UINTN) VarPtr - (UINTN) VarStoreHeader);
+      VarHobPtr        = (UINT8 *) HEADER_ALIGN ((UINTN) (VarStoreHeaderHob + 1));
+      VarHobDataOffset = (UINT32) ((UINTN) VarHobPtr - (UINTN) VarStoreHeaderHob);
+      CopyMem (VarHobPtr, VarPtr, VarStoreHeader->Size - VarDataOffset);
+      //
+      // Update variable size.
+      //
+      VarStoreHeaderHob->Size = VarStoreHeader->Size - VarDataOffset + VarHobDataOffset;
+
+      //
+      // Update Delta Data
+      //
+      VarHobPtr = (UINT8 *) VarStoreHeaderHob - VarDataOffset + VarHobDataOffset;
+    } else {
+      //
+      // Apply delta setting
+      //
+      DataDelta     = (DATA_DELTA *) ((UINT8 *) DefaultData + DefaultData->HeaderSize);
+      DataDeltaSize = SectionLength - sizeof (EFI_COMMON_SECTION_HEADER) - DefaultData->HeaderSize;
+      for (Index = 0; Index < DataDeltaSize / sizeof (DATA_DELTA); Index ++) {
+        *((UINT8 *) VarHobPtr + DataDelta[Index].Offset) = DataDelta[Index].Value;
+      }
+    }
+
+    //
+    // Find the matched DefaultId
+    //
+    while ((UINTN) DefaultInfo < (UINTN) DefaultData + DefaultData->HeaderSize) {
+      if (DefaultInfo->DefaultId == DefaultId) {
+        DefaultSettingIsFound = TRUE;
+        break;
+      }
+      DefaultInfo ++;
+    }
+    //
+    // Size is 24 bits wide so mask upper 8 bits. 
+    // SectionLength is adjusted it is 4 byte aligned.
+    // Go to the next section
+    //
+    SectionLength = (SectionLength + 3) & (~3);
+    ASSERT (SectionLength != 0);
+    Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
+    IsFirstSection = FALSE;
+  }
+  //
+  // Matched default data is not found.
+  //
+  if (!DefaultSettingIsFound) {
+    //
+    // Change created HOB type to be unused.
+    //
+    if (VarStoreHeaderHob != NULL) {
+      ((EFI_HOB_GUID_TYPE *)((UINT8 *) VarStoreHeaderHob - sizeof (EFI_HOB_GUID_TYPE)))->Header.HobType = EFI_HOB_TYPE_UNUSED;
+    }
+    return EFI_NOT_FOUND;
+  }
+
+
+  return EFI_SUCCESS;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.h b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.h
index 17b4dad..3aa5033 100644
--- a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.h
+++ b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformPreMemPei/PlatformInitPreMem.h
@@ -139,5 +139,9 @@ InstallMonoStatusCode (
   IN CONST EFI_PEI_SERVICES    **PeiServices
   );
 
+EFI_STATUS 
+PlatformCreateDefaultVariableHob (
+IN UINT16  DefaultId
+);
 #endif
 
diff --git a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/PlatformSetupDxe.c b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/PlatformSetupDxe.c
index 54c751f..ff59496 100644
--- a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/PlatformSetupDxe.c
+++ b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/PlatformSetupDxe.c
@@ -402,6 +402,8 @@ SystemConfigCallback (
   CHAR16                                     *StringBuffer2;
   EFI_STATUS                                 Status;
   SEC_OPERATION_PROTOCOL                     *SeCOp;
+  UINTN                        VariableSize;
+  UINT32                       VariableAttributes;
 
   StringBuffer1 = AllocateZeroPool (200 * sizeof (CHAR16));
   ASSERT (StringBuffer1 != NULL);
@@ -412,7 +414,43 @@ SystemConfigCallback (
     return EFI_OUT_OF_RESOURCES;
   }
 
+  Private = EFI_CALLBACK_INFO_FROM_THIS (This);
+  FakeNvData = &Private->FakeNvData;
+
   switch (Action) {
+    case EFI_BROWSER_ACTION_FORM_OPEN:
+    {
+      if (KeyValue == 0x1003) {
+        if (!HiiGetBrowserData (&mSystemConfigGuid, mVariableName, sizeof (SYSTEM_CONFIGURATION), (UINT8 *) FakeNvData)) {
+           return EFI_NOT_FOUND;
+        }
+
+        CheckSystemConfigLoad (FakeNvData);
+
+        //
+        // Pass changed uncommitted data back to Form Browser
+        //
+        HiiSetBrowserData (&mSystemConfigGuid, mVariableName, sizeof (SYSTEM_CONFIGURATION), (UINT8 *) FakeNvData, NULL);
+      }
+      break;
+    }
+    case EFI_BROWSER_ACTION_SUBMITTED:
+    {
+      if (KeyValue == 0x1002) {
+        VariableSize = sizeof (SYSTEM_CONFIGURATION);
+        Status = gRT->GetVariable (
+                        L"Setup",
+                        &gEfiSetupVariableGuid,
+                        &VariableAttributes,
+                        &VariableSize,
+                        FakeNvData
+                        );
+        if (!EFI_ERROR (Status)) {
+          CheckSystemConfigSave (FakeNvData);
+        }
+      }
+      break;
+    }
     case EFI_BROWSER_ACTION_CHANGING:
     case EFI_BROWSER_ACTION_CHANGED:
     {
diff --git a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/Vfr.vfr b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/Vfr.vfr
index 4b10a49..5e5b4fa 100644
--- a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/Vfr.vfr
+++ b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/Vfr.vfr
@@ -16,6 +16,9 @@
 #include "PlatformSetupDxeStrDefs.h"
 #include "Guid/SetupVariable.h"
 
+#define EFI_VARIABLE_NON_VOLATILE       0x00000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define EFI_VARIABLE_RUNTIME_ACCESS     0x00000004
 
 formset
   guid     = SYSTEM_CONFIGURATION_GUID,
@@ -24,8 +27,7 @@ formset
   class    = 1,
   subclass = 0,
 
-
-  varstore SYSTEM_CONFIGURATION, name = Setup, guid = SYSTEM_CONFIGURATION_GUID;
+  efivarstore SYSTEM_CONFIGURATION, attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS, name = Setup, guid = SYSTEM_CONFIGURATION_GUID;
   form formid = ROOT_FORM_ID,
     title    = STRING_TOKEN(STR_SYSTEM_SETUP_TITLE);
 
@@ -34,7 +36,9 @@ formset
     //
     goto ROOT_MAIN_FORM_ID,
       prompt = STRING_TOKEN(STR_MAIN_TITLE),
-      help   = STRING_TOKEN(STR_MAIN_HELP);
+      help   = STRING_TOKEN(STR_MAIN_HELP),
+      flags  = INTERACTIVE,                      // INTERACTIVE indicate it's marked with EFI_IFR_FLAG_CALLBACK
+      key    = 0x1003;                           // Question ID which will be passed-in in COnfigAccess.Callback()
 
     //
     // Jump to  2)CPU Configuration Form 
-- 
2.10.1.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel