Files
kern/boot/stage2/stdio.c
T

144 lines
2.7 KiB
C

#include "stdarg.h"
#include "stdint.h"
#include "string.h"
#include "stdio.h"
#include "port.h"
static uint32_t xpos;
static uint32_t ypos;
static uint8_t attr;
void setAttr(uint8_t newattr) { attr = newattr; }
void setCursor(uint32_t row, uint32_t col) {
xpos = col;
ypos = row;
updateCursor();
}
void updateCursor() {
uint16_t pos = xpos + ypos * COLS;
outb(0x3d4, 0x0f);
outb(0x3d5, pos & 0xff);
outb(0x3d4, 0x0e);
outb(0x3d5, (pos >> 8) & 0xff);
}
void hideCursor() {
outb(0x3d4, 0x0a);
outb(0x3d5, 0x20);
}
void showCursor() {
uint8_t start = 0;
uint8_t end = 15;
outb(0x3d4, 0x0a);
outb(0x3d5, (inb(0x3d5) & 0xc0) | start);
outb(0x3d4, 0x0b);
outb(0x3d5, (inb(0x3d5) & 0xe0) | end);
}
void cls() {
uint8_t* vidmem = (uint8_t*)VIDMEM;
for (size_t i = 0; i < ROWS * COLS; i++) {
vidmem[i * 2] = 0;
vidmem[i * 2 + 1] = attr;
}
xpos = 0;
ypos = 0;
updateCursor();
}
void putat(uint32_t row, uint32_t col, int c) {
uint8_t* vidmem = (uint8_t*)VIDMEM;
vidmem[(col + row * COLS) * 2] = c & 0xFF;
vidmem[(col + row * COLS) * 2 + 1] = attr;
}
void newline() {
xpos = 0;
ypos++;
if (ypos >= ROWS) ypos = 0;
updateCursor();
}
void putc(int c) {
putat(ypos, xpos, c);
xpos++;
if (xpos >= COLS) newline();
updateCursor();
}
void puts(char* s) {
while (*s != '\0') {
if (*s == '\n' || *s == '\r') {
newline();
s++;
} else putc(*s++);
}
}
int vsnprintf(void* buf, size_t len, char* fmt, va_list args) {
char* str = (char*)buf;
size_t pos = 0;
while (*fmt != '\0') {
if (*fmt != '%') {
if (pos < len - 1) str[pos++] = *fmt++;
continue;
}
fmt++;
char pad = ' ';
int width = 0;
if (*fmt == '0') pad = '0';
while (*fmt >= '0' && *fmt <= '9') {
width *= 10;
width += *fmt++ - '0';
}
// DO NOT TALK ABOUT THIS ABOMINATION
char* s;
switch (*fmt++) {
case 'd': s = itoa(va_arg(args, int), 10); goto string;
case 'x': s = itoa(va_arg(args, int), 16); goto string;
case 's': s = va_arg(args, char*); goto string;
case 'c': if (pos < len - 1) str[pos++] = va_arg(args, char); break;
case '%': if (pos < len - 1) str[pos++] = '%'; break;
default:
if (pos < len - 1) str[pos++] = '%';
if (pos < len - 1) str[pos++] = *(fmt - 1);
break;
string:
width -= strlen(s) - 1;
if (width < 0) width = 0;
while (width-- && pos < len - 1) str[pos++] = pad;
while (*s && pos < len - 1) str[pos++] = *s++;
break;
}
}
if (len > 0) {
if (pos < len) str[pos++] = '\0';
else str[len - 1] = '\0'; // Shouldn't be able to be reached, but who knows
}
return pos;
}
int printf(char* fmt, ...) {
va_list args;
va_start(args, fmt);
char buf[256];
int ret = vsnprintf(buf, 256, fmt, args);
va_end(args);
puts(buf);
return ret;
}