Restructuration part 2: libc, programs

This commit is contained in:
xamidev
2024-07-19 17:40:53 +02:00
parent 014b0d2b50
commit b8faf9dd8e
24 changed files with 17 additions and 12 deletions

48
src/kernel/gdt.c Normal file
View File

@@ -0,0 +1,48 @@
#include "gdt.h"
struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
struct gdt_entry gdt[3];
struct gdt_ptr gp;
extern void gdt_flush();
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
void gdt_install()
{
gp.limit = (sizeof(struct gdt_entry)*3) - 1;
gp.base = (unsigned int)&gdt;
gdt_set_gate(0, 0, 0, 0, 0);
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
gdt_flush();
}

8
src/kernel/gdt.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef GDT_H
#define GDT_H
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran);
void gdt_install();
#endif

42
src/kernel/idt.c Normal file
View File

@@ -0,0 +1,42 @@
#include "idt.h"
#include "system.h"
struct idt_entry
{
unsigned short base_lo;
unsigned short sel;
unsigned char always0;
unsigned char flags;
unsigned short base_hi;
} __attribute__((packed));
struct idt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
struct idt_entry idt[256];
struct idt_ptr idtp;
extern void idt_load();
void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
{
idt[num].base_lo = (base & 0xFFFF);
idt[num].base_hi = (base >> 16) & 0xFFFF;
idt[num].sel = sel;
idt[num].always0 = 0;
idt[num].flags = flags;
}
void idt_install()
{
idtp.limit = (sizeof (struct idt_entry)*256) - 1;
idtp.base = (unsigned int)&idt;
memset(&idt, 0, sizeof(struct idt_entry)*256);
idt_load();
}

8
src/kernel/idt.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef IDT_H
#define IDT_H
void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags);
void idt_install();
#endif

10
src/kernel/io.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef INCLUDE_IO_H
#define INCLUDE_IO_H
#include "../libc/stdint.h"
void outb(unsigned short port, unsigned char data);
unsigned char inb(unsigned short port);
void x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut);
#endif

44
src/kernel/io.s Normal file
View File

@@ -0,0 +1,44 @@
global outb
outb:
mov al, [esp + 8]
mov dx, [esp + 4]
out dx, al
ret
global inb
inb:
mov dx, [esp + 4]
in al, dx
ret
global x86_div64_32
x86_div64_32:
push ebp
mov ebp, esp
; Arguments:
; [ebp + 8] - lower 32 bits of dividend (uint32_t)
; [ebp + 12] - upper 32 bits of dividend (uint32_t)
; [ebp + 16] - divisor (uint32_t)
; [ebp + 20] - pointer to quotient (uint64_t*)
; [ebp + 24] - pointer to remainder (uint32_t*)
mov eax, [ebp + 8]
mov edx, [ebp + 12]
mov ecx, [ebp + 16]
div ecx
mov esi, [ebp + 20]
mov [esi], eax
mov dword [esi + 4], 0
mov esi, [ebp + 24]
mov [esi], edx
pop ebp
ret

90
src/kernel/irq.c Normal file
View File

@@ -0,0 +1,90 @@
#include "system.h"
#include "io.h"
#include "idt.h"
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
void *irq_routines[16] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
void irq_install_handler(int irq, void (*handler)(struct regs *r))
{
irq_routines[irq] = handler;
}
void irq_uninstall_handler(int irq)
{
irq_routines[irq] = 0;
}
void irq_remap(void)
{
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
}
void irq_install()
{
irq_remap();
idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E);
idt_set_gate(33, (unsigned)irq1, 0x08, 0x8E);
idt_set_gate(34, (unsigned)irq2, 0x08, 0x8E);
idt_set_gate(35, (unsigned)irq3, 0x08, 0x8E);
idt_set_gate(36, (unsigned)irq4, 0x08, 0x8E);
idt_set_gate(37, (unsigned)irq5, 0x08, 0x8E);
idt_set_gate(38, (unsigned)irq6, 0x08, 0x8E);
idt_set_gate(39, (unsigned)irq7, 0x08, 0x8E);
idt_set_gate(40, (unsigned)irq8, 0x08, 0x8E);
idt_set_gate(41, (unsigned)irq9, 0x08, 0x8E);
idt_set_gate(42, (unsigned)irq10, 0x08, 0x8E);
idt_set_gate(43, (unsigned)irq11, 0x08, 0x8E);
idt_set_gate(44, (unsigned)irq12, 0x08, 0x8E);
idt_set_gate(45, (unsigned)irq13, 0x08, 0x8E);
idt_set_gate(46, (unsigned)irq14, 0x08, 0x8E);
idt_set_gate(47, (unsigned)irq15, 0x08, 0x8E);
}
void irq_handler(struct regs *r)
{
void (*handler)(struct regs *r);
handler = irq_routines[r->int_no-32];
if (handler)
{
handler(r);
}
if (r->int_no >= 40)
{
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
}

118
src/kernel/isr.c Normal file
View File

@@ -0,0 +1,118 @@
#include "system.h"
#include "../libc/stdio.h"
#include "idt.h"
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();
void isr_install()
{
idt_set_gate(0, (unsigned)isr0, 0x08, 0x8E);
idt_set_gate(1, (unsigned)isr1, 0x08, 0x8E);
idt_set_gate(2, (unsigned)isr2, 0x08, 0x8E);
idt_set_gate(3, (unsigned)isr3, 0x08, 0x8E);
idt_set_gate(4, (unsigned)isr4, 0x08, 0x8E);
idt_set_gate(5, (unsigned)isr5, 0x08, 0x8E);
idt_set_gate(6, (unsigned)isr6, 0x08, 0x8E);
idt_set_gate(7, (unsigned)isr7, 0x08, 0x8E);
idt_set_gate(8, (unsigned)isr8, 0x08, 0x8E);
idt_set_gate(9, (unsigned)isr9, 0x08, 0x8E);
idt_set_gate(10, (unsigned)isr10, 0x08, 0x8E);
idt_set_gate(11, (unsigned)isr11, 0x08, 0x8E);
idt_set_gate(12, (unsigned)isr12, 0x08, 0x8E);
idt_set_gate(13, (unsigned)isr13, 0x08, 0x8E);
idt_set_gate(14, (unsigned)isr14, 0x08, 0x8E);
idt_set_gate(15, (unsigned)isr15, 0x08, 0x8E);
idt_set_gate(16, (unsigned)isr16, 0x08, 0x8E);
idt_set_gate(17, (unsigned)isr17, 0x08, 0x8E);
idt_set_gate(18, (unsigned)isr18, 0x08, 0x8E);
idt_set_gate(19, (unsigned)isr19, 0x08, 0x8E);
idt_set_gate(20, (unsigned)isr20, 0x08, 0x8E);
idt_set_gate(21, (unsigned)isr21, 0x08, 0x8E);
idt_set_gate(22, (unsigned)isr22, 0x08, 0x8E);
idt_set_gate(23, (unsigned)isr23, 0x08, 0x8E);
idt_set_gate(24, (unsigned)isr24, 0x08, 0x8E);
idt_set_gate(25, (unsigned)isr25, 0x08, 0x8E);
idt_set_gate(26, (unsigned)isr26, 0x08, 0x8E);
idt_set_gate(27, (unsigned)isr27, 0x08, 0x8E);
idt_set_gate(28, (unsigned)isr28, 0x08, 0x8E);
idt_set_gate(29, (unsigned)isr29, 0x08, 0x8E);
idt_set_gate(30, (unsigned)isr30, 0x08, 0x8E);
idt_set_gate(31, (unsigned)isr31, 0x08, 0x8E);
}
char *exception_messages[] =
{
"Division by Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
void fault_handler(struct regs *r)
{
if (r->int_no < 32)
{
printf("\n\n*** [Kernel panic - %s Exception] ***\nInterrupt error code %u\nedi: %x esi: %u ebp: %u esp: %u\nebx: %u edx: %u ecx: %u eax: %u\neip: %x cs:%x eflags: %x ss: %x\ngs: %x fs: %x es: %x ds: %x\nHalting!\n", exception_messages[r->int_no], r->err_code, r->edi, r->esi, r->ebp, r->esp, r->ebx, r->edx, r->ecx, r->eax, r->eip, r->cs, r->eflags, r->ss, r->gs, r->fs, r->es, r->ds);
for (;;);
}
}

63
src/kernel/kb.c Normal file
View File

@@ -0,0 +1,63 @@
#include "io.h"
#include "../libc/stdio.h"
#include "system.h"
unsigned char kbdus[128] =
{
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
'q', 'w', 'e', 'r', /* 19 */
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
0, /* 29 - Control */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
'\'', '`', 0, /* Left shift */
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
'm', ',', '.', '/', 0, /* Right shift */
'*',
0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 key ... > */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* < ... F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home key */
0, /* Up Arrow */
0, /* Page Up */
'-',
0, /* Left Arrow */
0,
0, /* Right Arrow */
'+',
0, /* 79 - End key*/
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert Key */
0, /* Delete Key */
0, 0, 0,
0, /* F11 Key */
0, /* F12 Key */
0, /* All other keys are undefined */
};
void keyboard_handler()
{
unsigned char scancode;
scancode = inb(0x60);
if (scancode & 0x80)
{
}
else
{
putc(kbdus[scancode]);
}
}
void keyboard_install()
{
irq_install_handler(1, keyboard_handler);
}

36
src/kernel/kmain.c Normal file
View File

@@ -0,0 +1,36 @@
#include "../libc/stdio.h"
#include "serial.h"
#include "gdt.h"
#include "idt.h"
#include "system.h"
int kmain(int retvalue)
{
init_serial();
log("serial connection established", 3);
gdt_install();
log("initialized GDT entries", 2);
idt_install();
log("initialized IDT", 2);
isr_install();
log("initialized ISRs", 2);
irq_install();
__asm__ __volatile__("sti");
log("initialized IRQs", 2),
log("kernel started", 2);
clear();
colorputs("Blank OS version 1 iteration 3 minor 20\n", 10);
// TODO: Serial printf to dump registers on kernel panic
// TODO: Fix scrolling bug (framebuffer driver)
// TODO: Fix keyboard driver bug (some keys mapped weirdly) + add suport for SHIFT and backspace (deleting character)
// TODO: Grub modules to load programs
//timer_install();
keyboard_install();
return retvalue;
}

440
src/kernel/loader.s Normal file
View File

@@ -0,0 +1,440 @@
global loader
section .__mbHeader
align 0x4
section .text:
MAGIC_NUMBER equ 0x1BADB002 ; multiboot magic
FLAGS equ 0x0
CHECKSUM equ -MAGIC_NUMBER
KERNEL_STACK_SIZE equ 4096
dd MAGIC_NUMBER
dd FLAGS
dd CHECKSUM
extern kmain
loader:
cli
; mov eax, 0xCAFEBABE
push dword 42
call kmain
.loop:
jmp .loop
global gdt_flush
extern gp
gdt_flush:
lgdt [gp]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2
flush2:
ret
global idt_load
extern idtp
idt_load:
lidt [idtp]
ret
global isr0
global isr1
global isr2
global isr3
global isr4
global isr5
global isr6
global isr7
global isr8
global isr9
global isr10
global isr11
global isr12
global isr13
global isr14
global isr15
global isr16
global isr17
global isr18
global isr19
global isr20
global isr21
global isr22
global isr23
global isr24
global isr25
global isr26
global isr27
global isr28
global isr29
global isr30
global isr31
; Interrupt service routine exceptions
isr0:
cli
push byte 0
push byte 0
jmp isr_common_stub
isr1:
cli
push byte 0
push byte 1
jmp isr_common_stub
isr2:
cli
push byte 0
push byte 2
jmp isr_common_stub
isr3:
cli
push byte 0
push byte 3
jmp isr_common_stub
isr4:
cli
push byte 0
push byte 4
jmp isr_common_stub
isr5:
cli
push byte 0
push byte 5
jmp isr_common_stub
isr6:
cli
push byte 0
push byte 6
jmp isr_common_stub
isr7:
cli
push byte 0
push byte 7
jmp isr_common_stub
isr8:
cli
push byte 8
jmp isr_common_stub
isr9:
cli
push byte 0
push byte 9
jmp isr_common_stub
isr10:
cli
push byte 10
jmp isr_common_stub
isr11:
cli
push byte 11
jmp isr_common_stub
isr12:
cli
push byte 12
jmp isr_common_stub
isr13:
cli
push byte 13
jmp isr_common_stub
isr14:
cli
push byte 14
jmp isr_common_stub
isr15:
cli
push byte 0
push byte 15
jmp isr_common_stub
isr16:
cli
push byte 0
push byte 16
jmp isr_common_stub
isr17:
cli
push byte 0
push byte 17
jmp isr_common_stub
isr18:
cli
push byte 0
push byte 18
jmp isr_common_stub
isr19:
cli
push byte 0
push byte 19
jmp isr_common_stub
isr20:
cli
push byte 0
push byte 20
jmp isr_common_stub
isr21:
cli
push byte 0
push byte 21
jmp isr_common_stub
isr22:
cli
push byte 0
push byte 22
jmp isr_common_stub
isr23:
cli
push byte 0
push byte 23
jmp isr_common_stub
isr24:
cli
push byte 0
push byte 24
jmp isr_common_stub
isr25:
cli
push byte 0
push byte 25
jmp isr_common_stub
isr26:
cli
push byte 0
push byte 26
jmp isr_common_stub
isr27:
cli
push byte 0
push byte 27
jmp isr_common_stub
isr28:
cli
push byte 0
push byte 28
jmp isr_common_stub
isr29:
cli
push byte 0
push byte 29
jmp isr_common_stub
isr30:
cli
push byte 0
push byte 30
jmp isr_common_stub
isr31:
cli
push byte 0
push byte 31
jmp isr_common_stub
extern fault_handler
isr_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, fault_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
global irq0
global irq1
global irq2
global irq3
global irq4
global irq5
global irq6
global irq7
global irq8
global irq9
global irq10
global irq11
global irq12
global irq13
global irq14
global irq15
irq0:
cli
push byte 0
push byte 32
jmp irq_common_stub
irq1:
cli
push byte 0
push byte 33
jmp irq_common_stub
irq2:
cli
push byte 0
push byte 34
jmp irq_common_stub
irq3:
cli
push byte 0
push byte 35
jmp irq_common_stub
irq4:
cli
push byte 0
push byte 36
jmp irq_common_stub
irq5:
cli
push byte 0
push byte 37
jmp irq_common_stub
irq6:
cli
push byte 0
push byte 38
jmp irq_common_stub
irq7:
cli
push byte 0
push byte 39
jmp irq_common_stub
irq8:
cli
push byte 0
push byte 40
jmp irq_common_stub
irq9:
cli
push byte 0
push byte 41
jmp irq_common_stub
irq10:
cli
push byte 0
push byte 42
jmp irq_common_stub
irq11:
cli
push byte 0
push byte 43
jmp irq_common_stub
irq12:
cli
push byte 0
push byte 44
jmp irq_common_stub
irq13:
cli
push byte 0
push byte 45
jmp irq_common_stub
irq14:
cli
push byte 0
push byte 46
jmp irq_common_stub
irq15:
cli
push byte 0
push byte 47
jmp irq_common_stub
extern irq_handler
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
section .bss
align 4
kernel_stack:
resb KERNEL_STACK_SIZE
mov esp, kernel_stack + KERNEL_STACK_SIZE

65
src/kernel/serial.c Normal file
View File

@@ -0,0 +1,65 @@
#include "io.h"
#include "serial.h"
int init_serial()
{
outb(PORT+1, 0x00);
outb(PORT+3, 0x80);
outb(PORT+0, 0x03);
outb(PORT+1, 0x00);
outb(PORT+3, 0x03);
outb(PORT+2, 0xC7);
outb(PORT+4, 0x0B);
outb(PORT+4, 0x1E);
outb(PORT+0, 0xAE);
if (inb(PORT+0) != 0xAE) {
return 1;
}
outb(PORT+4, 0x0F);
return 0;
}
int is_transmit_empty()
{
return inb(PORT+5) & 0x20;
}
void write_serial(const char a)
{
while (is_transmit_empty() == 0);
outb(PORT, a);
}
void serial_puts(const char* str)
{
unsigned int i = 0;
write_serial(str[0]); // Transmit first byte 2 times
while (*str++)
{
write_serial(str[i]);
}
}
void log(const char* str, const int errlevel)
{
switch (errlevel)
{
case 0:
serial_puts("[ERROR] ");
break;
case 1:
serial_puts("[WARNING] ");
break;
case 2:
serial_puts("[INFO] ");
break;
case 3:
serial_puts("[DEBUG] ");
break;
}
serial_puts(str);
serial_puts("\n");
}

12
src/kernel/serial.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef INCLUDE_SERIAL_H
#define INCLUDE_SERIAL_H
#define PORT 0x3f8 //COM1
int init_serial();
int is_transmit_empty();
void write_serial(const char a);
void serial_puts(const char* str);
void log(const char* str, const int errlevel);
#endif

8
src/kernel/system.c Normal file
View File

@@ -0,0 +1,8 @@
#include "system.h"
void *memset(void *dest, char val, size_t count)
{
char *temp = (char *)dest;
for(; count != 0; count--) *temp++ = val;
return dest;
}

24
src/kernel/system.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef SYSTEM_H
#define SYSTEM_H
typedef int size_t;
void *memset(void *dest, char val, size_t count);
struct regs
{
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_no, err_code;
unsigned int eip, cs, eflags, useresp, ss;
};
void isr_install();
void irq_install();
void irq_install_handler(int irq, void (*handler)(struct regs *r));
void irq_uninstall_handler(int irq);
void timer_install();
void delay(int ticks);
void keyboard_install();
#endif

26
src/kernel/timer.c Normal file
View File

@@ -0,0 +1,26 @@
#include "system.h"
#include "../libc/stdio.h"
int timer_ticks = 0;
void timer_handler()
{
timer_ticks++;
if(timer_ticks % 18 == 0)
{
puts("One second has passed\n");
}
}
void timer_install()
{
irq_install_handler(0, timer_handler);
}
void delay(int ticks)
{
unsigned long eticks;
eticks = timer_ticks + ticks;
while ((unsigned long)timer_ticks < eticks);
}