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.d...@intel.com> Cc: Liming Gao <liming....@intel.com> Cc: Dandan Bi <dandan...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Dandan Bi <dandan...@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...@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