commit 5248b49ebf84d98a0597fa5aa4d813a38f581acc Author: Andriy Gapon Date: Thu Sep 8 10:31:11 2011 +0300 [wip] kern cons: introduce infrastructure for grabbing of console (input) by kernel use CONSOLE_DRIVER2 as a temporary step to avoid immediately changing all consoles diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c index 42b98cf..31f2bda 100644 --- a/sys/kern/kern_cons.c +++ b/sys/kern/kern_cons.c @@ -344,6 +344,32 @@ SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW, 0, sizeof(cn_mute), sysctl_kern_consmute, "I", "State of the console muting"); +void +cngrab() +{ + struct cn_device *cnd; + struct consdev *cn; + + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + cn = cnd->cnd_cn; + if (cn->cn_ops->cn_grab != NULL) + cn->cn_ops->cn_grab(cn); + } +} + +void +cnungrab() +{ + struct cn_device *cnd; + struct consdev *cn; + + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + cn = cnd->cnd_cn; + if (cn->cn_ops->cn_ungrab != NULL) + cn->cn_ops->cn_ungrab(cn); + } +} + /* * Low level console routines. */ diff --git a/sys/sys/cons.h b/sys/sys/cons.h index e84318f..20057f5 100644 --- a/sys/sys/cons.h +++ b/sys/sys/cons.h @@ -44,6 +44,8 @@ struct tty; typedef void cn_probe_t(struct consdev *); typedef void cn_init_t(struct consdev *); typedef void cn_term_t(struct consdev *); +typedef void cn_grab_t(struct consdev *); +typedef void cn_ungrab_t(struct consdev *); typedef int cn_getc_t(struct consdev *); typedef void cn_putc_t(struct consdev *, int); @@ -58,6 +60,10 @@ struct consdev_ops { /* kernel getchar interface */ cn_putc_t *cn_putc; /* kernel putchar interface */ + cn_grab_t *cn_grab; + /* grab console for exclusive kernel use */ + cn_ungrab_t *cn_ungrab; + /* ungrab console */ }; struct consdev { @@ -99,6 +105,20 @@ extern struct tty *constty; /* Temporary virtual console. */ .cn_term = name##_cnterm, \ .cn_getc = name##_cngetc, \ .cn_putc = name##_cnputc, \ + .cn_grab = NULL, \ + .cn_ungrab = NULL, \ + }; \ + CONSOLE_DEVICE(name##_consdev, name##_consdev_ops, NULL) + +#define CONSOLE_DRIVER2(name) \ + static const struct consdev_ops name##_consdev_ops = { \ + .cn_probe = name##_cnprobe, \ + .cn_init = name##_cninit, \ + .cn_term = name##_cnterm, \ + .cn_getc = name##_cngetc, \ + .cn_putc = name##_cnputc, \ + .cn_grab = name##_cngrab, \ + .cn_ungrab = name##_cnungrab, \ }; \ CONSOLE_DEVICE(name##_consdev, name##_consdev_ops, NULL) @@ -109,8 +129,11 @@ int cnadd(struct consdev *); void cnavailable(struct consdev *, int); void cnremove(struct consdev *); void cnselect(struct consdev *); +void cngrab(void); +void cnungrab(void); int cncheckc(void); int cngetc(void); +void cngets(char *, size_t, int); void cnputc(int); void cnputs(char *); int cnunavailable(void); commit a0849c52242378474bb2eaa41726376fbc4c5bf6 Author: Andriy Gapon Date: Thu Sep 8 10:32:22 2011 +0300 [wip] kern cons: introduce uses of cngrab()/cnungrab() diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c index 31f2bda..88c0d92 100644 --- a/sys/kern/kern_cons.c +++ b/sys/kern/kern_cons.c @@ -427,8 +427,10 @@ cnputc(int c) if (console_pausing && c == '\n' && !kdb_active) { for (cp = console_pausestr; *cp != '\0'; cp++) cnputc(*cp); + cngrab(); if (cngetc() == '.') console_pausing = 0; + cnungrab(); cnputc('\r'); for (cp = console_pausestr; *cp != '\0'; cp++) cnputc(' '); diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index d421d81..c6dde56 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -440,6 +440,8 @@ kern_reboot(int howto) print_uptime(); + cngrab(); + /* * Ok, now do things that assume all filesystem activity has * been completed. @@ -601,6 +603,7 @@ panic(const char *fmt, ...) if (newpanic) { (void)vsnprintf(buf, sizeof(buf), fmt, ap); panicstr = buf; + cngrab(); printf("panic: %s\n", buf); } else { printf("panic: "); diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c index a328268..d458c88 100644 --- a/sys/kern/subr_kdb.c +++ b/sys/kern/subr_kdb.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -621,6 +622,8 @@ kdb_trap(int type, int code, struct trapframe *tf) makectx(tf, &kdb_pcb); kdb_thr_select(curthread); + cngrab(); + for (;;) { handled = be->dbbe_trap(type, code); if (be == kdb_dbbe) @@ -631,6 +634,8 @@ kdb_trap(int type, int code, struct trapframe *tf) printf("Switching to %s back-end\n", be->dbbe_name); } + cnungrab(); + kdb_active--; #ifdef SMP commit a67515cbd720b16f03ba435ed182966a8a338b15 Author: Andriy Gapon Date: Thu Sep 8 10:41:02 2011 +0300 [wip] syscons: introduce implementation of cngrab and cnungrab methods diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 23337b9..92fb53e 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -229,8 +229,10 @@ static cn_init_t sc_cninit; static cn_term_t sc_cnterm; static cn_getc_t sc_cngetc; static cn_putc_t sc_cnputc; +static cn_grab_t sc_cngrab; +static cn_ungrab_t sc_cnungrab; -CONSOLE_DRIVER(sc); +CONSOLE_DRIVER2(sc); static tsw_open_t sctty_open; static tsw_close_t sctty_close; @@ -1609,6 +1611,51 @@ sc_cnterm(struct consdev *cp) } static void +sc_cngrab(struct consdev *cp) +{ + scr_stat *scp; + + scp = sc_console->sc->cur_scp; + if (scp->sc->kbd == NULL) + return; + + if (scp->grabbed++ > 0) + return; + + /* + * Make sure the keyboard is accessible even when the kbd device + * driver is disabled. + */ + kbdd_enable(scp->sc->kbd); + + /* we shall always use the keyboard in the XLATE mode here */ + scp->kbd_prev_mode = scp->kbd_mode; + scp->kbd_mode = K_XLATE; + (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); + + kbdd_poll(scp->sc->kbd, TRUE); +} + +static void +sc_cnungrab(struct consdev *cp) +{ + scr_stat *scp; + + scp = sc_console->sc->cur_scp; /* XXX */ + if (scp->sc->kbd == NULL) + return; + + if (--scp->grabbed > 0) + return; + + kbdd_poll(scp->sc->kbd, FALSE); + + scp->kbd_mode = scp->kbd_prev_mode; + (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); + kbdd_disable(scp->sc->kbd); +} + +static void sc_cnputc(struct consdev *cd, int c) { u_char buf[1]; @@ -1663,7 +1710,6 @@ sc_cngetc(struct consdev *cd) static int fkeycp; scr_stat *scp; const u_char *p; - int cur_mode; int s = spltty(); /* block sckbdevent and scrn_timer while we poll */ int c; @@ -1687,25 +1733,7 @@ sc_cngetc(struct consdev *cd) return -1; } - /* - * Make sure the keyboard is accessible even when the kbd device - * driver is disabled. - */ - kbdd_enable(scp->sc->kbd); - - /* we shall always use the keyboard in the XLATE mode here */ - cur_mode = scp->kbd_mode; - scp->kbd_mode = K_XLATE; - (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); - - kbdd_poll(scp->sc->kbd, TRUE); c = scgetc(scp->sc, SCGETC_CN | SCGETC_NONBLOCK); - kbdd_poll(scp->sc->kbd, FALSE); - - scp->kbd_mode = cur_mode; - (void)kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode); - kbdd_disable(scp->sc->kbd); - splx(s); switch (KEYFLAGS(c)) { case 0: /* normal char */ diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index 7280d89..e88ac43 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -301,7 +301,9 @@ typedef struct scr_stat { void *ts; int status; /* status (bitfield) */ + int grabbed; int kbd_mode; /* keyboard I/O mode */ + int kbd_prev_mode; /* keyboard I/O mode */ int cursor_pos; /* cursor buffer position */ int cursor_oldpos; /* cursor old buffer position */ commit b8864b68b4c0e26ece065a38301c305833be32eb Author: Andriy Gapon Date: Thu Sep 8 10:34:11 2011 +0300 [wip] add cngets, a method to read a string from console This method replaces gets() from libkern, which can be removed now. This function uses cngrab()/cnungrab() to take over the console when getting the input. diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c index 88c0d92..836835e 100644 --- a/sys/kern/kern_cons.c +++ b/sys/kern/kern_cons.c @@ -408,6 +408,55 @@ cncheckc(void) } void +cngets(char *cp, size_t size, int visible) +{ + char *lp, *end; + int c; + + cngrab(); + + lp = cp; + end = cp + size - 1; + for (;;) { + c = cngetc() & 0177; + switch (c) { + case '\n': + case '\r': + cnputc(c); + *lp = '\0'; + cnungrab(); + return; + case '\b': + case '\177': + if (lp > cp) { + if (visible) { + cnputc(c); + cnputs(" \b"); + } + lp--; + } + continue; + case '\0': + continue; + default: + if (lp < end) { + switch (visible) { + case GETS_NOECHO: + break; + case GETS_ECHOPASS: + cnputc('*'); + break; + default: + cnputc(c); + break; + } + *lp++ = c; + } + } + } +} + +void cnputc(int c) { struct cn_device *cnd; commit 1017ae425d8abecd7482bd6c6deaaf9f25f5c6cd Author: Andriy Gapon Date: Thu Sep 8 10:34:42 2011 +0300 [wip] use cngets instead of libkern gets diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c index 874aa26..72f93f4 100644 --- a/sys/geom/eli/g_eli.c +++ b/sys/geom/eli/g_eli.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -1085,7 +1086,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) /* Ask for the passphrase if defined. */ if (md.md_iterations >= 0) { printf("Enter passphrase for %s: ", pp->name); - gets(passphrase, sizeof(passphrase), + cngets(passphrase, sizeof(passphrase), g_eli_visible_passphrase); } diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c index 98e252e..f622cc5 100644 --- a/sys/kern/vfs_mountroot.c +++ b/sys/kern/vfs_mountroot.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -486,7 +487,7 @@ parse_dir_ask(char **conf) do { error = EINVAL; printf("\nmountroot> "); - gets(name, sizeof(name), GETS_ECHO); + cngets(name, sizeof(name), GETS_ECHO); if (name[0] == '\0') break; if (name[0] == '?' && name[1] == '\0') {