+/**\r
+ Get Question default value from AltCfg string.\r
+\r
+ @param FormSet The form set.\r
+ @param Question The question.\r
+ @param DefaultId The default Id.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDefaultValueFromAltCfg (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ BOOLEAN IsBufferStorage;\r
+ BOOLEAN IsString; \r
+ UINTN Length;\r
+ BROWSER_STORAGE *Storage;\r
+ CHAR16 *ConfigRequest;\r
+ CHAR16 *Progress;\r
+ CHAR16 *Result;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Value;\r
+ CHAR16 *StringPtr;\r
+ UINTN LengthStr;\r
+ UINT8 *Dst;\r
+ CHAR16 TemStr[5];\r
+ UINTN Index;\r
+ UINT8 DigitUint8;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_NOT_FOUND;\r
+ Length = 0;\r
+ Dst = NULL;\r
+ ConfigRequest = NULL;\r
+ Result = NULL;\r
+ ConfigResp = NULL;\r
+ Value = NULL;\r
+ Storage = Question->Storage;\r
+\r
+ if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Question Value is provided by Buffer Storage or NameValue Storage\r
+ //\r
+ if (Question->BufferValue != NULL) {\r
+ //\r
+ // This Question is password or orderedlist\r
+ //\r
+ Dst = Question->BufferValue;\r
+ } else {\r
+ //\r
+ // Other type of Questions\r
+ //\r
+ Dst = (UINT8 *) &Question->HiiValue.Value;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ IsBufferStorage = TRUE;\r
+ } else {\r
+ IsBufferStorage = FALSE;\r
+ }\r
+ IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
+\r
+ //\r
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+ // <ConfigHdr> + "&" + <VariableName>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Length = StrLen (Storage->ConfigHdr);\r
+ Length += StrLen (Question->BlockName);\r
+ } else {\r
+ Length = StrLen (Storage->ConfigHdr);\r
+ Length += StrLen (Question->VariableName) + 1;\r
+ }\r
+ ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+ ASSERT (ConfigRequest != NULL);\r
+\r
+ StrCpy (ConfigRequest, Storage->ConfigHdr);\r
+ if (IsBufferStorage) {\r
+ StrCat (ConfigRequest, Question->BlockName);\r
+ } else {\r
+ StrCat (ConfigRequest, L"&");\r
+ StrCat (ConfigRequest, Question->VariableName);\r
+ }\r
+\r
+ Status = mHiiConfigRouting->ExtractConfig (\r
+ mHiiConfigRouting,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+ // Get the default configuration string according to the default ID.\r
+ //\r
+ Status = mHiiConfigRouting->GetAltConfig (\r
+ mHiiConfigRouting,\r
+ Result,\r
+ &Storage->Guid,\r
+ Storage->Name,\r
+ NULL,\r
+ &DefaultId, // it can be NULL to get the current setting.\r
+ &ConfigResp\r
+ );\r
+ \r
+ //\r
+ // The required setting can't be found. So, it is not required to be validated and set.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (ConfigResp == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigRequest>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Value = StrStr (ConfigResp, L"&VALUE");\r
+ ASSERT (Value != NULL);\r
+ //\r
+ // Skip "&VALUE"\r
+ //\r
+ Value = Value + 6;\r
+ } else {\r
+ Value = StrStr (ConfigResp, Question->VariableName);\r
+ ASSERT (Value != NULL);\r
+\r
+ Value = Value + StrLen (Question->VariableName);\r
+ }\r
+ if (*Value != '=') {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Skip '=', point to value\r
+ //\r
+ Value = Value + 1;\r
+\r
+ //\r
+ // Suppress <AltResp> if any\r
+ //\r
+ StringPtr = Value;\r
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+ *StringPtr = L'\0';\r
+\r
+ LengthStr = StrLen (Value);\r
+ if (!IsBufferStorage && IsString) {\r
+ StringPtr = (CHAR16 *) Dst;\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < LengthStr; Index += 4) {\r
+ StrnCpy (TemStr, Value + Index, 4);\r
+ StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
+ }\r
+ //\r
+ // Add tailing L'\0' character\r
+ //\r
+ StringPtr[Index/4] = L'\0';\r
+ } else {\r
+ ZeroMem (TemStr, sizeof (TemStr));\r
+ for (Index = 0; Index < LengthStr; Index ++) {\r
+ TemStr[0] = Value[LengthStr - Index - 1];\r
+ DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+ if ((Index & 1) == 0) {\r
+ Dst [Index/2] = DigitUint8;\r
+ } else {\r
+ Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]);\r
+ }\r
+ }\r
+ }\r
+\r
+Done:\r
+ if (ConfigRequest != NULL){\r
+ FreePool (ConfigRequest);\r
+ }\r
+\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ }\r
+ \r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get default Id value used for browser.\r
+\r
+ @param DefaultId The default id value used by hii.\r
+\r
+ @retval Browser used default value.\r
+\r
+**/\r
+INTN\r
+GetDefaultIdForCallBack (\r
+ UINTN DefaultId\r
+ )\r
+{ \r
+ if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
+ } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
+ } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
+ } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
+ } else {\r
+ return -1;\r
+ }\r
+}\r
+\r
+\r
+\r
+/**\r
+ Return data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+\r
+ @retval Value The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index\r
+ )\r
+{\r
+ UINT64 Data;\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ Data = 0;\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Data = (UINT64) *(((UINT8 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Data = (UINT64) *(((UINT16 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Data = (UINT64) *(((UINT32 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ Data = (UINT64) *(((UINT64 *) Array) + Index);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Data;\r
+}\r
+\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+ @param Value The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Search an Option of a Question by its value.\r
+\r
+ @param Question The Question\r
+ @param OptionValue Value for Option to be searched.\r
+\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
+\r
+**/\r
+QUESTION_OPTION *\r
+ValueToOption (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN EFI_HII_VALUE *OptionValue\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ QUESTION_OPTION *Option;\r
+ INTN Result;\r
+\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ //\r
+ // Check the suppressif condition, only a valid option can be return.\r
+ //\r
+ if ((Option->SuppressExpression == NULL) ||\r
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
+ return Option;\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Reset Question to its default value.\r
+\r
+ @param FormSet The form set.\r
+ @param Form The form.\r
+ @param Question The question.\r
+ @param DefaultId The Class of the default.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ QUESTION_DEFAULT *Default;\r
+ QUESTION_OPTION *Option;\r
+ EFI_HII_VALUE *HiiValue;\r
+ UINT8 Index;\r
+ EFI_STRING StrValue;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ INTN Action;\r
+\r
+ Status = EFI_NOT_FOUND;\r
+ StrValue = NULL;\r
+\r
+ //\r
+ // Statement don't have storage, skip them\r
+ //\r
+ if (Question->QuestionId == 0) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // There are Five ways to specify default value for a Question:\r
+ // 1, use call back function (highest priority)\r
+ // 2, use ExtractConfig function\r
+ // 3, use nested EFI_IFR_DEFAULT \r
+ // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+ // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+ //\r
+ HiiValue = &Question->HiiValue;\r
+\r
+ //\r
+ // Get Question defaut value from call back function.\r
+ //\r
+ ConfigAccess = FormSet->ConfigAccess;\r
+ Action = GetDefaultIdForCallBack (DefaultId);\r
+ if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ Action,\r
+ Question->QuestionId,\r
+ HiiValue->Type,\r
+ &HiiValue->Value,\r
+ &ActionRequest\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get default value from altcfg string.\r
+ //\r
+ if (ConfigAccess != NULL) { \r
+ Status = GetDefaultValueFromAltCfg(FormSet, Question, DefaultId);\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_DEFAULT has highest priority\r
+ //\r
+ if (!IsListEmpty (&Question->DefaultListHead)) {\r
+ Link = GetFirstNode (&Question->DefaultListHead);\r
+ while (!IsNull (&Question->DefaultListHead, Link)) {\r
+ Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+ if (Default->DefaultId == DefaultId) {\r
+ if (Default->ValueExpression != NULL) {\r
+ //\r
+ // Default is provided by an Expression, evaluate it\r
+ //\r
+ Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {\r
+ ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && Question->BufferValue != NULL);\r
+ if (Question->StorageWidth > Default->ValueExpression->Result.BufferLen) {\r
+ CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);\r
+ Question->HiiValue.BufferLen = Default->ValueExpression->Result.BufferLen;\r
+ } else {\r
+ CopyMem (Question->HiiValue.Buffer, Default->ValueExpression->Result.Buffer, Question->StorageWidth);\r
+ Question->HiiValue.BufferLen = Question->StorageWidth;\r
+ }\r
+ FreePool (Default->ValueExpression->Result.Buffer);\r
+ }\r
+ HiiValue->Type = Default->ValueExpression->Result.Type;\r
+ CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE)); \r
+ } else {\r
+ //\r
+ // Default value is embedded in EFI_IFR_DEFAULT\r
+ //\r
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+\r
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+ StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);\r
+ if (StrValue == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ if (Question->StorageWidth > StrSize (StrValue)) {\r
+ CopyMem (Question->BufferValue, StrValue, StrSize (StrValue));\r
+ } else {\r
+ CopyMem (Question->BufferValue, StrValue, Question->StorageWidth);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->DefaultListHead, Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_ONE_OF_OPTION\r
+ //\r
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // OneOfOption could only provide Standard and Manufacturing default\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+ continue;\r
+ }\r
+\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+ ) {\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_CHECKBOX - lowest priority\r
+ //\r
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // Checkbox could only provide Standard and Manufacturing default\r
+ //\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+ ) {\r
+ HiiValue->Value.b = TRUE;\r
+ } else {\r
+ HiiValue->Value.b = FALSE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // For Questions without default\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_NUMERIC_OP:\r
+ //\r
+ // Take minimum value as numeric default value\r
+ //\r
+ if ((HiiValue->Value.u64 < Question->Minimum) || (HiiValue->Value.u64 > Question->Maximum)) {\r
+ HiiValue->Value.u64 = Question->Minimum;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ //\r
+ // Take first oneof option as oneof's default value\r
+ //\r
+ if (ValueToOption (Question, HiiValue) == NULL) {\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+ continue;\r
+ }\r
+\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ //\r
+ // Take option sequence in IFR as ordered list's default value\r
+ //\r
+ Index = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Status = EFI_SUCCESS;\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
+ continue;\r
+ }\r
+\r
+ SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);\r
+\r
+ Index++;\r
+ if (Index >= Question->MaxContainers) {\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Reset Questions to their initial value or default value in a Form, Formset or System.\r
+\r
+ GetDefaultValueScope parameter decides which questions will reset \r
+ to its default value.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param DefaultId The Class of the default.\r
+ @param SettingScope Setting Scope for Default action.\r
+ @param GetDefaultValueScope Get default value scope.\r
+ @param Storage Get default value only for this storage.\r
+ @param RetrieveValueFirst Whether call the retrieve call back to\r
+ get the initial value before get default\r
+ value.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_UNSUPPORTED Unsupport SettingScope.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 DefaultId,\r
+ IN BROWSER_SETTING_SCOPE SettingScope,\r
+ IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,\r
+ IN BROWSER_STORAGE *Storage OPTIONAL,\r
+ IN BOOLEAN RetrieveValueFirst\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *FormLink;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+ FORM_BROWSER_FORMSET *OldFormSet;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Check the supported setting level.\r
+ //\r
+ if (SettingScope >= MaxLevel || GetDefaultValueScope >= GetDefaultForMax) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (GetDefaultValueScope == GetDefaultForStorage && Storage == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ if (SettingScope == FormLevel) {\r
+ //\r
+ // Extract Form default\r
+ //\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+ //\r
+ // If get default value only for this storage, check the storage first.\r
+ //\r
+ if ((GetDefaultValueScope == GetDefaultForStorage) && (Question->Storage != Storage)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If get default value only for no storage question, just skip the question which has storage.\r
+ //\r
+ if ((GetDefaultValueScope == GetDefaultForNoStorage) && (Question->Storage != NULL)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If Question is disabled, don't reset it to default\r
+ //\r
+ if (Question->Expression != NULL) {\r
+ if (EvaluateExpressionList(Question->Expression, TRUE, FormSet, Form) == ExpressDisable) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (RetrieveValueFirst) {\r
+ //\r
+ // Call the Retrieve call back to get the initial question value.\r
+ //\r
+ Status = ProcessRetrieveForQuestion(FormSet->ConfigAccess, Question);\r
+ }\r
+\r
+ //\r
+ // If not request to get the initial value or get initial value fail, then get default value.\r
+ //\r
+ if (!RetrieveValueFirst || EFI_ERROR (Status)) {\r
+ Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Synchronize Buffer storage's Edit buffer\r
+ //\r
+ if ((Question->Storage != NULL) &&\r
+ (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+ }\r
+ }\r
+ } else if (SettingScope == FormSetLevel) {\r
+ FormLink = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, FormLink)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);\r
+ ExtractDefault (FormSet, Form, DefaultId, FormLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
+ FormLink = GetNextNode (&FormSet->FormListHead, FormLink);\r
+ }\r
+ } else if (SettingScope == SystemLevel) {\r
+ //\r
+ // Preload all Hii formset.\r
+ //\r
+ LoadAllHiiFormset();\r
+\r
+ OldFormSet = mSystemLevelFormSet;\r
+\r
+ //\r
+ // Set Default Value for each FormSet in the maintain list.\r
+ //\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet(LocalFormSet)) {\r
+ continue;\r
+ }\r
+\r
+ mSystemLevelFormSet = LocalFormSet;\r
+\r
+ ExtractDefault (LocalFormSet, NULL, DefaultId, FormSetLevel, GetDefaultValueScope, Storage, RetrieveValueFirst);\r
+ }\r
+\r
+ mSystemLevelFormSet = OldFormSet;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Validate whether this question's value has changed.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Question to be initialized.\r
+ @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+ @retval TRUE Question's value has changed.\r
+ @retval FALSE Question's value has not changed\r
+\r
+**/\r
+BOOLEAN\r
+IsQuestionValueChanged (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
+ )\r
+{\r
+ EFI_HII_VALUE BackUpValue;\r
+ CHAR8 *BackUpBuffer;\r
+ EFI_STATUS Status;\r
+ BOOLEAN ValueChanged;\r
+ UINTN BufferWidth;\r
+\r
+ //\r
+ // For quetion without storage, always mark it as data not changed.\r
+ //\r
+ if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
+ return FALSE;\r
+ }\r
+\r
+ BackUpBuffer = NULL;\r
+ ValueChanged = FALSE;\r
+\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ BufferWidth = Question->StorageWidth;\r
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer != NULL);\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer != NULL);\r
+ break;\r
+\r
+ default:\r
+ BufferWidth = 0;\r
+ break;\r
+ }\r
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
+ CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
+ ValueChanged = TRUE;\r
+ }\r
+\r
+ CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
+ CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
+\r
+ if (BackUpBuffer != NULL) {\r
+ FreePool (BackUpBuffer);\r
+ }\r
+\r
+ return ValueChanged;\r
+}\r
+\r
+/**\r
+ Initialize Question's Edit copy from Storage.\r
+\r
+ @param Selection Selection contains the information about \r
+ the Selection, form and formset to be displayed.\r
+ Selection action may be updated in retrieve callback.\r
+ If Selection is NULL, only initialize Question value.\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ UINT8 *BufferValue;\r
+ UINTN StorageWidth;\r
+ \r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ //\r
+ // Initialize local copy of Value for each Question\r
+ //\r
+ if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
+ } else {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((Question->Operand == EFI_IFR_STRING_OP) || (Question->Operand == EFI_IFR_PASSWORD_OP)) {\r
+ HiiSetString (FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
+ }\r
+\r
+ //\r
+ // Call the Retrieve call back function for all questions.\r
+ //\r
+ if ((FormSet->ConfigAccess != NULL) && (Selection != NULL) &&\r
+ ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) &&\r
+ !gFinishRetrieveCall) {\r
+ //\r
+ // Check QuestionValue does exist.\r
+ //\r
+ StorageWidth = Question->StorageWidth;\r
+ if (Question->BufferValue != NULL) {\r
+ BufferValue = Question->BufferValue;\r
+ } else {\r
+ BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
+ }\r
+\r
+ //\r
+ // For efivarstore storage, initial question value first.\r
+ //\r
+ if ((Question->Storage != NULL) && (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ Status = gRT->GetVariable (\r
+ Question->VariableName,\r
+ &Question->Storage->Guid,\r
+ NULL,\r
+ &StorageWidth,\r
+ BufferValue\r
+ );\r
+ }\r
+\r
+ Status = ProcessCallBackFunction(Selection, FormSet, Form, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
+ }\r
+\r
+ //\r
+ // Update Question Value changed flag.\r
+ //\r
+ Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initialize Question's Edit copy from Storage for the whole Formset.\r
+\r
+ @param Selection Selection contains the information about \r
+ the Selection, form and formset to be displayed.\r
+ Selection action may be updated in retrieve callback.\r
+ If Selection is NULL, only initialize Question value.\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormSetConfig (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ //\r
+ // Initialize local copy of Value for each Form\r
+ //\r
+ Status = LoadFormConfig (Selection, FormSet, Form);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Finished question initialization.\r
+ // \r
+ FormSet->QuestionInited = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Remove the Request element from the Config Request.\r
+\r
+ @param Storage Pointer to the browser storage.\r
+ @param RequestElement The pointer to the Request element.\r
+\r
+**/\r
+VOID\r
+RemoveElement (\r
+ IN OUT BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *RequestElement\r
+ )\r
+{\r
+ CHAR16 *NewStr;\r
+ CHAR16 *DestStr;\r
+\r
+ ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);\r
+\r
+ NewStr = StrStr (Storage->ConfigRequest, RequestElement);\r
+\r
+ if (NewStr == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Remove this element from this ConfigRequest.\r
+ //\r
+ DestStr = NewStr;\r
+ NewStr += StrLen (RequestElement);\r
+ CopyMem (DestStr, NewStr, StrSize (NewStr));\r
+ \r
+ Storage->SpareStrLen += StrLen (RequestElement); \r
+}\r
+\r
+/**\r
+ Adjust config request in storage, remove the request elements existed in the input ConfigRequest.\r
+\r
+ @param Storage Pointer to the browser storage.\r
+ @param ConfigRequest The pointer to the Request element.\r
+\r
+**/\r
+VOID\r
+RemoveConfigRequest (\r
+ BROWSER_STORAGE *Storage,\r
+ CHAR16 *ConfigRequest\r
+ )\r
+{\r
+ CHAR16 *RequestElement;\r
+ CHAR16 *NextRequestElement;\r
+ CHAR16 *SearchKey;\r
+\r
+ //\r
+ // No request element in it, just return.\r
+ //\r
+ if (ConfigRequest == NULL) {\r
+ return;\r
+ }\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
+ //\r
+ SearchKey = L"&";\r
+ } else {\r
+ //\r
+ // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage\r
+ //\r
+ SearchKey = L"&OFFSET";\r
+ }\r
+\r
+ //\r
+ // Find SearchKey storage\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ RequestElement = StrStr (ConfigRequest, L"PATH");\r
+ ASSERT (RequestElement != NULL);\r
+ RequestElement = StrStr (RequestElement, SearchKey); \r
+ } else {\r
+ RequestElement = StrStr (ConfigRequest, SearchKey);\r
+ }\r
+\r
+ while (RequestElement != NULL) {\r
+ //\r
+ // +1 to avoid find header itself.\r
+ //\r
+ NextRequestElement = StrStr (RequestElement + 1, SearchKey);\r
+\r
+ //\r
+ // The last Request element in configRequest string.\r
+ //\r
+ if (NextRequestElement != NULL) {\r
+ //\r
+ // Replace "&" with '\0'.\r
+ //\r
+ *NextRequestElement = L'\0';\r
+ }\r
+\r
+ RemoveElement (Storage, RequestElement);\r
+\r
+ if (NextRequestElement != NULL) {\r
+ //\r
+ // Restore '&' with '\0' for later used.\r
+ //\r
+ *NextRequestElement = L'&';\r
+ }\r
+\r
+ RequestElement = NextRequestElement;\r
+ }\r
+\r
+ //\r
+ // If no request element remain, just remove the ConfigRequest string.\r
+ //\r
+ if (StrCmp (Storage->ConfigRequest, Storage->ConfigHdr) == 0) {\r
+ FreePool (Storage->ConfigRequest);\r
+ Storage->ConfigRequest = NULL;\r
+ Storage->SpareStrLen = 0;\r
+ }\r
+}\r
+\r
+/**\r
+ Base on the current formset info, clean the ConfigRequest string in browser storage.\r
+\r
+ @param FormSet Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+CleanBrowserStorage (\r
+ IN OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+ CHAR16 *ConfigRequest;\r
+\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {\r
+ continue;\r
+ }\r
+\r
+ ConfigRequest = FormSet->QuestionInited ? Storage->ConfigRequest : Storage->ConfigElements;\r
+ RemoveConfigRequest (Storage->BrowserStorage, ConfigRequest);\r
+ } else if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
+ Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ if (Storage->BrowserStorage->ConfigRequest != NULL) { \r
+ FreePool (Storage->BrowserStorage->ConfigRequest);\r
+ }\r
+ Storage->BrowserStorage->Initialized = FALSE;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether current element in the ConfigReqeust string.\r
+\r
+ @param BrowserStorage Storage which includes ConfigReqeust.\r
+ @param RequestElement New element need to check.\r
+\r
+ @retval TRUE The Element is in the ConfigReqeust string.\r
+ @retval FALSE The Element not in the configReqeust String.\r
+\r
+**/\r
+BOOLEAN \r
+ElementValidation (\r
+ BROWSER_STORAGE *BrowserStorage,\r
+ CHAR16 *RequestElement\r
+ )\r
+{\r
+ return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;\r
+}\r