1 // Raw screen writing and debug output code.
3 // Copyright (C) 2008-2013 Kevin O'Connor <kevin@koconnor.net>
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
7 #include <stdarg.h> // va_list
9 #include "farptr.h" // GET_VAR
10 #include "bregs.h" // struct bregs
11 #include "config.h" // CONFIG_*
12 #include "biosvar.h" // GET_GLOBAL
13 #include "hw/serialio.h" // serial_debug_putc
14 #include "malloc.h" // malloc_tmp
15 #include "output.h" // dprintf
16 #include "stacks.h" // call16_int
17 #include "string.h" // memset
18 #include "util.h" // ScreenAndDebug
21 void (*func)(struct putcinfo *info, char c);
25 /****************************************************************
27 ****************************************************************/
32 dprintf(1, "SeaBIOS (version %s)\n", VERSION);
33 dprintf(1, "BUILD: %s\n", BUILDINFO);
36 // Write a character to debug port(s).
38 debug_putc(struct putcinfo *action, char c)
40 if (! CONFIG_DEBUG_LEVEL)
44 coreboot_debug_putc(c);
48 // Flush any pending output to debug port(s).
55 // In segmented mode just need a dummy variable (debug_putc is always
56 // used anyway), and in 32bit flat mode need a pointer to the 32bit
57 // instance of debug_putc().
59 static struct putcinfo debuginfo VAR16;
61 static struct putcinfo debuginfo VAR32SEG;
63 static struct putcinfo debuginfo = { debug_putc };
67 /****************************************************************
69 ****************************************************************/
71 // Show a character on the screen.
76 memset(&br, 0, sizeof(br));
81 call16_int(0x10, &br);
84 // Handle a character from a printf request.
86 screen_putc(struct putcinfo *action, char c)
89 debug_putc(&debuginfo, c);
95 static struct putcinfo screeninfo = { screen_putc };
98 /****************************************************************
100 ****************************************************************/
102 // Output a character.
104 putc(struct putcinfo *action, char c)
107 // Only debugging output supported in segmented mode.
108 debug_putc(action, c);
112 void (*func)(struct putcinfo *info, char c) = GET_GLOBAL(action->func);
118 puts(struct putcinfo *action, const char *s)
120 if (!MODESEGMENT && !s)
126 // Output a string that is in the CS segment.
128 puts_cs(struct putcinfo *action, const char *s)
132 char c = GET_GLOBAL(*vs);
139 // Output an unsigned integer.
141 putuint(struct putcinfo *action, u32 val)
144 char *d = &buf[sizeof(buf) - 1];
147 *d = (val % 10) + '0';
156 // Output a single digit hex character.
158 putsinglehex(struct putcinfo *action, u32 val)
163 val = 'a' + val - 10;
167 // Output an integer in hexadecimal with a specified width.
169 puthex(struct putcinfo *action, u32 val, int width)
172 default: putsinglehex(action, (val >> 28) & 0xf);
173 case 7: putsinglehex(action, (val >> 24) & 0xf);
174 case 6: putsinglehex(action, (val >> 20) & 0xf);
175 case 5: putsinglehex(action, (val >> 16) & 0xf);
176 case 4: putsinglehex(action, (val >> 12) & 0xf);
177 case 3: putsinglehex(action, (val >> 8) & 0xf);
178 case 2: putsinglehex(action, (val >> 4) & 0xf);
179 case 1: putsinglehex(action, (val >> 0) & 0xf);
183 // Output an integer in hexadecimal with a minimum width.
185 putprettyhex(struct putcinfo *action, u32 val, int width, char padchar)
193 putc(action, padchar);
194 puthex(action, val, count);
200 return ((u8)(c - '0')) < 10;
204 bvprintf(struct putcinfo *action, const char *fmt, va_list args)
208 char c = GET_GLOBAL(*(u8*)s);
220 c = GET_GLOBAL(*(u8*)n);
223 if (!field_width && (c == '0'))
226 field_width = field_width * 10 + c - '0';
230 // Ignore long format indicator
232 c = GET_GLOBAL(*(u8*)n);
237 c = GET_GLOBAL(*(u8*)n);
246 val = va_arg(args, s32);
253 putuint(action, val);
256 val = va_arg(args, s32);
259 putuint(action, val);
262 val = va_arg(args, s32);
265 puthex(action, val, 8);
268 val = va_arg(args, s32);
270 u32 upper = va_arg(args, s32);
272 putprettyhex(action, upper, field_width - 8, padchar);
273 puthex(action, val, 8);
277 putprettyhex(action, val, field_width, padchar);
280 val = va_arg(args, int);
284 // Hack to support "%.s" - meaning string on stack.
285 if (GET_GLOBAL(*(u8*)(n+1)) != 's')
288 sarg = va_arg(args, const char *);
292 sarg = va_arg(args, const char *);
293 puts_cs(action, sarg);
304 panic(const char *fmt, ...)
306 if (CONFIG_DEBUG_LEVEL) {
309 bvprintf(&debuginfo, fmt, args);
314 // XXX - use PANIC PORT.
321 __dprintf(const char *fmt, ...)
323 if (!MODESEGMENT && CONFIG_THREADS && CONFIG_DEBUG_LEVEL >= DEBUG_thread
324 && *fmt != '\\' && *fmt != '/') {
325 struct thread_info *cur = getCurThread();
326 if (cur != &MainThread) {
327 // Show "thread id" for this debug message.
328 debug_putc(&debuginfo, '|');
329 puthex(&debuginfo, (u32)cur, 8);
330 debug_putc(&debuginfo, '|');
331 debug_putc(&debuginfo, ' ');
337 bvprintf(&debuginfo, fmt, args);
343 printf(const char *fmt, ...)
348 bvprintf(&screeninfo, fmt, args);
355 /****************************************************************
357 ****************************************************************/
359 struct snprintfinfo {
360 struct putcinfo info;
365 putc_str(struct putcinfo *info, char c)
367 struct snprintfinfo *sinfo = container_of(info, struct snprintfinfo, info);
368 if (sinfo->str >= sinfo->end)
374 // Build a formatted string. Note, this function returns the actual
375 // number of bytes used (not including null) even in the overflow
378 snprintf(char *str, size_t size, const char *fmt, ...)
383 struct snprintfinfo sinfo = { { putc_str }, str, str + size };
386 bvprintf(&sinfo.info, fmt, args);
388 char *end = sinfo.str;
389 if (end >= sinfo.end)
395 // Build a formatted string - malloc'ing the memory.
397 znprintf(size_t size, const char *fmt, ...)
402 char *str = malloc_tmp(size);
407 struct snprintfinfo sinfo = { { putc_str }, str, str + size };
410 bvprintf(&sinfo.info, fmt, args);
412 char *end = sinfo.str;
413 if (end >= sinfo.end)
420 /****************************************************************
422 ****************************************************************/
425 hexdump(const void *d, int len)
429 if (count % 8 == 0) {
430 putc(&debuginfo, '\n');
431 puthex(&debuginfo, count*4, 8);
432 putc(&debuginfo, ':');
434 putc(&debuginfo, ' ');
436 puthex(&debuginfo, *(u32*)d, 8);
441 putc(&debuginfo, '\n');
446 dump_regs(struct bregs *regs)
449 dprintf(1, " NULL\n");
452 dprintf(1, " a=%08x b=%08x c=%08x d=%08x ds=%04x es=%04x ss=%04x\n"
453 , regs->eax, regs->ebx, regs->ecx, regs->edx
454 , regs->ds, regs->es, GET_SEG(SS));
455 dprintf(1, " si=%08x di=%08x bp=%08x sp=%08x cs=%04x ip=%04x f=%04x\n"
456 , regs->esi, regs->edi, regs->ebp, (u32)®s[1]
457 , regs->code.seg, regs->code.offset, regs->flags);
460 // Report entry to an Interrupt Service Routine (ISR).
462 __debug_isr(const char *fname)
464 puts_cs(&debuginfo, fname);
465 putc(&debuginfo, '\n');
469 // Function called on handler startup.
471 __debug_enter(struct bregs *regs, const char *fname)
473 dprintf(1, "enter %s:\n", fname);
477 // Send debugging output info.
479 __debug_stub(struct bregs *regs, int lineno, const char *fname)
481 dprintf(1, "stub %s:%d:\n", fname, lineno);
485 // Report on an invalid parameter.
487 __warn_invalid(struct bregs *regs, int lineno, const char *fname)
489 if (CONFIG_DEBUG_LEVEL >= DEBUG_invalid) {
490 dprintf(1, "invalid %s:%d:\n", fname, lineno);
495 // Report on an unimplemented feature.
497 __warn_unimplemented(struct bregs *regs, int lineno, const char *fname)
499 if (CONFIG_DEBUG_LEVEL >= DEBUG_unimplemented) {
500 dprintf(1, "unimplemented %s:%d:\n", fname, lineno);
505 // Report a detected internal inconsistency.
507 __warn_internalerror(int lineno, const char *fname)
509 dprintf(1, "WARNING - internal error detected at %s:%d!\n"
513 // Report on an allocation failure.
515 __warn_noalloc(int lineno, const char *fname)
517 dprintf(1, "WARNING - Unable to allocate resource at %s:%d!\n"
521 // Report on a timeout exceeded.
523 __warn_timeout(int lineno, const char *fname)
525 dprintf(1, "WARNING - Timeout at %s:%d!\n", fname, lineno);
528 // Report a handler reporting an invalid parameter to the caller.
530 __set_invalid(struct bregs *regs, int lineno, const char *fname)
532 __warn_invalid(regs, lineno, fname);
533 set_invalid_silent(regs);
536 // Report a call of an unimplemented function.
538 __set_unimplemented(struct bregs *regs, int lineno, const char *fname)
540 __warn_unimplemented(regs, lineno, fname);
541 set_invalid_silent(regs);
544 // Report a handler reporting an invalid parameter code to the
545 // caller. Note, the lineno and return code are encoded in the same
546 // parameter as gcc does a better job of scheduling function calls
547 // when there are 3 or less parameters.
549 __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname)
552 u32 lineno = linecode >> 8;
553 __warn_invalid(regs, lineno, fname);
554 set_code_invalid_silent(regs, code);
557 // Report a call of an unimplemented function.
559 __set_code_unimplemented(struct bregs *regs, u32 linecode, const char *fname)
562 u32 lineno = linecode >> 8;
563 __warn_unimplemented(regs, lineno, fname);
564 set_code_invalid_silent(regs, code);