Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
9259 libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c
+++ new/usr/src/cmd/mdb/common/kmdb/kmdb_promif.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 *
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 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <sys/types.h>
28 28 #include <sys/termios.h>
29 29 #include <sys/promif.h>
30 30 #ifdef sun4v
31 31 #include <sys/promif_impl.h>
32 32 #endif
33 33 #include <unistd.h>
34 34 #include <string.h>
35 35 #include <stdlib.h>
36 36
37 37 #include <kmdb/kmdb_promif_impl.h>
38 38 #include <kmdb/kmdb_kdi.h>
39 39 #include <kmdb/kmdb_dpi.h>
40 40 #include <mdb/mdb_debug.h>
41 41 #include <mdb/mdb_err.h>
42 42 #include <mdb/mdb_frame.h>
43 43 #include <mdb/mdb_string.h>
44 44 #include <mdb/mdb.h>
45 45
46 46 #define KMDB_PROM_DEF_CONS_MODE "9600,n,1,-,-"
47 47
48 48 #define KMDB_PROM_READBUF_SIZE 1024
49 49
50 50 static char kmdb_prom_readbuf[KMDB_PROM_READBUF_SIZE];
51 51 static int kmdb_prom_readbuf_head;
52 52 static int kmdb_prom_readbuf_tail;
53 53
54 54 static int
55 55 kmdb_prom_getchar(int wait)
56 56 {
57 57 struct cons_polledio *pio = mdb.m_pio;
58 58 uintptr_t ischar;
59 59 uintptr_t getchar;
60 60 uintptr_t arg;
61 61
62 62 if (pio == NULL || pio->cons_polledio_getchar == NULL) {
63 63 int c;
64 64 while ((c = prom_mayget()) == -1) {
65 65 if (!wait)
66 66 return (-1);
67 67 }
68 68 return (c);
69 69 }
70 70
71 71 ischar = (uintptr_t)pio->cons_polledio_ischar;
72 72 getchar = (uintptr_t)pio->cons_polledio_getchar;
73 73 arg = (uintptr_t)pio->cons_polledio_argument;
74 74
75 75 if (!wait && ischar != NULL && !kmdb_dpi_call(ischar, 1, &arg))
76 76 return (-1);
77 77
78 78 return ((int)kmdb_dpi_call(getchar, 1, &arg));
79 79 }
80 80
81 81 static ssize_t
82 82 kmdb_prom_polled_write(caddr_t buf, size_t len)
83 83 {
84 84 uintptr_t args[2];
85 85 int i;
86 86
87 87 args[0] = (uintptr_t)mdb.m_pio->cons_polledio_argument;
88 88
89 89 for (i = 0; i < len; i++) {
90 90 args[1] = *buf++;
91 91 (void) kmdb_dpi_call(
92 92 (uintptr_t)mdb.m_pio->cons_polledio_putchar, 2, args);
93 93 }
94 94
95 95 return (len);
96 96 }
97 97
98 98 static ssize_t
99 99 kmdb_prom_reader(caddr_t buf, size_t len, int wait)
100 100 {
101 101 int nread = 0;
102 102 int c;
103 103
104 104 while (nread < len) {
105 105 if ((c = kmdb_prom_getchar(wait)) == -1)
106 106 break;
107 107
108 108 *buf++ = (char)c;
109 109 nread++;
110 110 wait = 0;
111 111 }
112 112
113 113 return (nread);
114 114 }
115 115
116 116 static ssize_t
117 117 kmdb_prom_writer(caddr_t buf, size_t len)
118 118 {
119 119 if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_putchar != NULL)
120 120 return (kmdb_prom_polled_write(buf, len));
121 121
122 122 return (kmdb_prom_obp_writer(buf, len));
123 123 }
124 124
125 125 /*
126 126 * Due to the nature of kmdb, we don't have signals. This prevents us from
127 127 * receiving asynchronous notification when the user would like to abort active
128 128 * dcmds. Whereas mdb can simply declare a SIGINT handler, we must
129 129 * occasionally poll the input stream, looking for pending ^C characters. To
130 130 * give the illusion of asynchronous interrupt delivery, this polling is
131 131 * triggered from several commonly-used functions, such as kmdb_prom_write and
132 132 * the *read and *write target ops. When an interrupt check is triggered, we
133 133 * read through pending input, looking for interrupt characters. If we find
134 134 * one, we deliver an interrupt immediately.
135 135 *
136 136 * In a read context, we can deliver the interrupt character directly back to
137 137 * the termio handler rather than raising an interrupt.
138 138 *
139 139 * OBP doesn't have an "unget" facility. Any character read for interrupt
140 140 * checking is gone forever, unless we save it. Loss of these characters
141 141 * would prevent us from supporting typeahead. We like typeahead, so we're
142 142 * going to save characters gathered during interrupt checking. As with
143 143 * ungetc(3c), however, we can only store a finite number of characters in
144 144 * our typeahead buffer. Characters read beyond that will be silently dropped
145 145 * after they undergo interrupt processing.
146 146 *
147 147 * The typeahead facility is implemented as a ring buffer, stored in
148 148 * kmdb_prom_readbuf.
149 149 */
150 150 static size_t
151 151 kmdb_prom_drain_readbuf(void *buf, size_t len)
152 152 {
153 153 size_t n, tailread;
154 154
155 155 /*
156 156 * If head > tail, life is easy - we can simply read as much as we need
157 157 * in one gulp.
158 158 */
159 159 if (kmdb_prom_readbuf_head > kmdb_prom_readbuf_tail) {
160 160 n = MIN(kmdb_prom_readbuf_head - kmdb_prom_readbuf_tail, len);
161 161 bcopy(kmdb_prom_readbuf + kmdb_prom_readbuf_tail, buf, n);
162 162 kmdb_prom_readbuf_tail += n;
163 163 return (n);
164 164
165 165 } else if (kmdb_prom_readbuf_head == kmdb_prom_readbuf_tail) {
166 166 return (0);
167 167 }
168 168
169 169 /*
170 170 * The consumable slots wrap around zero (there are slots from tail to
171 171 * zero, and from zero to head). We have to read them in two parts.
172 172 */
173 173 n = MIN(KMDB_PROM_READBUF_SIZE - kmdb_prom_readbuf_tail, len);
174 174 bcopy(kmdb_prom_readbuf + kmdb_prom_readbuf_tail, buf, n);
175 175 kmdb_prom_readbuf_tail = (kmdb_prom_readbuf_tail + n) %
176 176 KMDB_PROM_READBUF_SIZE;
177 177
178 178 if (n == len) {
179 179 /*
180 180 * We filled the passed buffer from the first part, so there's
181 181 * no need to read the second.
182 182 */
183 183 return (n);
184 184 } else {
185 185 tailread = n;
186 186 }
187 187
188 188 n = MIN(kmdb_prom_readbuf_head, len - tailread);
189 189 buf = (void *)((uintptr_t)buf + tailread);
190 190 bcopy(kmdb_prom_readbuf, buf, n);
191 191
192 192 kmdb_prom_readbuf_tail = (kmdb_prom_readbuf_tail + n) %
193 193 KMDB_PROM_READBUF_SIZE;
194 194
195 195 return (tailread + n);
196 196 }
197 197
198 198 static void
199 199 check_int(char *buf, size_t len)
200 200 {
201 201 int i;
202 202
203 203 for (i = 0; i < len; i++) {
204 204 if (buf[i] == CTRL('c')) {
205 205 kmdb_prom_readbuf_tail = kmdb_prom_readbuf_head;
206 206 if (mdb.m_intr == 0)
207 207 longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT);
208 208 else
209 209 mdb.m_pend++;
210 210 }
211 211 }
212 212 }
213 213
214 214 /*
215 215 * Attempt to refill the ring buffer from the input stream. This called from
216 216 * two contexts:
217 217 *
218 218 * Direct read: read the input into our buffer until input is exhausted, or the
219 219 * buffer is full.
220 220 *
221 221 * Interrupt check: called 'asynchronously' from the normal read routines; read
222 222 * the input into our buffer until it is exhausted, discarding input if the
223 223 * buffer is full. In this case we look ahead for any interrupt characters,
224 224 * delivering an interrupt directly if we find one.
225 225 */
226 226 static void
227 227 kmdb_prom_fill_readbuf(int check_for_int, int wait)
228 228 {
229 229 int oldhead, left, n;
230 230
231 231 /*
232 232 * Calculate the number of slots left before we wrap around to the
233 233 * beginning again.
234 234 */
235 235 left = KMDB_PROM_READBUF_SIZE - kmdb_prom_readbuf_head;
236 236 if (kmdb_prom_readbuf_tail == 0)
237 237 left--;
238 238
239 239 if (kmdb_prom_readbuf_head == kmdb_prom_readbuf_tail ||
240 240 (kmdb_prom_readbuf_head > kmdb_prom_readbuf_tail && left > 0)) {
241 241 /*
242 242 * head > tail, so we have to read in two parts - the slots
243 243 * from head until we wrap back around to zero, and the ones
244 244 * from zero to tail. We handle the first part here, and let
245 245 * the common code handle the second.
246 246 */
247 247 if ((n = kmdb_prom_reader(kmdb_prom_readbuf +
248 248 kmdb_prom_readbuf_head, left, wait)) <= 0)
249 249 return;
250 250
251 251 oldhead = kmdb_prom_readbuf_head;
252 252 kmdb_prom_readbuf_head = (kmdb_prom_readbuf_head + n) %
253 253 KMDB_PROM_READBUF_SIZE;
254 254
255 255 if (check_for_int)
256 256 check_int(kmdb_prom_readbuf + oldhead, n);
257 257
258 258 if (n != left)
259 259 return;
260 260 }
261 261
262 262 left = kmdb_prom_readbuf_tail - kmdb_prom_readbuf_head - 1;
263 263 if (left > 0) {
264 264 if ((n = kmdb_prom_reader(kmdb_prom_readbuf +
265 265 kmdb_prom_readbuf_head, left, wait)) <= 0)
266 266 return;
267 267
268 268 oldhead = kmdb_prom_readbuf_head;
269 269 kmdb_prom_readbuf_head = (kmdb_prom_readbuf_head + n) %
270 270 KMDB_PROM_READBUF_SIZE;
271 271
272 272 if (check_for_int)
273 273 check_int(kmdb_prom_readbuf + oldhead, n);
274 274
275 275 if (n != left)
276 276 return;
277 277 }
278 278
279 279 if (check_for_int) {
280 280 char c;
281 281
282 282 while (kmdb_prom_reader(&c, 1, 0) == 1)
283 283 check_int(&c, 1);
284 284 }
285 285 }
286 286
287 287 void
288 288 kmdb_prom_check_interrupt(void)
289 289 {
290 290 kmdb_prom_fill_readbuf(1, 0);
291 291 }
292 292
293 293 /*
294 294 * OBP reads are always non-blocking. If there are characters available,
295 295 * we'll return as many as we can. If nothing is available, we'll spin
296 296 * until one shows up.
297 297 */
298 298 ssize_t
299 299 kmdb_prom_read(void *buf, size_t len, struct termios *tio)
300 300 {
301 301 size_t totread = 0;
302 302 size_t thisread;
303 303 char *c = (char *)buf;
304 304 int wait = 1;
305 305
306 306 for (;;) {
307 307 kmdb_prom_fill_readbuf(0, wait);
308 308 thisread = kmdb_prom_drain_readbuf(c, len);
309 309 len -= thisread;
310 310 totread += thisread;
311 311 c += thisread;
312 312
313 313 /* wait until something shows up */
314 314 if (totread == 0)
315 315 continue;
316 316
317 317 wait = 0;
318 318
319 319 /*
320 320 * We're done if we've exhausted available input or if we've
321 321 * filled the provided buffer.
322 322 */
323 323 if (len == 0 || thisread == 0)
324 324 break;
325 325 }
326 326
327 327 if (tio->c_iflag & ICRNL) {
328 328 char *cbuf = buf;
329 329 int i;
330 330
331 331 for (i = 0; i < totread; i++) {
332 332 if (cbuf[i] == '\r')
333 333 cbuf[i] = '\n';
334 334 }
335 335 }
336 336
337 337 if (tio->c_lflag & ECHO)
338 338 (void) kmdb_prom_write(buf, totread, tio);
339 339
340 340 return (totread);
341 341 }
342 342
343 343 /*ARGSUSED*/
344 344 ssize_t
345 345 kmdb_prom_write(const void *bufp, size_t len, struct termios *tio)
346 346 {
347 347 caddr_t buf = (caddr_t)bufp;
348 348 size_t left = len;
349 349 char *nl = "\r\n";
350 350 char *c;
351 351
352 352 kmdb_prom_check_interrupt();
353 353
354 354 if (!(tio->c_oflag & ONLCR))
355 355 return (kmdb_prom_writer(buf, left));
356 356
357 357 /* translate every \n into \r\n */
358 358 while ((c = strnchr(buf, '\n', left)) != NULL) {
359 359 if (c != buf) {
360 360 size_t sz = (size_t)(c - buf);
361 361 (void) kmdb_prom_writer(buf, sz);
362 362 left -= sz;
363 363 }
364 364
365 365 buf = c + 1;
366 366 left--;
367 367
368 368 (void) kmdb_prom_writer(nl, 2);
369 369 }
370 370
371 371 if (*buf != '\0')
372 372 (void) kmdb_prom_writer(buf, left);
373 373
374 374 return (len);
375 375 }
376 376
377 377 static char *
378 378 kmdb_get_ttyio_mode(kmdb_auxv_t *kav, char *devname)
379 379 {
380 380 char *modepname, *modepval;
381 381
382 382 modepname = mdb_alloc(strlen(devname) + 5 + 1, UM_SLEEP);
383 383 (void) strcpy(modepname, devname);
384 384 (void) strcat(modepname, "-mode");
385 385
386 386 modepval = kmdb_prom_get_ddi_prop(kav, modepname);
387 387
388 388 strfree(modepname);
389 389
390 390 return (modepval);
391 391 }
392 392
393 393 static int
394 394 termios_setispeed(struct termios *tip, speed_t s)
395 395 {
396 396 if (s > (2 * CBAUD + 1))
397 397 return (-1);
398 398
399 399 if ((s << IBSHIFT) > CIBAUD) {
400 400 tip->c_cflag |= CIBAUDEXT;
401 401 s -= ((CIBAUD >> IBSHIFT) + 1);
402 402 } else
403 403 tip->c_cflag &= ~CIBAUDEXT;
404 404
405 405 tip->c_cflag = (tip->c_cflag & ~CIBAUD) | ((s << IBSHIFT) & CIBAUD);
406 406
407 407 return (0);
408 408 }
409 409
410 410 static int
411 411 termios_setospeed(struct termios *tip, speed_t s)
412 412 {
413 413 if (s > (2 * CBAUD + 1))
414 414 return (-1);
415 415
416 416 if (s > CBAUD) {
417 417 tip->c_cflag |= CBAUDEXT;
418 418 s -= (CBAUD + 1);
419 419 } else
420 420 tip->c_cflag &= ~CBAUDEXT;
421 421
422 422 tip->c_cflag = (tip->c_cflag & ~CBAUD) | (s & CBAUD);
423 423
424 424 return (0);
425 425 }
426 426
427 427 static int
428 428 kmdb_parse_mode(const char *mode, struct termios *tip, int in)
429 429 {
430 430 static const uint_t baudmap[] = {
431 431 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
432 432 1800, 2400, 4800, 9600, 19200, 38400, 57600,
433 433 76800, 115200, 153600, 230400, 307200, 460800, 921600
434 434 };
435 435 static const uint_t bitsmap[] = { CS6, CS6, CS7, CS8 };
436 436 char *m = strdup(mode);
437 437 char *w;
438 438 int rc = -1;
439 439 speed_t speed;
440 440 int baud, i;
441 441
442 442 /*
443 443 * termios supports different baud rates and flow control types for
444 444 * input and output, but it requires character width, parity, and stop
445 445 * bits to be equal in input and output. obp allows them to be
446 446 * different, but we're going to (silently) assume that nobody will use
447 447 * it that way.
448 448 */
449 449
450 450 /* baud rate - see baudmap above */
451 451 if ((w = strtok(m, ",")) == NULL)
452 452 goto parse_mode_bail;
453 453
454 454 baud = strtol(w, NULL, 10);
455 455 speed = 0;
456 456 for (i = 0; i < sizeof (baudmap) / sizeof (baudmap[0]); i++) {
457 457 if (baudmap[i] == baud) {
458 458 speed = i;
459 459 break;
460 460 }
461 461 }
462 462 if (speed == 0)
463 463 goto parse_mode_bail;
464 464
465 465 if (in == 1)
466 466 (void) termios_setispeed(tip, speed);
467 467 else
468 468 (void) termios_setospeed(tip, speed);
469 469
470 470 /* character width (bits) - 5, 6, 7, or 8 */
471 471 if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || *w < '5' ||
472 472 *w > '8')
473 473 goto parse_mode_bail;
474 474 tip->c_cflag = (tip->c_cflag & ~CSIZE) | bitsmap[*w - '5'];
475 475
476 476 /* parity - `n' (none), `e' (even), or `o' (odd) */
477 477 if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 ||
478 478 strchr("neo", *w) == NULL)
479 479 goto parse_mode_bail;
480 480
481 481 tip->c_cflag = (tip->c_cflag & ~(PARENB|PARODD));
482 482 switch (*w) {
483 483 case 'n':
484 484 /* nothing */
485 485 break;
486 486 case 'e':
487 487 tip->c_cflag |= PARENB;
488 488 break;
489 489 case 'o':
490 490 tip->c_cflag |= PARENB|PARODD;
491 491 break;
492 492 }
493 493
494 494 /*
495 495 * stop bits - 1, or 2. obp can, in theory, support 1.5 bits,
496 496 * but we can't. how many angels can dance on half of a bit?
497 497 */
498 498 if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || *w < '1' ||
499 499 *w > '2')
500 500 goto parse_mode_bail;
501 501
502 502 if (*w == '1')
503 503 tip->c_cflag &= ~CSTOPB;
504 504 else
505 505 tip->c_cflag |= CSTOPB;
506 506
507 507 /* flow control - `-' (none), `h' (h/w), or `s' (s/w - XON/XOFF) */
508 508 if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 ||
509 509 strchr("-hs", *w) == NULL)
510 510 goto parse_mode_bail;
511 511
512 512 tip->c_cflag &= ~(CRTSXOFF|CRTSCTS);
513 513 tip->c_iflag &= ~(IXON|IXANY|IXOFF);
514 514
515 515 switch (*w) {
516 516 case 'h':
517 517 tip->c_cflag |= (in == 1 ? CRTSXOFF : CRTSCTS);
518 518 break;
519 519
520 520 case 's':
521 521 tip->c_iflag |= (in == 1 ? IXOFF : IXON);
522 522 break;
523 523 }
524 524
525 525 rc = 0;
526 526
527 527 parse_mode_bail:
528 528 strfree(m);
529 529
530 530 return (rc);
531 531 }
532 532
533 533 #ifdef __sparc
534 534 #define ATTACHED_TERM_TYPE "sun"
535 535 #else
|
↓ open down ↓ |
535 lines elided |
↑ open up ↑ |
536 536 #define ATTACHED_TERM_TYPE "sun-color"
537 537 #endif
538 538
539 539 static void
540 540 kmdb_prom_term_init(kmdb_auxv_t *kav, kmdb_promif_t *pif)
541 541 {
542 542 const char ccs[NCCS] = { 0x03, 0x1c, 0x08, 0x15, 0x04, 0x00, 0x00,
543 543 0x00, 0x11, 0x13, 0x1a, 0x19, 0x12, 0x0f, 0x17, 0x16 };
544 544 char *conin = NULL, *conout = NULL;
545 545
546 - if (kmdb_prom_stdout_is_framebuffer(kav))
546 + if (kmdb_prom_stdout_is_framebuffer(kav)) {
547 + struct winsize *wsz = &pif->pif_wsz;
548 +
549 + /* Set default dimensions. */
550 + wsz->ws_row = KMDB_PIF_WINSIZE_ROWS;
551 + wsz->ws_col = KMDB_PIF_WINSIZE_COLS;
552 +
553 + kmdb_prom_get_tem_size(kav, &wsz->ws_row, &wsz->ws_col);
547 554 pif->pif_oterm = ATTACHED_TERM_TYPE;
555 + }
548 556
549 557 bzero(&pif->pif_tios, sizeof (struct termios));
550 558
551 559 /* output device characteristics */
552 560 if ((conout = kmdb_prom_get_ddi_prop(kav, "output-device")) ==
553 561 NULL || strcmp(conout, "screen") == 0) {
554 562 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
555 563 &pif->pif_tios, 0);
556 564 } else if (*conout == '/') {
557 565 /*
558 566 * We're not going to be able to get characteristics for a
559 567 * device that's specified as a path, so don't even try.
560 568 * Conveniently, this allows us to avoid chattering on
561 569 * Serengetis.
562 570 */
563 571 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
564 572 &pif->pif_tios, 0);
565 573 } else {
566 574 char *mode = kmdb_get_ttyio_mode(kav, conout);
567 575
568 576 #ifdef __sparc
569 577 /*
570 578 * Some platforms (Starfire) define a value of `ttya' for
571 579 * output-device, but neglect to provide a specific property
572 580 * with the characteristics. We'll provide a default value.
573 581 */
574 582 if (mode == NULL && strcmp(conout, "ttya") == 0) {
575 583 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
576 584 &pif->pif_tios, 0);
577 585 } else
578 586 #endif
579 587 {
580 588 if (mode == NULL || kmdb_parse_mode(mode,
581 589 &pif->pif_tios, 0) < 0) {
582 590 /*
583 591 * Either we couldn't retrieve the
584 592 * characteristics for this console, or they
585 593 * weren't parseable. The console hasn't been
586 594 * set up yet, so we can't warn. We'll have to
587 595 * silently fall back to the default
588 596 * characteristics.
589 597 */
590 598 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
591 599 &pif->pif_tios, 0);
592 600 }
593 601 }
594 602
595 603 if (mode != NULL)
596 604 kmdb_prom_free_ddi_prop(mode);
597 605 }
598 606
599 607 /* input device characteristics */
600 608 if ((conin = kmdb_prom_get_ddi_prop(kav, "input-device")) == NULL ||
601 609 strcmp(conin, "keyboard") == 0) {
602 610 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
603 611 &pif->pif_tios, 1);
604 612 } else if (*conin == '/') {
605 613 /* See similar case in output-device above */
606 614 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
607 615 &pif->pif_tios, 1);
608 616 } else {
609 617 char *mode = kmdb_get_ttyio_mode(kav, conin);
610 618
611 619 #ifdef __sparc
612 620 /*
613 621 * Some platforms (Starfire) define a value of `ttya' for
614 622 * input-device, but neglect to provide a specific property
615 623 * with the characteristics. We'll provide a default value.
616 624 */
617 625 if (mode == NULL && strcmp(conin, "ttya") == 0) {
618 626 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
619 627 &pif->pif_tios, 1);
620 628 } else
621 629 #endif
622 630 {
623 631 if (mode == NULL || kmdb_parse_mode(mode,
624 632 &pif->pif_tios, 1) < 0) {
625 633 /*
626 634 * Either we couldn't retrieve the
627 635 * characteristics for this console, or they
628 636 * weren't parseable. The console hasn't been
629 637 * set up yet, so we can't warn. We'll have to
630 638 * silently fall back to the default
631 639 * characteristics.
632 640 */
633 641 (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
634 642 &pif->pif_tios, 1);
635 643 }
636 644 }
637 645
638 646 if (mode != NULL)
639 647 kmdb_prom_free_ddi_prop(mode);
640 648 }
641 649
642 650 /* various characteristics of the prom read/write interface */
643 651 pif->pif_tios.c_iflag |= ICRNL;
644 652 pif->pif_tios.c_lflag |= ECHO;
645 653 bcopy(ccs, &pif->pif_tios.c_cc, sizeof (ccs));
646 654
647 655 if (conin != NULL)
648 656 kmdb_prom_free_ddi_prop(conin);
649 657 if (conout != NULL)
650 658 kmdb_prom_free_ddi_prop(conout);
651 659 }
652 660
653 661 char *
654 662 kmdb_prom_term_type(void)
655 663 {
656 664 return (mdb.m_promif->pif_oterm);
657 665 }
658 666
659 667 int
660 668 kmdb_prom_term_ctl(int req, void *arg)
661 669 {
662 670 switch (req) {
663 671 case TCGETS: {
664 672 struct termios *ti = arg;
665 673 bcopy(&mdb.m_promif->pif_tios, ti, sizeof (struct termios));
666 674 return (0);
667 675 }
668 676 case TIOCGWINSZ:
669 677 /*
670 678 * When kmdb is used over a serial console, we have no idea how
671 679 * large the terminal window is. When we're invoked on a local
672 680 * console, however, we do, and need to share that information
|
↓ open down ↓ |
115 lines elided |
↑ open up ↑ |
673 681 * with the debugger in order to contradict potentially
674 682 * incorrect sizing information retrieved from the terminfo
675 683 * database. One specific case where this happens is with the
676 684 * Intel console, which is 80x25. The terminfo entry for
677 685 * sun-color -- the default terminal type for local Intel
678 686 * consoles -- was cloned from sun, which has a height of 34
679 687 * rows.
680 688 */
681 689 if (mdb.m_promif->pif_oterm != NULL) {
682 690 struct winsize *wsz = arg;
683 - wsz->ws_row = KMDB_PIF_WINSIZE_ROWS;
684 - wsz->ws_col = KMDB_PIF_WINSIZE_COLS;
691 +
692 + wsz->ws_row = mdb.m_promif->pif_wsz.ws_row;
693 + wsz->ws_col = mdb.m_promif->pif_wsz.ws_col;
685 694 wsz->ws_xpixel = wsz->ws_ypixel = 0;
686 695 return (0);
687 696 }
688 697
689 698 return (set_errno(ENOTSUP));
690 699 default:
691 700 return (set_errno(EINVAL));
692 701 }
693 702 }
694 703
695 704 int
696 705 kmdb_prom_vtop(uintptr_t virt, physaddr_t *pap)
697 706 {
698 707 physaddr_t pa;
699 708 int rc = kmdb_kdi_vtop(virt, &pa);
700 709
701 710 #ifdef __sparc
702 711 if (rc < 0 && errno == EAGAIN)
703 712 rc = kmdb_prom_translate_virt(virt, &pa);
704 713 #endif
705 714
706 715 if (rc == 0 && pap != NULL)
707 716 *pap = pa;
708 717
709 718 return (rc);
710 719 }
711 720
712 721 void
713 722 kmdb_prom_debugger_entry(void)
714 723 {
715 724 /*
716 725 * While kmdb_prom_debugger_entry and kmdb_prom_debugger_exit are not
717 726 * guaranteed to be called an identical number of times (an intentional
718 727 * debugger fault will cause an additional entry call without a matching
719 728 * exit call), we must ensure that the polled I/O entry and exit calls
720 729 * match.
721 730 */
722 731 if (mdb.m_pio == NULL) {
723 732 mdb.m_pio = kmdb_kdi_get_polled_io();
724 733
725 734 if (mdb.m_pio != NULL &&
726 735 mdb.m_pio->cons_polledio_enter != NULL) {
727 736 (void) kmdb_dpi_call(
728 737 (uintptr_t)mdb.m_pio->cons_polledio_enter, 1,
729 738 (uintptr_t *)&mdb.m_pio->cons_polledio_argument);
730 739 }
731 740 }
732 741 }
733 742
734 743 void
735 744 kmdb_prom_debugger_exit(void)
736 745 {
737 746 if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_exit != NULL) {
738 747 (void) kmdb_dpi_call((uintptr_t)mdb.m_pio->cons_polledio_exit,
739 748 1, (uintptr_t *)&mdb.m_pio->cons_polledio_argument);
740 749 }
741 750
742 751 mdb.m_pio = NULL;
743 752 }
744 753
745 754 #ifdef DEBUG
746 755 /*
747 756 * The prom_* files use ASSERT, which is #defined as assfail().
748 757 * We need to redirect that to our assert function.
749 758 */
750 759 int
751 760 kmdb_prom_assfail(const char *assertion, const char *file, int line)
752 761 {
753 762 (void) mdb_dassert(assertion, file, line);
754 763 /*NOTREACHED*/
755 764 return (0);
756 765 }
757 766 #endif
758 767
759 768 /*
760 769 * Begin the initialization of the debugger/PROM interface. Initialization is
761 770 * performed in two steps due to interlocking dependencies between promif and
762 771 * both the memory allocator and mdb_create. The first phase is performed
763 772 * before either of the others have been initialized, and thus must neither
764 773 * attempt to allocate memory nor access/write to `mdb'.
765 774 */
766 775 void
767 776 kmdb_prom_init_begin(char *pgmname, kmdb_auxv_t *kav)
768 777 {
769 778 #ifdef sun4v
770 779 if (kav->kav_domaining)
771 780 kmdb_prom_init_promif(pgmname, kav);
772 781 else
773 782 prom_init(pgmname, kav->kav_romp);
774 783 #else
775 784 prom_init(pgmname, kav->kav_romp);
776 785 #endif
777 786
778 787 /* Initialize the interrupt ring buffer */
779 788 kmdb_prom_readbuf_head = kmdb_prom_readbuf_tail;
780 789
781 790 #if defined(__i386) || defined(__amd64)
782 791 kmdb_sysp = kav->kav_romp;
783 792 #endif
784 793 }
785 794
786 795 #ifdef sun4v
787 796 void
788 797 kmdb_prom_init_promif(char *pgmname, kmdb_auxv_t *kav)
789 798 {
790 799 ASSERT(kav->kav_domaining);
791 800 cif_init(pgmname, kav->kav_promif_root,
792 801 kav->kav_promif_in, kav->kav_promif_out,
793 802 kav->kav_promif_pin, kav->kav_promif_pout,
794 803 kav->kav_promif_chosennode, kav->kav_promif_optionsnode);
795 804 }
796 805 #endif
797 806
798 807 /*
799 808 * Conclude the initialization of the debugger/PROM interface. Memory
800 809 * allocation and the global `mdb' object are now available.
801 810 */
802 811 void
803 812 kmdb_prom_init_finish(kmdb_auxv_t *kav)
804 813 {
805 814 mdb.m_promif = mdb_zalloc(sizeof (kmdb_promif_t), UM_SLEEP);
806 815 kmdb_prom_term_init(kav, mdb.m_promif);
807 816 }
|
↓ open down ↓ |
113 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX