Yoooooo userland execution :3
This commit is contained in:
parent
c8ce4a2de0
commit
cac521ded0
4
Makefile
4
Makefile
|
@ -51,7 +51,7 @@ clean:
|
||||||
rm -f isodir/boot/myos.kernel
|
rm -f isodir/boot/myos.kernel
|
||||||
|
|
||||||
$(ARCHDIR)/interrupt.o: CFLAGS += -mgeneral-regs-only
|
$(ARCHDIR)/interrupt.o: CFLAGS += -mgeneral-regs-only
|
||||||
kernel/elf.o: CFLAGS += -masm=intel
|
# kernel/elf.o: CFLAGS += -masm=intel
|
||||||
|
|
||||||
%.o : %.c
|
%.o : %.c
|
||||||
i686-elf-gcc -c $< -o $@ $(CFLAGS)
|
i686-elf-gcc -c $< -o $@ $(CFLAGS)
|
||||||
|
@ -71,7 +71,7 @@ debug: CFLAGS += -g -O0
|
||||||
debug: ASFLAGS += -g
|
debug: ASFLAGS += -g
|
||||||
debug: all
|
debug: all
|
||||||
|
|
||||||
run: myos.iso
|
run: all
|
||||||
qemu-system-i386 myos.iso
|
qemu-system-i386 myos.iso
|
||||||
|
|
||||||
run-debug: debug
|
run-debug: debug
|
||||||
|
|
|
@ -70,7 +70,7 @@ _start:
|
||||||
|
|
||||||
call gdt_init
|
call gdt_init
|
||||||
|
|
||||||
movw 0x10, %ax
|
movw $0x10, %ax
|
||||||
movw %ax, %ds
|
movw %ax, %ds
|
||||||
movw %ax, %es
|
movw %ax, %es
|
||||||
movw %ax, %fs
|
movw %ax, %fs
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define NUM_ENTRIES 6
|
#define NUM_ENTRIES 256
|
||||||
|
|
||||||
struct SegmentDescriptor {
|
struct SegmentDescriptor {
|
||||||
uint32_t limit;
|
uint32_t limit;
|
||||||
|
@ -101,7 +101,7 @@ static void add_entry(struct SegmentDescriptor entry)
|
||||||
|
|
||||||
static void load_gdt()
|
static void load_gdt()
|
||||||
{
|
{
|
||||||
gdt.size = NUM_ENTRIES * 8 - 1;
|
gdt.size = NUM_ENTRIES * sizeof(struct SegmentDescriptor) - 1;
|
||||||
gdt.base = entries;
|
gdt.base = entries;
|
||||||
|
|
||||||
asm ( "lgdt %0" : : "m"(gdt) );
|
asm ( "lgdt %0" : : "m"(gdt) );
|
||||||
|
@ -125,7 +125,7 @@ void gdt_init()
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
struct SegmentDescriptor kernel_code;
|
struct SegmentDescriptor kernel_code;
|
||||||
kernel_code.limit = 0x000003FF;
|
kernel_code.limit = 0xFFFFF;
|
||||||
kernel_code.base = 0x00000000;
|
kernel_code.base = 0x00000000;
|
||||||
kernel_code.access_byte = 0b10011010;
|
kernel_code.access_byte = 0b10011010;
|
||||||
kernel_code.flags = 0b1100;
|
kernel_code.flags = 0b1100;
|
||||||
|
@ -136,8 +136,8 @@ void gdt_init()
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
struct SegmentDescriptor kernel_data;
|
struct SegmentDescriptor kernel_data;
|
||||||
kernel_data.limit = 0x000003FF;
|
kernel_data.limit = 0xFFFFF;
|
||||||
kernel_data.base = 0x00400000;
|
kernel_data.base = 0x00000000;
|
||||||
kernel_data.access_byte = 0b10010010;
|
kernel_data.access_byte = 0b10010010;
|
||||||
kernel_data.flags = 0b1100;
|
kernel_data.flags = 0b1100;
|
||||||
|
|
||||||
|
@ -146,8 +146,8 @@ void gdt_init()
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
struct SegmentDescriptor user_code;
|
struct SegmentDescriptor user_code;
|
||||||
user_code.limit = 0x000003FF;
|
user_code.limit = 0xFFFFF;
|
||||||
user_code.base = 0x00800000;
|
user_code.base = 0x00000000;
|
||||||
user_code.access_byte = 0b11111010;
|
user_code.access_byte = 0b11111010;
|
||||||
user_code.flags = 0b1100;
|
user_code.flags = 0b1100;
|
||||||
|
|
||||||
|
@ -157,8 +157,8 @@ void gdt_init()
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
struct SegmentDescriptor user_data;
|
struct SegmentDescriptor user_data;
|
||||||
user_data.limit = 0x000FFFFF;
|
user_data.limit = 0xFFFFF;
|
||||||
user_data.base = 0x00c00000;
|
user_data.base = 0x00000000;
|
||||||
user_data.access_byte = 0b11110010;
|
user_data.access_byte = 0b11110010;
|
||||||
user_data.flags = 0b1100;
|
user_data.flags = 0b1100;
|
||||||
|
|
||||||
|
@ -179,4 +179,9 @@ void gdt_init()
|
||||||
terminal_putchar('\n');
|
terminal_putchar('\n');
|
||||||
|
|
||||||
load_gdt();
|
load_gdt();
|
||||||
|
|
||||||
|
tss.ss0 = 0x10;
|
||||||
|
asm("mov %%esp, %0" : "=r" (tss.esp0));
|
||||||
|
|
||||||
|
asm ("ltr %%ax" : : "a"(0x28));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include <kernel/tty.h>
|
|
||||||
#include <kernel/gdt.h>
|
#include <kernel/gdt.h>
|
||||||
|
#include <kernel/tty.h>
|
||||||
#include <debugging.h>
|
#include <debugging.h>
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
#define NUM_ENTRIES 0x100
|
#define NUM_ENTRIES 0x100
|
||||||
|
|
||||||
|
@ -101,20 +102,9 @@ struct InterruptDescriptor generate_entry(bool present, void isr(struct interrup
|
||||||
return entry;
|
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()
|
void idt_init()
|
||||||
{
|
{
|
||||||
outb(0x21,0xfd);
|
terminal_initialize();
|
||||||
outb(0xa1,0xff);
|
|
||||||
|
|
||||||
struct InterruptDescriptor entry;
|
struct InterruptDescriptor entry;
|
||||||
|
|
||||||
entry = generate_entry(true, exception, 0xF, 0, 0x8);
|
entry = generate_entry(true, exception, 0xF, 0, 0x8);
|
||||||
|
@ -123,12 +113,6 @@ void idt_init()
|
||||||
add_entry(entry, 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);
|
entry = generate_entry(true, divide_by_zero, 0xF, 0, 0x8);
|
||||||
add_entry(entry, DivisionByZero);
|
add_entry(entry, DivisionByZero);
|
||||||
|
|
||||||
|
@ -138,11 +122,18 @@ void idt_init()
|
||||||
entry = generate_entry(true, double_fault, 0xF, 0, 0x8);
|
entry = generate_entry(true, double_fault, 0xF, 0, 0x8);
|
||||||
add_entry(entry, DoubleFault);
|
add_entry(entry, DoubleFault);
|
||||||
|
|
||||||
|
outb(0x21,0x20); // Tell the PIC to use interrupts 0x20 - 0x27
|
||||||
|
entry = generate_entry(true, irq, 0xE, 0, 0x8);
|
||||||
|
for (int i = 0x20; i < 0x28; i++)
|
||||||
|
{
|
||||||
|
add_entry(entry, i);
|
||||||
|
}
|
||||||
|
|
||||||
struct InterruptDescriptor print_entry;
|
struct InterruptDescriptor print_entry;
|
||||||
print_entry.present = true;
|
print_entry.present = true;
|
||||||
print_entry.offset = (uint32_t)print;
|
print_entry.offset = (uint32_t)print;
|
||||||
print_entry.gate_type = 0xE;
|
print_entry.gate_type = 0xE;
|
||||||
print_entry.ring = 3;
|
print_entry.ring = 0;
|
||||||
print_entry.selector = 0x8;
|
print_entry.selector = 0x8;
|
||||||
|
|
||||||
add_entry(print_entry, 0x80);
|
add_entry(print_entry, 0x80);
|
||||||
|
@ -157,9 +148,4 @@ void idt_init()
|
||||||
add_entry(input_entry, 0x81);
|
add_entry(input_entry, 0x81);
|
||||||
|
|
||||||
load_idt();
|
load_idt();
|
||||||
|
|
||||||
tss.ss0 = 0x10;
|
|
||||||
asm("mov %%esp, %0" : "=r" (tss.esp0));
|
|
||||||
asm("mov $0x28, %ax");
|
|
||||||
asm("ltr %ax");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <debugging.h>
|
#include <debugging.h>
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
struct interrupt_frame {
|
struct interrupt_frame {
|
||||||
uint32_t eflags;
|
uint32_t eflags;
|
||||||
|
@ -25,35 +26,26 @@ static void stack_trace()
|
||||||
|
|
||||||
__attribute__((interrupt)) void divide_by_zero(struct interrupt_frame* frame)
|
__attribute__((interrupt)) void divide_by_zero(struct interrupt_frame* frame)
|
||||||
{
|
{
|
||||||
terminal_initialize();
|
|
||||||
stack_trace();
|
|
||||||
terminal_writestring("Yo dude u cant divide by zero yao\n");
|
terminal_writestring("Yo dude u cant divide by zero yao\n");
|
||||||
while (1) { }
|
while (1) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((interrupt)) void general_protection_fault(struct interrupt_frame* frame)
|
__attribute__((interrupt)) void general_protection_fault(struct interrupt_frame* frame)
|
||||||
{
|
{
|
||||||
/* terminal_initialize();
|
terminal_writestring("GPF handler called\n");
|
||||||
stack_trace();
|
|
||||||
terminal_writestring("General protection fault\n");
|
|
||||||
terminal_writestring("Error code:\n");
|
|
||||||
print_hex_bytes(frame, sizeof(frame));
|
|
||||||
terminal_putchar('\n'); */
|
|
||||||
while (1) { }
|
while (1) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((interrupt)) void double_fault(struct interrupt_frame* frame)
|
__attribute__((interrupt)) void double_fault(struct interrupt_frame* frame)
|
||||||
{
|
{
|
||||||
// terminal_writestring("2 Errors in a row, u better behave naughty naughty\n");
|
terminal_writestring("2 Errors in a row, u better behave naughty naughty\n");
|
||||||
// while (1) { }
|
while (1) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((interrupt)) void exception(struct interrupt_frame* frame)
|
__attribute__((interrupt)) void exception(struct interrupt_frame* frame)
|
||||||
{
|
{
|
||||||
/* terminal_initialize();
|
|
||||||
stack_trace();
|
|
||||||
terminal_writestring("Some weird error code stuff\n");
|
terminal_writestring("Some weird error code stuff\n");
|
||||||
terminal_writestring("Error code:\n");
|
/* terminal_writestring("Error code:\n");
|
||||||
print_hex_bytes(frame, sizeof(frame));
|
print_hex_bytes(frame, sizeof(frame));
|
||||||
terminal_putchar('\n'); */
|
terminal_putchar('\n'); */
|
||||||
while (1) { }
|
while (1) { }
|
||||||
|
@ -109,6 +101,7 @@ __attribute__((interrupt)) void input(struct interrupt_frame* frame)
|
||||||
|
|
||||||
__attribute__((interrupt)) void irq(struct interrupt_frame* frame)
|
__attribute__((interrupt)) void irq(struct interrupt_frame* frame)
|
||||||
{
|
{
|
||||||
|
terminal_writestring("Test");
|
||||||
|
outb(0x20, 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
arch/i686/io.h
Normal file
19
arch/i686/io.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void inb(uint16_t port, uint8_t val)
|
||||||
|
{
|
||||||
|
__asm__ volatile ( "inb %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 */
|
||||||
|
}
|
17
arch/i686/pic.c
Normal file
17
arch/i686/pic.c
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#define ICW1_ICW4 0x01 /* Indicates that ICW4 will be present */
|
||||||
|
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||||
|
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||||
|
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||||
|
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||||
|
|
||||||
|
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||||
|
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||||
|
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||||
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
|
|
||||||
|
void init_pic() {
|
||||||
|
|
||||||
|
}
|
0
arch/i686/pic.h
Normal file
0
arch/i686/pic.h
Normal file
60
kernel/elf.c
60
kernel/elf.c
|
@ -3,43 +3,35 @@
|
||||||
#include <debugging.h>
|
#include <debugging.h>
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
#include <kernel/gdt.h>
|
#include <kernel/gdt.h>
|
||||||
|
#include <debugging.h>
|
||||||
|
|
||||||
|
static void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t size) {
|
||||||
|
unsigned char* dst = (unsigned char*) dstptr;
|
||||||
|
const unsigned char* src = (const unsigned char*) srcptr;
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
dst[i] = src[i];
|
||||||
|
return dstptr;
|
||||||
|
}
|
||||||
|
|
||||||
void run_program(uint8_t* program, size_t length)
|
void run_program(uint8_t* program, size_t length)
|
||||||
{
|
{
|
||||||
uint8_t* userland_code = (uint8_t*) 0x00800004;
|
uint8_t* userland_code = (uint8_t*) 0x0;
|
||||||
|
memcpy(userland_code, program, length);
|
||||||
|
|
||||||
for (size_t i = 0; i < length; i++) {
|
print_hex_bytes(userland_code, 1);
|
||||||
userland_code[i] = program[i];
|
terminal_putchar('\n');
|
||||||
}
|
|
||||||
|
|
||||||
tss.ss0 = 0x10;
|
asm ("\
|
||||||
|
mov $0x20 | 0x3, %%ax;\
|
||||||
asm("sti");
|
movw %%ax, %%ds;\
|
||||||
asm("int 0x80");
|
movw %%ax, %%es;\
|
||||||
|
movw %%ax, %%fs;\
|
||||||
asm("mov %0, esp" : "=r" (tss.esp0));
|
movw %%ax, %%gs;\
|
||||||
|
pushl $0x20 | 0x3; /* SS selector */ \
|
||||||
// Generates segfault
|
pushl $0x00c00100; /* ESP */ \
|
||||||
// asm("mov esp, %0" : "=r" (tss.esp0));
|
pushf; /* EFLAGS */ \
|
||||||
|
popl %%eax; orl $0x200, %%eax; pushl %%eax; /* Set interrupts in USERPACE */\
|
||||||
asm("mov ax, 0x23 # Load registers with the correct GDT segments values");
|
pushl $0x18 | 0x3; /* CS selector */\
|
||||||
asm("mov ds, ax");
|
pushl $0x0; /* EIP */ \
|
||||||
asm("mov es, ax");
|
iret;":::"eax");
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,30 +9,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t program[] = {
|
uint8_t program[] = {
|
||||||
/* 0xcd,
|
0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x0 (Just a simple NOP-like instruction)
|
||||||
0x80,
|
0xF4 // hlt (halts the CPU, should trap to kernel if interrupts enabled)
|
||||||
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)
|
||||||
|
@ -42,6 +20,12 @@ void kernel_main(void)
|
||||||
|
|
||||||
idt_init();
|
idt_init();
|
||||||
|
|
||||||
|
// asm("int $13");
|
||||||
|
// asm("ljmp $0x18, $0x00c00100"); // Example: Far jump to user code segment with selector 0x18
|
||||||
|
|
||||||
|
print_hex_bytes(idt_init, 4);
|
||||||
|
terminal_putchar('\n');
|
||||||
|
|
||||||
run_program(program, 15);
|
run_program(program, 15);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue