aboutsummaryrefslogtreecommitdiff
path: root/printf.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2015-05-20 17:09:34 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2015-05-21 11:44:57 +0200
commiteaae11e17f022188755c67e4dd3436875e84110d (patch)
tree35625017b95776f3eb2470705cb3af2b44687548 /printf.c
parentedba90fb16ec7224da591ab8f83efe3673853a3f (diff)
downloadqboot-eaae11e17f022188755c67e4dd3436875e84110d.zip
qboot-eaae11e17f022188755c67e4dd3436875e84110d.tar.gz
qboot-eaae11e17f022188755c67e4dd3436875e84110d.tar.bz2
make a bootable BIOS
includes source from kvm-unit-tests Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'printf.c')
-rw-r--r--printf.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/printf.c b/printf.c
new file mode 100644
index 0000000..a171d24
--- /dev/null
+++ b/printf.c
@@ -0,0 +1,256 @@
+#include "bios.h"
+#include "stdio.h"
+#include "string.h"
+#include "stdlib.h"
+#include "ioport.h"
+
+typedef struct pstream {
+ char *buffer;
+ int remain;
+ int added;
+} pstream_t;
+
+typedef struct strprops {
+ char pad;
+ int npad;
+} strprops_t;
+
+static void addchar(pstream_t *p, char c)
+{
+ if (p->remain) {
+ *p->buffer++ = c;
+ --p->remain;
+ }
+ ++p->added;
+}
+
+int puts(const char *c)
+{
+ int n = 0;
+ while (c[n])
+ outb(0x3f8, c[n++]);
+ return n;
+}
+
+void print_str(pstream_t *p, const char *s, strprops_t props)
+{
+ const char *s_orig = s;
+ int npad = props.npad;
+
+ if (npad > 0) {
+ npad -= strlen(s_orig);
+ while (npad > 0) {
+ addchar(p, props.pad);
+ --npad;
+ }
+ }
+
+ while (*s)
+ addchar(p, *s++);
+
+ if (npad < 0) {
+ props.pad = ' '; /* ignore '0' flag with '-' flag */
+ npad += strlen(s_orig);
+ while (npad < 0) {
+ addchar(p, props.pad);
+ ++npad;
+ }
+ }
+}
+
+static char digits[16] = "0123456789abcdef";
+
+void print_int(pstream_t *ps, long n, int base, strprops_t props)
+{
+ char buf[sizeof(long) * 3 + 2], *p = buf;
+ int s = 0, i;
+
+ if (n < 0) {
+ n = -n;
+ s = 1;
+ }
+
+ while (n) {
+ *p++ = digits[n % base];
+ n /= base;
+ }
+
+ if (s)
+ *p++ = '-';
+
+ if (p == buf)
+ *p++ = '0';
+
+ for (i = 0; i < (p - buf) / 2; ++i) {
+ char tmp;
+
+ tmp = buf[i];
+ buf[i] = p[-1-i];
+ p[-1-i] = tmp;
+ }
+
+ *p = 0;
+
+ print_str(ps, buf, props);
+}
+
+void print_unsigned(pstream_t *ps, unsigned long n, int base,
+ strprops_t props)
+{
+ char buf[sizeof(long) * 3 + 1], *p = buf;
+ int i;
+
+ while (n) {
+ *p++ = digits[n % base];
+ n /= base;
+ }
+
+ if (p == buf)
+ *p++ = '0';
+
+ for (i = 0; i < (p - buf) / 2; ++i) {
+ char tmp;
+
+ tmp = buf[i];
+ buf[i] = p[-1-i];
+ p[-1-i] = tmp;
+ }
+
+ *p = 0;
+
+ print_str(ps, buf, props);
+}
+
+static int fmtnum(const char **fmt)
+{
+ const char *f = *fmt;
+ int len = 0, num;
+
+ if (*f == '-')
+ ++f, ++len;
+
+ while (*f >= '0' && *f <= '9')
+ ++f, ++len;
+
+ num = atol(*fmt);
+ *fmt += len;
+ return num;
+}
+
+int vsnprintf(char *buf, int size, const char *fmt, va_list va)
+{
+ pstream_t s;
+
+ s.buffer = buf;
+ s.remain = size - 1;
+ s.added = 0;
+ while (*fmt) {
+ char f = *fmt++;
+ int nlong = 0;
+ strprops_t props;
+ memset(&props, 0, sizeof(props));
+ props.pad = ' ';
+
+ if (f != '%') {
+ addchar(&s, f);
+ continue;
+ }
+ morefmt:
+ f = *fmt++;
+ do {
+ if (f == '%') {
+ addchar(&s, '%');
+ break;
+ }
+ if (f == 'c') {
+ addchar(&s, va_arg(va, int));
+ break;
+ }
+ if (f == '\0') {
+ --fmt;
+ break;
+ }
+ if (f == '0') {
+ props.pad = '0';
+ ++fmt;
+ /* fall through */
+ }
+ if ((f >= '1' && f <= '9') || f == '-') {
+ --fmt;
+ props.npad = fmtnum(&fmt);
+ goto morefmt;
+ }
+ if (f == 'l') {
+ ++nlong;
+ goto morefmt;
+ }
+ if (f == 'd') {
+ switch (nlong) {
+ case 0:
+ print_int(&s, va_arg(va, int), 10, props);
+ break;
+ case 1:
+ print_int(&s, va_arg(va, long), 10, props);
+ break;
+ default:
+ panic();
+ break;
+ }
+ break;
+ }
+ if (f == 'x') {
+ switch (nlong) {
+ case 0:
+ print_unsigned(&s, va_arg(va, unsigned), 16, props);
+ break;
+ case 1:
+ print_unsigned(&s, va_arg(va, unsigned long), 16, props);
+ break;
+ default:
+ panic();
+ break;
+ }
+ break;
+ }
+ if (f == 'p') {
+ print_str(&s, "0x", props);
+ print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props);
+ break;
+ }
+ if (f == 's') {
+ print_str(&s, va_arg(va, const char *), props);
+ break;
+ }
+ addchar(&s, f);
+ break;
+ } while(0);
+ }
+ *s.buffer = 0;
+ ++s.added;
+ return s.added;
+}
+
+
+int snprintf(char *buf, int size, const char *fmt, ...)
+{
+ va_list va;
+ int r;
+
+ va_start(va, fmt);
+ r = vsnprintf(buf, size, fmt, va);
+ va_end(va);
+ return r;
+}
+
+int printf(const char *fmt, ...)
+{
+ va_list va;
+ char buf[2000];
+ int r;
+
+ va_start(va, fmt);
+ r = vsnprintf(buf, sizeof buf, fmt, va);
+ va_end(va);
+ puts(buf);
+ return r;
+}