diff options
author | jhb <jhb@FreeBSD.org> | 2005-05-27 19:31:00 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-05-27 19:31:00 +0000 |
commit | 65ffcee053e76ba577b7e36112e113c94a943ade (patch) | |
tree | 859ee2269f72fa748bba4cbbbbab735220546737 | |
parent | e2d11cf4d44df5cebaebaafbedc7183804582ff5 (diff) | |
download | FreeBSD-src-65ffcee053e76ba577b7e36112e113c94a943ade.zip FreeBSD-src-65ffcee053e76ba577b7e36112e113c94a943ade.tar.gz |
- Add support to the loader for multiple consoles.
- Teach the i386 and pc98 loaders to honor multiple console requests from
their respective boot2 binaries so that the same console(s) are used in
both boot2 and the loader.
- Since the kernel doesn't support multiple consoles, whichever console is
listed first is treated as the "primary" console and is passed to the
kernel in the boot_howto flags.
PR: kern/66425
Submitted by: Gavin Atkinson gavin at ury dot york dot ac dot uk
MFC after: 1 week
-rw-r--r-- | sys/boot/common/console.c | 132 | ||||
-rw-r--r-- | sys/boot/common/loader.8 | 7 | ||||
-rw-r--r-- | sys/boot/i386/libi386/bootinfo.c | 36 | ||||
-rw-r--r-- | sys/boot/i386/loader/main.c | 12 | ||||
-rw-r--r-- | sys/boot/pc98/loader/main.c | 12 |
5 files changed, 146 insertions, 53 deletions
diff --git a/sys/boot/common/console.c b/sys/boot/common/console.c index 0fc138c..196e715 100644 --- a/sys/boot/common/console.c +++ b/sys/boot/common/console.c @@ -35,14 +35,15 @@ __FBSDID("$FreeBSD$"); * Core console support */ -static int cons_set(struct env_var *ev, int flags, void *value); -static int cons_find(char *name); +static int cons_set(struct env_var *ev, int flags, const void *value); +static int cons_find(const char *name); +static int cons_check(const char *string); +static void cons_change(const char *string); /* - * Detect possible console(s) to use. The first probed console - * is marked active. Also create the console variable. - * - * XXX Add logic for multiple console support. + * Detect possible console(s) to use. If preferred console(s) have been + * specified, mark them as active. Else, mark the first probed console + * as active. Also create the console variable. */ void cons_probe(void) @@ -64,6 +65,9 @@ cons_probe(void) if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)) active = cons; } + /* Force a console even if all probes failed */ + if (active == -1) + active = 0; /* Check to see if a console preference has already been registered */ prefconsole = getenv("console"); @@ -71,21 +75,24 @@ cons_probe(void) prefconsole = strdup(prefconsole); if (prefconsole != NULL) { unsetenv("console"); /* we want to replace this */ - for (cons = 0; consoles[cons] != NULL; cons++) - /* look for the nominated console, use it if it's functional */ - if (!strcmp(prefconsole, consoles[cons]->c_name) && - (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT))) - active = cons; - free(prefconsole); + cons_change(prefconsole); + } else { + consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; + consoles[active]->c_init(0); + prefconsole = strdup(consoles[active]->c_name); } - if (active == -1) - active = 0; - consoles[active]->c_flags |= (C_ACTIVEIN | C_ACTIVEOUT); - consoles[active]->c_init(0); - printf("Console: %s\n", consoles[active]->c_desc); - env_setenv("console", EV_VOLATILE, consoles[active]->c_name, cons_set, - env_nounset); + printf("Consoles: "); + for (cons = 0; consoles[cons] != NULL; cons++) + if (consoles[cons]->c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) + printf("%s ", consoles[cons]->c_desc); + printf("\n"); + + if (prefconsole != NULL) { + env_setenv("console", EV_VOLATILE, prefconsole, cons_set, + env_nounset); + free(prefconsole); + } } int @@ -128,46 +135,93 @@ putchar(int c) consoles[cons]->c_out(c); } +/* + * Find the console with the specified name. + */ static int -cons_find(char *name) +cons_find(const char *name) { int cons; - + for (cons = 0; consoles[cons] != NULL; cons++) if (!strcmp(consoles[cons]->c_name, name)) - return(cons); - return(-1); + return (cons); + return (-1); } - /* - * Select a console. - * - * XXX Note that the console system design allows for some extension - * here (eg. multiple consoles, input/output only, etc.) + * Select one or more consoles. */ static int -cons_set(struct env_var *ev, int flags, void *value) +cons_set(struct env_var *ev, int flags, const void *value) { - int cons, active; + int cons; - if ((value == NULL) || ((active = cons_find(value)) == -1)) { + if ((value == NULL) || (cons_check(value) == -1)) { if (value != NULL) - printf("no such console '%s'\n", (char *)value); + printf("no such console!\n"); printf("Available consoles:\n"); for (cons = 0; consoles[cons] != NULL; cons++) printf(" %s\n", consoles[cons]->c_name); return(CMD_ERROR); } - /* disable all current consoles */ - for (cons = 0; consoles[cons] != NULL; cons++) - consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT); - - /* enable selected console */ - consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; - consoles[active]->c_init(0); + cons_change(value); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return(CMD_OK); } + +/* + * Check that all of the consoles listed in *string are valid consoles + */ +static int +cons_check(const char *string) +{ + int cons; + char *curpos, *dup, *next; + + dup = next = strdup(string); + cons = -1; + while (next != NULL) { + curpos = strsep(&next, " ,"); + if (*curpos != '\0') { + cons = cons_find(curpos); + if (cons == -1) + break; + } + } + + free(dup); + return (cons); +} + +/* + * Activate all of the consoles listed in *string and disable all the others. + */ +static void +cons_change(const char *string) +{ + int cons; + char *curpos, *dup, *next; + + /* Disable all consoles */ + for (cons = 0; consoles[cons] != NULL; cons++) { + consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT); + } + + /* Enable selected consoles */ + dup = next = strdup(string); + while (next != NULL) { + curpos = strsep(&next, " ,"); + if (*curpos == '\0') + continue; + cons = cons_find(curpos); + if (cons > 0) { + consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; + consoles[cons]->c_init(0); + } + } + + free(dup); +} diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8 index b67f8bf..299f402 100644 --- a/sys/boot/common/loader.8 +++ b/sys/boot/common/loader.8 @@ -65,6 +65,7 @@ will probe for a console and set the variable, or set it to serial console .Pq Dq comconsole if the previous boot stage used that. +If multiple consoles are selected, they will be listed separated by spaces. Then, devices are probed, .Va currdev and @@ -391,7 +392,11 @@ List of semicolon-separated search path for bootable kernels. The default is .Dq Li kernel . .It Va console -Defines the current console. +Defines the current console or consoles. +Multiple consoles may be specified. +In that case, the first listed console will become the default console for +userland output (e.g. from +.Xr init 8 ). .It Va currdev Selects the default device. Syntax for devices is odd. diff --git a/sys/boot/i386/libi386/bootinfo.c b/sys/boot/i386/libi386/bootinfo.c index 85638fe..623351c 100644 --- a/sys/boot/i386/libi386/bootinfo.c +++ b/sys/boot/i386/libi386/bootinfo.c @@ -59,10 +59,12 @@ int bi_getboothowto(char *kargs) { char *cp; + char *curpos, *next, *string; int howto; int active; int i; - + int vidconsole; + /* Parse kargs */ howto = 0; if (kargs != NULL) { @@ -117,10 +119,34 @@ bi_getboothowto(char *kargs) for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; - if (!strcmp(getenv("console"), "comconsole")) - howto |= RB_SERIAL; - if (!strcmp(getenv("console"), "nullconsole")) - howto |= RB_MUTE; + + /* Enable selected consoles */ + string = next = strdup(getenv("console")); + vidconsole = 0; + while (next != NULL) { + curpos = strsep(&next, " ,"); + if (*curpos == '\0') + continue; + if (!strcmp(curpos, "vidconsole")) + vidconsole = 1; + else if (!strcmp(curpos, "comconsole")) + howto |= RB_SERIAL; + else if (!strcmp(curpos, "nullconsole")) + howto |= RB_MUTE; + } + + if (vidconsole && (howto & RB_SERIAL)) + howto |= RB_MULTIPLE; + + /* + * XXX: Note that until the kernel is ready to respect multiple consoles + * for the boot messages, the first named console is the primary console + */ + if (!strcmp(string, "vidconsole")) + howto &= ~RB_SERIAL; + + free(string); + return(howto); } diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c index 2282309..1e2f568 100644 --- a/sys/boot/i386/loader/main.c +++ b/sys/boot/i386/loader/main.c @@ -98,12 +98,16 @@ main(void) * We can use printf() etc. once this is done. * If the previous boot stage has requested a serial console, prefer that. */ - if (initial_howto & RB_SERIAL) + if (initial_howto & RB_MULTIPLE) { + setenv("boot_multicons", "YES", 1); + if (initial_howto & RB_SERIAL) + setenv("console", "comconsole vidconsole", 1); + else + setenv("console", "vidconsole comconsole", 1); + } else if (initial_howto & RB_SERIAL) setenv("console", "comconsole", 1); - if (initial_howto & RB_MUTE) + else if (initial_howto & RB_MUTE) setenv("console", "nullconsole", 1); - if (initial_howto & RB_MULTIPLE) - setenv("boot_multicons", "YES", 1); cons_probe(); /* diff --git a/sys/boot/pc98/loader/main.c b/sys/boot/pc98/loader/main.c index 8b472c5..14354f3 100644 --- a/sys/boot/pc98/loader/main.c +++ b/sys/boot/pc98/loader/main.c @@ -98,12 +98,16 @@ main(void) * We can use printf() etc. once this is done. * If the previous boot stage has requested a serial console, prefer that. */ - if (initial_howto & RB_SERIAL) + if (initial_howto & RB_MULTIPLE) { + setenv("boot_multicons", "YES", 1); + if (initial_howto & RB_SERIAL) + setenv("console", "comconsole vidconsole", 1); + else + setenv("console", "vidconsole comconsole", 1); + } else if (initial_howto & RB_SERIAL) setenv("console", "comconsole", 1); - if (initial_howto & RB_MUTE) + else if (initial_howto & RB_MUTE) setenv("console", "nullconsole", 1); - if (initial_howto & RB_MULTIPLE) - setenv("boot_multicons", "YES", 1); cons_probe(); /* |