--- //depot/vendor/freebsd/src/sys/boot/common/console.c 2003/08/25 23:35:37 +++ //depot/user/jhb/boot/sys/boot/common/console.c 2005/04/14 22:32:21 @@ -35,14 +35,15 @@ * 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 @@ 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 @@ 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; + cons_change(prefconsole); + } else { + consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; + consoles[active]->c_init(0); + prefconsole = strdup(consoles[active]->c_name); + } + + 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); } - 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); } int @@ -128,46 +135,93 @@ 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); +} --- //depot/vendor/freebsd/src/sys/boot/common/loader.8 2005/02/17 11:15:58 +++ //depot/user/jhb/boot/sys/boot/common/loader.8 2005/04/14 22:06:27 @@ -65,6 +65,7 @@ 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 @@ -360,7 +361,11 @@ 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. --- //depot/vendor/freebsd/src/sys/boot/i386/boot2/boot2.c 2004/09/18 02:10:37 +++ //depot/user/jhb/boot/sys/boot/i386/boot2/boot2.c 2005/04/11 23:45:58 @@ -243,9 +243,9 @@ fsread(ino, cmd, sizeof(cmd)); if (*cmd) { - printf("%s: %s", PATH_CONFIG, cmd); if (parse()) autoboot = 0; + printf("%s: %s", PATH_CONFIG, cmd); /* Do not process this command twice */ *cmd = 0; } --- //depot/vendor/freebsd/src/sys/boot/i386/libi386/bootinfo.c 2004/12/01 05:01:14 +++ //depot/user/jhb/boot/sys/boot/i386/libi386/bootinfo.c 2005/04/14 22:06:49 @@ -59,10 +59,12 @@ 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 @@ 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); } --- //depot/vendor/freebsd/src/sys/boot/i386/libi386/devicename.c 2003/08/25 23:30:36 +++ //depot/user/jhb/boot/sys/boot/i386/libi386/devicename.c 2005/04/14 22:19:51 @@ -230,7 +230,7 @@ * Set currdev to suit the value being supplied in (value) */ int -i386_setcurrdev(struct env_var *ev, int flags, void *value) +i386_setcurrdev(struct env_var *ev, int flags, const void *value) { struct i386_devdesc *ncurr; int rv; --- //depot/vendor/freebsd/src/sys/boot/i386/libi386/libi386.h 2004/10/22 15:01:00 +++ //depot/user/jhb/boot/sys/boot/i386/libi386/libi386.h 2005/04/14 22:19:51 @@ -59,7 +59,7 @@ int i386_getdev(void **vdev, const char *devspec, const char **path); char *i386_fmtdev(void *vdev); -int i386_setcurrdev(struct env_var *ev, int flags, void *value); +int i386_setcurrdev(struct env_var *ev, int flags, const void *value); extern struct devdesc currdev; /* our current device */ --- //depot/vendor/freebsd/src/sys/boot/i386/loader/main.c 2004/10/22 15:01:00 +++ //depot/user/jhb/boot/sys/boot/i386/loader/main.c 2005/04/14 22:09:53 @@ -98,12 +98,16 @@ * 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(); /* --- //depot/vendor/freebsd/src/sys/boot/pc98/boot2/boot.c 2004/12/01 05:01:14 +++ //depot/user/jhb/boot/sys/boot/pc98/boot2/boot.c 2005/04/14 22:33:55 @@ -158,8 +158,8 @@ readfile("boot.config", boot_config, BOOT_CONFIG_SIZE); name = "/boot/loader"; if (boot_config[0] != '\0') { + getbootdev(boot_config, &loadflags); printf("boot.config: %s", boot_config); - getbootdev(boot_config, &loadflags); if (openrd() != 0) name = "kernel"; } --- //depot/vendor/freebsd/src/sys/boot/pc98/loader/main.c 2004/10/24 12:16:01 +++ //depot/user/jhb/boot/sys/boot/pc98/loader/main.c 2005/04/14 22:09:53 @@ -98,12 +98,16 @@ * 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(); /*