mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-02 13:03:28 +01:00
811 lines
24 KiB
C
811 lines
24 KiB
C
/** @file
|
|
Implementation of HII utility library.
|
|
|
|
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
|
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
|
|
Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "HiiInternal.h"
|
|
|
|
/**
|
|
Initialize the internal data structure of a FormSet.
|
|
|
|
@param Handle PackageList Handle
|
|
@param FormSetGuid On input, GUID or class GUID of a formset. If not
|
|
specified (NULL or zero GUID), take the first
|
|
FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
|
|
found in package list.
|
|
On output, GUID of the formset found(if not NULL).
|
|
@param FormSet FormSet data structure.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_NOT_FOUND The specified FormSet could not be found.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
CreateFormSetFromHiiHandle (
|
|
IN EFI_HII_HANDLE Handle,
|
|
IN OUT EFI_GUID *FormSetGuid,
|
|
OUT HII_FORMSET *FormSet
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE DriverHandle;
|
|
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
|
|
|
|
if ((FormSetGuid == NULL) || (FormSet == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Locate required Hii Database protocol
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHiiDatabaseProtocolGuid,
|
|
NULL,
|
|
(VOID **)&HiiDatabase
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
FormSet->Signature = HII_FORMSET_SIGNATURE;
|
|
FormSet->HiiHandle = Handle;
|
|
CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
|
|
//
|
|
// Retrieve ConfigAccess Protocol associated with this HiiPackageList
|
|
//
|
|
Status = HiiDatabase->GetPackageListHandle (HiiDatabase, Handle, &DriverHandle);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
FormSet->DriverHandle = DriverHandle;
|
|
Status = gBS->HandleProtocol (
|
|
DriverHandle,
|
|
&gEfiHiiConfigAccessProtocolGuid,
|
|
(VOID **)&FormSet->ConfigAccess
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Configuration Driver don't attach ConfigAccess protocol to its HII package
|
|
// list, then there will be no configuration action required
|
|
//
|
|
FormSet->ConfigAccess = NULL;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
DriverHandle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **)&FormSet->DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Configuration Driver don't attach ConfigAccess protocol to its HII package
|
|
// list, then there will be no configuration action required
|
|
//
|
|
FormSet->DevicePath = NULL;
|
|
}
|
|
|
|
//
|
|
// Parse the IFR binary OpCodes
|
|
//
|
|
Status = ParseOpCodes (FormSet);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Initialize a Formset and get current setting for Questions.
|
|
|
|
@param FormSet FormSet data structure.
|
|
|
|
**/
|
|
VOID
|
|
InitializeFormSet (
|
|
IN OUT HII_FORMSET *FormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
HII_FORMSET_STORAGE *Storage;
|
|
LIST_ENTRY *FormLink;
|
|
HII_STATEMENT *Question;
|
|
HII_FORM *Form;
|
|
|
|
if (FormSet == NULL) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Load Storage for all questions with storage
|
|
//
|
|
Link = GetFirstNode (&FormSet->StorageListHead);
|
|
while (!IsNull (&FormSet->StorageListHead, Link)) {
|
|
Storage = HII_STORAGE_FROM_LINK (Link);
|
|
LoadFormSetStorage (FormSet, Storage);
|
|
Link = GetNextNode (&FormSet->StorageListHead, Link);
|
|
}
|
|
|
|
//
|
|
// Get Current Value for all no storage questions
|
|
//
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
Form = HII_FORM_FROM_LINK (FormLink);
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Question = HII_STATEMENT_FROM_LINK (Link);
|
|
if (Question->Storage == NULL) {
|
|
RetrieveQuestion (FormSet, Form, Question);
|
|
}
|
|
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
}
|
|
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Free resources allocated for a FormSet.
|
|
|
|
@param[in,out] FormSet Pointer of the FormSet
|
|
|
|
**/
|
|
VOID
|
|
DestroyFormSet (
|
|
IN OUT HII_FORMSET *FormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
HII_FORMSET_STORAGE *Storage;
|
|
HII_FORMSET_DEFAULTSTORE *DefaultStore;
|
|
HII_FORM *Form;
|
|
|
|
if (FormSet->IfrBinaryData == NULL) {
|
|
//
|
|
// Uninitialized FormSet
|
|
//
|
|
FreePool (FormSet);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Free IFR binary buffer
|
|
//
|
|
FreePool (FormSet->IfrBinaryData);
|
|
|
|
//
|
|
// Free FormSet Storage
|
|
//
|
|
if (FormSet->StorageListHead.ForwardLink != NULL) {
|
|
while (!IsListEmpty (&FormSet->StorageListHead)) {
|
|
Link = GetFirstNode (&FormSet->StorageListHead);
|
|
Storage = HII_STORAGE_FROM_LINK (Link);
|
|
RemoveEntryList (&Storage->Link);
|
|
|
|
if (Storage != NULL) {
|
|
FreePool (Storage);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free FormSet Default Store
|
|
//
|
|
if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
|
|
while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
|
|
Link = GetFirstNode (&FormSet->DefaultStoreListHead);
|
|
DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (Link);
|
|
RemoveEntryList (&DefaultStore->Link);
|
|
|
|
FreePool (DefaultStore);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free Forms
|
|
//
|
|
if (FormSet->FormListHead.ForwardLink != NULL) {
|
|
while (!IsListEmpty (&FormSet->FormListHead)) {
|
|
Link = GetFirstNode (&FormSet->FormListHead);
|
|
Form = HII_FORM_FROM_LINK (Link);
|
|
RemoveEntryList (&Form->Link);
|
|
|
|
DestroyForm (FormSet, Form);
|
|
}
|
|
}
|
|
|
|
FreePool (FormSet);
|
|
}
|
|
|
|
/**
|
|
Submit data for a form.
|
|
|
|
@param[in] FormSet FormSet which contains the Form.
|
|
@param[in] Form Form to submit.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval Others Other errors occur.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SubmitForm (
|
|
IN HII_FORMSET *FormSet,
|
|
IN HII_FORM *Form
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
|
|
LIST_ENTRY *Link;
|
|
EFI_STRING ConfigResp;
|
|
EFI_STRING Progress;
|
|
HII_FORMSET_STORAGE *Storage;
|
|
HII_FORM_CONFIG_REQUEST *ConfigInfo;
|
|
|
|
if ((FormSet == NULL) || (Form == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = NoSubmitCheck (FormSet, &Form, NULL);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Link = GetFirstNode (&Form->ConfigRequestHead);
|
|
while (!IsNull (&Form->ConfigRequestHead, Link)) {
|
|
ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
|
|
Link = GetNextNode (&Form->ConfigRequestHead, Link);
|
|
|
|
Storage = ConfigInfo->Storage;
|
|
if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Skip if there is no RequestElement
|
|
//
|
|
if (ConfigInfo->ElementCount == 0) {
|
|
continue;
|
|
}
|
|
|
|
Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHiiConfigRoutingProtocolGuid,
|
|
NULL,
|
|
(VOID **)&HiiConfigRouting
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = HiiConfigRouting->RouteConfig (
|
|
HiiConfigRouting,
|
|
ConfigResp,
|
|
&Progress
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (ConfigResp);
|
|
continue;
|
|
}
|
|
|
|
FreePool (ConfigResp);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Save Question Value to the memory, but not to storage.
|
|
|
|
@param[in] FormSet FormSet data structure.
|
|
@param[in] Form Form data structure.
|
|
@param[in,out] Question Pointer to the Question.
|
|
@param[in] QuestionValue New Question Value to be set.
|
|
|
|
@retval EFI_SUCCESS The question value has been set successfully.
|
|
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SetQuestionValue (
|
|
IN HII_FORMSET *FormSet,
|
|
IN HII_FORM *Form,
|
|
IN OUT HII_STATEMENT *Question,
|
|
IN HII_STATEMENT_VALUE *QuestionValue
|
|
)
|
|
{
|
|
UINT8 *Src;
|
|
UINTN BufferLen;
|
|
UINTN StorageWidth;
|
|
HII_FORMSET_STORAGE *Storage;
|
|
CHAR16 *ValueStr;
|
|
BOOLEAN IsBufferStorage;
|
|
UINT8 *TemBuffer;
|
|
CHAR16 *TemName;
|
|
CHAR16 *TemString;
|
|
UINTN Index;
|
|
HII_NAME_VALUE_NODE *Node;
|
|
EFI_STATUS Status;
|
|
|
|
if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (QuestionValue == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
Node = NULL;
|
|
|
|
//
|
|
// If Question value is provided by an Expression, then it is read only
|
|
//
|
|
if ((Question->ValueExpression != NULL) || (Question->Value.Type != QuestionValue->Type)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Before set question value, evaluate its write expression.
|
|
//
|
|
if ((Question->WriteExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {
|
|
Status = EvaluateHiiExpression (FormSet, Form, Question->WriteExpression);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
Storage = Question->Storage;
|
|
if (Storage != NULL) {
|
|
StorageWidth = Question->StorageWidth;
|
|
if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {
|
|
Question->Value.BufferLen = QuestionValue->BufferLen;
|
|
Question->Value.Buffer = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);
|
|
if (Question->Value.Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Question->Value.BufferValueType = QuestionValue->BufferValueType;
|
|
Src = Question->Value.Buffer;
|
|
} else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
|
|
Question->Value.Value.string = QuestionValue->Value.string;
|
|
TemString = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);
|
|
if (TemString == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
Question->Value.BufferLen = Question->StorageWidth;
|
|
Question->Value.Buffer = AllocateZeroPool (Question->StorageWidth);
|
|
if (Question->Value.Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));
|
|
Src = Question->Value.Buffer;
|
|
} else {
|
|
CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));
|
|
Src = (UINT8 *)&Question->Value.Value;
|
|
}
|
|
|
|
if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
|
|
IsBufferStorage = TRUE;
|
|
} else {
|
|
IsBufferStorage = FALSE;
|
|
}
|
|
|
|
if (IsBufferStorage) {
|
|
//
|
|
// If the Question refer to bit filed, copy the value in related bit filed to storage edit buffer.
|
|
//
|
|
if (Question->QuestionReferToBitField) {
|
|
SetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, (UINT32)(*Src));
|
|
} else {
|
|
CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
|
|
}
|
|
} else {
|
|
if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
|
|
//
|
|
// Allocate enough string buffer.
|
|
//
|
|
ValueStr = NULL;
|
|
BufferLen = ((StrLen ((CHAR16 *)Src) * 4) + 1) * sizeof (CHAR16);
|
|
ValueStr = AllocatePool (BufferLen);
|
|
if (ValueStr == NULL) {
|
|
if (Question->Value.Buffer != NULL) {
|
|
FreePool (Question->Value.Buffer);
|
|
}
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
|
|
//
|
|
TemName = (CHAR16 *)Src;
|
|
TemString = ValueStr;
|
|
for ( ; *TemName != L'\0'; TemName++) {
|
|
UnicodeValueToStringS (
|
|
TemString,
|
|
BufferLen - ((UINTN)TemString - (UINTN)ValueStr),
|
|
PREFIX_ZERO | RADIX_HEX,
|
|
*TemName,
|
|
4
|
|
);
|
|
TemString += StrnLenS (TemString, (BufferLen - ((UINTN)TemString - (UINTN)ValueStr)) / sizeof (CHAR16));
|
|
}
|
|
} else {
|
|
BufferLen = StorageWidth * 2 + 1;
|
|
ValueStr = AllocateZeroPool (BufferLen * sizeof (CHAR16));
|
|
if (ValueStr == NULL) {
|
|
if (Question->Value.Buffer != NULL) {
|
|
FreePool (Question->Value.Buffer);
|
|
}
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Convert Buffer to Hex String
|
|
//
|
|
TemBuffer = Src + StorageWidth - 1;
|
|
TemString = ValueStr;
|
|
for (Index = 0; Index < StorageWidth; Index++, TemBuffer--) {
|
|
UnicodeValueToStringS (
|
|
TemString,
|
|
BufferLen * sizeof (CHAR16) - ((UINTN)TemString - (UINTN)ValueStr),
|
|
PREFIX_ZERO | RADIX_HEX,
|
|
*TemBuffer,
|
|
2
|
|
);
|
|
TemString += StrnLenS (TemString, BufferLen - ((UINTN)TemString - (UINTN)ValueStr) / sizeof (CHAR16));
|
|
}
|
|
}
|
|
|
|
Status = SetValueByName (Storage, Question->VariableName, ValueStr, &Node);
|
|
FreePool (ValueStr);
|
|
if (EFI_ERROR (Status)) {
|
|
if (Question->Value.Buffer != NULL) {
|
|
FreePool (Question->Value.Buffer);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
}
|
|
} else {
|
|
if (Question->Value.Type == EFI_IFR_TYPE_BUFFER) {
|
|
Question->Value.BufferLen = QuestionValue->BufferLen;
|
|
Question->Value.Buffer = AllocateCopyPool (QuestionValue->BufferLen, QuestionValue->Buffer);
|
|
if (Question->Value.Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Question->Value.BufferValueType = QuestionValue->BufferValueType;
|
|
} else if (Question->Value.Type == EFI_IFR_TYPE_STRING) {
|
|
Question->Value.Value.string = QuestionValue->Value.string;
|
|
TemString = HiiGetString (FormSet->HiiHandle, QuestionValue->Value.string, NULL);
|
|
if (TemString == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
Question->Value.BufferLen = (UINT16)StrSize (TemString);
|
|
Question->Value.Buffer = AllocateZeroPool (QuestionValue->BufferLen);
|
|
if (Question->Value.Buffer == NULL) {
|
|
FreePool (TemString);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
CopyMem (Question->Value.Buffer, TemString, StrSize (TemString));
|
|
FreePool (TemString);
|
|
} else {
|
|
CopyMem (&Question->Value.Value, &QuestionValue->Value, sizeof (EFI_IFR_TYPE_VALUE));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get Question's current Value from storage.
|
|
|
|
@param[in] FormSet FormSet data structure.
|
|
@param[in] Form Form data structure.
|
|
@param[in,out] Question Question to be initialized.
|
|
|
|
@return the current Question Value in storage if success.
|
|
@return NULL if Question is not found or any error occurs.
|
|
|
|
**/
|
|
HII_STATEMENT_VALUE *
|
|
RetrieveQuestion (
|
|
IN HII_FORMSET *FormSet,
|
|
IN HII_FORM *Form,
|
|
IN OUT HII_STATEMENT *Question
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
|
|
EFI_BROWSER_ACTION_REQUEST ActionRequest;
|
|
HII_FORMSET_STORAGE *Storage;
|
|
HII_STATEMENT_VALUE *QuestionValue;
|
|
EFI_IFR_TYPE_VALUE *TypeValue;
|
|
EFI_TIME EfiTime;
|
|
BOOLEAN Enabled;
|
|
BOOLEAN Pending;
|
|
UINT8 *Dst;
|
|
UINTN StorageWidth;
|
|
CHAR16 *ConfigRequest;
|
|
CHAR16 *Progress;
|
|
CHAR16 *Result;
|
|
CHAR16 *ValueStr;
|
|
UINTN Length;
|
|
BOOLEAN IsBufferStorage;
|
|
CHAR16 *NewHiiString;
|
|
|
|
if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
ValueStr = NULL;
|
|
Result = NULL;
|
|
|
|
QuestionValue = AllocateZeroPool (sizeof (HII_STATEMENT_VALUE));
|
|
if (QuestionValue == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
QuestionValue->Type = Question->Value.Type;
|
|
QuestionValue->BufferLen = Question->Value.BufferLen;
|
|
if (QuestionValue->BufferLen != 0) {
|
|
QuestionValue->Buffer = AllocateZeroPool (QuestionValue->BufferLen);
|
|
if (QuestionValue->Buffer == NULL) {
|
|
FreePool (QuestionValue);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Question value is provided by RTC
|
|
//
|
|
Storage = Question->Storage;
|
|
StorageWidth = Question->StorageWidth;
|
|
|
|
if (Storage == NULL) {
|
|
//
|
|
// It's a Question without storage, or RTC date/time
|
|
//
|
|
if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
|
|
//
|
|
// Date and time define the same Flags bit
|
|
//
|
|
switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {
|
|
case QF_DATE_STORAGE_TIME:
|
|
|
|
Status = gRT->GetTime (&EfiTime, NULL);
|
|
break;
|
|
|
|
case QF_DATE_STORAGE_WAKEUP:
|
|
|
|
Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
|
|
break;
|
|
|
|
case QF_DATE_STORAGE_NORMAL:
|
|
default:
|
|
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
if (Question->Operand == EFI_IFR_DATE_OP) {
|
|
QuestionValue->Value.date.Year = 0xff;
|
|
QuestionValue->Value.date.Month = 0xff;
|
|
QuestionValue->Value.date.Day = 0xff;
|
|
} else {
|
|
QuestionValue->Value.time.Hour = 0xff;
|
|
QuestionValue->Value.time.Minute = 0xff;
|
|
QuestionValue->Value.time.Second = 0xff;
|
|
}
|
|
|
|
return QuestionValue;
|
|
}
|
|
|
|
if (Question->Operand == EFI_IFR_DATE_OP) {
|
|
QuestionValue->Value.date.Year = EfiTime.Year;
|
|
QuestionValue->Value.date.Month = EfiTime.Month;
|
|
QuestionValue->Value.date.Day = EfiTime.Day;
|
|
} else {
|
|
QuestionValue->Value.time.Hour = EfiTime.Hour;
|
|
QuestionValue->Value.time.Minute = EfiTime.Minute;
|
|
QuestionValue->Value.time.Second = EfiTime.Second;
|
|
}
|
|
} else {
|
|
if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) ||
|
|
(FormSet->ConfigAccess == NULL))
|
|
{
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
if (QuestionValue->Type == EFI_IFR_TYPE_BUFFER) {
|
|
//
|
|
// For OrderedList, passing in the value buffer to Callback()
|
|
//
|
|
TypeValue = (EFI_IFR_TYPE_VALUE *)QuestionValue->Buffer;
|
|
} else {
|
|
TypeValue = &QuestionValue->Value;
|
|
}
|
|
|
|
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
|
|
Status = FormSet->ConfigAccess->Callback (
|
|
FormSet->ConfigAccess,
|
|
EFI_BROWSER_ACTION_RETRIEVE,
|
|
Question->QuestionId,
|
|
QuestionValue->Type,
|
|
TypeValue,
|
|
&ActionRequest
|
|
);
|
|
|
|
if (!EFI_ERROR (Status) && (QuestionValue->Type == EFI_IFR_TYPE_STRING)) {
|
|
if (TypeValue->string == 0) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
NewHiiString = GetTokenString (TypeValue->string, FormSet->HiiHandle);
|
|
if (NewHiiString == NULL) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
QuestionValue->Buffer = AllocatePool (StrSize (NewHiiString));
|
|
if (QuestionValue->Buffer == NULL) {
|
|
FreePool (NewHiiString);
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
CopyMem (QuestionValue->Buffer, NewHiiString, StrSize (NewHiiString));
|
|
QuestionValue->BufferLen = (UINT16)StrSize (NewHiiString);
|
|
|
|
FreePool (NewHiiString);
|
|
}
|
|
}
|
|
|
|
return QuestionValue;
|
|
}
|
|
|
|
//
|
|
// Question value is provided by EFI variable
|
|
//
|
|
if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
|
|
if ((QuestionValue->Type != EFI_IFR_TYPE_BUFFER) && (QuestionValue->Type != EFI_IFR_TYPE_STRING)) {
|
|
Dst = QuestionValue->Buffer;
|
|
StorageWidth = QuestionValue->BufferLen;
|
|
} else {
|
|
Dst = (UINT8 *)&QuestionValue->Value;
|
|
StorageWidth = sizeof (EFI_IFR_TYPE_VALUE);
|
|
}
|
|
|
|
Status = gRT->GetVariable (
|
|
Question->VariableName,
|
|
&Storage->Guid,
|
|
NULL,
|
|
&StorageWidth,
|
|
Dst
|
|
);
|
|
|
|
return QuestionValue;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiHiiConfigRoutingProtocolGuid,
|
|
NULL,
|
|
(VOID **)&HiiConfigRouting
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
if (QuestionValue->BufferLen != 0) {
|
|
Dst = QuestionValue->Buffer;
|
|
} else {
|
|
Dst = (UINT8 *)&QuestionValue->Value;
|
|
}
|
|
|
|
if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
|
|
IsBufferStorage = TRUE;
|
|
} else {
|
|
IsBufferStorage = FALSE;
|
|
}
|
|
|
|
Storage = GetFstStgFromVarId (FormSet, Question->VarStoreId);
|
|
if (Storage == NULL) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// <ConfigRequest> ::= <ConfigHdr> + <BlockName> || <ConfigHdr> + "&" + <VariableName>
|
|
//
|
|
if (IsBufferStorage) {
|
|
Length = StrLen (Storage->ConfigHdr);
|
|
Length += StrLen (Question->BlockName);
|
|
} else {
|
|
Length = StrLen (Storage->ConfigHdr);
|
|
Length += StrLen (Question->VariableName) + 1;
|
|
}
|
|
|
|
ConfigRequest = AllocatePool ((Length + 1) * sizeof (CHAR16));
|
|
if (ConfigRequest == NULL) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
StrCpyS (ConfigRequest, Length + 1, Storage->ConfigHdr);
|
|
if (IsBufferStorage) {
|
|
StrCatS (ConfigRequest, Length + 1, Question->BlockName);
|
|
} else {
|
|
StrCatS (ConfigRequest, Length + 1, L"&");
|
|
StrCatS (ConfigRequest, Length + 1, Question->VariableName);
|
|
}
|
|
|
|
//
|
|
// Request current settings from Configuration Driver
|
|
//
|
|
Status = HiiConfigRouting->ExtractConfig (
|
|
HiiConfigRouting,
|
|
ConfigRequest,
|
|
&Progress,
|
|
&Result
|
|
);
|
|
FreePool (ConfigRequest);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
if (IsBufferStorage) {
|
|
ValueStr = StrStr (Result, L"&VALUE");
|
|
if (ValueStr == NULL) {
|
|
FreePool (Result);
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
ValueStr = ValueStr + 6;
|
|
} else {
|
|
ValueStr = Result + Length;
|
|
}
|
|
|
|
if (*ValueStr != '=') {
|
|
FreePool (Result);
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
ValueStr++;
|
|
Status = BufferToQuestionValue (Question, ValueStr, QuestionValue);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (Result);
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
if (Result != NULL) {
|
|
FreePool (Result);
|
|
}
|
|
|
|
return QuestionValue;
|
|
|
|
ON_ERROR:
|
|
|
|
if (QuestionValue->Buffer != NULL) {
|
|
FreePool (QuestionValue->Buffer);
|
|
}
|
|
|
|
FreePool (QuestionValue);
|
|
|
|
return NULL;
|
|
}
|