Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

495 lines
11 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
input.c
Author:
Ken Reneris Oct-2-1997
Abstract:
--*/
#if defined (_IA64_)
#include "bootia64.h"
#endif
#if defined (_X86_)
#include "bldrx86.h"
#endif
#include "displayp.h"
#include "stdio.h"
#include "efi.h"
#include "efip.h"
#include "flop.h"
#include "bootefi.h"
//
// Externals
//
extern BOOT_CONTEXT BootContext;
extern EFI_HANDLE EfiImageHandle;
extern EFI_SYSTEM_TABLE *EfiST;
extern EFI_BOOT_SERVICES *EfiBS;
extern EFI_RUNTIME_SERVICES *EfiRS;
extern EFI_GUID EfiDevicePathProtocol;
extern EFI_GUID EfiBlockIoProtocol;
//
// Globals
//
ULONGLONG InputTimeout = 0;
//
// Takes any pending input and converts it into a KEY value. Non-blocking, returning 0 if no input available.
//
ULONG
BlGetKey()
{
ULONG Key = 0;
UCHAR Ch;
ULONG Count;
if (ArcGetReadStatus(BlConsoleInDeviceId) == ESUCCESS) {
ArcRead(BlConsoleInDeviceId, &Ch, sizeof(Ch), &Count);
if (Ch == ASCI_CSI_IN) {
if (ArcGetReadStatus(BlConsoleInDeviceId) == ESUCCESS) {
ArcRead(BlConsoleInDeviceId, &Ch, sizeof(Ch), &Count);
//
// All the function keys start with ESC-O
//
switch (Ch) {
case 'O':
ArcRead(BlConsoleInDeviceId, &Ch, sizeof(Ch), &Count); // will not or block, as the buffer is already filled
switch (Ch) {
case 'P':
Key = F1_KEY;
break;
case 'Q':
Key = F2_KEY;
break;
case 'w':
Key = F3_KEY;
break;
case 'x':
Key = F4_KEY;
break;
case 't':
Key = F5_KEY;
break;
case 'u':
Key = F6_KEY;
break;
case 'r':
Key = F8_KEY;
break;
case 'M':
Key = F10_KEY;
break;
}
break;
case 'A':
Key = UP_ARROW;
break;
case 'B':
Key = DOWN_ARROW;
break;
case 'C':
Key = RIGHT_KEY;
break;
case 'D':
Key = LEFT_KEY;
break;
case 'H':
Key = HOME_KEY;
break;
case 'K':
Key = END_KEY;
break;
case '@':
Key = INS_KEY;
break;
case 'P':
Key = DEL_KEY;
break;
case TAB_KEY:
Key = BACKTAB_KEY;
break;
}
} else { // Single escape key, as no input is waiting.
Key = ESCAPE_KEY;
}
} else if (Ch == 0x8) {
Key = BKSP_KEY;
} else {
Key = (ULONG)Ch;
}
}
return Key;
}
VOID
BlInputString(
IN ULONG Prompt,
IN ULONG CursorX,
IN ULONG PosY,
IN PUCHAR String,
IN ULONG MaxLength
)
{
PTCHAR PromptString;
ULONG TextX, TextY;
ULONG Length, Index;
_TUCHAR CursorChar[2];
ULONG Key;
_PTUCHAR p;
ULONG i;
ULONG Count;
_PTUCHAR pString;
#ifdef UNICODE
WCHAR StringW[200];
UNICODE_STRING uString;
ANSI_STRING aString;
pString = StringW;
uString.Buffer = StringW;
uString.MaximumLength = sizeof(StringW);
RtlInitAnsiString(&aString, (PCHAR)String );
RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
#else
pString = String;
#endif
PromptString = BlFindMessage(Prompt);
Length = (ULONG)strlen((PCHAR)String);
CursorChar[1] = TEXT('\0');
//
// Print prompt
//
BlEfiPositionCursor( PosY, CursorX );
BlEfiEnableCursor( TRUE );
ArcWrite(BlConsoleOutDeviceId, PromptString, (ULONG)_tcslen(PromptString)*sizeof(TCHAR), &Count);
//
// Indent cursor to right of prompt
//
CursorX += (ULONG)_tcslen(PromptString);
TextX = CursorX;
Key = 0;
for (; ;) {
TextY = TextX + Length;
if (CursorX > TextY) {
CursorX = TextY;
}
if (CursorX < TextX) {
CursorX = TextX;
}
Index = CursorX - TextX;
pString[Length] = 0;
//
// Display current string
//
BlEfiPositionCursor( TextY, TextX );
ArcWrite(
BlConsoleOutDeviceId,
pString,
(ULONG)_tcslen(pString)*sizeof(TCHAR),
&Count);
ArcWrite(BlConsoleOutDeviceId, TEXT(" "), sizeof(TEXT(" ")), &Count);
if (Key == 0x0d) { // enter key?
break ;
}
//
// Display cursor
//
BlEfiPositionCursor( PosY, CursorX );
BlEfiSetInverseMode( TRUE );
CursorChar[0] = pString[Index] ? pString[Index] : TEXT(' ');
ArcWrite(BlConsoleOutDeviceId, CursorChar, sizeof(_TUCHAR), &Count);
BlEfiSetInverseMode( FALSE );
BlEfiPositionCursor( PosY, CursorX );
BlEfiEnableCursor(TRUE);
//
// Get key and process it
//
while ((Key = BlGetKey()) == 0) ;
switch (Key) {
case HOME_KEY:
CursorX = TextX;
break;
case END_KEY:
CursorX = TextY;
break;
case LEFT_KEY:
CursorX -= 1;
break;
case RIGHT_KEY:
CursorX += 1;
break;
case BKSP_KEY:
if (!Index) {
break;
}
CursorX -= 1;
pString[Index-1] = CursorChar[0];
// fallthough to DEL_KEY
case DEL_KEY:
if (Length) {
p = pString+Index;
i = Length-Index+1;
while (i) {
p[0] = p[1];
p += 1;
i -= 1;
}
Length -= 1;
}
break;
case INS_KEY:
if (Length < MaxLength) {
p = pString+Length;
i = Length-Index+1;
while (i) {
p[1] = p[0];
p -= 1;
i -= 1;
}
pString[Index] = TEXT(' ');
Length += 1;
}
break;
default:
Key = Key & 0xff;
if (Key >= ' ' && Key <= 'z') {
if (CursorX == TextY && Length < MaxLength) {
Length += 1;
}
pString[Index] = (_TUCHAR)Key;
pString[MaxLength] = 0;
CursorX += 1;
}
break;
}
}
}
ULONGLONG
BlSetInputTimeout(
ULONGLONG Timeout
)
/*++
Routine Description:
Sets the InputTimeout value. This is used
when getting local input. When attempting
to get local input, we will wait for up
to InputTimeout for a local key to be
pressed.
Arguments:
Timeout - Value to set the global InputTimeout to
(in 100 nanoseconds)
Return Value:
The value stored in InputTimeout
--*/
{
InputTimeout = Timeout;
return InputTimeout;
}
ULONGLONG
BlGetInputTimeout(
VOID
)
/*++
Routine Description:
Gets the InputTimeout value. This is used
when getting local input. When attempting
to get local input, we will wait for up
to InputTimeout for a local key to be
pressed.
Arguments:
none.
Return Value:
The value stored in InputTimeout
--*/
{
return InputTimeout;
}
EFI_STATUS
BlWaitForInput(
EFI_INPUT_KEY *Key,
ULONGLONG Timeout
)
/*++
Routine Description:
creates an event consisting of a time interval
and an efi event (local input). Once event
is signaled, will check for input
Assumes it is being called in PHYSICAL mode
Arguments:
Key - input key structure to return
input in
Timeout - Timer interval to wait.
Return Value:
EFI_TIMEOUT if timer interval met
EFI_SUCCESS if passed in event is met.
other error if EFI call failed.
--*/
{
EFI_STATUS Status = EFI_SUCCESS;
//
// start by seeing if there is any pending input
//
Status = EfiST->ConIn->ReadKeyStroke(EfiST->ConIn,
Key
);
if (Status == EFI_SUCCESS) {
return Status;
}
//
// create events to wait on
//
if (Timeout) {
EFI_EVENT Event;
EFI_EVENT TimerEvent;
EFI_EVENT WaitList[2];
UINTN Index;
Event = EfiST->ConIn->WaitForKey;
//
// Create a timer event
//
Status = EfiBS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &TimerEvent);
if (Status == EFI_SUCCESS) {
//
// set the timer event
//
EfiBS->SetTimer(TimerEvent,
TimerRelative,
Timeout
);
//
// Wait for the original event or timer
//
WaitList[0] = Event;
WaitList[1] = TimerEvent;
Status = EfiBS->WaitForEvent(2,
WaitList,
&Index
);
EfiBS->CloseEvent(TimerEvent);
//
// if the timer expired, change the return to timed out
//
if(Status == EFI_SUCCESS && Index == 1) {
Status = EFI_TIMEOUT;
}
//
// attempt to read local input
//
if (Status == EFI_SUCCESS) {
Status = EfiST->ConIn->ReadKeyStroke(EfiST->ConIn,
Key
);
}
}
}
return Status;
}