summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2021-07-22 19:11:42 +0200
committerdzwdz2021-07-22 19:11:42 +0200
commit4823f92f9d3feabdc758d8cd6eef855de90fee2a (patch)
tree374c065807f422818d79b35c33082df3d00b461d
parent8a168f2be5d90f972975abf0b40145a75c0231b7 (diff)
implement the debuglog() syscall
-rw-r--r--src/init/main.c12
-rw-r--r--src/kernel/arch/generic.h4
-rw-r--r--src/kernel/arch/i386/pagedir.c27
-rw-r--r--src/kernel/syscalls.c32
-rw-r--r--src/kernel/syscalls.h6
5 files changed, 70 insertions, 11 deletions
diff --git a/src/init/main.c b/src/init/main.c
index 6c4ccc3..fda68b7 100644
--- a/src/init/main.c
+++ b/src/init/main.c
@@ -1,15 +1,23 @@
+#include <kernel/syscalls.h>
+#include <stddef.h>
#include <stdint.h>
int _syscall(int, int, int, int);
+int debuglog(const char *msg, size_t len) {
+ return _syscall(SC_DEBUGLOG, (void*)msg, len, 0);
+}
+
+
int main() {
- uint8_t color = _syscall(1, 2, 3, 4);
+ debuglog("hello from init! ",
+ sizeof("hello from init! ") - 1);
// change the colors of VGA text
// doesn't require a lot of code, but still shows that it's working
uint8_t *vga = (void*) 0xB8000;
for (int i = 0; i < 80 * 25; i++)
- vga[(i << 1) + 1] = color;
+ vga[(i << 1) + 1] = 0x4e;
// try to mess with kernel memory
uint8_t *kernel = (void*) 0x100000;
diff --git a/src/kernel/arch/generic.h b/src/kernel/arch/generic.h
index 0b005a2..6200320 100644
--- a/src/kernel/arch/generic.h
+++ b/src/kernel/arch/generic.h
@@ -24,3 +24,7 @@ struct pagedir *pagedir_new();
void pagedir_map(struct pagedir *dir, void *virt, void *phys,
bool user, bool writeable);
void pagedir_switch(struct pagedir *);
+
+// return 0 on failure
+void *pagedir_virt2phys(struct pagedir *dir, const void *virt,
+ bool user, bool writeable);
diff --git a/src/kernel/arch/i386/pagedir.c b/src/kernel/arch/i386/pagedir.c
index 8ab406d..02361e6 100644
--- a/src/kernel/arch/i386/pagedir.c
+++ b/src/kernel/arch/i386/pagedir.c
@@ -91,3 +91,30 @@ void pagedir_map(struct pagedir *dir, void *virt, void *phys,
void pagedir_switch(struct pagedir *dir) {
asm volatile("mov %0, %%cr3;" : : "r" (dir) : "memory");
}
+
+void *pagedir_virt2phys(struct pagedir *dir, const void *virt,
+ bool user, bool writeable)
+{
+ uintptr_t virt_casted = (uintptr_t) virt;
+ uintptr_t phys;
+ uint32_t pd_idx = virt_casted >> 22;
+ uint32_t pt_idx = virt_casted >> 12 & 0x03FF;
+ struct pagetable_entry *pagetable, page;
+
+ /* DOESN'T CHECK PERMISSIONS ON PAGE DIRS, TODO
+ * while i don't currently see a reason to set permissions
+ * directly on page dirs, i might see one in the future.
+ * leaving this as-is would be a security bug */
+ if (!dir->e[pd_idx].present) return 0;
+
+ pagetable = (void*)(dir->e[pd_idx].address << 11);
+ page = pagetable[pt_idx];
+
+ if (!page.present) return 0;
+ if (user && !page.user) return 0;
+ if (writeable && !page.writeable) return 0;
+
+ phys = page.address << 11;
+ phys |= (uintptr_t)virt & 0xFFF;
+ return (void*)phys;
+}
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index a42dc44..2af8cf9 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -1,15 +1,29 @@
#include <kernel/arch/generic.h>
#include <kernel/panic.h>
+#include <kernel/proc.h>
+#include <kernel/syscalls.h>
+#include <stdint.h>
-int syscall_handler(int a, int b, int c, int d) {
- // verify that the parameters get passed correctly
- if (a != 1) panic();
- if (b != 2) panic();
- if (c != 3) panic();
- if (d != 4) panic();
+int sc_debuglog(const char *msg, size_t len) {
+ struct pagedir *pages = process_current->pages;
+ void *phys = pagedir_virt2phys(pages, msg, true, false);
- log_const("in a syscall!");
+ // page overrun check
+ if (((uintptr_t)msg & PAGE_MASK) + len > PAGE_SIZE)
+ len = PAGE_SIZE - ((uintptr_t)msg & PAGE_MASK);
+ if (((uintptr_t)msg & PAGE_MASK) + len > PAGE_SIZE)
+ panic(); // just in case I made an off by 1 error
- // used to check if the return value gets passed correctly
- return 0x4e;
+ log_write(phys, len);
+ return len;
+}
+
+int syscall_handler(int num, int a, int b, int c) {
+ switch (num) {
+ case SC_DEBUGLOG:
+ return sc_debuglog((void*)a, b);
+ default:
+ log_const("unknown syscall ");
+ panic();
+ }
}
diff --git a/src/kernel/syscalls.h b/src/kernel/syscalls.h
new file mode 100644
index 0000000..39db6a9
--- /dev/null
+++ b/src/kernel/syscalls.h
@@ -0,0 +1,6 @@
+#pragma once
+
+// not caring about stable syscall numbers just yet
+enum {
+ SC_DEBUGLOG
+};