blob: 1c3831d9b09b9cd0b9b6057a15b5949ed238d058 [file] [log] [blame]
Kevin O'Connorf076a3e2008-02-25 22:25:15 -05001// 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
Kevin O'Connor567e4e32008-04-05 11:37:51 -040010#include "util.h" // printf
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050011#include "biosvar.h" // struct bregs
12
13static void
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050014screenc(u8 c)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050015{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050016 struct bregs br;
17 memset(&br, 0, sizeof(br));
18 br.ah = 0x0e;
19 br.al = c;
20 call16_int(0x10, &br);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050021}
22
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050023// Write a charcter to the framebuffer.
24static void
25putc(u16 action, char c)
26{
Kevin O'Connorac8df8c2008-05-24 23:46:33 -040027 if (CONFIG_DEBUG_LEVEL) {
28 if (! CONFIG_COREBOOT)
29 // Send character to debug port.
30 outb(c, PORT_BIOS_DEBUG);
31 if (CONFIG_DEBUG_SERIAL)
32 // Send character to serial port.
33 debug_serial(c);
34 }
Kevin O'Connor1812e202008-05-07 21:29:50 -040035
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050036 if (action) {
Kevin O'Connor1812e202008-05-07 21:29:50 -040037 // Send character to video screen.
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -050038 if (c == '\n')
39 screenc('\r');
40 screenc(c);
41 }
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050042}
43
44// Write a string to the framebuffer.
45static void
46puts(u16 action, const char *s)
47{
48 for (; *s; s++)
49 putc(action, *s);
50}
51
52// Write a string to the framebuffer.
53static void
54puts_cs(u16 action, const char *s)
55{
56 for (;; s++) {
Kevin O'Connor41d28102008-03-30 23:22:39 -040057 char c = GET_VAR(CS, *(u8*)s);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050058 if (!c)
59 break;
60 putc(action, c);
61 }
62}
63
64// Write an unsigned integer to the screen.
65static void
66putuint(u16 action, u32 val)
67{
68 char buf[12];
69 char *d = &buf[sizeof(buf) - 1];
70 *d-- = '\0';
71 for (;;) {
Kevin O'Connor4b60c002008-02-25 22:29:55 -050072 *d = (val % 10) + '0';
Kevin O'Connorf076a3e2008-02-25 22:25:15 -050073 val /= 10;
74 if (!val)
75 break;
76 d--;
77 }
78 puts(action, d);
79}
80
81// Write a single digit hex character to the screen.
82static inline void
83putsinglehex(u16 action, u32 val)
84{
85 if (val <= 9)
86 val = '0' + val;
87 else
88 val = 'a' + val - 10;
89 putc(action, val);
90}
91
92// Write an integer in hexadecimal to the screen.
93static void
94puthex(u16 action, u32 val)
95{
96 putsinglehex(action, (val >> 28) & 0xf);
97 putsinglehex(action, (val >> 24) & 0xf);
98 putsinglehex(action, (val >> 20) & 0xf);
99 putsinglehex(action, (val >> 16) & 0xf);
100 putsinglehex(action, (val >> 12) & 0xf);
101 putsinglehex(action, (val >> 8) & 0xf);
102 putsinglehex(action, (val >> 4) & 0xf);
103 putsinglehex(action, (val >> 0) & 0xf);
104}
105
Kevin O'Connor7d0f08a2008-03-04 22:27:55 -0500106static inline int
107isdigit(u8 c)
108{
109 return c - '0' < 10;
110}
111
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400112static void
113bvprintf(u16 action, const char *fmt, va_list args)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500114{
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500115 const char *s = fmt;
116 for (;; s++) {
Kevin O'Connor41d28102008-03-30 23:22:39 -0400117 char c = GET_VAR(CS, *(u8*)s);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500118 if (!c)
119 break;
120 if (c != '%') {
121 putc(action, c);
122 continue;
123 }
124 const char *n = s+1;
Kevin O'Connor7d0f08a2008-03-04 22:27:55 -0500125 for (;;) {
Kevin O'Connor41d28102008-03-30 23:22:39 -0400126 c = GET_VAR(CS, *(u8*)n);
Kevin O'Connor7d0f08a2008-03-04 22:27:55 -0500127 if (!isdigit(c))
128 break;
129 n++;
130 }
Kevin O'Connora9096f42008-03-08 15:40:43 -0500131 if (c == 'l') {
132 // Ignore long format indicator
133 n++;
Kevin O'Connor41d28102008-03-30 23:22:39 -0400134 c = GET_VAR(CS, *(u8*)n);
Kevin O'Connora9096f42008-03-08 15:40:43 -0500135 }
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500136 s32 val;
137 const char *sarg;
138 switch (c) {
139 case '%':
140 putc(action, '%');
141 break;
142 case 'd':
143 val = va_arg(args, s32);
144 if (val < 0) {
145 putc(action, '-');
146 val = -val;
147 }
148 putuint(action, val);
149 break;
150 case 'u':
151 val = va_arg(args, s32);
152 putuint(action, val);
153 break;
Kevin O'Connorf06f03a2008-03-29 12:44:32 -0400154 case 'p':
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500155 case 'x':
156 val = va_arg(args, s32);
157 puthex(action, val);
158 break;
Kevin O'Connor12dade52008-03-01 13:35:17 -0500159 case 'c':
160 val = va_arg(args, int);
161 putc(action, val);
162 break;
Kevin O'Connore0113c92008-04-05 15:51:12 -0400163 case '.':
164 // Hack to support "%.s" - meaning string on stack.
165 if (GET_VAR(CS, *(u8*)(n+1)) != 's')
166 break;
167 n++;
168 sarg = va_arg(args, const char *);
169 puts(action, sarg);
170 break;
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500171 case 's':
172 sarg = va_arg(args, const char *);
173 puts_cs(action, sarg);
174 break;
175 default:
Kevin O'Connor4ce6a492008-02-29 00:21:27 -0500176 putc(action, '%');
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500177 n = s;
178 }
179 s = n;
180 }
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400181}
182
183void
184BX_PANIC(const char *fmt, ...)
185{
186 va_list args;
187 va_start(args, fmt);
188 bvprintf(0, fmt, args);
189 va_end(args);
190
191 // XXX - use PANIC PORT.
192 irq_disable();
193 for (;;)
194 hlt();
195}
196
197void
Kevin O'Connorac8df8c2008-05-24 23:46:33 -0400198__dprintf(const char *fmt, ...)
Kevin O'Connor567e4e32008-04-05 11:37:51 -0400199{
200 va_list args;
201 va_start(args, fmt);
202 bvprintf(0, fmt, args);
203 va_end(args);
204}
205
206void
207printf(const char *fmt, ...)
208{
209 va_list args;
210 va_start(args, fmt);
211 bvprintf(1, fmt, args);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500212 va_end(args);
213}
214
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500215static void
216dump_regs(const char *fname, const char *type, struct bregs *regs)
217{
218 if (!regs) {
Kevin O'Connorac8df8c2008-05-24 23:46:33 -0400219 __dprintf("%s %s: NULL\n", type, fname);
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500220 return;
221 }
Kevin O'Connorac8df8c2008-05-24 23:46:33 -0400222 __dprintf("%s %s: a=%x b=%x c=%x d=%x si=%x di=%x\n"
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500223 , type, fname, regs->eax, regs->ebx, regs->ecx, regs->edx
224 , regs->esi, regs->edi);
Kevin O'Connorac8df8c2008-05-24 23:46:33 -0400225 __dprintf(" ds=%x es=%x ip=%x cs=%x f=%x r=%p\n"
Kevin O'Connorf06f03a2008-03-29 12:44:32 -0400226 , regs->ds, regs->es, regs->ip, regs->cs, regs->flags, regs);
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500227}
228
Kevin O'Connorc65a3802008-03-02 13:58:23 -0500229void
Kevin O'Connored128492008-03-11 11:14:59 -0400230__debug_isr(const char *fname)
Kevin O'Connorc65a3802008-03-02 13:58:23 -0500231{
232 puts_cs(0, fname);
233 putc(0, '\n');
234}
235
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500236// Function called on handler startup.
237void
238__debug_enter(const char *fname, struct bregs *regs)
239{
Kevin O'Connor38fcbfe2008-02-25 22:30:47 -0500240 // XXX - implement run time suppression test
241 dump_regs(fname, "enter", regs);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500242}
243
244void
Kevin O'Connor6c781222008-03-09 12:19:23 -0400245__debug_fail(const char *fname, struct bregs *regs)
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500246{
Kevin O'Connor6c781222008-03-09 12:19:23 -0400247 dump_regs(fname, "fail", regs);
Kevin O'Connorf076a3e2008-02-25 22:25:15 -0500248}
Kevin O'Connor4ce6a492008-02-29 00:21:27 -0500249
250void
251__debug_stub(const char *fname, struct bregs *regs)
252{
253 dump_regs(fname, "stub", regs);
254}