diff options
| author | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2022-10-06 16:45:17 +0200 |
|---|---|---|
| committer | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2022-10-06 16:45:17 +0200 |
| commit | f8397815545adb7d0da36614e0065aa68453a2e4 (patch) | |
| tree | a771f526970c6724b2511577dceece8783450a49 /stage3 | |
| download | cuddles-f8397815545adb7d0da36614e0065aa68453a2e4.tar.xz | |
Initial commit
Diffstat (limited to 'stage3')
| -rw-r--r-- | stage3/colors.asm | 16 | ||||
| -rw-r--r-- | stage3/def.h | 21 | ||||
| -rw-r--r-- | stage3/font.asm | 243 | ||||
| -rw-r--r-- | stage3/framebuffer.asm | 176 | ||||
| -rwxr-xr-x | stage3/fut/linkgen.lua | 101 | ||||
| -rw-r--r-- | stage3/fut/os | 161 | ||||
| -rw-r--r-- | stage3/fut/process.c | 77 | ||||
| -rw-r--r-- | stage3/fut/sys_kern.c | 21 | ||||
| -rw-r--r-- | stage3/fut/sys_kern.h | 91 | ||||
| -rw-r--r-- | stage3/fut/sys_user.c | 36 | ||||
| -rw-r--r-- | stage3/fut/sys_user.h | 91 | ||||
| -rw-r--r-- | stage3/fut/yield.asm | 49 | ||||
| -rw-r--r-- | stage3/gfx.c | 32 | ||||
| -rw-r--r-- | stage3/gfx.h | 21 | ||||
| -rw-r--r-- | stage3/halt.c | 7 | ||||
| -rw-r--r-- | stage3/halt.h | 6 | ||||
| -rw-r--r-- | stage3/main.c | 34 | ||||
| -rw-r--r-- | stage3/memory.asm | 59 | ||||
| -rw-r--r-- | stage3/paging.asm | 336 | ||||
| -rw-r--r-- | stage3/paging.h | 20 |
20 files changed, 1598 insertions, 0 deletions
diff --git a/stage3/colors.asm b/stage3/colors.asm new file mode 100644 index 0000000..a53efff --- /dev/null +++ b/stage3/colors.asm @@ -0,0 +1,16 @@ +%define COLOR_BLACK 0 +%define COLOR_BLUE 1 +%define COLOR_GREEN 2 +%define COLOR_CYAN 3 +%define COLOR_RED 4 +%define COLOR_MAGENTA 5 +%define COLOR_BROWN 6 +%define COLOR_LIGHT_GREY 7 +%define COLOR_DARK_GREY 8 +%define COLOR_LIGHT_BLUE 9 +%define COLOR_LIGHT_GREEN 10 +%define COLOR_LIGHT_CYAN 11 +%define COLOR_LIGHT_RED 12 +%define COLOR_LIGHT_MAGENTA 13 +%define COLOR_LIGHT_BROWN 14 +%define COLOR_WHITE 15 diff --git a/stage3/def.h b/stage3/def.h new file mode 100644 index 0000000..c2f8311 --- /dev/null +++ b/stage3/def.h @@ -0,0 +1,21 @@ +#ifndef _DEF_H_ +#define _DEF_H_ + +#define nil ((void *) 0x0) + +typedef unsigned char u8; +typedef signed char i8; + +typedef unsigned short u16; +typedef short i16; + +typedef unsigned int u32; +typedef int i32; + +typedef unsigned long u64; +typedef long i64; + +typedef u64 usize; +typedef i64 isize; + +#endif diff --git a/stage3/font.asm b/stage3/font.asm new file mode 100644 index 0000000..b73edab --- /dev/null +++ b/stage3/font.asm @@ -0,0 +1,243 @@ +global debug + +%define GFXINFO 0x1000-10 +%define PITCH GFXINFO+0 +%define WIDTH GFXINFO+2 +%define HEIGHT GFXINFO+4 +%define FRAMEBUFFER GFXINFO+6 + +section .text + +; str in rdi +debug: + mov r9, [line] + + mov rax, rcx + mov rbx, 15 + xor rdx, rdx + mul rbx + + cmp rax, [HEIGHT] + jmp .char + + xor rax, rax + xor r9, r9 + +.char: + xor rax, rax + + mov al, [rdi] + cmp al, 0 + je .return + + cmp al, ' ' + je .space + + cmp al, 'a' + jb .invalid + + cmp al, 'z' + ja .invalid + + sub al, 'a' + mov bl, 15 + mul bl + + add rax, letters + mov r8, rax + + jmp .render + +.space: + mov r8, letters.space + +.render: + +.target: + xor rdx, rdx + mul [PITCH] + + xor rbx, rbx + mov ebx, [FRAMEBUFFER] + add rax, rbx + + inc rdi + jmp debug + +.return: + ret + +.invalid: + mov rdi, .invalid_msg + call debug + jmp $ + +.invalid_msg: "invalid character in message", 0 + +section .data + +line: dq 0 + +letters: +.a: db +1, 1, 1, +1, 0, 1, +1, 1, 1, +1, 0, 1, +1, 0, 1 +.b: db +1, 1, 0, +1, 0, 1, +1, 1, 1, +1, 0, 1, +1, 1, 1 +.c: db +1, 1, 1, +1, 0, 0, +1, 0, 0, +1, 0, 0, +1, 1, 1 +.d: db +1, 1, 0, +1, 0, 1, +1, 0, 1, +1, 0, 1, +1, 1, 1 +e: db +1, 1, 1, +1, 0, 0, +1, 1, 1, +1, 0, 0, +1, 1, 1 +f: db +1, 1, 1, +1, 0, 0, +1, 1, 1, +1, 0, 0, +1, 0, 0 +g: db +1, 1, 1, +1, 0, 0, +1, 0, 1, +1, 0, 1, +1, 1, 1 +h: db +1, 0, 1, +1, 0, 1, +1, 1, 1, +1, 0, 1, +1, 0, 1 +i: db +0, 1, 0, +0, 1, 0, +0, 1, 0, +0, 1, 0, +0, 1, 0 +j: db +0, 0, 1, +0, 0, 1, +0, 0, 1, +0, 0, 1, +1, 1, 1 +k: db +1, 0, 1, +1, 1, 0, +1, 0, 0, +1, 1, 0, +1, 0, 1, +l: db +1, 0, 0, +1, 0, 0, +1, 0, 0, +1, 0, 0, +1, 1, 1 +m: db +1, 0, 1, +1, 1, 1, +1, 0, 1, +1, 0, 1, +1, 0, 1 +n: db +1, 0, 1, +1, 0, 1, +1, 1, 1, +1, 1, 1, +1, 0, 1 +o: db +1, 1, 1, +1, 0, 1, +1, 0, 1, +1, 0, 1, +1, 1, 1 +p: db +1, 1, 1, +1, 0, 1, +1, 1, 1, +1, 0, 0, +1, 0, 0 +q: db +1, 1, 1, +1, 0, 1, +1, 1, 1, +1, 1, 1, +0, 0, 1 +r: db +1, 1, 1, +1, 0, 1, +1, 1, 1, +1, 1, 0, +1, 0, 1 +s: db +1, 1, 1, +1, 0, 0, +1, 1, 1, +0, 0, 1, +1, 1, 1 +t: db +1, 1, 1, +0, 1, 0, +0, 1, 0, +0, 1, 0, +0, 1, 0 +u: db +1, 0, 1, +1, 0, 1, +1, 0, 1, +1, 0, 1, +1, 1, 1 +v: db +1, 0, 1, +1, 0, 1, +1, 0, 1, +1, 0, 1, +0, 1, 0 +w: db +1, 0, 1, +1, 0, 1, +1, 0, 1, +1, 1, 1, +1, 0, 1 +x: db +1, 0, 1, +1, 0, 1, +0, 1, 0, +1, 0, 1, +1, 0, 1 +y: db +1, 0, 1, +1, 0, 1, +1, 1, 1, +0, 1, 0, +0, 1, 0 +z: db +1, 1, 1, +0, 0, 1, +0, 1, 0 +1, 0, 0 +1, 1, 1 +.space: +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0, +0, 0, 0 diff --git a/stage3/framebuffer.asm b/stage3/framebuffer.asm new file mode 100644 index 0000000..e55ad04 --- /dev/null +++ b/stage3/framebuffer.asm @@ -0,0 +1,176 @@ +%include "stage3/colors.asm" +global print_chr, print_str, print_dec, print_hex, clear_screen, newline +extern memcpy + +section .data + +pos: +.row: db 0 +.col: db 0 + +cursor: dq 0xB8000 +color: db COLOR_WHITE | (COLOR_BLACK << 4) + +section .text + +set_color: + shl sil, 4 + add dil, sil + mov [color], dil + +update_cursor: + mov rbx, [cursor] + sub rbx, 0xB8000 + shr rbx, 1 + + mov dx, 0x3D4 + mov al, 14 + out dx, al + + mov dx, 0x3D5 + mov al, bh + out dx, al + + mov dx, 0x3D4 + mov al, 15 + out dx, al + + mov dx, 0x3D5 + mov al, bl + out dx, al + + ret + +set_chr: + mov rax, [cursor] + mov byte[rax], dil + inc rax + mov dil, [color] + mov [rax], dil + inc rax + mov [cursor], rax + jmp update_cursor + +vertical_tab: + mov al, [pos.row] + inc al + cmp al, 25 + je .scroll + mov [pos.row], al + mov rax, [cursor] + add rax, 160 + mov [cursor], rax + jmp update_cursor +.scroll: + mov rdi, 0xB8000 + mov rsi, 0xB80A0 + mov rdx, 0xF00 + jmp memcpy + +carriage_return: + mov rax, [cursor] + xor rbx, rbx + mov bl, [pos.col] + shl bl, 1 + sub rax, rbx + mov [cursor], rax + mov byte[pos.col], 0 + jmp update_cursor + +newline: + call vertical_tab + jmp carriage_return + +print_chr: + cmp dil, 10 + je newline + cmp dil, 11 + je vertical_tab + cmp dil, 13 + je carriage_return + mov al, [pos.col] + inc al + cmp al, 80 + je .newline + mov [pos.col], al + jmp set_chr +.newline: + push rdi + call newline + pop rdi + jmp set_chr + +print_str: + mov rax, rdi +.print: + mov dil, [rax] + cmp dil, 0 + je .return + push rax + call print_chr + pop rax + inc rax + jmp .print +.return: + ret + +print_hex: + mov rsi, 0x10 + jmp print_num +print_dec: + mov rsi, 10 +print_num: + mov rax, rdi + xor rcx, rcx +.convert: + inc rcx + xor rdx, rdx + div rsi + cmp dl, 10 + jb .digit + add dl, 'A'-10 + jmp .next +.digit: + add dl, '0' +.next: + push rdx + cmp rax, 0 + jne .convert +.print: + cmp rcx, 0 + je .return + dec rcx + pop rdi + push rcx + call print_chr + pop rcx + jmp .print +.return: + ret + +clear_screen: + push rbx + push r12 + push r13 + push r14 + push r15 + + mov qword[cursor], 0xB8000 +.clr: + cmp qword[cursor], 0xB8FA0 + je .return + mov dil, ' ' + call set_chr + jmp .clr +.return: + mov qword[cursor], 0xB8000 + mov byte[pos.row], 0 + mov byte[pos.col], 0 + call update_cursor + + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + ret diff --git a/stage3/fut/linkgen.lua b/stage3/fut/linkgen.lua new file mode 100755 index 0000000..f7a6d21 --- /dev/null +++ b/stage3/fut/linkgen.lua @@ -0,0 +1,101 @@ +#!/usr/bin/env lua +--[[ + +--- trigger warning: brain damage --- + +BOGUS DYNAMIC LINKING v69.420 by LIZZY FLECKENSTEIN + +How this works: +⠀⠀⠀⠀⠀⢰⡿⠋⠁⠀⠀⠈⠉⠙⠻⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢀⣿⠇⠀⢀⣴⣶⡾⠿⠿⠿⢿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⣀⣀⣸⡿⠀⠀⢸⣿⣇⠀⠀⠀⠀⠀⠀⠙⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⣾⡟⠛⣿⡇⠀⠀⢸⣿⣿⣷⣤⣤⣤⣤⣶⣶⣿⠇⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀ +⢀⣿⠀⢀⣿⡇⠀⠀⠀⠻⢿⣿⣿⣿⣿⣿⠿⣿⡏⠀⠀⠀⠀⢴⣶⣶⣿⣿⣿⣆ +⢸⣿⠀⢸⣿⡇⠀⠀⠀⠀⠀⠈⠉⠁⠀⠀⠀⣿⡇⣀⣠⣴⣾⣮⣝⠿⠿⠿⣻⡟ +⢸⣿⠀⠘⣿⡇⠀⠀⠀⠀⠀⠀⠀⣠⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠉⠀ +⠸⣿⠀⠀⣿⡇⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠉⠀⠀⠀⠀ +⠀⠻⣷⣶⣿⣇⠀⠀⠀⢠⣼⣿⣿⣿⣿⣿⣿⣿⣛⣛⣻⠉⠁⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⣿⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⣿⣀⣀⣀⣼⡿⢿⣿⣿⣿⣿⣿⡿⣿⣿⡿ + +Amogus sus 😳 ((impassta)) + +I FUCKING HATE TEH ANTICRIST!!!! +WE GOT YOU SURROUNDEND, USE DYNAMIC LINKING + +:trollface: + +]] + +-- in +local hdr_kern = io.open("sys_kern.h", "r") +-- out +local hdr_user = io.open("sys_user.h", "w") +local src_kern = io.open("sys_kern.c", "w") +local src_user = io.open("sys_user.c", "w") + +local count = 0 +local calltable = "0x500" + +local body_kern = "" +local body_user = "" + +src_kern:write("#include <sys_kern.h>\n") +src_user:write("#include <sys_user.h>\n\n") + +local function process_line(line) + if line == "" or line:sub(1, 1) == "\t" then + return + end + + local f, t = line:find("[%w_]+%(") + + if not f then + return + end + + local start, mid, fin = line:sub(1, f-1), line:sub(f, t-1), line:sub(t) + + if mid == "__attribute__" or mid == "link" then + return + end + + local decl = start .. "(*" .. mid .. ")" .. fin .. "\n" + + hdr_user:write("extern " .. decl) + src_user:write(decl) + + body_kern = body_kern .. "\tcalltable[" .. count .. "] = &" .. mid .. ";\n" + body_user = body_user .. "\t" .. mid .. " = calltable[" .. count .. "];\n" + + count = count + 1 + + return true +end + +while true do + local line = hdr_kern:read() + + if not line then + break + end + + if not process_line(line) then + hdr_user:write(line .. "\n") + end +end + +local function write_link(f, content) + f:write("\nvoid link()\n{\n") + f:write("\tvoid **calltable = " .. calltable .. ";\n\n") + f:write(content) + f:write("}\n") +end + +write_link(src_kern, body_kern) +write_link(src_user, body_user) + +hdr_kern:close() +hdr_user:close() +src_kern:close() +src_user:close() diff --git a/stage3/fut/os b/stage3/fut/os new file mode 100644 index 0000000..64d627f --- /dev/null +++ b/stage3/fut/os @@ -0,0 +1,161 @@ +gfx + - modes text, pixel + - different buffers + - switch between them manually or thingily + +- similar to tmux +- hierarchy + +- text input channel +- keyboard input channel +- mouse input channel + +- text output channel + - +- graphics output channel + +- add text? +- scrollback? + +init + +copy +remove +move +list +edit +directory + +shell +terminal + +mouse +keyboard +text + +tiler +desktop + +-- + +process, display, channel + +-- + +display.x +display.y +display.width +display.height +display.index +display.parent + +display = current_display() +display = create_display(x, y, width, height) + +add_display(parent, child, -1) +remove_display(parent, child) + +display.set_char(pos, color, text) +display.set_pixel(pos, color) +display.flush() + +channel = create_channel() +add_channel(display, channel, name) +channel = get_channel(display, name) + +-- + +process = create_process(path, display) + +add_channel(process, channel) +get_channel(process, "signal") +get_channel(process, "status") + +-- + +current_process() + .get_channel("status") + .send(finish) + +-- +void main() +{ + current_display() + .get_channel("text") + .send("hello, world\n"); +} + +-- + +append(string self, string other) +{ + self.grow(other.len()) + memcpy(self.ptr + self.len() - other.len(), other.ptr, other.len()) +} + +-- +string get_line(channel input) +{ + string s = ""; + + loop { + string c = input.recv(); + + if (c[0] == '\n') + break; + + s.append(c); + } + + return s; +} + +-- +void main() +{ + channel input = current_display() + .get_channel("keyboard"); + + loop { + string command = get_line(input); + + process proc = create_process(path, current_display()); + + receiver status = proc + .get_channel("status") + .subscribe(); + + proc.start(); + + while (!status.recv().equal("finish")) + yield(); + } +} + +-- +void main() +{ + +} + +-- channels +void send(channel c, value v) +{ + listener l = c.listeners.pop(); + + if (l) { + listener.resume(v) + } else { + for (s in c.subscribers) { + if (s.active) + s.active.resume(v) + else + s.buffer.append(v) + } + } +} + +-- queue + +- runqueue pointer at fixed address +- processes must free all heap allocated memory before exit diff --git a/stage3/fut/process.c b/stage3/fut/process.c new file mode 100644 index 0000000..ea99ccf --- /dev/null +++ b/stage3/fut/process.c @@ -0,0 +1,77 @@ +#define STACK_SIZE 65536 +#define CURRENT *((process *) 0x500) + +process process_current() +{ + return CURRENT; +} + +static void process_delete(process p) +{ + free(p->stack); + free(p->code); + map_clear(&p->channels); +} + +static void process_push(process p, u64 value) +{ + p->stack_ptr -= sizeof value; + *p->stack_ptr = value; +} + +void process_exit() +{ + if (CURRENT->next == CURRENT) + panic("init exited"); + + CURRENT->prev->next = CURRENT->next; + CURRENT->next->prev = CURRENT->prev; + rc_drop(*current); + + process_yield(); +} + +process process_create(char *path, display d) +{ + process p = rc_create(sizeof *p, &process_delete); + + p->state = PROCESS_CREATED; + + p->stack = malloc(STACK_SIZE); + p->stack_ptr = p->stack + STACK_SIZE; + p->code = p->code_ptr = file_read(path); + + process_push(p, (u64) &process_exit); + // push 6 callee resaved registers - contents dont actually matter. + for (int i = 0; i < 6; i++) + process_push(p, 0); + + p->displ = d; + p->next = p->prev = nil; + map_init(&p->channels); + + channel sig = channel_create(); + process_channel_add(p, "signal", sig); + rc_drop(sig); + + channel stat = channel_create(); + process_channel_add(p, "status", stat); + rc_drop(stat); + + return p; +} + +void process_start(process p) +{ + if (p->code_ptr == nil) + panic("attempt to start invalid process"); + + if (p->state != PROCESS_CREATED) + panic("attempt to start running or dead process"); + + rc_grab(p); + + p->next = CURRENT->next; + CURRENT->next = p; + p->prev = CURRENT; +} diff --git a/stage3/fut/sys_kern.c b/stage3/fut/sys_kern.c new file mode 100644 index 0000000..c7c5fcc --- /dev/null +++ b/stage3/fut/sys_kern.c @@ -0,0 +1,21 @@ +#include <sys_kern.h> + +void link() +{ + void **calltable = 0x500; + + calltable[0] = &display_current; + calltable[1] = &display_create; + calltable[2] = &display_add; + calltable[3] = &display_remove; + calltable[4] = &display_pixel; + calltable[5] = &display_channel_add; + calltable[6] = &display_channel_get; + calltable[7] = &rc_grab; + calltable[8] = &rc_drop; + calltable[9] = &rc_create; + calltable[10] = &weak_downgrade; + calltable[11] = &weak_upgrade; + calltable[12] = &weak_drop; + calltable[13] = &channel_create; +} diff --git a/stage3/fut/sys_kern.h b/stage3/fut/sys_kern.h new file mode 100644 index 0000000..083fce3 --- /dev/null +++ b/stage3/fut/sys_kern.h @@ -0,0 +1,91 @@ +#ifndef _SYS_H_ +#define _SYS_H_ + +// misc + +typedef struct { + i32 x, y; +} pos; + +typedef struct { + u32 width, height; +} bounds; + +typedef struct { + u8 r, g, b +} color; + +// display + +typedef struct display { + pos p; + bounds b; + struct display *parent; + u64 index; +} *display; + +display display_current(); +display display_create(); +void display_add(display parent, display child, i32 index); +void display_remove(display child); + +void display_pixel(display d, pos p, color c); + +void display_channel_add(char *name, channel ch); +channel display_channel_get(char *name); + +// rc + +typedef struct __attribute__((packed)) { + u32 ref; + u32 own; + void *data; + void (*delete)(void *data); +} rc_header; + +void rc_grab(void *rc); +void rc_drop(void *rc); + +void *rc_create(u64 siz, void *delete); +void *weak_downgrade(void *rc); +void *weak_upgrade(void *weak) +void weak_drop(void *weak); + +// channel + +typedef struct { + array listeners; + array subscribers; +} *channel; + +channel channel_create(); + +// buffered + +typedef struct { + void *active; + array buffer; +} buffered; + +// process + +typedef struct process __attribute__((packed)) { + void *code; + void *stack; + u64 *stack_ptr; + struct process *next; + struct process *prev; + map channels; + display displ; + enum { + PROCESS_CREATED, + PROCESS_RUNNING, + PROCESS_DEAD, + } state; +} *process; + +// setup pointers + +void link(); + +#endif diff --git a/stage3/fut/sys_user.c b/stage3/fut/sys_user.c new file mode 100644 index 0000000..4490513 --- /dev/null +++ b/stage3/fut/sys_user.c @@ -0,0 +1,36 @@ +#include <sys_user.h> + +display (*display_current)(); +display (*display_create)(); +void (*display_add)(display parent, display child, i32 index); +void (*display_remove)(display child); +void (*display_pixel)(display d, pos p, color c); +void (*display_channel_add)(char *name, channel ch); +channel (*display_channel_get)(char *name); +void (*rc_grab)(void *rc); +void (*rc_drop)(void *rc); +void *(*rc_create)(u64 siz, void *delete); +void *(*weak_downgrade)(void *rc); +void *(*weak_upgrade)(void *weak) +void (*weak_drop)(void *weak); +channel (*channel_create)(); + +void link() +{ + void **calltable = 0x500; + + display_current = calltable[0]; + display_create = calltable[1]; + display_add = calltable[2]; + display_remove = calltable[3]; + display_pixel = calltable[4]; + display_channel_add = calltable[5]; + display_channel_get = calltable[6]; + rc_grab = calltable[7]; + rc_drop = calltable[8]; + rc_create = calltable[9]; + weak_downgrade = calltable[10]; + weak_upgrade = calltable[11]; + weak_drop = calltable[12]; + channel_create = calltable[13]; +} diff --git a/stage3/fut/sys_user.h b/stage3/fut/sys_user.h new file mode 100644 index 0000000..3be3d58 --- /dev/null +++ b/stage3/fut/sys_user.h @@ -0,0 +1,91 @@ +#ifndef _SYS_H_ +#define _SYS_H_ + +// misc + +typedef struct { + i32 x, y; +} pos; + +typedef struct { + u32 width, height; +} bounds; + +typedef struct { + u8 r, g, b +} color; + +// display + +typedef struct display { + pos p; + bounds b; + struct display *parent; + u64 index; +} *display; + +extern display (*display_current)(); +extern display (*display_create)(); +extern void (*display_add)(display parent, display child, i32 index); +extern void (*display_remove)(display child); + +extern void (*display_pixel)(display d, pos p, color c); + +extern void (*display_channel_add)(char *name, channel ch); +extern channel (*display_channel_get)(char *name); + +// rc + +typedef struct __attribute__((packed)) { + u32 ref; + u32 own; + void *data; + void (*delete)(void *data); +} rc_header; + +extern void (*rc_grab)(void *rc); +extern void (*rc_drop)(void *rc); + +extern void *(*rc_create)(u64 siz, void *delete); +extern void *(*weak_downgrade)(void *rc); +extern void *(*weak_upgrade)(void *weak) +extern void (*weak_drop)(void *weak); + +// channel + +typedef struct { + array listeners; + array subscribers; +} *channel; + +extern channel (*channel_create)(); + +// buffered + +typedef struct { + void *active; + array buffer; +} buffered; + +// process + +typedef struct process __attribute__((packed)) { + void *code; + void *stack; + u64 *stack_ptr; + struct process *next; + struct process *prev; + map channels; + display displ; + enum { + PROCESS_CREATED, + PROCESS_RUNNING, + PROCESS_DEAD, + } state; +} *process; + +// setup pointers + +void link(); + +#endif diff --git a/stage3/fut/yield.asm b/stage3/fut/yield.asm new file mode 100644 index 0000000..0c4a134 --- /dev/null +++ b/stage3/fut/yield.asm @@ -0,0 +1,49 @@ +global process_yield +extern rc_drop + +%define CURRENT [0x500] + +section .text +process_yield: + ; save callee reserved regs to old stack + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + + ; get CURRENT + mov rdi, CURRENT + + ; set CURRENT->stack_ptr + mov rax, rdi + add rax, 16 + mov [rax], rsp + + ; switch to new process + add rax, 8 + mov rbx, [rax] + mov CURRENT, rbx + + ; activate new stack + add rbx, 16 + mov rsp, [rbx] + + ; drop old process (=rdi) + call rc_drop + + ; grab new process + mov rdi, CURRENT + call rc_grab + + ; restore callee reserved registers + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + + ; jump into new process, with style + ret diff --git a/stage3/gfx.c b/stage3/gfx.c new file mode 100644 index 0000000..0ecf423 --- /dev/null +++ b/stage3/gfx.c @@ -0,0 +1,32 @@ +#include "gfx.h" + +struct GfxInfo *gfxinfo = (void *) (0x1000-10); + +// byteswap +u32 make_color(color col) +{ + return ((u32) 0) + & ((u32) col.r << 0) + & ((u32) col.g << 8) + & ((u32) col.b << 16) + & ((u32) col.a << 24); +} + +void set_pixel(u16 x, u16 y, u32 col) +{ + *((u32 *) (u64) (gfxinfo->framebuffer + y * gfxinfo->pitch + x * sizeof col)) = col; +} + +void set_region(u16 x, u16 y, u16 w, u16 h, u32 col) +{ + void *cbeg = (void *) (u64) (gfxinfo->framebuffer + y * gfxinfo->pitch + x * sizeof col); + void *cend = cbeg + h * gfxinfo->pitch; + + for (; cbeg < cend; cbeg += gfxinfo->pitch) { + void *rbeg = cbeg; + void *rend = rbeg + w * sizeof col; + + for (; rbeg < rend; rbeg += sizeof col) + *((u32 *) rbeg) = col; + } +} diff --git a/stage3/gfx.h b/stage3/gfx.h new file mode 100644 index 0000000..e4e5d8b --- /dev/null +++ b/stage3/gfx.h @@ -0,0 +1,21 @@ +#ifndef _GFX_H_ +#define _GFX_H_ + +#include "def.h" + +extern struct __attribute__((packed)) GfxInfo { + u16 pitch; + u16 width; + u16 height; + u32 framebuffer; +} *gfxinfo; + +typedef struct { + u8 r, g, b, a; +} color; + +u32 make_color(color col); +void set_pixel(u16 x, u16 y, u32 col); +void set_region(u16 x, u16 y, u16 w, u16 h, u32 col); + +#endif diff --git a/stage3/halt.c b/stage3/halt.c new file mode 100644 index 0000000..63ad8e2 --- /dev/null +++ b/stage3/halt.c @@ -0,0 +1,7 @@ +#include "halt.h" + +void halt() +{ + for (;;) + ; +} diff --git a/stage3/halt.h b/stage3/halt.h new file mode 100644 index 0000000..9521dd9 --- /dev/null +++ b/stage3/halt.h @@ -0,0 +1,6 @@ +#ifndef _HALT_H_ +#define _HALT_H_ + +void halt(); + +#endif diff --git a/stage3/main.c b/stage3/main.c new file mode 100644 index 0000000..7c84d05 --- /dev/null +++ b/stage3/main.c @@ -0,0 +1,34 @@ +#include "paging.h" +#include "def.h" +#include "gfx.h" +#include "halt.h" + +void clear_screen(); // framebuffer.asm + +void kmain() +{ + clear_screen(); + + for (MemRegion *mmap = (void *) 0x500; mmap->start != nil; mmap++) + page_region(mmap); + + page_region(&(MemRegion) { + .start = (void *) (u64) gfxinfo->framebuffer, + .size = gfxinfo->pitch * gfxinfo->height, + .type = MEM_RESERVED, + .zero = 0, + }); + + /* + for (u16 x = 0; x < gfxinfo->width; x++) + for (u16 y = 0; y < gfxinfo->height; y++) + set_pixel(x, y, 0x0087CEEB); + */ + + set_region(0, 0, gfxinfo->width, gfxinfo->height, 0x0087CEEB); + + halt(); +} + +// 0xE0000000 +// 0xE03E8000 diff --git a/stage3/memory.asm b/stage3/memory.asm new file mode 100644 index 0000000..b4410a3 --- /dev/null +++ b/stage3/memory.asm @@ -0,0 +1,59 @@ +global memcpy, memmove + +section .text + +memcpy: +.bulk_copy: + cmp rdx, 8 + jl .bytewise_copy + mov rax, qword[rsi] + mov qword[rdi], rax + sub rdx, 8 + add rdi, 8 + add rsi, 8 +.bytewise_copy: + cmp rdx, 0 + je .return + mov al, byte[rsi] + mov byte[rdi], al + dec rdx + inc rdi + inc rsi + jmp .bytewise_copy +.return: + ret + +memmove: + mov rcx, rdx +.bulk_read: + cmp rdx, 8 + jl .bytewise_read + push qword[rsi] + add rsi, 8 + sub rdx, 8 + jmp .bulk_read +.bytewise_read: + cmp rdx, 0 + je .bulk_write + dec rsp + mov al, byte[rsi] + mov byte[rsp], al + inc rsi + dec rdx + jmp .bytewise_read +.bulk_write: + cmp rcx, 8 + jl .bytewise_write + pop qword[rdi] + add rdi, 8 + sub rcx, 8 +.bytewise_write: + cmp rcx, 0 + je .return + mov al, byte[rsp] + mov byte[rdi], al + inc rsp + inc rdi + dec rcx +.return: + ret diff --git a/stage3/paging.asm b/stage3/paging.asm new file mode 100644 index 0000000..8b1d571 --- /dev/null +++ b/stage3/paging.asm @@ -0,0 +1,336 @@ +global page_region +extern print_hex, print_chr, newline, print_dec, print_str + +section .text + +pagebuf_init: + .start: dq 0x5000 + .size: dq 0x2000 + .used: dq 0 + +pagebuf: dq pagebuf_init + +next_page: dq 0 + +; allocate new page table buffer +alloc: + ; rsi = buffer (result) + ; rdi = next_page + ; r8 = pagebuf + ; rbx = upper + ; rax = tmp; used_next + + mov r8, [pagebuf] ; *pagebuf + mov rsi, [r8] ; start = pagebuf->start + + mov rbx, [r8+8] ; size = pagebuf->size + add rbx, rsi ; upper_have = start + size + + ; round *up* to 0x1000 align + mov rax, 0xfff + add rsi, rax + not rax + and rsi, rax ; aligned_start = (start + 0xfff) & (~0xfff) + + mov rax, [r8+16] ; used = pagebuf->used + add rax, 0x1000 + add rsi, rax ; upper_need = aligned_start + used + 0x1000 + + cmp rsi, rbx ; if upper_need > upper_have + ja .newbuf ; current region is full, get new + + cmp rsi, r10 ; if upper_need >= next_page + jae .oom ; out of memory (target buffer isn't paged yet) + + mov [r8+16], rax ; pagebuf->used = used + 0x1000 + + ; clear out buffer + + mov rbx, rsi + sub rsi, 0x1000 + +.clear: + sub rbx, 8 + mov qword[rbx], 0 + cmp rbx, rsi + jne .clear + + ret + +; select next page buffer +.newbuf: + cmp r8, pagebuf_init + jne .nextbuf + + mov r8, 0x500 + jmp .trybuf + +.nextbuf: + add r8, 24 + +.trybuf: + cmp qword[r8], 0 + je .oom ; last region reached + + mov rax, [r8+16] + + cmp rax, -1 + je .nextbuf ; region is reserved + + cmp rax, 0 + jne .oom ; region has not been paged yet + + mov [pagebuf], r8 + jmp alloc + +.oom: + push rdi + + mov rdi, .oom_msg + call print_str + + pop rdi + + call print_hex + call newline + + jmp $ + +.oom_msg: db "out of memory for page table", 10, "next_page = ", 0 + +; get/create page tables +get_tables: +; level 4 + + ; rdi = address (arg, persist) + ; rax = tmp + ; rbx = mask + ; rcx = bits (persist) + ; rdx = level (persist) + ; r8 = table address + ; rsi = next offset (persist) + + mov cl, 12+9*4 + mov dl, 4 + + mov rsi, 0x1000 + +; level 4 +.level: + dec dl + mov r8, rdi + mov rbx, -1 ; reset remainder mask + shl rbx, cl ; update remainder mask + not rbx ; negate remainder mask + and r8, rbx ; apply remainder mask + + mov al, 9 + mul dl + add al, 12 + mov cl, al + + shr r8, cl ; divide + shl r8, 3 ; multiply by 8 + + mov rbx, 0xfff ; 0x1000 alignment + not rbx ; offset mask + + and rsi, rbx ; apply offset mask + add r8, rsi ; add offset + push r8 ; store + + cmp dl, 0 + je .done + + mov rsi, [r8] ; next offset + cmp rsi, 0 + jne .level + + call alloc + or rsi, 3 + mov r8, [rsp] + mov [r8], rsi + + jmp .level + +.done: + pop r11 + pop r12 + pop r13 + pop r14 + + ret + +space: + mov dil, ' ' + jmp print_chr + +page_region: + push rbx + push r12 + push r13 + push r14 + push r15 + + mov r9, rdi + + mov rdi, [r9] ; ptr = mmap_entry->ptr + mov r10, [next_page] + + push rdi + + mov rax, 1 << 63 + + or rdi, rax + call print_hex + call space + + mov rdi, [r9+8] + add rdi, [rsp] + or rdi, rax + + call print_hex + call newline + + pop rdi + + ; for usable region (type = 1), set mmap_entry->used = 0 + ; for reserved region (type = 2), set mmap_entry->used = -1 + xor rax, rax + xor rbx, rbx + mov eax, dword[r9+16] + cmp rax, 1 + je .set_used + dec rbx +.set_used: + mov [r9+16], rbx + + mov r10, rdi + mov r15, rdi ; r15 = end of region + add r15, [r9+8] + + mov rax, 0xfff + not rax + and rdi, rax ; round down to 0x1000 aligned + + cmp rdi, r10 + jb .get_tables + + mov r10, rdi + +.get_tables: + call get_tables ; page tables into r11-r14 + + ; start filling L1 map +.l1: + mov rax, rdi + or rax, 3 + mov [r11], rax + + add rdi, 0x1000 + + cmp rdi, r10 + jb .next + + mov r10, rdi + +.next: + cmp rdi, r15 ; if next >= end + jae .done + + ; prepare rcx mask for later + mov rcx, -1 + shl rcx, 3 + + ; bump L1 + + add r11, 8 + mov rax, r11 + and rax, 0xfff + jnz .l1 + + ; bump L2 + + add r12, 8 + mov rax, r12 + and rax, 0xfff + jnz .l2 + + ; bump L3 + + add r13, 8 + mov rax, r13 + and rax, 0xfff + jnz .l3 + + ; bump L4 + + add r14, 8 + mov rax, r14 + and rax, 0xfff + jnz .l4 + + ; machine has more than 256TB of RAM, tell user to fuck off + jmp .bruh + +.l4: + mov r13, [r14] + and r13, rcx + jnz .l3 + + call alloc + mov r13, rsi + or rsi, 3 + mov [r14], rsi + +.l3: + mov r12, [r13] + and r12, rcx + jnz .l2 + + call alloc + mov r12, rsi + or rsi, 3 + mov [r13], rsi + +.l2: + mov r11, [r12] + and r11, rcx + jnz .l2 + + call alloc + mov r11, rsi + or rsi, 3 + mov [r12], rsi + + jmp .l1 + +.done: + mov [next_page], r10 + + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + + ret + +.bruh: + mov rdi, .bruh_msg + call print_str + jmp $ + +.bruh_msg: db "bruh why do you have more than 256TB of RAM (you fucking glow)", 10, 0 + +; identity map available memory +old_page_map: + mov r9, 0x0500 ; mmap_entry +.entry: + cmp qword[r9], 0 + je .done + call page_region + add r9, 24 + jmp .entry +.done: + ret diff --git a/stage3/paging.h b/stage3/paging.h new file mode 100644 index 0000000..b9a3930 --- /dev/null +++ b/stage3/paging.h @@ -0,0 +1,20 @@ +#ifndef _PAGING_H_ +#define _PAGING_H_ + +#include "def.h" + +typedef enum { + MEM_USABLE = 1, + MEM_RESERVED = 2, +} MemRegionType; + +typedef struct __attribute__((packed)) { + void *start; + usize size; + u16 type; + u16 zero; +} MemRegion; + +void page_region(MemRegion *region); + +#endif |
