- 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:
John Baldwin 2005-05-27 19:31:00 +00:00
parent 9389b62e52
commit 8b7c03a7a4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146698
5 changed files with 155 additions and 62 deletions

View File

@ -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);
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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();
/*

View File

@ -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();
/*