Version 0.1.2
[seabios.git] / src / output.c
1 // Raw screen writing code.
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU GPLv3 license.
6
7 #include <stdarg.h> // va_list
8
9 #include "farptr.h" // GET_VAR
10 #include "util.h" // bprintf
11 #include "biosvar.h" // struct bregs
12
13 static void
14 screenc(u8 c)
15 {
16     struct bregs br;
17     memset(&br, 0, sizeof(br));
18     br.ah = 0x0e;
19     br.al = c;
20     call16_int(0x10, &br);
21 }
22
23 // XXX
24 #define PORT_DEBUG  0x403
25
26 // Write a charcter to the framebuffer.
27 static void
28 putc(u16 action, char c)
29 {
30     outb(c, PORT_DEBUG);
31     if (action) {
32         if (c == '\n')
33             screenc('\r');
34         screenc(c);
35     }
36 }
37
38 // Write a string to the framebuffer.
39 static void
40 puts(u16 action, const char *s)
41 {
42     for (; *s; s++)
43         putc(action, *s);
44 }
45
46 // Write a string to the framebuffer.
47 static void
48 puts_cs(u16 action, const char *s)
49 {
50     for (;; s++) {
51         char c = GET_VAR(CS, (u8)*s);
52         if (!c)
53             break;
54         putc(action, c);
55     }
56 }
57
58 // Write an unsigned integer to the screen.
59 static void
60 putuint(u16 action, u32 val)
61 {
62     char buf[12];
63     char *d = &buf[sizeof(buf) - 1];
64     *d-- = '\0';
65     for (;;) {
66         *d = (val % 10) + '0';
67         val /= 10;
68         if (!val)
69             break;
70         d--;
71     }
72     puts(action, d);
73 }
74
75 // Write a single digit hex character to the screen.
76 static inline void
77 putsinglehex(u16 action, u32 val)
78 {
79     if (val <= 9)
80         val = '0' + val;
81     else
82         val = 'a' + val - 10;
83     putc(action, val);
84 }
85
86 // Write an integer in hexadecimal to the screen.
87 static void
88 puthex(u16 action, u32 val)
89 {
90     putsinglehex(action, (val >> 28) & 0xf);
91     putsinglehex(action, (val >> 24) & 0xf);
92     putsinglehex(action, (val >> 20) & 0xf);
93     putsinglehex(action, (val >> 16) & 0xf);
94     putsinglehex(action, (val >> 12) & 0xf);
95     putsinglehex(action, (val >> 8) & 0xf);
96     putsinglehex(action, (val >> 4) & 0xf);
97     putsinglehex(action, (val >> 0) & 0xf);
98 }
99
100 void
101 bprintf(u16 action, const char *fmt, ...)
102 {
103     va_list args;
104     va_start(args, fmt);
105     const char *s = fmt;
106     for (;; s++) {
107         char c = GET_VAR(CS, (u8)*s);
108         if (!c)
109             break;
110         if (c != '%') {
111             putc(action, c);
112             continue;
113         }
114         const char *n = s+1;
115         c = GET_VAR(CS, (u8)*n);
116         s32 val;
117         const char *sarg;
118         switch (c) {
119         case '%':
120             putc(action, '%');
121             break;
122         case 'd':
123             val = va_arg(args, s32);
124             if (val < 0) {
125                 putc(action, '-');
126                 val = -val;
127             }
128             putuint(action, val);
129             break;
130         case 'u':
131             val = va_arg(args, s32);
132             putuint(action, val);
133             break;
134         case 'x':
135             val = va_arg(args, s32);
136             puthex(action, val);
137             break;
138         case 's':
139             sarg = va_arg(args, const char *);
140             puts_cs(action, sarg);
141             break;
142         default:
143             putc(action, *s);
144             n = s;
145         }
146         s = n;
147     }
148     va_end(args);
149 }
150
151 static void
152 dump_regs(const char *fname, const char *type, struct bregs *regs)
153 {
154     if (!regs) {
155         bprintf(0, "%s %s: NULL\n", type, fname);
156         return;
157     }
158     bprintf(0, "%s %s: a=%x b=%x c=%x d=%x si=%x di=%x\n"
159             , type, fname, regs->eax, regs->ebx, regs->ecx, regs->edx
160             , regs->esi, regs->edi);
161     bprintf(0, "  ds=%x es=%x bp=%x sp=%x ip=%x cs=%x f=%x\n"
162             , regs->ds, regs->es, regs->ebp, regs->esp
163             , regs->ip, regs->cs, regs->flags);
164 }
165
166 // Function called on handler startup.
167 void
168 __debug_enter(const char *fname, struct bregs *regs)
169 {
170     // XXX - implement run time suppression test
171     dump_regs(fname, "enter", regs);
172 }
173
174 void
175 __debug_exit(const char *fname, struct bregs *regs)
176 {
177     if (! (regs->flags & F_CF))
178         return;
179     dump_regs(fname, "exit", regs);
180 }