[edk2] [RFC V2 3/5] MdeModulePkg/SetupBrowser: Handle questions with Bit VarStore

Dandan Bi posted 5 patches 143 weeks ago

[edk2] [RFC V2 3/5] MdeModulePkg/SetupBrowser: Handle questions with Bit VarStore

Posted by Dandan Bi 143 weeks ago
For oneof/numeric/CheckBox(storage can be Bit VarStore)
If we want question value can be updated and shown correctly
in UI page, we need do enhancements in following cases:
1. Parse the Ifr data to get the bit VarStore info correctly.
2. Set/get value to/from bit VarStore correctly.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c  | 140 ++++++++++++++++-----
 MdeModulePkg/Universal/SetupBrowserDxe/Setup.c     | 108 +++++++++++++++-
 MdeModulePkg/Universal/SetupBrowserDxe/Setup.h     |   3 +
 .../Universal/SetupBrowserDxe/SetupBrowserDxe.inf  |   1 +
 4 files changed, 214 insertions(+), 38 deletions(-)

diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
index 6b3e5e0..0de1144 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
@@ -15,10 +15,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Setup.h"
 
 UINT16           mStatementIndex;
 UINT16           mExpressionOpCodeIndex;
 EFI_QUESTION_ID  mUsedQuestionId;
+BOOLEAN          mQuestionReferBitVar = FALSE;
+
 extern LIST_ENTRY      gBrowserStorageList;
 /**
   Initialize Statement header members.
 
   @param  OpCodeData             Pointer of the raw OpCode data.
@@ -57,10 +59,11 @@ CreateStatement (
 
   Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
 
   Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
   Statement->OpCode  = (EFI_IFR_OP_HEADER *) OpCodeData;
+  Statement->QuestionReferToBitFields = FALSE;
 
   StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
   CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
   CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
 
@@ -1312,10 +1315,12 @@ ParseOpCodes (
   BOOLEAN                 InUnknownScope;
   UINT8                   UnknownDepth;
   FORMSET_DEFAULTSTORE    *PreDefaultStore;
   LIST_ENTRY              *DefaultLink;
   BOOLEAN                 HaveInserted;
+  UINT16                  ByteWidth;
+  UINT16                  BitWidth;
 
   SuppressForQuestion      = FALSE;
   SuppressForOption        = FALSE;
   InScopeDisable           = FALSE;
   DepthOfDisable           = 0;
@@ -1978,47 +1983,103 @@ ParseOpCodes (
       ASSERT(CurrentStatement != NULL);
 
       CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
       Value = &CurrentStatement->HiiValue;
 
-      switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
-      case EFI_IFR_NUMERIC_SIZE_1:
-        CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
-        CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
-        CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
-        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
-        Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
-        break;
+      if (mQuestionReferBitVar) {
+        mQuestionReferBitVar = FALSE;
+        CurrentStatement->StorageBitWidth = CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE_BIT;
+        CurrentStatement->QuestionReferToBitFields = TRUE;
+        CurrentStatement->VarBitOffset = CurrentStatement->VarStoreInfo.VarOffset;
+        CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->VarBitOffset / 8;
+        BitWidth = CurrentStatement->VarBitOffset - (CurrentStatement->VarStoreInfo.VarOffset * 8) +  CurrentStatement->StorageBitWidth;
+        ByteWidth = BitWidth / 8;
+        CurrentStatement->StorageWidth = (BitWidth % 8 == 0? ByteWidth: ByteWidth + 1);
+        CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue;
+        CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue;
+        CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step;
+        if (Operand == EFI_IFR_NUMERIC_OP) {
+          switch (CurrentStatement->StorageWidth) {
+            case 1:
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags &= EFI_IFR_DISPLAY_BIT;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags >>= 2;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_8;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue = (UINT8)CurrentStatement->Minimum;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue = (UINT8)CurrentStatement->Maximum;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step = (UINT8)CurrentStatement->Step;
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+              break;
+            case 2:
+             ((EFI_IFR_NUMERIC *) OpCodeData)->Flags &= EFI_IFR_DISPLAY_BIT;
+             ((EFI_IFR_NUMERIC *) OpCodeData)->Flags >>= 2;
+             ((EFI_IFR_NUMERIC *) OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_16;
+             ((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue = (UINT16)CurrentStatement->Minimum;
+             ((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue = (UINT16)CurrentStatement->Maximum;
+             ((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step = (UINT16)CurrentStatement->Step;
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+              break;
+            case 3:
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags &= EFI_IFR_DISPLAY_BIT;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags >>= 2;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_32;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue = (UINT32)CurrentStatement->Minimum;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue = (UINT32)CurrentStatement->Maximum;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step = (UINT32)CurrentStatement->Step;
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+              break;
+            case 4:
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags &= EFI_IFR_DISPLAY_BIT;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags >>= 2;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->Flags |= EFI_IFR_TYPE_NUM_SIZE_32;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue = (UINT32)CurrentStatement->Minimum;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue = (UINT32)CurrentStatement->Maximum;
+              ((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step = (UINT32)CurrentStatement->Step;
+              Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+              break;
+            default:
+              break;
+          }
+        }
+      } else {
 
-      case EFI_IFR_NUMERIC_SIZE_2:
-        CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
-        CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
-        CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step,     sizeof (UINT16));
-        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
-        Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
-        break;
+        switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
+        case EFI_IFR_NUMERIC_SIZE_1:
+          CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
+          CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
+          CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
+          CurrentStatement->StorageWidth = (UINT16) sizeof (UINT8);
+          Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+          break;
 
-      case EFI_IFR_NUMERIC_SIZE_4:
-        CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
-        CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
-        CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step,     sizeof (UINT32));
-        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
-        Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
-        break;
+        case EFI_IFR_NUMERIC_SIZE_2:
+          CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
+          CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
+          CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step,     sizeof (UINT16));
+          CurrentStatement->StorageWidth = (UINT16) sizeof (UINT16);
+          Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+          break;
 
-      case EFI_IFR_NUMERIC_SIZE_8:
-        CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
-        CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
-        CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step,     sizeof (UINT64));
-        CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
-        Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-        break;
+        case EFI_IFR_NUMERIC_SIZE_4:
+          CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
+          CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
+          CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step,     sizeof (UINT32));
+          CurrentStatement->StorageWidth = (UINT16) sizeof (UINT32);
+          Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+          break;
 
-      default:
-        break;
-      }
+        case EFI_IFR_NUMERIC_SIZE_8:
+          CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
+          CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
+          CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step,     sizeof (UINT64));
+          CurrentStatement->StorageWidth = (UINT16) sizeof (UINT64);
+          Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+          break;
 
+        default:
+          break;
+        }
+      }
       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
 
       if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
         SuppressForOption = TRUE;
       }
@@ -2045,10 +2106,21 @@ ParseOpCodes (
 
       CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
       CurrentStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
 
+      if (mQuestionReferBitVar) {
+        mQuestionReferBitVar = FALSE;
+        CurrentStatement->StorageBitWidth = 1;
+        CurrentStatement->QuestionReferToBitFields = TRUE;
+        CurrentStatement->VarBitOffset = CurrentStatement->VarStoreInfo.VarOffset;
+        CurrentStatement->VarStoreInfo.VarOffset = CurrentStatement->VarBitOffset / 8;
+        BitWidth = CurrentStatement->VarBitOffset - (CurrentStatement->VarStoreInfo.VarOffset * 8) +  CurrentStatement->StorageBitWidth;
+        ByteWidth = BitWidth / 8;
+        CurrentStatement->StorageWidth = (BitWidth % 8 == 0? ByteWidth: ByteWidth + 1);
+      }
+
       InitializeRequestElement (FormSet, CurrentStatement, CurrentForm);
 
       break;
 
     case EFI_IFR_STRING_OP:
@@ -2594,10 +2666,14 @@ ParseOpCodes (
     //
     // Vendor specific
     //
     case EFI_IFR_GUID_OP:     
       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+      if (CompareGuid ((EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)), &gEfiIfrBitvarstoreGuid)) {
+        Scope = 0;
+        mQuestionReferBitVar = TRUE;
+      }
       break;
 
     //
     // Scope End
     //
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
index 83dc2b8..73dab0a 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -1392,10 +1392,16 @@ BufferToValue (
   UINTN                        Index;
   UINT8                        DigitUint8;
   BOOLEAN                      IsString;
   UINTN                        Length;
   EFI_STATUS                   Status;
+  UINT8                        *Buffer;
+  UINT32                        Mask;
+  UINT32                        PreBits;
+  UINT32                        BufferValue;
+
+  Buffer = NULL;
 
   IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ?  TRUE : FALSE);
   if (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER || 
       Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
     IsBufferStorage = TRUE;
@@ -1413,11 +1419,17 @@ BufferToValue (
     Dst = Question->BufferValue;
   } else {
     //
     // Other type of Questions
     //
-    Dst = (UINT8 *) &Question->HiiValue.Value;
+    if (Question->QuestionReferToBitFields) {
+      Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);
+      ASSERT (Buffer != NULL);
+      Dst = Buffer;
+    } else {
+      Dst = (UINT8 *) &Question->HiiValue.Value;
+    }
   }
 
   //
   // Temp cut at the end of this section, end with '\0' or '&'.
   //
@@ -1471,10 +1483,27 @@ BufferToValue (
     }
   }
 
   *StringPtr = TempChar;
 
+  if (Question->QuestionReferToBitFields) {
+    PreBits = Question->VarBitOffset - Question->VarStoreInfo.VarOffset * 8;
+    Mask = (1 << Question->StorageBitWidth) - 1;
+    BufferValue = *(Buffer);
+    BufferValue |= *(Buffer + 1) << 8;
+    BufferValue |= *(Buffer + 2) << 16;
+    BufferValue |= *(Buffer + 3) << 24;
+    BufferValue >>= PreBits;
+    BufferValue &= Mask;
+
+    CopyMem ((UINT8 *) &Question->HiiValue.Value, (UINT8*)&BufferValue, Question->StorageWidth);
+
+    if (Buffer != NULL) {
+      FreePool (Buffer);
+    }
+  }
+
   return Status;
 }
 
 /**
   Get Question's current Value.
@@ -1509,10 +1538,13 @@ GetQuestionValue (
   CHAR16              *Result;
   CHAR16              *Value;
   UINTN               Length;
   BOOLEAN             IsBufferStorage;
   UINTN               MaxLen;
+  UINT32              PreBits;
+  UINT32              Mask;
+  UINT32              BufferValue;
 
   Status = EFI_SUCCESS;
   Value  = NULL;
   Result = NULL;
 
@@ -1676,16 +1708,40 @@ GetQuestionValue (
     if (IsBufferStorage) {
       if (GetValueFrom == GetSetValueWithEditBuffer) {
         //
         // Copy from storage Edit buffer
         //
-        CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+         if (Question->QuestionReferToBitFields) {
+          PreBits = Question->VarBitOffset - Question->VarStoreInfo.VarOffset * 8;
+          Mask = (1<< Question->StorageBitWidth) -1;
+          BufferValue = *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset);
+          BufferValue |= *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 1) << 8;
+          BufferValue |= *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 2) << 16;
+          BufferValue |= *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 3) << 24;
+          BufferValue >>= PreBits;
+          BufferValue &= Mask;
+          CopyMem (Dst, (UINT8*)&BufferValue, StorageWidth);
+        } else {
+          CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+        }
       } else {
         //
         // Copy from storage Edit buffer
         //
-        CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+        if (Question->QuestionReferToBitFields) {
+          PreBits = Question->VarBitOffset - Question->VarStoreInfo.VarOffset * 8;
+          Mask = (1<< Question->StorageBitWidth) -1;
+          BufferValue = *(Storage->Buffer + Question->VarStoreInfo.VarOffset);
+          BufferValue |= *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 1) << 8;
+          BufferValue |= *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 2) << 16;
+          BufferValue |= *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 3) << 24;
+          BufferValue >>= PreBits;
+          BufferValue &= Mask;
+          CopyMem (Dst, (UINT8*)&BufferValue, StorageWidth);
+        } else {
+          CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+        }
       }
     } else {
       Value = NULL;
       Status = GetValueByName (Storage, Question->VariableName, &Value, GetValueFrom);
       if (EFI_ERROR (Status)) {
@@ -1825,10 +1881,14 @@ SetQuestionValue (
   CHAR16              *TemName;
   CHAR16              *TemString;
   UINTN               Index;
   NAME_VALUE_NODE     *Node;
   UINTN               MaxLen;
+  UINT32              PreBits;
+  UINT32              Mask;
+  UINT32              Buffer;
+  UINT32              SrcValue;
 
   Status = EFI_SUCCESS;
   Node   = NULL;
 
   if (SetValueTo >= GetSetValueWithMax) {
@@ -1947,17 +2007,53 @@ SetQuestionValue (
   if (SetValueTo == GetSetValueWithEditBuffer || SetValueTo == GetSetValueWithBuffer) {
     if (IsBufferStorage) {
       if (SetValueTo == GetSetValueWithEditBuffer) {
         //
         // Copy to storage edit buffer
-        //      
-        CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+        //
+        if (Question->QuestionReferToBitFields) {
+          PreBits = Question->VarBitOffset - Question->VarStoreInfo.VarOffset * 8;
+          SrcValue = (UINT32)(*Src);
+          SrcValue <<= PreBits;
+          Mask = (1<< Question->StorageBitWidth) -1;
+          Mask <<= PreBits;
+          Buffer = *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset);
+          Buffer |= *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 1) << 8;
+          Buffer |= *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 2) << 16;
+          Buffer |= *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 3) << 24;
+
+          Buffer = (Buffer & (~Mask)) | SrcValue;
+          *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset) = (UINT8) Buffer & 0xFF;
+          *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 1) = (UINT8) (Buffer >> 8);
+          *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 2) = (UINT8) (Buffer >> 16);
+          *(Storage->EditBuffer + Question->VarStoreInfo.VarOffset + 3) = (UINT8) (Buffer >> 24);
+        } else {
+          CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+        }
       } else if (SetValueTo == GetSetValueWithBuffer) {
         //
         // Copy to storage edit buffer
         //     
-        CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+        if (Question->QuestionReferToBitFields) {
+          PreBits = Question->VarBitOffset - Question->VarStoreInfo.VarOffset * 8;
+          SrcValue = (UINT32)(*Src);
+          SrcValue <<= PreBits;
+          Mask = (1<< Question->StorageBitWidth) -1;
+          Mask <<= PreBits;
+          Buffer = *(Storage->Buffer + Question->VarStoreInfo.VarOffset);
+          Buffer |= *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 1) << 8;
+          Buffer |= *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 2) << 16;
+          Buffer |= *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 3) << 24;
+
+          Buffer = (Buffer & (~Mask)) | SrcValue;
+          *(Storage->Buffer + Question->VarStoreInfo.VarOffset) = (UINT8) Buffer & 0xFF;
+          *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 1) = (UINT8) (Buffer >> 8);
+          *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 2) = (UINT8) (Buffer >> 16);
+          *(Storage->Buffer + Question->VarStoreInfo.VarOffset + 3) = (UINT8) (Buffer >> 24);
+        } else {
+          CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+        }
       }
     } else {
       if (IsString) {
         //
         // Allocate enough string buffer.
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
index f1accdf..d5889cc 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
@@ -327,11 +327,14 @@ struct _FORM_BROWSER_STATEMENT{
   EFI_QUESTION_ID       QuestionId;       // The value of zero is reserved
   EFI_VARSTORE_ID       VarStoreId;       // A value of zero indicates no variable storage
   BROWSER_STORAGE       *Storage;
   VAR_STORE_INFO        VarStoreInfo;
   UINT16                StorageWidth;
+  UINT16                StorageBitWidth;
+  UINT16                VarBitOffset;
   UINT8                 QuestionFlags;
+  BOOLEAN               QuestionReferToBitFields;
   CHAR16                *VariableName;    // Name/Value or EFI Variable name
   CHAR16                *BlockName;       // Buffer storage block name: "OFFSET=...WIDTH=..."
 
   EFI_HII_VALUE         HiiValue;         // Edit copy for checkbox, numberic, oneof
   UINT8                 *BufferValue;     // Edit copy for string, password, orderedlist
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
index 012a39b..77e0a48 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
@@ -60,10 +60,11 @@
 [Guids]
   gEfiIfrFrameworkGuid                          ## SOMETIMES_CONSUMES  ## GUID
   gEfiHiiPlatformSetupFormsetGuid               ## SOMETIMES_CONSUMES  ## GUID
   gEfiHiiStandardFormGuid                       ## SOMETIMES_CONSUMES  ## GUID
   gZeroGuid                                     ## SOMETIMES_CONSUMES  ## GUID
+  gEfiIfrBitvarstoreGuid                        ## SOMETIMES_CONSUMES  ## GUID
 
 [Protocols]
   gEfiHiiConfigAccessProtocolGuid               ## SOMETIMES_CONSUMES
   gEfiFormBrowser2ProtocolGuid                  ## PRODUCES
   gEdkiiFormBrowserEx2ProtocolGuid              ## PRODUCES
-- 
1.9.5.msysgit.1

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