Allow EfiVarStore to get <AltResp> from Hii Driver, and enhance code logic in MergeDefaultString function to get a full AltCfgResp. The logic in function MergeDefaultString after enhancement: (1) If there are no <AltResp> in AltCfgResp, merge the <AltResp> in DefaultAltCfgResp to AltCfgResp. (2) If there are <AltResp> in AltCfgResp, for the same <AltConfigHdr>, if the <ConfigElement> already in AltCfgResp, don't need to merge from DefaultAltCfgResp, else merge the <ConfigElement> in the DefaultAltCfgResp to the related <AltResp> in AltCfgResp. AltCfgResp: Generated by Driver. DefaultAltCfgResp: Generated by HiiDatabase.
Notes: V2: - Refine the code logic and comments. Cc: Liming Gao <liming....@intel.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Dandan Bi <dandan...@intel.com> --- .../Universal/HiiDatabaseDxe/ConfigRouting.c | 534 +++++++++++++++++++++ 1 file changed, 534 insertions(+) diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c index 3a871cf..94c6101 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c @@ -508,10 +508,474 @@ Exit: return Status; } /** + To find the BlockName in the string with same value. + + @param String Pointer to a Null-terminated Unicode string. + @param BlockName Pointer to a Null-terminated Unicode string to search for. + @param Value Pointer to the value correspond to the BlockName. + @param Found The Block whether has been found. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures. + @retval EFI_SUCCESS The function finishes successfully. + +**/ +EFI_STATUS +FindSameBlockElement( + IN EFI_STRING String, + IN EFI_STRING BlockName, + IN UINT8 *Value, + OUT BOOLEAN *Found + ) +{ + EFI_STRING BlockPtr; + UINTN Length; + UINT8 *TempBuffer; + EFI_STATUS Status; + + TempBuffer = NULL; + *Found = FALSE; + BlockPtr = StrStr (String, BlockName); + + while (BlockPtr != NULL) { + BlockPtr += StrLen (BlockName); + Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (TempBuffer != NULL); + if (*TempBuffer == *Value) { + *Found = TRUE; + return EFI_SUCCESS; + } else { + FreePool (TempBuffer); + TempBuffer = NULL; + BlockPtr = StrStr (BlockPtr + 1, BlockName); + } + } + return EFI_SUCCESS; +} + +/** + Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp> + in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp. + + @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in + <MultiConfigAltResp> format. The default value + string may contain more than one ConfigAltResp + string for the different varstore buffer. + @param ConfigAltResp Pointer to a null-terminated Unicode string in + <ConfigAltResp> format. + @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format. + @param ConfigAltRespChanged Whether the ConfigAltResp has been changed. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures. + @retval EFI_SUCCESS The function finishes successfully. + +**/ +EFI_STATUS +CompareBlockElementDefault ( + IN EFI_STRING DefaultAltCfgResp, + IN OUT EFI_STRING *ConfigAltResp, + IN EFI_STRING AltConfigHdr, + IN OUT BOOLEAN *ConfigAltRespChanged +) +{ + EFI_STATUS Status; + EFI_STRING BlockPtr; + EFI_STRING BlockPtrStart; + EFI_STRING StringPtr; + EFI_STRING AppendString; + EFI_STRING AltConfigHdrPtr; + UINT8 *TempBuffer; + UINTN OffsetLength; + UINTN AppendSize; + UINTN TotalSize; + BOOLEAN FoundOffset; + + AppendString = NULL; + // + // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp. + // + AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr); + ASSERT (AltConfigHdrPtr != NULL); + BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET="); + // + // Make StringPtr point to the AltConfigHdr in ConfigAltResp. + // + StringPtr = StrStr (*ConfigAltResp, AltConfigHdr); + ASSERT (StringPtr != NULL); + + while (BlockPtr != NULL) { + // + // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp. + // + BlockPtrStart = BlockPtr; + BlockPtr += StrLen (L"&OFFSET="); + Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + // + // To find the same "&OFFSET=<Number>" block in ConfigAltResp. + // + Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + if (!FoundOffset) { + // + // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp. + // Calculate the size of <BlockConfig>. + // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>. + // + BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET="); + if (BlockPtr != NULL) { + AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16); + } else { + AppendSize = StrSize (BlockPtrStart); + } + // + // Copy the <BlockConfig> to AppendString. + // + if (AppendString == NULL) { + AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16)); + StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16)); + } else { + TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16); + AppendString = (EFI_STRING) ReallocatePool ( + StrSize (AppendString), + TotalSize, + AppendString + ); + if (AppendString == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16)); + } + } else { + // + // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp. + // + BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET="); + } + } + + if (AppendString != NULL) { + // + // Reallocate ConfigAltResp to copy the AppendString. + // + TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16); + *ConfigAltResp = (EFI_STRING) ReallocatePool ( + StrSize (*ConfigAltResp), + TotalSize, + *ConfigAltResp + ); + if (*ConfigAltResp == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString); + *ConfigAltRespChanged = TRUE; + } + + Status = EFI_SUCCESS; + +Exit: + if (AppendString != NULL) { + FreePool (AppendString); + } + + return Status; +} + +/** + Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp> + in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp. + + @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in + <MultiConfigAltResp> format. The default value + string may contain more than one ConfigAltResp + string for the different varstore buffer. + @param ConfigAltResp Pointer to a null-terminated Unicode string in + <ConfigAltResp> format. + @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format. + @param ConfigAltRespChanged Whether the ConfigAltResp has been changed. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures. + @retval EFI_SUCCESS The function finishes successfully. + +**/ +EFI_STATUS +CompareNameElementDefault ( + IN EFI_STRING DefaultAltCfgResp, + IN OUT EFI_STRING *ConfigAltResp, + IN EFI_STRING AltConfigHdr, + IN OUT BOOLEAN *ConfigAltRespChanged +) +{ + EFI_STATUS Status; + EFI_STRING NvConfigPtr; + EFI_STRING NvConfigStart; + EFI_STRING NvConfigValuePtr; + EFI_STRING StringPtr; + EFI_STRING NvConfigExist; + EFI_STRING AppendString; + CHAR16 TempChar; + UINTN AppendSize; + UINTN TotalSize; + + AppendString = NULL; + NvConfigExist = NULL; + // + // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp. + // + NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr); + ASSERT (NvConfigPtr != NULL); + NvConfigPtr = StrStr (NvConfigPtr + StrLen(AltConfigHdr),L"&"); + // + // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp. + // + StringPtr = StrStr (*ConfigAltResp, AltConfigHdr); + ASSERT (StringPtr != NULL); + StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&"); + ASSERT (StringPtr != NULL); + + while (NvConfigPtr != NULL) { + // + // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>. + // Get the <Label> with AltConfigHdr in DefaultAltCfgResp. + // + NvConfigStart = NvConfigPtr; + NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"="); + ASSERT (NvConfigValuePtr != NULL); + TempChar = *NvConfigValuePtr; + *NvConfigValuePtr = L'\0'; + // + // Get the <Label> with AltConfigHdr in ConfigAltResp. + // + NvConfigExist = StrStr (StringPtr, NvConfigPtr); + if (NvConfigExist == NULL) { + // + // Don't find same <Label> in ConfigAltResp. + // Calculate the size of <NvConfig>. + // + *NvConfigValuePtr = TempChar; + NvConfigPtr = StrStr (NvConfigPtr + 1, L"&"); + if (NvConfigPtr != NULL) { + AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16); + } else { + AppendSize = StrSize (NvConfigStart); + } + // + // Copy the <NvConfig> to AppendString. + // + if (AppendString == NULL) { + AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16)); + StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16)); + } else { + TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16); + AppendString = (EFI_STRING) ReallocatePool ( + StrSize (AppendString), + TotalSize, + AppendString + ); + if (AppendString == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16)); + } + } else { + // + // To find next <Label> in DefaultAltCfgResp. + // + *NvConfigValuePtr = TempChar; + NvConfigPtr = StrStr (NvConfigPtr + 1, L"&"); + } + } + if (AppendString != NULL) { + // + // Reallocate ConfigAltResp to copy the AppendString. + // + TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16); + *ConfigAltResp = (EFI_STRING) ReallocatePool ( + StrSize (*ConfigAltResp), + StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16), + *ConfigAltResp + ); + if (*ConfigAltResp == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString); + *ConfigAltRespChanged = TRUE; + } + Status = EFI_SUCCESS; + +Exit: + if (AppendString != NULL) { + FreePool (AppendString); + } + return Status; +} + +/** + Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp> + in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp. + + @param AltCfgResp Pointer to a null-terminated Unicode string in + <ConfigAltResp> format. + @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in + <MultiConfigAltResp> format. The default value + string may contain more than one ConfigAltResp + string for the different varstore buffer. + @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary + structures. + @retval EFI_SUCCESS The function finishes successfully. + +**/ +EFI_STATUS +CompareAndMergeDefaultString ( + IN OUT EFI_STRING *AltCfgResp, + IN EFI_STRING DefaultAltCfgResp, + IN EFI_STRING AltConfigHdr + ) +{ + EFI_STATUS Status; + EFI_STRING AltCfgRespBackup; + EFI_STRING AltConfigHdrPtr; + EFI_STRING AltConfigHdrPtrNext; + EFI_STRING ConfigAltResp; + EFI_STRING StringPtr; + EFI_STRING StringPtrNext; + EFI_STRING BlockPtr; + UINTN ReallocateSize; + CHAR16 TempChar; + CHAR16 TempCharA; + BOOLEAN ConfigAltRespChanged; + + Status = EFI_OUT_OF_RESOURCES; + BlockPtr = NULL; + AltConfigHdrPtrNext = NULL; + StringPtrNext = NULL; + ConfigAltResp = NULL; + AltCfgRespBackup = NULL; + ConfigAltRespChanged = FALSE; + + // + //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it. + // + AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr); + ASSERT (AltConfigHdrPtr != NULL); + AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID"); + if (AltConfigHdrPtrNext != NULL) { + TempChar = *AltConfigHdrPtrNext; + *AltConfigHdrPtrNext = L'\0'; + } + // + // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it. + // + StringPtr = StrStr (*AltCfgResp, AltConfigHdr); + StringPtrNext = StrStr (StringPtr + 1, L"&GUID"); + if (StringPtrNext != NULL) { + TempCharA = *StringPtrNext; + *StringPtrNext = L'\0'; + } + // + // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp. + // + ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp); + if (ConfigAltResp == NULL) { + goto Exit; + } + // + //To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp. + // + BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET="); + if (BlockPtr != NULL) { + // + // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style. + // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp. + // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp. + // + Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged); + if (EFI_ERROR(Status)) { + goto Exit; + } + } else { + // + // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style. + // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp. + // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp. + // + Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged); + if (EFI_ERROR(Status)) { + goto Exit; + } + } + // + // Restore the AltCfgResp. + // + if (StringPtrNext != NULL) { + *StringPtrNext = TempCharA; + } + + // + // If the ConfigAltResp has no change,no need to update the content in AltCfgResp. + // + if (ConfigAltRespChanged == FALSE) { + Status = EFI_SUCCESS; + goto Exit; + } + // + // ConfigAltResp has been changed, need to update the content in AltCfgResp. + // + if (StringPtrNext != NULL) { + ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16); + } else { + ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16); + } + + AltCfgRespBackup = (EFI_STRING) AllocateZeroPool (ReallocateSize); + if (AltCfgRespBackup == NULL) { + goto Exit; + } + + StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp); + if (StringPtrNext != NULL) { + StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext); + } + + FreePool (*AltCfgResp); + *AltCfgResp = AltCfgRespBackup; + + Status = EFI_SUCCESS; + +Exit: + if (ConfigAltResp != NULL) { + FreePool(ConfigAltResp); + } + // + // Restore the DefaultAltCfgResp. + // + if ( AltConfigHdrPtrNext != NULL) { + *AltConfigHdrPtrNext = TempChar; + AltConfigHdrPtrNext = NULL; + } + + return Status; +} + +/** This function merges DefaultAltCfgResp string into AltCfgResp string for the missing AltCfgId in AltCfgResq. @param AltCfgResp Pointer to a null-terminated Unicode string in <ConfigAltResp> format. The default value string @@ -629,10 +1093,17 @@ MergeDefaultString ( return EFI_OUT_OF_RESOURCES; } StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault); *StringPtrEnd = TempChar; } + } else { + // + // The AltCfgResp contains <AltCfgResp>. + // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the + // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge. + // + CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr); } // // Find next AltCfg String // @@ -3799,17 +4270,22 @@ HiiConfigRoutingExtractConfig ( EFI_HANDLE DriverHandle; EFI_HII_HANDLE HiiHandle; EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; EFI_STRING AccessProgress; EFI_STRING AccessResults; + EFI_STRING AccessProgressBackup; + EFI_STRING AccessResultsBackup; EFI_STRING DefaultResults; BOOLEAN FirstElement; BOOLEAN IfrDataParsedFlag; BOOLEAN IsEfiVarStore; EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo; EFI_STRING ErrorPtr; UINTN DevicePathSize; + UINTN ConigStringSize; + UINTN ConigStringSizeNewsize; + EFI_STRING ConfigStringPtr; if (This == NULL || Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; } @@ -3824,10 +4300,12 @@ HiiConfigRoutingExtractConfig ( DefaultResults = NULL; ConfigRequest = NULL; Status = EFI_SUCCESS; AccessResults = NULL; AccessProgress = NULL; + AccessResultsBackup = NULL; + AccessProgressBackup = NULL; DevicePath = NULL; IfrDataParsedFlag = FALSE; IsEfiVarStore = FALSE; EfiVarStoreInfo = NULL; @@ -3973,10 +4451,66 @@ HiiConfigRoutingExtractConfig ( // // Call the GetVariable function to extract settings. // Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress); FreePool (EfiVarStoreInfo); + if (EFI_ERROR (Status)) { + // + // AccessProgress indicates the parsing progress on <ConfigRequest>. + // Map it to the progress on <MultiConfigRequest> then return it. + // + *Progress = StrStr (StringPtr, AccessProgress); + goto Done; + } + + // + // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver. + // + Status = gBS->HandleProtocol ( + DriverHandle, + &gEfiHiiConfigAccessProtocolGuid, + (VOID **) &ConfigAccess + ); + if (EFI_ERROR (Status)) { + // + // The driver has EfiVarStore, may not install ConfigAccess protocol. + // So ignore the error status in this case. + // + Status = EFI_SUCCESS; + } else { + Status = ConfigAccess->ExtractConfig ( + ConfigAccess, + ConfigRequest, + &AccessProgressBackup, + &AccessResultsBackup + ); + if (!EFI_ERROR(Status)) { + // + //Merge the AltCfgResp in AccessResultsBackup to AccessResults + // + if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) { + ConigStringSize = StrSize (AccessResults); + ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID="); + ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16); + AccessResults =(EFI_STRING) ReallocatePool ( + ConigStringSize, + ConigStringSizeNewsize, + AccessResults); + StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr); + } + } else { + // + // In the ExtractConfig function of some driver may not support EfiVarStore, + // may return error status, just ignore the error status in this case. + // + Status = EFI_SUCCESS; + } + if (AccessResultsBackup != NULL) { + FreePool (AccessResultsBackup); + AccessResultsBackup = NULL; + } + } } else { // // Call corresponding ConfigAccess protocol to extract settings // Status = gBS->HandleProtocol ( -- 1.9.5.msysgit.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel