Enhance SetupBrowser to support new UEFI HiiFormMap feature

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10069 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lgao4
2010-02-25 10:10:59 +00:00
parent 234980f6e9
commit 2573712e01
10 changed files with 1022 additions and 99 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -450,6 +450,8 @@ DestroyExpression (
{
LIST_ENTRY *Link;
EXPRESSION_OPCODE *OpCode;
LIST_ENTRY *SubExpressionLink;
FORM_EXPRESSION *SubExpression;
while (!IsListEmpty (&Expression->OpCodeListHead)) {
Link = GetFirstNode (&Expression->OpCodeListHead);
@@ -459,6 +461,19 @@ DestroyExpression (
if (OpCode->ValueList != NULL) {
FreePool (OpCode->ValueList);
}
if (OpCode->ValueName != NULL) {
FreePool (OpCode->ValueName);
}
if (OpCode->MapExpressionList.ForwardLink != NULL) {
while (!IsListEmpty (&OpCode->MapExpressionList)) {
SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
RemoveEntryList(&SubExpression->Link);
DestroyExpression (SubExpression);
}
}
}
//
@@ -746,10 +761,12 @@ IsExpressionOpCode (
)
{
if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SET_OP)) ||
((Operand >= EFI_IFR_EQUAL_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
(Operand == EFI_IFR_CATENATE_OP) ||
(Operand == EFI_IFR_TO_LOWER_OP) ||
(Operand == EFI_IFR_TO_UPPER_OP) ||
(Operand == EFI_IFR_MAP_OP) ||
(Operand == EFI_IFR_VERSION_OP) ||
(Operand == EFI_IFR_SECURITY_OP)) {
return TRUE;
@@ -848,6 +865,12 @@ ParseOpCodes (
BOOLEAN SingleOpCodeExpression;
BOOLEAN InScopeDefault;
EFI_HII_VALUE *Value;
EFI_IFR_FORM_MAP_METHOD *MapMethod;
UINT8 MapScopeDepth;
LIST_ENTRY *Link;
FORMSET_STORAGE *VarStorage;
LIST_ENTRY *MapExpressionList;
EFI_VARSTORE_ID TempVarstoreId;
mInScopeSubtitle = FALSE;
SuppressForQuestion = FALSE;
@@ -867,6 +890,12 @@ ParseOpCodes (
OptionSuppressExpression = NULL;
FormSuppressExpression = NULL;
ImageId = NULL;
MapMethod = NULL;
MapScopeDepth = 0;
Link = NULL;
VarStorage = NULL;
MapExpressionList = NULL;
TempVarstoreId = 0;
//
// Get the number of Statements and Expressions
@@ -888,6 +917,8 @@ ParseOpCodes (
InitializeListHead (&FormSet->StorageListHead);
InitializeListHead (&FormSet->DefaultStoreListHead);
InitializeListHead (&FormSet->FormListHead);
ResetCurrentExpressionStack ();
ResetMapExpressionListStack ();
CurrentForm = NULL;
CurrentStatement = NULL;
@@ -989,6 +1020,81 @@ ParseOpCodes (
CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
break;
case EFI_IFR_GET_OP:
case EFI_IFR_SET_OP:
CopyMem (&TempVarstoreId, &((EFI_IFR_GET *) OpCodeData)->VarStoreId, sizeof (TempVarstoreId));
if (TempVarstoreId != 0) {
if (FormSet->StorageListHead.ForwardLink != NULL) {
Link = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, Link)) {
VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
ExpressionOpCode->VarStorage = VarStorage;
break;
}
Link = GetNextNode (&FormSet->StorageListHead, Link);
}
}
if (ExpressionOpCode->VarStorage == NULL) {
//
// VarStorage is not found.
//
return EFI_INVALID_PARAMETER;
}
}
ExpressionOpCode->ValueType = ((EFI_IFR_GET *) OpCodeData)->VarStoreType;
switch (ExpressionOpCode->ValueType) {
case EFI_IFR_TYPE_BOOLEAN:
case EFI_IFR_TYPE_NUM_SIZE_8:
ExpressionOpCode->ValueWidth = 1;
break;
case EFI_IFR_TYPE_NUM_SIZE_16:
case EFI_IFR_TYPE_STRING:
ExpressionOpCode->ValueWidth = 2;
break;
case EFI_IFR_TYPE_NUM_SIZE_32:
ExpressionOpCode->ValueWidth = 4;
break;
case EFI_IFR_TYPE_NUM_SIZE_64:
ExpressionOpCode->ValueWidth = 8;
break;
case EFI_IFR_TYPE_DATE:
ExpressionOpCode->ValueWidth = sizeof (EFI_IFR_DATE);
break;
case EFI_IFR_TYPE_TIME:
ExpressionOpCode->ValueWidth = sizeof (EFI_IFR_TIME);
break;
case EFI_IFR_TYPE_OTHER:
case EFI_IFR_TYPE_UNDEFINED:
case EFI_IFR_TYPE_ACTION:
case EFI_IFR_TYPE_BUFFER:
default:
//
// Invalid value type for Get/Set opcode.
//
return EFI_INVALID_PARAMETER;
}
CopyMem (&ExpressionOpCode->VarStoreInfo.VarName, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarName, sizeof (EFI_STRING_ID));
CopyMem (&ExpressionOpCode->VarStoreInfo.VarOffset, &((EFI_IFR_GET *) OpCodeData)->VarStoreInfo.VarOffset, sizeof (UINT16));
if ((ExpressionOpCode->VarStorage != NULL) &&
(ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_NAME_VALUE ||
ExpressionOpCode->VarStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
ExpressionOpCode->ValueName = GetToken (ExpressionOpCode->VarStoreInfo.VarName, FormSet->HiiHandle);
if (ExpressionOpCode->ValueName == NULL) {
//
// String ID is invalid.
//
return EFI_INVALID_PARAMETER;
}
}
break;
case EFI_IFR_QUESTION_REF1_OP:
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
break;
@@ -1063,11 +1169,37 @@ ParseOpCodes (
default:
break;
}
//
// Create sub expression nested in MAP opcode
//
if (CurrentExpression == NULL && MapScopeDepth > 0) {
CurrentExpression = CreateExpression (CurrentForm);
InsertTailList (MapExpressionList, &CurrentExpression->Link);
if (Scope == 0) {
SingleOpCodeExpression = TRUE;
}
}
ASSERT (CurrentExpression != NULL);
InsertTailList (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
if (SingleOpCodeExpression) {
if (Operand == EFI_IFR_MAP_OP) {
//
// Store current Map Expression List.
//
if (MapExpressionList != NULL) {
PushMapExpressionList (MapExpressionList);
}
//
// Initialize new Map Expression List.
//
MapExpressionList = &ExpressionOpCode->MapExpressionList;
InitializeListHead (MapExpressionList);
//
// Store current expression.
//
PushCurrentExpression (CurrentExpression);
CurrentExpression = NULL;
MapScopeDepth ++;
} else if (SingleOpCodeExpression) {
//
// There are two cases to indicate the end of an Expression:
// for single OpCode expression: one Expression OpCode
@@ -1134,6 +1266,7 @@ ParseOpCodes (
InitializeListHead (&CurrentForm->ExpressionListHead);
InitializeListHead (&CurrentForm->StatementListHead);
CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
@@ -1157,6 +1290,63 @@ ParseOpCodes (
InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
break;
case EFI_IFR_FORM_MAP_OP:
//
// Create a new Form for this FormSet
//
CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
ASSERT (CurrentForm != NULL);
CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
InitializeListHead (&CurrentForm->ExpressionListHead);
InitializeListHead (&CurrentForm->StatementListHead);
CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
//
// FormMap Form must contain at least one Map Method.
//
if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < ((UINTN) (UINT8 *) (MapMethod + 1) - (UINTN) OpCodeData)) {
return EFI_INVALID_PARAMETER;
}
//
// Try to find the standard form map method.
//
while (((UINTN) (UINT8 *) MapMethod - (UINTN) OpCodeData) < ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) {
if (CompareGuid ((EFI_GUID *) (VOID *) &MapMethod->MethodIdentifier, &gEfiHiiStandardFormGuid)) {
CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
break;
}
MapMethod ++;
}
//
// If the standard form map method is not found, the first map method title will be used.
//
if (CurrentForm->FormTitle == 0) {
MapMethod = (EFI_IFR_FORM_MAP_METHOD *) (OpCodeData + sizeof (EFI_IFR_FORM_MAP));
CopyMem (&CurrentForm->FormTitle, &MapMethod->MethodTitle, sizeof (EFI_STRING_ID));
}
if (InScopeFormSuppress) {
//
// Form is inside of suppressif
//
CurrentForm->SuppressExpression = FormSuppressExpression;
}
if (Scope != 0) {
//
// Enter scope of a Form, suppressif will be used for Question or Option
//
SuppressForQuestion = TRUE;
}
//
// Insert into Form list of this FormSet
//
InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
break;
//
// Storage
//
@@ -1707,6 +1897,50 @@ ParseOpCodes (
}
break;
case EFI_IFR_READ_OP:
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
//
// Make sure CurrentStatement is not NULL.
// If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
// file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
//
ASSERT (CurrentStatement != NULL);
CurrentStatement->ReadExpression = CurrentExpression;
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
case EFI_IFR_WRITE_OP:
CurrentExpression = CreateExpression (CurrentForm);
CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
//
// Make sure CurrentStatement is not NULL.
// If it is NULL, 1) ParseOpCodes functions may parse the IFR wrongly. Or 2) the IFR
// file is wrongly generated by tools such as VFR Compiler. There may be a bug in VFR Compiler.
//
ASSERT (CurrentStatement != NULL);
CurrentStatement->WriteExpression = CurrentExpression;
//
// Take a look at next OpCode to see whether current expression consists
// of single OpCode
//
if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
SingleOpCodeExpression = TRUE;
}
break;
//
// Image
//
@@ -1723,6 +1957,7 @@ ParseOpCodes (
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
ASSERT (CurrentForm != NULL);
ImageId = &CurrentForm->ImageId;
break;
@@ -1818,6 +2053,7 @@ ParseOpCodes (
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
//
// End of Form
//
@@ -1871,6 +2107,22 @@ ParseOpCodes (
InScopeDefault = FALSE;
break;
case EFI_IFR_MAP_OP:
//
// Get current Map Expression List.
//
Status = PopMapExpressionList ((VOID **) &MapExpressionList);
if (Status == EFI_ACCESS_DENIED) {
MapExpressionList = NULL;
}
//
// Get current expression.
//
Status = PopCurrentExpression ((VOID **) &CurrentExpression);
ASSERT_EFI_ERROR (Status);
MapScopeDepth --;
break;
default:
if (IsExpressionOpCode (ScopeOpCode)) {
if (mInScopeDisable && CurrentForm == NULL) {
@@ -1889,7 +2141,7 @@ ParseOpCodes (
OpCodeDisabled = CurrentExpression->Result.Value.b;
//
// DisableIf Expression is only used once and not quequed, free it
// DisableIf Expression is only used once and not queued, free it
//
DestroyExpression (CurrentExpression);
}

View File

@@ -387,9 +387,11 @@ EvaluateFormExpressions (
Link = GetNextNode (&Form->ExpressionListHead, Link);
if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||
Expression->Type == EFI_HII_EXPRESSION_WRITE ||
(Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {
//
// Postpone Form validation to Question editing or Form submiting
// Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
//
continue;
}

View File

@@ -661,6 +661,10 @@ GetToken (
{
EFI_STRING String;
if (HiiHandle == NULL) {
return NULL;
}
String = HiiGetString (HiiHandle, Token, NULL);
if (String == NULL) {
String = AllocateCopyPool (sizeof (mUnknownString), mUnknownString);
@@ -1041,6 +1045,20 @@ GetQuestionValue (
}
return Status;
}
//
// Get question value by read expression.
//
if (Question->ReadExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {
Status = EvaluateExpression (FormSet, Form, Question->ReadExpression);
if (!EFI_ERROR (Status) && (Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER)) {
//
// Only update question value to the valid result.
//
CopyMem (&Question->HiiValue, &Question->ReadExpression->Result, sizeof (EFI_HII_VALUE));
return EFI_SUCCESS;
}
}
//
// Question value is provided by RTC
@@ -1369,6 +1387,16 @@ SetQuestionValue (
if (Question->ValueExpression != NULL) {
return Status;
}
//
// Before set question value, evaluate its write expression.
//
if (Question->WriteExpression != NULL && Form->FormType == STANDARD_MAP_FORM_TYPE) {
Status = EvaluateExpression (FormSet, Form, Question->WriteExpression);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Question value is provided by RTC

View File

@@ -32,6 +32,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Guid/MdeModuleHii.h>
#include <Guid/HiiPlatformSetupFormset.h>
#include <Guid/HiiFormMapMethodGuid.h>
#include <Library/PrintLib.h>
#include <Library/DebugLib.h>
@@ -183,6 +184,8 @@ typedef struct {
#define EFI_HII_EXPRESSION_DISABLE_IF 4
#define EFI_HII_EXPRESSION_VALUE 5
#define EFI_HII_EXPRESSION_RULE 6
#define EFI_HII_EXPRESSION_READ 7
#define EFI_HII_EXPRESSION_WRITE 8
#define EFI_HII_VARSTORE_BUFFER 0
#define EFI_HII_VARSTORE_NAME_VALUE 1
@@ -239,6 +242,11 @@ typedef struct {
#define FORMSET_STORAGE_FROM_LINK(a) CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)
typedef union {
EFI_STRING_ID VarName;
UINT16 VarOffset;
} VAR_STORE_INFO;
#define EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O', 'P')
typedef struct {
@@ -261,6 +269,13 @@ typedef struct {
EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
EFI_GUID Guid;
FORMSET_STORAGE *VarStorage; // For EFI_IFR_SET, EFI_IFR_GET
VAR_STORE_INFO VarStoreInfo;// For EFI_IFR_SET, EFI_IFR_GET
UINT8 ValueType; // For EFI_IFR_SET, EFI_IFR_GET
UINT8 ValueWidth; // For EFI_IFR_SET, EFI_IFR_GET
CHAR16 *ValueName; // For EFI_IFR_SET, EFI_IFR_GET
LIST_ENTRY MapExpressionList; // nested expressions inside of Map opcode.
} EXPRESSION_OPCODE;
#define EXPRESSION_OPCODE_FROM_LINK(a) CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)
@@ -315,11 +330,6 @@ typedef struct {
#define FORM_BROWSER_STATEMENT_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'A')
typedef union {
EFI_STRING_ID VarName;
UINT16 VarOffset;
} VAR_STORE_INFO;
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
@@ -386,18 +396,22 @@ typedef struct {
FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf
FORM_EXPRESSION *DisableExpression; // nesting inside of DisableIf
FORM_EXPRESSION *ReadExpression; // nested EFI_IFR_READ, provide this question value by read expression.
FORM_EXPRESSION *WriteExpression; // nested EFI_IFR_WRITE, evaluate write expression after this question value is set.
} FORM_BROWSER_STATEMENT;
#define FORM_BROWSER_STATEMENT_FROM_LINK(a) CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)
#define FORM_BROWSER_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')
#define STANDARD_MAP_FORM_TYPE 0x01
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
UINT16 FormId;
EFI_STRING_ID FormTitle;
UINT16 FormId; // FormId of normal form or formmap form.
EFI_STRING_ID FormTitle; // FormTile of normal form, or FormMapMethod title of formmap form.
UINT16 FormType; // Specific form type for the different form.
EFI_IMAGE_ID ImageId;
@@ -795,6 +809,42 @@ CreateDialog (
...
);
/**
Get Value for given Name from a NameValue Storage.
@param Storage The NameValue Storage.
@param Name The Name.
@param Value The retured Value.
@retval EFI_SUCCESS Value found for given Name.
@retval EFI_NOT_FOUND No such Name found in NameValue storage.
**/
EFI_STATUS
GetValueByName (
IN FORMSET_STORAGE *Storage,
IN CHAR16 *Name,
IN OUT CHAR16 **Value
);
/**
Set Value of given Name in a NameValue Storage.
@param Storage The NameValue Storage.
@param Name The Name.
@param Value The Value to set.
@retval EFI_SUCCESS Value found for given Name.
@retval EFI_NOT_FOUND No such Name found in NameValue storage.
**/
EFI_STATUS
SetValueByName (
IN FORMSET_STORAGE *Storage,
IN CHAR16 *Name,
IN CHAR16 *Value
);
/**
Get Question's current Value.

View File

@@ -63,6 +63,7 @@
gEfiIfrTianoGuid ## CONSUMES ## GUID
gEfiIfrFrameworkGuid ## CONSUMES ## GUID
gEfiHiiPlatformSetupFormsetGuid
gEfiHiiStandardFormGuid ## SOMETIMES_CONSUMES ## GUID
[Protocols]
gEfiHiiConfigAccessProtocolGuid ## CONSUMES

View File

@@ -735,6 +735,80 @@ PopScope (
OUT UINT8 *Operand
);
/**
Reset stack pointer to begin of the stack.
**/
VOID
ResetCurrentExpressionStack (
VOID
);
/**
Push current expression onto the Stack
@param Pointer Pointer to current expression.
@retval EFI_SUCCESS The value was pushed onto the stack.
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
**/
EFI_STATUS
PushCurrentExpression (
IN VOID *Pointer
);
/**
Pop current expression from the Stack
@param Pointer Pointer to current expression to be pop.
@retval EFI_SUCCESS The value was pushed onto the stack.
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
**/
EFI_STATUS
PopCurrentExpression (
OUT VOID **Pointer
);
/**
Reset stack pointer to begin of the stack.
**/
VOID
ResetMapExpressionListStack (
VOID
);
/**
Push the list of map expression onto the Stack
@param Pointer Pointer to the list of map expression to be pushed.
@retval EFI_SUCCESS The value was pushed onto the stack.
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
**/
EFI_STATUS
PushMapExpressionList (
IN VOID *Pointer
);
/**
Pop the list of map expression from the Stack
@param Pointer Pointer to the list of map expression to be pop.
@retval EFI_SUCCESS The value was pushed onto the stack.
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
**/
EFI_STATUS
PopMapExpressionList (
OUT VOID **Pointer
);
/**
Get Form given its FormId.