/* * Copyright 2010 Stefan Lankes, Chair for Operating Systems, * RWTH Aachen University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of MetalSVM. */ #include <metalsvm/stdio.h> #include <metalsvm/string.h> #include <metalsvm/stdarg.h> #include <metalsvm/spinlocks.h> #ifdef USE_VGA #include <asm/vga.h> #endif static unsigned int kmsg_counter = 0; static unsigned char kmessages[KMSG_SIZE]; static spinlock_t kio_lock = SPINLOCK_INIT; int koutput_init(void) { #ifdef USE_VGA vga_init(); #endif memset(kmessages, 0, sizeof(unsigned char)*KMSG_SIZE); return 0; } int kputchar(int c) { int ret = 1; spinlock_lock(&kio_lock); kmessages[kmsg_counter++ % KMSG_SIZE] = c; #ifdef USE_VGA ret = vga_putchar(c); #endif spinlock_unlock(&kio_lock); return ret; } int kputs(const char *str) { int i; spinlock_lock(&kio_lock); for(i=0; str[i] != '\0'; i++) kmessages[kmsg_counter++ % KMSG_SIZE] = str[i]; #ifdef USE_VGA i = vga_puts(str); #endif spinlock_unlock(&kio_lock); return i; } static void kprintu(unsigned int val, int* count) { int c = val % 10; val /= 10; if (val) kprintu(val, count); kputchar(c+0x30); if (count) (*count)++; } static void kprintx(unsigned int val, int* count) { int c = val % 16; val /= 16; if (val) kprintu(val, count); if (c < 10) kputchar(c+0x30); else kputchar(c-10+0x61); if (count) (*count)++; } int kprintf(const char* fmt, ...) { va_list ap; unsigned int i = 0; int count = 0; if (BUILTIN_EXPECT(!fmt, 0)) return 0; va_start(ap, fmt); while(fmt[i] != '\0') { if (fmt[i] == '%') { i++; switch(fmt[i]) { case '\0': continue; case 'c': { int c = va_arg(ap, int); kputchar(c); count++; } break; case 's': { char* str = va_arg(ap, char*); count += kputs(str); } break; case 'd': case 'i': { int val = va_arg(ap, int); int sig = (val < 0); if (sig) { val = -val; kputchar('-'); count++; } kprintu((unsigned int)val, &count); } break; case 'u': { unsigned int val = va_arg(ap, unsigned int); kprintu(val, &count); } break; case 'x': { unsigned int val = va_arg(ap, unsigned int); kprintx(val, &count); } break; case 'p': { size_t val = (size_t) va_arg(ap, void*); kputs("0x"); count += 2; kprintx(val, &count); } break; default: kputchar('%'); kputchar(fmt[i]); count++; break; } } else { kputchar(fmt[i]); count++; } i++; } va_end(ap); return count; }