├── kernel ├── paging.c ├── include │ ├── paging.h │ ├── types.h │ ├── memory.h │ ├── interrupts.h │ ├── io.h │ ├── shell.h │ ├── ata.h │ ├── idt.h │ ├── string.h │ ├── gdt.h │ ├── multiboot.h │ ├── terminal.h │ ├── pci.h │ └── keyboard.h ├── memory.c ├── ata.c ├── idt.c ├── keyboard.c ├── boot.s ├── kernel.c ├── gdt.c ├── pci.c ├── shell.c ├── string.c ├── terminal.c ├── interrupts.c └── io.s ├── 311pres.pptx ├── grub.cfg ├── movetohd.sh ├── .gitignore ├── linker.ld ├── README.md ├── Makefile └── bochsrc.txt /kernel/paging.c: -------------------------------------------------------------------------------- 1 | #include "include/paging.h" 2 | -------------------------------------------------------------------------------- /311pres.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylecs/Kernel/HEAD/311pres.pptx -------------------------------------------------------------------------------- /grub.cfg: -------------------------------------------------------------------------------- 1 | menuentry "kernel" { 2 | multiboot /boot/kernel.elf 3 | } 4 | -------------------------------------------------------------------------------- /kernel/include/paging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | void install_paging(); 4 | -------------------------------------------------------------------------------- /movetohd.sh: -------------------------------------------------------------------------------- 1 | sudo mount /dev/sda4 /mnt/kernel 2 | sudo cp latest.bin /mnt/kernel/boot/kernel.elf 3 | -------------------------------------------------------------------------------- /kernel/include/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /isodir 2 | /out 3 | latest.bin 4 | bochsout.log 5 | bootable.iso 6 | TODO 7 | test_disk.img 8 | movetohd.sh 9 | -------------------------------------------------------------------------------- /kernel/include/memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | 5 | void memcpy(void* src, void* dest, size_t size); 6 | void* kalloc(size_t size); 7 | void memset(void* dst, uint32_t size, uint8_t fill); 8 | -------------------------------------------------------------------------------- /kernel/include/interrupts.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | 5 | typedef struct { 6 | int present: 1; 7 | void* handler; 8 | } interrupt_handler_t; 9 | 10 | void install_interrupt_interface(); 11 | void general_interrupt_handler(int offset); 12 | -------------------------------------------------------------------------------- /linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS 4 | { 5 | . = 1M; 6 | .text BLOCK(4K) : ALIGN(4K) 7 | { 8 | *(.multiboot) 9 | *(.text) 10 | } 11 | .rodata BLOCK(4K) : ALIGN(4K) 12 | { 13 | *(.rodata) 14 | } 15 | .data BLOCK(4K) : ALIGN(4K){ 16 | *(.data) 17 | } 18 | .bss BLOCK(4K) : ALIGN(4K){ 19 | *(COMMON) 20 | *(.bss) 21 | *(.bootstrap_stack) 22 | } 23 | } -------------------------------------------------------------------------------- /kernel/include/io.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | extern void outb(uint16_t port, uint8_t data); 5 | extern uint8_t inb(uint16_t port); 6 | 7 | extern void outw(uint16_t port, uint16_t data); 8 | extern uint16_t inw(uint16_t port); 9 | 10 | extern void outdw(uint16_t port, uint32_t data); 11 | extern uint32_t indw(uint16_t port); 12 | 13 | extern void enable_interrupts(); 14 | extern void disable_interrupts(); 15 | -------------------------------------------------------------------------------- /kernel/include/shell.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | typedef struct command { 5 | uint8_t present; 6 | char* command; 7 | void* callback; 8 | char* description; 9 | } command_t; 10 | 11 | void shell_handle_key(int32_t keycode, char ch); 12 | void shell_initialize(); 13 | void shell_print_kernel(); 14 | void shell_handle_command(); 15 | void shell_reset_buffer(); 16 | void register_command(char* command, void* callback, char* description); 17 | void help_menu(); 18 | void pong(); 19 | -------------------------------------------------------------------------------- /kernel/memory.c: -------------------------------------------------------------------------------- 1 | #include "include/memory.h" 2 | 3 | void memcpy(void* src, void* dst , size_t size){ 4 | uint8_t* bsrc = (uint8_t*)src; 5 | uint8_t* bdst = (uint8_t*)dst; 6 | for(size_t i = 0; i < size; i++){ 7 | bdst[i] = bsrc[i]; 8 | } 9 | } 10 | void memset(void* dst, uint32_t size, uint8_t fill){ 11 | for(uint32_t i = 0; i < size; i++){ 12 | ((uint8_t*)dst)[i] = fill; 13 | } 14 | } 15 | 16 | //this is definately fool-proof ;) 17 | uint8_t* ptr = (uint8_t*) 3145728; 18 | void* kalloc(size_t size){ 19 | void* ret = (void*) ptr; 20 | ptr += size; 21 | ptr+= 2; 22 | return ret; 23 | } 24 | -------------------------------------------------------------------------------- /kernel/include/ata.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "pci.h" 4 | 5 | //Ata status port results 6 | #define ATA_SR_BSY 0x80 // Busy 7 | #define ATA_SR_DRDY 0x40 // Drive ready 8 | #define ATA_SR_DF 0x20 // Drive write fault 9 | #define ATA_SR_DSC 0x10 // Drive seek complete 10 | #define ATA_SR_DRQ 0x08 // Data request ready 11 | #define ATA_SR_CORR 0x04 // Corrected data 12 | #define ATA_SR_IDX 0x02 // Inlex 13 | #define ATA_SR_ERR 0x01 // Error 14 | 15 | typedef struct { 16 | int io_base; 17 | int control; 18 | } ata_device_t; 19 | 20 | void setup_ata(); 21 | void setup_device(pci_device_t* device); 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kernel 2 | A simple x86 kernel written in C and Assembly 3 | 4 | ## Demo 5 | *Click to play* 6 | 7 | [![Demo Video HERE](https://img.youtube.com/vi/McJ6sdyONg8/0.jpg)](https://www.youtube.com/watch?v=McJ6sdyONg8) 8 | 9 | ## Features 10 | * Color Terminal with scrolling(page up and down keys) 11 | * Scan PCI devices and print some info about them 12 | * Prints multiboot data 13 | * Basic command(cls, echo, help, color) 14 | 15 | ## Install 16 | *You must have a GCC cross compiler targeting i686-elf.* 17 | 1. Modify the make file to point $(CC) and $(AS) at your cross compiler. 18 | 2. Run `make` to compile into an elf binary. 19 | 3. Run `make run` to load the binary with qemu. 20 | 4. Run `make buildiso` to make a bootable iso with grub-mkrescue. 21 | -------------------------------------------------------------------------------- /kernel/include/idt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | #define PIC1_CONTROL 0x20 5 | #define PIC1_DATA 0x21 6 | #define PIC2_CONTROL 0xA0 7 | #define PIC2_DATA 0xA1 8 | 9 | #define NUM_IDT_GATES 256 10 | 11 | struct __attribute__((__packed__)) idt_gate{ 12 | uint16_t offset_lower; 13 | uint16_t selector; 14 | uint8_t _empty; 15 | uint8_t flags; 16 | uint16_t offset_upper; 17 | }; 18 | typedef struct idt_gate idt_gate_t; 19 | 20 | struct __attribute__((__packed__)) idt_descriptor{ 21 | uint16_t limit; 22 | uint32_t base; 23 | }; 24 | typedef struct idt_descriptor idt_descriptor_t; 25 | 26 | extern void load_idt(idt_descriptor_t idtr); 27 | 28 | void install_idt(); 29 | void add_idt_entry(uint16_t num, unsigned long offset, uint16_t selector, uint8_t flags); 30 | -------------------------------------------------------------------------------- /kernel/ata.c: -------------------------------------------------------------------------------- 1 | #include "include/ata.h" 2 | #include "include/pci.h" 3 | #include "include/io.h" 4 | 5 | static ata_device_t ata_primary = {.io_base = 0x1F0, .control=0x3F6}; 6 | static ata_device_t ata_secondary = {.io_base = 0x170, .control=0x376}; 7 | 8 | void setup_ata(){ 9 | int size = 0; 10 | pci_device_t* device = pci_get_devices(&size); 11 | printf("Scanning %s devices for IDE controllers.\n", size); 12 | for(int i = 0; i < size; i++){ 13 | if(device[i].class == 0x01 && device[i].subclass == 0x1){ 14 | println("PCI IDE Controller found!"); 15 | setup_device(&device[i]); 16 | return; 17 | } 18 | } 19 | } 20 | 21 | void setup_device(pci_device_t* device){ 22 | println("Setting up ATA"); 23 | uint32_t result = pci_device_read(device, 0x14); 24 | printf("Bar1 result: %s\n", result); 25 | } 26 | -------------------------------------------------------------------------------- /kernel/include/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | uint16_t strlen(char* c); 5 | char digit_to_char(uint8_t input); 6 | char* substring(char* str, uint16_t start, uint16_t end); 7 | char* concat(char* str1, char* str2); 8 | uint8_t string_starts_with(char* full, char* start); 9 | char** string_split(char* str, char delim, int* arr_length); 10 | uint8_t strcmp(char* str1, char* str2); 11 | int32_t string_index_of_char(char* str, char look); 12 | uint8_t hexchar_to_decimal(char input); 13 | char* number_to_string_template(uint32_t input, uint8_t base, uint8_t sign_bit, 14 | char* prefix); 15 | //common aliases for number_to_string_template 16 | char* int_to_string(int32_t input); 17 | char* uint_to_string(uint32_t input); 18 | char* int_to_hexstring(int32_t input); 19 | char* uint_to_hexstring(uint32_t input); 20 | char* int_to_binstring(int32_t input); 21 | char* uint_to_binstring(uint32_t input); 22 | -------------------------------------------------------------------------------- /kernel/include/gdt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | typedef struct { 5 | uint16_t limit_lower; 6 | uint16_t base_lower; 7 | uint8_t base_middle; 8 | 9 | //access byte 10 | int access: 1; 11 | int readwrite: 1; 12 | int direction: 1; 13 | int executable: 1; 14 | int one: 1; 15 | int privilege: 2; 16 | int present: 1; 17 | 18 | int limit_upper : 4; 19 | 20 | //flags 21 | int zero: 2; 22 | int size: 1; 23 | int granulatity: 1; 24 | 25 | uint8_t base_upper; 26 | } __attribute__((__packed__)) gdt_entry_t; 27 | 28 | typedef struct { 29 | uint16_t size; 30 | uintptr_t offset; 31 | } __attribute__((__packed__)) gdt_descriptor_t; 32 | 33 | extern void load_gdt(gdt_descriptor_t gdtr); 34 | 35 | void install_gdt(); 36 | 37 | void add_gdt_entry(uint16_t offset, uint64_t base, uint64_t limit, 38 | uint8_t size, uint8_t granularity, uint8_t readwrite, 39 | uint8_t direction, uint8_t executable, uint8_t privlege, 40 | uint8_t present); 41 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = ~/opt/cross/bin/i686-elf-gcc 2 | AS = ~/opt/cross/bin/i686-elf-as 3 | LNFLAGS = -T linker.ld -ffreestanding -O2 -nostdlib -lgcc 4 | CCFLAGS = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra 5 | ASFLAGS = -c 6 | CTMP = $(wildcard kernel/*.c) 7 | ATMP = $(wildcard kernel/*.s) 8 | CFILE = $(subst kernel/, ,$(CTMP)) 9 | AFILE = $(subst kernel/, ,$(ATMP)) 10 | CSRC = $(CFILE:.c=) 11 | ASRC = $(AFILE:.s=) 12 | 13 | OUT = $(wildcard out/*.o) 14 | 15 | all: ccompile acompile link 16 | 17 | ccompile: 18 | for file in $(CSRC) ; do \ 19 | $(CC) $(CCFLAGS) kernel/$$file.c -o out/$$file.o ; \ 20 | done 21 | 22 | acompile: 23 | for file in $(ASRC) ; do \ 24 | $(AS) $(ASFLAGS) kernel/$$file.s -o out/$$file.o ; \ 25 | done 26 | 27 | link: 28 | $(CC) $(LNFLAGS) -o latest.bin $(OUT) 29 | 30 | run: 31 | qemu-system-i386 -kernel latest.bin 32 | 33 | bochs: 34 | bochs -q -f bochsrc.txt 35 | 36 | clean: 37 | rm -f $(OUT) 38 | rm -f latest.bin 39 | 40 | buildiso: 41 | mkdir -p isodir/boot/grub 42 | cp latest.bin isodir/boot/kernel.elf 43 | cp grub.cfg isodir/boot/grub/grub.cfg 44 | sudo grub-mkrescue -o bootable.iso isodir 45 | 46 | fullbochs: ccompile acompile link buildiso bochs 47 | -------------------------------------------------------------------------------- /kernel/idt.c: -------------------------------------------------------------------------------- 1 | #include "include/idt.h" 2 | #include "include/io.h" 3 | #include "include/terminal.h" 4 | #include "include/io.h" 5 | 6 | extern void handle_interrupt(void); 7 | extern void gpf_handler(void); 8 | 9 | idt_gate_t IDT[NUM_IDT_GATES]; 10 | idt_descriptor_t idt_desc; 11 | 12 | void install_idt() { 13 | print("Installing IDT ...\t\t"); 14 | size_t size = sizeof(idt_gate_t) * NUM_IDT_GATES; 15 | idt_descriptor_t idt_desc; 16 | idt_desc.base = IDT; 17 | idt_desc.limit = sizeof(IDT) - 1; 18 | 19 | //configure PIC 20 | outb(PIC1_CONTROL, 0x11); 21 | outb(PIC2_CONTROL, 0x11); 22 | 23 | outb(PIC1_DATA, 0x20); 24 | outb(PIC2_DATA, 0x28); 25 | 26 | outb(PIC1_DATA, 4); 27 | outb(PIC2_DATA, 2); 28 | 29 | outb(PIC1_DATA, 0x01); 30 | outb(PIC2_DATA, 0x01); 31 | 32 | //only enable keyboard IRQ 33 | outb(PIC1_DATA, 0b11111101); 34 | outb(PIC2_DATA, 0xff); 35 | 36 | load_idt(idt_desc); 37 | print("done\n"); 38 | 39 | enable_interrupts(); 40 | } 41 | 42 | void add_idt_entry(uint16_t num, unsigned long offset, uint16_t selector, uint8_t flags) { 43 | IDT[num].offset_lower = offset & 0xFFFF; 44 | IDT[num].offset_upper = (offset & 0xFFFF0000) >> 16; 45 | 46 | IDT[num].selector = selector; 47 | 48 | IDT[num]._empty = 0; 49 | 50 | IDT[num].flags = flags; 51 | } 52 | -------------------------------------------------------------------------------- /kernel/include/multiboot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | //QEMU FLAGS: 4 | //0000001001001111 5 | 6 | //VIRTUALBOX FLAGS: 7 | //0001101001100111 8 | typedef struct{ 9 | //data on this struct 10 | uint32_t flags;//0 11 | 12 | //memory info 13 | uint32_t mem_lower;//4 14 | uint32_t mem_upper;//8 15 | 16 | //info on disk os was loaded from 17 | uint32_t boot_device;//12 18 | uint32_t cmdline;//16 19 | 20 | //boot modules 21 | uint32_t mods_count;//20 22 | uint32_t mods_addr;//24 23 | 24 | //placeholder for some systeminfo 25 | uint32_t syms1;//28 26 | uint32_t syms2;//32 27 | uint32_t syms3;//36 28 | uint32_t syms4;//40 29 | 30 | //memory map data 31 | uint32_t mmap_length;//44 32 | uint32_t mmap_addr;//48 33 | 34 | //drive data 35 | uint32_t drives_length;//52 36 | uint32_t drives_addr;//56 37 | 38 | //some sort of configuration table? 39 | uint32_t config_table;//60 40 | 41 | //c string of boot loader name 42 | uint32_t boot_loader_name;//64 43 | 44 | //power managment thing 45 | uint32_t apm_table;//68 46 | 47 | //vesa info 48 | uint32_t vbe_control_info;//72 49 | uint32_t vbe_mode_info;//76 50 | uint16_t vbe_mode;//80 51 | uint16_t vbe_interface_seg;//82 52 | uint16_t vbe_interface_off;//84 53 | int16_t vge_interface_len;//86 54 | 55 | } __attribute__((__packed__)) multiboot_header_t; 56 | -------------------------------------------------------------------------------- /kernel/keyboard.c: -------------------------------------------------------------------------------- 1 | #include "include/keyboard.h" 2 | #include "include/io.h" 3 | #include "include/terminal.h" 4 | #include "include/interrupts.h" 5 | #include "include/shell.h" 6 | 7 | //#define KEYBOARD_PRINTCODE 8 | 9 | uint8_t shift = 0; 10 | uint8_t caps = 0; 11 | 12 | void keyboard_interrupt_handler() { 13 | uint8_t status; 14 | signed char keycode; 15 | //write interrupt end 16 | outb(0x20, 0x20); 17 | 18 | status = inb(0x64); 19 | if(status & 1){ 20 | keycode = inb(0x60); 21 | handle_key(keycode); 22 | #ifdef KEYBOARD_PRINTCODE 23 | printf("%s\n", keycode); 24 | #endif 25 | } 26 | } 27 | 28 | void handle_key(int32_t keycode) { 29 | switch(keycode) { 30 | case SHIFT: 31 | shift = 1; 32 | break; 33 | case SHIFT_RELEASE: 34 | shift = 0; 35 | break; 36 | case CAPSLOCK: 37 | if(caps > 0){ 38 | caps = 0; 39 | }else { 40 | caps = 1; 41 | } 42 | break; 43 | default: 44 | if(keycode < 0) return; 45 | char ch; 46 | if(shift || caps) { 47 | ch = keymap_upper[keycode]; 48 | }else { 49 | ch = keymap_lower[keycode]; 50 | } 51 | //case handled, now pass to shell 52 | shell_handle_key(keycode, ch); 53 | 54 | } 55 | } 56 | 57 | void install_keyboard() { 58 | print("Installing keyboard ...\t"); 59 | install_interrupt_handler(33, keyboard_interrupt_handler); 60 | print("done\n"); 61 | } 62 | -------------------------------------------------------------------------------- /kernel/include/terminal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | #define TERMINAL_COMMAND_PORT 0x3D4 5 | #define TERMINAL_DATA_PORT 0x3D5 6 | 7 | #define VGA_CONTROL 0x3C0 8 | #define VGA_CONTROL_READ 0x3C1 9 | typedef struct{ 10 | char character; 11 | uint8_t color; 12 | } __attribute__((__packed__)) vga_entry_t; 13 | 14 | //function definitions 15 | void terminal_writeline(char* c); 16 | void terminal_clear(); 17 | void terminal_hard_clear(); 18 | void terminal_scroll(); 19 | void terminal_initialize(); 20 | void terminal_backspace(); 21 | void terminal_write_next_entry(vga_entry_t entry); 22 | void terminal_write_next_char(char c); 23 | vga_entry_t terminal_make_vga_entry(char c); 24 | uint8_t terminal_make_color(uint8_t bg, uint8_t fg); 25 | void terminal_write_char_at(uint16_t x, uint16_t y, vga_entry_t entry); 26 | void terminal_set_cursor_position(uint8_t x, uint8_t y); 27 | void printf(char* str, int32_t rpl); 28 | void print(char* str); 29 | uint8_t terminal_getX(); 30 | uint8_t terminal_getY(); 31 | void terminal_set_color(uint8_t bg, uint8_t fg); 32 | void println(char* str); 33 | void linebreak(); 34 | void terminal_up(); 35 | void terminal_replay_future(); 36 | void terminal_reset_scroll(); 37 | uint8_t terminal_get_color(); 38 | void terminal_set_color_code(uint8_t newcolor); 39 | void uprintf(char* str, uint32_t rpl); 40 | void printsf(char* str, char* repl); 41 | 42 | uint8_t terminal_get_background(); 43 | uint8_t terminal_get_foreground(); 44 | -------------------------------------------------------------------------------- /bochsrc.txt: -------------------------------------------------------------------------------- 1 | # configuration file generated by Bochs 2 | plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1, iodebug=1 3 | config_interface: textconfig 4 | display_library: x 5 | memory: host=32, guest=32 6 | romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0xfffe0000 7 | vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" 8 | floppy_bootsig_check: disabled=0 9 | # no floppya 10 | # no floppyb 11 | ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 12 | ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 13 | ata0-slave: type=cdrom, path="bootable.iso", status=inserted 14 | boot: cdrom 15 | ata2: enabled=0 16 | ata3: enabled=0 17 | pci: enabled=1, chipset=i440fx 18 | vga: extension=vbe, update_freq=5 19 | cpu: count=1, ips=1000000, model=corei7_ivy_bridge_3770k, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 20 | print_timestamps: enabled=0 21 | debugger_log: - 22 | magic_break: enabled=0 23 | port_e9_hack: enabled=0 24 | private_colormap: enabled=0 25 | clock: sync=none, time0=local, rtc_sync=0 26 | # no cmosimage 27 | # no loader 28 | log: - 29 | logprefix: %t%e%d 30 | panic: action=ask 31 | error: action=report 32 | info: action=report 33 | debug: action=ignore 34 | keyboard: type=mf, serial_delay=250, paste_delay=100000, keymap= 35 | user_shortcut: keys=none 36 | mouse: enabled=0, type=ps2 37 | parport1: enabled=1, file="" 38 | parport2: enabled=0 39 | com1: enabled=1, mode=null, dev="" 40 | com2: enabled=0 41 | com3: enabled=0 42 | com4: enabled=0 43 | -------------------------------------------------------------------------------- /kernel/boot.s: -------------------------------------------------------------------------------- 1 | .intel_syntax noprefix 2 | 3 | /*Aligns boot modules on 4KB boundries*/ 4 | .set ALIGN, 1<<0 5 | 6 | /*Requires memory data in the multiboot structure*/ 7 | .set MEMINFO, 1 << 1 8 | 9 | /*Requires video mode info be available to the kernel*/ 10 | .set VIDEOINFO, 1<<2 11 | 12 | /* 13 | .set VIDEOMODE, 1 14 | .set VIDEOWIDTH, 200 15 | .set VIDEOHEIGHT, 30 16 | .set VIDEODEPTH, 0 17 | */ 18 | 19 | .set MAGIC, 0x1BADB002 20 | .set FLAGS, ALIGN | MEMINFO /*| VIDEOINFO*/ 21 | .set CHECKSUM, -(MAGIC + FLAGS) 22 | 23 | 24 | .section .multiboot 25 | .align 4 26 | .long MAGIC 27 | .long FLAGS 28 | .long CHECKSUM 29 | .skip 20 30 | /* 31 | .long VIDEOMODE 32 | .long VIDEOWIDTH 33 | .long VIDEOHEIGHT 34 | .long VIDEODEPTH 35 | */ 36 | 37 | /* 38 | a and w are both attributes, a means allocatable and w means writable 39 | @nobits means that the section does not contain data and only occupies space 40 | */ 41 | .section .bootstrap_stack, "aw", @nobits 42 | .align 16 43 | stack_bottom: 44 | .skip 32768 45 | stack_top: 46 | 47 | .section .text 48 | .global _start 49 | .extern kmain 50 | .global outb 51 | .type _start, @function 52 | .type kmain, @function 53 | _start: 54 | cli 55 | 56 | /*Grab addresses of the stack*/ 57 | lea edx, stack_top 58 | lea ecx, stack_bottom 59 | 60 | /*Setup stack*/ 61 | mov esp, edx 62 | 63 | /*Some parameters*/ 64 | push eax 65 | push ebx 66 | push ecx 67 | push edx 68 | 69 | /*Our main C function*/ 70 | call kmain 71 | hlt 72 | -------------------------------------------------------------------------------- /kernel/include/pci.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | #define PCI_CONFIG 0xCF8 5 | #define PCI_DATA 0xCFC 6 | 7 | #define MAX_PCI_FUNCTIONS 16 8 | 9 | static char* const DEVICE_CLASS_LIST[] = { 10 | "Unclassified device", 11 | "Mass storage controller", 12 | "Network controller", 13 | "Display controller", 14 | "Multimedia controller", 15 | "Memory controller", 16 | "Bridge", 17 | "Communication controller", 18 | "Generic system peripheral", 19 | "Input device controller", 20 | "Docking station", 21 | "Processor", 22 | "Serial bus controller", 23 | "Wireless controller", 24 | "Intelligent controller", 25 | "Satellite communications controller", 26 | "Encreption controller", 27 | "Signal processing controller", 28 | "Processing accelerators", 29 | "Non-essential instrumentation", //offset 0x13 30 | }; 31 | 32 | typedef struct { 33 | uint8_t bus; 34 | uint8_t device; 35 | uint8_t function; 36 | uint32_t address; 37 | uint16_t vendor_id; 38 | uint16_t device_id; 39 | uint8_t class; 40 | uint8_t subclass; 41 | uint8_t header_type; 42 | } pci_device_t; 43 | 44 | uint32_t pci_query(uint32_t address); 45 | void pci_scan_bus(uint8_t bus); 46 | void pci_scan(); 47 | uint32_t pci_make_address(uint8_t bus, uint8_t device, uint8_t function, 48 | uint8_t reg); 49 | void pci_print_device(pci_device_t device); 50 | void pci_print_all(char* args); 51 | pci_device_t* pci_get_devices(int* size); 52 | void pci_device_write(pci_device_t* device, uint8_t offset, uint32_t); 53 | uint32_t pci_device_read(pci_device_t* device, uint8_t offset); 54 | -------------------------------------------------------------------------------- /kernel/kernel.c: -------------------------------------------------------------------------------- 1 | #include "include/terminal.h" 2 | #include "include/io.h" 3 | #include 4 | #include 5 | #include "include/string.h" 6 | #include "include/gdt.h" 7 | #include "include/idt.h" 8 | #include "include/interrupts.h" 9 | #include "include/keyboard.h" 10 | #include "include/shell.h" 11 | #include "include/multiboot.h" 12 | #include "include/pci.h" 13 | #include "include/ata.h" 14 | 15 | void kmain(uintptr_t stack_top, uintptr_t stack_bottom, 16 | multiboot_header_t* mboot, uint32_t magic){ 17 | terminal_initialize(); 18 | terminal_linebreak(); 19 | //print some non-multiboot table things 20 | printf("Magic number:\t%s\n", magic); 21 | printsf("Stack bottom:\t%s\n", uint_to_hexstring(stack_bottom)); 22 | printsf("Stack top:\t%s\n", uint_to_hexstring(stack_top)); 23 | 24 | 25 | terminal_linebreak(); 26 | //dive into multiboot data structure data 27 | printsf("Flags:\t\t%s\n", uint_to_binstring(mboot->flags)); 28 | printsf("Bootloader:\t%s\n", mboot->boot_loader_name); 29 | printsf("Lower memory:\t", uint_to_hexstring(mboot->mem_lower)); 30 | printsf("Upper memory:\t", uint_to_hexstring(mboot->mem_upper)); 31 | printsf("Mods count:\t%s\n", uint_to_string(mboot->mods_count)); 32 | printsf("Mods addr:\t%s\n", uint_to_hexstring(mboot->mods_addr)); 33 | terminal_linebreak(); 34 | install_gdt(); 35 | install_idt(); 36 | install_interrupt_interface(); 37 | pci_scan(); 38 | setup_ata(); 39 | install_keyboard(); 40 | 41 | shell_initialize(); 42 | register_command("pci_scan", pci_print_all, "Scan PCI for devices."); 43 | while(1) {} 44 | } 45 | -------------------------------------------------------------------------------- /kernel/gdt.c: -------------------------------------------------------------------------------- 1 | #include "include/gdt.h" 2 | #include "include/terminal.h" 3 | #include "include/memory.h" 4 | #include "include/io.h" 5 | 6 | gdt_entry_t GDT[3]; 7 | gdt_descriptor_t gdt_desc; 8 | 9 | void install_gdt() { 10 | print("Installing GDT ...\t\t"); 11 | 12 | gdt_desc.offset = GDT; 13 | gdt_desc.size = sizeof(GDT) - 1; 14 | //empty entry 15 | memset(&(GDT[0]), sizeof(gdt_entry_t), 0); 16 | //code segment 17 | add_gdt_entry(1, 0, 0xFFFFFFFF, 1, 1, 1, 0, 1, 0, 1); 18 | //data segment 19 | add_gdt_entry(2, 0, 0xFFFFFFFF, 1, 1, 1, 0, 0, 0, 1); 20 | 21 | //debug data 22 | /*printf("GDT is located at %s\n", (uintptr_t)&(GDT[0])); 23 | printf("GDT Descriptor is located at %s\n", &gdt_desc); 24 | printf("Size of GDT - 1 is %s\n", sizeof(GDT) - 1); 25 | printf("Size of gdt_entry_t is %s\n", sizeof(gdt_entry_t)); 26 | printf("gdt descriptor offset value is %s\n", gdt_desc.offset);*/ 27 | 28 | //load it 29 | load_gdt(gdt_desc); 30 | print("done\n"); 31 | 32 | } 33 | 34 | void add_gdt_entry(uint16_t offset, uint64_t base, uint64_t limit, 35 | uint8_t size, uint8_t granularity, uint8_t readwrite, 36 | uint8_t direction, uint8_t executable, uint8_t privilege, 37 | uint8_t present) 38 | { 39 | //encode base 40 | GDT[offset].base_lower = base & 0xFFFF; //that is the first 16 bits 41 | GDT[offset].base_middle = (base & 0xFF0000) >> 16;//8 bits after first 16 42 | GDT[offset].base_upper = (base & 0xFF000000) >> 24;//upper 8 bits 43 | 44 | //encode limit 45 | GDT[offset].limit_lower = limit & 0xFFFF; //first 16 46 | GDT[offset].limit_upper = (limit & 0xF0000) >> 16; //next 4 47 | 48 | //encode flags 49 | GDT[offset].size = size; 50 | GDT[offset].granulatity = granularity; 51 | 52 | //encode access byte 53 | GDT[offset].access = 0; 54 | GDT[offset].readwrite = readwrite; 55 | GDT[offset].direction = direction; 56 | GDT[offset].executable = executable; 57 | GDT[offset].privilege = privilege; 58 | GDT[offset].present = present; 59 | 60 | //some definate stuff 61 | GDT[offset].zero = 0; 62 | GDT[offset].one = 1; 63 | } 64 | -------------------------------------------------------------------------------- /kernel/include/keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | #define ESCAPE 1 5 | #define SHIFT 42 6 | #define SHIFT_RELEASE -86 7 | #define CAPSLOCK 58 8 | #define BACKSPACE 14 9 | #define PAGEUP 73 10 | #define PAGEDOWN 81 11 | 12 | static unsigned char keymap_lower[128] = 13 | { 14 | 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ 15 | '9', '0', '-', '=', 0, /* Backspace */ 16 | '\t', /* Tab */ 17 | 'q', 'w', 'e', 'r', /* 19 */ 18 | 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ 19 | 0, /* 29 - Control */ 20 | 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */ 21 | '\'', '`', 0, /* Left shift */ 22 | '\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */ 23 | 'm', ',', '.', '/', 0, /* Right shift */ 24 | '*', 25 | 0, /* Alt */ 26 | ' ', /* Space bar */ 27 | 0, /* Caps lock */ 28 | 0, /* 59 - F1 key ... > */ 29 | 0, 0, 0, 0, 0, 0, 0, 0, 30 | 0, /* < ... F10 */ 31 | 0, /* 69 - Num lock*/ 32 | 0, /* Scroll Lock */ 33 | 0, /* Home key */ 34 | 0, /* Up Arrow */ 35 | 0, /* Page Up */ 36 | '-', 37 | 0, /* Left Arrow */ 38 | 0, 39 | 0, /* Right Arrow */ 40 | '+', 41 | 0, /* 79 - End key*/ 42 | 0, /* Down Arrow */ 43 | 0, /* Page Down */ 44 | 0, /* Insert Key */ 45 | 0, /* Delete Key */ 46 | 0, 0, 0, 47 | 0, /* F11 Key */ 48 | 0, /* F12 Key */ 49 | 0, /* All other keys are undefined */ 50 | }; 51 | static unsigned char keymap_upper[128] = 52 | { 53 | 0, 0, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */ 54 | '(', ')', '_', '+', 0, /* Backspace */ 55 | '\t', /* Tab */ 56 | 'Q', 'W', 'E', 'R', /* 19 */ 57 | 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */ 58 | 0, /* 29 - Control */ 59 | 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */ 60 | '|', '~', 0, /* Left shift */ 61 | '\\', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */ 62 | 'M', '<', '>', '?', 0, /* Right shift */ 63 | '*', 64 | 0, /* Alt */ 65 | ' ', /* Space bar */ 66 | 0, /* Caps lock */ 67 | 0, /* 59 - F1 key ... > */ 68 | 0, 0, 0, 0, 0, 0, 0, 0, 69 | 0, /* < ... F10 */ 70 | 0, /* 69 - Num lock*/ 71 | 0, /* Scroll Lock */ 72 | 0, /* Home key */ 73 | 0, /* Up Arrow */ 74 | 0, /* Page Up */ 75 | '-', 76 | 0, /* Left Arrow */ 77 | 0, 78 | 0, /* Right Arrow */ 79 | '+', 80 | 0, /* 79 - End key*/ 81 | 0, /* Down Arrow */ 82 | 0, /* Page Down */ 83 | 0, /* Insert Key */ 84 | 0, /* Delete Key */ 85 | 0, 0, 0, 86 | 0, /* F11 Key */ 87 | 0, /* F12 Key */ 88 | 0, /* All other keys are undefined */ 89 | }; 90 | 91 | void keyboard_interrupt_handler(); 92 | void install_keyboard(); 93 | void handle_key(int32_t keycode); 94 | -------------------------------------------------------------------------------- /kernel/pci.c: -------------------------------------------------------------------------------- 1 | #include "include/pci.h" 2 | #include "include/types.h" 3 | 4 | pci_device_t devices[MAX_PCI_FUNCTIONS]; 5 | uint16_t device_counter = 0; 6 | bool scanned = false; 7 | 8 | pci_device_t* pci_get_devices(int* size){ 9 | *size = device_counter; 10 | return devices; 11 | } 12 | 13 | void pci_device_write(pci_device_t* device, uint8_t offset, uint32_t data){ 14 | uint32_t address = 15 | pci_make_address(device->bus, device->device, device->function, offset); 16 | outdw(PCI_CONFIG, address); 17 | outdw(PCI_DATA, data); 18 | } 19 | 20 | uint32_t pci_device_read(pci_device_t* device, uint8_t offset){ 21 | uint32_t address = 22 | pci_make_address(device->bus, device->device, device->function, offset); 23 | outdw(PCI_CONFIG, address); 24 | return indw(PCI_DATA); 25 | } 26 | 27 | void pci_print_device(pci_device_t device){ 28 | uprintf("BUS: %s, ", device.bus); 29 | uprintf("DEVICE: %s, ", device.device); 30 | uprintf("FUNCTION: %s\n", device.function); 31 | printsf("VENDORID: %s ", uint_to_hexstring(device.vendor_id)); 32 | printsf("DEVICEID: %s\n", uint_to_hexstring(device.device_id)); 33 | printsf("CLASS: %s, ", uint_to_hexstring(device.class)); 34 | printsf("SUBCLASS: %s, ", uint_to_hexstring(device.subclass)); 35 | printsf("HEADER: %s\n", uint_to_hexstring(device.header_type)); 36 | 37 | if(device.class > 0x13){ 38 | if(device.class == 0x40){ 39 | println("Coprocessor"); 40 | }else if(device.class == 0xff){ 41 | println("Unassigned class"); 42 | }else{ 43 | println("Unknown"); 44 | } 45 | }else{ 46 | println(DEVICE_CLASS_LIST[device.class]); 47 | } 48 | println(""); 49 | } 50 | 51 | void pci_print_all(char* args){ 52 | if(!scanned){ 53 | pci_scan(); 54 | scanned = true; 55 | } 56 | for(int i = 0; i < device_counter; i++){ 57 | pci_print_device(devices[i]); 58 | } 59 | } 60 | 61 | //BAR = base address registers 62 | uint32_t pci_query(uint32_t address) { 63 | 64 | outdw(PCI_CONFIG, address); 65 | uint32_t got = indw(PCI_DATA); 66 | return got; 67 | } 68 | 69 | uint32_t pci_make_address(uint8_t bus, uint8_t device, uint8_t function, 70 | uint8_t reg){ 71 | return 0 | (1 << 31) | (bus << 16) | ((device & 0x1f) << 11) | 72 | ((function & 0x7) << 8) | ((reg & 0xFC)); 73 | } 74 | 75 | void pci_scan_device(uint8_t bus, uint8_t device){ 76 | uint8_t continue_scan = 1; 77 | uint8_t function = 0; 78 | while(continue_scan){ 79 | uint32_t address = pci_make_address(bus, device, function, 0); 80 | uint32_t result = pci_query(address); 81 | if(result == 0xFFFFFFFF){ 82 | continue_scan = false; 83 | }else{ 84 | //valid function, print info 85 | uint16_t vendor_id = result & 0xFFFF; 86 | uint16_t device_id = (result >> 16) & 0xFFFF; 87 | 88 | uint32_t reg_data = pci_query(pci_make_address(bus, device, function, 0x08)); 89 | uint8_t class = (reg_data >> 24) & 0xFF; 90 | uint8_t subclass = (reg_data >> 16) & 0xFF; 91 | 92 | uint32_t header_blob = 93 | pci_query(pci_make_address(bus, device, function, 0x0C)); 94 | uint8_t header_type = (header_blob >> 16) & 0xFF; 95 | 96 | pci_device_t dev; 97 | dev.address = address; 98 | dev.bus = bus; 99 | dev.device = device; 100 | dev.function = function; 101 | dev.vendor_id = vendor_id; 102 | dev.device_id = device_id; 103 | dev.class = class; 104 | dev.subclass = subclass; 105 | dev.header_type = header_type; 106 | devices[device_counter] = dev; 107 | device_counter++; 108 | 109 | 110 | function++; 111 | } 112 | } 113 | } 114 | 115 | void pci_scan_bus(uint8_t bus){ 116 | uint8_t continue_scan = 1; 117 | uint8_t device = 0; 118 | while(continue_scan){ 119 | uint32_t result = pci_query(pci_make_address(bus, device, 0, 0)); 120 | if(result == 0xFFFFFFFF){ 121 | continue_scan = 0; 122 | }else{ 123 | //valid device, scan it 124 | pci_scan_device(bus, device); 125 | device++; 126 | } 127 | } 128 | } 129 | 130 | void pci_scan(){ 131 | print("Scanning PCI ...\t\t"); 132 | uint8_t continue_scan = 1; 133 | uint8_t bus = 0; 134 | while(continue_scan){ 135 | uint32_t result = pci_query(pci_make_address(bus, 0, 0, 0)); 136 | if(result == 0xFFFFFFFF){ 137 | continue_scan = 0; 138 | }else{ 139 | //valid bus, scan it 140 | pci_scan_bus(bus); 141 | bus++; 142 | } 143 | } 144 | println("done"); 145 | } 146 | -------------------------------------------------------------------------------- /kernel/shell.c: -------------------------------------------------------------------------------- 1 | #include "include/shell.h" 2 | #include "include/terminal.h" 3 | #include "include/keyboard.h" 4 | #include "include/memory.h" 5 | #include "include/string.h" 6 | 7 | char buffer[200]; 8 | uint16_t key_index = 0; 9 | 10 | command_t commands[10]; 11 | uint8_t command_index = 0; 12 | 13 | void shell_handle_key(int32_t keycode, char ch) { 14 | //write to terminal if it has a character 15 | if(keycode > 0 && ch > 2 && key_index + 1 < 200 && ch != '\n') { 16 | terminal_write_next_char(ch); 17 | buffer[key_index] = ch; 18 | key_index++; 19 | } 20 | 21 | //reprint kernel> on new line 22 | if(ch == '\n') { 23 | terminal_write_next_char('\n'); 24 | shell_handle_command(); 25 | shell_print_kernel(); 26 | } 27 | 28 | //handle some special characters 29 | if(keycode == BACKSPACE) { 30 | //protect the 'kernel>' prefix 31 | if(terminal_getX() > 7) { 32 | terminal_backspace(); 33 | //backspace command buffer as well 34 | buffer[key_index] = 0; 35 | key_index--; 36 | } 37 | } 38 | 39 | if(keycode == ESCAPE) { 40 | terminal_clear(); 41 | shell_print_kernel(); 42 | shell_reset_buffer(); 43 | } 44 | 45 | if(keycode == PAGEUP) { 46 | terminal_up(); 47 | } 48 | 49 | if(keycode == PAGEDOWN) { 50 | terminal_replay_future(); 51 | } 52 | } 53 | 54 | void help_menu(char* args) { 55 | for(uint8_t i = 0; i < command_index; i++) { 56 | print(commands[i].command); 57 | print(" - "); 58 | println(commands[i].description); 59 | } 60 | } 61 | 62 | void pong(char* args) { 63 | println("PONG!"); 64 | } 65 | 66 | void cls(char* args) { 67 | terminal_clear(); 68 | } 69 | 70 | void echo(char* args) { 71 | if(!args){ 72 | println(""); 73 | return; 74 | } 75 | println(args); 76 | } 77 | 78 | void TODO(char* args) { 79 | println("- Figure out how to interface with the IDE controller"); 80 | println("- Create a filesystem driver, probably ext2."); 81 | println("- Add a better memory allocator, including the reuse of memory"); 82 | } 83 | 84 | void linebreak(char* args) { 85 | terminal_linebreak(); 86 | } 87 | 88 | void command_color(char* args){ 89 | int len = strlen(args); 90 | if(len != 2 || !args) { 91 | println("Incorrect use of color, provide 2 characters only."); 92 | println("ex: color FF"); 93 | println("The first color is background."); 94 | println("The second color is foreground."); 95 | println("0 - black 9 - light blue"); 96 | println("1 - blue A - light green"); 97 | println("2 - green B - light cyan"); 98 | println("3 - cyan C - light red"); 99 | println("4 - red D - light magenta"); 100 | println("5 - magenta E - yellow"); 101 | println("6 - brown F - white"); 102 | println("7 - light gray"); 103 | println("8 - dark gray"); 104 | return; 105 | } 106 | 107 | terminal_set_color(hexchar_to_decimal(args[0]), hexchar_to_decimal(args[1])); 108 | terminal_clear(); 109 | } 110 | 111 | void shell_initialize() { 112 | print("Initializing shell...\t"); 113 | memset(commands, sizeof(commands), 0); 114 | register_command("help", help_menu, "Displays this menu."); 115 | register_command("ping", pong, "Responds with PONG!"); 116 | register_command("cls", cls, "Clears the terminal."); 117 | register_command("todo", TODO, "Prints the short term list of things to do."); 118 | register_command("echo", echo, "Print given string."); 119 | register_command("break", linebreak, "Print a red separating line."); 120 | register_command("color", command_color, "Set the terminal colors."); 121 | print("done"); 122 | terminal_linebreak(); 123 | shell_print_kernel(); 124 | } 125 | 126 | void shell_print_kernel() { 127 | uint8_t color = terminal_get_color(); 128 | terminal_set_color(terminal_get_background(), 0xC); 129 | print("kernel>"); 130 | terminal_set_color_code(color); 131 | } 132 | typedef void func(char* parameters); 133 | 134 | 135 | void shell_handle_command() { 136 | char* cmd_buf = (char*)kalloc(sizeof(char) * (key_index + 1)); 137 | cmd_buf[key_index] = 0; 138 | memcpy(buffer, cmd_buf, key_index); 139 | int len = strlen(cmd_buf); 140 | shell_reset_buffer(); 141 | 142 | int space_index = string_index_of_char(cmd_buf, ' '); 143 | char* command; 144 | char* parameters; 145 | 146 | if(space_index >= 0){ 147 | command = substring(cmd_buf, 0, space_index); 148 | parameters = substring(cmd_buf, space_index + 1, len); 149 | }else{ 150 | command = cmd_buf; 151 | parameters = 0; 152 | } 153 | 154 | //see if the command exists 155 | uint8_t handled = 0; 156 | for(int i = 0; i < command_index; i++){ 157 | if(strcmp(command, commands[i].command)){ 158 | ((func*)commands[i].callback)(parameters); 159 | handled = 1; 160 | break; 161 | } 162 | } 163 | if(!handled) { 164 | println("Command not recognized! Type 'help' for some commands."); 165 | } 166 | } 167 | 168 | 169 | void shell_reset_buffer() { 170 | key_index = 0; 171 | memset(buffer, sizeof(buffer), 0); 172 | } 173 | 174 | void register_command(char* command, void* callback, char* description) { 175 | command_t newcommand; 176 | newcommand.command = command; 177 | newcommand.callback = callback; 178 | newcommand.description = description; 179 | commands[command_index] = newcommand; 180 | command_index++; 181 | } 182 | -------------------------------------------------------------------------------- /kernel/string.c: -------------------------------------------------------------------------------- 1 | #include "include/string.h" 2 | #include "include/terminal.h" 3 | 4 | uint16_t strlen(char* c){ 5 | char i; 6 | uint16_t length = 0; 7 | while((i = c[length]) != 0){ 8 | length++; 9 | } 10 | return length; 11 | } 12 | 13 | 14 | char digit_to_char(uint8_t input){ 15 | switch(input){ 16 | case 0: 17 | return '0'; 18 | case 1: 19 | return '1'; 20 | case 2: 21 | return '2'; 22 | case 3: 23 | return '3'; 24 | case 4: 25 | return '4'; 26 | case 5: 27 | return '5'; 28 | case 6: 29 | return '6'; 30 | case 7: 31 | return '7'; 32 | case 8: 33 | return '8'; 34 | case 9: 35 | return '9'; 36 | case 10: 37 | return 'A'; 38 | case 11: 39 | return 'B'; 40 | case 12: 41 | return 'C'; 42 | case 13: 43 | return 'D'; 44 | case 14: 45 | return 'E'; 46 | case 15: 47 | return 'F'; 48 | default: 49 | return '.'; 50 | } 51 | } 52 | 53 | uint8_t hexchar_to_decimal(char input){ 54 | switch(input){ 55 | case '0': 56 | return 0; 57 | case '1': 58 | return 1; 59 | case '2': 60 | return 2; 61 | case '3': 62 | return 3; 63 | case '4': 64 | return 4; 65 | case '5': 66 | return 5; 67 | case '6': 68 | return 6; 69 | case '7': 70 | return 7; 71 | case '8': 72 | return 9; 73 | case 'a': 74 | case 'A': 75 | return 10; 76 | case 'b': 77 | case 'B': 78 | return 11; 79 | case 'c': 80 | case 'C': 81 | return 12; 82 | case 'd': 83 | case 'D': 84 | return 13; 85 | case 'e': 86 | case 'E': 87 | return 14; 88 | case 'f': 89 | case 'F': 90 | return 15; 91 | default: 92 | return 0; 93 | } 94 | } 95 | 96 | //common aliases for number_to_string_template 97 | char* int_to_string(int32_t input){ 98 | return number_to_string_template(input, 10, 1, ""); 99 | } 100 | 101 | char* uint_to_string(uint32_t input){ 102 | return number_to_string_template(input, 10, 0, ""); 103 | } 104 | 105 | char* int_to_hexstring(int32_t input){ 106 | return number_to_string_template(input, 16, 1, "0x"); 107 | } 108 | 109 | char* uint_to_hexstring(uint32_t input){ 110 | return number_to_string_template(input, 16, 0, "0x"); 111 | } 112 | 113 | char* int_to_binstring(int32_t input){ 114 | return number_to_string_template(input, 2, 1, "0b"); 115 | } 116 | 117 | char* uint_to_binstring(uint32_t input){ 118 | return number_to_string_template(input, 2, 0, "0b"); 119 | } 120 | 121 | char* number_to_string_template(uint32_t input, uint8_t base, uint8_t sign_bit, 122 | char* prefix) 123 | { 124 | uint8_t prefix_len = strlen(prefix); 125 | uint8_t negative = sign_bit && ((int32_t)input < 0); 126 | 127 | //ignore the sign bit and invert all bits 128 | if(sign_bit){ 129 | if((int32_t)input < 0){ 130 | input = ~input; 131 | input += 1; 132 | } 133 | input &= 0x7FFFFFFF; 134 | 135 | } 136 | 137 | uint8_t num_len = 1; 138 | uint32_t temp = input; 139 | while((temp /= base) > 0){ 140 | num_len++; 141 | } 142 | 143 | uint8_t full_length = num_len + prefix_len; 144 | if(negative){ 145 | full_length++; 146 | } 147 | 148 | char* str = (char*)kalloc(full_length + 1); 149 | str[full_length] = 0; 150 | 151 | uint32_t targetmod = 1; 152 | for(uint16_t i = 0; i < (num_len - 1); i++){ 153 | targetmod *= base; 154 | } 155 | 156 | uint16_t start = (negative ? 1 : 0) + prefix_len; 157 | for(uint8_t i = start; i < num_len + start; i++){ 158 | str[i] = digit_to_char((input - (input % targetmod)) / targetmod); 159 | input = input % targetmod; 160 | targetmod /= base; 161 | } 162 | 163 | uint8_t prefix_start = 0; 164 | if(negative){ 165 | str[0] = '-'; 166 | prefix_start = 1; 167 | } 168 | 169 | for(uint8_t i = prefix_start; i < prefix_len + prefix_start; i++){ 170 | str[i] = prefix[i - prefix_start]; 171 | } 172 | 173 | return str; 174 | } 175 | 176 | char* substring(char* str, uint16_t start, uint16_t end){ 177 | 178 | char* ret = (char* )kalloc((sizeof(char)) * (end - start + 1)); 179 | ret[end-start] = 0; 180 | 181 | for(uint16_t i = 0; i < (end - start); i++){ 182 | ret[i] = str[i + start]; 183 | } 184 | 185 | return ret; 186 | } 187 | char* concat(char* str1, char* str2){ 188 | uint16_t size1 = strlen(str1); 189 | uint16_t size2 = strlen(str2); 190 | char* ret = (char*)kalloc((sizeof(char)) * (size1 + size2 + 1)); 191 | ret[size1+size2] = 0; 192 | for(uint16_t i = 0; i < size1; i++){ 193 | ret[i] = str1[i]; 194 | } 195 | for(uint16_t i = 0; i < size2; i++){ 196 | ret[i + size1] = str2[i]; 197 | } 198 | return ret; 199 | } 200 | 201 | uint8_t string_starts_with(char* full, char* start) { 202 | if(strlen(full) < strlen(start)) { 203 | return 0; 204 | } 205 | for(int i = 0; i < strlen(start); i++) { 206 | if(full[i] != start[i]){ 207 | return 0; 208 | } 209 | } 210 | return 1; 211 | } 212 | 213 | char** string_split(char* str, char delim, int* arr_length) { 214 | int len = strlen(str); 215 | int num_delimeters = 0; 216 | //first we count delimeters 217 | //we won't check the last character because no string would be able to 218 | //come after it 219 | for(int i = 0; i < len - 2; i++){ 220 | if(str[i] == delim){ 221 | num_delimeters++; 222 | } 223 | } 224 | char** str_array = (char**)kalloc(sizeof(char*) * (num_delimeters + 1)); 225 | int str_offset = 0; 226 | 227 | int start = 0; 228 | int end = 0; 229 | while(end < len){ 230 | while(str[end] != delim && end < len){ 231 | end++; 232 | } 233 | //end should hold index of delimeter now 234 | char* substr = (char*)kalloc((sizeof(char)) * (end - start + 1)); 235 | memcpy(str + start, substr, end - start); 236 | start = end + 1; 237 | end++; 238 | str_array[str_offset] = substr; 239 | str_offset++; 240 | } 241 | 242 | //return necessary data now 243 | *arr_length = str_offset; 244 | return str_array; 245 | } 246 | 247 | uint8_t strcmp(char* str1, char* str2){ 248 | int len1 = strlen(str1); 249 | int len2 = strlen(str2); 250 | if(len1 != len2){ 251 | return false; 252 | } 253 | for(int i = 0; i < len1; i++){ 254 | if(str1[i] != str2[i]){ 255 | return false; 256 | } 257 | } 258 | return true; 259 | } 260 | 261 | int32_t string_index_of_char(char* str, char look){ 262 | for(int i = 0; i < strlen(str); i++){ 263 | if(str[i] == look){ 264 | return i; 265 | } 266 | } 267 | return -1; 268 | } 269 | -------------------------------------------------------------------------------- /kernel/terminal.c: -------------------------------------------------------------------------------- 1 | #include "include/terminal.h" 2 | #include "include/memory.h"; 3 | #include "include/io.h" 4 | #include "include/string.h" 5 | 6 | //some constants 7 | const uint16_t WIDTH = 80; 8 | const uint16_t HEIGHT = 25; 9 | 10 | //terminal global variables 11 | vga_entry_t* terminal = (vga_entry_t*)0xB8000; 12 | uint8_t color = 0; 13 | uint8_t background = 0; 14 | uint8_t foreground = 0; 15 | uint8_t x, y; 16 | 17 | //store history and future for scrolling support 18 | vga_entry_t* history; 19 | uint32_t history_index = 0; 20 | 21 | vga_entry_t* future; 22 | uint32_t future_index = 0; 23 | 24 | uint8_t terminal_make_color(uint8_t background, uint8_t foreground){ 25 | return foreground | background << 4; 26 | } 27 | 28 | vga_entry_t terminal_make_vga_entry(char c){ 29 | vga_entry_t ret; 30 | ret.character = c; 31 | ret.color = color; 32 | return ret; 33 | } 34 | 35 | void terminal_set_color(uint8_t bg, uint8_t fg) { 36 | background = bg; 37 | foreground = fg; 38 | color = terminal_make_color(bg, fg); 39 | } 40 | 41 | uint8_t terminal_get_background(){ 42 | return background; 43 | } 44 | 45 | uint8_t terminal_get_foreground(){ 46 | return foreground; 47 | } 48 | 49 | void terminal_write_char_at(uint16_t x, uint16_t y, vga_entry_t entry){ 50 | terminal[y * WIDTH + x] = entry; 51 | } 52 | void terminal_set_cursor_position(uint8_t x, uint8_t y){ 53 | uint16_t pos = y*WIDTH + x; 54 | outb(TERMINAL_COMMAND_PORT, 14); 55 | outb(TERMINAL_DATA_PORT, (pos >> 8) & 0x00FF); 56 | outb(TERMINAL_COMMAND_PORT, 15); 57 | outb(TERMINAL_DATA_PORT, pos & 0x00FF); 58 | } 59 | 60 | uint8_t terminal_getX() { 61 | return x; 62 | } 63 | 64 | uint8_t terminal_getY() { 65 | return y; 66 | } 67 | 68 | void terminal_backspace(){ 69 | terminal_reset_scroll(); 70 | if(x > 0) x--; 71 | terminal_write_char_at(x, y, terminal_make_vga_entry(' ')); 72 | terminal_set_cursor_position(x, y); 73 | } 74 | void terminal_write_next_entry(vga_entry_t entry){ 75 | if(x == WIDTH){ 76 | x = 0; 77 | y++; 78 | } 79 | if(y == HEIGHT){ 80 | terminal_scroll(); 81 | } 82 | if(entry.character == '\n'){ 83 | x = 0; 84 | y++; 85 | }else if(entry.character == '\t'){ 86 | terminal_write_next_char(' '); 87 | while(x % 7 != 0){ 88 | x++; 89 | if(x >= 80){ 90 | x = 0; 91 | y++; 92 | if(y > 25){ 93 | terminal_scroll(); 94 | } 95 | } 96 | } 97 | }else{ 98 | terminal_write_char_at(x, y, entry); 99 | x++; 100 | } 101 | terminal_set_cursor_position(x, y); 102 | 103 | } 104 | 105 | void terminal_clear(){ 106 | terminal_write_next_char('\n'); 107 | for(int i = 0; i < 25 * 80; i++){ 108 | terminal_write_next_char(' '); 109 | } 110 | x = 0; 111 | y = 0; 112 | terminal_set_cursor_position(x, y); 113 | } 114 | 115 | void terminal_hard_clear(){ 116 | future_index = 0; 117 | history_index = 0; 118 | for(uint16_t n = 0; n < WIDTH * HEIGHT; n++){ 119 | terminal[n] = terminal_make_vga_entry(' '); 120 | } 121 | x = 0, y = 0; 122 | terminal_set_cursor_position(x, y); 123 | } 124 | 125 | void terminal_initialize(){ 126 | //configure vga to use last bit of vga_entry as color and not a blink bit 127 | inb(0x3DA); //reset VGA_CONTROL to access an index next 128 | uint8_t state = inb(VGA_CONTROL); 129 | outb(VGA_CONTROL, 0x10); 130 | uint8_t attr = inb(VGA_CONTROL_READ); 131 | attr &= 0xF7; 132 | outb(VGA_CONTROL, attr); 133 | outb(VGA_CONTROL, state); 134 | inb(0x3DA); 135 | 136 | x = 0; 137 | y = 0; 138 | color = terminal_make_color(0, 15); 139 | terminal_hard_clear(); 140 | print("Initializing terminal...\n"); 141 | history = (vga_entry_t*)kalloc(sizeof(char) * 32000); 142 | future = (vga_entry_t*)kalloc(sizeof(char) * 32000); 143 | } 144 | void terminal_write_next_char(char c){ 145 | terminal_reset_scroll(); 146 | terminal_write_next_entry(terminal_make_vga_entry(c)); 147 | } 148 | 149 | void terminal_writeline(char* string){ 150 | terminal_reset_scroll(); 151 | uint16_t length = strlen(string); 152 | for(uint16_t i = 0; i < length; i++){ 153 | terminal_write_next_entry(terminal_make_vga_entry(string[i])); 154 | } 155 | } 156 | 157 | void terminal_reset_scroll() { 158 | while(future_index >= 80) { 159 | terminal_scroll(); 160 | } 161 | } 162 | 163 | //only scrolls if there is some future to move into the current row 164 | void terminal_replay_future(){ 165 | if(future_index >= 80) { 166 | terminal_scroll(); 167 | } 168 | 169 | } 170 | 171 | void terminal_scroll(){ 172 | //don't allow scroll if the buffer can't hold any more data 173 | if(history_index + 80 >= 32000){ 174 | return; 175 | } 176 | 177 | for(int i = 0; i < 80; i++){ 178 | history[history_index] = terminal[i]; 179 | history_index++; 180 | terminal[i] = terminal[i + 80]; 181 | } 182 | 183 | for(uint16_t i = 80; i < 80*24; i++){ 184 | terminal[i] = terminal[i + 80]; 185 | } 186 | 187 | //fill bottom row with whitespace if future doesn't contain enough data 188 | if(future_index < 80) { 189 | for(uint16_t i = 80*24; i < 80*25; i++){ 190 | terminal[i] = terminal_make_vga_entry(' '); 191 | } 192 | y--; 193 | x = 0; 194 | }else { 195 | for(uint16_t i = 80*25 - 1; i >= 80*24; i--){ 196 | future_index--; 197 | terminal[i] = future[future_index]; 198 | } 199 | } 200 | if(future_index < 80) { 201 | terminal_set_cursor_position(x, y); 202 | } 203 | } 204 | 205 | void terminal_up() { 206 | if(history_index < 80) { 207 | //no rows have been scrolled away 208 | return; 209 | } 210 | 211 | //place bottom row into future 212 | for(int i = 80*24; i < 80 * 25; i++) { 213 | future[future_index] = terminal[i]; 214 | future_index++; 215 | } 216 | 217 | //move all middle rows, which are just shifted in the array 218 | for(int i = 80 * 25 - 1; i >= 80; i--) { 219 | terminal[i] = terminal[i - 80]; 220 | } 221 | 222 | //insert first row from history 223 | for(int i = 80 - 1; i >= 0; i--) { 224 | history_index--; 225 | terminal[i] = history[history_index]; 226 | } 227 | terminal_set_cursor_position(0xFF, 0xFF); 228 | } 229 | 230 | void printf(char* str, int32_t rpl){ 231 | printsf(str, int_to_string(rpl)); 232 | } 233 | 234 | void uprintf(char* str, uint32_t rpl){ 235 | printsf(str, uint_to_string(rpl)); 236 | } 237 | 238 | void printsf(char* str, char* repl){ 239 | uint16_t size = strlen(str); 240 | for(uint16_t i = 0; i < size - 1; i++){ 241 | if(str[i] == '%' && str[i+1] == 's'){ 242 | char* str1 = substring(str, 0, i); 243 | char* str2 = substring(str, i+2, size); 244 | print(str1); 245 | print(repl); 246 | print(str2); 247 | return; 248 | } 249 | } 250 | } 251 | void print(char* str){ 252 | terminal_writeline(str); 253 | } 254 | 255 | void println(char* str){ 256 | print(str); 257 | print("\n"); 258 | } 259 | 260 | uint8_t terminal_get_color(){ 261 | return color; 262 | } 263 | 264 | void terminal_set_color_code(uint8_t newcolor){ 265 | color = newcolor; 266 | background = (0xF0 & color) >> 4; 267 | foreground = 0xF & color; 268 | } 269 | 270 | void terminal_linebreak(){ 271 | if(x > 0){ 272 | print("\n"); 273 | } 274 | uint8_t prev_color = color; 275 | terminal_set_color(background, 0xC); 276 | for(uint8_t i = 0; i < 80; i++) { 277 | print("-"); 278 | } 279 | color = prev_color; 280 | } 281 | -------------------------------------------------------------------------------- /kernel/interrupts.c: -------------------------------------------------------------------------------- 1 | #include "include/interrupts.h" 2 | #include "include/idt.h" 3 | #include "include/terminal.h" 4 | #include "include/memory.h" 5 | 6 | typedef void func(void); 7 | 8 | interrupt_handler_t HANDLERS[256]; 9 | 10 | //I am not proud of this, but it works for now 11 | #define INSTALL_HANDLER(x) extern void INTERRUPT_##x(); \ 12 | add_idt_entry(x, INTERRUPT_##x, 0x08, 0x8e); 13 | 14 | void general_interrupt_handler(int offset) { 15 | if(HANDLERS[offset].present) { 16 | ((func*)HANDLERS[offset].handler)(); 17 | }else { 18 | printf("Unhandled interrupt at offset: %s\n", offset); 19 | } 20 | } 21 | 22 | void install_interrupt_handler(int offset, void* handler) { 23 | HANDLERS[offset].present = 1; 24 | HANDLERS[offset].handler = handler; 25 | } 26 | 27 | void install_interrupt_interface() { 28 | memset(&HANDLERS, sizeof(HANDLERS), 0); 29 | //TODO: Try to macro this into oblivion 30 | INSTALL_HANDLER(0) 31 | INSTALL_HANDLER(1) 32 | INSTALL_HANDLER(2) 33 | INSTALL_HANDLER(3) 34 | INSTALL_HANDLER(4) 35 | INSTALL_HANDLER(5) 36 | INSTALL_HANDLER(6) 37 | INSTALL_HANDLER(7) 38 | INSTALL_HANDLER(8) 39 | INSTALL_HANDLER(9) 40 | INSTALL_HANDLER(10) 41 | INSTALL_HANDLER(11) 42 | INSTALL_HANDLER(12) 43 | INSTALL_HANDLER(13) 44 | INSTALL_HANDLER(14) 45 | INSTALL_HANDLER(15) 46 | INSTALL_HANDLER(16) 47 | INSTALL_HANDLER(17) 48 | INSTALL_HANDLER(18) 49 | INSTALL_HANDLER(19) 50 | INSTALL_HANDLER(20) 51 | INSTALL_HANDLER(21) 52 | INSTALL_HANDLER(22) 53 | INSTALL_HANDLER(23) 54 | INSTALL_HANDLER(24) 55 | INSTALL_HANDLER(25) 56 | INSTALL_HANDLER(26) 57 | INSTALL_HANDLER(27) 58 | INSTALL_HANDLER(28) 59 | INSTALL_HANDLER(29) 60 | INSTALL_HANDLER(30) 61 | INSTALL_HANDLER(31) 62 | INSTALL_HANDLER(32) 63 | INSTALL_HANDLER(33) 64 | INSTALL_HANDLER(34) 65 | INSTALL_HANDLER(35) 66 | INSTALL_HANDLER(36) 67 | INSTALL_HANDLER(37) 68 | INSTALL_HANDLER(38) 69 | INSTALL_HANDLER(39) 70 | INSTALL_HANDLER(40) 71 | INSTALL_HANDLER(41) 72 | INSTALL_HANDLER(42) 73 | INSTALL_HANDLER(43) 74 | INSTALL_HANDLER(44) 75 | INSTALL_HANDLER(45) 76 | INSTALL_HANDLER(46) 77 | INSTALL_HANDLER(47) 78 | INSTALL_HANDLER(48) 79 | INSTALL_HANDLER(49) 80 | INSTALL_HANDLER(50) 81 | INSTALL_HANDLER(51) 82 | INSTALL_HANDLER(52) 83 | INSTALL_HANDLER(53) 84 | INSTALL_HANDLER(54) 85 | INSTALL_HANDLER(55) 86 | INSTALL_HANDLER(56) 87 | INSTALL_HANDLER(57) 88 | INSTALL_HANDLER(58) 89 | INSTALL_HANDLER(59) 90 | INSTALL_HANDLER(60) 91 | INSTALL_HANDLER(61) 92 | INSTALL_HANDLER(62) 93 | INSTALL_HANDLER(63) 94 | INSTALL_HANDLER(64) 95 | INSTALL_HANDLER(65) 96 | INSTALL_HANDLER(66) 97 | INSTALL_HANDLER(67) 98 | INSTALL_HANDLER(68) 99 | INSTALL_HANDLER(69) 100 | INSTALL_HANDLER(70) 101 | INSTALL_HANDLER(71) 102 | INSTALL_HANDLER(72) 103 | INSTALL_HANDLER(73) 104 | INSTALL_HANDLER(74) 105 | INSTALL_HANDLER(75) 106 | INSTALL_HANDLER(76) 107 | INSTALL_HANDLER(77) 108 | INSTALL_HANDLER(78) 109 | INSTALL_HANDLER(79) 110 | INSTALL_HANDLER(80) 111 | INSTALL_HANDLER(81) 112 | INSTALL_HANDLER(82) 113 | INSTALL_HANDLER(83) 114 | INSTALL_HANDLER(84) 115 | INSTALL_HANDLER(85) 116 | INSTALL_HANDLER(86) 117 | INSTALL_HANDLER(87) 118 | INSTALL_HANDLER(88) 119 | INSTALL_HANDLER(89) 120 | INSTALL_HANDLER(90) 121 | INSTALL_HANDLER(91) 122 | INSTALL_HANDLER(92) 123 | INSTALL_HANDLER(93) 124 | INSTALL_HANDLER(94) 125 | INSTALL_HANDLER(95) 126 | INSTALL_HANDLER(96) 127 | INSTALL_HANDLER(97) 128 | INSTALL_HANDLER(98) 129 | INSTALL_HANDLER(99) 130 | INSTALL_HANDLER(100) 131 | INSTALL_HANDLER(101) 132 | INSTALL_HANDLER(102) 133 | INSTALL_HANDLER(103) 134 | INSTALL_HANDLER(104) 135 | INSTALL_HANDLER(105) 136 | INSTALL_HANDLER(106) 137 | INSTALL_HANDLER(107) 138 | INSTALL_HANDLER(108) 139 | INSTALL_HANDLER(109) 140 | INSTALL_HANDLER(110) 141 | INSTALL_HANDLER(111) 142 | INSTALL_HANDLER(112) 143 | INSTALL_HANDLER(113) 144 | INSTALL_HANDLER(114) 145 | INSTALL_HANDLER(115) 146 | INSTALL_HANDLER(116) 147 | INSTALL_HANDLER(117) 148 | INSTALL_HANDLER(118) 149 | INSTALL_HANDLER(119) 150 | INSTALL_HANDLER(120) 151 | INSTALL_HANDLER(121) 152 | INSTALL_HANDLER(122) 153 | INSTALL_HANDLER(123) 154 | INSTALL_HANDLER(124) 155 | INSTALL_HANDLER(125) 156 | INSTALL_HANDLER(126) 157 | INSTALL_HANDLER(127) 158 | INSTALL_HANDLER(128) 159 | INSTALL_HANDLER(129) 160 | INSTALL_HANDLER(130) 161 | INSTALL_HANDLER(131) 162 | INSTALL_HANDLER(132) 163 | INSTALL_HANDLER(133) 164 | INSTALL_HANDLER(134) 165 | INSTALL_HANDLER(135) 166 | INSTALL_HANDLER(136) 167 | INSTALL_HANDLER(137) 168 | INSTALL_HANDLER(138) 169 | INSTALL_HANDLER(139) 170 | INSTALL_HANDLER(140) 171 | INSTALL_HANDLER(141) 172 | INSTALL_HANDLER(142) 173 | INSTALL_HANDLER(143) 174 | INSTALL_HANDLER(144) 175 | INSTALL_HANDLER(145) 176 | INSTALL_HANDLER(146) 177 | INSTALL_HANDLER(147) 178 | INSTALL_HANDLER(148) 179 | INSTALL_HANDLER(149) 180 | INSTALL_HANDLER(150) 181 | INSTALL_HANDLER(151) 182 | INSTALL_HANDLER(152) 183 | INSTALL_HANDLER(153) 184 | INSTALL_HANDLER(154) 185 | INSTALL_HANDLER(155) 186 | INSTALL_HANDLER(156) 187 | INSTALL_HANDLER(157) 188 | INSTALL_HANDLER(158) 189 | INSTALL_HANDLER(159) 190 | INSTALL_HANDLER(160) 191 | INSTALL_HANDLER(161) 192 | INSTALL_HANDLER(162) 193 | INSTALL_HANDLER(163) 194 | INSTALL_HANDLER(164) 195 | INSTALL_HANDLER(165) 196 | INSTALL_HANDLER(166) 197 | INSTALL_HANDLER(167) 198 | INSTALL_HANDLER(168) 199 | INSTALL_HANDLER(169) 200 | INSTALL_HANDLER(170) 201 | INSTALL_HANDLER(171) 202 | INSTALL_HANDLER(172) 203 | INSTALL_HANDLER(173) 204 | INSTALL_HANDLER(174) 205 | INSTALL_HANDLER(175) 206 | INSTALL_HANDLER(176) 207 | INSTALL_HANDLER(177) 208 | INSTALL_HANDLER(178) 209 | INSTALL_HANDLER(179) 210 | INSTALL_HANDLER(180) 211 | INSTALL_HANDLER(181) 212 | INSTALL_HANDLER(182) 213 | INSTALL_HANDLER(183) 214 | INSTALL_HANDLER(184) 215 | INSTALL_HANDLER(185) 216 | INSTALL_HANDLER(186) 217 | INSTALL_HANDLER(187) 218 | INSTALL_HANDLER(188) 219 | INSTALL_HANDLER(189) 220 | INSTALL_HANDLER(190) 221 | INSTALL_HANDLER(191) 222 | INSTALL_HANDLER(192) 223 | INSTALL_HANDLER(193) 224 | INSTALL_HANDLER(194) 225 | INSTALL_HANDLER(195) 226 | INSTALL_HANDLER(196) 227 | INSTALL_HANDLER(197) 228 | INSTALL_HANDLER(198) 229 | INSTALL_HANDLER(199) 230 | INSTALL_HANDLER(200) 231 | INSTALL_HANDLER(201) 232 | INSTALL_HANDLER(202) 233 | INSTALL_HANDLER(203) 234 | INSTALL_HANDLER(204) 235 | INSTALL_HANDLER(205) 236 | INSTALL_HANDLER(206) 237 | INSTALL_HANDLER(207) 238 | INSTALL_HANDLER(208) 239 | INSTALL_HANDLER(209) 240 | INSTALL_HANDLER(210) 241 | INSTALL_HANDLER(211) 242 | INSTALL_HANDLER(212) 243 | INSTALL_HANDLER(213) 244 | INSTALL_HANDLER(214) 245 | INSTALL_HANDLER(215) 246 | INSTALL_HANDLER(216) 247 | INSTALL_HANDLER(217) 248 | INSTALL_HANDLER(218) 249 | INSTALL_HANDLER(219) 250 | INSTALL_HANDLER(220) 251 | INSTALL_HANDLER(221) 252 | INSTALL_HANDLER(222) 253 | INSTALL_HANDLER(223) 254 | INSTALL_HANDLER(224) 255 | INSTALL_HANDLER(225) 256 | INSTALL_HANDLER(226) 257 | INSTALL_HANDLER(227) 258 | INSTALL_HANDLER(228) 259 | INSTALL_HANDLER(229) 260 | INSTALL_HANDLER(230) 261 | INSTALL_HANDLER(231) 262 | INSTALL_HANDLER(232) 263 | INSTALL_HANDLER(233) 264 | INSTALL_HANDLER(234) 265 | INSTALL_HANDLER(235) 266 | INSTALL_HANDLER(236) 267 | INSTALL_HANDLER(237) 268 | INSTALL_HANDLER(238) 269 | INSTALL_HANDLER(239) 270 | INSTALL_HANDLER(240) 271 | INSTALL_HANDLER(241) 272 | INSTALL_HANDLER(242) 273 | INSTALL_HANDLER(243) 274 | INSTALL_HANDLER(244) 275 | INSTALL_HANDLER(245) 276 | INSTALL_HANDLER(246) 277 | INSTALL_HANDLER(247) 278 | INSTALL_HANDLER(248) 279 | INSTALL_HANDLER(249) 280 | INSTALL_HANDLER(250) 281 | INSTALL_HANDLER(251) 282 | INSTALL_HANDLER(252) 283 | INSTALL_HANDLER(253) 284 | INSTALL_HANDLER(254) 285 | INSTALL_HANDLER(255) 286 | } 287 | -------------------------------------------------------------------------------- /kernel/io.s: -------------------------------------------------------------------------------- 1 | .intel_syntax noprefix 2 | .section .text 3 | .global outb 4 | .type outb, @function 5 | 6 | .global inb 7 | .type inb, @function 8 | 9 | .global load_gdt 10 | .type load_gdt, @function 11 | 12 | .global load_idt 13 | .type load_idt, @function 14 | 15 | .global enable_interrupts 16 | .type enable_interrupts, @function 17 | 18 | .global disable_interrupts 19 | .type disable_interrupts, @function 20 | 21 | .global flush_gdt 22 | .type flush_gdt, @function 23 | 24 | .global gpf_handler 25 | .type gpf_handler, @function 26 | 27 | .extern c_gpf_handler 28 | .type c_gpf_handler, @function 29 | 30 | /* 31 | Writes 1 bytesto given port 32 | Takes 2 bytes address, then 1 bytes of data 33 | */ 34 | outb: 35 | push ebp 36 | mov ebp, esp 37 | mov dx, [ebp+8] 38 | mov al, [ebp+12] 39 | out dx, al 40 | pop ebp 41 | ret 42 | 43 | /* 44 | Reads 2 bytes from the given address 45 | */ 46 | inb: 47 | push ebp 48 | mov ebp, esp 49 | mov dx, [ebp+8] 50 | in al, dx 51 | pop ebp 52 | ret 53 | 54 | .global outw 55 | outw: 56 | push ebp 57 | mov ebp, esp 58 | mov dx, [ebp+8] 59 | mov ax, [ebp+12] 60 | out dx, ax 61 | pop ebp 62 | ret 63 | 64 | .global inw 65 | inw: 66 | push ebp 67 | mov ebp, esp 68 | mov dx, [ebp+8] 69 | in ax, dx 70 | pop ebp 71 | ret 72 | 73 | .global outdw 74 | outdw: 75 | push ebp 76 | mov ebp, esp 77 | mov dx, [ebp+8] 78 | mov eax, [ebp+12] 79 | out dx, eax 80 | pop ebp 81 | ret 82 | 83 | .global indw 84 | indw: 85 | push ebp 86 | mov ebp, esp 87 | mov dx, [ebp+8] 88 | in eax, dx 89 | pop ebp 90 | ret 91 | /* 92 | calls lgdt 93 | */ 94 | load_gdt: 95 | lgdt [esp+4] 96 | jmp 0x08:flush_gdt 97 | ret 98 | 99 | flush_gdt: 100 | mov ax, 0x10 101 | mov ds, ax 102 | mov ds, ax 103 | mov es, ax 104 | mov fs, ax 105 | mov gs, ax 106 | mov ss, ax 107 | ret 108 | 109 | load_idt: 110 | lidt [esp+4] 111 | ret 112 | 113 | enable_interrupts: 114 | sti 115 | ret 116 | 117 | disable_interrupts: 118 | cli 119 | ret 120 | 121 | .global general_interrupt_handler 122 | .type general_interrupt_handler, @function 123 | 124 | .macro INTERRUPT OFFSET 125 | .global INTERRUPT_\OFFSET 126 | INTERRUPT_\OFFSET: 127 | cli 128 | pusha 129 | mov eax, \OFFSET 130 | push eax 131 | call general_interrupt_handler 132 | pop eax 133 | popa 134 | sti 135 | iretd 136 | .endm 137 | 138 | INTERRUPT 0 139 | INTERRUPT 1 140 | INTERRUPT 2 141 | INTERRUPT 3 142 | INTERRUPT 4 143 | INTERRUPT 5 144 | INTERRUPT 6 145 | INTERRUPT 7 146 | INTERRUPT 8 147 | INTERRUPT 9 148 | INTERRUPT 10 149 | INTERRUPT 11 150 | INTERRUPT 12 151 | INTERRUPT 13 152 | INTERRUPT 14 153 | INTERRUPT 15 154 | INTERRUPT 16 155 | INTERRUPT 17 156 | INTERRUPT 18 157 | INTERRUPT 19 158 | INTERRUPT 20 159 | INTERRUPT 21 160 | INTERRUPT 22 161 | INTERRUPT 23 162 | INTERRUPT 24 163 | INTERRUPT 25 164 | INTERRUPT 26 165 | INTERRUPT 27 166 | INTERRUPT 28 167 | INTERRUPT 29 168 | INTERRUPT 30 169 | INTERRUPT 31 170 | INTERRUPT 32 171 | INTERRUPT 33 172 | INTERRUPT 34 173 | INTERRUPT 35 174 | INTERRUPT 36 175 | INTERRUPT 37 176 | INTERRUPT 38 177 | INTERRUPT 39 178 | INTERRUPT 40 179 | INTERRUPT 41 180 | INTERRUPT 42 181 | INTERRUPT 43 182 | INTERRUPT 44 183 | INTERRUPT 45 184 | INTERRUPT 46 185 | INTERRUPT 47 186 | INTERRUPT 48 187 | INTERRUPT 49 188 | INTERRUPT 50 189 | INTERRUPT 51 190 | INTERRUPT 52 191 | INTERRUPT 53 192 | INTERRUPT 54 193 | INTERRUPT 55 194 | INTERRUPT 56 195 | INTERRUPT 57 196 | INTERRUPT 58 197 | INTERRUPT 59 198 | INTERRUPT 60 199 | INTERRUPT 61 200 | INTERRUPT 62 201 | INTERRUPT 63 202 | INTERRUPT 64 203 | INTERRUPT 65 204 | INTERRUPT 66 205 | INTERRUPT 67 206 | INTERRUPT 68 207 | INTERRUPT 69 208 | INTERRUPT 70 209 | INTERRUPT 71 210 | INTERRUPT 72 211 | INTERRUPT 73 212 | INTERRUPT 74 213 | INTERRUPT 75 214 | INTERRUPT 76 215 | INTERRUPT 77 216 | INTERRUPT 78 217 | INTERRUPT 79 218 | INTERRUPT 80 219 | INTERRUPT 81 220 | INTERRUPT 82 221 | INTERRUPT 83 222 | INTERRUPT 84 223 | INTERRUPT 85 224 | INTERRUPT 86 225 | INTERRUPT 87 226 | INTERRUPT 88 227 | INTERRUPT 89 228 | INTERRUPT 90 229 | INTERRUPT 91 230 | INTERRUPT 92 231 | INTERRUPT 93 232 | INTERRUPT 94 233 | INTERRUPT 95 234 | INTERRUPT 96 235 | INTERRUPT 97 236 | INTERRUPT 98 237 | INTERRUPT 99 238 | INTERRUPT 100 239 | INTERRUPT 101 240 | INTERRUPT 102 241 | INTERRUPT 103 242 | INTERRUPT 104 243 | INTERRUPT 105 244 | INTERRUPT 106 245 | INTERRUPT 107 246 | INTERRUPT 108 247 | INTERRUPT 109 248 | INTERRUPT 110 249 | INTERRUPT 111 250 | INTERRUPT 112 251 | INTERRUPT 113 252 | INTERRUPT 114 253 | INTERRUPT 115 254 | INTERRUPT 116 255 | INTERRUPT 117 256 | INTERRUPT 118 257 | INTERRUPT 119 258 | INTERRUPT 120 259 | INTERRUPT 121 260 | INTERRUPT 122 261 | INTERRUPT 123 262 | INTERRUPT 124 263 | INTERRUPT 125 264 | INTERRUPT 126 265 | INTERRUPT 127 266 | INTERRUPT 128 267 | INTERRUPT 129 268 | INTERRUPT 130 269 | INTERRUPT 131 270 | INTERRUPT 132 271 | INTERRUPT 133 272 | INTERRUPT 134 273 | INTERRUPT 135 274 | INTERRUPT 136 275 | INTERRUPT 137 276 | INTERRUPT 138 277 | INTERRUPT 139 278 | INTERRUPT 140 279 | INTERRUPT 141 280 | INTERRUPT 142 281 | INTERRUPT 143 282 | INTERRUPT 144 283 | INTERRUPT 145 284 | INTERRUPT 146 285 | INTERRUPT 147 286 | INTERRUPT 148 287 | INTERRUPT 149 288 | INTERRUPT 150 289 | INTERRUPT 151 290 | INTERRUPT 152 291 | INTERRUPT 153 292 | INTERRUPT 154 293 | INTERRUPT 155 294 | INTERRUPT 156 295 | INTERRUPT 157 296 | INTERRUPT 158 297 | INTERRUPT 159 298 | INTERRUPT 160 299 | INTERRUPT 161 300 | INTERRUPT 162 301 | INTERRUPT 163 302 | INTERRUPT 164 303 | INTERRUPT 165 304 | INTERRUPT 166 305 | INTERRUPT 167 306 | INTERRUPT 168 307 | INTERRUPT 169 308 | INTERRUPT 170 309 | INTERRUPT 171 310 | INTERRUPT 172 311 | INTERRUPT 173 312 | INTERRUPT 174 313 | INTERRUPT 175 314 | INTERRUPT 176 315 | INTERRUPT 177 316 | INTERRUPT 178 317 | INTERRUPT 179 318 | INTERRUPT 180 319 | INTERRUPT 181 320 | INTERRUPT 182 321 | INTERRUPT 183 322 | INTERRUPT 184 323 | INTERRUPT 185 324 | INTERRUPT 186 325 | INTERRUPT 187 326 | INTERRUPT 188 327 | INTERRUPT 189 328 | INTERRUPT 190 329 | INTERRUPT 191 330 | INTERRUPT 192 331 | INTERRUPT 193 332 | INTERRUPT 194 333 | INTERRUPT 195 334 | INTERRUPT 196 335 | INTERRUPT 197 336 | INTERRUPT 198 337 | INTERRUPT 199 338 | INTERRUPT 200 339 | INTERRUPT 201 340 | INTERRUPT 202 341 | INTERRUPT 203 342 | INTERRUPT 204 343 | INTERRUPT 205 344 | INTERRUPT 206 345 | INTERRUPT 207 346 | INTERRUPT 208 347 | INTERRUPT 209 348 | INTERRUPT 210 349 | INTERRUPT 211 350 | INTERRUPT 212 351 | INTERRUPT 213 352 | INTERRUPT 214 353 | INTERRUPT 215 354 | INTERRUPT 216 355 | INTERRUPT 217 356 | INTERRUPT 218 357 | INTERRUPT 219 358 | INTERRUPT 220 359 | INTERRUPT 221 360 | INTERRUPT 222 361 | INTERRUPT 223 362 | INTERRUPT 224 363 | INTERRUPT 225 364 | INTERRUPT 226 365 | INTERRUPT 227 366 | INTERRUPT 228 367 | INTERRUPT 229 368 | INTERRUPT 230 369 | INTERRUPT 231 370 | INTERRUPT 232 371 | INTERRUPT 233 372 | INTERRUPT 234 373 | INTERRUPT 235 374 | INTERRUPT 236 375 | INTERRUPT 237 376 | INTERRUPT 238 377 | INTERRUPT 239 378 | INTERRUPT 240 379 | INTERRUPT 241 380 | INTERRUPT 242 381 | INTERRUPT 243 382 | INTERRUPT 244 383 | INTERRUPT 245 384 | INTERRUPT 246 385 | INTERRUPT 247 386 | INTERRUPT 248 387 | INTERRUPT 249 388 | INTERRUPT 250 389 | INTERRUPT 251 390 | INTERRUPT 252 391 | INTERRUPT 253 392 | INTERRUPT 254 393 | INTERRUPT 255 394 | --------------------------------------------------------------------------------