summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-05-27 19:31:00 +0000
committerjhb <jhb@FreeBSD.org>2005-05-27 19:31:00 +0000
commit65ffcee053e76ba577b7e36112e113c94a943ade (patch)
tree859ee2269f72fa748bba4cbbbbab735220546737
parente2d11cf4d44df5cebaebaafbedc7183804582ff5 (diff)
downloadFreeBSD-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.c132
-rw-r--r--sys/boot/common/loader.87
-rw-r--r--sys/boot/i386/libi386/bootinfo.c36
-rw-r--r--sys/boot/i386/loader/main.c12
-rw-r--r--sys/boot/pc98/loader/main.c12
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();
/*
OpenPOWER on IntegriCloud