public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Dandan Bi <dandan.bi@intel.com>
To: edk2-devel@lists.01.org
Cc: Eric Dong <eric.dong@intel.com>, Liming Gao <liming.gao@intel.com>
Subject: [RFC patch 3/4] MdeModulePkg/HiiDatabase: Handle questions with Bit VarStore
Date: Tue, 18 Apr 2017 20:46:31 +0800	[thread overview]
Message-ID: <1492519592-173060-4-git-send-email-dandan.bi@intel.com> (raw)
In-Reply-To: <1492519592-173060-1-git-send-email-dandan.bi@intel.com>

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



  parent reply	other threads:[~2017-04-18 12:47 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-18 12:46 [RFC patch 0/4] Support Bit fields in EFI Variable Storage Dandan Bi
2017-04-18 12:46 ` [RFC patch 1/4] BaseTool/VfrCompiler: Support bit " Dandan Bi
2017-04-18 12:46 ` [RFC patch 2/4] MdeModulePkg/SetupBrowser: Handle questions with Bit VarStore Dandan Bi
2017-04-18 12:46 ` Dandan Bi [this message]
2017-04-18 12:46 ` [RFC patch 4/4] MdeModulePkg/DriverSample: Add smaple questions with bit VarStore Dandan Bi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1492519592-173060-4-git-send-email-dandan.bi@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox