diff options
author | Piotr Jaroszyński <p.jaroszynski@gmail.com> | 2010-04-08 01:40:31 +0200 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2010-08-19 12:31:13 +0100 |
commit | 18d3c12b01466e424d9a54e4dbbba94e7859ec48 (patch) | |
tree | 1e55385d625f14d5cf34c64af6cee0b09efc2957 | |
parent | 1812bfd5d0d304baf3974c100b284ee8059c77fe (diff) | |
download | ipxe-18d3c12b01466e424d9a54e4dbbba94e7859ec48.tar.gz |
[linux] Add console
Add linux console using stdin/out. Configure the attached terminal for
readline use.
Signed-off-by: Piotr Jaroszyński <p.jaroszynski@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/config/config.c | 3 | ||||
-rw-r--r-- | src/config/defaults/linux.h | 2 | ||||
-rw-r--r-- | src/interface/linux/linux_console.c | 146 |
4 files changed, 152 insertions, 1 deletions
diff --git a/src/Makefile b/src/Makefile index 4dd761c1f..18e0334eb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -73,7 +73,7 @@ SRCDIRS += drivers/block SRCDIRS += drivers/nvs SRCDIRS += drivers/bitbash SRCDIRS += drivers/infiniband -SRCDIRS += interface/pxe interface/efi interface/smbios +SRCDIRS += interface/pxe interface/efi interface/smbios interface/linux SRCDIRS += tests SRCDIRS += crypto crypto/axtls crypto/matrixssl SRCDIRS += hci hci/commands hci/tui diff --git a/src/config/config.c b/src/config/config.c index 98be65d3b..561e53d40 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -82,6 +82,9 @@ REQUIRE_OBJECT ( syslog ); #ifdef CONSOLE_EFI REQUIRE_OBJECT ( efi_console ); #endif +#ifdef CONSOLE_LINUX +REQUIRE_OBJECT ( linux_console ); +#endif /* * Drag in all requested network protocols diff --git a/src/config/defaults/linux.h b/src/config/defaults/linux.h index fbb2c17b9..91f85c43b 100644 --- a/src/config/defaults/linux.h +++ b/src/config/defaults/linux.h @@ -7,6 +7,8 @@ * */ +#define CONSOLE_LINUX + #define IMAGE_SCRIPT #endif /* CONFIG_DEFAULTS_LINUX_H */ diff --git a/src/interface/linux/linux_console.c b/src/interface/linux/linux_console.c new file mode 100644 index 000000000..0fdb8f2f9 --- /dev/null +++ b/src/interface/linux/linux_console.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +FILE_LICENCE(GPL2_OR_LATER); + +/** @file + * + * Linux console implementation. + * + */ + +#include <console.h> + +#include <ipxe/init.h> +#include <ipxe/keys.h> +#include <linux_api.h> + +#include <linux/termios.h> +#include <asm/errno.h> + +static void linux_console_putchar(int c) +{ + /* write to stdout */ + if (linux_write(1, &c, 1) != 1) + DBG("linux_console write failed (%s)\n", linux_strerror(linux_errno)); +} + +static int linux_console_getchar() +{ + char c; + + /* read from stdin */ + if (linux_read(0, &c, 1) < 0) { + DBG("linux_console read failed (%s)\n", linux_strerror(linux_errno)); + return 0; + } + /* backspace seems to be returned as ascii del, map it here */ + if (c == 0x7f) + return KEY_BACKSPACE; + else + return c; +} + +static int linux_console_iskey() +{ + struct pollfd pfd; + pfd.fd = 0; + pfd.events = POLLIN; + + /* poll for data to be read on stdin */ + if (linux_poll(&pfd, 1, 0) == -1) { + DBG("linux_console poll failed (%s)\n", linux_strerror(linux_errno)); + return 0; + } + + if (pfd.revents & POLLIN) + return 1; + else + return 0; +} + +struct console_driver linux_console __console_driver = { + .disabled = 0, + .putchar = linux_console_putchar, + .getchar = linux_console_getchar, + .iskey = linux_console_iskey, +}; + +static int linux_tcgetattr(int fd, struct termios *termios_p) +{ + return linux_ioctl(fd, TCGETS, termios_p); +} + +static int linux_tcsetattr(int fd, int optional_actions, const struct termios *termios_p) +{ + unsigned long int cmd; + + switch (optional_actions) + { + case TCSANOW: + cmd = TCSETS; + break; + case TCSADRAIN: + cmd = TCSETSW; + break; + case TCSAFLUSH: + cmd = TCSETSF; + break; + default: + linux_errno = EINVAL; + return -1; + } + + return linux_ioctl(fd, cmd, termios_p); +} + +/** Saved termios attributes */ +static struct termios saved_termios; + +/** Setup the terminal for our use */ +static void linux_console_startup(void) +{ + struct termios t; + + if (linux_tcgetattr(0, &t)) { + DBG("linux_console tcgetattr failed (%s)", linux_strerror(linux_errno)); + return; + } + + saved_termios = t; + + /* Disable canonical mode and echo. Let readline handle that */ + t.c_lflag &= ~(ECHO | ICANON); + /* stop ^C from sending a signal */ + t.c_cc[VINTR] = 0; + + if (linux_tcsetattr(0, TCSAFLUSH, &t)) + DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno)); +} + +/** Restores original terminal attributes on shutdown */ +static void linux_console_shutdown(int flags __unused) +{ + if (linux_tcsetattr(0, TCSAFLUSH, &saved_termios)) + DBG("linux_console tcsetattr failed (%s)", linux_strerror(linux_errno)); +} + +struct startup_fn linux_console_startup_fn __startup_fn(STARTUP_EARLY) = { + .startup = linux_console_startup, + .shutdown = linux_console_shutdown, +}; |