Prevent loader.conf load failure due to unknown console entries

When processing loader.conf if console contained an entry for an unsupported
console then cons_set would return an error refusing to set any console.

This has two side effects:

1. Forth would throw a syntax error and stop processing loader.conf at that
  point.
2. The value of console is ignored.

#1 Means other important loader.conf entries may not be processed, which is
   clearly undesirable.
#2 Means the users preference for console aren't applied even if they did
   contain valid options. Now we have support for multi boot paths from a
   single image e.g. bios and efi mode the console preference needs to deal
   with the need to set preference for more than one source.

Fix this by:
* Returning CMD_OK where possible from cons_set.
* Allowing set with at least one valid console to proceed.

Reviewed by:	allanjude
MFC after:	1 week
Sponsored by:	Multiplay
Differential Revision:	https://reviews.freebsd.org/D5018
This commit is contained in:
Steven Hartland 2016-01-21 15:27:44 +00:00
parent 2d1bee654a
commit 9e055ad144
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=294506

View File

@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
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);
static int cons_change(const char *string);
static int twiddle_set(struct env_var *ev, int flags, const void *value);
/*
@ -47,12 +47,12 @@ static int twiddle_set(struct env_var *ev, int flags, const void *value);
* as active. Also create the console variable.
*/
void
cons_probe(void)
cons_probe(void)
{
int cons;
int active;
char *prefconsole;
/* We want a callback to install the new value when this var changes. */
env_setenv("twiddle_divisor", EV_VOLATILE, "1", twiddle_set, env_nounset);
@ -162,54 +162,69 @@ cons_find(const char *name)
static int
cons_set(struct env_var *ev, int flags, const void *value)
{
int cons;
int ret;
if ((value == NULL) || (cons_check(value) == -1)) {
if (value != NULL)
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);
if ((value == NULL) || (cons_check(value) == 0)) {
/*
* Return CMD_OK instead of CMD_ERROR to prevent forth syntax error,
* which would prevent it processing any further loader.conf entries.
*/
return (CMD_OK);
}
cons_change(value);
ret = cons_change(value);
if (ret != CMD_OK)
return (ret);
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
* Check that at least one the consoles listed in *string is valid
*/
static int
cons_check(const char *string)
{
int cons;
int cons, found, failed;
char *curpos, *dup, *next;
dup = next = strdup(string);
cons = -1;
found = failed = 0;
while (next != NULL) {
curpos = strsep(&next, " ,");
if (*curpos != '\0') {
cons = cons_find(curpos);
if (cons == -1)
break;
if (cons == -1) {
printf("console %s is invalid!\n", curpos);
failed++;
} else {
found++;
}
}
}
free(dup);
return (cons);
if (found == 0)
printf("no valid consoles!\n");
if (found == 0 || failed != 0) {
printf("Available consoles:\n");
for (cons = 0; consoles[cons] != NULL; cons++)
printf(" %s\n", consoles[cons]->c_name);
}
return (found);
}
/*
* Activate all of the consoles listed in *string and disable all the others.
* Activate all the valid consoles listed in *string and disable all others.
*/
static void
static int
cons_change(const char *string)
{
int cons;
int cons, active;
char *curpos, *dup, *next;
/* Disable all consoles */
@ -219,6 +234,7 @@ cons_change(const char *string)
/* Enable selected consoles */
dup = next = strdup(string);
active = 0;
while (next != NULL) {
curpos = strsep(&next, " ,");
if (*curpos == '\0')
@ -227,14 +243,37 @@ cons_change(const char *string)
if (cons >= 0) {
consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
consoles[cons]->c_init(0);
if ((consoles[cons]->c_flags & (C_PRESENTIN | C_PRESENTOUT)) !=
(C_PRESENTIN | C_PRESENTOUT))
printf("console %s failed to initialize\n",
consoles[cons]->c_name);
if ((consoles[cons]->c_flags & (C_PRESENTIN | C_PRESENTOUT)) ==
(C_PRESENTIN | C_PRESENTOUT)) {
active++;
continue;
}
if (active != 0) {
/* If no consoles have initialised we wouldn't see this. */
printf("console %s failed to initialize\n", consoles[cons]->c_name);
}
}
}
free(dup);
if (active == 0) {
/* All requested consoles failed to initialise, try to recover. */
for (cons = 0; consoles[cons] != NULL; cons++) {
consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
consoles[cons]->c_init(0);
if ((consoles[cons]->c_flags &
(C_PRESENTIN | C_PRESENTOUT)) ==
(C_PRESENTIN | C_PRESENTOUT))
active++;
}
if (active == 0)
return (CMD_ERROR); /* Recovery failed. */
}
return (CMD_OK);
}
/*