Added code to setup and build the IDT. Updated the Bochs' configuration file to allow break points to be set and did some general code clean-up.

This commit is contained in:
2020-08-06 15:20:45 -05:00
parent d8071c0eac
commit 9fe73abe53
15 changed files with 453 additions and 19 deletions
+3
View File
@@ -5,3 +5,6 @@
*.bin
*.ini
*.out
*.pdf
*.aux
*.gz
+1 -1
View File
@@ -1,3 +1,3 @@
#ifndef KERNEL_VERSION_NUMBER
#define KERNEL_VERSION_NUMBER "0.0.1-354"
#define KERNEL_VERSION_NUMBER "0.0.3-0"
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef IDT_H
#define IDT_H
struct idt_entry
{
unsigned short base_lo;
unsigned short sel; /* Our kernel segment goes here. */
unsigned char always0;
unsigned char flags;
unsigned short base_hi;
} __attribute__((packed));
struct idt_ptr
{
unsigned short size;
struct idt_entry* idt_entries_start;
} __attribute__((packed));
void install_idt(void);
void idt_set_gate(struct idt_entry*, unsigned long, unsigned short, unsigned char);
void load_idt(struct idt_ptr*);
#endif
+46
View File
@@ -0,0 +1,46 @@
#ifndef INTERRUPT_HANDLER_H
#define INTERRUPT_HANDLER_H
struct isr_state
{
unsigned int gs, fs, es, ds; // The segement registers pushed last
unsigned int edi, esi, edp, esp, ebx, eax; // Pushed by pusha
unsigned int int_no, error; // Data pushed by the 'isr#' routines.
unsigned int eip, cs, eflags, useresp, ss; // Pushed by the processor
};
void interrupt_handler(struct isr_state);
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
#endif
+11
View File
@@ -0,0 +1,11 @@
#ifndef LOADER_H
#define LOADER_H
struct multiboot_header
{
unsigned long magic;
unsigned long flags;
unsigned long checksum;
};
#endif
+1
View File
@@ -20,4 +20,5 @@
void set_serial_baud_rate(unsigned short, unsigned short);
void configure_serial_line(unsigned short);
int serial_transmit_fifo_empty(unsigned int);
void write_to_com(unsigned int, char*);
#endif
+2 -3
View File
@@ -1,6 +1,7 @@
#include "../includes/gdt.h"
/* Code taken from http://www.osdever.net/bkerndev/Docs/gdt.htm with some minor tweaks. */
struct gdt_entry gdt_entries[3];
struct gdt gdt_ptr;
/* Should be called by main. This will setup the special GDT
* pointer, set up the first 3 entries in our GDT, and then
* finally call load_gdt() in our assembler file in order
@@ -8,8 +9,6 @@
* new segment registers */
void gdt_install()
{
struct gdt_entry gdt_entries[3];
struct gdt gdt_ptr;
/* Setup the GDT pointer and the size of the table */
gdt_ptr.size = sizeof(struct gdt_entry) * 3 - 1;
gdt_ptr.address = (unsigned int) &gdt_entries;
+56
View File
@@ -0,0 +1,56 @@
#include "../includes/idt.h"
#include "../includes/interrupt_handler.h"
struct idt_entry idt_entries[256];
struct idt_ptr idt;
void idt_install()
{
idt.size = (sizeof (struct idt_entry) * 256) - 1;
idt.idt_entries_start = (struct idt_entry *) &idt_entries;
idt_set_gate(&idt_entries[0], (unsigned int) isr0, 0x08, 0x8E);
idt_set_gate(&idt_entries[1], (unsigned int) isr1, 0x08, 0x8E);
idt_set_gate(&idt_entries[2], (unsigned int) isr2, 0x08, 0x8E);
idt_set_gate(&idt_entries[3], (unsigned int) isr3, 0x08, 0x8E);
idt_set_gate(&idt_entries[4], (unsigned int) isr4, 0x08, 0x8E);
idt_set_gate(&idt_entries[5], (unsigned int) isr5, 0x08, 0x8E);
idt_set_gate(&idt_entries[6], (unsigned int) isr6, 0x08, 0x8E);
idt_set_gate(&idt_entries[7], (unsigned int) isr7, 0x08, 0x8E);
idt_set_gate(&idt_entries[8], (unsigned int) isr8, 0x08, 0x8E);
idt_set_gate(&idt_entries[9], (unsigned int) isr9, 0x08, 0x8E);
idt_set_gate(&idt_entries[10], (unsigned int) isr10, 0x08, 0x8E);
idt_set_gate(&idt_entries[11], (unsigned int) isr11, 0x08, 0x8E);
idt_set_gate(&idt_entries[12], (unsigned int) isr12, 0x08, 0x8E);
idt_set_gate(&idt_entries[13], (unsigned int) isr13, 0x08, 0x8E);
idt_set_gate(&idt_entries[14], (unsigned int) isr14, 0x08, 0x8E);
idt_set_gate(&idt_entries[15], (unsigned int) isr15, 0x08, 0x8E);
idt_set_gate(&idt_entries[16], (unsigned int) isr16, 0x08, 0x8E);
idt_set_gate(&idt_entries[17], (unsigned int) isr17, 0x08, 0x8E);
idt_set_gate(&idt_entries[18], (unsigned int) isr18, 0x08, 0x8E);
idt_set_gate(&idt_entries[19], (unsigned int) isr19, 0x08, 0x8E);
idt_set_gate(&idt_entries[20], (unsigned int) isr20, 0x08, 0x8E);
idt_set_gate(&idt_entries[21], (unsigned int) isr21, 0x08, 0x8E);
idt_set_gate(&idt_entries[22], (unsigned int) isr22, 0x08, 0x8E);
idt_set_gate(&idt_entries[23], (unsigned int) isr23, 0x08, 0x8E);
idt_set_gate(&idt_entries[24], (unsigned int) isr24, 0x08, 0x8E);
idt_set_gate(&idt_entries[25], (unsigned int) isr25, 0x08, 0x8E);
idt_set_gate(&idt_entries[26], (unsigned int) isr26, 0x08, 0x8E);
idt_set_gate(&idt_entries[27], (unsigned int) isr27, 0x08, 0x8E);
idt_set_gate(&idt_entries[28], (unsigned int) isr28, 0x08, 0x8E);
idt_set_gate(&idt_entries[29], (unsigned int) isr29, 0x08, 0x8E);
idt_set_gate(&idt_entries[30], (unsigned int) isr30, 0x08, 0x8E);
idt_set_gate(&idt_entries[31], (unsigned int) isr31, 0x08, 0x8E);
//asm("xchg %bx, %bx");
load_idt(&idt);
}
void idt_set_gate(struct idt_entry* entry, unsigned long base, unsigned short sel, unsigned char flags)
{
entry->base_lo = (base & 0xFFFF);
entry->base_hi = (base >> 16) & 0xFFFF;
entry->sel = sel;
entry->always0 = 0;
entry->flags = flags;
}
+7
View File
@@ -0,0 +1,7 @@
#include "../includes/interrupt_handler.h"
#include "../includes/serial.h"
void interrupt_handler(struct isr_state stack)
{
write_to_com(COM1_PORT, "Interrupt detected!\n");
}
+277
View File
@@ -0,0 +1,277 @@
global isr0 ; division by zero
global isr1 ; debug exception
global isr2 ; Non-maskable interrupt
global isr3 ; Breakpoint exception
global isr4 ; Into detected overflow exception
global isr5 ; Out of bounds exception
global isr6 ; Invalid opcode exception
global isr7 ; No co-processor exception
global isr8 ; Double fault exception
global isr9 ; Co-processor segment overrun exception
global isr10 ; Bad TSS exception
global isr11 ; Segment not present
global isr12 ; Stack fault exception
global isr13 ; General protection fault
global isr14 ; Page fault exception
global isr15 ; Unkown interrupt exception
global isr16 ; Co-processor fault exception
global isr17 ; Alignment check exception
global isr18 ; Machine check exception
global isr19 ; Reserved
global isr20
global isr21
global isr22
global isr23
global isr24
global isr25
global isr26
global isr27
global isr28
global isr29
global isr30
global isr31 ; reserved
isr0: ; division by zero
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 0 ; Push the interrupt number to the stack
jmp isr_common_stub
isr1: ; debug exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 1 ; Push the interrupt number to the stack
jmp isr_common_stub
isr2: ; Non-maskable interrupt
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 2 ; Push the interrupt number to the stack
jmp isr_common_stub
isr3: ; Breakpoint exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 3 ; Push the interrupt number to the stack
jmp isr_common_stub
isr4: ; Into detected overflow exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 4 ; Push the interrupt number to the stack
jmp isr_common_stub
isr5: ; Out of bounds exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 5 ; Push the interrupt number to the stack
jmp isr_common_stub
isr6: ; Invalid opcode exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 6 ; Push the interrupt number to the stack
jmp isr_common_stub
isr7: ; No co-processor exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 7 ; Push the interrupt number to the stack
jmp isr_common_stub
isr8: ; Double fault exception
cli
; This interrupt pushes an error code, so we only need to push its number.
push byte 8 ; Push the interrupt number to the stack
jmp isr_common_stub
isr9: ; Co-processor segment overrun exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 9 ; Push the interrupt number to the stack
jmp isr_common_stub
isr10: ; Bad TSS exception
cli
; This interrupt pushes an error code, so we only need to push its number.
push byte 10 ; Push the interrupt number to the stack
jmp isr_common_stub
isr11: ; Segment not present
cli
; This interrupt pushes an error code, so we only need to push its number.
push byte 11 ; Push the interrupt number to the stack
jmp isr_common_stub
isr12: ; Stack fault exception
cli
; This interrupt pushes an error code, so we only need to push its number.
push byte 12 ; Push the interrupt number to the stack
jmp isr_common_stub
isr13: ; General protection fault
cli
; This interrupt pushes an error code, so we only need to push its number.
push byte 13 ; Push the interrupt number to the stack
jmp isr_common_stub
isr14: ; Page fault exception
cli
; This interrupt pushes an error code, so we only need to push its number.
push byte 14 ; Push the interrupt number to the stack
jmp isr_common_stub
isr15: ; Unkown interrupt exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 15 ; Push the interrupt number to the stack
jmp isr_common_stub
isr16: ; Co-processor fault exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 16 ; Push the interrupt number to the stack
jmp isr_common_stub
isr17: ; Alignment check exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 17 ; Push the interrupt number to the stack
jmp isr_common_stub
isr18: ; Machine check exception
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 18 ; Push the interrupt number to the stack
jmp isr_common_stub
isr19: ; Reserved
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 19 ; Push the interrupt number to the stack
jmp isr_common_stub
isr20:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 20 ; Push the interrupt number to the stack
jmp isr_common_stub
isr21:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 21 ; Push the interrupt number to the stack
jmp isr_common_stub
isr22:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 22 ; Push the interrupt number to the stack
jmp isr_common_stub
isr23:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 23 ; Push the interrupt number to the stack
jmp isr_common_stub
isr24:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 24 ; Push the interrupt number to the stack
jmp isr_common_stub
isr25:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 25 ; Push the interrupt number to the stack
jmp isr_common_stub
isr26:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 26 ; Push the interrupt number to the stack
jmp isr_common_stub
isr27:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 27 ; Push the interrupt number to the stack
jmp isr_common_stub
isr28:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 28 ; Push the interrupt number to the stack
jmp isr_common_stub
isr29:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 29 ; Push the interrupt number to the stack
jmp isr_common_stub
isr30:
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 30 ; Push the interrupt number to the stack
jmp isr_common_stub
isr31: ; reserved
cli
push byte 0 ; This doesn't produce an error code, so push a dummy code
; to the stack. This keeps the stack uniform when calling the common interrupt stub.
push byte 31 ; Push the interrupt number to the stack
jmp isr_common_stub
extern interrupt_handler
isr_common_stub:
pusha ; Registers are pushed in this order: AX, CX, DX, BX, SP, BP, SI, DI
push ds
push es
push fs
push gs
mov ax, 0x10 ; Load the Kernel Data Segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp ; Push the stack pointer
push eax
mov eax, interrupt_handler
call eax ; A special call, preserves the 'eip' register
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP!
+10
View File
@@ -38,3 +38,13 @@ load_gdt:
return:
ret ; Now we've changed CS to 0x08
global load_idt
; load_idt - Installs the IDT
; stack: [esp + 4] The address of the IDT
; [esp ] The return address
load_idt:
mov eax, [esp + 4]
lidt [eax]
ret
+13 -3
View File
@@ -1,7 +1,11 @@
#include "../includes/io.h"
#include "../includes/gdt.h"
#include "../includes/idt.h"
#include "../includes/serial.h"
#include "../includes/screen.h"
#include "../includes/loader.h"
struct multiboot_header header __attribute((section(".multiboot"))) = (struct multiboot_header) {.magic = 0x1BADB002, .flags = 0x1, .checksum = -464367619};
void kmain()
{
@@ -39,9 +43,15 @@ void kmain()
draw_string("Installing GDT...\n", 0xF, 0x0);
write_to_com(COM1_PORT, "Installing the GDT.\n");
gdt_install();
move_cursor(0, 4);
write_to_com(COM1_PORT, "GDT installed.\n");
draw_string("Installed GDT\n", 0xf, 0x0);
//move_cursor(0, 4);
//asm("xchg %bx, %bx");
//write_to_com(COM1_PORT, "GDT installed.\n");
//asm("xchg %bx, %bx"); // Boch's break point
//draw_string("Installed GDT\n", 0xf, 0x0);
//asm("xchg %bx, %bx");
idt_install();
write_to_com(COM1_PORT, "IDT installed.\n");
int i = 5 / 0;
asm("hlt");
}
+2 -10
View File
@@ -1,16 +1,8 @@
global loader
align 4
MAGIC_NUMBER equ 0x1BADB002
FLAGS equ 0x0
CHECKSUM equ -MAGIC_NUMBER
KERNEL_STACK_SIZE equ 4096 ; size of stack in bytes
dd MAGIC_NUMBER
dd FLAGS
dd CHECKSUM
align 8
loader:
KERNEL_STACK_SIZE equ 8192
mov esp, kernel_stack; + KERNEL_STACK_SIZE ; ont ESP to the start of the stack (end of memory area)
extern kmain
call kmain
+1 -1
View File
@@ -1,5 +1,4 @@
megs: 32
display_library: x, options = "gui_debug"
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
ata0-master: type=cdrom, path=kernel.iso, status=inserted
@@ -8,3 +7,4 @@ log: bochs.log
clock: sync=realtime, time0=local
cpu: count=1, ips=1000000
com1: enabled=1, mode=file, dev=com1.out
magic_break: enabled=1
+1
View File
@@ -5,6 +5,7 @@ SECTIONS {
.text ALIGN (0x1000) :
{
KEEP(*(.multiboot))
*(.text)
}