diff --git a/arch/i386/boot.s b/arch/i386/boot.s index 17ce395..93820cd 100755 --- a/arch/i386/boot.s +++ b/arch/i386/boot.s @@ -81,141 +81,11 @@ load_gdt: jmp 0x08:flush flush: ret - -%macro ISR 1 - global isr%1 - isr%1: - cli - push byte 0 - push byte %1 - jmp isr_common -%endmacro - -%macro ISR_ERR 1 - global isr%1 - isr%1: - cli - push byte %1 - jmp isr_common -%endmacro - -%macro IRQ 2 - global irq%1 - irq%1: - cli - push byte 0 - push byte %2 - jmp irq_common -%endmacro - -ISR 0 -ISR 1 -ISR 2 -ISR 3 -ISR 4 -ISR 5 -ISR 6 -ISR 7 -ISR_ERR 8 -ISR 9 -ISR_ERR 10 -ISR_ERR 11 -ISR_ERR 12 -ISR_ERR 13 -ISR_ERR 14 -ISR 15 -ISR 16 -ISR_ERR 17 -ISR 18 -ISR 19 -ISR 20 -ISR 21 -ISR 22 -ISR 23 -ISR 24 -ISR 25 -ISR 26 -ISR 27 -ISR 28 -ISR 29 -ISR_ERR 30 -ISR 31 - -IRQ 0, 32 -IRQ 1, 33 -IRQ 2, 34 -IRQ 3, 35 -IRQ 4, 36 -IRQ 5, 37 -IRQ 6, 38 -IRQ 7, 39 -IRQ 8, 40 -IRQ 9, 41 -IRQ 10, 42 -IRQ 11, 43 -IRQ 12, 44 -IRQ 13, 45 -IRQ 14, 46 -IRQ 15, 47 - -[EXTERN fault_handler] - -isr_common: - 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 - -[EXTERN irq_handler] - -irq_common: - 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 [GLOBAL idt_load] [EXTERN idtp] idt_load: - lidt [eax] + lidt [idtp] ret diff --git a/arch/i386/sys_clock.c b/arch/i386/sys_clock.c index 9c0e067..f53907d 100755 --- a/arch/i386/sys_clock.c +++ b/arch/i386/sys_clock.c @@ -1,10 +1,12 @@ #include -#include +#include #include +#include size_t timer_ticks = 0; size_t flag = 0; -void timer_handler(registers_t* r) { +void timer_handler(struct int_frame* r) { + gdb_end(); timer_ticks++; if(timer_ticks % 18 == 0) { @@ -14,8 +16,11 @@ void timer_handler(registers_t* r) { serial_print(0x3F8, "Tock."); } } + + if(timer_ticks > 18) + timer_ticks = 0; } void timer_install() { - irq_install_handler(0, timer_handler); + irq_install_handler(0, &timer_handler); } \ No newline at end of file diff --git a/include/kernel.h b/include/kernel.h new file mode 100644 index 0000000..2e72732 --- /dev/null +++ b/include/kernel.h @@ -0,0 +1,12 @@ +/************************ + *** Team Kitty, 2019 *** + *** ProjectRED *** + ***********************/ + +#include +#include +#include + +void panic(char*); + +void gdb_end(); \ No newline at end of file diff --git a/include/kernel/descriptor_tables.h b/include/kernel/descriptor_tables.h index cab4560..6aaa2c7 100755 --- a/include/kernel/descriptor_tables.h +++ b/include/kernel/descriptor_tables.h @@ -2,20 +2,62 @@ #include #include - - -void gdt_set_gate(int, unsigned long, unsigned long, unsigned char, unsigned char); +void gdt_set_gate(int, uint32_t, uint32_t, uint8_t, uint8_t); void gdt_install(); +struct gdt_item { + uint16_t low_limit; + uint16_t low_base; + uint8_t middle_base; + uint8_t access; + uint8_t granular; + uint8_t high_base; +} __attribute__((packed)); //Prevent compiler optimisation by packing + +struct gdt_ptr { + uint16_t limit; + unsigned int base; +} __attribute__((packed)); + +struct gdt_item gdt[3]; //3-entry gdt +struct gdt_ptr gp; + +extern void load_gdt(); + void idt_set_gate(unsigned char, unsigned long, unsigned short, unsigned char); void idt_install(); -typedef struct registers { - uint32_t ds; - uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; - uint32_t int_no, err_code; - uint32_t eip, cs, eflags, useresp, ss; -} registers_t; +struct idt_entry { + unsigned short base_low; + unsigned short selector; + unsigned char always0; + unsigned char flags; + unsigned short base_high; +} __attribute__((packed)); + +struct idt_ptr { + unsigned short limit; + unsigned int base; +}__attribute__((packed)); + +struct idt_entry idt[256]; //interrupt table of 256 entries +struct idt_ptr idtp; //pointer to idt table + +struct int_frame { + void (*eip) (void); + uint16_t cs, :16; + uint32_t eflags; + void* esp; + uint16_t ss, :16; +} __attribute__((packed)); + +void isr_common(struct int_frame*, size_t); + +void isr_error_common(struct int_frame*, size_t, size_t); + +void irq_common(struct int_frame*, size_t); + +extern void idt_load(); //These are all reserved by Intel, and need to be here. extern void isr0(); @@ -73,13 +115,13 @@ static void* irq_routines[16] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -void irq_install_handler(int irq, void (*handler)(registers_t* r)); +void irq_install_handler(int irq, void (*handler)(struct int_frame* r)); void irq_uninstall_handler(int); void irq_install(); -void irq_handler(registers_t*); +void irq_remap(); void timer_install(); @@ -116,4 +158,4 @@ static const char* exception_messages[] = { "Reserved", "Reserved", "Reserved" -}; \ No newline at end of file +}; diff --git a/include/kernel/gdt.h b/include/kernel/gdt.h deleted file mode 100755 index 780ba8f..0000000 --- a/include/kernel/gdt.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -void gdt_set_gate(int, unsigned long, unsigned long, unsigned char, unsigned char); -void gdt_install(); \ No newline at end of file diff --git a/include/kernel/idt.h b/include/kernel/idt.h deleted file mode 100755 index c3f9aa7..0000000 --- a/include/kernel/idt.h +++ /dev/null @@ -1,19 +0,0 @@ -#include - -struct idt_entry { - unsigned short base_low; - unsigned short selector; - unsigned char always0; - unsigned char flags; - unsigned short base_high; -} __attribute__((packed)); - -struct idt_ptr { - unsigned short limit; - unsigned int base; -}__attribute__((packed)); - -struct idt_entry idt[256]; //interrupt table of 256 entries -struct idt_ptr idtp; //pointer to idt table - -extern void idt_load(); diff --git a/include/kernel/multiboot.h b/include/kernel/multiboot.h new file mode 100644 index 0000000..bb9602d --- /dev/null +++ b/include/kernel/multiboot.h @@ -0,0 +1,278 @@ + /* multiboot.h - Multiboot header file. */ + /* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + #ifndef MULTIBOOT_HEADER + #define MULTIBOOT_HEADER 1 + + /* How many bytes from the start of the file we search for the header. */ + #define MULTIBOOT_SEARCH 8192 + #define MULTIBOOT_HEADER_ALIGN 4 + + /* The magic field should contain this. */ + #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + + /* This should be in %eax. */ + #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + + /* Alignment of multiboot modules. */ + #define MULTIBOOT_MOD_ALIGN 0x00001000 + + /* Alignment of the multiboot info structure. */ + #define MULTIBOOT_INFO_ALIGN 0x00000004 + + /* Flags set in the 'flags' member of the multiboot header. */ + + /* Align all boot modules on i386 page (4KB) boundaries. */ + #define MULTIBOOT_PAGE_ALIGN 0x00000001 + + /* Must pass memory information to OS. */ + #define MULTIBOOT_MEMORY_INFO 0x00000002 + + /* Must pass video information to OS. */ + #define MULTIBOOT_VIDEO_MODE 0x00000004 + + /* This flag indicates the use of the address fields in the header. */ + #define MULTIBOOT_AOUT_KLUDGE 0x00010000 + + /* Flags to be set in the 'flags' member of the multiboot info structure. */ + + /* is there basic lower/upper memory information? */ + #define MULTIBOOT_INFO_MEMORY 0x00000001 + /* is there a boot device set? */ + #define MULTIBOOT_INFO_BOOTDEV 0x00000002 + /* is the command-line defined? */ + #define MULTIBOOT_INFO_CMDLINE 0x00000004 + /* are there modules to do something with? */ + #define MULTIBOOT_INFO_MODS 0x00000008 + + /* These next two are mutually exclusive */ + + /* is there a symbol table loaded? */ + #define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 + /* is there an ELF section header table? */ + #define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + + /* is there a full memory map? */ + #define MULTIBOOT_INFO_MEM_MAP 0x00000040 + + /* Is there drive info? */ + #define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + + /* Is there a config table? */ + #define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + + /* Is there a boot loader name? */ + #define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + + /* Is there a APM table? */ + #define MULTIBOOT_INFO_APM_TABLE 0x00000400 + + /* Is there video information? */ + #define MULTIBOOT_INFO_VBE_INFO 0x00000800 + #define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 + + #ifndef ASM_FILE + + typedef unsigned char multiboot_uint8_t; + typedef unsigned short multiboot_uint16_t; + typedef unsigned int multiboot_uint32_t; + typedef unsigned long long multiboot_uint64_t; + + struct multiboot_header + { + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; + }; + + /* The symbol table for a.out. */ + struct multiboot_aout_symbol_table + { + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; + }; + typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + + /* The section header table for ELF. */ + struct multiboot_elf_section_header_table + { + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; + }; + typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + + struct multiboot_info + { + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; + #define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 + #define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 + #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union + { + struct + { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; + }; + typedef struct multiboot_info multiboot_info_t; + + struct multiboot_color + { + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; + }; + + struct multiboot_mmap_entry + { + multiboot_uint32_t size; + multiboot_uint64_t addr; + multiboot_uint64_t len; + #define MULTIBOOT_MEMORY_AVAILABLE 1 + #define MULTIBOOT_MEMORY_RESERVED 2 + #define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 + #define MULTIBOOT_MEMORY_NVS 4 + #define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; + } __attribute__((packed)); + typedef struct multiboot_mmap_entry multiboot_memory_map_t; + + struct multiboot_mod_list + { + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; + }; + typedef struct multiboot_mod_list multiboot_module_t; + + /* APM BIOS info. */ + struct multiboot_apm_info + { + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; + }; + + #endif /* ! ASM_FILE */ + + #endif /* ! MULTIBOOT_HEADER */ + + + + diff --git a/include/kernel/serial.h b/include/kernel/serial.h index 18b20ba..26ae4fa 100755 --- a/include/kernel/serial.h +++ b/include/kernel/serial.h @@ -2,20 +2,20 @@ #include #include -extern void init_serial(); +void init_serial(); -extern void serial_set_baud_rate(uint16_t, uint16_t); +void serial_set_baud_rate(uint16_t, uint16_t); -extern void serial_configure_line(uint16_t); +void serial_configure_line(uint16_t); -extern void serial_configure_buffers(uint16_t); +void serial_configure_buffers(uint16_t); -extern void serial_write(uint16_t, const char); +void serial_write(uint16_t, const char); -extern void serial_configure_modem(uint16_t); +void serial_configure_modem(uint16_t); -extern int serial_check_tqueue(uint16_t); +int serial_check_tqueue(uint16_t); -extern void serial_print(uint16_t, const char*); +void serial_print(uint16_t, const char*); -extern void serial_printf(const char*, ...); +void serial_printf(uint16_t, const char*, ...); diff --git a/kernel/descriptor_tables.c b/kernel/descriptor_tables.c new file mode 100755 index 0000000..0bb2907 --- /dev/null +++ b/kernel/descriptor_tables.c @@ -0,0 +1,257 @@ +/************************ + *** Team Kitty, 2019 *** + *** ProjectRED *** + ***********************/ + +/* This file combines the implementation + of IDT and GDT, Interrupt Descriptor + Table and Global Descriptor Table + respectively. + + These are in the same file, because + otherwise the GDT file would be + roughly 10 lines long. + + This file contains the code to set up + and configure the PIC, to configure and + load the IDT and GDT through the processor, + and other functions that are uniquely + related to the above tasks. */ + +#include +#include +#include + + /* + * The GDT gate setting function. + * Defines where the important parts of memory are. + * + * @param num: GDT position ID. + * @param base: Start of the memory block this entry is for. + * @param limit: End of the above memory block. + * @param access: The ring number associated with this entry. + * @param gran: Granularity - how big the assigned chunks of memory are. + */ +void gdt_set_gate(int num, uint32_t base, + uint32_t limit, uint8_t access, + uint8_t gran) { + + /* The function is mostly shifts and masks, nothing too special. */ + /* The gdt[] array is defined in the descriptor_tables header. */ + gdt[num].low_base = (base & 0xFFFF); + gdt[num].middle_base = (base >> 16) & 0xFF; + gdt[num].high_base = (base >> 24) & 0xFF; + + gdt[num].low_limit = (limit & 0xFFFF); + gdt[num].granular = ((limit >> 16) & 0x0F); + + gdt[num].granular = (gran & 0xF0); + gdt[num].access = access; +} + +/* + The function that puts it all together. It sets up the pointer, + fills it in, and tells the CPU to load the new GDT immediately. + */ +void gdt_install() { + /* gp = GDT Pointer, defined in descriptor_tables header. */ + gp.limit = (sizeof(struct gdt_item) * 3) - 1; + gp.base = (uint32_t)&gdt; + + /* The CPU requires that the first gate always be null. */ + gdt_set_gate(0, 0, 0, 0, 0); + + /* This is the Code Segment, it starts at 0 and ends at 4GB, meaning + that it encompasses the entirety of available memory. + + This defines the code segment with exclusive execute permission, + allowing the kernel to execute itself. */ + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + + /* The Data Segment, the same range as the Code Segment (0 - 4GB) + but with Read/Write permission, allowing the kernel to modify RAM. */ + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + /* Lastly, call the external ASM function that loads the GDT into the + processor. */ + load_gdt(); +} + +/* + Identically to the GDT set gate function, but for the IDT array. + * @param num: IDT access ID + * @param base: Start of memory block + * @param sel: Selector. I have no idea what that means. + * @param flags: Permission levels and all that stuff. + */ +void idt_set_gate(unsigned char num, + unsigned long base, + unsigned short sel, + unsigned char flags) { + /* Again, it's all shifts and masks. Nothing special. */ + idt[num].base_low = base & 0xFFFF; + idt[num].base_high = (base >> 16) & 0xFFFF; + + idt[num].selector = sel; + idt[num].always0 = 0; + + /* Set the permission level to 3. All interrupts are from ring 3. */ + idt[num].flags = flags | 0x60; +} + +/* + Same as GDT_install: sets up the pointers and fills in the contents, then passes + it on to the CPU to be loaded. + */ +void idt_install() { + /* idtp is the IDT Pointer, defined in the descriptor_tables header. */ + idtp.limit = (sizeof (struct idt_entry) * 256) - 1; + idtp.base = (uint32_t) &idt; + + memset(&idt, 0, sizeof(struct idt_entry) * 256); + + /* Manually fill in the array - these functions are defined in + interrupts.c */ + + 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); + + idt_load(); + irq_install(); + +} + +/* A simple wrapper that adds a function pointer to the IRQ array. */ +void irq_install_handler(int irq, void (*handler)(struct int_frame* r)) { + irq_routines[irq] = handler; +} + +/* A simple wrapper that unlinks a function pointer, rendering the IRQ unused. */ +void irq_uninstall_handler(int irq) { + irq_routines[irq] = 0; +} + +/* + Since the PIC starts with irq values that overlap with the CPU default ISR + lines, it's necessary to remap the PIC. + + Doing this also means that we have to completely reinitialize the PIC, which + is why this is so long. + */ + +void irq_remap() { + /* 0x20 is the Master PIC, + 0xA0 is the Slave PIC. */ + 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); +} + +/* A handler function to perform all of the required steps in one function call. + TODO: move all Descriptor Table things to a single callable function. +*/ +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); +} + + +/* All of the ISR routines call this function for now. + ! This function is NOT leaf, and it might clobber the stack. + ! Be careful! +*/ +void isr_common(struct int_frame* r, size_t exception) { + /* We only have the capacity to handle 32 exceptions. This is a limitation of the CPU. */ + if(exception < 32) { + /* exception_messages is an array defined in descriptor_tables.h */ + serial_print(0x3F8, exception_messages[exception]); + serial_print(0x3F8, " Exception.\r\n"); + panic(exception_messages[exception]); + } +} + +/* The common handler for exceptions that throw error codes, which give us useful insight + into what went wrong. In pure Curle style, though, we just ignore the error code. */ +void isr_error_common(struct int_frame* r, size_t exception, size_t error) { + + if(exception < 32) { + serial_print(0x3F8, exception_messages[exception]); + serial_printf(0x3F8, " Exception. Context given: %d\r\n", error); + panic(exception_messages[exception]); + } + +} + +/* Likewise, this function is common to all IRQ handlers. It calls the assigned routine, + which was set up earlier by irq_install.*/ +void irq_common(struct int_frame* r, size_t interrupt) { + void (*handler)(struct int_frame* r); + serial_print(0x3F8, "[INFO] Received IRQ: " + interrupt); + /* We set all uninitialized routines to 0, so the if(handler) check here allows us to + safely tell whether we've actually got something for this IRQ. */ + handler = irq_routines[interrupt]; + if(handler) + handler(r); + + /* The Slave PIC must be told it's been read in order to receive another 8+ IRQ. */ + if(interrupt > 7) + outb(0xA0, 0x20); + + /* In either case, we tell the Master PIC it's been read to receive any IRQ. */ + outb(0x20, 0x20); +} diff --git a/kernel/gdt.c b/kernel/gdt.c deleted file mode 100755 index ea727b7..0000000 --- a/kernel/gdt.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include - - -struct gdt_item { - uint16_t low_limit; - uint16_t low_base; - uint8_t middle_base; - uint8_t access; - uint8_t granular; - uint8_t high_base; -} __attribute__((packed)); //Prevent compiler optimisation by packing - -struct gdt_ptr { - uint16_t limit; - unsigned int base; -} __attribute__((packed)); - -struct gdt_item gdt[3]; //3-entry gdt -struct gdt_ptr gp; - -extern void load_gdt(); - -void gdt_set_gate(int num, uint32_t base, - uint32_t limit, uint8_t access, - uint8_t gran) { - //Implementation taken from osdever.net - gdt[num].low_base = (base & 0xFFFF); - gdt[num].middle_base = (base >> 16) & 0xFF; - gdt[num].high_base = (base >> 24) & 0xFF; - - gdt[num].low_limit = (limit & 0xFFFF); - gdt[num].granular = ((limit >> 16) & 0x0F); - - gdt[num].granular = (gran & 0xF0); - gdt[num].access = access; -} - -void gdt_install() { - gp.limit = (sizeof(struct gdt_item) * 3) - 1; - gp.base = (unsigned int)&gdt; - - - gdt_set_gate(0, 0, 0, 0, 0); //NULL item - - //Code Segment - base 0, 4KiB granularity, 4GiB limit - gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); - - //Data Segment - ditto - gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); - - //Apply changes - load_gdt(); -} \ No newline at end of file diff --git a/kernel/idt.c b/kernel/idt.c deleted file mode 100755 index ba49a88..0000000 --- a/kernel/idt.c +++ /dev/null @@ -1,142 +0,0 @@ -#include -#include - -struct idt_entry { - unsigned short base_low; - unsigned short selector; - unsigned char always0; - unsigned char flags; - unsigned short base_high; -} __attribute__((packed)); - -struct idt_ptr { - unsigned short limit; - unsigned int base; -} __attribute__((packed)); - -struct idt_entry idt[256]; // Interrupt table of 256 entries -struct idt_ptr idtp; // Pointer to idt table - -extern void idt_load(); - -void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags) { - idt[num].base_low = base & 0xFFFF; - idt[num].base_high = (base >> 16) & 0xFFFF; - - idt[num].selector = sel; - idt[num].always0 = 0; - - // Must be uncommented when we get to usermode - it sets the permission - // level to 3 - idt[num].flags = flags; // | 0x60; -} - -void idt_install() { - idtp.limit = (sizeof (struct idt_entry) * 256) - 1; - idtp.base = (uint16_t) &idt; - - memset(&idt, 0, sizeof(struct idt_entry) * 256); - - 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); - - idt_load(); - irq_install(); - -} - -void irq_install_handler(int irq, void (*handler)(registers_t* r)) { - irq_routines[irq] = handler; -} - -void irq_uninstall_handler(int irq) { - irq_routines[irq] = 0; -} - -void irq_remap() { - 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 fault_handler(registers_t *r) { - if(r->int_no < 32) { - serial_print(exception_messages[r->int_no], strlen(exception_messages[r->int_no])); - serial_print(" Exception. Halting.\r\n"); - for(;;); - } -} - -void irq_handler(registers_t *r) { - void (*handler)(registers_t* r); - - serial_print(0x3F8, "[INFO] Received IRQ: " + r->int_no); - handler = irq_routines[r->int_no - 32]; - if(handler) - handler(r); - - if(r->int_no > 39) - outb(0xA0, 0x20); - - outb(0x20, 0x20); -} diff --git a/kernel/interrupts.c b/kernel/interrupts.c new file mode 100644 index 0000000..1b87f48 --- /dev/null +++ b/kernel/interrupts.c @@ -0,0 +1,212 @@ +/************************ + *** Team Kitty, 2019 *** + *******ProjectRED******* + ***********************/ + +/* This file contains all of the ISR and IRQ + * (Interrupt Service Request) functions. + * + * As they use the GCC interrupt attribute, + * this file must be compiled without red- + * zone protection, thus all of these + * functions are in their own file to + * accomodate this. + * + * Calling a function like so: + * + * __attribute__((interrupt)) isr1(registers_t* frame) {} + * + * allows the function to be used to serve + * interrupts - GCC compiles it under unique + * conditions, as it preserves the state of + * the processor and stack between execution, + * as well as using the IRET instruction to + * return to the middle of the previous function. + * + * There is also a version of the interrupt + * attribute which allows for error handlers, + * these having a size_t input as an error code. + */ + + +#include +#include +#include "kernel/descriptor_tables.h" + +#ifdef __x86_64__ +typedef unsigned long long int uword_t; +#else +typedef unsigned int uword_t; +#endif + +/* The interrupt numbers, their meanings, and + * special information is laid out below: + * + * 0 - Divide by Zero + * 1 - Debug + * 2 - Non-Maskable + * 3 - Breakpoint + * 4 - Into Detected Overflow + * 5 - Out of Bounds + * 6 - Invalid Opcode + * 7 - No Coprocessor + * 8 - Double Fault * (With Error) + * 9 - Coprocessor Segment Overrun + * 10 - Bad TSS * (With Error) + * 11 - Segment Not Present * (With Error) + * 12 - Stack Fault * (With Error) + * 13 - General Protection Fault * (With Error) + * 14 - Page Fault * (With Error) + * 15 - Unknown Interrupt + * 16 - Coprocessor Fault + * 17 - Alignment Check + * 18 - Machine Check + * 19 to 31 - Reserved + */ + +__attribute__((interrupt)) void isr0(struct int_frame* r) { + isr_common(r, 0); +} +__attribute__((interrupt)) void isr1(struct int_frame* r) { + isr_common(r, 1); +} +__attribute__((interrupt)) void isr2(struct int_frame* r) { + isr_common(r, 2); +} +__attribute__((interrupt)) void isr3(struct int_frame* r) { + isr_common(r, 3); +} +__attribute__((interrupt)) void isr4(struct int_frame* r) { + isr_common(r, 4); +} +__attribute__((interrupt)) void isr5(struct int_frame* r) { + isr_common(r, 5); +} +__attribute__((interrupt)) void isr6(struct int_frame* r) { + isr_common(r, 6); +} +__attribute__((interrupt)) void isr7(struct int_frame* r) { + isr_common(r, 7); +} +__attribute__((interrupt)) void isr8(struct int_frame* r, size_t error) { + isr_error_common(r, 8, error); +} +__attribute__((interrupt)) void isr9(struct int_frame* r) { + isr_common(r, 9); +} +__attribute__((interrupt)) void isr10(struct int_frame* r, size_t error) { + isr_error_common(r, 10, error); +} +__attribute__((interrupt)) void isr11(struct int_frame* r, size_t error) { + isr_error_common(r, 11, error); +} +__attribute__((interrupt)) void isr12(struct int_frame* r, size_t error) { + isr_error_common(r, 12, error); +} +__attribute__((interrupt)) void isr13(struct int_frame* r, size_t error) { + isr_error_common(r, 13, error); +} +__attribute__((interrupt)) void isr14(struct int_frame* r, size_t error) { + isr_error_common(r, 14, error); +} +__attribute__((interrupt)) void isr15(struct int_frame* r) { + isr_common(r, 15); +} +__attribute__((interrupt)) void isr16(struct int_frame* r) { + isr_common(r, 16); +} +__attribute__((interrupt)) void isr17(struct int_frame* r) { + isr_common(r, 17); +} +__attribute__((interrupt)) void isr18(struct int_frame* r) { + isr_common(r, 18); +} +__attribute__((interrupt)) void isr19(struct int_frame* r) { + isr_common(r, 19); +} +__attribute__((interrupt)) void isr20(struct int_frame* r) { + isr_common(r, 20); +} +__attribute__((interrupt)) void isr21(struct int_frame* r) { + isr_common(r, 21); +} +__attribute__((interrupt)) void isr22(struct int_frame* r) { + isr_common(r, 22); +} +__attribute__((interrupt)) void isr23(struct int_frame* r) { + isr_common(r, 23); +} +__attribute__((interrupt)) void isr24(struct int_frame* r) { + isr_common(r, 24); +} +__attribute__((interrupt)) void isr25(struct int_frame* r) { + isr_common(r, 25); +} +__attribute__((interrupt)) void isr26(struct int_frame* r) { + isr_common(r, 26); +} +__attribute__((interrupt)) void isr27(struct int_frame* r) { + isr_common(r, 27); +} +__attribute__((interrupt)) void isr28(struct int_frame* r) { + isr_common(r, 28); +} +__attribute__((interrupt)) void isr29(struct int_frame* r) { + isr_common(r, 29); +} +__attribute__((interrupt)) void isr30(struct int_frame* r) { + isr_common(r, 30); +} +__attribute__((interrupt)) void isr31(struct int_frame* r) { + isr_common(r, 31); +} + + +__attribute__((interrupt)) void irq0(struct int_frame* r) { + irq_common(r, 0); +} +__attribute__((interrupt)) void irq1(struct int_frame* r) { + irq_common(r, 1); +} +__attribute__((interrupt)) void irq2(struct int_frame* r) { + irq_common(r, 2); +} +__attribute__((interrupt)) void irq3(struct int_frame* r) { + irq_common(r, 3); +} +__attribute__((interrupt)) void irq4(struct int_frame* r) { + irq_common(r, 4); +} +__attribute__((interrupt)) void irq5(struct int_frame* r) { + irq_common(r, 5); +} +__attribute__((interrupt)) void irq6(struct int_frame* r) { + irq_common(r, 6); +} +__attribute__((interrupt)) void irq7(struct int_frame* r) { + irq_common(r, 7); +} +__attribute__((interrupt)) void irq8(struct int_frame* r) { + irq_common(r, 8); +} +__attribute__((interrupt)) void irq9(struct int_frame* r) { + irq_common(r, 9); +} +__attribute__((interrupt)) void irq10(struct int_frame* r) { + irq_common(r, 10); +} +__attribute__((interrupt)) void irq11(struct int_frame* r) { + irq_common(r, 11); +} +__attribute__((interrupt)) void irq12(struct int_frame* r) { + irq_common(r, 12); +} +__attribute__((interrupt)) void irq13(struct int_frame* r) { + irq_common(r, 13); +} +__attribute__((interrupt)) void irq14(struct int_frame* r) { + irq_common(r, 14); +} +__attribute__((interrupt)) void irq15(struct int_frame* r) { + irq_common(r, 15); +} \ No newline at end of file diff --git a/kernel/isr.c b/kernel/isr.c deleted file mode 100755 index 8380c6f..0000000 --- a/kernel/isr.c +++ /dev/null @@ -1,5 +0,0 @@ -#include -#include -#include -#include - diff --git a/kernel/kernel.c b/kernel/kernel.c index a0b3cd1..974a90d 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,15 +1,13 @@ -///////////////////////////// -/// /// -/// Team Kitty, 2019 /// -/// ProjectRED /// -/// /// -///////////////////////////// +/************************ + *** Team Kitty, 2019 *** + *** ProjectRED *** + ***********************/ //#include - +#include #include -#include #include +#include void gdb_end() {} /* GDB Debugging stump */ @@ -77,9 +75,9 @@ int kernel_main(void) { /* A stub causing a Divide by Zero error. */ - //serial_print(0x3F8, "[DEBUG] Attempting a Divide by Zero error.\r\n"); - //char div = (5 / 0); - //serial_print(0x3F8, "[DEBUG] Survived the error!\r\n"); + serial_print(0x3F8, "[DEBUG] Attempting a Divide by Zero error.\r\n"); + char div = (5 / 0); + serial_print(0x3F8, "[DEBUG] Survived the error!\r\n"); gdb_end(); /* Everything is done. The last debug routine. */ return 0; diff --git a/kernel/utils.c b/kernel/utils.c index 31bf598..1ede1ec 100644 --- a/kernel/utils.c +++ b/kernel/utils.c @@ -1,9 +1,19 @@ +/************************ + *** Team Kitty, 2019 *** + *** ProjectRED *** + ***********************/ + #include +#include #include #include #include #include +/* + Returns the length of a given string. + * @param string: String to count + */ size_t strlen(const char* string) { size_t size = 0; while (string[size]) @@ -11,16 +21,33 @@ size_t strlen(const char* string) { return size; } -unsigned char inb(unsigned short port) { - unsigned char ptr; +/* + Read data from a port. Effectively communicates with hardware. + * @param port: The port number to read, as a hex short. + */ +uint8_t inb(uint16_t port) { + uint8_t ptr; asm volatile("inb %1, %0" : "=a" (ptr) : "dN" (port)); return ptr; } -void outb(unsigned short port, unsigned char data) { +/* + Write data to a port. Effectively communicates with hardware. + * @param port: The port to read + * @param data: A pointer to which the data will be stored. + + */ +void outb(uint16_t port, uint8_t data) { asm volatile("outb %1, %0" : : "dN" (port), "a" (data)); } + +/* + Memory Copy. Required by GCC. + * @param dest: The destination in memory, to which the data will be copied. + * @param src: The source of the data which will be copied. + * @param n: The length of the copy, in byets. + */ void memcpy(void* dest, void* src, size_t n) { char* src_c = (char*)src; char* dest_c = (char*)dest; @@ -30,16 +57,29 @@ void memcpy(void* dest, void* src, size_t n) { } } +/* + Memory Set. Required by GCC> + * @param src: The data to be overwritten. + * @param chr: The byte to overwrite the source with. + * @param n: How many bytes to overwrite. +*/ void memset(void* src, int chr, size_t n) { - unsigned char* ptr = src; + uint8_t* ptr = src; while(n--) { - *ptr++ = (unsigned char) chr; + *ptr++ = (uint8_t) chr; } } + /* + Turns an integer into a C-str. + * @note Inefficient and unsafe. + * @param num: The number to convert + * @param string: The string to be written into. + */ + void int_to_ascii(int num, char* string) { size_t i = 0; //Counter. - //TODO: Convert this to a for-loop? + // TODO: Convert this to a for-loop? int32_t calc = 0; bool negative = false; @@ -49,32 +89,40 @@ void int_to_ascii(int num, char* string) { return; } + // TODO: Implement this as an abs() function? if(num < 0) { - negative = true; num = -num; - } - - while(num != 0) { - calc = num % 10; - num = num / 10; - calc += 48; - - string[i] = calc; - i++; - } - - if(negative) { string[i] = '-'; i++; } + while(num != 0) { + // Overall this looks pretty confusing. + // TODO: cleanup? + calc = num % 10; // Gets the lowest digit, + num = num / 10; // Shifts the other digits down to prepare for the next iteration. + calc += 48; // Convert the number to an ASCII value + + string[i] = calc;// Set the current position in the string + i++; // Increase for the next number. + } + + // ! This code does weird things. + // It serves an unknown purpose, and should not be used, but is left here just in case. + /* for(size_t j = 0; j < i/2; j++) { calc = string[j]; string[j] = string[i-j-1]; string[j-i-1] = calc; } + */ } + /* + A strange version of the above function. Different way of doing the same thing? + * @param num: the number to convert. Must be positive + * @retval The new string. + */ char* itoc(size_t num) { char* result; size_t tmp_value; @@ -87,6 +135,12 @@ char* itoc(size_t num) { return result; } + +/* + Same as itoa, but for hexadecimal. + * @param num: Number to convert + * @param string: String pointer to put the converted number. +*/ void int_to_hex(int num, char* string) { empty_string(string); @@ -107,6 +161,11 @@ void int_to_hex(int num, char* string) { } } + /* + Converts a C-str to an empty C-str. :) + * @param string: The string to empty. + */ + void empty_string(char* string) { size_t len = strlen(string); @@ -114,3 +173,20 @@ void empty_string(char* string) { string[i] = '\0'; } } + + + /* + The signal that everything has gone wrong. + Equivalent to a linux kernel panic and a Windows Blue Screen. + + TODO: Needs to be re-engineered to give as much useful information as possible. Ideally also have a visual interface, XP installer style. + + * @param cause: A string, telling the basic reason for the crash. + */ +void panic(char* cause) { + term_writes("\n\n>>>> PANIC <<<<\nCaused by: "); + term_writes(cause); + + for(;;); + +} diff --git a/makefile b/makefile index 92b8a5e..1ae0951 100755 --- a/makefile +++ b/makefile @@ -1,8 +1,9 @@ DEFAULT_HOST:=i686-elf HOST?=DEFAULT_HOST HOSTARCH:=i386 +CC:=$(PREFIX)/bin/$(DEFAULT_HOST)-gcc -CFLAGS?= -O2 -g -m32 -fno-pie -fno-stack-protector -Wl,--build-id=none +CFLAGS?= -O0 -g -fno-pie -fno-stack-protector -Wl,--build-id=none CPPFLAGS?= LDFLAGS?= LIBS?= @@ -31,8 +32,8 @@ KERNEL_OBJS= \ $(KERNEL_ARCH_OBJS) \ kernel/utils.o \ kernel/serial.o \ -kernel/gdt.o \ -kernel/idt.o \ +kernel/interrupts.o \ +kernel/descriptor_tables.o\ kernel/kernel.o OBJS=\ @@ -51,6 +52,9 @@ all: red.kernel red.kernel: $(OBJS) $(ARCHDIR)/linker.ld $(CC) -T $(ARCHDIR)/linker.ld -o $@ $(CFLAGS) $(LINK_LIST) +kernel/interrupts.o: + $(CC) -MD -c kernel/interrupts.c -o $@ -std=gnu11 $(CFLAGS) -mno-red-zone -mgeneral-regs-only $(CPPFLAGS) + .c.o: $(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS) .s.o: @@ -85,4 +89,3 @@ gen-iso: iso -include $(OBJS:.o=.d) -