diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/arch/amd64/32/paging.c | 24 | ||||
-rw-r--r-- | src/kernel/arch/amd64/boot.c | 13 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/fsroot.c | 4 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/video.c | 82 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/video.h | 11 | ||||
-rw-r--r-- | src/kernel/arch/amd64/multiboot.h | 10 | ||||
-rw-r--r-- | src/kernel/arch/amd64/multiboot.s | 12 | ||||
-rw-r--r-- | src/kernel/mem/alloc.c | 1 |
8 files changed, 142 insertions, 15 deletions
diff --git a/src/kernel/arch/amd64/32/paging.c b/src/kernel/arch/amd64/32/paging.c index f33168d..16c3526 100644 --- a/src/kernel/arch/amd64/32/paging.c +++ b/src/kernel/arch/amd64/32/paging.c @@ -8,7 +8,7 @@ __attribute__((aligned(4096))) static pe_generic_t pdpte_low[512]; // 0-512gb __attribute__((aligned(4096))) -static pe_generic_t pde_low[512]; // 0-1gb +static pe_generic_t pde_low[4][512]; // 4 * 0-1gb void pml4_identity_init(void) { memset32(pml4_identity, 0, sizeof pml4_identity); @@ -21,18 +21,20 @@ void pml4_identity_init(void) { .address = ((uintptr_t)pdpte_low) >> 12, }; - pdpte_low[0] = (pe_generic_t) { - .present = 1, - .writeable = 1, - .address = ((uintptr_t)pde_low) >> 12, - }; - - for (int i = 0; i < 512; i++) { - pde_low[i] = (pe_generic_t) { + for (int i = 0; i < 4; i++) { + pdpte_low[i] = (pe_generic_t) { .present = 1, .writeable = 1, - .large = 1, - .address = (i * 2 * 1024 * 1024) >> 12, + .address = ((uintptr_t)&pde_low[i]) >> 12, }; + + for (int j = 0; j < 512; j++) { + pde_low[i][j] = (pe_generic_t) { + .present = 1, + .writeable = 1, + .large = 1, + .address = (i * 512 + j) << 9, + }; + } } } diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c index e8f9a26..301df52 100644 --- a/src/kernel/arch/amd64/boot.c +++ b/src/kernel/arch/amd64/boot.c @@ -3,6 +3,7 @@ #include <kernel/arch/amd64/driver/fsroot.h> #include <kernel/arch/amd64/driver/ps2.h> #include <kernel/arch/amd64/driver/serial.h> +#include <kernel/arch/amd64/driver/video.h> #include <kernel/arch/amd64/interrupts/idt.h> #include <kernel/arch/amd64/interrupts/irq.h> #include <kernel/arch/amd64/multiboot.h> @@ -25,6 +26,7 @@ static void find_init(struct multiboot_info *multiboot, struct kmain_info *info) void kmain_early(struct multiboot_info *multiboot) { struct kmain_info info; + struct fb_info vid; tty_init(); kprintf("idt..."); @@ -45,5 +47,16 @@ void kmain_early(struct multiboot_info *multiboot) { kprintf("ata..."); ata_init(); + vid.b = (void*)multiboot->framebuffer_addr; + vid.pitch = multiboot->framebuffer_pitch; + vid.width = multiboot->framebuffer_width; + vid.height = multiboot->framebuffer_height; + vid.bpp = multiboot->framebuffer_bpp; + + // TODO printf decimal + kprintf("framebuffer at 0x%x, %xx%x bpp 0x%x\n", vid.b, vid.width, vid.height, vid.bpp); + video_init(vid); + + kmain(info); } diff --git a/src/kernel/arch/amd64/driver/fsroot.c b/src/kernel/arch/amd64/driver/fsroot.c index 2feaf67..e0f5e77 100644 --- a/src/kernel/arch/amd64/driver/fsroot.c +++ b/src/kernel/arch/amd64/driver/fsroot.c @@ -58,11 +58,13 @@ static int handle(struct vfs_request *req) { switch (id) { case HANDLE_ROOT: { // TODO document directory read format + // TODO don't hardcode const char src[] = "vga\0" "com1\0" "ps2\0" - "ata/"; + "ata/\0" + "video/"; return req_readcopy(req, src, sizeof src); } case HANDLE_VGA: diff --git a/src/kernel/arch/amd64/driver/video.c b/src/kernel/arch/amd64/driver/video.c new file mode 100644 index 0000000..8ace3d4 --- /dev/null +++ b/src/kernel/arch/amd64/driver/video.c @@ -0,0 +1,82 @@ +#include <camellia/fsutil.h> +#include <camellia/errno.h> +#include <kernel/arch/amd64/driver/video.h> +#include <kernel/mem/virt.h> +#include <kernel/panic.h> +#include <kernel/vfs/request.h> + +static struct fb_info fb; + +enum { + H_ROOT, + H_FB, +}; + +/* stolen from fsroot.c, TODO shared copy? i guess? */ +static int req_readcopy(struct vfs_request *req, const void *buf, size_t len) { + if (!req->caller) return -1; + assert(req->type == VFSOP_READ); + fs_normslice(&req->offset, &req->output.len, len, false); + virt_cpy_to( + req->caller->pages, req->output.buf, + buf + req->offset, req->output.len); + /* read errors are ignored. TODO write docs */ + return req->output.len; +} + +static int handle(struct vfs_request *req) { + switch (req->type) { + case VFSOP_OPEN: + if (req->input.len == 1) { + return H_ROOT; + } else if (req->input.len == 2 && req->input.kern && req->input.buf_kern[1] == 'b') { + return H_FB; + } else { + return -1; + } + + case VFSOP_READ: + if (req->id == H_ROOT) { + // TODO list available modes, e.g /640x480x24 + const char src[] = "b"; + return req_readcopy(req, src, sizeof src); + } else { + return req_readcopy(req, fb.b, fb.pitch * fb.height); + } + + case VFSOP_WRITE: + if ((long)req->id != H_FB) { + return -1; + } + fs_normslice(&req->offset, &req->input.len, fb.pitch * fb.height, false); + if (!virt_cpy_from(req->caller->pages, fb.b + req->offset, + req->input.buf, req->input.len)) + { + panic_invalid_state(); + return -EFAULT; + } + return req->input.len; + + default: + return -1; + } +} + +static void accept(struct vfs_request *req) { + if (req->caller) { + vfsreq_finish_short(req, handle(req)); + } else { + vfsreq_finish_short(req, -1); + } +} + +static bool is_ready(struct vfs_backend *self) { + (void)self; + return true; +} + +static struct vfs_backend backend = BACKEND_KERN(is_ready, accept); +void video_init(struct fb_info fb_) { + fb = fb_; + vfs_mount_root_register("/video", &backend); +} diff --git a/src/kernel/arch/amd64/driver/video.h b/src/kernel/arch/amd64/driver/video.h new file mode 100644 index 0000000..c1680c4 --- /dev/null +++ b/src/kernel/arch/amd64/driver/video.h @@ -0,0 +1,11 @@ +#pragma once +#include <stdint.h> + +struct fb_info { + char *b; + uint32_t width, height; + uint32_t pitch; /* width in bytes of a single scanline */ + uint8_t bpp; +}; + +void video_init(struct fb_info); diff --git a/src/kernel/arch/amd64/multiboot.h b/src/kernel/arch/amd64/multiboot.h index c6a2650..526dd4c 100644 --- a/src/kernel/arch/amd64/multiboot.h +++ b/src/kernel/arch/amd64/multiboot.h @@ -25,5 +25,13 @@ struct multiboot_info { uint32_t mods_count; uint32_t mods; - // [...] + uint8_t _padding[60]; + + uint64_t framebuffer_addr; + uint32_t framebuffer_pitch; + uint32_t framebuffer_width; + uint32_t framebuffer_height; + uint8_t framebuffer_bpp; + uint8_t framebuffer_type; + uint8_t color_info[6]; } __attribute__((packed)); diff --git a/src/kernel/arch/amd64/multiboot.s b/src/kernel/arch/amd64/multiboot.s index dc19b36..c809297 100644 --- a/src/kernel/arch/amd64/multiboot.s +++ b/src/kernel/arch/amd64/multiboot.s @@ -1,7 +1,8 @@ .set MAGIC, 0x1BADB002 -/* 1<<0 - align modules on page boundaries. */ -.set FLAGS, 1<<0 +/* 1<<0 - align modules on page boundaries. + 1<<2 - enable graphic mode fields */ +.set FLAGS, 1<<0 | 1<<2 .set CHECKSUM, -(MAGIC + FLAGS) .section .multiboot @@ -10,3 +11,10 @@ multiboot_header: .long MAGIC .long FLAGS .long CHECKSUM + + .skip 5 * 4 + + .long 0 + .long 640 + .long 480 + .long 0 diff --git a/src/kernel/mem/alloc.c b/src/kernel/mem/alloc.c index 8d6fa5b..e3eaf41 100644 --- a/src/kernel/mem/alloc.c +++ b/src/kernel/mem/alloc.c @@ -74,6 +74,7 @@ static void bitmap_set(size_t i, bool v) { } void *page_alloc(size_t pages) { + // TODO can allocate in the framebuffer /* i do realize how painfully slow this is */ size_t streak = 0; for (size_t i = 0; i < page_bitmap_len * 8; i++) { |