Wire up logic for graphical terminal
This commit is contained in:
parent
3eb7d5f0ba
commit
902109ef68
BIN
limine.bin
BIN
limine.bin
Binary file not shown.
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
209
src/lib/term.c
Normal 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
21
src/lib/term.h
Normal 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
|
30
src/main.c
30
src/main.c
@ -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");
|
||||||
|
14
src/menu.c
14
src/menu.c
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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"
|
||||||
|
@ -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 (;;);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
TIMEOUT=3
|
TIMEOUT=3
|
||||||
|
GRAPHICS=on
|
||||||
|
|
||||||
:MyOS
|
:MyOS
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user