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"); | 
