- 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:
parent
9389b62e52
commit
8b7c03a7a4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146698
@ -35,14 +35,15 @@ __FBSDID("$FreeBSD$");
|
|||||||
* Core console support
|
* Core console support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int cons_set(struct env_var *ev, int flags, void *value);
|
static int cons_set(struct env_var *ev, int flags, const void *value);
|
||||||
static int cons_find(char *name);
|
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
|
* Detect possible console(s) to use. If preferred console(s) have been
|
||||||
* is marked active. Also create the console variable.
|
* specified, mark them as active. Else, mark the first probed console
|
||||||
*
|
* as active. Also create the console variable.
|
||||||
* XXX Add logic for multiple console support.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
cons_probe(void)
|
cons_probe(void)
|
||||||
@ -64,6 +65,9 @@ cons_probe(void)
|
|||||||
if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT))
|
if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT))
|
||||||
active = cons;
|
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 */
|
/* Check to see if a console preference has already been registered */
|
||||||
prefconsole = getenv("console");
|
prefconsole = getenv("console");
|
||||||
@ -71,21 +75,24 @@ cons_probe(void)
|
|||||||
prefconsole = strdup(prefconsole);
|
prefconsole = strdup(prefconsole);
|
||||||
if (prefconsole != NULL) {
|
if (prefconsole != NULL) {
|
||||||
unsetenv("console"); /* we want to replace this */
|
unsetenv("console"); /* we want to replace this */
|
||||||
for (cons = 0; consoles[cons] != NULL; cons++)
|
cons_change(prefconsole);
|
||||||
/* look for the nominated console, use it if it's functional */
|
} else {
|
||||||
if (!strcmp(prefconsole, consoles[cons]->c_name) &&
|
consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
|
||||||
(consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)))
|
consoles[active]->c_init(0);
|
||||||
active = cons;
|
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);
|
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
|
int
|
||||||
@ -128,46 +135,93 @@ putchar(int c)
|
|||||||
consoles[cons]->c_out(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.
|
* Find the console with the specified name.
|
||||||
*
|
|
||||||
* XXX Note that the console system design allows for some extension
|
|
||||||
* here (eg. multiple consoles, input/output only, etc.)
|
|
||||||
*/
|
*/
|
||||||
static int
|
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)
|
if (value != NULL)
|
||||||
printf("no such console '%s'\n", (char *)value);
|
printf("no such console!\n");
|
||||||
printf("Available consoles:\n");
|
printf("Available consoles:\n");
|
||||||
for (cons = 0; consoles[cons] != NULL; cons++)
|
for (cons = 0; consoles[cons] != NULL; cons++)
|
||||||
printf(" %s\n", consoles[cons]->c_name);
|
printf(" %s\n", consoles[cons]->c_name);
|
||||||
return(CMD_ERROR);
|
return(CMD_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable all current consoles */
|
cons_change(value);
|
||||||
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);
|
|
||||||
|
|
||||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
||||||
return(CMD_OK);
|
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
|
variable, or set it to serial console
|
||||||
.Pq Dq comconsole
|
.Pq Dq comconsole
|
||||||
if the previous boot stage used that.
|
if the previous boot stage used that.
|
||||||
|
If multiple consoles are selected, they will be listed separated by spaces.
|
||||||
Then, devices are probed,
|
Then, devices are probed,
|
||||||
.Va currdev
|
.Va currdev
|
||||||
and
|
and
|
||||||
@ -391,7 +392,11 @@ List of semicolon-separated search path for bootable kernels.
|
|||||||
The default is
|
The default is
|
||||||
.Dq Li kernel .
|
.Dq Li kernel .
|
||||||
.It Va console
|
.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
|
.It Va currdev
|
||||||
Selects the default device.
|
Selects the default device.
|
||||||
Syntax for devices is odd.
|
Syntax for devices is odd.
|
||||||
|
@ -59,10 +59,12 @@ int
|
|||||||
bi_getboothowto(char *kargs)
|
bi_getboothowto(char *kargs)
|
||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
|
char *curpos, *next, *string;
|
||||||
int howto;
|
int howto;
|
||||||
int active;
|
int active;
|
||||||
int i;
|
int i;
|
||||||
|
int vidconsole;
|
||||||
|
|
||||||
/* Parse kargs */
|
/* Parse kargs */
|
||||||
howto = 0;
|
howto = 0;
|
||||||
if (kargs != NULL) {
|
if (kargs != NULL) {
|
||||||
@ -117,10 +119,34 @@ bi_getboothowto(char *kargs)
|
|||||||
for (i = 0; howto_names[i].ev != NULL; i++)
|
for (i = 0; howto_names[i].ev != NULL; i++)
|
||||||
if (getenv(howto_names[i].ev) != NULL)
|
if (getenv(howto_names[i].ev) != NULL)
|
||||||
howto |= howto_names[i].mask;
|
howto |= howto_names[i].mask;
|
||||||
if (!strcmp(getenv("console"), "comconsole"))
|
|
||||||
howto |= RB_SERIAL;
|
/* Enable selected consoles */
|
||||||
if (!strcmp(getenv("console"), "nullconsole"))
|
string = next = strdup(getenv("console"));
|
||||||
howto |= RB_MUTE;
|
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);
|
return(howto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,12 +98,16 @@ main(void)
|
|||||||
* We can use printf() etc. once this is done.
|
* We can use printf() etc. once this is done.
|
||||||
* If the previous boot stage has requested a serial console, prefer that.
|
* If the previous boot stage has requested a serial console, prefer that.
|
||||||
*/
|
*/
|
||||||
if (initial_howto & RB_SERIAL)
|
if (initial_howto & RB_MULTIPLE) {
|
||||||
setenv("console", "comconsole", 1);
|
|
||||||
if (initial_howto & RB_MUTE)
|
|
||||||
setenv("console", "nullconsole", 1);
|
|
||||||
if (initial_howto & RB_MULTIPLE)
|
|
||||||
setenv("boot_multicons", "YES", 1);
|
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();
|
cons_probe();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -98,12 +98,16 @@ main(void)
|
|||||||
* We can use printf() etc. once this is done.
|
* We can use printf() etc. once this is done.
|
||||||
* If the previous boot stage has requested a serial console, prefer that.
|
* If the previous boot stage has requested a serial console, prefer that.
|
||||||
*/
|
*/
|
||||||
if (initial_howto & RB_SERIAL)
|
if (initial_howto & RB_MULTIPLE) {
|
||||||
setenv("console", "comconsole", 1);
|
|
||||||
if (initial_howto & RB_MUTE)
|
|
||||||
setenv("console", "nullconsole", 1);
|
|
||||||
if (initial_howto & RB_MULTIPLE)
|
|
||||||
setenv("boot_multicons", "YES", 1);
|
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();
|
cons_probe();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user