Quick commit, haven't done anything in a while
This commit is contained in:
parent
fc95fb5ff6
commit
c8ce4a2de0
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1 @@
|
||||||
/build
|
bochsout.txt
|
||||||
|
|
13
Makefile
13
Makefile
|
@ -21,11 +21,13 @@ $(ASFLAGS)
|
||||||
KERNEL_OBJS=\
|
KERNEL_OBJS=\
|
||||||
kernel/kernel.o \
|
kernel/kernel.o \
|
||||||
kernel/debugging.o \
|
kernel/debugging.o \
|
||||||
|
kernel/elf.o \
|
||||||
|
|
||||||
LIB_OBJS=\
|
LIB_OBJS=\
|
||||||
$(ARCHDIR)/bootstrap.o \
|
$(ARCHDIR)/bootstrap.o \
|
||||||
$(ARCHDIR)/tty.o \
|
$(ARCHDIR)/tty.o \
|
||||||
$(ARCHDIR)/strlib.o \
|
$(ARCHDIR)/strlib.o \
|
||||||
|
$(ARCHDIR)/idt.o \
|
||||||
$(ARCHDIR)/interrupt.o \
|
$(ARCHDIR)/interrupt.o \
|
||||||
$(ARCHDIR)/gdt.o \
|
$(ARCHDIR)/gdt.o \
|
||||||
|
|
||||||
|
@ -48,10 +50,13 @@ clean:
|
||||||
rm -f myos.iso
|
rm -f myos.iso
|
||||||
rm -f isodir/boot/myos.kernel
|
rm -f isodir/boot/myos.kernel
|
||||||
|
|
||||||
.c.o:
|
$(ARCHDIR)/interrupt.o: CFLAGS += -mgeneral-regs-only
|
||||||
|
kernel/elf.o: CFLAGS += -masm=intel
|
||||||
|
|
||||||
|
%.o : %.c
|
||||||
i686-elf-gcc -c $< -o $@ $(CFLAGS)
|
i686-elf-gcc -c $< -o $@ $(CFLAGS)
|
||||||
|
|
||||||
.s.o:
|
%.o : %.s
|
||||||
i686-elf-as $< -o $@ $(ASFLAGS)
|
i686-elf-as $< -o $@ $(ASFLAGS)
|
||||||
|
|
||||||
myos.kernel: $(OBJS)
|
myos.kernel: $(OBJS)
|
||||||
|
@ -67,7 +72,7 @@ debug: ASFLAGS += -g
|
||||||
debug: all
|
debug: all
|
||||||
|
|
||||||
run: myos.iso
|
run: myos.iso
|
||||||
qemu-system-i386 myos.iso -display curses
|
qemu-system-i386 myos.iso
|
||||||
|
|
||||||
run-debug: debug
|
run-debug: debug
|
||||||
qemu-system-i386 -S -gdb tcp::9000 myos.iso -display curses
|
qemu-system-i386 -S -gdb tcp::9000 myos.iso
|
||||||
|
|
|
@ -30,6 +30,7 @@ System V ABI standard and de-facto extensions. The compiler will assume the
|
||||||
stack is properly aligned and failure to align the stack will result in
|
stack is properly aligned and failure to align the stack will result in
|
||||||
undefined behavior.
|
undefined behavior.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.section .bss
|
.section .bss
|
||||||
.align 16
|
.align 16
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
|
@ -69,12 +70,12 @@ _start:
|
||||||
|
|
||||||
call gdt_init
|
call gdt_init
|
||||||
|
|
||||||
movw %ax, 0x10
|
movw 0x10, %ax
|
||||||
movw %ds, %ax
|
movw %ax, %ds
|
||||||
movw %es, %ax
|
movw %ax, %es
|
||||||
movw %fs, %ax
|
movw %ax, %fs
|
||||||
movw %gs, %ax
|
movw %ax, %gs
|
||||||
movw %ss, %ax
|
movw %ax, %ss
|
||||||
# jmp kernel
|
# jmp kernel
|
||||||
ljmp $0x08, $kernel
|
ljmp $0x08, $kernel
|
||||||
|
|
||||||
|
@ -99,8 +100,6 @@ kernel:
|
||||||
preserved and the call is well defined.
|
preserved and the call is well defined.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mov %esp, %edx
|
|
||||||
|
|
||||||
call kernel_main
|
call kernel_main
|
||||||
|
|
||||||
.global keyboard_test
|
.global keyboard_test
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define NUM_ENTRIES 3
|
#define NUM_ENTRIES 6
|
||||||
|
|
||||||
struct SegmentDescriptor {
|
struct SegmentDescriptor {
|
||||||
uint32_t limit;
|
uint32_t limit;
|
||||||
|
@ -17,6 +17,39 @@ struct GDT {
|
||||||
uint64_t* base;
|
uint64_t* base;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct tss_entry_struct {
|
||||||
|
uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list.
|
||||||
|
uint32_t esp0; // The stack pointer to load when changing to kernel mode.
|
||||||
|
uint32_t ss0; // The stack segment to load when changing to kernel mode.
|
||||||
|
// Everything below here is unused.
|
||||||
|
uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2.
|
||||||
|
uint32_t ss1;
|
||||||
|
uint32_t esp2;
|
||||||
|
uint32_t ss2;
|
||||||
|
uint32_t cr3;
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t eax;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t es;
|
||||||
|
uint32_t cs;
|
||||||
|
uint32_t ss;
|
||||||
|
uint32_t ds;
|
||||||
|
uint32_t fs;
|
||||||
|
uint32_t gs;
|
||||||
|
uint32_t ldt;
|
||||||
|
uint16_t trap;
|
||||||
|
uint16_t iomap_base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct tss_entry_struct tss;
|
||||||
|
|
||||||
static uint64_t entries[NUM_ENTRIES];
|
static uint64_t entries[NUM_ENTRIES];
|
||||||
static size_t current_entry = 0;
|
static size_t current_entry = 0;
|
||||||
struct GDT gdt;
|
struct GDT gdt;
|
||||||
|
@ -71,16 +104,13 @@ static void load_gdt()
|
||||||
gdt.size = NUM_ENTRIES * 8 - 1;
|
gdt.size = NUM_ENTRIES * 8 - 1;
|
||||||
gdt.base = entries;
|
gdt.base = entries;
|
||||||
|
|
||||||
for (int i = 0; i < NUM_ENTRIES; i++) {
|
|
||||||
print_hex_bytes(gdt.base + i, 8);
|
|
||||||
terminal_putchar('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
asm ( "lgdt %0" : : "m"(gdt) );
|
asm ( "lgdt %0" : : "m"(gdt) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdt_init()
|
void gdt_init()
|
||||||
{
|
{
|
||||||
|
// https://wiki.osdev.org/Global_Descriptor_Table
|
||||||
|
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
struct SegmentDescriptor null;
|
struct SegmentDescriptor null;
|
||||||
null.limit = 0;
|
null.limit = 0;
|
||||||
|
@ -106,15 +136,47 @@ void gdt_init()
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
struct SegmentDescriptor kernel_data;
|
struct SegmentDescriptor kernel_data;
|
||||||
kernel_code.limit = 0x000003FF;
|
kernel_data.limit = 0x000003FF;
|
||||||
kernel_data.base = 0x00400000;
|
kernel_data.base = 0x00400000;
|
||||||
kernel_data.access_byte = 0b10010010;
|
kernel_data.access_byte = 0b10010010;
|
||||||
kernel_data.flags = 0b1100;
|
kernel_data.flags = 0b1100;
|
||||||
|
|
||||||
terminal_writestring("Kernel Data: ");
|
terminal_writestring("Kernel Data: ");
|
||||||
|
|
||||||
add_entry(kernel_data);
|
add_entry(kernel_data);
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
|
struct SegmentDescriptor user_code;
|
||||||
|
user_code.limit = 0x000003FF;
|
||||||
|
user_code.base = 0x00800000;
|
||||||
|
user_code.access_byte = 0b11111010;
|
||||||
|
user_code.flags = 0b1100;
|
||||||
|
|
||||||
|
terminal_writestring("User Code: ");
|
||||||
|
|
||||||
|
add_entry(user_code);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
|
||||||
|
struct SegmentDescriptor user_data;
|
||||||
|
user_data.limit = 0x000FFFFF;
|
||||||
|
user_data.base = 0x00c00000;
|
||||||
|
user_data.access_byte = 0b11110010;
|
||||||
|
user_data.flags = 0b1100;
|
||||||
|
|
||||||
|
terminal_writestring("User Data: ");
|
||||||
|
|
||||||
|
add_entry(user_data);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
|
||||||
|
struct SegmentDescriptor tss_segment;
|
||||||
|
tss_segment.limit = sizeof(tss_segment) - 1;
|
||||||
|
tss_segment.base = (uint32_t) &tss;
|
||||||
|
tss_segment.access_byte = 0x89;
|
||||||
|
tss_segment.flags = 0b0000;
|
||||||
|
|
||||||
|
terminal_writestring("TSS Segment: ");
|
||||||
|
|
||||||
|
add_entry(tss_segment);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
|
||||||
load_gdt();
|
load_gdt();
|
||||||
}
|
}
|
||||||
|
|
165
arch/i686/idt.c
Normal file
165
arch/i686/idt.c
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
#include <kernel/tty.h>
|
||||||
|
#include <kernel/gdt.h>
|
||||||
|
#include <debugging.h>
|
||||||
|
#include "interrupt.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define NUM_ENTRIES 0x100
|
||||||
|
|
||||||
|
struct InterruptDescriptor {
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t selector;
|
||||||
|
uint8_t gate_type;
|
||||||
|
uint8_t ring;
|
||||||
|
bool present;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IDT {
|
||||||
|
uint16_t size;
|
||||||
|
uint64_t* base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static uint64_t entries[NUM_ENTRIES];
|
||||||
|
struct IDT idt;
|
||||||
|
|
||||||
|
enum EntryTypes {
|
||||||
|
DivisionByZero = 0x00,
|
||||||
|
_Reserved0 = 0x01,
|
||||||
|
NMIInterrupt = 0x02,
|
||||||
|
Breakpoint = 0x03,
|
||||||
|
Overflow = 0x04,
|
||||||
|
BoundsExceeded = 0x05,
|
||||||
|
InvalidOpcode = 0x06,
|
||||||
|
DeviceNotAvail = 0x07,
|
||||||
|
DoubleFault = 0x08,
|
||||||
|
CoprocSegORun = 0x09,
|
||||||
|
InvalidTSS = 0x0A,
|
||||||
|
SegNotPresent = 0x0B,
|
||||||
|
StackSegFault = 0x0C,
|
||||||
|
GenerProtFault = 0x0D,
|
||||||
|
PageFault = 0x0E,
|
||||||
|
_Reserved1 = 0x0F,
|
||||||
|
x87FPUError = 0x10,
|
||||||
|
AlignmentCheck = 0x11,
|
||||||
|
MachineCheck = 0x12,
|
||||||
|
SIMDFloatExcep = 0x13,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void encodeIdtEntry(uint8_t *target, struct InterruptDescriptor source)
|
||||||
|
{
|
||||||
|
// Encode the present bit
|
||||||
|
if (source.present) {
|
||||||
|
target[5] |= 0x80;
|
||||||
|
} else {
|
||||||
|
// Not present, return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode the offset
|
||||||
|
target[0] = (source.offset >> 0x00) & 0xFF;
|
||||||
|
target[1] = (source.offset >> 0x08) & 0xFF;
|
||||||
|
target[6] = (source.offset >> 0x10) & 0xFF;
|
||||||
|
target[7] = (source.offset >> 0x18) & 0xFF;
|
||||||
|
|
||||||
|
// Encode the base
|
||||||
|
target[2] = (source.selector >> 0x00) & 0xFF;
|
||||||
|
target[3] = (source.selector >> 0x08) & 0xFF;
|
||||||
|
|
||||||
|
// Encode the gate type
|
||||||
|
target[5] |= source.gate_type;
|
||||||
|
|
||||||
|
// Encode the DPL
|
||||||
|
target[5] |= (source.ring << 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_entry(struct InterruptDescriptor entry, uint8_t index)
|
||||||
|
{
|
||||||
|
uint64_t descriptor = 0;
|
||||||
|
encodeIdtEntry((uint8_t*) &descriptor, entry);
|
||||||
|
|
||||||
|
entries[index] = descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_idt()
|
||||||
|
{
|
||||||
|
idt.size = NUM_ENTRIES * 8 - 1;
|
||||||
|
idt.base = entries;
|
||||||
|
|
||||||
|
asm ( "lidt %0" : : "m"(idt) );
|
||||||
|
asm ( "sti" );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InterruptDescriptor generate_entry(bool present, void isr(struct interrupt_frame*), uint8_t gate_type, uint8_t ring, uint8_t selector)
|
||||||
|
{
|
||||||
|
struct InterruptDescriptor entry;
|
||||||
|
entry.present = present;
|
||||||
|
entry.offset = (uint32_t)isr;
|
||||||
|
entry.gate_type = gate_type;
|
||||||
|
entry.ring = ring;
|
||||||
|
entry.selector = selector;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void outb(uint16_t port, uint8_t val)
|
||||||
|
{
|
||||||
|
__asm__ volatile ( "outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
|
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
|
||||||
|
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
|
||||||
|
* The outb %al, %dx encoding is the only option for all other cases.
|
||||||
|
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_init()
|
||||||
|
{
|
||||||
|
outb(0x21,0xfd);
|
||||||
|
outb(0xa1,0xff);
|
||||||
|
|
||||||
|
struct InterruptDescriptor entry;
|
||||||
|
|
||||||
|
entry = generate_entry(true, exception, 0xF, 0, 0x8);
|
||||||
|
for (int i = 0; i < 0x20; i++)
|
||||||
|
{
|
||||||
|
add_entry(entry, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = generate_entry(true, irq, 0xF, 0, 0x8);
|
||||||
|
for (int i = 0x20; i < 0x28; i++)
|
||||||
|
{
|
||||||
|
add_entry(entry, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = generate_entry(true, divide_by_zero, 0xF, 0, 0x8);
|
||||||
|
add_entry(entry, DivisionByZero);
|
||||||
|
|
||||||
|
entry = generate_entry(true, general_protection_fault, 0xF, 0, 0x8);
|
||||||
|
add_entry(entry, GenerProtFault);
|
||||||
|
|
||||||
|
entry = generate_entry(true, double_fault, 0xF, 0, 0x8);
|
||||||
|
add_entry(entry, DoubleFault);
|
||||||
|
|
||||||
|
struct InterruptDescriptor print_entry;
|
||||||
|
print_entry.present = true;
|
||||||
|
print_entry.offset = (uint32_t)print;
|
||||||
|
print_entry.gate_type = 0xE;
|
||||||
|
print_entry.ring = 3;
|
||||||
|
print_entry.selector = 0x8;
|
||||||
|
|
||||||
|
add_entry(print_entry, 0x80);
|
||||||
|
|
||||||
|
struct InterruptDescriptor input_entry;
|
||||||
|
input_entry.present = true;
|
||||||
|
input_entry.offset = (uint32_t)input;
|
||||||
|
input_entry.gate_type = 0xE;
|
||||||
|
input_entry.ring = 0;
|
||||||
|
input_entry.selector = 0x8;
|
||||||
|
|
||||||
|
add_entry(input_entry, 0x81);
|
||||||
|
|
||||||
|
load_idt();
|
||||||
|
|
||||||
|
tss.ss0 = 0x10;
|
||||||
|
asm("mov %%esp, %0" : "=r" (tss.esp0));
|
||||||
|
asm("mov $0x28, %ax");
|
||||||
|
asm("ltr %ax");
|
||||||
|
}
|
|
@ -1,88 +1,114 @@
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
#include <debugging.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <debugging.h>
|
||||||
|
|
||||||
#define NUM_ENTRIES 0
|
struct interrupt_frame {
|
||||||
|
uint32_t eflags;
|
||||||
struct InterruptDescriptor {
|
uint32_t cs;
|
||||||
uint32_t offset;
|
uint32_t eip;
|
||||||
uint32_t selector;
|
|
||||||
uint8_t gate_type;
|
|
||||||
uint8_t ring;
|
|
||||||
bool present;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IDT {
|
uint8_t test = 'a';
|
||||||
uint16_t size;
|
|
||||||
uint64_t* base;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
static uint64_t entries[NUM_ENTRIES];
|
static void stack_trace()
|
||||||
static size_t current_entry = 0;
|
|
||||||
struct IDT idt;
|
|
||||||
|
|
||||||
static void encodeIdtEntry(uint8_t *target, struct InterruptDescriptor source)
|
|
||||||
{
|
{
|
||||||
// Encode the present bit
|
uint32_t* stack = 0;
|
||||||
if (source.present) {
|
asm("mov %%esp, %0" : "=r" (stack));
|
||||||
target[5] |= 0xF0;
|
for (int i = 0; i < 25; i++) {
|
||||||
} else {
|
uint32_t* current_address = stack + (i * 4);
|
||||||
// Not present, return
|
print_hex_bytes(¤t_address, 4);
|
||||||
return;
|
terminal_writestring(": ");
|
||||||
}
|
print_hex_bytes(current_address, 4);
|
||||||
|
|
||||||
// Encode the offset
|
|
||||||
target[0] = (source.offset >> 0x00) & 0xFF;
|
|
||||||
target[1] = (source.offset >> 0x08) & 0xFF;
|
|
||||||
target[6] = (source.offset >> 0x10) & 0xFF;
|
|
||||||
target[7] = (source.offset >> 0x18) & 0xFF;
|
|
||||||
|
|
||||||
// Encode the base
|
|
||||||
target[2] = (source.selector >> 0x00) & 0xFF;
|
|
||||||
target[3] = (source.selector >> 0x08) & 0xFF;
|
|
||||||
|
|
||||||
// Encode the gate type
|
|
||||||
target[5] |= source.gate_type;
|
|
||||||
|
|
||||||
// Encode the DPL
|
|
||||||
target[5] |= (source.ring >> 5);
|
|
||||||
|
|
||||||
print_hex_bytes(target, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_entry(struct InterruptDescriptor entry)
|
|
||||||
{
|
|
||||||
if (current_entry == NUM_ENTRIES) {
|
|
||||||
terminal_writestring("WARNING: More IDT entries than NUM_ENTRIES.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t descriptor = 0;
|
|
||||||
encodeIdtEntry((uint8_t*) &descriptor, entry);
|
|
||||||
|
|
||||||
entries[current_entry] = descriptor;
|
|
||||||
|
|
||||||
current_entry++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_idt()
|
|
||||||
{
|
|
||||||
idt.size = NUM_ENTRIES * 8 - 1;
|
|
||||||
idt.base = entries;
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_ENTRIES; i++) {
|
|
||||||
print_hex_bytes(idt.base + i, 8);
|
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
asm ( "lidt %0" : : "m"(idt) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_init()
|
__attribute__((interrupt)) void divide_by_zero(struct interrupt_frame* frame)
|
||||||
{
|
{
|
||||||
terminal_writestring("TODO: Add interrupts");
|
terminal_initialize();
|
||||||
terminal_putchar('\n');
|
stack_trace();
|
||||||
|
terminal_writestring("Yo dude u cant divide by zero yao\n");
|
||||||
// load_idt();
|
while (1) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void general_protection_fault(struct interrupt_frame* frame)
|
||||||
|
{
|
||||||
|
/* terminal_initialize();
|
||||||
|
stack_trace();
|
||||||
|
terminal_writestring("General protection fault\n");
|
||||||
|
terminal_writestring("Error code:\n");
|
||||||
|
print_hex_bytes(frame, sizeof(frame));
|
||||||
|
terminal_putchar('\n'); */
|
||||||
|
while (1) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void double_fault(struct interrupt_frame* frame)
|
||||||
|
{
|
||||||
|
// terminal_writestring("2 Errors in a row, u better behave naughty naughty\n");
|
||||||
|
// while (1) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void exception(struct interrupt_frame* frame)
|
||||||
|
{
|
||||||
|
/* terminal_initialize();
|
||||||
|
stack_trace();
|
||||||
|
terminal_writestring("Some weird error code stuff\n");
|
||||||
|
terminal_writestring("Error code:\n");
|
||||||
|
print_hex_bytes(frame, sizeof(frame));
|
||||||
|
terminal_putchar('\n'); */
|
||||||
|
while (1) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void print(struct interrupt_frame* frame)
|
||||||
|
{
|
||||||
|
/* terminal_initialize();
|
||||||
|
terminal_putchar(test);
|
||||||
|
test++; */
|
||||||
|
|
||||||
|
char* start;
|
||||||
|
asm("mov %%edx, %0" : "=r" (start));
|
||||||
|
terminal_writestring(start);
|
||||||
|
|
||||||
|
/* uint8_t* stack;
|
||||||
|
asm("mov %%esp, %0" : "=r" (stack));
|
||||||
|
|
||||||
|
terminal_writestring("\nSTACK:\n");
|
||||||
|
print_hex_bytes(stack - 24, 4);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
print_hex_bytes(stack - 20, 4);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
print_hex_bytes(stack - 16, 4);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
print_hex_bytes(stack - 12, 4);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
print_hex_bytes(stack - 8, 4);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
print_hex_bytes(stack - 4, 4);
|
||||||
|
terminal_putchar('\n'); */
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void input(struct interrupt_frame* frame)
|
||||||
|
{
|
||||||
|
char* buffer;
|
||||||
|
asm("mov %%edx, %0" : "=r" (buffer));
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
char current_character = get_last_key_pressed();
|
||||||
|
while (current_character != '\n') {
|
||||||
|
char tmp = get_last_key_pressed();
|
||||||
|
if (current_character != -1 && tmp != current_character) {
|
||||||
|
buffer[index] = current_character;
|
||||||
|
terminal_putchar(current_character);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
current_character = tmp;
|
||||||
|
}
|
||||||
|
buffer[index] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void irq(struct interrupt_frame* frame)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
12
arch/i686/interrupt.h
Normal file
12
arch/i686/interrupt.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
struct interrupt_frame;
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void divide_by_zero(struct interrupt_frame* frame);
|
||||||
|
__attribute__((interrupt)) void general_protection_fault(struct interrupt_frame* frame);
|
||||||
|
__attribute__((interrupt)) void double_fault(struct interrupt_frame* frame);
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void exception(struct interrupt_frame* frame);
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void print(struct interrupt_frame* frame);
|
||||||
|
__attribute__((interrupt)) void input(struct interrupt_frame* frame);
|
||||||
|
|
||||||
|
__attribute__((interrupt)) void irq(struct interrupt_frame* frame);
|
4
bochsrc.txt
Normal file
4
bochsrc.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
megs: 32
|
||||||
|
log: ./bochsout.txt
|
||||||
|
ata0-master: type=disk, path="myos.iso",
|
||||||
|
boot: disk
|
5
include/kernel/elf.h
Normal file
5
include/kernel/elf.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void run_program(uint8_t* program, size_t length);
|
||||||
|
|
34
include/kernel/gdt.h
Normal file
34
include/kernel/gdt.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct tss_entry_struct {
|
||||||
|
uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list.
|
||||||
|
uint32_t esp0; // The stack pointer to load when changing to kernel mode.
|
||||||
|
uint32_t ss0; // The stack segment to load when changing to kernel mode.
|
||||||
|
// Everything below here is unused.
|
||||||
|
uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2.
|
||||||
|
uint32_t ss1;
|
||||||
|
uint32_t esp2;
|
||||||
|
uint32_t ss2;
|
||||||
|
uint32_t cr3;
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t eax;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t es;
|
||||||
|
uint32_t cs;
|
||||||
|
uint32_t ss;
|
||||||
|
uint32_t ds;
|
||||||
|
uint32_t fs;
|
||||||
|
uint32_t gs;
|
||||||
|
uint32_t ldt;
|
||||||
|
uint16_t trap;
|
||||||
|
uint16_t iomap_base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
extern struct tss_entry_struct tss;
|
45
kernel/elf.c
Normal file
45
kernel/elf.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <debugging.h>
|
||||||
|
#include <kernel/tty.h>
|
||||||
|
#include <kernel/gdt.h>
|
||||||
|
|
||||||
|
void run_program(uint8_t* program, size_t length)
|
||||||
|
{
|
||||||
|
uint8_t* userland_code = (uint8_t*) 0x00800004;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < length; i++) {
|
||||||
|
userland_code[i] = program[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
tss.ss0 = 0x10;
|
||||||
|
|
||||||
|
asm("sti");
|
||||||
|
asm("int 0x80");
|
||||||
|
|
||||||
|
asm("mov %0, esp" : "=r" (tss.esp0));
|
||||||
|
|
||||||
|
// Generates segfault
|
||||||
|
// asm("mov esp, %0" : "=r" (tss.esp0));
|
||||||
|
|
||||||
|
asm("mov ax, 0x23 # Load registers with the correct GDT segments values");
|
||||||
|
asm("mov ds, ax");
|
||||||
|
asm("mov es, ax");
|
||||||
|
asm("mov fs, ax");
|
||||||
|
asm("mov gs, ax");
|
||||||
|
|
||||||
|
asm("push 0x23");
|
||||||
|
asm("push 0x00c00100");
|
||||||
|
|
||||||
|
asm("pushfd");
|
||||||
|
asm("pop eax");
|
||||||
|
asm("or eax, 0x200");
|
||||||
|
asm("push eax");
|
||||||
|
|
||||||
|
asm("push 0x1b");
|
||||||
|
asm("push 0x00800000");
|
||||||
|
|
||||||
|
asm("iret");
|
||||||
|
|
||||||
|
asm("int 0x21");
|
||||||
|
}
|
3
kernel/heap.c
Normal file
3
kernel/heap.c
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint8_t heap[2000];
|
|
@ -1,28 +1,58 @@
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
#include <kernel/interrupt.h>
|
#include <kernel/idt.h>
|
||||||
#include <debugging.h>
|
#include <debugging.h>
|
||||||
|
#include <kernel/elf.h>
|
||||||
|
|
||||||
/* Check if the compiler thinks you are targeting the wrong operating system. */
|
/* Check if the compiler thinks you are targeting the wrong operating system. */
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#error "You are not using a cross-compiler, you will most certainly run into trouble"
|
#error "You are not using a cross-compiler, you will most certainly run into trouble"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint8_t program[] = {
|
||||||
|
/* 0xcd,
|
||||||
|
0x80,
|
||||||
|
0xc6,
|
||||||
|
0x05,
|
||||||
|
0x00,
|
||||||
|
0x80,
|
||||||
|
0x0b,
|
||||||
|
0x00,
|
||||||
|
0x62,
|
||||||
|
0xeb,
|
||||||
|
0xfe, */
|
||||||
|
/* 0x90,
|
||||||
|
0xe9,
|
||||||
|
0xfa,
|
||||||
|
0x7f,
|
||||||
|
0x7b,
|
||||||
|
0xf8, */
|
||||||
|
/* 0x90,
|
||||||
|
0xeb,
|
||||||
|
0xfd, */
|
||||||
|
0x6a,
|
||||||
|
0x69,
|
||||||
|
0xeb,
|
||||||
|
0xfc,
|
||||||
|
};
|
||||||
|
|
||||||
void kernel_main(void)
|
void kernel_main(void)
|
||||||
{
|
{
|
||||||
/* Initialize terminal interface */
|
/* Initialize terminal interface */
|
||||||
terminal_initialize();
|
// terminal_initialize();
|
||||||
|
|
||||||
// TODO: Add interrupts
|
idt_init();
|
||||||
// idt_init();
|
|
||||||
|
|
||||||
terminal_putchar(get_last_key_pressed());
|
run_program(program, 15);
|
||||||
|
|
||||||
char current_character = get_last_key_pressed();
|
/*
|
||||||
while (current_character != ',') {
|
char buf[100];
|
||||||
char tmp = get_last_key_pressed();
|
|
||||||
if (current_character != -1 && tmp != current_character) {
|
while (true) {
|
||||||
terminal_putchar(current_character);
|
asm("mov %0, %%edx" :: "r" (buf));
|
||||||
}
|
asm("int $0x81");
|
||||||
current_character = tmp;
|
terminal_writestring("newline");
|
||||||
|
terminal_putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
2
libc/include/stdio.h
Normal file
2
libc/include/stdio.h
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
void print(char* s);
|
||||||
|
void input(char* buf);
|
11
libc/stdio.c
Normal file
11
libc/stdio.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
void print(char* s)
|
||||||
|
{
|
||||||
|
asm("mov %0, %%edx" :: "r" (s));
|
||||||
|
asm("int $0x21");
|
||||||
|
}
|
||||||
|
|
||||||
|
void input(char* buf)
|
||||||
|
{
|
||||||
|
asm("mov %0, %%edx" :: "r" (buf));
|
||||||
|
asm("int $0x22");
|
||||||
|
}
|
Loading…
Reference in a new issue