Fix GDT subroutine

Also made some type changes in serial.h
This commit is contained in:
Jenny Curle 2019-04-07 16:36:51 +01:00
parent e4fcbb20b4
commit 15dc60aa12
7 changed files with 46 additions and 34 deletions

View File

@ -35,25 +35,6 @@ _start:
.size _start, . - _start
# GDT segment register setup
.global gdt_flush
.extern gp
gdt_flush:
lgdt (gp) #load the GDT with the special pointer
mov %eax,0x10 #offset from GDT to data segment
mov %eax, %ds
mov %eax, %es
mov %eax, %fs
mov %eax, %gs
mov %eax, %ss
pushl 12(%esp)
push $flush2
ljmp *(%esp) #long jump
flush2:
ret #return to c code
.global idt_load
.extern idtp
idt_load:

17
arch/i386/gdt.s Executable file
View File

@ -0,0 +1,17 @@
; This file is written with Intel ASM Syntax.
[GLOBAL load_gdt] ; Allows the C code to call gdt_flush().
load_gdt:
mov eax, [esp+4] ; Get the pointer to the GDT, passed as a parameter.
lgdt [eax] ; Load the new GDT pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax ; Load all data segment selectors
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:.flush ; 0x08 is the offset to our code segment: Far jump!
.flush:
ret

View File

@ -5,4 +5,5 @@ KERNEL_ARCH_LIBS=
KERNEL_ARCH_OBJS= \
$(ARCHDIR)/boot.o \
$(ARCHDIR)/gdt.o \
$(ARCHDIR)/tty.o

View File

@ -1,4 +1,6 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
extern void init_serial();

View File

@ -1,27 +1,31 @@
#include <kernel/utils.h>
#include <kernel/serial.h>
#include <stddef.h>
#include <stdint.h>
struct gdt_item {
unsigned short low_limit;
unsigned short low_base;
unsigned char middle_base;
unsigned char access;
unsigned char granular;
unsigned char high_base;
uint16_t low_limit;
uint16_t low_base;
uint8_t middle_base;
uint8_t access;
uint8_t granular;
uint8_t high_base;
} __attribute__((packed)); //Prevent compiler optimisation by packing
struct gdt_ptr {
unsigned short limit;
uint16_t limit;
unsigned int base;
} __attribute__((packed));
struct gdt_item gdt[3]; //3-entry gdt
struct gdt_ptr gp;
extern void gdt_flush();
extern void load_gdt(uint32_t);
void gdt_set_gate(int num, unsigned long base,
unsigned long limit, unsigned char access,
unsigned char gran) {
void gdt_set_gate(int num, uint32_t base,
uint32_t limit, uint8_t access,
uint8_t gran) {
//Implementation taken from osdever.net
gdt[num].low_base = (base & 0xFFFF);
gdt[num].middle_base = (base >> 16) & 0xFF;
@ -38,6 +42,7 @@ void gdt_install() {
gp.limit = (sizeof(struct gdt_item) * 3) - 1;
gp.base = (unsigned int)&gdt;
gdt_set_gate(0, 0, 0, 0, 0); //NULL item
//Code Segment - base 0, 4KiB granularity, 4GiB limit
@ -47,5 +52,5 @@ void gdt_install() {
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
//Apply changes
gdt_flush();
load_gdt((uint32_t) &gp);
}

View File

@ -11,9 +11,12 @@ int kernel_main(void) {
// Prepare the serial console.
init_serial();
serial_print(0x3F8, "[INFO] Serial ready.");
// Prepare the GDT
//gdt_install();
serial_print(0x3F8, "[INFO] Serial ready.");
// Prepare the GDT
serial_print(0x3F8, "[INFO] Beginning GDT subroutine.");
gdt_install();
// Prepare interrupts
//idt_install();

View File

@ -61,6 +61,9 @@ red.kernel: $(OBJS) $(ARCHDIR)/linker.ld
$(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o:
OBJ=`$(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@
$(ARCHDIR)/gdt.o:
nasm -f elf $(ARCHDIR)/gdt.s
.c.o:
$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS)