Clib/EFI: Add standard input descriptor support

This patch implements stdin for EFI environment using
SIMPLE_INPUT_INTERFACE. Lv Zheng.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
This commit is contained in:
Lv Zheng 2016-05-23 23:06:55 +08:00
parent 973f73ca34
commit 9bba284f4d
3 changed files with 134 additions and 15 deletions

View File

@ -324,9 +324,11 @@ struct _EFI_SYSTEM_TABLE;
extern struct _EFI_SYSTEM_TABLE *ST;
extern struct _EFI_BOOT_SERVICES *BS;
#define FILE struct _SIMPLE_TEXT_OUTPUT_INTERFACE
#define stdout ST->ConOut
#define stderr ST->ConOut
#define stdin NULL
typedef union acpi_efi_file ACPI_EFI_FILE;
#define FILE ACPI_EFI_FILE
#define stdout ((FILE *) (ST)->ConOut)
#define stderr ((FILE *) (ST)->ConOut)
#define stdin ((FILE *) (ST)->ConIn)
#endif /* __ACEFI_H__ */

View File

@ -516,6 +516,15 @@ EFI_STATUS
EFI_HANDLE ImageHandle);
typedef
EFI_STATUS
(EFIAPI *EFI_SET_WATCHDOG_TIMER) (
UINTN Timeout,
UINT64 WatchdogCode,
UINTN DataSize,
CHAR16 *WatchdogData);
#define EFI_IMAGE_INFORMATION_REVISION 0x1000
typedef struct {
UINT32 Revision;
@ -803,13 +812,12 @@ typedef struct _EFI_BOOT_SERVICES {
EFI_EXIT_BOOT_SERVICES ExitBootServices;
EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount;
EFI_STALL Stall;
EFI_SET_WATCHDOG_TIMER SetWatchdogTimer;
#else
EFI_UNKNOWN_INTERFACE ExitBootServices;
EFI_UNKNOWN_INTERFACE GetNextMonotonicCount;
EFI_UNKNOWN_INTERFACE Stall;
EFI_UNKNOWN_INTERFACE SetWatchdogTimer;
#endif
EFI_SET_WATCHDOG_TIMER SetWatchdogTimer;
#if 0
EFI_CONNECT_CONTROLLER ConnectController;
@ -890,6 +898,15 @@ typedef struct _EFI_SYSTEM_TABLE {
} EFI_SYSTEM_TABLE;
/* FILE abstraction */
union acpi_efi_file {
struct _EFI_FILE_IO_INTERFACE File;
struct _SIMPLE_TEXT_OUTPUT_INTERFACE ConOut;
struct _SIMPLE_INPUT_INTERFACE ConIn;
};
/* GNU EFI definitions */
#if defined(_GNU_EFI)

View File

@ -125,6 +125,17 @@
#define ACPI_EFI_PRINT_LENGTH 256
#define ACPI_EFI_KEY_ESC 0x0000
#define ACPI_EFI_KEY_BACKSPACE 0x0008
#define ACPI_EFI_KEY_ENTER 0x000D
#define ACPI_EFI_KEY_CTRL_C 0x0003
#define ACPI_EFI_ASCII_NULL 0x00
#define ACPI_EFI_ASCII_DEL 0x7F
#define ACPI_EFI_ASCII_ESC 0x1B
#define ACPI_EFI_ASCII_CR '\r'
#define ACPI_EFI_ASCII_NL '\n'
/* Local prototypes */
@ -322,7 +333,8 @@ fclose (
EFI_FILE_HANDLE EfiFile;
if (File == stdout || File == stderr)
if (File == stdin || File == stdout ||
File == stderr)
{
return;
}
@ -425,14 +437,87 @@ fread (
ACPI_SIZE Count,
FILE *File)
{
int Length = -1;
int Length = -EINVAL;
EFI_FILE_HANDLE EfiFile;
SIMPLE_INPUT_INTERFACE *In;
UINTN ReadSize;
EFI_STATUS EfiStatus;
EFI_INPUT_KEY Key;
ACPI_SIZE Pos = 0;
if (!Buffer)
{
errno = EINVAL;
goto ErrorExit;
}
ReadSize = Size * Count;
if (File == stdout || File == stderr)
{
/* Do not support read operations on output console */
}
else if (File == stdin)
{
In = ACPI_CAST_PTR (SIMPLE_INPUT_INTERFACE, File);
while (Pos < ReadSize)
{
WaitKey:
EfiStatus = uefi_call_wrapper (In->ReadKeyStroke, 2, In, &Key);
if (EFI_ERROR (EfiStatus))
{
if (EfiStatus == EFI_NOT_READY)
{
goto WaitKey;
}
errno = EIO;
Length = -EIO;
fprintf (stderr,
"SIMPLE_INPUT_INTERFACE->ReadKeyStroke() failure.\n");
goto ErrorExit;
}
switch (Key.UnicodeChar)
{
case ACPI_EFI_KEY_CTRL_C:
break;
case ACPI_EFI_KEY_ENTER:
*(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_CR;
if (Pos < ReadSize - 1)
{
/* Drop CR in case we don't have sufficient buffer */
Pos++;
}
*(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_NL;
Pos++;
break;
case ACPI_EFI_KEY_BACKSPACE:
*(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_DEL;
Pos++;
break;
case ACPI_EFI_KEY_ESC:
*(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) ACPI_EFI_ASCII_ESC;
Pos++;
break;
default:
*(ACPI_ADD_PTR (UINT8, Buffer, Pos)) = (UINT8) Key.UnicodeChar;
Pos++;
break;
}
}
Length = Pos;
}
else
{
@ -442,7 +527,6 @@ fread (
errno = EINVAL;
goto ErrorExit;
}
ReadSize = Size * Count;
EfiStatus = uefi_call_wrapper (AcpiGbl_EfiCurrentVolume->Read, 3,
EfiFile, &ReadSize, Buffer);
@ -450,6 +534,7 @@ fread (
{
fprintf (stderr, "EFI_FILE_HANDLE->Read() failure.\n");
errno = EIO;
Length = -EIO;
goto ErrorExit;
}
Length = ReadSize;
@ -485,12 +570,19 @@ AcpiEfiFlushFile (
CHAR16 *Pos,
BOOLEAN FlushAll)
{
SIMPLE_TEXT_OUTPUT_INTERFACE *Out;
if (FlushAll || Pos >= (End - 1))
if (File == stdout || File == stderr)
{
*Pos = 0;
uefi_call_wrapper (File->OutputString, 2, File, Begin);
Pos = Begin;
Out = ACPI_CAST_PTR (SIMPLE_TEXT_OUTPUT_INTERFACE, File);
if (FlushAll || Pos >= (End - 1))
{
*Pos = 0;
uefi_call_wrapper (Out->OutputString, 2, Out, Begin);
Pos = Begin;
}
}
return (Pos);
@ -519,7 +611,7 @@ fwrite (
ACPI_SIZE Count,
FILE *File)
{
int Length = -1;
int Length = -EINVAL;
CHAR16 String[ACPI_EFI_PRINT_LENGTH];
const char *Ascii;
CHAR16 *End;
@ -530,7 +622,11 @@ fwrite (
EFI_STATUS EfiStatus;
if (File == stdout || File == stderr)
if (File == stdin)
{
/* Do not support write operations on input console */
}
else if (File == stdout || File == stderr)
{
Pos = String;
End = String + ACPI_EFI_PRINT_LENGTH - 1;
@ -898,6 +994,10 @@ efi_main (
ST = SystemTab;
BS = SystemTab->BootServices;
/* Disable the platform watchdog timer if we go interactive */
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x0, 0, NULL);
/* Retrieve image information */
EfiStatus = uefi_call_wrapper (BS->HandleProtocol, 3,