diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2017-03-05 22:37:54 +0100 |
---|---|---|
committer | Robin Krahl <robin.krahl@ireas.org> | 2017-03-05 22:51:36 +0100 |
commit | f01e48444829cce9eec25f4562778da0ed4ae66c (patch) | |
tree | 7ccf320bd4fb611c989f21f679ad5eed7b77c409 /core | |
parent | d42b629d983de336ddd3c22782caa2791ab78897 (diff) | |
download | garmos-f01e48444829cce9eec25f4562778da0ed4ae66c.tar.gz garmos-f01e48444829cce9eec25f4562778da0ed4ae66c.tar.bz2 |
gdt: add simple gdt implementation
Add a simple Global Descriptor Table implementation based on [0].
[0] http://www.lowlevel.eu/wiki/Global_Descriptor_Table
Diffstat (limited to 'core')
-rw-r--r-- | core/gdt.c | 77 | ||||
-rw-r--r-- | core/kernel.c | 3 |
2 files changed, 80 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"); |