From ed285c9fc665e262ed21c7bf5734acb2b7a532db Mon Sep 17 00:00:00 2001 From: hachem Date: Fri, 25 Sep 2026 11:31:59 +0200 Subject: feat: load + run native ELF binaries --- kernel/console.rv | 64 +++++++++++++++ kernel/font.rv | 102 +++++++++++++++++++++++ kernel/input.rv | 47 +++++++++++ kernel/main.rv | 236 +----------------------------------------------------- kernel/proc.rv | 40 +++++++++ kernel/shell.rv | 55 +++++++++++++ kernel/vmm.rv | 24 ++++++ 7 files changed, 333 insertions(+), 235 deletions(-) create mode 100644 kernel/console.rv create mode 100644 kernel/font.rv create mode 100644 kernel/input.rv create mode 100644 kernel/proc.rv create mode 100644 kernel/shell.rv create mode 100644 kernel/vmm.rv (limited to 'kernel') diff --git a/kernel/console.rv b/kernel/console.rv new file mode 100644 index 0000000..a448ef9 --- /dev/null +++ b/kernel/console.rv @@ -0,0 +1,64 @@ +const FW = 8 # glyph width in pixels +const FH = 16 # glyph height in pixels (8x16 VGA bitmap font) +const FG = 0xd0d0d0 +const CON_BG = 0x101018 + +global con = { col = 0, row = 0, scale = 1 } + +# cell size in pixels at the current zoom. named cell_* (not cw/ch) so they don't +# collide with draw_glyph's `ch` character parameter. +fn cell_w() FW * con.scale +fn cell_h() FH * con.scale +fn con_cols() fb_width() / cell_w() +fn con_rows() fb_height() / cell_h() + +fn draw_glyph(col, row, ch) do + const x0 = col * cell_w() + const y0 = row * cell_h() + fill_rect(x0, y0, cell_w(), cell_h(), CON_BG) # clear the cell + const code = ch:ascii() + if code < 32 return :nil + if code > 127 return :nil + const g = FONT[code - 32] + for fy in 0..FH do + const bits = g[fy] + for fx in 0..FW do + if (bits shr fx) band 1 == 1 fill_rect(x0 + fx * con.scale, y0 + fy * con.scale, con.scale, con.scale, FG) + end + end +end + +fn con_newline() do + con.col = 0 + con.row = con.row + 1 + if con.row >= con_rows() do + fb_scroll(cell_h(), CON_BG) + con.row = con_rows() - 1 + end +end + +# we dont do Shift/Cntrl +# thats a job for future me lmao +fn con_putc(ch) do + const code = ch:ascii() + if code == 10 do con_newline() return :nil end # \n + if code == 13 do con.col = 0 return :nil end # \r + if code == 8 do # backspace: move left + if con.col > 0 con.col = con.col - 1 + return :nil + end + if code < 32 return :nil + draw_glyph(con.col, con.row, ch) + con.col = con.col + 1 + if con.col >= con_cols() con_newline() +end + +fn puts(s) serial_puts(s) + +global flush_console = fn() do + let c = serial_next() + while c >= 0 do + con_putc(string.of_ascii(c)) + c = serial_next() + end +end diff --git a/kernel/font.rv b/kernel/font.rv new file mode 100644 index 0000000..7bd7c6a --- /dev/null +++ b/kernel/font.rv @@ -0,0 +1,102 @@ +# IBM VGA 8x16 font (from Linux lib/fonts/font_8x16.c) +# ASCII 0x20..0x7f, indexed by (code - 32). +# one byte per row, 16 rows. +# bit 0 (LSB) of a byte is the leftmost pixel (VGA data is MSB-first, reversed here). +global FONT = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # space + { 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }, # ! + { 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # " + { 0x00, 0x00, 0x00, 0x36, 0x36, 0x7F, 0x36, 0x36, 0x36, 0x7F, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00 }, # # + { 0x18, 0x18, 0x3E, 0x63, 0x43, 0x03, 0x3E, 0x60, 0x60, 0x61, 0x63, 0x3E, 0x18, 0x18, 0x00, 0x00 }, # $ + { 0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x30, 0x18, 0x0C, 0x06, 0x63, 0x61, 0x00, 0x00, 0x00, 0x00 }, # % + { 0x00, 0x00, 0x1C, 0x36, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x33, 0x33, 0x6E, 0x00, 0x00, 0x00, 0x00 }, # & + { 0x00, 0x0C, 0x0C, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # ' + { 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00 }, # ( + { 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00 }, # ) + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # * + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x00 }, # , + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # - + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }, # . + { 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00 }, # / + { 0x00, 0x00, 0x1C, 0x36, 0x63, 0x63, 0x6B, 0x6B, 0x63, 0x63, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00 }, # 0 + { 0x00, 0x00, 0x18, 0x1C, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00 }, # 1 + { 0x00, 0x00, 0x3E, 0x63, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x63, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # 2 + { 0x00, 0x00, 0x3E, 0x63, 0x60, 0x60, 0x3C, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # 3 + { 0x00, 0x00, 0x30, 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00 }, # 4 + { 0x00, 0x00, 0x7F, 0x03, 0x03, 0x03, 0x3F, 0x60, 0x60, 0x60, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # 5 + { 0x00, 0x00, 0x1C, 0x06, 0x03, 0x03, 0x3F, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # 6 + { 0x00, 0x00, 0x7F, 0x63, 0x60, 0x60, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00 }, # 7 + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # 8 + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x60, 0x60, 0x30, 0x1E, 0x00, 0x00, 0x00, 0x00 }, # 9 + { 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }, # : + { 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00 }, # ; + { 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00 }, # < + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # = + { 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00 }, # > + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x30, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }, # ? + { 0x00, 0x00, 0x00, 0x3E, 0x63, 0x63, 0x7B, 0x7B, 0x7B, 0x3B, 0x03, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # @ + { 0x00, 0x00, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # A + { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3F, 0x00, 0x00, 0x00, 0x00 }, # B + { 0x00, 0x00, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # C + { 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00, 0x00, 0x00, 0x00 }, # D + { 0x00, 0x00, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x46, 0x66, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # E + { 0x00, 0x00, 0x7F, 0x66, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00 }, # F + { 0x00, 0x00, 0x3C, 0x66, 0x43, 0x03, 0x03, 0x7B, 0x63, 0x63, 0x66, 0x5C, 0x00, 0x00, 0x00, 0x00 }, # G + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # H + { 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # I + { 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1E, 0x00, 0x00, 0x00, 0x00 }, # J + { 0x00, 0x00, 0x67, 0x66, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # K + { 0x00, 0x00, 0x0F, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # L + { 0x00, 0x00, 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # M + { 0x00, 0x00, 0x63, 0x67, 0x6F, 0x7F, 0x7B, 0x73, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # N + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # O + { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00 }, # P + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x7B, 0x3E, 0x30, 0x70, 0x00, 0x00 }, # Q + { 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # R + { 0x00, 0x00, 0x3E, 0x63, 0x63, 0x06, 0x1C, 0x30, 0x60, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # S + { 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # T + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # U + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x08, 0x00, 0x00, 0x00, 0x00 }, # V + { 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x77, 0x36, 0x00, 0x00, 0x00, 0x00 }, # W + { 0x00, 0x00, 0x63, 0x63, 0x36, 0x3E, 0x1C, 0x1C, 0x3E, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }, # X + { 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # Y + { 0x00, 0x00, 0x7F, 0x63, 0x61, 0x30, 0x18, 0x0C, 0x06, 0x43, 0x63, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # Z + { 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # [ + { 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00 }, # \ + { 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # ] + { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # ^ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00 }, # _ + { 0x00, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # ` + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0x00, 0x00, 0x00, 0x00 }, # a + { 0x00, 0x00, 0x07, 0x06, 0x06, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # b + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x63, 0x03, 0x03, 0x03, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # c + { 0x00, 0x00, 0x38, 0x30, 0x30, 0x3C, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00, 0x00, 0x00, 0x00 }, # d + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x63, 0x7F, 0x03, 0x03, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # e + { 0x00, 0x00, 0x38, 0x6C, 0x4C, 0x0C, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00 }, # f + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x33, 0x1E, 0x00 }, # g + { 0x00, 0x00, 0x07, 0x06, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # h + { 0x00, 0x00, 0x18, 0x18, 0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # i + { 0x00, 0x00, 0x60, 0x60, 0x00, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3C, 0x00 }, # j + { 0x00, 0x00, 0x07, 0x06, 0x06, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }, # k + { 0x00, 0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 }, # l + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7F, 0x6B, 0x6B, 0x6B, 0x6B, 0x63, 0x00, 0x00, 0x00, 0x00 }, # m + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, # n + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # o + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00 }, # p + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x78, 0x00 }, # q + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x06, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00 }, # r + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x63, 0x06, 0x1C, 0x30, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00 }, # s + { 0x00, 0x00, 0x08, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00 }, # t + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00, 0x00, 0x00, 0x00 }, # u + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00 }, # v + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x6B, 0x6B, 0x6B, 0x7F, 0x36, 0x00, 0x00, 0x00, 0x00 }, # w + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x36, 0x1C, 0x1C, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00 }, # x + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7E, 0x60, 0x30, 0x1F, 0x00 }, # y + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x33, 0x18, 0x0C, 0x06, 0x63, 0x7F, 0x00, 0x00, 0x00, 0x00 }, # z + { 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00 }, # { + { 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }, # | + { 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00 }, # } + { 0x00, 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, # ~ + { 0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x36, 0x63, 0x63, 0x63, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 }, #  +} diff --git a/kernel/input.rv b/kernel/input.rv new file mode 100644 index 0000000..33cf65d --- /dev/null +++ b/kernel/input.rv @@ -0,0 +1,47 @@ +# keyboard scancode table +# ts is NOT a good way to write a driver LMAO +const KBD = " 1234567890-= qwertyuiop[] asdfghjkl;'` \\zxcvbnm,./ " +# same layout, shifted. index 42 (left shift) / 54 (right shift) stay blank. +const KBD_SHIFT = " !@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"~ |ZXCVBNM<>? " + +# 8259 PIC +fn pic_remap() do + outb(0x20, 0x11) outb(0xa0, 0x11) + outb(0x21, 0x20) outb(0xa1, 0x28) + outb(0x21, 0x04) outb(0xa1, 0x02) + outb(0x21, 0x01) outb(0xa1, 0x01) + outb(0x21, 0xff) outb(0xa1, 0xff) +end +fn pic_unmask(line) outb(0x21, inb(0x21) band (255 bxor (1 shl line))) + +# she stroke my keys till i handle +# no fr this is just a key stroke handler +global sh = { line = "", shift = :false } +global on_key = fn(code) do + # shift: 0x2a/0x36 press, + # 0xaa/0xb6 release + # index a blank cell and type a stray space. + if code == 0x2a do sh.shift = :true return :nil end + if code == 0x36 do sh.shift = :true return :nil end + if code == 0xaa do sh.shift = :false return :nil end + if code == 0xb6 do sh.shift = :false return :nil end + if code >= 128 return :nil # other key releases + if code == 28 do # Enter + puts("\n") + run(sh.line) + sh.line = "" + return :nil + end + if code == 14 do # Backspace + if sh.line:len() > 0 do + sh.line = sh.line:sub(0, sh.line:len() - 1) + puts("\x08 \x08") + end + return :nil + end + if code < 2 return :nil + if code >= KBD:len() return :nil + const ch = if sh.shift KBD_SHIFT[code] else KBD[code] + sh.line = sh.line ~ ch + puts(ch) +end diff --git a/kernel/main.rv b/kernel/main.rv index 8fe3b81..d3f1b23 100644 --- a/kernel/main.rv +++ b/kernel/main.rv @@ -1,240 +1,6 @@ -# font8x8_basic (printable ASCII 0x20..0x7f), one row of 8 glyphs per line -# each glyph is 8 bytes; bit 0 (LSB) of a byte is the leftmost pixel -global FONT = { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00 }, - { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00 }, - { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00 }, - { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00 }, - { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00 }, - { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00 }, - { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00 }, - { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00 }, - { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06 }, - { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00 }, - { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00 }, - { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00 }, - { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00 }, - { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00 }, - { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00 }, - { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00 }, - { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00 }, - { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00 }, - { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00 }, - { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00 }, - { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00 }, - { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00 }, - { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06 }, - { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00 }, - { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00 }, - { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00 }, - { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00 }, - { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00 }, - { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00 }, - { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00 }, - { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00 }, - { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00 }, - { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00 }, - { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00 }, - { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00 }, - { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00 }, - { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 }, - { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00 }, - { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00 }, - { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00 }, - { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00 }, - { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00 }, - { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00 }, - { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00 }, - { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00 }, - { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00 }, - { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00 }, - { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 }, - { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00 }, - { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00 }, - { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00 }, - { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00 }, - { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00 }, - { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00 }, - { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00 }, - { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00 }, - { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00 }, - { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }, - { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00 }, - { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00 }, - { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00 }, - { 0x38, 0x30, 0x30, 0x3E, 0x33, 0x33, 0x6E, 0x00 }, - { 0x00, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00 }, - { 0x1C, 0x36, 0x06, 0x0F, 0x06, 0x06, 0x0F, 0x00 }, - { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F }, - { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00 }, - { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 }, - { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E }, - { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00 }, - { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00 }, - { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00 }, - { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00 }, - { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00 }, - { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F }, - { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78 }, - { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00 }, - { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00 }, - { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00 }, - { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00 }, - { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00 }, - { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00 }, - { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00 }, - { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F }, - { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00 }, - { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00 }, - { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 }, - { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00 }, - { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, -} - -const SCALE = 2 -const CW = 8 * SCALE -const CH = 8 * SCALE -const FG = 0xd0d0d0 -const CON_BG = 0x101018 -global con = { col = 0, row = 0 } - -fn con_cols() fb_width() / CW -fn con_rows() fb_height() / CH - -fn draw_glyph(col, row, ch) do - const x0 = col * CW - const y0 = row * CH - fill_rect(x0, y0, CW, CH, CON_BG) # clear the cell - const code = ch:ascii() - if code < 32 return :nil - if code > 127 return :nil - const g = FONT[code - 32] - for fy in 0..8 do - const bits = g[fy] - for fx in 0..8 do - if (bits shr fx) band 1 == 1 fill_rect(x0 + fx * SCALE, y0 + fy * SCALE, SCALE, SCALE, FG) - end - end -end - -fn con_newline() do - con.col = 0 - con.row = con.row + 1 - if con.row >= con_rows() do - fb_scroll(CH, CON_BG) - con.row = con_rows() - 1 - end -end - -# we dont do Shift/Cntrl -# thats a job for future me lmao -fn con_putc(ch) do - const code = ch:ascii() - if code == 10 do con_newline() return :nil end # \n - if code == 13 do con.col = 0 return :nil end # \r - if code == 8 do # backspace: move left - if con.col > 0 con.col = con.col - 1 - return :nil - end - if code < 32 return :nil - draw_glyph(con.col, con.row, ch) - con.col = con.col + 1 - if con.col >= con_cols() con_newline() -end - -# render a string to the screen and mirror to serial -fn puts(s) do - serial_puts(s) - for i in 0..s:len() do con_putc(s[i]) end -end - -# keyboard scancode table -# ts is NOT a good way to write a driver LMAO -const KBD = " 1234567890-= qwertyuiop[] asdfghjkl;'` \\zxcvbnm,./ " - -# 8259 PIC -fn pic_remap() do - outb(0x20, 0x11) outb(0xa0, 0x11) - outb(0x21, 0x20) outb(0xa1, 0x28) - outb(0x21, 0x04) outb(0xa1, 0x02) - outb(0x21, 0x01) outb(0xa1, 0x01) - outb(0x21, 0xff) outb(0xa1, 0xff) -end -fn pic_unmask(line) outb(0x21, inb(0x21) band (255 bxor (1 shl line))) - -# this is just a simple prompt to test that shit is working -fn cmd_help() puts("commands: help, clear, bars, echo , time\n") - -fn cmd_clear() do - fill_rect(0, 0, fb_width(), fb_height(), CON_BG) - con.col = 0 - con.row = 0 -end - -fn cmd_bars() do - const bars = { 0xff5555, 0xffaa00, 0xffff55, 0x55ff55, 0x55ffff, 0x5599ff, 0xaa55ff, 0xffffff } - const bw = fb_width() / 8 - for i in 0..8 do fill_rect(i * bw, 0, bw, 40, bars[i]) end - puts("painted 8 bars from revo\n") -end - -fn bcd(b) (b shr 4) * 10 + (b band 15) -fn rtc(reg) do - outb(0x70, reg) - inb(0x71) -end -fn cmd_time() puts("utc " ~ bcd(rtc(4)) ~ ":" ~ bcd(rtc(2)) ~ ":" ~ bcd(rtc(0)) ~ "\n") - -fn run(line) do - const words = line:split(" ") - const cmd = words[0] - if cmd == "help" do cmd_help() end - else if cmd == "clear" do cmd_clear() end - else if cmd == "bars" do cmd_bars() end - else if cmd == "time" do cmd_time() end - else if cmd == "echo" do - if line:len() > 5 puts(line:sub(5, line:len() - 5) ~ "\n") else puts("\n") - end - else if line:len() == 0 do :nil end - else do puts("unknown command: " ~ cmd ~ "\n") end - puts("> ") -end - -# she stroke my keys till i handle -# no fr this is just a key stroke handler -global sh = { line = "" } -global on_key = fn(code) do - if code >= 128 return :nil # key release - if code == 28 do # Enter - puts("\n") - run(sh.line) - sh.line = "" - return :nil - end - if code == 14 do # Backspace - if sh.line:len() > 0 do - sh.line = sh.line:sub(0, sh.line:len() - 1) - puts("\x08 \x08") - end - return :nil - end - if code < 2 return :nil - if code >= KBD:len() return :nil - const ch = KBD[code] - sh.line = sh.line ~ ch - puts(ch) -end - # kmain pic_remap() pic_unmask(1) cmd_clear() puts("revel shell, live in revo. type `help`\n> ") +flush_console() diff --git a/kernel/proc.rv b/kernel/proc.rv new file mode 100644 index 0000000..af6e8f7 --- /dev/null +++ b/kernel/proc.rv @@ -0,0 +1,40 @@ +# parse the embedded ELF (physical address from elf_phys()) and run it in ring 3 + +const PT_LOAD = 1 +const PAGE_FLAGS = 6 # WRITE | USER + +fn cmd_run() do + const base = elf_phys() + if mem_read(base, 4) != 0x464c457f do + puts("run: not an ELF\n") + return :nil + end + const entry = mem_read(base + 24, 8) + const phoff = mem_read(base + 32, 8) + const phnum = mem_read(base + 56, 2) + const phentsize = mem_read(base + 54, 2) + const as = as_create() + for i in 0..phnum do + const ph = base + phoff + i * phentsize + if mem_read(ph, 4) == PT_LOAD do + const offset = mem_read(ph + 8, 8) + const vaddr = mem_read(ph + 16, 8) + const filesz = mem_read(ph + 32, 8) + const memsz = mem_read(ph + 40, 8) + let off = 0 + while off < memsz do + const frame = frame_alloc() + mem_zero(frame, 4096) + if off < filesz do + const left = filesz - off + mem_copy(frame, base + offset + off, if left > 4096 4096 else left) + end + as_map(as, vaddr + off, frame, PAGE_FLAGS) + off = off + 4096 + end + end + end + const stack_top = 0x7fff0000 + as_map(as, stack_top - 4096, frame_alloc(), PAGE_FLAGS) + proc_run(as, entry, stack_top) +end diff --git a/kernel/shell.rv b/kernel/shell.rv new file mode 100644 index 0000000..562f3c4 --- /dev/null +++ b/kernel/shell.rv @@ -0,0 +1,55 @@ +# this is just a simple prompt to test that shit is working +fn cmd_help() puts("commands: help, clear, bars, echo , time, run, zoom in|out\n") + +fn zoom_by(d) do + let s = con.scale + d + if s < 1 do s = 1 end + if s > 6 do s = 6 end + con.scale = s + cmd_clear() + puts("zoom " ~ s ~ "x\n") +end + +fn cmd_zoom(words) do + const dir = if words:len() > 1 words[1] else "" + if dir == "in" do zoom_by(1) end + else if dir == "out" do zoom_by(-1) end + else do puts("usage: zoom in | zoom out\n") end +end + +fn cmd_clear() do + fill_rect(0, 0, fb_width(), fb_height(), CON_BG) + con.col = 0 + con.row = 0 +end + +fn cmd_bars() do + const bars = { 0xff5555, 0xffaa00, 0xffff55, 0x55ff55, 0x55ffff, 0x5599ff, 0xaa55ff, 0xffffff } + const bw = fb_width() / 8 + for i in 0..8 do fill_rect(i * bw, 0, bw, 40, bars[i]) end + puts("painted 8 bars from revo\n") +end + +fn bcd(b) (b shr 4) * 10 + (b band 15) +fn rtc(reg) do + outb(0x70, reg) + inb(0x71) +end +fn cmd_time() puts("utc " ~ bcd(rtc(4)) ~ ":" ~ bcd(rtc(2)) ~ ":" ~ bcd(rtc(0)) ~ "\n") + +fn run(line) do + const words = line:split(" ") + const cmd = words[0] + if cmd == "help" do cmd_help() end + else if cmd == "clear" do cmd_clear() end + else if cmd == "bars" do cmd_bars() end + else if cmd == "time" do cmd_time() end + else if cmd == "run" do cmd_run() end + else if cmd == "zoom" do cmd_zoom(words) end + else if cmd == "echo" do + if line:len() > 5 puts(line:sub(5, line:len() - 5) ~ "\n") else puts("\n") + end + else if line:len() == 0 do :nil end + else do puts("unknown command: " ~ cmd ~ "\n") end + puts("> ") +end diff --git a/kernel/vmm.rv b/kernel/vmm.rv new file mode 100644 index 0000000..d6673b3 --- /dev/null +++ b/kernel/vmm.rv @@ -0,0 +1,24 @@ +# build the 4-level page tables for one user page +# everything here only writes small entries we construct, so it's f64-safe +const PTE_ADDR = 0x000FFFFFFFFFF000 + +fn pte_idx(virt, level) (virt shr (12 + 9 * level)) band 0x1ff + +# next-level table phys under entry `i` of table `tbl`, creating it if absent +fn next_table(tbl, i) do + const slot = tbl + i * 8 + const entry = mem_read(slot, 8) + if (entry band 1) != 0 return entry band PTE_ADDR + const frame = frame_alloc() + mem_zero(frame, 4096) + mem_write(slot, frame bor 7, 8) # present | write | user + frame +end + +fn as_map(pml4, virt, phys, flags) do + const pdpt = next_table(pml4, pte_idx(virt, 3)) + const pd = next_table(pdpt, pte_idx(virt, 2)) + const pt = next_table(pd, pte_idx(virt, 1)) + mem_write(pt + pte_idx(virt, 0) * 8, (phys band PTE_ADDR) bor flags bor 1, 8) + invlpg(virt) +end -- cgit v1.3