summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kernel/arch/amd64/32/paging.c24
-rw-r--r--src/kernel/arch/amd64/boot.c13
-rw-r--r--src/kernel/arch/amd64/driver/fsroot.c4
-rw-r--r--src/kernel/arch/amd64/driver/video.c82
-rw-r--r--src/kernel/arch/amd64/driver/video.h11
-rw-r--r--src/kernel/arch/amd64/multiboot.h10
-rw-r--r--src/kernel/arch/amd64/multiboot.s12
-rw-r--r--src/kernel/mem/alloc.c1
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++) {