gdt idt stuff
This commit is contained in:
@@ -57,6 +57,12 @@ void vga_initialize()
|
||||
|
||||
void vga_putchar(char c)
|
||||
{
|
||||
if (c == '\n') {
|
||||
terminal_row++;
|
||||
terminal_column = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t index = terminal_row * VGA_WIDTH + terminal_column;
|
||||
terminal_buffer[index] = vga_entry(c, terminal_color);
|
||||
if (++terminal_column == VGA_WIDTH) {
|
||||
|
||||
41
kernel/gdt.c
41
kernel/gdt.c
@@ -40,23 +40,44 @@
|
||||
#define GDT_DATA_PL3 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \
|
||||
SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \
|
||||
SEG_PRIV(3) | SEG_DATA_RDWR
|
||||
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} gdt_ptr_t;
|
||||
|
||||
uint64_t gdt[5];
|
||||
gdt_ptr_t gdtr;
|
||||
|
||||
extern void load_gdt();
|
||||
|
||||
uint64_t create_descriptor(uint32_t base, uint32_t limit, uint16_t flag)
|
||||
{
|
||||
uint64_t descriptor;
|
||||
|
||||
// Create the high 32 bit segment
|
||||
descriptor = limit & 0x000F0000; // set limit bits 19:16
|
||||
descriptor |= (flag << 8) & 0x00F0FF00; // set type, p, dpl, s, g, d/b, l and avl fields
|
||||
descriptor |= (base >> 16) & 0x000000FF; // set base bits 23:16
|
||||
descriptor |= base & 0xFF000000; // set base bits 31:24
|
||||
descriptor = limit & 0x000F0000;
|
||||
descriptor |= (flag << 8) & 0x00F0FF00;
|
||||
descriptor |= (base >> 16) & 0x000000FF;
|
||||
descriptor |= base & 0xFF000000;
|
||||
|
||||
// Shift by 32 to allow for low part of segment
|
||||
descriptor <<= 32;
|
||||
|
||||
// Create the low 32 bit segment
|
||||
descriptor |= base << 16; // set base bits 15:0
|
||||
descriptor |= limit & 0x0000FFFF; // set limit bits 15:0
|
||||
descriptor |= base << 16;
|
||||
descriptor |= limit & 0x0000FFFF;
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
void init_gdt() {
|
||||
gdt[0] = create_descriptor(0, 0, 0);
|
||||
gdt[1] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL0));
|
||||
gdt[2] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL0));
|
||||
gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3));
|
||||
gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3));
|
||||
|
||||
gdtr.limit = 5 * sizeof(uint64_t) - 1;
|
||||
gdtr.base = (uint32_t)&gdt;
|
||||
|
||||
load_gdt();
|
||||
}
|
||||
|
||||
|
||||
14
kernel/gdt_stubs.s
Normal file
14
kernel/gdt_stubs.s
Normal file
@@ -0,0 +1,14 @@
|
||||
.code32
|
||||
.extern gdtr
|
||||
.global load_gdt
|
||||
load_gdt:
|
||||
lgdt gdtr
|
||||
ljmpl $0x08, $reload_segments
|
||||
reload_segments:
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
ret
|
||||
@@ -54,5 +54,4 @@ void init_idt() {
|
||||
}
|
||||
|
||||
load_idt();
|
||||
enable_int();
|
||||
}
|
||||
@@ -3,17 +3,17 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
typedef struct __attribute__((packed)){
|
||||
uint16_t isr_low; // The lower 16 bits of the ISR's address
|
||||
uint16_t kernel_cs; // The GDT segment selector the CPU will load into CS
|
||||
uint8_t reserved; // Set to 0
|
||||
uint8_t attributes;// Type and attributes flags
|
||||
uint16_t isr_high; // The higher 16 bits of the ISR's address
|
||||
} idt_entry __attribute__((packed));
|
||||
} idt_entry;
|
||||
|
||||
typedef struct {
|
||||
typedef struct __attribute__((packed)){
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} idt_ptr __attribute__((packed));
|
||||
} idt_ptr;
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
extern void init_idt();
|
||||
extern idt_entry create_idt_entry(uint32_t addr, uint16_t segment, uint8_t attributes);
|
||||
extern void init_gdt();
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
@@ -15,7 +15,11 @@ void kernel_main(void)
|
||||
kout = &vga_print_stream;
|
||||
kout->trunc();
|
||||
|
||||
kprint("RockOS booting...");
|
||||
kprint("RockOS booting...\n");
|
||||
|
||||
init_gdt();
|
||||
kprint("GDT set\n");
|
||||
|
||||
init_idt();
|
||||
kprint("IDT set\n");
|
||||
}
|
||||
|
||||
8
makefile
8
makefile
@@ -6,6 +6,7 @@ OSNAME := rockos
|
||||
C_SOURCES := $(shell find kernel -type f -name '*.c')
|
||||
S_SOURCES := $(shell find kernel -type f -name '*.s')
|
||||
|
||||
# This correctly generates paths like obj/kernel/main.o
|
||||
OBJECTS := $(patsubst %.c, obj/%.o, $(C_SOURCES)) $(patsubst %.s, obj/%.o, $(S_SOURCES))
|
||||
|
||||
CFLAGS := -ffreestanding -O2 -Wall -Wextra -Ikernel
|
||||
@@ -13,6 +14,8 @@ LDFLAGS := -T kernel/linker.ld
|
||||
|
||||
.PHONY: all run clean
|
||||
|
||||
all: $(OSNAME).iso
|
||||
|
||||
$(OSNAME).bin: $(OBJECTS)
|
||||
$(LD) $(LDFLAGS) -o $@ $(OBJECTS)
|
||||
|
||||
@@ -22,11 +25,12 @@ $(OSNAME).iso: $(OSNAME).bin grub.cfg
|
||||
cp grub.cfg isodir/boot/grub/grub.cfg
|
||||
grub-mkrescue -o $(OSNAME).iso isodir
|
||||
|
||||
obj/%.o: %.c
|
||||
# FIX: Pattern rules now explicitly expect the 'kernel' directory layout
|
||||
obj/kernel/%.o: kernel/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $< -o $@ $(CFLAGS)
|
||||
|
||||
obj/%.o: %.s
|
||||
obj/kernel/%.o: kernel/%.s
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $< -o $@ $(CFLAGS)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user