Print this page
12220 loader multi-console shouldn't override bootenv.rc
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/boot/boot_console.c
+++ new/usr/src/uts/i86pc/boot/boot_console.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2012 Gary Mills
23 + * Copyright 2020 Joyent, Inc.
23 24 *
24 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 26 * Use is subject to license terms.
26 27 */
27 28
29 +/*
30 + * Boot console support. Most of the file is shared between dboot, and the
31 + * early kernel / fakebop.
32 + */
33 +
28 34 #include <sys/types.h>
29 35 #include <sys/systm.h>
30 36 #include <sys/archsystm.h>
31 37 #include <sys/framebuffer.h>
32 38 #include <sys/boot_console.h>
33 39 #include <sys/panic.h>
34 40 #include <sys/ctype.h>
35 41 #include <sys/ascii.h>
36 42 #include <sys/vgareg.h>
37 43 #if defined(__xpv)
38 44 #include <sys/hypervisor.h>
39 45 #endif /* __xpv */
40 46
41 47 #include "boot_console_impl.h"
42 48 #include "boot_serial.h"
43 49
44 50 #if defined(_BOOT)
45 51 #include <dboot/dboot_asm.h>
46 52 #include <dboot/dboot_xboot.h>
47 53 #else /* _BOOT */
48 54 #include <sys/bootconf.h>
49 55 #if defined(__xpv)
50 56 #include <sys/evtchn_impl.h>
51 57 #endif /* __xpv */
52 58 static char *defcons_buf;
53 59 static char *defcons_cur;
54 60 #endif /* _BOOT */
55 61
56 62 #if defined(__xpv)
57 63 extern void bcons_init_xen(char *);
58 64 extern void bcons_putchar_xen(int);
59 65 extern int bcons_getchar_xen(void);
60 66 extern int bcons_ischar_xen(void);
61 67 #endif /* __xpv */
62 68
63 69 fb_info_t fb_info;
64 70 static bcons_dev_t bcons_dev; /* Device callbacks */
65 71 static int console = CONS_SCREEN_TEXT;
66 72 static int diag = CONS_INVALID;
67 73 static int tty_num = 0;
68 74 static int tty_addr[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
69 75 static char *boot_line;
70 76 static struct boot_env {
71 77 char *be_env; /* ends with double ascii nul */
72 78 size_t be_size; /* size of the environment, including nul */
73 79 } boot_env;
74 80
75 81 /*
76 82 * Simple console terminal emulator for early boot.
77 83 * We need this to support kmdb, all other console output is supposed
78 84 * to be simple text output.
79 85 */
80 86 typedef enum btem_state_type {
81 87 A_STATE_START,
82 88 A_STATE_ESC,
83 89 A_STATE_CSI,
84 90 A_STATE_CSI_QMARK,
85 91 A_STATE_CSI_EQUAL
86 92 } btem_state_type_t;
87 93
88 94 #define BTEM_MAXPARAMS 5
89 95 typedef struct btem_state {
90 96 btem_state_type_t btem_state;
91 97 boolean_t btem_gotparam;
92 98 int btem_curparam;
93 99 int btem_paramval;
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
94 100 int btem_params[BTEM_MAXPARAMS];
95 101 } btem_state_t;
96 102
97 103 static btem_state_t boot_tem;
98 104
99 105 static int serial_ischar(void);
100 106 static int serial_getchar(void);
101 107 static void serial_putchar(int);
102 108 static void serial_adjust_prop(void);
103 109
110 +static void defcons_putchar(int);
111 +
104 112 #if !defined(_BOOT)
105 -/* Set if the console or mode are expressed in the boot line */
106 -static int console_set, console_mode_set;
113 +static boolean_t bootprop_set_tty_mode;
107 114 #endif
108 115
109 116 #if defined(__xpv)
110 117 static int console_hypervisor_redirect = B_FALSE;
111 118 static int console_hypervisor_device = CONS_INVALID;
112 119 static int console_hypervisor_tty_num = 0;
113 120
114 121 /* Obtain the hypervisor console type */
115 122 int
116 123 console_hypervisor_dev_type(int *tnum)
117 124 {
118 125 if (tnum != NULL)
119 126 *tnum = console_hypervisor_tty_num;
120 127 return (console_hypervisor_device);
121 128 }
122 129 #endif /* __xpv */
123 130
124 131 static int port;
125 132
126 133 static void
127 134 serial_init(void)
128 135 {
129 136 port = tty_addr[tty_num];
130 137
131 138 outb(port + ISR, 0x20);
132 139 if (inb(port + ISR) & 0x20) {
133 140 /*
134 141 * 82510 chip is present
135 142 */
136 143 outb(port + DAT+7, 0x04); /* clear status */
137 144 outb(port + ISR, 0x40); /* set to bank 2 */
138 145 outb(port + MCR, 0x08); /* IMD */
139 146 outb(port + DAT, 0x21); /* FMD */
140 147 outb(port + ISR, 0x00); /* set to bank 0 */
141 148 } else {
142 149 /*
143 150 * set the UART in FIFO mode if it has FIFO buffers.
144 151 * use 16550 fifo reset sequence specified in NS
145 152 * application note. disable fifos until chip is
146 153 * initialized.
147 154 */
148 155 outb(port + FIFOR, 0x00); /* clear */
149 156 outb(port + FIFOR, FIFO_ON); /* enable */
150 157 outb(port + FIFOR, FIFO_ON|FIFORXFLSH); /* reset */
151 158 outb(port + FIFOR,
152 159 FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80);
153 160 if ((inb(port + ISR) & 0xc0) != 0xc0) {
154 161 /*
155 162 * no fifo buffers so disable fifos.
156 163 * this is true for 8250's
157 164 */
158 165 outb(port + FIFOR, 0x00);
159 166 }
160 167 }
161 168
162 169 /* disable interrupts */
163 170 outb(port + ICR, 0);
164 171
165 172 #if !defined(_BOOT)
166 173 if (IN_XPV_PANIC())
167 174 return;
168 175 #endif
169 176
170 177 /* adjust setting based on tty properties */
171 178 serial_adjust_prop();
172 179 }
173 180
174 181 /* Advance str pointer past white space */
175 182 #define EAT_WHITE_SPACE(str) { \
176 183 while ((*str != '\0') && ISSPACE(*str)) \
177 184 str++; \
178 185 }
179 186
180 187 /*
181 188 * boot_line is set when we call here. Search it for the argument name,
182 189 * and if found, return a pointer to it.
183 190 */
184 191 static char *
185 192 find_boot_line_prop(const char *name)
186 193 {
187 194 char *ptr;
188 195 char *ret = NULL;
189 196 char end_char;
190 197 size_t len;
191 198
192 199 if (boot_line == NULL)
193 200 return (NULL);
194 201
195 202 len = strlen(name);
196 203
197 204 /*
198 205 * We have two nested loops here: the outer loop discards all options
199 206 * except -B, and the inner loop parses the -B options looking for
200 207 * the one we're interested in.
201 208 */
202 209 for (ptr = boot_line; *ptr != '\0'; ptr++) {
203 210 EAT_WHITE_SPACE(ptr);
204 211
205 212 if (*ptr == '-') {
206 213 ptr++;
207 214 while ((*ptr != '\0') && (*ptr != 'B') &&
208 215 !ISSPACE(*ptr))
209 216 ptr++;
210 217 if (*ptr == '\0')
211 218 goto out;
212 219 else if (*ptr != 'B')
213 220 continue;
214 221 } else {
215 222 while ((*ptr != '\0') && !ISSPACE(*ptr))
216 223 ptr++;
217 224 if (*ptr == '\0')
218 225 goto out;
219 226 continue;
220 227 }
221 228
222 229 do {
223 230 ptr++;
224 231 EAT_WHITE_SPACE(ptr);
225 232
226 233 if ((strncmp(ptr, name, len) == 0) &&
227 234 (ptr[len] == '=')) {
228 235 ptr += len + 1;
229 236 if ((*ptr == '\'') || (*ptr == '"')) {
230 237 ret = ptr + 1;
231 238 end_char = *ptr;
232 239 ptr++;
233 240 } else {
234 241 ret = ptr;
235 242 end_char = ',';
236 243 }
237 244 goto consume_property;
238 245 }
239 246
240 247 /*
241 248 * We have a property, and it's not the one we're
242 249 * interested in. Skip the property name. A name
243 250 * can end with '=', a comma, or white space.
244 251 */
245 252 while ((*ptr != '\0') && (*ptr != '=') &&
246 253 (*ptr != ',') && (!ISSPACE(*ptr)))
247 254 ptr++;
248 255
249 256 /*
250 257 * We only want to go through the rest of the inner
251 258 * loop if we have a comma. If we have a property
252 259 * name without a value, either continue or break.
253 260 */
254 261 if (*ptr == '\0')
255 262 goto out;
256 263 else if (*ptr == ',')
257 264 continue;
258 265 else if (ISSPACE(*ptr))
259 266 break;
260 267 ptr++;
261 268
262 269 /*
263 270 * Is the property quoted?
264 271 */
265 272 if ((*ptr == '\'') || (*ptr == '"')) {
266 273 end_char = *ptr;
267 274 ptr++;
268 275 } else {
269 276 /*
270 277 * Not quoted, so the string ends at a comma
271 278 * or at white space. Deal with white space
272 279 * later.
273 280 */
274 281 end_char = ',';
275 282 }
276 283
277 284 /*
278 285 * Now, we can ignore any characters until we find
279 286 * end_char.
280 287 */
281 288 consume_property:
282 289 for (; (*ptr != '\0') && (*ptr != end_char); ptr++) {
283 290 if ((end_char == ',') && ISSPACE(*ptr))
284 291 break;
285 292 }
286 293 if (*ptr && (*ptr != ',') && !ISSPACE(*ptr))
287 294 ptr++;
288 295 } while (*ptr == ',');
289 296 }
290 297 out:
291 298 return (ret);
292 299 }
293 300
294 301 /*
295 302 * Find prop from boot env module. The data in module is list of C strings
296 303 * name=value, the list is terminated by double nul.
297 304 */
298 305 static const char *
299 306 find_boot_env_prop(const char *name)
300 307 {
301 308 char *ptr;
302 309 size_t len;
303 310 uintptr_t size;
304 311
305 312 if (boot_env.be_env == NULL)
306 313 return (NULL);
307 314
308 315 ptr = boot_env.be_env;
309 316 len = strlen(name);
310 317
311 318 /*
312 319 * Make sure we have at least len + 2 bytes in the environment.
313 320 * We are looking for name=value\0 constructs, and the environment
314 321 * itself is terminated by '\0'.
315 322 */
316 323 if (boot_env.be_size < len + 2)
317 324 return (NULL);
318 325
319 326 do {
320 327 if ((strncmp(ptr, name, len) == 0) && (ptr[len] == '=')) {
321 328 ptr += len + 1;
322 329 return (ptr);
323 330 }
324 331 /* find the first '\0' */
325 332 while (*ptr != '\0') {
326 333 ptr++;
327 334 size = (uintptr_t)ptr - (uintptr_t)boot_env.be_env;
328 335 if (size > boot_env.be_size)
329 336 return (NULL);
330 337 }
331 338 ptr++;
332 339
333 340 /* If the remainder is shorter than name + 2, get out. */
334 341 size = (uintptr_t)ptr - (uintptr_t)boot_env.be_env;
335 342 if (boot_env.be_size - size < len + 2)
336 343 return (NULL);
337 344 } while (*ptr != '\0');
338 345 return (NULL);
339 346 }
340 347
341 348 /*
342 349 * Get prop value from either command line or boot environment.
343 350 * We always check kernel command line first, as this will keep the
344 351 * functionality and will allow user to override the values in environment.
345 352 */
346 353 const char *
347 354 find_boot_prop(const char *name)
348 355 {
349 356 const char *value = find_boot_line_prop(name);
350 357
351 358 if (value == NULL)
352 359 value = find_boot_env_prop(name);
353 360 return (value);
354 361 }
355 362
356 363 #define MATCHES(p, pat) \
357 364 (strncmp(p, pat, strlen(pat)) == 0 ? (p += strlen(pat), 1) : 0)
358 365
359 366 #define SKIP(p, c) \
360 367 while (*(p) != 0 && *p != (c)) \
361 368 ++(p); \
362 369 if (*(p) == (c)) \
363 370 ++(p);
364 371
365 372 /*
366 373 * find a tty mode property either from cmdline or from boot properties
367 374 */
368 375 static const char *
369 376 get_mode_value(char *name)
370 377 {
371 378 /*
372 379 * when specified on boot line it looks like "name" "="....
373 380 */
374 381 if (boot_line != NULL) {
375 382 return (find_boot_prop(name));
376 383 }
377 384
378 385 #if defined(_BOOT)
379 386 return (NULL);
380 387 #else
381 388 /*
382 389 * if we're running in the full kernel we check the bootenv.rc settings
383 390 */
384 391 {
385 392 static char propval[20];
386 393
387 394 propval[0] = 0;
388 395 if (do_bsys_getproplen(NULL, name) <= 0)
389 396 return (NULL);
390 397 (void) do_bsys_getprop(NULL, name, propval);
391 398 return (propval);
392 399 }
393 400 #endif
394 401 }
395 402
396 403 /*
397 404 * adjust serial port based on properties
398 405 * These come either from the cmdline or from boot properties.
399 406 */
400 407 static void
401 408 serial_adjust_prop(void)
402 409 {
↓ open down ↓ |
286 lines elided |
↑ open up ↑ |
403 410 char propname[20];
404 411 const char *propval;
405 412 const char *p;
406 413 ulong_t baud;
407 414 uchar_t lcr = 0;
408 415 uchar_t mcr = DTR | RTS;
409 416
410 417 (void) strcpy(propname, "ttyX-mode");
411 418 propname[3] = 'a' + tty_num;
412 419 propval = get_mode_value(propname);
413 - if (propval == NULL)
414 - propval = "9600,8,n,1,-";
415 420 #if !defined(_BOOT)
416 - else
417 - console_mode_set = 1;
421 + if (propval != NULL)
422 + bootprop_set_tty_mode = B_TRUE;
418 423 #endif
424 + if (propval == NULL)
425 + propval = "9600,8,n,1,-";
419 426
420 427 /* property is of the form: "9600,8,n,1,-" */
421 428 p = propval;
422 429 if (MATCHES(p, "110,"))
423 430 baud = ASY110;
424 431 else if (MATCHES(p, "150,"))
425 432 baud = ASY150;
426 433 else if (MATCHES(p, "300,"))
427 434 baud = ASY300;
428 435 else if (MATCHES(p, "600,"))
429 436 baud = ASY600;
430 437 else if (MATCHES(p, "1200,"))
431 438 baud = ASY1200;
432 439 else if (MATCHES(p, "2400,"))
433 440 baud = ASY2400;
434 441 else if (MATCHES(p, "4800,"))
435 442 baud = ASY4800;
436 443 else if (MATCHES(p, "19200,"))
437 444 baud = ASY19200;
438 445 else if (MATCHES(p, "38400,"))
439 446 baud = ASY38400;
440 447 else if (MATCHES(p, "57600,"))
441 448 baud = ASY57600;
442 449 else if (MATCHES(p, "115200,"))
443 450 baud = ASY115200;
444 451 else {
445 452 baud = ASY9600;
446 453 SKIP(p, ',');
447 454 }
448 455 outb(port + LCR, DLAB);
449 456 outb(port + DAT + DLL, baud & 0xff);
450 457 outb(port + DAT + DLH, (baud >> 8) & 0xff);
451 458
452 459 switch (*p) {
453 460 case '5':
454 461 lcr |= BITS5;
455 462 ++p;
456 463 break;
457 464 case '6':
458 465 lcr |= BITS6;
459 466 ++p;
460 467 break;
461 468 case '7':
462 469 lcr |= BITS7;
463 470 ++p;
464 471 break;
465 472 case '8':
466 473 ++p;
467 474 /* FALLTHROUGH */
468 475 default:
469 476 lcr |= BITS8;
470 477 break;
471 478 }
472 479
473 480 SKIP(p, ',');
474 481
475 482 switch (*p) {
476 483 case 'n':
477 484 lcr |= PARITY_NONE;
478 485 ++p;
479 486 break;
480 487 case 'o':
481 488 lcr |= PARITY_ODD;
482 489 ++p;
483 490 break;
484 491 case 'e':
485 492 ++p;
486 493 /* FALLTHROUGH */
487 494 default:
488 495 lcr |= PARITY_EVEN;
489 496 break;
490 497 }
491 498
492 499
493 500 SKIP(p, ',');
494 501
495 502 switch (*p) {
496 503 case '1':
497 504 /* STOP1 is 0 */
498 505 ++p;
499 506 break;
500 507 default:
501 508 lcr |= STOP2;
502 509 break;
503 510 }
504 511 /* set parity bits */
505 512 outb(port + LCR, lcr);
506 513
507 514 (void) strcpy(propname, "ttyX-rts-dtr-off");
508 515 propname[3] = 'a' + tty_num;
509 516 propval = get_mode_value(propname);
510 517 if (propval == NULL)
511 518 propval = "false";
512 519 if (propval[0] != 'f' && propval[0] != 'F')
513 520 mcr = 0;
514 521 /* set modem control bits */
515 522 outb(port + MCR, mcr | OUT2);
516 523 }
517 524
518 525 /* Obtain the console type */
519 526 int
520 527 boot_console_type(int *tnum)
521 528 {
522 529 if (tnum != NULL)
523 530 *tnum = tty_num;
524 531 return (console);
525 532 }
526 533
527 534 /*
528 535 * A structure to map console names to values.
529 536 */
530 537 typedef struct {
531 538 char *name;
532 539 int value;
533 540 } console_value_t;
534 541
535 542 console_value_t console_devices[] = {
536 543 { "ttya", CONS_TTY }, /* 0 */
537 544 { "ttyb", CONS_TTY }, /* 1 */
538 545 { "ttyc", CONS_TTY }, /* 2 */
539 546 { "ttyd", CONS_TTY }, /* 3 */
540 547 { "text", CONS_SCREEN_TEXT },
541 548 { "graphics", CONS_SCREEN_GRAPHICS },
542 549 #if defined(__xpv)
543 550 { "hypervisor", CONS_HYPERVISOR },
544 551 #endif
545 552 #if !defined(_BOOT)
546 553 { "usb-serial", CONS_USBSER },
547 554 #endif
548 555 { NULL, CONS_INVALID }
549 556 };
550 557
551 558 static void
552 559 bcons_init_env(struct xboot_info *xbi)
553 560 {
554 561 uint32_t i;
555 562 struct boot_modules *modules;
556 563
557 564 modules = (struct boot_modules *)(uintptr_t)xbi->bi_modules;
558 565 for (i = 0; i < xbi->bi_module_cnt; i++) {
559 566 if (modules[i].bm_type == BMT_ENV)
560 567 break;
561 568 }
562 569 if (i == xbi->bi_module_cnt)
563 570 return;
564 571
565 572 boot_env.be_env = (char *)(uintptr_t)modules[i].bm_addr;
566 573 boot_env.be_size = modules[i].bm_size;
567 574 }
568 575
569 576 int
570 577 boot_fb(struct xboot_info *xbi, int console)
571 578 {
572 579 if (xbi_fb_init(xbi, &bcons_dev) == B_FALSE)
573 580 return (console);
574 581
575 582 /* FB address is not set, fall back to serial terminal. */
576 583 if (fb_info.paddr == 0)
577 584 return (CONS_TTY);
578 585
579 586 fb_info.terminal.x = VGA_TEXT_COLS;
580 587 fb_info.terminal.y = VGA_TEXT_ROWS;
581 588 boot_fb_init(CONS_FRAMEBUFFER);
582 589
583 590 if (console == CONS_SCREEN_TEXT)
584 591 return (CONS_FRAMEBUFFER);
585 592 return (console);
586 593 }
587 594
588 595 /*
589 596 * TODO.
590 597 * quick and dirty local atoi. Perhaps should build with strtol, but
591 598 * dboot & early boot mix does overcomplicate things much.
592 599 * Stolen from libc anyhow.
593 600 */
594 601 static int
595 602 atoi(const char *p)
596 603 {
597 604 int n, c, neg = 0;
598 605 unsigned char *up = (unsigned char *)p;
599 606
600 607 if (!isdigit(c = *up)) {
601 608 while (isspace(c))
602 609 c = *++up;
603 610 switch (c) {
604 611 case '-':
605 612 neg++;
606 613 /* FALLTHROUGH */
607 614 case '+':
608 615 c = *++up;
609 616 }
610 617 if (!isdigit(c))
611 618 return (0);
612 619 }
613 620 for (n = '0' - c; isdigit(c = *++up); ) {
614 621 n *= 10; /* two steps to avoid unnecessary overflow */
615 622 n += '0' - c; /* accum neg to avoid surprises at MAX */
616 623 }
617 624 return (neg ? n : -n);
618 625 }
619 626
620 627 static void
621 628 bcons_init_fb(void)
622 629 {
623 630 const char *propval;
624 631 int intval;
625 632
626 633 /* initialize with explicit default values */
627 634 fb_info.fg_color = CONS_COLOR;
628 635 fb_info.bg_color = 0;
629 636 fb_info.inverse = B_FALSE;
630 637 fb_info.inverse_screen = B_FALSE;
631 638
632 639 /* color values are 0 - 255 */
633 640 propval = find_boot_prop("tem.fg_color");
634 641 if (propval != NULL) {
635 642 intval = atoi(propval);
636 643 if (intval >= 0 && intval <= 255)
637 644 fb_info.fg_color = intval;
638 645 }
639 646
640 647 /* color values are 0 - 255 */
641 648 propval = find_boot_prop("tem.bg_color");
642 649 if (propval != NULL && ISDIGIT(*propval)) {
643 650 intval = atoi(propval);
644 651 if (intval >= 0 && intval <= 255)
645 652 fb_info.bg_color = intval;
646 653 }
647 654
648 655 /* get inverses. allow 0, 1, true, false */
649 656 propval = find_boot_prop("tem.inverse");
650 657 if (propval != NULL) {
651 658 if (*propval == '1' || MATCHES(propval, "true"))
652 659 fb_info.inverse = B_TRUE;
653 660 }
654 661
655 662 propval = find_boot_prop("tem.inverse-screen");
656 663 if (propval != NULL) {
657 664 if (*propval == '1' || MATCHES(propval, "true"))
658 665 fb_info.inverse_screen = B_TRUE;
659 666 }
660 667
661 668 #if defined(_BOOT)
662 669 /*
663 670 * Load cursor position from bootloader only in dboot,
664 671 * dboot will pass cursor position to kernel via xboot info.
665 672 */
666 673 propval = find_boot_prop("tem.cursor.row");
667 674 if (propval != NULL) {
668 675 intval = atoi(propval);
669 676 if (intval >= 0 && intval <= 0xFFFF)
670 677 fb_info.cursor.pos.y = intval;
671 678 }
672 679
↓ open down ↓ |
244 lines elided |
↑ open up ↑ |
673 680 propval = find_boot_prop("tem.cursor.col");
674 681 if (propval != NULL) {
675 682 intval = atoi(propval);
676 683 if (intval >= 0 && intval <= 0xFFFF)
677 684 fb_info.cursor.pos.x = intval;
678 685 }
679 686 #endif
680 687 }
681 688
682 689 /*
683 - * Go through the console_devices array trying to match the string
684 - * we were given. The string on the command line must end with
685 - * a comma or white space.
690 + * Go through the known console device names trying to match the string we were
691 + * given. The string on the command line must end with a comma or white space.
686 692 *
687 - * This function does set tty_num as an side effect, this does imply that
688 - * only one of the main console and the diag-device can be using serial.
693 + * For convenience, we provide the caller with an integer index for the CONS_TTY
694 + * case.
689 695 */
690 696 static int
691 -lookup_console_devices(const char *cons_str)
697 +lookup_console_device(const char *cons_str, int *indexp)
692 698 {
693 699 int n, cons;
694 700 size_t len, cons_len;
695 701 console_value_t *consolep;
696 702
697 703 cons = CONS_INVALID;
698 704 if (cons_str != NULL) {
699 705
700 706 cons_len = strlen(cons_str);
701 707 for (n = 0; console_devices[n].name != NULL; n++) {
702 708 consolep = &console_devices[n];
703 709 len = strlen(consolep->name);
704 710 if ((len <= cons_len) && ((cons_str[len] == '\0') ||
705 711 (cons_str[len] == ',') || (cons_str[len] == '\'') ||
706 712 (cons_str[len] == '"') || ISSPACE(cons_str[len])) &&
707 713 (strncmp(cons_str, consolep->name, len) == 0)) {
708 714 cons = consolep->value;
709 715 if (cons == CONS_TTY)
710 - tty_num = n;
716 + *indexp = n;
711 717 break;
712 718 }
713 719 }
714 720 }
715 721 return (cons);
716 722 }
717 723
718 724 void
719 725 bcons_init(struct xboot_info *xbi)
720 726 {
721 727 const char *cons_str;
722 728 #if !defined(_BOOT)
723 729 static char console_text[] = "text";
724 730 extern int post_fastreboot;
725 731 #endif
726 732
727 733 if (xbi == NULL) {
728 734 /* This is very early dboot console, set up ttya. */
729 735 console = CONS_TTY;
730 736 serial_init();
731 737 return;
732 738 }
733 739
734 740 /* Set up data to fetch properties from commad line and boot env. */
735 741 boot_line = (char *)(uintptr_t)xbi->bi_cmdline;
736 742 bcons_init_env(xbi);
737 743 console = CONS_INVALID;
738 744
739 745 /* set up initial fb_info */
740 746 bcons_init_fb();
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
741 747
742 748 #if defined(__xpv)
743 749 bcons_init_xen(boot_line);
744 750 #endif /* __xpv */
745 751
746 752 /*
747 753 * First check for diag-device.
748 754 */
749 755 cons_str = find_boot_prop("diag-device");
750 756 if (cons_str != NULL)
751 - diag = lookup_console_devices(cons_str);
757 + diag = lookup_console_device(cons_str, &tty_num);
752 758
753 759 cons_str = find_boot_prop("console");
754 760 if (cons_str == NULL)
755 761 cons_str = find_boot_prop("output-device");
756 762
757 763 #if !defined(_BOOT)
758 764 if (post_fastreboot && strcmp(cons_str, "graphics") == 0)
759 765 cons_str = console_text;
760 766 #endif
761 767
762 768 if (cons_str != NULL)
763 - console = lookup_console_devices(cons_str);
769 + console = lookup_console_device(cons_str, &tty_num);
764 770
765 771 #if defined(__xpv)
766 772 /*
767 773 * domU's always use the hypervisor regardless of what
768 774 * the console variable may be set to.
769 775 */
770 776 if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
771 777 console = CONS_HYPERVISOR;
772 778 console_hypervisor_redirect = B_TRUE;
773 779 }
774 780 #endif /* __xpv */
775 781
776 - /*
777 - * If no console device specified, default to text.
778 - * Remember what was specified for second phase.
779 - */
780 782 if (console == CONS_INVALID)
781 783 console = CONS_SCREEN_TEXT;
782 -#if !defined(_BOOT)
783 - else
784 - console_set = 1;
785 -#endif
786 784
787 785 #if defined(__xpv)
788 786 if (DOMAIN_IS_INITDOMAIN(xen_info)) {
789 787 switch (HYPERVISOR_console_io(CONSOLEIO_get_device, 0, NULL)) {
790 788 case XEN_CONSOLE_COM1:
791 789 case XEN_CONSOLE_COM2:
792 790 console_hypervisor_device = CONS_TTY;
793 791 console_hypervisor_tty_num = tty_num;
794 792 break;
795 793 case XEN_CONSOLE_VGA:
796 794 /*
797 795 * Currently xen doesn't really support
798 796 * keyboard/display console devices.
799 797 * What this setting means is that
800 798 * "vga=keep" has been enabled, which is
801 799 * more of a xen debugging tool that a
802 800 * true console mode. Hence, we're going
803 801 * to ignore this xen "console" setting.
804 802 */
805 803 /*FALLTHROUGH*/
806 804 default:
807 805 console_hypervisor_device = CONS_INVALID;
808 806 }
809 807 }
810 808
811 809 /*
812 810 * if the hypervisor is using the currently selected serial
813 811 * port then default to using the hypervisor as the console
814 812 * device.
815 813 */
816 814 if (console == console_hypervisor_device) {
817 815 console = CONS_HYPERVISOR;
818 816 console_hypervisor_redirect = B_TRUE;
819 817 }
820 818 #endif /* __xpv */
821 819
822 820 /* make sure the FB is set up if present */
823 821 console = boot_fb(xbi, console);
824 822 switch (console) {
825 823 case CONS_TTY:
826 824 serial_init();
827 825 break;
828 826
829 827 case CONS_HYPERVISOR:
830 828 break;
831 829
832 830 #if !defined(_BOOT)
833 831 case CONS_USBSER:
834 832 /*
835 833 * We can't do anything with the usb serial
836 834 * until we have memory management.
837 835 */
838 836 break;
839 837 #endif
840 838 case CONS_SCREEN_GRAPHICS:
841 839 kb_init();
842 840 break;
843 841 case CONS_SCREEN_TEXT:
844 842 boot_vga_init(&bcons_dev);
845 843 /* Fall through */
846 844 default:
847 845 kb_init();
848 846 break;
849 847 }
850 848
851 849 /*
852 850 * Initialize diag device unless already done.
853 851 */
854 852 switch (diag) {
855 853 case CONS_TTY:
856 854 if (console != CONS_TTY)
857 855 serial_init();
858 856 break;
859 857 case CONS_SCREEN_GRAPHICS:
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
860 858 case CONS_SCREEN_TEXT:
861 859 if (console != CONS_SCREEN_GRAPHICS &&
862 860 console != CONS_SCREEN_TEXT)
863 861 kb_init();
864 862 break;
865 863 default:
866 864 break;
867 865 }
868 866 }
869 867
870 -#if !defined(_BOOT)
871 -/*
872 - * 2nd part of console initialization.
873 - * In the kernel (ie. fakebop), this can be used only to switch to
874 - * using a serial port instead of screen based on the contents
875 - * of the bootenv.rc file.
876 - */
877 -/*ARGSUSED*/
878 -void
879 -bcons_init2(char *inputdev, char *outputdev, char *consoledev)
880 -{
881 - int cons = CONS_INVALID;
882 - int ttyn;
883 - char *devnames[] = { consoledev, outputdev, inputdev, NULL };
884 - console_value_t *consolep;
885 - int i;
886 - extern int post_fastreboot;
887 -
888 - if (post_fastreboot && console == CONS_SCREEN_GRAPHICS)
889 - console = CONS_SCREEN_TEXT;
890 -
891 - if (console != CONS_USBSER && console != CONS_SCREEN_GRAPHICS) {
892 - if (console_set) {
893 - /*
894 - * If the console was set on the command line,
895 - * but the ttyX-mode was not, we only need to
896 - * check bootenv.rc for that setting.
897 - */
898 - if ((!console_mode_set) && (console == CONS_TTY))
899 - serial_init();
900 - return;
901 - }
902 -
903 - for (i = 0; devnames[i] != NULL; i++) {
904 - int n;
905 -
906 - for (n = 0; console_devices[n].name != NULL; n++) {
907 - consolep = &console_devices[n];
908 - if (strcmp(devnames[i], consolep->name) == 0) {
909 - cons = consolep->value;
910 - if (cons == CONS_TTY)
911 - ttyn = n;
912 - }
913 - }
914 - if (cons != CONS_INVALID)
915 - break;
916 - }
917 -
918 -#if defined(__xpv)
919 - /*
920 - * if the hypervisor is using the currently selected console
921 - * device then default to using the hypervisor as the console
922 - * device.
923 - */
924 - if (cons == console_hypervisor_device) {
925 - cons = CONS_HYPERVISOR;
926 - console_hypervisor_redirect = B_TRUE;
927 - }
928 -#endif /* __xpv */
929 -
930 - if ((cons == CONS_INVALID) || (cons == console)) {
931 - /*
932 - * we're sticking with whatever the current setting is
933 - */
934 - return;
935 - }
936 -
937 - console = cons;
938 - if (cons == CONS_TTY) {
939 - tty_num = ttyn;
940 - serial_init();
941 - return;
942 - }
943 - } else {
944 - /*
945 - * USB serial and GRAPHICS console
946 - * we just collect data into a buffer
947 - */
948 - extern void *defcons_init(size_t);
949 - defcons_buf = defcons_cur = defcons_init(MMU_PAGESIZE);
950 - }
951 -}
952 -
953 -#if defined(__xpv)
954 -boolean_t
955 -bcons_hypervisor_redirect(void)
956 -{
957 - return (console_hypervisor_redirect);
958 -}
959 -
960 -void
961 -bcons_device_change(int new_console)
962 -{
963 - if (new_console < CONS_MIN || new_console > CONS_MAX)
964 - return;
965 -
966 - /*
967 - * If we are asked to switch the console to the hypervisor, that
968 - * really means to switch the console to whichever device the
969 - * hypervisor is/was using.
970 - */
971 - if (new_console == CONS_HYPERVISOR)
972 - new_console = console_hypervisor_device;
973 -
974 - console = new_console;
975 -
976 - if (new_console == CONS_TTY) {
977 - tty_num = console_hypervisor_tty_num;
978 - serial_init();
979 - }
980 -}
981 -#endif /* __xpv */
982 -
983 868 static void
984 -defcons_putchar(int c)
985 -{
986 - if (defcons_buf != NULL &&
987 - defcons_cur + 1 - defcons_buf < MMU_PAGESIZE) {
988 - *defcons_cur++ = c;
989 - *defcons_cur = 0;
990 - }
991 -}
992 -#endif /* _BOOT */
993 -
994 -static void
995 869 serial_putchar(int c)
996 870 {
997 871 int checks = 10000;
998 872
999 873 while (((inb(port + LSR) & XHRE) == 0) && checks--)
1000 874 ;
1001 875 outb(port + DAT, (char)c);
1002 876 }
1003 877
1004 878 static int
1005 879 serial_getchar(void)
1006 880 {
1007 881 uchar_t lsr;
1008 882
1009 883 while (serial_ischar() == 0)
1010 884 ;
1011 885
1012 886 lsr = inb(port + LSR);
1013 887 if (lsr & (SERIAL_BREAK | SERIAL_FRAME |
1014 888 SERIAL_PARITY | SERIAL_OVERRUN)) {
1015 889 if (lsr & SERIAL_OVERRUN) {
1016 890 return (inb(port + DAT));
1017 891 } else {
1018 892 /* Toss the garbage */
1019 893 (void) inb(port + DAT);
1020 894 return (0);
1021 895 }
1022 896 }
1023 897 return (inb(port + DAT));
1024 898 }
1025 899
1026 900 static int
1027 901 serial_ischar(void)
1028 902 {
1029 903 return (inb(port + LSR) & RCA);
1030 904 }
1031 905
1032 906 static void
1033 907 btem_control(btem_state_t *btem, int c)
1034 908 {
1035 909 int y, rows, cols;
1036 910
1037 911 rows = fb_info.cursor.pos.y;
1038 912 cols = fb_info.cursor.pos.x;
1039 913
1040 914 btem->btem_state = A_STATE_START;
1041 915 switch (c) {
1042 916 case A_BS:
1043 917 bcons_dev.bd_setpos(rows, cols - 1);
1044 918 break;
1045 919
1046 920 case A_HT:
1047 921 cols += 8 - (cols % 8);
1048 922 if (cols >= fb_info.terminal.x)
1049 923 cols = fb_info.terminal.x - 1;
1050 924 bcons_dev.bd_setpos(rows, cols);
1051 925 break;
1052 926
1053 927 case A_CR:
1054 928 bcons_dev.bd_setpos(rows, 0);
1055 929 break;
1056 930
1057 931 case A_FF:
1058 932 for (y = 0; y < fb_info.terminal.y; y++) {
1059 933 bcons_dev.bd_setpos(y, 0);
1060 934 bcons_dev.bd_eraseline();
1061 935 }
1062 936 bcons_dev.bd_setpos(0, 0);
1063 937 break;
1064 938
1065 939 case A_ESC:
1066 940 btem->btem_state = A_STATE_ESC;
1067 941 break;
1068 942
1069 943 default:
1070 944 bcons_dev.bd_putchar(c);
1071 945 break;
1072 946 }
1073 947 }
1074 948
1075 949 /*
1076 950 * if parameters [0..count - 1] are not set, set them to the value
1077 951 * of newparam.
1078 952 */
1079 953 static void
1080 954 btem_setparam(btem_state_t *btem, int count, int newparam)
1081 955 {
1082 956 int i;
1083 957
1084 958 for (i = 0; i < count; i++) {
1085 959 if (btem->btem_params[i] == -1)
1086 960 btem->btem_params[i] = newparam;
1087 961 }
1088 962 }
1089 963
1090 964 static void
1091 965 btem_chkparam(btem_state_t *btem, int c)
1092 966 {
1093 967 int rows, cols;
1094 968
1095 969 rows = fb_info.cursor.pos.y;
1096 970 cols = fb_info.cursor.pos.x;
1097 971 switch (c) {
1098 972 case '@': /* insert char */
1099 973 btem_setparam(btem, 1, 1);
1100 974 bcons_dev.bd_shift(btem->btem_params[0]);
1101 975 break;
1102 976
1103 977 case 'A': /* cursor up */
1104 978 btem_setparam(btem, 1, 1);
1105 979 bcons_dev.bd_setpos(rows - btem->btem_params[0], cols);
1106 980 break;
1107 981
1108 982 case 'B': /* cursor down */
1109 983 btem_setparam(btem, 1, 1);
1110 984 bcons_dev.bd_setpos(rows + btem->btem_params[0], cols);
1111 985 break;
1112 986
1113 987 case 'C': /* cursor right */
1114 988 btem_setparam(btem, 1, 1);
1115 989 bcons_dev.bd_setpos(rows, cols + btem->btem_params[0]);
1116 990 break;
1117 991
1118 992 case 'D': /* cursor left */
1119 993 btem_setparam(btem, 1, 1);
1120 994 bcons_dev.bd_setpos(rows, cols - btem->btem_params[0]);
1121 995 break;
1122 996
1123 997 case 'K':
1124 998 bcons_dev.bd_eraseline();
1125 999 break;
1126 1000 default:
1127 1001 /* bcons_dev.bd_putchar(c); */
1128 1002 break;
1129 1003 }
1130 1004 btem->btem_state = A_STATE_START;
1131 1005 }
1132 1006
1133 1007 static void
1134 1008 btem_getparams(btem_state_t *btem, int c)
1135 1009 {
1136 1010 if (isdigit(c)) {
1137 1011 btem->btem_paramval = btem->btem_paramval * 10 + c - '0';
1138 1012 btem->btem_gotparam = B_TRUE;
1139 1013 return;
1140 1014 }
1141 1015
1142 1016 if (btem->btem_curparam < BTEM_MAXPARAMS) {
1143 1017 if (btem->btem_gotparam == B_TRUE) {
1144 1018 btem->btem_params[btem->btem_curparam] =
1145 1019 btem->btem_paramval;
1146 1020 }
1147 1021 btem->btem_curparam++;
1148 1022 }
1149 1023
1150 1024 if (c == ';') {
1151 1025 /* Restart parameter search */
1152 1026 btem->btem_gotparam = B_FALSE;
1153 1027 btem->btem_paramval = 0;
1154 1028 } else {
1155 1029 btem_chkparam(btem, c);
1156 1030 }
1157 1031 }
1158 1032
1159 1033 /* Simple boot terminal parser. */
1160 1034 static void
1161 1035 btem_parse(btem_state_t *btem, int c)
1162 1036 {
1163 1037 int i;
1164 1038
1165 1039 /* Normal state? */
1166 1040 if (btem->btem_state == A_STATE_START) {
1167 1041 if (c == A_CSI || c < ' ')
1168 1042 btem_control(btem, c);
1169 1043 else
1170 1044 bcons_dev.bd_putchar(c);
1171 1045 return;
1172 1046 }
1173 1047
1174 1048 /* In <ESC> sequence */
1175 1049 if (btem->btem_state != A_STATE_ESC) {
1176 1050 btem_getparams(btem, c);
1177 1051 return;
1178 1052 }
1179 1053
1180 1054 /* Previous char was <ESC> */
1181 1055 switch (c) {
1182 1056 case '[':
1183 1057 btem->btem_curparam = 0;
1184 1058 btem->btem_paramval = 0;
1185 1059 btem->btem_gotparam = B_FALSE;
1186 1060 /* clear the parameters */
1187 1061 for (i = 0; i < BTEM_MAXPARAMS; i++)
1188 1062 btem->btem_params[i] = -1;
1189 1063 btem->btem_state = A_STATE_CSI;
1190 1064 return;
1191 1065
1192 1066 case 'Q': /* <ESC>Q */
1193 1067 case 'C': /* <ESC>C */
1194 1068 btem->btem_state = A_STATE_START;
1195 1069 return;
1196 1070
1197 1071 default:
1198 1072 btem->btem_state = A_STATE_START;
1199 1073 break;
1200 1074 }
1201 1075
1202 1076 if (c < ' ')
1203 1077 btem_control(btem, c);
1204 1078 else
1205 1079 bcons_dev.bd_putchar(c);
1206 1080 }
1207 1081
1208 1082 static void
1209 1083 _doputchar(int device, int c)
1210 1084 {
1211 1085 switch (device) {
1212 1086 case CONS_TTY:
1213 1087 serial_putchar(c);
1214 1088 return;
1215 1089 case CONS_SCREEN_TEXT:
1216 1090 case CONS_FRAMEBUFFER:
1217 1091 bcons_dev.bd_cursor(B_FALSE);
1218 1092 btem_parse(&boot_tem, c);
1219 1093 bcons_dev.bd_cursor(B_TRUE);
1220 1094 return;
1221 1095 case CONS_SCREEN_GRAPHICS:
1222 1096 #if !defined(_BOOT)
1223 1097 case CONS_USBSER:
1224 1098 defcons_putchar(c);
1225 1099 #endif /* _BOOT */
1226 1100 default:
1227 1101 return;
1228 1102 }
1229 1103 }
1230 1104
1231 1105 void
1232 1106 bcons_putchar(int c)
1233 1107 {
1234 1108 #if defined(__xpv)
1235 1109 if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
1236 1110 console == CONS_HYPERVISOR) {
1237 1111 bcons_putchar_xen(c);
1238 1112 return;
1239 1113 }
1240 1114 #endif /* __xpv */
1241 1115
1242 1116 if (c == '\n') {
1243 1117 _doputchar(console, '\r');
1244 1118 if (diag != console)
1245 1119 _doputchar(diag, '\r');
1246 1120 }
1247 1121 _doputchar(console, c);
1248 1122 if (diag != console)
1249 1123 _doputchar(diag, c);
1250 1124 }
1251 1125
1252 1126 /*
1253 1127 * kernel character input functions
1254 1128 */
1255 1129 int
1256 1130 bcons_getchar(void)
1257 1131 {
1258 1132 #if defined(__xpv)
1259 1133 if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
1260 1134 console == CONS_HYPERVISOR)
1261 1135 return (bcons_getchar_xen());
1262 1136 #endif /* __xpv */
1263 1137
1264 1138 for (;;) {
1265 1139 if (console == CONS_TTY || diag == CONS_TTY) {
↓ open down ↓ |
261 lines elided |
↑ open up ↑ |
1266 1140 if (serial_ischar())
1267 1141 return (serial_getchar());
1268 1142 }
1269 1143 if (console != CONS_INVALID || diag != CONS_INVALID) {
1270 1144 if (kb_ischar())
1271 1145 return (kb_getchar());
1272 1146 }
1273 1147 }
1274 1148 }
1275 1149
1150 +/*
1151 + * Nothing below is used by dboot.
1152 + */
1276 1153 #if !defined(_BOOT)
1277 1154
1278 1155 int
1279 1156 bcons_ischar(void)
1280 1157 {
1281 1158 int c = 0;
1282 1159
1283 1160 #if defined(__xpv)
1284 1161 if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
1285 1162 console == CONS_HYPERVISOR)
1286 1163 return (bcons_ischar_xen());
1287 1164 #endif /* __xpv */
1288 1165
1289 1166 switch (console) {
1290 1167 case CONS_TTY:
1291 1168 c = serial_ischar();
1292 1169 break;
1293 1170
1294 1171 case CONS_INVALID:
1295 1172 break;
1296 1173
1297 1174 default:
1298 1175 c = kb_ischar();
1299 1176 }
1300 1177 if (c != 0)
1301 1178 return (c);
1302 1179
1303 1180 switch (diag) {
1304 1181 case CONS_TTY:
1305 1182 c = serial_ischar();
1306 1183 break;
1307 1184
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
1308 1185 case CONS_INVALID:
1309 1186 break;
1310 1187
1311 1188 default:
1312 1189 c = kb_ischar();
1313 1190 }
1314 1191
1315 1192 return (c);
1316 1193 }
1317 1194
1195 +/*
1196 + * 2nd part of console initialization: we've now processed bootenv.rc; update
1197 + * console settings as appropriate. This only really processes serial console
1198 + * modifications.
1199 + */
1200 +void
1201 +bcons_post_bootenvrc(char *inputdev, char *outputdev, char *consoledev)
1202 +{
1203 + int cons = CONS_INVALID;
1204 + int ttyn;
1205 + char *devnames[] = { consoledev, outputdev, inputdev, NULL };
1206 + console_value_t *consolep;
1207 + int i;
1208 + extern int post_fastreboot;
1209 +
1210 + if (post_fastreboot && console == CONS_SCREEN_GRAPHICS)
1211 + console = CONS_SCREEN_TEXT;
1212 +
1213 + /*
1214 + * USB serial and GRAPHICS console: we just collect data into a buffer.
1215 + */
1216 + if (console == CONS_USBSER || console == CONS_SCREEN_GRAPHICS) {
1217 + extern void *defcons_init(size_t);
1218 + defcons_buf = defcons_cur = defcons_init(MMU_PAGESIZE);
1219 + return;
1220 + }
1221 +
1222 + for (i = 0; devnames[i] != NULL; i++) {
1223 + cons = lookup_console_device(devnames[i], &ttyn);
1224 + if (cons != CONS_INVALID)
1225 + break;
1226 + }
1227 +
1228 + if (cons == CONS_INVALID) {
1229 + /*
1230 + * No console change, but let's see if bootenv.rc had a mode
1231 + * setting we should apply.
1232 + */
1233 + if (console == CONS_TTY && !bootprop_set_tty_mode)
1234 + serial_init();
1235 + return;
1236 + }
1237 +
1238 +#if defined(__xpv)
1239 + /*
1240 + * if the hypervisor is using the currently selected console device then
1241 + * default to using the hypervisor as the console device.
1242 + */
1243 + if (cons == console_hypervisor_device) {
1244 + cons = CONS_HYPERVISOR;
1245 + console_hypervisor_redirect = B_TRUE;
1246 + }
1247 +#endif /* __xpv */
1248 +
1249 + console = cons;
1250 +
1251 + if (console == CONS_TTY) {
1252 + tty_num = ttyn;
1253 + serial_init();
1254 + }
1255 +}
1256 +
1257 +#if defined(__xpv)
1258 +boolean_t
1259 +bcons_hypervisor_redirect(void)
1260 +{
1261 + return (console_hypervisor_redirect);
1262 +}
1263 +
1264 +void
1265 +bcons_device_change(int new_console)
1266 +{
1267 + if (new_console < CONS_MIN || new_console > CONS_MAX)
1268 + return;
1269 +
1270 + /*
1271 + * If we are asked to switch the console to the hypervisor, that
1272 + * really means to switch the console to whichever device the
1273 + * hypervisor is/was using.
1274 + */
1275 + if (new_console == CONS_HYPERVISOR)
1276 + new_console = console_hypervisor_device;
1277 +
1278 + console = new_console;
1279 +
1280 + if (new_console == CONS_TTY) {
1281 + tty_num = console_hypervisor_tty_num;
1282 + serial_init();
1283 + }
1284 +}
1285 +#endif /* __xpv */
1286 +
1287 +static void
1288 +defcons_putchar(int c)
1289 +{
1290 + if (defcons_buf != NULL &&
1291 + defcons_cur + 1 - defcons_buf < MMU_PAGESIZE) {
1292 + *defcons_cur++ = c;
1293 + *defcons_cur = 0;
1294 + }
1295 +}
1296 +
1318 1297 #endif /* _BOOT */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX