Wire up logic for graphical terminal
diff --git a/limine.bin b/limine.bin
index e6bb1327..c0cbc09c 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/src/drivers/vbe.c b/src/drivers/vbe.c
index 5fac9b83..c96eeb35 100644
--- a/src/drivers/vbe.c
+++ b/src/drivers/vbe.c
@@ -19,7 +19,7 @@ static void vga_font_retrieve(void) {
struct rm_regs r = {0};
r.eax = 0x1130;
- r.ebx = 0x06;
+ r.ebx = 0x0600;
rm_int(0x10, &r, &r);
vga_font = ext_mem_balloc(VGA_FONT_MAX);
@@ -39,6 +39,12 @@ void vbe_plot_px(int x, int y, uint32_t hex) {
vbe_framebuffer[fb_i] = hex;
}
+struct vbe_char {
+ char c;
+ uint32_t fg;
+ uint32_t bg;
+};
+
void vbe_plot_char(struct vbe_char c, int x, int y) {
int orig_x = x;
uint8_t *glyph = &vga_font[c.c * VGA_FONT_HEIGHT];
@@ -86,7 +92,7 @@ static void draw_cursor(void) {
vbe_plot_char(c, cursor_x * VGA_FONT_WIDTH, cursor_y * VGA_FONT_HEIGHT);
}
-void vbe_scroll(void) {
+static void scroll(void) {
clear_cursor();
for (int i = cols; i < rows * cols; i++) {
@@ -105,7 +111,7 @@ void vbe_scroll(void) {
draw_cursor();
}
-void vbe_clear(void) {
+void vbe_clear(bool move) {
clear_cursor();
struct vbe_char empty;
@@ -116,8 +122,10 @@ void vbe_clear(void) {
plot_char_grid(empty, i % cols, i / cols);
}
- cursor_x = 0;
- cursor_y = 0;
+ if (move) {
+ cursor_x = 0;
+ cursor_y = 0;
+ }
draw_cursor();
}
@@ -144,25 +152,78 @@ void vbe_get_cursor_pos(int *x, int *y) {
*y = cursor_y;
}
-void vbe_set_text_attributes(uint32_t fg, uint32_t bg) {
- text_fg = fg;
- text_bg = bg;
+static uint32_t ansi_colours[] = {
+ 0x00000000, // black
+ 0x00aa0000, // red
+ 0x0000aa00, // green
+ 0x00aa5500, // brown
+ 0x000000aa, // blue
+ 0x00aa00aa, // magenta
+ 0x0000aaaa, // cyan
+ 0x00aaaaaa // grey
+};
+
+void vbe_set_text_fg(int fg) {
+ text_fg = ansi_colours[fg];
}
-void vbe_set_cursor_attributes(uint32_t fg, uint32_t bg) {
- clear_cursor();
- cursor_fg = fg;
- cursor_bg = bg;
- draw_cursor();
+void vbe_set_text_bg(int bg) {
+ text_bg = ansi_colours[bg];
+}
+
+void vbe_putchar(char c) {
+ switch (c) {
+ case '\b':
+ if (cursor_x || cursor_y) {
+ clear_cursor();
+ if (cursor_x) {
+ cursor_x--;
+ } else {
+ cursor_y--;
+ cursor_x = cols - 1;
+ }
+ draw_cursor();
+ }
+ break;
+ case '\r':
+ vbe_set_cursor_pos(0, cursor_y);
+ break;
+ case '\n':
+ if (cursor_y == (rows - 1)) {
+ vbe_set_cursor_pos(0, rows - 1);
+ scroll();
+ } else {
+ vbe_set_cursor_pos(0, cursor_y + 1);
+ }
+ break;
+ default: {
+ clear_cursor();
+ struct vbe_char ch;
+ ch.c = c;
+ ch.fg = text_fg;
+ ch.bg = text_bg;
+ plot_char_grid(ch, cursor_x++, cursor_y);
+ if (cursor_x == cols) {
+ cursor_x = 0;
+ cursor_y++;
+ }
+ if (cursor_y == rows) {
+ cursor_y--;
+ scroll();
+ }
+ draw_cursor();
+ break;
+ }
+ }
}
-void vbe_tty_init(void) {
+void vbe_tty_init(int *_rows, int *_cols) {
init_vbe(&vbe_framebuffer, &vbe_pitch, &vbe_width, &vbe_height, &vbe_bpp);
vga_font_retrieve();
- cols = vbe_width / VGA_FONT_WIDTH;
- rows = vbe_height / VGA_FONT_HEIGHT;
+ *_cols = cols = vbe_width / VGA_FONT_WIDTH;
+ *_rows = rows = vbe_height / VGA_FONT_HEIGHT;
grid = ext_mem_balloc(rows * cols * sizeof(struct vbe_char));
- vbe_clear();
+ vbe_clear(true);
}
struct vbe_info_struct {
diff --git a/src/drivers/vbe.h b/src/drivers/vbe.h
index af9fa30e..03f6ac65 100644
--- a/src/drivers/vbe.h
+++ b/src/drivers/vbe.h
@@ -2,13 +2,19 @@
#define __DRIVERS__VBE_H__
#include <stdint.h>
-
-struct vbe_char {
- char c;
- uint32_t fg;
- uint32_t bg;
-};
+#include <stdbool.h>
int init_vbe(uint32_t **framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp);
+void vbe_tty_init(int *rows, int *cols);
+
+void vbe_putchar(char c);
+void vbe_clear(bool move);
+void vbe_enable_cursor(void);
+void vbe_disable_cursor(void);
+void vbe_set_cursor_pos(int x, int y);
+void vbe_get_cursor_pos(int *x, int *y);
+void vbe_set_text_fg(int fg);
+void vbe_set_text_bg(int bg);
+
#endif
diff --git a/src/drivers/vga_textmode.c b/src/drivers/vga_textmode.c
index 4aeafd41..15dcf47b 100644
--- a/src/drivers/vga_textmode.c
+++ b/src/drivers/vga_textmode.c
@@ -9,23 +9,11 @@
#define VD_COLS (80 * 2)
#define VD_ROWS 25
-static bool vga_textmode_initialised = false;
-
-static void escape_parse(char c);
-static void text_putchar(char c);
-
static char *video_mem = (char *)0xb8000;
static size_t cursor_offset = 0;
static int cursor_status = 1;
static uint8_t text_palette = 0x07;
static uint8_t cursor_palette = 0x70;
-static int escape = 0;
-static int esc_value0 = 0;
-static int esc_value1 = 0;
-static int *esc_value = &esc_value0;
-static int esc_default0 = 1;
-static int esc_default1 = 1;
-static int *esc_default = &esc_default0;
static void clear_cursor(void) {
video_mem[cursor_offset + 1] = text_palette;
@@ -51,23 +39,14 @@ static void scroll(void) {
return;
}
-void text_clear(void) {
- clear_cursor();
- for (size_t i = 0; i < VIDEO_BOTTOM; i += 2) {
- video_mem[i] = ' ';
- video_mem[i + 1] = text_palette;
- }
- cursor_offset = 0;
- draw_cursor();
- return;
-}
-
-static void text_clear_no_move(void) {
+void text_clear(bool move) {
clear_cursor();
for (size_t i = 0; i < VIDEO_BOTTOM; i += 2) {
video_mem[i] = ' ';
video_mem[i + 1] = text_palette;
}
+ if (move)
+ cursor_offset = 0;
draw_cursor();
return;
}
@@ -86,20 +65,13 @@ void text_disable_cursor(void) {
// VGA cursor code taken from: https://wiki.osdev.org/Text_Mode_Cursor
-void init_vga_textmode(void) {
+void init_vga_textmode(int *_rows, int *_cols) {
port_out_b(0x3d4, 0x0a);
port_out_b(0x3d5, 0x20);
- text_clear();
-
- vga_textmode_initialised = true;
-}
-
-void deinit_vga_textmode(void) {
- struct rm_regs r = {0};
- r.eax = 0x0003;
- rm_int(0x10, &r, &r);
+ text_clear(true);
- vga_textmode_initialised = false;
+ *_rows = VD_ROWS;
+ *_cols = VD_COLS / 2;
}
static void text_set_cursor_palette(uint8_t c) {
@@ -140,24 +112,28 @@ void text_set_cursor_pos(int x, int y) {
draw_cursor();
}
-void text_write(const char *buf, size_t count) {
- if (!vga_textmode_initialised)
- return;
- for (size_t i = 0; i < count; i++)
- text_putchar(buf[i]);
+static uint8_t ansi_colours[] = { 0, 4, 2, 0x0e, 1, 5, 3, 7 };
+
+void text_set_text_fg(int fg) {
+ text_palette = (text_palette & 0xf0) | ansi_colours[fg];
}
-static void text_putchar(char c) {
- if (escape) {
- escape_parse(c);
- return;
- }
+void text_set_text_bg(int bg) {
+ text_palette = (text_palette & 0x0f) | (ansi_colours[bg] << 4);
+}
+
+void text_putchar(char c) {
switch (c) {
- case 0x00:
+ case '\b':
+ if (cursor_offset) {
+ clear_cursor();
+ cursor_offset -= 2;
+ draw_cursor();
+ }
+ break;
+ case '\r':
+ text_set_cursor_pos(0, text_get_cursor_pos_y());
break;
- case 0x1B:
- escape = 1;
- return;
case '\n':
if (text_get_cursor_pos_y() == (VD_ROWS - 1)) {
clear_cursor();
@@ -167,16 +143,6 @@ static void text_putchar(char c) {
text_set_cursor_pos(0, (text_get_cursor_pos_y() + 1));
}
break;
- case '\r':
- text_set_cursor_pos(0, text_get_cursor_pos_y());
- break;
- case '\b':
- if (cursor_offset) {
- clear_cursor();
- cursor_offset -= 2;
- draw_cursor();
- }
- break;
default:
clear_cursor();
video_mem[cursor_offset] = c;
@@ -187,116 +153,4 @@ static void text_putchar(char c) {
cursor_offset += 2;
draw_cursor();
}
- return;
-}
-
-static uint8_t ansi_colours[] = { 0, 4, 2, 0x0e, 1, 5, 3, 7 };
-
-static void sgr(void) {
-
- if (esc_value0 >= 30 && esc_value0 <= 37) {
- uint8_t pal = text_get_text_palette();
- pal = (pal & 0xf0) + ansi_colours[esc_value0 - 30];
- text_set_text_palette(pal);
- return;
- }
-
- if (esc_value0 >= 40 && esc_value0 <= 47) {
- uint8_t pal = text_get_text_palette();
- pal = (pal & 0x0f) + ansi_colours[esc_value0 - 40] * 0x10;
- text_set_text_palette(pal);
- return;
- }
-
- return;
-}
-
-static void escape_parse(char c) {
-
- if (c >= '0' && c <= '9') {
- *esc_value *= 10;
- *esc_value += c - '0';
- *esc_default = 0;
- return;
- }
-
- switch (c) {
- case '[':
- return;
- case ';':
- esc_value = &esc_value1;
- esc_default = &esc_default1;
- return;
- case 'A':
- if (esc_default0)
- esc_value0 = 1;
- if (esc_value0 > text_get_cursor_pos_y())
- esc_value0 = text_get_cursor_pos_y();
- text_set_cursor_pos(text_get_cursor_pos_x(),
- text_get_cursor_pos_y() - esc_value0);
- break;
- case 'B':
- if (esc_default0)
- esc_value0 = 1;
- if ((text_get_cursor_pos_y() + esc_value0) > (VD_ROWS - 1))
- esc_value0 = (VD_ROWS - 1) - text_get_cursor_pos_y();
- text_set_cursor_pos(text_get_cursor_pos_x(),
- text_get_cursor_pos_y() + esc_value0);
- break;
- case 'C':
- if (esc_default0)
- esc_value0 = 1;
- if ((text_get_cursor_pos_x() + esc_value0) > (VD_COLS / 2 - 1))
- esc_value0 = (VD_COLS / 2 - 1) - text_get_cursor_pos_x();
- text_set_cursor_pos(text_get_cursor_pos_x() + esc_value0,
- text_get_cursor_pos_y());
- break;
- case 'D':
- if (esc_default0)
- esc_value0 = 1;
- if (esc_value0 > text_get_cursor_pos_x())
- esc_value0 = text_get_cursor_pos_x();
- text_set_cursor_pos(text_get_cursor_pos_x() - esc_value0,
- text_get_cursor_pos_y());
- break;
- case 'H':
- esc_value0--;
- esc_value1--;
- if (esc_default0)
- esc_value0 = 0;
- if (esc_default1)
- esc_value1 = 0;
- if (esc_value1 >= (VD_COLS / 2))
- esc_value1 = (VD_COLS / 2) - 1;
- if (esc_value0 >= VD_ROWS)
- esc_value0 = VD_ROWS - 1;
- text_set_cursor_pos(esc_value1, esc_value0);
- break;
- case 'm':
- sgr();
- break;
- case 'J':
- switch (esc_value0) {
- case 2:
- text_clear_no_move();
- break;
- default:
- break;
- }
- break;
- default:
- escape = 0;
- text_putchar('?');
- break;
- }
-
- esc_value = &esc_value0;
- esc_value0 = 0;
- esc_value1 = 0;
- esc_default = &esc_default0;
- esc_default0 = 1;
- esc_default1 = 1;
- escape = 0;
-
- return;
}
diff --git a/src/drivers/vga_textmode.h b/src/drivers/vga_textmode.h
index 310badf0..7cc3cc97 100644
--- a/src/drivers/vga_textmode.h
+++ b/src/drivers/vga_textmode.h
@@ -1,18 +1,17 @@
#ifndef __DRIVERS__VGA_TEXTMODE_H__
#define __DRIVERS__VGA_TEXTMODE_H__
-#include <stddef.h>
+#include <stdbool.h>
-void init_vga_textmode(void);
-void deinit_vga_textmode(void);
+void init_vga_textmode(int *rows, int *cols);
-void text_write(const char *, size_t);
-
-void text_get_cursor_pos(int *x, int *y);
-void text_set_cursor_pos(int x, int y);
-
-void text_clear(void);
+void text_putchar(char c);
+void text_clear(bool move);
void text_enable_cursor(void);
void text_disable_cursor(void);
+void text_set_cursor_pos(int x, int y);
+void text_get_cursor_pos(int *x, int *y);
+void text_set_text_fg(int fg);
+void text_set_text_bg(int bg);
#endif
diff --git a/src/lib/blib.c b/src/lib/blib.c
index 3165da38..6f598cd3 100644
--- a/src/lib/blib.c
+++ b/src/lib/blib.c
@@ -4,7 +4,7 @@
#include <stdbool.h>
#include <lib/blib.h>
#include <lib/libc.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
#include <lib/real.h>
#include <lib/cio.h>
#include <lib/e820.h>
@@ -214,14 +214,14 @@ int getchar(void) {
static void gets_reprint_string(int x, int y, const char *s, size_t limit) {
int last_x, last_y;
- text_get_cursor_pos(&last_x, &last_y);
- text_set_cursor_pos(x, y);
+ get_cursor_pos(&last_x, &last_y);
+ set_cursor_pos(x, y);
for (size_t i = 0; i < limit; i++) {
- text_write(" ", 1);
+ term_write(" ", 1);
}
- text_set_cursor_pos(x, y);
- text_write(s, strlen(s));
- text_set_cursor_pos(last_x, last_y);
+ set_cursor_pos(x, y);
+ term_write(s, strlen(s));
+ set_cursor_pos(last_x, last_y);
}
void gets(const char *orig_str, char *buf, size_t limit) {
@@ -230,7 +230,7 @@ void gets(const char *orig_str, char *buf, size_t limit) {
buf[orig_str_len] = 0;
int orig_x, orig_y;
- text_get_cursor_pos(&orig_x, &orig_y);
+ get_cursor_pos(&orig_x, &orig_y);
print("%s", buf);
@@ -240,13 +240,13 @@ void gets(const char *orig_str, char *buf, size_t limit) {
case GETCHAR_CURSOR_LEFT:
if (i) {
i--;
- text_write("\b", 1);
+ term_write("\b", 1);
}
continue;
case GETCHAR_CURSOR_RIGHT:
if (i < strlen(buf)) {
i++;
- text_write(" ", 1);
+ term_write(" ", 1);
gets_reprint_string(orig_x, orig_y, buf, limit);
}
continue;
@@ -258,12 +258,12 @@ void gets(const char *orig_str, char *buf, size_t limit) {
if (!buf[j])
break;
}
- text_write("\b", 1);
+ term_write("\b", 1);
gets_reprint_string(orig_x, orig_y, buf, limit);
}
continue;
case '\r':
- text_write("\n", 1);
+ term_write("\n", 1);
return;
default:
if (strlen(buf) < limit-1) {
@@ -273,7 +273,7 @@ void gets(const char *orig_str, char *buf, size_t limit) {
break;
}
buf[i++] = c;
- text_write(" ", 1);
+ term_write(" ", 1);
gets_reprint_string(orig_x, orig_y, buf, limit);
}
}
diff --git a/src/lib/print.c b/src/lib/print.c
index 947817fc..6531654a 100644
--- a/src/lib/print.c
+++ b/src/lib/print.c
@@ -4,7 +4,7 @@
#include <lib/print.h>
#include <lib/blib.h>
#include <lib/cio.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
static const char *base_digits = "0123456789abcdef";
@@ -167,7 +167,7 @@ void vprint(const char *fmt, va_list args) {
}
out:
- text_write(print_buf, print_buf_i);
+ term_write(print_buf, print_buf_i);
#ifdef E9_OUTPUT
for (size_t i = 0; i < print_buf_i; i++)
diff --git a/src/lib/term.c b/src/lib/term.c
new file mode 100644
index 00000000..1f87dfcf
--- /dev/null
+++ b/src/lib/term.c
@@ -0,0 +1,209 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <lib/term.h>
+#include <lib/real.h>
+#include <drivers/vga_textmode.h>
+#include <drivers/vbe.h>
+
+static enum {
+ NOT_READY,
+ VBE,
+ TEXTMODE
+} term_backend = NOT_READY;
+
+void (*raw_putchar)(char c);
+void (*clear)(bool move);
+void (*enable_cursor)(void);
+void (*disable_cursor)(void);
+void (*set_cursor_pos)(int x, int y);
+void (*get_cursor_pos)(int *x, int *y);
+void (*set_text_fg)(int fg);
+void (*set_text_bg)(int bg);
+
+static int rows, cols;
+
+void term_vbe(void) {
+ vbe_tty_init(&rows, &cols);
+
+ raw_putchar = vbe_putchar;
+ clear = vbe_clear;
+ enable_cursor = vbe_enable_cursor;
+ disable_cursor = vbe_disable_cursor;
+ set_cursor_pos = vbe_set_cursor_pos;
+ get_cursor_pos = vbe_get_cursor_pos;
+ set_text_fg = vbe_set_text_fg;
+ set_text_bg = vbe_set_text_bg;
+
+ term_backend = VBE;
+}
+
+void term_textmode(void) {
+ init_vga_textmode(&rows, &cols);
+
+ raw_putchar = text_putchar;
+ clear = text_clear;
+ enable_cursor = text_enable_cursor;
+ disable_cursor = text_disable_cursor;
+ set_cursor_pos = text_set_cursor_pos;
+ get_cursor_pos = text_get_cursor_pos;
+ set_text_fg = text_set_text_fg;
+ set_text_bg = text_set_text_bg;
+
+ term_backend = TEXTMODE;
+}
+
+void term_deinit(void) {
+ struct rm_regs r = {0};
+ r.eax = 0x0003;
+ rm_int(0x10, &r, &r);
+
+ term_backend = NOT_READY;
+}
+
+static void term_putchar(char c);
+
+void term_write(const char *buf, size_t count) {
+ if (term_backend == NOT_READY)
+ return;
+ for (size_t i = 0; i < count; i++)
+ term_putchar(buf[i]);
+}
+
+static int get_cursor_pos_x(void) {
+ int x, y;
+ get_cursor_pos(&x, &y);
+ return x;
+}
+
+static int get_cursor_pos_y(void) {
+ int x, y;
+ get_cursor_pos(&x, &y);
+ return y;
+}
+
+static void escape_parse(char c);
+
+static int escape = 0;
+static int esc_value0 = 0;
+static int esc_value1 = 0;
+static int *esc_value = &esc_value0;
+static int esc_default0 = 1;
+static int esc_default1 = 1;
+static int *esc_default = &esc_default0;
+
+static void term_putchar(char c) {
+ if (escape) {
+ escape_parse(c);
+ return;
+ }
+ switch (c) {
+ case 0x00:
+ break;
+ case 0x1B:
+ escape = 1;
+ return;
+ default:
+ raw_putchar(c);
+ break;
+ }
+}
+
+static void sgr(void) {
+ if (esc_value0 >= 30 && esc_value0 <= 37) {
+ set_text_fg(esc_value0 - 30);
+ return;
+ }
+
+ if (esc_value0 >= 40 && esc_value0 <= 47) {
+ set_text_bg(esc_value0 - 40);
+ return;
+ }
+}
+
+static void escape_parse(char c) {
+ if (c >= '0' && c <= '9') {
+ *esc_value *= 10;
+ *esc_value += c - '0';
+ *esc_default = 0;
+ return;
+ }
+
+ switch (c) {
+ case '[':
+ return;
+ case ';':
+ esc_value = &esc_value1;
+ esc_default = &esc_default1;
+ return;
+ case 'A':
+ if (esc_default0)
+ esc_value0 = 1;
+ if (esc_value0 > get_cursor_pos_y())
+ esc_value0 = get_cursor_pos_y();
+ set_cursor_pos(get_cursor_pos_x(),
+ get_cursor_pos_y() - esc_value0);
+ break;
+ case 'B':
+ if (esc_default0)
+ esc_value0 = 1;
+ if ((get_cursor_pos_y() + esc_value0) > (rows - 1))
+ esc_value0 = (rows - 1) - get_cursor_pos_y();
+ set_cursor_pos(get_cursor_pos_x(),
+ get_cursor_pos_y() + esc_value0);
+ break;
+ case 'C':
+ if (esc_default0)
+ esc_value0 = 1;
+ if ((get_cursor_pos_x() + esc_value0) > (cols - 1))
+ esc_value0 = (cols - 1) - get_cursor_pos_x();
+ set_cursor_pos(get_cursor_pos_x() + esc_value0,
+ get_cursor_pos_y());
+ break;
+ case 'D':
+ if (esc_default0)
+ esc_value0 = 1;
+ if (esc_value0 > get_cursor_pos_x())
+ esc_value0 = get_cursor_pos_x();
+ set_cursor_pos(get_cursor_pos_x() - esc_value0,
+ get_cursor_pos_y());
+ break;
+ case 'H':
+ esc_value0--;
+ esc_value1--;
+ if (esc_default0)
+ esc_value0 = 0;
+ if (esc_default1)
+ esc_value1 = 0;
+ if (esc_value1 >= cols)
+ esc_value1 = cols - 1;
+ if (esc_value0 >= rows)
+ esc_value0 = rows - 1;
+ set_cursor_pos(esc_value1, esc_value0);
+ break;
+ case 'm':
+ sgr();
+ break;
+ case 'J':
+ switch (esc_value0) {
+ case 2:
+ clear(false);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ escape = 0;
+ raw_putchar('?');
+ break;
+ }
+
+ esc_value = &esc_value0;
+ esc_value0 = 0;
+ esc_value1 = 0;
+ esc_default = &esc_default0;
+ esc_default0 = 1;
+ esc_default1 = 1;
+ escape = 0;
+}
diff --git a/src/lib/term.h b/src/lib/term.h
new file mode 100644
index 00000000..4a4be458
--- /dev/null
+++ b/src/lib/term.h
@@ -0,0 +1,21 @@
+#ifndef __LIB__TERM_H__
+#define __LIB__TERM_H__
+
+#include <stddef.h>
+#include <stdbool.h>
+
+extern void (*raw_putchar)(char c);
+extern void (*clear)(bool move);
+extern void (*enable_cursor)(void);
+extern void (*disable_cursor)(void);
+extern void (*set_cursor_pos)(int x, int y);
+extern void (*get_cursor_pos)(int *x, int *y);
+extern void (*set_text_fg)(int fg);
+extern void (*set_text_bg)(int bg);
+
+void term_vbe(void);
+void term_textmode(void);
+void term_deinit(void);
+void term_write(const char *buf, size_t count);
+
+#endif
diff --git a/src/main.c b/src/main.c
index 480ba396..4edbd029 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@ ASM_BASIC(
);
#include <limine.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
#include <lib/real.h>
#include <lib/blib.h>
#include <lib/libc.h>
@@ -32,8 +32,7 @@ ASM_BASIC(
#include <menu.h>
void main(int boot_drive) {
- // Initial prompt.
- init_vga_textmode();
+ term_textmode();
print("Limine " LIMINE_VERSION "\n\n");
@@ -59,25 +58,32 @@ void main(int boot_drive) {
}
}
- char *cmdline = menu();
-
init_e820();
init_memmap();
- char proto[32];
- if (!config_get_value(proto, 0, 32, "KERNEL_PROTO")) {
- if (!config_get_value(proto, 0, 32, "PROTOCOL")) {
+ char buf[32];
+
+ if (config_get_value(buf, 0, 32, "GRAPHICS")) {
+ if (!strcmp(buf, "on")) {
+ term_vbe();
+ }
+ }
+
+ char *cmdline = menu();
+
+ if (!config_get_value(buf, 0, 32, "KERNEL_PROTO")) {
+ if (!config_get_value(buf, 0, 32, "PROTOCOL")) {
panic("PROTOCOL not specified");
}
}
- if (!strcmp(proto, "stivale")) {
+ if (!strcmp(buf, "stivale")) {
stivale_load(cmdline, boot_drive);
- } else if (!strcmp(proto, "stivale2")) {
+ } else if (!strcmp(buf, "stivale2")) {
stivale2_load(cmdline, boot_drive);
- } else if (!strcmp(proto, "linux")) {
+ } else if (!strcmp(buf, "linux")) {
linux_load(cmdline, boot_drive);
- } else if (!strcmp(proto, "chainload")) {
+ } else if (!strcmp(buf, "chainload")) {
chainload();
} else {
panic("Invalid protocol specified");
diff --git a/src/menu.c b/src/menu.c
index 8766c147..cf1f139a 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -7,7 +7,7 @@
#include <lib/blib.h>
#include <lib/libc.h>
#include <lib/config.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
static char *cmdline;
#define CMDLINE_MAX 1024
@@ -26,12 +26,12 @@ char *menu(void) {
}
}
- text_disable_cursor();
+ disable_cursor();
int selected_entry = 0;
bool skip_timeout = false;
refresh:
- text_clear();
+ clear(true);
print("\n\n \e[36m Limine " LIMINE_VERSION " \e[37m\n\n\n");
print("Select an entry:\n\n");
@@ -78,17 +78,17 @@ refresh:
case '\r':
autoboot:
config_set_entry(selected_entry);
- text_enable_cursor();
+ enable_cursor();
if (!config_get_value(cmdline, 0, CMDLINE_MAX, "KERNEL_CMDLINE")) {
if (!config_get_value(cmdline, 0, CMDLINE_MAX, "CMDLINE")) {
cmdline[0] = '\0';
}
}
- text_clear();
+ clear(true);
return cmdline;
case 'e':
config_set_entry(selected_entry);
- text_enable_cursor();
+ enable_cursor();
if (!config_get_value(cmdline, 0, CMDLINE_MAX, "KERNEL_CMDLINE")) {
if (!config_get_value(cmdline, 0, CMDLINE_MAX, "CMDLINE")) {
cmdline[0] = '\0';
@@ -96,7 +96,7 @@ refresh:
}
print("\n\n> ");
gets(cmdline, cmdline, CMDLINE_MAX);
- text_clear();
+ clear(true);
return cmdline;
}
}
diff --git a/src/protos/chainload.c b/src/protos/chainload.c
index d72f5c48..f073db13 100644
--- a/src/protos/chainload.c
+++ b/src/protos/chainload.c
@@ -5,7 +5,7 @@
#include <lib/config.h>
#include <lib/blib.h>
#include <drivers/disk.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
#include <lib/asm.h>
void chainload(void) {
@@ -25,7 +25,7 @@ void chainload(void) {
drive = (int)strtoui(buf);
}
- deinit_vga_textmode();
+ term_deinit();
if (part != -1) {
struct part p;
diff --git a/src/protos/linux.c b/src/protos/linux.c
index e296b599..3e38f3b7 100644
--- a/src/protos/linux.c
+++ b/src/protos/linux.c
@@ -4,7 +4,7 @@
#include <fs/file.h>
#include <lib/blib.h>
#include <lib/real.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
#include <lib/config.h>
#include <lib/print.h>
#include <lib/memmap.h>
@@ -135,7 +135,7 @@ void linux_load(char *cmdline, int boot_drive) {
uint16_t real_mode_code_seg = rm_seg(real_mode_code);
uint16_t kernel_entry_seg = real_mode_code_seg + 0x20;
- deinit_vga_textmode();
+ term_deinit();
ASM(
"cli\n\t"
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index ebf10fce..6bec7370 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -12,7 +12,7 @@
#include <lib/rand.h>
#include <lib/real.h>
#include <drivers/vbe.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
#include <drivers/pic.h>
#include <fs/file.h>
#include <lib/asm.h>
@@ -224,6 +224,8 @@ void stivale_load(char *cmdline, int boot_drive) {
stivale_struct.framebuffer_height = stivale_hdr.framebuffer_height;
stivale_struct.framebuffer_bpp = stivale_hdr.framebuffer_bpp;
+ term_deinit();
+
if (stivale_hdr.flags & (1 << 0)) {
uint32_t *fb32;
init_vbe(&fb32,
@@ -232,8 +234,6 @@ void stivale_load(char *cmdline, int boot_drive) {
&stivale_struct.framebuffer_height,
&stivale_struct.framebuffer_bpp);
stivale_struct.framebuffer_addr = (uint64_t)(size_t)fb32;
- } else {
- deinit_vga_textmode();
}
size_t memmap_entries;
@@ -241,6 +241,12 @@ void stivale_load(char *cmdline, int boot_drive) {
stivale_struct.memory_map_entries = (uint64_t)memmap_entries;
stivale_struct.memory_map_addr = (uint64_t)(size_t)memmap;
+ stivale_spinup(bits, level5pg && (stivale_hdr.flags & (1 << 1)),
+ entry_point, &stivale_struct, stivale_hdr.stack);
+}
+
+__attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
+ uint64_t entry_point, void *stivale_struct, uint64_t stack) {
if (bits == 64) {
// If we're going 64, we might as well call this BIOS interrupt
// to tell the BIOS that we are entering Long Mode, since it is in
@@ -256,7 +262,7 @@ void stivale_load(char *cmdline, int boot_drive) {
if (bits == 64) {
void *pagemap_ptr;
- if (level5pg && (stivale_hdr.flags & (1 << 1))) {
+ if (level5pg) {
// Enable CR4.LA57
ASM(
"mov eax, cr4\n\t"
@@ -376,7 +382,7 @@ void stivale_load(char *cmdline, int boot_drive) {
"iretq\n\t"
".code32\n\t",
: "a" (pagemap_ptr), "b" (&entry_point),
- "D" (&stivale_struct), "S" (&stivale_hdr.stack)
+ "D" (stivale_struct), "S" (&stack)
: "memory"
);
} else if (bits == 32) {
@@ -402,8 +408,9 @@ void stivale_load(char *cmdline, int boot_drive) {
"xor ebp, ebp\n\t"
"iret\n\t",
- : "b" (&entry_point), "D" (&stivale_struct), "S" (&stivale_hdr.stack)
+ : "b" (&entry_point), "D" (stivale_struct), "S" (&stack)
: "memory"
);
}
+ for (;;);
}
diff --git a/src/protos/stivale.h b/src/protos/stivale.h
index 5c808917..5a6fdaa6 100644
--- a/src/protos/stivale.h
+++ b/src/protos/stivale.h
@@ -1,8 +1,11 @@
#ifndef __PROTOS__STIVALE_H__
#define __PROTOS__STIVALE_H__
-#include <fs/file.h>
+#include <stdbool.h>
+#include <stdint.h>
void stivale_load(char *cmdline, int boot_drive);
+__attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
+ uint64_t entry_point, void *stivale_struct, uint64_t stack);
#endif
diff --git a/src/protos/stivale2.c b/src/protos/stivale2.c
index b7a1fd46..d5a4d6f2 100644
--- a/src/protos/stivale2.c
+++ b/src/protos/stivale2.c
@@ -2,6 +2,7 @@
#include <stddef.h>
#include <stdbool.h>
#include <limine.h>
+#include <protos/stivale.h>
#include <protos/stivale2.h>
#include <lib/elf.h>
#include <lib/blib.h>
@@ -14,7 +15,7 @@
#include <lib/real.h>
#include <lib/libc.h>
#include <drivers/vbe.h>
-#include <drivers/vga_textmode.h>
+#include <lib/term.h>
#include <drivers/pic.h>
#include <fs/file.h>
#include <lib/asm.h>
@@ -364,9 +365,9 @@ void stivale2_load(char *cmdline, int boot_drive) {
{
struct stivale2_hdr_tag_framebuffer *hdrtag = get_tag(&stivale2_hdr, STIVALE2_HDR_TAG_FRAMEBUFFER_ID);
- if (hdrtag == NULL) {
- deinit_vga_textmode();
- } else {
+ term_deinit();
+
+ if (hdrtag != NULL) {
struct stivale2_struct_tag_framebuffer *tag = balloc(sizeof(struct stivale2_struct_tag_framebuffer));
tag->tag.identifier = STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID;
@@ -407,169 +408,6 @@ void stivale2_load(char *cmdline, int boot_drive) {
// Check if 5-level paging tag is requesting support
bool level5pg_requested = get_tag(&stivale2_hdr, STIVALE2_HDR_TAG_5LV_PAGING_ID) ? true : false;
- if (bits == 64) {
- // If we're going 64, we might as well call this BIOS interrupt
- // to tell the BIOS that we are entering Long Mode, since it is in
- // the specification.
- struct rm_regs r = {0};
- r.eax = 0xec00;
- r.ebx = 0x02; // Long mode only
- rm_int(0x15, &r, &r);
- }
-
- pic_mask_all();
- pic_flush();
-
- if (bits == 64) {
- void *pagemap_ptr;
- if (level5pg && level5pg_requested) {
- // Enable CR4.LA57
- ASM(
- "mov eax, cr4\n\t"
- "bts eax, 12\n\t"
- "mov cr4, eax\n\t", :: "eax", "memory"
- );
-
- struct pagemap {
- uint64_t pml5[512];
- uint64_t pml4_lo[512];
- uint64_t pml4_hi[512];
- uint64_t pml3_lo[512];
- uint64_t pml3_hi[512];
- uint64_t pml2_0gb[512];
- uint64_t pml2_1gb[512];
- uint64_t pml2_2gb[512];
- uint64_t pml2_3gb[512];
- };
- struct pagemap *pagemap = balloc_aligned(sizeof(struct pagemap), 0x1000);
- pagemap_ptr = (void *)pagemap;
-
- // zero out the pagemap
- for (uint64_t *p = (uint64_t *)pagemap; p < &pagemap->pml3_hi[512]; p++)
- *p = 0;
-
- pagemap->pml5[511] = (uint64_t)(size_t)pagemap->pml4_hi | 0x03;
- pagemap->pml5[0] = (uint64_t)(size_t)pagemap->pml4_lo | 0x03;
- pagemap->pml4_hi[511] = (uint64_t)(size_t)pagemap->pml3_hi | 0x03;
- pagemap->pml4_hi[256] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
- pagemap->pml4_lo[0] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
- pagemap->pml3_hi[510] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
- pagemap->pml3_hi[511] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
- pagemap->pml3_lo[0] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
- pagemap->pml3_lo[1] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
- pagemap->pml3_lo[2] = (uint64_t)(size_t)pagemap->pml2_2gb | 0x03;
- pagemap->pml3_lo[3] = (uint64_t)(size_t)pagemap->pml2_3gb | 0x03;
-
- // populate the page directories
- for (size_t i = 0; i < 512 * 4; i++)
- (&pagemap->pml2_0gb[0])[i] = (i * 0x200000) | 0x03 | (1 << 7);
- } else {
- struct pagemap {
- uint64_t pml4[512];
- uint64_t pml3_lo[512];
- uint64_t pml3_hi[512];
- uint64_t pml2_0gb[512];
- uint64_t pml2_1gb[512];
- uint64_t pml2_2gb[512];
- uint64_t pml2_3gb[512];
- };
- struct pagemap *pagemap = balloc_aligned(sizeof(struct pagemap), 0x1000);
- pagemap_ptr = (void *)pagemap;
-
- // zero out the pagemap
- for (uint64_t *p = (uint64_t *)pagemap; p < &pagemap->pml3_hi[512]; p++)
- *p = 0;
-
- pagemap->pml4[511] = (uint64_t)(size_t)pagemap->pml3_hi | 0x03;
- pagemap->pml4[256] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
- pagemap->pml4[0] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
- pagemap->pml3_hi[510] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
- pagemap->pml3_hi[511] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
- pagemap->pml3_lo[0] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
- pagemap->pml3_lo[1] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
- pagemap->pml3_lo[2] = (uint64_t)(size_t)pagemap->pml2_2gb | 0x03;
- pagemap->pml3_lo[3] = (uint64_t)(size_t)pagemap->pml2_3gb | 0x03;
-
- // populate the page directories
- for (size_t i = 0; i < 512 * 4; i++)
- (&pagemap->pml2_0gb[0])[i] = (i * 0x200000) | 0x03 | (1 << 7);
- }
-
- ASM(
- "cli\n\t"
- "cld\n\t"
- "mov cr3, eax\n\t"
- "mov eax, cr4\n\t"
- "or eax, 1 << 5\n\t"
- "mov cr4, eax\n\t"
- "mov ecx, 0xc0000080\n\t"
- "rdmsr\n\t"
- "or eax, 1 << 8\n\t"
- "wrmsr\n\t"
- "mov eax, cr0\n\t"
- "or eax, 1 << 31\n\t"
- "mov cr0, eax\n\t"
- FARJMP32("0x28", "1f")
- "1: .code64\n\t"
- "mov ax, 0x30\n\t"
- "mov ds, ax\n\t"
- "mov es, ax\n\t"
- "mov fs, ax\n\t"
- "mov gs, ax\n\t"
- "mov ss, ax\n\t"
-
- "push 0x30\n\t"
- "push [rsi]\n\t"
- "pushfq\n\t"
- "push 0x28\n\t"
- "push [rbx]\n\t"
-
- "xor rax, rax\n\t"
- "xor rbx, rbx\n\t"
- "xor rcx, rcx\n\t"
- "xor rdx, rdx\n\t"
- "xor rsi, rsi\n\t"
- "xor rbp, rbp\n\t"
- "xor r8, r8\n\t"
- "xor r9, r9\n\t"
- "xor r10, r10\n\t"
- "xor r11, r11\n\t"
- "xor r12, r12\n\t"
- "xor r13, r13\n\t"
- "xor r14, r14\n\t"
- "xor r15, r15\n\t"
-
- "iretq\n\t"
- ".code32\n\t",
- : "a" (pagemap_ptr), "b" (&entry_point),
- "D" (&stivale2_struct), "S" (&stivale2_hdr.stack)
- : "memory"
- );
- } else if (bits == 32) {
- ASM(
- "cli\n\t"
- "cld\n\t"
-
- "sub esp, 4\n\t"
- "mov [esp], edi\n\t"
-
- "push 0x20\n\t"
- "push [esi]\n\t"
- "pushfd\n\t"
- "push 0x18\n\t"
- "push [ebx]\n\t"
-
- "xor eax, eax\n\t"
- "xor ebx, ebx\n\t"
- "xor ecx, ecx\n\t"
- "xor edx, edx\n\t"
- "xor esi, esi\n\t"
- "xor edi, edi\n\t"
- "xor ebp, ebp\n\t"
-
- "iret\n\t",
- : "b" (&entry_point), "D" (&stivale2_struct), "S" (&stivale2_hdr.stack)
- : "memory"
- );
- }
+ stivale_spinup(bits, level5pg && level5pg_requested,
+ entry_point, &stivale2_struct, stivale2_hdr.stack);
}
diff --git a/test/limine.cfg b/test/limine.cfg
index 2492b4d2..8f70a2f0 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -1,4 +1,5 @@
TIMEOUT=3
+GRAPHICS=on
:MyOS
