aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/gdt.c77
-rw-r--r--core/kernel.c3
-rw-r--r--include/garmos/gdt.h22
3 files changed, 102 insertions, 0 deletions
diff --git a/core/gdt.c b/core/gdt.c
new file mode 100644
index 0000000..0085e2f
--- /dev/null
+++ b/core/gdt.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 Robin Krahl <robin.krahl@ireas.org>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <garmos/gdt.h>
+#include <garmos/types.h>
+
+struct gdt_sgmt {
+ uint16_t limit_lo;
+ uint16_t base_lo;
+ uint8_t base_hi;
+ uint8_t access;
+ uint8_t flags_limit_h;
+ uint8_t base_vhi;
+} __attribute__((packed));
+
+enum gdt_sgmts {
+ GDT_SGMT_NULL,
+ GDT_SGMT_CODE,
+ GDT_SGMT_DATA,
+ GDT_SGMT_COUNT
+};
+
+static struct gdt_sgmt gdt[GDT_SGMT_COUNT];
+
+struct gdtp {
+ uint16_t limit;
+ void *pointer;
+} __attribute__((packed));
+
+static struct gdtp gdtp = {
+ .limit = GDT_SGMT_COUNT * sizeof(*gdt) - 1,
+ .pointer = gdt,
+};
+
+static void gdt_sgmt_set(uint32_t base, uint32_t limit, uint8_t access,
+ struct gdt_sgmt *s)
+{
+ if (limit <= 0xFFFF) {
+ s->flags_limit_h = 0x40;
+ } else {
+ if ((limit & 0xFFF) != 0xFFF) {
+ limit = (limit >> 12) - 1;
+ } else {
+ limit >>= 12;
+ }
+ s->flags_limit_h = 0xC0;
+ }
+
+ s->limit_lo = limit & 0xFFFF;
+ s->flags_limit_h |= (limit >> 16) & 0xF;
+
+ s->base_lo = base & 0xFFFF;
+ s->base_hi = (base >> 16) & 0xFF;
+ s->base_vhi = (base >> 24) & 0xFF;
+
+ s->access = access;
+}
+
+void gdt_init(void)
+{
+ gdt_sgmt_set(0, 0, 0, &gdt[GDT_SGMT_NULL]);
+ gdt_sgmt_set(0, 64 * 1024 * 1024, 0x9A, &gdt[GDT_SGMT_CODE]);
+ gdt_sgmt_set(0, 64 * 1024 * 1024, 0x92, &gdt[GDT_SGMT_NULL]);
+
+ asm volatile("lgdt %0" : : "m" (gdtp));
+}
diff --git a/core/kernel.c b/core/kernel.c
index be9782d..586fe20 100644
--- a/core/kernel.c
+++ b/core/kernel.c
@@ -12,11 +12,14 @@
* more details.
*/
+#include <garmos/gdt.h>
#include <garmos/term.h>
#include <garmos/types.h>
void kernel_main(uint32_t multiboot, unsigned int *magicno)
{
+ gdt_init();
+
term_clear();
term_print("garmos 0.1.0\n\n");
diff --git a/include/garmos/gdt.h b/include/garmos/gdt.h
new file mode 100644
index 0000000..b49f42d
--- /dev/null
+++ b/include/garmos/gdt.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Robin Krahl <robin.krahl@ireas.org>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef GARMOS_GDT_H
+#define GARMOS_GDT_H
+
+#include <garmos/types.h>
+
+void gdt_init(void);
+
+#endif