122028508SToomas Soome /*
222028508SToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
322028508SToomas Soome * All rights reserved.
422028508SToomas Soome *
522028508SToomas Soome * Redistribution and use in source and binary forms, with or without
622028508SToomas Soome * modification, are permitted provided that the following conditions
722028508SToomas Soome * are met:
822028508SToomas Soome * 1. Redistributions of source code must retain the above copyright
922028508SToomas Soome * notice, this list of conditions and the following disclaimer.
1022028508SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
1122028508SToomas Soome * notice, this list of conditions and the following disclaimer in the
1222028508SToomas Soome * documentation and/or other materials provided with the distribution.
1322028508SToomas Soome *
1422028508SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1522028508SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1622028508SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1722028508SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1822028508SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1922028508SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2022028508SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2122028508SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2222028508SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2322028508SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2422028508SToomas Soome * SUCH DAMAGE.
2522028508SToomas Soome */
2622028508SToomas Soome
2722028508SToomas Soome #include <sys/cdefs.h>
2822028508SToomas Soome
2922028508SToomas Soome #include <stand.h>
3022028508SToomas Soome #include <string.h>
3122028508SToomas Soome
3222028508SToomas Soome #include "bootstrap.h"
3322028508SToomas Soome /*
3422028508SToomas Soome * Core console support
3522028508SToomas Soome */
3622028508SToomas Soome
3722028508SToomas Soome static int cons_set(struct env_var *ev, int flags, const void *value);
3822028508SToomas Soome static int cons_find(const char *name);
3922028508SToomas Soome static int cons_check(const char *string);
40f3ba9b4eSToomas Soome static int cons_change(const char *string, char **);
4122028508SToomas Soome static int twiddle_set(struct env_var *ev, int flags, const void *value);
4222028508SToomas Soome
43b72c8d00SToomas Soome static int last_input = -1; /* input device index */
44b72c8d00SToomas Soome
45b72c8d00SToomas Soome /*
46b72c8d00SToomas Soome * With multiple active console devices, return index of last input
47b72c8d00SToomas Soome * device, so we can set up os_console variable to denote console
48b72c8d00SToomas Soome * device for kernel.
49b72c8d00SToomas Soome *
50b72c8d00SToomas Soome * Please note, this feature can not really work with UEFI, because
51b72c8d00SToomas Soome * efi console input is returned from any device listed in ConIn,
52b72c8d00SToomas Soome * and we have no way to check which device from ConIn actually was
53b72c8d00SToomas Soome * generating input.
54b72c8d00SToomas Soome */
55b72c8d00SToomas Soome int
cons_inputdev(void)56b72c8d00SToomas Soome cons_inputdev(void)
57b72c8d00SToomas Soome {
58b72c8d00SToomas Soome int cons;
59b72c8d00SToomas Soome int flags = C_PRESENTIN | C_ACTIVEIN;
60b72c8d00SToomas Soome int active = 0;
61b72c8d00SToomas Soome
62b72c8d00SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++)
63b72c8d00SToomas Soome if ((consoles[cons]->c_flags & flags) == flags)
64b72c8d00SToomas Soome active++;
65b72c8d00SToomas Soome
66b72c8d00SToomas Soome /* With just one active console, we will not set os_console */
67b72c8d00SToomas Soome if (active == 1)
68b72c8d00SToomas Soome return (-1);
69b72c8d00SToomas Soome
70b72c8d00SToomas Soome return (last_input);
71b72c8d00SToomas Soome }
72b72c8d00SToomas Soome
7322028508SToomas Soome /*
74d3bd5503SToomas Soome * Return number of array slots.
75d3bd5503SToomas Soome */
76d3bd5503SToomas Soome uint_t
cons_array_size(void)77d3bd5503SToomas Soome cons_array_size(void)
78d3bd5503SToomas Soome {
79d3bd5503SToomas Soome uint_t n;
80d3bd5503SToomas Soome
81d3bd5503SToomas Soome if (consoles == NULL)
82d3bd5503SToomas Soome return (0);
83d3bd5503SToomas Soome
84d3bd5503SToomas Soome for (n = 0; consoles[n] != NULL; n++)
85d3bd5503SToomas Soome ;
86d3bd5503SToomas Soome return (n + 1);
87d3bd5503SToomas Soome }
88d3bd5503SToomas Soome
89*4ac2186dSToomas Soome struct console *
cons_get_console(const char * name)90*4ac2186dSToomas Soome cons_get_console(const char *name)
91*4ac2186dSToomas Soome {
92*4ac2186dSToomas Soome char port[5];
93*4ac2186dSToomas Soome
94*4ac2186dSToomas Soome (void) strlcpy(port, name, sizeof (port));
95*4ac2186dSToomas Soome for (uint_t i = 0; consoles[i] != NULL; i++) {
96*4ac2186dSToomas Soome if (strcmp(port, consoles[i]->c_name) == 0)
97*4ac2186dSToomas Soome return (consoles[i]);
98*4ac2186dSToomas Soome }
99*4ac2186dSToomas Soome
100*4ac2186dSToomas Soome printf("No such port: %s\n", port);
101*4ac2186dSToomas Soome return (NULL);
102*4ac2186dSToomas Soome }
103*4ac2186dSToomas Soome
104d3bd5503SToomas Soome static void
cons_add_dev(struct console * dev)105d3bd5503SToomas Soome cons_add_dev(struct console *dev)
106d3bd5503SToomas Soome {
107d3bd5503SToomas Soome uint_t c = cons_array_size();
108d3bd5503SToomas Soome uint_t n = 1;
109d3bd5503SToomas Soome struct console **tmp;
110d3bd5503SToomas Soome
111d3bd5503SToomas Soome if (c == 0)
112d3bd5503SToomas Soome n++;
113d3bd5503SToomas Soome tmp = realloc(consoles, (c + n) * sizeof (struct console *));
114d3bd5503SToomas Soome if (tmp == NULL)
115d3bd5503SToomas Soome return;
116d3bd5503SToomas Soome if (c > 0)
117d3bd5503SToomas Soome c--;
118d3bd5503SToomas Soome consoles = tmp;
119d3bd5503SToomas Soome consoles[c] = dev;
120d3bd5503SToomas Soome consoles[c + 1] = NULL;
121d3bd5503SToomas Soome }
122d3bd5503SToomas Soome
123d3bd5503SToomas Soome /*
12422028508SToomas Soome * Detect possible console(s) to use. If preferred console(s) have been
12522028508SToomas Soome * specified, mark them as active. Else, mark the first probed console
12622028508SToomas Soome * as active. Also create the console variable.
12722028508SToomas Soome */
12822028508SToomas Soome void
cons_probe(void)12922028508SToomas Soome cons_probe(void)
13022028508SToomas Soome {
13122028508SToomas Soome int cons;
13222028508SToomas Soome int active;
133f3ba9b4eSToomas Soome char *prefconsole, *list, *console;
13422028508SToomas Soome
135d3bd5503SToomas Soome /* Build list of consoles */
136d3bd5503SToomas Soome consoles = NULL;
137d3bd5503SToomas Soome for (cons = 0;; cons++) {
138d3bd5503SToomas Soome if (ct_list[cons].ct_dev != NULL) {
139d3bd5503SToomas Soome cons_add_dev(ct_list[cons].ct_dev);
140d3bd5503SToomas Soome continue;
141d3bd5503SToomas Soome }
142d3bd5503SToomas Soome if (ct_list[cons].ct_init != NULL) {
143d3bd5503SToomas Soome ct_list[cons].ct_init();
144d3bd5503SToomas Soome continue;
145d3bd5503SToomas Soome }
146d3bd5503SToomas Soome break;
147d3bd5503SToomas Soome }
148d3bd5503SToomas Soome
14922028508SToomas Soome /* We want a callback to install the new value when this var changes. */
150ae676b12SColin Percival (void) env_setenv("twiddle_divisor", EV_VOLATILE, "16", twiddle_set,
15122028508SToomas Soome env_nounset);
15222028508SToomas Soome
15322028508SToomas Soome /* Do all console probes */
15422028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++) {
15522028508SToomas Soome consoles[cons]->c_flags = 0;
15622028508SToomas Soome consoles[cons]->c_probe(consoles[cons]);
15722028508SToomas Soome }
15822028508SToomas Soome /* Now find the first working one */
15922028508SToomas Soome active = -1;
160f3ba9b4eSToomas Soome for (cons = 0; consoles[cons] != NULL; cons++) {
161f3ba9b4eSToomas Soome if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)) {
16222028508SToomas Soome active = cons;
163f3ba9b4eSToomas Soome break;
16422028508SToomas Soome }
165f3ba9b4eSToomas Soome }
166f3ba9b4eSToomas Soome
16722028508SToomas Soome /* Force a console even if all probes failed */
16822028508SToomas Soome if (active == -1)
16922028508SToomas Soome active = 0;
17022028508SToomas Soome
17122028508SToomas Soome /* Check to see if a console preference has already been registered */
172f3ba9b4eSToomas Soome list = NULL;
17322028508SToomas Soome prefconsole = getenv("console");
17422028508SToomas Soome if (prefconsole != NULL)
17522028508SToomas Soome prefconsole = strdup(prefconsole);
176f3ba9b4eSToomas Soome if (prefconsole == NULL)
17722028508SToomas Soome prefconsole = strdup(consoles[active]->c_name);
178f3ba9b4eSToomas Soome
179f3ba9b4eSToomas Soome /*
180f3ba9b4eSToomas Soome * unset "console", we need to create one with callbacks.
181f3ba9b4eSToomas Soome */
182f3ba9b4eSToomas Soome unsetenv("console");
183f3ba9b4eSToomas Soome cons_change(prefconsole, &list);
18422028508SToomas Soome
18522028508SToomas Soome printf("Consoles: ");
18622028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++)
18722028508SToomas Soome if (consoles[cons]->c_flags & (C_ACTIVEIN | C_ACTIVEOUT))
18822028508SToomas Soome printf("%s ", consoles[cons]->c_desc);
18922028508SToomas Soome printf("\n");
19022028508SToomas Soome
191f3ba9b4eSToomas Soome if (list != NULL)
192f3ba9b4eSToomas Soome console = list;
193f3ba9b4eSToomas Soome else
194f3ba9b4eSToomas Soome console = prefconsole;
195f3ba9b4eSToomas Soome
196ae676b12SColin Percival (void) env_setenv("console", EV_VOLATILE, console, cons_set,
19722028508SToomas Soome env_nounset);
198f3ba9b4eSToomas Soome
19922028508SToomas Soome free(prefconsole);
200f3ba9b4eSToomas Soome free(list);
20122028508SToomas Soome }
20222028508SToomas Soome
20322028508SToomas Soome void
cons_mode(int raw)20422028508SToomas Soome cons_mode(int raw)
20522028508SToomas Soome {
20622028508SToomas Soome int cons;
20722028508SToomas Soome
20822028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++) {
20922028508SToomas Soome if (raw == 0)
21022028508SToomas Soome consoles[cons]->c_flags &= ~C_MODERAW;
21122028508SToomas Soome else
21222028508SToomas Soome consoles[cons]->c_flags |= C_MODERAW;
21322028508SToomas Soome }
21422028508SToomas Soome }
21522028508SToomas Soome
21622028508SToomas Soome int
getchar(void)21722028508SToomas Soome getchar(void)
21822028508SToomas Soome {
21922028508SToomas Soome int cons;
22022028508SToomas Soome int flags = C_PRESENTIN | C_ACTIVEIN;
22122028508SToomas Soome int rv;
22222028508SToomas Soome
22322028508SToomas Soome /*
22422028508SToomas Soome * Loop forever polling all active consoles. Somewhat strangely,
22522028508SToomas Soome * this code expects all ->c_in() implementations to effectively do an
22622028508SToomas Soome * ischar() check first, returning -1 if there's not a char ready.
22722028508SToomas Soome */
22822028508SToomas Soome for (;;) {
22922028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++) {
230b72c8d00SToomas Soome if ((consoles[cons]->c_flags & flags) == flags) {
231b72c8d00SToomas Soome rv = consoles[cons]->c_in(consoles[cons]);
232b72c8d00SToomas Soome if (rv != -1) {
233b72c8d00SToomas Soome #ifndef EFI
234b72c8d00SToomas Soome last_input = cons;
235b72c8d00SToomas Soome #endif
23622028508SToomas Soome return (rv);
23722028508SToomas Soome }
238b72c8d00SToomas Soome }
239b72c8d00SToomas Soome }
24022028508SToomas Soome delay(30 * 1000); /* delay 30ms */
24122028508SToomas Soome }
24222028508SToomas Soome }
24322028508SToomas Soome
24422028508SToomas Soome int
ischar(void)24522028508SToomas Soome ischar(void)
24622028508SToomas Soome {
24722028508SToomas Soome int cons;
24822028508SToomas Soome
24922028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++)
25022028508SToomas Soome if ((consoles[cons]->c_flags & (C_PRESENTIN | C_ACTIVEIN)) ==
25122028508SToomas Soome (C_PRESENTIN | C_ACTIVEIN) &&
25222028508SToomas Soome (consoles[cons]->c_ready(consoles[cons]) != 0))
25322028508SToomas Soome return (1);
25422028508SToomas Soome return (0);
25522028508SToomas Soome }
25622028508SToomas Soome
25722028508SToomas Soome void
putchar(int c)25822028508SToomas Soome putchar(int c)
25922028508SToomas Soome {
26022028508SToomas Soome int cons;
26122028508SToomas Soome
26222028508SToomas Soome /* Expand newlines if not in raw mode */
26322028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++)
26422028508SToomas Soome if ((consoles[cons]->c_flags & (C_PRESENTOUT | C_ACTIVEOUT)) ==
26522028508SToomas Soome (C_PRESENTOUT | C_ACTIVEOUT)) {
26622028508SToomas Soome if (c == '\n' &&
26722028508SToomas Soome (consoles[cons]->c_flags & C_MODERAW) == 0)
26822028508SToomas Soome consoles[cons]->c_out(consoles[cons], '\r');
26922028508SToomas Soome consoles[cons]->c_out(consoles[cons], c);
27022028508SToomas Soome }
27122028508SToomas Soome }
27222028508SToomas Soome
27322028508SToomas Soome /*
27422028508SToomas Soome * Find the console with the specified name.
27522028508SToomas Soome */
27622028508SToomas Soome static int
cons_find(const char * name)27722028508SToomas Soome cons_find(const char *name)
27822028508SToomas Soome {
27922028508SToomas Soome int cons;
28022028508SToomas Soome
28122028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++)
28222028508SToomas Soome if (strcmp(consoles[cons]->c_name, name) == 0)
28322028508SToomas Soome return (cons);
28422028508SToomas Soome return (-1);
28522028508SToomas Soome }
28622028508SToomas Soome
28722028508SToomas Soome /*
28822028508SToomas Soome * Select one or more consoles.
28922028508SToomas Soome */
29022028508SToomas Soome static int
cons_set(struct env_var * ev,int flags,const void * value)29122028508SToomas Soome cons_set(struct env_var *ev, int flags, const void *value)
29222028508SToomas Soome {
293f3ba9b4eSToomas Soome int ret;
294f3ba9b4eSToomas Soome char *list;
29522028508SToomas Soome
29622028508SToomas Soome if ((value == NULL) || (cons_check(value) == 0)) {
29722028508SToomas Soome /*
29822028508SToomas Soome * Return CMD_OK instead of CMD_ERROR to prevent forth syntax
29922028508SToomas Soome * error, which would prevent it processing any further
30022028508SToomas Soome * loader.conf entries.
30122028508SToomas Soome */
30222028508SToomas Soome return (CMD_OK);
30322028508SToomas Soome }
30422028508SToomas Soome
305f3ba9b4eSToomas Soome list = NULL;
306f3ba9b4eSToomas Soome ret = cons_change(value, &list);
30722028508SToomas Soome if (ret != CMD_OK)
30822028508SToomas Soome return (ret);
30922028508SToomas Soome
31022028508SToomas Soome /*
31122028508SToomas Soome * set console variable.
31222028508SToomas Soome */
31322028508SToomas Soome if (list != NULL) {
31422028508SToomas Soome (void) env_setenv(ev->ev_name, flags | EV_NOHOOK, list,
31522028508SToomas Soome NULL, NULL);
31622028508SToomas Soome } else {
31722028508SToomas Soome (void) env_setenv(ev->ev_name, flags | EV_NOHOOK, value,
31822028508SToomas Soome NULL, NULL);
31922028508SToomas Soome }
32022028508SToomas Soome free(list);
321f3ba9b4eSToomas Soome return (ret);
32222028508SToomas Soome }
32322028508SToomas Soome
32422028508SToomas Soome /*
32522028508SToomas Soome * Check that at least one the consoles listed in *string is valid
32622028508SToomas Soome */
32722028508SToomas Soome static int
cons_check(const char * string)32822028508SToomas Soome cons_check(const char *string)
32922028508SToomas Soome {
33022028508SToomas Soome int cons, found, failed;
33122028508SToomas Soome char *curpos, *dup, *next;
33222028508SToomas Soome
33322028508SToomas Soome dup = next = strdup(string);
33422028508SToomas Soome found = failed = 0;
33522028508SToomas Soome while (next != NULL) {
33622028508SToomas Soome curpos = strsep(&next, " ,");
33722028508SToomas Soome if (*curpos != '\0') {
33822028508SToomas Soome cons = cons_find(curpos);
33922028508SToomas Soome if (cons == -1) {
34022028508SToomas Soome printf("console %s is invalid!\n", curpos);
34122028508SToomas Soome failed++;
34222028508SToomas Soome } else {
34322028508SToomas Soome if ((consoles[cons]->c_flags &
34422028508SToomas Soome (C_PRESENTIN | C_PRESENTOUT)) !=
34522028508SToomas Soome (C_PRESENTIN | C_PRESENTOUT)) {
34622028508SToomas Soome failed++;
34722028508SToomas Soome } else
34822028508SToomas Soome found++;
34922028508SToomas Soome }
35022028508SToomas Soome }
35122028508SToomas Soome }
35222028508SToomas Soome
35322028508SToomas Soome free(dup);
35422028508SToomas Soome
35522028508SToomas Soome if (found == 0)
35622028508SToomas Soome printf("no valid consoles!\n");
35722028508SToomas Soome
35822028508SToomas Soome if (found == 0 || failed != 0) {
35922028508SToomas Soome printf("Available consoles:\n");
36022028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++) {
36122028508SToomas Soome printf(" %s", consoles[cons]->c_name);
36222028508SToomas Soome if (consoles[cons]->c_devinfo != NULL)
36322028508SToomas Soome consoles[cons]->c_devinfo(consoles[cons]);
36422028508SToomas Soome printf("\n");
36522028508SToomas Soome }
36622028508SToomas Soome }
36722028508SToomas Soome
36822028508SToomas Soome return (found);
36922028508SToomas Soome }
37022028508SToomas Soome
371f3ba9b4eSToomas Soome /*
372f3ba9b4eSToomas Soome * Helper function to build string with list of console names.
373f3ba9b4eSToomas Soome */
374f3ba9b4eSToomas Soome static char *
cons_add_list(char * list,const char * value)375f3ba9b4eSToomas Soome cons_add_list(char *list, const char *value)
376f3ba9b4eSToomas Soome {
377f3ba9b4eSToomas Soome char *tmp;
378f3ba9b4eSToomas Soome
379f3ba9b4eSToomas Soome if (list == NULL)
380f3ba9b4eSToomas Soome return (strdup(value));
381f3ba9b4eSToomas Soome
382f3ba9b4eSToomas Soome if (asprintf(&tmp, "%s,%s", list, value) > 0) {
383f3ba9b4eSToomas Soome free(list);
384f3ba9b4eSToomas Soome list = tmp;
385f3ba9b4eSToomas Soome }
386f3ba9b4eSToomas Soome return (list);
387f3ba9b4eSToomas Soome }
38822028508SToomas Soome
38922028508SToomas Soome /*
390f3ba9b4eSToomas Soome * Activate all the valid consoles listed in string and disable all others.
391f3ba9b4eSToomas Soome * Return comma separated string with list of activated console names.
39222028508SToomas Soome */
39322028508SToomas Soome static int
cons_change(const char * string,char ** list)394f3ba9b4eSToomas Soome cons_change(const char *string, char **list)
39522028508SToomas Soome {
396f3ba9b4eSToomas Soome int cons, active, rv;
39722028508SToomas Soome char *curpos, *dup, *next;
39822028508SToomas Soome
39922028508SToomas Soome /* Disable all consoles */
40022028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++) {
40122028508SToomas Soome consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT);
40222028508SToomas Soome }
40322028508SToomas Soome
40422028508SToomas Soome /* Enable selected consoles */
40522028508SToomas Soome dup = next = strdup(string);
40622028508SToomas Soome active = 0;
407f3ba9b4eSToomas Soome *list = NULL;
408f3ba9b4eSToomas Soome rv = CMD_OK;
40922028508SToomas Soome while (next != NULL) {
41022028508SToomas Soome curpos = strsep(&next, " ,");
41122028508SToomas Soome if (*curpos == '\0')
41222028508SToomas Soome continue;
41322028508SToomas Soome cons = cons_find(curpos);
41422028508SToomas Soome if (cons >= 0) {
41522028508SToomas Soome consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
41622028508SToomas Soome consoles[cons]->c_init(consoles[cons], 0);
41722028508SToomas Soome if ((consoles[cons]->c_flags &
41822028508SToomas Soome (C_ACTIVEIN | C_ACTIVEOUT)) ==
41922028508SToomas Soome (C_ACTIVEIN | C_ACTIVEOUT)) {
42022028508SToomas Soome active++;
421f3ba9b4eSToomas Soome *list = cons_add_list(*list, curpos);
42222028508SToomas Soome continue;
42322028508SToomas Soome }
42422028508SToomas Soome
42522028508SToomas Soome if (active != 0) {
42622028508SToomas Soome /*
42722028508SToomas Soome * If no consoles have initialised we wouldn't
42822028508SToomas Soome * see this.
42922028508SToomas Soome */
43022028508SToomas Soome printf("console %s failed to initialize\n",
43122028508SToomas Soome consoles[cons]->c_name);
43222028508SToomas Soome }
43322028508SToomas Soome }
43422028508SToomas Soome }
43522028508SToomas Soome
43622028508SToomas Soome free(dup);
43722028508SToomas Soome
43822028508SToomas Soome if (active == 0) {
43922028508SToomas Soome /*
44022028508SToomas Soome * All requested consoles failed to initialise, try to recover.
44122028508SToomas Soome */
44222028508SToomas Soome for (cons = 0; consoles[cons] != NULL; cons++) {
44322028508SToomas Soome consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
44422028508SToomas Soome consoles[cons]->c_init(consoles[cons], 0);
44522028508SToomas Soome if ((consoles[cons]->c_flags &
44622028508SToomas Soome (C_ACTIVEIN | C_ACTIVEOUT)) ==
447f3ba9b4eSToomas Soome (C_ACTIVEIN | C_ACTIVEOUT)) {
44822028508SToomas Soome active++;
449f3ba9b4eSToomas Soome *list = cons_add_list(*list,
450f3ba9b4eSToomas Soome consoles[cons]->c_name);
451f3ba9b4eSToomas Soome }
45222028508SToomas Soome }
45322028508SToomas Soome
45422028508SToomas Soome if (active == 0)
455f3ba9b4eSToomas Soome rv = CMD_ERROR; /* Recovery failed. */
45622028508SToomas Soome }
45722028508SToomas Soome
458f3ba9b4eSToomas Soome return (rv);
45922028508SToomas Soome }
46022028508SToomas Soome
46122028508SToomas Soome /*
46222028508SToomas Soome * Change the twiddle divisor.
46322028508SToomas Soome *
46422028508SToomas Soome * The user can set the twiddle_divisor variable to directly control how fast
46522028508SToomas Soome * the progress twiddle spins, useful for folks with slow serial consoles. The
46622028508SToomas Soome * code to monitor changes to the variable and propagate them to the twiddle
46722028508SToomas Soome * routines has to live somewhere. Twiddling is console-related so it's here.
46822028508SToomas Soome */
46922028508SToomas Soome static int
twiddle_set(struct env_var * ev,int flags,const void * value)47022028508SToomas Soome twiddle_set(struct env_var *ev, int flags, const void *value)
47122028508SToomas Soome {
47222028508SToomas Soome ulong_t tdiv;
47322028508SToomas Soome char *eptr;
47422028508SToomas Soome
47522028508SToomas Soome tdiv = strtoul(value, &eptr, 0);
47622028508SToomas Soome if (*(const char *)value == 0 || *eptr != 0) {
47722028508SToomas Soome printf("invalid twiddle_divisor '%s'\n", (const char *)value);
47822028508SToomas Soome return (CMD_ERROR);
47922028508SToomas Soome }
48022028508SToomas Soome twiddle_divisor((uint_t)tdiv);
481ae676b12SColin Percival (void) env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
48222028508SToomas Soome
48322028508SToomas Soome return (CMD_OK);
48422028508SToomas Soome }
48522028508SToomas Soome
48622028508SToomas Soome COMMAND_SET(console, "console", "console info", command_console);
48722028508SToomas Soome
48822028508SToomas Soome static int
command_console(int argc,char * argv[])48922028508SToomas Soome command_console(int argc, char *argv[])
49022028508SToomas Soome {
49122028508SToomas Soome if (argc > 1)
49222028508SToomas Soome printf("%s: list info about available consoles\n", argv[0]);
49322028508SToomas Soome
49422028508SToomas Soome printf("Current console: %s\n", getenv("console"));
49522028508SToomas Soome printf("Available consoles:\n");
49622028508SToomas Soome for (int cons = 0; consoles[cons] != NULL; cons++) {
49722028508SToomas Soome printf(" %s", consoles[cons]->c_name);
49822028508SToomas Soome if (consoles[cons]->c_devinfo != NULL)
49922028508SToomas Soome consoles[cons]->c_devinfo(consoles[cons]);
50022028508SToomas Soome printf("\n");
50122028508SToomas Soome }
50222028508SToomas Soome
50322028508SToomas Soome return (CMD_OK);
50422028508SToomas Soome }
505