diff --git a/Makefile b/Makefile index 525510e..7e55caa 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ KERNEL = deados.bin ISO = deados.iso SOURCES_C = kernel.c tty.c idt.c timer.c io.c vga.c gdt.c sys.c irq.c isr.c keyboard.c shell.c string.c user_space.c syscall.c -SOURCES_ASM = boot.s idt_load.s gdt_flush.s pit_handler.s irq_e.s isr_e.s tss.s +SOURCES_ASM = boot.s idt_load.s gdt_flush.s irq_flush.s isr_flush.s tss_flush.s OBJECTS = $(SOURCES_ASM:.s=.o) $(SOURCES_C:.c=.o) ISO_DIR = isodir diff --git a/boot.s b/boot.s index 10899ee..1025369 100644 --- a/boot.s +++ b/boot.s @@ -12,24 +12,20 @@ .section .bss .align 16 - stack_bottom: - .skip 1024 * 32 # 32 KB +.skip 16384 +stack_top: stack_top: .section .text .global _start .type _start, @function _start: - cli mov $stack_top, %esp - + push %ebx call kernel_main - - hlt - jmp 1 1: - jmp 1 + jmp 1b .size _start, . - _start diff --git a/gdt.c b/gdt.c index eddd3ae..d74a403 100644 --- a/gdt.c +++ b/gdt.c @@ -4,14 +4,14 @@ #define GDT_ENTRY 6 Gdt_entry gdt[GDT_ENTRY]; -Gdt_ptr gdtp; +Gdt_ptr gdt_ptr; -extern void gdt_flush(uint32_t); +extern void gdt_flush(void); Tss_entry tss; extern void tss_flush(void); -static void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity) +void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity) { gdt[num].base_low = base & 0xFFFF; gdt[num].base_middle = (base >> 16) & 0xFF; @@ -25,45 +25,37 @@ static void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t acc gdt[num].access = access; } -static void tss_install(uint8_t num, uint16_t kernel_ss, uint16_t kernel_esp) +void tss_set_gate(uint32_t num, uint16_t ss0, uint32_t esp0) { uint32_t base = (uint32_t)&tss; uint32_t limit = base + sizeof(Tss_entry); - gdt_set_gate(num, base, limit, 0xE9, 0x0); + memset(&tss, 0x0, sizeof(Tss_entry)); + tss.ss0 = ss0; + tss.esp0 = esp0; - memset(&tss, 0, sizeof(Tss_entry)); - - tss.ss0 = kernel_ss; - tss.esp0 = kernel_esp; - - tss.cs = 0x0B; - tss.ss = 0x13; - tss.es = 0x13; - tss.ds = 0x13; - tss.fs = 0x13; - tss.gs = 0x13; -} - -void set_kernel_stack(uint32_t stack) -{ - tss.esp0 = stack; + tss.cs = 0x1B; + tss.ss = 0x23; + tss.es = 0x23; + tss.ds = 0x23; + tss.fs = 0x23; + tss.gs = 0x23; } void gdt_install() { gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0); // Null segment - gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF); // Kernel code segment - gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment - gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF); // User code segment - gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF); // User data segment + gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xC0); // 0x08 Kernel code segment + gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xC0); // 0x10 Kernel data segment + gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xC0); // 0x18 User code segment + gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xC0); // 0x20 User data segment - tss_install(5, 0x10, 0x0); + tss_set_gate(5, 0x10, 0); - gdtp.limit = (sizeof(Gdt_entry) * GDT_ENTRY) - 1; - gdtp.base = (uint32_t)&gdt; + gdt_ptr.limit = (sizeof(Gdt_entry) * GDT_ENTRY) - 1; + gdt_ptr.base = (uint32_t)&gdt; - gdt_flush((uint32_t)&gdtp); + gdt_flush(); tss_flush(); } diff --git a/gdt.h b/gdt.h index 89946f1..d164b74 100644 --- a/gdt.h +++ b/gdt.h @@ -21,7 +21,7 @@ struct gdt_ptr_t uint32_t base; } __attribute__((packed)); -static void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity); +void gdt_set_gate(uint8_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t granularity); void gdt_install(); void set_kernel_stack(uint32_t stack); diff --git a/gdt_flush.s b/gdt_flush.s index 0527400..8a3b75b 100644 --- a/gdt_flush.s +++ b/gdt_flush.s @@ -1,19 +1,17 @@ +.section .text +.align 4 + .global gdt_flush - +.type gdt_flush, @function gdt_flush: - cli + lgdt gdt_ptr + jmp $0x08, $reload_cs - mov 4(%esp), %eax - lgdt (%eax) - - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - - jmp $0x08, $.flush - -.flush: - ret + reload_cs: + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + ret diff --git a/idt_load.s b/idt_load.s index 9023c29..63d9ae4 100644 --- a/idt_load.s +++ b/idt_load.s @@ -1,5 +1,8 @@ .section .text +.align 4 + .global idt_load +.type idt_load, @function idt_load: - lidt [idtp] + lidt idtp ret diff --git a/interrupts.h b/interrupts.h index ab68303..1dfdbe8 100644 --- a/interrupts.h +++ b/interrupts.h @@ -25,8 +25,8 @@ void isr_install(void); #define NB_IRQ_ROUTINES 16 -#define PIC1 0x20 /* master PIC */ -#define PIC2 0xA0 /* slave PIC */ +#define PIC1 0x20 +#define PIC2 0xA0 #define PIC1_CMD PIC1 #define PIC1_DATA (PIC1 + 1) #define PIC2_CMD PIC2 diff --git a/io.c b/io.c index 047ed28..118e1e4 100644 --- a/io.c +++ b/io.c @@ -1,18 +1,20 @@ #include "io.h" -void outb(uint16_t port, uint8_t val) { - asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); +void outb(uint16_t port, uint8_t val) +{ + asm volatile("outb %0, %1" : : "a"(val), "Nd"(port)); } -uint8_t inb(uint16_t port) { +uint8_t inb(uint16_t port) +{ uint8_t ret; - asm volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); + asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); return ret; } void io_wait(void) { - asm volatile ( "jmp 1f\n\t" - "1:jmp 2f\n\t" - "2:" ); + asm volatile("jmp 1f\n\t" + "1:jmp 2f\n\t" + "2:"); } diff --git a/irq.c b/irq.c index 11642da..cc63ea1 100644 --- a/irq.c +++ b/irq.c @@ -4,6 +4,7 @@ #include "io.h" #include "sys.h" #include "idt.h" +#include "tty.h" extern void irq0(void); extern void irq1(void); @@ -42,24 +43,16 @@ void irq_call_handler(Stack *registers) handler(registers); } -static void irq_remap(void) +static void irq_remap(void) // PIC REMAP { outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4); - io_wait(); outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4); - io_wait(); outb(PIC1_DATA, PIC1_OFFSET); - io_wait(); outb(PIC2_DATA, PIC2_OFFSET); - io_wait(); outb(PIC1_DATA, 0x04); - io_wait(); outb(PIC2_DATA, 0x02); - io_wait(); outb(PIC1_DATA, ICW4_8086); - io_wait(); outb(PIC2_DATA, ICW4_8086); - io_wait(); } void irq_install(void) diff --git a/irq_e.s b/irq_flush.s similarity index 98% rename from irq_e.s rename to irq_flush.s index 4b71781..3155047 100644 --- a/irq_e.s +++ b/irq_flush.s @@ -30,7 +30,6 @@ IRQ 15, 47 irq_common_stub: pusha - push %ds push %es push %fs @@ -56,4 +55,4 @@ irq_common_stub: popa add $8, %esp - iret + iret \ No newline at end of file diff --git a/isr.c b/isr.c index 4a91979..c70645c 100644 --- a/isr.c +++ b/isr.c @@ -139,23 +139,20 @@ static const char *exception_messages[] = void fault_handler(Stack *registers) { + // check this if (registers->id == 128) + { isr_call_handler(registers); + } if (registers->id < 32) { - terminal_printc("Exception. System Halted!\n"); - - const char *message = exception_messages[registers->id]; - while (*message) - { - terminal_putchar(*message); - message++; - } isr_call_handler(registers); for (;;) + { sys_halt(); + } } } \ No newline at end of file diff --git a/isr_e.s b/isr_e.s deleted file mode 100644 index e638953..0000000 --- a/isr_e.s +++ /dev/null @@ -1,85 +0,0 @@ -.section .text -.align 4 - -.macro ISR_NO_ERR index - .global isr\index - isr\index: - cli - push $0 - push $\index - jmp isr_common_stub -.endm - -.macro ISR_ERR index - .global isr\index - isr\index: - cli - push $\index - jmp isr_common_stub -.endm - - -ISR_NO_ERR 0 # Division By Zero Exception -ISR_NO_ERR 1 # Debug Exception -ISR_NO_ERR 2 # Non Maskable Interrupt Exception -ISR_NO_ERR 3 # Breakpoint Exception -ISR_NO_ERR 4 # Into Detected Overflow Exception -ISR_NO_ERR 5 # Out of Bounds Exception -ISR_NO_ERR 6 # Invalid Opcode Exception -ISR_NO_ERR 7 # No Coprocessor Exception -ISR_ERR 8 # Double Fault Exception -ISR_NO_ERR 9 # Coprocessor Segment Overrun Exception -ISR_ERR 10 # Bad TSS Exception -ISR_ERR 11 # Segment Not Present Exception -ISR_ERR 12 # Stack Fault Exception -ISR_ERR 13 # General Protection Fault Exception -ISR_ERR 14 # Page Fault Exception -ISR_NO_ERR 15 # Unknown Interrupt Exception -ISR_NO_ERR 16 # Coprocessor Fault Exception -ISR_NO_ERR 17 # Alignment Check Exception -ISR_NO_ERR 18 # Machine Check Exception - -ISR_NO_ERR 19 # Other -ISR_NO_ERR 20 -ISR_NO_ERR 21 -ISR_NO_ERR 22 -ISR_NO_ERR 23 -ISR_NO_ERR 24 -ISR_NO_ERR 25 -ISR_NO_ERR 26 -ISR_NO_ERR 27 -ISR_NO_ERR 28 -ISR_NO_ERR 29 -ISR_NO_ERR 30 -ISR_NO_ERR 31 -ISR_NO_ERR 128 # Syscal - - -isr_common_stub: - pusha - push %ds - push %es - push %fs - push %gs - - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - - mov %esp, %eax - push %eax - mov $fault_handler, %eax - - call *%eax - pop %eax - - pop %gs - pop %fs - pop %es - pop %ds - popa - - add $8, %esp - iret diff --git a/isr_flush.s b/isr_flush.s new file mode 100644 index 0000000..50a40eb --- /dev/null +++ b/isr_flush.s @@ -0,0 +1,102 @@ +.section .text +.align 4 + + +.macro ISR_NO_ERR index + .global isr\index + isr\index: + cli + push $0 + push $\index + jmp isr_common_stub +.endm + +.macro ISR_ERR index + .global isr\index + isr\index: + cli + push $\index + jmp isr_common_stub +.endm + +/* Division By Zero Exception */ +ISR_NO_ERR 0 +/* Debug Exception */ +ISR_NO_ERR 1 +/* Non Maskable Interrupt Exception */ +ISR_NO_ERR 2 +/* Breakpoint Exception */ +ISR_NO_ERR 3 +/* Into Detected Overflow Exception */ +ISR_NO_ERR 4 +/* Out of Bounds Exception */ +ISR_NO_ERR 5 +/* Invalid Opcode Exception */ +ISR_NO_ERR 6 +/* No Coprocessor Exception */ +ISR_NO_ERR 7 +/* Double Fault Exception */ +ISR_ERR 8 +/* Coprocessor Segment Overrun Exception */ +ISR_NO_ERR 9 +/* Bad TSS Exception */ +ISR_ERR 10 +/* Segment Not Present Exception */ +ISR_ERR 11 +/* Stack Fault Exception */ +ISR_ERR 12 +/* General Protection Fault Exception */ +ISR_ERR 13 +/* Page Fault Exception */ +ISR_ERR 14 +/* Unknown Interrupt Exception */ +ISR_NO_ERR 15 +/* Coprocessor Fault Exception */ +ISR_NO_ERR 16 +/* Alignment Check Exception */ +ISR_NO_ERR 17 +/* Machine Check Exception */ +ISR_NO_ERR 18 +/* All the others are reserved */ +ISR_NO_ERR 19 +ISR_NO_ERR 20 +ISR_NO_ERR 21 +ISR_NO_ERR 22 +ISR_NO_ERR 23 +ISR_NO_ERR 24 +ISR_NO_ERR 25 +ISR_NO_ERR 26 +ISR_NO_ERR 27 +ISR_NO_ERR 28 +ISR_NO_ERR 29 +ISR_NO_ERR 30 +ISR_NO_ERR 31 +/* Syscall */ +ISR_NO_ERR 128 + +isr_common_stub: + pusha + push %ds + push %es + push %fs + push %gs + + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %esp, %eax + push %eax + mov $fault_handler, %eax + call *%eax + pop %eax + + pop %gs + pop %fs + pop %es + pop %ds + popa + + add $8, %esp + iret \ No newline at end of file diff --git a/kernel.c b/kernel.c index d6cccf8..3468ce8 100644 --- a/kernel.c +++ b/kernel.c @@ -22,10 +22,9 @@ void kernel_main(void) irq_install(); timer_install(); - keyboard_install(); - terminal_printc("Welcome to &cDeadOS&7.\n"); + syscall_init(); for (int i = 0; i < 3; i++) { terminal_printc("&cDead &7"); @@ -34,9 +33,22 @@ void kernel_main(void) terminal_printc("\n"); delay(100); } - syscall_init(); - enter_user_space(); + enter_user_space_v2(); +} + +void user_main(void) +{ + terminal_printc("Welcome to &cDeadOS&7.\n"); + + for (int i = 0; i < 3; i++) + { + terminal_printc("&cDead2 &7"); + terminal_putchar('0' + (i / 10)); + terminal_putchar('0' + (i % 10)); + terminal_printc("\n"); + delay(100); + } shell_init(); } \ No newline at end of file diff --git a/linker.ld b/linker.ld index d2ab833..72a0f57 100644 --- a/linker.ld +++ b/linker.ld @@ -1,24 +1,43 @@ +/* The bootloader will look at this image and start execution at the symbol + designated at the entry point. */ ENTRY(_start) +/* Tell where the various sections of the object files will be put in the final + kernel image. */ SECTIONS { - . = 1M; + /* The kernel is situated at 1 MiB */ + . = 1M; - .text ALIGN(4K) : - { - *(.multiboot) - *(.text) - *(.rodata) - } + kernel_start = .; - .data ALIGN(4K) : - { - *(.data) - } + /* First put the multiboot header, as it is required to be put very early + early in the image or the bootloader won't recognize the file format. + Next we'll put the .text section. */ + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } - .bss ALIGN(4K) : - { - *(.bss) - *(COMMON) - } -} + /* Read-only data */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(.bss) + *(.stack) + } + + kernel_end = .; +} \ No newline at end of file diff --git a/syscall.c b/syscall.c index cad9597..762b166 100644 --- a/syscall.c +++ b/syscall.c @@ -21,8 +21,6 @@ void *syscalls[NB_SYSCALL] = { void syscall_handler(Stack *registers) { - terminal_writestring("Syscall\n"); - int sys_index = registers->eax; if (sys_index >= NB_SYSCALL) @@ -51,4 +49,4 @@ void syscall_handler(Stack *registers) void syscall_init(void) { isr_install_handler(128, syscall_handler); -} \ No newline at end of file +} diff --git a/timer.c b/timer.c index 1159cb3..cbfa559 100644 --- a/timer.c +++ b/timer.c @@ -1,48 +1,20 @@ #include "timer.h" #include "io.h" #include "sys.h" -#include "idt.h" - -#define PIT_FREQUENCY 1193182 -#define PIT_CHANNEL_0 0x40 -#define PIT_COMMAND 0x43 +#include "interrupts.h" volatile uint32_t tick = 0; -void pit_handler() +void pit_handler(Stack *registers) { - tick++; - outb(0x20, 0x20); -} - -void pic_remap(int offset1, int offset2) -{ - unsigned char a1, a2; - - a1 = inb(0x21); - a2 = inb(0xA1); - - outb(0x20, 0x11); - outb(0xA0, 0x11); - outb(0x21, offset1); - outb(0xA1, offset2); - outb(0x21, 0x04); - outb(0xA1, 0x02); - - outb(0x21, 0x01); - outb(0xA1, 0x01); - - outb(0x21, a1); - outb(0xA1, a2); + ++tick; } void delay(uint32_t milliseconds) { uint32_t end = tick + milliseconds; while (tick < end) - { - sys_halt(); - } + ; } void pit_set_frequency(uint32_t frequency) @@ -50,12 +22,11 @@ void pit_set_frequency(uint32_t frequency) uint32_t divisor = PIT_FREQUENCY / frequency; outb(PIT_COMMAND, 0x36); outb(PIT_CHANNEL_0, divisor & 0xFF); - outb(PIT_CHANNEL_0, (divisor >> 8) & 0xFF); + outb(PIT_CHANNEL_0, divisor >> 8); } void timer_install(void) { - pic_remap(0x20, 0x28); + irq_install_handler(0, pit_handler); pit_set_frequency(1000); - idt_set_gate(32, (uint32_t)pit_handler_asm, 0x08, 0x8E); -} \ No newline at end of file +} diff --git a/timer.h b/timer.h index c7c705c..f541bb4 100644 --- a/timer.h +++ b/timer.h @@ -3,12 +3,16 @@ #include -extern void pit_handler_asm(); +#define PIT_FREQUENCY 1193182 +#define PIT_CHANNEL_0 0x40 +#define PIT_COMMAND 0x43 + +extern void pit_handler_asm(); // defined in pit_handler.s remove this void pit_handler(); void delay(uint32_t milliseconds); void pit_set_frequency(uint32_t frequency); -void pic_remap(int offset1, int offset2); +void pic_remap(int offset1, int offset2); // moved to irq_remap void timer_install(void); -#endif \ No newline at end of file +#endif diff --git a/tss.s b/tss_flush.s similarity index 100% rename from tss.s rename to tss_flush.s diff --git a/tty.c b/tty.c index 06420ae..688baef 100644 --- a/tty.c +++ b/tty.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "string.h" static const size_t VGA_WIDTH = 80; @@ -138,6 +139,7 @@ void terminal_writestring(const char *data) terminal_write(data, strlen(data)); } +// Існуюча функція для виводу одного рядка void terminal_printc(const char *data) { while (*data) @@ -156,6 +158,86 @@ void terminal_printc(const char *data) } } +void itoa(int value, char *str, int base) +{ + char *rc; + char *ptr; + char *low; + + if (value < 0 && base == 10) + { + *str++ = '-'; + value = -value; + } + + rc = ptr = str; + do + { + *ptr++ = "0123456789abcdef"[value % base]; + value /= base; + } while (value); + + *ptr-- = '\0'; + + for (low = rc; low < ptr; low++, ptr--) + { + char tmp = *low; + *low = *ptr; + *ptr = tmp; + } +} + +void terminal_printf_int(int value) +{ + char buffer[12]; + itoa(value, buffer, 10); + terminal_printf(buffer); +} + +void terminal_printf_hex(unsigned int value) +{ + char buffer[12]; + itoa(value, buffer, 16); + terminal_printf(buffer); +} + +void terminal_printf(const char *format, ...) +{ + va_list args; + va_start(args, format); + + const char *p = format; + while (*p) + { + if (*p == '%' && (*(p + 1) == 's' || *(p + 1) == 'd' || *(p + 1) == 'x')) + { + p++; + if (*p == 's') + { + const char *str = va_arg(args, const char *); + terminal_printc(str); + } + else if (*p == 'd') + { + int value = va_arg(args, int); + terminal_printf_int(value); + } + else if (*p == 'x') + { + unsigned int value = va_arg(args, unsigned int); + terminal_printf_hex(value); + } + } + else + { + terminal_putchar(*p); + } + p++; + } + + va_end(args); +} + void terminal_update_cursor(void) { uint16_t pos = terminal_row * VGA_WIDTH + terminal_column; diff --git a/tty.h b/tty.h index 56641bc..deac756 100644 --- a/tty.h +++ b/tty.h @@ -10,6 +10,7 @@ void terminal_putentryat(char c, uint8_t color, size_t x, size_t y); void terminal_putchar(char c); void terminal_write(const char *data, size_t size); void terminal_writestring(const char *data); +void terminal_printf(const char *data, ...); void terminal_printc(const char *data); void terminal_update_cursor(void); void terminal_clear(void); diff --git a/user_space.c b/user_space.c index 34559bc..67f0240 100644 --- a/user_space.c +++ b/user_space.c @@ -1,9 +1,5 @@ -#include "user_space.h" -#include "gdt.h" - void enter_user_space(void) { - set_kernel_stack(0x110); // 128KB ?? WHY? ?? asm volatile("cli; \ mov $0x23, %ax; \ mov %ax, %ds; \ @@ -22,4 +18,27 @@ void enter_user_space(void) iret; \ 1: \ "); +} + +void enter_user_space_v2() +{ + asm volatile("cli; \ + mov $0x23, %ax; \ + mov %ax, %ds; \ + mov %ax, %es; \ + mov %ax, %fs; \ + mov %ax, %gs; \ + mov %esp, %eax; \ + push $0x23; \ + push %eax; \ + pushf; \ + pop %eax; \ + or $0x200, %eax; \ + push %eax; \ + push $0x1B; \ + push $user_code_entry; \ + iret; \ + user_code_entry: \ + call user_main; \ + "); } \ No newline at end of file diff --git a/user_space.h b/user_space.h index 7102d6a..3d8dc70 100644 --- a/user_space.h +++ b/user_space.h @@ -2,5 +2,6 @@ #define _USER_SPACE_H void enter_user_space(void); +void enter_user_space_v2(void); #endif \ No newline at end of file