diff options
Diffstat (limited to 'qemu/roms/seabios/src/output.c')
-rw-r--r-- | qemu/roms/seabios/src/output.c | 565 |
1 files changed, 0 insertions, 565 deletions
diff --git a/qemu/roms/seabios/src/output.c b/qemu/roms/seabios/src/output.c deleted file mode 100644 index 8a883889c..000000000 --- a/qemu/roms/seabios/src/output.c +++ /dev/null @@ -1,565 +0,0 @@ -// Raw screen writing and debug output code. -// -// Copyright (C) 2008-2013 Kevin O'Connor <kevin@koconnor.net> -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include <stdarg.h> // va_list - -#include "farptr.h" // GET_VAR -#include "bregs.h" // struct bregs -#include "config.h" // CONFIG_* -#include "biosvar.h" // GET_GLOBAL -#include "hw/serialio.h" // serial_debug_putc -#include "malloc.h" // malloc_tmp -#include "output.h" // dprintf -#include "stacks.h" // call16_int -#include "string.h" // memset -#include "util.h" // ScreenAndDebug - -struct putcinfo { - void (*func)(struct putcinfo *info, char c); -}; - - -/**************************************************************** - * Debug output - ****************************************************************/ - -void -debug_banner(void) -{ - dprintf(1, "SeaBIOS (version %s)\n", VERSION); - dprintf(1, "BUILD: %s\n", BUILDINFO); -} - -// Write a character to debug port(s). -static void -debug_putc(struct putcinfo *action, char c) -{ - if (! CONFIG_DEBUG_LEVEL) - return; - qemu_debug_putc(c); - if (!MODESEGMENT) - coreboot_debug_putc(c); - serial_debug_putc(c); -} - -// Flush any pending output to debug port(s). -static void -debug_flush(void) -{ - serial_debug_flush(); -} - -// In segmented mode just need a dummy variable (debug_putc is always -// used anyway), and in 32bit flat mode need a pointer to the 32bit -// instance of debug_putc(). -#if MODE16 -static struct putcinfo debuginfo VAR16; -#elif MODESEGMENT -static struct putcinfo debuginfo VAR32SEG; -#else -static struct putcinfo debuginfo = { debug_putc }; -#endif - - -/**************************************************************** - * Screen writing - ****************************************************************/ - -// Show a character on the screen. -static void -screenc(char c) -{ - struct bregs br; - memset(&br, 0, sizeof(br)); - br.flags = F_IF; - br.ah = 0x0e; - br.al = c; - br.bl = 0x07; - call16_int(0x10, &br); -} - -// Handle a character from a printf request. -static void -screen_putc(struct putcinfo *action, char c) -{ - if (ScreenAndDebug) - debug_putc(&debuginfo, c); - if (c == '\n') - screenc('\r'); - screenc(c); -} - -static struct putcinfo screeninfo = { screen_putc }; - - -/**************************************************************** - * Xprintf code - ****************************************************************/ - -// Output a character. -static void -putc(struct putcinfo *action, char c) -{ - if (MODESEGMENT) { - // Only debugging output supported in segmented mode. - debug_putc(action, c); - return; - } - - void (*func)(struct putcinfo *info, char c) = GET_GLOBAL(action->func); - func(action, c); -} - -// Ouptut a string. -static void -puts(struct putcinfo *action, const char *s) -{ - if (!MODESEGMENT && !s) - s = "(NULL)"; - for (; *s; s++) - putc(action, *s); -} - -// Output a string that is in the CS segment. -static void -puts_cs(struct putcinfo *action, const char *s) -{ - char *vs = (char*)s; - for (;; vs++) { - char c = GET_GLOBAL(*vs); - if (!c) - break; - putc(action, c); - } -} - -// Output an unsigned integer. -static void -putuint(struct putcinfo *action, u32 val) -{ - char buf[12]; - char *d = &buf[sizeof(buf) - 1]; - *d-- = '\0'; - for (;;) { - *d = (val % 10) + '0'; - val /= 10; - if (!val) - break; - d--; - } - puts(action, d); -} - -// Output a single digit hex character. -static inline void -putsinglehex(struct putcinfo *action, u32 val) -{ - if (val <= 9) - val = '0' + val; - else - val = 'a' + val - 10; - putc(action, val); -} - -// Output an integer in hexadecimal with a specified width. -static void -puthex(struct putcinfo *action, u32 val, int width) -{ - switch (width) { - default: putsinglehex(action, (val >> 28) & 0xf); - case 7: putsinglehex(action, (val >> 24) & 0xf); - case 6: putsinglehex(action, (val >> 20) & 0xf); - case 5: putsinglehex(action, (val >> 16) & 0xf); - case 4: putsinglehex(action, (val >> 12) & 0xf); - case 3: putsinglehex(action, (val >> 8) & 0xf); - case 2: putsinglehex(action, (val >> 4) & 0xf); - case 1: putsinglehex(action, (val >> 0) & 0xf); - } -} - -// Output an integer in hexadecimal with a minimum width. -static void -putprettyhex(struct putcinfo *action, u32 val, int width, char padchar) -{ - u32 tmp = val; - int count = 1; - while (tmp >>= 4) - count++; - width -= count; - while (width-- > 0) - putc(action, padchar); - puthex(action, val, count); -} - -static inline int -isdigit(u8 c) -{ - return ((u8)(c - '0')) < 10; -} - -static void -bvprintf(struct putcinfo *action, const char *fmt, va_list args) -{ - const char *s = fmt; - for (;; s++) { - char c = GET_GLOBAL(*(u8*)s); - if (!c) - break; - if (c != '%') { - putc(action, c); - continue; - } - const char *n = s+1; - int field_width = 0; - char padchar = ' '; - u8 is64 = 0; - for (;;) { - c = GET_GLOBAL(*(u8*)n); - if (!isdigit(c)) - break; - if (!field_width && (c == '0')) - padchar = '0'; - else - field_width = field_width * 10 + c - '0'; - n++; - } - if (c == 'l') { - // Ignore long format indicator - n++; - c = GET_GLOBAL(*(u8*)n); - } - if (c == 'l') { - is64 = 1; - n++; - c = GET_GLOBAL(*(u8*)n); - } - s32 val; - const char *sarg; - switch (c) { - case '%': - putc(action, '%'); - break; - case 'd': - val = va_arg(args, s32); - if (is64) - va_arg(args, s32); - if (val < 0) { - putc(action, '-'); - val = -val; - } - putuint(action, val); - break; - case 'u': - val = va_arg(args, s32); - if (is64) - va_arg(args, s32); - putuint(action, val); - break; - case 'p': - val = va_arg(args, s32); - putc(action, '0'); - putc(action, 'x'); - puthex(action, val, 8); - break; - case 'x': - val = va_arg(args, s32); - if (is64) { - u32 upper = va_arg(args, s32); - if (upper) { - putprettyhex(action, upper, field_width - 8, padchar); - puthex(action, val, 8); - break; - } - } - putprettyhex(action, val, field_width, padchar); - break; - case 'c': - val = va_arg(args, int); - putc(action, val); - break; - case '.': - // Hack to support "%.s" - meaning string on stack. - if (GET_GLOBAL(*(u8*)(n+1)) != 's') - break; - n++; - sarg = va_arg(args, const char *); - puts(action, sarg); - break; - case 's': - sarg = va_arg(args, const char *); - puts_cs(action, sarg); - break; - default: - putc(action, '%'); - n = s; - } - s = n; - } -} - -void -panic(const char *fmt, ...) -{ - if (CONFIG_DEBUG_LEVEL) { - va_list args; - va_start(args, fmt); - bvprintf(&debuginfo, fmt, args); - va_end(args); - debug_flush(); - } - - // XXX - use PANIC PORT. - irq_disable(); - for (;;) - hlt(); -} - -void -__dprintf(const char *fmt, ...) -{ - if (!MODESEGMENT && CONFIG_THREADS && CONFIG_DEBUG_LEVEL >= DEBUG_thread - && *fmt != '\\' && *fmt != '/') { - struct thread_info *cur = getCurThread(); - if (cur != &MainThread) { - // Show "thread id" for this debug message. - debug_putc(&debuginfo, '|'); - puthex(&debuginfo, (u32)cur, 8); - debug_putc(&debuginfo, '|'); - debug_putc(&debuginfo, ' '); - } - } - - va_list args; - va_start(args, fmt); - bvprintf(&debuginfo, fmt, args); - va_end(args); - debug_flush(); -} - -void -printf(const char *fmt, ...) -{ - ASSERT32FLAT(); - va_list args; - va_start(args, fmt); - bvprintf(&screeninfo, fmt, args); - va_end(args); - if (ScreenAndDebug) - debug_flush(); -} - - -/**************************************************************** - * snprintf - ****************************************************************/ - -struct snprintfinfo { - struct putcinfo info; - char *str, *end; -}; - -static void -putc_str(struct putcinfo *info, char c) -{ - struct snprintfinfo *sinfo = container_of(info, struct snprintfinfo, info); - if (sinfo->str >= sinfo->end) - return; - *sinfo->str = c; - sinfo->str++; -} - -// Build a formatted string. Note, this function returns the actual -// number of bytes used (not including null) even in the overflow -// case. -int -snprintf(char *str, size_t size, const char *fmt, ...) -{ - ASSERT32FLAT(); - if (!size) - return 0; - struct snprintfinfo sinfo = { { putc_str }, str, str + size }; - va_list args; - va_start(args, fmt); - bvprintf(&sinfo.info, fmt, args); - va_end(args); - char *end = sinfo.str; - if (end >= sinfo.end) - end = sinfo.end - 1; - *end = '\0'; - return end - str; -} - -// Build a formatted string - malloc'ing the memory. -char * -znprintf(size_t size, const char *fmt, ...) -{ - ASSERT32FLAT(); - if (!size) - return NULL; - char *str = malloc_tmp(size); - if (!str) { - warn_noalloc(); - return NULL; - } - struct snprintfinfo sinfo = { { putc_str }, str, str + size }; - va_list args; - va_start(args, fmt); - bvprintf(&sinfo.info, fmt, args); - va_end(args); - char *end = sinfo.str; - if (end >= sinfo.end) - end = sinfo.end - 1; - *end = '\0'; - return str; -} - - -/**************************************************************** - * Misc helpers - ****************************************************************/ - -void -hexdump(const void *d, int len) -{ - int count=0; - while (len > 0) { - if (count % 8 == 0) { - putc(&debuginfo, '\n'); - puthex(&debuginfo, count*4, 8); - putc(&debuginfo, ':'); - } else { - putc(&debuginfo, ' '); - } - puthex(&debuginfo, *(u32*)d, 8); - count++; - len-=4; - d+=4; - } - putc(&debuginfo, '\n'); - debug_flush(); -} - -static void -dump_regs(struct bregs *regs) -{ - if (!regs) { - dprintf(1, " NULL\n"); - return; - } - dprintf(1, " a=%08x b=%08x c=%08x d=%08x ds=%04x es=%04x ss=%04x\n" - , regs->eax, regs->ebx, regs->ecx, regs->edx - , regs->ds, regs->es, GET_SEG(SS)); - dprintf(1, " si=%08x di=%08x bp=%08x sp=%08x cs=%04x ip=%04x f=%04x\n" - , regs->esi, regs->edi, regs->ebp, (u32)®s[1] - , regs->code.seg, regs->code.offset, regs->flags); -} - -// Report entry to an Interrupt Service Routine (ISR). -void -__debug_isr(const char *fname) -{ - puts_cs(&debuginfo, fname); - putc(&debuginfo, '\n'); - debug_flush(); -} - -// Function called on handler startup. -void -__debug_enter(struct bregs *regs, const char *fname) -{ - dprintf(1, "enter %s:\n", fname); - dump_regs(regs); -} - -// Send debugging output info. -void -__debug_stub(struct bregs *regs, int lineno, const char *fname) -{ - dprintf(1, "stub %s:%d:\n", fname, lineno); - dump_regs(regs); -} - -// Report on an invalid parameter. -void -__warn_invalid(struct bregs *regs, int lineno, const char *fname) -{ - if (CONFIG_DEBUG_LEVEL >= DEBUG_invalid) { - dprintf(1, "invalid %s:%d:\n", fname, lineno); - dump_regs(regs); - } -} - -// Report on an unimplemented feature. -void -__warn_unimplemented(struct bregs *regs, int lineno, const char *fname) -{ - if (CONFIG_DEBUG_LEVEL >= DEBUG_unimplemented) { - dprintf(1, "unimplemented %s:%d:\n", fname, lineno); - dump_regs(regs); - } -} - -// Report a detected internal inconsistency. -void -__warn_internalerror(int lineno, const char *fname) -{ - dprintf(1, "WARNING - internal error detected at %s:%d!\n" - , fname, lineno); -} - -// Report on an allocation failure. -void -__warn_noalloc(int lineno, const char *fname) -{ - dprintf(1, "WARNING - Unable to allocate resource at %s:%d!\n" - , fname, lineno); -} - -// Report on a timeout exceeded. -void -__warn_timeout(int lineno, const char *fname) -{ - dprintf(1, "WARNING - Timeout at %s:%d!\n", fname, lineno); -} - -// Report a handler reporting an invalid parameter to the caller. -void -__set_invalid(struct bregs *regs, int lineno, const char *fname) -{ - __warn_invalid(regs, lineno, fname); - set_invalid_silent(regs); -} - -// Report a call of an unimplemented function. -void -__set_unimplemented(struct bregs *regs, int lineno, const char *fname) -{ - __warn_unimplemented(regs, lineno, fname); - set_invalid_silent(regs); -} - -// Report a handler reporting an invalid parameter code to the -// caller. Note, the lineno and return code are encoded in the same -// parameter as gcc does a better job of scheduling function calls -// when there are 3 or less parameters. -void -__set_code_invalid(struct bregs *regs, u32 linecode, const char *fname) -{ - u8 code = linecode; - u32 lineno = linecode >> 8; - __warn_invalid(regs, lineno, fname); - set_code_invalid_silent(regs, code); -} - -// Report a call of an unimplemented function. -void -__set_code_unimplemented(struct bregs *regs, u32 linecode, const char *fname) -{ - u8 code = linecode; - u32 lineno = linecode >> 8; - __warn_unimplemented(regs, lineno, fname); - set_code_invalid_silent(regs, code); -} |