summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal')
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Colors.h17
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Expression.c3863
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c47
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c2290
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c1933
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Print.c675
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Print.h10
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c34
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.c4614
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.h1818
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.c5732
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.h1270
12 files changed, 11479 insertions, 10824 deletions
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
index 1b355ec..94c3368 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
@@ -1,4 +1,5 @@
/** @file
+MACRO definitions for color used in Setup Browser.
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
@@ -9,20 +10,12 @@ http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-Module Name:
-
- Colors.h
-
-Abstract:
-
-
-Revision History
-
-
**/
+//
+// Unicode collation protocol in
-#ifndef _COLORS_H
-#define _COLORS_H
+#ifndef _COLORS_H_
+#define _COLORS_H_
//
// Screen Color Settings
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
index a074b92..25d4e0a 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
@@ -1,1938 +1,1925 @@
-/** @file
-
-Copyright (c) 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- Expression.c
-
-Abstract:
-
- Expression evaluation.
-
-
-**/
-
-#include "Ui.h"
-#include "Setup.h"
-
-//
-// Global stack used to evaluate boolean expresions
-//
-EFI_HII_VALUE *mOpCodeScopeStack = NULL;
-EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
-EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
-
-EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
-EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
-EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
-
-//
-// Unicode collation protocol interface
-//
-EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
-
-
-/**
- Grow size of the stack
-
- @param Stack On input: old stack; On output: new stack
- @param StackPtr On input: old stack pointer; On output: new stack
- pointer
- @param StackPtr On input: old stack end; On output: new stack end
-
- @retval EFI_SUCCESS Grow stack success.
- @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
-
-**/
-STATIC
-EFI_STATUS
-GrowStack (
- IN OUT EFI_HII_VALUE **Stack,
- IN OUT EFI_HII_VALUE **StackPtr,
- IN OUT EFI_HII_VALUE **StackEnd
- )
-{
- UINTN Size;
- EFI_HII_VALUE *NewStack;
-
- Size = EXPRESSION_STACK_SIZE_INCREMENT;
- if (*StackPtr != NULL) {
- Size = Size + (*StackEnd - *Stack);
- }
-
- NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
- if (NewStack == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- if (*StackPtr != NULL) {
- //
- // Copy from Old Stack to the New Stack
- //
- CopyMem (
- NewStack,
- *Stack,
- (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
- );
-
- //
- // Free The Old Stack
- //
- gBS->FreePool (*Stack);
- }
-
- //
- // Make the Stack pointer point to the old data in the new stack
- //
- *StackPtr = NewStack + (*StackPtr - *Stack);
- *Stack = NewStack;
- *StackEnd = NewStack + Size;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Push an element onto the Boolean Stack
-
- @param Stack On input: old stack; On output: new stack
- @param StackPtr On input: old stack pointer; On output: new stack
- pointer
- @param StackPtr On input: old stack end; On output: new stack end
- @param Data Data to push.
-
- @retval EFI_SUCCESS Push stack success.
-
-**/
-EFI_STATUS
-PushStack (
- IN OUT EFI_HII_VALUE **Stack,
- IN OUT EFI_HII_VALUE **StackPtr,
- IN OUT EFI_HII_VALUE **StackEnd,
- IN EFI_HII_VALUE *Data
- )
-{
- EFI_STATUS Status;
-
- //
- // Check for a stack overflow condition
- //
- if (*StackPtr >= *StackEnd) {
- //
- // Grow the stack
- //
- Status = GrowStack (Stack, StackPtr, StackEnd);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- //
- // Push the item onto the stack
- //
- CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
- *StackPtr = *StackPtr + 1;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Pop an element from the stack.
-
- @param Stack On input: old stack; On output: new stack
- @param StackPtr On input: old stack pointer; On output: new stack
- pointer
- @param StackPtr On input: old stack end; On output: new stack end
- @param Data Data to pop.
-
- @retval EFI_SUCCESS The value was popped onto the stack.
- @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
-
-**/
-EFI_STATUS
-PopStack (
- IN OUT EFI_HII_VALUE **Stack,
- IN OUT EFI_HII_VALUE **StackPtr,
- IN OUT EFI_HII_VALUE **StackEnd,
- OUT EFI_HII_VALUE *Data
- )
-{
- //
- // Check for a stack underflow condition
- //
- if (*StackPtr == *Stack) {
- return EFI_ACCESS_DENIED;
- }
-
- //
- // Pop the item off the stack
- //
- *StackPtr = *StackPtr - 1;
- CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
- return EFI_SUCCESS;
-}
-
-
-/**
- Reset stack pointer to begin of the stack.
-
- None.
-
- @return None.
-
-**/
-VOID
-ResetScopeStack (
- VOID
- )
-{
- mOpCodeScopeStackPointer = mOpCodeScopeStack;
-}
-
-
-/**
- Push an Operand onto the Stack
-
- @param Operand Operand to push.
-
- @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
-PushScope (
- IN UINT8 Operand
- )
-{
- EFI_HII_VALUE Data;
-
- Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
- Data.Value.u8 = Operand;
-
- return PushStack (
- &mOpCodeScopeStack,
- &mOpCodeScopeStackPointer,
- &mOpCodeScopeStackEnd,
- &Data
- );
-}
-
-
-/**
- Pop an Operand from the Stack
-
- @param Operand Operand to 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
-PopScope (
- OUT UINT8 *Operand
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Data;
-
- Status = PopStack (
- &mOpCodeScopeStack,
- &mOpCodeScopeStackPointer,
- &mOpCodeScopeStackEnd,
- &Data
- );
-
- *Operand = Data.Value.u8;
-
- return Status;
-}
-
-
-/**
- Reset stack pointer to begin of the stack.
-
- None.
-
- @return None.
-
-**/
-VOID
-ResetExpressionStack (
- VOID
- )
-{
- mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
-}
-
-
-/**
- Push an Expression value onto the Stack
-
- @param Value Expression value to push.
-
- @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
-PushExpression (
- IN EFI_HII_VALUE *Value
- )
-{
- return PushStack (
- &mExpressionEvaluationStack,
- &mExpressionEvaluationStackPointer,
- &mExpressionEvaluationStackEnd,
- Value
- );
-}
-
-
-/**
- Pop an Expression value from the stack.
-
- @param Value Expression value to pop.
-
- @retval EFI_SUCCESS The value was popped onto the stack.
- @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
-
-**/
-EFI_STATUS
-PopExpression (
- OUT EFI_HII_VALUE *Value
- )
-{
- return PopStack (
- &mExpressionEvaluationStack,
- &mExpressionEvaluationStackPointer,
- &mExpressionEvaluationStackEnd,
- Value
- );
-}
-
-
-/**
- Get Form given its FormId.
-
- @param FormSet The formset which contains this form.
- @param FormId Id of this form.
-
- @retval Pointer The form.
- @retval NULL Specified Form is not found in the formset.
-
-**/
-FORM_BROWSER_FORM *
-IdToForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN UINT16 FormId
-)
-{
- LIST_ENTRY *Link;
- FORM_BROWSER_FORM *Form;
-
- Link = GetFirstNode (&FormSet->FormListHead);
- while (!IsNull (&FormSet->FormListHead, Link)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
- if (Form->FormId == FormId) {
- return Form;
- }
-
- Link = GetNextNode (&FormSet->FormListHead, Link);
- }
-
- return NULL;
-}
-
-
-/**
- Search a Question in Form scope using its QuestionId.
-
- @param Form The form which contains this Question.
- @param QuestionId Id of this Question.
-
- @retval Pointer The Question.
- @retval NULL Specified Question not found in the form.
-
-**/
-FORM_BROWSER_STATEMENT *
-IdToQuestion2 (
- IN FORM_BROWSER_FORM *Form,
- IN UINT16 QuestionId
- )
-{
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Question;
-
- if (QuestionId == 0) {
- //
- // The value of zero is reserved
- //
- return NULL;
- }
-
- Link = GetFirstNode (&Form->StatementListHead);
- while (!IsNull (&Form->StatementListHead, Link)) {
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
- if (Question->QuestionId == QuestionId) {
- return Question;
- }
-
- Link = GetNextNode (&Form->StatementListHead, Link);
- }
-
- return NULL;
-}
-
-
-/**
- Search a Question in Formset scope using its QuestionId.
-
- @param FormSet The formset which contains this form.
- @param Form The form which contains this Question.
- @param QuestionId Id of this Question.
-
- @retval Pointer The Question.
- @retval NULL Specified Question not found in the form.
-
-**/
-FORM_BROWSER_STATEMENT *
-IdToQuestion (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN UINT16 QuestionId
- )
-{
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Question;
-
- //
- // Search in the form scope first
- //
- Question = IdToQuestion2 (Form, QuestionId);
- if (Question != NULL) {
- return Question;
- }
-
- //
- // Search in the formset scope
- //
- Link = GetFirstNode (&FormSet->FormListHead);
- while (!IsNull (&FormSet->FormListHead, Link)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
- Question = IdToQuestion2 (Form, QuestionId);
- if (Question != NULL) {
- return Question;
- }
-
- Link = GetNextNode (&FormSet->FormListHead, Link);
- }
-
- return NULL;
-}
-
-
-/**
- Get Expression given its RuleId.
-
- @param Form The form which contains this Expression.
- @param RuleId Id of this Expression.
-
- @retval Pointer The Expression.
- @retval NULL Specified Expression not found in the form.
-
-**/
-FORM_EXPRESSION *
-RuleIdToExpression (
- IN FORM_BROWSER_FORM *Form,
- IN UINT8 RuleId
- )
-{
- LIST_ENTRY *Link;
- FORM_EXPRESSION *Expression;
-
- Link = GetFirstNode (&Form->ExpressionListHead);
- while (!IsNull (&Form->ExpressionListHead, Link)) {
- Expression = FORM_EXPRESSION_FROM_LINK (Link);
-
- if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {
- return Expression;
- }
-
- Link = GetNextNode (&Form->ExpressionListHead, Link);
- }
-
- return NULL;
-}
-
-
-/**
- Locate the Unicode Collation Protocol interface for later use.
-
- None.
-
- @retval EFI_SUCCESS Protocol interface initialize success.
- @retval Other Protocol interface initialize failed.
-
-**/
-EFI_STATUS
-InitializeUnicodeCollationProtocol (
- VOID
- )
-{
- EFI_STATUS Status;
-
- if (mUnicodeCollation != NULL) {
- return EFI_SUCCESS;
- }
-
- //
- // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
- // instances first and then select one which support English language.
- // Current implementation just pick the first instance.
- //
- Status = gBS->LocateProtocol (
- &gEfiUnicodeCollation2ProtocolGuid,
- NULL,
- (VOID **) &mUnicodeCollation
- );
- return Status;
-}
-
-VOID
-IfrStrToUpper (
- CHAR16 *String
- )
-{
- while (*String != 0) {
- if ((*String >= 'a') && (*String <= 'z')) {
- *String = (UINT16) ((*String) & ((UINT16) ~0x20));
- }
- String++;
- }
-}
-
-
-/**
- Evaluate opcode EFI_IFR_TO_STRING.
-
- @param FormSet Formset which contains this opcode.
- @param Format String format in EFI_IFR_TO_STRING.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrToString (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN UINT8 Format,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String;
- CHAR16 *PrintFormat;
- CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];
- UINTN BufferSize;
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- switch (Value.Type) {
- case EFI_IFR_TYPE_NUM_SIZE_8:
- case EFI_IFR_TYPE_NUM_SIZE_16:
- case EFI_IFR_TYPE_NUM_SIZE_32:
- case EFI_IFR_TYPE_NUM_SIZE_64:
- BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
- switch (Format) {
- case EFI_IFR_STRING_UNSIGNED_DEC:
- case EFI_IFR_STRING_SIGNED_DEC:
- PrintFormat = L"%ld";
- break;
-
- case EFI_IFR_STRING_LOWERCASE_HEX:
- PrintFormat = L"%lx";
- break;
-
- case EFI_IFR_STRING_UPPERCASE_HEX:
- PrintFormat = L"%lX";
- break;
-
- default:
- return EFI_UNSUPPORTED;
- }
- UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
- String = Buffer;
- break;
-
- case EFI_IFR_TYPE_STRING:
- CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
- return EFI_SUCCESS;
-
- case EFI_IFR_TYPE_BOOLEAN:
- String = (Value.Value.b) ? L"True" : L"False";
- break;
-
- default:
- return EFI_UNSUPPORTED;
- }
-
- Result->Type = EFI_IFR_TYPE_STRING;
- Result->Value.string = NewString (String, FormSet->HiiHandle);
- return EFI_SUCCESS;
-}
-
-
-/**
- Evaluate opcode EFI_IFR_TO_UINT.
-
- @param FormSet Formset which contains this opcode.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrToUint (
- IN FORM_BROWSER_FORMSET *FormSet,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String;
- CHAR16 *StringPtr;
- UINTN BufferSize;
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (Value.Type >= EFI_IFR_TYPE_OTHER) {
- return EFI_UNSUPPORTED;
- }
-
- Status = EFI_SUCCESS;
- if (Value.Type == EFI_IFR_TYPE_STRING) {
- String = GetToken (Value.Value.string, FormSet->HiiHandle);
- if (String == NULL) {
- return EFI_NOT_FOUND;
- }
-
- IfrStrToUpper (String);
- StringPtr = StrStr (String, L"0X");
- if (StringPtr != NULL) {
- //
- // Hex string
- //
- BufferSize = sizeof (UINT64);
- Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);
- } else {
- //
- // BUGBUG: Need handle decimal string
- //
- }
- gBS->FreePool (String);
- } else {
- CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
- }
-
- Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
- return Status;
-}
-
-
-/**
- Evaluate opcode EFI_IFR_CATENATE.
-
- @param FormSet Formset which contains this opcode.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrCatenate (
- IN FORM_BROWSER_FORMSET *FormSet,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String[2];
- UINTN Index;
- CHAR16 *StringPtr;
- UINTN Size;
-
- //
- // String[0] - The second string
- // String[1] - The first string
- //
- String[0] = NULL;
- String[1] = NULL;
- StringPtr = NULL;
- Status = EFI_SUCCESS;
-
- for (Index = 0; Index < 2; Index++) {
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (Value.Type != EFI_IFR_TYPE_STRING) {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
- if (String== NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
- }
-
- Size = StrSize (String[0]);
- StringPtr= AllocatePool (StrSize (String[1]) + Size);
- ASSERT (StringPtr != NULL);
- StrCpy (StringPtr, String[1]);
- StrCat (StringPtr, String[0]);
-
- Result->Type = EFI_IFR_TYPE_STRING;
- Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
-
-Done:
- SafeFreePool (String[0]);
- SafeFreePool (String[1]);
- SafeFreePool (StringPtr);
-
- return Status;
-}
-
-
-/**
- Evaluate opcode EFI_IFR_MATCH.
-
- @param FormSet Formset which contains this opcode.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrMatch (
- IN FORM_BROWSER_FORMSET *FormSet,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String[2];
- UINTN Index;
-
- //
- // String[0] - The string to search
- // String[1] - pattern
- //
- String[0] = NULL;
- String[1] = NULL;
- Status = EFI_SUCCESS;
- for (Index = 0; Index < 2; Index++) {
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (Value.Type != EFI_IFR_TYPE_STRING) {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
- if (String== NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
- }
-
- Result->Type = EFI_IFR_TYPE_BOOLEAN;
- Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
-
-Done:
- SafeFreePool (String[0]);
- SafeFreePool (String[1]);
-
- return Status;
-}
-
-
-/**
- Evaluate opcode EFI_IFR_FIND.
-
- @param FormSet Formset which contains this opcode.
- @param Format Case sensitive or insensitive.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrFind (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN UINT8 Format,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String[2];
- UINTN Base;
- CHAR16 *StringPtr;
- UINTN Index;
-
- if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
- return EFI_UNSUPPORTED;
- }
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
- return EFI_UNSUPPORTED;
- }
- Base = (UINTN) Value.Value.u64;
-
- //
- // String[0] - sub-string
- // String[1] - The string to search
- //
- String[0] = NULL;
- String[1] = NULL;
- for (Index = 0; Index < 2; Index++) {
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (Value.Type != EFI_IFR_TYPE_STRING) {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
- if (String== NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
- //
- // Case insensitive, convert both string to upper case
- //
- IfrStrToUpper (String[Index]);
- }
- }
-
- Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
- if (Base >= StrLen (String[1])) {
- Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
- } else {
- StringPtr = StrStr (String[1] + Base, String[0]);
- Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
- }
-
-Done:
- SafeFreePool (String[0]);
- SafeFreePool (String[1]);
-
- return Status;
-}
-
-
-/**
- Evaluate opcode EFI_IFR_MID.
-
- @param FormSet Formset which contains this opcode.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrMid (
- IN FORM_BROWSER_FORMSET *FormSet,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String;
- UINTN Base;
- UINTN Length;
- CHAR16 *SubString;
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
- return EFI_UNSUPPORTED;
- }
- Length = (UINTN) Value.Value.u64;
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
- return EFI_UNSUPPORTED;
- }
- Base = (UINTN) Value.Value.u64;
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value.Type != EFI_IFR_TYPE_STRING) {
- return EFI_UNSUPPORTED;
- }
- String = GetToken (Value.Value.string, FormSet->HiiHandle);
- if (String == NULL) {
- return EFI_NOT_FOUND;
- }
-
- if (Length == 0 || Base >= StrLen (String)) {
- SubString = gEmptyString;
- } else {
- SubString = String + Base;
- if ((Base + Length) < StrLen (String)) {
- SubString[Length] = L'\0';
- }
- }
-
- Result->Type = EFI_IFR_TYPE_STRING;
- Result->Value.string = NewString (SubString, FormSet->HiiHandle);
-
- gBS->FreePool (String);
-
- return Status;
-}
-
-
-/**
- Evaluate opcode EFI_IFR_TOKEN.
-
- @param FormSet Formset which contains this opcode.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrToken (
- IN FORM_BROWSER_FORMSET *FormSet,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String[2];
- UINTN Count;
- CHAR16 *Delimiter;
- CHAR16 *SubString;
- CHAR16 *StringPtr;
- UINTN Index;
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
- return EFI_UNSUPPORTED;
- }
- Count = (UINTN) Value.Value.u64;
-
- //
- // String[0] - Delimiter
- // String[1] - The string to search
- //
- String[0] = NULL;
- String[1] = NULL;
- for (Index = 0; Index < 2; Index++) {
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (Value.Type != EFI_IFR_TYPE_STRING) {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
- if (String== NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
- }
-
- Delimiter = String[0];
- SubString = String[1];
- while (Count > 0) {
- SubString = StrStr (SubString, Delimiter);
- if (SubString != NULL) {
- //
- // Skip over the delimiter
- //
- SubString = SubString + StrLen (Delimiter);
- } else {
- break;
- }
- Count--;
- }
-
- if (SubString == NULL) {
- //
- // nth delimited sub-string not found, push an empty string
- //
- SubString = gEmptyString;
- } else {
- //
- // Put a NULL terminator for nth delimited sub-string
- //
- StringPtr = StrStr (SubString, Delimiter);
- if (StringPtr != NULL) {
- *StringPtr = L'\0';
- }
- }
-
- Result->Type = EFI_IFR_TYPE_STRING;
- Result->Value.string = NewString (SubString, FormSet->HiiHandle);
-
-Done:
- SafeFreePool (String[0]);
- SafeFreePool (String[1]);
-
- return Status;
-}
-
-
-/**
- Evaluate opcode EFI_IFR_SPAN.
-
- @param FormSet Formset which contains this opcode.
- @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
- @param Result Evaluation result for this opcode.
-
- @retval EFI_SUCCESS Opcode evaluation success.
- @retval Other Opcode evaluation failed.
-
-**/
-EFI_STATUS
-IfrSpan (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN UINT8 Flags,
- OUT EFI_HII_VALUE *Result
- )
-{
- EFI_STATUS Status;
- EFI_HII_VALUE Value;
- CHAR16 *String[2];
- CHAR16 *Charset;
- UINTN Base;
- UINTN Index;
- CHAR16 *StringPtr;
- BOOLEAN Found;
-
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
- return EFI_UNSUPPORTED;
- }
- Base = (UINTN) Value.Value.u64;
-
- //
- // String[0] - Charset
- // String[1] - The string to search
- //
- String[0] = NULL;
- String[1] = NULL;
- for (Index = 0; Index < 2; Index++) {
- Status = PopExpression (&Value);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (Value.Type != EFI_IFR_TYPE_STRING) {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
- if (String== NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
- }
-
- if (Base >= StrLen (String[1])) {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- Found = FALSE;
- StringPtr = String[1] + Base;
- Charset = String[0];
- while (*StringPtr != 0 && !Found) {
- Index = 0;
- while (Charset[Index] != 0) {
- if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {
- if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
- Found = TRUE;
- break;
- }
- } else {
- if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
- Found = TRUE;
- break;
- }
- }
- //
- // Skip characters pair representing low-end of a range and high-end of a range
- //
- Index += 2;
- }
-
- if (!Found) {
- StringPtr++;
- }
- }
-
- Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
- Result->Value.u64 = StringPtr - String[1];
-
-Done:
- SafeFreePool (String[0]);
- SafeFreePool (String[1]);
-
- return Status;
-}
-
-
-/**
- Zero extend integer/boolean/date/time to UINT64 for comparing.
-
- @param Value HII Value to be converted.
-
- @return None.
-
-**/
-VOID
-ExtendValueToU64 (
- IN EFI_HII_VALUE *Value
- )
-{
- UINT64 Temp;
-
- Temp = 0;
- switch (Value->Type) {
- case EFI_IFR_TYPE_NUM_SIZE_8:
- Temp = Value->Value.u8;
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_16:
- Temp = Value->Value.u16;
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_32:
- Temp = Value->Value.u32;
- break;
-
- case EFI_IFR_TYPE_BOOLEAN:
- Temp = Value->Value.b;
- break;
-
- case EFI_IFR_TYPE_TIME:
- Temp = Value->Value.u32 & 0xffffff;
- break;
-
- case EFI_IFR_TYPE_DATE:
- Temp = Value->Value.u32;
- break;
-
- default:
- return;
- }
-
- Value->Value.u64 = Temp;
-}
-
-
-/**
- Compare two Hii value.
-
- @param Value1 Expression value to compare on left-hand
- @param Value2 Expression value to compare on right-hand
- @param HiiHandle Only required for string compare
-
- @retval EFI_INVALID_PARAMETER Could not perform comparation on two values
- @retval 0 Two operators equeal
- @retval 0 Value1 is greater than Value2
- @retval 0 Value1 is less than Value2
-
-**/
-INTN
-CompareHiiValue (
- IN EFI_HII_VALUE *Value1,
- IN EFI_HII_VALUE *Value2,
- IN EFI_HII_HANDLE HiiHandle OPTIONAL
- )
-{
- INTN Result;
- INT64 Temp64;
- CHAR16 *Str1;
- CHAR16 *Str2;
-
- if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
- if (Value1->Type != Value2->Type) {
- //
- // Both Operator should be type of String
- //
- return EFI_INVALID_PARAMETER;
- }
-
- if (Value1->Value.string == 0 || Value2->Value.string == 0) {
- //
- // StringId 0 is reserved
- //
- return EFI_INVALID_PARAMETER;
- }
-
- if (Value1->Value.string == Value2->Value.string) {
- return 0;
- }
-
- Str1 = GetToken (Value1->Value.string, HiiHandle);
- if (Str1 == NULL) {
- //
- // String not found
- //
- return EFI_INVALID_PARAMETER;
- }
-
- Str2 = GetToken (Value2->Value.string, HiiHandle);
- if (Str2 == NULL) {
- gBS->FreePool (Str1);
- return EFI_INVALID_PARAMETER;
- }
-
- Result = StrCmp (Str1, Str2);
-
- gBS->FreePool (Str1);
- gBS->FreePool (Str2);
-
- return Result;
- }
-
- //
- // Take remain types(integer, boolean, date/time) as integer
- //
- Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
- if (Temp64 > 0) {
- Result = 1;
- } else if (Temp64 < 0) {
- Result = -1;
- } else {
- Result = 0;
- }
-
- return Result;
-}
-
-
-/**
- Evaluate the result of a HII expression
-
- @param FormSet FormSet associated with this expression.
- @param Form Form associated with this expression.
- @param Expression Expression to be evaluated.
-
- @retval EFI_SUCCESS The expression evaluated successfuly
- @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
- could not be found.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
- stack.
- @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
- @retval EFI_INVALID_PARAMETER Syntax error with the Expression
-
-**/
-EFI_STATUS
-EvaluateExpression (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN OUT FORM_EXPRESSION *Expression
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- EXPRESSION_OPCODE *OpCode;
- FORM_BROWSER_STATEMENT *Question;
- FORM_BROWSER_STATEMENT *Question2;
- UINT16 Index;
- EFI_HII_VALUE Data1;
- EFI_HII_VALUE Data2;
- EFI_HII_VALUE Data3;
- FORM_EXPRESSION *RuleExpression;
- EFI_HII_VALUE *Value;
- INTN Result;
- CHAR16 *StrPtr;
- UINT32 TempValue;
-
- //
- // Always reset the stack before evaluating an Expression
- //
- ResetExpressionStack ();
-
- Expression->Result.Type = EFI_IFR_TYPE_OTHER;
-
- Link = GetFirstNode (&Expression->OpCodeListHead);
- while (!IsNull (&Expression->OpCodeListHead, Link)) {
- OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
-
- Link = GetNextNode (&Expression->OpCodeListHead, Link);
-
- ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
- ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
- ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
-
- Value = &Data3;
- Value->Type = EFI_IFR_TYPE_BOOLEAN;
- Status = EFI_SUCCESS;
-
- switch (OpCode->Operand) {
- //
- // Built-in functions
- //
- case EFI_IFR_EQ_ID_VAL_OP:
- Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
- if (Question == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);
- if (Result == EFI_INVALID_PARAMETER) {
- return EFI_INVALID_PARAMETER;
- }
- Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
- break;
-
- case EFI_IFR_EQ_ID_ID_OP:
- Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
- if (Question == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
- if (Question2 == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);
- if (Result == EFI_INVALID_PARAMETER) {
- return EFI_INVALID_PARAMETER;
- }
- Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
- break;
-
- case EFI_IFR_EQ_ID_LIST_OP:
- Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
- if (Question == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Value->Value.b = FALSE;
- for (Index =0; Index < OpCode->ListLength; Index++) {
- if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
- Value->Value.b = TRUE;
- break;
- }
- }
- break;
-
- case EFI_IFR_DUP_OP:
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = PushExpression (Value);
- break;
-
- case EFI_IFR_QUESTION_REF1_OP:
- case EFI_IFR_THIS_OP:
- Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
- if (Question == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Value = &Question->HiiValue;
- break;
-
- case EFI_IFR_QUESTION_REF3_OP:
- if (OpCode->DevicePath == 0) {
- //
- // EFI_IFR_QUESTION_REF3
- // Pop an expression from the expression stack
- //
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Validate the expression value
- //
- if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
- return EFI_NOT_FOUND;
- }
-
- Question = IdToQuestion (FormSet, Form, Value->Value.u16);
- if (Question == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // push the questions' value on to the expression stack
- //
- Value = &Question->HiiValue;
- } else {
- //
- // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
- // since it is impractical to evaluate the value of a Question in another
- // Hii Package list.
- //
- ZeroMem (Value, sizeof (EFI_HII_VALUE));
- }
- break;
-
- case EFI_IFR_RULE_REF_OP:
- //
- // Find expression for this rule
- //
- RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
- if (RuleExpression == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Evaluate this rule expression
- //
- Status = EvaluateExpression (FormSet, Form, RuleExpression);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Value = &RuleExpression->Result;
- break;
-
- case EFI_IFR_STRING_REF1_OP:
- Value->Type = EFI_IFR_TYPE_STRING;
- Value->Value.string = OpCode->Value.Value.string;
- break;
-
- //
- // Constant
- //
- case EFI_IFR_TRUE_OP:
- case EFI_IFR_FALSE_OP:
- case EFI_IFR_ONE_OP:
- case EFI_IFR_ONES_OP:
- case EFI_IFR_UINT8_OP:
- case EFI_IFR_UINT16_OP:
- case EFI_IFR_UINT32_OP:
- case EFI_IFR_UINT64_OP:
- case EFI_IFR_UNDEFINED_OP:
- case EFI_IFR_VERSION_OP:
- case EFI_IFR_ZERO_OP:
- Value = &OpCode->Value;
- break;
-
- //
- // unary-op
- //
- case EFI_IFR_LENGTH_OP:
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value->Type != EFI_IFR_TYPE_STRING) {
- return EFI_INVALID_PARAMETER;
- }
-
- StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
- if (StrPtr == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
- Value->Value.u64 = StrLen (StrPtr);
- gBS->FreePool (StrPtr);
- break;
-
- case EFI_IFR_NOT_OP:
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
- return EFI_INVALID_PARAMETER;
- }
- Value->Value.b = (BOOLEAN) (!Value->Value.b);
- break;
-
- case EFI_IFR_QUESTION_REF2_OP:
- //
- // Pop an expression from the expression stack
- //
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Validate the expression value
- //
- if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
- return EFI_NOT_FOUND;
- }
-
- Question = IdToQuestion (FormSet, Form, Value->Value.u16);
- if (Question == NULL) {
- return EFI_NOT_FOUND;
- }
-
- Value = &Question->HiiValue;
- break;
-
- case EFI_IFR_STRING_REF2_OP:
- //
- // Pop an expression from the expression stack
- //
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Validate the expression value
- //
- if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
- return EFI_NOT_FOUND;
- }
-
- Value->Type = EFI_IFR_TYPE_STRING;
- StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
- if (StrPtr == NULL) {
- //
- // If String not exit, push an empty string
- //
- Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
- } else {
- Index = (UINT16) Value->Value.u64;
- Value->Value.string = Index;
- gBS->FreePool (StrPtr);
- }
- break;
-
- case EFI_IFR_TO_BOOLEAN_OP:
- //
- // Pop an expression from the expression stack
- //
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Convert an expression to a Boolean
- //
- if (Value->Type <= EFI_IFR_TYPE_DATE) {
- //
- // When converting from an unsigned integer, zero will be converted to
- // FALSE and any other value will be converted to TRUE.
- //
- Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);
-
- Value->Type = EFI_IFR_TYPE_BOOLEAN;
- } else if (Value->Type == EFI_IFR_TYPE_STRING) {
- //
- // When converting from a string, if case-insensitive compare
- // with "true" is True, then push True. If a case-insensitive compare
- // with "false" is True, then push False.
- //
- StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
- if (StrPtr == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){
- Value->Value.b = TRUE;
- } else {
- Value->Value.b = FALSE;
- }
- gBS->FreePool (StrPtr);
- Value->Type = EFI_IFR_TYPE_BOOLEAN;
- }
- break;
-
- case EFI_IFR_TO_STRING_OP:
- Status = IfrToString (FormSet, OpCode->Format, Value);
- break;
-
- case EFI_IFR_TO_UINT_OP:
- Status = IfrToUint (FormSet, Value);
- break;
-
- case EFI_IFR_TO_LOWER_OP:
- case EFI_IFR_TO_UPPER_OP:
- Status = InitializeUnicodeCollationProtocol ();
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (Value->Type != EFI_IFR_TYPE_STRING) {
- return EFI_UNSUPPORTED;
- }
-
- StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
- if (StrPtr == NULL) {
- return EFI_NOT_FOUND;
- }
-
- if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
- mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
- } else {
- mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
- }
- Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
- gBS->FreePool (StrPtr);
- break;
-
- case EFI_IFR_BITWISE_NOT_OP:
- //
- // Pop an expression from the expression stack
- //
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Value->Type > EFI_IFR_TYPE_DATE) {
- return EFI_INVALID_PARAMETER;
- }
-
- Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
- Value->Value.u64 = ~Value->Value.u64;
- break;
-
- //
- // binary-op
- //
- case EFI_IFR_ADD_OP:
- case EFI_IFR_SUBTRACT_OP:
- case EFI_IFR_MULTIPLY_OP:
- case EFI_IFR_DIVIDE_OP:
- case EFI_IFR_MODULO_OP:
- case EFI_IFR_BITWISE_AND_OP:
- case EFI_IFR_BITWISE_OR_OP:
- case EFI_IFR_SHIFT_LEFT_OP:
- case EFI_IFR_SHIFT_RIGHT_OP:
- //
- // Pop an expression from the expression stack
- //
- Status = PopExpression (&Data2);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Data2.Type > EFI_IFR_TYPE_DATE) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Pop another expression from the expression stack
- //
- Status = PopExpression (&Data1);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Data1.Type > EFI_IFR_TYPE_DATE) {
- return EFI_INVALID_PARAMETER;
- }
-
- Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
-
- switch (OpCode->Operand) {
- case EFI_IFR_ADD_OP:
- Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
- break;
-
- case EFI_IFR_SUBTRACT_OP:
- Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
- break;
-
- case EFI_IFR_MULTIPLY_OP:
- Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
- break;
-
- case EFI_IFR_DIVIDE_OP:
- Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
- break;
-
- case EFI_IFR_MODULO_OP:
- DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
- Value->Value.u64 = TempValue;
- break;
-
- case EFI_IFR_BITWISE_AND_OP:
- Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
- break;
-
- case EFI_IFR_BITWISE_OR_OP:
- Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
- break;
-
- case EFI_IFR_SHIFT_LEFT_OP:
- Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
- break;
-
- case EFI_IFR_SHIFT_RIGHT_OP:
- Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
- break;
-
- default:
- break;
- }
- break;
-
- case EFI_IFR_AND_OP:
- case EFI_IFR_OR_OP:
- //
- // Two Boolean operator
- //
- Status = PopExpression (&Data2);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Pop another expression from the expression stack
- //
- Status = PopExpression (&Data1);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (OpCode->Operand == EFI_IFR_AND_OP) {
- Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
- } else {
- Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
- }
- break;
-
- case EFI_IFR_EQUAL_OP:
- case EFI_IFR_NOT_EQUAL_OP:
- case EFI_IFR_GREATER_EQUAL_OP:
- case EFI_IFR_GREATER_THAN_OP:
- case EFI_IFR_LESS_EQUAL_OP:
- case EFI_IFR_LESS_THAN_OP:
- //
- // Compare two integer, string, boolean or date/time
- //
- Status = PopExpression (&Data2);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Pop another expression from the expression stack
- //
- Status = PopExpression (&Data1);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);
- if (Result == EFI_INVALID_PARAMETER) {
- return EFI_INVALID_PARAMETER;
- }
-
- switch (OpCode->Operand) {
- case EFI_IFR_EQUAL_OP:
- Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
- break;
-
- case EFI_IFR_NOT_EQUAL_OP:
- Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
- break;
-
- case EFI_IFR_GREATER_EQUAL_OP:
- Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
- break;
-
- case EFI_IFR_GREATER_THAN_OP:
- Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
- break;
-
- case EFI_IFR_LESS_EQUAL_OP:
- Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
- break;
-
- case EFI_IFR_LESS_THAN_OP:
- Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
- break;
-
- default:
- break;
- }
- break;
-
- case EFI_IFR_MATCH_OP:
- Status = IfrMatch (FormSet, Value);
- break;
-
- case EFI_IFR_CATENATE_OP:
- Status = IfrCatenate (FormSet, Value);
- break;
-
- //
- // ternary-op
- //
- case EFI_IFR_CONDITIONAL_OP:
- //
- // Pop third expression from the expression stack
- //
- Status = PopExpression (&Data3);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Pop second expression from the expression stack
- //
- Status = PopExpression (&Data2);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Pop first expression from the expression stack
- //
- Status = PopExpression (&Data1);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (Data1.Value.b) {
- Value = &Data3;
- } else {
- Value = &Data2;
- }
- break;
-
- case EFI_IFR_FIND_OP:
- Status = IfrFind (FormSet, OpCode->Format, Value);
- break;
-
- case EFI_IFR_MID_OP:
- Status = IfrMid (FormSet, Value);
- break;
-
- case EFI_IFR_TOKEN_OP:
- Status = IfrToken (FormSet, Value);
- break;
-
- case EFI_IFR_SPAN_OP:
- Status = IfrSpan (FormSet, OpCode->Flags, Value);
- break;
-
- default:
- break;
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = PushExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- //
- // Pop the final result from expression stack
- //
- Value = &Data1;
- Status = PopExpression (Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // After evaluating an expression, there should be only one value left on the expression stack
- //
- if (PopExpression (Value) != EFI_ACCESS_DENIED) {
- return EFI_INVALID_PARAMETER;
- }
-
- CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
-
- return EFI_SUCCESS;
-}
+/** @file
+Utility functions for expression evaluation.
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ui.h"
+#include "Setup.h"
+
+//
+// Global stack used to evaluate boolean expresions
+//
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
+
+EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
+
+//
+// Unicode collation protocol interface
+//
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
+
+
+/**
+ Grow size of the stack.
+
+ This is an internal function.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+
+ @retval EFI_SUCCESS Grow stack success.
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
+
+**/
+EFI_STATUS
+GrowStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd
+ )
+{
+ UINTN Size;
+ EFI_HII_VALUE *NewStack;
+
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;
+ if (*StackPtr != NULL) {
+ Size = Size + (*StackEnd - *Stack);
+ }
+
+ NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (*StackPtr != NULL) {
+ //
+ // Copy from Old Stack to the New Stack
+ //
+ CopyMem (
+ NewStack,
+ *Stack,
+ (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
+ );
+
+ //
+ // Free The Old Stack
+ //
+ gBS->FreePool (*Stack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ *StackPtr = NewStack + (*StackPtr - *Stack);
+ *Stack = NewStack;
+ *StackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Push an element onto the Boolean Stack.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+ @param Data Data to push.
+
+ @retval EFI_SUCCESS Push stack success.
+
+**/
+EFI_STATUS
+PushStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd,
+ IN EFI_HII_VALUE *Data
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (*StackPtr >= *StackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowStack (Stack, StackPtr, StackEnd);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
+ *StackPtr = *StackPtr + 1;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Pop an element from the stack.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackEnd On input: old stack end; On output: new stack end
+ @param Data Data to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd,
+ OUT EFI_HII_VALUE *Data
+ )
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (*StackPtr == *Stack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ *StackPtr = *StackPtr - 1;
+ CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetScopeStack (
+ VOID
+ )
+{
+ mOpCodeScopeStackPointer = mOpCodeScopeStack;
+}
+
+
+/**
+ Push an Operand onto the Stack
+
+ @param Operand Operand to push.
+
+ @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
+PushScope (
+ IN UINT8 Operand
+ )
+{
+ EFI_HII_VALUE Data;
+
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Data.Value.u8 = Operand;
+
+ return PushStack (
+ &mOpCodeScopeStack,
+ &mOpCodeScopeStackPointer,
+ &mOpCodeScopeStackEnd,
+ &Data
+ );
+}
+
+
+/**
+ Pop an Operand from the Stack
+
+ @param Operand Operand to 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
+PopScope (
+ OUT UINT8 *Operand
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Data;
+
+ Status = PopStack (
+ &mOpCodeScopeStack,
+ &mOpCodeScopeStackPointer,
+ &mOpCodeScopeStackEnd,
+ &Data
+ );
+
+ *Operand = Data.Value.u8;
+
+ return Status;
+}
+
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetExpressionStack (
+ VOID
+ )
+{
+ mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
+}
+
+
+/**
+ Push an Expression value onto the Stack
+
+ @param Value Expression value to push.
+
+ @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
+PushExpression (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ return PushStack (
+ &mExpressionEvaluationStack,
+ &mExpressionEvaluationStackPointer,
+ &mExpressionEvaluationStackEnd,
+ Value
+ );
+}
+
+
+/**
+ Pop an Expression value from the stack.
+
+ @param Value Expression value to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopExpression (
+ OUT EFI_HII_VALUE *Value
+ )
+{
+ return PopStack (
+ &mExpressionEvaluationStack,
+ &mExpressionEvaluationStackPointer,
+ &mExpressionEvaluationStackEnd,
+ Value
+ );
+}
+
+
+/**
+ Get Form given its FormId.
+
+ @param FormSet The formset which contains this form.
+ @param FormId Id of this form.
+
+ @retval Pointer The form.
+ @retval NULL Specified Form is not found in the formset.
+
+**/
+FORM_BROWSER_FORM *
+IdToForm (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN UINT16 FormId
+)
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_FORM *Form;
+
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+ if (Form->FormId == FormId) {
+ return Form;
+ }
+
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Search a Question in Form scope using its QuestionId.
+
+ @param Form The form which contains this Question.
+ @param QuestionId Id of this Question.
+
+ @retval Pointer The Question.
+ @retval NULL Specified Question not found in the form.
+
+**/
+FORM_BROWSER_STATEMENT *
+IdToQuestion2 (
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT16 QuestionId
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ if (QuestionId == 0) {
+ //
+ // The value of zero is reserved
+ //
+ return NULL;
+ }
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ if (Question->QuestionId == QuestionId) {
+ return Question;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Search a Question in Formset scope using its QuestionId.
+
+ @param FormSet The formset which contains this form.
+ @param Form The form which contains this Question.
+ @param QuestionId Id of this Question.
+
+ @retval Pointer The Question.
+ @retval NULL Specified Question not found in the form.
+
+**/
+FORM_BROWSER_STATEMENT *
+IdToQuestion (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT16 QuestionId
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ //
+ // Search in the form scope first
+ //
+ Question = IdToQuestion2 (Form, QuestionId);
+ if (Question != NULL) {
+ return Question;
+ }
+
+ //
+ // Search in the formset scope
+ //
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+ Question = IdToQuestion2 (Form, QuestionId);
+ if (Question != NULL) {
+ return Question;
+ }
+
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Get Expression given its RuleId.
+
+ @param Form The form which contains this Expression.
+ @param RuleId Id of this Expression.
+
+ @retval Pointer The Expression.
+ @retval NULL Specified Expression not found in the form.
+
+**/
+FORM_EXPRESSION *
+RuleIdToExpression (
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT8 RuleId
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_EXPRESSION *Expression;
+
+ Link = GetFirstNode (&Form->ExpressionListHead);
+ while (!IsNull (&Form->ExpressionListHead, Link)) {
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+
+ if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {
+ return Expression;
+ }
+
+ Link = GetNextNode (&Form->ExpressionListHead, Link);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Locate the Unicode Collation Protocol interface for later use.
+
+ @retval EFI_SUCCESS Protocol interface initialize success.
+ @retval Other Protocol interface initialize failed.
+
+**/
+EFI_STATUS
+InitializeUnicodeCollationProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (mUnicodeCollation != NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
+ // instances first and then select one which support English language.
+ // Current implementation just pick the first instance.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiUnicodeCollation2ProtocolGuid,
+ NULL,
+ (VOID **) &mUnicodeCollation
+ );
+ return Status;
+}
+
+/**
+ Convert the input Unicode character to upper.
+
+ @param String Th Unicode character to be converted.
+
+**/
+VOID
+IfrStrToUpper (
+ CHAR16 *String
+ )
+{
+ while (*String != 0) {
+ if ((*String >= 'a') && (*String <= 'z')) {
+ *String = (UINT16) ((*String) & ((UINT16) ~0x20));
+ }
+ String++;
+ }
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_TO_STRING.
+
+ @param FormSet Formset which contains this opcode.
+ @param Format String format in EFI_IFR_TO_STRING.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToString (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN UINT8 Format,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String;
+ CHAR16 *PrintFormat;
+ CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];
+ UINTN BufferSize;
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (Value.Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
+ switch (Format) {
+ case EFI_IFR_STRING_UNSIGNED_DEC:
+ case EFI_IFR_STRING_SIGNED_DEC:
+ PrintFormat = L"%ld";
+ break;
+
+ case EFI_IFR_STRING_LOWERCASE_HEX:
+ PrintFormat = L"%lx";
+ break;
+
+ case EFI_IFR_STRING_UPPERCASE_HEX:
+ PrintFormat = L"%lX";
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
+ String = Buffer;
+ break;
+
+ case EFI_IFR_TYPE_STRING:
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
+ return EFI_SUCCESS;
+
+ case EFI_IFR_TYPE_BOOLEAN:
+ String = (Value.Value.b) ? L"True" : L"False";
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewString (String, FormSet->HiiHandle);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_TO_UINT.
+
+ @param FormSet Formset which contains this opcode.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToUint (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String;
+ CHAR16 *StringPtr;
+ UINTN BufferSize;
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Value.Type >= EFI_IFR_TYPE_OTHER) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EFI_SUCCESS;
+ if (Value.Type == EFI_IFR_TYPE_STRING) {
+ String = GetToken (Value.Value.string, FormSet->HiiHandle);
+ if (String == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ IfrStrToUpper (String);
+ StringPtr = StrStr (String, L"0X");
+ if (StringPtr != NULL) {
+ //
+ // Hex string
+ //
+ BufferSize = sizeof (UINT64);
+ Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);
+ } else {
+ //
+ // BUGBUG: Need handle decimal string
+ //
+ }
+ gBS->FreePool (String);
+ } else {
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
+ }
+
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ return Status;
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_CATENATE.
+
+ @param FormSet Formset which contains this opcode.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrCatenate (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String[2];
+ UINTN Index;
+ CHAR16 *StringPtr;
+ UINTN Size;
+
+ //
+ // String[0] - The second string
+ // String[1] - The first string
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ StringPtr = NULL;
+ Status = EFI_SUCCESS;
+
+ for (Index = 0; Index < 2; Index++) {
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value.Type != EFI_IFR_TYPE_STRING) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+ if (String== NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ Size = StrSize (String[0]);
+ StringPtr= AllocatePool (StrSize (String[1]) + Size);
+ ASSERT (StringPtr != NULL);
+ StrCpy (StringPtr, String[1]);
+ StrCat (StringPtr, String[0]);
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
+
+Done:
+ SafeFreePool (String[0]);
+ SafeFreePool (String[1]);
+ SafeFreePool (StringPtr);
+
+ return Status;
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_MATCH.
+
+ @param FormSet Formset which contains this opcode.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrMatch (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String[2];
+ UINTN Index;
+
+ //
+ // String[0] - The string to search
+ // String[1] - pattern
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ Status = EFI_SUCCESS;
+ for (Index = 0; Index < 2; Index++) {
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value.Type != EFI_IFR_TYPE_STRING) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+ if (String== NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_BOOLEAN;
+ Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
+
+Done:
+ SafeFreePool (String[0]);
+ SafeFreePool (String[1]);
+
+ return Status;
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_FIND.
+
+ @param FormSet Formset which contains this opcode.
+ @param Format Case sensitive or insensitive.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrFind (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN UINT8 Format,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String[2];
+ UINTN Base;
+ CHAR16 *StringPtr;
+ UINTN Index;
+
+ if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ return EFI_UNSUPPORTED;
+ }
+ Base = (UINTN) Value.Value.u64;
+
+ //
+ // String[0] - sub-string
+ // String[1] - The string to search
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ for (Index = 0; Index < 2; Index++) {
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value.Type != EFI_IFR_TYPE_STRING) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+ if (String== NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
+ //
+ // Case insensitive, convert both string to upper case
+ //
+ IfrStrToUpper (String[Index]);
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ if (Base >= StrLen (String[1])) {
+ Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
+ } else {
+ StringPtr = StrStr (String[1] + Base, String[0]);
+ Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
+ }
+
+Done:
+ SafeFreePool (String[0]);
+ SafeFreePool (String[1]);
+
+ return Status;
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_MID.
+
+ @param FormSet Formset which contains this opcode.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrMid (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String;
+ UINTN Base;
+ UINTN Length;
+ CHAR16 *SubString;
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ return EFI_UNSUPPORTED;
+ }
+ Length = (UINTN) Value.Value.u64;
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ return EFI_UNSUPPORTED;
+ }
+ Base = (UINTN) Value.Value.u64;
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value.Type != EFI_IFR_TYPE_STRING) {
+ return EFI_UNSUPPORTED;
+ }
+ String = GetToken (Value.Value.string, FormSet->HiiHandle);
+ if (String == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (Length == 0 || Base >= StrLen (String)) {
+ SubString = gEmptyString;
+ } else {
+ SubString = String + Base;
+ if ((Base + Length) < StrLen (String)) {
+ SubString[Length] = L'\0';
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewString (SubString, FormSet->HiiHandle);
+
+ gBS->FreePool (String);
+
+ return Status;
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_TOKEN.
+
+ @param FormSet Formset which contains this opcode.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrToken (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String[2];
+ UINTN Count;
+ CHAR16 *Delimiter;
+ CHAR16 *SubString;
+ CHAR16 *StringPtr;
+ UINTN Index;
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ return EFI_UNSUPPORTED;
+ }
+ Count = (UINTN) Value.Value.u64;
+
+ //
+ // String[0] - Delimiter
+ // String[1] - The string to search
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ for (Index = 0; Index < 2; Index++) {
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value.Type != EFI_IFR_TYPE_STRING) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+ if (String== NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ Delimiter = String[0];
+ SubString = String[1];
+ while (Count > 0) {
+ SubString = StrStr (SubString, Delimiter);
+ if (SubString != NULL) {
+ //
+ // Skip over the delimiter
+ //
+ SubString = SubString + StrLen (Delimiter);
+ } else {
+ break;
+ }
+ Count--;
+ }
+
+ if (SubString == NULL) {
+ //
+ // nth delimited sub-string not found, push an empty string
+ //
+ SubString = gEmptyString;
+ } else {
+ //
+ // Put a NULL terminator for nth delimited sub-string
+ //
+ StringPtr = StrStr (SubString, Delimiter);
+ if (StringPtr != NULL) {
+ *StringPtr = L'\0';
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_STRING;
+ Result->Value.string = NewString (SubString, FormSet->HiiHandle);
+
+Done:
+ SafeFreePool (String[0]);
+ SafeFreePool (String[1]);
+
+ return Status;
+}
+
+
+/**
+ Evaluate opcode EFI_IFR_SPAN.
+
+ @param FormSet Formset which contains this opcode.
+ @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
+ @param Result Evaluation result for this opcode.
+
+ @retval EFI_SUCCESS Opcode evaluation success.
+ @retval Other Opcode evaluation failed.
+
+**/
+EFI_STATUS
+IfrSpan (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN UINT8 Flags,
+ OUT EFI_HII_VALUE *Result
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Value;
+ CHAR16 *String[2];
+ CHAR16 *Charset;
+ UINTN Base;
+ UINTN Index;
+ CHAR16 *StringPtr;
+ BOOLEAN Found;
+
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
+ return EFI_UNSUPPORTED;
+ }
+ Base = (UINTN) Value.Value.u64;
+
+ //
+ // String[0] - Charset
+ // String[1] - The string to search
+ //
+ String[0] = NULL;
+ String[1] = NULL;
+ for (Index = 0; Index < 2; Index++) {
+ Status = PopExpression (&Value);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Value.Type != EFI_IFR_TYPE_STRING) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
+ if (String== NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+ if (Base >= StrLen (String[1])) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Found = FALSE;
+ StringPtr = String[1] + Base;
+ Charset = String[0];
+ while (*StringPtr != 0 && !Found) {
+ Index = 0;
+ while (Charset[Index] != 0) {
+ if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {
+ if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
+ Found = TRUE;
+ break;
+ }
+ } else {
+ if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
+ Found = TRUE;
+ break;
+ }
+ }
+ //
+ // Skip characters pair representing low-end of a range and high-end of a range
+ //
+ Index += 2;
+ }
+
+ if (!Found) {
+ StringPtr++;
+ }
+ }
+
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Result->Value.u64 = StringPtr - String[1];
+
+Done:
+ SafeFreePool (String[0]);
+ SafeFreePool (String[1]);
+
+ return Status;
+}
+
+
+/**
+ Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+ @param Value HII Value to be converted.
+
+**/
+VOID
+ExtendValueToU64 (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ UINT64 Temp;
+
+ Temp = 0;
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ Temp = Value->Value.u8;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ Temp = Value->Value.u16;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ Temp = Value->Value.u32;
+ break;
+
+ case EFI_IFR_TYPE_BOOLEAN:
+ Temp = Value->Value.b;
+ break;
+
+ case EFI_IFR_TYPE_TIME:
+ Temp = Value->Value.u32 & 0xffffff;
+ break;
+
+ case EFI_IFR_TYPE_DATE:
+ Temp = Value->Value.u32;
+ break;
+
+ default:
+ return;
+ }
+
+ Value->Value.u64 = Temp;
+}
+
+
+/**
+ Compare two Hii value.
+
+ @param Value1 Expression value to compare on left-hand.
+ @param Value2 Expression value to compare on right-hand.
+ @param HiiHandle Only required for string compare.
+
+ @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.
+ @retval 0 Two operators equeal.
+ @return Positive value if Value1 is greater than Value2.
+ @retval Negative value if Value1 is less than Value2.
+
+**/
+INTN
+CompareHiiValue (
+ IN EFI_HII_VALUE *Value1,
+ IN EFI_HII_VALUE *Value2,
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL
+ )
+{
+ INTN Result;
+ INT64 Temp64;
+ CHAR16 *Str1;
+ CHAR16 *Str2;
+
+ if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
+ if (Value1->Type != Value2->Type) {
+ //
+ // Both Operator should be type of String
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Value1->Value.string == 0 || Value2->Value.string == 0) {
+ //
+ // StringId 0 is reserved
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Value1->Value.string == Value2->Value.string) {
+ return 0;
+ }
+
+ Str1 = GetToken (Value1->Value.string, HiiHandle);
+ if (Str1 == NULL) {
+ //
+ // String not found
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Str2 = GetToken (Value2->Value.string, HiiHandle);
+ if (Str2 == NULL) {
+ gBS->FreePool (Str1);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Result = StrCmp (Str1, Str2);
+
+ gBS->FreePool (Str1);
+ gBS->FreePool (Str2);
+
+ return Result;
+ }
+
+ //
+ // Take remain types(integer, boolean, date/time) as integer
+ //
+ Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
+ if (Temp64 > 0) {
+ Result = 1;
+ } else if (Temp64 < 0) {
+ Result = -1;
+ } else {
+ Result = 0;
+ }
+
+ return Result;
+}
+
+
+/**
+ Evaluate the result of a HII expression
+
+ @param FormSet FormSet associated with this expression.
+ @param Form Form associated with this expression.
+ @param Expression Expression to be evaluated.
+
+ @retval EFI_SUCCESS The expression evaluated successfuly
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
+ could not be found.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression
+
+**/
+EFI_STATUS
+EvaluateExpression (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_EXPRESSION *Expression
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ EXPRESSION_OPCODE *OpCode;
+ FORM_BROWSER_STATEMENT *Question;
+ FORM_BROWSER_STATEMENT *Question2;
+ UINT16 Index;
+ EFI_HII_VALUE Data1;
+ EFI_HII_VALUE Data2;
+ EFI_HII_VALUE Data3;
+ FORM_EXPRESSION *RuleExpression;
+ EFI_HII_VALUE *Value;
+ INTN Result;
+ CHAR16 *StrPtr;
+ UINT32 TempValue;
+
+ //
+ // Always reset the stack before evaluating an Expression
+ //
+ ResetExpressionStack ();
+
+ Expression->Result.Type = EFI_IFR_TYPE_OTHER;
+
+ Link = GetFirstNode (&Expression->OpCodeListHead);
+ while (!IsNull (&Expression->OpCodeListHead, Link)) {
+ OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
+
+ Link = GetNextNode (&Expression->OpCodeListHead, Link);
+
+ ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
+ ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
+ ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
+
+ Value = &Data3;
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ Status = EFI_SUCCESS;
+
+ switch (OpCode->Operand) {
+ //
+ // Built-in functions
+ //
+ case EFI_IFR_EQ_ID_VAL_OP:
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+ if (Question == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);
+ if (Result == EFI_INVALID_PARAMETER) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+ if (Question == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
+ if (Question2 == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);
+ if (Result == EFI_INVALID_PARAMETER) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+ if (Question == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Value->Value.b = FALSE;
+ for (Index =0; Index < OpCode->ListLength; Index++) {
+ if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
+ Value->Value.b = TRUE;
+ break;
+ }
+ }
+ break;
+
+ case EFI_IFR_DUP_OP:
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PushExpression (Value);
+ break;
+
+ case EFI_IFR_QUESTION_REF1_OP:
+ case EFI_IFR_THIS_OP:
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
+ if (Question == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Value = &Question->HiiValue;
+ break;
+
+ case EFI_IFR_QUESTION_REF3_OP:
+ if (OpCode->DevicePath == 0) {
+ //
+ // EFI_IFR_QUESTION_REF3
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Validate the expression value
+ //
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Question = IdToQuestion (FormSet, Form, Value->Value.u16);
+ if (Question == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // push the questions' value on to the expression stack
+ //
+ Value = &Question->HiiValue;
+ } else {
+ //
+ // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
+ // since it is impractical to evaluate the value of a Question in another
+ // Hii Package list.
+ //
+ ZeroMem (Value, sizeof (EFI_HII_VALUE));
+ }
+ break;
+
+ case EFI_IFR_RULE_REF_OP:
+ //
+ // Find expression for this rule
+ //
+ RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
+ if (RuleExpression == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Evaluate this rule expression
+ //
+ Status = EvaluateExpression (FormSet, Form, RuleExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Value = &RuleExpression->Result;
+ break;
+
+ case EFI_IFR_STRING_REF1_OP:
+ Value->Type = EFI_IFR_TYPE_STRING;
+ Value->Value.string = OpCode->Value.Value.string;
+ break;
+
+ //
+ // Constant
+ //
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_FALSE_OP:
+ case EFI_IFR_ONE_OP:
+ case EFI_IFR_ONES_OP:
+ case EFI_IFR_UINT8_OP:
+ case EFI_IFR_UINT16_OP:
+ case EFI_IFR_UINT32_OP:
+ case EFI_IFR_UINT64_OP:
+ case EFI_IFR_UNDEFINED_OP:
+ case EFI_IFR_VERSION_OP:
+ case EFI_IFR_ZERO_OP:
+ Value = &OpCode->Value;
+ break;
+
+ //
+ // unary-op
+ //
+ case EFI_IFR_LENGTH_OP:
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value->Type != EFI_IFR_TYPE_STRING) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Value->Value.u64 = StrLen (StrPtr);
+ gBS->FreePool (StrPtr);
+ break;
+
+ case EFI_IFR_NOT_OP:
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Value->Value.b = (BOOLEAN) (!Value->Value.b);
+ break;
+
+ case EFI_IFR_QUESTION_REF2_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Validate the expression value
+ //
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Question = IdToQuestion (FormSet, Form, Value->Value.u16);
+ if (Question == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Value = &Question->HiiValue;
+ break;
+
+ case EFI_IFR_STRING_REF2_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Validate the expression value
+ //
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Value->Type = EFI_IFR_TYPE_STRING;
+ StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ //
+ // If String not exit, push an empty string
+ //
+ Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
+ } else {
+ Index = (UINT16) Value->Value.u64;
+ Value->Value.string = Index;
+ gBS->FreePool (StrPtr);
+ }
+ break;
+
+ case EFI_IFR_TO_BOOLEAN_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert an expression to a Boolean
+ //
+ if (Value->Type <= EFI_IFR_TYPE_DATE) {
+ //
+ // When converting from an unsigned integer, zero will be converted to
+ // FALSE and any other value will be converted to TRUE.
+ //
+ Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);
+
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ } else if (Value->Type == EFI_IFR_TYPE_STRING) {
+ //
+ // When converting from a string, if case-insensitive compare
+ // with "true" is True, then push True. If a case-insensitive compare
+ // with "false" is True, then push False.
+ //
+ StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){
+ Value->Value.b = TRUE;
+ } else {
+ Value->Value.b = FALSE;
+ }
+ gBS->FreePool (StrPtr);
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;
+ }
+ break;
+
+ case EFI_IFR_TO_STRING_OP:
+ Status = IfrToString (FormSet, OpCode->Format, Value);
+ break;
+
+ case EFI_IFR_TO_UINT_OP:
+ Status = IfrToUint (FormSet, Value);
+ break;
+
+ case EFI_IFR_TO_LOWER_OP:
+ case EFI_IFR_TO_UPPER_OP:
+ Status = InitializeUnicodeCollationProtocol ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Value->Type != EFI_IFR_TYPE_STRING) {
+ return EFI_UNSUPPORTED;
+ }
+
+ StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
+ if (StrPtr == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
+ mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
+ } else {
+ mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
+ }
+ Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
+ gBS->FreePool (StrPtr);
+ break;
+
+ case EFI_IFR_BITWISE_NOT_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Value->Type > EFI_IFR_TYPE_DATE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ Value->Value.u64 = ~Value->Value.u64;
+ break;
+
+ //
+ // binary-op
+ //
+ case EFI_IFR_ADD_OP:
+ case EFI_IFR_SUBTRACT_OP:
+ case EFI_IFR_MULTIPLY_OP:
+ case EFI_IFR_DIVIDE_OP:
+ case EFI_IFR_MODULO_OP:
+ case EFI_IFR_BITWISE_AND_OP:
+ case EFI_IFR_BITWISE_OR_OP:
+ case EFI_IFR_SHIFT_LEFT_OP:
+ case EFI_IFR_SHIFT_RIGHT_OP:
+ //
+ // Pop an expression from the expression stack
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Data2.Type > EFI_IFR_TYPE_DATE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Pop another expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Data1.Type > EFI_IFR_TYPE_DATE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+
+ switch (OpCode->Operand) {
+ case EFI_IFR_ADD_OP:
+ Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
+ break;
+
+ case EFI_IFR_SUBTRACT_OP:
+ Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
+ break;
+
+ case EFI_IFR_MULTIPLY_OP:
+ Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
+ break;
+
+ case EFI_IFR_DIVIDE_OP:
+ Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
+ break;
+
+ case EFI_IFR_MODULO_OP:
+ DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
+ Value->Value.u64 = TempValue;
+ break;
+
+ case EFI_IFR_BITWISE_AND_OP:
+ Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
+ break;
+
+ case EFI_IFR_BITWISE_OR_OP:
+ Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
+ break;
+
+ case EFI_IFR_SHIFT_LEFT_OP:
+ Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
+ break;
+
+ case EFI_IFR_SHIFT_RIGHT_OP:
+ Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ //
+ // Two Boolean operator
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Pop another expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (OpCode->Operand == EFI_IFR_AND_OP) {
+ Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
+ } else {
+ Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
+ }
+ break;
+
+ case EFI_IFR_EQUAL_OP:
+ case EFI_IFR_NOT_EQUAL_OP:
+ case EFI_IFR_GREATER_EQUAL_OP:
+ case EFI_IFR_GREATER_THAN_OP:
+ case EFI_IFR_LESS_EQUAL_OP:
+ case EFI_IFR_LESS_THAN_OP:
+ //
+ // Compare two integer, string, boolean or date/time
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Pop another expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);
+ if (Result == EFI_INVALID_PARAMETER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (OpCode->Operand) {
+ case EFI_IFR_EQUAL_OP:
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_NOT_EQUAL_OP:
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_GREATER_EQUAL_OP:
+ Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_GREATER_THAN_OP:
+ Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_LESS_EQUAL_OP:
+ Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
+ break;
+
+ case EFI_IFR_LESS_THAN_OP:
+ Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case EFI_IFR_MATCH_OP:
+ Status = IfrMatch (FormSet, Value);
+ break;
+
+ case EFI_IFR_CATENATE_OP:
+ Status = IfrCatenate (FormSet, Value);
+ break;
+
+ //
+ // ternary-op
+ //
+ case EFI_IFR_CONDITIONAL_OP:
+ //
+ // Pop third expression from the expression stack
+ //
+ Status = PopExpression (&Data3);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Pop second expression from the expression stack
+ //
+ Status = PopExpression (&Data2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Pop first expression from the expression stack
+ //
+ Status = PopExpression (&Data1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Data1.Value.b) {
+ Value = &Data3;
+ } else {
+ Value = &Data2;
+ }
+ break;
+
+ case EFI_IFR_FIND_OP:
+ Status = IfrFind (FormSet, OpCode->Format, Value);
+ break;
+
+ case EFI_IFR_MID_OP:
+ Status = IfrMid (FormSet, Value);
+ break;
+
+ case EFI_IFR_TOKEN_OP:
+ Status = IfrToken (FormSet, Value);
+ break;
+
+ case EFI_IFR_SPAN_OP:
+ Status = IfrSpan (FormSet, OpCode->Flags, Value);
+ break;
+
+ default:
+ break;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PushExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Pop the final result from expression stack
+ //
+ Value = &Data1;
+ Status = PopExpression (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // After evaluating an expression, there should be only one value left on the expression stack
+ //
+ if (PopExpression (Value) != EFI_ACCESS_DENIED) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
index 9108acb..7e5f668 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
@@ -1,4 +1,6 @@
/** @file
+Parser for IFR binary encoding.
+
Copyright (c) 2007 - 2008, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -8,15 +10,6 @@ http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-Module Name:
-
- IfrParse.c
-
-Abstract:
-
- Parser for IFR binary encoding.
-
-
**/
#include "Setup.h"
@@ -337,7 +330,7 @@ InitializeRequestElement (
StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
}
- if ((Question->Operand == EFI_IFR_PASSWORD_OP) && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)) {
+ if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
//
// Password with CALLBACK flag is stored in encoded format,
// so don't need to append it to <ConfigRequest>
@@ -371,12 +364,10 @@ InitializeRequestElement (
/**
- Free resources of a Expression
+ Free resources of a Expression.
@param FormSet Pointer of the Expression
- @return None.
-
**/
VOID
DestroyExpression (
@@ -402,12 +393,10 @@ DestroyExpression (
/**
- Free resources of a storage
+ Free resources of a storage.
@param Storage Pointer of the storage
- @return None.
-
**/
VOID
DestroyStorage (
@@ -444,12 +433,10 @@ DestroyStorage (
/**
- Free resources of a Statement
+ Free resources of a Statement.
@param Statement Pointer of the Statement
- @return None.
-
**/
VOID
DestroyStatement (
@@ -511,11 +498,9 @@ DestroyStatement (
/**
- Free resources of a Form
+ Free resources of a Form.
- @param Form Pointer of the Form
-
- @return None.
+ @param Form Pointer of the Form.
**/
VOID
@@ -557,12 +542,10 @@ DestroyForm (
/**
- Free resources allocated for a FormSet
+ Free resources allocated for a FormSet.
@param FormSet Pointer of the FormSet
- @return None.
-
**/
VOID
DestroyFormSet (
@@ -657,8 +640,6 @@ IsExpressionOpCode (
@param NumberOfStatement Number of Statemens(Questions)
@param NumberOfExpression Number of Expression OpCodes
- @return None.
-
**/
VOID
CountOpCodes (
@@ -791,7 +772,7 @@ ParseOpCodes (
//
// If scope bit set, push onto scope stack
//
- if (Scope) {
+ if (Scope != 0) {
PushScope (Operand);
}
@@ -1091,7 +1072,7 @@ ParseOpCodes (
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
- if (Scope) {
+ if (Scope != 0) {
mInScopeSubtitle = TRUE;
}
break;
@@ -1187,7 +1168,7 @@ ParseOpCodes (
InitializeRequestElement (FormSet, CurrentStatement);
- if ((Operand == EFI_IFR_ONE_OF_OP) && Scope) {
+ if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
SuppressForOption = TRUE;
}
break;
@@ -1208,7 +1189,7 @@ ParseOpCodes (
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;
CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
- if (Scope) {
+ if (Scope != 0) {
SuppressForOption = TRUE;
}
break;
@@ -1320,7 +1301,7 @@ ParseOpCodes (
//
InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
- if (Scope) {
+ if (Scope != 0) {
InScopeDefault = TRUE;
}
break;
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
index cc580b8..b958f4f 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
@@ -1,1146 +1,1144 @@
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- InputHandler.c
-
-Abstract:
-
- Implementation for handling user input from the User Interface
-
-Revision History
-
-
-**/
-
-#include "Ui.h"
-#include "Setup.h"
-
-
-/**
- Get string or password input from user.
-
- @param MenuOption Pointer to the current input menu.
- @param Prompt The prompt string shown on popup window.
- @param StringPtr Destination for use input string.
-
- @retval EFI_SUCCESS If string input is read successfully
- @retval EFI_DEVICE_ERROR If operation fails
-
-**/
-EFI_STATUS
-ReadString (
- IN UI_MENU_OPTION *MenuOption,
- IN CHAR16 *Prompt,
- OUT CHAR16 *StringPtr
- )
-{
- EFI_STATUS Status;
- EFI_INPUT_KEY Key;
- CHAR16 NullCharacter;
- UINTN ScreenSize;
- CHAR16 Space[2];
- CHAR16 KeyPad[2];
- CHAR16 *TempString;
- CHAR16 *BufferedString;
- UINTN Index;
- UINTN Count;
- UINTN Start;
- UINTN Top;
- UINTN DimensionsWidth;
- UINTN DimensionsHeight;
- BOOLEAN CursorVisible;
- UINTN Minimum;
- UINTN Maximum;
- FORM_BROWSER_STATEMENT *Question;
- BOOLEAN IsPassword;
-
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
-
- NullCharacter = CHAR_NULL;
- ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16);
- Space[0] = L' ';
- Space[1] = CHAR_NULL;
-
- Question = MenuOption->ThisTag;
- Minimum = (UINTN) Question->Minimum;
- Maximum = (UINTN) Question->Maximum;
-
- if (Question->Operand == EFI_IFR_PASSWORD_OP) {
- IsPassword = TRUE;
- } else {
- IsPassword = FALSE;
- }
-
- TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));
- ASSERT (TempString);
-
- if (ScreenSize < (Maximum + 1)) {
- ScreenSize = Maximum + 1;
- }
-
- if ((ScreenSize + 2) > DimensionsWidth) {
- ScreenSize = DimensionsWidth - 2;
- }
-
- BufferedString = AllocateZeroPool (ScreenSize * 2);
- ASSERT (BufferedString);
-
- Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;
- Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
-
- //
- // Display prompt for string
- //
- CreatePopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);
-
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
-
- CursorVisible = gST->ConOut->Mode->CursorVisible;
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-
- do {
- Status = WaitForKeyStroke (&Key);
- ASSERT_EFI_ERROR (Status);
-
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
- switch (Key.UnicodeChar) {
- case CHAR_NULL:
- switch (Key.ScanCode) {
- case SCAN_LEFT:
- break;
-
- case SCAN_RIGHT:
- break;
-
- case SCAN_ESC:
- gBS->FreePool (TempString);
- gBS->FreePool (BufferedString);
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
- return EFI_DEVICE_ERROR;
-
- default:
- break;
- }
-
- break;
-
- case CHAR_CARRIAGE_RETURN:
- if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {
-
- gBS->FreePool (TempString);
- gBS->FreePool (BufferedString);
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
- return EFI_SUCCESS;
- } else {
- //
- // Simply create a popup to tell the user that they had typed in too few characters.
- // To save code space, we can then treat this as an error and return back to the menu.
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
- gBS->FreePool (TempString);
- gBS->FreePool (BufferedString);
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
- return EFI_DEVICE_ERROR;
- }
-
- break;
-
- case CHAR_BACKSPACE:
- if (StringPtr[0] != CHAR_NULL) {
- for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
- TempString[Index] = StringPtr[Index];
- }
- //
- // Effectively truncate string by 1 character
- //
- TempString[Index - 1] = CHAR_NULL;
- StrCpy (StringPtr, TempString);
- }
-
- default:
- //
- // If it is the beginning of the string, don't worry about checking maximum limits
- //
- if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
- StrnCpy (StringPtr, &Key.UnicodeChar, 1);
- StrnCpy (TempString, &Key.UnicodeChar, 1);
- } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
- KeyPad[0] = Key.UnicodeChar;
- KeyPad[1] = CHAR_NULL;
- StrCat (StringPtr, KeyPad);
- StrCat (TempString, KeyPad);
- }
-
- //
- // If the width of the input string is now larger than the screen, we nee to
- // adjust the index to start printing portions of the string
- //
- SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');
- PrintStringAt (Start + 1, Top + 3, BufferedString);
-
- if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {
- Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;
- } else {
- Index = 0;
- }
-
- if (IsPassword) {
- gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);
- }
-
- for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {
- BufferedString[Count] = StringPtr[Index];
-
- if (IsPassword) {
- PrintChar (L'*');
- }
- }
-
- if (!IsPassword) {
- PrintStringAt (Start + 1, Top + 3, BufferedString);
- }
- break;
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);
- } while (TRUE);
-
-}
-
-
-/**
- This routine reads a numeric value from the user input.
-
- @param Selection Pointer to current selection.
- @param MenuOption Pointer to the current input menu.
-
- @retval EFI_SUCCESS If numerical input is read successfully
- @retval EFI_DEVICE_ERROR If operation fails
-
-**/
-EFI_STATUS
-GetNumericInput (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption
- )
-{
- EFI_STATUS Status;
- UINTN Column;
- UINTN Row;
- CHAR16 InputText[23];
- CHAR16 FormattedNumber[22];
- UINT64 PreviousNumber[20];
- UINTN Count;
- UINTN Loop;
- BOOLEAN ManualInput;
- BOOLEAN HexInput;
- BOOLEAN DateOrTime;
- UINTN InputWidth;
- UINT64 EditValue;
- UINT64 Step;
- UINT64 Minimum;
- UINT64 Maximum;
- UINTN EraseLen;
- UINT8 Digital;
- EFI_INPUT_KEY Key;
- EFI_HII_VALUE *QuestionValue;
- FORM_BROWSER_FORM *Form;
- FORM_BROWSER_FORMSET *FormSet;
- FORM_BROWSER_STATEMENT *Question;
-
- Column = MenuOption->OptCol;
- Row = MenuOption->Row;
- PreviousNumber[0] = 0;
- Count = 0;
- InputWidth = 0;
- Digital = 0;
-
- FormSet = Selection->FormSet;
- Form = Selection->Form;
- Question = MenuOption->ThisTag;
- QuestionValue = &Question->HiiValue;
- Step = Question->Step;
- Minimum = Question->Minimum;
- Maximum = Question->Maximum;
-
- if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
- DateOrTime = TRUE;
- } else {
- DateOrTime = FALSE;
- }
-
- //
- // Prepare Value to be edit
- //
- EraseLen = 0;
- EditValue = 0;
- if (Question->Operand == EFI_IFR_DATE_OP) {
- Step = 1;
- Minimum = 1;
-
- switch (MenuOption->Sequence) {
- case 0:
- Maximum = 12;
- EraseLen = 4;
- EditValue = QuestionValue->Value.date.Month;
- break;
-
- case 1:
- Maximum = 31;
- EraseLen = 3;
- EditValue = QuestionValue->Value.date.Day;
- break;
-
- case 2:
- Maximum = 0xffff;
- EraseLen = 5;
- EditValue = QuestionValue->Value.date.Year;
- break;
-
- default:
- break;
- }
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
- Step = 1;
- Minimum = 0;
-
- switch (MenuOption->Sequence) {
- case 0:
- Maximum = 23;
- EraseLen = 4;
- EditValue = QuestionValue->Value.time.Hour;
- break;
-
- case 1:
- Maximum = 59;
- EraseLen = 3;
- EditValue = QuestionValue->Value.time.Minute;
- break;
-
- case 2:
- Maximum = 59;
- EraseLen = 3;
- EditValue = QuestionValue->Value.time.Second;
- break;
-
- default:
- break;
- }
- } else {
- //
- // Numeric
- //
- EraseLen = gOptionBlockWidth;
- EditValue = QuestionValue->Value.u64;
- if (Maximum == 0) {
- Maximum = (UINT64) -1;
- }
- }
-
- if (Step == 0) {
- ManualInput = TRUE;
- } else {
- ManualInput = FALSE;
- }
-
- if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&
- ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
- HexInput = TRUE;
- } else {
- HexInput = FALSE;
- }
-
- if (ManualInput) {
- if (HexInput) {
- InputWidth = Question->StorageWidth * 2;
- } else {
- switch (Question->StorageWidth) {
- case 1:
- InputWidth = 3;
- break;
-
- case 2:
- InputWidth = 5;
- break;
-
- case 4:
- InputWidth = 10;
- break;
-
- case 8:
- InputWidth = 20;
- break;
-
- default:
- InputWidth = 0;
- break;
- }
- }
-
- InputText[0] = LEFT_NUMERIC_DELIMITER;
- SetUnicodeMem (InputText + 1, InputWidth, L' ');
- InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;
- InputText[InputWidth + 2] = L'\0';
-
- PrintAt (Column, Row, InputText);
- Column++;
- }
-
- //
- // First time we enter this handler, we need to check to see if
- // we were passed an increment or decrement directive
- //
- do {
- Key.UnicodeChar = CHAR_NULL;
- if (gDirection != 0) {
- Key.ScanCode = gDirection;
- gDirection = 0;
- goto TheKey2;
- }
-
- Status = WaitForKeyStroke (&Key);
-
-TheKey2:
- switch (Key.UnicodeChar) {
-
- case '+':
- case '-':
- if (Key.UnicodeChar == '+') {
- Key.ScanCode = SCAN_RIGHT;
- } else {
- Key.ScanCode = SCAN_LEFT;
- }
- Key.UnicodeChar = CHAR_NULL;
- goto TheKey2;
-
- case CHAR_NULL:
- switch (Key.ScanCode) {
- case SCAN_LEFT:
- case SCAN_RIGHT:
- if (DateOrTime) {
- //
- // By setting this value, we will return back to the caller.
- // We need to do this since an auto-refresh will destroy the adjustment
- // based on what the real-time-clock is showing. So we always commit
- // upon changing the value.
- //
- gDirection = SCAN_DOWN;
- }
-
- if (!ManualInput) {
- if (Key.ScanCode == SCAN_LEFT) {
- if (EditValue > Step) {
- EditValue = EditValue - Step;
- } else {
- EditValue = Minimum;
- }
- } else if (Key.ScanCode == SCAN_RIGHT) {
- EditValue = EditValue + Step;
- if (EditValue > Maximum) {
- EditValue = Maximum;
- }
- }
-
- ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
- if (Question->Operand == EFI_IFR_DATE_OP) {
- if (MenuOption->Sequence == 2) {
- //
- // Year
- //
- UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", EditValue);
- } else {
- //
- // Month/Day
- //
- UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
- }
-
- if (MenuOption->Sequence == 0) {
- FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;
- } else if (MenuOption->Sequence == 1) {
- FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;
- }
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
- UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
-
- if (MenuOption->Sequence == 0) {
- FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;
- } else if (MenuOption->Sequence == 1) {
- FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;
- }
- } else {
- QuestionValue->Value.u64 = EditValue;
- PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
- for (Loop = 0; Loop < EraseLen; Loop++) {
- PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
- }
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
-
- if (MenuOption->Sequence == 0) {
- PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
- Column = MenuOption->OptCol + 1;
- }
-
- PrintStringAt (Column, Row, FormattedNumber);
-
- if (!DateOrTime || MenuOption->Sequence == 2) {
- PrintChar (RIGHT_NUMERIC_DELIMITER);
- }
- }
- break;
-
- case SCAN_UP:
- case SCAN_DOWN:
- goto EnterCarriageReturn;
-
- case SCAN_ESC:
- return EFI_DEVICE_ERROR;
-
- default:
- break;
- }
-
- break;
-
-EnterCarriageReturn:
-
- case CHAR_CARRIAGE_RETURN:
- //
- // Store Edit value back to Question
- //
- if (Question->Operand == EFI_IFR_DATE_OP) {
- switch (MenuOption->Sequence) {
- case 0:
- QuestionValue->Value.date.Month = (UINT8) EditValue;
- break;
-
- case 1:
- QuestionValue->Value.date.Day = (UINT8) EditValue;
- break;
-
- case 2:
- QuestionValue->Value.date.Year = (UINT16) EditValue;
- break;
-
- default:
- break;
- }
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
- switch (MenuOption->Sequence) {
- case 0:
- QuestionValue->Value.time.Hour = (UINT8) EditValue;
- break;
-
- case 1:
- QuestionValue->Value.time.Minute = (UINT8) EditValue;
- break;
-
- case 2:
- QuestionValue->Value.time.Second = (UINT8) EditValue;
- break;
-
- default:
- break;
- }
- } else {
- //
- // Numeric
- //
- QuestionValue->Value.u64 = EditValue;
- }
-
- //
- // Check to see if the Value is something reasonable against consistency limitations.
- // If not, let's kick the error specified.
- //
- Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
- if (EFI_ERROR (Status)) {
- //
- // Input value is not valid, restore Question Value
- //
- GetQuestionValue (FormSet, Form, Question, TRUE);
- } else {
- SetQuestionValue (FormSet, Form, Question, TRUE);
- if (!DateOrTime || (Question->Storage != NULL)) {
- //
- // NV flag is unnecessary for RTC type of Date/Time
- //
- UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- }
- }
-
- return Status;
- break;
-
- case CHAR_BACKSPACE:
- if (ManualInput) {
- if (Count == 0) {
- break;
- }
- //
- // Remove a character
- //
- EditValue = PreviousNumber[Count - 1];
- UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
- Count--;
- Column--;
- PrintAt (Column, Row, L" ");
- }
- break;
-
- default:
- if (ManualInput) {
- if (HexInput) {
- if (!IsHexDigit (&Digital, Key.UnicodeChar)) {
- UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
- break;
- }
- } else {
- if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
- UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
- break;
- }
- }
-
- //
- // If Count exceed input width, there is no way more is valid
- //
- if (Count >= InputWidth) {
- break;
- }
- //
- // Someone typed something valid!
- //
- if (Count != 0) {
- if (HexInput) {
- EditValue = LShiftU64 (EditValue, 4) + Digital;
- } else {
- EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');
- }
- } else {
- if (HexInput) {
- EditValue = Digital;
- } else {
- EditValue = Key.UnicodeChar - L'0';
- }
- }
-
- if (EditValue > Maximum) {
- UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
- EditValue = PreviousNumber[Count];
- break;
- } else {
- UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
- }
-
- Count++;
- PreviousNumber[Count] = EditValue;
-
- PrintCharAt (Column, Row, Key.UnicodeChar);
- Column++;
- }
- break;
- }
- } while (TRUE);
-
-}
-
-
-/**
- Get selection for OneOf and OrderedList (Left/Right will be ignored).
-
- @param Selection Pointer to current selection.
- @param MenuOption Pointer to the current input menu.
-
- @retval EFI_SUCCESS If Option input is processed successfully
- @retval EFI_DEVICE_ERROR If operation fails
-
-**/
-EFI_STATUS
-GetSelectionInputPopUp (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption
- )
-{
- EFI_STATUS Status;
- EFI_INPUT_KEY Key;
- UINTN Index;
- CHAR16 *StringPtr;
- CHAR16 *TempStringPtr;
- UINTN Index2;
- UINTN TopOptionIndex;
- UINTN HighlightOptionIndex;
- UINTN Start;
- UINTN End;
- UINTN Top;
- UINTN Bottom;
- UINTN PopUpMenuLines;
- UINTN MenuLinesInView;
- UINTN PopUpWidth;
- CHAR16 Character;
- INT32 SavedAttribute;
- BOOLEAN ShowDownArrow;
- BOOLEAN ShowUpArrow;
- UINTN DimensionsWidth;
- LIST_ENTRY *Link;
- BOOLEAN OrderedList;
- UINT8 *ValueArray;
- EFI_HII_VALUE HiiValue;
- EFI_HII_VALUE *HiiValueArray;
- UINTN OptionCount;
- QUESTION_OPTION *OneOfOption;
- QUESTION_OPTION *CurrentOption;
- FORM_BROWSER_STATEMENT *Question;
-
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
-
- ValueArray = NULL;
- CurrentOption = NULL;
- ShowDownArrow = FALSE;
- ShowUpArrow = FALSE;
-
- StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);
- ASSERT (StringPtr);
-
- Question = MenuOption->ThisTag;
- if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {
- ValueArray = Question->BufferValue;
- OrderedList = TRUE;
- } else {
- OrderedList = FALSE;
- }
-
- //
- // Calculate Option count
- //
- if (OrderedList) {
- for (Index = 0; Index < Question->MaxContainers; Index++) {
- if (ValueArray[Index] == 0) {
- break;
- }
- }
-
- OptionCount = Index;
- } else {
- OptionCount = 0;
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
- OptionCount++;
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- }
-
- //
- // Prepare HiiValue array
- //
- HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));
- ASSERT (HiiValueArray != NULL);
- Link = GetFirstNode (&Question->OptionListHead);
- for (Index = 0; Index < OptionCount; Index++) {
- if (OrderedList) {
- HiiValueArray[Index].Type = EFI_IFR_TYPE_NUM_SIZE_8;
- HiiValueArray[Index].Value.u8 = ValueArray[Index];
- } else {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
- CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- }
-
- //
- // Move Suppressed Option to list tail
- //
- PopUpMenuLines = 0;
- for (Index = 0; Index < OptionCount; Index++) {
- OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);
- if (OneOfOption == NULL) {
- return EFI_NOT_FOUND;
- }
-
- RemoveEntryList (&OneOfOption->Link);
-
- if ((OneOfOption->SuppressExpression != NULL) &&
- (OneOfOption->SuppressExpression->Result.Value.b)) {
- //
- // This option is suppressed, insert to tail
- //
- InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
- } else {
- //
- // Insert to head
- //
- InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
-
- PopUpMenuLines++;
- }
- }
-
- //
- // Get the number of one of options present and its size
- //
- PopUpWidth = 0;
- HighlightOptionIndex = 0;
- Link = GetFirstNode (&Question->OptionListHead);
- for (Index = 0; Index < PopUpMenuLines; Index++) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
- if (StrLen (StringPtr) > PopUpWidth) {
- PopUpWidth = StrLen (StringPtr);
- }
- gBS->FreePool (StringPtr);
-
- if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) {
- //
- // Find current selected Option for OneOf
- //
- HighlightOptionIndex = Index;
- }
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
-
- //
- // Perform popup menu initialization.
- //
- PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
-
- SavedAttribute = gST->ConOut->Mode->Attribute;
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
-
- if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
- PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
- }
-
- Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
- End = Start + PopUpWidth + POPUP_FRAME_WIDTH;
- Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
- Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1;
-
- MenuLinesInView = Bottom - Top - 1;
- if (MenuLinesInView >= PopUpMenuLines) {
- Top = Top + (MenuLinesInView - PopUpMenuLines) / 2;
- Bottom = Top + PopUpMenuLines + 1;
- } else {
- ShowDownArrow = TRUE;
- }
-
- if (HighlightOptionIndex > (MenuLinesInView - 1)) {
- TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;
- } else {
- TopOptionIndex = 0;
- }
-
- do {
- //
- // Clear that portion of the screen
- //
- ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
-
- //
- // Draw "One of" pop-up menu
- //
- Character = BOXDRAW_DOWN_RIGHT;
- PrintCharAt (Start, Top, Character);
- for (Index = Start; Index + 2 < End; Index++) {
- if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {
- Character = GEOMETRICSHAPE_UP_TRIANGLE;
- } else {
- Character = BOXDRAW_HORIZONTAL;
- }
-
- PrintChar (Character);
- }
-
- Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
- Character = BOXDRAW_VERTICAL;
- for (Index = Top + 1; Index < Bottom; Index++) {
- PrintCharAt (Start, Index, Character);
- PrintCharAt (End - 1, Index, Character);
- }
-
- //
- // Move to top Option
- //
- Link = GetFirstNode (&Question->OptionListHead);
- for (Index = 0; Index < TopOptionIndex; Index++) {
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
-
- //
- // Display the One of options
- //
- Index2 = Top + 1;
- for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
- Link = GetNextNode (&Question->OptionListHead, Link);
-
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
- //
- // If the string occupies multiple lines, truncate it to fit in one line,
- // and append a "..." for indication.
- //
- if (StrLen (StringPtr) > (PopUpWidth - 1)) {
- TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));
- ASSERT ( TempStringPtr != NULL );
- CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));
- gBS->FreePool (StringPtr);
- StringPtr = TempStringPtr;
- StrCat (StringPtr, L"...");
- }
-
- if (Index == HighlightOptionIndex) {
- //
- // Highlight the selected one
- //
- CurrentOption = OneOfOption;
-
- gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);
- PrintStringAt (Start + 2, Index2, StringPtr);
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
- } else {
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
- PrintStringAt (Start + 2, Index2, StringPtr);
- }
-
- Index2++;
- gBS->FreePool (StringPtr);
- }
-
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (Start, Bottom, Character);
- for (Index = Start; Index + 2 < End; Index++) {
- if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {
- Character = GEOMETRICSHAPE_DOWN_TRIANGLE;
- } else {
- Character = BOXDRAW_HORIZONTAL;
- }
-
- PrintChar (Character);
- }
-
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
-
- //
- // Get User selection
- //
- Key.UnicodeChar = CHAR_NULL;
- if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {
- Key.ScanCode = gDirection;
- gDirection = 0;
- goto TheKey;
- }
-
- Status = WaitForKeyStroke (&Key);
-
-TheKey:
- switch (Key.UnicodeChar) {
- case '+':
- if (OrderedList) {
- if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
- //
- // Highlight reaches the top of the popup window, scroll one menu item.
- //
- TopOptionIndex--;
- ShowDownArrow = TRUE;
- }
-
- if (TopOptionIndex == 0) {
- ShowUpArrow = FALSE;
- }
-
- if (HighlightOptionIndex > 0) {
- HighlightOptionIndex--;
-
- SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);
- }
- }
- break;
-
- case '-':
- //
- // If an ordered list op-code, we will allow for a popup of +/- keys
- // to create an ordered list of items
- //
- if (OrderedList) {
- if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
- (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
- //
- // Highlight reaches the bottom of the popup window, scroll one menu item.
- //
- TopOptionIndex++;
- ShowUpArrow = TRUE;
- }
-
- if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
- ShowDownArrow = FALSE;
- }
-
- if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
- HighlightOptionIndex++;
-
- SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);
- }
- }
- break;
-
- case CHAR_NULL:
- switch (Key.ScanCode) {
- case SCAN_UP:
- case SCAN_DOWN:
- if (Key.ScanCode == SCAN_UP) {
- if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
- //
- // Highlight reaches the top of the popup window, scroll one menu item.
- //
- TopOptionIndex--;
- ShowDownArrow = TRUE;
- }
-
- if (TopOptionIndex == 0) {
- ShowUpArrow = FALSE;
- }
-
- if (HighlightOptionIndex > 0) {
- HighlightOptionIndex--;
- }
- } else {
- if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
- (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
- //
- // Highlight reaches the bottom of the popup window, scroll one menu item.
- //
- TopOptionIndex++;
- ShowUpArrow = TRUE;
- }
-
- if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
- ShowDownArrow = FALSE;
- }
-
- if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
- HighlightOptionIndex++;
- }
- }
- break;
-
- case SCAN_ESC:
- gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
-
- //
- // Restore link list order for orderedlist
- //
- if (OrderedList) {
- HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
- HiiValue.Value.u64 = 0;
- for (Index = 0; Index < Question->MaxContainers; Index++) {
- HiiValue.Value.u8 = ValueArray[Index];
- if (HiiValue.Value.u8) {
- break;
- }
-
- OneOfOption = ValueToOption (Question, &HiiValue);
- if (OneOfOption == NULL) {
- return EFI_NOT_FOUND;
- }
-
- RemoveEntryList (&OneOfOption->Link);
- InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
- }
- }
-
- gBS->FreePool (HiiValueArray);
- return EFI_DEVICE_ERROR;
-
- default:
- break;
- }
-
- break;
-
- case CHAR_CARRIAGE_RETURN:
- //
- // return the current selection
- //
- if (OrderedList) {
- Index = 0;
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
- Question->BufferValue[Index] = OneOfOption->Value.Value.u8;
-
- Index++;
- if (Index > Question->MaxContainers) {
- break;
- }
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- } else {
- CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
- gBS->FreePool (HiiValueArray);
-
- Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
- if (EFI_ERROR (Status)) {
- //
- // Input value is not valid, restore Question Value
- //
- GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
- } else {
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
- UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- }
-
- return Status;
-
- default:
- break;
- }
- } while (TRUE);
-
-}
-
-EFI_STATUS
-WaitForKeyStroke (
- OUT EFI_INPUT_KEY *Key
- )
-{
- EFI_STATUS Status;
-
- do {
- UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
- } while (EFI_ERROR(Status));
-
- return Status;
-}
+/** @file
+Implementation for handling user input from the User Interfaces.
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ui.h"
+#include "Setup.h"
+
+
+/**
+ Get string or password input from user.
+
+ @param MenuOption Pointer to the current input menu.
+ @param Prompt The prompt string shown on popup window.
+ @param StringPtr Destination for use input string.
+
+ @retval EFI_SUCCESS If string input is read successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+ReadString (
+ IN UI_MENU_OPTION *MenuOption,
+ IN CHAR16 *Prompt,
+ OUT CHAR16 *StringPtr
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ CHAR16 NullCharacter;
+ UINTN ScreenSize;
+ CHAR16 Space[2];
+ CHAR16 KeyPad[2];
+ CHAR16 *TempString;
+ CHAR16 *BufferedString;
+ UINTN Index;
+ UINTN Count;
+ UINTN Start;
+ UINTN Top;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+ BOOLEAN CursorVisible;
+ UINTN Minimum;
+ UINTN Maximum;
+ FORM_BROWSER_STATEMENT *Question;
+ BOOLEAN IsPassword;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ NullCharacter = CHAR_NULL;
+ ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16);
+ Space[0] = L' ';
+ Space[1] = CHAR_NULL;
+
+ Question = MenuOption->ThisTag;
+ Minimum = (UINTN) Question->Minimum;
+ Maximum = (UINTN) Question->Maximum;
+
+ if (Question->Operand == EFI_IFR_PASSWORD_OP) {
+ IsPassword = TRUE;
+ } else {
+ IsPassword = FALSE;
+ }
+
+ TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));
+ ASSERT (TempString);
+
+ if (ScreenSize < (Maximum + 1)) {
+ ScreenSize = Maximum + 1;
+ }
+
+ if ((ScreenSize + 2) > DimensionsWidth) {
+ ScreenSize = DimensionsWidth - 2;
+ }
+
+ BufferedString = AllocateZeroPool (ScreenSize * 2);
+ ASSERT (BufferedString);
+
+ Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+ Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
+
+ //
+ // Display prompt for string
+ //
+ CreatePopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
+
+ CursorVisible = gST->ConOut->Mode->CursorVisible;
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ do {
+ Status = WaitForKeyStroke (&Key);
+ ASSERT_EFI_ERROR (Status);
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
+ switch (Key.UnicodeChar) {
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_LEFT:
+ break;
+
+ case SCAN_RIGHT:
+ break;
+
+ case SCAN_ESC:
+ gBS->FreePool (TempString);
+ gBS->FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {
+
+ gBS->FreePool (TempString);
+ gBS->FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Simply create a popup to tell the user that they had typed in too few characters.
+ // To save code space, we can then treat this as an error and return back to the menu.
+ //
+ do {
+ CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+ gBS->FreePool (TempString);
+ gBS->FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
+ return EFI_DEVICE_ERROR;
+ }
+
+ break;
+
+ case CHAR_BACKSPACE:
+ if (StringPtr[0] != CHAR_NULL) {
+ for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
+ TempString[Index] = StringPtr[Index];
+ }
+ //
+ // Effectively truncate string by 1 character
+ //
+ TempString[Index - 1] = CHAR_NULL;
+ StrCpy (StringPtr, TempString);
+ }
+
+ default:
+ //
+ // If it is the beginning of the string, don't worry about checking maximum limits
+ //
+ if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ StrnCpy (StringPtr, &Key.UnicodeChar, 1);
+ StrnCpy (TempString, &Key.UnicodeChar, 1);
+ } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ KeyPad[0] = Key.UnicodeChar;
+ KeyPad[1] = CHAR_NULL;
+ StrCat (StringPtr, KeyPad);
+ StrCat (TempString, KeyPad);
+ }
+
+ //
+ // If the width of the input string is now larger than the screen, we nee to
+ // adjust the index to start printing portions of the string
+ //
+ SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');
+ PrintStringAt (Start + 1, Top + 3, BufferedString);
+
+ if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {
+ Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;
+ } else {
+ Index = 0;
+ }
+
+ if (IsPassword) {
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);
+ }
+
+ for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {
+ BufferedString[Count] = StringPtr[Index];
+
+ if (IsPassword) {
+ PrintChar (L'*');
+ }
+ }
+
+ if (!IsPassword) {
+ PrintStringAt (Start + 1, Top + 3, BufferedString);
+ }
+ break;
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);
+ } while (TRUE);
+
+}
+
+
+/**
+ This routine reads a numeric value from the user input.
+
+ @param Selection Pointer to current selection.
+ @param MenuOption Pointer to the current input menu.
+
+ @retval EFI_SUCCESS If numerical input is read successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+GetNumericInput (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption
+ )
+{
+ EFI_STATUS Status;
+ UINTN Column;
+ UINTN Row;
+ CHAR16 InputText[23];
+ CHAR16 FormattedNumber[22];
+ UINT64 PreviousNumber[20];
+ UINTN Count;
+ UINTN Loop;
+ BOOLEAN ManualInput;
+ BOOLEAN HexInput;
+ BOOLEAN DateOrTime;
+ UINTN InputWidth;
+ UINT64 EditValue;
+ UINT64 Step;
+ UINT64 Minimum;
+ UINT64 Maximum;
+ UINTN EraseLen;
+ UINT8 Digital;
+ EFI_INPUT_KEY Key;
+ EFI_HII_VALUE *QuestionValue;
+ FORM_BROWSER_FORM *Form;
+ FORM_BROWSER_FORMSET *FormSet;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Column = MenuOption->OptCol;
+ Row = MenuOption->Row;
+ PreviousNumber[0] = 0;
+ Count = 0;
+ InputWidth = 0;
+ Digital = 0;
+
+ FormSet = Selection->FormSet;
+ Form = Selection->Form;
+ Question = MenuOption->ThisTag;
+ QuestionValue = &Question->HiiValue;
+ Step = Question->Step;
+ Minimum = Question->Minimum;
+ Maximum = Question->Maximum;
+
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
+ DateOrTime = TRUE;
+ } else {
+ DateOrTime = FALSE;
+ }
+
+ //
+ // Prepare Value to be edit
+ //
+ EraseLen = 0;
+ EditValue = 0;
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ Step = 1;
+ Minimum = 1;
+
+ switch (MenuOption->Sequence) {
+ case 0:
+ Maximum = 12;
+ EraseLen = 4;
+ EditValue = QuestionValue->Value.date.Month;
+ break;
+
+ case 1:
+ Maximum = 31;
+ EraseLen = 3;
+ EditValue = QuestionValue->Value.date.Day;
+ break;
+
+ case 2:
+ Maximum = 0xffff;
+ EraseLen = 5;
+ EditValue = QuestionValue->Value.date.Year;
+ break;
+
+ default:
+ break;
+ }
+ } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ Step = 1;
+ Minimum = 0;
+
+ switch (MenuOption->Sequence) {
+ case 0:
+ Maximum = 23;
+ EraseLen = 4;
+ EditValue = QuestionValue->Value.time.Hour;
+ break;
+
+ case 1:
+ Maximum = 59;
+ EraseLen = 3;
+ EditValue = QuestionValue->Value.time.Minute;
+ break;
+
+ case 2:
+ Maximum = 59;
+ EraseLen = 3;
+ EditValue = QuestionValue->Value.time.Second;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ //
+ // Numeric
+ //
+ EraseLen = gOptionBlockWidth;
+ EditValue = QuestionValue->Value.u64;
+ if (Maximum == 0) {
+ Maximum = (UINT64) -1;
+ }
+ }
+
+ if (Step == 0) {
+ ManualInput = TRUE;
+ } else {
+ ManualInput = FALSE;
+ }
+
+ if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&
+ ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
+ HexInput = TRUE;
+ } else {
+ HexInput = FALSE;
+ }
+
+ if (ManualInput) {
+ if (HexInput) {
+ InputWidth = Question->StorageWidth * 2;
+ } else {
+ switch (Question->StorageWidth) {
+ case 1:
+ InputWidth = 3;
+ break;
+
+ case 2:
+ InputWidth = 5;
+ break;
+
+ case 4:
+ InputWidth = 10;
+ break;
+
+ case 8:
+ InputWidth = 20;
+ break;
+
+ default:
+ InputWidth = 0;
+ break;
+ }
+ }
+
+ InputText[0] = LEFT_NUMERIC_DELIMITER;
+ SetUnicodeMem (InputText + 1, InputWidth, L' ');
+ InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;
+ InputText[InputWidth + 2] = L'\0';
+
+ PrintAt (Column, Row, InputText);
+ Column++;
+ }
+
+ //
+ // First time we enter this handler, we need to check to see if
+ // we were passed an increment or decrement directive
+ //
+ do {
+ Key.UnicodeChar = CHAR_NULL;
+ if (gDirection != 0) {
+ Key.ScanCode = gDirection;
+ gDirection = 0;
+ goto TheKey2;
+ }
+
+ Status = WaitForKeyStroke (&Key);
+
+TheKey2:
+ switch (Key.UnicodeChar) {
+
+ case '+':
+ case '-':
+ if (Key.UnicodeChar == '+') {
+ Key.ScanCode = SCAN_RIGHT;
+ } else {
+ Key.ScanCode = SCAN_LEFT;
+ }
+ Key.UnicodeChar = CHAR_NULL;
+ goto TheKey2;
+
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_LEFT:
+ case SCAN_RIGHT:
+ if (DateOrTime) {
+ //
+ // By setting this value, we will return back to the caller.
+ // We need to do this since an auto-refresh will destroy the adjustment
+ // based on what the real-time-clock is showing. So we always commit
+ // upon changing the value.
+ //
+ gDirection = SCAN_DOWN;
+ }
+
+ if (!ManualInput) {
+ if (Key.ScanCode == SCAN_LEFT) {
+ if (EditValue > Step) {
+ EditValue = EditValue - Step;
+ } else {
+ EditValue = Minimum;
+ }
+ } else if (Key.ScanCode == SCAN_RIGHT) {
+ EditValue = EditValue + Step;
+ if (EditValue > Maximum) {
+ EditValue = Maximum;
+ }
+ }
+
+ ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (MenuOption->Sequence == 2) {
+ //
+ // Year
+ //
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", EditValue);
+ } else {
+ //
+ // Month/Day
+ //
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
+ }
+
+ if (MenuOption->Sequence == 0) {
+ FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;
+ } else if (MenuOption->Sequence == 1) {
+ FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;
+ }
+ } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);
+
+ if (MenuOption->Sequence == 0) {
+ FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;
+ } else if (MenuOption->Sequence == 1) {
+ FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;
+ }
+ } else {
+ QuestionValue->Value.u64 = EditValue;
+ PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ for (Loop = 0; Loop < EraseLen; Loop++) {
+ PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
+ }
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
+
+ if (MenuOption->Sequence == 0) {
+ PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
+ Column = MenuOption->OptCol + 1;
+ }
+
+ PrintStringAt (Column, Row, FormattedNumber);
+
+ if (!DateOrTime || MenuOption->Sequence == 2) {
+ PrintChar (RIGHT_NUMERIC_DELIMITER);
+ }
+ }
+ break;
+
+ case SCAN_UP:
+ case SCAN_DOWN:
+ goto EnterCarriageReturn;
+
+ case SCAN_ESC:
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+EnterCarriageReturn:
+
+ case CHAR_CARRIAGE_RETURN:
+ //
+ // Store Edit value back to Question
+ //
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ switch (MenuOption->Sequence) {
+ case 0:
+ QuestionValue->Value.date.Month = (UINT8) EditValue;
+ break;
+
+ case 1:
+ QuestionValue->Value.date.Day = (UINT8) EditValue;
+ break;
+
+ case 2:
+ QuestionValue->Value.date.Year = (UINT16) EditValue;
+ break;
+
+ default:
+ break;
+ }
+ } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ switch (MenuOption->Sequence) {
+ case 0:
+ QuestionValue->Value.time.Hour = (UINT8) EditValue;
+ break;
+
+ case 1:
+ QuestionValue->Value.time.Minute = (UINT8) EditValue;
+ break;
+
+ case 2:
+ QuestionValue->Value.time.Second = (UINT8) EditValue;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ //
+ // Numeric
+ //
+ QuestionValue->Value.u64 = EditValue;
+ }
+
+ //
+ // Check to see if the Value is something reasonable against consistency limitations.
+ // If not, let's kick the error specified.
+ //
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
+ if (EFI_ERROR (Status)) {
+ //
+ // Input value is not valid, restore Question Value
+ //
+ GetQuestionValue (FormSet, Form, Question, TRUE);
+ } else {
+ SetQuestionValue (FormSet, Form, Question, TRUE);
+ if (!DateOrTime || (Question->Storage != NULL)) {
+ //
+ // NV flag is unnecessary for RTC type of Date/Time
+ //
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+ }
+ }
+
+ return Status;
+ break;
+
+ case CHAR_BACKSPACE:
+ if (ManualInput) {
+ if (Count == 0) {
+ break;
+ }
+ //
+ // Remove a character
+ //
+ EditValue = PreviousNumber[Count - 1];
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
+ Count--;
+ Column--;
+ PrintAt (Column, Row, L" ");
+ }
+ break;
+
+ default:
+ if (ManualInput) {
+ if (HexInput) {
+ if (!IsHexDigit (&Digital, Key.UnicodeChar)) {
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
+ break;
+ }
+ } else {
+ if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
+ break;
+ }
+ }
+
+ //
+ // If Count exceed input width, there is no way more is valid
+ //
+ if (Count >= InputWidth) {
+ break;
+ }
+ //
+ // Someone typed something valid!
+ //
+ if (Count != 0) {
+ if (HexInput) {
+ EditValue = LShiftU64 (EditValue, 4) + Digital;
+ } else {
+ EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');
+ }
+ } else {
+ if (HexInput) {
+ EditValue = Digital;
+ } else {
+ EditValue = Key.UnicodeChar - L'0';
+ }
+ }
+
+ if (EditValue > Maximum) {
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);
+ EditValue = PreviousNumber[Count];
+ break;
+ } else {
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);
+ }
+
+ Count++;
+ PreviousNumber[Count] = EditValue;
+
+ PrintCharAt (Column, Row, Key.UnicodeChar);
+ Column++;
+ }
+ break;
+ }
+ } while (TRUE);
+
+}
+
+
+/**
+ Get selection for OneOf and OrderedList (Left/Right will be ignored).
+
+ @param Selection Pointer to current selection.
+ @param MenuOption Pointer to the current input menu.
+
+ @retval EFI_SUCCESS If Option input is processed successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+GetSelectionInputPopUp (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ UINTN Index;
+ CHAR16 *StringPtr;
+ CHAR16 *TempStringPtr;
+ UINTN Index2;
+ UINTN TopOptionIndex;
+ UINTN HighlightOptionIndex;
+ UINTN Start;
+ UINTN End;
+ UINTN Top;
+ UINTN Bottom;
+ UINTN PopUpMenuLines;
+ UINTN MenuLinesInView;
+ UINTN PopUpWidth;
+ CHAR16 Character;
+ INT32 SavedAttribute;
+ BOOLEAN ShowDownArrow;
+ BOOLEAN ShowUpArrow;
+ UINTN DimensionsWidth;
+ LIST_ENTRY *Link;
+ BOOLEAN OrderedList;
+ UINT8 *ValueArray;
+ EFI_HII_VALUE HiiValue;
+ EFI_HII_VALUE *HiiValueArray;
+ UINTN OptionCount;
+ QUESTION_OPTION *OneOfOption;
+ QUESTION_OPTION *CurrentOption;
+ FORM_BROWSER_STATEMENT *Question;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+
+ ValueArray = NULL;
+ CurrentOption = NULL;
+ ShowDownArrow = FALSE;
+ ShowUpArrow = FALSE;
+
+ StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);
+ ASSERT (StringPtr);
+
+ Question = MenuOption->ThisTag;
+ if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ ValueArray = Question->BufferValue;
+ OrderedList = TRUE;
+ } else {
+ OrderedList = FALSE;
+ }
+
+ //
+ // Calculate Option count
+ //
+ if (OrderedList) {
+ for (Index = 0; Index < Question->MaxContainers; Index++) {
+ if (ValueArray[Index] == 0) {
+ break;
+ }
+ }
+
+ OptionCount = Index;
+ } else {
+ OptionCount = 0;
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+ OptionCount++;
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ }
+
+ //
+ // Prepare HiiValue array
+ //
+ HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));
+ ASSERT (HiiValueArray != NULL);
+ Link = GetFirstNode (&Question->OptionListHead);
+ for (Index = 0; Index < OptionCount; Index++) {
+ if (OrderedList) {
+ HiiValueArray[Index].Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ HiiValueArray[Index].Value.u8 = ValueArray[Index];
+ } else {
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+ CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ }
+
+ //
+ // Move Suppressed Option to list tail
+ //
+ PopUpMenuLines = 0;
+ for (Index = 0; Index < OptionCount; Index++) {
+ OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);
+ if (OneOfOption == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ RemoveEntryList (&OneOfOption->Link);
+
+ if ((OneOfOption->SuppressExpression != NULL) &&
+ (OneOfOption->SuppressExpression->Result.Value.b)) {
+ //
+ // This option is suppressed, insert to tail
+ //
+ InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
+ } else {
+ //
+ // Insert to head
+ //
+ InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
+
+ PopUpMenuLines++;
+ }
+ }
+
+ //
+ // Get the number of one of options present and its size
+ //
+ PopUpWidth = 0;
+ HighlightOptionIndex = 0;
+ Link = GetFirstNode (&Question->OptionListHead);
+ for (Index = 0; Index < PopUpMenuLines; Index++) {
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+ StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+ if (StrLen (StringPtr) > PopUpWidth) {
+ PopUpWidth = StrLen (StringPtr);
+ }
+ gBS->FreePool (StringPtr);
+
+ if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) {
+ //
+ // Find current selected Option for OneOf
+ //
+ HighlightOptionIndex = Index;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+
+ //
+ // Perform popup menu initialization.
+ //
+ PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
+
+ SavedAttribute = gST->ConOut->Mode->Attribute;
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+
+ if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
+ PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
+ }
+
+ Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
+ End = Start + PopUpWidth + POPUP_FRAME_WIDTH;
+ Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
+ Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1;
+
+ MenuLinesInView = Bottom - Top - 1;
+ if (MenuLinesInView >= PopUpMenuLines) {
+ Top = Top + (MenuLinesInView - PopUpMenuLines) / 2;
+ Bottom = Top + PopUpMenuLines + 1;
+ } else {
+ ShowDownArrow = TRUE;
+ }
+
+ if (HighlightOptionIndex > (MenuLinesInView - 1)) {
+ TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;
+ } else {
+ TopOptionIndex = 0;
+ }
+
+ do {
+ //
+ // Clear that portion of the screen
+ //
+ ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
+
+ //
+ // Draw "One of" pop-up menu
+ //
+ Character = BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (Start, Top, Character);
+ for (Index = Start; Index + 2 < End; Index++) {
+ if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {
+ Character = GEOMETRICSHAPE_UP_TRIANGLE;
+ } else {
+ Character = BOXDRAW_HORIZONTAL;
+ }
+
+ PrintChar (Character);
+ }
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+ Character = BOXDRAW_VERTICAL;
+ for (Index = Top + 1; Index < Bottom; Index++) {
+ PrintCharAt (Start, Index, Character);
+ PrintCharAt (End - 1, Index, Character);
+ }
+
+ //
+ // Move to top Option
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ for (Index = 0; Index < TopOptionIndex; Index++) {
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+
+ //
+ // Display the One of options
+ //
+ Index2 = Top + 1;
+ for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+ //
+ // If the string occupies multiple lines, truncate it to fit in one line,
+ // and append a "..." for indication.
+ //
+ if (StrLen (StringPtr) > (PopUpWidth - 1)) {
+ TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));
+ ASSERT ( TempStringPtr != NULL );
+ CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));
+ gBS->FreePool (StringPtr);
+ StringPtr = TempStringPtr;
+ StrCat (StringPtr, L"...");
+ }
+
+ if (Index == HighlightOptionIndex) {
+ //
+ // Highlight the selected one
+ //
+ CurrentOption = OneOfOption;
+
+ gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);
+ PrintStringAt (Start + 2, Index2, StringPtr);
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ PrintStringAt (Start + 2, Index2, StringPtr);
+ }
+
+ Index2++;
+ gBS->FreePool (StringPtr);
+ }
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (Start, Bottom, Character);
+ for (Index = Start; Index + 2 < End; Index++) {
+ if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {
+ Character = GEOMETRICSHAPE_DOWN_TRIANGLE;
+ } else {
+ Character = BOXDRAW_HORIZONTAL;
+ }
+
+ PrintChar (Character);
+ }
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+
+ //
+ // Get User selection
+ //
+ Key.UnicodeChar = CHAR_NULL;
+ if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {
+ Key.ScanCode = gDirection;
+ gDirection = 0;
+ goto TheKey;
+ }
+
+ Status = WaitForKeyStroke (&Key);
+
+TheKey:
+ switch (Key.UnicodeChar) {
+ case '+':
+ if (OrderedList) {
+ if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
+ //
+ // Highlight reaches the top of the popup window, scroll one menu item.
+ //
+ TopOptionIndex--;
+ ShowDownArrow = TRUE;
+ }
+
+ if (TopOptionIndex == 0) {
+ ShowUpArrow = FALSE;
+ }
+
+ if (HighlightOptionIndex > 0) {
+ HighlightOptionIndex--;
+
+ SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);
+ }
+ }
+ break;
+
+ case '-':
+ //
+ // If an ordered list op-code, we will allow for a popup of +/- keys
+ // to create an ordered list of items
+ //
+ if (OrderedList) {
+ if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
+ (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
+ //
+ // Highlight reaches the bottom of the popup window, scroll one menu item.
+ //
+ TopOptionIndex++;
+ ShowUpArrow = TRUE;
+ }
+
+ if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
+ ShowDownArrow = FALSE;
+ }
+
+ if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
+ HighlightOptionIndex++;
+
+ SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);
+ }
+ }
+ break;
+
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_UP:
+ case SCAN_DOWN:
+ if (Key.ScanCode == SCAN_UP) {
+ if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
+ //
+ // Highlight reaches the top of the popup window, scroll one menu item.
+ //
+ TopOptionIndex--;
+ ShowDownArrow = TRUE;
+ }
+
+ if (TopOptionIndex == 0) {
+ ShowUpArrow = FALSE;
+ }
+
+ if (HighlightOptionIndex > 0) {
+ HighlightOptionIndex--;
+ }
+ } else {
+ if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
+ (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
+ //
+ // Highlight reaches the bottom of the popup window, scroll one menu item.
+ //
+ TopOptionIndex++;
+ ShowUpArrow = TRUE;
+ }
+
+ if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
+ ShowDownArrow = FALSE;
+ }
+
+ if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
+ HighlightOptionIndex++;
+ }
+ }
+ break;
+
+ case SCAN_ESC:
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+
+ //
+ // Restore link list order for orderedlist
+ //
+ if (OrderedList) {
+ HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ HiiValue.Value.u64 = 0;
+ for (Index = 0; Index < Question->MaxContainers; Index++) {
+ HiiValue.Value.u8 = ValueArray[Index];
+ if (HiiValue.Value.u8) {
+ break;
+ }
+
+ OneOfOption = ValueToOption (Question, &HiiValue);
+ if (OneOfOption == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ RemoveEntryList (&OneOfOption->Link);
+ InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
+ }
+ }
+
+ gBS->FreePool (HiiValueArray);
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ //
+ // return the current selection
+ //
+ if (OrderedList) {
+ Index = 0;
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+
+ Question->BufferValue[Index] = OneOfOption->Value.Value.u8;
+
+ Index++;
+ if (Index > Question->MaxContainers) {
+ break;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ } else {
+ CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
+ gBS->FreePool (HiiValueArray);
+
+ Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
+ if (EFI_ERROR (Status)) {
+ //
+ // Input value is not valid, restore Question Value
+ //
+ GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+ } else {
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
+ }
+
+ return Status;
+
+ default:
+ break;
+ }
+ } while (TRUE);
+
+}
+
+/**
+ Wait for a key to be pressed by user.
+
+ @param Key The key which is pressed by user.
+
+ @retval EFI_SUCCESS The function always completed successfully.
+
+**/
+EFI_STATUS
+WaitForKeyStroke (
+ OUT EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+
+ do {
+ UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
+ } while (EFI_ERROR(Status));
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
index 631f641..47f99f5 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -1,928 +1,1005 @@
-/** @file
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
- Presentation.c
-
-Abstract:
-
- Some presentation routines.
-
-
-**/
-
-#include "Setup.h"
-#include "Ui.h"
-
-BOOLEAN mHiiPackageListUpdated;
-UI_MENU_SELECTION *gCurrentSelection;
-
-
-/**
- Clear retangle with specified text attribute.
-
- @param LeftColumn Left column of retangle.
- @param RightColumn Right column of retangle.
- @param TopRow Start row of retangle.
- @param BottomRow End row of retangle.
- @param TextAttribute The character foreground and background.
-
- @return None.
-
-**/
-VOID
-ClearLines (
- UINTN LeftColumn,
- UINTN RightColumn,
- UINTN TopRow,
- UINTN BottomRow,
- UINTN TextAttribute
- )
-{
- CHAR16 *Buffer;
- UINTN Row;
-
- //
- // For now, allocate an arbitrarily long buffer
- //
- Buffer = AllocateZeroPool (0x10000);
- ASSERT (Buffer != NULL);
-
- //
- // Set foreground and background as defined
- //
- gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
-
- //
- // Much faster to buffer the long string instead of print it a character at a time
- //
- SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
-
- //
- // Clear the desired area with the appropriate foreground/background
- //
- for (Row = TopRow; Row <= BottomRow; Row++) {
- PrintStringAt (LeftColumn, Row, Buffer);
- }
-
- gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
-
- gBS->FreePool (Buffer);
- return ;
-}
-
-VOID
-NewStrCat (
- CHAR16 *Destination,
- CHAR16 *Source
- )
-{
- UINTN Length;
-
- for (Length = 0; Destination[Length] != 0; Length++)
- ;
-
- //
- // We now have the length of the original string
- // We can safely assume for now that we are concatenating a narrow value to this string.
- // For instance, the string is "XYZ" and cat'ing ">"
- // If this assumption changes, we need to make this routine a bit more complex
- //
- Destination[Length] = NARROW_CHAR;
- Length++;
-
- StrCpy (Destination + Length, Source);
-}
-
-UINTN
-GetStringWidth (
- CHAR16 *String
- )
-{
- UINTN Index;
- UINTN Count;
- UINTN IncrementValue;
-
- Index = 0;
- Count = 0;
- IncrementValue = 1;
-
- do {
- //
- // Advance to the null-terminator or to the first width directive
- //
- for (;
- (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
- Index++, Count = Count + IncrementValue
- )
- ;
-
- //
- // We hit the null-terminator, we now have a count
- //
- if (String[Index] == 0) {
- break;
- }
- //
- // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
- // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
- //
- if (String[Index] == NARROW_CHAR) {
- //
- // Skip to the next character
- //
- Index++;
- IncrementValue = 1;
- } else {
- //
- // Skip to the next character
- //
- Index++;
- IncrementValue = 2;
- }
- } while (String[Index] != 0);
-
- //
- // Increment by one to include the null-terminator in the size
- //
- Count++;
-
- return Count * sizeof (CHAR16);
-}
-
-VOID
-DisplayPageFrame (
- VOID
- )
-{
- UINTN Index;
- UINT8 Line;
- UINT8 Alignment;
- CHAR16 Character;
- CHAR16 *Buffer;
- CHAR16 *StrFrontPageBanner;
- UINTN Row;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
-
- ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));
- gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);
- ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);
-
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- //
- // For now, allocate an arbitrarily long buffer
- //
- Buffer = AllocateZeroPool (0x10000);
- ASSERT (Buffer != NULL);
-
- Character = BOXDRAW_HORIZONTAL;
-
- for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
- Buffer[Index] = Character;
- }
-
- if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
- //
- // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
- //
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- LocalScreen.TopRow,
- FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
- BANNER_TEXT | BANNER_BACKGROUND
- );
- //
- // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
- //
- for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
- //
- // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
- //
- for (Alignment = (UINT8) LocalScreen.LeftColumn;
- Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;
- Alignment++
- ) {
- if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {
- StrFrontPageBanner = GetToken (
- BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],
- FrontPageHandle
- );
- } else {
- continue;
- }
-
- switch (Alignment - LocalScreen.LeftColumn) {
- case 0:
- //
- // Handle left column
- //
- PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);
- break;
-
- case 1:
- //
- // Handle center column
- //
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
- Line,
- StrFrontPageBanner
- );
- break;
-
- case 2:
- //
- // Handle right column
- //
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
- Line,
- StrFrontPageBanner
- );
- break;
- }
-
- gBS->FreePool (StrFrontPageBanner);
- }
- }
- }
-
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
- KEYHELP_TEXT | KEYHELP_BACKGROUND
- );
-
- if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- LocalScreen.TopRow,
- LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
- TITLE_TEXT | TITLE_BACKGROUND
- );
- //
- // Print Top border line
- // +------------------------------------------------------------------------------+
- // ? ?
- // +------------------------------------------------------------------------------+
- //
- Character = BOXDRAW_DOWN_RIGHT;
-
- PrintChar (Character);
- PrintString (Buffer);
-
- Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
-
- Character = BOXDRAW_VERTICAL;
- for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
- PrintCharAt (LocalScreen.LeftColumn, Row, Character);
- PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
- }
-
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
- PrintString (Buffer);
-
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
-
- if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
- //
- // Print Bottom border line
- // +------------------------------------------------------------------------------+
- // ? ?
- // +------------------------------------------------------------------------------+
- //
- Character = BOXDRAW_DOWN_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
-
- PrintString (Buffer);
-
- Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
- Character = BOXDRAW_VERTICAL;
- for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;
- Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
- Row++
- ) {
- PrintCharAt (LocalScreen.LeftColumn, Row, Character);
- PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
- }
-
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
-
- PrintString (Buffer);
-
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
- }
- }
-
- gBS->FreePool (Buffer);
-
-}
-
-
-/**
- Evaluate all expressions in a Form.
-
- @param FormSet FormSet this Form belongs to.
- @param Form The Form.
-
- @retval EFI_SUCCESS The expression evaluated successfuly
-
-**/
-EFI_STATUS
-EvaluateFormExpressions (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- FORM_EXPRESSION *Expression;
-
- Link = GetFirstNode (&Form->ExpressionListHead);
- while (!IsNull (&Form->ExpressionListHead, Link)) {
- Expression = FORM_EXPRESSION_FROM_LINK (Link);
- Link = GetNextNode (&Form->ExpressionListHead, Link);
-
- if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
- Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
- //
- // Postpone Form validation to Question editing or Form submiting
- //
- continue;
- }
-
- Status = EvaluateExpression (FormSet, Form, Expression);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/*
-+------------------------------------------------------------------------------+
-?F2=Previous Page Setup Page ?
-+------------------------------------------------------------------------------+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-+------------------------------------------------------------------------------+
-?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
-| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
-+------------------------------------------------------------------------------+
-*/
-EFI_STATUS
-DisplayForm (
- IN OUT UI_MENU_SELECTION *Selection
- )
-{
- CHAR16 *StringPtr;
- UINT16 MenuItemCount;
- EFI_HII_HANDLE Handle;
- BOOLEAN Suppress;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- UINT16 Width;
- UINTN ArrayEntry;
- CHAR16 *OutputString;
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Statement;
- UINT16 NumberOfLines;
- EFI_STATUS Status;
-
- Handle = Selection->Handle;
- MenuItemCount = 0;
- ArrayEntry = 0;
- OutputString = NULL;
-
- UiInitMenu ();
-
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- StringPtr = GetToken (Selection->FormSet->FormSetTitle, Handle);
-
- if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
- gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
- PrintStringAt (
- (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
- LocalScreen.TopRow + 1,
- StringPtr
- );
- }
-
- if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
- gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
- //
- // Display the infrastructure strings
- //
- if (!IsListEmpty (&gMenuList)) {
- PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
- }
-
- PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
- LocalScreen.BottomRow - 4,
- gFunctionNineString
- );
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
- LocalScreen.BottomRow - 4,
- gFunctionTenString
- );
- PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
- LocalScreen.BottomRow - 3,
- gEscapeString
- );
- }
- //
- // Remove Buffer allocated for StringPtr after it has been used.
- //
- gBS->FreePool (StringPtr);
-
- //
- // Evaluate all the Expressions in this Form
- //
- Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Link = GetFirstNode (&Selection->Form->StatementListHead);
- while (!IsNull (&Selection->Form->StatementListHead, Link)) {
- Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
- if (Statement->SuppressExpression != NULL) {
- Suppress = Statement->SuppressExpression->Result.Value.b;
- } else {
- Suppress = FALSE;
- }
-
- if (!Suppress) {
- StringPtr = GetToken (Statement->Prompt, Handle);
-
- Width = GetWidth (Statement, Handle);
-
- NumberOfLines = 1;
- ArrayEntry = 0;
- for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&StringPtr[ArrayEntry])) {
- NumberOfLines++;
- }
-
- gBS->FreePool (OutputString);
- }
-
- //
- // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
- // it in UiFreeMenu.
- //
- UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);
- MenuItemCount++;
- }
-
- Link = GetNextNode (&Selection->Form->StatementListHead, Link);
- }
-
- Status = UiDisplayMenu (Selection);
-
- UiFreeMenu ();
-
- return Status;
-}
-
-VOID
-InitializeBrowserStrings (
- VOID
- )
-{
- gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);
- gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);
- gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
- gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
- gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
- gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
- gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
- gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
- gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
- gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
- gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);
- gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);
- gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
- gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
- gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
- gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
- gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
- gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
- gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
- gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
- gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
- gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);
- gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
- gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
- gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
- gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);
- gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);
- gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);
- return ;
-}
-
-VOID
-FreeBrowserStrings (
- VOID
- )
-{
- SafeFreePool (gFunctionOneString);
- SafeFreePool (gFunctionTwoString);
- SafeFreePool (gFunctionNineString);
- SafeFreePool (gFunctionTenString);
- SafeFreePool (gEnterString);
- SafeFreePool (gEnterCommitString);
- SafeFreePool (gEscapeString);
- SafeFreePool (gMoveHighlight);
- SafeFreePool (gMakeSelection);
- SafeFreePool (gDecNumericInput);
- SafeFreePool (gHexNumericInput);
- SafeFreePool (gToggleCheckBox);
- SafeFreePool (gPromptForData);
- SafeFreePool (gPromptForPassword);
- SafeFreePool (gPromptForNewPassword);
- SafeFreePool (gConfirmPassword);
- SafeFreePool (gPassowordInvalid);
- SafeFreePool (gConfirmError);
- SafeFreePool (gPressEnter);
- SafeFreePool (gEmptyString);
- SafeFreePool (gAreYouSure);
- SafeFreePool (gYesResponse);
- SafeFreePool (gNoResponse);
- SafeFreePool (gMiniString);
- SafeFreePool (gPlusString);
- SafeFreePool (gMinusString);
- SafeFreePool (gAdjustNumber);
- return ;
-}
-
-
-/**
- Update key's help imformation
-
- @param MenuOption The Menu option
- @param Selected Whether or not a tag be selected
-
- @return None
-
-**/
-VOID
-UpdateKeyHelp (
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected
- )
-{
- UINTN SecCol;
- UINTN ThdCol;
- UINTN LeftColumnOfHelp;
- UINTN RightColumnOfHelp;
- UINTN TopRowOfHelp;
- UINTN BottomRowOfHelp;
- UINTN StartColumnOfHelp;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- FORM_BROWSER_STATEMENT *Statement;
-
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
- ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
-
- StartColumnOfHelp = LocalScreen.LeftColumn + 2;
- LeftColumnOfHelp = LocalScreen.LeftColumn + 1;
- RightColumnOfHelp = LocalScreen.RightColumn - 2;
- TopRowOfHelp = LocalScreen.BottomRow - 4;
- BottomRowOfHelp = LocalScreen.BottomRow - 3;
-
- if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
- return ;
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
- Statement = MenuOption->ThisTag;
- switch (Statement->Operand) {
- case EFI_IFR_ORDERED_LIST_OP:
- case EFI_IFR_ONE_OF_OP:
- case EFI_IFR_NUMERIC_OP:
- case EFI_IFR_TIME_OP:
- case EFI_IFR_DATE_OP:
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
- if (!Selected) {
- if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
- PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
- PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
-
- if ((Statement->Operand == EFI_IFR_DATE_OP) ||
- (Statement->Operand == EFI_IFR_TIME_OP) ||
- (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
- PrintAt (
- StartColumnOfHelp,
- BottomRowOfHelp,
- L"%c%c%c%c%s",
- ARROW_UP,
- ARROW_DOWN,
- ARROW_RIGHT,
- ARROW_LEFT,
- gMoveHighlight
- );
- PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
- } else {
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
- }
- } else {
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
-
- //
- // If it is a selected numeric with manual input, display different message
- //
- if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {
- PrintStringAt (
- SecCol,
- TopRowOfHelp,
- (Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput
- );
- } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- }
-
- if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
- PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
- }
-
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
- break;
-
- case EFI_IFR_CHECKBOX_OP:
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
- if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
- PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
- PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
-
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
- break;
-
- case EFI_IFR_REF_OP:
- case EFI_IFR_PASSWORD_OP:
- case EFI_IFR_STRING_OP:
- case EFI_IFR_TEXT_OP:
- case EFI_IFR_ACTION_OP:
- case EFI_IFR_RESET_BUTTON_OP:
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
- if (!Selected) {
- if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
- PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
- PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
-
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- if (Statement->Operand != EFI_IFR_TEXT_OP) {
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
- }
- } else {
- if (Statement->Operand != EFI_IFR_REF_OP) {
- PrintStringAt (
- (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
- BottomRowOfHelp,
- gEnterCommitString
- );
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
- }
- break;
-
- default:
- break;
- }
-}
-
-EFI_STATUS
-FormUpdateNotify (
- IN UINT8 PackageType,
- IN CONST EFI_GUID *PackageGuid,
- IN CONST EFI_HII_PACKAGE_HEADER *Package,
- IN EFI_HII_HANDLE Handle,
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
- )
-{
- mHiiPackageListUpdated = TRUE;
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-SetupBrowser (
- IN OUT UI_MENU_SELECTION *Selection
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- EFI_BROWSER_ACTION_REQUEST ActionRequest;
- EFI_HANDLE NotifyHandle;
- EFI_HII_VALUE *HiiValue;
- FORM_BROWSER_STATEMENT *Statement;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
-
- gMenuRefreshHead = NULL;
- gResetRequired = FALSE;
- gNvUpdateRequired = FALSE;
-
- UiInitMenuList ();
-
- //
- // Register notify for Form package update
- //
- Status = mHiiDatabase->RegisterPackageNotify (
- mHiiDatabase,
- EFI_HII_PACKAGE_FORM,
- NULL,
- FormUpdateNotify,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- &NotifyHandle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- do {
- //
- // Displays the Header and Footer borders
- //
- DisplayPageFrame ();
-
- //
- // Initialize Selection->Form
- //
- if (Selection->FormId == 0) {
- //
- // Zero FormId indicates display the first Form in a FormSet
- //
- Link = GetFirstNode (&Selection->FormSet->FormListHead);
-
- Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);
- Selection->FormId = Selection->Form->FormId;
- } else {
- Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);
- }
-
- //
- // Load Questions' Value for display
- //
- Status = LoadFormConfig (Selection->FormSet, Selection->Form);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Display form
- //
- Status = DisplayForm (Selection);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
- //
- Statement = Selection->Statement;
- if (Statement != NULL) {
- if (Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) {
- gResetRequired = TRUE;
- }
-
- //
- // Reset FormPackage update flag
- //
- mHiiPackageListUpdated = FALSE;
-
- if (Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK && Statement->Operand != EFI_IFR_PASSWORD_OP) {
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
-
- HiiValue = &Statement->HiiValue;
- if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
- //
- // Create String in HII database for Configuration Driver to retrieve
- //
- HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);
- }
-
- ConfigAccess = Selection->FormSet->ConfigAccess;
- if (ConfigAccess == NULL) {
- return EFI_UNSUPPORTED;
- }
- Status = ConfigAccess->Callback (
- ConfigAccess,
- EFI_BROWSER_ACTION_CHANGING,
- Statement->QuestionId,
- HiiValue->Type,
- &HiiValue->Value,
- &ActionRequest
- );
-
- if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
- //
- // Clean the String in HII Database
- //
- DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);
- }
-
- if (!EFI_ERROR (Status)) {
- switch (ActionRequest) {
- case EFI_BROWSER_ACTION_REQUEST_RESET:
- gResetRequired = TRUE;
- break;
-
- case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
- SubmitForm (Selection->FormSet, Selection->Form);
- break;
-
- case EFI_BROWSER_ACTION_REQUEST_EXIT:
- Selection->Action = UI_ACTION_EXIT;
- gNvUpdateRequired = FALSE;
- break;
-
- default:
- break;
- }
- }
- }
-
- //
- // Check whether Form Package has been updated during Callback
- //
- if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {
- //
- // Force to reparse IFR binary of target Formset
- //
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
- }
- }
- } while (Selection->Action == UI_ACTION_REFRESH_FORM);
-
- //
- // Unregister notify for Form package update
- //
- Status = mHiiDatabase->UnregisterPackageNotify (
- mHiiDatabase,
- NotifyHandle
- );
- return Status;
-}
+/** @file
+Utility functions for UI presentation.
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Setup.h"
+#include "Ui.h"
+
+BOOLEAN mHiiPackageListUpdated;
+UI_MENU_SELECTION *gCurrentSelection;
+
+
+/**
+ Clear retangle with specified text attribute.
+
+ @param LeftColumn Left column of retangle.
+ @param RightColumn Right column of retangle.
+ @param TopRow Start row of retangle.
+ @param BottomRow End row of retangle.
+ @param TextAttribute The character foreground and background.
+
+**/
+VOID
+ClearLines (
+ UINTN LeftColumn,
+ UINTN RightColumn,
+ UINTN TopRow,
+ UINTN BottomRow,
+ UINTN TextAttribute
+ )
+{
+ CHAR16 *Buffer;
+ UINTN Row;
+
+ //
+ // For now, allocate an arbitrarily long buffer
+ //
+ Buffer = AllocateZeroPool (0x10000);
+ ASSERT (Buffer != NULL);
+
+ //
+ // Set foreground and background as defined
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
+
+ //
+ // Much faster to buffer the long string instead of print it a character at a time
+ //
+ SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
+
+ //
+ // Clear the desired area with the appropriate foreground/background
+ //
+ for (Row = TopRow; Row <= BottomRow; Row++) {
+ PrintStringAt (LeftColumn, Row, Buffer);
+ }
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
+
+ gBS->FreePool (Buffer);
+ return ;
+}
+
+/**
+ Concatenate a narrow string to another string.
+
+ @param Destination The destination string.
+ @param Source The source string. The string to be concatenated.
+ to the end of Destination.
+
+**/
+VOID
+NewStrCat (
+ CHAR16 *Destination,
+ CHAR16 *Source
+ )
+{
+ UINTN Length;
+
+ for (Length = 0; Destination[Length] != 0; Length++)
+ ;
+
+ //
+ // We now have the length of the original string
+ // We can safely assume for now that we are concatenating a narrow value to this string.
+ // For instance, the string is "XYZ" and cat'ing ">"
+ // If this assumption changes, we need to make this routine a bit more complex
+ //
+ Destination[Length] = NARROW_CHAR;
+ Length++;
+
+ StrCpy (Destination + Length, Source);
+}
+
+/**
+ Count the storage space of a Unicode string.
+
+ This function handles the Unicode string with NARROW_CHAR
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
+ does not count in the resultant output. If a WIDE_CHAR is
+ hit, then 2 Unicode character will consume an output storage
+ space with size of CHAR16 till a NARROW_CHAR is hit.
+
+ @param String The input string to be counted.
+
+ @return Storage space for the input string.
+
+**/
+UINTN
+GetStringWidth (
+ CHAR16 *String
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ UINTN IncrementValue;
+
+ Index = 0;
+ Count = 0;
+ IncrementValue = 1;
+
+ do {
+ //
+ // Advance to the null-terminator or to the first width directive
+ //
+ for (;
+ (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
+ Index++, Count = Count + IncrementValue
+ )
+ ;
+
+ //
+ // We hit the null-terminator, we now have a count
+ //
+ if (String[Index] == 0) {
+ break;
+ }
+ //
+ // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
+ // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
+ //
+ if (String[Index] == NARROW_CHAR) {
+ //
+ // Skip to the next character
+ //
+ Index++;
+ IncrementValue = 1;
+ } else {
+ //
+ // Skip to the next character
+ //
+ Index++;
+ IncrementValue = 2;
+ }
+ } while (String[Index] != 0);
+
+ //
+ // Increment by one to include the null-terminator in the size
+ //
+ Count++;
+
+ return Count * sizeof (CHAR16);
+}
+
+/**
+ This function displays the page frame.
+
+**/
+VOID
+DisplayPageFrame (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT8 Line;
+ UINT8 Alignment;
+ CHAR16 Character;
+ CHAR16 *Buffer;
+ CHAR16 *StrFrontPageBanner;
+ UINTN Row;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+
+ ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);
+ ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ //
+ // For now, allocate an arbitrarily long buffer
+ //
+ Buffer = AllocateZeroPool (0x10000);
+ ASSERT (Buffer != NULL);
+
+ Character = BOXDRAW_HORIZONTAL;
+
+ for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
+ Buffer[Index] = Character;
+ }
+
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ //
+ // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
+ //
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ LocalScreen.TopRow,
+ FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
+ BANNER_TEXT | BANNER_BACKGROUND
+ );
+ //
+ // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
+ //
+ for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
+ //
+ // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
+ //
+ for (Alignment = (UINT8) LocalScreen.LeftColumn;
+ Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;
+ Alignment++
+ ) {
+ if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {
+ StrFrontPageBanner = GetToken (
+ BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],
+ FrontPageHandle
+ );
+ } else {
+ continue;
+ }
+
+ switch (Alignment - LocalScreen.LeftColumn) {
+ case 0:
+ //
+ // Handle left column
+ //
+ PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);
+ break;
+
+ case 1:
+ //
+ // Handle center column
+ //
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+ Line,
+ StrFrontPageBanner
+ );
+ break;
+
+ case 2:
+ //
+ // Handle right column
+ //
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
+ Line,
+ StrFrontPageBanner
+ );
+ break;
+ }
+
+ gBS->FreePool (StrFrontPageBanner);
+ }
+ }
+ }
+
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
+ KEYHELP_TEXT | KEYHELP_BACKGROUND
+ );
+
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ LocalScreen.TopRow,
+ LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
+ TITLE_TEXT | TITLE_BACKGROUND
+ );
+ //
+ // Print Top border line
+ // +------------------------------------------------------------------------------+
+ // ? ?
+ // +------------------------------------------------------------------------------+
+ //
+ Character = BOXDRAW_DOWN_RIGHT;
+
+ PrintChar (Character);
+ PrintString (Buffer);
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+
+ Character = BOXDRAW_VERTICAL;
+ for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
+ }
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
+ PrintString (Buffer);
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ //
+ // Print Bottom border line
+ // +------------------------------------------------------------------------------+
+ // ? ?
+ // +------------------------------------------------------------------------------+
+ //
+ Character = BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
+
+ PrintString (Buffer);
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+ Character = BOXDRAW_VERTICAL;
+ for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;
+ Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
+ Row++
+ ) {
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
+ }
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
+
+ PrintString (Buffer);
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+ }
+ }
+
+ gBS->FreePool (Buffer);
+
+}
+
+
+/**
+ Evaluate all expressions in a Form.
+
+ @param FormSet FormSet this Form belongs to.
+ @param Form The Form.
+
+ @retval EFI_SUCCESS The expression evaluated successfuly
+
+**/
+EFI_STATUS
+EvaluateFormExpressions (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_EXPRESSION *Expression;
+
+ Link = GetFirstNode (&Form->ExpressionListHead);
+ while (!IsNull (&Form->ExpressionListHead, Link)) {
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+ Link = GetNextNode (&Form->ExpressionListHead, Link);
+
+ if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
+ Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+ //
+ // Postpone Form validation to Question editing or Form submiting
+ //
+ continue;
+ }
+
+ Status = EvaluateExpression (FormSet, Form, Expression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/*
++------------------------------------------------------------------------------+
+?F2=Previous Page Setup Page ?
++------------------------------------------------------------------------------+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
++------------------------------------------------------------------------------+
+?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
++------------------------------------------------------------------------------+
+*/
+
+/**
+
+
+ Display form and wait for user to select one menu option, then return it.
+
+ @param Selection On input, Selection tell setup browser the information
+ about the Selection, form and formset to be displayed.
+ On output, Selection return the screen item that is selected
+ by user.
+ @retval EFI_SUCESSS This function always return successfully for now.
+
+**/
+EFI_STATUS
+DisplayForm (
+ IN OUT UI_MENU_SELECTION *Selection
+ )
+{
+ CHAR16 *StringPtr;
+ UINT16 MenuItemCount;
+ EFI_HII_HANDLE Handle;
+ BOOLEAN Suppress;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ UINT16 Width;
+ UINTN ArrayEntry;
+ CHAR16 *OutputString;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Statement;
+ UINT16 NumberOfLines;
+ EFI_STATUS Status;
+
+ Handle = Selection->Handle;
+ MenuItemCount = 0;
+ ArrayEntry = 0;
+ OutputString = NULL;
+
+ UiInitMenu ();
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ StringPtr = GetToken (Selection->FormSet->FormSetTitle, Handle);
+
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
+ PrintStringAt (
+ (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
+ LocalScreen.TopRow + 1,
+ StringPtr
+ );
+ }
+
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ //
+ // Display the infrastructure strings
+ //
+ if (!IsListEmpty (&gMenuList)) {
+ PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
+ }
+
+ PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+ LocalScreen.BottomRow - 4,
+ gFunctionNineString
+ );
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
+ LocalScreen.BottomRow - 4,
+ gFunctionTenString
+ );
+ PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
+ LocalScreen.BottomRow - 3,
+ gEscapeString
+ );
+ }
+ //
+ // Remove Buffer allocated for StringPtr after it has been used.
+ //
+ gBS->FreePool (StringPtr);
+
+ //
+ // Evaluate all the Expressions in this Form
+ //
+ Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = GetFirstNode (&Selection->Form->StatementListHead);
+ while (!IsNull (&Selection->Form->StatementListHead, Link)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ if (Statement->SuppressExpression != NULL) {
+ Suppress = Statement->SuppressExpression->Result.Value.b;
+ } else {
+ Suppress = FALSE;
+ }
+
+ if (!Suppress) {
+ StringPtr = GetToken (Statement->Prompt, Handle);
+
+ Width = GetWidth (Statement, Handle);
+
+ NumberOfLines = 1;
+ ArrayEntry = 0;
+ for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&StringPtr[ArrayEntry])) {
+ NumberOfLines++;
+ }
+
+ gBS->FreePool (OutputString);
+ }
+
+ //
+ // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
+ // it in UiFreeMenu.
+ //
+ UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);
+ MenuItemCount++;
+ }
+
+ Link = GetNextNode (&Selection->Form->StatementListHead, Link);
+ }
+
+ Status = UiDisplayMenu (Selection);
+
+ UiFreeMenu ();
+
+ return Status;
+}
+
+/**
+ Initialize the HII String Token to the correct values.
+
+**/
+VOID
+InitializeBrowserStrings (
+ VOID
+ )
+{
+ gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);
+ gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);
+ gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
+ gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
+ gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
+ gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
+ gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
+ gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
+ gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
+ gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
+ gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);
+ gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);
+ gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
+ gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
+ gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
+ gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
+ gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
+ gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
+ gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
+ gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
+ gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);
+ gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
+ gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
+ gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
+ gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);
+ gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);
+ gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);
+ return ;
+}
+
+/**
+ Free up the resource allocated for all strings required
+ by Setup Browser.
+
+**/
+VOID
+FreeBrowserStrings (
+ VOID
+ )
+{
+ SafeFreePool (gFunctionOneString);
+ SafeFreePool (gFunctionTwoString);
+ SafeFreePool (gFunctionNineString);
+ SafeFreePool (gFunctionTenString);
+ SafeFreePool (gEnterString);
+ SafeFreePool (gEnterCommitString);
+ SafeFreePool (gEscapeString);
+ SafeFreePool (gMoveHighlight);
+ SafeFreePool (gMakeSelection);
+ SafeFreePool (gDecNumericInput);
+ SafeFreePool (gHexNumericInput);
+ SafeFreePool (gToggleCheckBox);
+ SafeFreePool (gPromptForData);
+ SafeFreePool (gPromptForPassword);
+ SafeFreePool (gPromptForNewPassword);
+ SafeFreePool (gConfirmPassword);
+ SafeFreePool (gPassowordInvalid);
+ SafeFreePool (gConfirmError);
+ SafeFreePool (gPressEnter);
+ SafeFreePool (gEmptyString);
+ SafeFreePool (gAreYouSure);
+ SafeFreePool (gYesResponse);
+ SafeFreePool (gNoResponse);
+ SafeFreePool (gMiniString);
+ SafeFreePool (gPlusString);
+ SafeFreePool (gMinusString);
+ SafeFreePool (gAdjustNumber);
+ return ;
+}
+
+
+/**
+ Update key's help imformation.
+
+ @param MenuOption The Menu option
+ @param Selected Whether or not a tag be selected
+
+**/
+VOID
+UpdateKeyHelp (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected
+ )
+{
+ UINTN SecCol;
+ UINTN ThdCol;
+ UINTN LeftColumnOfHelp;
+ UINTN RightColumnOfHelp;
+ UINTN TopRowOfHelp;
+ UINTN BottomRowOfHelp;
+ UINTN StartColumnOfHelp;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
+ ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
+
+ StartColumnOfHelp = LocalScreen.LeftColumn + 2;
+ LeftColumnOfHelp = LocalScreen.LeftColumn + 1;
+ RightColumnOfHelp = LocalScreen.RightColumn - 2;
+ TopRowOfHelp = LocalScreen.BottomRow - 4;
+ BottomRowOfHelp = LocalScreen.BottomRow - 3;
+
+ if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
+ return ;
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ Statement = MenuOption->ThisTag;
+ switch (Statement->Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_TIME_OP:
+ case EFI_IFR_DATE_OP:
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ if (!Selected) {
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ if ((Statement->Operand == EFI_IFR_DATE_OP) ||
+ (Statement->Operand == EFI_IFR_TIME_OP) ||
+ (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
+ PrintAt (
+ StartColumnOfHelp,
+ BottomRowOfHelp,
+ L"%c%c%c%c%s",
+ ARROW_UP,
+ ARROW_DOWN,
+ ARROW_RIGHT,
+ ARROW_LEFT,
+ gMoveHighlight
+ );
+ PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
+ } else {
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ }
+ } else {
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
+
+ //
+ // If it is a selected numeric with manual input, display different message
+ //
+ if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {
+ PrintStringAt (
+ SecCol,
+ TopRowOfHelp,
+ ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput
+ );
+ } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ }
+
+ if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
+ }
+
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
+ break;
+
+ case EFI_IFR_REF_OP:
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ case EFI_IFR_TEXT_OP:
+ case EFI_IFR_ACTION_OP:
+ case EFI_IFR_RESET_BUTTON_OP:
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ if (!Selected) {
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ if (Statement->Operand != EFI_IFR_TEXT_OP) {
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ }
+ } else {
+ if (Statement->Operand != EFI_IFR_REF_OP) {
+ PrintStringAt (
+ (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
+ BottomRowOfHelp,
+ gEnterCommitString
+ );
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Functions which are registered to receive notification of
+ database events have this prototype. The actual event is encoded
+ in NotifyType. The following table describes how PackageType,
+ PackageGuid, Handle, and Package are used for each of the
+ notification types.
+
+ @param PackageType Package type of the notification.
+
+ @param PackageGuid If PackageType is
+ EFI_HII_PACKAGE_TYPE_GUID, then this is
+ the pointer to the GUID from the Guid
+ field of EFI_HII_PACKAGE_GUID_HEADER.
+ Otherwise, it must be NULL.
+
+ @param Package Points to the package referred to by the
+ notification Handle The handle of the package
+ list which contains the specified package.
+
+ @param Handle The HII handle.
+
+ @param NotifyType The type of change concerning the
+ database. See
+ EFI_HII_DATABASE_NOTIFY_TYPE.
+
+**/
+EFI_STATUS
+FormUpdateNotify (
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+ )
+{
+ mHiiPackageListUpdated = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The worker function that send the displays to the screen. On output,
+ the selection made by user is returned.
+
+ @param Selection On input, Selection tell setup browser the information
+ about the Selection, form and formset to be displayed.
+ On output, Selection return the screen item that is selected
+ by user.
+
+ @retval EFI_SUCCESS The page is displayed successfully.
+ @return Other value if the page failed to be diplayed.
+
+**/
+EFI_STATUS
+SetupBrowser (
+ IN OUT UI_MENU_SELECTION *Selection
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ EFI_HANDLE NotifyHandle;
+ EFI_HII_VALUE *HiiValue;
+ FORM_BROWSER_STATEMENT *Statement;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+
+ gMenuRefreshHead = NULL;
+ gResetRequired = FALSE;
+ gNvUpdateRequired = FALSE;
+
+ UiInitMenuList ();
+
+ //
+ // Register notify for Form package update
+ //
+ Status = mHiiDatabase->RegisterPackageNotify (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_FORM,
+ NULL,
+ FormUpdateNotify,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ &NotifyHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ do {
+ //
+ // Displays the Header and Footer borders
+ //
+ DisplayPageFrame ();
+
+ //
+ // Initialize Selection->Form
+ //
+ if (Selection->FormId == 0) {
+ //
+ // Zero FormId indicates display the first Form in a FormSet
+ //
+ Link = GetFirstNode (&Selection->FormSet->FormListHead);
+
+ Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+ Selection->FormId = Selection->Form->FormId;
+ } else {
+ Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);
+ }
+
+ //
+ // Load Questions' Value for display
+ //
+ Status = LoadFormConfig (Selection->FormSet, Selection->Form);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Display form
+ //
+ Status = DisplayForm (Selection);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check Selected Statement (if press ESC, Selection->Statement will be NULL)
+ //
+ Statement = Selection->Statement;
+ if (Statement != NULL) {
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {
+ gResetRequired = TRUE;
+ }
+
+ //
+ // Reset FormPackage update flag
+ //
+ mHiiPackageListUpdated = FALSE;
+
+ if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+ HiiValue = &Statement->HiiValue;
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
+ //
+ // Create String in HII database for Configuration Driver to retrieve
+ //
+ HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);
+ }
+
+ ConfigAccess = Selection->FormSet->ConfigAccess;
+ if (ConfigAccess == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = ConfigAccess->Callback (
+ ConfigAccess,
+ EFI_BROWSER_ACTION_CHANGING,
+ Statement->QuestionId,
+ HiiValue->Type,
+ &HiiValue->Value,
+ &ActionRequest
+ );
+
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
+ //
+ // Clean the String in HII Database
+ //
+ DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ switch (ActionRequest) {
+ case EFI_BROWSER_ACTION_REQUEST_RESET:
+ gResetRequired = TRUE;
+ break;
+
+ case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
+ SubmitForm (Selection->FormSet, Selection->Form);
+ break;
+
+ case EFI_BROWSER_ACTION_REQUEST_EXIT:
+ Selection->Action = UI_ACTION_EXIT;
+ gNvUpdateRequired = FALSE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ //
+ // Check whether Form Package has been updated during Callback
+ //
+ if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {
+ //
+ // Force to reparse IFR binary of target Formset
+ //
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;
+ }
+ }
+ } while (Selection->Action == UI_ACTION_REFRESH_FORM);
+
+ //
+ // Unregister notify for Form package update
+ //
+ Status = mHiiDatabase->UnregisterPackageNotify (
+ mHiiDatabase,
+ NotifyHandle
+ );
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Print.c b/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
index 235ee45..d8b42f8 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
@@ -1,326 +1,349 @@
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- Print.c
-
-Abstract:
-
- Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very
- simple implemenation of SPrint() and Print() to support debug.
-
- You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a
- time. This makes the implementation very simple.
-
- VSPrint, Print, SPrint format specification has the follwoing form
-
- %type
-
- type:
- 'S','s' - argument is an Unicode string
- 'c' - argument is an ascii character
- '%' - Print a %
-
-
-**/
-
-#include "Setup.h"
-
-UINTN
-ValueToString (
- IN OUT CHAR16 *Buffer,
- IN BOOLEAN Flags,
- IN INT64 Value
- );
-
-UINTN
-PrintInternal (
- IN UINTN Column,
- IN UINTN Row,
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,
- IN CHAR16 *fmt,
- IN VA_LIST args
- )
-//
-// Display string worker for: Print, PrintAt, IPrint, IPrintAt
-//
-{
- CHAR16 *Buffer;
- CHAR16 *BackupBuffer;
- UINTN Index;
- UINTN PreviousIndex;
-
- //
- // For now, allocate an arbitrarily long buffer
- //
- Buffer = AllocateZeroPool (0x10000);
- BackupBuffer = AllocateZeroPool (0x10000);
- ASSERT (Buffer);
- ASSERT (BackupBuffer);
-
- if (Column != (UINTN) -1) {
- Out->SetCursorPosition (Out, Column, Row);
- }
-
- UnicodeVSPrint (Buffer, 0x10000, fmt, args);
-
- Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
-
- Out->SetAttribute (Out, Out->Mode->Attribute);
-
- Index = 0;
- PreviousIndex = 0;
-
- do {
- for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {
- BackupBuffer[Index] = Buffer[Index];
- }
-
- if (Buffer[Index] == 0) {
- break;
- }
- //
- // Null-terminate the temporary string
- //
- BackupBuffer[Index] = 0;
-
- //
- // Print this out, we are about to switch widths
- //
- Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
-
- //
- // Preserve the current index + 1, since this is where we will start printing from next
- //
- PreviousIndex = Index + 1;
-
- //
- // We are at a narrow or wide character directive. Set attributes and strip it and print it
- //
- if (Buffer[Index] == NARROW_CHAR) {
- //
- // Preserve bits 0 - 6 and zero out the rest
- //
- Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
- Out->SetAttribute (Out, Out->Mode->Attribute);
- } else {
- //
- // Must be wide, set bit 7 ON
- //
- Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;
- Out->SetAttribute (Out, Out->Mode->Attribute);
- }
-
- Index++;
-
- } while (Buffer[Index] != 0);
-
- //
- // We hit the end of the string - print it
- //
- Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
-
- gBS->FreePool (Buffer);
- gBS->FreePool (BackupBuffer);
- return EFI_SUCCESS;
-}
-
-
-/**
- Prints a formatted unicode string to the default console
-
- @param fmt Format string
-
- @return Length of string printed to the console
-
-**/
-UINTN
-ConsolePrint (
- IN CHAR16 *fmt,
- ...
- )
-{
- VA_LIST args;
-
- VA_START (args, fmt);
- return PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, fmt, args);
-}
-
-
-/**
- Prints a unicode string to the default console,
- using L"%s" format.
-
- @param String String pointer.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-PrintString (
- CHAR16 *String
- )
-{
- return ConsolePrint (L"%s", String);
-}
-
-
-/**
- Prints a chracter to the default console,
- using L"%c" format.
-
- @param Character Character to print.
-
- @return Length of string printed to the console.
-
-**/
-UINTN
-PrintChar (
- CHAR16 Character
- )
-{
- return ConsolePrint (L"%c", Character);
-}
-
-
-/**
- Prints a formatted unicode string to the default console, at
- the supplied cursor position
-
- @param Row The cursor position to print the string at
- @param fmt Format string
-
- @return Length of string printed to the console
-
-**/
-UINTN
-PrintAt (
- IN UINTN Column,
- IN UINTN Row,
- IN CHAR16 *fmt,
- ...
- )
-{
- VA_LIST args;
-
- VA_START (args, fmt);
- return PrintInternal (Column, Row, gST->ConOut, fmt, args);
-}
-
-
-/**
- Prints a unicode string to the default console, at
- the supplied cursor position, using L"%s" format.
-
- @param Row The cursor position to print the string at
- @param String String pointer.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-PrintStringAt (
- IN UINTN Column,
- IN UINTN Row,
- CHAR16 *String
- )
-{
- return PrintAt (Column, Row, L"%s", String);
-}
-
-
-/**
- Prints a chracter to the default console, at
- the supplied cursor position, using L"%c" format.
-
- @param Row The cursor position to print the string at
- @param Character Character to print.
-
- @return Length of string printed to the console.
-
-**/
-UINTN
-PrintCharAt (
- IN UINTN Column,
- IN UINTN Row,
- CHAR16 Character
- )
-{
- return PrintAt (Column, Row, L"%c", Character);
-}
-
-
-/**
- VSPrint worker function that prints a Value as a decimal number in Buffer
-
- @param Buffer Location to place ascii decimal number string of Value.
- @param Value Decimal value to convert to a string in Buffer.
- @param Flags Flags to use in printing decimal string, see file header for
- details.
-
- @return Number of characters printed.
-
-**/
-UINTN
-ValueToString (
- IN OUT CHAR16 *Buffer,
- IN BOOLEAN Flags,
- IN INT64 Value
- )
-{
- CHAR16 TempBuffer[30];
- CHAR16 *TempStr;
- CHAR16 *BufferPtr;
- UINTN Count;
- UINTN NumberCount;
- UINT32 Remainder;
- BOOLEAN Negative;
-
- Negative = FALSE;
- TempStr = TempBuffer;
- BufferPtr = Buffer;
- Count = 0;
- NumberCount = 0;
-
- if (Value < 0) {
- Negative = TRUE;
- Value = -Value;
- }
-
- do {
- Value = (INT64) DivU64x32Remainder ((UINT64) Value, 10, &Remainder);
- *(TempStr++) = (CHAR16) (Remainder + '0');
- Count++;
- NumberCount++;
- if ((Flags & COMMA_TYPE) == COMMA_TYPE) {
- if (NumberCount % 3 == 0 && Value != 0) {
- *(TempStr++) = ',';
- Count++;
- }
- }
- } while (Value != 0);
-
- if (Negative) {
- *(BufferPtr++) = '-';
- Count++;
- }
-
- //
- // Reverse temp string into Buffer.
- //
- while (TempStr != TempBuffer) {
- *(BufferPtr++) = *(--TempStr);
- }
-
- *BufferPtr = 0;
- return Count;
-}
+/** @file
+Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very
+simple implemenation of SPrint() and Print() to support debug.
+
+You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a
+time. This makes the implementation very simple.
+
+VSPrint, Print, SPrint format specification has the follwoing form
+
+%type
+
+type:
+ 'S','s' - argument is an Unicode string
+ 'c' - argument is an ascii character
+ '%' - Print a %
+
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Setup.h"
+
+/**
+ VSPrint worker function that prints a Value as a decimal number in Buffer.
+
+ @param Buffer Location to place ascii decimal number string of Value.
+ @param Flags Flags to use in printing decimal string, see file header for
+ details.
+ @param Value Decimal value to convert to a string in Buffer.
+
+ @return Number of characters printed.
+
+**/
+UINTN
+ValueToString (
+ IN OUT CHAR16 *Buffer,
+ IN BOOLEAN Flags,
+ IN INT64 Value
+ );
+
+/**
+ The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+ protocol instance.
+
+ @param Column The position of the output string.
+ @param Row The position of the output string.
+ @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
+ @param Fmt The format string.
+ @param Args The additional argument for the variables in the format string.
+
+ @return Number of Unicode character printed.
+
+**/
+UINTN
+PrintInternal (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,
+ IN CHAR16 *Fmt,
+ IN VA_LIST Args
+ )
+{
+ CHAR16 *Buffer;
+ CHAR16 *BackupBuffer;
+ UINTN Index;
+ UINTN PreviousIndex;
+ UINTN Count;
+
+ //
+ // For now, allocate an arbitrarily long buffer
+ //
+ Buffer = AllocateZeroPool (0x10000);
+ BackupBuffer = AllocateZeroPool (0x10000);
+ ASSERT (Buffer);
+ ASSERT (BackupBuffer);
+
+ if (Column != (UINTN) -1) {
+ Out->SetCursorPosition (Out, Column, Row);
+ }
+
+ UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);
+
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
+
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+
+ Index = 0;
+ PreviousIndex = 0;
+ Count = 0;
+
+ do {
+ for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {
+ BackupBuffer[Index] = Buffer[Index];
+ }
+
+ if (Buffer[Index] == 0) {
+ break;
+ }
+ //
+ // Null-terminate the temporary string
+ //
+ BackupBuffer[Index] = 0;
+
+ //
+ // Print this out, we are about to switch widths
+ //
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
+ Count += StrLen (&BackupBuffer[PreviousIndex]);
+
+ //
+ // Preserve the current index + 1, since this is where we will start printing from next
+ //
+ PreviousIndex = Index + 1;
+
+ //
+ // We are at a narrow or wide character directive. Set attributes and strip it and print it
+ //
+ if (Buffer[Index] == NARROW_CHAR) {
+ //
+ // Preserve bits 0 - 6 and zero out the rest
+ //
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+ } else {
+ //
+ // Must be wide, set bit 7 ON
+ //
+ Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+ }
+
+ Index++;
+
+ } while (Buffer[Index] != 0);
+
+ //
+ // We hit the end of the string - print it
+ //
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
+ Count += StrLen (&BackupBuffer[PreviousIndex]);
+
+ gBS->FreePool (Buffer);
+ gBS->FreePool (BackupBuffer);
+ return Count;
+}
+
+
+/**
+ Prints a formatted unicode string to the default console.
+
+ @param Fmt Format string
+ @param ... Variable argument list for format string.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+ConsolePrint (
+ IN CHAR16 *Fmt,
+ IN ...
+ )
+{
+ VA_LIST Args;
+
+ VA_START (Args, Fmt);
+ return PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, Fmt, Args);
+}
+
+
+/**
+ Prints a unicode string to the default console,
+ using L"%s" format.
+
+ @param String String pointer.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+PrintString (
+ IN CHAR16 *String
+ )
+{
+ return ConsolePrint (L"%s", String);
+}
+
+
+/**
+ Prints a chracter to the default console,
+ using L"%c" format.
+
+ @param Character Character to print.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+PrintChar (
+ CHAR16 Character
+ )
+{
+ return ConsolePrint (L"%c", Character);
+}
+
+
+/**
+ Prints a formatted unicode string to the default console, at
+ the supplied cursor position.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at.
+ @param Fmt Format string.
+ @param ... Variable argument list for format string.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+PrintAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *Fmt,
+ ...
+ )
+{
+ VA_LIST Args;
+
+ VA_START (Args, Fmt);
+ return PrintInternal (Column, Row, gST->ConOut, Fmt, Args);
+}
+
+
+/**
+ Prints a unicode string to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at
+ @param String String pointer.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+PrintStringAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 *String
+ )
+{
+ return PrintAt (Column, Row, L"%s", String);
+}
+
+
+/**
+ Prints a chracter to the default console, at
+ the supplied cursor position, using L"%c" format.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at.
+ @param Character Character to print.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+PrintCharAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 Character
+ )
+{
+ return PrintAt (Column, Row, L"%c", Character);
+}
+
+
+/**
+ VSPrint worker function that prints a Value as a decimal number in Buffer.
+
+ @param Buffer Location to place ascii decimal number string of Value.
+ @param Flags Flags to use in printing decimal string, see file header for
+ details.
+ @param Value Decimal value to convert to a string in Buffer.
+
+ @return Number of characters printed.
+
+**/
+UINTN
+ValueToString (
+ IN OUT CHAR16 *Buffer,
+ IN BOOLEAN Flags,
+ IN INT64 Value
+ )
+{
+ CHAR16 TempBuffer[30];
+ CHAR16 *TempStr;
+ CHAR16 *BufferPtr;
+ UINTN Count;
+ UINTN NumberCount;
+ UINT32 Remainder;
+ BOOLEAN Negative;
+
+ Negative = FALSE;
+ TempStr = TempBuffer;
+ BufferPtr = Buffer;
+ Count = 0;
+ NumberCount = 0;
+
+ if (Value < 0) {
+ Negative = TRUE;
+ Value = -Value;
+ }
+
+ do {
+ Value = (INT64) DivU64x32Remainder ((UINT64) Value, 10, &Remainder);
+ *(TempStr++) = (CHAR16) (Remainder + '0');
+ Count++;
+ NumberCount++;
+ if ((Flags & COMMA_TYPE) == COMMA_TYPE) {
+ if (NumberCount % 3 == 0 && Value != 0) {
+ *(TempStr++) = ',';
+ Count++;
+ }
+ }
+ } while (Value != 0);
+
+ if (Negative) {
+ *(BufferPtr++) = '-';
+ Count++;
+ }
+
+ //
+ // Reverse temp string into Buffer.
+ //
+ while (TempStr != TempBuffer) {
+ *(BufferPtr++) = *(--TempStr);
+ }
+
+ *BufferPtr = 0;
+ return Count;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Print.h b/MdeModulePkg/Universal/SetupBrowserDxe/Print.h
index c473a26..b75e0ff 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Print.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Print.h
@@ -1,4 +1,5 @@
/** @file
+Micro definitions data for Print.c
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
@@ -9,15 +10,6 @@ http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-Module Name:
-
- Print.h
-
-Abstract:
-
- Private data for Print.c
-
-
**/
#ifndef _PRINT_H_
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
index ac9eeda..3e2cd18 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
@@ -1,4 +1,6 @@
/** @file
+Implementation for handling the User Interface option processing.
+
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
@@ -9,17 +11,6 @@ http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-Module Name:
-
- ProcessOptions.c
-
-Abstract:
-
- Implementation for handling the User Interface option processing.
-
-Revision History
-
-
**/
#include "Ui.h"
@@ -113,7 +104,7 @@ ValueToOption (
/**
Print Question Value according to it's storage width and display attributes.
- @param Event The event to wait for
+ @param Question The Question to be printed.
@param FormattedNumber Buffer for output string.
@param BufferSize The FormattedNumber buffer size in bytes.
@@ -265,10 +256,6 @@ PasswordCallback (
/**
Display error message for invalid password.
- None.
-
- @return None.
-
**/
VOID
PasswordInvalid (
@@ -624,7 +611,7 @@ ProcessOptions (
//
// For interactive passwords, old password is validated by callback
//
- if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
//
// Use a NULL password to test whether old password is required
//
@@ -707,7 +694,7 @@ ProcessOptions (
//
// Reset state machine for interactive password
//
- if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
PasswordCallback (Selection, MenuOption, NULL);
}
@@ -725,7 +712,7 @@ ProcessOptions (
//
// Reset state machine for interactive password
//
- if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
PasswordCallback (Selection, MenuOption, NULL);
}
@@ -741,7 +728,7 @@ ProcessOptions (
//
// Two password match, send it to Configuration Driver
//
- if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
PasswordCallback (Selection, MenuOption, StringPtr);
} else {
CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
@@ -751,7 +738,7 @@ ProcessOptions (
//
// Reset state machine for interactive password
//
- if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) {
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
PasswordCallback (Selection, MenuOption, NULL);
}
@@ -781,11 +768,8 @@ ProcessOptions (
FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
@param StringPtr The entire help string.
- @param MenuOption The MenuOption for this Question.
+ @param FormattedString The oupput formatted string.
@param RowCount TRUE: if Question is selected.
- @param OptionString Pointer of the Option String to be displayed.
-
- @return None.
**/
VOID
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
index ff85775..40c2544 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -1,2312 +1,2302 @@
-/** @file
-Copyright (c) 2007 - 2008, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- Setup.c
-
-Abstract:
-
- Entry and initialization module for the browser.
-
-
-**/
-
-#include "Setup.h"
-#include "Ui.h"
-
-
-SETUP_DRIVER_PRIVATE_DATA mPrivateData = {
- SETUP_DRIVER_SIGNATURE,
- NULL,
- {
- SendForm,
- BrowserCallback
- },
- {
- UnicodeVSPrint
- }
-};
-
-EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
-EFI_HII_STRING_PROTOCOL *mHiiString;
-EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
-
-BANNER_DATA *BannerData;
-EFI_HII_HANDLE FrontPageHandle;
-UINTN gClassOfVfr;
-UINTN gFunctionKeySetting;
-BOOLEAN gResetRequired;
-BOOLEAN gNvUpdateRequired;
-EFI_HII_HANDLE gHiiHandle;
-BOOLEAN gFirstIn;
-UINT16 gDirection;
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;
-BOOLEAN gUpArrow;
-BOOLEAN gDownArrow;
-
-//
-// Browser Global Strings
-//
-CHAR16 *gFunctionOneString;
-CHAR16 *gFunctionTwoString;
-CHAR16 *gFunctionNineString;
-CHAR16 *gFunctionTenString;
-CHAR16 *gEnterString;
-CHAR16 *gEnterCommitString;
-CHAR16 *gEscapeString;
-CHAR16 *gSaveFailed;
-CHAR16 *gMoveHighlight;
-CHAR16 *gMakeSelection;
-CHAR16 *gDecNumericInput;
-CHAR16 *gHexNumericInput;
-CHAR16 *gToggleCheckBox;
-CHAR16 *gPromptForData;
-CHAR16 *gPromptForPassword;
-CHAR16 *gPromptForNewPassword;
-CHAR16 *gConfirmPassword;
-CHAR16 *gConfirmError;
-CHAR16 *gPassowordInvalid;
-CHAR16 *gPressEnter;
-CHAR16 *gEmptyString;
-CHAR16 *gAreYouSure;
-CHAR16 *gYesResponse;
-CHAR16 *gNoResponse;
-CHAR16 *gMiniString;
-CHAR16 *gPlusString;
-CHAR16 *gMinusString;
-CHAR16 *gAdjustNumber;
-
-CHAR16 gPromptBlockWidth;
-CHAR16 gOptionBlockWidth;
-CHAR16 gHelpBlockWidth;
-
-EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
-EFI_GUID gSetupBrowserGuid = {
- 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
-};
-
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
- //
- // Boot Manager
- //
- {
- {
- 0x847bc3fe,
- 0xb974,
- 0x446d,
- {
- 0x94,
- 0x49,
- 0x5a,
- 0xd5,
- 0x41,
- 0x2e,
- 0x99,
- 0x3b
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
- //
- // Device Manager
- //
- {
- {
- 0x3ebfa8e6,
- 0x511d,
- 0x4b5b,
- {
- 0xa9,
- 0x5f,
- 0xfb,
- 0x38,
- 0x26,
- 0xf,
- 0x1c,
- 0x27
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
- //
- // BMM FormSet.
- //
- {
- {
- 0x642237c7,
- 0x35d4,
- 0x472d,
- {
- 0x83,
- 0x65,
- 0x12,
- 0xe0,
- 0xcc,
- 0xf2,
- 0x7a,
- 0x22
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
- //
- // BMM File Explorer FormSet.
- //
- {
- {
- 0x1f2d63e1,
- 0xfebd,
- 0x4dc7,
- {
- 0x9c,
- 0xc5,
- 0xba,
- 0x2b,
- 0x1c,
- 0xef,
- 0x9c,
- 0x5b
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
-};
-
-EFI_STATUS
-EFIAPI
-SendForm (
- IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
- IN EFI_HII_HANDLE *Handles,
- IN UINTN HandleCount,
- IN EFI_GUID *FormSetGuid, OPTIONAL
- IN UINT16 FormId, OPTIONAL
- IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
- OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
- )
-/*++
-
-Routine Description:
- This is the routine which an external caller uses to direct the browser
- where to obtain it's information.
-
-Arguments:
- This - The Form Browser protocol instanse.
- Handles - A pointer to an array of Handles. If HandleCount > 1 we
- display a list of the formsets for the handles specified.
- HandleCount - The number of Handles specified in Handle.
- FormSetGuid - This field points to the EFI_GUID which must match the Guid
- field in the EFI_IFR_FORM_SET op-code for the specified
- forms-based package. If FormSetGuid is NULL, then this
- function will display the first found forms package.
- FormId - This field specifies which EFI_IFR_FORM to render as the first
- displayable page. If this field has a value of 0x0000, then
- the forms browser will render the specified forms in their encoded order.
- ScreenDimenions - This allows the browser to be called so that it occupies a
- portion of the physical screen instead of dynamically determining the screen dimensions.
- ActionRequest - Points to the action recommended by the form.
-
-Returns:
- EFI_SUCCESS - The function completed successfully.
- EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
- EFI_NOT_FOUND - No valid forms could be found to display.
-
---*/
-{
- EFI_STATUS Status;
- UI_MENU_SELECTION *Selection;
- UINTN Index;
- FORM_BROWSER_FORMSET *FormSet;
-
- Status = EFI_SUCCESS;
- ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- //
- // Seed the dimensions in the global
- //
- gST->ConOut->QueryMode (
- gST->ConOut,
- gST->ConOut->Mode->Mode,
- &gScreenDimensions.RightColumn,
- &gScreenDimensions.BottomRow
- );
-
- if (ScreenDimensions != NULL) {
- //
- // Check local dimension vs. global dimension.
- //
- if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
- (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
- ) {
- return EFI_INVALID_PARAMETER;
- } else {
- //
- // Local dimension validation.
- //
- if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
- (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
- ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
- (
- (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
- SCROLL_ARROW_HEIGHT *
- 2 +
- FRONT_PAGE_HEADER_HEIGHT +
- FOOTER_HEIGHT +
- 1
- )
- ) {
- CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
- } else {
- return EFI_INVALID_PARAMETER;
- }
- }
- }
-
- gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
- gHelpBlockWidth = gOptionBlockWidth;
- gPromptBlockWidth = gOptionBlockWidth;
-
- //
- // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
- //
- InitializeBrowserStrings ();
-
- gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
- gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;
-
- //
- // Ensure we are in Text mode
- //
- if (gFirstIn) {
- gFirstIn = FALSE;
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- DisableQuietBoot ();
- }
-
- for (Index = 0; Index < HandleCount; Index++) {
- Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
- ASSERT (Selection != NULL);
-
- Selection->Handle = Handles[Index];
- if (FormSetGuid != NULL) {
- CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
- Selection->FormId = FormId;
- }
-
- do {
- FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
- ASSERT (FormSet != NULL);
-
- //
- // Initialize internal data structures of FormSet
- //
- Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
- if (EFI_ERROR (Status)) {
- DestroyFormSet (FormSet);
- break;
- }
- Selection->FormSet = FormSet;
-
- //
- // Initialize current settings of Questions in this FormSet
- //
- Status = InitializeCurrentSetting (FormSet);
- if (EFI_ERROR (Status)) {
- DestroyFormSet (FormSet);
- break;
- }
-
- //
- // Display this formset
- //
- gCurrentSelection = Selection;
-
- Status = SetupBrowser (Selection);
-
- gCurrentSelection = NULL;
- DestroyFormSet (FormSet);
-
- if (EFI_ERROR (Status)) {
- break;
- }
-
- } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
-
- gBS->FreePool (Selection);
- }
-
- if (ActionRequest != NULL) {
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
- if (gResetRequired) {
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
- }
- }
-
- FreeBrowserStrings ();
-
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->ClearScreen (gST->ConOut);
-
- return Status;
-}
-
-
-/**
- This function is called by a callback handler to retrieve uncommitted state
- data from the browser.
-
- @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
- instance.
- @param ResultsDataSize A pointer to the size of the buffer associated
- with ResultsData.
- @param ResultsData A string returned from an IFR browser or
- equivalent. The results string will have no
- routing information in them.
- @param RetrieveData A BOOLEAN field which allows an agent to retrieve
- (if RetrieveData = TRUE) data from the uncommitted
- browser state information or set (if RetrieveData
- = FALSE) data in the uncommitted browser state
- information.
- @param VariableGuid An optional field to indicate the target variable
- GUID name to use.
- @param VariableName An optional field to indicate the target
- human-readable variable name.
-
- @retval EFI_SUCCESS The results have been distributed or are awaiting
- distribution.
- @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
- contain the results data.
-
-**/
-EFI_STATUS
-EFIAPI
-BrowserCallback (
- IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
- IN OUT UINTN *ResultsDataSize,
- IN OUT EFI_STRING ResultsData,
- IN BOOLEAN RetrieveData,
- IN CONST EFI_GUID *VariableGuid, OPTIONAL
- IN CONST CHAR16 *VariableName OPTIONAL
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- FORMSET_STORAGE *Storage;
- FORM_BROWSER_FORMSET *FormSet;
- BOOLEAN Found;
- CHAR16 *ConfigResp;
- CHAR16 *StrPtr;
- UINTN BufferSize;
- UINTN TmpSize;
-
- if (ResultsDataSize == NULL || ResultsData == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (gCurrentSelection == NULL) {
- return EFI_NOT_READY;
- }
-
- Storage = NULL;
- ConfigResp = NULL;
- FormSet = gCurrentSelection->FormSet;
-
- //
- // Find target storage
- //
- Link = GetFirstNode (&FormSet->StorageListHead);
- if (IsNull (&FormSet->StorageListHead, Link)) {
- return EFI_UNSUPPORTED;
- }
-
- if (VariableGuid != NULL) {
- //
- // Try to find target storage
- //
- Found = FALSE;
- while (!IsNull (&FormSet->StorageListHead, Link)) {
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
- Link = GetNextNode (&FormSet->StorageListHead, Link);
-
- if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
- //
- // Buffer storage require both GUID and Name
- //
- if (VariableName == NULL) {
- return EFI_NOT_FOUND;
- }
-
- if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
- continue;
- }
- }
- Found = TRUE;
- break;
- }
- }
-
- if (!Found) {
- return EFI_NOT_FOUND;
- }
- } else {
- //
- // GUID/Name is not specified, take the first storage in FormSet
- //
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
- }
-
- if (RetrieveData) {
- //
- // Skip if there is no RequestElement
- //
- if (Storage->ElementCount == 0) {
- return EFI_SUCCESS;
- }
-
- //
- // Generate <ConfigResp>
- //
- Status = StorageToConfigResp (Storage, &ConfigResp);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Skip <ConfigHdr> and '&' to point to <ConfigBody>
- //
- StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
-
- BufferSize = StrSize (StrPtr);
- if (*ResultsDataSize < BufferSize) {
- *ResultsDataSize = BufferSize;
-
- gBS->FreePool (ConfigResp);
- return EFI_BUFFER_TOO_SMALL;
- }
-
- *ResultsDataSize = BufferSize;
- CopyMem (ResultsData, StrPtr, BufferSize);
-
- gBS->FreePool (ConfigResp);
- } else {
- //
- // Prepare <ConfigResp>
- //
- TmpSize = StrLen (ResultsData);
- BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
- ConfigResp = AllocateZeroPool (BufferSize);
- ASSERT (ConfigResp != NULL);
-
- StrCpy (ConfigResp, Storage->ConfigHdr);
- StrCat (ConfigResp, L"&");
- StrCat (ConfigResp, ResultsData);
-
- //
- // Update Browser uncommited data
- //
- Status = ConfigRespToStorage (Storage, ConfigResp);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Initialize Setup
-
- @param entry EFI_IMAGE_ENTRY_POINT)
-
- @retval EFI_SUCCESS Setup loaded.
- @retval other Setup Error
-
-**/
-EFI_STATUS
-EFIAPI
-InitializeSetup (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE HiiDriverHandle;
- EFI_HII_PACKAGE_LIST_HEADER *PackageList;
-
- //
- // Locate required Hii relative protocols
- //
- Status = gBS->LocateProtocol (
- &gEfiHiiDatabaseProtocolGuid,
- NULL,
- (VOID **) &mHiiDatabase
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->LocateProtocol (
- &gEfiHiiStringProtocolGuid,
- NULL,
- (VOID **) &mHiiString
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->LocateProtocol (
- &gEfiHiiConfigRoutingProtocolGuid,
- NULL,
- (VOID **) &mHiiConfigRouting
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Publish our HII data
- //
- Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);
- ASSERT_EFI_ERROR (Status);
-
- PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
- ASSERT (PackageList != NULL);
- Status = mHiiDatabase->NewPackageList (
- mHiiDatabase,
- PackageList,
- HiiDriverHandle,
- &gHiiHandle
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Initialize Driver private data
- //
- gFirstIn = TRUE;
- BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
- ASSERT (BannerData != NULL);
-
- //
- // Install FormBrowser2 protocol
- //
- mPrivateData.Handle = NULL;
- Status = gBS->InstallProtocolInterface (
- &mPrivateData.Handle,
- &gEfiFormBrowser2ProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mPrivateData.FormBrowser2
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Install Print protocol
- //
- Status = gBS->InstallProtocolInterface (
- &mPrivateData.Handle,
- &gEfiPrintProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mPrivateData.Print
- );
-
- return Status;
-}
-
-
-/**
- Create a new string in HII Package List.
-
- @param String The String to be added
- @param HiiHandle The package list in the HII database to insert the
- specified string.
-
- @return The output string.
-
-**/
-EFI_STRING_ID
-NewString (
- IN CHAR16 *String,
- IN EFI_HII_HANDLE HiiHandle
- )
-{
- EFI_STRING_ID StringId;
- EFI_STATUS Status;
-
- StringId = 0;
- Status = HiiLibNewString (HiiHandle, &StringId, String);
- ASSERT_EFI_ERROR (Status);
-
- return StringId;
-}
-
-
-/**
- Delete a string from HII Package List.
-
- @param StringId Id of the string in HII database.
- @param HiiHandle The HII package list handle.
-
- @retval EFI_SUCCESS The string was deleted successfully.
-
-**/
-EFI_STATUS
-DeleteString (
- IN EFI_STRING_ID StringId,
- IN EFI_HII_HANDLE HiiHandle
- )
-{
- CHAR16 NullChar;
-
- NullChar = CHAR_NULL;
- return HiiLibSetString (HiiHandle, StringId, &NullChar);
-}
-
-
-/**
- Get the string based on the StringId and HII Package List Handle.
-
- @param Token The String's ID.
- @param HiiHandle The package list in the HII database to search for
- the specified string.
-
- @return The output string.
-
-**/
-CHAR16 *
-GetToken (
- IN EFI_STRING_ID Token,
- IN EFI_HII_HANDLE HiiHandle
- )
-{
- EFI_STATUS Status;
- CHAR16 *String;
- UINTN BufferLength;
-
- //
- // Set default string size assumption at no more than 256 bytes
- //
- BufferLength = 0x100;
- String = AllocateZeroPool (BufferLength);
- ASSERT (String != NULL);
-
- Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
-
- if (Status == EFI_BUFFER_TOO_SMALL) {
- gBS->FreePool (String);
- String = AllocateZeroPool (BufferLength);
- ASSERT (String != NULL);
-
- Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
- }
- ASSERT_EFI_ERROR (Status);
-
- return String;
-}
-
-
-/**
- Allocate new memory and then copy the Unicode string Source to Destination.
-
- @param Dest Location to copy string
- @param Src String to copy
-
- @return NONE
-
-**/
-VOID
-NewStringCpy (
- IN OUT CHAR16 **Dest,
- IN CHAR16 *Src
- )
-{
- SafeFreePool (*Dest);
- *Dest = AllocateCopyPool (StrSize (Src), Src);
- ASSERT (*Dest != NULL);
-}
-
-
-/**
- Allocate new memory and concatinate Source on the end of Destination.
-
- @param Dest String to added to the end of.
- @param Src String to concatinate.
-
- @return NONE
-
-**/
-VOID
-NewStringCat (
- IN OUT CHAR16 **Dest,
- IN CHAR16 *Src
- )
-{
- CHAR16 *NewString;
- UINTN TmpSize;
-
- if (*Dest == NULL) {
- NewStringCpy (Dest, Src);
- return;
- }
-
- TmpSize = StrSize (*Dest);
- NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
- ASSERT (NewString != NULL);
-
- StrCpy (NewString, *Dest);
- StrCat (NewString, Src);
-
- gBS->FreePool (*Dest);
- *Dest = NewString;
-}
-
-
-/**
- Synchronize Storage's Edit copy to Shadow copy.
-
- @param Storage The Storage to be synchronized.
-
- @return NONE
-
-**/
-VOID
-SynchronizeStorage (
- IN FORMSET_STORAGE *Storage
- )
-{
- LIST_ENTRY *Link;
- NAME_VALUE_NODE *Node;
-
- switch (Storage->Type) {
- case EFI_HII_VARSTORE_BUFFER:
- CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
- break;
-
- case EFI_HII_VARSTORE_NAME_VALUE:
- Link = GetFirstNode (&Storage->NameValueListHead);
- while (!IsNull (&Storage->NameValueListHead, Link)) {
- Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
- NewStringCpy (&Node->Value, Node->EditValue);
-
- Link = GetNextNode (&Storage->NameValueListHead, Link);
- }
- break;
-
- case EFI_HII_VARSTORE_EFI_VARIABLE:
- default:
- break;
- }
-}
-
-
-/**
- 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
- )
-{
- LIST_ENTRY *Link;
- NAME_VALUE_NODE *Node;
-
- *Value = NULL;
-
- Link = GetFirstNode (&Storage->NameValueListHead);
- while (!IsNull (&Storage->NameValueListHead, Link)) {
- Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
- if (StrCmp (Name, Node->Name) == 0) {
- NewStringCpy (Value, Node->EditValue);
- return EFI_SUCCESS;
- }
-
- Link = GetNextNode (&Storage->NameValueListHead, Link);
- }
-
- return EFI_NOT_FOUND;
-}
-
-
-/**
- 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
- )
-{
- LIST_ENTRY *Link;
- NAME_VALUE_NODE *Node;
-
- Link = GetFirstNode (&Storage->NameValueListHead);
- while (!IsNull (&Storage->NameValueListHead, Link)) {
- Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
- if (StrCmp (Name, Node->Name) == 0) {
- SafeFreePool (Node->EditValue);
- Node->EditValue = AllocateCopyPool (StrSize (Value), Value);
- ASSERT (Node->EditValue != NULL);
- return EFI_SUCCESS;
- }
-
- Link = GetNextNode (&Storage->NameValueListHead, Link);
- }
-
- return EFI_NOT_FOUND;
-}
-
-
-/**
- Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
-
- @param Storage The Storage to be conveted.
- @param ConfigResp The returned <ConfigResp>.
-
- @retval EFI_SUCCESS Convert success.
- @retval EFI_INVALID_PARAMETER Incorrect storage type.
-
-**/
-EFI_STATUS
-StorageToConfigResp (
- IN FORMSET_STORAGE *Storage,
- IN CHAR16 **ConfigResp
- )
-{
- EFI_STATUS Status;
- EFI_STRING Progress;
- LIST_ENTRY *Link;
- NAME_VALUE_NODE *Node;
-
- Status = EFI_SUCCESS;
-
- switch (Storage->Type) {
- case EFI_HII_VARSTORE_BUFFER:
- Status = mHiiConfigRouting->BlockToConfig (
- mHiiConfigRouting,
- Storage->ConfigRequest,
- Storage->EditBuffer,
- Storage->Size,
- ConfigResp,
- &Progress
- );
- break;
-
- case EFI_HII_VARSTORE_NAME_VALUE:
- *ConfigResp = NULL;
- NewStringCat (ConfigResp, Storage->ConfigHdr);
-
- Link = GetFirstNode (&Storage->NameValueListHead);
- while (!IsNull (&Storage->NameValueListHead, Link)) {
- Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
- NewStringCat (ConfigResp, L"&");
- NewStringCat (ConfigResp, Node->Name);
- NewStringCat (ConfigResp, L"=");
- NewStringCat (ConfigResp, Node->EditValue);
-
- Link = GetNextNode (&Storage->NameValueListHead, Link);
- }
- break;
-
- case EFI_HII_VARSTORE_EFI_VARIABLE:
- default:
- Status = EFI_INVALID_PARAMETER;
- break;
- }
-
- return Status;
-}
-
-
-/**
- Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
-
- @param Storage The Storage to receive the settings.
- @param ConfigResp The <ConfigResp> to be converted.
-
- @retval EFI_SUCCESS Convert success.
- @retval EFI_INVALID_PARAMETER Incorrect storage type.
-
-**/
-EFI_STATUS
-ConfigRespToStorage (
- IN FORMSET_STORAGE *Storage,
- IN CHAR16 *ConfigResp
- )
-{
- EFI_STATUS Status;
- EFI_STRING Progress;
- UINTN BufferSize;
- CHAR16 *StrPtr;
- CHAR16 *Name;
- CHAR16 *Value;
-
- Status = EFI_SUCCESS;
-
- switch (Storage->Type) {
- case EFI_HII_VARSTORE_BUFFER:
- BufferSize = Storage->Size;
- Status = mHiiConfigRouting->ConfigToBlock (
- mHiiConfigRouting,
- ConfigResp,
- Storage->EditBuffer,
- &BufferSize,
- &Progress
- );
- break;
-
- case EFI_HII_VARSTORE_NAME_VALUE:
- StrPtr = StrStr (ConfigResp, L"&");
- while (StrPtr != NULL) {
- //
- // Skip '&'
- //
- StrPtr = StrPtr + 1;
- Name = StrPtr;
- StrPtr = StrStr (StrPtr, L"=");
- if (StrPtr == NULL) {
- break;
- }
- *StrPtr = 0;
-
- //
- // Skip '='
- //
- StrPtr = StrPtr + 1;
- Value = StrPtr;
- StrPtr = StrStr (StrPtr, L"&");
- if (StrPtr != NULL) {
- *StrPtr = 0;
- }
- SetValueByName (Storage, Name, Value);
- }
- break;
-
- case EFI_HII_VARSTORE_EFI_VARIABLE:
- default:
- Status = EFI_INVALID_PARAMETER;
- break;
- }
-
- return Status;
-}
-
-
-/**
- Get Question's current Value.
-
- @param FormSet FormSet data structure.
- @param Form Form data structure.
- @param Question Question to be initialized.
- @param Cached TRUE: get from Edit copy FALSE: get from original
- Storage
-
- @retval EFI_SUCCESS The function completed successfully.
-
-**/
-EFI_STATUS
-GetQuestionValue (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN OUT FORM_BROWSER_STATEMENT *Question,
- IN BOOLEAN Cached
- )
-{
- EFI_STATUS Status;
- BOOLEAN Enabled;
- BOOLEAN Pending;
- UINT8 *Dst;
- UINTN StorageWidth;
- EFI_TIME EfiTime;
- FORMSET_STORAGE *Storage;
- EFI_IFR_TYPE_VALUE *QuestionValue;
- CHAR16 *ConfigRequest;
- CHAR16 *Progress;
- CHAR16 *Result;
- CHAR16 *Value;
- UINTN Length;
- BOOLEAN IsBufferStorage;
- BOOLEAN IsString;
-
- Status = EFI_SUCCESS;
-
- //
- // Statement don't have storage, skip them
- //
- if (Question->QuestionId == 0) {
- return Status;
- }
-
- //
- // Question value is provided by an Expression, evaluate it
- //
- if (Question->ValueExpression != NULL) {
- Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
- if (!EFI_ERROR (Status)) {
- CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));
- }
- return Status;
- }
-
- //
- // Question value is provided by RTC
- //
- Storage = Question->Storage;
- QuestionValue = &Question->HiiValue.Value;
- 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->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:
- //
- // For date/time without storage
- //
- return EFI_SUCCESS;
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (Question->Operand == EFI_IFR_DATE_OP) {
- QuestionValue->date.Year = EfiTime.Year;
- QuestionValue->date.Month = EfiTime.Month;
- QuestionValue->date.Day = EfiTime.Day;
- } else {
- QuestionValue->time.Hour = EfiTime.Hour;
- QuestionValue->time.Minute = EfiTime.Minute;
- QuestionValue->time.Second = EfiTime.Second;
- }
- }
-
- return EFI_SUCCESS;
- }
-
- //
- // Question value is provided by EFI variable
- //
- StorageWidth = Question->StorageWidth;
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
- if (Question->BufferValue != NULL) {
- Dst = Question->BufferValue;
- } else {
- Dst = (UINT8 *) QuestionValue;
- }
-
- Status = gRT->GetVariable (
- Question->VariableName,
- &Storage->Guid,
- NULL,
- &StorageWidth,
- Dst
- );
- //
- // Always return success, even this EFI variable doesn't exist
- //
- return EFI_SUCCESS;
- }
-
- //
- // Question Value is provided by Buffer Storage or NameValue Storage
- //
- if (Question->BufferValue != NULL) {
- //
- // This Question is password or orderedlist
- //
- Dst = Question->BufferValue;
- } else {
- //
- // Other type of Questions
- //
- Dst = (UINT8 *) &Question->HiiValue.Value;
- }
-
- IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
- IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
- if (Cached) {
- if (IsBufferStorage) {
- //
- // Copy from storage Edit buffer
- //
- CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
- } else {
- Status = GetValueByName (Storage, Question->VariableName, &Value);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (IsString) {
- //
- // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
- //
- Length = StorageWidth + sizeof (CHAR16);
- Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
- } else {
- Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
- }
-
- gBS->FreePool (Value);
- }
- } else {
- //
- // Request current settings from Configuration Driver
- //
- if (FormSet->ConfigAccess == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // <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 = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
- ASSERT (ConfigRequest != NULL);
-
- StrCpy (ConfigRequest, Storage->ConfigHdr);
- if (IsBufferStorage) {
- StrCat (ConfigRequest, Question->BlockName);
- } else {
- StrCat (ConfigRequest, L"&");
- StrCat (ConfigRequest, Question->VariableName);
- }
-
- Status = FormSet->ConfigAccess->ExtractConfig (
- FormSet->ConfigAccess,
- ConfigRequest,
- &Progress,
- &Result
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Skip <ConfigRequest>
- //
- Value = Result + Length;
- if (IsBufferStorage) {
- //
- // Skip "&VALUE"
- //
- Value = Value + 6;
- }
- if (*Value != '=') {
- gBS->FreePool (Result);
- return EFI_NOT_FOUND;
- }
- //
- // Skip '=', point to value
- //
- Value = Value + 1;
- if (!IsBufferStorage && IsString) {
- //
- // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
- //
- Length = StorageWidth + sizeof (CHAR16);
- Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
- } else {
- Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
- if (EFI_ERROR (Status)) {
- gBS->FreePool (Result);
- return Status;
- }
- }
-
- //
- // Synchronize Edit Buffer
- //
- if (IsBufferStorage) {
- CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
- } else {
- SetValueByName (Storage, Question->VariableName, Value);
- }
- gBS->FreePool (Result);
- }
-
- return Status;
-}
-
-
-/**
- Save Question Value to edit copy(cached) or Storage(uncached).
-
- @param FormSet FormSet data structure.
- @param Form Form data structure.
- @param Question Pointer to the Question.
- @param Cached TRUE: set to Edit copy FALSE: set to original
- Storage
-
- @retval EFI_SUCCESS The function completed successfully.
-
-**/
-EFI_STATUS
-SetQuestionValue (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN OUT FORM_BROWSER_STATEMENT *Question,
- IN BOOLEAN Cached
- )
-{
- EFI_STATUS Status;
- BOOLEAN Enabled;
- BOOLEAN Pending;
- UINT8 *Src;
- EFI_TIME EfiTime;
- UINTN BufferLen;
- UINTN StorageWidth;
- FORMSET_STORAGE *Storage;
- EFI_IFR_TYPE_VALUE *QuestionValue;
- CHAR16 *ConfigResp;
- CHAR16 *Progress;
- CHAR16 *Value;
- UINTN Length;
- BOOLEAN IsBufferStorage;
- BOOLEAN IsString;
-
- Status = EFI_SUCCESS;
-
- //
- // Statement don't have storage, skip them
- //
- if (Question->QuestionId == 0) {
- return Status;
- }
-
- //
- // If Question value is provided by an Expression, then it is read only
- //
- if (Question->ValueExpression != NULL) {
- return Status;
- }
-
- //
- // Question value is provided by RTC
- //
- Storage = Question->Storage;
- QuestionValue = &Question->HiiValue.Value;
- 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->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:
- //
- // For date/time without storage
- //
- return EFI_SUCCESS;
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (Question->Operand == EFI_IFR_DATE_OP) {
- EfiTime.Year = QuestionValue->date.Year;
- EfiTime.Month = QuestionValue->date.Month;
- EfiTime.Day = QuestionValue->date.Day;
- } else {
- EfiTime.Hour = QuestionValue->time.Hour;
- EfiTime.Minute = QuestionValue->time.Minute;
- EfiTime.Second = QuestionValue->time.Second;
- }
-
- if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
- Status = gRT->SetTime (&EfiTime);
- } else {
- Status = gRT->SetWakeupTime (TRUE, &EfiTime);
- }
- }
-
- return Status;
- }
-
- //
- // Question value is provided by EFI variable
- //
- StorageWidth = Question->StorageWidth;
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
- if (Question->BufferValue != NULL) {
- Src = Question->BufferValue;
- } else {
- Src = (UINT8 *) QuestionValue;
- }
-
- Status = gRT->SetVariable (
- Question->VariableName,
- &Storage->Guid,
- Storage->Attributes,
- StorageWidth,
- Src
- );
- return Status;
- }
-
- //
- // Question Value is provided by Buffer Storage or NameValue Storage
- //
- if (Question->BufferValue != NULL) {
- Src = Question->BufferValue;
- } else {
- Src = (UINT8 *) &Question->HiiValue.Value;
- }
-
- IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
- IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
- if (IsBufferStorage) {
- //
- // Copy to storage edit buffer
- //
- CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
- } else {
- if (IsString) {
- //
- // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
- //
- Value = NULL;
- BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
- Value = AllocateZeroPool (BufferLen);
- ASSERT (Value != NULL);
- Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
- ASSERT_EFI_ERROR (Status);
- } else {
- BufferLen = StorageWidth * 2 + 1;
- Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));
- ASSERT (Value != NULL);
- BufToHexString (Value, &BufferLen, Src, StorageWidth);
- ToLower (Value);
- }
-
- Status = SetValueByName (Storage, Question->VariableName, Value);
- gBS->FreePool (Value);
- }
-
- if (!Cached) {
- //
- // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
- // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
- //
- if (IsBufferStorage) {
- Length = StrLen (Question->BlockName) + 7;
- } else {
- Length = StrLen (Question->VariableName) + 2;
- }
- if (!IsBufferStorage && IsString) {
- Length += (StrLen ((CHAR16 *) Src) * 4);
- } else {
- Length += (StorageWidth * 2);
- }
- ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
- ASSERT (ConfigResp != NULL);
-
- StrCpy (ConfigResp, Storage->ConfigHdr);
- if (IsBufferStorage) {
- StrCat (ConfigResp, Question->BlockName);
- StrCat (ConfigResp, L"&VALUE=");
- } else {
- StrCat (ConfigResp, L"&");
- StrCat (ConfigResp, Question->VariableName);
- StrCat (ConfigResp, L"=");
- }
-
- Value = ConfigResp + StrLen (ConfigResp);
- if (!IsBufferStorage && IsString) {
- //
- // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
- //
- BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
- Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
- ASSERT_EFI_ERROR (Status);
- } else {
- BufferLen = StorageWidth * 2 + 1;
- BufToHexString (Value, &BufferLen, Src, StorageWidth);
- ToLower (Value);
- }
-
- //
- // Submit Question Value to Configuration Driver
- //
- if (FormSet->ConfigAccess != NULL) {
- Status = FormSet->ConfigAccess->RouteConfig (
- FormSet->ConfigAccess,
- ConfigResp,
- &Progress
- );
- if (EFI_ERROR (Status)) {
- gBS->FreePool (ConfigResp);
- return Status;
- }
- }
- gBS->FreePool (ConfigResp);
-
- //
- // Synchronize shadow Buffer
- //
- SynchronizeStorage (Storage);
- }
-
- return Status;
-}
-
-
-/**
- Perform inconsistent check for a Form.
-
- @param FormSet FormSet data structure.
- @param Form Form data structure.
- @param Question The Question to be validated.
- @param Type Validation type: InConsistent or NoSubmit
-
- @retval EFI_SUCCESS Form validation pass.
- @retval other Form validation failed.
-
-**/
-EFI_STATUS
-ValidateQuestion (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN FORM_BROWSER_STATEMENT *Question,
- IN UINTN Type
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- LIST_ENTRY *ListHead;
- EFI_STRING PopUp;
- EFI_INPUT_KEY Key;
- FORM_EXPRESSION *Expression;
-
- if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
- ListHead = &Question->InconsistentListHead;
- } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
- ListHead = &Question->NoSubmitListHead;
- } else {
- return EFI_UNSUPPORTED;
- }
-
- Link = GetFirstNode (ListHead);
- while (!IsNull (ListHead, Link)) {
- Expression = FORM_EXPRESSION_FROM_LINK (Link);
-
- //
- // Evaluate the expression
- //
- Status = EvaluateExpression (FormSet, Form, Expression);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (Expression->Result.Value.b) {
- //
- // Condition meet, show up error message
- //
- if (Expression->Error != 0) {
- PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- gBS->FreePool (PopUp);
- }
-
- return EFI_NOT_READY;
- }
-
- Link = GetNextNode (ListHead, Link);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Perform NoSubmit check for a Form.
-
- @param FormSet FormSet data structure.
- @param Form Form data structure.
-
- @retval EFI_SUCCESS Form validation pass.
- @retval other Form validation failed.
-
-**/
-EFI_STATUS
-NoSubmitCheck (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Question;
-
- Link = GetFirstNode (&Form->StatementListHead);
- while (!IsNull (&Form->StatementListHead, Link)) {
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
- Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Link = GetNextNode (&Form->StatementListHead, Link);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Submit a Form.
-
- @param FormSet FormSet data structure.
- @param Form Form data structure.
-
- @retval EFI_SUCCESS The function completed successfully.
-
-**/
-EFI_STATUS
-SubmitForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- EFI_STRING ConfigResp;
- EFI_STRING Progress;
- FORMSET_STORAGE *Storage;
-
- //
- // Validate the Form by NoSubmit check
- //
- Status = NoSubmitCheck (FormSet, Form);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Submit Buffer storage or Name/Value storage
- //
- Link = GetFirstNode (&FormSet->StorageListHead);
- while (!IsNull (&FormSet->StorageListHead, Link)) {
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
- Link = GetNextNode (&FormSet->StorageListHead, Link);
-
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
- continue;
- }
-
- //
- // Skip if there is no RequestElement
- //
- if (Storage->ElementCount == 0) {
- continue;
- }
-
- //
- // Prepare <ConfigResp>
- //
- Status = StorageToConfigResp (Storage, &ConfigResp);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Send <ConfigResp> to Configuration Driver
- //
- if (FormSet->ConfigAccess != NULL) {
- Status = FormSet->ConfigAccess->RouteConfig (
- FormSet->ConfigAccess,
- ConfigResp,
- &Progress
- );
- if (EFI_ERROR (Status)) {
- gBS->FreePool (ConfigResp);
- return Status;
- }
- }
- gBS->FreePool (ConfigResp);
-
- //
- // Config success, update storage shadow Buffer
- //
- SynchronizeStorage (Storage);
- }
-
- gNvUpdateRequired = FALSE;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Reset Question to its default value.
-
- @param FormSet FormSet data structure.
- @param DefaultId The Class of the default.
-
- @retval EFI_SUCCESS Question is reset to default value.
-
-**/
-EFI_STATUS
-GetQuestionDefault (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN FORM_BROWSER_STATEMENT *Question,
- IN UINT16 DefaultId
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- QUESTION_DEFAULT *Default;
- QUESTION_OPTION *Option;
- EFI_HII_VALUE *HiiValue;
- UINT8 Index;
-
- Status = EFI_SUCCESS;
-
- //
- // Statement don't have storage, skip them
- //
- if (Question->QuestionId == 0) {
- return Status;
- }
-
- //
- // There are three ways to specify default value for a Question:
- // 1, use nested EFI_IFR_DEFAULT (highest priority)
- // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
- // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
- //
- HiiValue = &Question->HiiValue;
-
- //
- // EFI_IFR_DEFAULT has highest priority
- //
- if (!IsListEmpty (&Question->DefaultListHead)) {
- Link = GetFirstNode (&Question->DefaultListHead);
- while (!IsNull (&Question->DefaultListHead, Link)) {
- Default = QUESTION_DEFAULT_FROM_LINK (Link);
-
- if (Default->DefaultId == DefaultId) {
- if (Default->ValueExpression != NULL) {
- //
- // Default is provided by an Expression, evaluate it
- //
- Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
- } else {
- //
- // Default value is embedded in EFI_IFR_DEFAULT
- //
- CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
- }
-
- return EFI_SUCCESS;
- }
-
- Link = GetNextNode (&Question->DefaultListHead, Link);
- }
- }
-
- //
- // EFI_ONE_OF_OPTION
- //
- if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
- if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
- //
- // OneOfOption could only provide Standard and Manufacturing default
- //
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- Option = QUESTION_OPTION_FROM_LINK (Link);
-
- if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
- ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
- ) {
- CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
-
- return EFI_SUCCESS;
- }
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- }
- }
-
- //
- // EFI_IFR_CHECKBOX - lowest priority
- //
- if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
- if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
- //
- // Checkbox could only provide Standard and Manufacturing default
- //
- if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
- ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
- ) {
- HiiValue->Value.b = TRUE;
- } else {
- HiiValue->Value.b = FALSE;
- }
-
- return EFI_SUCCESS;
- }
- }
-
- //
- // For Questions without default
- //
- switch (Question->Operand) {
- case EFI_IFR_NUMERIC_OP:
- //
- // Take minimal value as numeric's default value
- //
- HiiValue->Value.u64 = Question->Minimum;
- break;
-
- case EFI_IFR_ONE_OF_OP:
- //
- // Take first oneof option as oneof's default value
- //
- Link = GetFirstNode (&Question->OptionListHead);
- if (!IsNull (&Question->OptionListHead, Link)) {
- Option = QUESTION_OPTION_FROM_LINK (Link);
- CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
- }
- break;
-
- case EFI_IFR_ORDERED_LIST_OP:
- //
- // Take option sequence in IFR as ordered list's default value
- //
- Index = 0;
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- Option = QUESTION_OPTION_FROM_LINK (Link);
-
- Question->BufferValue[Index] = Option->Value.Value.u8;
-
- Index++;
- if (Index >= Question->MaxContainers) {
- break;
- }
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- break;
-
- default:
- Status = EFI_NOT_FOUND;
- break;
- }
-
- return Status;
-}
-
-
-/**
- Reset Questions in a Form to their default value.
-
- @param FormSet FormSet data structure.
- @param Form The Form which to be reset.
- @param DefaultId The Class of the default.
-
- @retval EFI_SUCCESS The function completed successfully.
-
-**/
-EFI_STATUS
-ExtractFormDefault (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN UINT16 DefaultId
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Question;
-
- Link = GetFirstNode (&Form->StatementListHead);
- while (!IsNull (&Form->StatementListHead, Link)) {
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
- Link = GetNextNode (&Form->StatementListHead, Link);
-
- //
- // Reset Question to its default value
- //
- Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- //
- // Synchronize Buffer storage's Edit buffer
- //
- if ((Question->Storage != NULL) &&
- (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
- SetQuestionValue (FormSet, Form, Question, TRUE);
- }
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Initialize Question's Edit copy from Storage.
-
- @param FormSet FormSet data structure.
- @param Form Form data structure.
-
- @retval EFI_SUCCESS The function completed successfully.
-
-**/
-EFI_STATUS
-LoadFormConfig (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Question;
-
- Link = GetFirstNode (&Form->StatementListHead);
- while (!IsNull (&Form->StatementListHead, Link)) {
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
-
- //
- // Initialize local copy of Value for each Question
- //
- Status = GetQuestionValue (FormSet, Form, Question, TRUE);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Link = GetNextNode (&Form->StatementListHead, Link);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Fill storage's edit copy with settings requested from Configuration Driver.
-
- @param FormSet FormSet data structure.
- @param Storage Buffer Storage.
-
- @retval EFI_SUCCESS The function completed successfully.
-
-**/
-EFI_STATUS
-LoadStorage (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORMSET_STORAGE *Storage
- )
-{
- EFI_STATUS Status;
- EFI_STRING Progress;
- EFI_STRING Result;
- CHAR16 *StrPtr;
-
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
- return EFI_SUCCESS;
- }
-
- if (FormSet->ConfigAccess == NULL) {
- return EFI_NOT_FOUND;
- }
-
- if (Storage->ElementCount == 0) {
- //
- // Skip if there is no RequestElement
- //
- return EFI_SUCCESS;
- }
-
- //
- // Request current settings from Configuration Driver
- //
- Status = FormSet->ConfigAccess->ExtractConfig (
- FormSet->ConfigAccess,
- Storage->ConfigRequest,
- &Progress,
- &Result
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Convert Result from <ConfigAltResp> to <ConfigResp>
- //
- StrPtr = StrStr (Result, L"ALTCFG");
- if (StrPtr != NULL) {
- *StrPtr = L'\0';
- }
-
- Status = ConfigRespToStorage (Storage, Result);
- gBS->FreePool (Result);
- return Status;
-}
-
-
-/**
- Get current setting of Questions.
-
- @param FormSet FormSet data structure.
-
- @retval EFI_SUCCESS The function completed successfully.
-
-**/
-EFI_STATUS
-InitializeCurrentSetting (
- IN OUT FORM_BROWSER_FORMSET *FormSet
- )
-{
- LIST_ENTRY *Link;
- FORMSET_STORAGE *Storage;
- FORM_BROWSER_FORM *Form;
- EFI_STATUS Status;
-
- //
- // Extract default from IFR binary
- //
- Link = GetFirstNode (&FormSet->FormListHead);
- while (!IsNull (&FormSet->FormListHead, Link)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
- Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);
-
- Link = GetNextNode (&FormSet->FormListHead, Link);
- }
-
- //
- // Request current settings from Configuration Driver
- //
- Link = GetFirstNode (&FormSet->StorageListHead);
- while (!IsNull (&FormSet->StorageListHead, Link)) {
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
-
- Status = LoadStorage (FormSet, Storage);
-
- //
- // Now Edit Buffer is filled with default values(lower priority) and current
- // settings(higher priority), sychronize it to shadow Buffer
- //
- if (!EFI_ERROR (Status)) {
- SynchronizeStorage (Storage);
- }
-
- Link = GetNextNode (&FormSet->StorageListHead, Link);
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Fetch the Ifr binary data of a FormSet.
-
- @param Handle PackageList Handle
- @param FormSetGuid GUID of a formset. If not specified (NULL or zero
- GUID), take the first FormSet found in package
- list.
- @param BinaryLength The length of the FormSet IFR binary.
- @param BinaryData The buffer designed to receive the FormSet.
-
- @retval EFI_SUCCESS Buffer filled with the requested FormSet.
- BufferLength was updated.
- @retval EFI_INVALID_PARAMETER The handle is unknown.
- @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
- be found with the requested FormId.
-
-**/
-EFI_STATUS
-GetIfrBinaryData (
- IN EFI_HII_HANDLE Handle,
- IN OUT EFI_GUID *FormSetGuid,
- OUT UINTN *BinaryLength,
- OUT UINT8 **BinaryData
- )
-{
- EFI_STATUS Status;
- EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
- UINTN BufferSize;
- UINT8 *Package;
- UINT8 *OpCodeData;
- UINT32 Offset;
- UINT32 Offset2;
- BOOLEAN ReturnDefault;
- UINT32 PackageListLength;
- EFI_HII_PACKAGE_HEADER PackageHeader;
-
- OpCodeData = NULL;
- Package = NULL;
- ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
-
- //
- // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
- //
- if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
- ReturnDefault = TRUE;
- } else {
- ReturnDefault = FALSE;
- }
-
- //
- // Get HII PackageList
- //
- BufferSize = 0;
- HiiPackageList = NULL;
- Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- HiiPackageList = AllocatePool (BufferSize);
- ASSERT (HiiPackageList != NULL);
-
- Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Get Form package from this HII package List
- //
- Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
- Offset2 = 0;
- CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
-
- while (Offset < PackageListLength) {
- Package = ((UINT8 *) HiiPackageList) + Offset;
- CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
-
- if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
- //
- // Search FormSet in this Form Package
- //
- Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
- while (Offset2 < PackageHeader.Length) {
- OpCodeData = Package + Offset2;
-
- if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
- //
- // Check whether return default FormSet
- //
- if (ReturnDefault) {
- break;
- }
-
- //
- // FormSet GUID is specified, check it
- //
- if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
- break;
- }
- }
-
- Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
- }
-
- if (Offset2 < PackageHeader.Length) {
- //
- // Target formset found
- //
- break;
- }
- }
-
- Offset += PackageHeader.Length;
- }
-
- if (Offset >= PackageListLength) {
- //
- // Form package not found in this Package List
- //
- gBS->FreePool (HiiPackageList);
- return EFI_NOT_FOUND;
- }
-
- if (ReturnDefault && FormSetGuid != NULL) {
- //
- // Return the default FormSet GUID
- //
- CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
- }
-
- //
- // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
- // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
- // of the Form Package.
- //
- *BinaryLength = PackageHeader.Length - Offset2;
- *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
-
- gBS->FreePool (HiiPackageList);
-
- if (*BinaryData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Initialize the internal data structure of a FormSet.
-
- @param Handle PackageList Handle
- @param FormSetGuid GUID of a formset. If not specified (NULL or zero
- GUID), take the first FormSet found in package
- list.
- @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
-InitializeFormSet (
- IN EFI_HII_HANDLE Handle,
- IN OUT EFI_GUID *FormSetGuid,
- OUT FORM_BROWSER_FORMSET *FormSet
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE DriverHandle;
- UINT16 Index;
-
- Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- FormSet->HiiHandle = Handle;
- CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
-
- //
- // Retrieve ConfigAccess Protocol associated with this HiiPackageList
- //
- Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, 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;
- }
-
- //
- // Parse the IFR binary OpCodes
- //
- Status = ParseOpCodes (FormSet);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- gClassOfVfr = FormSet->SubClass;
- if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
- FrontPageHandle = FormSet->HiiHandle;
- }
-
- //
- // Match GUID to find out the function key setting. If match fail, use the default setting.
- //
- for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
- if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
- //
- // Update the function key setting.
- //
- gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
- //
- // Function key prompt can not be displayed if the function key has been disabled.
- //
- if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
- gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
- }
-
- if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
- gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
- }
-
- if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
- gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
- }
-
- if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
- gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
- }
- }
- }
-
- return Status;
-}
+/** @file
+Entry and initialization module for the browser.
+
+Copyright (c) 2007 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Setup.h"
+#include "Ui.h"
+
+
+SETUP_DRIVER_PRIVATE_DATA mPrivateData = {
+ SETUP_DRIVER_SIGNATURE,
+ NULL,
+ {
+ SendForm,
+ BrowserCallback
+ },
+ {
+ UnicodeVSPrint
+ }
+};
+
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+EFI_HII_STRING_PROTOCOL *mHiiString;
+EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
+
+BANNER_DATA *BannerData;
+EFI_HII_HANDLE FrontPageHandle;
+UINTN gClassOfVfr;
+UINTN gFunctionKeySetting;
+BOOLEAN gResetRequired;
+BOOLEAN gNvUpdateRequired;
+EFI_HII_HANDLE gHiiHandle;
+BOOLEAN gFirstIn;
+UINT16 gDirection;
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+BOOLEAN gUpArrow;
+BOOLEAN gDownArrow;
+
+//
+// Browser Global Strings
+//
+CHAR16 *gFunctionOneString;
+CHAR16 *gFunctionTwoString;
+CHAR16 *gFunctionNineString;
+CHAR16 *gFunctionTenString;
+CHAR16 *gEnterString;
+CHAR16 *gEnterCommitString;
+CHAR16 *gEscapeString;
+CHAR16 *gSaveFailed;
+CHAR16 *gMoveHighlight;
+CHAR16 *gMakeSelection;
+CHAR16 *gDecNumericInput;
+CHAR16 *gHexNumericInput;
+CHAR16 *gToggleCheckBox;
+CHAR16 *gPromptForData;
+CHAR16 *gPromptForPassword;
+CHAR16 *gPromptForNewPassword;
+CHAR16 *gConfirmPassword;
+CHAR16 *gConfirmError;
+CHAR16 *gPassowordInvalid;
+CHAR16 *gPressEnter;
+CHAR16 *gEmptyString;
+CHAR16 *gAreYouSure;
+CHAR16 *gYesResponse;
+CHAR16 *gNoResponse;
+CHAR16 *gMiniString;
+CHAR16 *gPlusString;
+CHAR16 *gMinusString;
+CHAR16 *gAdjustNumber;
+
+CHAR16 gPromptBlockWidth;
+CHAR16 gOptionBlockWidth;
+CHAR16 gHelpBlockWidth;
+
+EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
+EFI_GUID gSetupBrowserGuid = {
+ 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
+};
+
+FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
+ //
+ // Boot Manager
+ //
+ {
+ {
+ 0x847bc3fe,
+ 0xb974,
+ 0x446d,
+ {
+ 0x94,
+ 0x49,
+ 0x5a,
+ 0xd5,
+ 0x41,
+ 0x2e,
+ 0x99,
+ 0x3b
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // Device Manager
+ //
+ {
+ {
+ 0x3ebfa8e6,
+ 0x511d,
+ 0x4b5b,
+ {
+ 0xa9,
+ 0x5f,
+ 0xfb,
+ 0x38,
+ 0x26,
+ 0xf,
+ 0x1c,
+ 0x27
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // BMM FormSet.
+ //
+ {
+ {
+ 0x642237c7,
+ 0x35d4,
+ 0x472d,
+ {
+ 0x83,
+ 0x65,
+ 0x12,
+ 0xe0,
+ 0xcc,
+ 0xf2,
+ 0x7a,
+ 0x22
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+ //
+ // BMM File Explorer FormSet.
+ //
+ {
+ {
+ 0x1f2d63e1,
+ 0xfebd,
+ 0x4dc7,
+ {
+ 0x9c,
+ 0xc5,
+ 0xba,
+ 0x2b,
+ 0x1c,
+ 0xef,
+ 0x9c,
+ 0x5b
+ }
+ },
+ NONE_FUNCTION_KEY_SETTING
+ },
+};
+
+/**
+ This is the routine which an external caller uses to direct the browser
+ where to obtain it's information.
+
+
+ @param This The Form Browser protocol instanse.
+ @param Handles A pointer to an array of Handles. If HandleCount > 1 we
+ display a list of the formsets for the handles specified.
+ @param HandleCount The number of Handles specified in Handle.
+ @param FormSetGuid This field points to the EFI_GUID which must match the Guid
+ field in the EFI_IFR_FORM_SET op-code for the specified
+ forms-based package. If FormSetGuid is NULL, then this
+ function will display the first found forms package.
+ @param FormId This field specifies which EFI_IFR_FORM to render as the first
+ displayable page. If this field has a value of 0x0000, then
+ the forms browser will render the specified forms in their encoded order.
+ ScreenDimenions - This allows the browser to be called so that it occupies a
+ portion of the physical screen instead of dynamically determining the screen dimensions.
+ ActionRequest - Points to the action recommended by the form.
+ @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
+ characters.
+ @param ActionRequest Points to the action recommended by the form.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_NOT_FOUND No valid forms could be found to display.
+
+**/
+EFI_STATUS
+EFIAPI
+SendForm (
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN EFI_HII_HANDLE *Handles,
+ IN UINTN HandleCount,
+ IN EFI_GUID *FormSetGuid, OPTIONAL
+ IN UINT16 FormId, OPTIONAL
+ IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UI_MENU_SELECTION *Selection;
+ UINTN Index;
+ FORM_BROWSER_FORMSET *FormSet;
+
+ Status = EFI_SUCCESS;
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ //
+ // Seed the dimensions in the global
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &gScreenDimensions.RightColumn,
+ &gScreenDimensions.BottomRow
+ );
+
+ if (ScreenDimensions != NULL) {
+ //
+ // Check local dimension vs. global dimension.
+ //
+ if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
+ (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Local dimension validation.
+ //
+ if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
+ (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
+ ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
+ (
+ (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
+ SCROLL_ARROW_HEIGHT *
+ 2 +
+ FRONT_PAGE_HEADER_HEIGHT +
+ FOOTER_HEIGHT +
+ 1
+ )
+ ) {
+ CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
+ gHelpBlockWidth = gOptionBlockWidth;
+ gPromptBlockWidth = gOptionBlockWidth;
+
+ //
+ // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
+ //
+ InitializeBrowserStrings ();
+
+ gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
+ gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;
+
+ //
+ // Ensure we are in Text mode
+ //
+ if (gFirstIn) {
+ gFirstIn = FALSE;
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ DisableQuietBoot ();
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
+ ASSERT (Selection != NULL);
+
+ Selection->Handle = Handles[Index];
+ if (FormSetGuid != NULL) {
+ CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
+ Selection->FormId = FormId;
+ }
+
+ do {
+ FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
+ ASSERT (FormSet != NULL);
+
+ //
+ // Initialize internal data structures of FormSet
+ //
+ Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
+ if (EFI_ERROR (Status)) {
+ DestroyFormSet (FormSet);
+ break;
+ }
+ Selection->FormSet = FormSet;
+
+ //
+ // Initialize current settings of Questions in this FormSet
+ //
+ Status = InitializeCurrentSetting (FormSet);
+ if (EFI_ERROR (Status)) {
+ DestroyFormSet (FormSet);
+ break;
+ }
+
+ //
+ // Display this formset
+ //
+ gCurrentSelection = Selection;
+
+ Status = SetupBrowser (Selection);
+
+ gCurrentSelection = NULL;
+ DestroyFormSet (FormSet);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
+
+ gBS->FreePool (Selection);
+ }
+
+ if (ActionRequest != NULL) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ if (gResetRequired) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;
+ }
+ }
+
+ FreeBrowserStrings ();
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ return Status;
+}
+
+
+/**
+ This function is called by a callback handler to retrieve uncommitted state
+ data from the browser.
+
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
+ instance.
+ @param ResultsDataSize A pointer to the size of the buffer associated
+ with ResultsData.
+ @param ResultsData A string returned from an IFR browser or
+ equivalent. The results string will have no
+ routing information in them.
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve
+ (if RetrieveData = TRUE) data from the uncommitted
+ browser state information or set (if RetrieveData
+ = FALSE) data in the uncommitted browser state
+ information.
+ @param VariableGuid An optional field to indicate the target variable
+ GUID name to use.
+ @param VariableName An optional field to indicate the target
+ human-readable variable name.
+
+ @retval EFI_SUCCESS The results have been distributed or are awaiting
+ distribution.
+ @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
+ contain the results data.
+
+**/
+EFI_STATUS
+EFIAPI
+BrowserCallback (
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN OUT UINTN *ResultsDataSize,
+ IN OUT EFI_STRING ResultsData,
+ IN BOOLEAN RetrieveData,
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL
+ IN CONST CHAR16 *VariableName OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORMSET_STORAGE *Storage;
+ FORM_BROWSER_FORMSET *FormSet;
+ BOOLEAN Found;
+ CHAR16 *ConfigResp;
+ CHAR16 *StrPtr;
+ UINTN BufferSize;
+ UINTN TmpSize;
+
+ if (ResultsDataSize == NULL || ResultsData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (gCurrentSelection == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Storage = NULL;
+ ConfigResp = NULL;
+ FormSet = gCurrentSelection->FormSet;
+
+ //
+ // Find target storage
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ if (IsNull (&FormSet->StorageListHead, Link)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (VariableGuid != NULL) {
+ //
+ // Try to find target storage
+ //
+ Found = FALSE;
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+ if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+ //
+ // Buffer storage require both GUID and Name
+ //
+ if (VariableName == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
+ continue;
+ }
+ }
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+ } else {
+ //
+ // GUID/Name is not specified, take the first storage in FormSet
+ //
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ }
+
+ if (RetrieveData) {
+ //
+ // Skip if there is no RequestElement
+ //
+ if (Storage->ElementCount == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Generate <ConfigResp>
+ //
+ Status = StorageToConfigResp (Storage, &ConfigResp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Skip <ConfigHdr> and '&' to point to <ConfigBody>
+ //
+ StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
+
+ BufferSize = StrSize (StrPtr);
+ if (*ResultsDataSize < BufferSize) {
+ *ResultsDataSize = BufferSize;
+
+ gBS->FreePool (ConfigResp);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *ResultsDataSize = BufferSize;
+ CopyMem (ResultsData, StrPtr, BufferSize);
+
+ gBS->FreePool (ConfigResp);
+ } else {
+ //
+ // Prepare <ConfigResp>
+ //
+ TmpSize = StrLen (ResultsData);
+ BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
+ ConfigResp = AllocateZeroPool (BufferSize);
+ ASSERT (ConfigResp != NULL);
+
+ StrCpy (ConfigResp, Storage->ConfigHdr);
+ StrCat (ConfigResp, L"&");
+ StrCat (ConfigResp, ResultsData);
+
+ //
+ // Update Browser uncommited data
+ //
+ Status = ConfigRespToStorage (Storage, ConfigResp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Setup Browser driver.
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
+ @return Other value if failed to initialize the Setup Browser module.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeSetup (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE HiiDriverHandle;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Locate required Hii relative protocols
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **) &mHiiDatabase
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiStringProtocolGuid,
+ NULL,
+ (VOID **) &mHiiString
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **) &mHiiConfigRouting
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);
+ ASSERT (PackageList != NULL);
+ Status = mHiiDatabase->NewPackageList (
+ mHiiDatabase,
+ PackageList,
+ HiiDriverHandle,
+ &gHiiHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Driver private data
+ //
+ gFirstIn = TRUE;
+ BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
+ ASSERT (BannerData != NULL);
+
+ //
+ // Install FormBrowser2 protocol
+ //
+ mPrivateData.Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &mPrivateData.Handle,
+ &gEfiFormBrowser2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.FormBrowser2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Print protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mPrivateData.Handle,
+ &gEfiPrintProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.Print
+ );
+
+ return Status;
+}
+
+
+/**
+ Create a new string in HII Package List.
+
+ @param String The String to be added
+ @param HiiHandle The package list in the HII database to insert the
+ specified string.
+
+ @return The output string.
+
+**/
+EFI_STRING_ID
+NewString (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STRING_ID StringId;
+ EFI_STATUS Status;
+
+ StringId = 0;
+ Status = HiiLibNewString (HiiHandle, &StringId, String);
+ ASSERT_EFI_ERROR (Status);
+
+ return StringId;
+}
+
+
+/**
+ Delete a string from HII Package List.
+
+ @param StringId Id of the string in HII database.
+ @param HiiHandle The HII package list handle.
+
+ @retval EFI_SUCCESS The string was deleted successfully.
+
+**/
+EFI_STATUS
+DeleteString (
+ IN EFI_STRING_ID StringId,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ CHAR16 NullChar;
+
+ NullChar = CHAR_NULL;
+ return HiiLibSetString (HiiHandle, StringId, &NullChar);
+}
+
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param Token The String's ID.
+ @param HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *String;
+ UINTN BufferLength;
+
+ //
+ // Set default string size assumption at no more than 256 bytes
+ //
+ BufferLength = 0x100;
+ String = AllocateZeroPool (BufferLength);
+ ASSERT (String != NULL);
+
+ Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ gBS->FreePool (String);
+ String = AllocateZeroPool (BufferLength);
+ ASSERT (String != NULL);
+
+ Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ return String;
+}
+
+
+/**
+ Allocate new memory and then copy the Unicode string Source to Destination.
+
+ @param Dest Location to copy string
+ @param Src String to copy
+
+**/
+VOID
+NewStringCpy (
+ IN OUT CHAR16 **Dest,
+ IN CHAR16 *Src
+ )
+{
+ SafeFreePool (*Dest);
+ *Dest = AllocateCopyPool (StrSize (Src), Src);
+ ASSERT (*Dest != NULL);
+}
+
+
+/**
+ Allocate new memory and concatinate Source on the end of Destination.
+
+ @param Dest String to added to the end of.
+ @param Src String to concatinate.
+
+**/
+VOID
+NewStringCat (
+ IN OUT CHAR16 **Dest,
+ IN CHAR16 *Src
+ )
+{
+ CHAR16 *NewString;
+ UINTN TmpSize;
+
+ if (*Dest == NULL) {
+ NewStringCpy (Dest, Src);
+ return;
+ }
+
+ TmpSize = StrSize (*Dest);
+ NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);
+ ASSERT (NewString != NULL);
+
+ StrCpy (NewString, *Dest);
+ StrCat (NewString, Src);
+
+ gBS->FreePool (*Dest);
+ *Dest = NewString;
+}
+
+
+/**
+ Synchronize Storage's Edit copy to Shadow copy.
+
+ @param Storage The Storage to be synchronized.
+
+**/
+VOID
+SynchronizeStorage (
+ IN FORMSET_STORAGE *Storage
+ )
+{
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ NewStringCpy (&Node->Value, Node->EditValue);
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ break;
+ }
+}
+
+
+/**
+ 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
+ )
+{
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ *Value = NULL;
+
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrCmp (Name, Node->Name) == 0) {
+ NewStringCpy (Value, Node->EditValue);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ 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
+ )
+{
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ if (StrCmp (Name, Node->Name) == 0) {
+ SafeFreePool (Node->EditValue);
+ Node->EditValue = AllocateCopyPool (StrSize (Value), Value);
+ ASSERT (Node->EditValue != NULL);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
+
+ @param Storage The Storage to be conveted.
+ @param ConfigResp The returned <ConfigResp>.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+StorageToConfigResp (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 **ConfigResp
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ LIST_ENTRY *Link;
+ NAME_VALUE_NODE *Node;
+
+ Status = EFI_SUCCESS;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ Status = mHiiConfigRouting->BlockToConfig (
+ mHiiConfigRouting,
+ Storage->ConfigRequest,
+ Storage->EditBuffer,
+ Storage->Size,
+ ConfigResp,
+ &Progress
+ );
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ *ConfigResp = NULL;
+ NewStringCat (ConfigResp, Storage->ConfigHdr);
+
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+
+ NewStringCat (ConfigResp, L"&");
+ NewStringCat (ConfigResp, Node->Name);
+ NewStringCat (ConfigResp, L"=");
+ NewStringCat (ConfigResp, Node->EditValue);
+
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+ }
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
+
+ @param Storage The Storage to receive the settings.
+ @param ConfigResp The <ConfigResp> to be converted.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+ConfigRespToStorage (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 *ConfigResp
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ UINTN BufferSize;
+ CHAR16 *StrPtr;
+ CHAR16 *Name;
+ CHAR16 *Value;
+
+ Status = EFI_SUCCESS;
+
+ switch (Storage->Type) {
+ case EFI_HII_VARSTORE_BUFFER:
+ BufferSize = Storage->Size;
+ Status = mHiiConfigRouting->ConfigToBlock (
+ mHiiConfigRouting,
+ ConfigResp,
+ Storage->EditBuffer,
+ &BufferSize,
+ &Progress
+ );
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ StrPtr = StrStr (ConfigResp, L"&");
+ while (StrPtr != NULL) {
+ //
+ // Skip '&'
+ //
+ StrPtr = StrPtr + 1;
+ Name = StrPtr;
+ StrPtr = StrStr (StrPtr, L"=");
+ if (StrPtr == NULL) {
+ break;
+ }
+ *StrPtr = 0;
+
+ //
+ // Skip '='
+ //
+ StrPtr = StrPtr + 1;
+ Value = StrPtr;
+ StrPtr = StrStr (StrPtr, L"&");
+ if (StrPtr != NULL) {
+ *StrPtr = 0;
+ }
+ SetValueByName (Storage, Name, Value);
+ }
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Get Question's current Value.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Question to be initialized.
+ @param Cached TRUE: get from Edit copy FALSE: get from original
+ Storage
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetQuestionValue (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN BOOLEAN Cached
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Enabled;
+ BOOLEAN Pending;
+ UINT8 *Dst;
+ UINTN StorageWidth;
+ EFI_TIME EfiTime;
+ FORMSET_STORAGE *Storage;
+ EFI_IFR_TYPE_VALUE *QuestionValue;
+ CHAR16 *ConfigRequest;
+ CHAR16 *Progress;
+ CHAR16 *Result;
+ CHAR16 *Value;
+ UINTN Length;
+ BOOLEAN IsBufferStorage;
+ BOOLEAN IsString;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ return Status;
+ }
+
+ //
+ // Question value is provided by an Expression, evaluate it
+ //
+ if (Question->ValueExpression != NULL) {
+ Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));
+ }
+ return Status;
+ }
+
+ //
+ // Question value is provided by RTC
+ //
+ Storage = Question->Storage;
+ QuestionValue = &Question->HiiValue.Value;
+ 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->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:
+ //
+ // For date/time without storage
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ QuestionValue->date.Year = EfiTime.Year;
+ QuestionValue->date.Month = EfiTime.Month;
+ QuestionValue->date.Day = EfiTime.Day;
+ } else {
+ QuestionValue->time.Hour = EfiTime.Hour;
+ QuestionValue->time.Minute = EfiTime.Minute;
+ QuestionValue->time.Second = EfiTime.Second;
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Question value is provided by EFI variable
+ //
+ StorageWidth = Question->StorageWidth;
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ if (Question->BufferValue != NULL) {
+ Dst = Question->BufferValue;
+ } else {
+ Dst = (UINT8 *) QuestionValue;
+ }
+
+ Status = gRT->GetVariable (
+ Question->VariableName,
+ &Storage->Guid,
+ NULL,
+ &StorageWidth,
+ Dst
+ );
+ //
+ // Always return success, even this EFI variable doesn't exist
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Question Value is provided by Buffer Storage or NameValue Storage
+ //
+ if (Question->BufferValue != NULL) {
+ //
+ // This Question is password or orderedlist
+ //
+ Dst = Question->BufferValue;
+ } else {
+ //
+ // Other type of Questions
+ //
+ Dst = (UINT8 *) &Question->HiiValue.Value;
+ }
+
+ IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
+ IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
+ if (Cached) {
+ if (IsBufferStorage) {
+ //
+ // Copy from storage Edit buffer
+ //
+ CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);
+ } else {
+ Status = GetValueByName (Storage, Question->VariableName, &Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (IsString) {
+ //
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
+ //
+ Length = StorageWidth + sizeof (CHAR16);
+ Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
+ } else {
+ Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
+ }
+
+ gBS->FreePool (Value);
+ }
+ } else {
+ //
+ // Request current settings from Configuration Driver
+ //
+ if (FormSet->ConfigAccess == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // <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 = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
+ ASSERT (ConfigRequest != NULL);
+
+ StrCpy (ConfigRequest, Storage->ConfigHdr);
+ if (IsBufferStorage) {
+ StrCat (ConfigRequest, Question->BlockName);
+ } else {
+ StrCat (ConfigRequest, L"&");
+ StrCat (ConfigRequest, Question->VariableName);
+ }
+
+ Status = FormSet->ConfigAccess->ExtractConfig (
+ FormSet->ConfigAccess,
+ ConfigRequest,
+ &Progress,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Skip <ConfigRequest>
+ //
+ Value = Result + Length;
+ if (IsBufferStorage) {
+ //
+ // Skip "&VALUE"
+ //
+ Value = Value + 6;
+ }
+ if (*Value != '=') {
+ gBS->FreePool (Result);
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Skip '=', point to value
+ //
+ Value = Value + 1;
+ if (!IsBufferStorage && IsString) {
+ //
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
+ //
+ Length = StorageWidth + sizeof (CHAR16);
+ Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);
+ } else {
+ Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Result);
+ return Status;
+ }
+ }
+
+ //
+ // Synchronize Edit Buffer
+ //
+ if (IsBufferStorage) {
+ CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
+ } else {
+ SetValueByName (Storage, Question->VariableName, Value);
+ }
+ gBS->FreePool (Result);
+ }
+
+ return Status;
+}
+
+
+/**
+ Save Question Value to edit copy(cached) or Storage(uncached).
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Pointer to the Question.
+ @param Cached TRUE: set to Edit copy FALSE: set to original
+ Storage
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+SetQuestionValue (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN BOOLEAN Cached
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Enabled;
+ BOOLEAN Pending;
+ UINT8 *Src;
+ EFI_TIME EfiTime;
+ UINTN BufferLen;
+ UINTN StorageWidth;
+ FORMSET_STORAGE *Storage;
+ EFI_IFR_TYPE_VALUE *QuestionValue;
+ CHAR16 *ConfigResp;
+ CHAR16 *Progress;
+ CHAR16 *Value;
+ UINTN Length;
+ BOOLEAN IsBufferStorage;
+ BOOLEAN IsString;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ return Status;
+ }
+
+ //
+ // If Question value is provided by an Expression, then it is read only
+ //
+ if (Question->ValueExpression != NULL) {
+ return Status;
+ }
+
+ //
+ // Question value is provided by RTC
+ //
+ Storage = Question->Storage;
+ QuestionValue = &Question->HiiValue.Value;
+ 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->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:
+ //
+ // For date/time without storage
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Question->Operand == EFI_IFR_DATE_OP) {
+ EfiTime.Year = QuestionValue->date.Year;
+ EfiTime.Month = QuestionValue->date.Month;
+ EfiTime.Day = QuestionValue->date.Day;
+ } else {
+ EfiTime.Hour = QuestionValue->time.Hour;
+ EfiTime.Minute = QuestionValue->time.Minute;
+ EfiTime.Second = QuestionValue->time.Second;
+ }
+
+ if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {
+ Status = gRT->SetTime (&EfiTime);
+ } else {
+ Status = gRT->SetWakeupTime (TRUE, &EfiTime);
+ }
+ }
+
+ return Status;
+ }
+
+ //
+ // Question value is provided by EFI variable
+ //
+ StorageWidth = Question->StorageWidth;
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ if (Question->BufferValue != NULL) {
+ Src = Question->BufferValue;
+ } else {
+ Src = (UINT8 *) QuestionValue;
+ }
+
+ Status = gRT->SetVariable (
+ Question->VariableName,
+ &Storage->Guid,
+ Storage->Attributes,
+ StorageWidth,
+ Src
+ );
+ return Status;
+ }
+
+ //
+ // Question Value is provided by Buffer Storage or NameValue Storage
+ //
+ if (Question->BufferValue != NULL) {
+ Src = Question->BufferValue;
+ } else {
+ Src = (UINT8 *) &Question->HiiValue.Value;
+ }
+
+ IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);
+ IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
+ if (IsBufferStorage) {
+ //
+ // Copy to storage edit buffer
+ //
+ CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
+ } else {
+ if (IsString) {
+ //
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
+ //
+ Value = NULL;
+ BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
+ Value = AllocateZeroPool (BufferLen);
+ ASSERT (Value != NULL);
+ Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ BufferLen = StorageWidth * 2 + 1;
+ Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));
+ ASSERT (Value != NULL);
+ BufToHexString (Value, &BufferLen, Src, StorageWidth);
+ ToLower (Value);
+ }
+
+ Status = SetValueByName (Storage, Question->VariableName, Value);
+ gBS->FreePool (Value);
+ }
+
+ if (!Cached) {
+ //
+ // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||
+ // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"
+ //
+ if (IsBufferStorage) {
+ Length = StrLen (Question->BlockName) + 7;
+ } else {
+ Length = StrLen (Question->VariableName) + 2;
+ }
+ if (!IsBufferStorage && IsString) {
+ Length += (StrLen ((CHAR16 *) Src) * 4);
+ } else {
+ Length += (StorageWidth * 2);
+ }
+ ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));
+ ASSERT (ConfigResp != NULL);
+
+ StrCpy (ConfigResp, Storage->ConfigHdr);
+ if (IsBufferStorage) {
+ StrCat (ConfigResp, Question->BlockName);
+ StrCat (ConfigResp, L"&VALUE=");
+ } else {
+ StrCat (ConfigResp, L"&");
+ StrCat (ConfigResp, Question->VariableName);
+ StrCat (ConfigResp, L"=");
+ }
+
+ Value = ConfigResp + StrLen (ConfigResp);
+ if (!IsBufferStorage && IsString) {
+ //
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
+ //
+ BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);
+ Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ BufferLen = StorageWidth * 2 + 1;
+ BufToHexString (Value, &BufferLen, Src, StorageWidth);
+ ToLower (Value);
+ }
+
+ //
+ // Submit Question Value to Configuration Driver
+ //
+ if (FormSet->ConfigAccess != NULL) {
+ Status = FormSet->ConfigAccess->RouteConfig (
+ FormSet->ConfigAccess,
+ ConfigResp,
+ &Progress
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ConfigResp);
+ return Status;
+ }
+ }
+ gBS->FreePool (ConfigResp);
+
+ //
+ // Synchronize shadow Buffer
+ //
+ SynchronizeStorage (Storage);
+ }
+
+ return Status;
+}
+
+
+/**
+ Perform inconsistent check for a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question The Question to be validated.
+ @param Type Validation type: InConsistent or NoSubmit
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+ValidateQuestion (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINTN Type
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *ListHead;
+ EFI_STRING PopUp;
+ EFI_INPUT_KEY Key;
+ FORM_EXPRESSION *Expression;
+
+ if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
+ ListHead = &Question->InconsistentListHead;
+ } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+ ListHead = &Question->NoSubmitListHead;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ Link = GetFirstNode (ListHead);
+ while (!IsNull (ListHead, Link)) {
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+
+ //
+ // Evaluate the expression
+ //
+ Status = EvaluateExpression (FormSet, Form, Expression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Expression->Result.Value.b) {
+ //
+ // Condition meet, show up error message
+ //
+ if (Expression->Error != 0) {
+ PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
+ do {
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ gBS->FreePool (PopUp);
+ }
+
+ return EFI_NOT_READY;
+ }
+
+ Link = GetNextNode (ListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Perform NoSubmit check for a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+NoSubmitCheck (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Submit a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+SubmitForm (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ EFI_STRING ConfigResp;
+ EFI_STRING Progress;
+ FORMSET_STORAGE *Storage;
+
+ //
+ // Validate the Form by NoSubmit check
+ //
+ Status = NoSubmitCheck (FormSet, Form);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Submit Buffer storage or Name/Value storage
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ continue;
+ }
+
+ //
+ // Skip if there is no RequestElement
+ //
+ if (Storage->ElementCount == 0) {
+ continue;
+ }
+
+ //
+ // Prepare <ConfigResp>
+ //
+ Status = StorageToConfigResp (Storage, &ConfigResp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Send <ConfigResp> to Configuration Driver
+ //
+ if (FormSet->ConfigAccess != NULL) {
+ Status = FormSet->ConfigAccess->RouteConfig (
+ FormSet->ConfigAccess,
+ ConfigResp,
+ &Progress
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ConfigResp);
+ return Status;
+ }
+ }
+ gBS->FreePool (ConfigResp);
+
+ //
+ // Config success, update storage shadow Buffer
+ //
+ SynchronizeStorage (Storage);
+ }
+
+ gNvUpdateRequired = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset Question to its default value.
+
+ @param FormSet The form set.
+ @param Form The form.
+ @param Question The question.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINT16 DefaultId
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ QUESTION_DEFAULT *Default;
+ QUESTION_OPTION *Option;
+ EFI_HII_VALUE *HiiValue;
+ UINT8 Index;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ return Status;
+ }
+
+ //
+ // There are three ways to specify default value for a Question:
+ // 1, use nested EFI_IFR_DEFAULT (highest priority)
+ // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
+ // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
+ //
+ HiiValue = &Question->HiiValue;
+
+ //
+ // EFI_IFR_DEFAULT has highest priority
+ //
+ if (!IsListEmpty (&Question->DefaultListHead)) {
+ Link = GetFirstNode (&Question->DefaultListHead);
+ while (!IsNull (&Question->DefaultListHead, Link)) {
+ Default = QUESTION_DEFAULT_FROM_LINK (Link);
+
+ if (Default->DefaultId == DefaultId) {
+ if (Default->ValueExpression != NULL) {
+ //
+ // Default is provided by an Expression, evaluate it
+ //
+ Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));
+ } else {
+ //
+ // Default value is embedded in EFI_IFR_DEFAULT
+ //
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Question->DefaultListHead, Link);
+ }
+ }
+
+ //
+ // EFI_ONE_OF_OPTION
+ //
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // OneOfOption could only provide Standard and Manufacturing default
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
+ ) {
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ }
+ }
+
+ //
+ // EFI_IFR_CHECKBOX - lowest priority
+ //
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // Checkbox could only provide Standard and Manufacturing default
+ //
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
+ ) {
+ HiiValue->Value.b = TRUE;
+ } else {
+ HiiValue->Value.b = FALSE;
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // For Questions without default
+ //
+ switch (Question->Operand) {
+ case EFI_IFR_NUMERIC_OP:
+ //
+ // Take minimal value as numeric's default value
+ //
+ HiiValue->Value.u64 = Question->Minimum;
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ //
+ // Take first oneof option as oneof's default value
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ if (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+ }
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ //
+ // Take option sequence in IFR as ordered list's default value
+ //
+ Index = 0;
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+
+ Question->BufferValue[Index] = Option->Value.Value.u8;
+
+ Index++;
+ if (Index >= Question->MaxContainers) {
+ break;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ break;
+
+ default:
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Reset Questions in a Form to their default value.
+
+ @param FormSet FormSet data structure.
+ @param Form The Form which to be reset.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+ExtractFormDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT16 DefaultId
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&Form->StatementListHead, Link);
+
+ //
+ // Reset Question to its default value
+ //
+ Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Synchronize Buffer storage's Edit buffer
+ //
+ if ((Question->Storage != NULL) &&
+ (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
+ SetQuestionValue (FormSet, Form, Question, TRUE);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Question's Edit copy from Storage.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LoadFormConfig (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ //
+ // Initialize local copy of Value for each Question
+ //
+ Status = GetQuestionValue (FormSet, Form, Question, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Fill storage's edit copy with settings requested from Configuration Driver.
+
+ @param FormSet FormSet data structure.
+ @param Storage Buffer Storage.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LoadStorage (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORMSET_STORAGE *Storage
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ EFI_STRING Result;
+ CHAR16 *StrPtr;
+
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ return EFI_SUCCESS;
+ }
+
+ if (FormSet->ConfigAccess == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (Storage->ElementCount == 0) {
+ //
+ // Skip if there is no RequestElement
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Status = FormSet->ConfigAccess->ExtractConfig (
+ FormSet->ConfigAccess,
+ Storage->ConfigRequest,
+ &Progress,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert Result from <ConfigAltResp> to <ConfigResp>
+ //
+ StrPtr = StrStr (Result, L"ALTCFG");
+ if (StrPtr != NULL) {
+ *StrPtr = L'\0';
+ }
+
+ Status = ConfigRespToStorage (Storage, Result);
+ gBS->FreePool (Result);
+ return Status;
+}
+
+
+/**
+ Get current setting of Questions.
+
+ @param FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+InitializeCurrentSetting (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ LIST_ENTRY *Link;
+ FORMSET_STORAGE *Storage;
+ FORM_BROWSER_FORM *Form;
+ EFI_STATUS Status;
+
+ //
+ // Extract default from IFR binary
+ //
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+ Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);
+
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+
+ Status = LoadStorage (FormSet, Storage);
+
+ //
+ // Now Edit Buffer is filled with default values(lower priority) and current
+ // settings(higher priority), sychronize it to shadow Buffer
+ //
+ if (!EFI_ERROR (Status)) {
+ SynchronizeStorage (Storage);
+ }
+
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Fetch the Ifr binary data of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @param BinaryLength The length of the FormSet IFR binary.
+ @param BinaryData The buffer designed to receive the FormSet.
+
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.
+ BufferLength was updated.
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
+ be found with the requested FormId.
+
+**/
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT UINTN *BinaryLength,
+ OUT UINT8 **BinaryData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINTN BufferSize;
+ UINT8 *Package;
+ UINT8 *OpCodeData;
+ UINT32 Offset;
+ UINT32 Offset2;
+ BOOLEAN ReturnDefault;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ OpCodeData = NULL;
+ Package = NULL;
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
+
+ //
+ // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
+ //
+ if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
+ ReturnDefault = TRUE;
+ } else {
+ ReturnDefault = FALSE;
+ }
+
+ //
+ // Get HII PackageList
+ //
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocatePool (BufferSize);
+ ASSERT (HiiPackageList != NULL);
+
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ Offset2 = 0;
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+
+ while (Offset < PackageListLength) {
+ Package = ((UINT8 *) HiiPackageList) + Offset;
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
+ //
+ // Search FormSet in this Form Package
+ //
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset2 < PackageHeader.Length) {
+ OpCodeData = Package + Offset2;
+
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
+ //
+ // Check whether return default FormSet
+ //
+ if (ReturnDefault) {
+ break;
+ }
+
+ //
+ // FormSet GUID is specified, check it
+ //
+ if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+ break;
+ }
+ }
+
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ }
+
+ if (Offset2 < PackageHeader.Length) {
+ //
+ // Target formset found
+ //
+ break;
+ }
+ }
+
+ Offset += PackageHeader.Length;
+ }
+
+ if (Offset >= PackageListLength) {
+ //
+ // Form package not found in this Package List
+ //
+ gBS->FreePool (HiiPackageList);
+ return EFI_NOT_FOUND;
+ }
+
+ if (ReturnDefault && FormSetGuid != NULL) {
+ //
+ // Return the default FormSet GUID
+ //
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ }
+
+ //
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
+ // of the Form Package.
+ //
+ *BinaryLength = PackageHeader.Length - Offset2;
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
+
+ gBS->FreePool (HiiPackageList);
+
+ if (*BinaryData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize the internal data structure of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @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
+InitializeFormSet (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ UINT16 Index;
+
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FormSet->HiiHandle = Handle;
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
+
+ //
+ // Retrieve ConfigAccess Protocol associated with this HiiPackageList
+ //
+ Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, 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;
+ }
+
+ //
+ // Parse the IFR binary OpCodes
+ //
+ Status = ParseOpCodes (FormSet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gClassOfVfr = FormSet->SubClass;
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ FrontPageHandle = FormSet->HiiHandle;
+ }
+
+ //
+ // Match GUID to find out the function key setting. If match fail, use the default setting.
+ //
+ for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
+ if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
+ //
+ // Update the function key setting.
+ //
+ gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
+ //
+ // Function key prompt can not be displayed if the function key has been disabled.
+ //
+ if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
+ gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
+ gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
+ gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+
+ if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
+ gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ }
+ }
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
index 80a9d29..2a4eb9e 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
@@ -1,747 +1,1071 @@
-/** @file
-
-Copyright (c) 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- Setup.h
-
-Abstract:
-
-
-Revision History
-
-
-**/
-
-#ifndef _SETUP_H
-#define _SETUP_H
-
-
-#include <PiDxe.h>
-
-#include <Protocol/Print.h>
-#include <Protocol/SimpleTextOut.h>
-#include <Protocol/SimpleTextIn.h>
-#include <Protocol/FormBrowser2.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/UnicodeCollation.h>
-#include <Protocol/HiiConfigAccess.h>
-#include <Protocol/HiiConfigRouting.h>
-#include <Protocol/HiiDatabase.h>
-#include <Protocol/HiiString.h>
-
-#include <MdeModuleHii.h>
-
-#include <Library/GraphicsLib.h>
-#include <Library/PrintLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/BaseLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/IfrSupportLib.h>
-#include <Library/ExtendedIfrSupportLib.h>
-#include <Library/HiiLib.h>
-#include <Library/ExtendedHiiLib.h>
-
-#include "Colors.h"
-
-//
-// This is the generated header file which includes whatever needs to be exported (strings + IFR)
-//
-
-extern UINT8 SetupBrowserStrings[];
-
-//
-// Screen definitions
-//
-#define BANNER_HEIGHT 6
-#define BANNER_COLUMNS 3
-
-#define FRONT_PAGE_HEADER_HEIGHT 6
-#define NONE_FRONT_PAGE_HEADER_HEIGHT 3
-#define LEFT_SKIPPED_COLUMNS 4
-#define FOOTER_HEIGHT 4
-#define STATUS_BAR_HEIGHT 1
-#define SCROLL_ARROW_HEIGHT 1
-#define POPUP_PAD_SPACE_COUNT 5
-#define POPUP_FRAME_WIDTH 2
-
-//
-// Definition for function key setting
-//
-#define NONE_FUNCTION_KEY_SETTING 0
-#define DEFAULT_FUNCTION_KEY_SETTING (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)
-
-#define FUNCTION_ONE (1 << 0)
-#define FUNCTION_TWO (1 << 1)
-#define FUNCTION_NINE (1 << 2)
-#define FUNCTION_TEN (1 << 3)
-
-typedef struct {
- EFI_GUID FormSetGuid;
- UINTN KeySetting;
-} FUNCTIION_KEY_SETTING;
-
-//
-// Character definitions
-//
-#define CHAR_SPACE 0x0020
-#define UPPER_LOWER_CASE_OFFSET 0x20
-
-//
-// Time definitions
-//
-#define ONE_SECOND 10000000
-
-//
-// Display definitions
-//
-#define LEFT_HYPER_DELIMITER L'<'
-#define RIGHT_HYPER_DELIMITER L'>'
-
-#define LEFT_ONEOF_DELIMITER L'<'
-#define RIGHT_ONEOF_DELIMITER L'>'
-
-#define LEFT_NUMERIC_DELIMITER L'['
-#define RIGHT_NUMERIC_DELIMITER L']'
-
-#define LEFT_CHECKBOX_DELIMITER L'['
-#define RIGHT_CHECKBOX_DELIMITER L']'
-
-#define CHECK_ON L'X'
-#define CHECK_OFF L' '
-
-#define TIME_SEPARATOR L':'
-#define DATE_SEPARATOR L'/'
-
-#define YES_ANSWER L'Y'
-#define NO_ANSWER L'N'
-
-//
-// This is the Input Error Message
-//
-#define INPUT_ERROR 1
-
-//
-// This is the NV RAM update required Message
-//
-#define NV_UPDATE_REQUIRED 2
-
-//
-// Refresh the Status Bar with flags
-//
-#define REFRESH_STATUS_BAR 0xff
-
-//
-// Incremental string lenght of ConfigRequest
-//
-#define CONFIG_REQUEST_STRING_INCREMENTAL 1024
-
-//
-// HII value compare result
-//
-#define HII_VALUE_UNDEFINED 0
-#define HII_VALUE_EQUAL 1
-#define HII_VALUE_LESS_THAN 2
-#define HII_VALUE_GREATER_THAN 3
-
-//
-// Incremental size of stack for expression
-//
-#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
-
-
-#define EFI_SPECIFICATION_ERRATA_VERSION 0
-
-#define EFI_IFR_SPECIFICATION_VERSION \
- ((((EFI_SPECIFICATION_VERSION) >> 8) & 0xff00) | \
- (((EFI_SPECIFICATION_VERSION) & 0xf) << 4) | \
- ((EFI_SPECIFICATION_ERRATA_VERSION) & 0xf))
-
-#define SETUP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'D', 'V')
-typedef struct {
- UINT32 Signature;
-
- EFI_HANDLE Handle;
-
- //
- // Produced protocol
- //
- EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;
- EFI_PRINT_PROTOCOL Print;
-
-} SETUP_DRIVER_PRIVATE_DATA;
-
-typedef struct {
- EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];
-} BANNER_DATA;
-
-//
-// IFR relative definition
-//
-#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0
-#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1
-#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2
-#define EFI_HII_EXPRESSION_SUPPRESS_IF 3
-#define EFI_HII_EXPRESSION_DISABLE_IF 4
-#define EFI_HII_EXPRESSION_VALUE 5
-#define EFI_HII_EXPRESSION_RULE 6
-
-#define EFI_HII_VARSTORE_BUFFER 0
-#define EFI_HII_VARSTORE_NAME_VALUE 1
-#define EFI_HII_VARSTORE_EFI_VARIABLE 2
-
-#define FORM_INCONSISTENT_VALIDATION 0
-#define FORM_NO_SUBMIT_VALIDATION 1
-
-typedef struct {
- UINT8 Type;
- EFI_IFR_TYPE_VALUE Value;
-} EFI_HII_VALUE;
-
-#define NAME_VALUE_NODE_SIGNATURE EFI_SIGNATURE_32 ('N', 'V', 'S', 'T')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
- CHAR16 *Name;
- CHAR16 *Value;
- CHAR16 *EditValue;
-} NAME_VALUE_NODE;
-
-#define NAME_VALUE_NODE_FROM_LINK(a) CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)
-
-#define FORMSET_STORAGE_SIGNATURE EFI_SIGNATURE_32 ('F', 'S', 'T', 'G')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- UINT8 Type; // Storage type
-
- UINT16 VarStoreId;
- EFI_GUID Guid;
-
- CHAR16 *Name; // For EFI_IFR_VARSTORE
- UINT16 Size;
- UINT8 *Buffer;
- UINT8 *EditBuffer; // Edit copy for Buffer Storage
-
- LIST_ENTRY NameValueListHead; // List of NAME_VALUE_NODE
-
- UINT32 Attributes; // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute
-
- CHAR16 *ConfigHdr; // <ConfigHdr>
- CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
- UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>
- UINTN SpareStrLen; // Spare length of ConfigRequest string buffer
-} FORMSET_STORAGE;
-
-#define FORMSET_STORAGE_FROM_LINK(a) CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)
-
-#define EXPRESSION_OPCODE_SIGNATURE EFI_SIGNATURE_32 ('E', 'X', 'O', 'P')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- UINT8 Operand;
-
- UINT8 Format; // For EFI_IFR_TO_STRING, EFI_IFR_FIND
- UINT8 Flags; // For EFI_IFR_SPAN
- UINT8 RuleId; // For EFI_IFR_RULE_REF
-
- EFI_HII_VALUE Value; // For EFI_IFR_EQ_ID_VAL, EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
-
- EFI_QUESTION_ID QuestionId; // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_LIST, EFI_IFR_QUESTION_REF1
- EFI_QUESTION_ID QuestionId2;
-
- UINT16 ListLength; // For EFI_IFR_EQ_ID_LIST
- UINT16 *ValueList;
-
- EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
- EFI_GUID Guid;
-} EXPRESSION_OPCODE;
-
-#define EXPRESSION_OPCODE_FROM_LINK(a) CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)
-
-#define FORM_EXPRESSION_SIGNATURE EFI_SIGNATURE_32 ('F', 'E', 'X', 'P')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- UINT8 Type; // Type for this expression
-
- UINT8 RuleId; // For EFI_IFR_RULE only
- EFI_STRING_ID Error; // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
-
- EFI_HII_VALUE Result; // Expression evaluation result
-
- LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE)
-} FORM_EXPRESSION;
-
-#define FORM_EXPRESSION_FROM_LINK(a) CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)
-
-#define QUESTION_DEFAULT_SIGNATURE EFI_SIGNATURE_32 ('Q', 'D', 'F', 'T')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- UINT16 DefaultId;
- EFI_HII_VALUE Value; // Default value
-
- FORM_EXPRESSION *ValueExpression; // Not-NULL indicates default value is provided by EFI_IFR_VALUE
-} QUESTION_DEFAULT;
-
-#define QUESTION_DEFAULT_FROM_LINK(a) CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)
-
-#define QUESTION_OPTION_SIGNATURE EFI_SIGNATURE_32 ('Q', 'O', 'P', 'T')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- EFI_STRING_ID Text;
- UINT8 Flags;
- EFI_HII_VALUE Value;
- EFI_IMAGE_ID ImageId;
-
- FORM_EXPRESSION *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf
-} QUESTION_OPTION;
-
-#define QUESTION_OPTION_FROM_LINK(a) CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)
-
-#define FORM_BROWSER_STATEMENT_SIGNATURE EFI_SIGNATURE_32 ('F', 'S', 'T', 'A')
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- UINT8 Operand; // The operand (first byte) of this Statement or Question
-
- //
- // Statement Header
- //
- EFI_STRING_ID Prompt;
- EFI_STRING_ID Help;
- EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT
-
- //
- // Question Header
- //
- EFI_QUESTION_ID QuestionId; // The value of zero is reserved
- EFI_VARSTORE_ID VarStoreId; // A value of zero indicates no variable storage
- FORMSET_STORAGE *Storage;
- union {
- EFI_STRING_ID VarName;
- UINT16 VarOffset;
- } VarStoreInfo;
- UINT16 StorageWidth;
- UINT8 QuestionFlags;
- CHAR16 *VariableName; // Name/Value or EFI Variable name
- CHAR16 *BlockName; // Buffer storage block name: "OFFSET=...WIDTH=..."
-
- EFI_HII_VALUE HiiValue; // Edit copy for checkbox, numberic, oneof
- UINT8 *BufferValue; // Edit copy for string, password, orderedlist
-
- //
- // OpCode specific members
- //
- UINT8 Flags; // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,
- // EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER
- UINT8 MaxContainers; // for EFI_IFR_ORDERED_LIST
-
- UINT16 BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number
- EFI_STRING_ID QuestionConfig; // for EFI_IFR_ACTION, if 0 then no configuration string will be processed
-
- UINT64 Minimum; // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value
- UINT64 Maximum; // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length
- UINT64 Step;
-
- EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON
- EFI_FORM_ID RefFormId; // for EFI_IFR_REF
- EFI_QUESTION_ID RefQuestionId; // for EFI_IFR_REF2
- EFI_GUID RefFormSetId; // for EFI_IFR_REF3
- EFI_STRING_ID RefDevicePath; // for EFI_IFR_REF4
-
- //
- // Get from IFR parsing
- //
- FORM_EXPRESSION *ValueExpression; // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly
- LIST_ENTRY DefaultListHead; // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values
- LIST_ENTRY OptionListHead; // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)
-
- EFI_IMAGE_ID ImageId; // nested EFI_IFR_IMAGE
- UINT8 RefreshInterval; // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh
- BOOLEAN InSubtitle; // nesting inside of EFI_IFR_SUBTITLE
-
- LIST_ENTRY InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)
- LIST_ENTRY NoSubmitListHead; // nested nosubmit expression list (FORM_EXPRESSION)
- FORM_EXPRESSION *GrayOutExpression; // nesting inside of GrayOutIf
- FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf
-
-} 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 EFI_SIGNATURE_32 ('F', 'F', 'R', 'M')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- UINT16 FormId;
- EFI_STRING_ID FormTitle;
-
- EFI_IMAGE_ID ImageId;
-
- LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)
- LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT)
-} FORM_BROWSER_FORM;
-
-#define FORM_BROWSER_FORM_FROM_LINK(a) CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)
-
-#define FORMSET_DEFAULTSTORE_SIGNATURE EFI_SIGNATURE_32 ('F', 'D', 'F', 'S')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- UINT16 DefaultId;
- EFI_STRING_ID DefaultName;
-} FORMSET_DEFAULTSTORE;
-
-#define FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)
-
-typedef struct {
- EFI_HII_HANDLE HiiHandle;
- EFI_HANDLE DriverHandle;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- UINTN IfrBinaryLength;
- UINT8 *IfrBinaryData;
-
- EFI_GUID Guid;
- EFI_STRING_ID FormSetTitle;
- EFI_STRING_ID Help;
- UINT16 Class;
- UINT16 SubClass;
- EFI_IMAGE_ID ImageId;
-
- FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions
- EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode
-
- LIST_ENTRY StorageListHead; // Storage list (FORMSET_STORAGE)
- LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)
- LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)
-} FORM_BROWSER_FORMSET;
-
-
-extern EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
-extern EFI_HII_STRING_PROTOCOL *mHiiString;
-extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
-
-extern BANNER_DATA *BannerData;
-extern EFI_HII_HANDLE FrontPageHandle;
-extern UINTN gClassOfVfr;
-extern UINTN gFunctionKeySetting;
-extern BOOLEAN gResetRequired;
-extern BOOLEAN gNvUpdateRequired;
-extern EFI_HII_HANDLE gHiiHandle;
-extern BOOLEAN gFirstIn;
-extern UINT16 gDirection;
-extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
-extern BOOLEAN gUpArrow;
-extern BOOLEAN gDownArrow;
-
-//
-// Browser Global Strings
-//
-extern CHAR16 *gFunctionOneString;
-extern CHAR16 *gFunctionTwoString;
-extern CHAR16 *gFunctionNineString;
-extern CHAR16 *gFunctionTenString;
-extern CHAR16 *gEnterString;
-extern CHAR16 *gEnterCommitString;
-extern CHAR16 *gEscapeString;
-extern CHAR16 *gSaveFailed;
-extern CHAR16 *gMoveHighlight;
-extern CHAR16 *gMakeSelection;
-extern CHAR16 *gDecNumericInput;
-extern CHAR16 *gHexNumericInput;
-extern CHAR16 *gToggleCheckBox;
-extern CHAR16 *gPromptForData;
-extern CHAR16 *gPromptForPassword;
-extern CHAR16 *gPromptForNewPassword;
-extern CHAR16 *gConfirmPassword;
-extern CHAR16 *gConfirmError;
-extern CHAR16 *gPassowordInvalid;
-extern CHAR16 *gPressEnter;
-extern CHAR16 *gEmptyString;
-extern CHAR16 *gAreYouSure;
-extern CHAR16 *gYesResponse;
-extern CHAR16 *gNoResponse;
-extern CHAR16 *gMiniString;
-extern CHAR16 *gPlusString;
-extern CHAR16 *gMinusString;
-extern CHAR16 *gAdjustNumber;
-
-extern CHAR16 gPromptBlockWidth;
-extern CHAR16 gOptionBlockWidth;
-extern CHAR16 gHelpBlockWidth;
-
-extern EFI_GUID gZeroGuid;
-extern EFI_GUID gTianoHiiIfrGuid;
-
-//
-// Global Procedure Defines
-//
-VOID
-InitializeBrowserStrings (
- VOID
- )
-;
-
-UINTN
-_Print (
- IN CHAR16 *fmt,
- ...
- )
-;
-
-UINTN
-PrintString (
- CHAR16 *String
- )
-;
-
-UINTN
-PrintChar (
- CHAR16 Character
- )
-;
-
-UINTN
-PrintAt (
- IN UINTN Column,
- IN UINTN Row,
- IN CHAR16 *fmt,
- ...
- )
-;
-
-UINTN
-PrintStringAt (
- IN UINTN Column,
- IN UINTN Row,
- CHAR16 *String
- )
-;
-
-UINTN
-PrintCharAt (
- IN UINTN Column,
- IN UINTN Row,
- CHAR16 Character
- )
-;
-
-EFI_STATUS
-ParseOpCodes (
- IN FORM_BROWSER_FORMSET *FormSet
- )
-;
-
-VOID
-DestroyFormSet (
- IN OUT FORM_BROWSER_FORMSET *FormSet
- )
-;
-
-VOID
-DisplayPageFrame (
- VOID
- )
-;
-
-EFI_STRING_ID
-NewString (
- IN CHAR16 *String,
- IN EFI_HII_HANDLE HiiHandle
- )
-;
-
-EFI_STATUS
-DeleteString (
- IN EFI_STRING_ID StringId,
- IN EFI_HII_HANDLE HiiHandle
- )
-;
-CHAR16 *
-GetToken (
- IN EFI_STRING_ID Token,
- IN EFI_HII_HANDLE HiiHandle
- )
-;
-
-VOID
-CreateSharedPopUp (
- IN UINTN RequestedWidth,
- IN UINTN NumberOfLines,
- IN CHAR16 **ArrayOfStrings
- )
-;
-
-EFI_STATUS
-CreateDialog (
- IN UINTN NumberOfLines,
- IN BOOLEAN HotKey,
- IN UINTN MaximumStringSize,
- OUT CHAR16 *StringBuffer,
- OUT EFI_INPUT_KEY *KeyValue,
- IN CHAR16 *String,
- ...
- )
-;
-
-EFI_STATUS
-GetQuestionValue (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN OUT FORM_BROWSER_STATEMENT *Question,
- IN BOOLEAN Cached
- )
-;
-
-EFI_STATUS
-SetQuestionValue (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN OUT FORM_BROWSER_STATEMENT *Question,
- IN BOOLEAN Cached
- )
-;
-
-EFI_STATUS
-ValidateQuestion (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN FORM_BROWSER_STATEMENT *Question,
- IN UINTN Type
- )
-;
-
-EFI_STATUS
-SubmitForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
- )
-;
-
-EFI_STATUS
-GetQuestionDefault (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN FORM_BROWSER_STATEMENT *Question,
- IN UINT16 DefaultId
- )
-;
-
-EFI_STATUS
-InitializeCurrentSetting (
- IN OUT FORM_BROWSER_FORMSET *FormSet
- )
-;
-
-EFI_STATUS
-InitializeFormSet (
- IN EFI_HII_HANDLE Handle,
- IN OUT EFI_GUID *FormSetGuid,
- OUT FORM_BROWSER_FORMSET *FormSet
- )
-;
-
-EFI_STATUS
-ExtractFormDefault (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN UINT16 DefaultId
- )
-;
-
-EFI_STATUS
-LoadFormConfig (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
- )
-;
-
-EFI_STATUS
-StorageToConfigResp (
- IN FORMSET_STORAGE *Storage,
- IN CHAR16 **ConfigResp
- )
-;
-
-EFI_STATUS
-ConfigRespToStorage (
- IN FORMSET_STORAGE *Storage,
- IN CHAR16 *ConfigResp
- )
-;
-
-EFI_STATUS
-LoadStorage (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORMSET_STORAGE *Storage
- )
-;
-
-EFI_STATUS
-GetIfrBinaryData (
- IN EFI_HII_HANDLE Handle,
- IN OUT EFI_GUID *FormSetGuid,
- OUT UINTN *BinaryLength,
- OUT UINT8 **BinaryData
- )
-;
-
-EFI_STATUS
-EFIAPI
-SendForm (
- IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
- IN EFI_HII_HANDLE *Handles,
- IN UINTN HandleCount,
- IN EFI_GUID *FormSetGuid, OPTIONAL
- IN UINT16 FormId, OPTIONAL
- IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
- OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
- )
-;
-
-EFI_STATUS
-EFIAPI
-BrowserCallback (
- IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
- IN OUT UINTN *ResultsDataSize,
- IN OUT EFI_STRING ResultsData,
- IN BOOLEAN RetrieveData,
- IN CONST EFI_GUID *VariableGuid, OPTIONAL
- IN CONST CHAR16 *VariableName OPTIONAL
- )
-;
-
-#endif
+/** @file
+Private MACRO, structure and function definitions for Setup Browser module.
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#ifndef _SETUP_H_
+#define _SETUP_H_
+
+
+#include <PiDxe.h>
+
+#include <Protocol/Print.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+
+#include <MdeModuleHii.h>
+
+#include <Library/GraphicsLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/ExtendedIfrSupportLib.h>
+#include <Library/HiiLib.h>
+#include <Library/ExtendedHiiLib.h>
+
+#include "Colors.h"
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+
+extern UINT8 SetupBrowserStrings[];
+
+//
+// Screen definitions
+//
+#define BANNER_HEIGHT 6
+#define BANNER_COLUMNS 3
+
+#define FRONT_PAGE_HEADER_HEIGHT 6
+#define NONE_FRONT_PAGE_HEADER_HEIGHT 3
+#define LEFT_SKIPPED_COLUMNS 4
+#define FOOTER_HEIGHT 4
+#define STATUS_BAR_HEIGHT 1
+#define SCROLL_ARROW_HEIGHT 1
+#define POPUP_PAD_SPACE_COUNT 5
+#define POPUP_FRAME_WIDTH 2
+
+//
+// Definition for function key setting
+//
+#define NONE_FUNCTION_KEY_SETTING 0
+#define DEFAULT_FUNCTION_KEY_SETTING (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)
+
+#define FUNCTION_ONE (1 << 0)
+#define FUNCTION_TWO (1 << 1)
+#define FUNCTION_NINE (1 << 2)
+#define FUNCTION_TEN (1 << 3)
+
+typedef struct {
+ EFI_GUID FormSetGuid;
+ UINTN KeySetting;
+} FUNCTIION_KEY_SETTING;
+
+//
+// Character definitions
+//
+#define CHAR_SPACE 0x0020
+#define UPPER_LOWER_CASE_OFFSET 0x20
+
+//
+// Time definitions
+//
+#define ONE_SECOND 10000000
+
+//
+// Display definitions
+//
+#define LEFT_HYPER_DELIMITER L'<'
+#define RIGHT_HYPER_DELIMITER L'>'
+
+#define LEFT_ONEOF_DELIMITER L'<'
+#define RIGHT_ONEOF_DELIMITER L'>'
+
+#define LEFT_NUMERIC_DELIMITER L'['
+#define RIGHT_NUMERIC_DELIMITER L']'
+
+#define LEFT_CHECKBOX_DELIMITER L'['
+#define RIGHT_CHECKBOX_DELIMITER L']'
+
+#define CHECK_ON L'X'
+#define CHECK_OFF L' '
+
+#define TIME_SEPARATOR L':'
+#define DATE_SEPARATOR L'/'
+
+#define YES_ANSWER L'Y'
+#define NO_ANSWER L'N'
+
+//
+// This is the Input Error Message
+//
+#define INPUT_ERROR 1
+
+//
+// This is the NV RAM update required Message
+//
+#define NV_UPDATE_REQUIRED 2
+
+//
+// Refresh the Status Bar with flags
+//
+#define REFRESH_STATUS_BAR 0xff
+
+//
+// Incremental string lenght of ConfigRequest
+//
+#define CONFIG_REQUEST_STRING_INCREMENTAL 1024
+
+//
+// HII value compare result
+//
+#define HII_VALUE_UNDEFINED 0
+#define HII_VALUE_EQUAL 1
+#define HII_VALUE_LESS_THAN 2
+#define HII_VALUE_GREATER_THAN 3
+
+//
+// Incremental size of stack for expression
+//
+#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
+
+
+#define EFI_SPECIFICATION_ERRATA_VERSION 0
+
+#define EFI_IFR_SPECIFICATION_VERSION \
+ ((((EFI_SPECIFICATION_VERSION) >> 8) & 0xff00) | \
+ (((EFI_SPECIFICATION_VERSION) & 0xf) << 4) | \
+ ((EFI_SPECIFICATION_ERRATA_VERSION) & 0xf))
+
+#define SETUP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'D', 'V')
+typedef struct {
+ UINT32 Signature;
+
+ EFI_HANDLE Handle;
+
+ //
+ // Produced protocol
+ //
+ EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;
+ EFI_PRINT_PROTOCOL Print;
+
+} SETUP_DRIVER_PRIVATE_DATA;
+
+typedef struct {
+ EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];
+} BANNER_DATA;
+
+//
+// IFR relative definition
+//
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2
+#define EFI_HII_EXPRESSION_SUPPRESS_IF 3
+#define EFI_HII_EXPRESSION_DISABLE_IF 4
+#define EFI_HII_EXPRESSION_VALUE 5
+#define EFI_HII_EXPRESSION_RULE 6
+
+#define EFI_HII_VARSTORE_BUFFER 0
+#define EFI_HII_VARSTORE_NAME_VALUE 1
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2
+
+#define FORM_INCONSISTENT_VALIDATION 0
+#define FORM_NO_SUBMIT_VALIDATION 1
+
+typedef struct {
+ UINT8 Type;
+ EFI_IFR_TYPE_VALUE Value;
+} EFI_HII_VALUE;
+
+#define NAME_VALUE_NODE_SIGNATURE EFI_SIGNATURE_32 ('N', 'V', 'S', 'T')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ CHAR16 *Name;
+ CHAR16 *Value;
+ CHAR16 *EditValue;
+} NAME_VALUE_NODE;
+
+#define NAME_VALUE_NODE_FROM_LINK(a) CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)
+
+#define FORMSET_STORAGE_SIGNATURE EFI_SIGNATURE_32 ('F', 'S', 'T', 'G')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Type; // Storage type
+
+ UINT16 VarStoreId;
+ EFI_GUID Guid;
+
+ CHAR16 *Name; // For EFI_IFR_VARSTORE
+ UINT16 Size;
+ UINT8 *Buffer;
+ UINT8 *EditBuffer; // Edit copy for Buffer Storage
+
+ LIST_ENTRY NameValueListHead; // List of NAME_VALUE_NODE
+
+ UINT32 Attributes; // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute
+
+ CHAR16 *ConfigHdr; // <ConfigHdr>
+ CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
+ UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>
+ UINTN SpareStrLen; // Spare length of ConfigRequest string buffer
+} FORMSET_STORAGE;
+
+#define FORMSET_STORAGE_FROM_LINK(a) CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)
+
+#define EXPRESSION_OPCODE_SIGNATURE EFI_SIGNATURE_32 ('E', 'X', 'O', 'P')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Operand;
+
+ UINT8 Format; // For EFI_IFR_TO_STRING, EFI_IFR_FIND
+ UINT8 Flags; // For EFI_IFR_SPAN
+ UINT8 RuleId; // For EFI_IFR_RULE_REF
+
+ EFI_HII_VALUE Value; // For EFI_IFR_EQ_ID_VAL, EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
+
+ EFI_QUESTION_ID QuestionId; // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_LIST, EFI_IFR_QUESTION_REF1
+ EFI_QUESTION_ID QuestionId2;
+
+ UINT16 ListLength; // For EFI_IFR_EQ_ID_LIST
+ UINT16 *ValueList;
+
+ EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
+ EFI_GUID Guid;
+} EXPRESSION_OPCODE;
+
+#define EXPRESSION_OPCODE_FROM_LINK(a) CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)
+
+#define FORM_EXPRESSION_SIGNATURE EFI_SIGNATURE_32 ('F', 'E', 'X', 'P')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Type; // Type for this expression
+
+ UINT8 RuleId; // For EFI_IFR_RULE only
+ EFI_STRING_ID Error; // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
+
+ EFI_HII_VALUE Result; // Expression evaluation result
+
+ LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE)
+} FORM_EXPRESSION;
+
+#define FORM_EXPRESSION_FROM_LINK(a) CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)
+
+#define QUESTION_DEFAULT_SIGNATURE EFI_SIGNATURE_32 ('Q', 'D', 'F', 'T')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 DefaultId;
+ EFI_HII_VALUE Value; // Default value
+
+ FORM_EXPRESSION *ValueExpression; // Not-NULL indicates default value is provided by EFI_IFR_VALUE
+} QUESTION_DEFAULT;
+
+#define QUESTION_DEFAULT_FROM_LINK(a) CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)
+
+#define QUESTION_OPTION_SIGNATURE EFI_SIGNATURE_32 ('Q', 'O', 'P', 'T')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_STRING_ID Text;
+ UINT8 Flags;
+ EFI_HII_VALUE Value;
+ EFI_IMAGE_ID ImageId;
+
+ FORM_EXPRESSION *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf
+} QUESTION_OPTION;
+
+#define QUESTION_OPTION_FROM_LINK(a) CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)
+
+#define FORM_BROWSER_STATEMENT_SIGNATURE EFI_SIGNATURE_32 ('F', 'S', 'T', 'A')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Operand; // The operand (first byte) of this Statement or Question
+
+ //
+ // Statement Header
+ //
+ EFI_STRING_ID Prompt;
+ EFI_STRING_ID Help;
+ EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT
+
+ //
+ // Question Header
+ //
+ EFI_QUESTION_ID QuestionId; // The value of zero is reserved
+ EFI_VARSTORE_ID VarStoreId; // A value of zero indicates no variable storage
+ FORMSET_STORAGE *Storage;
+ union {
+ EFI_STRING_ID VarName;
+ UINT16 VarOffset;
+ } VarStoreInfo;
+ UINT16 StorageWidth;
+ UINT8 QuestionFlags;
+ CHAR16 *VariableName; // Name/Value or EFI Variable name
+ CHAR16 *BlockName; // Buffer storage block name: "OFFSET=...WIDTH=..."
+
+ EFI_HII_VALUE HiiValue; // Edit copy for checkbox, numberic, oneof
+ UINT8 *BufferValue; // Edit copy for string, password, orderedlist
+
+ //
+ // OpCode specific members
+ //
+ UINT8 Flags; // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,
+ // EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER
+ UINT8 MaxContainers; // for EFI_IFR_ORDERED_LIST
+
+ UINT16 BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number
+ EFI_STRING_ID QuestionConfig; // for EFI_IFR_ACTION, if 0 then no configuration string will be processed
+
+ UINT64 Minimum; // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value
+ UINT64 Maximum; // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length
+ UINT64 Step;
+
+ EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON
+ EFI_FORM_ID RefFormId; // for EFI_IFR_REF
+ EFI_QUESTION_ID RefQuestionId; // for EFI_IFR_REF2
+ EFI_GUID RefFormSetId; // for EFI_IFR_REF3
+ EFI_STRING_ID RefDevicePath; // for EFI_IFR_REF4
+
+ //
+ // Get from IFR parsing
+ //
+ FORM_EXPRESSION *ValueExpression; // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly
+ LIST_ENTRY DefaultListHead; // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values
+ LIST_ENTRY OptionListHead; // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)
+
+ EFI_IMAGE_ID ImageId; // nested EFI_IFR_IMAGE
+ UINT8 RefreshInterval; // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh
+ BOOLEAN InSubtitle; // nesting inside of EFI_IFR_SUBTITLE
+
+ LIST_ENTRY InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)
+ LIST_ENTRY NoSubmitListHead; // nested nosubmit expression list (FORM_EXPRESSION)
+ FORM_EXPRESSION *GrayOutExpression; // nesting inside of GrayOutIf
+ FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf
+
+} 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 EFI_SIGNATURE_32 ('F', 'F', 'R', 'M')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 FormId;
+ EFI_STRING_ID FormTitle;
+
+ EFI_IMAGE_ID ImageId;
+
+ LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)
+ LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT)
+} FORM_BROWSER_FORM;
+
+#define FORM_BROWSER_FORM_FROM_LINK(a) CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)
+
+#define FORMSET_DEFAULTSTORE_SIGNATURE EFI_SIGNATURE_32 ('F', 'D', 'F', 'S')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 DefaultId;
+ EFI_STRING_ID DefaultName;
+} FORMSET_DEFAULTSTORE;
+
+#define FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)
+
+typedef struct {
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ UINTN IfrBinaryLength;
+ UINT8 *IfrBinaryData;
+
+ EFI_GUID Guid;
+ EFI_STRING_ID FormSetTitle;
+ EFI_STRING_ID Help;
+ UINT16 Class;
+ UINT16 SubClass;
+ EFI_IMAGE_ID ImageId;
+
+ FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions
+ EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode
+
+ LIST_ENTRY StorageListHead; // Storage list (FORMSET_STORAGE)
+ LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)
+ LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)
+} FORM_BROWSER_FORMSET;
+
+
+extern EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+extern EFI_HII_STRING_PROTOCOL *mHiiString;
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
+
+extern BANNER_DATA *BannerData;
+extern EFI_HII_HANDLE FrontPageHandle;
+extern UINTN gClassOfVfr;
+extern UINTN gFunctionKeySetting;
+extern BOOLEAN gResetRequired;
+extern BOOLEAN gNvUpdateRequired;
+extern EFI_HII_HANDLE gHiiHandle;
+extern BOOLEAN gFirstIn;
+extern UINT16 gDirection;
+extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+extern BOOLEAN gUpArrow;
+extern BOOLEAN gDownArrow;
+
+//
+// Browser Global Strings
+//
+extern CHAR16 *gFunctionOneString;
+extern CHAR16 *gFunctionTwoString;
+extern CHAR16 *gFunctionNineString;
+extern CHAR16 *gFunctionTenString;
+extern CHAR16 *gEnterString;
+extern CHAR16 *gEnterCommitString;
+extern CHAR16 *gEscapeString;
+extern CHAR16 *gSaveFailed;
+extern CHAR16 *gMoveHighlight;
+extern CHAR16 *gMakeSelection;
+extern CHAR16 *gDecNumericInput;
+extern CHAR16 *gHexNumericInput;
+extern CHAR16 *gToggleCheckBox;
+extern CHAR16 *gPromptForData;
+extern CHAR16 *gPromptForPassword;
+extern CHAR16 *gPromptForNewPassword;
+extern CHAR16 *gConfirmPassword;
+extern CHAR16 *gConfirmError;
+extern CHAR16 *gPassowordInvalid;
+extern CHAR16 *gPressEnter;
+extern CHAR16 *gEmptyString;
+extern CHAR16 *gAreYouSure;
+extern CHAR16 *gYesResponse;
+extern CHAR16 *gNoResponse;
+extern CHAR16 *gMiniString;
+extern CHAR16 *gPlusString;
+extern CHAR16 *gMinusString;
+extern CHAR16 *gAdjustNumber;
+
+extern CHAR16 gPromptBlockWidth;
+extern CHAR16 gOptionBlockWidth;
+extern CHAR16 gHelpBlockWidth;
+
+extern EFI_GUID gZeroGuid;
+extern EFI_GUID gTianoHiiIfrGuid;
+
+//
+// Global Procedure Defines
+//
+
+/**
+ Initialize the HII String Token to the correct values.
+
+**/
+VOID
+InitializeBrowserStrings (
+ VOID
+ )
+;
+
+/**
+ Prints a unicode string to the default console,
+ using L"%s" format.
+
+ @param String String pointer.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+PrintString (
+ IN CHAR16 *String
+ )
+;
+
+/**
+ Prints a chracter to the default console,
+ using L"%c" format.
+
+ @param Character Character to print.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+PrintChar (
+ CHAR16 Character
+ )
+;
+
+/**
+ Prints a formatted unicode string to the default console, at
+ the supplied cursor position.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at
+ @param Fmt Format string
+ @param ... Variable argument list for formating string.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+PrintAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *Fmt,
+ ...
+ )
+;
+
+/**
+ Prints a unicode string to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at
+ @param String String pointer.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+PrintStringAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *String
+ )
+;
+
+/**
+ Prints a chracter to the default console, at
+ the supplied cursor position, using L"%c" format.
+
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at.
+ @param Character Character to print.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+PrintCharAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 Character
+ )
+;
+
+/**
+ Parse opcodes in the formset IFR binary.
+
+ @param FormSet Pointer of the FormSet data structure.
+
+ @retval EFI_SUCCESS Opcode parse success.
+ @retval Other Opcode parse fail.
+
+**/
+EFI_STATUS
+ParseOpCodes (
+ IN FORM_BROWSER_FORMSET *FormSet
+ )
+;
+
+/**
+ Free resources allocated for a FormSet.
+
+ @param FormSet Pointer of the FormSet
+
+**/
+VOID
+DestroyFormSet (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ )
+;
+
+/**
+ This function displays the page frame.
+
+**/
+VOID
+DisplayPageFrame (
+ VOID
+ )
+;
+
+/**
+ Create a new string in HII Package List.
+
+ @param String The String to be added
+ @param HiiHandle The package list in the HII database to insert the
+ specified string.
+
+ @return The output string.
+
+**/
+EFI_STRING_ID
+NewString (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+;
+
+/**
+ Delete a string from HII Package List.
+
+ @param StringId Id of the string in HII database.
+ @param HiiHandle The HII package list handle.
+
+ @retval EFI_SUCCESS The string was deleted successfully.
+
+**/
+EFI_STATUS
+DeleteString (
+ IN EFI_STRING_ID StringId,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+;
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param Token The String's ID.
+ @param HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+;
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param ArrayOfStrings The array of string to be printed.
+
+**/
+VOID
+CreateSharedPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 **ArrayOfStrings
+ )
+;
+
+/**
+ Routine used to abstract a generic dialog interface and return the selected key or string
+
+ @param NumberOfLines The number of lines for the dialog box
+ @param HotKey Defines whether a single character is parsed
+ (TRUE) and returned in KeyValue or a string is
+ returned in StringBuffer. Two special characters
+ are considered when entering a string, a SCAN_ESC
+ and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates
+ string input and returns
+ @param MaximumStringSize The maximum size in bytes of a typed in string
+ (each character is a CHAR16) and the minimum
+ string returned is two bytes
+ @param StringBuffer The passed in pointer to the buffer which will
+ hold the typed in string if HotKey is FALSE
+ @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
+ @param String Pointer to the first string in the list
+ @param ... A series of (quantity == NumberOfLines) text
+ strings which will be used to construct the dialog
+ box
+
+ @retval EFI_SUCCESS Displayed dialog and received user interaction
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.
+ (StringBuffer == NULL) && (HotKey == FALSE))
+ @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine
+
+**/
+EFI_STATUS
+CreateDialog (
+ IN UINTN NumberOfLines,
+ IN BOOLEAN HotKey,
+ IN UINTN MaximumStringSize,
+ OUT CHAR16 *StringBuffer,
+ OUT EFI_INPUT_KEY *KeyValue,
+ IN CHAR16 *String,
+ ...
+ )
+;
+
+/**
+ Get Question's current Value.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Question to be initialized.
+ @param Cached TRUE: get from Edit copy FALSE: get from original
+ Storage
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetQuestionValue (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN BOOLEAN Cached
+ )
+;
+
+/**
+ Save Question Value to edit copy(cached) or Storage(uncached).
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Pointer to the Question.
+ @param Cached TRUE: set to Edit copy FALSE: set to original
+ Storage
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+SetQuestionValue (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN BOOLEAN Cached
+ )
+;
+
+/**
+ Perform inconsistent check for a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question The Question to be validated.
+ @param Type Validation type: InConsistent or NoSubmit
+
+ @retval EFI_SUCCESS Form validation pass.
+ @retval other Form validation failed.
+
+**/
+EFI_STATUS
+ValidateQuestion (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINTN Type
+ )
+;
+
+/**
+ Submit a Form.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+SubmitForm (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+;
+
+/**
+ Reset Question to its default value.
+
+ @param FormSet The form set.
+ @param Form The form.
+ @param Question The question.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINT16 DefaultId
+ )
+;
+
+/**
+ Get current setting of Questions.
+
+ @param FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+InitializeCurrentSetting (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ )
+;
+
+/**
+ Initialize the internal data structure of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @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
+InitializeFormSet (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT FORM_BROWSER_FORMSET *FormSet
+ )
+;
+
+/**
+ Reset Questions in a Form to their default value.
+
+ @param FormSet FormSet data structure.
+ @param Form The Form which to be reset.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+ExtractFormDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT16 DefaultId
+ )
+;
+
+/**
+ Initialize Question's Edit copy from Storage.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LoadFormConfig (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+;
+
+/**
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
+
+ @param Storage The Storage to be conveted.
+ @param ConfigResp The returned <ConfigResp>.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+StorageToConfigResp (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 **ConfigResp
+ )
+;
+
+/**
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
+
+ @param Storage The Storage to receive the settings.
+ @param ConfigResp The <ConfigResp> to be converted.
+
+ @retval EFI_SUCCESS Convert success.
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.
+
+**/
+EFI_STATUS
+ConfigRespToStorage (
+ IN FORMSET_STORAGE *Storage,
+ IN CHAR16 *ConfigResp
+ )
+;
+
+/**
+ Fill storage's edit copy with settings requested from Configuration Driver.
+
+ @param FormSet FormSet data structure.
+ @param Storage Buffer Storage.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+LoadStorage (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORMSET_STORAGE *Storage
+ )
+;
+
+/**
+ Fetch the Ifr binary data of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @param BinaryLength The length of the FormSet IFR binary.
+ @param BinaryData The buffer designed to receive the FormSet.
+
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.
+ BufferLength was updated.
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
+ be found with the requested FormId.
+
+**/
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT UINTN *BinaryLength,
+ OUT UINT8 **BinaryData
+ )
+;
+
+/**
+ This is the routine which an external caller uses to direct the browser
+ where to obtain it's information.
+
+
+ @param This The Form Browser protocol instanse.
+ @param Handles A pointer to an array of Handles. If HandleCount > 1 we
+ display a list of the formsets for the handles specified.
+ @param HandleCount The number of Handles specified in Handle.
+ @param FormSetGuid This field points to the EFI_GUID which must match the Guid
+ field in the EFI_IFR_FORM_SET op-code for the specified
+ forms-based package. If FormSetGuid is NULL, then this
+ function will display the first found forms package.
+ @param FormId This field specifies which EFI_IFR_FORM to render as the first
+ displayable page. If this field has a value of 0x0000, then
+ the forms browser will render the specified forms in their encoded order.
+ ScreenDimenions - This allows the browser to be called so that it occupies a
+ portion of the physical screen instead of dynamically determining the screen dimensions.
+ ActionRequest - Points to the action recommended by the form.
+ @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
+ characters.
+ @param ActionRequest Points to the action recommended by the form.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_NOT_FOUND No valid forms could be found to display.
+
+**/
+EFI_STATUS
+EFIAPI
+SendForm (
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN EFI_HII_HANDLE *Handles,
+ IN UINTN HandleCount,
+ IN EFI_GUID *FormSetGuid, OPTIONAL
+ IN UINT16 FormId, OPTIONAL
+ IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
+ )
+;
+
+/**
+ This function is called by a callback handler to retrieve uncommitted state
+ data from the browser.
+
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
+ instance.
+ @param ResultsDataSize A pointer to the size of the buffer associated
+ with ResultsData.
+ @param ResultsData A string returned from an IFR browser or
+ equivalent. The results string will have no
+ routing information in them.
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve
+ (if RetrieveData = TRUE) data from the uncommitted
+ browser state information or set (if RetrieveData
+ = FALSE) data in the uncommitted browser state
+ information.
+ @param VariableGuid An optional field to indicate the target variable
+ GUID name to use.
+ @param VariableName An optional field to indicate the target
+ human-readable variable name.
+
+ @retval EFI_SUCCESS The results have been distributed or are awaiting
+ distribution.
+ @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to
+ contain the results data.
+
+**/
+EFI_STATUS
+EFIAPI
+BrowserCallback (
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
+ IN OUT UINTN *ResultsDataSize,
+ IN OUT EFI_STRING ResultsData,
+ IN BOOLEAN RetrieveData,
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL
+ IN CONST CHAR16 *VariableName OPTIONAL
+ )
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
index 04b9f69..a66e946 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
@@ -1,2874 +1,2858 @@
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- Ui.c
-
-Abstract:
-
- Implementation for UI.
-
-Revision History
-
-
-**/
-
-#include "Ui.h"
-#include "Setup.h"
-
-LIST_ENTRY Menu;
-LIST_ENTRY gMenuList;
-MENU_REFRESH_ENTRY *gMenuRefreshHead;
-
-//
-// Search table for UiDisplayMenu()
-//
-SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {
- {
- SCAN_UP,
- UiUp,
- },
- {
- SCAN_DOWN,
- UiDown,
- },
- {
- SCAN_PAGE_UP,
- UiPageUp,
- },
- {
- SCAN_PAGE_DOWN,
- UiPageDown,
- },
- {
- SCAN_ESC,
- UiReset,
- },
- {
- SCAN_F2,
- UiPrevious,
- },
- {
- SCAN_LEFT,
- UiLeft,
- },
- {
- SCAN_RIGHT,
- UiRight,
- },
- {
- SCAN_F9,
- UiDefault,
- },
- {
- SCAN_F10,
- UiSave
- }
-};
-
-SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {
- {
- UiNoOperation,
- CfUiNoOperation,
- },
- {
- UiDefault,
- CfUiDefault,
- },
- {
- UiSelect,
- CfUiSelect,
- },
- {
- UiUp,
- CfUiUp,
- },
- {
- UiDown,
- CfUiDown,
- },
- {
- UiLeft,
- CfUiLeft,
- },
- {
- UiRight,
- CfUiRight,
- },
- {
- UiReset,
- CfUiReset,
- },
- {
- UiSave,
- CfUiSave,
- },
- {
- UiPrevious,
- CfUiPrevious,
- },
- {
- UiPageUp,
- CfUiPageUp,
- },
- {
- UiPageDown,
- CfUiPageDown
- }
-};
-
-
-/**
- Set Buffer to Value for Size bytes.
-
- @param Buffer Memory to set.
- @param Size Number of bytes to set
- @param Value Value of the set operation.
-
- @return None
-
-**/
-VOID
-SetUnicodeMem (
- IN VOID *Buffer,
- IN UINTN Size,
- IN CHAR16 Value
- )
-{
- CHAR16 *Ptr;
-
- Ptr = Buffer;
- while (Size--) {
- *(Ptr++) = Value;
- }
-}
-
-
-/**
- Initialize Menu option list.
-
- None.
-
- @return None.
-
-**/
-VOID
-UiInitMenu (
- VOID
- )
-{
- InitializeListHead (&Menu);
-}
-
-
-/**
- Initialize Menu option list.
-
- None.
-
- @return None.
-
-**/
-VOID
-UiInitMenuList (
- VOID
- )
-{
- InitializeListHead (&gMenuList);
-}
-
-
-/**
- Remove a Menu in list, and return FormId/QuestionId for previous Menu.
-
- @param Selection Menu selection.
-
- @return None.
-
-**/
-VOID
-UiRemoveMenuListEntry (
- IN OUT UI_MENU_SELECTION *Selection
- )
-{
- UI_MENU_LIST *UiMenuList;
-
- if (!IsListEmpty (&gMenuList)) {
- UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
-
- Selection->FormId = UiMenuList->FormId;
- Selection->QuestionId = UiMenuList->QuestionId;
- RemoveEntryList (&UiMenuList->MenuLink);
- gBS->FreePool (UiMenuList);
- }
-}
-
-
-/**
- Free Menu option linked list.
-
- None.
-
- @return None.
-
-**/
-VOID
-UiFreeMenuList (
- VOID
- )
-{
- UI_MENU_LIST *UiMenuList;
-
- while (!IsListEmpty (&gMenuList)) {
- UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
- RemoveEntryList (&UiMenuList->MenuLink);
- gBS->FreePool (UiMenuList);
- }
-}
-
-
-/**
- Add one menu entry to the linked lst
-
- @param Selection Menu selection.
-
- @return None.
-
-**/
-VOID
-UiAddMenuListEntry (
- IN UI_MENU_SELECTION *Selection
- )
-{
- UI_MENU_LIST *UiMenuList;
-
- UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
- ASSERT (UiMenuList != NULL);
-
- UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;
- UiMenuList->FormId = Selection->FormId;
- UiMenuList->QuestionId = Selection->QuestionId;
-
- InsertHeadList (&gMenuList, &UiMenuList->MenuLink);
-}
-
-
-/**
- Free Menu option linked list.
-
- None.
-
- @return None.
-
-**/
-VOID
-UiFreeMenu (
- VOID
- )
-{
- UI_MENU_OPTION *MenuOption;
-
- while (!IsListEmpty (&Menu)) {
- MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);
- RemoveEntryList (&MenuOption->Link);
-
- //
- // We allocated space for this description when we did a GetToken, free it here
- //
- if (MenuOption->Skip != 0) {
- //
- // For date/time, MenuOption->Description is shared by three Menu Options
- // Data format : [01/02/2004] [11:22:33]
- // Line number : 0 0 1 0 0 1
- //
- gBS->FreePool (MenuOption->Description);
- }
- gBS->FreePool (MenuOption);
- }
-}
-
-
-/**
- Free Menu option linked list.
-
- None.
-
- @return None.
-
-**/
-VOID
-UiFreeRefreshList (
- VOID
- )
-{
- MENU_REFRESH_ENTRY *OldMenuRefreshEntry;
-
- while (gMenuRefreshHead != NULL) {
- OldMenuRefreshEntry = gMenuRefreshHead->Next;
- gBS->FreePool (gMenuRefreshHead);
- gMenuRefreshHead = OldMenuRefreshEntry;
- }
-
- gMenuRefreshHead = NULL;
-}
-
-
-
-/**
- Refresh screen.
-
- None.
-
- @return None.
-
-**/
-VOID
-RefreshForm (
- VOID
- )
-{
- CHAR16 *OptionString;
- MENU_REFRESH_ENTRY *MenuRefreshEntry;
- UINTN Index;
- UINTN Loop;
- EFI_STATUS Status;
- UI_MENU_SELECTION *Selection;
- FORM_BROWSER_STATEMENT *Question;
-
- OptionString = NULL;
-
- if (gMenuRefreshHead != NULL) {
-
- MenuRefreshEntry = gMenuRefreshHead;
-
- do {
- gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);
-
- Selection = MenuRefreshEntry->Selection;
- Question = MenuRefreshEntry->MenuOption->ThisTag;
-
- //
- // Don't update Question being edited
- //
- if (Question != MenuRefreshEntry->Selection->Statement) {
-
- Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);
-
- if (OptionString != NULL) {
- //
- // If leading spaces on OptionString - remove the spaces
- //
- for (Index = 0; OptionString[Index] == L' '; Index++)
- ;
-
- for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {
- OptionString[Loop] = OptionString[Index];
- Loop++;
- }
-
- OptionString[Loop] = CHAR_NULL;
-
- PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);
- gBS->FreePool (OptionString);
- }
- }
-
- MenuRefreshEntry = MenuRefreshEntry->Next;
-
- } while (MenuRefreshEntry != NULL);
- }
-}
-
-
-/**
- Wait for a given event to fire, or for an optional timeout to expire.
-
- @param Event The event to wait for
- @param Timeout An optional timeout value in 100 ns units.
- @param RefreshInterval Menu refresh interval (in seconds).
-
- @retval EFI_SUCCESS Event fired before Timeout expired.
- @retval EFI_TIME_OUT Timout expired before Event fired.
-
-**/
-EFI_STATUS
-UiWaitForSingleEvent (
- IN EFI_EVENT Event,
- IN UINT64 Timeout, OPTIONAL
- IN UINT8 RefreshInterval OPTIONAL
- )
-{
- EFI_STATUS Status;
- UINTN Index;
- EFI_EVENT TimerEvent;
- EFI_EVENT WaitList[2];
-
- if (Timeout) {
- //
- // Create a timer event
- //
- Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
- if (!EFI_ERROR (Status)) {
- //
- // Set the timer event
- //
- gBS->SetTimer (
- TimerEvent,
- TimerRelative,
- Timeout
- );
-
- //
- // Wait for the original event or the timer
- //
- WaitList[0] = Event;
- WaitList[1] = TimerEvent;
- Status = gBS->WaitForEvent (2, WaitList, &Index);
- gBS->CloseEvent (TimerEvent);
-
- //
- // If the timer expired, change the return to timed out
- //
- if (!EFI_ERROR (Status) && Index == 1) {
- Status = EFI_TIMEOUT;
- }
- }
- } else {
- //
- // Update screen every second
- //
- if (RefreshInterval == 0) {
- Timeout = ONE_SECOND;
- } else {
- Timeout = RefreshInterval * ONE_SECOND;
- }
-
- do {
- Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
-
- //
- // Set the timer event
- //
- gBS->SetTimer (
- TimerEvent,
- TimerRelative,
- Timeout
- );
-
- //
- // Wait for the original event or the timer
- //
- WaitList[0] = Event;
- WaitList[1] = TimerEvent;
- Status = gBS->WaitForEvent (2, WaitList, &Index);
-
- //
- // If the timer expired, update anything that needs a refresh and keep waiting
- //
- if (!EFI_ERROR (Status) && Index == 1) {
- Status = EFI_TIMEOUT;
- if (RefreshInterval != 0) {
- RefreshForm ();
- }
- }
-
- gBS->CloseEvent (TimerEvent);
- } while (Status == EFI_TIMEOUT);
- }
-
- return Status;
-}
-
-
-/**
- Add one menu option by specified description and context.
-
- @param String String description for this option.
- @param Handle Hii handle for the package list.
- @param Statement Statement of this Menu Option.
- @param NumberOfLines Display lines for this Menu Option.
- @param MenuItemCount The index for this Option in the Menu.
-
- @return None.
-
-**/
-VOID
-UiAddMenuOption (
- IN CHAR16 *String,
- IN EFI_HII_HANDLE Handle,
- IN FORM_BROWSER_STATEMENT *Statement,
- IN UINT16 NumberOfLines,
- IN UINT16 MenuItemCount
- )
-{
- UI_MENU_OPTION *MenuOption;
- UINTN Index;
- UINTN Count;
-
- Count = 1;
-
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
- //
- // Add three MenuOptions for Date/Time
- // Data format : [01/02/2004] [11:22:33]
- // Line number : 0 0 1 0 0 1
- //
- NumberOfLines = 0;
- Count = 3;
-
- if (Statement->Storage == NULL) {
- //
- // For RTC type of date/time, set default refresh interval to be 1 second
- //
- if (Statement->RefreshInterval == 0) {
- Statement->RefreshInterval = 1;
- }
- }
- }
-
- for (Index = 0; Index < Count; Index++) {
- MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
- ASSERT (MenuOption);
-
- MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;
- MenuOption->Description = String;
- MenuOption->Handle = Handle;
- MenuOption->ThisTag = Statement;
- MenuOption->EntryNumber = MenuItemCount;
-
- if (Index == 2) {
- //
- // Override LineNumber for the MenuOption in Date/Time sequence
- //
- MenuOption->Skip = 1;
- } else {
- MenuOption->Skip = NumberOfLines;
- }
- MenuOption->Sequence = Index;
-
- if (Statement->GrayOutExpression != NULL) {
- MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b;
- }
-
- if ((Statement->ValueExpression != NULL) ||
- (Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY)) {
- MenuOption->ReadOnly = TRUE;
- }
-
- InsertTailList (&Menu, &MenuOption->Link);
- }
-}
-
-
-/**
- Routine used to abstract a generic dialog interface and return the selected key or string
-
- @param NumberOfLines The number of lines for the dialog box
- @param HotKey Defines whether a single character is parsed
- (TRUE) and returned in KeyValue or a string is
- returned in StringBuffer. Two special characters
- are considered when entering a string, a SCAN_ESC
- and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates
- string input and returns
- @param MaximumStringSize The maximum size in bytes of a typed in string
- (each character is a CHAR16) and the minimum
- string returned is two bytes
- @param StringBuffer The passed in pointer to the buffer which will
- hold the typed in string if HotKey is FALSE
- @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
- @param String Pointer to the first string in the list
- @param ... A series of (quantity == NumberOfLines) text
- strings which will be used to construct the dialog
- box
-
- @retval EFI_SUCCESS Displayed dialog and received user interaction
- @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.
- (StringBuffer == NULL) && (HotKey == FALSE))
- @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine
-
-**/
-EFI_STATUS
-CreateDialog (
- IN UINTN NumberOfLines,
- IN BOOLEAN HotKey,
- IN UINTN MaximumStringSize,
- OUT CHAR16 *StringBuffer,
- OUT EFI_INPUT_KEY *KeyValue,
- IN CHAR16 *String,
- ...
- )
-{
- VA_LIST Marker;
- UINTN Count;
- EFI_INPUT_KEY Key;
- UINTN LargestString;
- CHAR16 *TempString;
- CHAR16 *BufferedString;
- CHAR16 *StackString;
- CHAR16 KeyPad[2];
- UINTN Start;
- UINTN Top;
- UINTN Index;
- EFI_STATUS Status;
- BOOLEAN SelectionComplete;
- UINTN InputOffset;
- UINTN CurrentAttribute;
- UINTN DimensionsWidth;
- UINTN DimensionsHeight;
-
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
-
- SelectionComplete = FALSE;
- InputOffset = 0;
- TempString = AllocateZeroPool (MaximumStringSize * 2);
- BufferedString = AllocateZeroPool (MaximumStringSize * 2);
- CurrentAttribute = gST->ConOut->Mode->Attribute;
-
- ASSERT (TempString);
- ASSERT (BufferedString);
-
- VA_START (Marker, String);
-
- //
- // Zero the outgoing buffer
- //
- ZeroMem (StringBuffer, MaximumStringSize);
-
- if (HotKey) {
- if (KeyValue == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- } else {
- if (StringBuffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- }
- //
- // Disable cursor
- //
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);
-
- LargestString = (GetStringWidth (String) / 2);
-
- if (*String == L' ') {
- InputOffset = 1;
- }
- //
- // Determine the largest string in the dialog box
- // Notice we are starting with 1 since String is the first string
- //
- for (Count = 1; Count < NumberOfLines; Count++) {
- StackString = VA_ARG (Marker, CHAR16 *);
-
- if (StackString[0] == L' ') {
- InputOffset = Count + 1;
- }
-
- if ((GetStringWidth (StackString) / 2) > LargestString) {
- //
- // Size of the string visually and subtract the width by one for the null-terminator
- //
- LargestString = (GetStringWidth (StackString) / 2);
- }
- }
-
- Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
- Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
-
- Count = 0;
-
- //
- // Display the Popup
- //
- CreateSharedPopUp (LargestString, NumberOfLines, &String);
-
- //
- // Take the first key typed and report it back?
- //
- if (HotKey) {
- Status = WaitForKeyStroke (&Key);
- ASSERT_EFI_ERROR (Status);
- CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
-
- } else {
- do {
- Status = WaitForKeyStroke (&Key);
-
- switch (Key.UnicodeChar) {
- case CHAR_NULL:
- switch (Key.ScanCode) {
- case SCAN_ESC:
- gBS->FreePool (TempString);
- gBS->FreePool (BufferedString);
- gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- return EFI_DEVICE_ERROR;
-
- default:
- break;
- }
-
- break;
-
- case CHAR_CARRIAGE_RETURN:
- SelectionComplete = TRUE;
- gBS->FreePool (TempString);
- gBS->FreePool (BufferedString);
- gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- return EFI_SUCCESS;
- break;
-
- case CHAR_BACKSPACE:
- if (StringBuffer[0] != CHAR_NULL) {
- for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {
- TempString[Index] = StringBuffer[Index];
- }
- //
- // Effectively truncate string by 1 character
- //
- TempString[Index - 1] = CHAR_NULL;
- StrCpy (StringBuffer, TempString);
- }
-
- default:
- //
- // If it is the beginning of the string, don't worry about checking maximum limits
- //
- if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
- StrnCpy (StringBuffer, &Key.UnicodeChar, 1);
- StrnCpy (TempString, &Key.UnicodeChar, 1);
- } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
- KeyPad[0] = Key.UnicodeChar;
- KeyPad[1] = CHAR_NULL;
- StrCat (StringBuffer, KeyPad);
- StrCat (TempString, KeyPad);
- }
- //
- // If the width of the input string is now larger than the screen, we nee to
- // adjust the index to start printing portions of the string
- //
- SetUnicodeMem (BufferedString, LargestString, L' ');
-
- PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
-
- if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {
- Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;
- } else {
- Index = 0;
- }
-
- for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {
- BufferedString[Count] = StringBuffer[Index];
- }
-
- PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
- break;
- }
- } while (!SelectionComplete);
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- return EFI_SUCCESS;
-}
-
-VOID
-CreateSharedPopUp (
- IN UINTN RequestedWidth,
- IN UINTN NumberOfLines,
- IN CHAR16 **ArrayOfStrings
- )
-{
- UINTN Index;
- UINTN Count;
- CHAR16 Character;
- UINTN Start;
- UINTN End;
- UINTN Top;
- UINTN Bottom;
- CHAR16 *String;
- UINTN DimensionsWidth;
- UINTN DimensionsHeight;
-
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
-
- Count = 0;
-
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
-
- if ((RequestedWidth + 2) > DimensionsWidth) {
- RequestedWidth = DimensionsWidth - 2;
- }
-
- //
- // Subtract the PopUp width from total Columns, allow for one space extra on
- // each end plus a border.
- //
- Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;
- End = Start + RequestedWidth + 1;
-
- Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
- Bottom = Top + NumberOfLines + 2;
-
- Character = BOXDRAW_DOWN_RIGHT;
- PrintCharAt (Start, Top, Character);
- Character = BOXDRAW_HORIZONTAL;
- for (Index = Start; Index + 2 < End; Index++) {
- PrintChar (Character);
- }
-
- Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
- Character = BOXDRAW_VERTICAL;
- for (Index = Top; Index + 2 < Bottom; Index++) {
- String = ArrayOfStrings[Count];
- Count++;
-
- //
- // This will clear the background of the line - we never know who might have been
- // here before us. This differs from the next clear in that it used the non-reverse
- // video for normal printing.
- //
- if (GetStringWidth (String) / 2 > 1) {
- ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
- }
-
- //
- // Passing in a space results in the assumption that this is where typing will occur
- //
- if (String[0] == L' ') {
- ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
- }
-
- //
- // Passing in a NULL results in a blank space
- //
- if (String[0] == CHAR_NULL) {
- ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
- }
-
- PrintStringAt (
- ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
- Index + 1,
- String
- );
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
- PrintCharAt (Start, Index + 1, Character);
- PrintCharAt (End - 1, Index + 1, Character);
- }
-
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (Start, Bottom - 1, Character);
- Character = BOXDRAW_HORIZONTAL;
- for (Index = Start; Index + 2 < End; Index++) {
- PrintChar (Character);
- }
-
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
-}
-
-VOID
-CreatePopUp (
- IN UINTN RequestedWidth,
- IN UINTN NumberOfLines,
- IN CHAR16 *ArrayOfStrings,
- ...
- )
-{
- CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);
-}
-
-
-/**
- Update status bar on the bottom of menu.
-
- @param MessageType The type of message to be shown.
- @param Flags The flags in Question header.
- @param State Set or clear.
-
- @return None.
-
-**/
-VOID
-UpdateStatusBar (
- IN UINTN MessageType,
- IN UINT8 Flags,
- IN BOOLEAN State
- )
-{
- UINTN Index;
- STATIC BOOLEAN InputError;
- CHAR16 *NvUpdateMessage;
- CHAR16 *InputErrorMessage;
-
- NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);
- InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);
-
- switch (MessageType) {
- case INPUT_ERROR:
- if (State) {
- gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
- PrintStringAt (
- gScreenDimensions.LeftColumn + gPromptBlockWidth,
- gScreenDimensions.BottomRow - 1,
- InputErrorMessage
- );
- InputError = TRUE;
- } else {
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
- for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
- PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");
- }
-
- InputError = FALSE;
- }
- break;
-
- case NV_UPDATE_REQUIRED:
- if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
- if (State) {
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
- PrintStringAt (
- gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
- gScreenDimensions.BottomRow - 1,
- NvUpdateMessage
- );
- gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
-
- gNvUpdateRequired = TRUE;
- } else {
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
- for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
- PrintAt (
- (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
- gScreenDimensions.BottomRow - 1,
- L" "
- );
- }
-
- gNvUpdateRequired = FALSE;
- }
- }
- break;
-
- case REFRESH_STATUS_BAR:
- if (InputError) {
- UpdateStatusBar (INPUT_ERROR, Flags, TRUE);
- }
-
- if (gNvUpdateRequired) {
- UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);
- }
- break;
-
- default:
- break;
- }
-
- gBS->FreePool (InputErrorMessage);
- gBS->FreePool (NvUpdateMessage);
- return ;
-}
-
-
-/**
- Get the supported width for a particular op-code
-
- @param Statement The FORM_BROWSER_STATEMENT structure passed in.
- @param Handle The handle in the HII database being used
-
- @return Returns the number of CHAR16 characters that is support.
-
-**/
-UINT16
-GetWidth (
- IN FORM_BROWSER_STATEMENT *Statement,
- IN EFI_HII_HANDLE Handle
- )
-{
- CHAR16 *String;
- UINTN Size;
- UINT16 Width;
-
- Size = 0;
-
- //
- // See if the second text parameter is really NULL
- //
- if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
- String = GetToken (Statement->TextTwo, Handle);
- Size = StrLen (String);
- gBS->FreePool (String);
- }
-
- if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||
- (Statement->Operand == EFI_IFR_REF_OP) ||
- (Statement->Operand == EFI_IFR_PASSWORD_OP) ||
- (Statement->Operand == EFI_IFR_ACTION_OP) ||
- (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||
- //
- // Allow a wide display if text op-code and no secondary text op-code
- //
- ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))
- ) {
- Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
- } else {
- Width = (UINT16) gPromptBlockWidth;
- }
-
- if (Statement->InSubtitle) {
- Width -= SUBTITLE_INDENT;
- }
-
- return Width;
-}
-
-
-/**
- Will copy LineWidth amount of a string in the OutputString buffer and return the
- number of CHAR16 characters that were copied into the OutputString buffer.
-
- @param InputString String description for this option.
- @param LineWidth Width of the desired string to extract in CHAR16
- characters
- @param Index Where in InputString to start the copy process
- @param OutputString Buffer to copy the string into
-
- @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.
-
-**/
-UINT16
-GetLineByWidth (
- IN CHAR16 *InputString,
- IN UINT16 LineWidth,
- IN OUT UINTN *Index,
- OUT CHAR16 **OutputString
- )
-{
- static BOOLEAN Finished;
- UINT16 Count;
- UINT16 Count2;
-
- if (Finished) {
- Finished = FALSE;
- return (UINT16) 0;
- }
-
- Count = LineWidth;
- Count2 = 0;
-
- *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));
-
- //
- // Ensure we have got a valid buffer
- //
- if (*OutputString != NULL) {
-
- //
- //NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.
- //To avoid displaying this empty line in screen, just skip the two CHARs here.
- //
- if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
- *Index = *Index + 2;
- }
-
- //
- // Fast-forward the string and see if there is a carriage-return in the string
- //
- for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
- ;
-
- //
- // Copy the desired LineWidth of data to the output buffer.
- // Also make sure that we don't copy more than the string.
- // Also make sure that if there are linefeeds, we account for them.
- //
- if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
- (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
- ) {
- //
- // Convert to CHAR16 value and show that we are done with this operation
- //
- LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);
- if (LineWidth != 0) {
- Finished = TRUE;
- }
- } else {
- if (Count2 == LineWidth) {
- //
- // Rewind the string from the maximum size until we see a space to break the line
- //
- for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
- ;
- if (LineWidth == 0) {
- LineWidth = Count;
- }
- } else {
- LineWidth = Count2;
- }
- }
-
- CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);
-
- //
- // If currently pointing to a space, increment the index to the first non-space character
- //
- for (;
- (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);
- (*Index)++
- )
- ;
- *Index = (UINT16) (*Index + LineWidth);
- return LineWidth;
- } else {
- return (UINT16) 0;
- }
-}
-
-
-/**
- Update display lines for a Menu Option.
-
- @param MenuOption The MenuOption to be checked.
-
- @retval TRUE This Menu Option is selectable.
- @retval FALSE This Menu Option could not be selected.
-
-**/
-VOID
-UpdateOptionSkipLines (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN CHAR16 **OptionalString,
- IN UINTN SkipValue
- )
-{
- UINTN Index;
- UINT16 Width;
- UINTN Row;
- UINTN OriginalRow;
- CHAR16 *OutputString;
- CHAR16 *OptionString;
-
- Row = 0;
- OptionString = *OptionalString;
- OutputString = NULL;
-
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
-
- if (OptionString != NULL) {
- Width = (UINT16) gOptionBlockWidth;
-
- OriginalRow = Row;
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&OptionString[Index])) {
- if (SkipValue == 0) {
- Row++;
- //
- // Since the Number of lines for this menu entry may or may not be reflected accurately
- // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
- // some testing to ensure we are keeping this in-sync.
- //
- // If the difference in rows is greater than or equal to the skip value, increase the skip value
- //
- if ((Row - OriginalRow) >= MenuOption->Skip) {
- MenuOption->Skip++;
- }
- }
- }
-
- gBS->FreePool (OutputString);
- if (SkipValue != 0) {
- SkipValue--;
- }
- }
-
- Row = OriginalRow;
- }
-
- *OptionalString = OptionString;
-}
-
-
-/**
- Check whether this Menu Option could be highlighted.
-
- @param MenuOption The MenuOption to be checked.
-
- @retval TRUE This Menu Option is selectable.
- @retval FALSE This Menu Option could not be selected.
-
-**/
-STATIC
-BOOLEAN
-IsSelectable (
- UI_MENU_OPTION *MenuOption
- )
-{
- if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||
- MenuOption->GrayOut || MenuOption->ReadOnly) {
- return FALSE;
- } else {
- return TRUE;
- }
-}
-
-
-/**
- Determine if the menu is the last menu that can be selected.
-
- @param Direction the scroll direction. False is down. True is up.
-
- @return FALSE -- the menu isn't the last menu that can be selected.
- @return TRUE -- the menu is the last menu that can be selected.
-
-**/
-STATIC
-BOOLEAN
-ValueIsScroll (
- IN BOOLEAN Direction,
- IN LIST_ENTRY *CurrentPos
- )
-{
- LIST_ENTRY *Temp;
- UI_MENU_OPTION *MenuOption;
-
- Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
-
- if (Temp == &Menu) {
- return TRUE;
- }
-
- for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
- MenuOption = MENU_OPTION_FROM_LINK (Temp);
- if (IsSelectable (MenuOption)) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-
-/**
- Move to next selectable statement.
-
- @param GoUp The navigation direction. TRUE: up, FALSE: down.
- @param CurrentPosition Current position.
-
- @return The row distance from current MenuOption to next selectable MenuOption.
-
-**/
-STATIC
-INTN
-MoveToNextStatement (
- IN BOOLEAN GoUp,
- IN OUT LIST_ENTRY **CurrentPosition
- )
-{
- INTN Distance;
- LIST_ENTRY *Pos;
- BOOLEAN HitEnd;
- UI_MENU_OPTION *NextMenuOption;
-
- Distance = 0;
- Pos = *CurrentPosition;
- HitEnd = FALSE;
-
- while (TRUE) {
- NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
- if (IsSelectable (NextMenuOption)) {
- break;
- }
- if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
- HitEnd = TRUE;
- break;
- }
- Distance += NextMenuOption->Skip;
- Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);
- }
-
- if (HitEnd) {
- //
- // If we hit end there is still no statement can be focused,
- // we go backwards to find the statement can be focused.
- //
- Distance = 0;
- Pos = *CurrentPosition;
-
- while (TRUE) {
- NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
- if (IsSelectable (NextMenuOption)) {
- break;
- }
- if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
- ASSERT (FALSE);
- break;
- }
- Distance -= NextMenuOption->Skip;
- Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);
- }
- }
-
- *CurrentPosition = &NextMenuOption->Link;
- return Distance;
-}
-
-
-/**
- Adjust Data and Time position accordingly.
- Data format : [01/02/2004] [11:22:33]
- Line number : 0 0 1 0 0 1
-
- @param DirectionUp the up or down direction. False is down. True is
- up.
- @param CurrentPosition Current position. On return: Point to the last
- Option (Year or Second) if up; Point to the first
- Option (Month or Hour) if down.
-
- @return Return line number to pad. It is possible that we stand on a zero-advance
- @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
-
-**/
-STATIC
-UINTN
-AdjustDateAndTimePosition (
- IN BOOLEAN DirectionUp,
- IN OUT LIST_ENTRY **CurrentPosition
- )
-{
- UINTN Count;
- LIST_ENTRY *NewPosition;
- UI_MENU_OPTION *MenuOption;
- UINTN PadLineNumber;
-
- PadLineNumber = 0;
- NewPosition = *CurrentPosition;
- MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
-
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
- (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
- //
- // Calculate the distance from current position to the last Date/Time MenuOption
- //
- Count = 0;
- while (MenuOption->Skip == 0) {
- Count++;
- NewPosition = NewPosition->ForwardLink;
- MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
- PadLineNumber = 1;
- }
-
- NewPosition = *CurrentPosition;
- if (DirectionUp) {
- //
- // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
- // to be one that back to the previous set of MenuOptions, we need to advance to the first
- // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate
- // checking can be done.
- //
- while (Count++ < 2) {
- NewPosition = NewPosition->BackLink;
- }
- } else {
- //
- // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended
- // to be one that progresses to the next set of MenuOptions, we need to advance to the last
- // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate
- // checking can be done.
- //
- while (Count-- > 0) {
- NewPosition = NewPosition->ForwardLink;
- }
- }
-
- *CurrentPosition = NewPosition;
- }
-
- return PadLineNumber;
-}
-
-
-/**
- Display menu and wait for user to select one menu option, then return it.
- If AutoBoot is enabled, then if user doesn't select any option,
- after period of time, it will automatically return the first menu option.
-
-
- @return Return the pointer of the menu which selected,
- @return otherwise return NULL.
-
-**/
-EFI_STATUS
-UiDisplayMenu (
- IN OUT UI_MENU_SELECTION *Selection
- )
-{
- INTN SkipValue;
- INTN Difference;
- INTN OldSkipValue;
- UINTN DistanceValue;
- UINTN Row;
- UINTN Col;
- UINTN Temp;
- UINTN Temp2;
- UINTN TopRow;
- UINTN BottomRow;
- UINTN OriginalRow;
- UINTN Index;
- UINT32 Count;
- UINT16 Width;
- CHAR16 *StringPtr;
- CHAR16 *OptionString;
- CHAR16 *OutputString;
- CHAR16 *FormattedString;
- CHAR16 YesResponse;
- CHAR16 NoResponse;
- BOOLEAN NewLine;
- BOOLEAN Repaint;
- BOOLEAN SavedValue;
- EFI_STATUS Status;
- EFI_INPUT_KEY Key;
- LIST_ENTRY *Link;
- LIST_ENTRY *NewPos;
- LIST_ENTRY *TopOfScreen;
- LIST_ENTRY *SavedListEntry;
- UI_MENU_OPTION *MenuOption;
- UI_MENU_OPTION *NextMenuOption;
- UI_MENU_OPTION *SavedMenuOption;
- UI_MENU_OPTION *PreviousMenuOption;
- UI_CONTROL_FLAG ControlFlag;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- MENU_REFRESH_ENTRY *MenuRefreshEntry;
- UI_SCREEN_OPERATION ScreenOperation;
- UINT8 MinRefreshInterval;
- UINTN BufferSize;
- UINT16 DefaultId;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- FORM_BROWSER_STATEMENT *Statement;
-
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- Status = EFI_SUCCESS;
- FormattedString = NULL;
- OptionString = NULL;
- ScreenOperation = UiNoOperation;
- NewLine = TRUE;
- MinRefreshInterval = 0;
- DefaultId = 0;
-
- OutputString = NULL;
- gUpArrow = FALSE;
- gDownArrow = FALSE;
- SkipValue = 0;
- OldSkipValue = 0;
- MenuRefreshEntry = gMenuRefreshHead;
-
- NextMenuOption = NULL;
- PreviousMenuOption = NULL;
- SavedMenuOption = NULL;
-
- ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
-
- if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
- TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
- Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
- } else {
- TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
- Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
- }
-
- Col = LocalScreen.LeftColumn;
- BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;
-
- Selection->TopRow = TopRow;
- Selection->BottomRow = BottomRow;
- Selection->PromptCol = Col;
- Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
- Selection->Statement = NULL;
-
- TopOfScreen = Menu.ForwardLink;
- Repaint = TRUE;
- MenuOption = NULL;
-
- //
- // Get user's selection
- //
- NewPos = Menu.ForwardLink;
-
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);
- UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
-
- ControlFlag = CfInitialization;
- Selection->Action = UI_ACTION_NONE;
- while (TRUE) {
- switch (ControlFlag) {
- case CfInitialization:
- if (IsListEmpty (&Menu)) {
- ControlFlag = CfReadKey;
- } else {
- ControlFlag = CfCheckSelection;
- }
- break;
-
- case CfCheckSelection:
- if (Selection->Action != UI_ACTION_NONE) {
- ControlFlag = CfExit;
- } else {
- ControlFlag = CfRepaint;
- }
- break;
-
- case CfRepaint:
- ControlFlag = CfRefreshHighLight;
-
- if (Repaint) {
- //
- // Display menu
- //
- gDownArrow = FALSE;
- gUpArrow = FALSE;
- Row = TopRow;
-
- Temp = SkipValue;
- Temp2 = SkipValue;
-
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- TopRow - SCROLL_ARROW_HEIGHT,
- BottomRow + SCROLL_ARROW_HEIGHT,
- FIELD_TEXT | FIELD_BACKGROUND
- );
-
- UiFreeRefreshList ();
- MinRefreshInterval = 0;
-
- for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
- MenuOption = MENU_OPTION_FROM_LINK (Link);
- MenuOption->Row = Row;
- MenuOption->Col = Col;
- MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
-
- Statement = MenuOption->ThisTag;
- if (Statement->InSubtitle) {
- MenuOption->Col += SUBTITLE_INDENT;
- }
-
- if (MenuOption->GrayOut) {
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
- } else {
- if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {
- gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
- }
- }
-
- Width = GetWidth (Statement, MenuOption->Handle);
- OriginalRow = Row;
-
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
- if ((Temp == 0) && (Row <= BottomRow)) {
- PrintStringAt (MenuOption->Col, Row, OutputString);
- }
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&MenuOption->Description[Index])) {
- if (Temp == 0) {
- Row++;
- }
- }
-
- gBS->FreePool (OutputString);
- if (Temp != 0) {
- Temp--;
- }
- }
-
- Temp = 0;
- Row = OriginalRow;
-
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
-
- if (OptionString != NULL) {
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
- //
- // If leading spaces on OptionString - remove the spaces
- //
- for (Index = 0; OptionString[Index] == L' '; Index++) {
- MenuOption->OptCol++;
- }
-
- for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
- OptionString[Count] = OptionString[Index];
- Count++;
- }
-
- OptionString[Count] = CHAR_NULL;
- }
-
- //
- // If Question request refresh, register the op-code
- //
- if (Statement->RefreshInterval != 0) {
- //
- // Menu will be refreshed at minimal interval of all Questions
- // which have refresh request
- //
- if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {
- MinRefreshInterval = Statement->RefreshInterval;
- }
-
- if (gMenuRefreshHead == NULL) {
- MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
- ASSERT (MenuRefreshEntry != NULL);
- MenuRefreshEntry->MenuOption = MenuOption;
- MenuRefreshEntry->Selection = Selection;
- MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
- MenuRefreshEntry->CurrentRow = MenuOption->Row;
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
- gMenuRefreshHead = MenuRefreshEntry;
- } else {
- //
- // Advance to the last entry
- //
- for (MenuRefreshEntry = gMenuRefreshHead;
- MenuRefreshEntry->Next != NULL;
- MenuRefreshEntry = MenuRefreshEntry->Next
- )
- ;
- MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
- ASSERT (MenuRefreshEntry->Next != NULL);
- MenuRefreshEntry = MenuRefreshEntry->Next;
- MenuRefreshEntry->MenuOption = MenuOption;
- MenuRefreshEntry->Selection = Selection;
- MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
- MenuRefreshEntry->CurrentRow = MenuOption->Row;
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
- }
- }
-
- Width = (UINT16) gOptionBlockWidth;
- OriginalRow = Row;
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
- if ((Temp2 == 0) && (Row <= BottomRow)) {
- PrintStringAt (MenuOption->OptCol, Row, OutputString);
- }
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&OptionString[Index])) {
- if (Temp2 == 0) {
- Row++;
- //
- // Since the Number of lines for this menu entry may or may not be reflected accurately
- // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
- // some testing to ensure we are keeping this in-sync.
- //
- // If the difference in rows is greater than or equal to the skip value, increase the skip value
- //
- if ((Row - OriginalRow) >= MenuOption->Skip) {
- MenuOption->Skip++;
- }
- }
- }
-
- gBS->FreePool (OutputString);
- if (Temp2 != 0) {
- Temp2--;
- }
- }
-
- Temp2 = 0;
- Row = OriginalRow;
-
- gBS->FreePool (OptionString);
- }
- //
- // If this is a text op with secondary text information
- //
- if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
- StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle);
-
- Width = (UINT16) gOptionBlockWidth;
- OriginalRow = Row;
-
- for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
- if ((Temp == 0) && (Row <= BottomRow)) {
- PrintStringAt (MenuOption->OptCol, Row, OutputString);
- }
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&StringPtr[Index])) {
- if (Temp2 == 0) {
- Row++;
- //
- // Since the Number of lines for this menu entry may or may not be reflected accurately
- // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
- // some testing to ensure we are keeping this in-sync.
- //
- // If the difference in rows is greater than or equal to the skip value, increase the skip value
- //
- if ((Row - OriginalRow) >= MenuOption->Skip) {
- MenuOption->Skip++;
- }
- }
- }
-
- gBS->FreePool (OutputString);
- if (Temp2 != 0) {
- Temp2--;
- }
- }
-
- Row = OriginalRow;
- gBS->FreePool (StringPtr);
- }
-
- //
- // Need to handle the bottom of the display
- //
- if (MenuOption->Skip > 1) {
- Row += MenuOption->Skip - SkipValue;
- SkipValue = 0;
- } else {
- Row += MenuOption->Skip;
- }
-
- if (Row > BottomRow) {
- if (!ValueIsScroll (FALSE, Link)) {
- gDownArrow = TRUE;
- }
-
- Row = BottomRow + 1;
- break;
- }
- }
-
- if (!ValueIsScroll (TRUE, TopOfScreen)) {
- gUpArrow = TRUE;
- }
-
- if (gUpArrow) {
- gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
- PrintAt (
- LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
- TopRow - SCROLL_ARROW_HEIGHT,
- L"%c",
- ARROW_UP
- );
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
- }
-
- if (gDownArrow) {
- gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
- PrintAt (
- LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
- BottomRow + SCROLL_ARROW_HEIGHT,
- L"%c",
- ARROW_DOWN
- );
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
- }
-
- MenuOption = NULL;
- }
- break;
-
- case CfRefreshHighLight:
- //
- // MenuOption: Last menu option that need to remove hilight
- // MenuOption is set to NULL in Repaint
- // NewPos: Current menu option that need to hilight
- //
- ControlFlag = CfUpdateHelpString;
-
- //
- // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
- // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
- //
- SavedValue = Repaint;
- Repaint = FALSE;
-
- if (Selection->QuestionId != 0) {
- NewPos = Menu.ForwardLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
-
- while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) {
- NewPos = NewPos->ForwardLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
- }
- if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {
- //
- // Target Question found, find its MenuOption
- //
- Link = TopOfScreen;
-
- for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
- Index += SavedMenuOption->Skip;
- Link = Link->ForwardLink;
- }
-
- if (Link != NewPos || Index > BottomRow) {
- //
- // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page
- //
- Link = NewPos;
- for (Index = TopRow; Index <= BottomRow; ) {
- Link = Link->BackLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
- Index += SavedMenuOption->Skip;
- }
- TopOfScreen = Link->ForwardLink;
-
- Repaint = TRUE;
- NewLine = TRUE;
- ControlFlag = CfRepaint;
- break;
- }
- } else {
- //
- // Target Question not found, highlight the default menu option
- //
- NewPos = TopOfScreen;
- }
-
- Selection->QuestionId = 0;
- }
-
- if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {
- if (MenuOption != NULL) {
- //
- // Remove highlight on last Menu Option
- //
- gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
- if (OptionString != NULL) {
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
- (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
- ) {
- //
- // If leading spaces on OptionString - remove the spaces
- //
- for (Index = 0; OptionString[Index] == L' '; Index++)
- ;
-
- for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
- OptionString[Count] = OptionString[Index];
- Count++;
- }
-
- OptionString[Count] = CHAR_NULL;
- }
-
- Width = (UINT16) gOptionBlockWidth;
- OriginalRow = MenuOption->Row;
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
- PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
- }
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&OptionString[Index])) {
- MenuOption->Row++;
- }
-
- gBS->FreePool (OutputString);
- }
-
- MenuOption->Row = OriginalRow;
-
- gBS->FreePool (OptionString);
- } else {
- if (NewLine) {
- if (MenuOption->GrayOut) {
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
- } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
- gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
- }
-
- OriginalRow = MenuOption->Row;
- Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
-
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
- PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
- }
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&MenuOption->Description[Index])) {
- MenuOption->Row++;
- }
-
- gBS->FreePool (OutputString);
- }
-
- MenuOption->Row = OriginalRow;
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
- }
- }
- }
-
- //
- // This is only possible if we entered this page and the first menu option is
- // a "non-menu" item. In that case, force it UiDown
- //
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);
- if (!IsSelectable (MenuOption)) {
- ASSERT (ScreenOperation == UiNoOperation);
- ScreenOperation = UiDown;
- ControlFlag = CfScreenOperation;
- break;
- }
-
- //
- // This is the current selected statement
- //
- Statement = MenuOption->ThisTag;
- Selection->Statement = Statement;
-
- //
- // Set reverse attribute
- //
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
- gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
-
- //
- // Assuming that we have a refresh linked-list created, lets annotate the
- // appropriate entry that we are highlighting with its new attribute. Just prior to this
- // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
- //
- if (gMenuRefreshHead != NULL) {
- for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
- if (MenuRefreshEntry->MenuOption == MenuOption) {
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;
- }
- }
- }
-
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
- if (OptionString != NULL) {
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
- //
- // If leading spaces on OptionString - remove the spaces
- //
- for (Index = 0; OptionString[Index] == L' '; Index++)
- ;
-
- for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
- OptionString[Count] = OptionString[Index];
- Count++;
- }
-
- OptionString[Count] = CHAR_NULL;
- }
- Width = (UINT16) gOptionBlockWidth;
-
- OriginalRow = MenuOption->Row;
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
- PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
- }
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&OptionString[Index])) {
- MenuOption->Row++;
- }
-
- gBS->FreePool (OutputString);
- }
-
- MenuOption->Row = OriginalRow;
-
- gBS->FreePool (OptionString);
- } else {
- if (NewLine) {
- OriginalRow = MenuOption->Row;
-
- Width = GetWidth (Statement, MenuOption->Handle);
-
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
- if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
- PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
- }
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&MenuOption->Description[Index])) {
- MenuOption->Row++;
- }
-
- gBS->FreePool (OutputString);
- }
-
- MenuOption->Row = OriginalRow;
-
- }
- }
-
- if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||
- ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||
- (ScreenOperation == UiNoOperation)
- ) {
- UpdateKeyHelp (MenuOption, FALSE);
- }
- //
- // Clear reverse attribute
- //
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
- }
- //
- // Repaint flag will be used when process CfUpdateHelpString, so restore its value
- // if we didn't break halfway when process CfRefreshHighLight.
- //
- Repaint = SavedValue;
- break;
-
- case CfUpdateHelpString:
- ControlFlag = CfPrepareToReadKey;
-
- if ((Repaint || NewLine) && (gClassOfVfr != EFI_GENERAL_APPLICATION_SUBCLASS)) {
- //
- // Don't print anything if it is a NULL help token
- //
- if (MenuOption->ThisTag->Help == 0) {
- StringPtr = L"\0";
- } else {
- StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
- }
-
- ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);
-
- gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
-
- for (Index = 0; Index < BottomRow - TopRow; Index++) {
- //
- // Pad String with spaces to simulate a clearing of the previous line
- //
- for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {
- StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" ");
- }
-
- PrintStringAt (
- LocalScreen.RightColumn - gHelpBlockWidth,
- Index + TopRow,
- &FormattedString[Index * gHelpBlockWidth * 2]
- );
- }
- }
- //
- // Reset this flag every time we finish using it.
- //
- Repaint = FALSE;
- NewLine = FALSE;
- break;
-
- case CfPrepareToReadKey:
- ControlFlag = CfReadKey;
- ScreenOperation = UiNoOperation;
- break;
-
- case CfReadKey:
- ControlFlag = CfScreenOperation;
-
- //
- // Wait for user's selection
- //
- do {
- Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);
- } while (Status == EFI_TIMEOUT);
-
- if (Status == EFI_TIMEOUT) {
- Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
- } else {
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
- //
- // if we encounter error, continue to read another key in.
- //
- if (EFI_ERROR (Status)) {
- ControlFlag = CfReadKey;
- continue;
- }
- }
-
- if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {
- //
- // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
- //
- break;
- }
-
- switch (Key.UnicodeChar) {
- case CHAR_CARRIAGE_RETURN:
- ScreenOperation = UiSelect;
- gDirection = 0;
- break;
-
- //
- // We will push the adjustment of these numeric values directly to the input handler
- // NOTE: we won't handle manual input numeric
- //
- case '+':
- case '-':
- Statement = MenuOption->ThisTag;
- if ((Statement->Operand == EFI_IFR_DATE_OP)
- || (Statement->Operand == EFI_IFR_TIME_OP)
- || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))
- ){
- if (Key.UnicodeChar == '+') {
- gDirection = SCAN_RIGHT;
- } else {
- gDirection = SCAN_LEFT;
- }
- Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
- SafeFreePool (OptionString);
- }
- break;
-
- case '^':
- ScreenOperation = UiUp;
- break;
-
- case 'V':
- case 'v':
- ScreenOperation = UiDown;
- break;
-
- case ' ':
- if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
- if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) {
- ScreenOperation = UiSelect;
- }
- }
- break;
-
- case CHAR_NULL:
- if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||
- ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||
- ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||
- ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))
- ) {
- //
- // If the function key has been disabled, just ignore the key.
- //
- } else {
- for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {
- if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
- if (Key.ScanCode == SCAN_F9) {
- //
- // Reset to standard default
- //
- DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
- }
- ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
- break;
- }
- }
- }
- break;
- }
- break;
-
- case CfScreenOperation:
- if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {
- //
- // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
- // ignore the selection and go back to reading keys.
- //
- if (IsListEmpty (&Menu)) {
- ControlFlag = CfReadKey;
- break;
- }
- //
- // if there is nothing logical to place a cursor on, just move on to wait for a key.
- //
- for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);
- if (IsSelectable (NextMenuOption)) {
- break;
- }
- }
-
- if (Link == &Menu) {
- ControlFlag = CfPrepareToReadKey;
- break;
- }
- } else if (ScreenOperation == UiReset) {
- //
- // Press ESC to exit FormSet
- //
- Selection->Action = UI_ACTION_EXIT;
- Selection->Statement = NULL;
- }
-
- for (Index = 0;
- Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
- Index++
- ) {
- if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
- ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
- break;
- }
- }
- break;
-
- case CfUiPrevious:
- ControlFlag = CfCheckSelection;
-
- if (IsListEmpty (&gMenuList)) {
- Selection->Action = UI_ACTION_NONE;
- if (IsListEmpty (&Menu)) {
- ControlFlag = CfReadKey;
- }
- break;
- }
-
- //
- // Remove the Cached page entry
- //
- UiRemoveMenuListEntry (Selection);
-
- Selection->Action = UI_ACTION_REFRESH_FORM;
- Selection->Statement = NULL;
- break;
-
- case CfUiSelect:
- ControlFlag = CfCheckSelection;
-
- Statement = MenuOption->ThisTag;
- if ((Statement->Operand == EFI_IFR_TEXT_OP) ||
- (Statement->Operand == EFI_IFR_DATE_OP) ||
- (Statement->Operand == EFI_IFR_TIME_OP) ||
- (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
- break;
- }
-
- //
- // Keep highlight on current MenuOption
- //
- Selection->QuestionId = Statement->QuestionId;
-
- switch (Statement->Operand) {
- case EFI_IFR_REF_OP:
- if (Statement->RefDevicePath != 0) {
- //
- // Goto another Hii Package list
- //
- ControlFlag = CfUiReset;
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
-
- StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);
- if (StringPtr == NULL) {
- //
- // No device path string not found, exit
- //
- Selection->Action = UI_ACTION_EXIT;
- Selection->Statement = NULL;
- break;
- }
- BufferSize = StrLen (StringPtr) / 2;
- DevicePath = AllocatePool (BufferSize);
-
- HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, StringPtr);
- Selection->Handle = HiiLibDevicePathToHiiHandle (DevicePath);
- if (Selection->Handle == NULL) {
- //
- // If target Hii Handle not found, exit
- //
- Selection->Action = UI_ACTION_EXIT;
- Selection->Statement = NULL;
- break;
- }
-
- gBS->FreePool (StringPtr);
- gBS->FreePool (DevicePath);
-
- CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
- Selection->FormId = Statement->RefFormId;
- Selection->QuestionId = Statement->RefQuestionId;
- } else if (!CompareGuid (&Statement->RefFormSetId, &gZeroGuid)) {
- //
- // Goto another Formset, check for uncommitted data
- //
- ControlFlag = CfUiReset;
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
-
- CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
- Selection->FormId = Statement->RefFormId;
- Selection->QuestionId = Statement->RefQuestionId;
- } else if (Statement->RefFormId != 0) {
- //
- // Goto another form inside this formset,
- //
- Selection->Action = UI_ACTION_REFRESH_FORM;
-
- //
- // Link current form so that we can always go back when someone hits the UiPrevious
- //
- UiAddMenuListEntry (Selection);
-
- Selection->FormId = Statement->RefFormId;
- Selection->QuestionId = Statement->RefQuestionId;
- } else if (Statement->RefQuestionId != 0) {
- //
- // Goto another Question
- //
- Selection->QuestionId = Statement->RefQuestionId;
-
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK)) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- } else {
- Repaint = TRUE;
- NewLine = TRUE;
- break;
- }
- }
- break;
-
- case EFI_IFR_ACTION_OP:
- //
- // Process the Config string <ConfigResp>
- //
- Status = ProcessQuestionConfig (Selection, Statement);
-
- if (EFI_ERROR (Status)) {
- break;
- }
-
- //
- // The action button may change some Question value, so refresh the form
- //
- Selection->Action = UI_ACTION_REFRESH_FORM;
- break;
-
- case EFI_IFR_RESET_BUTTON_OP:
- //
- // Reset Question to default value specified by DefaultId
- //
- ControlFlag = CfUiDefault;
- DefaultId = Statement->DefaultId;
- break;
-
- default:
- //
- // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
- //
- UpdateKeyHelp (MenuOption, TRUE);
- Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
-
- if (EFI_ERROR (Status)) {
- Repaint = TRUE;
- NewLine = TRUE;
- break;
- }
-
- if (OptionString != NULL) {
- PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);
- gBS->FreePool (OptionString);
- }
-
- Selection->Action = UI_ACTION_REFRESH_FORM;
- break;
- }
- break;
-
- case CfUiReset:
- //
- // We are going to leave current FormSet, so check uncommited data in this FormSet
- //
- ControlFlag = CfCheckSelection;
-
- if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
- //
- // There is no parent menu for FrontPage
- //
- Selection->Action = UI_ACTION_NONE;
- Selection->Statement = MenuOption->ThisTag;
- break;
- }
-
- //
- // If NV flag is up, prompt user
- //
- if (gNvUpdateRequired) {
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
-
- YesResponse = gYesResponse[0];
- NoResponse = gNoResponse[0];
-
- do {
- CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);
- } while
- (
- (Key.ScanCode != SCAN_ESC) &&
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
- );
-
- //
- // If the user hits the YesResponse key
- //
- if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
- } else {
- Repaint = TRUE;
- NewLine = TRUE;
-
- Selection->Action = UI_ACTION_NONE;
- break;
- }
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
-
- UiFreeMenuList ();
- gST->ConOut->ClearScreen (gST->ConOut);
- return EFI_SUCCESS;
-
- case CfUiLeft:
- ControlFlag = CfCheckSelection;
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
- if (MenuOption->Sequence != 0) {
- //
- // In the middle or tail of the Date/Time op-code set, go left.
- //
- NewPos = NewPos->BackLink;
- }
- }
- break;
-
- case CfUiRight:
- ControlFlag = CfCheckSelection;
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
- if (MenuOption->Sequence != 2) {
- //
- // In the middle or tail of the Date/Time op-code set, go left.
- //
- NewPos = NewPos->ForwardLink;
- }
- }
- break;
-
- case CfUiUp:
- ControlFlag = CfCheckSelection;
-
- SavedListEntry = TopOfScreen;
-
- if (NewPos->BackLink != &Menu) {
- NewLine = TRUE;
- //
- // Adjust Date/Time position before we advance forward.
- //
- AdjustDateAndTimePosition (TRUE, &NewPos);
-
- //
- // Caution that we have already rewind to the top, don't go backward in this situation.
- //
- if (NewPos->BackLink != &Menu) {
- NewPos = NewPos->BackLink;
- }
-
- PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);
- DistanceValue = PreviousMenuOption->Skip;
-
- //
- // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
- // to be one that back to the previous set of op-codes, we need to advance to the sencond
- // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
- // checking can be done.
- //
- DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);
-
- //
- // Check the previous menu entry to see if it was a zero-length advance. If it was,
- // don't worry about a redraw.
- //
- if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
- Repaint = TRUE;
- TopOfScreen = NewPos;
- }
-
- Difference = MoveToNextStatement (TRUE, &NewPos);
- if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
- if (Difference > 0) {
- //
- // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
- //
- TopOfScreen = NewPos;
- Repaint = TRUE;
- }
- }
- if (Difference < 0) {
- //
- // We want to goto previous MenuOption, but finally we go down.
- // it means that we hit the begining MenuOption that can be focused
- // so we simply scroll to the top
- //
- if (SavedListEntry != Menu.ForwardLink) {
- TopOfScreen = Menu.ForwardLink;
- Repaint = TRUE;
- }
- }
-
- //
- // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
-
- UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
- } else {
- SavedMenuOption = MenuOption;
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);
- if (!IsSelectable (MenuOption)) {
- //
- // If we are at the end of the list and sitting on a text op, we need to more forward
- //
- ScreenOperation = UiDown;
- ControlFlag = CfScreenOperation;
- break;
- }
-
- MenuOption = SavedMenuOption;
- }
- break;
-
- case CfUiPageUp:
- ControlFlag = CfCheckSelection;
-
- if (NewPos->BackLink == &Menu) {
- NewLine = FALSE;
- Repaint = FALSE;
- break;
- }
-
- NewLine = TRUE;
- Repaint = TRUE;
- Link = TopOfScreen;
- PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
- Index = BottomRow;
- while ((Index >= TopRow) && (Link->BackLink != &Menu)) {
- Index = Index - PreviousMenuOption->Skip;
- Link = Link->BackLink;
- PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
- }
-
- TopOfScreen = Link;
- Difference = MoveToNextStatement (TRUE, &Link);
- if (Difference > 0) {
- //
- // The focus MenuOption is above the TopOfScreen
- //
- TopOfScreen = Link;
- } else if (Difference < 0) {
- //
- // This happens when there is no MenuOption can be focused from
- // Current MenuOption to the first MenuOption
- //
- TopOfScreen = Menu.ForwardLink;
- }
- Index += Difference;
- if (Index < TopRow) {
- MenuOption = NULL;
- }
-
- if (NewPos == Link) {
- Repaint = FALSE;
- NewLine = FALSE;
- } else {
- NewPos = Link;
- }
-
- //
- // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
- // Don't do this when we are already in the first page.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
- AdjustDateAndTimePosition (TRUE, &NewPos);
- break;
-
- case CfUiPageDown:
- ControlFlag = CfCheckSelection;
-
- if (NewPos->ForwardLink == &Menu) {
- NewLine = FALSE;
- Repaint = FALSE;
- break;
- }
-
- NewLine = TRUE;
- Repaint = TRUE;
- Link = TopOfScreen;
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);
- Index = TopRow;
- while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) {
- Index = Index + NextMenuOption->Skip;
- Link = Link->ForwardLink;
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);
- }
-
- Index += MoveToNextStatement (FALSE, &Link);
- if (Index > BottomRow) {
- //
- // There are more MenuOption needing scrolling
- //
- TopOfScreen = Link;
- MenuOption = NULL;
- }
- if (NewPos == Link && Index <= BottomRow) {
- //
- // Finally we know that NewPos is the last MenuOption can be focused.
- //
- NewLine = FALSE;
- Repaint = FALSE;
- } else {
- NewPos = Link;
- }
-
- //
- // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
- // Don't do this when we are already in the last page.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
- AdjustDateAndTimePosition (TRUE, &NewPos);
- break;
-
- case CfUiDown:
- ControlFlag = CfCheckSelection;
- //
- // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
- // to be one that progresses to the next set of op-codes, we need to advance to the last
- // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
- // checking can be done. The only other logic we need to introduce is that if a Date/Time
- // op-code is the last entry in the menu, we need to rewind back to the first op-code of
- // the Date/Time op-code.
- //
- SavedListEntry = NewPos;
- DistanceValue = AdjustDateAndTimePosition (FALSE, &NewPos);
-
- if (NewPos->ForwardLink != &Menu) {
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);
- NewLine = TRUE;
- NewPos = NewPos->ForwardLink;
- NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
-
- DistanceValue += NextMenuOption->Skip;
- DistanceValue += MoveToNextStatement (FALSE, &NewPos);
- //
- // An option might be multi-line, so we need to reflect that data in the overall skip value
- //
- UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue);
-
- Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;
- if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&
- (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
- NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
- ) {
- Temp ++;
- }
-
- //
- // If we are going to scroll, update TopOfScreen
- //
- if (Temp > BottomRow) {
- do {
- //
- // Is the current top of screen a zero-advance op-code?
- // If so, keep moving forward till we hit a >0 advance op-code
- //
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
-
- //
- // If bottom op-code is more than one line or top op-code is more than one line
- //
- if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {
- //
- // Is the bottom op-code greater than or equal in size to the top op-code?
- //
- if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {
- //
- // Skip the top op-code
- //
- TopOfScreen = TopOfScreen->ForwardLink;
- Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);
-
- OldSkipValue = Difference;
-
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
-
- //
- // If we have a remainder, skip that many more op-codes until we drain the remainder
- //
- for (;
- Difference >= (INTN) SavedMenuOption->Skip;
- Difference = Difference - (INTN) SavedMenuOption->Skip
- ) {
- //
- // Since the Difference is greater than or equal to this op-code's skip value, skip it
- //
- TopOfScreen = TopOfScreen->ForwardLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
- if (Difference < (INTN) SavedMenuOption->Skip) {
- Difference = SavedMenuOption->Skip - Difference - 1;
- break;
- } else {
- if (Difference == (INTN) SavedMenuOption->Skip) {
- TopOfScreen = TopOfScreen->ForwardLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
- Difference = SavedMenuOption->Skip - Difference;
- break;
- }
- }
- }
- //
- // Since we will act on this op-code in the next routine, and increment the
- // SkipValue, set the skips to one less than what is required.
- //
- SkipValue = Difference - 1;
-
- } else {
- //
- // Since we will act on this op-code in the next routine, and increment the
- // SkipValue, set the skips to one less than what is required.
- //
- SkipValue = OldSkipValue + (Temp - BottomRow) - 1;
- }
- } else {
- if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {
- TopOfScreen = TopOfScreen->ForwardLink;
- break;
- } else {
- SkipValue = OldSkipValue;
- }
- }
- //
- // If the op-code at the top of the screen is more than one line, let's not skip it yet
- // Let's set a skip flag to smoothly scroll the top of the screen.
- //
- if (SavedMenuOption->Skip > 1) {
- if (SavedMenuOption == NextMenuOption) {
- SkipValue = 0;
- } else {
- SkipValue++;
- }
- } else {
- SkipValue = 0;
- TopOfScreen = TopOfScreen->ForwardLink;
- }
- } while (SavedMenuOption->Skip == 0);
-
- Repaint = TRUE;
- OldSkipValue = SkipValue;
- }
-
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
-
- UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
-
- } else {
- SavedMenuOption = MenuOption;
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);
- if (!IsSelectable (MenuOption)) {
- //
- // If we are at the end of the list and sitting on a text op, we need to more forward
- //
- ScreenOperation = UiUp;
- ControlFlag = CfScreenOperation;
- break;
- }
-
- MenuOption = SavedMenuOption;
- //
- // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
- //
- AdjustDateAndTimePosition (TRUE, &NewPos);
- }
- break;
-
- case CfUiSave:
- ControlFlag = CfCheckSelection;
-
- //
- // Submit the form
- //
- Status = SubmitForm (Selection->FormSet, Selection->Form);
-
- if (!EFI_ERROR (Status)) {
- UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
- UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);
- } else {
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveFailed, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
- Repaint = TRUE;
- NewLine = TRUE;
- }
- break;
-
- case CfUiDefault:
- ControlFlag = CfCheckSelection;
-
- Status = ExtractFormDefault (Selection->FormSet, Selection->Form, DefaultId);
-
- if (!EFI_ERROR (Status)) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
-
- //
- // Show NV update flag on status bar
- //
- gNvUpdateRequired = TRUE;
- }
- break;
-
- case CfUiNoOperation:
- ControlFlag = CfCheckSelection;
- break;
-
- case CfExit:
- UiFreeRefreshList ();
-
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- gST->ConOut->OutputString (gST->ConOut, L"\n");
-
- return EFI_SUCCESS;
-
- default:
- break;
- }
- }
-}
+/** @file
+Utility functions for User Interface functions.
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ui.h"
+#include "Setup.h"
+
+LIST_ENTRY Menu;
+LIST_ENTRY gMenuList;
+MENU_REFRESH_ENTRY *gMenuRefreshHead;
+
+//
+// Search table for UiDisplayMenu()
+//
+SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {
+ {
+ SCAN_UP,
+ UiUp,
+ },
+ {
+ SCAN_DOWN,
+ UiDown,
+ },
+ {
+ SCAN_PAGE_UP,
+ UiPageUp,
+ },
+ {
+ SCAN_PAGE_DOWN,
+ UiPageDown,
+ },
+ {
+ SCAN_ESC,
+ UiReset,
+ },
+ {
+ SCAN_F2,
+ UiPrevious,
+ },
+ {
+ SCAN_LEFT,
+ UiLeft,
+ },
+ {
+ SCAN_RIGHT,
+ UiRight,
+ },
+ {
+ SCAN_F9,
+ UiDefault,
+ },
+ {
+ SCAN_F10,
+ UiSave
+ }
+};
+
+SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {
+ {
+ UiNoOperation,
+ CfUiNoOperation,
+ },
+ {
+ UiDefault,
+ CfUiDefault,
+ },
+ {
+ UiSelect,
+ CfUiSelect,
+ },
+ {
+ UiUp,
+ CfUiUp,
+ },
+ {
+ UiDown,
+ CfUiDown,
+ },
+ {
+ UiLeft,
+ CfUiLeft,
+ },
+ {
+ UiRight,
+ CfUiRight,
+ },
+ {
+ UiReset,
+ CfUiReset,
+ },
+ {
+ UiSave,
+ CfUiSave,
+ },
+ {
+ UiPrevious,
+ CfUiPrevious,
+ },
+ {
+ UiPageUp,
+ CfUiPageUp,
+ },
+ {
+ UiPageDown,
+ CfUiPageDown
+ }
+};
+
+
+/**
+ Set Buffer to Value for Size bytes.
+
+ @param Buffer Memory to set.
+ @param Size Number of bytes to set
+ @param Value Value of the set operation.
+
+**/
+VOID
+SetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ )
+{
+ CHAR16 *Ptr;
+
+ Ptr = Buffer;
+ while ((Size--) != 0) {
+ *(Ptr++) = Value;
+ }
+}
+
+
+/**
+ Initialize Menu option list.
+
+**/
+VOID
+UiInitMenu (
+ VOID
+ )
+{
+ InitializeListHead (&Menu);
+}
+
+
+/**
+ Initialize Menu option list.
+
+**/
+VOID
+UiInitMenuList (
+ VOID
+ )
+{
+ InitializeListHead (&gMenuList);
+}
+
+
+/**
+ Remove a Menu in list, and return FormId/QuestionId for previous Menu.
+
+ @param Selection Menu selection.
+
+**/
+VOID
+UiRemoveMenuListEntry (
+ OUT UI_MENU_SELECTION *Selection
+ )
+{
+ UI_MENU_LIST *UiMenuList;
+
+ if (!IsListEmpty (&gMenuList)) {
+ UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
+
+ Selection->FormId = UiMenuList->FormId;
+ Selection->QuestionId = UiMenuList->QuestionId;
+ RemoveEntryList (&UiMenuList->MenuLink);
+ gBS->FreePool (UiMenuList);
+ }
+}
+
+
+/**
+ Free Menu option linked list.
+
+**/
+VOID
+UiFreeMenuList (
+ VOID
+ )
+{
+ UI_MENU_LIST *UiMenuList;
+
+ while (!IsListEmpty (&gMenuList)) {
+ UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
+ RemoveEntryList (&UiMenuList->MenuLink);
+ gBS->FreePool (UiMenuList);
+ }
+}
+
+
+/**
+ Add one menu entry to the linked lst
+
+ @param Selection Menu selection.
+
+**/
+VOID
+UiAddMenuListEntry (
+ IN UI_MENU_SELECTION *Selection
+ )
+{
+ UI_MENU_LIST *UiMenuList;
+
+ UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
+ ASSERT (UiMenuList != NULL);
+
+ UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;
+ UiMenuList->FormId = Selection->FormId;
+ UiMenuList->QuestionId = Selection->QuestionId;
+
+ InsertHeadList (&gMenuList, &UiMenuList->MenuLink);
+}
+
+
+/**
+ Free Menu option linked list.
+
+**/
+VOID
+UiFreeMenu (
+ VOID
+ )
+{
+ UI_MENU_OPTION *MenuOption;
+
+ while (!IsListEmpty (&Menu)) {
+ MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);
+ RemoveEntryList (&MenuOption->Link);
+
+ //
+ // We allocated space for this description when we did a GetToken, free it here
+ //
+ if (MenuOption->Skip != 0) {
+ //
+ // For date/time, MenuOption->Description is shared by three Menu Options
+ // Data format : [01/02/2004] [11:22:33]
+ // Line number : 0 0 1 0 0 1
+ //
+ gBS->FreePool (MenuOption->Description);
+ }
+ gBS->FreePool (MenuOption);
+ }
+}
+
+
+/**
+ Free Menu option linked list.
+
+**/
+VOID
+UiFreeRefreshList (
+ VOID
+ )
+{
+ MENU_REFRESH_ENTRY *OldMenuRefreshEntry;
+
+ while (gMenuRefreshHead != NULL) {
+ OldMenuRefreshEntry = gMenuRefreshHead->Next;
+ gBS->FreePool (gMenuRefreshHead);
+ gMenuRefreshHead = OldMenuRefreshEntry;
+ }
+
+ gMenuRefreshHead = NULL;
+}
+
+
+
+/**
+ Refresh screen.
+
+**/
+VOID
+RefreshForm (
+ VOID
+ )
+{
+ CHAR16 *OptionString;
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;
+ UINTN Index;
+ UINTN Loop;
+ EFI_STATUS Status;
+ UI_MENU_SELECTION *Selection;
+ FORM_BROWSER_STATEMENT *Question;
+
+ OptionString = NULL;
+
+ if (gMenuRefreshHead != NULL) {
+
+ MenuRefreshEntry = gMenuRefreshHead;
+
+ do {
+ gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);
+
+ Selection = MenuRefreshEntry->Selection;
+ Question = MenuRefreshEntry->MenuOption->ThisTag;
+
+ //
+ // Don't update Question being edited
+ //
+ if (Question != MenuRefreshEntry->Selection->Statement) {
+
+ Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);
+
+ if (OptionString != NULL) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++)
+ ;
+
+ for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Loop] = OptionString[Index];
+ Loop++;
+ }
+
+ OptionString[Loop] = CHAR_NULL;
+
+ PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);
+ gBS->FreePool (OptionString);
+ }
+ }
+
+ MenuRefreshEntry = MenuRefreshEntry->Next;
+
+ } while (MenuRefreshEntry != NULL);
+ }
+}
+
+
+/**
+ Wait for a given event to fire, or for an optional timeout to expire.
+
+ @param Event The event to wait for
+ @param Timeout An optional timeout value in 100 ns units.
+ @param RefreshInterval Menu refresh interval (in seconds).
+
+ @retval EFI_SUCCESS Event fired before Timeout expired.
+ @retval EFI_TIME_OUT Timout expired before Event fired.
+
+**/
+EFI_STATUS
+UiWaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout, OPTIONAL
+ IN UINT8 RefreshInterval OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_EVENT TimerEvent;
+ EFI_EVENT WaitList[2];
+
+ if (Timeout != 0) {
+ //
+ // Create a timer event
+ //
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+ gBS->CloseEvent (TimerEvent);
+
+ //
+ // If the timer expired, change the return to timed out
+ //
+ if (!EFI_ERROR (Status) && Index == 1) {
+ Status = EFI_TIMEOUT;
+ }
+ }
+ } else {
+ //
+ // Update screen every second
+ //
+ if (RefreshInterval == 0) {
+ Timeout = ONE_SECOND;
+ } else {
+ Timeout = RefreshInterval * ONE_SECOND;
+ }
+
+ do {
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+
+ //
+ // If the timer expired, update anything that needs a refresh and keep waiting
+ //
+ if (!EFI_ERROR (Status) && Index == 1) {
+ Status = EFI_TIMEOUT;
+ if (RefreshInterval != 0) {
+ RefreshForm ();
+ }
+ }
+
+ gBS->CloseEvent (TimerEvent);
+ } while (Status == EFI_TIMEOUT);
+ }
+
+ return Status;
+}
+
+
+/**
+ Add one menu option by specified description and context.
+
+ @param String String description for this option.
+ @param Handle Hii handle for the package list.
+ @param Statement Statement of this Menu Option.
+ @param NumberOfLines Display lines for this Menu Option.
+ @param MenuItemCount The index for this Option in the Menu.
+
+**/
+VOID
+UiAddMenuOption (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE Handle,
+ IN FORM_BROWSER_STATEMENT *Statement,
+ IN UINT16 NumberOfLines,
+ IN UINT16 MenuItemCount
+ )
+{
+ UI_MENU_OPTION *MenuOption;
+ UINTN Index;
+ UINTN Count;
+
+ Count = 1;
+
+ if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
+ //
+ // Add three MenuOptions for Date/Time
+ // Data format : [01/02/2004] [11:22:33]
+ // Line number : 0 0 1 0 0 1
+ //
+ NumberOfLines = 0;
+ Count = 3;
+
+ if (Statement->Storage == NULL) {
+ //
+ // For RTC type of date/time, set default refresh interval to be 1 second
+ //
+ if (Statement->RefreshInterval == 0) {
+ Statement->RefreshInterval = 1;
+ }
+ }
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
+ ASSERT (MenuOption);
+
+ MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;
+ MenuOption->Description = String;
+ MenuOption->Handle = Handle;
+ MenuOption->ThisTag = Statement;
+ MenuOption->EntryNumber = MenuItemCount;
+
+ if (Index == 2) {
+ //
+ // Override LineNumber for the MenuOption in Date/Time sequence
+ //
+ MenuOption->Skip = 1;
+ } else {
+ MenuOption->Skip = NumberOfLines;
+ }
+ MenuOption->Sequence = Index;
+
+ if (Statement->GrayOutExpression != NULL) {
+ MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b;
+ }
+
+ if ((Statement->ValueExpression != NULL) ||
+ ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {
+ MenuOption->ReadOnly = TRUE;
+ }
+
+ InsertTailList (&Menu, &MenuOption->Link);
+ }
+}
+
+
+/**
+ Routine used to abstract a generic dialog interface and return the selected key or string
+
+ @param NumberOfLines The number of lines for the dialog box
+ @param HotKey Defines whether a single character is parsed
+ (TRUE) and returned in KeyValue or a string is
+ returned in StringBuffer. Two special characters
+ are considered when entering a string, a SCAN_ESC
+ and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates
+ string input and returns
+ @param MaximumStringSize The maximum size in bytes of a typed in string
+ (each character is a CHAR16) and the minimum
+ string returned is two bytes
+ @param StringBuffer The passed in pointer to the buffer which will
+ hold the typed in string if HotKey is FALSE
+ @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
+ @param String Pointer to the first string in the list
+ @param ... A series of (quantity == NumberOfLines) text
+ strings which will be used to construct the dialog
+ box
+
+ @retval EFI_SUCCESS Displayed dialog and received user interaction
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.
+ (StringBuffer == NULL) && (HotKey == FALSE))
+ @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine
+
+**/
+EFI_STATUS
+CreateDialog (
+ IN UINTN NumberOfLines,
+ IN BOOLEAN HotKey,
+ IN UINTN MaximumStringSize,
+ OUT CHAR16 *StringBuffer,
+ OUT EFI_INPUT_KEY *KeyValue,
+ IN CHAR16 *String,
+ ...
+ )
+{
+ VA_LIST Marker;
+ UINTN Count;
+ EFI_INPUT_KEY Key;
+ UINTN LargestString;
+ CHAR16 *TempString;
+ CHAR16 *BufferedString;
+ CHAR16 *StackString;
+ CHAR16 KeyPad[2];
+ UINTN Start;
+ UINTN Top;
+ UINTN Index;
+ EFI_STATUS Status;
+ BOOLEAN SelectionComplete;
+ UINTN InputOffset;
+ UINTN CurrentAttribute;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ SelectionComplete = FALSE;
+ InputOffset = 0;
+ TempString = AllocateZeroPool (MaximumStringSize * 2);
+ BufferedString = AllocateZeroPool (MaximumStringSize * 2);
+ CurrentAttribute = gST->ConOut->Mode->Attribute;
+
+ ASSERT (TempString);
+ ASSERT (BufferedString);
+
+ VA_START (Marker, String);
+
+ //
+ // Zero the outgoing buffer
+ //
+ ZeroMem (StringBuffer, MaximumStringSize);
+
+ if (HotKey) {
+ if (KeyValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ if (StringBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Disable cursor
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ LargestString = (GetStringWidth (String) / 2);
+
+ if (*String == L' ') {
+ InputOffset = 1;
+ }
+ //
+ // Determine the largest string in the dialog box
+ // Notice we are starting with 1 since String is the first string
+ //
+ for (Count = 1; Count < NumberOfLines; Count++) {
+ StackString = VA_ARG (Marker, CHAR16 *);
+
+ if (StackString[0] == L' ') {
+ InputOffset = Count + 1;
+ }
+
+ if ((GetStringWidth (StackString) / 2) > LargestString) {
+ //
+ // Size of the string visually and subtract the width by one for the null-terminator
+ //
+ LargestString = (GetStringWidth (StackString) / 2);
+ }
+ }
+
+ Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
+
+ Count = 0;
+
+ //
+ // Display the Popup
+ //
+ CreateSharedPopUp (LargestString, NumberOfLines, &String);
+
+ //
+ // Take the first key typed and report it back?
+ //
+ if (HotKey) {
+ Status = WaitForKeyStroke (&Key);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
+
+ } else {
+ do {
+ Status = WaitForKeyStroke (&Key);
+
+ switch (Key.UnicodeChar) {
+ case CHAR_NULL:
+ switch (Key.ScanCode) {
+ case SCAN_ESC:
+ gBS->FreePool (TempString);
+ gBS->FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_DEVICE_ERROR;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ SelectionComplete = TRUE;
+ gBS->FreePool (TempString);
+ gBS->FreePool (BufferedString);
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+ break;
+
+ case CHAR_BACKSPACE:
+ if (StringBuffer[0] != CHAR_NULL) {
+ for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {
+ TempString[Index] = StringBuffer[Index];
+ }
+ //
+ // Effectively truncate string by 1 character
+ //
+ TempString[Index - 1] = CHAR_NULL;
+ StrCpy (StringBuffer, TempString);
+ }
+
+ default:
+ //
+ // If it is the beginning of the string, don't worry about checking maximum limits
+ //
+ if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ StrnCpy (StringBuffer, &Key.UnicodeChar, 1);
+ StrnCpy (TempString, &Key.UnicodeChar, 1);
+ } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
+ KeyPad[0] = Key.UnicodeChar;
+ KeyPad[1] = CHAR_NULL;
+ StrCat (StringBuffer, KeyPad);
+ StrCat (TempString, KeyPad);
+ }
+ //
+ // If the width of the input string is now larger than the screen, we nee to
+ // adjust the index to start printing portions of the string
+ //
+ SetUnicodeMem (BufferedString, LargestString, L' ');
+
+ PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
+
+ if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {
+ Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;
+ } else {
+ Index = 0;
+ }
+
+ for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {
+ BufferedString[Count] = StringBuffer[Index];
+ }
+
+ PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
+ break;
+ }
+ } while (!SelectionComplete);
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+}
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param ArrayOfStrings The array of string to be printed.
+
+**/
+VOID
+CreateSharedPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 **ArrayOfStrings
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ CHAR16 Character;
+ UINTN Start;
+ UINTN End;
+ UINTN Top;
+ UINTN Bottom;
+ CHAR16 *String;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ Count = 0;
+
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+
+ if ((RequestedWidth + 2) > DimensionsWidth) {
+ RequestedWidth = DimensionsWidth - 2;
+ }
+
+ //
+ // Subtract the PopUp width from total Columns, allow for one space extra on
+ // each end plus a border.
+ //
+ Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+ End = Start + RequestedWidth + 1;
+
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
+ Bottom = Top + NumberOfLines + 2;
+
+ Character = BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (Start, Top, Character);
+ Character = BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintChar (Character);
+ }
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+ Character = BOXDRAW_VERTICAL;
+ for (Index = Top; Index + 2 < Bottom; Index++) {
+ String = ArrayOfStrings[Count];
+ Count++;
+
+ //
+ // This will clear the background of the line - we never know who might have been
+ // here before us. This differs from the next clear in that it used the non-reverse
+ // video for normal printing.
+ //
+ if (GetStringWidth (String) / 2 > 1) {
+ ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
+ }
+
+ //
+ // Passing in a space results in the assumption that this is where typing will occur
+ //
+ if (String[0] == L' ') {
+ ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
+ }
+
+ //
+ // Passing in a NULL results in a blank space
+ //
+ if (String[0] == CHAR_NULL) {
+ ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
+ }
+
+ PrintStringAt (
+ ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
+ Index + 1,
+ String
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ PrintCharAt (Start, Index + 1, Character);
+ PrintCharAt (End - 1, Index + 1, Character);
+ }
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (Start, Bottom - 1, Character);
+ Character = BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintChar (Character);
+ }
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+}
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param ArrayOfStrings The array of string to be printed.
+ @param ... A series of text strings that displayed in the pop-up.
+
+**/
+VOID
+CreatePopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 *ArrayOfStrings,
+ ...
+ )
+{
+ CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);
+}
+
+
+/**
+ Update status bar on the bottom of menu.
+
+ @param MessageType The type of message to be shown.
+ @param Flags The flags in Question header.
+ @param State Set or clear.
+
+**/
+VOID
+UpdateStatusBar (
+ IN UINTN MessageType,
+ IN UINT8 Flags,
+ IN BOOLEAN State
+ )
+{
+ UINTN Index;
+ STATIC BOOLEAN InputError;
+ CHAR16 *NvUpdateMessage;
+ CHAR16 *InputErrorMessage;
+
+ NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);
+ InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);
+
+ switch (MessageType) {
+ case INPUT_ERROR:
+ if (State) {
+ gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + gPromptBlockWidth,
+ gScreenDimensions.BottomRow - 1,
+ InputErrorMessage
+ );
+ InputError = TRUE;
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
+ for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
+ PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");
+ }
+
+ InputError = FALSE;
+ }
+ break;
+
+ case NV_UPDATE_REQUIRED:
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ if (State) {
+ gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
+ gScreenDimensions.BottomRow - 1,
+ NvUpdateMessage
+ );
+ gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
+
+ gNvUpdateRequired = TRUE;
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
+ for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
+ PrintAt (
+ (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
+ gScreenDimensions.BottomRow - 1,
+ L" "
+ );
+ }
+
+ gNvUpdateRequired = FALSE;
+ }
+ }
+ break;
+
+ case REFRESH_STATUS_BAR:
+ if (InputError) {
+ UpdateStatusBar (INPUT_ERROR, Flags, TRUE);
+ }
+
+ if (gNvUpdateRequired) {
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ gBS->FreePool (InputErrorMessage);
+ gBS->FreePool (NvUpdateMessage);
+ return ;
+}
+
+
+/**
+ Get the supported width for a particular op-code
+
+ @param Statement The FORM_BROWSER_STATEMENT structure passed in.
+ @param Handle The handle in the HII database being used
+
+ @return Returns the number of CHAR16 characters that is support.
+
+**/
+UINT16
+GetWidth (
+ IN FORM_BROWSER_STATEMENT *Statement,
+ IN EFI_HII_HANDLE Handle
+ )
+{
+ CHAR16 *String;
+ UINTN Size;
+ UINT16 Width;
+
+ Size = 0;
+
+ //
+ // See if the second text parameter is really NULL
+ //
+ if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
+ String = GetToken (Statement->TextTwo, Handle);
+ Size = StrLen (String);
+ gBS->FreePool (String);
+ }
+
+ if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||
+ (Statement->Operand == EFI_IFR_REF_OP) ||
+ (Statement->Operand == EFI_IFR_PASSWORD_OP) ||
+ (Statement->Operand == EFI_IFR_ACTION_OP) ||
+ (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||
+ //
+ // Allow a wide display if text op-code and no secondary text op-code
+ //
+ ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))
+ ) {
+ Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
+ } else {
+ Width = (UINT16) gPromptBlockWidth;
+ }
+
+ if (Statement->InSubtitle) {
+ Width -= SUBTITLE_INDENT;
+ }
+
+ return Width;
+}
+
+
+STATIC BOOLEAN GetLineByWidthFinished = FALSE;
+
+/**
+ Will copy LineWidth amount of a string in the OutputString buffer and return the
+ number of CHAR16 characters that were copied into the OutputString buffer.
+
+ @param InputString String description for this option.
+ @param LineWidth Width of the desired string to extract in CHAR16
+ characters
+ @param Index Where in InputString to start the copy process
+ @param OutputString Buffer to copy the string into
+
+ @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.
+
+**/
+UINT16
+GetLineByWidth (
+ IN CHAR16 *InputString,
+ IN UINT16 LineWidth,
+ IN OUT UINTN *Index,
+ OUT CHAR16 **OutputString
+ )
+{
+ UINT16 Count;
+ UINT16 Count2;
+
+ if (GetLineByWidthFinished) {
+ GetLineByWidthFinished = FALSE;
+ return (UINT16) 0;
+ }
+
+ Count = LineWidth;
+ Count2 = 0;
+
+ *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));
+
+ //
+ // Ensure we have got a valid buffer
+ //
+ if (*OutputString != NULL) {
+
+ //
+ //NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.
+ //To avoid displaying this empty line in screen, just skip the two CHARs here.
+ //
+ if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
+ *Index = *Index + 2;
+ }
+
+ //
+ // Fast-forward the string and see if there is a carriage-return in the string
+ //
+ for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
+ ;
+
+ //
+ // Copy the desired LineWidth of data to the output buffer.
+ // Also make sure that we don't copy more than the string.
+ // Also make sure that if there are linefeeds, we account for them.
+ //
+ if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
+ (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
+ ) {
+ //
+ // Convert to CHAR16 value and show that we are done with this operation
+ //
+ LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);
+ if (LineWidth != 0) {
+ GetLineByWidthFinished = TRUE;
+ }
+ } else {
+ if (Count2 == LineWidth) {
+ //
+ // Rewind the string from the maximum size until we see a space to break the line
+ //
+ for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
+ ;
+ if (LineWidth == 0) {
+ LineWidth = Count;
+ }
+ } else {
+ LineWidth = Count2;
+ }
+ }
+
+ CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);
+
+ //
+ // If currently pointing to a space, increment the index to the first non-space character
+ //
+ for (;
+ (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);
+ (*Index)++
+ )
+ ;
+ *Index = (UINT16) (*Index + LineWidth);
+ return LineWidth;
+ } else {
+ return (UINT16) 0;
+ }
+}
+
+
+/**
+ Update display lines for a Menu Option.
+
+ @param Selection The user's selection.
+ @param MenuOption The MenuOption to be checked.
+ @param OptionalString The option string.
+ @param SkipValue The number of lins to skip.
+
+ @retval TRUE This Menu Option is selectable.
+ @retval FALSE This Menu Option could not be selected.
+
+**/
+VOID
+UpdateOptionSkipLines (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption,
+ OUT CHAR16 **OptionalString,
+ IN UINTN SkipValue
+ )
+{
+ UINTN Index;
+ UINT16 Width;
+ UINTN Row;
+ UINTN OriginalRow;
+ CHAR16 *OutputString;
+ CHAR16 *OptionString;
+
+ Row = 0;
+ OptionString = *OptionalString;
+ OutputString = NULL;
+
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+
+ if (OptionString != NULL) {
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ if (SkipValue == 0) {
+ Row++;
+ //
+ // Since the Number of lines for this menu entry may or may not be reflected accurately
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+ // some testing to ensure we are keeping this in-sync.
+ //
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value
+ //
+ if ((Row - OriginalRow) >= MenuOption->Skip) {
+ MenuOption->Skip++;
+ }
+ }
+ }
+
+ gBS->FreePool (OutputString);
+ if (SkipValue != 0) {
+ SkipValue--;
+ }
+ }
+
+ Row = OriginalRow;
+ }
+
+ *OptionalString = OptionString;
+}
+
+
+/**
+ Check whether this Menu Option could be highlighted.
+
+ This is an internal function.
+
+ @param MenuOption The MenuOption to be checked.
+
+ @retval TRUE This Menu Option is selectable.
+ @retval FALSE This Menu Option could not be selected.
+
+**/
+BOOLEAN
+IsSelectable (
+ UI_MENU_OPTION *MenuOption
+ )
+{
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||
+ MenuOption->GrayOut || MenuOption->ReadOnly) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ Determine if the menu is the last menu that can be selected.
+
+ This is an internal function.
+
+ @param Direction The scroll direction. False is down. True is up.
+ @param CurrentPos The current focus.
+
+ @return FALSE -- the menu isn't the last menu that can be selected.
+ @return TRUE -- the menu is the last menu that can be selected.
+
+**/
+BOOLEAN
+ValueIsScroll (
+ IN BOOLEAN Direction,
+ IN LIST_ENTRY *CurrentPos
+ )
+{
+ LIST_ENTRY *Temp;
+ UI_MENU_OPTION *MenuOption;
+
+ Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
+
+ if (Temp == &Menu) {
+ return TRUE;
+ }
+
+ for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
+ MenuOption = MENU_OPTION_FROM_LINK (Temp);
+ if (IsSelectable (MenuOption)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Move to next selectable statement.
+
+ This is an internal function.
+
+ @param GoUp The navigation direction. TRUE: up, FALSE: down.
+ @param CurrentPosition Current position.
+
+ @return The row distance from current MenuOption to next selectable MenuOption.
+
+**/
+INTN
+MoveToNextStatement (
+ IN BOOLEAN GoUp,
+ IN OUT LIST_ENTRY **CurrentPosition
+ )
+{
+ INTN Distance;
+ LIST_ENTRY *Pos;
+ BOOLEAN HitEnd;
+ UI_MENU_OPTION *NextMenuOption;
+
+ Distance = 0;
+ Pos = *CurrentPosition;
+ HitEnd = FALSE;
+
+ while (TRUE) {
+ NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
+ if (IsSelectable (NextMenuOption)) {
+ break;
+ }
+ if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
+ HitEnd = TRUE;
+ break;
+ }
+ Distance += NextMenuOption->Skip;
+ Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);
+ }
+
+ if (HitEnd) {
+ //
+ // If we hit end there is still no statement can be focused,
+ // we go backwards to find the statement can be focused.
+ //
+ Distance = 0;
+ Pos = *CurrentPosition;
+
+ while (TRUE) {
+ NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
+ if (IsSelectable (NextMenuOption)) {
+ break;
+ }
+ if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
+ ASSERT (FALSE);
+ break;
+ }
+ Distance -= NextMenuOption->Skip;
+ Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);
+ }
+ }
+
+ *CurrentPosition = &NextMenuOption->Link;
+ return Distance;
+}
+
+
+/**
+ Adjust Data and Time position accordingly.
+ Data format : [01/02/2004] [11:22:33]
+ Line number : 0 0 1 0 0 1
+
+ This is an internal function.
+
+ @param DirectionUp the up or down direction. False is down. True is
+ up.
+ @param CurrentPosition Current position. On return: Point to the last
+ Option (Year or Second) if up; Point to the first
+ Option (Month or Hour) if down.
+
+ @return Return line number to pad. It is possible that we stand on a zero-advance
+ @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
+
+**/
+UINTN
+AdjustDateAndTimePosition (
+ IN BOOLEAN DirectionUp,
+ IN OUT LIST_ENTRY **CurrentPosition
+ )
+{
+ UINTN Count;
+ LIST_ENTRY *NewPosition;
+ UI_MENU_OPTION *MenuOption;
+ UINTN PadLineNumber;
+
+ PadLineNumber = 0;
+ NewPosition = *CurrentPosition;
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
+
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
+ (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ //
+ // Calculate the distance from current position to the last Date/Time MenuOption
+ //
+ Count = 0;
+ while (MenuOption->Skip == 0) {
+ Count++;
+ NewPosition = NewPosition->ForwardLink;
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
+ PadLineNumber = 1;
+ }
+
+ NewPosition = *CurrentPosition;
+ if (DirectionUp) {
+ //
+ // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
+ // to be one that back to the previous set of MenuOptions, we need to advance to the first
+ // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate
+ // checking can be done.
+ //
+ while (Count++ < 2) {
+ NewPosition = NewPosition->BackLink;
+ }
+ } else {
+ //
+ // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended
+ // to be one that progresses to the next set of MenuOptions, we need to advance to the last
+ // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate
+ // checking can be done.
+ //
+ while (Count-- > 0) {
+ NewPosition = NewPosition->ForwardLink;
+ }
+ }
+
+ *CurrentPosition = NewPosition;
+ }
+
+ return PadLineNumber;
+}
+
+
+/**
+ Display menu and wait for user to select one menu option, then return it.
+ If AutoBoot is enabled, then if user doesn't select any option,
+ after period of time, it will automatically return the first menu option.
+
+ @param Selection Menu selection.
+
+ @retval EFI_SUCESSS This function always return successfully for now.
+
+**/
+EFI_STATUS
+UiDisplayMenu (
+ IN OUT UI_MENU_SELECTION *Selection
+ )
+{
+ INTN SkipValue;
+ INTN Difference;
+ INTN OldSkipValue;
+ UINTN DistanceValue;
+ UINTN Row;
+ UINTN Col;
+ UINTN Temp;
+ UINTN Temp2;
+ UINTN TopRow;
+ UINTN BottomRow;
+ UINTN OriginalRow;
+ UINTN Index;
+ UINT32 Count;
+ UINT16 Width;
+ CHAR16 *StringPtr;
+ CHAR16 *OptionString;
+ CHAR16 *OutputString;
+ CHAR16 *FormattedString;
+ CHAR16 YesResponse;
+ CHAR16 NoResponse;
+ BOOLEAN NewLine;
+ BOOLEAN Repaint;
+ BOOLEAN SavedValue;
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NewPos;
+ LIST_ENTRY *TopOfScreen;
+ LIST_ENTRY *SavedListEntry;
+ UI_MENU_OPTION *MenuOption;
+ UI_MENU_OPTION *NextMenuOption;
+ UI_MENU_OPTION *SavedMenuOption;
+ UI_MENU_OPTION *PreviousMenuOption;
+ UI_CONTROL_FLAG ControlFlag;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;
+ UI_SCREEN_OPERATION ScreenOperation;
+ UINT8 MinRefreshInterval;
+ UINTN BufferSize;
+ UINT16 DefaultId;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ Status = EFI_SUCCESS;
+ FormattedString = NULL;
+ OptionString = NULL;
+ ScreenOperation = UiNoOperation;
+ NewLine = TRUE;
+ MinRefreshInterval = 0;
+ DefaultId = 0;
+
+ OutputString = NULL;
+ gUpArrow = FALSE;
+ gDownArrow = FALSE;
+ SkipValue = 0;
+ OldSkipValue = 0;
+ MenuRefreshEntry = gMenuRefreshHead;
+
+ NextMenuOption = NULL;
+ PreviousMenuOption = NULL;
+ SavedMenuOption = NULL;
+
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
+
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ } else {
+ TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
+ }
+
+ Col = LocalScreen.LeftColumn;
+ BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;
+
+ Selection->TopRow = TopRow;
+ Selection->BottomRow = BottomRow;
+ Selection->PromptCol = Col;
+ Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
+ Selection->Statement = NULL;
+
+ TopOfScreen = Menu.ForwardLink;
+ Repaint = TRUE;
+ MenuOption = NULL;
+
+ //
+ // Get user's selection
+ //
+ NewPos = Menu.ForwardLink;
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+ UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
+
+ ControlFlag = CfInitialization;
+ Selection->Action = UI_ACTION_NONE;
+ while (TRUE) {
+ switch (ControlFlag) {
+ case CfInitialization:
+ if (IsListEmpty (&Menu)) {
+ ControlFlag = CfReadKey;
+ } else {
+ ControlFlag = CfCheckSelection;
+ }
+ break;
+
+ case CfCheckSelection:
+ if (Selection->Action != UI_ACTION_NONE) {
+ ControlFlag = CfExit;
+ } else {
+ ControlFlag = CfRepaint;
+ }
+ break;
+
+ case CfRepaint:
+ ControlFlag = CfRefreshHighLight;
+
+ if (Repaint) {
+ //
+ // Display menu
+ //
+ gDownArrow = FALSE;
+ gUpArrow = FALSE;
+ Row = TopRow;
+
+ Temp = SkipValue;
+ Temp2 = SkipValue;
+
+ ClearLines (
+ LocalScreen.LeftColumn,
+ LocalScreen.RightColumn,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ FIELD_TEXT | FIELD_BACKGROUND
+ );
+
+ UiFreeRefreshList ();
+ MinRefreshInterval = 0;
+
+ for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
+ MenuOption = MENU_OPTION_FROM_LINK (Link);
+ MenuOption->Row = Row;
+ MenuOption->Col = Col;
+ MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
+
+ Statement = MenuOption->ThisTag;
+ if (Statement->InSubtitle) {
+ MenuOption->Col += SUBTITLE_INDENT;
+ }
+
+ if (MenuOption->GrayOut) {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
+ } else {
+ if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {
+ gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
+ }
+ }
+
+ Width = GetWidth (Statement, MenuOption->Handle);
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+ if ((Temp == 0) && (Row <= BottomRow)) {
+ PrintStringAt (MenuOption->Col, Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&MenuOption->Description[Index])) {
+ if (Temp == 0) {
+ Row++;
+ }
+ }
+
+ gBS->FreePool (OutputString);
+ if (Temp != 0) {
+ Temp--;
+ }
+ }
+
+ Temp = 0;
+ Row = OriginalRow;
+
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+
+ if (OptionString != NULL) {
+ if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++) {
+ MenuOption->OptCol++;
+ }
+
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Count] = OptionString[Index];
+ Count++;
+ }
+
+ OptionString[Count] = CHAR_NULL;
+ }
+
+ //
+ // If Question request refresh, register the op-code
+ //
+ if (Statement->RefreshInterval != 0) {
+ //
+ // Menu will be refreshed at minimal interval of all Questions
+ // which have refresh request
+ //
+ if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {
+ MinRefreshInterval = Statement->RefreshInterval;
+ }
+
+ if (gMenuRefreshHead == NULL) {
+ MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
+ ASSERT (MenuRefreshEntry != NULL);
+ MenuRefreshEntry->MenuOption = MenuOption;
+ MenuRefreshEntry->Selection = Selection;
+ MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
+ MenuRefreshEntry->CurrentRow = MenuOption->Row;
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
+ gMenuRefreshHead = MenuRefreshEntry;
+ } else {
+ //
+ // Advance to the last entry
+ //
+ for (MenuRefreshEntry = gMenuRefreshHead;
+ MenuRefreshEntry->Next != NULL;
+ MenuRefreshEntry = MenuRefreshEntry->Next
+ )
+ ;
+ MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
+ ASSERT (MenuRefreshEntry->Next != NULL);
+ MenuRefreshEntry = MenuRefreshEntry->Next;
+ MenuRefreshEntry->MenuOption = MenuOption;
+ MenuRefreshEntry->Selection = Selection;
+ MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
+ MenuRefreshEntry->CurrentRow = MenuOption->Row;
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
+ }
+ }
+
+ Width = (UINT16) gOptionBlockWidth;
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ if ((Temp2 == 0) && (Row <= BottomRow)) {
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ if (Temp2 == 0) {
+ Row++;
+ //
+ // Since the Number of lines for this menu entry may or may not be reflected accurately
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+ // some testing to ensure we are keeping this in-sync.
+ //
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value
+ //
+ if ((Row - OriginalRow) >= MenuOption->Skip) {
+ MenuOption->Skip++;
+ }
+ }
+ }
+
+ gBS->FreePool (OutputString);
+ if (Temp2 != 0) {
+ Temp2--;
+ }
+ }
+
+ Temp2 = 0;
+ Row = OriginalRow;
+
+ gBS->FreePool (OptionString);
+ }
+ //
+ // If this is a text op with secondary text information
+ //
+ if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
+ StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle);
+
+ Width = (UINT16) gOptionBlockWidth;
+ OriginalRow = Row;
+
+ for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
+ if ((Temp == 0) && (Row <= BottomRow)) {
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&StringPtr[Index])) {
+ if (Temp2 == 0) {
+ Row++;
+ //
+ // Since the Number of lines for this menu entry may or may not be reflected accurately
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
+ // some testing to ensure we are keeping this in-sync.
+ //
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value
+ //
+ if ((Row - OriginalRow) >= MenuOption->Skip) {
+ MenuOption->Skip++;
+ }
+ }
+ }
+
+ gBS->FreePool (OutputString);
+ if (Temp2 != 0) {
+ Temp2--;
+ }
+ }
+
+ Row = OriginalRow;
+ gBS->FreePool (StringPtr);
+ }
+
+ //
+ // Need to handle the bottom of the display
+ //
+ if (MenuOption->Skip > 1) {
+ Row += MenuOption->Skip - SkipValue;
+ SkipValue = 0;
+ } else {
+ Row += MenuOption->Skip;
+ }
+
+ if (Row > BottomRow) {
+ if (!ValueIsScroll (FALSE, Link)) {
+ gDownArrow = TRUE;
+ }
+
+ Row = BottomRow + 1;
+ break;
+ }
+ }
+
+ if (!ValueIsScroll (TRUE, TopOfScreen)) {
+ gUpArrow = TRUE;
+ }
+
+ if (gUpArrow) {
+ gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
+ PrintAt (
+ LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ L"%c",
+ ARROW_UP
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+
+ if (gDownArrow) {
+ gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
+ PrintAt (
+ LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ L"%c",
+ ARROW_DOWN
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+
+ MenuOption = NULL;
+ }
+ break;
+
+ case CfRefreshHighLight:
+ //
+ // MenuOption: Last menu option that need to remove hilight
+ // MenuOption is set to NULL in Repaint
+ // NewPos: Current menu option that need to hilight
+ //
+ ControlFlag = CfUpdateHelpString;
+
+ //
+ // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
+ // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
+ //
+ SavedValue = Repaint;
+ Repaint = FALSE;
+
+ if (Selection->QuestionId != 0) {
+ NewPos = Menu.ForwardLink;
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+
+ while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) {
+ NewPos = NewPos->ForwardLink;
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ }
+ if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {
+ //
+ // Target Question found, find its MenuOption
+ //
+ Link = TopOfScreen;
+
+ for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {
+ SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
+ Index += SavedMenuOption->Skip;
+ Link = Link->ForwardLink;
+ }
+
+ if (Link != NewPos || Index > BottomRow) {
+ //
+ // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page
+ //
+ Link = NewPos;
+ for (Index = TopRow; Index <= BottomRow; ) {
+ Link = Link->BackLink;
+ SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
+ Index += SavedMenuOption->Skip;
+ }
+ TopOfScreen = Link->ForwardLink;
+
+ Repaint = TRUE;
+ NewLine = TRUE;
+ ControlFlag = CfRepaint;
+ break;
+ }
+ } else {
+ //
+ // Target Question not found, highlight the default menu option
+ //
+ NewPos = TopOfScreen;
+ }
+
+ Selection->QuestionId = 0;
+ }
+
+ if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {
+ if (MenuOption != NULL) {
+ //
+ // Remove highlight on last Menu Option
+ //
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ if (OptionString != NULL) {
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
+ (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
+ ) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++)
+ ;
+
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Count] = OptionString[Index];
+ Count++;
+ }
+
+ OptionString[Count] = CHAR_NULL;
+ }
+
+ Width = (UINT16) gOptionBlockWidth;
+ OriginalRow = MenuOption->Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ MenuOption->Row++;
+ }
+
+ gBS->FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+
+ gBS->FreePool (OptionString);
+ } else {
+ if (NewLine) {
+ if (MenuOption->GrayOut) {
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
+ } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
+ gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
+ }
+
+ OriginalRow = MenuOption->Row;
+ Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&MenuOption->Description[Index])) {
+ MenuOption->Row++;
+ }
+
+ gBS->FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+ }
+ }
+
+ //
+ // This is only possible if we entered this page and the first menu option is
+ // a "non-menu" item. In that case, force it UiDown
+ //
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ if (!IsSelectable (MenuOption)) {
+ ASSERT (ScreenOperation == UiNoOperation);
+ ScreenOperation = UiDown;
+ ControlFlag = CfScreenOperation;
+ break;
+ }
+
+ //
+ // This is the current selected statement
+ //
+ Statement = MenuOption->ThisTag;
+ Selection->Statement = Statement;
+
+ //
+ // Set reverse attribute
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+
+ //
+ // Assuming that we have a refresh linked-list created, lets annotate the
+ // appropriate entry that we are highlighting with its new attribute. Just prior to this
+ // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
+ //
+ if (gMenuRefreshHead != NULL) {
+ for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
+ if (MenuRefreshEntry->MenuOption == MenuOption) {
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;
+ }
+ }
+ }
+
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
+ if (OptionString != NULL) {
+ if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++)
+ ;
+
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Count] = OptionString[Index];
+ Count++;
+ }
+
+ OptionString[Count] = CHAR_NULL;
+ }
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = MenuOption->Row;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&OptionString[Index])) {
+ MenuOption->Row++;
+ }
+
+ gBS->FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+
+ gBS->FreePool (OptionString);
+ } else {
+ if (NewLine) {
+ OriginalRow = MenuOption->Row;
+
+ Width = GetWidth (Statement, MenuOption->Handle);
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
+ PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);
+ }
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&MenuOption->Description[Index])) {
+ MenuOption->Row++;
+ }
+
+ gBS->FreePool (OutputString);
+ }
+
+ MenuOption->Row = OriginalRow;
+
+ }
+ }
+
+ if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||
+ ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||
+ (ScreenOperation == UiNoOperation)
+ ) {
+ UpdateKeyHelp (MenuOption, FALSE);
+ }
+ //
+ // Clear reverse attribute
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
+ }
+ //
+ // Repaint flag will be used when process CfUpdateHelpString, so restore its value
+ // if we didn't break halfway when process CfRefreshHighLight.
+ //
+ Repaint = SavedValue;
+ break;
+
+ case CfUpdateHelpString:
+ ControlFlag = CfPrepareToReadKey;
+
+ if ((Repaint || NewLine) && (gClassOfVfr != EFI_GENERAL_APPLICATION_SUBCLASS)) {
+ //
+ // Don't print anything if it is a NULL help token
+ //
+ if (MenuOption->ThisTag->Help == 0) {
+ StringPtr = L"\0";
+ } else {
+ StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
+ }
+
+ ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);
+
+ gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
+
+ for (Index = 0; Index < BottomRow - TopRow; Index++) {
+ //
+ // Pad String with spaces to simulate a clearing of the previous line
+ //
+ for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {
+ StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" ");
+ }
+
+ PrintStringAt (
+ LocalScreen.RightColumn - gHelpBlockWidth,
+ Index + TopRow,
+ &FormattedString[Index * gHelpBlockWidth * 2]
+ );
+ }
+ }
+ //
+ // Reset this flag every time we finish using it.
+ //
+ Repaint = FALSE;
+ NewLine = FALSE;
+ break;
+
+ case CfPrepareToReadKey:
+ ControlFlag = CfReadKey;
+ ScreenOperation = UiNoOperation;
+ break;
+
+ case CfReadKey:
+ ControlFlag = CfScreenOperation;
+
+ //
+ // Wait for user's selection
+ //
+ do {
+ Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);
+ } while (Status == EFI_TIMEOUT);
+
+ if (Status == EFI_TIMEOUT) {
+ Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
+ } else {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ //
+ // if we encounter error, continue to read another key in.
+ //
+ if (EFI_ERROR (Status)) {
+ ControlFlag = CfReadKey;
+ continue;
+ }
+ }
+
+ if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {
+ //
+ // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
+ //
+ break;
+ }
+
+ switch (Key.UnicodeChar) {
+ case CHAR_CARRIAGE_RETURN:
+ ScreenOperation = UiSelect;
+ gDirection = 0;
+ break;
+
+ //
+ // We will push the adjustment of these numeric values directly to the input handler
+ // NOTE: we won't handle manual input numeric
+ //
+ case '+':
+ case '-':
+ Statement = MenuOption->ThisTag;
+ if ((Statement->Operand == EFI_IFR_DATE_OP)
+ || (Statement->Operand == EFI_IFR_TIME_OP)
+ || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))
+ ){
+ if (Key.UnicodeChar == '+') {
+ gDirection = SCAN_RIGHT;
+ } else {
+ gDirection = SCAN_LEFT;
+ }
+ Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
+ SafeFreePool (OptionString);
+ }
+ break;
+
+ case '^':
+ ScreenOperation = UiUp;
+ break;
+
+ case 'V':
+ case 'v':
+ ScreenOperation = UiDown;
+ break;
+
+ case ' ':
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
+ if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) {
+ ScreenOperation = UiSelect;
+ }
+ }
+ break;
+
+ case CHAR_NULL:
+ if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||
+ ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||
+ ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||
+ ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))
+ ) {
+ //
+ // If the function key has been disabled, just ignore the key.
+ //
+ } else {
+ for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {
+ if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
+ if (Key.ScanCode == SCAN_F9) {
+ //
+ // Reset to standard default
+ //
+ DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ }
+ ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ break;
+
+ case CfScreenOperation:
+ if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {
+ //
+ // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
+ // ignore the selection and go back to reading keys.
+ //
+ if (IsListEmpty (&Menu)) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+ //
+ // if there is nothing logical to place a cursor on, just move on to wait for a key.
+ //
+ for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+ if (IsSelectable (NextMenuOption)) {
+ break;
+ }
+ }
+
+ if (Link == &Menu) {
+ ControlFlag = CfPrepareToReadKey;
+ break;
+ }
+ } else if (ScreenOperation == UiReset) {
+ //
+ // Press ESC to exit FormSet
+ //
+ Selection->Action = UI_ACTION_EXIT;
+ Selection->Statement = NULL;
+ }
+
+ for (Index = 0;
+ Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
+ Index++
+ ) {
+ if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
+ ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
+ break;
+ }
+ }
+ break;
+
+ case CfUiPrevious:
+ ControlFlag = CfCheckSelection;
+
+ if (IsListEmpty (&gMenuList)) {
+ Selection->Action = UI_ACTION_NONE;
+ if (IsListEmpty (&Menu)) {
+ ControlFlag = CfReadKey;
+ }
+ break;
+ }
+
+ //
+ // Remove the Cached page entry
+ //
+ UiRemoveMenuListEntry (Selection);
+
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+ Selection->Statement = NULL;
+ break;
+
+ case CfUiSelect:
+ ControlFlag = CfCheckSelection;
+
+ Statement = MenuOption->ThisTag;
+ if ((Statement->Operand == EFI_IFR_TEXT_OP) ||
+ (Statement->Operand == EFI_IFR_DATE_OP) ||
+ (Statement->Operand == EFI_IFR_TIME_OP) ||
+ (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
+ break;
+ }
+
+ //
+ // Keep highlight on current MenuOption
+ //
+ Selection->QuestionId = Statement->QuestionId;
+
+ switch (Statement->Operand) {
+ case EFI_IFR_REF_OP:
+ if (Statement->RefDevicePath != 0) {
+ //
+ // Goto another Hii Package list
+ //
+ ControlFlag = CfUiReset;
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;
+
+ StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);
+ if (StringPtr == NULL) {
+ //
+ // No device path string not found, exit
+ //
+ Selection->Action = UI_ACTION_EXIT;
+ Selection->Statement = NULL;
+ break;
+ }
+ BufferSize = StrLen (StringPtr) / 2;
+ DevicePath = AllocatePool (BufferSize);
+
+ HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, StringPtr);
+ Selection->Handle = HiiLibDevicePathToHiiHandle (DevicePath);
+ if (Selection->Handle == NULL) {
+ //
+ // If target Hii Handle not found, exit
+ //
+ Selection->Action = UI_ACTION_EXIT;
+ Selection->Statement = NULL;
+ break;
+ }
+
+ gBS->FreePool (StringPtr);
+ gBS->FreePool (DevicePath);
+
+ CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
+ Selection->FormId = Statement->RefFormId;
+ Selection->QuestionId = Statement->RefQuestionId;
+ } else if (!CompareGuid (&Statement->RefFormSetId, &gZeroGuid)) {
+ //
+ // Goto another Formset, check for uncommitted data
+ //
+ ControlFlag = CfUiReset;
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;
+
+ CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));
+ Selection->FormId = Statement->RefFormId;
+ Selection->QuestionId = Statement->RefQuestionId;
+ } else if (Statement->RefFormId != 0) {
+ //
+ // Goto another form inside this formset,
+ //
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+
+ //
+ // Link current form so that we can always go back when someone hits the UiPrevious
+ //
+ UiAddMenuListEntry (Selection);
+
+ Selection->FormId = Statement->RefFormId;
+ Selection->QuestionId = Statement->RefQuestionId;
+ } else if (Statement->RefQuestionId != 0) {
+ //
+ // Goto another Question
+ //
+ Selection->QuestionId = Statement->RefQuestionId;
+
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+ } else {
+ Repaint = TRUE;
+ NewLine = TRUE;
+ break;
+ }
+ }
+ break;
+
+ case EFI_IFR_ACTION_OP:
+ //
+ // Process the Config string <ConfigResp>
+ //
+ Status = ProcessQuestionConfig (Selection, Statement);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // The action button may change some Question value, so refresh the form
+ //
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+ break;
+
+ case EFI_IFR_RESET_BUTTON_OP:
+ //
+ // Reset Question to default value specified by DefaultId
+ //
+ ControlFlag = CfUiDefault;
+ DefaultId = Statement->DefaultId;
+ break;
+
+ default:
+ //
+ // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
+ //
+ UpdateKeyHelp (MenuOption, TRUE);
+ Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
+
+ if (EFI_ERROR (Status)) {
+ Repaint = TRUE;
+ NewLine = TRUE;
+ break;
+ }
+
+ if (OptionString != NULL) {
+ PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);
+ gBS->FreePool (OptionString);
+ }
+
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+ break;
+ }
+ break;
+
+ case CfUiReset:
+ //
+ // We are going to leave current FormSet, so check uncommited data in this FormSet
+ //
+ ControlFlag = CfCheckSelection;
+
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
+ //
+ // There is no parent menu for FrontPage
+ //
+ Selection->Action = UI_ACTION_NONE;
+ Selection->Statement = MenuOption->ThisTag;
+ break;
+ }
+
+ //
+ // If NV flag is up, prompt user
+ //
+ if (gNvUpdateRequired) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+
+ YesResponse = gYesResponse[0];
+ NoResponse = gNoResponse[0];
+
+ do {
+ CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);
+ } while
+ (
+ (Key.ScanCode != SCAN_ESC) &&
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
+ );
+
+ //
+ // If the user hits the YesResponse key
+ //
+ if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
+ } else {
+ Repaint = TRUE;
+ NewLine = TRUE;
+
+ Selection->Action = UI_ACTION_NONE;
+ break;
+ }
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ UiFreeMenuList ();
+ gST->ConOut->ClearScreen (gST->ConOut);
+ return EFI_SUCCESS;
+
+ case CfUiLeft:
+ ControlFlag = CfCheckSelection;
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ if (MenuOption->Sequence != 0) {
+ //
+ // In the middle or tail of the Date/Time op-code set, go left.
+ //
+ NewPos = NewPos->BackLink;
+ }
+ }
+ break;
+
+ case CfUiRight:
+ ControlFlag = CfCheckSelection;
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ if (MenuOption->Sequence != 2) {
+ //
+ // In the middle or tail of the Date/Time op-code set, go left.
+ //
+ NewPos = NewPos->ForwardLink;
+ }
+ }
+ break;
+
+ case CfUiUp:
+ ControlFlag = CfCheckSelection;
+
+ SavedListEntry = TopOfScreen;
+
+ if (NewPos->BackLink != &Menu) {
+ NewLine = TRUE;
+ //
+ // Adjust Date/Time position before we advance forward.
+ //
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+
+ //
+ // Caution that we have already rewind to the top, don't go backward in this situation.
+ //
+ if (NewPos->BackLink != &Menu) {
+ NewPos = NewPos->BackLink;
+ }
+
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ DistanceValue = PreviousMenuOption->Skip;
+
+ //
+ // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
+ // to be one that back to the previous set of op-codes, we need to advance to the sencond
+ // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
+ // checking can be done.
+ //
+ DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);
+
+ //
+ // Check the previous menu entry to see if it was a zero-length advance. If it was,
+ // don't worry about a redraw.
+ //
+ if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
+ Repaint = TRUE;
+ TopOfScreen = NewPos;
+ }
+
+ Difference = MoveToNextStatement (TRUE, &NewPos);
+ if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {
+ if (Difference > 0) {
+ //
+ // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
+ //
+ TopOfScreen = NewPos;
+ Repaint = TRUE;
+ }
+ }
+ if (Difference < 0) {
+ //
+ // We want to goto previous MenuOption, but finally we go down.
+ // it means that we hit the begining MenuOption that can be focused
+ // so we simply scroll to the top
+ //
+ if (SavedListEntry != Menu.ForwardLink) {
+ TopOfScreen = Menu.ForwardLink;
+ Repaint = TRUE;
+ }
+ }
+
+ //
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
+ } else {
+ SavedMenuOption = MenuOption;
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ if (!IsSelectable (MenuOption)) {
+ //
+ // If we are at the end of the list and sitting on a text op, we need to more forward
+ //
+ ScreenOperation = UiDown;
+ ControlFlag = CfScreenOperation;
+ break;
+ }
+
+ MenuOption = SavedMenuOption;
+ }
+ break;
+
+ case CfUiPageUp:
+ ControlFlag = CfCheckSelection;
+
+ if (NewPos->BackLink == &Menu) {
+ NewLine = FALSE;
+ Repaint = FALSE;
+ break;
+ }
+
+ NewLine = TRUE;
+ Repaint = TRUE;
+ Link = TopOfScreen;
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
+ Index = BottomRow;
+ while ((Index >= TopRow) && (Link->BackLink != &Menu)) {
+ Index = Index - PreviousMenuOption->Skip;
+ Link = Link->BackLink;
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
+ }
+
+ TopOfScreen = Link;
+ Difference = MoveToNextStatement (TRUE, &Link);
+ if (Difference > 0) {
+ //
+ // The focus MenuOption is above the TopOfScreen
+ //
+ TopOfScreen = Link;
+ } else if (Difference < 0) {
+ //
+ // This happens when there is no MenuOption can be focused from
+ // Current MenuOption to the first MenuOption
+ //
+ TopOfScreen = Menu.ForwardLink;
+ }
+ Index += Difference;
+ if (Index < TopRow) {
+ MenuOption = NULL;
+ }
+
+ if (NewPos == Link) {
+ Repaint = FALSE;
+ NewLine = FALSE;
+ } else {
+ NewPos = Link;
+ }
+
+ //
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+ // Don't do this when we are already in the first page.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ break;
+
+ case CfUiPageDown:
+ ControlFlag = CfCheckSelection;
+
+ if (NewPos->ForwardLink == &Menu) {
+ NewLine = FALSE;
+ Repaint = FALSE;
+ break;
+ }
+
+ NewLine = TRUE;
+ Repaint = TRUE;
+ Link = TopOfScreen;
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+ Index = TopRow;
+ while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) {
+ Index = Index + NextMenuOption->Skip;
+ Link = Link->ForwardLink;
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+ }
+
+ Index += MoveToNextStatement (FALSE, &Link);
+ if (Index > BottomRow) {
+ //
+ // There are more MenuOption needing scrolling
+ //
+ TopOfScreen = Link;
+ MenuOption = NULL;
+ }
+ if (NewPos == Link && Index <= BottomRow) {
+ //
+ // Finally we know that NewPos is the last MenuOption can be focused.
+ //
+ NewLine = FALSE;
+ Repaint = FALSE;
+ } else {
+ NewPos = Link;
+ }
+
+ //
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+ // Don't do this when we are already in the last page.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ break;
+
+ case CfUiDown:
+ ControlFlag = CfCheckSelection;
+ //
+ // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
+ // to be one that progresses to the next set of op-codes, we need to advance to the last
+ // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
+ // checking can be done. The only other logic we need to introduce is that if a Date/Time
+ // op-code is the last entry in the menu, we need to rewind back to the first op-code of
+ // the Date/Time op-code.
+ //
+ SavedListEntry = NewPos;
+ DistanceValue = AdjustDateAndTimePosition (FALSE, &NewPos);
+
+ if (NewPos->ForwardLink != &Menu) {
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ NewLine = TRUE;
+ NewPos = NewPos->ForwardLink;
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+
+ DistanceValue += NextMenuOption->Skip;
+ DistanceValue += MoveToNextStatement (FALSE, &NewPos);
+ //
+ // An option might be multi-line, so we need to reflect that data in the overall skip value
+ //
+ UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue);
+
+ Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;
+ if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&
+ (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
+ NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
+ ) {
+ Temp ++;
+ }
+
+ //
+ // If we are going to scroll, update TopOfScreen
+ //
+ if (Temp > BottomRow) {
+ do {
+ //
+ // Is the current top of screen a zero-advance op-code?
+ // If so, keep moving forward till we hit a >0 advance op-code
+ //
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+
+ //
+ // If bottom op-code is more than one line or top op-code is more than one line
+ //
+ if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {
+ //
+ // Is the bottom op-code greater than or equal in size to the top op-code?
+ //
+ if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {
+ //
+ // Skip the top op-code
+ //
+ TopOfScreen = TopOfScreen->ForwardLink;
+ Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);
+
+ OldSkipValue = Difference;
+
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+
+ //
+ // If we have a remainder, skip that many more op-codes until we drain the remainder
+ //
+ for (;
+ Difference >= (INTN) SavedMenuOption->Skip;
+ Difference = Difference - (INTN) SavedMenuOption->Skip
+ ) {
+ //
+ // Since the Difference is greater than or equal to this op-code's skip value, skip it
+ //
+ TopOfScreen = TopOfScreen->ForwardLink;
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+ if (Difference < (INTN) SavedMenuOption->Skip) {
+ Difference = SavedMenuOption->Skip - Difference - 1;
+ break;
+ } else {
+ if (Difference == (INTN) SavedMenuOption->Skip) {
+ TopOfScreen = TopOfScreen->ForwardLink;
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+ Difference = SavedMenuOption->Skip - Difference;
+ break;
+ }
+ }
+ }
+ //
+ // Since we will act on this op-code in the next routine, and increment the
+ // SkipValue, set the skips to one less than what is required.
+ //
+ SkipValue = Difference - 1;
+
+ } else {
+ //
+ // Since we will act on this op-code in the next routine, and increment the
+ // SkipValue, set the skips to one less than what is required.
+ //
+ SkipValue = OldSkipValue + (Temp - BottomRow) - 1;
+ }
+ } else {
+ if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {
+ TopOfScreen = TopOfScreen->ForwardLink;
+ break;
+ } else {
+ SkipValue = OldSkipValue;
+ }
+ }
+ //
+ // If the op-code at the top of the screen is more than one line, let's not skip it yet
+ // Let's set a skip flag to smoothly scroll the top of the screen.
+ //
+ if (SavedMenuOption->Skip > 1) {
+ if (SavedMenuOption == NextMenuOption) {
+ SkipValue = 0;
+ } else {
+ SkipValue++;
+ }
+ } else {
+ SkipValue = 0;
+ TopOfScreen = TopOfScreen->ForwardLink;
+ }
+ } while (SavedMenuOption->Skip == 0);
+
+ Repaint = TRUE;
+ OldSkipValue = SkipValue;
+ }
+
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
+
+ } else {
+ SavedMenuOption = MenuOption;
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ if (!IsSelectable (MenuOption)) {
+ //
+ // If we are at the end of the list and sitting on a text op, we need to more forward
+ //
+ ScreenOperation = UiUp;
+ ControlFlag = CfScreenOperation;
+ break;
+ }
+
+ MenuOption = SavedMenuOption;
+ //
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
+ //
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ }
+ break;
+
+ case CfUiSave:
+ ControlFlag = CfCheckSelection;
+
+ //
+ // Submit the form
+ //
+ Status = SubmitForm (Selection->FormSet, Selection->Form);
+
+ if (!EFI_ERROR (Status)) {
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
+ UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);
+ } else {
+ do {
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveFailed, gPressEnter, gEmptyString);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+ Repaint = TRUE;
+ NewLine = TRUE;
+ }
+ break;
+
+ case CfUiDefault:
+ ControlFlag = CfCheckSelection;
+
+ Status = ExtractFormDefault (Selection->FormSet, Selection->Form, DefaultId);
+
+ if (!EFI_ERROR (Status)) {
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+
+ //
+ // Show NV update flag on status bar
+ //
+ gNvUpdateRequired = TRUE;
+ }
+ break;
+
+ case CfUiNoOperation:
+ ControlFlag = CfCheckSelection;
+ break;
+
+ case CfExit:
+ UiFreeRefreshList ();
+
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ gST->ConOut->OutputString (gST->ConOut, L"\n");
+
+ return EFI_SUCCESS;
+
+ default:
+ break;
+ }
+ }
+}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
index e402248..6e6b897 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
@@ -1,474 +1,796 @@
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- Ui.h
-
-Abstract:
-
- Head file UI
-
-Revision History
-
-
-**/
-
-#ifndef _UI_H
-#define _UI_H
-
-#include "Setup.h"
-
-//
-// Globals
-//
-#define REGULAR_NUMERIC 0
-#define TIME_NUMERIC 1
-#define DATE_NUMERIC 2
-
-#define SUBTITLE_INDENT 2
-
-typedef enum {
- UiNoOperation,
- UiDefault,
- UiSelect,
- UiUp,
- UiDown,
- UiLeft,
- UiRight,
- UiReset,
- UiSave,
- UiPrevious,
- UiPageUp,
- UiPageDown,
- UiMaxOperation
-} UI_SCREEN_OPERATION;
-
-typedef enum {
- CfInitialization,
- CfCheckSelection,
- CfRepaint,
- CfRefreshHighLight,
- CfUpdateHelpString,
- CfPrepareToReadKey,
- CfReadKey,
- CfScreenOperation,
- CfUiPrevious,
- CfUiSelect,
- CfUiReset,
- CfUiLeft,
- CfUiRight,
- CfUiUp,
- CfUiPageUp,
- CfUiPageDown,
- CfUiDown,
- CfUiSave,
- CfUiDefault,
- CfUiNoOperation,
- CfExit,
- CfMaxControlFlag
-} UI_CONTROL_FLAG;
-
-#define UI_ACTION_NONE 0
-#define UI_ACTION_REFRESH_FORM 1
-#define UI_ACTION_REFRESH_FORMSET 2
-#define UI_ACTION_EXIT 3
-
-typedef struct {
- EFI_HII_HANDLE Handle;
-
- //
- // Target formset/form/Question information
- //
- EFI_GUID FormSetGuid;
- UINT16 FormId;
- UINT16 QuestionId;
-
- UINTN TopRow;
- UINTN BottomRow;
- UINTN PromptCol;
- UINTN OptionCol;
- UINTN CurrentRow;
-
- //
- // Ation for Browser to taken:
- // UI_ACTION_NONE - navigation inside a form
- // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form
- // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary
- //
- UINTN Action;
-
- //
- // Current selected fomset/form/Question
- //
- FORM_BROWSER_FORMSET *FormSet;
- FORM_BROWSER_FORM *Form;
- FORM_BROWSER_STATEMENT *Statement;
-} UI_MENU_SELECTION;
-
-#define UI_MENU_OPTION_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'm')
-#define UI_MENU_LIST_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'l')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- EFI_HII_HANDLE Handle;
- FORM_BROWSER_STATEMENT *ThisTag;
- UINT16 EntryNumber;
-
- UINTN Row;
- UINTN Col;
- UINTN OptCol;
- CHAR16 *Description;
- UINTN Skip; // Number of lines
-
- //
- // Display item sequence for date/time
- // Date: Month/Day/Year
- // Sequence: 0 1 2
- //
- // Time: Hour : Minute : Second
- // Sequence: 0 1 2
- //
- //
- UINTN Sequence;
-
- BOOLEAN GrayOut;
- BOOLEAN ReadOnly;
-} UI_MENU_OPTION;
-
-#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY MenuLink;
-
- UINT16 FormId;
- UINT16 QuestionId;
-} UI_MENU_LIST;
-
-typedef struct _MENU_REFRESH_ENTRY {
- struct _MENU_REFRESH_ENTRY *Next;
- UI_MENU_OPTION *MenuOption; // Describes the entry needing an update
- UI_MENU_SELECTION *Selection;
- UINTN CurrentColumn;
- UINTN CurrentRow;
- UINTN CurrentAttribute;
-} MENU_REFRESH_ENTRY;
-
-typedef struct {
- UINT16 ScanCode;
- UI_SCREEN_OPERATION ScreenOperation;
-} SCAN_CODE_TO_SCREEN_OPERATION;
-
-typedef struct {
- UI_SCREEN_OPERATION ScreenOperation;
- UI_CONTROL_FLAG ControlFlag;
-} SCREEN_OPERATION_T0_CONTROL_FLAG;
-
-
-extern LIST_ENTRY gMenuList;
-extern MENU_REFRESH_ENTRY *gMenuRefreshHead;
-extern UI_MENU_SELECTION *gCurrentSelection;
-
-//
-// Global Functions
-//
-VOID
-UiInitMenu (
- VOID
- )
-;
-
-VOID
-UiInitMenuList (
- VOID
- )
-;
-
-VOID
-UiRemoveMenuListEntry (
- OUT UI_MENU_SELECTION *Selection
- )
-;
-
-VOID
-UiFreeMenuList (
- VOID
- )
-;
-
-VOID
-UiAddMenuListEntry (
- IN UI_MENU_SELECTION *Selection
- )
-;
-
-VOID
-UiFreeMenu (
- VOID
- )
-;
-
-VOID
-UiAddMenuOption (
- IN CHAR16 *String,
- IN EFI_HII_HANDLE Handle,
- IN FORM_BROWSER_STATEMENT *Statement,
- IN UINT16 NumberOfLines,
- IN UINT16 MenuItemCount
- )
-;
-
-EFI_STATUS
-UiDisplayMenu (
- IN OUT UI_MENU_SELECTION *Selection
- )
-;
-
-VOID
-FreeBrowserStrings (
- VOID
- )
-;
-
-EFI_STATUS
-SetupBrowser (
- IN OUT UI_MENU_SELECTION *Selection
- )
-;
-
-VOID
-ValueToString (
- IN CHAR16 *Buffer,
- IN BOOLEAN Comma,
- IN INT64 v
- )
-;
-
-EFI_STATUS
-UiIntToString (
- IN UINTN num,
- IN OUT CHAR16 *str,
- IN UINT16 size
- )
-;
-
-VOID
-SetUnicodeMem (
- IN VOID *Buffer,
- IN UINTN Size,
- IN CHAR16 Value
- )
-;
-
-EFI_STATUS
-UiWaitForSingleEvent (
- IN EFI_EVENT Event,
- IN UINT64 Timeout, OPTIONAL
- IN UINT8 RefreshInterval OPTIONAL
- )
-;
-
-VOID
-CreatePopUp (
- IN UINTN ScreenWidth,
- IN UINTN NumberOfLines,
- IN CHAR16 *ArrayOfStrings,
- ...
- )
-;
-
-EFI_STATUS
-ReadString (
- IN UI_MENU_OPTION *MenuOption,
- IN CHAR16 *Prompt,
- OUT CHAR16 *StringPtr
- )
-;
-
-EFI_STATUS
-GetSelectionInputPopUp (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption
- )
-;
-
-EFI_STATUS
-GetNumericInput (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption
- )
-;
-
-VOID
-UpdateStatusBar (
- IN UINTN MessageType,
- IN UINT8 Flags,
- IN BOOLEAN State
- )
-;
-
-EFI_STATUS
-ProcessQuestionConfig (
- IN UI_MENU_SELECTION *Selection,
- IN FORM_BROWSER_STATEMENT *Question
- )
-;
-
-EFI_STATUS
-PrintFormattedNumber (
- IN FORM_BROWSER_STATEMENT *Question,
- IN OUT CHAR16 *FormattedNumber,
- IN UINTN BufferSize
- )
-;
-
-QUESTION_OPTION *
-ValueToOption (
- IN FORM_BROWSER_STATEMENT *Question,
- IN EFI_HII_VALUE *OptionValue
- )
-;
-
-EFI_STATUS
-ProcessOptions (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected,
- OUT CHAR16 **OptionString
- )
-;
-
-VOID
-ProcessHelpString (
- IN CHAR16 *StringPtr,
- OUT CHAR16 **FormattedString,
- IN UINTN RowCount
- )
-;
-
-VOID
-UpdateKeyHelp (
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected
- )
-;
-
-VOID
-ClearLines (
- UINTN LeftColumn,
- UINTN RightColumn,
- UINTN TopRow,
- UINTN BottomRow,
- UINTN TextAttribute
- )
-;
-
-UINTN
-GetStringWidth (
- CHAR16 *String
- )
-;
-
-UINT16
-GetLineByWidth (
- IN CHAR16 *InputString,
- IN UINT16 LineWidth,
- IN OUT UINTN *Index,
- OUT CHAR16 **OutputString
- )
-;
-
-UINT16
-GetWidth (
- IN FORM_BROWSER_STATEMENT *Statement,
- IN EFI_HII_HANDLE Handle
- )
-;
-
-VOID
-NewStrCat (
- CHAR16 *Destination,
- CHAR16 *Source
- )
-;
-
-EFI_STATUS
-WaitForKeyStroke (
- OUT EFI_INPUT_KEY *Key
- )
-;
-
-VOID
-ResetScopeStack (
- VOID
- )
-;
-
-EFI_STATUS
-PushScope (
- IN UINT8 Operand
- )
-;
-
-EFI_STATUS
-PopScope (
- OUT UINT8 *Operand
- )
-;
-
-FORM_BROWSER_FORM *
-IdToForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN UINT16 FormId
-)
-;
-
-FORM_BROWSER_STATEMENT *
-IdToQuestion (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN UINT16 QuestionId
- )
-;
-
-FORM_EXPRESSION *
-IdToExpression (
- IN FORM_BROWSER_FORM *Form,
- IN UINT8 RuleId
- )
-;
-
-VOID
-ExtendValueToU64 (
- IN EFI_HII_VALUE *Value
- )
-;
-
-INTN
-CompareHiiValue (
- IN EFI_HII_VALUE *Value1,
- IN EFI_HII_VALUE *Value2,
- IN EFI_HII_HANDLE HiiHandle OPTIONAL
- )
-;
-
-EFI_STATUS
-EvaluateExpression (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN OUT FORM_EXPRESSION *Expression
- )
-;
-
-#endif // _UI_H
+/** @file
+Private structure, MACRO and function definitions for User Interface related functionalities.
+
+Copyright (c) 2004 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UI_H_
+#define _UI_H_
+
+#include "Setup.h"
+
+//
+// Globals
+//
+#define REGULAR_NUMERIC 0
+#define TIME_NUMERIC 1
+#define DATE_NUMERIC 2
+
+#define SUBTITLE_INDENT 2
+
+typedef enum {
+ UiNoOperation,
+ UiDefault,
+ UiSelect,
+ UiUp,
+ UiDown,
+ UiLeft,
+ UiRight,
+ UiReset,
+ UiSave,
+ UiPrevious,
+ UiPageUp,
+ UiPageDown,
+ UiMaxOperation
+} UI_SCREEN_OPERATION;
+
+typedef enum {
+ CfInitialization,
+ CfCheckSelection,
+ CfRepaint,
+ CfRefreshHighLight,
+ CfUpdateHelpString,
+ CfPrepareToReadKey,
+ CfReadKey,
+ CfScreenOperation,
+ CfUiPrevious,
+ CfUiSelect,
+ CfUiReset,
+ CfUiLeft,
+ CfUiRight,
+ CfUiUp,
+ CfUiPageUp,
+ CfUiPageDown,
+ CfUiDown,
+ CfUiSave,
+ CfUiDefault,
+ CfUiNoOperation,
+ CfExit,
+ CfMaxControlFlag
+} UI_CONTROL_FLAG;
+
+#define UI_ACTION_NONE 0
+#define UI_ACTION_REFRESH_FORM 1
+#define UI_ACTION_REFRESH_FORMSET 2
+#define UI_ACTION_EXIT 3
+
+typedef struct {
+ EFI_HII_HANDLE Handle;
+
+ //
+ // Target formset/form/Question information
+ //
+ EFI_GUID FormSetGuid;
+ UINT16 FormId;
+ UINT16 QuestionId;
+
+ UINTN TopRow;
+ UINTN BottomRow;
+ UINTN PromptCol;
+ UINTN OptionCol;
+ UINTN CurrentRow;
+
+ //
+ // Ation for Browser to taken:
+ // UI_ACTION_NONE - navigation inside a form
+ // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form
+ // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary
+ //
+ UINTN Action;
+
+ //
+ // Current selected fomset/form/Question
+ //
+ FORM_BROWSER_FORMSET *FormSet;
+ FORM_BROWSER_FORM *Form;
+ FORM_BROWSER_STATEMENT *Statement;
+} UI_MENU_SELECTION;
+
+#define UI_MENU_OPTION_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'm')
+#define UI_MENU_LIST_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'l')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_HII_HANDLE Handle;
+ FORM_BROWSER_STATEMENT *ThisTag;
+ UINT16 EntryNumber;
+
+ UINTN Row;
+ UINTN Col;
+ UINTN OptCol;
+ CHAR16 *Description;
+ UINTN Skip; // Number of lines
+
+ //
+ // Display item sequence for date/time
+ // Date: Month/Day/Year
+ // Sequence: 0 1 2
+ //
+ // Time: Hour : Minute : Second
+ // Sequence: 0 1 2
+ //
+ //
+ UINTN Sequence;
+
+ BOOLEAN GrayOut;
+ BOOLEAN ReadOnly;
+} UI_MENU_OPTION;
+
+#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY MenuLink;
+
+ UINT16 FormId;
+ UINT16 QuestionId;
+} UI_MENU_LIST;
+
+typedef struct _MENU_REFRESH_ENTRY {
+ struct _MENU_REFRESH_ENTRY *Next;
+ UI_MENU_OPTION *MenuOption; // Describes the entry needing an update
+ UI_MENU_SELECTION *Selection;
+ UINTN CurrentColumn;
+ UINTN CurrentRow;
+ UINTN CurrentAttribute;
+} MENU_REFRESH_ENTRY;
+
+typedef struct {
+ UINT16 ScanCode;
+ UI_SCREEN_OPERATION ScreenOperation;
+} SCAN_CODE_TO_SCREEN_OPERATION;
+
+typedef struct {
+ UI_SCREEN_OPERATION ScreenOperation;
+ UI_CONTROL_FLAG ControlFlag;
+} SCREEN_OPERATION_T0_CONTROL_FLAG;
+
+
+extern LIST_ENTRY gMenuList;
+extern MENU_REFRESH_ENTRY *gMenuRefreshHead;
+extern UI_MENU_SELECTION *gCurrentSelection;
+
+//
+// Global Functions
+//
+/**
+ Initialize Menu option list.
+
+**/
+VOID
+UiInitMenu (
+ VOID
+ )
+;
+
+/**
+ Initialize Menu option list.
+
+**/
+VOID
+UiInitMenuList (
+ VOID
+ )
+;
+
+/**
+ Remove a Menu in list, and return FormId/QuestionId for previous Menu.
+
+ @param Selection Menu selection.
+
+**/
+VOID
+UiRemoveMenuListEntry (
+ OUT UI_MENU_SELECTION *Selection
+ )
+;
+
+/**
+ Free Menu option linked list.
+
+**/
+VOID
+UiFreeMenuList (
+ VOID
+ )
+;
+
+/**
+ Add one menu entry to the linked lst
+
+ @param Selection Menu selection.
+
+**/
+VOID
+UiAddMenuListEntry (
+ IN UI_MENU_SELECTION *Selection
+ )
+;
+
+/**
+ Free Menu option linked list.
+
+**/
+VOID
+UiFreeMenu (
+ VOID
+ )
+;
+
+/**
+ Add one menu option by specified description and context.
+
+ @param String String description for this option.
+ @param Handle Hii handle for the package list.
+ @param Statement Statement of this Menu Option.
+ @param NumberOfLines Display lines for this Menu Option.
+ @param MenuItemCount The index for this Option in the Menu.
+
+**/
+VOID
+UiAddMenuOption (
+ IN CHAR16 *String,
+ IN EFI_HII_HANDLE Handle,
+ IN FORM_BROWSER_STATEMENT *Statement,
+ IN UINT16 NumberOfLines,
+ IN UINT16 MenuItemCount
+ )
+;
+
+/**
+ Display menu and wait for user to select one menu option, then return it.
+ If AutoBoot is enabled, then if user doesn't select any option,
+ after period of time, it will automatically return the first menu option.
+
+ @param Selection Menu selection.
+
+ @return Return the pointer of the menu which selected,
+ @return otherwise return NULL.
+
+**/
+EFI_STATUS
+UiDisplayMenu (
+ IN OUT UI_MENU_SELECTION *Selection
+ )
+;
+
+/**
+ Free up the resource allocated for all strings required
+ by Setup Browser.
+
+**/
+VOID
+FreeBrowserStrings (
+ VOID
+ )
+;
+
+/**
+ The worker function that send the displays to the screen. On output,
+ the selection made by user is returned.
+
+ @param Selection On input, Selection tell setup browser the information
+ about the Selection, form and formset to be displayed.
+ On output, Selection return the screen item that is selected
+ by user.
+
+ @retval EFI_SUCCESS The page is displayed successfully.
+ @return Other value if the page failed to be diplayed.
+
+**/
+EFI_STATUS
+SetupBrowser (
+ IN OUT UI_MENU_SELECTION *Selection
+ )
+;
+
+/**
+ VSPrint worker function that prints a Value as a decimal number in Buffer.
+
+ @param Buffer Location to place ascii decimal number string of Value.
+ @param Flags Flags to use in printing decimal string, see file header for
+ details.
+ @param Value Decimal value to convert to a string in Buffer.
+
+ @return Number of characters printed.
+
+**/
+VOID
+ValueToString (
+ IN CHAR16 *Buffer,
+ IN BOOLEAN Flags,
+ IN INT64 Value
+ )
+;
+
+/**
+ Set Buffer to Value for Size bytes.
+
+ @param Buffer Memory to set.
+ @param Size Number of bytes to set
+ @param Value Value of the set operation.
+
+**/
+VOID
+SetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ )
+;
+
+/**
+ Wait for a given event to fire, or for an optional timeout to expire.
+
+ @param Event The event to wait for
+ @param Timeout An optional timeout value in 100 ns units.
+ @param RefreshInterval Menu refresh interval (in seconds).
+
+ @retval EFI_SUCCESS Event fired before Timeout expired.
+ @retval EFI_TIME_OUT Timout expired before Event fired.
+
+**/
+EFI_STATUS
+UiWaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout, OPTIONAL
+ IN UINT8 RefreshInterval OPTIONAL
+ )
+;
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param ArrayOfStrings The array of string to be printed.
+ @param ... A series of text strings that displayed in the pop-up.
+
+**/
+VOID
+CreatePopUp (
+ IN UINTN ScreenWidth,
+ IN UINTN NumberOfLines,
+ IN CHAR16 *ArrayOfStrings,
+ ...
+ )
+;
+
+/**
+ Get string or password input from user.
+
+ @param MenuOption Pointer to the current input menu.
+ @param Prompt The prompt string shown on popup window.
+ @param StringPtr Destination for use input string.
+
+ @retval EFI_SUCCESS If string input is read successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+ReadString (
+ IN UI_MENU_OPTION *MenuOption,
+ IN CHAR16 *Prompt,
+ OUT CHAR16 *StringPtr
+ )
+;
+
+/**
+ Get selection for OneOf and OrderedList (Left/Right will be ignored).
+
+ @param Selection Pointer to current selection.
+ @param MenuOption Pointer to the current input menu.
+
+ @retval EFI_SUCCESS If Option input is processed successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+GetSelectionInputPopUp (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption
+ )
+;
+
+/**
+ This routine reads a numeric value from the user input.
+
+ @param Selection Pointer to current selection.
+ @param MenuOption Pointer to the current input menu.
+
+ @retval EFI_SUCCESS If numerical input is read successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+GetNumericInput (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption
+ )
+;
+
+/**
+ Update status bar on the bottom of menu.
+
+ @param MessageType The type of message to be shown.
+ @param Flags The flags in Question header.
+ @param State Set or clear.
+
+**/
+VOID
+UpdateStatusBar (
+ IN UINTN MessageType,
+ IN UINT8 Flags,
+ IN BOOLEAN State
+ )
+;
+
+/**
+ Process Question Config.
+
+ @param Selection The UI menu selection.
+ @param Question The Question to be peocessed.
+
+ @retval EFI_SUCCESS Question Config process success.
+ @retval Other Question Config process fail.
+
+**/
+EFI_STATUS
+ProcessQuestionConfig (
+ IN UI_MENU_SELECTION *Selection,
+ IN FORM_BROWSER_STATEMENT *Question
+ )
+;
+
+/**
+ Print Question Value according to it's storage width and display attributes.
+
+ @param Question The Question to be printed.
+ @param FormattedNumber Buffer for output string.
+ @param BufferSize The FormattedNumber buffer size in bytes.
+
+ @retval EFI_SUCCESS Print success.
+ @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
+
+**/
+EFI_STATUS
+PrintFormattedNumber (
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN OUT CHAR16 *FormattedNumber,
+ IN UINTN BufferSize
+ )
+;
+
+/**
+ Search an Option of a Question by its value.
+
+ @param Question The Question
+ @param OptionValue Value for Option to be searched.
+
+ @retval Pointer Pointer to the found Option.
+ @retval NULL Option not found.
+
+**/
+QUESTION_OPTION *
+ValueToOption (
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN EFI_HII_VALUE *OptionValue
+ )
+;
+
+/**
+ Process a Question's Option (whether selected or un-selected).
+
+ @param Selection Pointer to UI_MENU_SELECTION.
+ @param MenuOption The MenuOption for this Question.
+ @param Selected TRUE: if Question is selected.
+ @param OptionString Pointer of the Option String to be displayed.
+
+ @retval EFI_SUCCESS Question Option process success.
+ @retval Other Question Option process fail.
+
+**/
+EFI_STATUS
+ProcessOptions (
+ IN UI_MENU_SELECTION *Selection,
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected,
+ OUT CHAR16 **OptionString
+ )
+;
+
+/**
+ Process the help string: Split StringPtr to several lines of strings stored in
+ FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
+
+ @param StringPtr The entire help string.
+ @param FormattedString The oupput formatted string.
+ @param RowCount TRUE: if Question is selected.
+
+**/
+VOID
+ProcessHelpString (
+ IN CHAR16 *StringPtr,
+ OUT CHAR16 **FormattedString,
+ IN UINTN RowCount
+ )
+;
+
+/**
+ Update key's help imformation.
+
+ @param MenuOption The Menu option
+ @param Selected Whether or not a tag be selected
+
+**/
+VOID
+UpdateKeyHelp (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected
+ )
+;
+
+/**
+ Clear retangle with specified text attribute.
+
+ @param LeftColumn Left column of retangle.
+ @param RightColumn Right column of retangle.
+ @param TopRow Start row of retangle.
+ @param BottomRow End row of retangle.
+ @param TextAttribute The character foreground and background.
+
+**/
+VOID
+ClearLines (
+ UINTN LeftColumn,
+ UINTN RightColumn,
+ UINTN TopRow,
+ UINTN BottomRow,
+ UINTN TextAttribute
+ )
+;
+
+/**
+ Count the storage space of a Unicode string.
+
+ This function handles the Unicode string with NARROW_CHAR
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
+ does not count in the resultant output. If a WIDE_CHAR is
+ hit, then 2 Unicode character will consume an output storage
+ space with size of CHAR16 till a NARROW_CHAR is hit.
+
+ @param String The input string to be counted.
+
+ @return Storage space for the input string.
+
+**/
+UINTN
+GetStringWidth (
+ CHAR16 *String
+ )
+;
+
+/**
+ Will copy LineWidth amount of a string in the OutputString buffer and return the
+ number of CHAR16 characters that were copied into the OutputString buffer.
+
+ @param InputString String description for this option.
+ @param LineWidth Width of the desired string to extract in CHAR16
+ characters
+ @param Index Where in InputString to start the copy process
+ @param OutputString Buffer to copy the string into
+
+ @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.
+
+**/
+UINT16
+GetLineByWidth (
+ IN CHAR16 *InputString,
+ IN UINT16 LineWidth,
+ IN OUT UINTN *Index,
+ OUT CHAR16 **OutputString
+ )
+;
+
+/**
+ Get the supported width for a particular op-code
+
+ @param Statement The FORM_BROWSER_STATEMENT structure passed in.
+ @param Handle The handle in the HII database being used
+
+ @return Returns the number of CHAR16 characters that is support.
+
+**/
+UINT16
+GetWidth (
+ IN FORM_BROWSER_STATEMENT *Statement,
+ IN EFI_HII_HANDLE Handle
+ )
+;
+
+/**
+ Concatenate a narrow string to another string.
+
+ @param Destination The destination string.
+ @param Source The source string. The string to be concatenated.
+ to the end of Destination.
+
+**/
+VOID
+NewStrCat (
+ CHAR16 *Destination,
+ CHAR16 *Source
+ )
+;
+
+/**
+ Wait for a key to be pressed by user.
+
+ @param Key The key which is pressed by user.
+
+ @retval EFI_SUCCESS The function always completed successfully.
+
+**/
+EFI_STATUS
+WaitForKeyStroke (
+ OUT EFI_INPUT_KEY *Key
+ )
+;
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetScopeStack (
+ VOID
+ )
+;
+
+/**
+ Push an Operand onto the Stack
+
+ @param Operand Operand to push.
+
+ @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
+PushScope (
+ IN UINT8 Operand
+ )
+;
+
+/**
+ Pop an Operand from the Stack
+
+ @param Operand Operand to 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
+PopScope (
+ OUT UINT8 *Operand
+ )
+;
+
+/**
+ Get Form given its FormId.
+
+ @param FormSet The formset which contains this form.
+ @param FormId Id of this form.
+
+ @retval Pointer The form.
+ @retval NULL Specified Form is not found in the formset.
+
+**/
+FORM_BROWSER_FORM *
+IdToForm (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN UINT16 FormId
+ )
+;
+
+/**
+ Search a Question in Formset scope using its QuestionId.
+
+ @param FormSet The formset which contains this form.
+ @param Form The form which contains this Question.
+ @param QuestionId Id of this Question.
+
+ @retval Pointer The Question.
+ @retval NULL Specified Question not found in the form.
+
+**/
+FORM_BROWSER_STATEMENT *
+IdToQuestion (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT16 QuestionId
+ )
+;
+
+/**
+ Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+ @param Value HII Value to be converted.
+
+**/
+VOID
+ExtendValueToU64 (
+ IN EFI_HII_VALUE *Value
+ )
+;
+
+/**
+ Compare two Hii value.
+
+ @param Value1 Expression value to compare on left-hand.
+ @param Value2 Expression value to compare on right-hand.
+ @param HiiHandle Only required for string compare.
+
+ @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.
+ @retval 0 Two operators equeal.
+ @return Positive value if Value1 is greater than Value2.
+ @retval Negative value if Value1 is less than Value2.
+
+**/
+INTN
+CompareHiiValue (
+ IN EFI_HII_VALUE *Value1,
+ IN EFI_HII_VALUE *Value2,
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL
+ )
+;
+
+/**
+ Evaluate the result of a HII expression
+
+ @param FormSet FormSet associated with this expression.
+ @param Form Form associated with this expression.
+ @param Expression Expression to be evaluated.
+
+ @retval EFI_SUCCESS The expression evaluated successfuly
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
+ could not be found.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression
+
+**/
+EFI_STATUS
+EvaluateExpression (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_EXPRESSION *Expression
+ )
+;
+
+#endif // _UI_H