1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 47 unchanged lines hidden (view full) ---

56#if defined(__xpv)
57extern void bcons_init_xen(char *);
58extern void bcons_putchar_xen(int);
59extern int bcons_getchar_xen(void);
60extern int bcons_ischar_xen(void);
61#endif /* __xpv */
62
63fb_info_t fb_info;
64static int cons_color = CONS_COLOR;
64static bcons_dev_t bcons_dev; /* Device callbacks */
65static int console = CONS_SCREEN_TEXT;
66static int diag = CONS_INVALID;
67static int tty_num = 0;
68static int tty_addr[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
69static char *boot_line;
70static struct boot_env {
71 char *be_env; /* ends with double ascii nul */
72 size_t be_size; /* size of the environment, including nul */
73} boot_env;
74
75/*
76 * Simple console terminal emulator for early boot.
77 * We need this to support kmdb, all other console output is supposed
78 * to be simple text output.
79 */
80typedef enum btem_state_type {
81 A_STATE_START,
82 A_STATE_ESC,
83 A_STATE_CSI,
84 A_STATE_CSI_QMARK,
85 A_STATE_CSI_EQUAL
86} btem_state_type_t;
87
88#define BTEM_MAXPARAMS 5
89typedef struct btem_state {
90 btem_state_type_t btem_state;
91 boolean_t btem_gotparam;
92 int btem_curparam;
93 int btem_paramval;
94 int btem_params[BTEM_MAXPARAMS];
95} btem_state_t;
96
97static btem_state_t boot_tem;
98
99static int serial_ischar(void);
100static int serial_getchar(void);
101static void serial_putchar(int);
102static void serial_adjust_prop(void);
103
104#if !defined(_BOOT)
105/* Set if the console or mode are expressed in the boot line */
106static int console_set, console_mode_set;

--- 9 unchanged lines hidden (view full) ---

116console_hypervisor_dev_type(int *tnum)
117{
118 if (tnum != NULL)
119 *tnum = console_hypervisor_tty_num;
120 return (console_hypervisor_device);
121}
122#endif /* __xpv */
123
100/* Put the character C on the screen. */
101static void
102screen_putchar(int c)
103{
104 int row, col;
105
106 vga_getpos(&row, &col);
107 switch (c) {
108 case '\t':
109 col += 8 - (col % 8);
110 if (col == VGA_TEXT_COLS)
111 col = 79;
112 vga_setpos(row, col);
113 break;
114
115 case '\r':
116 vga_setpos(row, 0);
117 break;
118
119 case '\b':
120 if (col > 0)
121 vga_setpos(row, col - 1);
122 break;
123
124 case '\n':
125 if (row < VGA_TEXT_ROWS - 1)
126 vga_setpos(row + 1, col);
127 else
128 vga_scroll(cons_color);
129 break;
130
131 default:
132 vga_drawc(c, cons_color);
133 if (col < VGA_TEXT_COLS -1)
134 vga_setpos(row, col + 1);
135 else if (row < VGA_TEXT_ROWS - 1)
136 vga_setpos(row + 1, 0);
137 else {
138 vga_setpos(row, 0);
139 vga_scroll(cons_color);
140 }
141 break;
142 }
143}
144
124static int port;
125
126static void
127serial_init(void)
128{
129 port = tty_addr[tty_num];
130
131 outb(port + ISR, 0x20);

--- 432 unchanged lines hidden (view full) ---

564
565 boot_env.be_env = (char *)(uintptr_t)modules[i].bm_addr;
566 boot_env.be_size = modules[i].bm_size;
567}
568
569int
570boot_fb(struct xboot_info *xbi, int console)
571{
593 if (xbi_fb_init(xbi) == B_FALSE)
572 if (xbi_fb_init(xbi, &bcons_dev) == B_FALSE)
573 return (console);
574
575 /* FB address is not set, fall back to serial terminal. */
597 if (fb_info.paddr == 0) {
576 if (fb_info.paddr == 0)
577 return (CONS_TTY);
599 }
578
601 fb_info.terminal.x = 80;
602 fb_info.terminal.y = 34;
579 fb_info.terminal.x = VGA_TEXT_COLS;
580 fb_info.terminal.y = VGA_TEXT_ROWS;
581 boot_fb_init(CONS_FRAMEBUFFER);
582
583 if (console == CONS_SCREEN_TEXT)
584 return (CONS_FRAMEBUFFER);
585 return (console);
586}
587
588/*

--- 23 unchanged lines hidden (view full) ---

612 }
613 for (n = '0' - c; isdigit(c = *++up); ) {
614 n *= 10; /* two steps to avoid unnecessary overflow */
615 n += '0' - c; /* accum neg to avoid surprises at MAX */
616 }
617 return (neg ? n : -n);
618}
619
642static int
643set_vga_color(void)
644{
645 int color;
646 uint8_t tmp;
647/* BEGIN CSTYLED */
648/* Bk Rd Gr Br Bl Mg Cy Wh */
649 uint8_t dim_xlate[] = { 1, 5, 3, 7, 2, 6, 4, 8 };
650 uint8_t brt_xlate[] = { 9, 13, 11, 15, 10, 14, 12, 0 };
651 uint8_t solaris_color_to_pc_color[16] = {
652 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
653 };
654/* END CSTYLED */
655
656 /*
657 * Now we have two principal cases, black on white and white on black.
658 * And we have possible inverse to switch them, and we want to
659 * follow the tem logic to set VGA TEXT color. FB will take care
660 * of itself in boot_fb.c
661 */
662 if (fb_info.inverse == B_TRUE ||
663 fb_info.inverse_screen == B_TRUE) {
664 tmp = dim_xlate[fb_info.fg_color];
665 color = solaris_color_to_pc_color[tmp] << 4;
666 tmp = brt_xlate[fb_info.bg_color];
667 color |= solaris_color_to_pc_color[tmp];
668 return (color);
669 }
670
671 /* use bright white for background */
672 if (fb_info.bg_color == 7)
673 tmp = brt_xlate[fb_info.bg_color];
674 else
675 tmp = dim_xlate[fb_info.bg_color];
676
677 color = solaris_color_to_pc_color[tmp] << 4;
678 tmp = dim_xlate[fb_info.fg_color];
679 color |= solaris_color_to_pc_color[tmp];
680 return (color);
681}
682
620static void
621bcons_init_fb(void)
622{
623 const char *propval;
624 int intval;
625
626 /* initialize with explicit default values */
627 fb_info.fg_color = CONS_COLOR;

--- 48 unchanged lines hidden (view full) ---

676
677 propval = find_boot_prop("tem.cursor.col");
678 if (propval != NULL) {
679 intval = atoi(propval);
680 if (intval >= 0 && intval <= 0xFFFF)
681 fb_info.cursor.pos.x = intval;
682 }
683#endif
747
748 cons_color = set_vga_color();
684}
685
686/*
687 * Go through the console_devices array trying to match the string
688 * we were given. The string on the command line must end with
689 * a comma or white space.
690 *
691 * This function does set tty_num as an side effect, this does imply that

--- 148 unchanged lines hidden (view full) ---

840 * until we have memory management.
841 */
842 break;
843#endif
844 case CONS_SCREEN_GRAPHICS:
845 kb_init();
846 break;
847 case CONS_SCREEN_TEXT:
913 boot_vga_init(cons_color);
848 boot_vga_init(&bcons_dev);
849 /* Fall through */
850 default:
851 kb_init();
852 break;
853 }
854
855 /*
856 * Initialize diag device unless already done.

--- 172 unchanged lines hidden (view full) ---

1029
1030static int
1031serial_ischar(void)
1032{
1033 return (inb(port + LSR) & RCA);
1034}
1035
1036static void
1037btem_control(btem_state_t *btem, int c)
1038{
1039 int y, rows, cols;
1040
1041 rows = fb_info.cursor.pos.y;
1042 cols = fb_info.cursor.pos.x;
1043
1044 btem->btem_state = A_STATE_START;
1045 switch (c) {
1046 case A_BS:
1047 bcons_dev.bd_setpos(rows, cols - 1);
1048 break;
1049
1050 case A_HT:
1051 cols += 8 - (cols % 8);
1052 if (cols >= fb_info.terminal.x)
1053 cols = fb_info.terminal.x - 1;
1054 bcons_dev.bd_setpos(rows, cols);
1055 break;
1056
1057 case A_CR:
1058 bcons_dev.bd_setpos(rows, 0);
1059 break;
1060
1061 case A_FF:
1062 for (y = 0; y < fb_info.terminal.y; y++) {
1063 bcons_dev.bd_setpos(y, 0);
1064 bcons_dev.bd_eraseline();
1065 }
1066 bcons_dev.bd_setpos(0, 0);
1067 break;
1068
1069 case A_ESC:
1070 btem->btem_state = A_STATE_ESC;
1071 break;
1072
1073 default:
1074 bcons_dev.bd_putchar(c);
1075 break;
1076 }
1077}
1078
1079/*
1080 * if parameters [0..count - 1] are not set, set them to the value
1081 * of newparam.
1082 */
1083static void
1084btem_setparam(btem_state_t *btem, int count, int newparam)
1085{
1086 int i;
1087
1088 for (i = 0; i < count; i++) {
1089 if (btem->btem_params[i] == -1)
1090 btem->btem_params[i] = newparam;
1091 }
1092}
1093
1094static void
1095btem_chkparam(btem_state_t *btem, int c)
1096{
1097 int rows, cols;
1098
1099 rows = fb_info.cursor.pos.y;
1100 cols = fb_info.cursor.pos.x;
1101 switch (c) {
1102 case '@': /* insert char */
1103 btem_setparam(btem, 1, 1);
1104 bcons_dev.bd_shift(btem->btem_params[0]);
1105 break;
1106
1107 case 'A': /* cursor up */
1108 btem_setparam(btem, 1, 1);
1109 bcons_dev.bd_setpos(rows - btem->btem_params[0], cols);
1110 break;
1111
1112 case 'B': /* cursor down */
1113 btem_setparam(btem, 1, 1);
1114 bcons_dev.bd_setpos(rows + btem->btem_params[0], cols);
1115 break;
1116
1117 case 'C': /* cursor right */
1118 btem_setparam(btem, 1, 1);
1119 bcons_dev.bd_setpos(rows, cols + btem->btem_params[0]);
1120 break;
1121
1122 case 'D': /* cursor left */
1123 btem_setparam(btem, 1, 1);
1124 bcons_dev.bd_setpos(rows, cols - btem->btem_params[0]);
1125 break;
1126
1127 case 'K':
1128 bcons_dev.bd_eraseline();
1129 break;
1130 default:
1131 /* bcons_dev.bd_putchar(c); */
1132 break;
1133 }
1134 btem->btem_state = A_STATE_START;
1135}
1136
1137static void
1138btem_getparams(btem_state_t *btem, int c)
1139{
1140 if (isdigit(c)) {
1141 btem->btem_paramval = btem->btem_paramval * 10 + c - '0';
1142 btem->btem_gotparam = B_TRUE;
1143 return;
1144 }
1145
1146 if (btem->btem_curparam < BTEM_MAXPARAMS) {
1147 if (btem->btem_gotparam == B_TRUE) {
1148 btem->btem_params[btem->btem_curparam] =
1149 btem->btem_paramval;
1150 }
1151 btem->btem_curparam++;
1152 }
1153
1154 if (c == ';') {
1155 /* Restart parameter search */
1156 btem->btem_gotparam = B_FALSE;
1157 btem->btem_paramval = 0;
1158 } else {
1159 btem_chkparam(btem, c);
1160 }
1161}
1162
1163/* Simple boot terminal parser. */
1164static void
1165btem_parse(btem_state_t *btem, int c)
1166{
1167 int i;
1168
1169 /* Normal state? */
1170 if (btem->btem_state == A_STATE_START) {
1171 if (c == A_CSI || c < ' ')
1172 btem_control(btem, c);
1173 else
1174 bcons_dev.bd_putchar(c);
1175 return;
1176 }
1177
1178 /* In <ESC> sequence */
1179 if (btem->btem_state != A_STATE_ESC) {
1180 btem_getparams(btem, c);
1181 return;
1182 }
1183
1184 /* Previous char was <ESC> */
1185 switch (c) {
1186 case '[':
1187 btem->btem_curparam = 0;
1188 btem->btem_paramval = 0;
1189 btem->btem_gotparam = B_FALSE;
1190 /* clear the parameters */
1191 for (i = 0; i < BTEM_MAXPARAMS; i++)
1192 btem->btem_params[i] = -1;
1193 btem->btem_state = A_STATE_CSI;
1194 return;
1195
1196 case 'Q': /* <ESC>Q */
1197 case 'C': /* <ESC>C */
1198 btem->btem_state = A_STATE_START;
1199 return;
1200
1201 default:
1202 btem->btem_state = A_STATE_START;
1203 break;
1204 }
1205
1206 if (c < ' ')
1207 btem_control(btem, c);
1208 else
1209 bcons_dev.bd_putchar(c);
1210}
1211
1212static void
1213_doputchar(int device, int c)
1214{
1215 switch (device) {
1216 case CONS_TTY:
1217 serial_putchar(c);
1218 return;
1219 case CONS_SCREEN_TEXT:
1109 screen_putchar(c);
1110 return;
1220 case CONS_FRAMEBUFFER:
1112 boot_fb_putchar(c);
1221 bcons_dev.bd_cursor(B_FALSE);
1222 btem_parse(&boot_tem, c);
1223 bcons_dev.bd_cursor(B_TRUE);
1224 return;
1225 case CONS_SCREEN_GRAPHICS:
1226#if !defined(_BOOT)
1227 case CONS_USBSER:
1228 defcons_putchar(c);
1229#endif /* _BOOT */
1230 default:
1231 return;
1232 }
1233}
1234
1235void
1236bcons_putchar(int c)
1237{
1127 static int bhcharpos = 0;
1128
1238#if defined(__xpv)
1239 if (!DOMAIN_IS_INITDOMAIN(xen_info) ||
1240 console == CONS_HYPERVISOR) {
1241 bcons_putchar_xen(c);
1242 return;
1243 }
1244#endif /* __xpv */
1245
1137 if (c == '\t') {
1138 do {
1139 _doputchar(console, ' ');
1140 if (diag != console)
1141 _doputchar(diag, ' ');
1142 } while (++bhcharpos % 8);
1143 return;
1144 } else if (c == '\n' || c == '\r') {
1145 bhcharpos = 0;
1146 if (console != CONS_FRAMEBUFFER)
1147 _doputchar(console, '\r');
1148 if (diag != console && diag != CONS_FRAMEBUFFER)
1149 _doputchar(diag, '\r');
1150 _doputchar(console, c);
1246 if (c == '\n') {
1247 _doputchar(console, '\r');
1248 if (diag != console)
1152 _doputchar(diag, c);
1153 return;
1154 } else if (c == '\b') {
1155 if (bhcharpos)
1156 bhcharpos--;
1157 _doputchar(console, c);
1158 if (diag != console)
1159 _doputchar(diag, c);
1160 return;
1249 _doputchar(diag, '\r');
1250 }
1162
1163 bhcharpos++;
1251 _doputchar(console, c);
1252 if (diag != console)
1253 _doputchar(diag, c);
1254}
1255
1256/*
1257 * kernel character input functions
1258 */

--- 64 unchanged lines hidden ---