diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index b077a3c0a0..33b14f3951 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -3436,6 +3436,175 @@ LoadFormSetConfig ( return EFI_SUCCESS; } +/** + Check whether current element in the ConfigReqeust string. + + @param BrowserStorage Storage which includes ConfigReqeust. + @param RequestElement New element need to check. + + @retval TRUE The Element is in the ConfigReqeust string. + @retval FALSE The Element not in the configReqeust String. + +**/ +BOOLEAN +ElementValidation ( + BROWSER_STORAGE *BrowserStorage, + CHAR16 *RequestElement + ) +{ + return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE; +} + +/** + Append the Request element to the Config Request. + + @param ConfigRequest Current ConfigRequest info. + @param SpareStrLen Current remain free buffer for config reqeust. + @param RequestElement New Request element. + +**/ +VOID +AppendConfigRequest ( + IN OUT CHAR16 **ConfigRequest, + IN OUT UINTN *SpareStrLen, + IN CHAR16 *RequestElement + ) +{ + CHAR16 *NewStr; + UINTN StringSize; + UINTN StrLength; + + StrLength = StrLen (RequestElement) * sizeof (CHAR16); + + // + // Append to + // + if (StrLength > *SpareStrLen) { + // + // Old String buffer is not sufficient for RequestElement, allocate a new one + // + StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16); + NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16)); + ASSERT (NewStr != NULL); + + if (*ConfigRequest != NULL) { + CopyMem (NewStr, *ConfigRequest, StringSize); + FreePool (*ConfigRequest); + } + *ConfigRequest = NewStr; + *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL; + } + + StrCat (*ConfigRequest, RequestElement); + *SpareStrLen -= StrLength; +} + +/** + Adjust the config request info, remove the request elements which already in AllConfigRequest string. + + @param Storage Form set Storage. + @param ConfigRequest Return the ConfigRequest info. + + @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig + @retval FALSE All elements covered by current used elements. + +**/ +BOOLEAN +ConfigRequestAdjust ( + IN FORMSET_STORAGE *Storage, + OUT CHAR16 **ConfigRequest + ) +{ + CHAR16 *RequestElement; + CHAR16 *NextRequestElement; + CHAR16 *RetBuf; + UINTN SpareBufLen; + CHAR16 *SearchKey; + BOOLEAN RetVal; + + SpareBufLen = 0; + RetBuf = NULL; + RetVal = FALSE; + + if (Storage->BrowserStorage->ConfigRequest == NULL) { + Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); + *ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); + return TRUE; + } + + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + // + // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage + // + SearchKey = L"&"; + } else { + // + // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage + // + SearchKey = L"&OFFSET"; + } + + // + // Prepare the config header. + // + RetBuf = AllocateCopyPool(StrSize (Storage->BrowserStorage->ConfigHdr), Storage->BrowserStorage->ConfigHdr); + ASSERT (RetBuf != NULL); + + // + // Find SearchKey storage + // + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + RequestElement = StrStr (Storage->ConfigRequest, L"PATH"); + ASSERT (RequestElement != NULL); + RequestElement = StrStr (RequestElement, SearchKey); + } else { + RequestElement = StrStr (Storage->ConfigRequest, SearchKey); + } + + while (RequestElement != NULL) { + // + // +1 to avoid find header itself. + // + NextRequestElement = StrStr (RequestElement + 1, SearchKey); + + // + // The last Request element in configRequest string. + // + if (NextRequestElement != NULL) { + // + // Replace "&" with '\0'. + // + *NextRequestElement = L'\0'; + } + + if (!ElementValidation (Storage->BrowserStorage, RequestElement)) { + // + // Add this element to the Storage->BrowserStorage->AllRequestElement. + // + AppendConfigRequest(&Storage->BrowserStorage->ConfigRequest, &Storage->BrowserStorage->SpareStrLen, RequestElement); + AppendConfigRequest (&RetBuf, &SpareBufLen, RequestElement); + RetVal = TRUE; + } + + if (NextRequestElement != NULL) { + // + // Restore '&' with '\0' for later used. + // + *NextRequestElement = L'&'; + } + + RequestElement = NextRequestElement; + } + + if (RetVal) { + *ConfigRequest = RetBuf; + } else { + FreePool (RetBuf); + } + + return RetVal; +} + /** Fill storage's edit copy with settings requested from Configuration Driver. @@ -3455,19 +3624,26 @@ LoadStorage ( EFI_STRING Progress; EFI_STRING Result; CHAR16 *StrPtr; + CHAR16 *ConfigRequest; if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { return EFI_SUCCESS; } if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - Status = gRT->GetVariable ( - Storage->BrowserStorage->Name, - &Storage->BrowserStorage->Guid, - NULL, - (UINTN*)&Storage->BrowserStorage->Size, - Storage->BrowserStorage->EditBuffer - ); + Status = EFI_SUCCESS; + // + // EFI varstore data all get from variable, so no need to get again. + // + if (Storage->BrowserStorage->ReferenceCount == 1) { + Status = gRT->GetVariable ( + Storage->BrowserStorage->Name, + &Storage->BrowserStorage->Guid, + NULL, + (UINTN*)&Storage->BrowserStorage->Size, + Storage->BrowserStorage->EditBuffer + ); + } return Status; } @@ -3482,15 +3658,25 @@ LoadStorage ( return EFI_SUCCESS; } + // + // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig + // will used to call ExtractConfig. + // + if (!ConfigRequestAdjust(Storage, &ConfigRequest)) { + return EFI_SUCCESS; + } + // // Request current settings from Configuration Driver // Status = FormSet->ConfigAccess->ExtractConfig ( FormSet->ConfigAccess, - Storage->ConfigRequest, + ConfigRequest, &Progress, &Result ); + FreePool (ConfigRequest); + if (EFI_ERROR (Status)) { return Status; } @@ -3564,7 +3750,7 @@ InitializeCurrentSetting ( // Storage is not found in backup formset and current global storage not has other driver used, // request it from ConfigDriver // - if (OldStorage == NULL && Storage->BrowserStorage->ReferenceCount == 1) { + if (OldStorage == NULL) { Status = LoadStorage (FormSet, Storage); if (EFI_ERROR (Status)) { diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h index 09fc54afeb..5930029b8d 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h @@ -236,6 +236,9 @@ typedef struct { UINT32 Attributes; // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute CHAR16 *ConfigHdr; // + CHAR16 *ConfigRequest; // = + + // includes all fields which is used by current form sets. + UINTN SpareStrLen; // Spare length of ConfigRequest string buffer UINT8 ReferenceCount; // How many form set storage refrence this storage. } BROWSER_STORAGE;