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
|
||||
|
||||
$(ARCHDIR)/interrupt.o: CFLAGS += -mgeneral-regs-only
|
||||
kernel/elf.o: CFLAGS += -masm=intel
|
||||
# kernel/elf.o: CFLAGS += -masm=intel
|
||||
|
||||
%.o : %.c
|
||||
i686-elf-gcc -c $< -o $@ $(CFLAGS)
|
||||
|
@ -71,7 +71,7 @@ debug: CFLAGS += -g -O0
|
|||
debug: ASFLAGS += -g
|
||||
debug: all
|
||||
|
||||
run: myos.iso
|
||||
run: all
|
||||
qemu-system-i386 myos.iso
|
||||
|
||||
run-debug: debug
|
||||
|
|
|
@ -70,7 +70,7 @@ _start:
|
|||
|
||||
call gdt_init
|
||||
|
||||
movw 0x10, %ax
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define NUM_ENTRIES 6
|
||||
#define NUM_ENTRIES 256
|
||||
|
||||
struct SegmentDescriptor {
|
||||
uint32_t limit;
|
||||
|
@ -101,7 +101,7 @@ static void add_entry(struct SegmentDescriptor entry)
|
|||
|
||||
static void load_gdt()
|
||||
{
|
||||
gdt.size = NUM_ENTRIES * 8 - 1;
|
||||
gdt.size = NUM_ENTRIES * sizeof(struct SegmentDescriptor) - 1;
|
||||
gdt.base = entries;
|
||||
|
||||
asm ( "lgdt %0" : : "m"(gdt) );
|
||||
|
@ -125,7 +125,7 @@ void gdt_init()
|
|||
terminal_putchar('\n');
|
||||
|
||||
struct SegmentDescriptor kernel_code;
|
||||
kernel_code.limit = 0x000003FF;
|
||||
kernel_code.limit = 0xFFFFF;
|
||||
kernel_code.base = 0x00000000;
|
||||
kernel_code.access_byte = 0b10011010;
|
||||
kernel_code.flags = 0b1100;
|
||||
|
@ -136,8 +136,8 @@ void gdt_init()
|
|||
terminal_putchar('\n');
|
||||
|
||||
struct SegmentDescriptor kernel_data;
|
||||
kernel_data.limit = 0x000003FF;
|
||||
kernel_data.base = 0x00400000;
|
||||
kernel_data.limit = 0xFFFFF;
|
||||
kernel_data.base = 0x00000000;
|
||||
kernel_data.access_byte = 0b10010010;
|
||||
kernel_data.flags = 0b1100;
|
||||
|
||||
|
@ -146,8 +146,8 @@ void gdt_init()
|
|||
terminal_putchar('\n');
|
||||
|
||||
struct SegmentDescriptor user_code;
|
||||
user_code.limit = 0x000003FF;
|
||||
user_code.base = 0x00800000;
|
||||
user_code.limit = 0xFFFFF;
|
||||
user_code.base = 0x00000000;
|
||||
user_code.access_byte = 0b11111010;
|
||||
user_code.flags = 0b1100;
|
||||
|
||||
|
@ -157,8 +157,8 @@ void gdt_init()
|
|||
terminal_putchar('\n');
|
||||
|
||||
struct SegmentDescriptor user_data;
|
||||
user_data.limit = 0x000FFFFF;
|
||||
user_data.base = 0x00c00000;
|
||||
user_data.limit = 0xFFFFF;
|
||||
user_data.base = 0x00000000;
|
||||
user_data.access_byte = 0b11110010;
|
||||
user_data.flags = 0b1100;
|
||||
|
||||
|
@ -179,4 +179,9 @@ void gdt_init()
|
|||
terminal_putchar('\n');
|
||||
|
||||
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/tty.h>
|
||||
#include <debugging.h>
|
||||
#include "interrupt.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "io.h"
|
||||
|
||||
#define NUM_ENTRIES 0x100
|
||||
|
||||
|
@ -101,20 +102,9 @@ struct InterruptDescriptor generate_entry(bool present, void isr(struct interrup
|
|||
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);
|
||||
|
||||
terminal_initialize();
|
||||
struct InterruptDescriptor entry;
|
||||
|
||||
entry = generate_entry(true, exception, 0xF, 0, 0x8);
|
||||
|
@ -123,12 +113,6 @@ void idt_init()
|
|||
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);
|
||||
|
||||
|
@ -138,11 +122,18 @@ void idt_init()
|
|||
entry = generate_entry(true, double_fault, 0xF, 0, 0x8);
|
||||
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;
|
||||
print_entry.present = true;
|
||||
print_entry.offset = (uint32_t)print;
|
||||
print_entry.gate_type = 0xE;
|
||||
print_entry.ring = 3;
|
||||
print_entry.ring = 0;
|
||||
print_entry.selector = 0x8;
|
||||
|
||||
add_entry(print_entry, 0x80);
|
||||
|
@ -157,9 +148,4 @@ void idt_init()
|
|||
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,6 +1,7 @@
|
|||
#include <kernel/tty.h>
|
||||
#include <stddef.h>
|
||||
#include <debugging.h>
|
||||
#include "io.h"
|
||||
|
||||
struct interrupt_frame {
|
||||
uint32_t eflags;
|
||||
|
@ -25,35 +26,26 @@ static void stack_trace()
|
|||
|
||||
__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");
|
||||
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'); */
|
||||
terminal_writestring("GPF handler called\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) { }
|
||||
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");
|
||||
/* terminal_writestring("Error code:\n");
|
||||
print_hex_bytes(frame, sizeof(frame));
|
||||
terminal_putchar('\n'); */
|
||||
while (1) { }
|
||||
|
@ -109,6 +101,7 @@ __attribute__((interrupt)) void input(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
62
kernel/elf.c
62
kernel/elf.c
|
@ -3,43 +3,35 @@
|
|||
#include <debugging.h>
|
||||
#include <kernel/tty.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)
|
||||
{
|
||||
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++) {
|
||||
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");
|
||||
print_hex_bytes(userland_code, 1);
|
||||
terminal_putchar('\n');
|
||||
|
||||
asm ("\
|
||||
mov $0x20 | 0x3, %%ax;\
|
||||
movw %%ax, %%ds;\
|
||||
movw %%ax, %%es;\
|
||||
movw %%ax, %%fs;\
|
||||
movw %%ax, %%gs;\
|
||||
pushl $0x20 | 0x3; /* SS selector */ \
|
||||
pushl $0x00c00100; /* ESP */ \
|
||||
pushf; /* EFLAGS */ \
|
||||
popl %%eax; orl $0x200, %%eax; pushl %%eax; /* Set interrupts in USERPACE */\
|
||||
pushl $0x18 | 0x3; /* CS selector */\
|
||||
pushl $0x0; /* EIP */ \
|
||||
iret;":::"eax");
|
||||
}
|
||||
|
|
|
@ -9,30 +9,8 @@
|
|||
#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,
|
||||
0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, 0x0 (Just a simple NOP-like instruction)
|
||||
0xF4 // hlt (halts the CPU, should trap to kernel if interrupts enabled)
|
||||
};
|
||||
|
||||
void kernel_main(void)
|
||||
|
@ -42,6 +20,12 @@ void kernel_main(void)
|
|||
|
||||
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);
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue