- 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
This commit is contained in:
+100
-46
@@ -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;
|
||||
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 @@ putchar(int c)
|
||||
consoles[cons]->c_out(c);
|
||||
}
|
||||
|
||||
static int
|
||||
cons_find(char *name)
|
||||
{
|
||||
int cons;
|
||||
|
||||
for (cons = 0; consoles[cons] != NULL; cons++)
|
||||
if (!strcmp(consoles[cons]->c_name, name))
|
||||
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.)
|
||||
* Find the console with the specified name.
|
||||
*/
|
||||
static int
|
||||
cons_set(struct env_var *ev, int flags, void *value)
|
||||
cons_find(const char *name)
|
||||
{
|
||||
int cons, active;
|
||||
int cons;
|
||||
|
||||
if ((value == NULL) || ((active = cons_find(value)) == -1)) {
|
||||
for (cons = 0; consoles[cons] != NULL; cons++)
|
||||
if (!strcmp(consoles[cons]->c_name, name))
|
||||
return (cons);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select one or more consoles.
|
||||
*/
|
||||
static int
|
||||
cons_set(struct env_var *ev, int flags, const void *value)
|
||||
{
|
||||
int cons;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
setenv("console", "comconsole", 1);
|
||||
if (initial_howto & RB_MUTE)
|
||||
setenv("console", "nullconsole", 1);
|
||||
if (initial_howto & RB_MULTIPLE)
|
||||
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);
|
||||
else if (initial_howto & RB_MUTE)
|
||||
setenv("console", "nullconsole", 1);
|
||||
cons_probe();
|
||||
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
setenv("console", "comconsole", 1);
|
||||
if (initial_howto & RB_MUTE)
|
||||
setenv("console", "nullconsole", 1);
|
||||
if (initial_howto & RB_MULTIPLE)
|
||||
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);
|
||||
else if (initial_howto & RB_MUTE)
|
||||
setenv("console", "nullconsole", 1);
|
||||
cons_probe();
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user