1*c84e4cc7SToomas Soome /*
2*c84e4cc7SToomas Soome * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
3*c84e4cc7SToomas Soome *
4*c84e4cc7SToomas Soome * Redistribution and use in source and binary forms, with or without
5*c84e4cc7SToomas Soome * modification, are permitted provided that the following conditions
6*c84e4cc7SToomas Soome * are met:
7*c84e4cc7SToomas Soome * 1. Redistributions of source code must retain the above copyright
8*c84e4cc7SToomas Soome * notice, this list of conditions and the following disclaimer.
9*c84e4cc7SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
10*c84e4cc7SToomas Soome * notice, this list of conditions and the following disclaimer in the
11*c84e4cc7SToomas Soome * documentation and/or other materials provided with the distribution.
12*c84e4cc7SToomas Soome *
13*c84e4cc7SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14*c84e4cc7SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*c84e4cc7SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*c84e4cc7SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17*c84e4cc7SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*c84e4cc7SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*c84e4cc7SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*c84e4cc7SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*c84e4cc7SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*c84e4cc7SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*c84e4cc7SToomas Soome * SUCH DAMAGE.
24*c84e4cc7SToomas Soome */
25*c84e4cc7SToomas Soome
26*c84e4cc7SToomas Soome #include <sys/cdefs.h>
27*c84e4cc7SToomas Soome
28*c84e4cc7SToomas Soome #include <stand.h>
29*c84e4cc7SToomas Soome #include <sys/errno.h>
30*c84e4cc7SToomas Soome #include <bootstrap.h>
31*c84e4cc7SToomas Soome
32*c84e4cc7SToomas Soome #include <efi.h>
33*c84e4cc7SToomas Soome #include <efilib.h>
34*c84e4cc7SToomas Soome
35*c84e4cc7SToomas Soome #include "loader_efi.h"
36*c84e4cc7SToomas Soome
37*c84e4cc7SToomas Soome static EFI_GUID serial = SERIAL_IO_PROTOCOL;
38*c84e4cc7SToomas Soome
39*c84e4cc7SToomas Soome #define COMC_TXWAIT 0x40000 /* transmit timeout */
40*c84e4cc7SToomas Soome
41*c84e4cc7SToomas Soome #ifndef COMSPEED
42*c84e4cc7SToomas Soome #define COMSPEED 9600
43*c84e4cc7SToomas Soome #endif
44*c84e4cc7SToomas Soome
45*c84e4cc7SToomas Soome struct serial {
46*c84e4cc7SToomas Soome uint64_t baudrate;
47*c84e4cc7SToomas Soome uint8_t databits;
48*c84e4cc7SToomas Soome EFI_PARITY_TYPE parity;
49*c84e4cc7SToomas Soome EFI_STOP_BITS_TYPE stopbits;
50*c84e4cc7SToomas Soome uint8_t ignore_cd; /* boolean */
51*c84e4cc7SToomas Soome uint8_t rtsdtr_off; /* boolean */
52*c84e4cc7SToomas Soome int ioaddr; /* index in handles array */
53*c84e4cc7SToomas Soome SERIAL_IO_INTERFACE *sio;
54*c84e4cc7SToomas Soome };
55*c84e4cc7SToomas Soome
56*c84e4cc7SToomas Soome static void comc_probe(struct console *);
57*c84e4cc7SToomas Soome static int comc_init(struct console *, int);
58*c84e4cc7SToomas Soome static void comc_putchar(struct console *, int);
59*c84e4cc7SToomas Soome static int comc_getchar(struct console *);
60*c84e4cc7SToomas Soome static int comc_ischar(struct console *);
61*c84e4cc7SToomas Soome static void comc_setup(struct console *);
62*c84e4cc7SToomas Soome static char *comc_asprint_mode(struct serial *);
63*c84e4cc7SToomas Soome static int comc_parse_mode(struct serial *, const char *);
64*c84e4cc7SToomas Soome static int comc_mode_set(struct env_var *, int, const void *);
65*c84e4cc7SToomas Soome static int comc_cd_set(struct env_var *, int, const void *);
66*c84e4cc7SToomas Soome static int comc_rtsdtr_set(struct env_var *, int, const void *);
67*c84e4cc7SToomas Soome
68*c84e4cc7SToomas Soome struct console ttya = {
69*c84e4cc7SToomas Soome .c_name = "ttya",
70*c84e4cc7SToomas Soome .c_desc = "serial port a",
71*c84e4cc7SToomas Soome .c_flags = 0,
72*c84e4cc7SToomas Soome .c_probe = comc_probe,
73*c84e4cc7SToomas Soome .c_init = comc_init,
74*c84e4cc7SToomas Soome .c_out = comc_putchar,
75*c84e4cc7SToomas Soome .c_in = comc_getchar,
76*c84e4cc7SToomas Soome .c_ready = comc_ischar,
77*c84e4cc7SToomas Soome .c_private = NULL
78*c84e4cc7SToomas Soome };
79*c84e4cc7SToomas Soome
80*c84e4cc7SToomas Soome struct console ttyb = {
81*c84e4cc7SToomas Soome .c_name = "ttyb",
82*c84e4cc7SToomas Soome .c_desc = "serial port b",
83*c84e4cc7SToomas Soome .c_flags = 0,
84*c84e4cc7SToomas Soome .c_probe = comc_probe,
85*c84e4cc7SToomas Soome .c_init = comc_init,
86*c84e4cc7SToomas Soome .c_out = comc_putchar,
87*c84e4cc7SToomas Soome .c_in = comc_getchar,
88*c84e4cc7SToomas Soome .c_ready = comc_ischar,
89*c84e4cc7SToomas Soome .c_private = NULL
90*c84e4cc7SToomas Soome };
91*c84e4cc7SToomas Soome
92*c84e4cc7SToomas Soome struct console ttyc = {
93*c84e4cc7SToomas Soome .c_name = "ttyc",
94*c84e4cc7SToomas Soome .c_desc = "serial port c",
95*c84e4cc7SToomas Soome .c_flags = 0,
96*c84e4cc7SToomas Soome .c_probe = comc_probe,
97*c84e4cc7SToomas Soome .c_init = comc_init,
98*c84e4cc7SToomas Soome .c_out = comc_putchar,
99*c84e4cc7SToomas Soome .c_in = comc_getchar,
100*c84e4cc7SToomas Soome .c_ready = comc_ischar,
101*c84e4cc7SToomas Soome .c_private = NULL
102*c84e4cc7SToomas Soome };
103*c84e4cc7SToomas Soome
104*c84e4cc7SToomas Soome struct console ttyd = {
105*c84e4cc7SToomas Soome .c_name = "ttyd",
106*c84e4cc7SToomas Soome .c_desc = "serial port d",
107*c84e4cc7SToomas Soome .c_flags = 0,
108*c84e4cc7SToomas Soome .c_probe = comc_probe,
109*c84e4cc7SToomas Soome .c_init = comc_init,
110*c84e4cc7SToomas Soome .c_out = comc_putchar,
111*c84e4cc7SToomas Soome .c_in = comc_getchar,
112*c84e4cc7SToomas Soome .c_ready = comc_ischar,
113*c84e4cc7SToomas Soome .c_private = NULL
114*c84e4cc7SToomas Soome };
115*c84e4cc7SToomas Soome
116*c84e4cc7SToomas Soome EFI_STATUS
efi_serial_init(EFI_HANDLE ** handlep,int * nhandles)117*c84e4cc7SToomas Soome efi_serial_init(EFI_HANDLE **handlep, int *nhandles)
118*c84e4cc7SToomas Soome {
119*c84e4cc7SToomas Soome UINTN bufsz = 0;
120*c84e4cc7SToomas Soome EFI_STATUS status;
121*c84e4cc7SToomas Soome EFI_HANDLE *handles;
122*c84e4cc7SToomas Soome
123*c84e4cc7SToomas Soome /*
124*c84e4cc7SToomas Soome * get buffer size
125*c84e4cc7SToomas Soome */
126*c84e4cc7SToomas Soome *nhandles = 0;
127*c84e4cc7SToomas Soome status = BS->LocateHandle(ByProtocol, &serial, NULL, &bufsz, handles);
128*c84e4cc7SToomas Soome if (status != EFI_BUFFER_TOO_SMALL)
129*c84e4cc7SToomas Soome return (status);
130*c84e4cc7SToomas Soome
131*c84e4cc7SToomas Soome if ((handles = malloc(bufsz)) == NULL)
132*c84e4cc7SToomas Soome return (ENOMEM);
133*c84e4cc7SToomas Soome
134*c84e4cc7SToomas Soome *nhandles = (int)(bufsz/sizeof (EFI_HANDLE));
135*c84e4cc7SToomas Soome /*
136*c84e4cc7SToomas Soome * get handle array
137*c84e4cc7SToomas Soome */
138*c84e4cc7SToomas Soome status = BS->LocateHandle(ByProtocol, &serial, NULL, &bufsz, handles);
139*c84e4cc7SToomas Soome if (EFI_ERROR(status)) {
140*c84e4cc7SToomas Soome free(handles);
141*c84e4cc7SToomas Soome *nhandles = 0;
142*c84e4cc7SToomas Soome } else
143*c84e4cc7SToomas Soome *handlep = handles;
144*c84e4cc7SToomas Soome return (status);
145*c84e4cc7SToomas Soome }
146*c84e4cc7SToomas Soome
147*c84e4cc7SToomas Soome static void
comc_probe(struct console * cp)148*c84e4cc7SToomas Soome comc_probe(struct console *cp)
149*c84e4cc7SToomas Soome {
150*c84e4cc7SToomas Soome EFI_STATUS status;
151*c84e4cc7SToomas Soome struct serial *port;
152*c84e4cc7SToomas Soome char name[20];
153*c84e4cc7SToomas Soome char value[20];
154*c84e4cc7SToomas Soome char *cons, *env;
155*c84e4cc7SToomas Soome EFI_HANDLE *handles = NULL; /* array of handles */
156*c84e4cc7SToomas Soome int nhandles = 0; /* number of handles in array */
157*c84e4cc7SToomas Soome
158*c84e4cc7SToomas Soome /* are we already set up? */
159*c84e4cc7SToomas Soome if (cp->c_private != NULL)
160*c84e4cc7SToomas Soome return;
161*c84e4cc7SToomas Soome
162*c84e4cc7SToomas Soome /* make sure the handles are available */
163*c84e4cc7SToomas Soome status = efi_serial_init(&handles, &nhandles);
164*c84e4cc7SToomas Soome
165*c84e4cc7SToomas Soome cp->c_private = malloc(sizeof (struct serial));
166*c84e4cc7SToomas Soome port = cp->c_private;
167*c84e4cc7SToomas Soome port->baudrate = COMSPEED;
168*c84e4cc7SToomas Soome
169*c84e4cc7SToomas Soome if (strcmp(cp->c_name, "ttya") == 0)
170*c84e4cc7SToomas Soome port->ioaddr = 0;
171*c84e4cc7SToomas Soome else if (strcmp(cp->c_name, "ttyb") == 0)
172*c84e4cc7SToomas Soome port->ioaddr = 1;
173*c84e4cc7SToomas Soome else if (strcmp(cp->c_name, "ttyc") == 0)
174*c84e4cc7SToomas Soome port->ioaddr = 2;
175*c84e4cc7SToomas Soome else if (strcmp(cp->c_name, "ttyd") == 0)
176*c84e4cc7SToomas Soome port->ioaddr = 3;
177*c84e4cc7SToomas Soome
178*c84e4cc7SToomas Soome if (port->ioaddr >= nhandles)
179*c84e4cc7SToomas Soome port->ioaddr = -1; /* invalid port */
180*c84e4cc7SToomas Soome
181*c84e4cc7SToomas Soome port->databits = 8; /* 8,n,1 */
182*c84e4cc7SToomas Soome port->parity = NoParity; /* 8,n,1 */
183*c84e4cc7SToomas Soome port->stopbits = OneStopBit; /* 8,n,1 */
184*c84e4cc7SToomas Soome port->ignore_cd = 1; /* ignore cd */
185*c84e4cc7SToomas Soome port->rtsdtr_off = 0; /* rts-dtr is on */
186*c84e4cc7SToomas Soome port->sio = NULL;
187*c84e4cc7SToomas Soome
188*c84e4cc7SToomas Soome if (port->ioaddr != -1) {
189*c84e4cc7SToomas Soome status = BS->OpenProtocol(handles[port->ioaddr],
190*c84e4cc7SToomas Soome &serial, (void**)&port->sio, IH, NULL,
191*c84e4cc7SToomas Soome EFI_OPEN_PROTOCOL_GET_PROTOCOL);
192*c84e4cc7SToomas Soome
193*c84e4cc7SToomas Soome if (EFI_ERROR(status))
194*c84e4cc7SToomas Soome port->ioaddr = -1; /* invalid port */
195*c84e4cc7SToomas Soome }
196*c84e4cc7SToomas Soome if (handles != NULL)
197*c84e4cc7SToomas Soome free(handles);
198*c84e4cc7SToomas Soome
199*c84e4cc7SToomas Soome snprintf(name, sizeof (name), "%s-mode", cp->c_name);
200*c84e4cc7SToomas Soome env = getenv(name);
201*c84e4cc7SToomas Soome
202*c84e4cc7SToomas Soome if (env != NULL)
203*c84e4cc7SToomas Soome (void) comc_parse_mode(port, env);
204*c84e4cc7SToomas Soome
205*c84e4cc7SToomas Soome env = comc_asprint_mode(port);
206*c84e4cc7SToomas Soome
207*c84e4cc7SToomas Soome if (env != NULL) {
208*c84e4cc7SToomas Soome unsetenv(name);
209*c84e4cc7SToomas Soome env_setenv(name, EV_VOLATILE, env, comc_mode_set, env_nounset);
210*c84e4cc7SToomas Soome free(env);
211*c84e4cc7SToomas Soome }
212*c84e4cc7SToomas Soome
213*c84e4cc7SToomas Soome snprintf(name, sizeof (name), "%s-ignore-cd", cp->c_name);
214*c84e4cc7SToomas Soome env = getenv(name);
215*c84e4cc7SToomas Soome if (env != NULL) {
216*c84e4cc7SToomas Soome if (strcmp(env, "true") == 0)
217*c84e4cc7SToomas Soome port->ignore_cd = 1;
218*c84e4cc7SToomas Soome else if (strcmp(env, "false") == 0)
219*c84e4cc7SToomas Soome port->ignore_cd = 0;
220*c84e4cc7SToomas Soome }
221*c84e4cc7SToomas Soome
222*c84e4cc7SToomas Soome snprintf(value, sizeof (value), "%s",
223*c84e4cc7SToomas Soome port->ignore_cd? "true" : "false");
224*c84e4cc7SToomas Soome unsetenv(name);
225*c84e4cc7SToomas Soome env_setenv(name, EV_VOLATILE, value, comc_cd_set, env_nounset);
226*c84e4cc7SToomas Soome
227*c84e4cc7SToomas Soome snprintf(name, sizeof (name), "%s-rts-dtr-off", cp->c_name);
228*c84e4cc7SToomas Soome env = getenv(name);
229*c84e4cc7SToomas Soome if (env != NULL) {
230*c84e4cc7SToomas Soome if (strcmp(env, "true") == 0)
231*c84e4cc7SToomas Soome port->rtsdtr_off = 1;
232*c84e4cc7SToomas Soome else if (strcmp(env, "false") == 0)
233*c84e4cc7SToomas Soome port->rtsdtr_off = 0;
234*c84e4cc7SToomas Soome }
235*c84e4cc7SToomas Soome
236*c84e4cc7SToomas Soome snprintf(value, sizeof (value), "%s",
237*c84e4cc7SToomas Soome port->rtsdtr_off? "true" : "false");
238*c84e4cc7SToomas Soome unsetenv(name);
239*c84e4cc7SToomas Soome env_setenv(name, EV_VOLATILE, value, comc_rtsdtr_set, env_nounset);
240*c84e4cc7SToomas Soome comc_setup(cp);
241*c84e4cc7SToomas Soome }
242*c84e4cc7SToomas Soome
243*c84e4cc7SToomas Soome static int
comc_init(struct console * cp,int arg __attribute ((unused)))244*c84e4cc7SToomas Soome comc_init(struct console *cp, int arg __attribute((unused)))
245*c84e4cc7SToomas Soome {
246*c84e4cc7SToomas Soome
247*c84e4cc7SToomas Soome comc_setup(cp);
248*c84e4cc7SToomas Soome
249*c84e4cc7SToomas Soome if ((cp->c_flags & (C_PRESENTIN | C_PRESENTOUT)) ==
250*c84e4cc7SToomas Soome (C_PRESENTIN | C_PRESENTOUT))
251*c84e4cc7SToomas Soome return (CMD_OK);
252*c84e4cc7SToomas Soome return (CMD_ERROR);
253*c84e4cc7SToomas Soome }
254*c84e4cc7SToomas Soome
255*c84e4cc7SToomas Soome static void
comc_putchar(struct console * cp,int c)256*c84e4cc7SToomas Soome comc_putchar(struct console *cp, int c)
257*c84e4cc7SToomas Soome {
258*c84e4cc7SToomas Soome int wait;
259*c84e4cc7SToomas Soome EFI_STATUS status;
260*c84e4cc7SToomas Soome UINTN bufsz = 1;
261*c84e4cc7SToomas Soome char cb = c;
262*c84e4cc7SToomas Soome struct serial *sp = cp->c_private;
263*c84e4cc7SToomas Soome
264*c84e4cc7SToomas Soome if (sp->sio == NULL)
265*c84e4cc7SToomas Soome return;
266*c84e4cc7SToomas Soome
267*c84e4cc7SToomas Soome for (wait = COMC_TXWAIT; wait > 0; wait--) {
268*c84e4cc7SToomas Soome status = sp->sio->Write(sp->sio, &bufsz, &cb);
269*c84e4cc7SToomas Soome if (status != EFI_TIMEOUT)
270*c84e4cc7SToomas Soome break;
271*c84e4cc7SToomas Soome }
272*c84e4cc7SToomas Soome }
273*c84e4cc7SToomas Soome
274*c84e4cc7SToomas Soome static int
comc_getchar(struct console * cp)275*c84e4cc7SToomas Soome comc_getchar(struct console *cp)
276*c84e4cc7SToomas Soome {
277*c84e4cc7SToomas Soome EFI_STATUS status;
278*c84e4cc7SToomas Soome UINTN bufsz = 1;
279*c84e4cc7SToomas Soome char c;
280*c84e4cc7SToomas Soome struct serial *sp = cp->c_private;
281*c84e4cc7SToomas Soome
282*c84e4cc7SToomas Soome if (sp->sio == NULL || !comc_ischar(cp))
283*c84e4cc7SToomas Soome return (-1);
284*c84e4cc7SToomas Soome
285*c84e4cc7SToomas Soome status = sp->sio->Read(sp->sio, &bufsz, &c);
286*c84e4cc7SToomas Soome if (EFI_ERROR(status) || bufsz == 0)
287*c84e4cc7SToomas Soome return (-1);
288*c84e4cc7SToomas Soome
289*c84e4cc7SToomas Soome return (c);
290*c84e4cc7SToomas Soome }
291*c84e4cc7SToomas Soome
292*c84e4cc7SToomas Soome static int
comc_ischar(struct console * cp)293*c84e4cc7SToomas Soome comc_ischar(struct console *cp)
294*c84e4cc7SToomas Soome {
295*c84e4cc7SToomas Soome EFI_STATUS status;
296*c84e4cc7SToomas Soome uint32_t control;
297*c84e4cc7SToomas Soome struct serial *sp = cp->c_private;
298*c84e4cc7SToomas Soome
299*c84e4cc7SToomas Soome if (sp->sio == NULL)
300*c84e4cc7SToomas Soome return (0);
301*c84e4cc7SToomas Soome
302*c84e4cc7SToomas Soome status = sp->sio->GetControl(sp->sio, &control);
303*c84e4cc7SToomas Soome if (EFI_ERROR(status))
304*c84e4cc7SToomas Soome return (0);
305*c84e4cc7SToomas Soome
306*c84e4cc7SToomas Soome return (!(status & EFI_SERIAL_INPUT_BUFFER_EMPTY));
307*c84e4cc7SToomas Soome }
308*c84e4cc7SToomas Soome
309*c84e4cc7SToomas Soome static char *
comc_asprint_mode(struct serial * sp)310*c84e4cc7SToomas Soome comc_asprint_mode(struct serial *sp)
311*c84e4cc7SToomas Soome {
312*c84e4cc7SToomas Soome char par = 'n', *buf;
313*c84e4cc7SToomas Soome int stop = 1;
314*c84e4cc7SToomas Soome
315*c84e4cc7SToomas Soome if (sp == NULL)
316*c84e4cc7SToomas Soome return (NULL);
317*c84e4cc7SToomas Soome
318*c84e4cc7SToomas Soome switch (sp->parity) {
319*c84e4cc7SToomas Soome case NoParity: par = 'n';
320*c84e4cc7SToomas Soome break;
321*c84e4cc7SToomas Soome case EvenParity: par = 'e';
322*c84e4cc7SToomas Soome break;
323*c84e4cc7SToomas Soome case OddParity: par = 'o';
324*c84e4cc7SToomas Soome break;
325*c84e4cc7SToomas Soome }
326*c84e4cc7SToomas Soome switch (sp->stopbits) {
327*c84e4cc7SToomas Soome case OneStopBit: stop = 1;
328*c84e4cc7SToomas Soome break;
329*c84e4cc7SToomas Soome case TwoStopBits: stop = 2;
330*c84e4cc7SToomas Soome break;
331*c84e4cc7SToomas Soome }
332*c84e4cc7SToomas Soome
333*c84e4cc7SToomas Soome asprintf(&buf, "%ju,%d,%c,%d,-", sp->baudrate, sp->databits, par, stop);
334*c84e4cc7SToomas Soome return (buf);
335*c84e4cc7SToomas Soome }
336*c84e4cc7SToomas Soome
337*c84e4cc7SToomas Soome static int
comc_parse_mode(struct serial * sp,const char * value)338*c84e4cc7SToomas Soome comc_parse_mode(struct serial *sp, const char *value)
339*c84e4cc7SToomas Soome {
340*c84e4cc7SToomas Soome unsigned long n;
341*c84e4cc7SToomas Soome uint64_t baudrate;
342*c84e4cc7SToomas Soome uint8_t databits = 8;
343*c84e4cc7SToomas Soome int parity = NoParity;
344*c84e4cc7SToomas Soome int stopbits = OneStopBit;
345*c84e4cc7SToomas Soome char *ep;
346*c84e4cc7SToomas Soome
347*c84e4cc7SToomas Soome if (value == NULL || *value == '\0')
348*c84e4cc7SToomas Soome return (CMD_ERROR);
349*c84e4cc7SToomas Soome
350*c84e4cc7SToomas Soome errno = 0;
351*c84e4cc7SToomas Soome n = strtoul(value, &ep, 10);
352*c84e4cc7SToomas Soome if (errno != 0 || *ep != ',')
353*c84e4cc7SToomas Soome return (CMD_ERROR);
354*c84e4cc7SToomas Soome baudrate = n;
355*c84e4cc7SToomas Soome
356*c84e4cc7SToomas Soome ep++;
357*c84e4cc7SToomas Soome n = strtoul(ep, &ep, 10);
358*c84e4cc7SToomas Soome if (errno != 0 || *ep != ',')
359*c84e4cc7SToomas Soome return (CMD_ERROR);
360*c84e4cc7SToomas Soome
361*c84e4cc7SToomas Soome switch (n) {
362*c84e4cc7SToomas Soome case 7: databits = 7;
363*c84e4cc7SToomas Soome break;
364*c84e4cc7SToomas Soome case 8: databits = 8;
365*c84e4cc7SToomas Soome break;
366*c84e4cc7SToomas Soome default:
367*c84e4cc7SToomas Soome return (CMD_ERROR);
368*c84e4cc7SToomas Soome }
369*c84e4cc7SToomas Soome
370*c84e4cc7SToomas Soome ep++;
371*c84e4cc7SToomas Soome switch (*ep++) {
372*c84e4cc7SToomas Soome case 'n': parity = NoParity;
373*c84e4cc7SToomas Soome break;
374*c84e4cc7SToomas Soome case 'e': parity = EvenParity;
375*c84e4cc7SToomas Soome break;
376*c84e4cc7SToomas Soome case 'o': parity = OddParity;
377*c84e4cc7SToomas Soome break;
378*c84e4cc7SToomas Soome default:
379*c84e4cc7SToomas Soome return (CMD_ERROR);
380*c84e4cc7SToomas Soome }
381*c84e4cc7SToomas Soome
382*c84e4cc7SToomas Soome if (*ep == ',')
383*c84e4cc7SToomas Soome ep++;
384*c84e4cc7SToomas Soome else
385*c84e4cc7SToomas Soome return (CMD_ERROR);
386*c84e4cc7SToomas Soome
387*c84e4cc7SToomas Soome switch (*ep++) {
388*c84e4cc7SToomas Soome case '1': stopbits = OneStopBit;
389*c84e4cc7SToomas Soome break;
390*c84e4cc7SToomas Soome case '2': stopbits = TwoStopBits;
391*c84e4cc7SToomas Soome break;
392*c84e4cc7SToomas Soome default:
393*c84e4cc7SToomas Soome return (CMD_ERROR);
394*c84e4cc7SToomas Soome }
395*c84e4cc7SToomas Soome
396*c84e4cc7SToomas Soome /* handshake is ignored, but we check syntax anyhow */
397*c84e4cc7SToomas Soome if (*ep == ',')
398*c84e4cc7SToomas Soome ep++;
399*c84e4cc7SToomas Soome else
400*c84e4cc7SToomas Soome return (CMD_ERROR);
401*c84e4cc7SToomas Soome
402*c84e4cc7SToomas Soome switch (*ep++) {
403*c84e4cc7SToomas Soome case '-':
404*c84e4cc7SToomas Soome case 'h':
405*c84e4cc7SToomas Soome case 's':
406*c84e4cc7SToomas Soome break;
407*c84e4cc7SToomas Soome default:
408*c84e4cc7SToomas Soome return (CMD_ERROR);
409*c84e4cc7SToomas Soome }
410*c84e4cc7SToomas Soome
411*c84e4cc7SToomas Soome if (*ep != '\0')
412*c84e4cc7SToomas Soome return (CMD_ERROR);
413*c84e4cc7SToomas Soome
414*c84e4cc7SToomas Soome sp->baudrate = baudrate;
415*c84e4cc7SToomas Soome sp->databits = databits;
416*c84e4cc7SToomas Soome sp->parity = parity;
417*c84e4cc7SToomas Soome sp->stopbits = stopbits;
418*c84e4cc7SToomas Soome return (CMD_OK);
419*c84e4cc7SToomas Soome }
420*c84e4cc7SToomas Soome
421*c84e4cc7SToomas Soome static struct console *
get_console(char * name)422*c84e4cc7SToomas Soome get_console(char *name)
423*c84e4cc7SToomas Soome {
424*c84e4cc7SToomas Soome struct console *cp = NULL;
425*c84e4cc7SToomas Soome
426*c84e4cc7SToomas Soome switch (name[3]) {
427*c84e4cc7SToomas Soome case 'a': cp = &ttya;
428*c84e4cc7SToomas Soome break;
429*c84e4cc7SToomas Soome case 'b': cp = &ttyb;
430*c84e4cc7SToomas Soome break;
431*c84e4cc7SToomas Soome case 'c': cp = &ttyc;
432*c84e4cc7SToomas Soome break;
433*c84e4cc7SToomas Soome case 'd': cp = &ttyd;
434*c84e4cc7SToomas Soome break;
435*c84e4cc7SToomas Soome }
436*c84e4cc7SToomas Soome return (cp);
437*c84e4cc7SToomas Soome }
438*c84e4cc7SToomas Soome
439*c84e4cc7SToomas Soome static int
comc_mode_set(struct env_var * ev,int flags,const void * value)440*c84e4cc7SToomas Soome comc_mode_set(struct env_var *ev, int flags, const void *value)
441*c84e4cc7SToomas Soome {
442*c84e4cc7SToomas Soome struct console *cp;
443*c84e4cc7SToomas Soome
444*c84e4cc7SToomas Soome if (value == NULL)
445*c84e4cc7SToomas Soome return (CMD_ERROR);
446*c84e4cc7SToomas Soome
447*c84e4cc7SToomas Soome if ((cp = get_console(ev->ev_name)) == NULL)
448*c84e4cc7SToomas Soome return (CMD_ERROR);
449*c84e4cc7SToomas Soome
450*c84e4cc7SToomas Soome if (comc_parse_mode(cp->c_private, value) == CMD_ERROR)
451*c84e4cc7SToomas Soome return (CMD_ERROR);
452*c84e4cc7SToomas Soome
453*c84e4cc7SToomas Soome comc_setup(cp);
454*c84e4cc7SToomas Soome env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
455*c84e4cc7SToomas Soome
456*c84e4cc7SToomas Soome return (CMD_OK);
457*c84e4cc7SToomas Soome }
458*c84e4cc7SToomas Soome
459*c84e4cc7SToomas Soome static int
comc_cd_set(struct env_var * ev,int flags,const void * value)460*c84e4cc7SToomas Soome comc_cd_set(struct env_var *ev, int flags, const void *value)
461*c84e4cc7SToomas Soome {
462*c84e4cc7SToomas Soome struct console *cp;
463*c84e4cc7SToomas Soome struct serial *sp;
464*c84e4cc7SToomas Soome
465*c84e4cc7SToomas Soome if (value == NULL)
466*c84e4cc7SToomas Soome return (CMD_ERROR);
467*c84e4cc7SToomas Soome
468*c84e4cc7SToomas Soome if ((cp = get_console(ev->ev_name)) == NULL)
469*c84e4cc7SToomas Soome return (CMD_ERROR);
470*c84e4cc7SToomas Soome
471*c84e4cc7SToomas Soome sp = cp->c_private;
472*c84e4cc7SToomas Soome if (strcmp(value, "true") == 0)
473*c84e4cc7SToomas Soome sp->ignore_cd = 1;
474*c84e4cc7SToomas Soome else if (strcmp(value, "false") == 0)
475*c84e4cc7SToomas Soome sp->ignore_cd = 0;
476*c84e4cc7SToomas Soome else
477*c84e4cc7SToomas Soome return (CMD_ERROR);
478*c84e4cc7SToomas Soome
479*c84e4cc7SToomas Soome comc_setup(cp);
480*c84e4cc7SToomas Soome env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
481*c84e4cc7SToomas Soome
482*c84e4cc7SToomas Soome return (CMD_OK);
483*c84e4cc7SToomas Soome }
484*c84e4cc7SToomas Soome
485*c84e4cc7SToomas Soome static int
comc_rtsdtr_set(struct env_var * ev,int flags,const void * value)486*c84e4cc7SToomas Soome comc_rtsdtr_set(struct env_var *ev, int flags, const void *value)
487*c84e4cc7SToomas Soome {
488*c84e4cc7SToomas Soome struct console *cp;
489*c84e4cc7SToomas Soome struct serial *sp;
490*c84e4cc7SToomas Soome
491*c84e4cc7SToomas Soome if (value == NULL)
492*c84e4cc7SToomas Soome return (CMD_ERROR);
493*c84e4cc7SToomas Soome
494*c84e4cc7SToomas Soome if ((cp = get_console(ev->ev_name)) == NULL)
495*c84e4cc7SToomas Soome return (CMD_ERROR);
496*c84e4cc7SToomas Soome
497*c84e4cc7SToomas Soome sp = cp->c_private;
498*c84e4cc7SToomas Soome if (strcmp(value, "true") == 0)
499*c84e4cc7SToomas Soome sp->rtsdtr_off = 1;
500*c84e4cc7SToomas Soome else if (strcmp(value, "false") == 0)
501*c84e4cc7SToomas Soome sp->rtsdtr_off = 0;
502*c84e4cc7SToomas Soome else
503*c84e4cc7SToomas Soome return (CMD_ERROR);
504*c84e4cc7SToomas Soome
505*c84e4cc7SToomas Soome comc_setup(cp);
506*c84e4cc7SToomas Soome env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
507*c84e4cc7SToomas Soome
508*c84e4cc7SToomas Soome return (CMD_OK);
509*c84e4cc7SToomas Soome }
510*c84e4cc7SToomas Soome
511*c84e4cc7SToomas Soome static void
comc_setup(struct console * cp)512*c84e4cc7SToomas Soome comc_setup(struct console *cp)
513*c84e4cc7SToomas Soome {
514*c84e4cc7SToomas Soome EFI_STATUS status;
515*c84e4cc7SToomas Soome UINT32 control;
516*c84e4cc7SToomas Soome struct serial *sp = cp->c_private;
517*c84e4cc7SToomas Soome
518*c84e4cc7SToomas Soome if ((cp->c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) == 0)
519*c84e4cc7SToomas Soome return;
520*c84e4cc7SToomas Soome
521*c84e4cc7SToomas Soome /* port is not usable */
522*c84e4cc7SToomas Soome if (sp->sio == NULL) {
523*c84e4cc7SToomas Soome cp->c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
524*c84e4cc7SToomas Soome return;
525*c84e4cc7SToomas Soome }
526*c84e4cc7SToomas Soome
527*c84e4cc7SToomas Soome cp->c_flags |= (C_PRESENTIN | C_PRESENTOUT);
528*c84e4cc7SToomas Soome status = sp->sio->Reset(sp->sio);
529*c84e4cc7SToomas Soome if (EFI_ERROR(status)) {
530*c84e4cc7SToomas Soome cp->c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
531*c84e4cc7SToomas Soome }
532*c84e4cc7SToomas Soome
533*c84e4cc7SToomas Soome status = sp->sio->SetAttributes(sp->sio, sp->baudrate, 0, 0, sp->parity,
534*c84e4cc7SToomas Soome sp->databits, sp->stopbits);
535*c84e4cc7SToomas Soome if (EFI_ERROR(status)) {
536*c84e4cc7SToomas Soome cp->c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
537*c84e4cc7SToomas Soome }
538*c84e4cc7SToomas Soome
539*c84e4cc7SToomas Soome if (sp->rtsdtr_off) {
540*c84e4cc7SToomas Soome status = sp->sio->GetControl(sp->sio, &control);
541*c84e4cc7SToomas Soome if (EFI_ERROR(status)) {
542*c84e4cc7SToomas Soome cp->c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
543*c84e4cc7SToomas Soome }
544*c84e4cc7SToomas Soome control &= ~(EFI_SERIAL_REQUEST_TO_SEND |
545*c84e4cc7SToomas Soome EFI_SERIAL_DATA_TERMINAL_READY);
546*c84e4cc7SToomas Soome status = sp->sio->SetControl(sp->sio, control);
547*c84e4cc7SToomas Soome if (EFI_ERROR(status)) {
548*c84e4cc7SToomas Soome cp->c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
549*c84e4cc7SToomas Soome }
550*c84e4cc7SToomas Soome }
551*c84e4cc7SToomas Soome }
552