inputhandler.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,569 行 · 第 1/4 页
C
1,569 行
/*++
Copyright (c) 2004 - 2006, 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"
EFI_STATUS
ReadString (
IN UI_MENU_OPTION *MenuOption,
OUT CHAR16 *StringPtr
)
{
EFI_STATUS Status;
EFI_INPUT_KEY Key;
CHAR16 NullCharacter;
UINTN ScreenSize;
EFI_TAG *Tag;
CHAR16 Space[2];
CHAR16 KeyPad[2];
BOOLEAN SelectionComplete;
CHAR16 *TempString;
CHAR16 *BufferedString;
UINTN Index;
UINTN Count;
UINTN Start;
UINTN Top;
CHAR16 *PromptForDataString;
UINTN DimensionsWidth;
UINTN DimensionsHeight;
BOOLEAN CursorVisible;
DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
PromptForDataString = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
NullCharacter = CHAR_NULL;
ScreenSize = GetStringWidth (PromptForDataString) / 2;
Tag = MenuOption->ThisTag;
Space[0] = L' ';
Space[1] = CHAR_NULL;
SelectionComplete = FALSE;
TempString = EfiLibAllocateZeroPool (MenuOption->ThisTag->Maximum * 2);
ASSERT (TempString);
if (ScreenSize < (Tag->Maximum / (UINTN) 2)) {
ScreenSize = Tag->Maximum / 2;
}
if ((ScreenSize + 2) > DimensionsWidth) {
ScreenSize = DimensionsWidth - 2;
}
BufferedString = EfiLibAllocateZeroPool (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, PromptForDataString, Space, &NullCharacter);
gBS->FreePool (PromptForDataString);
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);
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) >= MenuOption->ThisTag->Minimum) {
SelectionComplete = TRUE;
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 {
ScreenSize = GetStringWidth (gMiniString) / 2;
CreatePopUp (ScreenSize, 4, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);
//
// 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 {
Status = WaitForKeyStroke (&Key);
} 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;
EfiStrCpy (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) < MenuOption->ThisTag->Maximum) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
KeyPad[0] = Key.UnicodeChar;
KeyPad[1] = CHAR_NULL;
EfiStrCat (StringPtr, KeyPad);
EfiStrCat (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;
}
for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {
BufferedString[Count] = StringPtr[Index];
}
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 (!SelectionComplete);
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
return Status;
}
EFI_STATUS
ReadPassword (
IN UI_MENU_OPTION *MenuOption,
IN BOOLEAN PromptForPassword,
IN EFI_TAG *Tag,
IN EFI_IFR_DATA_ARRAY *PageData,
IN BOOLEAN SecondEntry,
IN EFI_FILE_FORM_TAGS *FileFormTags,
OUT CHAR16 *StringPtr
)
{
EFI_STATUS Status;
UINTN PasswordSize;
UINTN ScreenSize;
CHAR16 NullCharacter;
CHAR16 Space[2];
EFI_INPUT_KEY Key;
CHAR16 KeyPad[2];
UINTN Index;
UINTN Start;
UINTN Top;
CHAR16 *TempString;
CHAR16 *TempString2;
BOOLEAN Confirmation;
BOOLEAN ConfirmationComplete;
EFI_HII_CALLBACK_PACKET *Packet;
EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
EFI_VARIABLE_DEFINITION *VariableDefinition;
UINTN DimensionsWidth;
UINTN DimensionsHeight;
DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
VariableDefinition = NULL;
PasswordSize = 0;
NullCharacter = CHAR_NULL;
Space[0] = L' ';
Space[1] = CHAR_NULL;
Confirmation = FALSE;
ConfirmationComplete = FALSE;
Status = EFI_SUCCESS;
FormCallback = NULL;
Packet = NULL;
//
// Remember that dynamic pages in an environment where all pages are not
// dynamic require us to call back to the user to give them an opportunity
// to register fresh information in the HII database so that we can extract it.
//
Status = gBS->HandleProtocol (
(VOID *) (UINTN) MenuOption->Tags[0].CallbackHandle,
&gEfiFormCallbackProtocolGuid,
&FormCallback
);
TempString = EfiLibAllocateZeroPool (MenuOption->ThisTag->Maximum * 2);
TempString2 = EfiLibAllocateZeroPool (MenuOption->ThisTag->Maximum * 2);
ASSERT (TempString);
ASSERT (TempString2);
if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
//
// Password requires a callback to determine if a password exists
//
PageData->Data->OpCode = EFI_IFR_PASSWORD_OP;
PageData->Data->Length = 3;
ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
//
// The user is about to be prompted with a password field, Data = 0 (Return Status determines the type of prompt)
//
PageData->Data->Data = (VOID *) (UINTN) (UINT8) (0 + SecondEntry * 2);
PageData->NvRamMap = VariableDefinition->NvRamMap;
if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
Status = FormCallback->Callback (
FormCallback,
Tag->Key,
PageData,
&Packet
);
}
//
// If error on return, continue with the reading of a typed in password to verify user knows password
// If no error, there is no password set, so prompt for new password
// if the previous callback was to verify the user knew password, and user typed it correctly - should return no error
//
if (!EFI_ERROR (Status)) {
PromptForPassword = FALSE;
//
// Simulate this as the second entry into this routine for an interactive behavior
//
SecondEntry = TRUE;
} else if (Status == EFI_NOT_READY) {
Error:
if (Packet != NULL) {
//
// Upon error, we will likely receive a string to print out
// Display error popup
//
ScreenSize = EFI_MAX (GetStringWidth (Packet->String), GetStringWidth (gPressEnter)) / 2;
CreatePopUp (ScreenSize, 4, &NullCharacter, Packet->String, gPressEnter, &NullCharacter);
gBS->FreePool (Packet);
do {
Status = WaitForKeyStroke (&Key);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
}
gBS->FreePool (TempString);
gBS->FreePool (TempString2);
return EFI_NOT_READY;
}
}
do {
//
// Display PopUp Screen
//
ScreenSize = GetStringWidth (gPromptForNewPassword) / 2;
if (GetStringWidth (gConfirmPassword) / 2 > ScreenSize) {
ScreenSize = GetStringWidth (gConfirmPassword) / 2;
}
Start = (DimensionsWidth - ScreenSize - 4) / 2 + gScreenDimensions.LeftColumn + 2;
Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
if (!Confirmation) {
if (PromptForPassword) {
CreatePopUp (ScreenSize, 4, &NullCharacter, gPromptForPassword, Space, &NullCharacter);
} else {
CreatePopUp (ScreenSize, 4, &NullCharacter, gPromptForNewPassword, Space, &NullCharacter);
}
} else {
CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmPassword, Space, &NullCharacter);
StringPtr[0] = CHAR_NULL;
}
do {
Status = WaitForKeyStroke (&Key);
switch (Key.UnicodeChar) {
case CHAR_NULL:
if (Key.ScanCode == SCAN_ESC) {
return EFI_NOT_READY;
}
ConfirmationComplete = FALSE;
break;
case CHAR_CARRIAGE_RETURN:
if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
//
// User just typed a string in
//
PageData->Data->OpCode = EFI_IFR_PASSWORD_OP;
//
// If the user just typed in a password, Data = 1
// If the user just typed in a password to confirm the previous password, Data = 2
//
if (!Confirmation) {
PageData->Data->Length = 3;
PageData->Data->Data = (VOID *) (UINTN) (UINT8) (1 + SecondEntry * 2);
if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
Status = FormCallback->Callback (
FormCallback,
Tag->Key,
PageData,
&Packet
);
}
PageData->Data->Length = sizeof (EFI_IFR_DATA_ENTRY);
PageData->Data->Data = (VOID *) TempString;
} else {
PageData->Data->Length = 3;
PageData->Data->Data = (VOID *) (UINTN) (UINT8) (2 + SecondEntry * 2);
if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
Status = FormCallback->Callback (
FormCallback,
Tag->Key,
PageData,
&Packet
);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?