From fb88c62f678dc588f7a474d21e92d782471e056d Mon Sep 17 00:00:00 2001 From: Alexander Myltsev Date: Tue, 22 Nov 2022 21:24:49 +0300 Subject: [PATCH] Install new GDT in C code. --- Makefile | 2 +- cpu/gdt.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ cpu/gdt.h | 19 +++++++++++++++++++ kernel.c | 2 ++ mbr.S | 3 +-- 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 cpu/gdt.c create mode 100644 cpu/gdt.h diff --git a/Makefile b/Makefile index 760de1a..733507b 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ image.bin: mbr.bin fs.img cat $^ >$@ kernel.bin: kernel.o console.o drivers/vga.o drivers/keyboard.o \ - string.o drivers/ata.o cpu/vectors.o cpu/idt.o drivers/uart.o + string.o drivers/ata.o cpu/vectors.o cpu/idt.o cpu/gdt.o drivers/uart.o $(LD) $(LDFLAGS) -o $@ -Ttext 0x1000 $^ %.o: %.c diff --git a/cpu/gdt.c b/cpu/gdt.c new file mode 100644 index 0000000..4b1b6d2 --- /dev/null +++ b/cpu/gdt.c @@ -0,0 +1,49 @@ +#include "gdt.h" + +#include + +struct seg_desc_t { + uint16_t lim_15_0; // Low bits of segment limit + uint16_t base_15_0; // Low bits of segment base address + uint8_t base_23_16; // Middle bits of segment base address + uint8_t type : 4; // Segment type (see STS_ constants) + uint8_t s : 1; // 0 = system, 1 = application + uint8_t dpl : 2; // Descriptor Privilege Level + uint8_t p : 1; // Present + uint8_t lim_19_16 : 4; // High bits of segment limit + uint8_t avl : 1; // Unused (available for software use) + uint8_t rsv1 : 1; // Reserved + uint8_t db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + uint8_t g : 1; // Granularity: limit scaled by 4K when set + uint8_t base_31_24; // High bits of segment base address +} __attribute__((packed)); + +typedef unsigned uint; + +#define SEG(type, base, lim, dpl) (struct seg_desc_t) \ +{ ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ + ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 } + +struct seg_desc_t seg_desc[6]; + +void init_seg_desc() { + seg_desc[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0); + seg_desc[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); + seg_desc[SEG_UCODE] = SEG(STA_X|STA_R, USER_BASE, 0xffffffff - USER_BASE, DPL_USER); + seg_desc[SEG_UDATA] = SEG(STA_W, USER_BASE, 0xffffffff - USER_BASE, DPL_USER); +} + +struct gdt_desc_t { + uint16_t size; + void* ptr; +} __attribute__((packed)); + +void load_gdt() { + init_seg_desc(); + + struct gdt_desc_t gdt_desc; + gdt_desc.size = sizeof(seg_desc) - 1; + gdt_desc.ptr = seg_desc; + asm("lgdt %0": : "m"(gdt_desc)); +} diff --git a/cpu/gdt.h b/cpu/gdt.h new file mode 100644 index 0000000..578fcc8 --- /dev/null +++ b/cpu/gdt.h @@ -0,0 +1,19 @@ +#pragma once + +#define STA_X 0x8 // Executable segment +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) + +#define DPL_USER 3 + +#define SEG_KCODE 1 +#define SEG_KDATA 2 +#define SEG_UCODE 3 +#define SEG_UDATA 4 +#define SEG_TSS 5 + +#define USER_BASE 0x400000 // 4 MB + +#ifndef __ASSEMBLER__ +void load_gdt(); +#endif diff --git a/kernel.c b/kernel.c index 2cb823c..430c8d5 100644 --- a/kernel.c +++ b/kernel.c @@ -2,6 +2,7 @@ asm(".asciz \"kernel start\""); #include "console.h" #include "cpu/isr.h" +#include "cpu/gdt.h" #include "drivers/keyboard.h" #include "drivers/vga.h" #include "drivers/ata.h" @@ -9,6 +10,7 @@ asm(".asciz \"kernel start\""); #include "drivers/uart.h" void _start() { + load_gdt(); init_keyboard(); uartinit(); load_idt(); diff --git a/mbr.S b/mbr.S index dac62bb..a214220 100644 --- a/mbr.S +++ b/mbr.S @@ -80,8 +80,7 @@ bios_disk_read: 1: mov $2, %ah // read mode int $0x13 - test %ah, %ah - jnz fail + jc fail add $SECTOR_SIZE, %bx inc %cl dec %si