limine/common/lib/print.s2.c

240 lines
5.8 KiB
C
Raw Normal View History

2020-05-10 01:38:27 +03:00
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <lib/print.h>
#include <lib/blib.h>
2020-09-02 10:55:56 +03:00
#include <lib/term.h>
2020-10-20 03:38:44 +03:00
#include <lib/libc.h>
#if bios == 1
#include <lib/real.h>
#endif
2020-10-20 03:38:44 +03:00
#include <sys/cpu.h>
#if bios == 1
static void s2_print(const char *s, size_t len) {
for (size_t i = 0; i < len; i++) {
struct rm_regs r = {0};
char c = s[i];
switch (c) {
case '\n':
r.eax = 0x0e00 | '\r';
rm_int(0x10, &r, &r);
r = (struct rm_regs){0};
r.eax = 0x0e00 | '\n';
rm_int(0x10, &r, &r);
break;
default:
r.eax = 0x0e00 | s[i];
rm_int(0x10, &r, &r);
break;
}
}
}
#endif
2020-05-10 01:38:27 +03:00
static const char *base_digits = "0123456789abcdef";
2021-10-09 14:32:57 +03:00
#define PRINT_BUF_MAX 4096
2020-05-10 01:38:27 +03:00
static void prn_str(char *print_buf, size_t *print_buf_i, const char *string) {
size_t i;
for (i = 0; string[i]; i++) {
if (*print_buf_i == (PRINT_BUF_MAX - 1))
break;
print_buf[(*print_buf_i)++] = string[i];
}
print_buf[*print_buf_i] = 0;
}
static void prn_nstr(char *print_buf, size_t *print_buf_i, const char *string, size_t len) {
size_t i;
for (i = 0; i < len; i++) {
if (*print_buf_i == (PRINT_BUF_MAX - 1))
break;
print_buf[(*print_buf_i)++] = string[i];
}
print_buf[*print_buf_i] = 0;
}
static void prn_char(char *print_buf, size_t *print_buf_i, char c) {
if (*print_buf_i < (PRINT_BUF_MAX - 1)) {
print_buf[(*print_buf_i)++] = c;
}
print_buf[*print_buf_i] = 0;
}
static void prn_i(char *print_buf, size_t *print_buf_i, int64_t x) {
int i;
char buf[20] = {0};
if (!x) {
prn_char(print_buf, print_buf_i, '0');
return;
}
int sign = x < 0;
if (sign) x = -x;
for (i = 18; x; i--) {
buf[i] = (x % 10) + 0x30;
x = x / 10;
}
if (sign)
buf[i] = '-';
else
i++;
prn_str(print_buf, print_buf_i, buf + i);
}
static void prn_ui(char *print_buf, size_t *print_buf_i, uint64_t x) {
int i;
char buf[21] = {0};
if (!x) {
prn_char(print_buf, print_buf_i, '0');
return;
}
for (i = 19; x; i--) {
buf[i] = (x % 10) + 0x30;
x = x / 10;
}
i++;
prn_str(print_buf, print_buf_i, buf + i);
}
static void prn_x(char *print_buf, size_t *print_buf_i, uint64_t x) {
int i;
char buf[17] = {0};
if (!x) {
prn_str(print_buf, print_buf_i, "0x0");
return;
}
for (i = 15; x; i--) {
buf[i] = base_digits[(x % 16)];
x = x / 16;
}
i++;
prn_str(print_buf, print_buf_i, "0x");
prn_str(print_buf, print_buf_i, buf + i);
}
void print(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vprint(fmt, args);
va_end(args);
}
2020-09-20 13:03:44 +03:00
static char print_buf[PRINT_BUF_MAX];
2020-05-10 01:38:27 +03:00
void vprint(const char *fmt, va_list args) {
2021-02-26 03:30:27 +03:00
static bool com_initialised = false;
if (COM_OUTPUT && !com_initialised) {
// Init com1
outb(0x3F8 + 1, 0x00);
outb(0x3F8 + 3, 0x80);
2021-08-20 19:28:51 +03:00
outb(0x3F8 + 0, 0x0c); // 9600 baud
2021-02-26 03:30:27 +03:00
outb(0x3F8 + 1, 0x00);
outb(0x3F8 + 3, 0x03);
2021-08-20 19:28:51 +03:00
outb(0x3F8 + 2, 0xc7);
outb(0x3F8 + 4, 0x0b);
2021-02-26 03:30:27 +03:00
com_initialised = true;
2020-12-28 03:04:55 +03:00
}
2020-10-20 03:38:44 +03:00
2020-05-10 01:38:27 +03:00
size_t print_buf_i = 0;
for (;;) {
while (*fmt && *fmt != '%')
prn_char(print_buf, &print_buf_i, *fmt++);
if (!*fmt++)
goto out;
switch (*fmt++) {
case 's': {
char *str = (char *)va_arg(args, const char *);
if (!str)
prn_str(print_buf, &print_buf_i, "(null)");
else
prn_str(print_buf, &print_buf_i, str); }
break;
case 'S': {
char *str = (char *)va_arg(args, const char *);
size_t str_len = va_arg(args, size_t);
if (!str)
prn_str(print_buf, &print_buf_i, "(null)");
else
prn_nstr(print_buf, &print_buf_i, str, str_len); }
break;
case 'd':
prn_i(print_buf, &print_buf_i, (int64_t)va_arg(args, int32_t));
break;
case 'u':
prn_ui(print_buf, &print_buf_i, (uint64_t)va_arg(args, uint32_t));
break;
case 'x':
prn_x(print_buf, &print_buf_i, (uint64_t)va_arg(args, uint32_t));
break;
case 'D':
prn_i(print_buf, &print_buf_i, va_arg(args, int64_t));
break;
case 'U':
prn_ui(print_buf, &print_buf_i, va_arg(args, uint64_t));
break;
case 'X':
prn_x(print_buf, &print_buf_i, va_arg(args, uint64_t));
break;
case 'p':
prn_x(print_buf, &print_buf_i, va_arg(args, uintptr_t));
break;
2020-05-10 01:38:27 +03:00
case 'c': {
char c = (char)va_arg(args, int);
prn_char(print_buf, &print_buf_i, c); }
break;
default:
prn_char(print_buf, &print_buf_i, '?');
break;
}
}
out:
#if bios == 1
if (stage3_loaded) {
#endif
term_write((uint64_t)(uintptr_t)print_buf, print_buf_i);
#if bios == 1
} else {
s2_print(print_buf, print_buf_i);
}
#endif
2020-05-10 01:38:27 +03:00
2020-12-28 03:04:55 +03:00
for (size_t i = 0; i < print_buf_i; i++) {
2021-02-26 03:30:27 +03:00
if (E9_OUTPUT) {
2020-10-20 03:38:44 +03:00
outb(0xe9, print_buf[i]);
2021-02-26 03:30:27 +03:00
}
if (COM_OUTPUT) {
2021-08-20 19:28:51 +03:00
if (print_buf[i] == '\n') {
while ((inb(0x3f8 + 5) & 0x20) == 0);
2020-12-28 03:04:55 +03:00
outb(0x3f8, '\r');
2021-08-20 19:28:51 +03:00
}
while ((inb(0x3f8 + 5) & 0x20) == 0);
2020-12-28 03:04:55 +03:00
outb(0x3f8, print_buf[i]);
}
2020-10-20 03:38:44 +03:00
}
2020-05-10 01:38:27 +03:00
}