commit aab5207bbd3c17a735529e96624e47eedfee596f
parent 4fe48287b862385075279312d8863c37be3b63ad
Author: Stefan <misc@stefan-koch.name>
Date: Mon, 19 Oct 2015 21:53:39 +0200
setup GDT from kernel
Diffstat:
6 files changed, 79 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,9 +6,11 @@ GCCFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra
all: image kernel kernel-install
kernel:
- $(ASM) boot.asm -o boot.o -f elf
+ $(ASM) arch/x86/boot.asm -o arch/x86/boot.o -f elf
+ $(ASM) arch/x86/gdt.asm -o arch/x86/gdt_asm.o -f elf
$(GCC) -c kernel.c -o kernel.o $(GCCFLAGS)
- $(GCC) -T kernel.ld -o sos-kernel.img -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc
+ $(GCC) -c arch/x86/gdt.c -o arch/x86/gdt.o $(GCCFLAGS)
+ $(GCC) -T kernel.ld -o sos-kernel.img -ffreestanding -O2 -nostdlib arch/x86/boot.o kernel.o arch/x86/gdt_asm.o arch/x86/gdt.o -lgcc
kernel-install:
sudo losetup /dev/loop1 sos.img -o 1048576
@@ -26,13 +28,13 @@ image:
sudo mke2fs /dev/loop1
sudo mount /dev/loop1 /mnt
sudo grub-install --root-directory=/mnt --no-floppy --modules="normal ext2 part_msdos multiboot" /dev/loop0
- sudo cp sos-kernel.img /mnt/boot/
sudo cp grub/* /mnt/boot/grub/
sudo losetup -d /dev/loop0
sudo umount /mnt
sudo losetup -d /dev/loop1
clean:
+ rm arch/x86/*.o
rm *.o
rm sos-kernel.img
rm sos.img
diff --git a/boot.asm b/arch/x86/boot.asm
diff --git a/arch/x86/gdt.asm b/arch/x86/gdt.asm
@@ -0,0 +1,14 @@
+section .text
+extern gdt_desc
+global gdt_install
+gdt_install:
+ lgdt [gdt_desc]
+ jmp 08h:reload_cs
+reload_cs:
+ mov eax, 10h
+ mov ds, eax
+ mov es, eax
+ mov fs, eax
+ mov gs, eax
+ mov ss, eax
+ ret
diff --git a/arch/x86/gdt.c b/arch/x86/gdt.c
@@ -0,0 +1,29 @@
+#include <stdint.h>
+#include "gdt.h"
+
+extern void gdt_install();
+
+void gdt_set_entry(unsigned int pos, uint32_t base, uint32_t limit,
+ uint8_t access_rights, uint8_t flags)
+{
+ gdt[pos].base_lower = base & 0xffff;
+ gdt[pos].base_middle = (base >> 16) & 0xff;
+ gdt[pos].base_higher = (base >> 24) & 0xffff;
+
+ gdt[pos].limit_lower = limit & 0xffff;
+ gdt[pos].flags_limit_higher = ((flags << 4) & 0xf0) | ((limit >> 16) & 0x0f);
+
+ gdt[pos].access_rights = access_rights;
+}
+
+void gdt_setup()
+{
+ gdt_desc.limit = GDT_ENTRIES * sizeof(struct gdt_entry) - 1;
+ gdt_desc.base = (uint32_t) (uintptr_t) gdt;
+
+ gdt_set_entry(0, 0, 0, 0, 0);
+ gdt_set_entry(1, 0, 0xfffff, 0x9a, 0xcf);
+ gdt_set_entry(2, 0, 0xfffff, 0x92, 0xcf);
+
+ gdt_install();
+}
diff --git a/arch/x86/gdt.h b/arch/x86/gdt.h
@@ -0,0 +1,27 @@
+#ifndef GDT_H
+#define GDT_H
+
+#include <stdint.h>
+
+#define GDT_ENTRIES 3
+
+struct gdt_entry {
+ uint16_t limit_lower;
+ uint16_t base_lower;
+ uint8_t base_middle;
+ uint8_t access_rights;
+ uint8_t flags_limit_higher;
+ uint8_t base_higher;
+} __attribute__((packed));
+
+struct gdt_description {
+ uint16_t limit;
+ uint32_t base;
+} __attribute__((packed));
+
+struct gdt_entry gdt[GDT_ENTRIES];
+struct gdt_description gdt_desc;
+
+void gdt_setup();
+
+#endif
diff --git a/kernel.c b/kernel.c
@@ -1,5 +1,9 @@
+#include "arch/x86/gdt.h"
+
void kernel_main()
{
+ gdt_setup();
+
char *vidmem = (char*) 0xb8000;
vidmem[0] = 'H';
vidmem[2] = 'e';