Ignore precision specifiers in printf code.
[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 static inline int
101 isdigit(u8 c)
102 {
103     return c - '0' < 10;
104 }
105
106 void
107 bprintf(u16 action, const char *fmt, ...)
108 {
109     va_list args;
110     va_start(args, fmt);
111     const char *s = fmt;
112     for (;; s++) {
113         char c = GET_VAR(CS, (u8)*s);
114         if (!c)
115             break;
116         if (c != '%') {
117             putc(action, c);
118             continue;
119         }
120         const char *n = s+1;
121         for (;;) {
122             c = GET_VAR(CS, (u8)*n);
123             if (!isdigit(c))
124                 break;
125             n++;
126         }
127         s32 val;
128         const char *sarg;
129         switch (c) {
130         case '%':
131             putc(action, '%');
132             break;
133         case 'd':
134             val = va_arg(args, s32);
135             if (val < 0) {
136                 putc(action, '-');
137                 val = -val;
138             }
139             putuint(action, val);
140             break;
141         case 'u':
142             val = va_arg(args, s32);
143             putuint(action, val);
144             break;
145         case 'x':
146             val = va_arg(args, s32);
147             puthex(action, val);
148             break;
149         case 'c':
150             val = va_arg(args, int);
151             putc(action, val);
152             break;
153         case 's':
154             sarg = va_arg(args, const char *);
155             puts_cs(action, sarg);
156             break;
157         default:
158             putc(action, '%');
159             n = s;
160         }
161         s = n;
162     }
163     va_end(args);
164 }
165
166 static void
167 dump_regs(const char *fname, const char *type, struct bregs *regs)
168 {
169     if (!regs) {
170         bprintf(0, "%s %s: NULL\n", type, fname);
171         return;
172     }
173     bprintf(0, "%s %s: a=%x b=%x c=%x d=%x si=%x di=%x\n"
174             , type, fname, regs->eax, regs->ebx, regs->ecx, regs->edx
175             , regs->esi, regs->edi);
176     bprintf(0, "  ds=%x es=%x bp=%x sp=%x ip=%x cs=%x f=%x\n"
177             , regs->ds, regs->es, regs->ebp, regs->esp
178             , regs->ip, regs->cs, regs->flags);
179 }
180
181 void
182 __debug_isr(const char *fname, struct bregs *regs)
183 {
184     puts_cs(0, fname);
185     putc(0, '\n');
186 }
187
188 // Function called on handler startup.
189 void
190 __debug_enter(const char *fname, struct bregs *regs)
191 {
192     // XXX - implement run time suppression test
193     dump_regs(fname, "enter", regs);
194 }
195
196 void
197 __debug_exit(const char *fname, struct bregs *regs)
198 {
199     if (! (regs->flags & F_CF))
200         return;
201     dump_regs(fname, "exit", regs);
202 }
203
204 void
205 __debug_stub(const char *fname, struct bregs *regs)
206 {
207     dump_regs(fname, "stub", regs);
208 }