Wire up logic for graphical terminal

This commit is contained in:
mintsuki 2020-09-02 09:55:56 +02:00
parent 3eb7d5f0ba
commit 902109ef68
17 changed files with 422 additions and 417 deletions

Binary file not shown.

View File

@ -19,7 +19,7 @@ static void vga_font_retrieve(void) {
struct rm_regs r = {0}; struct rm_regs r = {0};
r.eax = 0x1130; r.eax = 0x1130;
r.ebx = 0x06; r.ebx = 0x0600;
rm_int(0x10, &r, &r); rm_int(0x10, &r, &r);
vga_font = ext_mem_balloc(VGA_FONT_MAX); 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; 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) { void vbe_plot_char(struct vbe_char c, int x, int y) {
int orig_x = x; int orig_x = x;
uint8_t *glyph = &vga_font[c.c * VGA_FONT_HEIGHT]; 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); vbe_plot_char(c, cursor_x * VGA_FONT_WIDTH, cursor_y * VGA_FONT_HEIGHT);
} }
void vbe_scroll(void) { static void scroll(void) {
clear_cursor(); clear_cursor();
for (int i = cols; i < rows * cols; i++) { for (int i = cols; i < rows * cols; i++) {
@ -105,7 +111,7 @@ void vbe_scroll(void) {
draw_cursor(); draw_cursor();
} }
void vbe_clear(void) { void vbe_clear(bool move) {
clear_cursor(); clear_cursor();
struct vbe_char empty; struct vbe_char empty;
@ -116,8 +122,10 @@ void vbe_clear(void) {
plot_char_grid(empty, i % cols, i / cols); plot_char_grid(empty, i % cols, i / cols);
} }
cursor_x = 0; if (move) {
cursor_y = 0; cursor_x = 0;
cursor_y = 0;
}
draw_cursor(); draw_cursor();
} }
@ -144,25 +152,78 @@ void vbe_get_cursor_pos(int *x, int *y) {
*y = cursor_y; *y = cursor_y;
} }
void vbe_set_text_attributes(uint32_t fg, uint32_t bg) { static uint32_t ansi_colours[] = {
text_fg = fg; 0x00000000, // black
text_bg = bg; 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) { void vbe_set_text_bg(int bg) {
clear_cursor(); text_bg = ansi_colours[bg];
cursor_fg = fg;
cursor_bg = bg;
draw_cursor();
} }
void vbe_tty_init(void) { 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(int *_rows, int *_cols) {
init_vbe(&vbe_framebuffer, &vbe_pitch, &vbe_width, &vbe_height, &vbe_bpp); init_vbe(&vbe_framebuffer, &vbe_pitch, &vbe_width, &vbe_height, &vbe_bpp);
vga_font_retrieve(); vga_font_retrieve();
cols = vbe_width / VGA_FONT_WIDTH; *_cols = cols = vbe_width / VGA_FONT_WIDTH;
rows = vbe_height / VGA_FONT_HEIGHT; *_rows = rows = vbe_height / VGA_FONT_HEIGHT;
grid = ext_mem_balloc(rows * cols * sizeof(struct vbe_char)); grid = ext_mem_balloc(rows * cols * sizeof(struct vbe_char));
vbe_clear(); vbe_clear(true);
} }
struct vbe_info_struct { struct vbe_info_struct {

View File

@ -2,13 +2,19 @@
#define __DRIVERS__VBE_H__ #define __DRIVERS__VBE_H__
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
struct vbe_char {
char c;
uint32_t fg;
uint32_t bg;
};
int init_vbe(uint32_t **framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp); 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 #endif

View File

@ -9,23 +9,11 @@
#define VD_COLS (80 * 2) #define VD_COLS (80 * 2)
#define VD_ROWS 25 #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 char *video_mem = (char *)0xb8000;
static size_t cursor_offset = 0; static size_t cursor_offset = 0;
static int cursor_status = 1; static int cursor_status = 1;
static uint8_t text_palette = 0x07; static uint8_t text_palette = 0x07;
static uint8_t cursor_palette = 0x70; 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) { static void clear_cursor(void) {
video_mem[cursor_offset + 1] = text_palette; video_mem[cursor_offset + 1] = text_palette;
@ -51,23 +39,14 @@ static void scroll(void) {
return; return;
} }
void text_clear(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;
}
cursor_offset = 0;
draw_cursor();
return;
}
static void text_clear_no_move(void) {
clear_cursor(); clear_cursor();
for (size_t i = 0; i < VIDEO_BOTTOM; i += 2) { for (size_t i = 0; i < VIDEO_BOTTOM; i += 2) {
video_mem[i] = ' '; video_mem[i] = ' ';
video_mem[i + 1] = text_palette; video_mem[i + 1] = text_palette;
} }
if (move)
cursor_offset = 0;
draw_cursor(); draw_cursor();
return; return;
} }
@ -86,20 +65,13 @@ void text_disable_cursor(void) {
// VGA cursor code taken from: https://wiki.osdev.org/Text_Mode_Cursor // 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(0x3d4, 0x0a);
port_out_b(0x3d5, 0x20); port_out_b(0x3d5, 0x20);
text_clear(); text_clear(true);
vga_textmode_initialised = true; *_rows = VD_ROWS;
} *_cols = VD_COLS / 2;
void deinit_vga_textmode(void) {
struct rm_regs r = {0};
r.eax = 0x0003;
rm_int(0x10, &r, &r);
vga_textmode_initialised = false;
} }
static void text_set_cursor_palette(uint8_t c) { static void text_set_cursor_palette(uint8_t c) {
@ -140,24 +112,28 @@ void text_set_cursor_pos(int x, int y) {
draw_cursor(); draw_cursor();
} }
void text_write(const char *buf, size_t count) { static uint8_t ansi_colours[] = { 0, 4, 2, 0x0e, 1, 5, 3, 7 };
if (!vga_textmode_initialised)
return; void text_set_text_fg(int fg) {
for (size_t i = 0; i < count; i++) text_palette = (text_palette & 0xf0) | ansi_colours[fg];
text_putchar(buf[i]);
} }
static void text_putchar(char c) { void text_set_text_bg(int bg) {
if (escape) { text_palette = (text_palette & 0x0f) | (ansi_colours[bg] << 4);
escape_parse(c); }
return;
} void text_putchar(char c) {
switch (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; break;
case 0x1B:
escape = 1;
return;
case '\n': case '\n':
if (text_get_cursor_pos_y() == (VD_ROWS - 1)) { if (text_get_cursor_pos_y() == (VD_ROWS - 1)) {
clear_cursor(); clear_cursor();
@ -167,16 +143,6 @@ static void text_putchar(char c) {
text_set_cursor_pos(0, (text_get_cursor_pos_y() + 1)); text_set_cursor_pos(0, (text_get_cursor_pos_y() + 1));
} }
break; 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: default:
clear_cursor(); clear_cursor();
video_mem[cursor_offset] = c; video_mem[cursor_offset] = c;
@ -187,116 +153,4 @@ static void text_putchar(char c) {
cursor_offset += 2; cursor_offset += 2;
draw_cursor(); 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;
} }

View File

@ -1,18 +1,17 @@
#ifndef __DRIVERS__VGA_TEXTMODE_H__ #ifndef __DRIVERS__VGA_TEXTMODE_H__
#define __DRIVERS__VGA_TEXTMODE_H__ #define __DRIVERS__VGA_TEXTMODE_H__
#include <stddef.h> #include <stdbool.h>
void init_vga_textmode(void); void init_vga_textmode(int *rows, int *cols);
void deinit_vga_textmode(void);
void text_write(const char *, size_t); void text_putchar(char c);
void text_clear(bool move);
void text_get_cursor_pos(int *x, int *y);
void text_set_cursor_pos(int x, int y);
void text_clear(void);
void text_enable_cursor(void); void text_enable_cursor(void);
void text_disable_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 #endif

View File

@ -4,7 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <lib/blib.h> #include <lib/blib.h>
#include <lib/libc.h> #include <lib/libc.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
#include <lib/real.h> #include <lib/real.h>
#include <lib/cio.h> #include <lib/cio.h>
#include <lib/e820.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) { static void gets_reprint_string(int x, int y, const char *s, size_t limit) {
int last_x, last_y; int last_x, last_y;
text_get_cursor_pos(&last_x, &last_y); get_cursor_pos(&last_x, &last_y);
text_set_cursor_pos(x, y); set_cursor_pos(x, y);
for (size_t i = 0; i < limit; i++) { for (size_t i = 0; i < limit; i++) {
text_write(" ", 1); term_write(" ", 1);
} }
text_set_cursor_pos(x, y); set_cursor_pos(x, y);
text_write(s, strlen(s)); term_write(s, strlen(s));
text_set_cursor_pos(last_x, last_y); set_cursor_pos(last_x, last_y);
} }
void gets(const char *orig_str, char *buf, size_t limit) { 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; buf[orig_str_len] = 0;
int orig_x, orig_y; int orig_x, orig_y;
text_get_cursor_pos(&orig_x, &orig_y); get_cursor_pos(&orig_x, &orig_y);
print("%s", buf); print("%s", buf);
@ -240,13 +240,13 @@ void gets(const char *orig_str, char *buf, size_t limit) {
case GETCHAR_CURSOR_LEFT: case GETCHAR_CURSOR_LEFT:
if (i) { if (i) {
i--; i--;
text_write("\b", 1); term_write("\b", 1);
} }
continue; continue;
case GETCHAR_CURSOR_RIGHT: case GETCHAR_CURSOR_RIGHT:
if (i < strlen(buf)) { if (i < strlen(buf)) {
i++; i++;
text_write(" ", 1); term_write(" ", 1);
gets_reprint_string(orig_x, orig_y, buf, limit); gets_reprint_string(orig_x, orig_y, buf, limit);
} }
continue; continue;
@ -258,12 +258,12 @@ void gets(const char *orig_str, char *buf, size_t limit) {
if (!buf[j]) if (!buf[j])
break; break;
} }
text_write("\b", 1); term_write("\b", 1);
gets_reprint_string(orig_x, orig_y, buf, limit); gets_reprint_string(orig_x, orig_y, buf, limit);
} }
continue; continue;
case '\r': case '\r':
text_write("\n", 1); term_write("\n", 1);
return; return;
default: default:
if (strlen(buf) < limit-1) { if (strlen(buf) < limit-1) {
@ -273,7 +273,7 @@ void gets(const char *orig_str, char *buf, size_t limit) {
break; break;
} }
buf[i++] = c; buf[i++] = c;
text_write(" ", 1); term_write(" ", 1);
gets_reprint_string(orig_x, orig_y, buf, limit); gets_reprint_string(orig_x, orig_y, buf, limit);
} }
} }

View File

@ -4,7 +4,7 @@
#include <lib/print.h> #include <lib/print.h>
#include <lib/blib.h> #include <lib/blib.h>
#include <lib/cio.h> #include <lib/cio.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
static const char *base_digits = "0123456789abcdef"; static const char *base_digits = "0123456789abcdef";
@ -167,7 +167,7 @@ void vprint(const char *fmt, va_list args) {
} }
out: out:
text_write(print_buf, print_buf_i); term_write(print_buf, print_buf_i);
#ifdef E9_OUTPUT #ifdef E9_OUTPUT
for (size_t i = 0; i < print_buf_i; i++) for (size_t i = 0; i < print_buf_i; i++)

209
src/lib/term.c Normal file
View File

@ -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;
}

21
src/lib/term.h Normal file
View File

@ -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

View File

@ -14,7 +14,7 @@ ASM_BASIC(
); );
#include <limine.h> #include <limine.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
#include <lib/real.h> #include <lib/real.h>
#include <lib/blib.h> #include <lib/blib.h>
#include <lib/libc.h> #include <lib/libc.h>
@ -32,8 +32,7 @@ ASM_BASIC(
#include <menu.h> #include <menu.h>
void main(int boot_drive) { void main(int boot_drive) {
// Initial prompt. term_textmode();
init_vga_textmode();
print("Limine " LIMINE_VERSION "\n\n"); print("Limine " LIMINE_VERSION "\n\n");
@ -59,25 +58,32 @@ void main(int boot_drive) {
} }
} }
char *cmdline = menu();
init_e820(); init_e820();
init_memmap(); init_memmap();
char proto[32]; char buf[32];
if (!config_get_value(proto, 0, 32, "KERNEL_PROTO")) {
if (!config_get_value(proto, 0, 32, "PROTOCOL")) { 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"); panic("PROTOCOL not specified");
} }
} }
if (!strcmp(proto, "stivale")) { if (!strcmp(buf, "stivale")) {
stivale_load(cmdline, boot_drive); stivale_load(cmdline, boot_drive);
} else if (!strcmp(proto, "stivale2")) { } else if (!strcmp(buf, "stivale2")) {
stivale2_load(cmdline, boot_drive); stivale2_load(cmdline, boot_drive);
} else if (!strcmp(proto, "linux")) { } else if (!strcmp(buf, "linux")) {
linux_load(cmdline, boot_drive); linux_load(cmdline, boot_drive);
} else if (!strcmp(proto, "chainload")) { } else if (!strcmp(buf, "chainload")) {
chainload(); chainload();
} else { } else {
panic("Invalid protocol specified"); panic("Invalid protocol specified");

View File

@ -7,7 +7,7 @@
#include <lib/blib.h> #include <lib/blib.h>
#include <lib/libc.h> #include <lib/libc.h>
#include <lib/config.h> #include <lib/config.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
static char *cmdline; static char *cmdline;
#define CMDLINE_MAX 1024 #define CMDLINE_MAX 1024
@ -26,12 +26,12 @@ char *menu(void) {
} }
} }
text_disable_cursor(); disable_cursor();
int selected_entry = 0; int selected_entry = 0;
bool skip_timeout = false; bool skip_timeout = false;
refresh: refresh:
text_clear(); clear(true);
print("\n\n \e[36m Limine " LIMINE_VERSION " \e[37m\n\n\n"); print("\n\n \e[36m Limine " LIMINE_VERSION " \e[37m\n\n\n");
print("Select an entry:\n\n"); print("Select an entry:\n\n");
@ -78,17 +78,17 @@ refresh:
case '\r': case '\r':
autoboot: autoboot:
config_set_entry(selected_entry); 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, "KERNEL_CMDLINE")) {
if (!config_get_value(cmdline, 0, CMDLINE_MAX, "CMDLINE")) { if (!config_get_value(cmdline, 0, CMDLINE_MAX, "CMDLINE")) {
cmdline[0] = '\0'; cmdline[0] = '\0';
} }
} }
text_clear(); clear(true);
return cmdline; return cmdline;
case 'e': case 'e':
config_set_entry(selected_entry); 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, "KERNEL_CMDLINE")) {
if (!config_get_value(cmdline, 0, CMDLINE_MAX, "CMDLINE")) { if (!config_get_value(cmdline, 0, CMDLINE_MAX, "CMDLINE")) {
cmdline[0] = '\0'; cmdline[0] = '\0';
@ -96,7 +96,7 @@ refresh:
} }
print("\n\n> "); print("\n\n> ");
gets(cmdline, cmdline, CMDLINE_MAX); gets(cmdline, cmdline, CMDLINE_MAX);
text_clear(); clear(true);
return cmdline; return cmdline;
} }
} }

View File

@ -5,7 +5,7 @@
#include <lib/config.h> #include <lib/config.h>
#include <lib/blib.h> #include <lib/blib.h>
#include <drivers/disk.h> #include <drivers/disk.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
#include <lib/asm.h> #include <lib/asm.h>
void chainload(void) { void chainload(void) {
@ -25,7 +25,7 @@ void chainload(void) {
drive = (int)strtoui(buf); drive = (int)strtoui(buf);
} }
deinit_vga_textmode(); term_deinit();
if (part != -1) { if (part != -1) {
struct part p; struct part p;

View File

@ -4,7 +4,7 @@
#include <fs/file.h> #include <fs/file.h>
#include <lib/blib.h> #include <lib/blib.h>
#include <lib/real.h> #include <lib/real.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
#include <lib/config.h> #include <lib/config.h>
#include <lib/print.h> #include <lib/print.h>
#include <lib/memmap.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 real_mode_code_seg = rm_seg(real_mode_code);
uint16_t kernel_entry_seg = real_mode_code_seg + 0x20; uint16_t kernel_entry_seg = real_mode_code_seg + 0x20;
deinit_vga_textmode(); term_deinit();
ASM( ASM(
"cli\n\t" "cli\n\t"

View File

@ -12,7 +12,7 @@
#include <lib/rand.h> #include <lib/rand.h>
#include <lib/real.h> #include <lib/real.h>
#include <drivers/vbe.h> #include <drivers/vbe.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
#include <drivers/pic.h> #include <drivers/pic.h>
#include <fs/file.h> #include <fs/file.h>
#include <lib/asm.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_height = stivale_hdr.framebuffer_height;
stivale_struct.framebuffer_bpp = stivale_hdr.framebuffer_bpp; stivale_struct.framebuffer_bpp = stivale_hdr.framebuffer_bpp;
term_deinit();
if (stivale_hdr.flags & (1 << 0)) { if (stivale_hdr.flags & (1 << 0)) {
uint32_t *fb32; uint32_t *fb32;
init_vbe(&fb32, init_vbe(&fb32,
@ -232,8 +234,6 @@ void stivale_load(char *cmdline, int boot_drive) {
&stivale_struct.framebuffer_height, &stivale_struct.framebuffer_height,
&stivale_struct.framebuffer_bpp); &stivale_struct.framebuffer_bpp);
stivale_struct.framebuffer_addr = (uint64_t)(size_t)fb32; stivale_struct.framebuffer_addr = (uint64_t)(size_t)fb32;
} else {
deinit_vga_textmode();
} }
size_t memmap_entries; 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_entries = (uint64_t)memmap_entries;
stivale_struct.memory_map_addr = (uint64_t)(size_t)memmap; 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 (bits == 64) {
// If we're going 64, we might as well call this BIOS interrupt // 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 // 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) { if (bits == 64) {
void *pagemap_ptr; void *pagemap_ptr;
if (level5pg && (stivale_hdr.flags & (1 << 1))) { if (level5pg) {
// Enable CR4.LA57 // Enable CR4.LA57
ASM( ASM(
"mov eax, cr4\n\t" "mov eax, cr4\n\t"
@ -376,7 +382,7 @@ void stivale_load(char *cmdline, int boot_drive) {
"iretq\n\t" "iretq\n\t"
".code32\n\t", ".code32\n\t",
: "a" (pagemap_ptr), "b" (&entry_point), : "a" (pagemap_ptr), "b" (&entry_point),
"D" (&stivale_struct), "S" (&stivale_hdr.stack) "D" (stivale_struct), "S" (&stack)
: "memory" : "memory"
); );
} else if (bits == 32) { } else if (bits == 32) {
@ -402,8 +408,9 @@ void stivale_load(char *cmdline, int boot_drive) {
"xor ebp, ebp\n\t" "xor ebp, ebp\n\t"
"iret\n\t", "iret\n\t",
: "b" (&entry_point), "D" (&stivale_struct), "S" (&stivale_hdr.stack) : "b" (&entry_point), "D" (stivale_struct), "S" (&stack)
: "memory" : "memory"
); );
} }
for (;;);
} }

View File

@ -1,8 +1,11 @@
#ifndef __PROTOS__STIVALE_H__ #ifndef __PROTOS__STIVALE_H__
#define __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); 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 #endif

View File

@ -2,6 +2,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <limine.h> #include <limine.h>
#include <protos/stivale.h>
#include <protos/stivale2.h> #include <protos/stivale2.h>
#include <lib/elf.h> #include <lib/elf.h>
#include <lib/blib.h> #include <lib/blib.h>
@ -14,7 +15,7 @@
#include <lib/real.h> #include <lib/real.h>
#include <lib/libc.h> #include <lib/libc.h>
#include <drivers/vbe.h> #include <drivers/vbe.h>
#include <drivers/vga_textmode.h> #include <lib/term.h>
#include <drivers/pic.h> #include <drivers/pic.h>
#include <fs/file.h> #include <fs/file.h>
#include <lib/asm.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); struct stivale2_hdr_tag_framebuffer *hdrtag = get_tag(&stivale2_hdr, STIVALE2_HDR_TAG_FRAMEBUFFER_ID);
if (hdrtag == NULL) { term_deinit();
deinit_vga_textmode();
} else { if (hdrtag != NULL) {
struct stivale2_struct_tag_framebuffer *tag = balloc(sizeof(struct stivale2_struct_tag_framebuffer)); struct stivale2_struct_tag_framebuffer *tag = balloc(sizeof(struct stivale2_struct_tag_framebuffer));
tag->tag.identifier = STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID; 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 // Check if 5-level paging tag is requesting support
bool level5pg_requested = get_tag(&stivale2_hdr, STIVALE2_HDR_TAG_5LV_PAGING_ID) ? true : false; bool level5pg_requested = get_tag(&stivale2_hdr, STIVALE2_HDR_TAG_5LV_PAGING_ID) ? true : false;
if (bits == 64) { stivale_spinup(bits, level5pg && level5pg_requested,
// If we're going 64, we might as well call this BIOS interrupt entry_point, &stivale2_struct, stivale2_hdr.stack);
// 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"
);
}
} }

View File

@ -1,4 +1,5 @@
TIMEOUT=3 TIMEOUT=3
GRAPHICS=on
:MyOS :MyOS