[edk2] [RFC patch 3/4] MdeModulePkg/HiiDatabase: Handle questions with Bit VarStore

Dandan Bi posted 4 patches 7 years, 8 months ago
[edk2] [RFC patch 3/4] MdeModulePkg/HiiDatabase: Handle questions with Bit VarStore
Posted by Dandan Bi 7 years, 8 months ago
For oneof/numeric/checkbox, their storage may be bit field.
When generating <ConfigAltResp> string to get default value
for these questions, we need to parse the Ifr data to get
the bit Varstore info,and then generating the correct
<ConfigAltResp> string.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
 .../Universal/HiiDatabaseDxe/ConfigRouting.c       | 197 +++++++++++++++++++--
 .../Universal/HiiDatabaseDxe/HiiDatabase.h         |   3 +
 2 files changed, 186 insertions(+), 14 deletions(-)

diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
index c9ff1cf..5da0ba6 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
@@ -13,10 +13,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 
 
 #include "HiiDatabase.h"
 extern HII_DATABASE_PRIVATE_DATA mPrivate;
+EFI_GUID         mBitVarstoreGuid  = {0x82DDD68B, 0x9163, 0x4187, {0x9B, 0x27, 0x20, 0xA8, 0xFD, 0x60 ,0xA7 , 0x1D}};
+BOOLEAN          mNeedUpdateBlockData = FALSE;
+BOOLEAN          mQuestionReferBitVar = FALSE;
 
 /**
   Calculate the number of Unicode characters of the incoming Configuration string,
   not including NULL terminator.
 
@@ -1223,19 +1226,19 @@ InsertBlockData (
   // Insert block data in its Offset and Width order.
   //
   for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
     BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
     if (BlockArray->Offset == BlockSingleData->Offset) {
-      if (BlockArray->Width > BlockSingleData->Width) {
+      if ((BlockArray->Width > BlockSingleData->Width) || (BlockSingleData->IsBitVar && BlockArray->Width == BlockSingleData->Width)) {
         //
         // Insert this block data in the front of block array
         //
         InsertTailList (Link, &BlockSingleData->Entry);
         return;
       }
 
-      if (BlockArray->Width == BlockSingleData->Width) {
+      if ((!BlockSingleData->IsBitVar) && BlockArray->Width == BlockSingleData->Width) {
         //
         // The same block array has been added.
         //
         if (BlockSingleData != BlockArray) {
           FreePool (BlockSingleData);
@@ -1991,17 +1994,21 @@ IsThisOpcodeRequired (
   IN     IFR_BLOCK_DATA           *RequestBlockArray,
   IN     EFI_HII_HANDLE           HiiHandle,
   IN OUT IFR_VARSTORAGE_DATA      *VarStorageData,
   IN     EFI_IFR_OP_HEADER        *IfrOpHdr,
   IN     UINT16                   VarWidth,
-  OUT    IFR_BLOCK_DATA           **ReturnData
+  OUT    IFR_BLOCK_DATA           **ReturnData,
+  IN     BOOLEAN                  IsBitVar
   )
 {
   IFR_BLOCK_DATA           *BlockData;
   UINT16                   VarOffset;
   EFI_STRING_ID            NameId;
   EFI_IFR_QUESTION_HEADER  *IfrQuestionHdr;
+  UINT16                   BitOffset;
+  UINT16                   BitWidth;
+  UINT16                   BitVarWidth;
 
   NameId    = 0;
   VarOffset = 0;
   IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER  *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
 
@@ -2016,11 +2023,19 @@ IsThisOpcodeRequired (
       // This question is not in the requested string. Skip it.
       //
       return EFI_NOT_FOUND;
     }
   } else {
-    VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+    if (IsBitVar) {
+       BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+       VarOffset = BitOffset / 8;
+       BitVarWidth = VarWidth;
+       BitWidth  = BitOffset - (VarOffset * 8) + BitVarWidth;
+       VarWidth  = (BitWidth % 8 == 0 ? BitWidth / 8: BitWidth / 8 + 1);
+    } else {
+      VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+    }
     
     //
     // Check whether this question is in requested block array.
     //
     if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
@@ -2051,10 +2066,13 @@ IsThisOpcodeRequired (
 
   BlockData->Width      = VarWidth;
   BlockData->QuestionId = IfrQuestionHdr->QuestionId;
   BlockData->OpCode     = IfrOpHdr->OpCode;
   BlockData->Scope      = IfrOpHdr->Scope;
+  BlockData->IsBitVar   = IsBitVar;
+  BlockData->BitOffset  = IfrQuestionHdr->VarStoreInfo.VarOffset;
+  BlockData->BitWidth   = BitVarWidth;
   InitializeListHead (&BlockData->DefaultValueEntry);
   //
   // Add Block Data into VarStorageData BlockEntry
   //
   InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
@@ -2124,10 +2142,11 @@ ParseIfrData (
   EFI_HII_PACKAGE_HEADER   *PackageHeader;
   EFI_VARSTORE_ID          VarStoreId;
   UINT16                   SmallestDefaultId;
   BOOLEAN                  SmallestIdFromFlag;
   BOOLEAN                  FromOtherDefaultOpcode;
+  BOOLEAN                  IsBitVar;
 
   Status           = EFI_SUCCESS;
   BlockData        = NULL;
   DefaultDataPtr   = NULL;
   FirstOneOfOption = FALSE;
@@ -2135,10 +2154,11 @@ ParseIfrData (
   FirstOrderedList = FALSE;
   VarStoreName     = NULL;
   ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
   SmallestDefaultId = 0xFFFF;
   FromOtherDefaultOpcode = FALSE;
+  IsBitVar = FALSE;
 
   //
   // Go through the form package to parse OpCode one by one.
   //
   PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
@@ -2309,11 +2329,11 @@ ParseIfrData (
       //
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2341,20 +2361,28 @@ ParseIfrData (
       //
       IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
       if (IfrOneOf->Question.VarStoreId != VarStoreId) {
         break;
       }
-      VarWidth  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
+
+      if (mQuestionReferBitVar) {
+        mQuestionReferBitVar = FALSE;
+        VarWidth = IfrOneOf->Flags & 0X0F;
+        IsBitVar = TRUE;
+      } else {
+        VarWidth  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
+        IsBitVar = FALSE;
+      }
 
       //
       // The BlockData may allocate by other opcode,need to clean.
       //
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, IsBitVar);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2439,11 +2467,11 @@ ParseIfrData (
       //
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2484,11 +2512,19 @@ ParseIfrData (
       //
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      if (mQuestionReferBitVar) {
+        mQuestionReferBitVar = FALSE;
+        VarWidth = 1;
+        IsBitVar = TRUE;
+      } else {
+        IsBitVar = FALSE;
+      }
+
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, IsBitVar);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2612,11 +2648,11 @@ ParseIfrData (
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
       VarWidth  = (UINT16) sizeof (EFI_HII_DATE);
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2654,11 +2690,11 @@ ParseIfrData (
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
       VarWidth  = (UINT16) sizeof (EFI_HII_TIME);
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2696,11 +2732,11 @@ ParseIfrData (
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
       VarWidth  = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2738,11 +2774,11 @@ ParseIfrData (
       if (BlockData != NULL){
         BlockData = NULL;
       }
 
       VarWidth  = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
-      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+      Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData, FALSE);
       if (EFI_ERROR (Status)) {
         if (Status == EFI_NOT_FOUND){
           //
           //The opcode is not required,exit and parse other opcode.
           //
@@ -2985,13 +3021,19 @@ ParseIfrData (
           //
           SmallestDefaultId = 0xFFFF;
           FromOtherDefaultOpcode = FALSE;
         }
       }
+      mQuestionReferBitVar = FALSE;
 
       break;
 
+    case EFI_IFR_GUID_OP:
+      if (CompareGuid ((EFI_GUID *)((UINT8*)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &mBitVarstoreGuid)) {
+        mQuestionReferBitVar = TRUE;
+      }
+
     default:
       if (BlockData != NULL) {
         if (BlockData->Scope > 0) {
           BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
         }
@@ -3567,13 +3609,138 @@ GetStorageWidth (
 
   return StorageWidth;
 }
 
 /**
+For some question (oneof/numeric/checkbox),their storage may be bit filed,
+their block data may have same OFFSET and WIDTH, this function merge the
+same block data to one.
+
+@param      BlockLink     The Link of the block data.
+
+**/
+VOID
+UpdateBlockDataArray(
+  IN LIST_ENTRY        *BlockLink
+)
+{
+  LIST_ENTRY          *Link;
+  LIST_ENTRY          *TempLink;
+  LIST_ENTRY          *ListEntry;
+  LIST_ENTRY          *NextListEntry;
+  LIST_ENTRY          *LinkDefault;
+  LIST_ENTRY          *NextLinkDefault;
+  IFR_BLOCK_DATA      *BlockData;
+  IFR_BLOCK_DATA      *NextBlockeData;
+  IFR_DEFAULT_DATA    *DefaultValueData;
+  IFR_DEFAULT_DATA    *NextDefaultValueData;
+  UINT32              Value;
+  UINT32              Mask;
+  UINT32              PreBits;
+  UINT32              *DefaultValue;
+  UINT8               *BufferValue;
+  BOOLEAN             BlockDataChanged;
+  BOOLEAN             DefaultIdChanged;
+  BOOLEAN             NextBlockChanged;
+
+  Value = 0;
+  Link = BlockLink->ForwardLink;
+  BlockDataChanged = TRUE;
+  DefaultIdChanged = FALSE;
+  NextBlockChanged = FALSE;
+
+  while (Link != BlockLink) {
+    BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+    TempLink = Link->ForwardLink;
+    if (!BlockData ->IsBitVar) {
+      Link = Link->ForwardLink;
+      continue;
+    }
+
+    while (TempLink != Link) {
+      NextBlockeData = BASE_CR (TempLink, IFR_BLOCK_DATA, Entry);
+      TempLink = TempLink->ForwardLink;
+      if (BlockData->Offset != NextBlockeData->Offset || BlockData->Width != NextBlockeData->Width) {
+        continue;
+      }
+      //
+      // They are the same blocks, merge them to one, and update the default value.
+      //
+      ListEntry     = &BlockData->DefaultValueEntry;
+      for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
+        DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
+        NextListEntry = &NextBlockeData->DefaultValueEntry;
+        for (NextLinkDefault = NextListEntry->ForwardLink; NextLinkDefault != NextListEntry; NextLinkDefault = NextLinkDefault->ForwardLink) {
+          NextDefaultValueData = BASE_CR (NextLinkDefault, IFR_DEFAULT_DATA, Entry);
+          if (DefaultValueData->DefaultId != NextDefaultValueData->DefaultId) {
+            continue;
+          }
+          //
+          // The default value with same default id.
+          //
+          if (BlockDataChanged) {
+            Mask = (1 << BlockData->BitWidth) - 1;
+            PreBits = BlockData->BitOffset - BlockData->Offset * 8;
+            DefaultValue = (UINT32*)&(DefaultValueData->Value);
+            *DefaultValue <<= PreBits;
+            Mask <<= PreBits;
+            Value = (Value & (~Mask)) | *DefaultValue;
+            BlockDataChanged = FALSE;
+          } else if (!BlockDataChanged && !NextBlockChanged && DefaultIdChanged){
+            Mask = (1 << BlockData->BitWidth) - 1;
+            PreBits = BlockData->BitOffset - BlockData->Offset * 8;
+            DefaultValue = (UINT32*)&(DefaultValueData->Value);
+            *DefaultValue <<= PreBits;
+            Mask <<= PreBits;
+            Value = (Value & (~Mask)) | *DefaultValue;
+            DefaultIdChanged = FALSE;
+          } else if (!BlockDataChanged && NextBlockChanged) {
+            BufferValue = (UINT8*)&(DefaultValueData->Value);
+            Value = (UINTN)(*BufferValue);
+          }
+
+          Mask = (1 << NextBlockeData->BitWidth) - 1;
+          PreBits = NextBlockeData->BitOffset - NextBlockeData->Offset * 8;
+          DefaultValue = (UINT32*) & (NextDefaultValueData->Value);
+          *DefaultValue <<= PreBits;
+          Mask <<= PreBits;
+          Value = (Value & (~Mask)) | *DefaultValue;
+
+          CopyMem (&DefaultValueData->Value, &Value, sizeof (EFI_IFR_TYPE_VALUE));
+        }
+        DefaultIdChanged = TRUE;
+      }
+      RemoveEntryList (&NextBlockeData->Entry);
+      if (NextBlockeData->Name != NULL) {
+        FreePool (NextBlockeData->Name);
+      }
+      //
+      // Free default value link array
+      //
+      while (!IsListEmpty (&NextBlockeData->DefaultValueEntry)) {
+        DefaultValueData = BASE_CR (NextBlockeData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
+        RemoveEntryList (&DefaultValueData->Entry);
+        FreePool (DefaultValueData);
+      }
+      FreePool (NextBlockeData);
+
+      Link->ForwardLink = TempLink;
+      NextBlockChanged = TRUE;
+    }
+
+    Link = Link->ForwardLink;
+    BlockDataChanged = TRUE;
+    NextBlockChanged = FALSE;
+    DefaultIdChanged = FALSE;
+  }
+}
+
+/**
   Generate ConfigAltResp string base on the varstore info.
 
-  @param      HiiHandle             Hii Handle for this hii package.
+  Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Dandan Bi <dandan.bi@intel.com>             Hii Handle for this hii package.
   @param      ConfigHdr             The config header for this varstore.
   @param      VarStorageData        The varstore info.
   @param      DefaultIdArray        The Default id array.
   @param      DefaultAltCfgResp     The DefaultAltCfgResp info may be return.
 
@@ -3610,10 +3777,12 @@ GenerateAltConfigResp (
   //
   // Add length for <ConfigHdr> + '\0'
   //
   Length = StrLen (ConfigHdr) + 1;
 
+  UpdateBlockDataArray (&VarStorageData->BlockEntry);
+
   for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
     DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
     //
     // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
     //                |1| StrLen (ConfigHdr) | 8 | 4 |
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
index e6760c3..e9962be 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
@@ -75,15 +75,18 @@ typedef struct {
 
 typedef struct {
   LIST_ENTRY          Entry;             // Link to Block array
   UINT16              Offset;
   UINT16              Width;
+  UINT16              BitOffset;
+  UINT16              BitWidth;
   EFI_QUESTION_ID     QuestionId;
   UINT8               OpCode;
   UINT8               Scope;
   LIST_ENTRY          DefaultValueEntry; // Link to its default value array
   CHAR16              *Name;
+  BOOLEAN             IsBitVar;
 } IFR_BLOCK_DATA;
 
 //
 // Get default value from IFR data.
 //
-- 
1.9.5.msysgit.1

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