ui/ncurses: Reset console options on boot
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 6 Nov 2018 04:34:51 +0000 (15:34 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Fri, 16 Nov 2018 02:55:29 +0000 (13:55 +1100)
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@mendozajonas.com>
discover/boot.c
discover/device-handler.c
lib/pb-protocol/pb-protocol.c
lib/types/types.h
ui/ncurses/nc-cui.c
ui/ncurses/nc-cui.h

index 3de7d28e3310979d2003c2f23078e7f7826cd9b9..ed67cd502ca9c22c4fdbeaa3107e5b16707d467e 100644 (file)
@@ -46,6 +46,7 @@ static void __attribute__((format(__printf__, 4, 5))) update_status(
 
        status.type = type;
        status.backlog = false;
 
        status.type = type;
        status.backlog = false;
+       status.boot_active = type == STATUS_INFO;
 
        pb_debug("boot status: [%d] %s\n", type, status.message);
 
 
        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");
                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;
        }
                                _("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__);
                } 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);
                                        _("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;
 
 {
        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);
                        _("Boot cancelled"));
 
        cleanup_cancellations(task, NULL);
index 983c50909ef7f5900f916bb5cf4040b7bdf6d994..271b9880b45d633f5013f2de11ec4c038f149e3b 100644 (file)
@@ -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.type = type;
        status.message = talloc_vasprintf(handler, fmt, ap);
        status.backlog = false;
+       status.boot_active = false;
 
        device_handler_status(handler, &status);
 
 
        device_handler_status(handler, &status);
 
index 315efc4cf000555f9575b20c489d01441aeca0e3..7c563c8e0ad17de54e8dd1ad86ae786949a11422 100644 (file)
@@ -223,7 +223,7 @@ int pb_protocol_boot_status_len(const struct status *status)
        return  4 +     /* type */
                4 + optional_strlen(status->message) +
                4 +     /* backlog */
        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)
 }
 
 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->backlog);
        pos += sizeof(bool);
 
+       *(bool *)pos = __cpu_to_be32(status->boot_active);
+       pos += sizeof(bool);
+
        assert(pos <= buf + buf_len);
        (void)buf_len;
 
        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);
 
        status->backlog = *(bool *)pos;
        pos += sizeof(status->backlog);
 
+       /* boot_active */
+       status->boot_active = *(bool *)pos;
+       pos += sizeof(status->boot_active);
+
        rc = 0;
 
 out:
        rc = 0;
 
 out:
index 5f99b58d52b33d11dc5dc8369bbdc5569489e8e4..f5392c89c4a7b1715622cf3d7520e956e24ac30b 100644 (file)
@@ -97,6 +97,7 @@ struct status {
        } type;
        char    *message;
        bool    backlog;
        } type;
        char    *message;
        bool    backlog;
+       bool    boot_active;
 };
 
 struct statuslog_entry {
 };
 
 struct statuslog_entry {
index d3e00aa03a0e6199f030b46209fe45194843092f..8ad89553a5ebed3875d1eaa0da5e71235172a2ba 100644 (file)
@@ -92,16 +92,30 @@ static bool lockdown_active(void)
 #endif
 }
 
 #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. */
 static void cui_start(void)
 {
        initscr();                      /* Initialize ncurses. */
-       cbreak();                       /* Disable line buffering. */
-       noecho();                       /* Disable getch() echo. */
        keypad(stdscr, TRUE);           /* Enable num keypad keys. */
        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
 
        /* 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) {
                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 */
        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);
+       }
 }
 
 /*
 }
 
 /*
index d26883b1e47d08a3a07d86c39898096e72e208fd..abe4db98173446fd34ddaeb04cd21018fce45e78 100644 (file)
@@ -77,6 +77,7 @@ struct cui {
        void *platform_info;
        unsigned int default_item;
        int (*on_boot)(struct cui *cui, struct cui_opt_data *cod);
        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,
 };
 
 struct cui *cui_init(void* platform_info,