2019-05-31 08:19:02 +03:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdarg.h>
|
2020-01-22 07:02:12 +03:00
|
|
|
#include <lib/blib.h>
|
2019-05-31 08:19:02 +03:00
|
|
|
#include <drivers/vga_textmode.h>
|
2020-01-22 07:02:12 +03:00
|
|
|
#include <lib/real.h>
|
2020-01-25 04:05:19 +03:00
|
|
|
#include <sys/interrupt.h>
|
2020-01-25 05:06:56 +03:00
|
|
|
#include <lib/libc.h>
|
2020-01-25 04:05:19 +03:00
|
|
|
|
|
|
|
void pit_sleep(uint64_t pit_ticks) {
|
|
|
|
uint64_t target = global_pit_tick + pit_ticks;
|
|
|
|
while (global_pit_tick < target) {
|
|
|
|
asm volatile ("hlt");
|
|
|
|
}
|
|
|
|
}
|
2020-01-22 07:02:12 +03:00
|
|
|
|
2020-01-25 05:06:56 +03:00
|
|
|
int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks) {
|
|
|
|
uint64_t target = global_pit_tick + pit_ticks;
|
|
|
|
while (global_pit_tick < target && !kbd_int) {
|
|
|
|
asm volatile ("hlt");
|
|
|
|
}
|
|
|
|
if (kbd_int) {
|
|
|
|
kbd_int = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-22 09:13:19 +03:00
|
|
|
uint64_t strtoui(const char *s) {
|
|
|
|
uint64_t n = 0;
|
|
|
|
while (*s)
|
|
|
|
n = n * 10 + ((*(s++)) - '0');
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2020-01-22 07:02:12 +03:00
|
|
|
char getchar(void) {
|
|
|
|
struct rm_regs r = {0};
|
|
|
|
rm_int(0x16, &r, &r);
|
|
|
|
return (char)(r.eax & 0xff);
|
|
|
|
}
|
|
|
|
|
2020-01-25 05:06:56 +03:00
|
|
|
void gets(const char *orig_str, char *buf, size_t limit) {
|
|
|
|
size_t orig_str_len = strlen(orig_str);
|
|
|
|
memmove(buf, orig_str, orig_str_len);
|
|
|
|
text_write(orig_str, orig_str_len);
|
|
|
|
for (size_t i = orig_str_len; ; ) {
|
2020-01-22 07:02:12 +03:00
|
|
|
char c = getchar();
|
|
|
|
switch (c) {
|
|
|
|
case '\b':
|
|
|
|
if (i) {
|
|
|
|
i--;
|
|
|
|
text_write(&c, 1);
|
|
|
|
}
|
|
|
|
continue;
|
2020-01-22 07:20:11 +03:00
|
|
|
case '\r':
|
2020-01-22 07:02:12 +03:00
|
|
|
buf[i] = 0;
|
2020-01-22 07:20:11 +03:00
|
|
|
text_write("\n", 1);
|
2020-01-22 07:02:12 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (i < limit-1) {
|
|
|
|
buf[i++] = c;
|
|
|
|
text_write(&c, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-31 08:19:02 +03:00
|
|
|
|
|
|
|
static const char *base_digits = "0123456789abcdef";
|
|
|
|
|
|
|
|
#define PRINT_BUF_MAX 512
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-22 05:11:26 +03:00
|
|
|
static void prn_i(char *print_buf, size_t *print_buf_i, int64_t x) {
|
2019-05-31 08:19:02 +03:00
|
|
|
int i;
|
2020-01-22 05:11:26 +03:00
|
|
|
char buf[20] = {0};
|
2019-05-31 08:19:02 +03:00
|
|
|
|
|
|
|
if (!x) {
|
|
|
|
prn_char(print_buf, print_buf_i, '0');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sign = x < 0;
|
|
|
|
if (sign) x = -x;
|
|
|
|
|
2020-01-22 05:11:26 +03:00
|
|
|
for (i = 18; x; i--) {
|
2019-05-31 08:19:02 +03:00
|
|
|
buf[i] = (x % 10) + 0x30;
|
|
|
|
x = x / 10;
|
|
|
|
}
|
|
|
|
if (sign)
|
|
|
|
buf[i] = '-';
|
|
|
|
else
|
|
|
|
i++;
|
|
|
|
|
|
|
|
prn_str(print_buf, print_buf_i, buf + i);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-22 05:11:26 +03:00
|
|
|
static void prn_ui(char *print_buf, size_t *print_buf_i, uint64_t x) {
|
2019-05-31 08:19:02 +03:00
|
|
|
int i;
|
2020-01-22 05:11:26 +03:00
|
|
|
char buf[21] = {0};
|
2019-05-31 08:19:02 +03:00
|
|
|
|
|
|
|
if (!x) {
|
|
|
|
prn_char(print_buf, print_buf_i, '0');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-22 05:11:26 +03:00
|
|
|
for (i = 19; x; i--) {
|
2019-05-31 08:19:02 +03:00
|
|
|
buf[i] = (x % 10) + 0x30;
|
|
|
|
x = x / 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
prn_str(print_buf, print_buf_i, buf + i);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-22 05:11:26 +03:00
|
|
|
static void prn_x(char *print_buf, size_t *print_buf_i, uint64_t x) {
|
2019-05-31 08:19:02 +03:00
|
|
|
int i;
|
2020-01-22 05:11:26 +03:00
|
|
|
char buf[17] = {0};
|
2019-05-31 08:19:02 +03:00
|
|
|
|
|
|
|
if (!x) {
|
|
|
|
prn_str(print_buf, print_buf_i, "0x0");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-22 05:11:26 +03:00
|
|
|
for (i = 15; x; i--) {
|
2019-05-31 08:19:02 +03:00
|
|
|
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);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void print(const char *fmt, ...) {
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
|
|
|
char print_buf[PRINT_BUF_MAX];
|
|
|
|
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':
|
2020-01-22 05:11:26 +03:00
|
|
|
prn_i(print_buf, &print_buf_i, (int64_t)va_arg(args, int32_t));
|
2019-05-31 08:19:02 +03:00
|
|
|
break;
|
|
|
|
case 'u':
|
2020-01-22 05:11:26 +03:00
|
|
|
prn_ui(print_buf, &print_buf_i, (uint64_t)va_arg(args, uint32_t));
|
2019-05-31 08:19:02 +03:00
|
|
|
break;
|
|
|
|
case 'x':
|
2020-01-22 05:11:26 +03:00
|
|
|
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));
|
2019-05-31 08:19:02 +03:00
|
|
|
break;
|
|
|
|
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:
|
|
|
|
va_end(args);
|
|
|
|
text_write(print_buf, print_buf_i);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|