├── .gitignore ├── dist └── arc.iso ├── wrapper └── wrapper.asm ├── kernel ├── kernel.h ├── kernel.c ├── process │ └── process.h └── cpu │ ├── idt.h │ └── idt │ ├── idt.c │ └── isr.asm ├── include ├── lib │ ├── stdlib.h │ ├── string.h │ ├── stdarg.h │ ├── stdio.h │ ├── stdlib │ │ └── stdlib.c │ ├── string │ │ └── string.c │ └── stdio │ │ └── stdio.c ├── util │ └── types.h └── arc │ ├── print │ └── print.c │ └── print.h ├── drivers ├── port │ ├── port.h │ └── port.c └── monitor │ ├── monitor.h │ └── monitor.c ├── boot ├── loadDisk.asm ├── gdt.asm ├── print16.asm ├── boot.asm └── switch.asm ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.o 3 | *.bin 4 | -------------------------------------------------------------------------------- /dist/arc.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kbrsh/arc/HEAD/dist/arc.iso -------------------------------------------------------------------------------- /wrapper/wrapper.asm: -------------------------------------------------------------------------------- 1 | [bits 64] 2 | [extern main] 3 | call main 4 | jmp $ 5 | -------------------------------------------------------------------------------- /kernel/kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef KERNEL_H 2 | #define KERNEL_H 3 | 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /kernel/kernel.c: -------------------------------------------------------------------------------- 1 | #include "kernel.h" 2 | #include "./cpu/idt.h" 3 | 4 | #include 5 | 6 | void main(void) { 7 | clear(); 8 | initIDT(); 9 | } 10 | -------------------------------------------------------------------------------- /kernel/process/process.h: -------------------------------------------------------------------------------- 1 | #ifndef PROCESS_H 2 | #define PROCESS_H 3 | 4 | #include 5 | 6 | struct process { 7 | u8* name 8 | }; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/lib/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef STDLIB_H 2 | #define STDLIB_H 3 | 4 | #include 5 | 6 | u8 intlen(u64 num); 7 | 8 | void* malloc(u32 size); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /drivers/port/port.h: -------------------------------------------------------------------------------- 1 | #ifndef PORT_H 2 | #define PORT_H 3 | 4 | #include 5 | 6 | u8 portByteIn(u16 port); 7 | void portByteOut(u16 port, u8 value); 8 | u16 portWordIn(u16 port); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/lib/string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include 5 | 6 | u32 strlen(s8 *str); 7 | 8 | s8 strcpy(s8 *str, const s8 *copy); 9 | 10 | s8 strcat(s8 *str, const s8 *add); 11 | 12 | void memset(void *pointer, u32 item, u64 length); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /boot/loadDisk.asm: -------------------------------------------------------------------------------- 1 | [bits 16] 2 | loadDisk: 3 | pusha 4 | push dx 5 | 6 | mov ah, 0x02 ; Read operation 7 | mov al, 10 ; Read 10 sectors 8 | mov ch, 0x00 ; Read cylinder 0 9 | mov dh, 0x00 ; Read head 0 10 | mov cl, 0x02 ; Read from sector 2 11 | 12 | int 0x13 13 | 14 | pop dx 15 | popa 16 | ret 17 | -------------------------------------------------------------------------------- /include/lib/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef STDARG_H 2 | #define STDARG_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | void *cur; 8 | } va_list; 9 | 10 | #define va_start(list, ref) list.cur = &ref + sizeof(ref); 11 | 12 | #define va_arg(list, type) *(type*)list.cur; list.cur += sizeof(type); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/util/types.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_H 2 | #define TYPES_H 3 | 4 | typedef unsigned long long u64; 5 | typedef long long s64; 6 | 7 | typedef unsigned int u32; 8 | typedef int s32; 9 | 10 | typedef unsigned short u16; 11 | typedef short s16; 12 | 13 | typedef unsigned char u8; 14 | typedef char s8; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /include/lib/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef STDIO_H 2 | #define STDIO_H 3 | 4 | #include 5 | 6 | #define calcf(str, ...) _calcf(str, ##__VA_ARGS__) 7 | u32 _calcf(const s8 *str, ...); 8 | 9 | #define sprintf(buf, str, ...) _sprintf(buf, str, ##__VA_ARGS__) 10 | void _sprintf(s8 *buf, const s8 *str, ...); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/lib/stdlib/stdlib.c: -------------------------------------------------------------------------------- 1 | #include "../stdlib.h" 2 | #include 3 | 4 | u8 intlen(u64 num) { 5 | // Length starts at one 6 | u8 length = 1; 7 | 8 | // Keep dividing by ten (base) to reach length 9 | while(num > 9) { 10 | length++; 11 | num /= 10; 12 | } 13 | 14 | return length; 15 | } 16 | 17 | void* malloc(u32 size) { 18 | // Placeholder 19 | return (void*)(0x00000f); 20 | } 21 | -------------------------------------------------------------------------------- /boot/gdt.asm: -------------------------------------------------------------------------------- 1 | GDT: 2 | .Null: 3 | dq 0 4 | 5 | .Code: 6 | dw 0 7 | dw 0 8 | db 0 9 | db 10011010b 10 | db 00100000b 11 | db 0 12 | 13 | .Data: 14 | dw 0 15 | dw 0 16 | db 0 17 | db 10010010b 18 | db 00000000b 19 | db 0 20 | 21 | .Pointer: 22 | dw $ - GDT.Null - 1 23 | dd GDT.Null 24 | 25 | .codeSeg: equ GDT.Code - GDT.Null 26 | .dataSeg: equ GDT.Data - GDT.Null 27 | -------------------------------------------------------------------------------- /drivers/port/port.c: -------------------------------------------------------------------------------- 1 | #include "port.h" 2 | 3 | u8 portByteIn(u16 port) { 4 | u8 output; 5 | __asm__("in %%dx, %%al" : "=a" (output) : "d" (port)); 6 | return output; 7 | } 8 | 9 | void portByteOut(u16 port, u8 value) { 10 | __asm__("out %%al, %%dx" : : "a" (value), "d" (port)); 11 | } 12 | 13 | unsigned short portWordIn(u16 port) { 14 | u16 output; 15 | __asm__("in %%dx, %%ax" : "=a" (output) : "d" (port)); 16 | return output; 17 | } 18 | -------------------------------------------------------------------------------- /drivers/monitor/monitor.h: -------------------------------------------------------------------------------- 1 | #ifndef MONITOR_H 2 | #define MONITOR_H 3 | 4 | #include 5 | 6 | #define VIDEO_LOCATION 0xb8000 7 | #define MAX_ROWS 25 8 | #define MAX_COLS 80 9 | #define SIZE 25 * 80 10 | 11 | #define SPACE *" " 12 | 13 | #define SCREEN_CONTROL_PORT 0x3d4 14 | #define SCREEN_DATA_PORT 0x3d5 15 | 16 | void monitorInit(void); 17 | void monitorClear(void); 18 | void monitorWriteChar(s8 ch); 19 | void monitorWrite(s8 *ch); 20 | void monitorPrintCenter(s8 *ch); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/arc/print/print.c: -------------------------------------------------------------------------------- 1 | #include "../print.h" 2 | #include "../../../drivers/monitor/monitor.h" 3 | 4 | void clear(void) { 5 | // Clear Monitor 6 | monitorClear(); 7 | } 8 | 9 | void _writek(s8 *str) { 10 | // Write to Monitor 11 | monitorWrite(str); 12 | } 13 | 14 | void _printk(s8 *str) { 15 | // Print to Monitor 16 | monitorWrite(str); 17 | monitorWriteChar('\n'); 18 | } 19 | 20 | void printkCenter(s8 *str) { 21 | // Print in Center of Monitor 22 | monitorPrintCenter(str); 23 | } 24 | -------------------------------------------------------------------------------- /boot/print16.asm: -------------------------------------------------------------------------------- 1 | ; 16 Bit Print 2 | [bits 16] 3 | 4 | ; Print Function 5 | print16: 6 | pusha ; Push registers to stack 7 | mov ah, 0x0e ; Switch to TTY Mode 8 | 9 | ; Printing Loop 10 | print16Loop: 11 | mov al, [bx] ; Set register to current character pointer to memory 12 | cmp al, 0 ; Compare index to 0 to see if string ended 13 | je print16End ; If string ended, exit loop 14 | 15 | int 0x10 ; Interupt and Print 16 | 17 | add bx, 1 ; Increment Counter 18 | jmp print16Loop ; Repeat 19 | 20 | ; End 21 | print16End: 22 | popa ; Pop all registers in stack 23 | ret ; Return 24 | -------------------------------------------------------------------------------- /include/arc/print.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_H 2 | #define PRINT_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void clear(void); 9 | 10 | #define writek(str, ...) { u32 size = calcf(str, ##__VA_ARGS__); s8 buf[size]; sprintf(buf, str, ##__VA_ARGS__); _writek(buf); } 11 | void _writek(s8 *str); 12 | 13 | #define printk(str, ...) { u32 size = calcf(str, ##__VA_ARGS__); s8 buf[size]; sprintf(buf, str, ##__VA_ARGS__); _printk(buf); } 14 | void _printk(s8 *str); 15 | 16 | void printkCenter(s8 *str); 17 | 18 | #define error(str, ...) { u32 size = 13 + calcf(str, ##__VA_ARGS__); s8 newStr[size]; strcpy(newStr, "[Arc] ERROR: "); strcat(newStr, str); s8 buf[size]; sprintf(buf, newStr, ##__VA_ARGS__); _printk(buf); } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/lib/string/string.c: -------------------------------------------------------------------------------- 1 | #include "../string.h" 2 | 3 | u32 strlen(s8 *str) { 4 | // Iterate through null terminated string and find length 5 | u32 i = 0; 6 | 7 | while(str[i] != '\0') { 8 | i++; 9 | } 10 | 11 | return i; 12 | } 13 | 14 | s8 strcpy(s8 *str, const s8 *copy) { 15 | s8 *start = str; 16 | 17 | while((*str++ = *copy++) != '\0') 18 | ; 19 | 20 | return *(s8*)start; 21 | } 22 | 23 | s8 strcat(s8 *str, const s8 *add) { 24 | s8 *start = str; 25 | 26 | while(*str != '\0') { 27 | str++; 28 | } 29 | 30 | while((*str++ = *add++) != '\0') 31 | ; 32 | 33 | return *(s8*)start; 34 | } 35 | 36 | void memset(void *voidPointer, u32 item, u64 length) { 37 | // Fill memory 38 | unsigned char *pointer = (unsigned char*) voidPointer; 39 | while(length--) { 40 | *pointer++ = item; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Kabir Shah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /boot/boot.asm: -------------------------------------------------------------------------------- 1 | [org 0x7c00] 2 | 3 | ; Main Boot 4 | [bits 16] 5 | boot: 6 | mov [bootDrive], dl ; Setup Boot Drive Location 7 | 8 | ; Setup stack 9 | mov bp, 0x1000 10 | mov sp, bp 11 | 12 | mov bx, intro ; Store Message in "Base Index" Register 13 | call print16 ; Print Intro 14 | 15 | call load ; Load Kernel 16 | 17 | call switch ; Switch to Protected Mode 18 | 19 | jmp $ ; Loop 20 | 21 | ; Load 16 bit printing utility 22 | %include "boot/print16.asm" 23 | 24 | ; Load 16 bit disk loading utility 25 | %include "boot/loadDisk.asm" 26 | 27 | ; Load Switcher to Protected Mode 28 | %include "boot/switch.asm" 29 | 30 | ; Load 64 bit GDT 31 | %include "boot/gdt.asm" 32 | 33 | ; Load Kernel 34 | [bits 16] 35 | load: 36 | ; Setup parameters to read from kernel location (0x10000) 37 | mov bx, 0x1000 38 | mov es, bx 39 | mov bx, 0 40 | 41 | mov dl, [bootDrive] ; Read from boot drive 42 | 43 | call loadDisk ; Load from disk 44 | 45 | ret 46 | 47 | ; After Switching to Long Mode 48 | [bits 64] 49 | afterSwitch: 50 | call 0x10000 ; Call Kernel 51 | 52 | hlt ; Halt CPU 53 | 54 | ; Intro Message 55 | intro db "Arc", 0 56 | 57 | ; Boot Drive Location 58 | bootDrive db 0 59 | 60 | times 510 - ($ - $$) db 0 ; Skip over 510 Bytes 61 | dw 0xaa55 ; Let BIOS know disk is Bootable 62 | -------------------------------------------------------------------------------- /boot/switch.asm: -------------------------------------------------------------------------------- 1 | ; Stay in 16 bits 2 | [bits 16] 3 | 4 | ; Initialize Switch to 64 bit long mode 5 | switch: 6 | cli ; Disable Interrupts 7 | 8 | ; Setup paging tables 9 | fill: 10 | mov dword [0x1000 + ecx], 0x2000 11 | or dword [0x1000 + ecx], 111b 12 | mov dword [0x1000 + ecx + 4], 0 13 | mov dword [0x2000 + ecx], 0x3000 14 | or dword [0x2000 + ecx], 111b 15 | mov dword [0x2000 + ecx + 4], 0 16 | mov dword [0x3000 + ecx], 0x4000 17 | or dword [0x3000 + ecx], 111b 18 | mov dword [0x3000 + ecx + 4], 0 19 | 20 | mov eax, (4096/8) 21 | mul ecx 22 | mov dword [0x4000 + ecx], eax 23 | or dword [0x4000 + ecx], 111b 24 | mov dword [0x4000 + ecx + 4], 0 25 | 26 | add ecx, 8 27 | cmp ecx, 4096 28 | jl fill 29 | 30 | ; Setup PAE 31 | mov eax, cr4 32 | or eax, 1 << 5 33 | mov cr4, eax 34 | 35 | ; Use page table in control register 36 | mov eax, 0x1000 37 | mov cr3, eax 38 | 39 | ; Setup Long Mode bit in EFER MSR 40 | mov ecx, 0xC0000080 41 | rdmsr 42 | or eax, 1 << 8 43 | wrmsr 44 | 45 | ; Enable Paging 46 | mov eax, cr0 47 | or eax, 1 << 31 | 1 48 | mov cr0, eax 49 | 50 | lgdt [GDT.Pointer] ; Load GDT 51 | jmp GDT.codeSeg:switch64 ; Perform far jump 52 | 53 | 54 | [bits 64] 55 | switch64: 56 | ; Update registers 57 | mov ax, GDT.dataSeg 58 | mov ds, ax 59 | mov es, ax 60 | mov ss, ax 61 | mov fs, ax 62 | mov gs, ax 63 | mov ss, ax 64 | 65 | ; After switching to 64 bit long mode, return to main loader and load kernel 66 | call afterSwitch 67 | -------------------------------------------------------------------------------- /drivers/monitor/monitor.c: -------------------------------------------------------------------------------- 1 | #include "monitor.h" 2 | #include "../port/port.h" 3 | #include 4 | 5 | u16 cursorX = 0; 6 | u16 cursorY = 0; 7 | 8 | void scrollToBottom(void) { 9 | 10 | } 11 | 12 | void updateCursorPosition(void) { 13 | u16 cursorPosition = cursorY * MAX_COLS + cursorX; 14 | portByteOut(0x3D4, 14); 15 | portByteOut(0x3D5, cursorPosition >> 8); 16 | portByteOut(0x3D4, 15); 17 | portByteOut(0x3D5, cursorPosition); 18 | } 19 | 20 | void monitorWriteChar(s8 ch) { 21 | u16 *videoMemory = (u16*)VIDEO_LOCATION; 22 | 23 | switch(ch) { 24 | case '\n': 25 | cursorX = 0; 26 | cursorY++; 27 | break; 28 | case '\t': 29 | cursorX += 2; 30 | break; 31 | case '\r': 32 | cursorX = 0; 33 | break; 34 | default: 35 | videoMemory[cursorY * MAX_COLS + cursorX] = ch | 3840; 36 | cursorX++; 37 | } 38 | 39 | if(cursorX >= MAX_COLS) { 40 | cursorX = 0; 41 | cursorY++; 42 | } 43 | 44 | updateCursorPosition(); 45 | } 46 | 47 | void monitorClear(void) { 48 | u16 *videoMemory = (u16*)VIDEO_LOCATION; 49 | u16 i; 50 | 51 | for(i = 0; i < SIZE; ++i) { 52 | videoMemory[i] = 0x20 | 3840; 53 | } 54 | 55 | cursorX = 0; 56 | cursorY = 0; 57 | updateCursorPosition(); 58 | } 59 | 60 | void monitorWrite(s8 *str) { 61 | u16 i = 0; 62 | while(str[i] != 0) { 63 | monitorWriteChar(str[i++]); 64 | } 65 | } 66 | 67 | void monitorPrintCenter(s8 *str) { 68 | u32 len = strlen(str); 69 | cursorX = (MAX_COLS / 2) - len; 70 | cursorY = (MAX_ROWS / 2) - 1; 71 | monitorWrite(str); 72 | } 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arc 2 | 3 | Minimalistic Kernel for Learning 4 | 5 | ### Todo 6 | 7 | - [x] Bootloader 8 | - [x] Real Mode 9 | - [x] Protected Mode 10 | - [x] Long Mode 11 | - [x] Give control to Kernel 12 | - [ ] Includes 13 | - [x] Ample 14 | - [x] Printing Utilities (`` - `printk`) 15 | - [ ] LibC 16 | - [x] Stdio 17 | - [x] `sprintf` - format string 18 | - [ ] Stdlib 19 | - [x] `intlen` - return length of an integer 20 | - [ ] `malloc` - allocate memory 21 | - [ ] `free` - free memory 22 | - [x] String 23 | - [x] `strlen` - give length of a string 24 | - [x] `memset` - set memory of a buffer to a value 25 | - [x] Stdarg 26 | - [x] Variadic Functions (`va_list`, `va_start`, `va_arg`) 27 | - [ ] Kernel 28 | - [ ] Interrupts 29 | - [ ] Virtual File System (VFS) 30 | - [ ] Processes 31 | - [ ] Threads 32 |  - [ ] Scheduler - Priority Round Robin 33 |  - [ ] Memory Allocation (`lib/stdlib.h`) 34 | - [ ] `malloc` 35 | - [ ] `free` 36 | - [ ] User Mode 37 | - [ ] Switch to user mode 38 | - [ ] Stdin 39 | - [ ] Stdout 40 | - [ ] System Calls 41 | - [ ] Shell (`ash`) 42 | - [ ] Logs 43 | - [ ] Initialize keyboard input 44 | - [ ] Commands 45 | - [ ] `pwd` 46 | - [ ] `ls` 47 | - [ ] `cd` 48 | - [ ] `mkdir` 49 | - [ ] `touch` 50 | - [ ] `cat` 51 | - [ ] `echo` 52 | 53 | 54 | 55 | 56 | 57 | 58 | ## License 59 | 60 | Licensed under the [MIT License](https://kbrsh.github.io/license) by [Kabir Shah](https://kabir.ml) 61 | -------------------------------------------------------------------------------- /kernel/cpu/idt.h: -------------------------------------------------------------------------------- 1 | #ifndef IDT_H 2 | #define IDT_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | u16 lowOffset; 8 | u16 selector; 9 | u8 always0; 10 | u8 flags; 11 | u16 middleOffset; 12 | u32 highOffset; 13 | u32 reserved; 14 | } __attribute__((packed)) idtEntry_t; 15 | 16 | typedef struct { 17 | u16 limit; 18 | u64 base; 19 | } __attribute__((packed)) idtHandlersPointer_t; 20 | 21 | typedef struct { 22 | u64 ds; 23 | u64 rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax; 24 | u64 intNum, errorCode; 25 | u64 rip, cs, eflags, useresp, ss; 26 | } registers_t; 27 | 28 | idtEntry_t idtHandlers[256]; 29 | idtHandlersPointer_t idtHandlersPointer; 30 | 31 | extern void isrHandler(registers_t registers); 32 | 33 | extern void isrHandler0(void); 34 | extern void isrHandler1(void); 35 | extern void isrHandler2(void); 36 | extern void isrHandler3(void); 37 | extern void isrHandler4(void); 38 | extern void isrHandler5(void); 39 | extern void isrHandler6(void); 40 | extern void isrHandler7(void); 41 | extern void isrHandler8(void); 42 | extern void isrHandler9(void); 43 | extern void isrHandler10(void); 44 | extern void isrHandler11(void); 45 | extern void isrHandler12(void); 46 | extern void isrHandler13(void); 47 | extern void isrHandler14(void); 48 | extern void isrHandler15(void); 49 | extern void isrHandler16(void); 50 | extern void isrHandler17(void); 51 | extern void isrHandler18(void); 52 | extern void isrHandler19(void); 53 | extern void isrHandler20(void); 54 | extern void isrHandler21(void); 55 | extern void isrHandler22(void); 56 | extern void isrHandler23(void); 57 | extern void isrHandler24(void); 58 | extern void isrHandler25(void); 59 | extern void isrHandler26(void); 60 | extern void isrHandler27(void); 61 | extern void isrHandler28(void); 62 | extern void isrHandler29(void); 63 | extern void isrHandler30(void); 64 | extern void isrHandler31(void); 65 | 66 | extern void loadIDT(void); 67 | 68 | void setIDTHandler(u32 num, u64 handler); 69 | void initIDT(void); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /kernel/cpu/idt/idt.c: -------------------------------------------------------------------------------- 1 | #include "../idt.h" 2 | #include 3 | 4 | const s8 *exceptionMessages[31] = { 5 | "Division By Zero", 6 | "Debug Breakpoint", 7 | "Non Maskable Interrupt", 8 | "Breakpoint", 9 | "Overflow", 10 | "Bounds", 11 | "Invalid Opcode", 12 | "Coprocessor Unavailable", 13 | "Double Fault", 14 | "Coprocessor Segment Overrun", 15 | "Invalid Task State Segment", 16 | "Segment Not Present", 17 | "Stack Fault", 18 | "General Protection Fault", 19 | "Page Fault", 20 | "Reserved", 21 | "x87 Floating-Point Exception", 22 | "Alignment Check", 23 | "Machine Check", 24 | "SIMD Floating-Point Exception", 25 | "Virtualization Exception", 26 | "Reserved", 27 | "Security Exception", 28 | "Reserved", 29 | "Triple Fault", 30 | "Reserved", 31 | "Reserved", 32 | "Reserved", 33 | "Reserved", 34 | "Reserved", 35 | "Reserved" 36 | }; 37 | 38 | void isrHandler(registers_t registers) { 39 | if(registers.intNum < 32) { 40 | error("Exception: %s Identifier: %ld", exceptionMessages[registers.intNum], registers.intNum); 41 | } 42 | } 43 | 44 | void setIDTHandler(u32 num, u64 handler) { 45 | idtHandlers[num].lowOffset = (u16)(handler & 0xFFFF); 46 | idtHandlers[num].selector = (u16)0x08; 47 | idtHandlers[num].always0 = (u8)0; 48 | idtHandlers[num].flags = (u8)0x8E; 49 | idtHandlers[num].middleOffset = (u16)((handler >> 16) & 0xFFFF); 50 | idtHandlers[num].highOffset = (u32)((handler >> 32) & 0xFFFFFFFF); 51 | idtHandlers[num].reserved = (u32)0; 52 | } 53 | 54 | void initIDT(void) { 55 | idtHandlersPointer.limit = 256 * sizeof(idtEntry_t) - 1; 56 | idtHandlersPointer.base = (u64) &idtHandlers; 57 | 58 | setIDTHandler(0, (u64)isrHandler0); 59 | setIDTHandler(1, (u64)isrHandler1); 60 | setIDTHandler(2, (u64)isrHandler2); 61 | setIDTHandler(3, (u64)isrHandler3); 62 | setIDTHandler(4, (u64)isrHandler4); 63 | setIDTHandler(5, (u64)isrHandler5); 64 | setIDTHandler(6, (u64)isrHandler6); 65 | setIDTHandler(7, (u64)isrHandler7); 66 | setIDTHandler(8, (u64)isrHandler8); 67 | setIDTHandler(9, (u64)isrHandler9); 68 | setIDTHandler(10, (u64)isrHandler10); 69 | setIDTHandler(11, (u64)isrHandler11); 70 | setIDTHandler(12, (u64)isrHandler12); 71 | setIDTHandler(13, (u64)isrHandler13); 72 | setIDTHandler(14, (u64)isrHandler14); 73 | setIDTHandler(15, (u64)isrHandler15); 74 | setIDTHandler(16, (u64)isrHandler16); 75 | setIDTHandler(17, (u64)isrHandler17); 76 | setIDTHandler(18, (u64)isrHandler18); 77 | setIDTHandler(19, (u64)isrHandler19); 78 | setIDTHandler(20, (u64)isrHandler20); 79 | setIDTHandler(21, (u64)isrHandler21); 80 | setIDTHandler(22, (u64)isrHandler22); 81 | setIDTHandler(23, (u64)isrHandler23); 82 | setIDTHandler(24, (u64)isrHandler24); 83 | setIDTHandler(25, (u64)isrHandler25); 84 | setIDTHandler(26, (u64)isrHandler26); 85 | setIDTHandler(27, (u64)isrHandler27); 86 | setIDTHandler(28, (u64)isrHandler28); 87 | setIDTHandler(29, (u64)isrHandler29); 88 | setIDTHandler(30, (u64)isrHandler30); 89 | setIDTHandler(31, (u64)isrHandler31); 90 | 91 | loadIDT(); 92 | } 93 | -------------------------------------------------------------------------------- /include/lib/stdio/stdio.c: -------------------------------------------------------------------------------- 1 | #include "../stdio.h" 2 | #include 3 | #include 4 | #include 5 | 6 | u32 _calcf(const s8 *str, ...) { 7 | va_list list; 8 | va_start(list, str); 9 | 10 | u32 i = 0; // Current position in string 11 | u32 len = 1; // Total length (including NULL terminator) 12 | 13 | s8 ch; // Current character 14 | s8 special; // Current special identifier 15 | 16 | u32 intDigit; 17 | s8 *currentStr; 18 | 19 | while(str[i] != 0) { 20 | ch = str[i]; 21 | if(ch == '%') { 22 | special = str[i + 1]; // Get special identifier 23 | switch(special) { 24 | case 'c': 25 | // A character takes up a byte 26 | len++; 27 | break; 28 | 29 | case 's': 30 | // A string 31 | currentStr = va_arg(list, s8*); 32 | len += strlen(currentStr); 33 | break; 34 | 35 | case 'd': 36 | // A single digit takes up the length of the number 37 | intDigit = va_arg(list, u32); 38 | len += intlen(intDigit); 39 | break; 40 | 41 | case 'l': 42 | i++; 43 | if(str[i + 1] == 'd') { 44 | intDigit = va_arg(list, u64); 45 | len += intlen(intDigit); 46 | } 47 | break; 48 | } 49 | 50 | // Increment position in string 51 | i++; 52 | } else { 53 | // Increment length by a byte 54 | len++; 55 | } 56 | 57 | // Increment position in string 58 | i++; 59 | } 60 | 61 | return len; 62 | } 63 | 64 | void _sprintf(s8 *buf, const s8 *str, ...) { 65 | va_list list; 66 | va_start(list, str); 67 | 68 | u32 i = 0; // Position in string (str) 69 | u32 j = 0; // Position in buffer (buf) 70 | 71 | s8 ch; // Current character 72 | s8 special; // Current special identifier 73 | 74 | u32 intDigit; 75 | u32 length; 76 | 77 | s8 *currentStr; 78 | 79 | while(str[i] != 0) { 80 | ch = str[i]; 81 | if(ch == '%') { 82 | special = str[i + 1]; // Get special identifier 83 | switch(special) { 84 | case 'c': 85 | // Insert character 86 | buf[j] = va_arg(list, s8); 87 | break; 88 | 89 | case 's': 90 | // Insert string 91 | currentStr = va_arg(list, s8*); 92 | while(*currentStr != '\0') { 93 | buf[j++] = *currentStr++; 94 | } 95 | j--; 96 | break; 97 | 98 | case 'd': 99 | // Insert digit (as int) 100 | intDigit = va_arg(list, u32); 101 | length = intlen(intDigit); 102 | j += length; 103 | 104 | while(intDigit != 0) { 105 | j--; 106 | buf[j] = (char)(48 + (intDigit % 10)); 107 | intDigit /= 10; 108 | } 109 | 110 | j += length - 1; 111 | break; 112 | 113 | case 'l': 114 | // Insert digit (as long) 115 | i++; 116 | if(str[i + 1] == 'd') { 117 | intDigit = va_arg(list, u64); 118 | length = intlen(intDigit); 119 | j += length; 120 | 121 | while(intDigit != 0) { 122 | j--; 123 | buf[j] = (char)(48 + (intDigit % 10)); 124 | intDigit /= 10; 125 | } 126 | 127 | j += length - 1; 128 | } 129 | break; 130 | } 131 | 132 | // Increment position in string to skip special identifier 133 | i++; 134 | } else { 135 | buf[j] = ch; 136 | } 137 | 138 | // Increment position in buffer 139 | j++; 140 | 141 | // Increment position in string 142 | i++; 143 | } 144 | 145 | buf[j] = '\0'; 146 | } 147 | -------------------------------------------------------------------------------- /kernel/cpu/idt/isr.asm: -------------------------------------------------------------------------------- 1 | %macro pushAll 0 2 | push rax 3 | push rcx 4 | push rdx 5 | push rbx 6 | push rsp 7 | push rbp 8 | push rsi 9 | push rdi 10 | %endmacro 11 | 12 | %macro popAll 0 13 | pop rdi 14 | pop rsi 15 | pop rbp 16 | pop rsp 17 | pop rbx 18 | pop rdx 19 | pop rcx 20 | pop rax 21 | %endmacro 22 | 23 | extern isrHandler 24 | isrHandlerWrapper: 25 | mov rcx, 10 26 | pushAll 27 | mov ax, ds 28 | push rax 29 | 30 | call isrHandler 31 | 32 | pop rax 33 | 34 | popAll 35 | add rsp, 16 36 | sti 37 | iretq 38 | 39 | global loadIDT 40 | extern idtHandlersPointer 41 | loadIDT: 42 | lidt [idtHandlersPointer] 43 | ret 44 | 45 | global isrHandler0 46 | global isrHandler1 47 | global isrHandler2 48 | global isrHandler3 49 | global isrHandler4 50 | global isrHandler5 51 | global isrHandler6 52 | global isrHandler7 53 | global isrHandler8 54 | global isrHandler9 55 | global isrHandler10 56 | global isrHandler11 57 | global isrHandler12 58 | global isrHandler13 59 | global isrHandler14 60 | global isrHandler15 61 | global isrHandler16 62 | global isrHandler17 63 | global isrHandler18 64 | global isrHandler19 65 | global isrHandler20 66 | global isrHandler21 67 | global isrHandler22 68 | global isrHandler23 69 | global isrHandler24 70 | global isrHandler25 71 | global isrHandler26 72 | global isrHandler27 73 | global isrHandler28 74 | global isrHandler29 75 | global isrHandler30 76 | global isrHandler31 77 | 78 | isrHandler0: 79 | cli 80 | push byte 0 81 | push byte 0 82 | jmp isrHandlerWrapper 83 | 84 | isrHandler1: 85 | cli 86 | push byte 0 87 | push byte 1 88 | jmp isrHandlerWrapper 89 | 90 | isrHandler2: 91 | cli 92 | push byte 0 93 | push byte 2 94 | jmp isrHandlerWrapper 95 | 96 | isrHandler3: 97 | cli 98 | push byte 0 99 | push byte 3 100 | jmp isrHandlerWrapper 101 | 102 | isrHandler4: 103 | cli 104 | push byte 0 105 | push byte 4 106 | jmp isrHandlerWrapper 107 | 108 | isrHandler5: 109 | cli 110 | push byte 0 111 | push byte 5 112 | jmp isrHandlerWrapper 113 | 114 | isrHandler6: 115 | cli 116 | push byte 0 117 | push byte 6 118 | jmp isrHandlerWrapper 119 | 120 | isrHandler7: 121 | cli 122 | push byte 0 123 | push byte 7 124 | jmp isrHandlerWrapper 125 | 126 | isrHandler8: 127 | cli 128 | push byte 8 129 | jmp isrHandlerWrapper 130 | 131 | isrHandler9: 132 | cli 133 | push byte 0 134 | push byte 9 135 | jmp isrHandlerWrapper 136 | 137 | isrHandler10: 138 | cli 139 | push byte 10 140 | jmp isrHandlerWrapper 141 | 142 | isrHandler11: 143 | cli 144 | push byte 11 145 | jmp isrHandlerWrapper 146 | 147 | isrHandler12: 148 | cli 149 | push byte 12 150 | jmp isrHandlerWrapper 151 | 152 | isrHandler13: 153 | cli 154 | push byte 13 155 | jmp isrHandlerWrapper 156 | 157 | isrHandler14: 158 | cli 159 | push byte 14 160 | jmp isrHandlerWrapper 161 | 162 | isrHandler15: 163 | cli 164 | push byte 0 165 | push byte 15 166 | jmp isrHandlerWrapper 167 | 168 | isrHandler16: 169 | cli 170 | push byte 0 171 | push byte 16 172 | jmp isrHandlerWrapper 173 | 174 | isrHandler17: 175 | cli 176 | push byte 0 177 | push byte 17 178 | jmp isrHandlerWrapper 179 | 180 | isrHandler18: 181 | cli 182 | push byte 0 183 | push byte 18 184 | jmp isrHandlerWrapper 185 | 186 | isrHandler19: 187 | cli 188 | push byte 0 189 | push byte 19 190 | jmp isrHandlerWrapper 191 | 192 | isrHandler20: 193 | cli 194 | push byte 0 195 | push byte 20 196 | jmp isrHandlerWrapper 197 | 198 | isrHandler21: 199 | cli 200 | push byte 0 201 | push byte 21 202 | jmp isrHandlerWrapper 203 | 204 | isrHandler22: 205 | cli 206 | push byte 0 207 | push byte 22 208 | jmp isrHandlerWrapper 209 | 210 | isrHandler23: 211 | cli 212 | push byte 0 213 | push byte 23 214 | jmp isrHandlerWrapper 215 | 216 | isrHandler24: 217 | cli 218 | push byte 0 219 | push byte 24 220 | jmp isrHandlerWrapper 221 | 222 | isrHandler25: 223 | cli 224 | push byte 0 225 | push byte 25 226 | jmp isrHandlerWrapper 227 | 228 | isrHandler26: 229 | cli 230 | push byte 0 231 | push byte 26 232 | jmp isrHandlerWrapper 233 | 234 | isrHandler27: 235 | cli 236 | push byte 0 237 | push byte 27 238 | jmp isrHandlerWrapper 239 | 240 | isrHandler28: 241 | cli 242 | push byte 0 243 | push byte 28 244 | jmp isrHandlerWrapper 245 | 246 | isrHandler29: 247 | cli 248 | push byte 0 249 | push byte 29 250 | jmp isrHandlerWrapper 251 | 252 | isrHandler30: 253 | cli 254 | push byte 0 255 | push byte 30 256 | jmp isrHandlerWrapper 257 | 258 | isrHandler31: 259 | cli 260 | push byte 0 261 | push byte 31 262 | jmp isrHandlerWrapper 263 | --------------------------------------------------------------------------------