/** @file
+MACRO definitions for color used in Setup Browser.
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
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
-/** @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\r
+Utility functions for expression evaluation.\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ui.h"\r
+#include "Setup.h"\r
+\r
+//\r
+// Global stack used to evaluate boolean expresions\r
+//\r
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
+\r
+EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
+EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
+EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
+\r
+//\r
+// Unicode collation protocol interface\r
+//\r
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
+\r
+\r
+/**\r
+ Grow size of the stack.\r
+\r
+ This is an internal function.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+\r
+ @retval EFI_SUCCESS Grow stack success.\r
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
+\r
+**/\r
+EFI_STATUS\r
+GrowStack (\r
+ IN OUT EFI_HII_VALUE **Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ IN OUT EFI_HII_VALUE **StackEnd\r
+ )\r
+{\r
+ UINTN Size;\r
+ EFI_HII_VALUE *NewStack;\r
+\r
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
+ if (*StackPtr != NULL) {\r
+ Size = Size + (*StackEnd - *Stack);\r
+ }\r
+\r
+ NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
+ if (NewStack == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (*StackPtr != NULL) {\r
+ //\r
+ // Copy from Old Stack to the New Stack\r
+ //\r
+ CopyMem (\r
+ NewStack,\r
+ *Stack,\r
+ (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
+ );\r
+\r
+ //\r
+ // Free The Old Stack\r
+ //\r
+ gBS->FreePool (*Stack);\r
+ }\r
+\r
+ //\r
+ // Make the Stack pointer point to the old data in the new stack\r
+ //\r
+ *StackPtr = NewStack + (*StackPtr - *Stack);\r
+ *Stack = NewStack;\r
+ *StackEnd = NewStack + Size;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Push an element onto the Boolean Stack.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param Data Data to push.\r
+\r
+ @retval EFI_SUCCESS Push stack success.\r
+\r
+**/\r
+EFI_STATUS\r
+PushStack (\r
+ IN OUT EFI_HII_VALUE **Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ IN OUT EFI_HII_VALUE **StackEnd,\r
+ IN EFI_HII_VALUE *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check for a stack overflow condition\r
+ //\r
+ if (*StackPtr >= *StackEnd) {\r
+ //\r
+ // Grow the stack\r
+ //\r
+ Status = GrowStack (Stack, StackPtr, StackEnd);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Push the item onto the stack\r
+ //\r
+ CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
+ *StackPtr = *StackPtr + 1;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Pop an element from the stack.\r
+\r
+ @param Stack On input: old stack; On output: new stack\r
+ @param StackPtr On input: old stack pointer; On output: new stack\r
+ pointer\r
+ @param StackEnd On input: old stack end; On output: new stack end\r
+ @param Data Data to pop.\r
+\r
+ @retval EFI_SUCCESS The value was popped onto the stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopStack (\r
+ IN OUT EFI_HII_VALUE **Stack,\r
+ IN OUT EFI_HII_VALUE **StackPtr,\r
+ IN OUT EFI_HII_VALUE **StackEnd,\r
+ OUT EFI_HII_VALUE *Data\r
+ )\r
+{\r
+ //\r
+ // Check for a stack underflow condition\r
+ //\r
+ if (*StackPtr == *Stack) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Pop the item off the stack\r
+ //\r
+ *StackPtr = *StackPtr - 1;\r
+ CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+ VOID\r
+ )\r
+{\r
+ mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
+}\r
+\r
+\r
+/**\r
+ Push an Operand onto the Stack\r
+\r
+ @param Operand Operand to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+ IN UINT8 Operand\r
+ )\r
+{\r
+ EFI_HII_VALUE Data;\r
+\r
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ Data.Value.u8 = Operand;\r
+\r
+ return PushStack (\r
+ &mOpCodeScopeStack,\r
+ &mOpCodeScopeStackPointer,\r
+ &mOpCodeScopeStackEnd,\r
+ &Data\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Pop an Operand from the Stack\r
+\r
+ @param Operand Operand to pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+ OUT UINT8 *Operand\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Data;\r
+\r
+ Status = PopStack (\r
+ &mOpCodeScopeStack,\r
+ &mOpCodeScopeStackPointer,\r
+ &mOpCodeScopeStackEnd,\r
+ &Data\r
+ );\r
+\r
+ *Operand = Data.Value.u8;\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetExpressionStack (\r
+ VOID\r
+ )\r
+{\r
+ mExpressionEvaluationStackPointer = mExpressionEvaluationStack;\r
+}\r
+\r
+\r
+/**\r
+ Push an Expression value onto the Stack\r
+\r
+ @param Value Expression value to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushExpression (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ return PushStack (\r
+ &mExpressionEvaluationStack,\r
+ &mExpressionEvaluationStackPointer,\r
+ &mExpressionEvaluationStackEnd,\r
+ Value\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Pop an Expression value from the stack.\r
+\r
+ @param Value Expression value to pop.\r
+\r
+ @retval EFI_SUCCESS The value was popped onto the stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+\r
+**/\r
+EFI_STATUS\r
+PopExpression (\r
+ OUT EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ return PopStack (\r
+ &mExpressionEvaluationStack,\r
+ &mExpressionEvaluationStackPointer,\r
+ &mExpressionEvaluationStackEnd,\r
+ Value\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Get Form given its FormId.\r
+\r
+ @param FormSet The formset which contains this form.\r
+ @param FormId Id of this form.\r
+\r
+ @retval Pointer The form.\r
+ @retval NULL Specified Form is not found in the formset.\r
+\r
+**/\r
+FORM_BROWSER_FORM *\r
+IdToForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN UINT16 FormId\r
+)\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ if (Form->FormId == FormId) {\r
+ return Form;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Search a Question in Form scope using its QuestionId.\r
+\r
+ @param Form The form which contains this Question.\r
+ @param QuestionId Id of this Question.\r
+\r
+ @retval Pointer The Question.\r
+ @retval NULL Specified Question not found in the form.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+IdToQuestion2 (\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 QuestionId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ if (QuestionId == 0) {\r
+ //\r
+ // The value of zero is reserved\r
+ //\r
+ return NULL;\r
+ }\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (Question->QuestionId == QuestionId) {\r
+ return Question;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Search a Question in Formset scope using its QuestionId.\r
+\r
+ @param FormSet The formset which contains this form.\r
+ @param Form The form which contains this Question.\r
+ @param QuestionId Id of this Question.\r
+\r
+ @retval Pointer The Question.\r
+ @retval NULL Specified Question not found in the form.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+IdToQuestion (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 QuestionId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ //\r
+ // Search in the form scope first\r
+ //\r
+ Question = IdToQuestion2 (Form, QuestionId);\r
+ if (Question != NULL) {\r
+ return Question;\r
+ }\r
+\r
+ //\r
+ // Search in the formset scope\r
+ //\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ Question = IdToQuestion2 (Form, QuestionId);\r
+ if (Question != NULL) {\r
+ return Question;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Get Expression given its RuleId.\r
+\r
+ @param Form The form which contains this Expression.\r
+ @param RuleId Id of this Expression.\r
+\r
+ @retval Pointer The Expression.\r
+ @retval NULL Specified Expression not found in the form.\r
+\r
+**/\r
+FORM_EXPRESSION *\r
+RuleIdToExpression (\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT8 RuleId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_EXPRESSION *Expression;\r
+\r
+ Link = GetFirstNode (&Form->ExpressionListHead);\r
+ while (!IsNull (&Form->ExpressionListHead, Link)) {\r
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+\r
+ if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
+ return Expression;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Locate the Unicode Collation Protocol interface for later use.\r
+\r
+ @retval EFI_SUCCESS Protocol interface initialize success.\r
+ @retval Other Protocol interface initialize failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeUnicodeCollationProtocol (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (mUnicodeCollation != NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
+ // instances first and then select one which support English language.\r
+ // Current implementation just pick the first instance.\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiUnicodeCollation2ProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mUnicodeCollation\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Convert the input Unicode character to upper.\r
+\r
+ @param String Th Unicode character to be converted.\r
+\r
+**/\r
+VOID\r
+IfrStrToUpper (\r
+ CHAR16 *String\r
+ )\r
+{\r
+ while (*String != 0) {\r
+ if ((*String >= 'a') && (*String <= 'z')) {\r
+ *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
+ }\r
+ String++;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_TO_STRING.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Format String format in EFI_IFR_TO_STRING.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToString (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN UINT8 Format,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String;\r
+ CHAR16 *PrintFormat;\r
+ CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
+ UINTN BufferSize;\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ switch (Value.Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
+ switch (Format) {\r
+ case EFI_IFR_STRING_UNSIGNED_DEC:\r
+ case EFI_IFR_STRING_SIGNED_DEC:\r
+ PrintFormat = L"%ld";\r
+ break;\r
+\r
+ case EFI_IFR_STRING_LOWERCASE_HEX:\r
+ PrintFormat = L"%lx";\r
+ break;\r
+\r
+ case EFI_IFR_STRING_UPPERCASE_HEX:\r
+ PrintFormat = L"%lX";\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
+ String = Buffer;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_STRING:\r
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+ return EFI_SUCCESS;\r
+\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ String = (Value.Value.b) ? L"True" : L"False";\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewString (String, FormSet->HiiHandle);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_TO_UINT.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToUint (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String;\r
+ CHAR16 *StringPtr;\r
+ UINTN BufferSize;\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Value.Type >= EFI_IFR_TYPE_OTHER) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ if (Value.Type == EFI_IFR_TYPE_STRING) {\r
+ String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+ if (String == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ IfrStrToUpper (String);\r
+ StringPtr = StrStr (String, L"0X");\r
+ if (StringPtr != NULL) {\r
+ //\r
+ // Hex string\r
+ //\r
+ BufferSize = sizeof (UINT64);\r
+ Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);\r
+ } else {\r
+ //\r
+ // BUGBUG: Need handle decimal string\r
+ //\r
+ }\r
+ gBS->FreePool (String);\r
+ } else {\r
+ CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_CATENATE.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrCatenate (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String[2];\r
+ UINTN Index;\r
+ CHAR16 *StringPtr;\r
+ UINTN Size;\r
+\r
+ //\r
+ // String[0] - The second string\r
+ // String[1] - The first string\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ StringPtr = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Index = 0; Index < 2; Index++) {\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+ if (String== NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Size = StrSize (String[0]);\r
+ StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
+ ASSERT (StringPtr != NULL);\r
+ StrCpy (StringPtr, String[1]);\r
+ StrCat (StringPtr, String[0]);\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
+\r
+Done:\r
+ SafeFreePool (String[0]);\r
+ SafeFreePool (String[1]);\r
+ SafeFreePool (StringPtr);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_MATCH.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMatch (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String[2];\r
+ UINTN Index;\r
+\r
+ //\r
+ // String[0] - The string to search\r
+ // String[1] - pattern\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ Status = EFI_SUCCESS;\r
+ for (Index = 0; Index < 2; Index++) {\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+ if (String== NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
+\r
+Done:\r
+ SafeFreePool (String[0]);\r
+ SafeFreePool (String[1]);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_FIND.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Format Case sensitive or insensitive.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrFind (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN UINT8 Format,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String[2];\r
+ UINTN Base;\r
+ CHAR16 *StringPtr;\r
+ UINTN Index;\r
+\r
+ if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Base = (UINTN) Value.Value.u64;\r
+\r
+ //\r
+ // String[0] - sub-string\r
+ // String[1] - The string to search\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ for (Index = 0; Index < 2; Index++) {\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+ if (String== NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
+ //\r
+ // Case insensitive, convert both string to upper case\r
+ //\r
+ IfrStrToUpper (String[Index]);\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ if (Base >= StrLen (String[1])) {\r
+ Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
+ } else {\r
+ StringPtr = StrStr (String[1] + Base, String[0]);\r
+ Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
+ }\r
+\r
+Done:\r
+ SafeFreePool (String[0]);\r
+ SafeFreePool (String[1]);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_MID.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrMid (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String;\r
+ UINTN Base;\r
+ UINTN Length;\r
+ CHAR16 *SubString;\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Length = (UINTN) Value.Value.u64;\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Base = (UINTN) Value.Value.u64;\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+ if (String == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (Length == 0 || Base >= StrLen (String)) {\r
+ SubString = gEmptyString;\r
+ } else {\r
+ SubString = String + Base;\r
+ if ((Base + Length) < StrLen (String)) {\r
+ SubString[Length] = L'\0';\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
+\r
+ gBS->FreePool (String);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_TOKEN.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrToken (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String[2];\r
+ UINTN Count;\r
+ CHAR16 *Delimiter;\r
+ CHAR16 *SubString;\r
+ CHAR16 *StringPtr;\r
+ UINTN Index;\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Count = (UINTN) Value.Value.u64;\r
+\r
+ //\r
+ // String[0] - Delimiter\r
+ // String[1] - The string to search\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ for (Index = 0; Index < 2; Index++) {\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+ if (String== NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Delimiter = String[0];\r
+ SubString = String[1];\r
+ while (Count > 0) {\r
+ SubString = StrStr (SubString, Delimiter);\r
+ if (SubString != NULL) {\r
+ //\r
+ // Skip over the delimiter\r
+ //\r
+ SubString = SubString + StrLen (Delimiter);\r
+ } else {\r
+ break;\r
+ }\r
+ Count--;\r
+ }\r
+\r
+ if (SubString == NULL) {\r
+ //\r
+ // nth delimited sub-string not found, push an empty string\r
+ //\r
+ SubString = gEmptyString;\r
+ } else {\r
+ //\r
+ // Put a NULL terminator for nth delimited sub-string\r
+ //\r
+ StringPtr = StrStr (SubString, Delimiter);\r
+ if (StringPtr != NULL) {\r
+ *StringPtr = L'\0';\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_STRING;\r
+ Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
+\r
+Done:\r
+ SafeFreePool (String[0]);\r
+ SafeFreePool (String[1]);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate opcode EFI_IFR_SPAN.\r
+\r
+ @param FormSet Formset which contains this opcode.\r
+ @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
+ @param Result Evaluation result for this opcode.\r
+\r
+ @retval EFI_SUCCESS Opcode evaluation success.\r
+ @retval Other Opcode evaluation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+IfrSpan (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN UINT8 Flags,\r
+ OUT EFI_HII_VALUE *Result\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_VALUE Value;\r
+ CHAR16 *String[2];\r
+ CHAR16 *Charset;\r
+ UINTN Base;\r
+ UINTN Index;\r
+ CHAR16 *StringPtr;\r
+ BOOLEAN Found;\r
+\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Base = (UINTN) Value.Value.u64;\r
+\r
+ //\r
+ // String[0] - Charset\r
+ // String[1] - The string to search\r
+ //\r
+ String[0] = NULL;\r
+ String[1] = NULL;\r
+ for (Index = 0; Index < 2; Index++) {\r
+ Status = PopExpression (&Value);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Value.Type != EFI_IFR_TYPE_STRING) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
+ if (String== NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (Base >= StrLen (String[1])) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Found = FALSE;\r
+ StringPtr = String[1] + Base;\r
+ Charset = String[0];\r
+ while (*StringPtr != 0 && !Found) {\r
+ Index = 0;\r
+ while (Charset[Index] != 0) {\r
+ if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
+ if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ } else {\r
+ if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Skip characters pair representing low-end of a range and high-end of a range\r
+ //\r
+ Index += 2;\r
+ }\r
+\r
+ if (!Found) {\r
+ StringPtr++;\r
+ }\r
+ }\r
+\r
+ Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Result->Value.u64 = StringPtr - String[1];\r
+\r
+Done:\r
+ SafeFreePool (String[0]);\r
+ SafeFreePool (String[1]);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+ @param Value HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+{\r
+ UINT64 Temp;\r
+\r
+ Temp = 0;\r
+ switch (Value->Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Temp = Value->Value.u8;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Temp = Value->Value.u16;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Temp = Value->Value.u32;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ Temp = Value->Value.b;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_TIME:\r
+ Temp = Value->Value.u32 & 0xffffff;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_DATE:\r
+ Temp = Value->Value.u32;\r
+ break;\r
+\r
+ default:\r
+ return;\r
+ }\r
+\r
+ Value->Value.u64 = Temp;\r
+}\r
+\r
+\r
+/**\r
+ Compare two Hii value.\r
+\r
+ @param Value1 Expression value to compare on left-hand.\r
+ @param Value2 Expression value to compare on right-hand.\r
+ @param HiiHandle Only required for string compare.\r
+\r
+ @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.\r
+ @retval 0 Two operators equeal.\r
+ @return Positive value if Value1 is greater than Value2.\r
+ @retval Negative value if Value1 is less than Value2.\r
+\r
+**/\r
+INTN\r
+CompareHiiValue (\r
+ IN EFI_HII_VALUE *Value1,\r
+ IN EFI_HII_VALUE *Value2,\r
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
+ )\r
+{\r
+ INTN Result;\r
+ INT64 Temp64;\r
+ CHAR16 *Str1;\r
+ CHAR16 *Str2;\r
+\r
+ if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
+ if (Value1->Type != Value2->Type) {\r
+ //\r
+ // Both Operator should be type of String\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
+ //\r
+ // StringId 0 is reserved\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Value1->Value.string == Value2->Value.string) {\r
+ return 0;\r
+ }\r
+\r
+ Str1 = GetToken (Value1->Value.string, HiiHandle);\r
+ if (Str1 == NULL) {\r
+ //\r
+ // String not found\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Str2 = GetToken (Value2->Value.string, HiiHandle);\r
+ if (Str2 == NULL) {\r
+ gBS->FreePool (Str1);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Result = StrCmp (Str1, Str2);\r
+\r
+ gBS->FreePool (Str1);\r
+ gBS->FreePool (Str2);\r
+\r
+ return Result;\r
+ }\r
+\r
+ //\r
+ // Take remain types(integer, boolean, date/time) as integer\r
+ //\r
+ Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
+ if (Temp64 > 0) {\r
+ Result = 1;\r
+ } else if (Temp64 < 0) {\r
+ Result = -1;\r
+ } else {\r
+ Result = 0;\r
+ }\r
+\r
+ return Result;\r
+}\r
+\r
+\r
+/**\r
+ Evaluate the result of a HII expression\r
+\r
+ @param FormSet FormSet associated with this expression.\r
+ @param Form Form associated with this expression.\r
+ @param Expression Expression to be evaluated.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfuly\r
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
+ could not be found.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateExpression (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_EXPRESSION *Expression\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ EXPRESSION_OPCODE *OpCode;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ FORM_BROWSER_STATEMENT *Question2;\r
+ UINT16 Index;\r
+ EFI_HII_VALUE Data1;\r
+ EFI_HII_VALUE Data2;\r
+ EFI_HII_VALUE Data3;\r
+ FORM_EXPRESSION *RuleExpression;\r
+ EFI_HII_VALUE *Value;\r
+ INTN Result;\r
+ CHAR16 *StrPtr;\r
+ UINT32 TempValue;\r
+\r
+ //\r
+ // Always reset the stack before evaluating an Expression\r
+ //\r
+ ResetExpressionStack ();\r
+\r
+ Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
+\r
+ Link = GetFirstNode (&Expression->OpCodeListHead);\r
+ while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
+ OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
+\r
+ Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
+\r
+ ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
+ ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
+ ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
+\r
+ Value = &Data3;\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (OpCode->Operand) {\r
+ //\r
+ // Built-in functions\r
+ //\r
+ case EFI_IFR_EQ_ID_VAL_OP:\r
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+ if (Question == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
+ if (Result == EFI_INVALID_PARAMETER) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_ID_OP:\r
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+ if (Question == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
+ if (Question2 == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
+ if (Result == EFI_INVALID_PARAMETER) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_EQ_ID_LIST_OP:\r
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+ if (Question == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Value->Value.b = FALSE;\r
+ for (Index =0; Index < OpCode->ListLength; Index++) {\r
+ if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
+ Value->Value.b = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_DUP_OP:\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PushExpression (Value);\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF1_OP:\r
+ case EFI_IFR_THIS_OP:\r
+ Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
+ if (Question == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Value = &Question->HiiValue;\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF3_OP:\r
+ if (OpCode->DevicePath == 0) {\r
+ //\r
+ // EFI_IFR_QUESTION_REF3\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Validate the expression value\r
+ //\r
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
+ if (Question == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // push the questions' value on to the expression stack\r
+ //\r
+ Value = &Question->HiiValue;\r
+ } else {\r
+ //\r
+ // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
+ // since it is impractical to evaluate the value of a Question in another\r
+ // Hii Package list.\r
+ //\r
+ ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_RULE_REF_OP:\r
+ //\r
+ // Find expression for this rule\r
+ //\r
+ RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
+ if (RuleExpression == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Evaluate this rule expression\r
+ //\r
+ Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Value = &RuleExpression->Result;\r
+ break;\r
+\r
+ case EFI_IFR_STRING_REF1_OP:\r
+ Value->Type = EFI_IFR_TYPE_STRING;\r
+ Value->Value.string = OpCode->Value.Value.string;\r
+ break;\r
+\r
+ //\r
+ // Constant\r
+ //\r
+ case EFI_IFR_TRUE_OP:\r
+ case EFI_IFR_FALSE_OP:\r
+ case EFI_IFR_ONE_OP:\r
+ case EFI_IFR_ONES_OP:\r
+ case EFI_IFR_UINT8_OP:\r
+ case EFI_IFR_UINT16_OP:\r
+ case EFI_IFR_UINT32_OP:\r
+ case EFI_IFR_UINT64_OP:\r
+ case EFI_IFR_UNDEFINED_OP:\r
+ case EFI_IFR_VERSION_OP:\r
+ case EFI_IFR_ZERO_OP:\r
+ Value = &OpCode->Value;\r
+ break;\r
+\r
+ //\r
+ // unary-op\r
+ //\r
+ case EFI_IFR_LENGTH_OP:\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Value->Value.u64 = StrLen (StrPtr);\r
+ gBS->FreePool (StrPtr);\r
+ break;\r
+\r
+ case EFI_IFR_NOT_OP:\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
+ break;\r
+\r
+ case EFI_IFR_QUESTION_REF2_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Validate the expression value\r
+ //\r
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
+ if (Question == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Value = &Question->HiiValue;\r
+ break;\r
+\r
+ case EFI_IFR_STRING_REF2_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Validate the expression value\r
+ //\r
+ if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_STRING;\r
+ StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ //\r
+ // If String not exit, push an empty string\r
+ //\r
+ Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
+ } else {\r
+ Index = (UINT16) Value->Value.u64;\r
+ Value->Value.string = Index;\r
+ gBS->FreePool (StrPtr);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_TO_BOOLEAN_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Convert an expression to a Boolean\r
+ //\r
+ if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
+ //\r
+ // When converting from an unsigned integer, zero will be converted to\r
+ // FALSE and any other value will be converted to TRUE.\r
+ //\r
+ Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);\r
+\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
+ //\r
+ // When converting from a string, if case-insensitive compare\r
+ // with "true" is True, then push True. If a case-insensitive compare\r
+ // with "false" is True, then push False.\r
+ //\r
+ StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
+ Value->Value.b = TRUE;\r
+ } else {\r
+ Value->Value.b = FALSE;\r
+ }\r
+ gBS->FreePool (StrPtr);\r
+ Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_TO_STRING_OP:\r
+ Status = IfrToString (FormSet, OpCode->Format, Value);\r
+ break;\r
+\r
+ case EFI_IFR_TO_UINT_OP:\r
+ Status = IfrToUint (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_TO_LOWER_OP:\r
+ case EFI_IFR_TO_UPPER_OP:\r
+ Status = InitializeUnicodeCollationProtocol ();\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
+ if (StrPtr == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
+ mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
+ } else {\r
+ mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
+ }\r
+ Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
+ gBS->FreePool (StrPtr);\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_NOT_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Value->Type > EFI_IFR_TYPE_DATE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+ Value->Value.u64 = ~Value->Value.u64;\r
+ break;\r
+\r
+ //\r
+ // binary-op\r
+ //\r
+ case EFI_IFR_ADD_OP:\r
+ case EFI_IFR_SUBTRACT_OP:\r
+ case EFI_IFR_MULTIPLY_OP:\r
+ case EFI_IFR_DIVIDE_OP:\r
+ case EFI_IFR_MODULO_OP:\r
+ case EFI_IFR_BITWISE_AND_OP:\r
+ case EFI_IFR_BITWISE_OR_OP:\r
+ case EFI_IFR_SHIFT_LEFT_OP:\r
+ case EFI_IFR_SHIFT_RIGHT_OP:\r
+ //\r
+ // Pop an expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Pop another expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
+\r
+ switch (OpCode->Operand) {\r
+ case EFI_IFR_ADD_OP:\r
+ Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
+ break;\r
+\r
+ case EFI_IFR_SUBTRACT_OP:\r
+ Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
+ break;\r
+\r
+ case EFI_IFR_MULTIPLY_OP:\r
+ Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
+ break;\r
+\r
+ case EFI_IFR_DIVIDE_OP:\r
+ Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
+ break;\r
+\r
+ case EFI_IFR_MODULO_OP:\r
+ DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
+ Value->Value.u64 = TempValue;\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_AND_OP:\r
+ Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
+ break;\r
+\r
+ case EFI_IFR_BITWISE_OR_OP:\r
+ Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
+ break;\r
+\r
+ case EFI_IFR_SHIFT_LEFT_OP:\r
+ Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
+ break;\r
+\r
+ case EFI_IFR_SHIFT_RIGHT_OP:\r
+ Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_AND_OP:\r
+ case EFI_IFR_OR_OP:\r
+ //\r
+ // Two Boolean operator\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Pop another expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (OpCode->Operand == EFI_IFR_AND_OP) {\r
+ Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
+ } else {\r
+ Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_EQUAL_OP:\r
+ case EFI_IFR_NOT_EQUAL_OP:\r
+ case EFI_IFR_GREATER_EQUAL_OP:\r
+ case EFI_IFR_GREATER_THAN_OP:\r
+ case EFI_IFR_LESS_EQUAL_OP:\r
+ case EFI_IFR_LESS_THAN_OP:\r
+ //\r
+ // Compare two integer, string, boolean or date/time\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Pop another expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
+ if (Result == EFI_INVALID_PARAMETER) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ switch (OpCode->Operand) {\r
+ case EFI_IFR_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_NOT_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_GREATER_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_GREATER_THAN_OP:\r
+ Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_LESS_EQUAL_OP:\r
+ Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ case EFI_IFR_LESS_THAN_OP:\r
+ Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_MATCH_OP:\r
+ Status = IfrMatch (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_CATENATE_OP:\r
+ Status = IfrCatenate (FormSet, Value);\r
+ break;\r
+\r
+ //\r
+ // ternary-op\r
+ //\r
+ case EFI_IFR_CONDITIONAL_OP:\r
+ //\r
+ // Pop third expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data3);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Pop second expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Pop first expression from the expression stack\r
+ //\r
+ Status = PopExpression (&Data1);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Data1.Value.b) {\r
+ Value = &Data3;\r
+ } else {\r
+ Value = &Data2;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_FIND_OP:\r
+ Status = IfrFind (FormSet, OpCode->Format, Value);\r
+ break;\r
+\r
+ case EFI_IFR_MID_OP:\r
+ Status = IfrMid (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_TOKEN_OP:\r
+ Status = IfrToken (FormSet, Value);\r
+ break;\r
+\r
+ case EFI_IFR_SPAN_OP:\r
+ Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PushExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Pop the final result from expression stack\r
+ //\r
+ Value = &Data1;\r
+ Status = PopExpression (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // After evaluating an expression, there should be only one value left on the expression stack\r
+ //\r
+ if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
/** @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
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"
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>
/**
- Free resources of a Expression
+ Free resources of a Expression.
@param FormSet Pointer of the Expression
- @return None.
-
**/
VOID
DestroyExpression (
/**
- Free resources of a storage
+ Free resources of a storage.
@param Storage Pointer of the storage
- @return None.
-
**/
VOID
DestroyStorage (
/**
- Free resources of a Statement
+ Free resources of a Statement.
@param Statement Pointer of the Statement
- @return None.
-
**/
VOID
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
/**
- Free resources allocated for a FormSet
+ Free resources allocated for a FormSet.
@param FormSet Pointer of the FormSet
- @return None.
-
**/
VOID
DestroyFormSet (
@param NumberOfStatement Number of Statemens(Questions)
@param NumberOfExpression Number of Expression OpCodes
- @return None.
-
**/
VOID
CountOpCodes (
//
// If scope bit set, push onto scope stack
//
- if (Scope) {
+ if (Scope != 0) {
PushScope (Operand);
}
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
- if (Scope) {
+ if (Scope != 0) {
mInScopeSubtitle = TRUE;
}
break;
InitializeRequestElement (FormSet, CurrentStatement);
- if ((Operand == EFI_IFR_ONE_OF_OP) && Scope) {
+ if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
SuppressForOption = TRUE;
}
break;
CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;
CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
- if (Scope) {
+ if (Scope != 0) {
SuppressForOption = TRUE;
}
break;
//
InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
- if (Scope) {
+ if (Scope != 0) {
InScopeDefault = TRUE;
}
break;
-/** @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\r
+Implementation for handling user input from the User Interfaces.\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ui.h"\r
+#include "Setup.h"\r
+\r
+\r
+/**\r
+ Get string or password input from user.\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+ @param Prompt The prompt string shown on popup window.\r
+ @param StringPtr Destination for use input string.\r
+\r
+ @retval EFI_SUCCESS If string input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+ReadString (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN CHAR16 *Prompt,\r
+ OUT CHAR16 *StringPtr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 NullCharacter;\r
+ UINTN ScreenSize;\r
+ CHAR16 Space[2];\r
+ CHAR16 KeyPad[2];\r
+ CHAR16 *TempString;\r
+ CHAR16 *BufferedString;\r
+ UINTN Index;\r
+ UINTN Count;\r
+ UINTN Start;\r
+ UINTN Top;\r
+ UINTN DimensionsWidth;\r
+ UINTN DimensionsHeight;\r
+ BOOLEAN CursorVisible;\r
+ UINTN Minimum;\r
+ UINTN Maximum;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ BOOLEAN IsPassword;\r
+\r
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
+\r
+ NullCharacter = CHAR_NULL;\r
+ ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16);\r
+ Space[0] = L' ';\r
+ Space[1] = CHAR_NULL;\r
+\r
+ Question = MenuOption->ThisTag;\r
+ Minimum = (UINTN) Question->Minimum;\r
+ Maximum = (UINTN) Question->Maximum;\r
+\r
+ if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
+ IsPassword = TRUE;\r
+ } else {\r
+ IsPassword = FALSE;\r
+ }\r
+\r
+ TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));\r
+ ASSERT (TempString);\r
+\r
+ if (ScreenSize < (Maximum + 1)) {\r
+ ScreenSize = Maximum + 1;\r
+ }\r
+\r
+ if ((ScreenSize + 2) > DimensionsWidth) {\r
+ ScreenSize = DimensionsWidth - 2;\r
+ }\r
+\r
+ BufferedString = AllocateZeroPool (ScreenSize * 2);\r
+ ASSERT (BufferedString);\r
+\r
+ Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
+ Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;\r
+\r
+ //\r
+ // Display prompt for string\r
+ //\r
+ CreatePopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
+\r
+ CursorVisible = gST->ConOut->Mode->CursorVisible;\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ do {\r
+ Status = WaitForKeyStroke (&Key);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
+ switch (Key.UnicodeChar) {\r
+ case CHAR_NULL:\r
+ switch (Key.ScanCode) {\r
+ case SCAN_LEFT:\r
+ break;\r
+\r
+ case SCAN_RIGHT:\r
+ break;\r
+\r
+ case SCAN_ESC:\r
+ gBS->FreePool (TempString);\r
+ gBS->FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {\r
+\r
+ gBS->FreePool (TempString);\r
+ gBS->FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Simply create a popup to tell the user that they had typed in too few characters.\r
+ // To save code space, we can then treat this as an error and return back to the menu.\r
+ //\r
+ do {\r
+ CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ gBS->FreePool (TempString);\r
+ gBS->FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ break;\r
+\r
+ case CHAR_BACKSPACE:\r
+ if (StringPtr[0] != CHAR_NULL) {\r
+ for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {\r
+ TempString[Index] = StringPtr[Index];\r
+ }\r
+ //\r
+ // Effectively truncate string by 1 character\r
+ //\r
+ TempString[Index - 1] = CHAR_NULL;\r
+ StrCpy (StringPtr, TempString);\r
+ }\r
+\r
+ default:\r
+ //\r
+ // If it is the beginning of the string, don't worry about checking maximum limits\r
+ //\r
+ if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+ StrnCpy (StringPtr, &Key.UnicodeChar, 1);\r
+ StrnCpy (TempString, &Key.UnicodeChar, 1);\r
+ } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+ KeyPad[0] = Key.UnicodeChar;\r
+ KeyPad[1] = CHAR_NULL;\r
+ StrCat (StringPtr, KeyPad);\r
+ StrCat (TempString, KeyPad);\r
+ }\r
+\r
+ //\r
+ // If the width of the input string is now larger than the screen, we nee to\r
+ // adjust the index to start printing portions of the string\r
+ //\r
+ SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');\r
+ PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+\r
+ if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {\r
+ Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;\r
+ } else {\r
+ Index = 0;\r
+ }\r
+\r
+ if (IsPassword) {\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);\r
+ }\r
+\r
+ for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {\r
+ BufferedString[Count] = StringPtr[Index];\r
+\r
+ if (IsPassword) {\r
+ PrintChar (L'*');\r
+ }\r
+ }\r
+\r
+ if (!IsPassword) {\r
+ PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+ }\r
+ break;\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);\r
+ } while (TRUE);\r
+\r
+}\r
+\r
+\r
+/**\r
+ This routine reads a numeric value from the user input.\r
+\r
+ @param Selection Pointer to current selection.\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If numerical input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetNumericInput (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Column;\r
+ UINTN Row;\r
+ CHAR16 InputText[23];\r
+ CHAR16 FormattedNumber[22];\r
+ UINT64 PreviousNumber[20];\r
+ UINTN Count;\r
+ UINTN Loop;\r
+ BOOLEAN ManualInput;\r
+ BOOLEAN HexInput;\r
+ BOOLEAN DateOrTime;\r
+ UINTN InputWidth;\r
+ UINT64 EditValue;\r
+ UINT64 Step;\r
+ UINT64 Minimum;\r
+ UINT64 Maximum;\r
+ UINTN EraseLen;\r
+ UINT8 Digital;\r
+ EFI_INPUT_KEY Key;\r
+ EFI_HII_VALUE *QuestionValue;\r
+ FORM_BROWSER_FORM *Form;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ Column = MenuOption->OptCol;\r
+ Row = MenuOption->Row;\r
+ PreviousNumber[0] = 0;\r
+ Count = 0;\r
+ InputWidth = 0;\r
+ Digital = 0;\r
+\r
+ FormSet = Selection->FormSet;\r
+ Form = Selection->Form;\r
+ Question = MenuOption->ThisTag;\r
+ QuestionValue = &Question->HiiValue;\r
+ Step = Question->Step;\r
+ Minimum = Question->Minimum;\r
+ Maximum = Question->Maximum;\r
+\r
+ if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
+ DateOrTime = TRUE;\r
+ } else {\r
+ DateOrTime = FALSE;\r
+ }\r
+\r
+ //\r
+ // Prepare Value to be edit\r
+ //\r
+ EraseLen = 0;\r
+ EditValue = 0;\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ Step = 1;\r
+ Minimum = 1;\r
+\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ Maximum = 12;\r
+ EraseLen = 4;\r
+ EditValue = QuestionValue->Value.date.Month;\r
+ break;\r
+\r
+ case 1:\r
+ Maximum = 31;\r
+ EraseLen = 3;\r
+ EditValue = QuestionValue->Value.date.Day;\r
+ break;\r
+\r
+ case 2:\r
+ Maximum = 0xffff;\r
+ EraseLen = 5;\r
+ EditValue = QuestionValue->Value.date.Year;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
+ Step = 1;\r
+ Minimum = 0;\r
+\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ Maximum = 23;\r
+ EraseLen = 4;\r
+ EditValue = QuestionValue->Value.time.Hour;\r
+ break;\r
+\r
+ case 1:\r
+ Maximum = 59;\r
+ EraseLen = 3;\r
+ EditValue = QuestionValue->Value.time.Minute;\r
+ break;\r
+\r
+ case 2:\r
+ Maximum = 59;\r
+ EraseLen = 3;\r
+ EditValue = QuestionValue->Value.time.Second;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ //\r
+ // Numeric\r
+ //\r
+ EraseLen = gOptionBlockWidth;\r
+ EditValue = QuestionValue->Value.u64;\r
+ if (Maximum == 0) {\r
+ Maximum = (UINT64) -1;\r
+ }\r
+ }\r
+\r
+ if (Step == 0) {\r
+ ManualInput = TRUE;\r
+ } else {\r
+ ManualInput = FALSE;\r
+ }\r
+\r
+ if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&\r
+ ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {\r
+ HexInput = TRUE;\r
+ } else {\r
+ HexInput = FALSE;\r
+ }\r
+\r
+ if (ManualInput) {\r
+ if (HexInput) {\r
+ InputWidth = Question->StorageWidth * 2;\r
+ } else {\r
+ switch (Question->StorageWidth) {\r
+ case 1:\r
+ InputWidth = 3;\r
+ break;\r
+\r
+ case 2:\r
+ InputWidth = 5;\r
+ break;\r
+\r
+ case 4:\r
+ InputWidth = 10;\r
+ break;\r
+\r
+ case 8:\r
+ InputWidth = 20;\r
+ break;\r
+\r
+ default:\r
+ InputWidth = 0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+ SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+ InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+ InputText[InputWidth + 2] = L'\0';\r
+\r
+ PrintAt (Column, Row, InputText);\r
+ Column++;\r
+ }\r
+\r
+ //\r
+ // First time we enter this handler, we need to check to see if\r
+ // we were passed an increment or decrement directive\r
+ //\r
+ do {\r
+ Key.UnicodeChar = CHAR_NULL;\r
+ if (gDirection != 0) {\r
+ Key.ScanCode = gDirection;\r
+ gDirection = 0;\r
+ goto TheKey2;\r
+ }\r
+\r
+ Status = WaitForKeyStroke (&Key);\r
+\r
+TheKey2:\r
+ switch (Key.UnicodeChar) {\r
+\r
+ case '+':\r
+ case '-':\r
+ if (Key.UnicodeChar == '+') {\r
+ Key.ScanCode = SCAN_RIGHT;\r
+ } else {\r
+ Key.ScanCode = SCAN_LEFT;\r
+ }\r
+ Key.UnicodeChar = CHAR_NULL;\r
+ goto TheKey2;\r
+\r
+ case CHAR_NULL:\r
+ switch (Key.ScanCode) {\r
+ case SCAN_LEFT:\r
+ case SCAN_RIGHT:\r
+ if (DateOrTime) {\r
+ //\r
+ // By setting this value, we will return back to the caller.\r
+ // We need to do this since an auto-refresh will destroy the adjustment\r
+ // based on what the real-time-clock is showing. So we always commit\r
+ // upon changing the value.\r
+ //\r
+ gDirection = SCAN_DOWN;\r
+ }\r
+\r
+ if (!ManualInput) {\r
+ if (Key.ScanCode == SCAN_LEFT) {\r
+ if (EditValue > Step) {\r
+ EditValue = EditValue - Step;\r
+ } else {\r
+ EditValue = Minimum;\r
+ }\r
+ } else if (Key.ScanCode == SCAN_RIGHT) {\r
+ EditValue = EditValue + Step;\r
+ if (EditValue > Maximum) {\r
+ EditValue = Maximum;\r
+ }\r
+ }\r
+\r
+ ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ if (MenuOption->Sequence == 2) {\r
+ //\r
+ // Year\r
+ //\r
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", EditValue);\r
+ } else {\r
+ //\r
+ // Month/Day\r
+ //\r
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);\r
+ }\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;\r
+ } else if (MenuOption->Sequence == 1) {\r
+ FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;\r
+ }\r
+ } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", EditValue);\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;\r
+ } else if (MenuOption->Sequence == 1) {\r
+ FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;\r
+ }\r
+ } else {\r
+ QuestionValue->Value.u64 = EditValue;\r
+ PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+ for (Loop = 0; Loop < EraseLen; Loop++) {\r
+ PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");\r
+ }\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);\r
+ Column = MenuOption->OptCol + 1;\r
+ }\r
+\r
+ PrintStringAt (Column, Row, FormattedNumber);\r
+\r
+ if (!DateOrTime || MenuOption->Sequence == 2) {\r
+ PrintChar (RIGHT_NUMERIC_DELIMITER);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case SCAN_UP:\r
+ case SCAN_DOWN:\r
+ goto EnterCarriageReturn;\r
+\r
+ case SCAN_ESC:\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+EnterCarriageReturn:\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ //\r
+ // Store Edit value back to Question\r
+ //\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ QuestionValue->Value.date.Month = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 1:\r
+ QuestionValue->Value.date.Day = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 2:\r
+ QuestionValue->Value.date.Year = (UINT16) EditValue;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ QuestionValue->Value.time.Hour = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 1:\r
+ QuestionValue->Value.time.Minute = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 2:\r
+ QuestionValue->Value.time.Second = (UINT8) EditValue;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ //\r
+ // Numeric\r
+ //\r
+ QuestionValue->Value.u64 = EditValue;\r
+ }\r
+\r
+ //\r
+ // Check to see if the Value is something reasonable against consistency limitations.\r
+ // If not, let's kick the error specified.\r
+ //\r
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Input value is not valid, restore Question Value\r
+ //\r
+ GetQuestionValue (FormSet, Form, Question, TRUE);\r
+ } else {\r
+ SetQuestionValue (FormSet, Form, Question, TRUE);\r
+ if (!DateOrTime || (Question->Storage != NULL)) {\r
+ //\r
+ // NV flag is unnecessary for RTC type of Date/Time\r
+ //\r
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+ break;\r
+\r
+ case CHAR_BACKSPACE:\r
+ if (ManualInput) {\r
+ if (Count == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Remove a character\r
+ //\r
+ EditValue = PreviousNumber[Count - 1];\r
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);\r
+ Count--;\r
+ Column--;\r
+ PrintAt (Column, Row, L" ");\r
+ }\r
+ break;\r
+\r
+ default:\r
+ if (ManualInput) {\r
+ if (HexInput) {\r
+ if (!IsHexDigit (&Digital, Key.UnicodeChar)) {\r
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+ break;\r
+ }\r
+ } else {\r
+ if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {\r
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If Count exceed input width, there is no way more is valid\r
+ //\r
+ if (Count >= InputWidth) {\r
+ break;\r
+ }\r
+ //\r
+ // Someone typed something valid!\r
+ //\r
+ if (Count != 0) {\r
+ if (HexInput) {\r
+ EditValue = LShiftU64 (EditValue, 4) + Digital;\r
+ } else {\r
+ EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');\r
+ }\r
+ } else {\r
+ if (HexInput) {\r
+ EditValue = Digital;\r
+ } else {\r
+ EditValue = Key.UnicodeChar - L'0';\r
+ }\r
+ }\r
+\r
+ if (EditValue > Maximum) {\r
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, TRUE);\r
+ EditValue = PreviousNumber[Count];\r
+ break;\r
+ } else {\r
+ UpdateStatusBar (INPUT_ERROR, Question->QuestionFlags, FALSE);\r
+ }\r
+\r
+ Count++;\r
+ PreviousNumber[Count] = EditValue;\r
+\r
+ PrintCharAt (Column, Row, Key.UnicodeChar);\r
+ Column++;\r
+ }\r
+ break;\r
+ }\r
+ } while (TRUE);\r
+\r
+}\r
+\r
+\r
+/**\r
+ Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
+\r
+ @param Selection Pointer to current selection.\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If Option input is processed successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetSelectionInputPopUp (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ UINTN Index;\r
+ CHAR16 *StringPtr;\r
+ CHAR16 *TempStringPtr;\r
+ UINTN Index2;\r
+ UINTN TopOptionIndex;\r
+ UINTN HighlightOptionIndex;\r
+ UINTN Start;\r
+ UINTN End;\r
+ UINTN Top;\r
+ UINTN Bottom;\r
+ UINTN PopUpMenuLines;\r
+ UINTN MenuLinesInView;\r
+ UINTN PopUpWidth;\r
+ CHAR16 Character;\r
+ INT32 SavedAttribute;\r
+ BOOLEAN ShowDownArrow;\r
+ BOOLEAN ShowUpArrow;\r
+ UINTN DimensionsWidth;\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN OrderedList;\r
+ UINT8 *ValueArray;\r
+ EFI_HII_VALUE HiiValue;\r
+ EFI_HII_VALUE *HiiValueArray;\r
+ UINTN OptionCount;\r
+ QUESTION_OPTION *OneOfOption;\r
+ QUESTION_OPTION *CurrentOption;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+\r
+ ValueArray = NULL;\r
+ CurrentOption = NULL;\r
+ ShowDownArrow = FALSE;\r
+ ShowUpArrow = FALSE;\r
+\r
+ StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);\r
+ ASSERT (StringPtr);\r
+\r
+ Question = MenuOption->ThisTag;\r
+ if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+ ValueArray = Question->BufferValue;\r
+ OrderedList = TRUE;\r
+ } else {\r
+ OrderedList = FALSE;\r
+ }\r
+\r
+ //\r
+ // Calculate Option count\r
+ //\r
+ if (OrderedList) {\r
+ for (Index = 0; Index < Question->MaxContainers; Index++) {\r
+ if (ValueArray[Index] == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ OptionCount = Index;\r
+ } else {\r
+ OptionCount = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ OptionCount++;\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Prepare HiiValue array\r
+ //\r
+ HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));\r
+ ASSERT (HiiValueArray != NULL);\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ if (OrderedList) {\r
+ HiiValueArray[Index].Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ HiiValueArray[Index].Value.u8 = ValueArray[Index];\r
+ } else {\r
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+ CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Move Suppressed Option to list tail\r
+ //\r
+ PopUpMenuLines = 0;\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);\r
+ if (OneOfOption == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ RemoveEntryList (&OneOfOption->Link);\r
+\r
+ if ((OneOfOption->SuppressExpression != NULL) &&\r
+ (OneOfOption->SuppressExpression->Result.Value.b)) {\r
+ //\r
+ // This option is suppressed, insert to tail\r
+ //\r
+ InsertTailList (&Question->OptionListHead, &OneOfOption->Link);\r
+ } else {\r
+ //\r
+ // Insert to head\r
+ //\r
+ InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);\r
+\r
+ PopUpMenuLines++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get the number of one of options present and its size\r
+ //\r
+ PopUpWidth = 0;\r
+ HighlightOptionIndex = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ for (Index = 0; Index < PopUpMenuLines; Index++) {\r
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
+ if (StrLen (StringPtr) > PopUpWidth) {\r
+ PopUpWidth = StrLen (StringPtr);\r
+ }\r
+ gBS->FreePool (StringPtr);\r
+\r
+ if (!OrderedList && CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, NULL) == 0) {\r
+ //\r
+ // Find current selected Option for OneOf\r
+ //\r
+ HighlightOptionIndex = Index;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Perform popup menu initialization.\r
+ //\r
+ PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;\r
+\r
+ SavedAttribute = gST->ConOut->Mode->Attribute;\r
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+\r
+ if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {\r
+ PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;\r
+ }\r
+\r
+ Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;\r
+ End = Start + PopUpWidth + POPUP_FRAME_WIDTH;\r
+ Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;\r
+ Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - 1;\r
+\r
+ MenuLinesInView = Bottom - Top - 1;\r
+ if (MenuLinesInView >= PopUpMenuLines) {\r
+ Top = Top + (MenuLinesInView - PopUpMenuLines) / 2;\r
+ Bottom = Top + PopUpMenuLines + 1;\r
+ } else {\r
+ ShowDownArrow = TRUE;\r
+ }\r
+\r
+ if (HighlightOptionIndex > (MenuLinesInView - 1)) {\r
+ TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;\r
+ } else {\r
+ TopOptionIndex = 0;\r
+ }\r
+\r
+ do {\r
+ //\r
+ // Clear that portion of the screen\r
+ //\r
+ ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);\r
+\r
+ //\r
+ // Draw "One of" pop-up menu\r
+ //\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (Start, Top, Character);\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {\r
+ Character = GEOMETRICSHAPE_UP_TRIANGLE;\r
+ } else {\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ }\r
+\r
+ PrintChar (Character);\r
+ }\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintChar (Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Index = Top + 1; Index < Bottom; Index++) {\r
+ PrintCharAt (Start, Index, Character);\r
+ PrintCharAt (End - 1, Index, Character);\r
+ }\r
+\r
+ //\r
+ // Move to top Option\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ for (Index = 0; Index < TopOptionIndex; Index++) {\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Display the One of options\r
+ //\r
+ Index2 = Top + 1;\r
+ for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {\r
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
+ //\r
+ // If the string occupies multiple lines, truncate it to fit in one line,\r
+ // and append a "..." for indication.\r
+ //\r
+ if (StrLen (StringPtr) > (PopUpWidth - 1)) {\r
+ TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));\r
+ ASSERT ( TempStringPtr != NULL );\r
+ CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));\r
+ gBS->FreePool (StringPtr);\r
+ StringPtr = TempStringPtr;\r
+ StrCat (StringPtr, L"...");\r
+ }\r
+\r
+ if (Index == HighlightOptionIndex) {\r
+ //\r
+ // Highlight the selected one\r
+ //\r
+ CurrentOption = OneOfOption;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);\r
+ PrintStringAt (Start + 2, Index2, StringPtr);\r
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+ PrintStringAt (Start + 2, Index2, StringPtr);\r
+ }\r
+\r
+ Index2++;\r
+ gBS->FreePool (StringPtr);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (Start, Bottom, Character);\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {\r
+ Character = GEOMETRICSHAPE_DOWN_TRIANGLE;\r
+ } else {\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ }\r
+\r
+ PrintChar (Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintChar (Character);\r
+\r
+ //\r
+ // Get User selection\r
+ //\r
+ Key.UnicodeChar = CHAR_NULL;\r
+ if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {\r
+ Key.ScanCode = gDirection;\r
+ gDirection = 0;\r
+ goto TheKey;\r
+ }\r
+\r
+ Status = WaitForKeyStroke (&Key);\r
+\r
+TheKey:\r
+ switch (Key.UnicodeChar) {\r
+ case '+':\r
+ if (OrderedList) {\r
+ if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
+ //\r
+ // Highlight reaches the top of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex--;\r
+ ShowDownArrow = TRUE;\r
+ }\r
+\r
+ if (TopOptionIndex == 0) {\r
+ ShowUpArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex > 0) {\r
+ HighlightOptionIndex--;\r
+\r
+ SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case '-':\r
+ //\r
+ // If an ordered list op-code, we will allow for a popup of +/- keys\r
+ // to create an ordered list of items\r
+ //\r
+ if (OrderedList) {\r
+ if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
+ (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
+ //\r
+ // Highlight reaches the bottom of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex++;\r
+ ShowUpArrow = TRUE;\r
+ }\r
+\r
+ if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
+ ShowDownArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
+ HighlightOptionIndex++;\r
+\r
+ SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CHAR_NULL:\r
+ switch (Key.ScanCode) {\r
+ case SCAN_UP:\r
+ case SCAN_DOWN:\r
+ if (Key.ScanCode == SCAN_UP) {\r
+ if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
+ //\r
+ // Highlight reaches the top of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex--;\r
+ ShowDownArrow = TRUE;\r
+ }\r
+\r
+ if (TopOptionIndex == 0) {\r
+ ShowUpArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex > 0) {\r
+ HighlightOptionIndex--;\r
+ }\r
+ } else {\r
+ if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
+ (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
+ //\r
+ // Highlight reaches the bottom of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex++;\r
+ ShowUpArrow = TRUE;\r
+ }\r
+\r
+ if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
+ ShowDownArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
+ HighlightOptionIndex++;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case SCAN_ESC:\r
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+\r
+ //\r
+ // Restore link list order for orderedlist\r
+ //\r
+ if (OrderedList) {\r
+ HiiValue.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
+ HiiValue.Value.u64 = 0;\r
+ for (Index = 0; Index < Question->MaxContainers; Index++) {\r
+ HiiValue.Value.u8 = ValueArray[Index];\r
+ if (HiiValue.Value.u8) {\r
+ break;\r
+ }\r
+\r
+ OneOfOption = ValueToOption (Question, &HiiValue);\r
+ if (OneOfOption == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ RemoveEntryList (&OneOfOption->Link);\r
+ InsertTailList (&Question->OptionListHead, &OneOfOption->Link);\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (HiiValueArray);\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ //\r
+ // return the current selection\r
+ //\r
+ if (OrderedList) {\r
+ Index = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ Question->BufferValue[Index] = OneOfOption->Value.Value.u8;\r
+\r
+ Index++;\r
+ if (Index > Question->MaxContainers) {\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+ } else {\r
+ CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+ gBS->FreePool (HiiValueArray);\r
+\r
+ Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Input value is not valid, restore Question Value\r
+ //\r
+ GetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
+ } else {\r
+ SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE);\r
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
+ }\r
+\r
+ return Status;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } while (TRUE);\r
+\r
+}\r
+\r
+/**\r
+ Wait for a key to be pressed by user.\r
+\r
+ @param Key The key which is pressed by user.\r
+\r
+ @retval EFI_SUCCESS The function always completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForKeyStroke (\r
+ OUT EFI_INPUT_KEY *Key\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ do {\r
+ UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
+ } while (EFI_ERROR(Status));\r
+\r
+ return Status;\r
+}\r
-/** @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\r
+Utility functions for UI presentation.\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+#include "Ui.h"\r
+\r
+BOOLEAN mHiiPackageListUpdated;\r
+UI_MENU_SELECTION *gCurrentSelection;\r
+\r
+\r
+/**\r
+ Clear retangle with specified text attribute.\r
+\r
+ @param LeftColumn Left column of retangle.\r
+ @param RightColumn Right column of retangle.\r
+ @param TopRow Start row of retangle.\r
+ @param BottomRow End row of retangle.\r
+ @param TextAttribute The character foreground and background.\r
+\r
+**/\r
+VOID\r
+ClearLines (\r
+ UINTN LeftColumn,\r
+ UINTN RightColumn,\r
+ UINTN TopRow,\r
+ UINTN BottomRow,\r
+ UINTN TextAttribute\r
+ )\r
+{\r
+ CHAR16 *Buffer;\r
+ UINTN Row;\r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ //\r
+ // Set foreground and background as defined\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\r
+\r
+ //\r
+ // Much faster to buffer the long string instead of print it a character at a time\r
+ //\r
+ SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\r
+\r
+ //\r
+ // Clear the desired area with the appropriate foreground/background\r
+ //\r
+ for (Row = TopRow; Row <= BottomRow; Row++) {\r
+ PrintStringAt (LeftColumn, Row, Buffer);\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
+\r
+ gBS->FreePool (Buffer);\r
+ return ;\r
+}\r
+\r
+/**\r
+ Concatenate a narrow string to another string.\r
+\r
+ @param Destination The destination string.\r
+ @param Source The source string. The string to be concatenated.\r
+ to the end of Destination.\r
+\r
+**/\r
+VOID\r
+NewStrCat (\r
+ CHAR16 *Destination,\r
+ CHAR16 *Source\r
+ )\r
+{\r
+ UINTN Length;\r
+\r
+ for (Length = 0; Destination[Length] != 0; Length++)\r
+ ;\r
+\r
+ //\r
+ // We now have the length of the original string\r
+ // We can safely assume for now that we are concatenating a narrow value to this string.\r
+ // For instance, the string is "XYZ" and cat'ing ">"\r
+ // If this assumption changes, we need to make this routine a bit more complex\r
+ //\r
+ Destination[Length] = NARROW_CHAR;\r
+ Length++;\r
+\r
+ StrCpy (Destination + Length, Source);\r
+}\r
+\r
+/**\r
+ Count the storage space of a Unicode string.\r
+\r
+ This function handles the Unicode string with NARROW_CHAR\r
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
+ does not count in the resultant output. If a WIDE_CHAR is \r
+ hit, then 2 Unicode character will consume an output storage\r
+ space with size of CHAR16 till a NARROW_CHAR is hit.\r
+\r
+ @param String The input string to be counted.\r
+\r
+ @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetStringWidth (\r
+ CHAR16 *String\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ UINTN IncrementValue;\r
+\r
+ Index = 0;\r
+ Count = 0;\r
+ IncrementValue = 1;\r
+\r
+ do {\r
+ //\r
+ // Advance to the null-terminator or to the first width directive\r
+ //\r
+ for (;\r
+ (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
+ Index++, Count = Count + IncrementValue\r
+ )\r
+ ;\r
+\r
+ //\r
+ // We hit the null-terminator, we now have a count\r
+ //\r
+ if (String[Index] == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
+ // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
+ //\r
+ if (String[Index] == NARROW_CHAR) {\r
+ //\r
+ // Skip to the next character\r
+ //\r
+ Index++;\r
+ IncrementValue = 1;\r
+ } else {\r
+ //\r
+ // Skip to the next character\r
+ //\r
+ Index++;\r
+ IncrementValue = 2;\r
+ }\r
+ } while (String[Index] != 0);\r
+\r
+ //\r
+ // Increment by one to include the null-terminator in the size\r
+ //\r
+ Count++;\r
+\r
+ return Count * sizeof (CHAR16);\r
+}\r
+\r
+/**\r
+ This function displays the page frame.\r
+\r
+**/\r
+VOID\r
+DisplayPageFrame (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 Line;\r
+ UINT8 Alignment;\r
+ CHAR16 Character;\r
+ CHAR16 *Buffer;\r
+ CHAR16 *StrFrontPageBanner;\r
+ UINTN Row;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+\r
+ ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
+ ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ Character = BOXDRAW_HORIZONTAL;\r
+\r
+ for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
+ Buffer[Index] = Character;\r
+ }\r
+\r
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+ //\r
+ // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
+ //\r
+ ClearLines (\r
+ LocalScreen.LeftColumn,\r
+ LocalScreen.RightColumn,\r
+ LocalScreen.TopRow,\r
+ FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
+ BANNER_TEXT | BANNER_BACKGROUND\r
+ );\r
+ //\r
+ // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
+ //\r
+ for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
+ //\r
+ // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
+ //\r
+ for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
+ Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
+ Alignment++\r
+ ) {\r
+ if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {\r
+ StrFrontPageBanner = GetToken (\r
+ BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],\r
+ FrontPageHandle\r
+ );\r
+ } else {\r
+ continue;\r
+ }\r
+\r
+ switch (Alignment - LocalScreen.LeftColumn) {\r
+ case 0:\r
+ //\r
+ // Handle left column\r
+ //\r
+ PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);\r
+ break;\r
+\r
+ case 1:\r
+ //\r
+ // Handle center column\r
+ //\r
+ PrintStringAt (\r
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
+ Line,\r
+ StrFrontPageBanner\r
+ );\r
+ break;\r
+\r
+ case 2:\r
+ //\r
+ // Handle right column\r
+ //\r
+ PrintStringAt (\r
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
+ Line,\r
+ StrFrontPageBanner\r
+ );\r
+ break;\r
+ }\r
+\r
+ gBS->FreePool (StrFrontPageBanner);\r
+ }\r
+ }\r
+ }\r
+\r
+ ClearLines (\r
+ LocalScreen.LeftColumn,\r
+ LocalScreen.RightColumn,\r
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,\r
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
+ KEYHELP_TEXT | KEYHELP_BACKGROUND\r
+ );\r
+\r
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+ ClearLines (\r
+ LocalScreen.LeftColumn,\r
+ LocalScreen.RightColumn,\r
+ LocalScreen.TopRow,\r
+ LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
+ TITLE_TEXT | TITLE_BACKGROUND\r
+ );\r
+ //\r
+ // Print Top border line\r
+ // +------------------------------------------------------------------------------+\r
+ // ? ?\r
+ // +------------------------------------------------------------------------------+\r
+ //\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+\r
+ PrintChar (Character);\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintChar (Character);\r
+\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintChar (Character);\r
+\r
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+ //\r
+ // Print Bottom border line\r
+ // +------------------------------------------------------------------------------+\r
+ // ? ?\r
+ // +------------------------------------------------------------------------------+\r
+ //\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);\r
+\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintChar (Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;\r
+ Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
+ Row++\r
+ ) {\r
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
+\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintChar (Character);\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (Buffer);\r
+\r
+}\r
+\r
+\r
+/**\r
+ Evaluate all expressions in a Form.\r
+\r
+ @param FormSet FormSet this Form belongs to.\r
+ @param Form The Form.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfuly\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateFormExpressions (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_EXPRESSION *Expression;\r
+\r
+ Link = GetFirstNode (&Form->ExpressionListHead);\r
+ while (!IsNull (&Form->ExpressionListHead, Link)) {\r
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+\r
+ if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+ //\r
+ // Postpone Form validation to Question editing or Form submiting\r
+ //\r
+ continue;\r
+ }\r
+\r
+ Status = EvaluateExpression (FormSet, Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/*\r
++------------------------------------------------------------------------------+\r
+?F2=Previous Page Setup Page ?\r
++------------------------------------------------------------------------------+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
++------------------------------------------------------------------------------+\r
+?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?\r
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |\r
++------------------------------------------------------------------------------+\r
+*/\r
+\r
+/**\r
+\r
+ \r
+ Display form and wait for user to select one menu option, then return it.\r
+ \r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+ @retval EFI_SUCESSS This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS\r
+DisplayForm (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ UINT16 MenuItemCount;\r
+ EFI_HII_HANDLE Handle;\r
+ BOOLEAN Suppress;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ UINT16 Width;\r
+ UINTN ArrayEntry;\r
+ CHAR16 *OutputString;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ UINT16 NumberOfLines;\r
+ EFI_STATUS Status;\r
+\r
+ Handle = Selection->Handle;\r
+ MenuItemCount = 0;\r
+ ArrayEntry = 0;\r
+ OutputString = NULL;\r
+\r
+ UiInitMenu ();\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ StringPtr = GetToken (Selection->FormSet->FormSetTitle, Handle);\r
+\r
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
+ PrintStringAt (\r
+ (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
+ LocalScreen.TopRow + 1,\r
+ StringPtr\r
+ );\r
+ }\r
+\r
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ //\r
+ // Display the infrastructure strings\r
+ //\r
+ if (!IsListEmpty (&gMenuList)) {\r
+ PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);\r
+ }\r
+\r
+ PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);\r
+ PrintStringAt (\r
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
+ LocalScreen.BottomRow - 4,\r
+ gFunctionNineString\r
+ );\r
+ PrintStringAt (\r
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
+ LocalScreen.BottomRow - 4,\r
+ gFunctionTenString\r
+ );\r
+ PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ PrintStringAt (\r
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
+ LocalScreen.BottomRow - 3,\r
+ gEscapeString\r
+ );\r
+ }\r
+ //\r
+ // Remove Buffer allocated for StringPtr after it has been used.\r
+ //\r
+ gBS->FreePool (StringPtr);\r
+\r
+ //\r
+ // Evaluate all the Expressions in this Form\r
+ //\r
+ Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = GetFirstNode (&Selection->Form->StatementListHead);\r
+ while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (Statement->SuppressExpression != NULL) {\r
+ Suppress = Statement->SuppressExpression->Result.Value.b;\r
+ } else {\r
+ Suppress = FALSE;\r
+ }\r
+\r
+ if (!Suppress) {\r
+ StringPtr = GetToken (Statement->Prompt, Handle);\r
+\r
+ Width = GetWidth (Statement, Handle);\r
+\r
+ NumberOfLines = 1;\r
+ ArrayEntry = 0;\r
+ for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&StringPtr[ArrayEntry])) {\r
+ NumberOfLines++;\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ }\r
+\r
+ //\r
+ // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
+ // it in UiFreeMenu.\r
+ //\r
+ UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
+ MenuItemCount++;\r
+ }\r
+\r
+ Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+ }\r
+\r
+ Status = UiDisplayMenu (Selection);\r
+\r
+ UiFreeMenu ();\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeBrowserStrings (\r
+ VOID\r
+ )\r
+{\r
+ gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);\r
+ gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);\r
+ gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
+ gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
+ gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
+ gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
+ gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
+ gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
+ gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
+ gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
+ gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
+ gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
+ gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
+ gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
+ gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
+ gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
+ gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
+ gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
+ gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
+ gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
+ gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
+ gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
+ gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
+ gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
+ gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
+ gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
+ gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
+ return ;\r
+}\r
+\r
+/**\r
+ Free up the resource allocated for all strings required\r
+ by Setup Browser.\r
+\r
+**/\r
+VOID\r
+FreeBrowserStrings (\r
+ VOID\r
+ )\r
+{\r
+ SafeFreePool (gFunctionOneString);\r
+ SafeFreePool (gFunctionTwoString);\r
+ SafeFreePool (gFunctionNineString);\r
+ SafeFreePool (gFunctionTenString);\r
+ SafeFreePool (gEnterString);\r
+ SafeFreePool (gEnterCommitString);\r
+ SafeFreePool (gEscapeString);\r
+ SafeFreePool (gMoveHighlight);\r
+ SafeFreePool (gMakeSelection);\r
+ SafeFreePool (gDecNumericInput);\r
+ SafeFreePool (gHexNumericInput);\r
+ SafeFreePool (gToggleCheckBox);\r
+ SafeFreePool (gPromptForData);\r
+ SafeFreePool (gPromptForPassword);\r
+ SafeFreePool (gPromptForNewPassword);\r
+ SafeFreePool (gConfirmPassword);\r
+ SafeFreePool (gPassowordInvalid);\r
+ SafeFreePool (gConfirmError);\r
+ SafeFreePool (gPressEnter);\r
+ SafeFreePool (gEmptyString);\r
+ SafeFreePool (gAreYouSure);\r
+ SafeFreePool (gYesResponse);\r
+ SafeFreePool (gNoResponse);\r
+ SafeFreePool (gMiniString);\r
+ SafeFreePool (gPlusString);\r
+ SafeFreePool (gMinusString);\r
+ SafeFreePool (gAdjustNumber);\r
+ return ;\r
+}\r
+\r
+\r
+/**\r
+ Update key's help imformation.\r
+\r
+ @param MenuOption The Menu option\r
+ @param Selected Whether or not a tag be selected\r
+\r
+**/\r
+VOID\r
+UpdateKeyHelp (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN BOOLEAN Selected\r
+ )\r
+{\r
+ UINTN SecCol;\r
+ UINTN ThdCol;\r
+ UINTN LeftColumnOfHelp;\r
+ UINTN RightColumnOfHelp;\r
+ UINTN TopRowOfHelp;\r
+ UINTN BottomRowOfHelp;\r
+ UINTN StartColumnOfHelp;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
+ ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;\r
+\r
+ StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
+ LeftColumnOfHelp = LocalScreen.LeftColumn + 1;\r
+ RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
+ TopRowOfHelp = LocalScreen.BottomRow - 4;\r
+ BottomRowOfHelp = LocalScreen.BottomRow - 3;\r
+\r
+ if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {\r
+ return ;\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ Statement = MenuOption->ThisTag;\r
+ switch (Statement->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_NUMERIC_OP:\r
+ case EFI_IFR_TIME_OP:\r
+ case EFI_IFR_DATE_OP:\r
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ if (!Selected) {\r
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
+ (Statement->Operand == EFI_IFR_TIME_OP) ||\r
+ (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {\r
+ PrintAt (\r
+ StartColumnOfHelp,\r
+ BottomRowOfHelp,\r
+ L"%c%c%c%c%s",\r
+ ARROW_UP,\r
+ ARROW_DOWN,\r
+ ARROW_RIGHT,\r
+ ARROW_LEFT,\r
+ gMoveHighlight\r
+ );\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
+ } else {\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ }\r
+ } else {\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
+\r
+ //\r
+ // If it is a selected numeric with manual input, display different message\r
+ //\r
+ if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {\r
+ PrintStringAt (\r
+ SecCol,\r
+ TopRowOfHelp,\r
+ ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
+ );\r
+ } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ }\r
+\r
+ if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
+ PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
+ }\r
+\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
+ break;\r
+\r
+ case EFI_IFR_REF_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ case EFI_IFR_STRING_OP:\r
+ case EFI_IFR_TEXT_OP:\r
+ case EFI_IFR_ACTION_OP:\r
+ case EFI_IFR_RESET_BUTTON_OP:\r
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ if (!Selected) {\r
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);\r
+ PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
+ PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ if (Statement->Operand != EFI_IFR_TEXT_OP) {\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ }\r
+ } else {\r
+ if (Statement->Operand != EFI_IFR_REF_OP) {\r
+ PrintStringAt (\r
+ (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
+ BottomRowOfHelp,\r
+ gEnterCommitString\r
+ );\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Functions which are registered to receive notification of\r
+ database events have this prototype. The actual event is encoded\r
+ in NotifyType. The following table describes how PackageType,\r
+ PackageGuid, Handle, and Package are used for each of the\r
+ notification types.\r
+\r
+ @param PackageType Package type of the notification.\r
+\r
+ @param PackageGuid If PackageType is\r
+ EFI_HII_PACKAGE_TYPE_GUID, then this is\r
+ the pointer to the GUID from the Guid\r
+ field of EFI_HII_PACKAGE_GUID_HEADER.\r
+ Otherwise, it must be NULL.\r
+\r
+ @param Package Points to the package referred to by the\r
+ notification Handle The handle of the package\r
+ list which contains the specified package.\r
+\r
+ @param Handle The HII handle.\r
+\r
+ @param NotifyType The type of change concerning the\r
+ database. See\r
+ EFI_HII_DATABASE_NOTIFY_TYPE.\r
+\r
+**/\r
+EFI_STATUS\r
+FormUpdateNotify (\r
+ IN UINT8 PackageType,\r
+ IN CONST EFI_GUID *PackageGuid,\r
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
+ )\r
+{\r
+ mHiiPackageListUpdated = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ The worker function that send the displays to the screen. On output,\r
+ the selection made by user is returned.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+\r
+ @retval EFI_SUCCESS The page is displayed successfully.\r
+ @return Other value if the page failed to be diplayed.\r
+\r
+**/\r
+EFI_STATUS\r
+SetupBrowser (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_HANDLE NotifyHandle;\r
+ EFI_HII_VALUE *HiiValue;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+\r
+ gMenuRefreshHead = NULL;\r
+ gResetRequired = FALSE;\r
+ gNvUpdateRequired = FALSE;\r
+\r
+ UiInitMenuList ();\r
+\r
+ //\r
+ // Register notify for Form package update\r
+ //\r
+ Status = mHiiDatabase->RegisterPackageNotify (\r
+ mHiiDatabase,\r
+ EFI_HII_PACKAGE_FORM,\r
+ NULL,\r
+ FormUpdateNotify,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ &NotifyHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ do {\r
+ //\r
+ // Displays the Header and Footer borders\r
+ //\r
+ DisplayPageFrame ();\r
+\r
+ //\r
+ // Initialize Selection->Form\r
+ //\r
+ if (Selection->FormId == 0) {\r
+ //\r
+ // Zero FormId indicates display the first Form in a FormSet\r
+ //\r
+ Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
+\r
+ Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Selection->FormId = Selection->Form->FormId;\r
+ } else {\r
+ Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
+ }\r
+\r
+ //\r
+ // Load Questions' Value for display\r
+ //\r
+ Status = LoadFormConfig (Selection->FormSet, Selection->Form);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Display form\r
+ //\r
+ Status = DisplayForm (Selection);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
+ //\r
+ Statement = Selection->Statement;\r
+ if (Statement != NULL) {\r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
+ gResetRequired = TRUE;\r
+ }\r
+\r
+ //\r
+ // Reset FormPackage update flag\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
+\r
+ if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ HiiValue = &Statement->HiiValue;\r
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+ //\r
+ // Create String in HII database for Configuration Driver to retrieve\r
+ //\r
+ HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
+ }\r
+\r
+ ConfigAccess = Selection->FormSet->ConfigAccess;\r
+ if (ConfigAccess == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ EFI_BROWSER_ACTION_CHANGING,\r
+ Statement->QuestionId,\r
+ HiiValue->Type,\r
+ &HiiValue->Value,\r
+ &ActionRequest\r
+ );\r
+\r
+ if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+ //\r
+ // Clean the String in HII Database\r
+ //\r
+ DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ switch (ActionRequest) {\r
+ case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+ gResetRequired = TRUE;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+ SubmitForm (Selection->FormSet, Selection->Form);\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ gNvUpdateRequired = FALSE;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check whether Form Package has been updated during Callback\r
+ //\r
+ if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
+ //\r
+ // Force to reparse IFR binary of target Formset\r
+ //\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ }\r
+ }\r
+ } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
+\r
+ //\r
+ // Unregister notify for Form package update\r
+ //\r
+ Status = mHiiDatabase->UnregisterPackageNotify (\r
+ mHiiDatabase,\r
+ NotifyHandle\r
+ );\r
+ return Status;\r
+}\r
-/** @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\r
+Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very\r
+simple implemenation of SPrint() and Print() to support debug.\r
+\r
+You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a\r
+time. This makes the implementation very simple.\r
+\r
+VSPrint, Print, SPrint format specification has the follwoing form\r
+\r
+%type\r
+\r
+type:\r
+ 'S','s' - argument is an Unicode string\r
+ 'c' - argument is an ascii character\r
+ '%' - Print a %\r
+\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+\r
+/**\r
+ VSPrint worker function that prints a Value as a decimal number in Buffer.\r
+\r
+ @param Buffer Location to place ascii decimal number string of Value.\r
+ @param Flags Flags to use in printing decimal string, see file header for\r
+ details.\r
+ @param Value Decimal value to convert to a string in Buffer.\r
+\r
+ @return Number of characters printed.\r
+\r
+**/\r
+UINTN\r
+ValueToString (\r
+ IN OUT CHAR16 *Buffer,\r
+ IN BOOLEAN Flags,\r
+ IN INT64 Value\r
+ );\r
+\r
+/**\r
+ The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
+ protocol instance.\r
+\r
+ @param Column The position of the output string.\r
+ @param Row The position of the output string.\r
+ @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.\r
+ @param Fmt The format string.\r
+ @param Args The additional argument for the variables in the format string.\r
+\r
+ @return Number of Unicode character printed.\r
+\r
+**/\r
+UINTN\r
+PrintInternal (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,\r
+ IN CHAR16 *Fmt,\r
+ IN VA_LIST Args\r
+ )\r
+{\r
+ CHAR16 *Buffer;\r
+ CHAR16 *BackupBuffer;\r
+ UINTN Index;\r
+ UINTN PreviousIndex;\r
+ UINTN Count;\r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ BackupBuffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer);\r
+ ASSERT (BackupBuffer);\r
+\r
+ if (Column != (UINTN) -1) {\r
+ Out->SetCursorPosition (Out, Column, Row);\r
+ }\r
+\r
+ UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);\r
+\r
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
+\r
+ Out->SetAttribute (Out, Out->Mode->Attribute);\r
+\r
+ Index = 0;\r
+ PreviousIndex = 0;\r
+ Count = 0;\r
+\r
+ do {\r
+ for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {\r
+ BackupBuffer[Index] = Buffer[Index];\r
+ }\r
+\r
+ if (Buffer[Index] == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Null-terminate the temporary string\r
+ //\r
+ BackupBuffer[Index] = 0;\r
+\r
+ //\r
+ // Print this out, we are about to switch widths\r
+ //\r
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
+ Count += StrLen (&BackupBuffer[PreviousIndex]);\r
+\r
+ //\r
+ // Preserve the current index + 1, since this is where we will start printing from next\r
+ //\r
+ PreviousIndex = Index + 1;\r
+\r
+ //\r
+ // We are at a narrow or wide character directive. Set attributes and strip it and print it\r
+ //\r
+ if (Buffer[Index] == NARROW_CHAR) {\r
+ //\r
+ // Preserve bits 0 - 6 and zero out the rest\r
+ //\r
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
+ Out->SetAttribute (Out, Out->Mode->Attribute);\r
+ } else {\r
+ //\r
+ // Must be wide, set bit 7 ON\r
+ //\r
+ Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;\r
+ Out->SetAttribute (Out, Out->Mode->Attribute);\r
+ }\r
+\r
+ Index++;\r
+\r
+ } while (Buffer[Index] != 0);\r
+\r
+ //\r
+ // We hit the end of the string - print it\r
+ //\r
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
+ Count += StrLen (&BackupBuffer[PreviousIndex]);\r
+\r
+ gBS->FreePool (Buffer);\r
+ gBS->FreePool (BackupBuffer);\r
+ return Count;\r
+}\r
+\r
+\r
+/**\r
+ Prints a formatted unicode string to the default console.\r
+\r
+ @param Fmt Format string\r
+ @param ... Variable argument list for format string.\r
+\r
+ @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+ConsolePrint (\r
+ IN CHAR16 *Fmt,\r
+ IN ...\r
+ )\r
+{\r
+ VA_LIST Args;\r
+\r
+ VA_START (Args, Fmt);\r
+ return PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, Fmt, Args);\r
+}\r
+\r
+\r
+/**\r
+ Prints a unicode string to the default console,\r
+ using L"%s" format.\r
+\r
+ @param String String pointer.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintString (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ return ConsolePrint (L"%s", String);\r
+}\r
+\r
+\r
+/**\r
+ Prints a chracter to the default console,\r
+ using L"%c" format.\r
+\r
+ @param Character Character to print.\r
+\r
+ @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintChar (\r
+ CHAR16 Character\r
+ )\r
+{\r
+ return ConsolePrint (L"%c", Character);\r
+}\r
+\r
+\r
+/**\r
+ Prints a formatted unicode string to the default console, at\r
+ the supplied cursor position.\r
+\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at.\r
+ @param Fmt Format string.\r
+ @param ... Variable argument list for format string.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *Fmt,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Args;\r
+\r
+ VA_START (Args, Fmt);\r
+ return PrintInternal (Column, Row, gST->ConOut, Fmt, Args);\r
+}\r
+\r
+\r
+/**\r
+ Prints a unicode string to the default console, at\r
+ the supplied cursor position, using L"%s" format.\r
+\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at\r
+ @param String String pointer.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintStringAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ CHAR16 *String\r
+ )\r
+{\r
+ return PrintAt (Column, Row, L"%s", String);\r
+}\r
+\r
+\r
+/**\r
+ Prints a chracter to the default console, at\r
+ the supplied cursor position, using L"%c" format.\r
+\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at.\r
+ @param Character Character to print.\r
+\r
+ @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintCharAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ CHAR16 Character\r
+ )\r
+{\r
+ return PrintAt (Column, Row, L"%c", Character);\r
+}\r
+\r
+\r
+/**\r
+ VSPrint worker function that prints a Value as a decimal number in Buffer.\r
+\r
+ @param Buffer Location to place ascii decimal number string of Value.\r
+ @param Flags Flags to use in printing decimal string, see file header for\r
+ details.\r
+ @param Value Decimal value to convert to a string in Buffer.\r
+\r
+ @return Number of characters printed.\r
+\r
+**/\r
+UINTN\r
+ValueToString (\r
+ IN OUT CHAR16 *Buffer,\r
+ IN BOOLEAN Flags,\r
+ IN INT64 Value\r
+ )\r
+{\r
+ CHAR16 TempBuffer[30];\r
+ CHAR16 *TempStr;\r
+ CHAR16 *BufferPtr;\r
+ UINTN Count;\r
+ UINTN NumberCount;\r
+ UINT32 Remainder;\r
+ BOOLEAN Negative;\r
+\r
+ Negative = FALSE;\r
+ TempStr = TempBuffer;\r
+ BufferPtr = Buffer;\r
+ Count = 0;\r
+ NumberCount = 0;\r
+\r
+ if (Value < 0) {\r
+ Negative = TRUE;\r
+ Value = -Value;\r
+ }\r
+\r
+ do {\r
+ Value = (INT64) DivU64x32Remainder ((UINT64) Value, 10, &Remainder);\r
+ *(TempStr++) = (CHAR16) (Remainder + '0');\r
+ Count++;\r
+ NumberCount++;\r
+ if ((Flags & COMMA_TYPE) == COMMA_TYPE) {\r
+ if (NumberCount % 3 == 0 && Value != 0) {\r
+ *(TempStr++) = ',';\r
+ Count++;\r
+ }\r
+ }\r
+ } while (Value != 0);\r
+\r
+ if (Negative) {\r
+ *(BufferPtr++) = '-';\r
+ Count++;\r
+ }\r
+\r
+ //\r
+ // Reverse temp string into Buffer.\r
+ //\r
+ while (TempStr != TempBuffer) {\r
+ *(BufferPtr++) = *(--TempStr);\r
+ }\r
+\r
+ *BufferPtr = 0;\r
+ return Count;\r
+}\r
/** @file
+Micro definitions data for Print.c
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
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_
/** @file
+Implementation for handling the User Interface option processing.
+
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
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"
/**
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.
/**
Display error message for invalid password.
- None.
-
- @return None.
-
**/
VOID
PasswordInvalid (
//
// 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
//
//
// 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);
}
//
// 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);
}
//
// 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));
//
// 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);
}
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
-/** @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\r
+Entry and initialization module for the browser.\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+#include "Ui.h"\r
+\r
+\r
+SETUP_DRIVER_PRIVATE_DATA mPrivateData = {\r
+ SETUP_DRIVER_SIGNATURE,\r
+ NULL,\r
+ {\r
+ SendForm,\r
+ BrowserCallback\r
+ },\r
+ {\r
+ UnicodeVSPrint\r
+ }\r
+};\r
+\r
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL *mHiiString;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
+\r
+BANNER_DATA *BannerData;\r
+EFI_HII_HANDLE FrontPageHandle;\r
+UINTN gClassOfVfr;\r
+UINTN gFunctionKeySetting;\r
+BOOLEAN gResetRequired;\r
+BOOLEAN gNvUpdateRequired;\r
+EFI_HII_HANDLE gHiiHandle;\r
+BOOLEAN gFirstIn;\r
+UINT16 gDirection;\r
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+BOOLEAN gUpArrow;\r
+BOOLEAN gDownArrow;\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+CHAR16 *gFunctionOneString;\r
+CHAR16 *gFunctionTwoString;\r
+CHAR16 *gFunctionNineString;\r
+CHAR16 *gFunctionTenString;\r
+CHAR16 *gEnterString;\r
+CHAR16 *gEnterCommitString;\r
+CHAR16 *gEscapeString;\r
+CHAR16 *gSaveFailed;\r
+CHAR16 *gMoveHighlight;\r
+CHAR16 *gMakeSelection;\r
+CHAR16 *gDecNumericInput;\r
+CHAR16 *gHexNumericInput;\r
+CHAR16 *gToggleCheckBox;\r
+CHAR16 *gPromptForData;\r
+CHAR16 *gPromptForPassword;\r
+CHAR16 *gPromptForNewPassword;\r
+CHAR16 *gConfirmPassword;\r
+CHAR16 *gConfirmError;\r
+CHAR16 *gPassowordInvalid;\r
+CHAR16 *gPressEnter;\r
+CHAR16 *gEmptyString;\r
+CHAR16 *gAreYouSure;\r
+CHAR16 *gYesResponse;\r
+CHAR16 *gNoResponse;\r
+CHAR16 *gMiniString;\r
+CHAR16 *gPlusString;\r
+CHAR16 *gMinusString;\r
+CHAR16 *gAdjustNumber;\r
+\r
+CHAR16 gPromptBlockWidth;\r
+CHAR16 gOptionBlockWidth;\r
+CHAR16 gHelpBlockWidth;\r
+\r
+EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+EFI_GUID gSetupBrowserGuid = {\r
+ 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
+};\r
+\r
+FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
+ //\r
+ // Boot Manager\r
+ //\r
+ {\r
+ {\r
+ 0x847bc3fe,\r
+ 0xb974,\r
+ 0x446d,\r
+ {\r
+ 0x94,\r
+ 0x49,\r
+ 0x5a,\r
+ 0xd5,\r
+ 0x41,\r
+ 0x2e,\r
+ 0x99,\r
+ 0x3b\r
+ }\r
+ },\r
+ NONE_FUNCTION_KEY_SETTING\r
+ },\r
+ //\r
+ // Device Manager\r
+ //\r
+ {\r
+ {\r
+ 0x3ebfa8e6,\r
+ 0x511d,\r
+ 0x4b5b,\r
+ {\r
+ 0xa9,\r
+ 0x5f,\r
+ 0xfb,\r
+ 0x38,\r
+ 0x26,\r
+ 0xf,\r
+ 0x1c,\r
+ 0x27\r
+ }\r
+ },\r
+ NONE_FUNCTION_KEY_SETTING\r
+ },\r
+ //\r
+ // BMM FormSet.\r
+ //\r
+ {\r
+ {\r
+ 0x642237c7,\r
+ 0x35d4,\r
+ 0x472d,\r
+ {\r
+ 0x83,\r
+ 0x65,\r
+ 0x12,\r
+ 0xe0,\r
+ 0xcc,\r
+ 0xf2,\r
+ 0x7a,\r
+ 0x22\r
+ }\r
+ },\r
+ NONE_FUNCTION_KEY_SETTING\r
+ },\r
+ //\r
+ // BMM File Explorer FormSet.\r
+ //\r
+ {\r
+ {\r
+ 0x1f2d63e1,\r
+ 0xfebd,\r
+ 0x4dc7,\r
+ {\r
+ 0x9c,\r
+ 0xc5,\r
+ 0xba,\r
+ 0x2b,\r
+ 0x1c,\r
+ 0xef,\r
+ 0x9c,\r
+ 0x5b\r
+ }\r
+ },\r
+ NONE_FUNCTION_KEY_SETTING\r
+ },\r
+};\r
+\r
+/**\r
+ This is the routine which an external caller uses to direct the browser\r
+ where to obtain it's information.\r
+\r
+\r
+ @param This The Form Browser protocol instanse.\r
+ @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
+ display a list of the formsets for the handles specified.\r
+ @param HandleCount The number of Handles specified in Handle.\r
+ @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
+ field in the EFI_IFR_FORM_SET op-code for the specified\r
+ forms-based package. If FormSetGuid is NULL, then this\r
+ function will display the first found forms package.\r
+ @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
+ displayable page. If this field has a value of 0x0000, then\r
+ the forms browser will render the specified forms in their encoded order.\r
+ ScreenDimenions - This allows the browser to be called so that it occupies a\r
+ portion of the physical screen instead of dynamically determining the screen dimensions.\r
+ ActionRequest - Points to the action recommended by the form.\r
+ @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in \r
+ characters.\r
+ @param ActionRequest Points to the action recommended by the form.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_NOT_FOUND No valid forms could be found to display.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SendForm (\r
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE *Handles,\r
+ IN UINTN HandleCount,\r
+ IN EFI_GUID *FormSetGuid, OPTIONAL\r
+ IN UINT16 FormId, OPTIONAL\r
+ IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UI_MENU_SELECTION *Selection;\r
+ UINTN Index;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+\r
+ Status = EFI_SUCCESS;\r
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ //\r
+ // Seed the dimensions in the global\r
+ //\r
+ gST->ConOut->QueryMode (\r
+ gST->ConOut,\r
+ gST->ConOut->Mode->Mode,\r
+ &gScreenDimensions.RightColumn,\r
+ &gScreenDimensions.BottomRow\r
+ );\r
+\r
+ if (ScreenDimensions != NULL) {\r
+ //\r
+ // Check local dimension vs. global dimension.\r
+ //\r
+ if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
+ (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else {\r
+ //\r
+ // Local dimension validation.\r
+ //\r
+ if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
+ (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
+ ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
+ (\r
+ (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
+ SCROLL_ARROW_HEIGHT *\r
+ 2 +\r
+ FRONT_PAGE_HEADER_HEIGHT +\r
+ FOOTER_HEIGHT +\r
+ 1\r
+ )\r
+ ) {\r
+ CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ }\r
+\r
+ gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
+ gHelpBlockWidth = gOptionBlockWidth;\r
+ gPromptBlockWidth = gOptionBlockWidth;\r
+\r
+ //\r
+ // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
+ //\r
+ InitializeBrowserStrings ();\r
+\r
+ gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
+ gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS;\r
+\r
+ //\r
+ // Ensure we are in Text mode\r
+ //\r
+ if (gFirstIn) {\r
+ gFirstIn = FALSE;\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ DisableQuietBoot ();\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
+ ASSERT (Selection != NULL);\r
+\r
+ Selection->Handle = Handles[Index];\r
+ if (FormSetGuid != NULL) {\r
+ CopyMem (&Selection->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->FormId = FormId;\r
+ }\r
+\r
+ do {\r
+ FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
+ ASSERT (FormSet != NULL);\r
+\r
+ //\r
+ // Initialize internal data structures of FormSet\r
+ //\r
+ Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ DestroyFormSet (FormSet);\r
+ break;\r
+ }\r
+ Selection->FormSet = FormSet;\r
+\r
+ //\r
+ // Initialize current settings of Questions in this FormSet\r
+ //\r
+ Status = InitializeCurrentSetting (FormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ DestroyFormSet (FormSet);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display this formset\r
+ //\r
+ gCurrentSelection = Selection;\r
+\r
+ Status = SetupBrowser (Selection);\r
+\r
+ gCurrentSelection = NULL;\r
+ DestroyFormSet (FormSet);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
+\r
+ gBS->FreePool (Selection);\r
+ }\r
+\r
+ if (ActionRequest != NULL) {\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ if (gResetRequired) {\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
+ }\r
+ }\r
+\r
+ FreeBrowserStrings ();\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function is called by a callback handler to retrieve uncommitted state\r
+ data from the browser.\r
+\r
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
+ instance.\r
+ @param ResultsDataSize A pointer to the size of the buffer associated\r
+ with ResultsData.\r
+ @param ResultsData A string returned from an IFR browser or\r
+ equivalent. The results string will have no\r
+ routing information in them.\r
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
+ (if RetrieveData = TRUE) data from the uncommitted\r
+ browser state information or set (if RetrieveData\r
+ = FALSE) data in the uncommitted browser state\r
+ information.\r
+ @param VariableGuid An optional field to indicate the target variable\r
+ GUID name to use.\r
+ @param VariableName An optional field to indicate the target\r
+ human-readable variable name.\r
+\r
+ @retval EFI_SUCCESS The results have been distributed or are awaiting\r
+ distribution.\r
+ @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
+ contain the results data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BrowserCallback (\r
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+ IN OUT UINTN *ResultsDataSize,\r
+ IN OUT EFI_STRING ResultsData,\r
+ IN BOOLEAN RetrieveData,\r
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST CHAR16 *VariableName OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+ BOOLEAN Found;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *StrPtr;\r
+ UINTN BufferSize;\r
+ UINTN TmpSize;\r
+\r
+ if (ResultsDataSize == NULL || ResultsData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (gCurrentSelection == NULL) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Storage = NULL;\r
+ ConfigResp = NULL;\r
+ FormSet = gCurrentSelection->FormSet;\r
+\r
+ //\r
+ // Find target storage\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ if (IsNull (&FormSet->StorageListHead, Link)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (VariableGuid != NULL) {\r
+ //\r
+ // Try to find target storage\r
+ //\r
+ Found = FALSE;\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {\r
+ //\r
+ // Buffer storage require both GUID and Name\r
+ //\r
+ if (VariableName == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
+ continue;\r
+ }\r
+ }\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!Found) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ } else {\r
+ //\r
+ // GUID/Name is not specified, take the first storage in FormSet\r
+ //\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ }\r
+\r
+ if (RetrieveData) {\r
+ //\r
+ // Skip if there is no RequestElement\r
+ //\r
+ if (Storage->ElementCount == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Generate <ConfigResp>\r
+ //\r
+ Status = StorageToConfigResp (Storage, &ConfigResp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
+ //\r
+ StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
+\r
+ BufferSize = StrSize (StrPtr);\r
+ if (*ResultsDataSize < BufferSize) {\r
+ *ResultsDataSize = BufferSize;\r
+\r
+ gBS->FreePool (ConfigResp);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *ResultsDataSize = BufferSize;\r
+ CopyMem (ResultsData, StrPtr, BufferSize);\r
+\r
+ gBS->FreePool (ConfigResp);\r
+ } else {\r
+ //\r
+ // Prepare <ConfigResp>\r
+ //\r
+ TmpSize = StrLen (ResultsData);\r
+ BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
+ ConfigResp = AllocateZeroPool (BufferSize);\r
+ ASSERT (ConfigResp != NULL);\r
+\r
+ StrCpy (ConfigResp, Storage->ConfigHdr);\r
+ StrCat (ConfigResp, L"&");\r
+ StrCat (ConfigResp, ResultsData);\r
+\r
+ //\r
+ // Update Browser uncommited data\r
+ //\r
+ Status = ConfigRespToStorage (Storage, ConfigResp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Initialize Setup Browser driver.\r
+\r
+ @param ImageHandle The image handle.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
+ @return Other value if failed to initialize the Setup Browser module.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeSetup (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE HiiDriverHandle;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ //\r
+ // Locate required Hii relative protocols\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mHiiDatabase\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiStringProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mHiiString\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mHiiConfigRouting\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&HiiDriverHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ PackageList = HiiLibPreparePackageList (1, &gSetupBrowserGuid, SetupBrowserStrings);\r
+ ASSERT (PackageList != NULL);\r
+ Status = mHiiDatabase->NewPackageList (\r
+ mHiiDatabase,\r
+ PackageList,\r
+ HiiDriverHandle,\r
+ &gHiiHandle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Initialize Driver private data\r
+ //\r
+ gFirstIn = TRUE;\r
+ BannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
+ ASSERT (BannerData != NULL);\r
+\r
+ //\r
+ // Install FormBrowser2 protocol\r
+ //\r
+ mPrivateData.Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mPrivateData.Handle,\r
+ &gEfiFormBrowser2ProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mPrivateData.FormBrowser2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Install Print protocol\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mPrivateData.Handle,\r
+ &gEfiPrintProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mPrivateData.Print\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Create a new string in HII Package List.\r
+\r
+ @param String The String to be added\r
+ @param HiiHandle The package list in the HII database to insert the\r
+ specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewString (\r
+ IN CHAR16 *String,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STRING_ID StringId;\r
+ EFI_STATUS Status;\r
+\r
+ StringId = 0;\r
+ Status = HiiLibNewString (HiiHandle, &StringId, String);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return StringId;\r
+}\r
+\r
+\r
+/**\r
+ Delete a string from HII Package List.\r
+\r
+ @param StringId Id of the string in HII database.\r
+ @param HiiHandle The HII package list handle.\r
+\r
+ @retval EFI_SUCCESS The string was deleted successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteString (\r
+ IN EFI_STRING_ID StringId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ CHAR16 NullChar;\r
+\r
+ NullChar = CHAR_NULL;\r
+ return HiiLibSetString (HiiHandle, StringId, &NullChar);\r
+}\r
+\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param Token The String's ID.\r
+ @param HiiHandle The package list in the HII database to search for\r
+ the specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetToken (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *String;\r
+ UINTN BufferLength;\r
+\r
+ //\r
+ // Set default string size assumption at no more than 256 bytes\r
+ //\r
+ BufferLength = 0x100;\r
+ String = AllocateZeroPool (BufferLength);\r
+ ASSERT (String != NULL);\r
+\r
+ Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);\r
+\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ gBS->FreePool (String);\r
+ String = AllocateZeroPool (BufferLength);\r
+ ASSERT (String != NULL);\r
+\r
+ Status = HiiLibGetString (HiiHandle, Token, String, &BufferLength);\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return String;\r
+}\r
+\r
+\r
+/**\r
+ Allocate new memory and then copy the Unicode string Source to Destination.\r
+\r
+ @param Dest Location to copy string\r
+ @param Src String to copy\r
+\r
+**/\r
+VOID\r
+NewStringCpy (\r
+ IN OUT CHAR16 **Dest,\r
+ IN CHAR16 *Src\r
+ )\r
+{\r
+ SafeFreePool (*Dest);\r
+ *Dest = AllocateCopyPool (StrSize (Src), Src);\r
+ ASSERT (*Dest != NULL);\r
+}\r
+\r
+\r
+/**\r
+ Allocate new memory and concatinate Source on the end of Destination.\r
+\r
+ @param Dest String to added to the end of.\r
+ @param Src String to concatinate.\r
+\r
+**/\r
+VOID\r
+NewStringCat (\r
+ IN OUT CHAR16 **Dest,\r
+ IN CHAR16 *Src\r
+ )\r
+{\r
+ CHAR16 *NewString;\r
+ UINTN TmpSize;\r
+\r
+ if (*Dest == NULL) {\r
+ NewStringCpy (Dest, Src);\r
+ return;\r
+ }\r
+\r
+ TmpSize = StrSize (*Dest);\r
+ NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1);\r
+ ASSERT (NewString != NULL);\r
+\r
+ StrCpy (NewString, *Dest);\r
+ StrCat (NewString, Src);\r
+\r
+ gBS->FreePool (*Dest);\r
+ *Dest = NewString;\r
+}\r
+\r
+\r
+/**\r
+ Synchronize Storage's Edit copy to Shadow copy.\r
+\r
+ @param Storage The Storage to be synchronized.\r
+\r
+**/\r
+VOID\r
+SynchronizeStorage (\r
+ IN FORMSET_STORAGE *Storage\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+\r
+ switch (Storage->Type) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ NewStringCpy (&Node->Value, Node->EditValue);\r
+\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Get Value for given Name from a NameValue Storage.\r
+\r
+ @param Storage The NameValue Storage.\r
+ @param Name The Name.\r
+ @param Value The retured Value.\r
+\r
+ @retval EFI_SUCCESS Value found for given Name.\r
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+GetValueByName (\r
+ IN FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN OUT CHAR16 **Value\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+\r
+ *Value = NULL;\r
+\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ if (StrCmp (Name, Node->Name) == 0) {\r
+ NewStringCpy (Value, Node->EditValue);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Set Value of given Name in a NameValue Storage.\r
+\r
+ @param Storage The NameValue Storage.\r
+ @param Name The Name.\r
+ @param Value The Value to set.\r
+\r
+ @retval EFI_SUCCESS Value found for given Name.\r
+ @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
+\r
+**/\r
+EFI_STATUS\r
+SetValueByName (\r
+ IN FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN CHAR16 *Value\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ if (StrCmp (Name, Node->Name) == 0) {\r
+ SafeFreePool (Node->EditValue);\r
+ Node->EditValue = AllocateCopyPool (StrSize (Value), Value);\r
+ ASSERT (Node->EditValue != NULL);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+ @param Storage The Storage to be conveted.\r
+ @param ConfigResp The returned <ConfigResp>.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+ IN FORMSET_STORAGE *Storage,\r
+ IN CHAR16 **ConfigResp\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ LIST_ENTRY *Link;\r
+ NAME_VALUE_NODE *Node;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (Storage->Type) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ Status = mHiiConfigRouting->BlockToConfig (\r
+ mHiiConfigRouting,\r
+ Storage->ConfigRequest,\r
+ Storage->EditBuffer,\r
+ Storage->Size,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ *ConfigResp = NULL;\r
+ NewStringCat (ConfigResp, Storage->ConfigHdr);\r
+\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+\r
+ NewStringCat (ConfigResp, L"&");\r
+ NewStringCat (ConfigResp, Node->Name);\r
+ NewStringCat (ConfigResp, L"=");\r
+ NewStringCat (ConfigResp, Node->EditValue);\r
+\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+ @param Storage The Storage to receive the settings.\r
+ @param ConfigResp The <ConfigResp> to be converted.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+ IN FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *ConfigResp\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ UINTN BufferSize;\r
+ CHAR16 *StrPtr;\r
+ CHAR16 *Name;\r
+ CHAR16 *Value;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (Storage->Type) {\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ BufferSize = Storage->Size;\r
+ Status = mHiiConfigRouting->ConfigToBlock (\r
+ mHiiConfigRouting,\r
+ ConfigResp,\r
+ Storage->EditBuffer,\r
+ &BufferSize,\r
+ &Progress\r
+ );\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ StrPtr = StrStr (ConfigResp, L"&");\r
+ while (StrPtr != NULL) {\r
+ //\r
+ // Skip '&'\r
+ //\r
+ StrPtr = StrPtr + 1;\r
+ Name = StrPtr;\r
+ StrPtr = StrStr (StrPtr, L"=");\r
+ if (StrPtr == NULL) {\r
+ break;\r
+ }\r
+ *StrPtr = 0;\r
+\r
+ //\r
+ // Skip '='\r
+ //\r
+ StrPtr = StrPtr + 1;\r
+ Value = StrPtr;\r
+ StrPtr = StrStr (StrPtr, L"&");\r
+ if (StrPtr != NULL) {\r
+ *StrPtr = 0;\r
+ }\r
+ SetValueByName (Storage, Name, Value);\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Get Question's current Value.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Question to be initialized.\r
+ @param Cached TRUE: get from Edit copy FALSE: get from original\r
+ Storage\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN BOOLEAN Cached\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Enabled;\r
+ BOOLEAN Pending;\r
+ UINT8 *Dst;\r
+ UINTN StorageWidth;\r
+ EFI_TIME EfiTime;\r
+ FORMSET_STORAGE *Storage;\r
+ EFI_IFR_TYPE_VALUE *QuestionValue;\r
+ CHAR16 *ConfigRequest;\r
+ CHAR16 *Progress;\r
+ CHAR16 *Result;\r
+ CHAR16 *Value;\r
+ UINTN Length;\r
+ BOOLEAN IsBufferStorage;\r
+ BOOLEAN IsString;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Statement don't have storage, skip them\r
+ //\r
+ if (Question->QuestionId == 0) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by an Expression, evaluate it\r
+ //\r
+ if (Question->ValueExpression != NULL) {\r
+ Status = EvaluateExpression (FormSet, Form, Question->ValueExpression);\r
+ if (!EFI_ERROR (Status)) {\r
+ CopyMem (&Question->HiiValue, &Question->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by RTC\r
+ //\r
+ Storage = Question->Storage;\r
+ QuestionValue = &Question->HiiValue.Value;\r
+ if (Storage == NULL) {\r
+ //\r
+ // It's a Question without storage, or RTC date/time\r
+ //\r
+ if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+ //\r
+ // Date and time define the same Flags bit\r
+ //\r
+ switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
+ case QF_DATE_STORAGE_TIME:\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_WAKEUP:\r
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_NORMAL:\r
+ default:\r
+ //\r
+ // For date/time without storage\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ QuestionValue->date.Year = EfiTime.Year;\r
+ QuestionValue->date.Month = EfiTime.Month;\r
+ QuestionValue->date.Day = EfiTime.Day;\r
+ } else {\r
+ QuestionValue->time.Hour = EfiTime.Hour;\r
+ QuestionValue->time.Minute = EfiTime.Minute;\r
+ QuestionValue->time.Second = EfiTime.Second;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by EFI variable\r
+ //\r
+ StorageWidth = Question->StorageWidth;\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ if (Question->BufferValue != NULL) {\r
+ Dst = Question->BufferValue;\r
+ } else {\r
+ Dst = (UINT8 *) QuestionValue;\r
+ }\r
+\r
+ Status = gRT->GetVariable (\r
+ Question->VariableName,\r
+ &Storage->Guid,\r
+ NULL,\r
+ &StorageWidth,\r
+ Dst\r
+ );\r
+ //\r
+ // Always return success, even this EFI variable doesn't exist\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Question Value is provided by Buffer Storage or NameValue Storage\r
+ //\r
+ if (Question->BufferValue != NULL) {\r
+ //\r
+ // This Question is password or orderedlist\r
+ //\r
+ Dst = Question->BufferValue;\r
+ } else {\r
+ //\r
+ // Other type of Questions\r
+ //\r
+ Dst = (UINT8 *) &Question->HiiValue.Value;\r
+ }\r
+\r
+ IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
+ IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
+ if (Cached) {\r
+ if (IsBufferStorage) {\r
+ //\r
+ // Copy from storage Edit buffer\r
+ //\r
+ CopyMem (Dst, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth);\r
+ } else {\r
+ Status = GetValueByName (Storage, Question->VariableName, &Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (IsString) {\r
+ //\r
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+ //\r
+ Length = StorageWidth + sizeof (CHAR16);\r
+ Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
+ } else {\r
+ Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
+ }\r
+\r
+ gBS->FreePool (Value);\r
+ }\r
+ } else {\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ if (FormSet->ConfigAccess == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||\r
+ // <ConfigHdr> + "&" + <VariableName>\r
+ //\r
+ if (IsBufferStorage) {\r
+ Length = StrLen (Storage->ConfigHdr);\r
+ Length += StrLen (Question->BlockName);\r
+ } else {\r
+ Length = StrLen (Storage->ConfigHdr);\r
+ Length += StrLen (Question->VariableName) + 1;\r
+ }\r
+ ConfigRequest = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+ ASSERT (ConfigRequest != NULL);\r
+\r
+ StrCpy (ConfigRequest, Storage->ConfigHdr);\r
+ if (IsBufferStorage) {\r
+ StrCat (ConfigRequest, Question->BlockName);\r
+ } else {\r
+ StrCat (ConfigRequest, L"&");\r
+ StrCat (ConfigRequest, Question->VariableName);\r
+ }\r
+\r
+ Status = FormSet->ConfigAccess->ExtractConfig (\r
+ FormSet->ConfigAccess,\r
+ ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigRequest>\r
+ //\r
+ Value = Result + Length;\r
+ if (IsBufferStorage) {\r
+ //\r
+ // Skip "&VALUE"\r
+ //\r
+ Value = Value + 6;\r
+ }\r
+ if (*Value != '=') {\r
+ gBS->FreePool (Result);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Skip '=', point to value\r
+ //\r
+ Value = Value + 1;\r
+ if (!IsBufferStorage && IsString) {\r
+ //\r
+ // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"\r
+ //\r
+ Length = StorageWidth + sizeof (CHAR16);\r
+ Status = ConfigStringToUnicode ((CHAR16 *) Dst, &Length, Value);\r
+ } else {\r
+ Status = HexStringToBuf (Dst, &StorageWidth, Value, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (Result);\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Synchronize Edit Buffer\r
+ //\r
+ if (IsBufferStorage) {\r
+ CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
+ } else {\r
+ SetValueByName (Storage, Question->VariableName, Value);\r
+ }\r
+ gBS->FreePool (Result);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Save Question Value to edit copy(cached) or Storage(uncached).\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Pointer to the Question.\r
+ @param Cached TRUE: set to Edit copy FALSE: set to original\r
+ Storage\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN BOOLEAN Cached\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Enabled;\r
+ BOOLEAN Pending;\r
+ UINT8 *Src;\r
+ EFI_TIME EfiTime;\r
+ UINTN BufferLen;\r
+ UINTN StorageWidth;\r
+ FORMSET_STORAGE *Storage;\r
+ EFI_IFR_TYPE_VALUE *QuestionValue;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Progress;\r
+ CHAR16 *Value;\r
+ UINTN Length;\r
+ BOOLEAN IsBufferStorage;\r
+ BOOLEAN IsString;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Statement don't have storage, skip them\r
+ //\r
+ if (Question->QuestionId == 0) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // If Question value is provided by an Expression, then it is read only\r
+ //\r
+ if (Question->ValueExpression != NULL) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by RTC\r
+ //\r
+ Storage = Question->Storage;\r
+ QuestionValue = &Question->HiiValue.Value;\r
+ if (Storage == NULL) {\r
+ //\r
+ // It's a Question without storage, or RTC date/time\r
+ //\r
+ if (Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
+ //\r
+ // Date and time define the same Flags bit\r
+ //\r
+ switch (Question->Flags & EFI_QF_DATE_STORAGE) {\r
+ case QF_DATE_STORAGE_TIME:\r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_WAKEUP:\r
+ Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);\r
+ break;\r
+\r
+ case QF_DATE_STORAGE_NORMAL:\r
+ default:\r
+ //\r
+ // For date/time without storage\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Question->Operand == EFI_IFR_DATE_OP) {\r
+ EfiTime.Year = QuestionValue->date.Year;\r
+ EfiTime.Month = QuestionValue->date.Month;\r
+ EfiTime.Day = QuestionValue->date.Day;\r
+ } else {\r
+ EfiTime.Hour = QuestionValue->time.Hour;\r
+ EfiTime.Minute = QuestionValue->time.Minute;\r
+ EfiTime.Second = QuestionValue->time.Second;\r
+ }\r
+\r
+ if ((Question->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_TIME) {\r
+ Status = gRT->SetTime (&EfiTime);\r
+ } else {\r
+ Status = gRT->SetWakeupTime (TRUE, &EfiTime);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Question value is provided by EFI variable\r
+ //\r
+ StorageWidth = Question->StorageWidth;\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ if (Question->BufferValue != NULL) {\r
+ Src = Question->BufferValue;\r
+ } else {\r
+ Src = (UINT8 *) QuestionValue;\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ Question->VariableName,\r
+ &Storage->Guid,\r
+ Storage->Attributes,\r
+ StorageWidth,\r
+ Src\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Question Value is provided by Buffer Storage or NameValue Storage\r
+ //\r
+ if (Question->BufferValue != NULL) {\r
+ Src = Question->BufferValue;\r
+ } else {\r
+ Src = (UINT8 *) &Question->HiiValue.Value;\r
+ }\r
+\r
+ IsBufferStorage = (BOOLEAN) ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ? TRUE : FALSE);\r
+ IsString = (BOOLEAN) ((Question->HiiValue.Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);\r
+ if (IsBufferStorage) {\r
+ //\r
+ // Copy to storage edit buffer\r
+ //\r
+ CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
+ } else {\r
+ if (IsString) {\r
+ //\r
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+ //\r
+ Value = NULL;\r
+ BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
+ Value = AllocateZeroPool (BufferLen);\r
+ ASSERT (Value != NULL);\r
+ Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ BufferLen = StorageWidth * 2 + 1;\r
+ Value = AllocateZeroPool (BufferLen * sizeof (CHAR16));\r
+ ASSERT (Value != NULL);\r
+ BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
+ ToLower (Value);\r
+ }\r
+\r
+ Status = SetValueByName (Storage, Question->VariableName, Value);\r
+ gBS->FreePool (Value);\r
+ }\r
+\r
+ if (!Cached) {\r
+ //\r
+ // <ConfigResp> ::= <ConfigHdr> + <BlockName> + "&VALUE=" + "<HexCh>StorageWidth * 2" ||\r
+ // <ConfigHdr> + "&" + <VariableName> + "=" + "<string>"\r
+ //\r
+ if (IsBufferStorage) {\r
+ Length = StrLen (Question->BlockName) + 7;\r
+ } else {\r
+ Length = StrLen (Question->VariableName) + 2;\r
+ }\r
+ if (!IsBufferStorage && IsString) {\r
+ Length += (StrLen ((CHAR16 *) Src) * 4);\r
+ } else {\r
+ Length += (StorageWidth * 2);\r
+ }\r
+ ConfigResp = AllocateZeroPool ((StrLen (Storage->ConfigHdr) + Length + 1) * sizeof (CHAR16));\r
+ ASSERT (ConfigResp != NULL);\r
+\r
+ StrCpy (ConfigResp, Storage->ConfigHdr);\r
+ if (IsBufferStorage) {\r
+ StrCat (ConfigResp, Question->BlockName);\r
+ StrCat (ConfigResp, L"&VALUE=");\r
+ } else {\r
+ StrCat (ConfigResp, L"&");\r
+ StrCat (ConfigResp, Question->VariableName);\r
+ StrCat (ConfigResp, L"=");\r
+ }\r
+\r
+ Value = ConfigResp + StrLen (ConfigResp);\r
+ if (!IsBufferStorage && IsString) {\r
+ //\r
+ // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"\r
+ //\r
+ BufferLen = ((StrLen ((CHAR16 *) Src) * 4) + 1) * sizeof (CHAR16);\r
+ Status = UnicodeToConfigString (Value, &BufferLen, (CHAR16 *) Src);\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ BufferLen = StorageWidth * 2 + 1;\r
+ BufToHexString (Value, &BufferLen, Src, StorageWidth);\r
+ ToLower (Value);\r
+ }\r
+\r
+ //\r
+ // Submit Question Value to Configuration Driver\r
+ //\r
+ if (FormSet->ConfigAccess != NULL) {\r
+ Status = FormSet->ConfigAccess->RouteConfig (\r
+ FormSet->ConfigAccess,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (ConfigResp);\r
+ return Status;\r
+ }\r
+ }\r
+ gBS->FreePool (ConfigResp);\r
+\r
+ //\r
+ // Synchronize shadow Buffer\r
+ //\r
+ SynchronizeStorage (Storage);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Perform inconsistent check for a Form.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question The Question to be validated.\r
+ @param Type Validation type: InConsistent or NoSubmit\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateQuestion (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINTN Type\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *ListHead;\r
+ EFI_STRING PopUp;\r
+ EFI_INPUT_KEY Key;\r
+ FORM_EXPRESSION *Expression;\r
+\r
+ if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
+ ListHead = &Question->InconsistentListHead;\r
+ } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+ ListHead = &Question->NoSubmitListHead;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Link = GetFirstNode (ListHead);\r
+ while (!IsNull (ListHead, Link)) {\r
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+\r
+ //\r
+ // Evaluate the expression\r
+ //\r
+ Status = EvaluateExpression (FormSet, Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Expression->Result.Value.b) {\r
+ //\r
+ // Condition meet, show up error message\r
+ //\r
+ if (Expression->Error != 0) {\r
+ PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
+ do {\r
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gBS->FreePool (PopUp);\r
+ }\r
+\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Link = GetNextNode (ListHead, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Perform NoSubmit check for a Form.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+NoSubmitCheck (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_NO_SUBMIT_IF);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Submit a Form.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ EFI_STRING ConfigResp;\r
+ EFI_STRING Progress;\r
+ FORMSET_STORAGE *Storage;\r
+\r
+ //\r
+ // Validate the Form by NoSubmit check\r
+ //\r
+ Status = NoSubmitCheck (FormSet, Form);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Submit Buffer storage or Name/Value storage\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Skip if there is no RequestElement\r
+ //\r
+ if (Storage->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Prepare <ConfigResp>\r
+ //\r
+ Status = StorageToConfigResp (Storage, &ConfigResp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Send <ConfigResp> to Configuration Driver\r
+ //\r
+ if (FormSet->ConfigAccess != NULL) {\r
+ Status = FormSet->ConfigAccess->RouteConfig (\r
+ FormSet->ConfigAccess,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (ConfigResp);\r
+ return Status;\r
+ }\r
+ }\r
+ gBS->FreePool (ConfigResp);\r
+\r
+ //\r
+ // Config success, update storage shadow Buffer\r
+ //\r
+ SynchronizeStorage (Storage);\r
+ }\r
+\r
+ gNvUpdateRequired = FALSE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Reset Question to its default value.\r
+\r
+ @param FormSet The form set.\r
+ @param Form The form.\r
+ @param Question The question.\r
+ @param DefaultId The Class of the default.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ QUESTION_DEFAULT *Default;\r
+ QUESTION_OPTION *Option;\r
+ EFI_HII_VALUE *HiiValue;\r
+ UINT8 Index;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Statement don't have storage, skip them\r
+ //\r
+ if (Question->QuestionId == 0) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // There are three ways to specify default value for a Question:\r
+ // 1, use nested EFI_IFR_DEFAULT (highest priority)\r
+ // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)\r
+ // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)\r
+ //\r
+ HiiValue = &Question->HiiValue;\r
+\r
+ //\r
+ // EFI_IFR_DEFAULT has highest priority\r
+ //\r
+ if (!IsListEmpty (&Question->DefaultListHead)) {\r
+ Link = GetFirstNode (&Question->DefaultListHead);\r
+ while (!IsNull (&Question->DefaultListHead, Link)) {\r
+ Default = QUESTION_DEFAULT_FROM_LINK (Link);\r
+\r
+ if (Default->DefaultId == DefaultId) {\r
+ if (Default->ValueExpression != NULL) {\r
+ //\r
+ // Default is provided by an Expression, evaluate it\r
+ //\r
+ Status = EvaluateExpression (FormSet, Form, Default->ValueExpression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE));\r
+ } else {\r
+ //\r
+ // Default value is embedded in EFI_IFR_DEFAULT\r
+ //\r
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->DefaultListHead, Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_ONE_OF_OPTION\r
+ //\r
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // OneOfOption could only provide Standard and Manufacturing default\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))\r
+ ) {\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI_IFR_CHECKBOX - lowest priority\r
+ //\r
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {\r
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ //\r
+ // Checkbox could only provide Standard and Manufacturing default\r
+ //\r
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||\r
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))\r
+ ) {\r
+ HiiValue->Value.b = TRUE;\r
+ } else {\r
+ HiiValue->Value.b = FALSE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ //\r
+ // For Questions without default\r
+ //\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_NUMERIC_OP:\r
+ //\r
+ // Take minimal value as numeric's default value\r
+ //\r
+ HiiValue->Value.u64 = Question->Minimum;\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ //\r
+ // Take first oneof option as oneof's default value\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ if (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ //\r
+ // Take option sequence in IFR as ordered list's default value\r
+ //\r
+ Index = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ Question->BufferValue[Index] = Option->Value.Value.u8;\r
+\r
+ Index++;\r
+ if (Index >= Question->MaxContainers) {\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Reset Questions in a Form to their default value.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form The Form which to be reset.\r
+ @param DefaultId The Class of the default.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractFormDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+\r
+ //\r
+ // Reset Question to its default value\r
+ //\r
+ Status = GetQuestionDefault (FormSet, Form, Question, DefaultId);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Synchronize Buffer storage's Edit buffer\r
+ //\r
+ if ((Question->Storage != NULL) &&\r
+ (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
+ SetQuestionValue (FormSet, Form, Question, TRUE);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Initialize Question's Edit copy from Storage.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ //\r
+ // Initialize local copy of Value for each Question\r
+ //\r
+ Status = GetQuestionValue (FormSet, Form, Question, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Fill storage's edit copy with settings requested from Configuration Driver.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Storage Buffer Storage.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadStorage (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORMSET_STORAGE *Storage\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ EFI_STRING Result;\r
+ CHAR16 *StrPtr;\r
+\r
+ if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (FormSet->ConfigAccess == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (Storage->ElementCount == 0) {\r
+ //\r
+ // Skip if there is no RequestElement\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Status = FormSet->ConfigAccess->ExtractConfig (\r
+ FormSet->ConfigAccess,\r
+ Storage->ConfigRequest,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+ //\r
+ StrPtr = StrStr (Result, L"ALTCFG");\r
+ if (StrPtr != NULL) {\r
+ *StrPtr = L'\0';\r
+ }\r
+\r
+ Status = ConfigRespToStorage (Storage, Result);\r
+ gBS->FreePool (Result);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Get current setting of Questions.\r
+\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeCurrentSetting (\r
+ IN OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+ FORM_BROWSER_FORM *Form;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Extract default from IFR binary\r
+ //\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ Status = ExtractFormDefault (FormSet, Form, EFI_HII_DEFAULT_CLASS_STANDARD);\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+\r
+ Status = LoadStorage (FormSet, Storage);\r
+\r
+ //\r
+ // Now Edit Buffer is filled with default values(lower priority) and current\r
+ // settings(higher priority), sychronize it to shadow Buffer\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ SynchronizeStorage (Storage);\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Fetch the Ifr binary data of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
+ GUID), take the first FormSet found in package\r
+ list.\r
+ @param BinaryLength The length of the FormSet IFR binary.\r
+ @param BinaryData The buffer designed to receive the FormSet.\r
+\r
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
+ BufferLength was updated.\r
+ @retval EFI_INVALID_PARAMETER The handle is unknown.\r
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
+ be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT UINTN *BinaryLength,\r
+ OUT UINT8 **BinaryData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINTN BufferSize;\r
+ UINT8 *Package;\r
+ UINT8 *OpCodeData;\r
+ UINT32 Offset;\r
+ UINT32 Offset2;\r
+ BOOLEAN ReturnDefault;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ OpCodeData = NULL;\r
+ Package = NULL;\r
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
+\r
+ //\r
+ // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
+ //\r
+ if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
+ ReturnDefault = TRUE;\r
+ } else {\r
+ ReturnDefault = FALSE;\r
+ }\r
+\r
+ //\r
+ // Get HII PackageList\r
+ //\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ ASSERT (HiiPackageList != NULL);\r
+\r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Offset2 = 0;\r
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+\r
+ while (Offset < PackageListLength) {\r
+ Package = ((UINT8 *) HiiPackageList) + Offset;\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
+ //\r
+ // Search FormSet in this Form Package\r
+ //\r
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset2 < PackageHeader.Length) {\r
+ OpCodeData = Package + Offset2;\r
+\r
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+ //\r
+ // Check whether return default FormSet\r
+ //\r
+ if (ReturnDefault) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // FormSet GUID is specified, check it\r
+ //\r
+ if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+ }\r
+\r
+ if (Offset2 < PackageHeader.Length) {\r
+ //\r
+ // Target formset found\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset += PackageHeader.Length;\r
+ }\r
+\r
+ if (Offset >= PackageListLength) {\r
+ //\r
+ // Form package not found in this Package List\r
+ //\r
+ gBS->FreePool (HiiPackageList);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (ReturnDefault && FormSetGuid != NULL) {\r
+ //\r
+ // Return the default FormSet GUID\r
+ //\r
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ }\r
+\r
+ //\r
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+ // of the Form Package.\r
+ //\r
+ *BinaryLength = PackageHeader.Length - Offset2;\r
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+\r
+ gBS->FreePool (HiiPackageList);\r
+\r
+ if (*BinaryData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Initialize the internal data structure of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
+ GUID), take the first FormSet found in package\r
+ list.\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+ UINT16 Index;\r
+\r
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FormSet->HiiHandle = Handle;\r
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+\r
+ //\r
+ // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+ //\r
+ Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ FormSet->DriverHandle = DriverHandle;\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **) &FormSet->ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+ // list, then there will be no configuration action required\r
+ //\r
+ FormSet->ConfigAccess = NULL;\r
+ }\r
+\r
+ //\r
+ // Parse the IFR binary OpCodes\r
+ //\r
+ Status = ParseOpCodes (FormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gClassOfVfr = FormSet->SubClass;\r
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+ FrontPageHandle = FormSet->HiiHandle;\r
+ }\r
+\r
+ //\r
+ // Match GUID to find out the function key setting. If match fail, use the default setting.\r
+ //\r
+ for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
+ if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
+ //\r
+ // Update the function key setting.\r
+ //\r
+ gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
+ //\r
+ // Function key prompt can not be displayed if the function key has been disabled.\r
+ //\r
+ if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {\r
+ gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ }\r
+\r
+ if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {\r
+ gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ }\r
+\r
+ if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {\r
+ gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ }\r
+\r
+ if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {\r
+ gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ }\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
-/** @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\r
+Private MACRO, structure and function definitions for Setup Browser module. \r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#ifndef _SETUP_H_\r
+#define _SETUP_H_\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Print.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/FormBrowser2.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/UnicodeCollation.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Library/GraphicsLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/ExtendedIfrSupportLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/ExtendedHiiLib.h>\r
+\r
+#include "Colors.h"\r
+\r
+//\r
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)\r
+//\r
+\r
+extern UINT8 SetupBrowserStrings[];\r
+\r
+//\r
+// Screen definitions\r
+//\r
+#define BANNER_HEIGHT 6\r
+#define BANNER_COLUMNS 3\r
+\r
+#define FRONT_PAGE_HEADER_HEIGHT 6\r
+#define NONE_FRONT_PAGE_HEADER_HEIGHT 3\r
+#define LEFT_SKIPPED_COLUMNS 4\r
+#define FOOTER_HEIGHT 4\r
+#define STATUS_BAR_HEIGHT 1\r
+#define SCROLL_ARROW_HEIGHT 1\r
+#define POPUP_PAD_SPACE_COUNT 5\r
+#define POPUP_FRAME_WIDTH 2\r
+\r
+//\r
+// Definition for function key setting\r
+//\r
+#define NONE_FUNCTION_KEY_SETTING 0\r
+#define DEFAULT_FUNCTION_KEY_SETTING (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN)\r
+\r
+#define FUNCTION_ONE (1 << 0)\r
+#define FUNCTION_TWO (1 << 1)\r
+#define FUNCTION_NINE (1 << 2)\r
+#define FUNCTION_TEN (1 << 3)\r
+\r
+typedef struct {\r
+ EFI_GUID FormSetGuid;\r
+ UINTN KeySetting;\r
+} FUNCTIION_KEY_SETTING;\r
+\r
+//\r
+// Character definitions\r
+//\r
+#define CHAR_SPACE 0x0020\r
+#define UPPER_LOWER_CASE_OFFSET 0x20\r
+\r
+//\r
+// Time definitions\r
+//\r
+#define ONE_SECOND 10000000\r
+\r
+//\r
+// Display definitions\r
+//\r
+#define LEFT_HYPER_DELIMITER L'<'\r
+#define RIGHT_HYPER_DELIMITER L'>'\r
+\r
+#define LEFT_ONEOF_DELIMITER L'<'\r
+#define RIGHT_ONEOF_DELIMITER L'>'\r
+\r
+#define LEFT_NUMERIC_DELIMITER L'['\r
+#define RIGHT_NUMERIC_DELIMITER L']'\r
+\r
+#define LEFT_CHECKBOX_DELIMITER L'['\r
+#define RIGHT_CHECKBOX_DELIMITER L']'\r
+\r
+#define CHECK_ON L'X'\r
+#define CHECK_OFF L' '\r
+\r
+#define TIME_SEPARATOR L':'\r
+#define DATE_SEPARATOR L'/'\r
+\r
+#define YES_ANSWER L'Y'\r
+#define NO_ANSWER L'N'\r
+\r
+//\r
+// This is the Input Error Message\r
+//\r
+#define INPUT_ERROR 1\r
+\r
+//\r
+// This is the NV RAM update required Message\r
+//\r
+#define NV_UPDATE_REQUIRED 2\r
+\r
+//\r
+// Refresh the Status Bar with flags\r
+//\r
+#define REFRESH_STATUS_BAR 0xff\r
+\r
+//\r
+// Incremental string lenght of ConfigRequest\r
+//\r
+#define CONFIG_REQUEST_STRING_INCREMENTAL 1024\r
+\r
+//\r
+// HII value compare result\r
+//\r
+#define HII_VALUE_UNDEFINED 0\r
+#define HII_VALUE_EQUAL 1\r
+#define HII_VALUE_LESS_THAN 2\r
+#define HII_VALUE_GREATER_THAN 3\r
+\r
+//\r
+// Incremental size of stack for expression\r
+//\r
+#define EXPRESSION_STACK_SIZE_INCREMENT 0x100\r
+\r
+\r
+#define EFI_SPECIFICATION_ERRATA_VERSION 0\r
+\r
+#define EFI_IFR_SPECIFICATION_VERSION \\r
+ ((((EFI_SPECIFICATION_VERSION) >> 8) & 0xff00) | \\r
+ (((EFI_SPECIFICATION_VERSION) & 0xf) << 4) | \\r
+ ((EFI_SPECIFICATION_ERRATA_VERSION) & 0xf))\r
+\r
+#define SETUP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'D', 'V')\r
+typedef struct {\r
+ UINT32 Signature;\r
+\r
+ EFI_HANDLE Handle;\r
+\r
+ //\r
+ // Produced protocol\r
+ //\r
+ EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;\r
+ EFI_PRINT_PROTOCOL Print;\r
+\r
+} SETUP_DRIVER_PRIVATE_DATA;\r
+\r
+typedef struct {\r
+ EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];\r
+} BANNER_DATA;\r
+\r
+//\r
+// IFR relative definition\r
+//\r
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0\r
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1\r
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2\r
+#define EFI_HII_EXPRESSION_SUPPRESS_IF 3\r
+#define EFI_HII_EXPRESSION_DISABLE_IF 4\r
+#define EFI_HII_EXPRESSION_VALUE 5\r
+#define EFI_HII_EXPRESSION_RULE 6\r
+\r
+#define EFI_HII_VARSTORE_BUFFER 0\r
+#define EFI_HII_VARSTORE_NAME_VALUE 1\r
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2\r
+\r
+#define FORM_INCONSISTENT_VALIDATION 0\r
+#define FORM_NO_SUBMIT_VALIDATION 1\r
+\r
+typedef struct {\r
+ UINT8 Type;\r
+ EFI_IFR_TYPE_VALUE Value;\r
+} EFI_HII_VALUE;\r
+\r
+#define NAME_VALUE_NODE_SIGNATURE EFI_SIGNATURE_32 ('N', 'V', 'S', 'T')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ CHAR16 *Name;\r
+ CHAR16 *Value;\r
+ CHAR16 *EditValue;\r
+} NAME_VALUE_NODE;\r
+\r
+#define NAME_VALUE_NODE_FROM_LINK(a) CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)\r
+\r
+#define FORMSET_STORAGE_SIGNATURE EFI_SIGNATURE_32 ('F', 'S', 'T', 'G')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT8 Type; // Storage type\r
+\r
+ UINT16 VarStoreId;\r
+ EFI_GUID Guid;\r
+\r
+ CHAR16 *Name; // For EFI_IFR_VARSTORE\r
+ UINT16 Size;\r
+ UINT8 *Buffer;\r
+ UINT8 *EditBuffer; // Edit copy for Buffer Storage\r
+\r
+ LIST_ENTRY NameValueListHead; // List of NAME_VALUE_NODE\r
+\r
+ UINT32 Attributes; // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute\r
+\r
+ CHAR16 *ConfigHdr; // <ConfigHdr>\r
+ CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>\r
+ UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>\r
+ UINTN SpareStrLen; // Spare length of ConfigRequest string buffer\r
+} FORMSET_STORAGE;\r
+\r
+#define FORMSET_STORAGE_FROM_LINK(a) CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)\r
+\r
+#define EXPRESSION_OPCODE_SIGNATURE EFI_SIGNATURE_32 ('E', 'X', 'O', 'P')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT8 Operand;\r
+\r
+ UINT8 Format; // For EFI_IFR_TO_STRING, EFI_IFR_FIND\r
+ UINT8 Flags; // For EFI_IFR_SPAN\r
+ UINT8 RuleId; // For EFI_IFR_RULE_REF\r
+\r
+ 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\r
+\r
+ EFI_QUESTION_ID QuestionId; // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_LIST, EFI_IFR_QUESTION_REF1\r
+ EFI_QUESTION_ID QuestionId2;\r
+\r
+ UINT16 ListLength; // For EFI_IFR_EQ_ID_LIST\r
+ UINT16 *ValueList;\r
+\r
+ EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3\r
+ EFI_GUID Guid;\r
+} EXPRESSION_OPCODE;\r
+\r
+#define EXPRESSION_OPCODE_FROM_LINK(a) CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)\r
+\r
+#define FORM_EXPRESSION_SIGNATURE EFI_SIGNATURE_32 ('F', 'E', 'X', 'P')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT8 Type; // Type for this expression\r
+\r
+ UINT8 RuleId; // For EFI_IFR_RULE only\r
+ EFI_STRING_ID Error; // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only\r
+\r
+ EFI_HII_VALUE Result; // Expression evaluation result\r
+\r
+ LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE)\r
+} FORM_EXPRESSION;\r
+\r
+#define FORM_EXPRESSION_FROM_LINK(a) CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)\r
+\r
+#define QUESTION_DEFAULT_SIGNATURE EFI_SIGNATURE_32 ('Q', 'D', 'F', 'T')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 DefaultId;\r
+ EFI_HII_VALUE Value; // Default value\r
+\r
+ FORM_EXPRESSION *ValueExpression; // Not-NULL indicates default value is provided by EFI_IFR_VALUE\r
+} QUESTION_DEFAULT;\r
+\r
+#define QUESTION_DEFAULT_FROM_LINK(a) CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)\r
+\r
+#define QUESTION_OPTION_SIGNATURE EFI_SIGNATURE_32 ('Q', 'O', 'P', 'T')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_STRING_ID Text;\r
+ UINT8 Flags;\r
+ EFI_HII_VALUE Value;\r
+ EFI_IMAGE_ID ImageId;\r
+\r
+ FORM_EXPRESSION *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf\r
+} QUESTION_OPTION;\r
+\r
+#define QUESTION_OPTION_FROM_LINK(a) CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)\r
+\r
+#define FORM_BROWSER_STATEMENT_SIGNATURE EFI_SIGNATURE_32 ('F', 'S', 'T', 'A')\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT8 Operand; // The operand (first byte) of this Statement or Question\r
+\r
+ //\r
+ // Statement Header\r
+ //\r
+ EFI_STRING_ID Prompt;\r
+ EFI_STRING_ID Help;\r
+ EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT\r
+\r
+ //\r
+ // Question Header\r
+ //\r
+ EFI_QUESTION_ID QuestionId; // The value of zero is reserved\r
+ EFI_VARSTORE_ID VarStoreId; // A value of zero indicates no variable storage\r
+ FORMSET_STORAGE *Storage;\r
+ union {\r
+ EFI_STRING_ID VarName;\r
+ UINT16 VarOffset;\r
+ } VarStoreInfo;\r
+ UINT16 StorageWidth;\r
+ UINT8 QuestionFlags;\r
+ CHAR16 *VariableName; // Name/Value or EFI Variable name\r
+ CHAR16 *BlockName; // Buffer storage block name: "OFFSET=...WIDTH=..."\r
+\r
+ EFI_HII_VALUE HiiValue; // Edit copy for checkbox, numberic, oneof\r
+ UINT8 *BufferValue; // Edit copy for string, password, orderedlist\r
+\r
+ //\r
+ // OpCode specific members\r
+ //\r
+ UINT8 Flags; // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,\r
+ // EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER\r
+ UINT8 MaxContainers; // for EFI_IFR_ORDERED_LIST\r
+\r
+ UINT16 BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number\r
+ EFI_STRING_ID QuestionConfig; // for EFI_IFR_ACTION, if 0 then no configuration string will be processed\r
+\r
+ UINT64 Minimum; // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value\r
+ UINT64 Maximum; // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length\r
+ UINT64 Step;\r
+\r
+ EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON\r
+ EFI_FORM_ID RefFormId; // for EFI_IFR_REF\r
+ EFI_QUESTION_ID RefQuestionId; // for EFI_IFR_REF2\r
+ EFI_GUID RefFormSetId; // for EFI_IFR_REF3\r
+ EFI_STRING_ID RefDevicePath; // for EFI_IFR_REF4\r
+\r
+ //\r
+ // Get from IFR parsing\r
+ //\r
+ FORM_EXPRESSION *ValueExpression; // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly\r
+ LIST_ENTRY DefaultListHead; // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values\r
+ LIST_ENTRY OptionListHead; // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)\r
+\r
+ EFI_IMAGE_ID ImageId; // nested EFI_IFR_IMAGE\r
+ UINT8 RefreshInterval; // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh\r
+ BOOLEAN InSubtitle; // nesting inside of EFI_IFR_SUBTITLE\r
+\r
+ LIST_ENTRY InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)\r
+ LIST_ENTRY NoSubmitListHead; // nested nosubmit expression list (FORM_EXPRESSION)\r
+ FORM_EXPRESSION *GrayOutExpression; // nesting inside of GrayOutIf\r
+ FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf\r
+\r
+} FORM_BROWSER_STATEMENT;\r
+\r
+#define FORM_BROWSER_STATEMENT_FROM_LINK(a) CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)\r
+\r
+#define FORM_BROWSER_FORM_SIGNATURE EFI_SIGNATURE_32 ('F', 'F', 'R', 'M')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 FormId;\r
+ EFI_STRING_ID FormTitle;\r
+\r
+ EFI_IMAGE_ID ImageId;\r
+\r
+ LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)\r
+ LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT)\r
+} FORM_BROWSER_FORM;\r
+\r
+#define FORM_BROWSER_FORM_FROM_LINK(a) CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)\r
+\r
+#define FORMSET_DEFAULTSTORE_SIGNATURE EFI_SIGNATURE_32 ('F', 'D', 'F', 'S')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ UINT16 DefaultId;\r
+ EFI_STRING_ID DefaultName;\r
+} FORMSET_DEFAULTSTORE;\r
+\r
+#define FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)\r
+\r
+typedef struct {\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ UINTN IfrBinaryLength;\r
+ UINT8 *IfrBinaryData;\r
+\r
+ EFI_GUID Guid;\r
+ EFI_STRING_ID FormSetTitle;\r
+ EFI_STRING_ID Help;\r
+ UINT16 Class;\r
+ UINT16 SubClass;\r
+ EFI_IMAGE_ID ImageId;\r
+\r
+ FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions\r
+ EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode\r
+\r
+ LIST_ENTRY StorageListHead; // Storage list (FORMSET_STORAGE)\r
+ LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)\r
+ LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)\r
+} FORM_BROWSER_FORMSET;\r
+\r
+\r
+extern EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
+extern EFI_HII_STRING_PROTOCOL *mHiiString;\r
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
+\r
+extern BANNER_DATA *BannerData;\r
+extern EFI_HII_HANDLE FrontPageHandle;\r
+extern UINTN gClassOfVfr;\r
+extern UINTN gFunctionKeySetting;\r
+extern BOOLEAN gResetRequired;\r
+extern BOOLEAN gNvUpdateRequired;\r
+extern EFI_HII_HANDLE gHiiHandle;\r
+extern BOOLEAN gFirstIn;\r
+extern UINT16 gDirection;\r
+extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+extern BOOLEAN gUpArrow;\r
+extern BOOLEAN gDownArrow;\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+extern CHAR16 *gFunctionOneString;\r
+extern CHAR16 *gFunctionTwoString;\r
+extern CHAR16 *gFunctionNineString;\r
+extern CHAR16 *gFunctionTenString;\r
+extern CHAR16 *gEnterString;\r
+extern CHAR16 *gEnterCommitString;\r
+extern CHAR16 *gEscapeString;\r
+extern CHAR16 *gSaveFailed;\r
+extern CHAR16 *gMoveHighlight;\r
+extern CHAR16 *gMakeSelection;\r
+extern CHAR16 *gDecNumericInput;\r
+extern CHAR16 *gHexNumericInput;\r
+extern CHAR16 *gToggleCheckBox;\r
+extern CHAR16 *gPromptForData;\r
+extern CHAR16 *gPromptForPassword;\r
+extern CHAR16 *gPromptForNewPassword;\r
+extern CHAR16 *gConfirmPassword;\r
+extern CHAR16 *gConfirmError;\r
+extern CHAR16 *gPassowordInvalid;\r
+extern CHAR16 *gPressEnter;\r
+extern CHAR16 *gEmptyString;\r
+extern CHAR16 *gAreYouSure;\r
+extern CHAR16 *gYesResponse;\r
+extern CHAR16 *gNoResponse;\r
+extern CHAR16 *gMiniString;\r
+extern CHAR16 *gPlusString;\r
+extern CHAR16 *gMinusString;\r
+extern CHAR16 *gAdjustNumber;\r
+\r
+extern CHAR16 gPromptBlockWidth;\r
+extern CHAR16 gOptionBlockWidth;\r
+extern CHAR16 gHelpBlockWidth;\r
+\r
+extern EFI_GUID gZeroGuid;\r
+extern EFI_GUID gTianoHiiIfrGuid;\r
+\r
+//\r
+// Global Procedure Defines\r
+//\r
+\r
+/**\r
+ Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeBrowserStrings (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ Prints a unicode string to the default console,\r
+ using L"%s" format.\r
+\r
+ @param String String pointer.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintString (\r
+ IN CHAR16 *String\r
+ )\r
+;\r
+\r
+/**\r
+ Prints a chracter to the default console,\r
+ using L"%c" format.\r
+\r
+ @param Character Character to print.\r
+\r
+ @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintChar (\r
+ CHAR16 Character\r
+ )\r
+;\r
+\r
+/**\r
+ Prints a formatted unicode string to the default console, at\r
+ the supplied cursor position.\r
+\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at\r
+ @param Fmt Format string\r
+ @param ... Variable argument list for formating string.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *Fmt,\r
+ ...\r
+ )\r
+;\r
+\r
+/**\r
+ Prints a unicode string to the default console, at\r
+ the supplied cursor position, using L"%s" format.\r
+\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at\r
+ @param String String pointer.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+PrintStringAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *String\r
+ )\r
+;\r
+\r
+/**\r
+ Prints a chracter to the default console, at\r
+ the supplied cursor position, using L"%c" format.\r
+\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at.\r
+ @param Character Character to print.\r
+\r
+ @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+PrintCharAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ CHAR16 Character\r
+ )\r
+;\r
+\r
+/**\r
+ Parse opcodes in the formset IFR binary.\r
+\r
+ @param FormSet Pointer of the FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS Opcode parse success.\r
+ @retval Other Opcode parse fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ParseOpCodes (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+;\r
+\r
+/**\r
+ Free resources allocated for a FormSet.\r
+\r
+ @param FormSet Pointer of the FormSet\r
+\r
+**/\r
+VOID\r
+DestroyFormSet (\r
+ IN OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+;\r
+\r
+/**\r
+ This function displays the page frame.\r
+\r
+**/\r
+VOID\r
+DisplayPageFrame (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ Create a new string in HII Package List.\r
+\r
+ @param String The String to be added\r
+ @param HiiHandle The package list in the HII database to insert the\r
+ specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+EFI_STRING_ID\r
+NewString (\r
+ IN CHAR16 *String,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+;\r
+\r
+/**\r
+ Delete a string from HII Package List.\r
+\r
+ @param StringId Id of the string in HII database.\r
+ @param HiiHandle The HII package list handle.\r
+\r
+ @retval EFI_SUCCESS The string was deleted successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+DeleteString (\r
+ IN EFI_STRING_ID StringId,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+;\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param Token The String's ID.\r
+ @param HiiHandle The package list in the HII database to search for\r
+ the specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetToken (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+;\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param ArrayOfStrings The array of string to be printed.\r
+\r
+**/\r
+VOID\r
+CreateSharedPopUp (\r
+ IN UINTN RequestedWidth,\r
+ IN UINTN NumberOfLines,\r
+ IN CHAR16 **ArrayOfStrings\r
+ )\r
+;\r
+\r
+/**\r
+ Routine used to abstract a generic dialog interface and return the selected key or string\r
+\r
+ @param NumberOfLines The number of lines for the dialog box\r
+ @param HotKey Defines whether a single character is parsed\r
+ (TRUE) and returned in KeyValue or a string is\r
+ returned in StringBuffer. Two special characters\r
+ are considered when entering a string, a SCAN_ESC\r
+ and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates\r
+ string input and returns\r
+ @param MaximumStringSize The maximum size in bytes of a typed in string\r
+ (each character is a CHAR16) and the minimum\r
+ string returned is two bytes\r
+ @param StringBuffer The passed in pointer to the buffer which will\r
+ hold the typed in string if HotKey is FALSE\r
+ @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
+ @param String Pointer to the first string in the list\r
+ @param ... A series of (quantity == NumberOfLines) text\r
+ strings which will be used to construct the dialog\r
+ box\r
+\r
+ @retval EFI_SUCCESS Displayed dialog and received user interaction\r
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.\r
+ (StringBuffer == NULL) && (HotKey == FALSE))\r
+ @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine\r
+\r
+**/\r
+EFI_STATUS\r
+CreateDialog (\r
+ IN UINTN NumberOfLines,\r
+ IN BOOLEAN HotKey,\r
+ IN UINTN MaximumStringSize,\r
+ OUT CHAR16 *StringBuffer,\r
+ OUT EFI_INPUT_KEY *KeyValue,\r
+ IN CHAR16 *String,\r
+ ...\r
+ )\r
+;\r
+\r
+/**\r
+ Get Question's current Value.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Question to be initialized.\r
+ @param Cached TRUE: get from Edit copy FALSE: get from original\r
+ Storage\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionValue (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN BOOLEAN Cached\r
+ )\r
+;\r
+\r
+/**\r
+ Save Question Value to edit copy(cached) or Storage(uncached).\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Pointer to the Question.\r
+ @param Cached TRUE: set to Edit copy FALSE: set to original\r
+ Storage\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SetQuestionValue (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN BOOLEAN Cached\r
+ )\r
+;\r
+\r
+/**\r
+ Perform inconsistent check for a Form.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question The Question to be validated.\r
+ @param Type Validation type: InConsistent or NoSubmit\r
+\r
+ @retval EFI_SUCCESS Form validation pass.\r
+ @retval other Form validation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+ValidateQuestion (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINTN Type\r
+ )\r
+;\r
+\r
+/**\r
+ Submit a Form.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+SubmitForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+;\r
+\r
+/**\r
+ Reset Question to its default value.\r
+\r
+ @param FormSet The form set.\r
+ @param Form The form.\r
+ @param Question The question.\r
+ @param DefaultId The Class of the default.\r
+\r
+ @retval EFI_SUCCESS Question is reset to default value.\r
+\r
+**/\r
+EFI_STATUS\r
+GetQuestionDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN UINT16 DefaultId\r
+ )\r
+;\r
+\r
+/**\r
+ Get current setting of Questions.\r
+\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeCurrentSetting (\r
+ IN OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+;\r
+\r
+/**\r
+ Initialize the internal data structure of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
+ GUID), take the first FormSet found in package\r
+ list.\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+;\r
+\r
+/**\r
+ Reset Questions in a Form to their default value.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form The Form which to be reset.\r
+ @param DefaultId The Class of the default.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractFormDefault (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 DefaultId\r
+ )\r
+;\r
+\r
+/**\r
+ Initialize Question's Edit copy from Storage.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormConfig (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+;\r
+\r
+/**\r
+ Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.\r
+\r
+ @param Storage The Storage to be conveted.\r
+ @param ConfigResp The returned <ConfigResp>.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+StorageToConfigResp (\r
+ IN FORMSET_STORAGE *Storage,\r
+ IN CHAR16 **ConfigResp\r
+ )\r
+;\r
+\r
+/**\r
+ Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.\r
+\r
+ @param Storage The Storage to receive the settings.\r
+ @param ConfigResp The <ConfigResp> to be converted.\r
+\r
+ @retval EFI_SUCCESS Convert success.\r
+ @retval EFI_INVALID_PARAMETER Incorrect storage type.\r
+\r
+**/\r
+EFI_STATUS\r
+ConfigRespToStorage (\r
+ IN FORMSET_STORAGE *Storage,\r
+ IN CHAR16 *ConfigResp\r
+ )\r
+;\r
+\r
+/**\r
+ Fill storage's edit copy with settings requested from Configuration Driver.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Storage Buffer Storage.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadStorage (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORMSET_STORAGE *Storage\r
+ )\r
+;\r
+\r
+/**\r
+ Fetch the Ifr binary data of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero\r
+ GUID), take the first FormSet found in package\r
+ list.\r
+ @param BinaryLength The length of the FormSet IFR binary.\r
+ @param BinaryData The buffer designed to receive the FormSet.\r
+\r
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.\r
+ BufferLength was updated.\r
+ @retval EFI_INVALID_PARAMETER The handle is unknown.\r
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot\r
+ be found with the requested FormId.\r
+\r
+**/\r
+EFI_STATUS\r
+GetIfrBinaryData (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT UINTN *BinaryLength,\r
+ OUT UINT8 **BinaryData\r
+ )\r
+;\r
+\r
+/**\r
+ This is the routine which an external caller uses to direct the browser\r
+ where to obtain it's information.\r
+\r
+\r
+ @param This The Form Browser protocol instanse.\r
+ @param Handles A pointer to an array of Handles. If HandleCount > 1 we\r
+ display a list of the formsets for the handles specified.\r
+ @param HandleCount The number of Handles specified in Handle.\r
+ @param FormSetGuid This field points to the EFI_GUID which must match the Guid\r
+ field in the EFI_IFR_FORM_SET op-code for the specified\r
+ forms-based package. If FormSetGuid is NULL, then this\r
+ function will display the first found forms package.\r
+ @param FormId This field specifies which EFI_IFR_FORM to render as the first\r
+ displayable page. If this field has a value of 0x0000, then\r
+ the forms browser will render the specified forms in their encoded order.\r
+ ScreenDimenions - This allows the browser to be called so that it occupies a\r
+ portion of the physical screen instead of dynamically determining the screen dimensions.\r
+ ActionRequest - Points to the action recommended by the form.\r
+ @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in \r
+ characters.\r
+ @param ActionRequest Points to the action recommended by the form.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_NOT_FOUND No valid forms could be found to display.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SendForm (\r
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE *Handles,\r
+ IN UINTN HandleCount,\r
+ IN EFI_GUID *FormSetGuid, OPTIONAL\r
+ IN UINT16 FormId, OPTIONAL\r
+ IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ This function is called by a callback handler to retrieve uncommitted state\r
+ data from the browser.\r
+\r
+ @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
+ instance.\r
+ @param ResultsDataSize A pointer to the size of the buffer associated\r
+ with ResultsData.\r
+ @param ResultsData A string returned from an IFR browser or\r
+ equivalent. The results string will have no\r
+ routing information in them.\r
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
+ (if RetrieveData = TRUE) data from the uncommitted\r
+ browser state information or set (if RetrieveData\r
+ = FALSE) data in the uncommitted browser state\r
+ information.\r
+ @param VariableGuid An optional field to indicate the target variable\r
+ GUID name to use.\r
+ @param VariableName An optional field to indicate the target\r
+ human-readable variable name.\r
+\r
+ @retval EFI_SUCCESS The results have been distributed or are awaiting\r
+ distribution.\r
+ @retval EFI_BUFFER_TOO_SMALL The ResultsDataSize specified was too small to\r
+ contain the results data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BrowserCallback (\r
+ IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,\r
+ IN OUT UINTN *ResultsDataSize,\r
+ IN OUT EFI_STRING ResultsData,\r
+ IN BOOLEAN RetrieveData,\r
+ IN CONST EFI_GUID *VariableGuid, OPTIONAL\r
+ IN CONST CHAR16 *VariableName OPTIONAL\r
+ )\r
+;\r
+\r
+#endif\r
-/** @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\r
+Utility functions for User Interface functions.\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ui.h"\r
+#include "Setup.h"\r
+\r
+LIST_ENTRY Menu;\r
+LIST_ENTRY gMenuList;\r
+MENU_REFRESH_ENTRY *gMenuRefreshHead;\r
+\r
+//\r
+// Search table for UiDisplayMenu()\r
+//\r
+SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {\r
+ {\r
+ SCAN_UP,\r
+ UiUp,\r
+ },\r
+ {\r
+ SCAN_DOWN,\r
+ UiDown,\r
+ },\r
+ {\r
+ SCAN_PAGE_UP,\r
+ UiPageUp,\r
+ },\r
+ {\r
+ SCAN_PAGE_DOWN,\r
+ UiPageDown,\r
+ },\r
+ {\r
+ SCAN_ESC,\r
+ UiReset,\r
+ },\r
+ {\r
+ SCAN_F2,\r
+ UiPrevious,\r
+ },\r
+ {\r
+ SCAN_LEFT,\r
+ UiLeft,\r
+ },\r
+ {\r
+ SCAN_RIGHT,\r
+ UiRight,\r
+ },\r
+ {\r
+ SCAN_F9,\r
+ UiDefault,\r
+ },\r
+ {\r
+ SCAN_F10,\r
+ UiSave\r
+ }\r
+};\r
+\r
+SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {\r
+ {\r
+ UiNoOperation,\r
+ CfUiNoOperation,\r
+ },\r
+ {\r
+ UiDefault,\r
+ CfUiDefault,\r
+ },\r
+ {\r
+ UiSelect,\r
+ CfUiSelect,\r
+ },\r
+ {\r
+ UiUp,\r
+ CfUiUp,\r
+ },\r
+ {\r
+ UiDown,\r
+ CfUiDown,\r
+ },\r
+ {\r
+ UiLeft,\r
+ CfUiLeft,\r
+ },\r
+ {\r
+ UiRight,\r
+ CfUiRight,\r
+ },\r
+ {\r
+ UiReset,\r
+ CfUiReset,\r
+ },\r
+ {\r
+ UiSave,\r
+ CfUiSave,\r
+ },\r
+ {\r
+ UiPrevious,\r
+ CfUiPrevious,\r
+ },\r
+ {\r
+ UiPageUp,\r
+ CfUiPageUp,\r
+ },\r
+ {\r
+ UiPageDown,\r
+ CfUiPageDown\r
+ }\r
+};\r
+\r
+\r
+/**\r
+ Set Buffer to Value for Size bytes.\r
+\r
+ @param Buffer Memory to set.\r
+ @param Size Number of bytes to set\r
+ @param Value Value of the set operation.\r
+\r
+**/\r
+VOID\r
+SetUnicodeMem (\r
+ IN VOID *Buffer,\r
+ IN UINTN Size,\r
+ IN CHAR16 Value\r
+ )\r
+{\r
+ CHAR16 *Ptr;\r
+\r
+ Ptr = Buffer;\r
+ while ((Size--) != 0) {\r
+ *(Ptr++) = Value;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenu (\r
+ VOID\r
+ )\r
+{\r
+ InitializeListHead (&Menu);\r
+}\r
+\r
+\r
+/**\r
+ Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenuList (\r
+ VOID\r
+ )\r
+{\r
+ InitializeListHead (&gMenuList);\r
+}\r
+\r
+\r
+/**\r
+ Remove a Menu in list, and return FormId/QuestionId for previous Menu.\r
+\r
+ @param Selection Menu selection.\r
+\r
+**/\r
+VOID\r
+UiRemoveMenuListEntry (\r
+ OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ UI_MENU_LIST *UiMenuList;\r
+\r
+ if (!IsListEmpty (&gMenuList)) {\r
+ UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);\r
+\r
+ Selection->FormId = UiMenuList->FormId;\r
+ Selection->QuestionId = UiMenuList->QuestionId;\r
+ RemoveEntryList (&UiMenuList->MenuLink);\r
+ gBS->FreePool (UiMenuList);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+ VOID\r
+ )\r
+{\r
+ UI_MENU_LIST *UiMenuList;\r
+\r
+ while (!IsListEmpty (&gMenuList)) {\r
+ UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);\r
+ RemoveEntryList (&UiMenuList->MenuLink);\r
+ gBS->FreePool (UiMenuList);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Add one menu entry to the linked lst\r
+\r
+ @param Selection Menu selection.\r
+\r
+**/\r
+VOID\r
+UiAddMenuListEntry (\r
+ IN UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ UI_MENU_LIST *UiMenuList;\r
+\r
+ UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));\r
+ ASSERT (UiMenuList != NULL);\r
+\r
+ UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;\r
+ UiMenuList->FormId = Selection->FormId;\r
+ UiMenuList->QuestionId = Selection->QuestionId;\r
+\r
+ InsertHeadList (&gMenuList, &UiMenuList->MenuLink);\r
+}\r
+\r
+\r
+/**\r
+ Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenu (\r
+ VOID\r
+ )\r
+{\r
+ UI_MENU_OPTION *MenuOption;\r
+\r
+ while (!IsListEmpty (&Menu)) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);\r
+ RemoveEntryList (&MenuOption->Link);\r
+\r
+ //\r
+ // We allocated space for this description when we did a GetToken, free it here\r
+ //\r
+ if (MenuOption->Skip != 0) {\r
+ //\r
+ // For date/time, MenuOption->Description is shared by three Menu Options\r
+ // Data format : [01/02/2004] [11:22:33]\r
+ // Line number : 0 0 1 0 0 1\r
+ //\r
+ gBS->FreePool (MenuOption->Description);\r
+ }\r
+ gBS->FreePool (MenuOption);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeRefreshList (\r
+ VOID\r
+ )\r
+{\r
+ MENU_REFRESH_ENTRY *OldMenuRefreshEntry;\r
+\r
+ while (gMenuRefreshHead != NULL) {\r
+ OldMenuRefreshEntry = gMenuRefreshHead->Next;\r
+ gBS->FreePool (gMenuRefreshHead);\r
+ gMenuRefreshHead = OldMenuRefreshEntry;\r
+ }\r
+\r
+ gMenuRefreshHead = NULL;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Refresh screen.\r
+\r
+**/\r
+VOID\r
+RefreshForm (\r
+ VOID\r
+ )\r
+{\r
+ CHAR16 *OptionString;\r
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
+ UINTN Index;\r
+ UINTN Loop;\r
+ EFI_STATUS Status;\r
+ UI_MENU_SELECTION *Selection;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ OptionString = NULL;\r
+\r
+ if (gMenuRefreshHead != NULL) {\r
+\r
+ MenuRefreshEntry = gMenuRefreshHead;\r
+\r
+ do {\r
+ gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
+\r
+ Selection = MenuRefreshEntry->Selection;\r
+ Question = MenuRefreshEntry->MenuOption->ThisTag;\r
+\r
+ //\r
+ // Don't update Question being edited\r
+ //\r
+ if (Question != MenuRefreshEntry->Selection->Statement) {\r
+\r
+ Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+\r
+ ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);\r
+\r
+ if (OptionString != NULL) {\r
+ //\r
+ // If leading spaces on OptionString - remove the spaces\r
+ //\r
+ for (Index = 0; OptionString[Index] == L' '; Index++)\r
+ ;\r
+\r
+ for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+ OptionString[Loop] = OptionString[Index];\r
+ Loop++;\r
+ }\r
+\r
+ OptionString[Loop] = CHAR_NULL;\r
+\r
+ PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);\r
+ gBS->FreePool (OptionString);\r
+ }\r
+ }\r
+\r
+ MenuRefreshEntry = MenuRefreshEntry->Next;\r
+\r
+ } while (MenuRefreshEntry != NULL);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Wait for a given event to fire, or for an optional timeout to expire.\r
+\r
+ @param Event The event to wait for\r
+ @param Timeout An optional timeout value in 100 ns units.\r
+ @param RefreshInterval Menu refresh interval (in seconds).\r
+\r
+ @retval EFI_SUCCESS Event fired before Timeout expired.\r
+ @retval EFI_TIME_OUT Timout expired before Event fired.\r
+\r
+**/\r
+EFI_STATUS\r
+UiWaitForSingleEvent (\r
+ IN EFI_EVENT Event,\r
+ IN UINT64 Timeout, OPTIONAL\r
+ IN UINT8 RefreshInterval OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_EVENT TimerEvent;\r
+ EFI_EVENT WaitList[2];\r
+\r
+ if (Timeout != 0) {\r
+ //\r
+ // Create a timer event\r
+ //\r
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Set the timer event\r
+ //\r
+ gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerRelative,\r
+ Timeout\r
+ );\r
+\r
+ //\r
+ // Wait for the original event or the timer\r
+ //\r
+ WaitList[0] = Event;\r
+ WaitList[1] = TimerEvent;\r
+ Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+ gBS->CloseEvent (TimerEvent);\r
+\r
+ //\r
+ // If the timer expired, change the return to timed out\r
+ //\r
+ if (!EFI_ERROR (Status) && Index == 1) {\r
+ Status = EFI_TIMEOUT;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // Update screen every second\r
+ //\r
+ if (RefreshInterval == 0) {\r
+ Timeout = ONE_SECOND;\r
+ } else {\r
+ Timeout = RefreshInterval * ONE_SECOND;\r
+ }\r
+\r
+ do {\r
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+\r
+ //\r
+ // Set the timer event\r
+ //\r
+ gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerRelative,\r
+ Timeout\r
+ );\r
+\r
+ //\r
+ // Wait for the original event or the timer\r
+ //\r
+ WaitList[0] = Event;\r
+ WaitList[1] = TimerEvent;\r
+ Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+\r
+ //\r
+ // If the timer expired, update anything that needs a refresh and keep waiting\r
+ //\r
+ if (!EFI_ERROR (Status) && Index == 1) {\r
+ Status = EFI_TIMEOUT;\r
+ if (RefreshInterval != 0) {\r
+ RefreshForm ();\r
+ }\r
+ }\r
+\r
+ gBS->CloseEvent (TimerEvent);\r
+ } while (Status == EFI_TIMEOUT);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Add one menu option by specified description and context.\r
+\r
+ @param String String description for this option.\r
+ @param Handle Hii handle for the package list.\r
+ @param Statement Statement of this Menu Option.\r
+ @param NumberOfLines Display lines for this Menu Option.\r
+ @param MenuItemCount The index for this Option in the Menu.\r
+\r
+**/\r
+VOID\r
+UiAddMenuOption (\r
+ IN CHAR16 *String,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN FORM_BROWSER_STATEMENT *Statement,\r
+ IN UINT16 NumberOfLines,\r
+ IN UINT16 MenuItemCount\r
+ )\r
+{\r
+ UI_MENU_OPTION *MenuOption;\r
+ UINTN Index;\r
+ UINTN Count;\r
+\r
+ Count = 1;\r
+\r
+ if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
+ //\r
+ // Add three MenuOptions for Date/Time\r
+ // Data format : [01/02/2004] [11:22:33]\r
+ // Line number : 0 0 1 0 0 1\r
+ //\r
+ NumberOfLines = 0;\r
+ Count = 3;\r
+\r
+ if (Statement->Storage == NULL) {\r
+ //\r
+ // For RTC type of date/time, set default refresh interval to be 1 second\r
+ //\r
+ if (Statement->RefreshInterval == 0) {\r
+ Statement->RefreshInterval = 1;\r
+ }\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < Count; Index++) {\r
+ MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));\r
+ ASSERT (MenuOption);\r
+\r
+ MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;\r
+ MenuOption->Description = String;\r
+ MenuOption->Handle = Handle;\r
+ MenuOption->ThisTag = Statement;\r
+ MenuOption->EntryNumber = MenuItemCount;\r
+\r
+ if (Index == 2) {\r
+ //\r
+ // Override LineNumber for the MenuOption in Date/Time sequence\r
+ //\r
+ MenuOption->Skip = 1;\r
+ } else {\r
+ MenuOption->Skip = NumberOfLines;\r
+ }\r
+ MenuOption->Sequence = Index;\r
+\r
+ if (Statement->GrayOutExpression != NULL) {\r
+ MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b;\r
+ }\r
+\r
+ if ((Statement->ValueExpression != NULL) ||\r
+ ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {\r
+ MenuOption->ReadOnly = TRUE;\r
+ }\r
+\r
+ InsertTailList (&Menu, &MenuOption->Link);\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Routine used to abstract a generic dialog interface and return the selected key or string\r
+\r
+ @param NumberOfLines The number of lines for the dialog box\r
+ @param HotKey Defines whether a single character is parsed\r
+ (TRUE) and returned in KeyValue or a string is\r
+ returned in StringBuffer. Two special characters\r
+ are considered when entering a string, a SCAN_ESC\r
+ and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates\r
+ string input and returns\r
+ @param MaximumStringSize The maximum size in bytes of a typed in string\r
+ (each character is a CHAR16) and the minimum\r
+ string returned is two bytes\r
+ @param StringBuffer The passed in pointer to the buffer which will\r
+ hold the typed in string if HotKey is FALSE\r
+ @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
+ @param String Pointer to the first string in the list\r
+ @param ... A series of (quantity == NumberOfLines) text\r
+ strings which will be used to construct the dialog\r
+ box\r
+\r
+ @retval EFI_SUCCESS Displayed dialog and received user interaction\r
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.\r
+ (StringBuffer == NULL) && (HotKey == FALSE))\r
+ @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine\r
+\r
+**/\r
+EFI_STATUS\r
+CreateDialog (\r
+ IN UINTN NumberOfLines,\r
+ IN BOOLEAN HotKey,\r
+ IN UINTN MaximumStringSize,\r
+ OUT CHAR16 *StringBuffer,\r
+ OUT EFI_INPUT_KEY *KeyValue,\r
+ IN CHAR16 *String,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Marker;\r
+ UINTN Count;\r
+ EFI_INPUT_KEY Key;\r
+ UINTN LargestString;\r
+ CHAR16 *TempString;\r
+ CHAR16 *BufferedString;\r
+ CHAR16 *StackString;\r
+ CHAR16 KeyPad[2];\r
+ UINTN Start;\r
+ UINTN Top;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ BOOLEAN SelectionComplete;\r
+ UINTN InputOffset;\r
+ UINTN CurrentAttribute;\r
+ UINTN DimensionsWidth;\r
+ UINTN DimensionsHeight;\r
+\r
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
+\r
+ SelectionComplete = FALSE;\r
+ InputOffset = 0;\r
+ TempString = AllocateZeroPool (MaximumStringSize * 2);\r
+ BufferedString = AllocateZeroPool (MaximumStringSize * 2);\r
+ CurrentAttribute = gST->ConOut->Mode->Attribute;\r
+\r
+ ASSERT (TempString);\r
+ ASSERT (BufferedString);\r
+\r
+ VA_START (Marker, String);\r
+\r
+ //\r
+ // Zero the outgoing buffer\r
+ //\r
+ ZeroMem (StringBuffer, MaximumStringSize);\r
+\r
+ if (HotKey) {\r
+ if (KeyValue == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ } else {\r
+ if (StringBuffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ //\r
+ // Disable cursor\r
+ //\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+ LargestString = (GetStringWidth (String) / 2);\r
+\r
+ if (*String == L' ') {\r
+ InputOffset = 1;\r
+ }\r
+ //\r
+ // Determine the largest string in the dialog box\r
+ // Notice we are starting with 1 since String is the first string\r
+ //\r
+ for (Count = 1; Count < NumberOfLines; Count++) {\r
+ StackString = VA_ARG (Marker, CHAR16 *);\r
+\r
+ if (StackString[0] == L' ') {\r
+ InputOffset = Count + 1;\r
+ }\r
+\r
+ if ((GetStringWidth (StackString) / 2) > LargestString) {\r
+ //\r
+ // Size of the string visually and subtract the width by one for the null-terminator\r
+ //\r
+ LargestString = (GetStringWidth (StackString) / 2);\r
+ }\r
+ }\r
+\r
+ Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
+\r
+ Count = 0;\r
+\r
+ //\r
+ // Display the Popup\r
+ //\r
+ CreateSharedPopUp (LargestString, NumberOfLines, &String);\r
+\r
+ //\r
+ // Take the first key typed and report it back?\r
+ //\r
+ if (HotKey) {\r
+ Status = WaitForKeyStroke (&Key);\r
+ ASSERT_EFI_ERROR (Status);\r
+ CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ } else {\r
+ do {\r
+ Status = WaitForKeyStroke (&Key);\r
+\r
+ switch (Key.UnicodeChar) {\r
+ case CHAR_NULL:\r
+ switch (Key.ScanCode) {\r
+ case SCAN_ESC:\r
+ gBS->FreePool (TempString);\r
+ gBS->FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ SelectionComplete = TRUE;\r
+ gBS->FreePool (TempString);\r
+ gBS->FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ return EFI_SUCCESS;\r
+ break;\r
+\r
+ case CHAR_BACKSPACE:\r
+ if (StringBuffer[0] != CHAR_NULL) {\r
+ for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {\r
+ TempString[Index] = StringBuffer[Index];\r
+ }\r
+ //\r
+ // Effectively truncate string by 1 character\r
+ //\r
+ TempString[Index - 1] = CHAR_NULL;\r
+ StrCpy (StringBuffer, TempString);\r
+ }\r
+\r
+ default:\r
+ //\r
+ // If it is the beginning of the string, don't worry about checking maximum limits\r
+ //\r
+ if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+ StrnCpy (StringBuffer, &Key.UnicodeChar, 1);\r
+ StrnCpy (TempString, &Key.UnicodeChar, 1);\r
+ } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+ KeyPad[0] = Key.UnicodeChar;\r
+ KeyPad[1] = CHAR_NULL;\r
+ StrCat (StringBuffer, KeyPad);\r
+ StrCat (TempString, KeyPad);\r
+ }\r
+ //\r
+ // If the width of the input string is now larger than the screen, we nee to\r
+ // adjust the index to start printing portions of the string\r
+ //\r
+ SetUnicodeMem (BufferedString, LargestString, L' ');\r
+\r
+ PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
+\r
+ if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {\r
+ Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;\r
+ } else {\r
+ Index = 0;\r
+ }\r
+\r
+ for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {\r
+ BufferedString[Count] = StringBuffer[Index];\r
+ }\r
+\r
+ PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
+ break;\r
+ }\r
+ } while (!SelectionComplete);\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param ArrayOfStrings The array of string to be printed.\r
+\r
+**/\r
+VOID\r
+CreateSharedPopUp (\r
+ IN UINTN RequestedWidth,\r
+ IN UINTN NumberOfLines,\r
+ IN CHAR16 **ArrayOfStrings\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ CHAR16 Character;\r
+ UINTN Start;\r
+ UINTN End;\r
+ UINTN Top;\r
+ UINTN Bottom;\r
+ CHAR16 *String;\r
+ UINTN DimensionsWidth;\r
+ UINTN DimensionsHeight;\r
+\r
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
+\r
+ Count = 0;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+\r
+ if ((RequestedWidth + 2) > DimensionsWidth) {\r
+ RequestedWidth = DimensionsWidth - 2;\r
+ }\r
+\r
+ //\r
+ // Subtract the PopUp width from total Columns, allow for one space extra on\r
+ // each end plus a border.\r
+ //\r
+ Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
+ End = Start + RequestedWidth + 1;\r
+\r
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
+ Bottom = Top + NumberOfLines + 2;\r
+\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (Start, Top, Character);\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ PrintChar (Character);\r
+ }\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintChar (Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Index = Top; Index + 2 < Bottom; Index++) {\r
+ String = ArrayOfStrings[Count];\r
+ Count++;\r
+\r
+ //\r
+ // This will clear the background of the line - we never know who might have been\r
+ // here before us. This differs from the next clear in that it used the non-reverse\r
+ // video for normal printing.\r
+ //\r
+ if (GetStringWidth (String) / 2 > 1) {\r
+ ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
+ }\r
+\r
+ //\r
+ // Passing in a space results in the assumption that this is where typing will occur\r
+ //\r
+ if (String[0] == L' ') {\r
+ ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);\r
+ }\r
+\r
+ //\r
+ // Passing in a NULL results in a blank space\r
+ //\r
+ if (String[0] == CHAR_NULL) {\r
+ ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
+ }\r
+\r
+ PrintStringAt (\r
+ ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,\r
+ Index + 1,\r
+ String\r
+ );\r
+ gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
+ PrintCharAt (Start, Index + 1, Character);\r
+ PrintCharAt (End - 1, Index + 1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (Start, Bottom - 1, Character);\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ PrintChar (Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintChar (Character);\r
+}\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param ArrayOfStrings The array of string to be printed.\r
+ @param ... A series of text strings that displayed in the pop-up.\r
+\r
+**/\r
+VOID\r
+CreatePopUp (\r
+ IN UINTN RequestedWidth,\r
+ IN UINTN NumberOfLines,\r
+ IN CHAR16 *ArrayOfStrings,\r
+ ...\r
+ )\r
+{\r
+ CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);\r
+}\r
+\r
+\r
+/**\r
+ Update status bar on the bottom of menu.\r
+\r
+ @param MessageType The type of message to be shown.\r
+ @param Flags The flags in Question header.\r
+ @param State Set or clear.\r
+\r
+**/\r
+VOID\r
+UpdateStatusBar (\r
+ IN UINTN MessageType,\r
+ IN UINT8 Flags,\r
+ IN BOOLEAN State\r
+ )\r
+{\r
+ UINTN Index;\r
+ STATIC BOOLEAN InputError;\r
+ CHAR16 *NvUpdateMessage;\r
+ CHAR16 *InputErrorMessage;\r
+\r
+ NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);\r
+ InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);\r
+\r
+ switch (MessageType) {\r
+ case INPUT_ERROR:\r
+ if (State) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);\r
+ PrintStringAt (\r
+ gScreenDimensions.LeftColumn + gPromptBlockWidth,\r
+ gScreenDimensions.BottomRow - 1,\r
+ InputErrorMessage\r
+ );\r
+ InputError = TRUE;\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);\r
+ for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {\r
+ PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");\r
+ }\r
+\r
+ InputError = FALSE;\r
+ }\r
+ break;\r
+\r
+ case NV_UPDATE_REQUIRED:\r
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+ if (State) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);\r
+ PrintStringAt (\r
+ gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,\r
+ gScreenDimensions.BottomRow - 1,\r
+ NvUpdateMessage\r
+ );\r
+ gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));\r
+\r
+ gNvUpdateRequired = TRUE;\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);\r
+ for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {\r
+ PrintAt (\r
+ (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),\r
+ gScreenDimensions.BottomRow - 1,\r
+ L" "\r
+ );\r
+ }\r
+\r
+ gNvUpdateRequired = FALSE;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case REFRESH_STATUS_BAR:\r
+ if (InputError) {\r
+ UpdateStatusBar (INPUT_ERROR, Flags, TRUE);\r
+ }\r
+\r
+ if (gNvUpdateRequired) {\r
+ UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ gBS->FreePool (InputErrorMessage);\r
+ gBS->FreePool (NvUpdateMessage);\r
+ return ;\r
+}\r
+\r
+\r
+/**\r
+ Get the supported width for a particular op-code\r
+\r
+ @param Statement The FORM_BROWSER_STATEMENT structure passed in.\r
+ @param Handle The handle in the HII database being used\r
+\r
+ @return Returns the number of CHAR16 characters that is support.\r
+\r
+**/\r
+UINT16\r
+GetWidth (\r
+ IN FORM_BROWSER_STATEMENT *Statement,\r
+ IN EFI_HII_HANDLE Handle\r
+ )\r
+{\r
+ CHAR16 *String;\r
+ UINTN Size;\r
+ UINT16 Width;\r
+\r
+ Size = 0;\r
+\r
+ //\r
+ // See if the second text parameter is really NULL\r
+ //\r
+ if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
+ String = GetToken (Statement->TextTwo, Handle);\r
+ Size = StrLen (String);\r
+ gBS->FreePool (String);\r
+ }\r
+\r
+ if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||\r
+ (Statement->Operand == EFI_IFR_REF_OP) ||\r
+ (Statement->Operand == EFI_IFR_PASSWORD_OP) ||\r
+ (Statement->Operand == EFI_IFR_ACTION_OP) ||\r
+ (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
+ //\r
+ // Allow a wide display if text op-code and no secondary text op-code\r
+ //\r
+ ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))\r
+ ) {\r
+ Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);\r
+ } else {\r
+ Width = (UINT16) gPromptBlockWidth;\r
+ }\r
+\r
+ if (Statement->InSubtitle) {\r
+ Width -= SUBTITLE_INDENT;\r
+ }\r
+\r
+ return Width;\r
+}\r
+\r
+\r
+STATIC BOOLEAN GetLineByWidthFinished = FALSE;\r
+\r
+/**\r
+ Will copy LineWidth amount of a string in the OutputString buffer and return the\r
+ number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+ @param InputString String description for this option.\r
+ @param LineWidth Width of the desired string to extract in CHAR16\r
+ characters\r
+ @param Index Where in InputString to start the copy process\r
+ @param OutputString Buffer to copy the string into\r
+\r
+ @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+**/\r
+UINT16\r
+GetLineByWidth (\r
+ IN CHAR16 *InputString,\r
+ IN UINT16 LineWidth,\r
+ IN OUT UINTN *Index,\r
+ OUT CHAR16 **OutputString\r
+ )\r
+{\r
+ UINT16 Count;\r
+ UINT16 Count2;\r
+\r
+ if (GetLineByWidthFinished) {\r
+ GetLineByWidthFinished = FALSE;\r
+ return (UINT16) 0;\r
+ }\r
+\r
+ Count = LineWidth;\r
+ Count2 = 0;\r
+\r
+ *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));\r
+\r
+ //\r
+ // Ensure we have got a valid buffer\r
+ //\r
+ if (*OutputString != NULL) {\r
+\r
+ //\r
+ //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.\r
+ //To avoid displaying this empty line in screen, just skip the two CHARs here.\r
+ //\r
+ if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
+ *Index = *Index + 2;\r
+ }\r
+\r
+ //\r
+ // Fast-forward the string and see if there is a carriage-return in the string\r
+ //\r
+ for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)\r
+ ;\r
+\r
+ //\r
+ // Copy the desired LineWidth of data to the output buffer.\r
+ // Also make sure that we don't copy more than the string.\r
+ // Also make sure that if there are linefeeds, we account for them.\r
+ //\r
+ if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&\r
+ (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))\r
+ ) {\r
+ //\r
+ // Convert to CHAR16 value and show that we are done with this operation\r
+ //\r
+ LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);\r
+ if (LineWidth != 0) {\r
+ GetLineByWidthFinished = TRUE;\r
+ }\r
+ } else {\r
+ if (Count2 == LineWidth) {\r
+ //\r
+ // Rewind the string from the maximum size until we see a space to break the line\r
+ //\r
+ for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)\r
+ ;\r
+ if (LineWidth == 0) {\r
+ LineWidth = Count;\r
+ }\r
+ } else {\r
+ LineWidth = Count2;\r
+ }\r
+ }\r
+\r
+ CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);\r
+\r
+ //\r
+ // If currently pointing to a space, increment the index to the first non-space character\r
+ //\r
+ for (;\r
+ (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);\r
+ (*Index)++\r
+ )\r
+ ;\r
+ *Index = (UINT16) (*Index + LineWidth);\r
+ return LineWidth;\r
+ } else {\r
+ return (UINT16) 0;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Update display lines for a Menu Option.\r
+\r
+ @param Selection The user's selection.\r
+ @param MenuOption The MenuOption to be checked.\r
+ @param OptionalString The option string.\r
+ @param SkipValue The number of lins to skip.\r
+\r
+ @retval TRUE This Menu Option is selectable.\r
+ @retval FALSE This Menu Option could not be selected.\r
+\r
+**/\r
+VOID\r
+UpdateOptionSkipLines (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ OUT CHAR16 **OptionalString,\r
+ IN UINTN SkipValue\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 Width;\r
+ UINTN Row;\r
+ UINTN OriginalRow;\r
+ CHAR16 *OutputString;\r
+ CHAR16 *OptionString;\r
+\r
+ Row = 0;\r
+ OptionString = *OptionalString;\r
+ OutputString = NULL;\r
+\r
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+\r
+ if (OptionString != NULL) {\r
+ Width = (UINT16) gOptionBlockWidth;\r
+\r
+ OriginalRow = Row;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&OptionString[Index])) {\r
+ if (SkipValue == 0) {\r
+ Row++;\r
+ //\r
+ // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+ // some testing to ensure we are keeping this in-sync.\r
+ //\r
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+ //\r
+ if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+ MenuOption->Skip++;\r
+ }\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ if (SkipValue != 0) {\r
+ SkipValue--;\r
+ }\r
+ }\r
+\r
+ Row = OriginalRow;\r
+ }\r
+\r
+ *OptionalString = OptionString;\r
+}\r
+\r
+\r
+/**\r
+ Check whether this Menu Option could be highlighted.\r
+\r
+ This is an internal function.\r
+\r
+ @param MenuOption The MenuOption to be checked.\r
+\r
+ @retval TRUE This Menu Option is selectable.\r
+ @retval FALSE This Menu Option could not be selected.\r
+\r
+**/\r
+BOOLEAN\r
+IsSelectable (\r
+ UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||\r
+ MenuOption->GrayOut || MenuOption->ReadOnly) {\r
+ return FALSE;\r
+ } else {\r
+ return TRUE;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Determine if the menu is the last menu that can be selected.\r
+\r
+ This is an internal function.\r
+ \r
+ @param Direction The scroll direction. False is down. True is up.\r
+ @param CurrentPos The current focus.\r
+\r
+ @return FALSE -- the menu isn't the last menu that can be selected.\r
+ @return TRUE -- the menu is the last menu that can be selected.\r
+\r
+**/\r
+BOOLEAN\r
+ValueIsScroll (\r
+ IN BOOLEAN Direction,\r
+ IN LIST_ENTRY *CurrentPos\r
+ )\r
+{\r
+ LIST_ENTRY *Temp;\r
+ UI_MENU_OPTION *MenuOption;\r
+\r
+ Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
+\r
+ if (Temp == &Menu) {\r
+ return TRUE;\r
+ }\r
+\r
+ for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (Temp);\r
+ if (IsSelectable (MenuOption)) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Move to next selectable statement.\r
+ \r
+ This is an internal function.\r
+ \r
+ @param GoUp The navigation direction. TRUE: up, FALSE: down.\r
+ @param CurrentPosition Current position.\r
+\r
+ @return The row distance from current MenuOption to next selectable MenuOption.\r
+\r
+**/\r
+INTN\r
+MoveToNextStatement (\r
+ IN BOOLEAN GoUp,\r
+ IN OUT LIST_ENTRY **CurrentPosition\r
+ )\r
+{\r
+ INTN Distance;\r
+ LIST_ENTRY *Pos;\r
+ BOOLEAN HitEnd;\r
+ UI_MENU_OPTION *NextMenuOption;\r
+\r
+ Distance = 0;\r
+ Pos = *CurrentPosition;\r
+ HitEnd = FALSE;\r
+\r
+ while (TRUE) {\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+ if (IsSelectable (NextMenuOption)) {\r
+ break;\r
+ }\r
+ if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {\r
+ HitEnd = TRUE;\r
+ break;\r
+ }\r
+ Distance += NextMenuOption->Skip;\r
+ Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+ }\r
+\r
+ if (HitEnd) {\r
+ //\r
+ // If we hit end there is still no statement can be focused,\r
+ // we go backwards to find the statement can be focused.\r
+ //\r
+ Distance = 0;\r
+ Pos = *CurrentPosition;\r
+\r
+ while (TRUE) {\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+ if (IsSelectable (NextMenuOption)) {\r
+ break;\r
+ }\r
+ if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+ Distance -= NextMenuOption->Skip;\r
+ Pos = (!GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+ }\r
+ }\r
+\r
+ *CurrentPosition = &NextMenuOption->Link;\r
+ return Distance;\r
+}\r
+\r
+\r
+/**\r
+ Adjust Data and Time position accordingly.\r
+ Data format : [01/02/2004] [11:22:33]\r
+ Line number : 0 0 1 0 0 1\r
+ \r
+ This is an internal function.\r
+\r
+ @param DirectionUp the up or down direction. False is down. True is\r
+ up.\r
+ @param CurrentPosition Current position. On return: Point to the last\r
+ Option (Year or Second) if up; Point to the first\r
+ Option (Month or Hour) if down.\r
+\r
+ @return Return line number to pad. It is possible that we stand on a zero-advance\r
+ @return data or time opcode, so pad one line when we judge if we are going to scroll outside.\r
+\r
+**/\r
+UINTN\r
+AdjustDateAndTimePosition (\r
+ IN BOOLEAN DirectionUp,\r
+ IN OUT LIST_ENTRY **CurrentPosition\r
+ )\r
+{\r
+ UINTN Count;\r
+ LIST_ENTRY *NewPosition;\r
+ UI_MENU_OPTION *MenuOption;\r
+ UINTN PadLineNumber;\r
+\r
+ PadLineNumber = 0;\r
+ NewPosition = *CurrentPosition;\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
+\r
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
+ (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
+ //\r
+ // Calculate the distance from current position to the last Date/Time MenuOption\r
+ //\r
+ Count = 0;\r
+ while (MenuOption->Skip == 0) {\r
+ Count++;\r
+ NewPosition = NewPosition->ForwardLink;\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
+ PadLineNumber = 1;\r
+ }\r
+\r
+ NewPosition = *CurrentPosition;\r
+ if (DirectionUp) {\r
+ //\r
+ // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended\r
+ // to be one that back to the previous set of MenuOptions, we need to advance to the first\r
+ // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate\r
+ // checking can be done.\r
+ //\r
+ while (Count++ < 2) {\r
+ NewPosition = NewPosition->BackLink;\r
+ }\r
+ } else {\r
+ //\r
+ // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended\r
+ // to be one that progresses to the next set of MenuOptions, we need to advance to the last\r
+ // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate\r
+ // checking can be done.\r
+ //\r
+ while (Count-- > 0) {\r
+ NewPosition = NewPosition->ForwardLink;\r
+ }\r
+ }\r
+\r
+ *CurrentPosition = NewPosition;\r
+ }\r
+\r
+ return PadLineNumber;\r
+}\r
+\r
+\r
+/**\r
+ Display menu and wait for user to select one menu option, then return it.\r
+ If AutoBoot is enabled, then if user doesn't select any option,\r
+ after period of time, it will automatically return the first menu option.\r
+\r
+ @param Selection Menu selection.\r
+\r
+ @retval EFI_SUCESSS This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS\r
+UiDisplayMenu (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ INTN SkipValue;\r
+ INTN Difference;\r
+ INTN OldSkipValue;\r
+ UINTN DistanceValue;\r
+ UINTN Row;\r
+ UINTN Col;\r
+ UINTN Temp;\r
+ UINTN Temp2;\r
+ UINTN TopRow;\r
+ UINTN BottomRow;\r
+ UINTN OriginalRow;\r
+ UINTN Index;\r
+ UINT32 Count;\r
+ UINT16 Width;\r
+ CHAR16 *StringPtr;\r
+ CHAR16 *OptionString;\r
+ CHAR16 *OutputString;\r
+ CHAR16 *FormattedString;\r
+ CHAR16 YesResponse;\r
+ CHAR16 NoResponse;\r
+ BOOLEAN NewLine;\r
+ BOOLEAN Repaint;\r
+ BOOLEAN SavedValue;\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NewPos;\r
+ LIST_ENTRY *TopOfScreen;\r
+ LIST_ENTRY *SavedListEntry;\r
+ UI_MENU_OPTION *MenuOption;\r
+ UI_MENU_OPTION *NextMenuOption;\r
+ UI_MENU_OPTION *SavedMenuOption;\r
+ UI_MENU_OPTION *PreviousMenuOption;\r
+ UI_CONTROL_FLAG ControlFlag;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
+ UI_SCREEN_OPERATION ScreenOperation;\r
+ UINT8 MinRefreshInterval;\r
+ UINTN BufferSize;\r
+ UINT16 DefaultId;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ Status = EFI_SUCCESS;\r
+ FormattedString = NULL;\r
+ OptionString = NULL;\r
+ ScreenOperation = UiNoOperation;\r
+ NewLine = TRUE;\r
+ MinRefreshInterval = 0;\r
+ DefaultId = 0;\r
+\r
+ OutputString = NULL;\r
+ gUpArrow = FALSE;\r
+ gDownArrow = FALSE;\r
+ SkipValue = 0;\r
+ OldSkipValue = 0;\r
+ MenuRefreshEntry = gMenuRefreshHead;\r
+\r
+ NextMenuOption = NULL;\r
+ PreviousMenuOption = NULL;\r
+ SavedMenuOption = NULL;\r
+\r
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+ TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+ Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+ } else {\r
+ TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+ Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
+ }\r
+\r
+ Col = LocalScreen.LeftColumn;\r
+ BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;\r
+\r
+ Selection->TopRow = TopRow;\r
+ Selection->BottomRow = BottomRow;\r
+ Selection->PromptCol = Col;\r
+ Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
+ Selection->Statement = NULL;\r
+\r
+ TopOfScreen = Menu.ForwardLink;\r
+ Repaint = TRUE;\r
+ MenuOption = NULL;\r
+\r
+ //\r
+ // Get user's selection\r
+ //\r
+ NewPos = Menu.ForwardLink;\r
+\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+ UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);\r
+\r
+ ControlFlag = CfInitialization;\r
+ Selection->Action = UI_ACTION_NONE;\r
+ while (TRUE) {\r
+ switch (ControlFlag) {\r
+ case CfInitialization:\r
+ if (IsListEmpty (&Menu)) {\r
+ ControlFlag = CfReadKey;\r
+ } else {\r
+ ControlFlag = CfCheckSelection;\r
+ }\r
+ break;\r
+\r
+ case CfCheckSelection:\r
+ if (Selection->Action != UI_ACTION_NONE) {\r
+ ControlFlag = CfExit;\r
+ } else {\r
+ ControlFlag = CfRepaint;\r
+ }\r
+ break;\r
+\r
+ case CfRepaint:\r
+ ControlFlag = CfRefreshHighLight;\r
+\r
+ if (Repaint) {\r
+ //\r
+ // Display menu\r
+ //\r
+ gDownArrow = FALSE;\r
+ gUpArrow = FALSE;\r
+ Row = TopRow;\r
+\r
+ Temp = SkipValue;\r
+ Temp2 = SkipValue;\r
+\r
+ ClearLines (\r
+ LocalScreen.LeftColumn,\r
+ LocalScreen.RightColumn,\r
+ TopRow - SCROLL_ARROW_HEIGHT,\r
+ BottomRow + SCROLL_ARROW_HEIGHT,\r
+ FIELD_TEXT | FIELD_BACKGROUND\r
+ );\r
+\r
+ UiFreeRefreshList ();\r
+ MinRefreshInterval = 0;\r
+\r
+ for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ MenuOption->Row = Row;\r
+ MenuOption->Col = Col;\r
+ MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
+\r
+ Statement = MenuOption->ThisTag;\r
+ if (Statement->InSubtitle) {\r
+ MenuOption->Col += SUBTITLE_INDENT;\r
+ }\r
+\r
+ if (MenuOption->GrayOut) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
+ } else {\r
+ if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);\r
+ }\r
+ }\r
+\r
+ Width = GetWidth (Statement, MenuOption->Handle);\r
+ OriginalRow = Row;\r
+\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp == 0) && (Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->Col, Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&MenuOption->Description[Index])) {\r
+ if (Temp == 0) {\r
+ Row++;\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ if (Temp != 0) {\r
+ Temp--;\r
+ }\r
+ }\r
+\r
+ Temp = 0;\r
+ Row = OriginalRow;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+\r
+ if (OptionString != NULL) {\r
+ if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
+ //\r
+ // If leading spaces on OptionString - remove the spaces\r
+ //\r
+ for (Index = 0; OptionString[Index] == L' '; Index++) {\r
+ MenuOption->OptCol++;\r
+ }\r
+\r
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+ OptionString[Count] = OptionString[Index];\r
+ Count++;\r
+ }\r
+\r
+ OptionString[Count] = CHAR_NULL;\r
+ }\r
+\r
+ //\r
+ // If Question request refresh, register the op-code\r
+ //\r
+ if (Statement->RefreshInterval != 0) {\r
+ //\r
+ // Menu will be refreshed at minimal interval of all Questions\r
+ // which have refresh request\r
+ //\r
+ if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {\r
+ MinRefreshInterval = Statement->RefreshInterval;\r
+ }\r
+\r
+ if (gMenuRefreshHead == NULL) {\r
+ MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
+ ASSERT (MenuRefreshEntry != NULL);\r
+ MenuRefreshEntry->MenuOption = MenuOption;\r
+ MenuRefreshEntry->Selection = Selection;\r
+ MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;\r
+ MenuRefreshEntry->CurrentRow = MenuOption->Row;\r
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;\r
+ gMenuRefreshHead = MenuRefreshEntry;\r
+ } else {\r
+ //\r
+ // Advance to the last entry\r
+ //\r
+ for (MenuRefreshEntry = gMenuRefreshHead;\r
+ MenuRefreshEntry->Next != NULL;\r
+ MenuRefreshEntry = MenuRefreshEntry->Next\r
+ )\r
+ ;\r
+ MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
+ ASSERT (MenuRefreshEntry->Next != NULL);\r
+ MenuRefreshEntry = MenuRefreshEntry->Next;\r
+ MenuRefreshEntry->MenuOption = MenuOption;\r
+ MenuRefreshEntry->Selection = Selection;\r
+ MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;\r
+ MenuRefreshEntry->CurrentRow = MenuOption->Row;\r
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;\r
+ }\r
+ }\r
+\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ OriginalRow = Row;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp2 == 0) && (Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&OptionString[Index])) {\r
+ if (Temp2 == 0) {\r
+ Row++;\r
+ //\r
+ // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+ // some testing to ensure we are keeping this in-sync.\r
+ //\r
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+ //\r
+ if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+ MenuOption->Skip++;\r
+ }\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ if (Temp2 != 0) {\r
+ Temp2--;\r
+ }\r
+ }\r
+\r
+ Temp2 = 0;\r
+ Row = OriginalRow;\r
+\r
+ gBS->FreePool (OptionString);\r
+ }\r
+ //\r
+ // If this is a text op with secondary text information\r
+ //\r
+ if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
+ StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle);\r
+\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ OriginalRow = Row;\r
+\r
+ for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp == 0) && (Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&StringPtr[Index])) {\r
+ if (Temp2 == 0) {\r
+ Row++;\r
+ //\r
+ // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+ // some testing to ensure we are keeping this in-sync.\r
+ //\r
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+ //\r
+ if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+ MenuOption->Skip++;\r
+ }\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ if (Temp2 != 0) {\r
+ Temp2--;\r
+ }\r
+ }\r
+\r
+ Row = OriginalRow;\r
+ gBS->FreePool (StringPtr);\r
+ }\r
+\r
+ //\r
+ // Need to handle the bottom of the display\r
+ //\r
+ if (MenuOption->Skip > 1) {\r
+ Row += MenuOption->Skip - SkipValue;\r
+ SkipValue = 0;\r
+ } else {\r
+ Row += MenuOption->Skip;\r
+ }\r
+\r
+ if (Row > BottomRow) {\r
+ if (!ValueIsScroll (FALSE, Link)) {\r
+ gDownArrow = TRUE;\r
+ }\r
+\r
+ Row = BottomRow + 1;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
+ gUpArrow = TRUE;\r
+ }\r
+\r
+ if (gUpArrow) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
+ PrintAt (\r
+ LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
+ TopRow - SCROLL_ARROW_HEIGHT,\r
+ L"%c",\r
+ ARROW_UP\r
+ );\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+ }\r
+\r
+ if (gDownArrow) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
+ PrintAt (\r
+ LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
+ BottomRow + SCROLL_ARROW_HEIGHT,\r
+ L"%c",\r
+ ARROW_DOWN\r
+ );\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+ }\r
+\r
+ MenuOption = NULL;\r
+ }\r
+ break;\r
+\r
+ case CfRefreshHighLight:\r
+ //\r
+ // MenuOption: Last menu option that need to remove hilight\r
+ // MenuOption is set to NULL in Repaint\r
+ // NewPos: Current menu option that need to hilight\r
+ //\r
+ ControlFlag = CfUpdateHelpString;\r
+\r
+ //\r
+ // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily\r
+ // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.\r
+ //\r
+ SavedValue = Repaint;\r
+ Repaint = FALSE;\r
+\r
+ if (Selection->QuestionId != 0) {\r
+ NewPos = Menu.ForwardLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+ while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) {\r
+ NewPos = NewPos->ForwardLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ }\r
+ if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {\r
+ //\r
+ // Target Question found, find its MenuOption\r
+ //\r
+ Link = TopOfScreen;\r
+\r
+ for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ Index += SavedMenuOption->Skip;\r
+ Link = Link->ForwardLink;\r
+ }\r
+\r
+ if (Link != NewPos || Index > BottomRow) {\r
+ //\r
+ // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page\r
+ //\r
+ Link = NewPos;\r
+ for (Index = TopRow; Index <= BottomRow; ) {\r
+ Link = Link->BackLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ Index += SavedMenuOption->Skip;\r
+ }\r
+ TopOfScreen = Link->ForwardLink;\r
+\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+ ControlFlag = CfRepaint;\r
+ break;\r
+ }\r
+ } else {\r
+ //\r
+ // Target Question not found, highlight the default menu option\r
+ //\r
+ NewPos = TopOfScreen;\r
+ }\r
+\r
+ Selection->QuestionId = 0;\r
+ }\r
+\r
+ if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
+ if (MenuOption != NULL) {\r
+ //\r
+ // Remove highlight on last Menu Option\r
+ //\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+ if (OptionString != NULL) {\r
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
+ (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
+ ) {\r
+ //\r
+ // If leading spaces on OptionString - remove the spaces\r
+ //\r
+ for (Index = 0; OptionString[Index] == L' '; Index++)\r
+ ;\r
+\r
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+ OptionString[Count] = OptionString[Index];\r
+ Count++;\r
+ }\r
+\r
+ OptionString[Count] = CHAR_NULL;\r
+ }\r
+\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ OriginalRow = MenuOption->Row;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&OptionString[Index])) {\r
+ MenuOption->Row++;\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+\r
+ gBS->FreePool (OptionString);\r
+ } else {\r
+ if (NewLine) {\r
+ if (MenuOption->GrayOut) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
+ } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);\r
+ }\r
+\r
+ OriginalRow = MenuOption->Row;\r
+ Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);\r
+\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+ PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&MenuOption->Description[Index])) {\r
+ MenuOption->Row++;\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // This is only possible if we entered this page and the first menu option is\r
+ // a "non-menu" item. In that case, force it UiDown\r
+ //\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ if (!IsSelectable (MenuOption)) {\r
+ ASSERT (ScreenOperation == UiNoOperation);\r
+ ScreenOperation = UiDown;\r
+ ControlFlag = CfScreenOperation;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // This is the current selected statement\r
+ //\r
+ Statement = MenuOption->ThisTag;\r
+ Selection->Statement = Statement;\r
+\r
+ //\r
+ // Set reverse attribute\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
+\r
+ //\r
+ // Assuming that we have a refresh linked-list created, lets annotate the\r
+ // appropriate entry that we are highlighting with its new attribute. Just prior to this\r
+ // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh\r
+ //\r
+ if (gMenuRefreshHead != NULL) {\r
+ for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {\r
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;\r
+ if (MenuRefreshEntry->MenuOption == MenuOption) {\r
+ MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;\r
+ }\r
+ }\r
+ }\r
+\r
+ ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
+ if (OptionString != NULL) {\r
+ if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
+ //\r
+ // If leading spaces on OptionString - remove the spaces\r
+ //\r
+ for (Index = 0; OptionString[Index] == L' '; Index++)\r
+ ;\r
+\r
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+ OptionString[Count] = OptionString[Index];\r
+ Count++;\r
+ }\r
+\r
+ OptionString[Count] = CHAR_NULL;\r
+ }\r
+ Width = (UINT16) gOptionBlockWidth;\r
+\r
+ OriginalRow = MenuOption->Row;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {\r
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&OptionString[Index])) {\r
+ MenuOption->Row++;\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+\r
+ gBS->FreePool (OptionString);\r
+ } else {\r
+ if (NewLine) {\r
+ OriginalRow = MenuOption->Row;\r
+\r
+ Width = GetWidth (Statement, MenuOption->Handle);\r
+\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {\r
+ if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {\r
+ PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&MenuOption->Description[Index])) {\r
+ MenuOption->Row++;\r
+ }\r
+\r
+ gBS->FreePool (OutputString);\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+\r
+ }\r
+ }\r
+\r
+ if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||\r
+ ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||\r
+ (ScreenOperation == UiNoOperation)\r
+ ) {\r
+ UpdateKeyHelp (MenuOption, FALSE);\r
+ }\r
+ //\r
+ // Clear reverse attribute\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);\r
+ }\r
+ //\r
+ // Repaint flag will be used when process CfUpdateHelpString, so restore its value\r
+ // if we didn't break halfway when process CfRefreshHighLight.\r
+ //\r
+ Repaint = SavedValue;\r
+ break;\r
+\r
+ case CfUpdateHelpString:\r
+ ControlFlag = CfPrepareToReadKey;\r
+\r
+ if ((Repaint || NewLine) && (gClassOfVfr != EFI_GENERAL_APPLICATION_SUBCLASS)) {\r
+ //\r
+ // Don't print anything if it is a NULL help token\r
+ //\r
+ if (MenuOption->ThisTag->Help == 0) {\r
+ StringPtr = L"\0";\r
+ } else {\r
+ StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
+ }\r
+\r
+ ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);\r
+\r
+ for (Index = 0; Index < BottomRow - TopRow; Index++) {\r
+ //\r
+ // Pad String with spaces to simulate a clearing of the previous line\r
+ //\r
+ for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {\r
+ StrCat (&FormattedString[Index * gHelpBlockWidth * 2], L" ");\r
+ }\r
+\r
+ PrintStringAt (\r
+ LocalScreen.RightColumn - gHelpBlockWidth,\r
+ Index + TopRow,\r
+ &FormattedString[Index * gHelpBlockWidth * 2]\r
+ );\r
+ }\r
+ }\r
+ //\r
+ // Reset this flag every time we finish using it.\r
+ //\r
+ Repaint = FALSE;\r
+ NewLine = FALSE;\r
+ break;\r
+\r
+ case CfPrepareToReadKey:\r
+ ControlFlag = CfReadKey;\r
+ ScreenOperation = UiNoOperation;\r
+ break;\r
+\r
+ case CfReadKey:\r
+ ControlFlag = CfScreenOperation;\r
+\r
+ //\r
+ // Wait for user's selection\r
+ //\r
+ do {\r
+ Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);\r
+ } while (Status == EFI_TIMEOUT);\r
+\r
+ if (Status == EFI_TIMEOUT) {\r
+ Key.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
+ } else {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ //\r
+ // if we encounter error, continue to read another key in.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ ControlFlag = CfReadKey;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) {\r
+ //\r
+ // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset\r
+ //\r
+ break;\r
+ }\r
+\r
+ switch (Key.UnicodeChar) {\r
+ case CHAR_CARRIAGE_RETURN:\r
+ ScreenOperation = UiSelect;\r
+ gDirection = 0;\r
+ break;\r
+\r
+ //\r
+ // We will push the adjustment of these numeric values directly to the input handler\r
+ // NOTE: we won't handle manual input numeric\r
+ //\r
+ case '+':\r
+ case '-':\r
+ Statement = MenuOption->ThisTag;\r
+ if ((Statement->Operand == EFI_IFR_DATE_OP)\r
+ || (Statement->Operand == EFI_IFR_TIME_OP)\r
+ || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))\r
+ ){\r
+ if (Key.UnicodeChar == '+') {\r
+ gDirection = SCAN_RIGHT;\r
+ } else {\r
+ gDirection = SCAN_LEFT;\r
+ }\r
+ Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
+ SafeFreePool (OptionString);\r
+ }\r
+ break;\r
+\r
+ case '^':\r
+ ScreenOperation = UiUp;\r
+ break;\r
+\r
+ case 'V':\r
+ case 'v':\r
+ ScreenOperation = UiDown;\r
+ break;\r
+\r
+ case ' ':\r
+ if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {\r
+ if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) {\r
+ ScreenOperation = UiSelect;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CHAR_NULL:\r
+ if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||\r
+ ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||\r
+ ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||\r
+ ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))\r
+ ) {\r
+ //\r
+ // If the function key has been disabled, just ignore the key.\r
+ //\r
+ } else {\r
+ for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {\r
+ if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
+ if (Key.ScanCode == SCAN_F9) {\r
+ //\r
+ // Reset to standard default\r
+ //\r
+ DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;\r
+ }\r
+ ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CfScreenOperation:\r
+ if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {\r
+ //\r
+ // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset\r
+ // ignore the selection and go back to reading keys.\r
+ //\r
+ if (IsListEmpty (&Menu)) {\r
+ ControlFlag = CfReadKey;\r
+ break;\r
+ }\r
+ //\r
+ // if there is nothing logical to place a cursor on, just move on to wait for a key.\r
+ //\r
+ for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ if (IsSelectable (NextMenuOption)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Link == &Menu) {\r
+ ControlFlag = CfPrepareToReadKey;\r
+ break;\r
+ }\r
+ } else if (ScreenOperation == UiReset) {\r
+ //\r
+ // Press ESC to exit FormSet\r
+ //\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ Selection->Statement = NULL;\r
+ }\r
+\r
+ for (Index = 0;\r
+ Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);\r
+ Index++\r
+ ) {\r
+ if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
+ ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CfUiPrevious:\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ if (IsListEmpty (&gMenuList)) {\r
+ Selection->Action = UI_ACTION_NONE;\r
+ if (IsListEmpty (&Menu)) {\r
+ ControlFlag = CfReadKey;\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Remove the Cached page entry\r
+ //\r
+ UiRemoveMenuListEntry (Selection);\r
+\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+ Selection->Statement = NULL;\r
+ break;\r
+\r
+ case CfUiSelect:\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ Statement = MenuOption->ThisTag;\r
+ if ((Statement->Operand == EFI_IFR_TEXT_OP) ||\r
+ (Statement->Operand == EFI_IFR_DATE_OP) ||\r
+ (Statement->Operand == EFI_IFR_TIME_OP) ||\r
+ (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Keep highlight on current MenuOption\r
+ //\r
+ Selection->QuestionId = Statement->QuestionId;\r
+\r
+ switch (Statement->Operand) {\r
+ case EFI_IFR_REF_OP:\r
+ if (Statement->RefDevicePath != 0) {\r
+ //\r
+ // Goto another Hii Package list\r
+ //\r
+ ControlFlag = CfUiReset;\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+\r
+ StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle);\r
+ if (StringPtr == NULL) {\r
+ //\r
+ // No device path string not found, exit\r
+ //\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ Selection->Statement = NULL;\r
+ break;\r
+ }\r
+ BufferSize = StrLen (StringPtr) / 2;\r
+ DevicePath = AllocatePool (BufferSize);\r
+\r
+ HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, StringPtr);\r
+ Selection->Handle = HiiLibDevicePathToHiiHandle (DevicePath);\r
+ if (Selection->Handle == NULL) {\r
+ //\r
+ // If target Hii Handle not found, exit\r
+ //\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ Selection->Statement = NULL;\r
+ break;\r
+ }\r
+\r
+ gBS->FreePool (StringPtr);\r
+ gBS->FreePool (DevicePath);\r
+\r
+ CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));\r
+ Selection->FormId = Statement->RefFormId;\r
+ Selection->QuestionId = Statement->RefQuestionId;\r
+ } else if (!CompareGuid (&Statement->RefFormSetId, &gZeroGuid)) {\r
+ //\r
+ // Goto another Formset, check for uncommitted data\r
+ //\r
+ ControlFlag = CfUiReset;\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+\r
+ CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID));\r
+ Selection->FormId = Statement->RefFormId;\r
+ Selection->QuestionId = Statement->RefQuestionId;\r
+ } else if (Statement->RefFormId != 0) {\r
+ //\r
+ // Goto another form inside this formset,\r
+ //\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+\r
+ //\r
+ // Link current form so that we can always go back when someone hits the UiPrevious\r
+ //\r
+ UiAddMenuListEntry (Selection);\r
+\r
+ Selection->FormId = Statement->RefFormId;\r
+ Selection->QuestionId = Statement->RefQuestionId;\r
+ } else if (Statement->RefQuestionId != 0) {\r
+ //\r
+ // Goto another Question\r
+ //\r
+ Selection->QuestionId = Statement->RefQuestionId;\r
+\r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+ } else {\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ACTION_OP:\r
+ //\r
+ // Process the Config string <ConfigResp>\r
+ //\r
+ Status = ProcessQuestionConfig (Selection, Statement);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The action button may change some Question value, so refresh the form\r
+ //\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+ break;\r
+\r
+ case EFI_IFR_RESET_BUTTON_OP:\r
+ //\r
+ // Reset Question to default value specified by DefaultId\r
+ //\r
+ ControlFlag = CfUiDefault;\r
+ DefaultId = Statement->DefaultId;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
+ //\r
+ UpdateKeyHelp (MenuOption, TRUE);\r
+ Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+ break;\r
+ }\r
+\r
+ if (OptionString != NULL) {\r
+ PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);\r
+ gBS->FreePool (OptionString);\r
+ }\r
+\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CfUiReset:\r
+ //\r
+ // We are going to leave current FormSet, so check uncommited data in this FormSet\r
+ //\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {\r
+ //\r
+ // There is no parent menu for FrontPage\r
+ //\r
+ Selection->Action = UI_ACTION_NONE;\r
+ Selection->Statement = MenuOption->ThisTag;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // If NV flag is up, prompt user\r
+ //\r
+ if (gNvUpdateRequired) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+\r
+ YesResponse = gYesResponse[0];\r
+ NoResponse = gNoResponse[0];\r
+\r
+ do {\r
+ CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);\r
+ } while\r
+ (\r
+ (Key.ScanCode != SCAN_ESC) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
+ );\r
+\r
+ //\r
+ // If the user hits the YesResponse key\r
+ //\r
+ if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
+ } else {\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+\r
+ Selection->Action = UI_ACTION_NONE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ UiFreeMenuList ();\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ return EFI_SUCCESS;\r
+\r
+ case CfUiLeft:\r
+ ControlFlag = CfCheckSelection;\r
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
+ if (MenuOption->Sequence != 0) {\r
+ //\r
+ // In the middle or tail of the Date/Time op-code set, go left.\r
+ //\r
+ NewPos = NewPos->BackLink;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CfUiRight:\r
+ ControlFlag = CfCheckSelection;\r
+ if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
+ if (MenuOption->Sequence != 2) {\r
+ //\r
+ // In the middle or tail of the Date/Time op-code set, go left.\r
+ //\r
+ NewPos = NewPos->ForwardLink;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CfUiUp:\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ SavedListEntry = TopOfScreen;\r
+\r
+ if (NewPos->BackLink != &Menu) {\r
+ NewLine = TRUE;\r
+ //\r
+ // Adjust Date/Time position before we advance forward.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+ //\r
+ // Caution that we have already rewind to the top, don't go backward in this situation.\r
+ //\r
+ if (NewPos->BackLink != &Menu) {\r
+ NewPos = NewPos->BackLink;\r
+ }\r
+\r
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ DistanceValue = PreviousMenuOption->Skip;\r
+\r
+ //\r
+ // Since the behavior of hitting the up arrow on a Date/Time op-code is intended\r
+ // to be one that back to the previous set of op-codes, we need to advance to the sencond\r
+ // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
+ // checking can be done.\r
+ //\r
+ DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos);\r
+\r
+ //\r
+ // Check the previous menu entry to see if it was a zero-length advance. If it was,\r
+ // don't worry about a redraw.\r
+ //\r
+ if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {\r
+ Repaint = TRUE;\r
+ TopOfScreen = NewPos;\r
+ }\r
+\r
+ Difference = MoveToNextStatement (TRUE, &NewPos);\r
+ if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) {\r
+ if (Difference > 0) {\r
+ //\r
+ // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
+ //\r
+ TopOfScreen = NewPos;\r
+ Repaint = TRUE;\r
+ }\r
+ }\r
+ if (Difference < 0) {\r
+ //\r
+ // We want to goto previous MenuOption, but finally we go down.\r
+ // it means that we hit the begining MenuOption that can be focused\r
+ // so we simply scroll to the top\r
+ //\r
+ if (SavedListEntry != Menu.ForwardLink) {\r
+ TopOfScreen = Menu.ForwardLink;\r
+ Repaint = TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+\r
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+ } else {\r
+ SavedMenuOption = MenuOption;\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ if (!IsSelectable (MenuOption)) {\r
+ //\r
+ // If we are at the end of the list and sitting on a text op, we need to more forward\r
+ //\r
+ ScreenOperation = UiDown;\r
+ ControlFlag = CfScreenOperation;\r
+ break;\r
+ }\r
+\r
+ MenuOption = SavedMenuOption;\r
+ }\r
+ break;\r
+\r
+ case CfUiPageUp:\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ if (NewPos->BackLink == &Menu) {\r
+ NewLine = FALSE;\r
+ Repaint = FALSE;\r
+ break;\r
+ }\r
+\r
+ NewLine = TRUE;\r
+ Repaint = TRUE;\r
+ Link = TopOfScreen;\r
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ Index = BottomRow;\r
+ while ((Index >= TopRow) && (Link->BackLink != &Menu)) {\r
+ Index = Index - PreviousMenuOption->Skip;\r
+ Link = Link->BackLink;\r
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ }\r
+\r
+ TopOfScreen = Link;\r
+ Difference = MoveToNextStatement (TRUE, &Link);\r
+ if (Difference > 0) {\r
+ //\r
+ // The focus MenuOption is above the TopOfScreen\r
+ //\r
+ TopOfScreen = Link;\r
+ } else if (Difference < 0) {\r
+ //\r
+ // This happens when there is no MenuOption can be focused from\r
+ // Current MenuOption to the first MenuOption\r
+ //\r
+ TopOfScreen = Menu.ForwardLink;\r
+ }\r
+ Index += Difference;\r
+ if (Index < TopRow) {\r
+ MenuOption = NULL;\r
+ }\r
+\r
+ if (NewPos == Link) {\r
+ Repaint = FALSE;\r
+ NewLine = FALSE;\r
+ } else {\r
+ NewPos = Link;\r
+ }\r
+\r
+ //\r
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+ // Don't do this when we are already in the first page.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+\r
+ case CfUiPageDown:\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ if (NewPos->ForwardLink == &Menu) {\r
+ NewLine = FALSE;\r
+ Repaint = FALSE;\r
+ break;\r
+ }\r
+\r
+ NewLine = TRUE;\r
+ Repaint = TRUE;\r
+ Link = TopOfScreen;\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ Index = TopRow;\r
+ while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) {\r
+ Index = Index + NextMenuOption->Skip;\r
+ Link = Link->ForwardLink;\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ }\r
+\r
+ Index += MoveToNextStatement (FALSE, &Link);\r
+ if (Index > BottomRow) {\r
+ //\r
+ // There are more MenuOption needing scrolling\r
+ //\r
+ TopOfScreen = Link;\r
+ MenuOption = NULL;\r
+ }\r
+ if (NewPos == Link && Index <= BottomRow) {\r
+ //\r
+ // Finally we know that NewPos is the last MenuOption can be focused.\r
+ //\r
+ NewLine = FALSE;\r
+ Repaint = FALSE;\r
+ } else {\r
+ NewPos = Link;\r
+ }\r
+\r
+ //\r
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+ // Don't do this when we are already in the last page.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+\r
+ case CfUiDown:\r
+ ControlFlag = CfCheckSelection;\r
+ //\r
+ // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
+ // to be one that progresses to the next set of op-codes, we need to advance to the last\r
+ // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
+ // checking can be done. The only other logic we need to introduce is that if a Date/Time\r
+ // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
+ // the Date/Time op-code.\r
+ //\r
+ SavedListEntry = NewPos;\r
+ DistanceValue = AdjustDateAndTimePosition (FALSE, &NewPos);\r
+\r
+ if (NewPos->ForwardLink != &Menu) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ NewLine = TRUE;\r
+ NewPos = NewPos->ForwardLink;\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+ DistanceValue += NextMenuOption->Skip;\r
+ DistanceValue += MoveToNextStatement (FALSE, &NewPos);\r
+ //\r
+ // An option might be multi-line, so we need to reflect that data in the overall skip value\r
+ //\r
+ UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue);\r
+\r
+ Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
+ if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
+ (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||\r
+ NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
+ ) {\r
+ Temp ++;\r
+ }\r
+\r
+ //\r
+ // If we are going to scroll, update TopOfScreen\r
+ //\r
+ if (Temp > BottomRow) {\r
+ do {\r
+ //\r
+ // Is the current top of screen a zero-advance op-code?\r
+ // If so, keep moving forward till we hit a >0 advance op-code\r
+ //\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+\r
+ //\r
+ // If bottom op-code is more than one line or top op-code is more than one line\r
+ //\r
+ if ((DistanceValue > 1) || (MenuOption->Skip > 1)) {\r
+ //\r
+ // Is the bottom op-code greater than or equal in size to the top op-code?\r
+ //\r
+ if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {\r
+ //\r
+ // Skip the top op-code\r
+ //\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);\r
+\r
+ OldSkipValue = Difference;\r
+\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+\r
+ //\r
+ // If we have a remainder, skip that many more op-codes until we drain the remainder\r
+ //\r
+ for (;\r
+ Difference >= (INTN) SavedMenuOption->Skip;\r
+ Difference = Difference - (INTN) SavedMenuOption->Skip\r
+ ) {\r
+ //\r
+ // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
+ //\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+ if (Difference < (INTN) SavedMenuOption->Skip) {\r
+ Difference = SavedMenuOption->Skip - Difference - 1;\r
+ break;\r
+ } else {\r
+ if (Difference == (INTN) SavedMenuOption->Skip) {\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+ Difference = SavedMenuOption->Skip - Difference;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Since we will act on this op-code in the next routine, and increment the\r
+ // SkipValue, set the skips to one less than what is required.\r
+ //\r
+ SkipValue = Difference - 1;\r
+\r
+ } else {\r
+ //\r
+ // Since we will act on this op-code in the next routine, and increment the\r
+ // SkipValue, set the skips to one less than what is required.\r
+ //\r
+ SkipValue = OldSkipValue + (Temp - BottomRow) - 1;\r
+ }\r
+ } else {\r
+ if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ break;\r
+ } else {\r
+ SkipValue = OldSkipValue;\r
+ }\r
+ }\r
+ //\r
+ // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
+ // Let's set a skip flag to smoothly scroll the top of the screen.\r
+ //\r
+ if (SavedMenuOption->Skip > 1) {\r
+ if (SavedMenuOption == NextMenuOption) {\r
+ SkipValue = 0;\r
+ } else {\r
+ SkipValue++;\r
+ }\r
+ } else {\r
+ SkipValue = 0;\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ }\r
+ } while (SavedMenuOption->Skip == 0);\r
+\r
+ Repaint = TRUE;\r
+ OldSkipValue = SkipValue;\r
+ }\r
+\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+\r
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+\r
+ } else {\r
+ SavedMenuOption = MenuOption;\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ if (!IsSelectable (MenuOption)) {\r
+ //\r
+ // If we are at the end of the list and sitting on a text op, we need to more forward\r
+ //\r
+ ScreenOperation = UiUp;\r
+ ControlFlag = CfScreenOperation;\r
+ break;\r
+ }\r
+\r
+ MenuOption = SavedMenuOption;\r
+ //\r
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ }\r
+ break;\r
+\r
+ case CfUiSave:\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ //\r
+ // Submit the form\r
+ //\r
+ Status = SubmitForm (Selection->FormSet, Selection->Form);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+ UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
+ } else {\r
+ do {\r
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveFailed, gPressEnter, gEmptyString);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+ }\r
+ break;\r
+\r
+ case CfUiDefault:\r
+ ControlFlag = CfCheckSelection;\r
+\r
+ Status = ExtractFormDefault (Selection->FormSet, Selection->Form, DefaultId);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+\r
+ //\r
+ // Show NV update flag on status bar\r
+ //\r
+ gNvUpdateRequired = TRUE;\r
+ }\r
+ break;\r
+\r
+ case CfUiNoOperation:\r
+ ControlFlag = CfCheckSelection;\r
+ break;\r
+\r
+ case CfExit:\r
+ UiFreeRefreshList ();\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+ gST->ConOut->OutputString (gST->ConOut, L"\n");\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+}\r
-/** @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\r
+Private structure, MACRO and function definitions for User Interface related functionalities.\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _UI_H_\r
+#define _UI_H_\r
+\r
+#include "Setup.h"\r
+\r
+//\r
+// Globals\r
+//\r
+#define REGULAR_NUMERIC 0\r
+#define TIME_NUMERIC 1\r
+#define DATE_NUMERIC 2\r
+\r
+#define SUBTITLE_INDENT 2\r
+\r
+typedef enum {\r
+ UiNoOperation,\r
+ UiDefault,\r
+ UiSelect,\r
+ UiUp,\r
+ UiDown,\r
+ UiLeft,\r
+ UiRight,\r
+ UiReset,\r
+ UiSave,\r
+ UiPrevious,\r
+ UiPageUp,\r
+ UiPageDown,\r
+ UiMaxOperation\r
+} UI_SCREEN_OPERATION;\r
+\r
+typedef enum {\r
+ CfInitialization,\r
+ CfCheckSelection,\r
+ CfRepaint,\r
+ CfRefreshHighLight,\r
+ CfUpdateHelpString,\r
+ CfPrepareToReadKey,\r
+ CfReadKey,\r
+ CfScreenOperation,\r
+ CfUiPrevious,\r
+ CfUiSelect,\r
+ CfUiReset,\r
+ CfUiLeft,\r
+ CfUiRight,\r
+ CfUiUp,\r
+ CfUiPageUp,\r
+ CfUiPageDown,\r
+ CfUiDown,\r
+ CfUiSave,\r
+ CfUiDefault,\r
+ CfUiNoOperation,\r
+ CfExit,\r
+ CfMaxControlFlag\r
+} UI_CONTROL_FLAG;\r
+\r
+#define UI_ACTION_NONE 0\r
+#define UI_ACTION_REFRESH_FORM 1\r
+#define UI_ACTION_REFRESH_FORMSET 2\r
+#define UI_ACTION_EXIT 3\r
+\r
+typedef struct {\r
+ EFI_HII_HANDLE Handle;\r
+\r
+ //\r
+ // Target formset/form/Question information\r
+ //\r
+ EFI_GUID FormSetGuid;\r
+ UINT16 FormId;\r
+ UINT16 QuestionId;\r
+\r
+ UINTN TopRow;\r
+ UINTN BottomRow;\r
+ UINTN PromptCol;\r
+ UINTN OptionCol;\r
+ UINTN CurrentRow;\r
+\r
+ //\r
+ // Ation for Browser to taken:\r
+ // UI_ACTION_NONE - navigation inside a form\r
+ // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form\r
+ // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary\r
+ //\r
+ UINTN Action;\r
+\r
+ //\r
+ // Current selected fomset/form/Question\r
+ //\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+ FORM_BROWSER_FORM *Form;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+} UI_MENU_SELECTION;\r
+\r
+#define UI_MENU_OPTION_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'm')\r
+#define UI_MENU_LIST_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'l')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_HII_HANDLE Handle;\r
+ FORM_BROWSER_STATEMENT *ThisTag;\r
+ UINT16 EntryNumber;\r
+\r
+ UINTN Row;\r
+ UINTN Col;\r
+ UINTN OptCol;\r
+ CHAR16 *Description;\r
+ UINTN Skip; // Number of lines\r
+\r
+ //\r
+ // Display item sequence for date/time\r
+ // Date: Month/Day/Year\r
+ // Sequence: 0 1 2\r
+ //\r
+ // Time: Hour : Minute : Second\r
+ // Sequence: 0 1 2\r
+ //\r
+ //\r
+ UINTN Sequence;\r
+\r
+ BOOLEAN GrayOut;\r
+ BOOLEAN ReadOnly;\r
+} UI_MENU_OPTION;\r
+\r
+#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY MenuLink;\r
+\r
+ UINT16 FormId;\r
+ UINT16 QuestionId;\r
+} UI_MENU_LIST;\r
+\r
+typedef struct _MENU_REFRESH_ENTRY {\r
+ struct _MENU_REFRESH_ENTRY *Next;\r
+ UI_MENU_OPTION *MenuOption; // Describes the entry needing an update\r
+ UI_MENU_SELECTION *Selection;\r
+ UINTN CurrentColumn;\r
+ UINTN CurrentRow;\r
+ UINTN CurrentAttribute;\r
+} MENU_REFRESH_ENTRY;\r
+\r
+typedef struct {\r
+ UINT16 ScanCode;\r
+ UI_SCREEN_OPERATION ScreenOperation;\r
+} SCAN_CODE_TO_SCREEN_OPERATION;\r
+\r
+typedef struct {\r
+ UI_SCREEN_OPERATION ScreenOperation;\r
+ UI_CONTROL_FLAG ControlFlag;\r
+} SCREEN_OPERATION_T0_CONTROL_FLAG;\r
+\r
+\r
+extern LIST_ENTRY gMenuList;\r
+extern MENU_REFRESH_ENTRY *gMenuRefreshHead;\r
+extern UI_MENU_SELECTION *gCurrentSelection;\r
+\r
+//\r
+// Global Functions\r
+//\r
+/**\r
+ Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenu (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ Initialize Menu option list.\r
+\r
+**/\r
+VOID\r
+UiInitMenuList (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ Remove a Menu in list, and return FormId/QuestionId for previous Menu.\r
+\r
+ @param Selection Menu selection.\r
+\r
+**/\r
+VOID\r
+UiRemoveMenuListEntry (\r
+ OUT UI_MENU_SELECTION *Selection\r
+ )\r
+;\r
+\r
+/**\r
+ Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ Add one menu entry to the linked lst\r
+\r
+ @param Selection Menu selection.\r
+\r
+**/\r
+VOID\r
+UiAddMenuListEntry (\r
+ IN UI_MENU_SELECTION *Selection\r
+ )\r
+;\r
+\r
+/**\r
+ Free Menu option linked list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenu (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ Add one menu option by specified description and context.\r
+\r
+ @param String String description for this option.\r
+ @param Handle Hii handle for the package list.\r
+ @param Statement Statement of this Menu Option.\r
+ @param NumberOfLines Display lines for this Menu Option.\r
+ @param MenuItemCount The index for this Option in the Menu.\r
+\r
+**/\r
+VOID\r
+UiAddMenuOption (\r
+ IN CHAR16 *String,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN FORM_BROWSER_STATEMENT *Statement,\r
+ IN UINT16 NumberOfLines,\r
+ IN UINT16 MenuItemCount\r
+ )\r
+;\r
+\r
+/**\r
+ Display menu and wait for user to select one menu option, then return it.\r
+ If AutoBoot is enabled, then if user doesn't select any option,\r
+ after period of time, it will automatically return the first menu option.\r
+\r
+ @param Selection Menu selection.\r
+\r
+ @return Return the pointer of the menu which selected,\r
+ @return otherwise return NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+UiDisplayMenu (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+;\r
+\r
+/**\r
+ Free up the resource allocated for all strings required\r
+ by Setup Browser.\r
+\r
+**/\r
+VOID\r
+FreeBrowserStrings (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ The worker function that send the displays to the screen. On output,\r
+ the selection made by user is returned.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+\r
+ @retval EFI_SUCCESS The page is displayed successfully.\r
+ @return Other value if the page failed to be diplayed.\r
+\r
+**/\r
+EFI_STATUS\r
+SetupBrowser (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+;\r
+\r
+/**\r
+ VSPrint worker function that prints a Value as a decimal number in Buffer.\r
+\r
+ @param Buffer Location to place ascii decimal number string of Value.\r
+ @param Flags Flags to use in printing decimal string, see file header for\r
+ details.\r
+ @param Value Decimal value to convert to a string in Buffer.\r
+\r
+ @return Number of characters printed.\r
+\r
+**/\r
+VOID\r
+ValueToString (\r
+ IN CHAR16 *Buffer,\r
+ IN BOOLEAN Flags,\r
+ IN INT64 Value\r
+ )\r
+;\r
+\r
+/**\r
+ Set Buffer to Value for Size bytes.\r
+\r
+ @param Buffer Memory to set.\r
+ @param Size Number of bytes to set\r
+ @param Value Value of the set operation.\r
+\r
+**/\r
+VOID\r
+SetUnicodeMem (\r
+ IN VOID *Buffer,\r
+ IN UINTN Size,\r
+ IN CHAR16 Value\r
+ )\r
+;\r
+\r
+/**\r
+ Wait for a given event to fire, or for an optional timeout to expire.\r
+\r
+ @param Event The event to wait for\r
+ @param Timeout An optional timeout value in 100 ns units.\r
+ @param RefreshInterval Menu refresh interval (in seconds).\r
+\r
+ @retval EFI_SUCCESS Event fired before Timeout expired.\r
+ @retval EFI_TIME_OUT Timout expired before Event fired.\r
+\r
+**/\r
+EFI_STATUS\r
+UiWaitForSingleEvent (\r
+ IN EFI_EVENT Event,\r
+ IN UINT64 Timeout, OPTIONAL\r
+ IN UINT8 RefreshInterval OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param ArrayOfStrings The array of string to be printed.\r
+ @param ... A series of text strings that displayed in the pop-up.\r
+\r
+**/\r
+VOID\r
+CreatePopUp (\r
+ IN UINTN ScreenWidth,\r
+ IN UINTN NumberOfLines,\r
+ IN CHAR16 *ArrayOfStrings,\r
+ ...\r
+ )\r
+;\r
+\r
+/**\r
+ Get string or password input from user.\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+ @param Prompt The prompt string shown on popup window.\r
+ @param StringPtr Destination for use input string.\r
+\r
+ @retval EFI_SUCCESS If string input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+ReadString (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN CHAR16 *Prompt,\r
+ OUT CHAR16 *StringPtr\r
+ )\r
+;\r
+\r
+/**\r
+ Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
+\r
+ @param Selection Pointer to current selection.\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If Option input is processed successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetSelectionInputPopUp (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+;\r
+\r
+/**\r
+ This routine reads a numeric value from the user input.\r
+\r
+ @param Selection Pointer to current selection.\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If numerical input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetNumericInput (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+;\r
+\r
+/**\r
+ Update status bar on the bottom of menu.\r
+\r
+ @param MessageType The type of message to be shown.\r
+ @param Flags The flags in Question header.\r
+ @param State Set or clear.\r
+\r
+**/\r
+VOID\r
+UpdateStatusBar (\r
+ IN UINTN MessageType,\r
+ IN UINT8 Flags,\r
+ IN BOOLEAN State\r
+ )\r
+;\r
+\r
+/**\r
+ Process Question Config.\r
+\r
+ @param Selection The UI menu selection.\r
+ @param Question The Question to be peocessed.\r
+\r
+ @retval EFI_SUCCESS Question Config process success.\r
+ @retval Other Question Config process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessQuestionConfig (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_STATEMENT *Question\r
+ )\r
+;\r
+\r
+/**\r
+ Print Question Value according to it's storage width and display attributes.\r
+\r
+ @param Question The Question to be printed.\r
+ @param FormattedNumber Buffer for output string.\r
+ @param BufferSize The FormattedNumber buffer size in bytes.\r
+\r
+ @retval EFI_SUCCESS Print success.\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
+\r
+**/\r
+EFI_STATUS\r
+PrintFormattedNumber (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN OUT CHAR16 *FormattedNumber,\r
+ IN UINTN BufferSize\r
+ )\r
+;\r
+\r
+/**\r
+ Search an Option of a Question by its value.\r
+\r
+ @param Question The Question\r
+ @param OptionValue Value for Option to be searched.\r
+\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
+\r
+**/\r
+QUESTION_OPTION *\r
+ValueToOption (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN EFI_HII_VALUE *OptionValue\r
+ )\r
+;\r
+\r
+/**\r
+ Process a Question's Option (whether selected or un-selected).\r
+\r
+ @param Selection Pointer to UI_MENU_SELECTION.\r
+ @param MenuOption The MenuOption for this Question.\r
+ @param Selected TRUE: if Question is selected.\r
+ @param OptionString Pointer of the Option String to be displayed.\r
+\r
+ @retval EFI_SUCCESS Question Option process success.\r
+ @retval Other Question Option process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOptions (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN BOOLEAN Selected,\r
+ OUT CHAR16 **OptionString\r
+ )\r
+;\r
+\r
+/**\r
+ Process the help string: Split StringPtr to several lines of strings stored in\r
+ FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
+\r
+ @param StringPtr The entire help string.\r
+ @param FormattedString The oupput formatted string.\r
+ @param RowCount TRUE: if Question is selected.\r
+\r
+**/\r
+VOID\r
+ProcessHelpString (\r
+ IN CHAR16 *StringPtr,\r
+ OUT CHAR16 **FormattedString,\r
+ IN UINTN RowCount\r
+ )\r
+;\r
+\r
+/**\r
+ Update key's help imformation.\r
+\r
+ @param MenuOption The Menu option\r
+ @param Selected Whether or not a tag be selected\r
+\r
+**/\r
+VOID\r
+UpdateKeyHelp (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN BOOLEAN Selected\r
+ )\r
+;\r
+\r
+/**\r
+ Clear retangle with specified text attribute.\r
+\r
+ @param LeftColumn Left column of retangle.\r
+ @param RightColumn Right column of retangle.\r
+ @param TopRow Start row of retangle.\r
+ @param BottomRow End row of retangle.\r
+ @param TextAttribute The character foreground and background.\r
+\r
+**/\r
+VOID\r
+ClearLines (\r
+ UINTN LeftColumn,\r
+ UINTN RightColumn,\r
+ UINTN TopRow,\r
+ UINTN BottomRow,\r
+ UINTN TextAttribute\r
+ )\r
+;\r
+\r
+/**\r
+ Count the storage space of a Unicode string.\r
+\r
+ This function handles the Unicode string with NARROW_CHAR\r
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
+ does not count in the resultant output. If a WIDE_CHAR is \r
+ hit, then 2 Unicode character will consume an output storage\r
+ space with size of CHAR16 till a NARROW_CHAR is hit.\r
+\r
+ @param String The input string to be counted.\r
+\r
+ @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetStringWidth (\r
+ CHAR16 *String\r
+ )\r
+;\r
+\r
+/**\r
+ Will copy LineWidth amount of a string in the OutputString buffer and return the\r
+ number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+ @param InputString String description for this option.\r
+ @param LineWidth Width of the desired string to extract in CHAR16\r
+ characters\r
+ @param Index Where in InputString to start the copy process\r
+ @param OutputString Buffer to copy the string into\r
+\r
+ @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
+\r
+**/\r
+UINT16\r
+GetLineByWidth (\r
+ IN CHAR16 *InputString,\r
+ IN UINT16 LineWidth,\r
+ IN OUT UINTN *Index,\r
+ OUT CHAR16 **OutputString\r
+ )\r
+;\r
+\r
+/**\r
+ Get the supported width for a particular op-code\r
+\r
+ @param Statement The FORM_BROWSER_STATEMENT structure passed in.\r
+ @param Handle The handle in the HII database being used\r
+\r
+ @return Returns the number of CHAR16 characters that is support.\r
+\r
+**/\r
+UINT16\r
+GetWidth (\r
+ IN FORM_BROWSER_STATEMENT *Statement,\r
+ IN EFI_HII_HANDLE Handle\r
+ )\r
+;\r
+\r
+/**\r
+ Concatenate a narrow string to another string.\r
+\r
+ @param Destination The destination string.\r
+ @param Source The source string. The string to be concatenated.\r
+ to the end of Destination.\r
+\r
+**/\r
+VOID\r
+NewStrCat (\r
+ CHAR16 *Destination,\r
+ CHAR16 *Source\r
+ )\r
+;\r
+\r
+/**\r
+ Wait for a key to be pressed by user.\r
+\r
+ @param Key The key which is pressed by user.\r
+\r
+ @retval EFI_SUCCESS The function always completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForKeyStroke (\r
+ OUT EFI_INPUT_KEY *Key\r
+ )\r
+;\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+ VOID\r
+ )\r
+;\r
+\r
+/**\r
+ Push an Operand onto the Stack\r
+\r
+ @param Operand Operand to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+ IN UINT8 Operand\r
+ )\r
+;\r
+\r
+/**\r
+ Pop an Operand from the Stack\r
+\r
+ @param Operand Operand to pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+ OUT UINT8 *Operand\r
+ )\r
+;\r
+\r
+/**\r
+ Get Form given its FormId.\r
+\r
+ @param FormSet The formset which contains this form.\r
+ @param FormId Id of this form.\r
+\r
+ @retval Pointer The form.\r
+ @retval NULL Specified Form is not found in the formset.\r
+\r
+**/\r
+FORM_BROWSER_FORM *\r
+IdToForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN UINT16 FormId\r
+ )\r
+;\r
+\r
+/**\r
+ Search a Question in Formset scope using its QuestionId.\r
+\r
+ @param FormSet The formset which contains this form.\r
+ @param Form The form which contains this Question.\r
+ @param QuestionId Id of this Question.\r
+\r
+ @retval Pointer The Question.\r
+ @retval NULL Specified Question not found in the form.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+IdToQuestion (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN UINT16 QuestionId\r
+ )\r
+;\r
+\r
+/**\r
+ Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+ @param Value HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+ IN EFI_HII_VALUE *Value\r
+ )\r
+;\r
+\r
+/**\r
+ Compare two Hii value.\r
+\r
+ @param Value1 Expression value to compare on left-hand.\r
+ @param Value2 Expression value to compare on right-hand.\r
+ @param HiiHandle Only required for string compare.\r
+\r
+ @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.\r
+ @retval 0 Two operators equeal.\r
+ @return Positive value if Value1 is greater than Value2.\r
+ @retval Negative value if Value1 is less than Value2.\r
+\r
+**/\r
+INTN\r
+CompareHiiValue (\r
+ IN EFI_HII_VALUE *Value1,\r
+ IN EFI_HII_VALUE *Value2,\r
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
+ )\r
+;\r
+\r
+/**\r
+ Evaluate the result of a HII expression\r
+\r
+ @param FormSet FormSet associated with this expression.\r
+ @param Form Form associated with this expression.\r
+ @param Expression Expression to be evaluated.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfuly\r
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
+ could not be found.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateExpression (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_EXPRESSION *Expression\r
+ )\r
+;\r
+\r
+#endif // _UI_H\r