[PATCH] ui/ncurses: Reset console options on boot
Samuel Mendoza-Jonas
sam at mendozajonas.com
Fri Nov 16 14:21:34 AEDT 2018
On Wed, 2018-11-07 at 11:51 +1100, Samuel Mendoza-Jonas wrote:
> The ncurses UI sets a few console options at startup that are needed for
> ncurses to work properly. These aren't reset however and can lead to
> quirks like the cursor being invisible after kexecing to the next
> kernel.
> The UI process doesn't have time to reset these when it is killed by
> kexec, so instead add a 'boot_active' field to status updates. This is
> set by boot.c's update handler so the UI can assume it is about to boot
> if it receives a status update with this field, and resets the console
> options. If the boot is cancelled for any reason the status update will
> reflect that and the console options are restored.
>
> Signed-off-by: Samuel Mendoza-Jonas <sam at mendozajonas.com>
Merged as 2bc0df4a
> ---
> discover/boot.c | 7 ++---
> discover/device-handler.c | 1 +
> lib/pb-protocol/pb-protocol.c | 9 ++++++-
> lib/types/types.h | 1 +
> ui/ncurses/nc-cui.c | 49 +++++++++++++++++++++++++++++------
> ui/ncurses/nc-cui.h | 1 +
> 6 files changed, 56 insertions(+), 12 deletions(-)
>
> diff --git a/discover/boot.c b/discover/boot.c
> index 3de7d28e..ed67cd50 100644
> --- a/discover/boot.c
> +++ b/discover/boot.c
> @@ -46,6 +46,7 @@ static void __attribute__((format(__printf__, 4, 5))) update_status(
>
> status.type = type;
> status.backlog = false;
> + status.boot_active = type == STATUS_INFO;
>
> pb_debug("boot status: [%d] %s\n", type, status.message);
>
> @@ -531,7 +532,7 @@ struct boot_task *boot(void *ctx, struct discover_boot_option *opt,
> image = opt->boot_image->url;
> } else {
> pb_log_fn("no image specified\n");
> - update_status(status_fn, status_arg, STATUS_INFO,
> + update_status(status_fn, status_arg, STATUS_ERROR,
> _("Boot failed: no image specified"));
> return NULL;
> }
> @@ -585,7 +586,7 @@ struct boot_task *boot(void *ctx, struct discover_boot_option *opt,
> } else {
> pb_log("%s: no command line signature file"
> " specified\n", __func__);
> - update_status(status_fn, status_arg, STATUS_INFO,
> + update_status(status_fn, status_arg, STATUS_ERROR,
> _("Boot failed: no command line"
> " signature file specified"));
> talloc_free(boot_task);
> @@ -654,7 +655,7 @@ void boot_cancel(struct boot_task *task)
> {
> task->cancelled = true;
>
> - update_status(task->status_fn, task->status_arg, STATUS_INFO,
> + update_status(task->status_fn, task->status_arg, STATUS_ERROR,
> _("Boot cancelled"));
>
> cleanup_cancellations(task, NULL);
> diff --git a/discover/device-handler.c b/discover/device-handler.c
> index 983c5090..271b9880 100644
> --- a/discover/device-handler.c
> +++ b/discover/device-handler.c
> @@ -534,6 +534,7 @@ static void _device_handler_vstatus(struct device_handler *handler,
> status.type = type;
> status.message = talloc_vasprintf(handler, fmt, ap);
> status.backlog = false;
> + status.boot_active = false;
>
> device_handler_status(handler, &status);
>
> diff --git a/lib/pb-protocol/pb-protocol.c b/lib/pb-protocol/pb-protocol.c
> index 315efc4c..7c563c8e 100644
> --- a/lib/pb-protocol/pb-protocol.c
> +++ b/lib/pb-protocol/pb-protocol.c
> @@ -223,7 +223,7 @@ int pb_protocol_boot_status_len(const struct status *status)
> return 4 + /* type */
> 4 + optional_strlen(status->message) +
> 4 + /* backlog */
> - 4;
> + 4; /* boot_active */
> }
>
> int pb_protocol_system_info_len(const struct system_info *sysinfo)
> @@ -457,6 +457,9 @@ int pb_protocol_serialise_boot_status(const struct status *status,
> *(bool *)pos = __cpu_to_be32(status->backlog);
> pos += sizeof(bool);
>
> + *(bool *)pos = __cpu_to_be32(status->boot_active);
> + pos += sizeof(bool);
> +
> assert(pos <= buf + buf_len);
> (void)buf_len;
>
> @@ -952,6 +955,10 @@ int pb_protocol_deserialise_boot_status(struct status *status,
> status->backlog = *(bool *)pos;
> pos += sizeof(status->backlog);
>
> + /* boot_active */
> + status->boot_active = *(bool *)pos;
> + pos += sizeof(status->boot_active);
> +
> rc = 0;
>
> out:
> diff --git a/lib/types/types.h b/lib/types/types.h
> index 5f99b58d..f5392c89 100644
> --- a/lib/types/types.h
> +++ b/lib/types/types.h
> @@ -97,6 +97,7 @@ struct status {
> } type;
> char *message;
> bool backlog;
> + bool boot_active;
> };
>
> struct statuslog_entry {
> diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c
> index d3e00aa0..8ad89553 100644
> --- a/ui/ncurses/nc-cui.c
> +++ b/ui/ncurses/nc-cui.c
> @@ -92,16 +92,30 @@ static bool lockdown_active(void)
> #endif
> }
>
> +static void cui_set_curses_options(bool curses_mode)
> +{
> + if (curses_mode) {
> + cbreak(); /* Disable line buffering. */
> + noecho(); /* Disable getch() echo. */
> + nonl(); /* Disable new-line translation. */
> + intrflush(stdscr, FALSE); /* Disable interrupt flush. */
> + curs_set(0); /* Make cursor invisible */
> + nodelay(stdscr, TRUE); /* Enable non-blocking getch() */
> + } else {
> + nocbreak(); /* Enable line buffering. */
> + echo(); /* Enable getch() echo. */
> + nl(); /* Enable new-line translation. */
> + intrflush(stdscr, TRUE); /* Enable interrupt flush. */
> + curs_set(1); /* Make cursor visible */
> + nodelay(stdscr, FALSE); /* Disable non-blocking getch() */
> + }
> +}
> +
> static void cui_start(void)
> {
> initscr(); /* Initialize ncurses. */
> - cbreak(); /* Disable line buffering. */
> - noecho(); /* Disable getch() echo. */
> keypad(stdscr, TRUE); /* Enable num keypad keys. */
> - nonl(); /* Disable new-line translation. */
> - intrflush(stdscr, FALSE); /* Disable interrupt flush. */
> - curs_set(0); /* Make cursor invisible */
> - nodelay(stdscr, TRUE); /* Enable non-blocking getch() */
> + cui_set_curses_options(true);
>
> /* We may be operating with an incorrect $TERM type; in this case
> * the keymappings will be slightly broken. We want at least
> @@ -650,6 +664,12 @@ static int cui_process_key(void *arg)
> }
> }
>
> + if (cui->preboot_mode) {
> + /* Turn curses options back on if the user interacts */
> + cui->preboot_mode = false;
> + cui_set_curses_options(true);
> + }
> +
> if (!cui->has_input && key_cancels_boot(c)) {
> cui->has_input = true;
> if (cui->client) {
> @@ -980,8 +1000,21 @@ static void cui_update_status(struct status *status, void *arg)
> statuslog_append_steal(cui, cui->statuslog, status);
>
> /* Ignore status messages from the backlog */
> - if (!status->backlog)
> - nc_scr_status_printf(cui->current, "%s", status->message);
> + if (status->backlog)
> + return;
> +
> + nc_scr_status_printf(cui->current, "%s", status->message);
> +
> + if (cui->preboot_mode &&
> + (!status->boot_active || status->type == STATUS_ERROR)) {
> + cui_set_curses_options(true);
> + cui->preboot_mode = false;
> + } else {
> + cui->preboot_mode = status->boot_active &&
> + status->type == STATUS_INFO;
> + if (cui->preboot_mode)
> + cui_set_curses_options(false);
> + }
> }
>
> /*
> diff --git a/ui/ncurses/nc-cui.h b/ui/ncurses/nc-cui.h
> index d26883b1..abe4db98 100644
> --- a/ui/ncurses/nc-cui.h
> +++ b/ui/ncurses/nc-cui.h
> @@ -77,6 +77,7 @@ struct cui {
> void *platform_info;
> unsigned int default_item;
> int (*on_boot)(struct cui *cui, struct cui_opt_data *cod);
> + bool preboot_mode;
> };
>
> struct cui *cui_init(void* platform_info,
More information about the Petitboot
mailing list