├── .gitignore ├── Makefile ├── breakpoints ├── gdb.patch ├── gdbinit ├── grub └── grub.cfg ├── kernel ├── Makefile ├── linker.ld ├── runtime.bc.o ├── src │ ├── asm │ │ ├── ceil.s │ │ ├── floor.s │ │ ├── loader.s │ │ └── loader.s.bak │ ├── c │ │ ├── hardware │ │ │ ├── PIC.c │ │ │ ├── PIC.h │ │ │ ├── io.c │ │ │ └── io.h │ │ ├── runtime │ │ │ ├── idt.c │ │ │ ├── idt.h │ │ │ ├── interrupts.c │ │ │ ├── interrupts.h │ │ │ ├── mem_utils.c │ │ │ └── static_alloc.c │ │ └── vga │ │ │ ├── utils.c │ │ │ ├── utils.h │ │ │ ├── vga_textmode.c │ │ │ └── vga_textmode.h │ ├── kotlin │ │ └── main.kt │ └── res │ │ ├── font │ │ ├── fira_mono_regular_17.PNG │ │ ├── font.dat │ │ ├── font.sfl │ │ ├── font_data.c │ │ ├── font_data.h │ │ └── font_defs.h │ │ ├── kotlin.dat │ │ ├── kotlin_250x250.png │ │ ├── resource_data.c │ │ └── resource_data.h └── stdlib.kt.bc.o ├── named_breakpoints └── setBreakpoints.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | vm-gdb: prepare-disk-for-run null_call_breakpoints manual_breakpoints 2 | qemu-system-x86_64 -cpu Haswell-noTSX -drive format=raw,file=build/disk.img -m 512M -s -monitor telnet:127.0.0.1:1235,server,nowait & \ 3 | bash -c 'konsole -e gdb -x gdbinit' 4 | 5 | 6 | vm-db: prepare-disk-for-run 7 | qemu-system-x86_64 -drive format=raw,file=build/disk.img -m 512M -s -S 8 | 9 | vm: prepare-disk-for-run 10 | qemu-system-x86_64 -cpu Haswell-noTSX -drive format=raw,file=build/disk.img -m 512M 11 | 12 | bochs: prepare-disk-for-run 13 | bochs -qf bochs-config 14 | bash -c 'konsole -e gdb -x gdbinit' 15 | 16 | prepare-disk-for-run: install-kernel install-grub-config umount 17 | umount: umount-disk-img lodel-disk-img 18 | umount-disk-img: 19 | sudo umount /tmp/mnt/disk_img || /bin/true \ 20 | && sync 21 | 22 | install-grub: format-disk-img mount-disk-img 23 | sudo grub-install --root-directory=/tmp/mnt/disk_img --no-floppy --modules="normal part_msdos ext2 multiboot" /dev/loop0 24 | 25 | mount-disk-img: losetup-disk-img 26 | mkdir -p /tmp/mnt/disk_img \ 27 | && sudo mount /dev/loop1 /tmp/mnt/disk_img || /bin/true \ 28 | && sudo chown -R 1000:1000 /tmp/mnt/disk_img 29 | 30 | format-disk-img: part-disk-img losetup-disk-img 31 | sudo mke2fs /dev/loop1 \ 32 | && sync 33 | 34 | losetup-disk-img: 35 | sudo losetup /dev/loop0 build/disk.img \ 36 | && sudo losetup /dev/loop1 build/disk.img -o 1048576 37 | 38 | lodel-disk-img: 39 | sudo losetup -d /dev/loop0 || /bin/true \ 40 | && sudo losetup -d /dev/loop1 || /bin/true 41 | 42 | part-disk-img: create-disk-img 43 | parted -s build/disk.img \ 44 | mklabel msdos \ 45 | mkpart primary 2048s 100% \ 46 | set 1 boot on \ 47 | print list 48 | 49 | create-disk-img: 50 | dd if=/dev/zero of=build/disk.img bs=512 count=131072 51 | 52 | install-grub-config: grub/grub.cfg 53 | cp grub /tmp/mnt/disk_img/boot -r 54 | verify-kernel: 55 | grub-file --is-x86-multiboot build/kernel.bin 56 | install-kernel: kernel.bin verify-kernel mount-disk-img 57 | cp build/kernel.bin /tmp/mnt/disk_img/boot/ktkernel.bin \ 58 | && sync 59 | .PHONY: vm-gdb vm prepare-disk-for-run umount umount-disk-img install-grub mount-disk-img format-disk-img losetup-disk-img lodel-disk-img part-disk-img create-disk-img install-grub-config verify-kernel install-kernel kernel/build/kernel.bin 60 | 61 | VPATH = build 62 | 63 | kernel.lst: kernel.bin 64 | nm build/kernel.bin > build/kernel.lst 65 | 66 | null_call_breakpoints: kernel.bin 67 | objdump -d kernel/build/kernel.bin | grep "callq 0" | awk "{print \$$1}" | sed -e "s/\([a-f0-9]*\):/hbreak *0x\1/g" > build/$@ 68 | 69 | manual_breakpoints: kernel.lst 70 | python setBreakpoints.py > build/$@ 71 | 72 | kernel.bin: kernel/build/kernel.bin 73 | cp kernel/build/kernel.bin build/ 74 | 75 | kernel/build/kernel.bin: 76 | $(MAKE) -C kernel all 77 | 78 | #kernel.bin: loader.o main.bc.o xpc.bc.o 79 | # ld -m elf_i386 -T linker.ld -o build/$@ build/loader.o build/main.bc.o build/xpc.bc.o 80 | # 81 | # loader.o: 82 | # as --32 -o build/loader.o loader/loader.s 83 | # 84 | # main.bc: 85 | # konanc kernel/main.kt -nolink -o build/main.bc 86 | # main.bc.o: main.bc 87 | # llc build/main.bc -o build/main.bc.o -filetype=obj -march=x86 -code-model=kernel 88 | # xpc.bc: 89 | # clang -S -emit-llvm kernel/c/vga_out.c -o build/xpc.bc 90 | # xpc.bc.o: xpc.bc 91 | # llc build/$^ -o build/$@ -filetype=obj -march=x86 -code-model=kernel 92 | # runtime.bc.o: 93 | # llc /fastspace/kotlin-native/dist/lib/host/runtime.bc -o build/$@ -filetype=obj -march=x86 -code-model=kernel 94 | -------------------------------------------------------------------------------- /breakpoints: -------------------------------------------------------------------------------- 1 | #^Realm64$ 2 | #^calloc$ 3 | #^malloc$ 4 | #^kfun:kernelMain\(\)$ 5 | #^handle_interrupt$ 6 | #^setup_idt$ 7 | -------------------------------------------------------------------------------- /gdb.patch: -------------------------------------------------------------------------------- 1 | --- remote.c 2015-02-20 19:11:44.000000000 +0200 2 | +++ remote.c 2015-08-12 20:00:14.966043900 +0300 3 | @@ -6154,8 +6154,20 @@ 4 | buf_len = strlen (rs->buf); 5 | 6 | /* Further sanity checks, with knowledge of the architecture. */ 7 | - if (buf_len > 2 * rsa->sizeof_g_packet) 8 | - error (_("Remote 'g' packet reply is too long: %s"), rs->buf); 9 | + //if (buf_len > 2 * rsa->sizeof_g_packet) 10 | + // error (_("Remote 'g' packet reply is too long: %s"), rs->buf); 11 | + 12 | + if(buf_len > 2 * rsa->sizeof_g_packet) { 13 | + rsa->sizeof_g_packet = buf_len; 14 | + for(i = 0; i < gdbarch_num_regs(gdbarch); i++){ 15 | + if(rsa->regs->pnum == -1) 16 | + continue; 17 | + if(rsa->regs->offset >= rsa->sizeof_g_packet) 18 | + rsa->regs->in_g_packet = 0; 19 | + else 20 | + rsa->regs->in_g_packet = 1; 21 | + } 22 | + } 23 | 24 | /* Save the size of the packet sent to us by the target. It is used 25 | as a heuristic when determining the max size of packets that the 26 | -------------------------------------------------------------------------------- /gdbinit: -------------------------------------------------------------------------------- 1 | set arch i386:x86-64 2 | target remote :1234 3 | set pagination off 4 | dir $cwd/kernel 5 | dir /fastspace/kotlin-native/runtime/ 6 | dir /fastspace/gcc-4.8.5/ 7 | 8 | symbol-file build/kernel.bin 9 | source build/manual_breakpoints 10 | source build/null_call_breakpoints 11 | source named_breakpoints 12 | 13 | #source /fastspace/gdb-gui/gdb-gui.py 14 | #gui source 15 | set substitute-path '../../../../../../src/libstdc++-v3' '/fastspace/gcc-4.8.5/libstdc++-v3/' 16 | set substitute-path '/src/libstdc++-v3' '/fastspace/gcc-4.8.5/libstdc++-v3/' 17 | 18 | set pagination on 19 | -------------------------------------------------------------------------------- /grub/grub.cfg: -------------------------------------------------------------------------------- 1 | menuentry "KtOS" { 2 | multiboot /boot/ktkernel.bin 3 | } 4 | 5 | GRUB_DEFAULT="KtOS" 6 | GRUB_TIMEOUT=1 7 | -------------------------------------------------------------------------------- /kernel/Makefile: -------------------------------------------------------------------------------- 1 | VPATH = build:src/c:src/kotlin:src/asm:src/res 2 | 3 | KOTLIN_RUNTIME_SOURCES = $(wildcard src/kotlin/runtime/*.kt) $(wildcard src/kotlin/runtime/kotlin/*.kt) $(wildcard src/kotlin/runtime/konan/*.kt) $(wildcard src/kotlin/runtime/konan/internal/*.kt) 4 | KOTLIN_SOURCES = main.kt 5 | 6 | ASM_SOURCES = loader.s ceil.s floor.s 7 | C_SOURCES = vga/vga_textmode.c vga/utils.c runtime/static_alloc.c runtime/idt.c hardware/PIC.c hardware/io.c runtime/interrupts.c resource_data.c runtime/mem_utils.c font/font_data.c 8 | 9 | IMG_SOURCES = kotlin.dat font/font.dat 10 | 11 | OBJECTS = $(C_SOURCES:.c=.bc.o) $(ASM_SOURCES:.s=.s.o) $(KOTLIN_SOURCES:.kt=.kt.bc.o) $(IMG_SOURCES:.dat=.dat.o) 12 | OBJECTS_LOCATION = $(addprefix build/,${OBJECTS}) 13 | 14 | LLC_FLAGS = -filetype=obj -march=x86-64 -code-model=kernel 15 | CLANG_FLAGS = -Isrc/c -g -c -emit-llvm 16 | 17 | KONANC_FLAGS = -nolink 18 | 19 | GCC_PREFIX = /usr/lib/gcc/x86_64-linux-gnu/4.8 20 | GCC_OBJ = crtbegin.o crtend.o libatomic.a libgcc.a libgcc_eh.a libstdc++.a 21 | GCC_LIBS = $(addprefix ${GCC_PREFIX}/,${GCC_OBJ}) 22 | 23 | LD_IGNORE_UNRESOLVED = --unresolved-symbols=ignore-all 24 | LD_FLAGS = -melf_x86_64 -g ${LD_IGNORE_UNRESOLVED} -T linker.ld --defsym=_Z19RuntimeAssertFailedPKcS0_=AssertionFailedPX -z max-page-size=0x1000 25 | 26 | .PHONY: all clean 27 | all: kernel.bin 28 | 29 | clean: 30 | rm build -rf 31 | # runtime.bc.o stdlib.kt.bc.o 32 | kernel.bin: $(OBJECTS) 33 | ld -o build/kernel.bin runtime.bc.o stdlib.kt.bc.o ${GCC_LIBS} ${OBJECTS_LOCATION} $(LD_FLAGS) 34 | 35 | 36 | %.bc: %.c 37 | mkdir -p build/$(dir $@) && clang $< -o build/$@ $(CLANG_FLAGS) 38 | %.kt.bc: %.kt 39 | mkdir -p build/$(dir $@) && konanc $< -o build/$@ $(KONANC_FLAGS) 40 | %.bc.o: %.bc 41 | mkdir -p build/$(dir $@) && llc build/$< -o build/$@ $(LLC_FLAGS) 42 | %.s.o: %.s 43 | as $< -o build/$@ 44 | 45 | %.dat.o: %.dat 46 | objcopy -B i386:x86-64 -I binary -O elf64-x86-64 $< build/$@ 47 | -------------------------------------------------------------------------------- /kernel/linker.ld: -------------------------------------------------------------------------------- 1 | /* The bootloader will look at this image and start execution at the symbol 2 | designated as the entry point. */ 3 | ENTRY(_start) 4 | 5 | /* Tell where the various sections of the object files will be put in the final 6 | kernel image. */ 7 | SECTIONS 8 | { 9 | /* Begin putting sections at 1 MiB, a conventional place for kernels to be 10 | loaded at by the bootloader. */ 11 | . = 1M; 12 | 13 | /* First put the multiboot header, as it is required to be put very early 14 | early in the image or the bootloader won't recognize the file format. 15 | Next we'll put the .text section. */ 16 | .text BLOCK(4K) : ALIGN(4K) 17 | { 18 | *(.multiboot) 19 | *(.text) 20 | } 21 | 22 | /* Read-only data. */ 23 | .rodata BLOCK(4K) : ALIGN(4K) 24 | { 25 | *(.rodata) 26 | } 27 | 28 | /* Read-write data (initialized) */ 29 | .data BLOCK(4K) : ALIGN(4K) 30 | { 31 | *(.data) 32 | } 33 | 34 | /* Read-write data (uninitialized) and stack */ 35 | .bss BLOCK(4K) : ALIGN(4K) 36 | { 37 | *(COMMON) 38 | *(.bss) 39 | } 40 | 41 | /* The compiler may produce other sections, by default it will put them in 42 | a segment with the same name. Simply add stuff here as needed. */ 43 | } 44 | -------------------------------------------------------------------------------- /kernel/runtime.bc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semoro/KOS/86171e3965a44ec2d150249187180ebcd58123a7/kernel/runtime.bc.o -------------------------------------------------------------------------------- /kernel/src/asm/ceil.s: -------------------------------------------------------------------------------- 1 | .global ceil 2 | .type ceil, @function 3 | ceil: 4 | roundsd $0xa, %xmm0, %xmm0 5 | retq 6 | 7 | -------------------------------------------------------------------------------- /kernel/src/asm/floor.s: -------------------------------------------------------------------------------- 1 | .global floor 2 | .type floor, @function 3 | 4 | floor: 5 | fldt 8(%rsp) 6 | 7 | fstcw -4(%rsp) /* store fpu control word */ 8 | 9 | /* We use here %edx although only the low 1 bits are defined. 10 | But none of the operations should care and they are faster 11 | than the 16 bit operations. */ 12 | movl $0x400,%edx /* round towards -oo */ 13 | orl -4(%rsp),%edx 14 | andl $0xf7ff,%edx 15 | movl %edx,-8(%rsp) 16 | fldcw -8(%rsp) /* load modified control word */ 17 | 18 | frndint /* round */ 19 | 20 | fldcw -4(%rsp) /* restore original control word */ 21 | 22 | ret 23 | -------------------------------------------------------------------------------- /kernel/src/asm/loader.s: -------------------------------------------------------------------------------- 1 | .code32 2 | .text 3 | .global loader 4 | # Declare constants for the multiboot header. 5 | .set ALIGN, 1<<0 # align loaded modules on page boundaries 6 | .set MEMINFO, 1<<1 # provide memory map 7 | 8 | .set MULTIBOOT_VIDEO_MODE, 0x00000004 9 | 10 | 11 | .set FLAGS, ALIGN | MEMINFO | MULTIBOOT_VIDEO_MODE # this is the Multiboot 'flag' field 12 | .set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header 13 | .set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot 14 | 15 | # Declare a multiboot header that marks the program as a kernel. These are magic 16 | # values that are documented in the multiboot standard. The bootloader will 17 | # search for this signature in the first 8 KiB of the kernel file, aligned at a 18 | # 32-bit boundary. The signature is in its own section so the header can be 19 | # forced to be within the first 8 KiB of the kernel file. 20 | .section .multiboot 21 | .align 4 22 | .long MAGIC 23 | .long FLAGS 24 | .long CHECKSUM 25 | .skip 20 26 | .long 0 27 | .long 1024 28 | .long 768 29 | .long 24 30 | 31 | # The multiboot standard does not define the value of the stack pointer register 32 | # (esp) and it is up to the kernel to provide a stack. This allocates room for a 33 | # small stack by creating a symbol at the bottom of it, then allocating 16384 34 | # bytes for it, and finally creating a symbol at the top. The stack grows 35 | # downwards on x86. The stack is in its own section so it can be marked nobits, 36 | # which means the kernel file is smaller because it does not contain an 37 | # uninitialized stack. The stack on x86 must be 16-byte aligned according to the 38 | # System V ABI standard and de-facto extensions. The compiler will assume the 39 | # stack is properly aligned and failure to align the stack will result in 40 | # undefined behavior. 41 | .section .bss 42 | 43 | .global idt_first_entry 44 | .type idt_first_entry, @common 45 | 46 | multiboot_info_ptr: 47 | .skip 4 48 | 49 | idt_first_entry: 50 | .skip 16 * 256 51 | 52 | 53 | 54 | .align 16 55 | stack_bottom: 56 | .skip 65536 # 64 KiB 57 | stack_top: 58 | 59 | free_space_start: 60 | 61 | .global free_space_start 62 | # The linker script specifies _start as the entry point to the kernel and the 63 | # bootloader will jump to this position once the kernel has been loaded. It 64 | # doesn't make sense to return from this function as the bootloader is gone. 65 | 66 | .section .rodata 67 | .align 16 68 | GDT64: # Global Descriptor Table (64-bit). 69 | #.equ Null, $ - $GDT64 # The null descriptor. 70 | .short 0 # Limit (low). 71 | .short 0 # Base (low). 72 | .byte 0 # Base (middle) 73 | .byte 0 # Access. 74 | .byte 0 # Granularity. 75 | .byte 0 # Base (high). 76 | #.equ Code, $ - $GDT64 # The code descriptor. 77 | .short 0xFFFF # Limit (low). 78 | .short 0 # Base (low). 79 | .byte 0 # Base (middle) 80 | .byte 0b10011010 # Access (exec/read). 81 | .byte 0b10101111 # Granularity. 82 | .byte 0 # Base (high). 83 | #.equ Data, $ - $GDT64 # The data descriptor. 84 | .short 0 # Limit (low). 85 | .short 0 # Base (low). 86 | .byte 0 # Base (middle) 87 | .byte 0b10010010 # Access (read/write). 88 | .byte 0b00000000 # Granularity. 89 | .byte 0 # Base (high). 90 | GDTPointer: # The GDT-pointer. 91 | .short (GDTPointer - GDT64 - 1) # Limit. 92 | .quad GDT64 # Base. 93 | 94 | 95 | .section .text 96 | .global abort 97 | .type abort, @function 98 | 99 | .global _start 100 | .type _start, @function 101 | 102 | 103 | CheckIsLongModeSupported: 104 | .code32 105 | mov $0x80000000, %eax 106 | cpuid 107 | cmp $0x80000001, %eax 108 | jb NoLongMode 109 | 110 | mov $0x80000001, %eax 111 | cpuid 112 | testl $(1 << 29), %edx 113 | jz NoLongMode 114 | ret 115 | 116 | NoLongMode: 117 | cli 118 | 1: hlt 119 | jmp 1b 120 | 121 | 122 | .text 123 | 124 | .code32 125 | _start: 126 | # The bootloader has loaded us into 32-bit protected mode on a x86 127 | # machine. Interrupts are disabled. Paging is disabled. The processor 128 | # state is as defined in the multiboot standard. The kernel has full 129 | # control of the CPU. The kernel can only make use of hardware features 130 | # and any code it provides as part of itself. There's no printf 131 | # function, unless the kernel provides its own header and a 132 | # printf implementation. There are no security restrictions, no 133 | # safeguards, no debugging mechanisms, only what the kernel provides 134 | # itself. It has absolute and complete power over the 135 | # machine. 136 | mov %ebx, (multiboot_info_ptr) 137 | 138 | # To set up a stack, we set the esp register to point to the top of our 139 | # stack (as it grows downwards on x86 systems). This is necessarily done 140 | # in assembly as languages such as C cannot function without a stack. 141 | mov $stack_top, %esp 142 | 143 | # This is a good place to initialize crucial processor state before the 144 | # high-level kernel is entered. It's best to minimize the early 145 | # environment where crucial features are offline. Note that the 146 | # processor is not fully initialized yet: Features such as floating 147 | # point instructions and instruction set extensions are not initialized 148 | # yet. The GDT should be loaded here. Paging should be enabled here. 149 | # C++ features such as global constructors and exceptions will require 150 | # runtime support to work as well. 151 | 152 | # Enter the high-level kernel. The ABI requires the stack is 16-byte 153 | # aligned at the time of the call instruction (which afterwards pushes 154 | # the return pointer of size 4 bytes). The stack was originally 16-byte 155 | # aligned above and we've since pushed a multiple of 16 bytes to the 156 | # stack since (pushed 0 bytes so far) and the alignment is thus 157 | # preserved and the call is well defined. 158 | call CheckIsLongModeSupported 159 | 160 | mov %cr0, %eax 161 | and $0b01111111111111111111111111111111, %eax 162 | mov %eax, %cr0 163 | 164 | mov $0x1000, %edi # Set the destination index to 0x1000. 165 | mov %edi, %cr3 # Set control register 3 to the destination index. 166 | xor %eax, %eax # Nullify the A-register. 167 | mov $4096, %ecx # Set the C-register to 4096. 168 | rep stos %eax,%es:(%edi) # Clear the memory. 169 | mov %cr3, %edi # Set the destination index to control register 3. 170 | movl $0x2003,(%edi) 171 | 172 | add $0x1000,%edi 173 | 174 | movl $0x3003,(%edi) 175 | add $0x1000,%edi 176 | 177 | movl $0x4003,(%edi) 178 | movl $0x5003,8(%edi) 179 | add $0x1000,%edi 180 | 181 | 182 | mov $0x3,%ebx 183 | mov $0x400,%ecx 184 | 185 | 186 | SetEntry: 187 | mov %ebx,(%edi) 188 | add $0x1000,%ebx 189 | add $0x8,%edi 190 | loop SetEntry 191 | 192 | 193 | 194 | mov %cr4,%eax 195 | or $0x20,%eax 196 | mov %eax,%cr4 197 | 198 | mov $0xC0000080,%ecx 199 | rdmsr 200 | or $(1 << 8),%eax 201 | wrmsr 202 | 203 | mov %cr0,%eax 204 | or $(1 << 31),%eax 205 | mov %eax,%cr0 206 | 207 | 208 | Pre64: 209 | lgdt GDTPointer 210 | ljmp $0x0008, $Realm64 211 | 212 | 213 | Realm64: 214 | .code64 215 | cli 216 | mov $0x10,%ax 217 | mov %eax,%ds 218 | mov %eax,%es 219 | mov %eax,%fs 220 | mov %eax,%gs 221 | mov %eax,%ss 222 | call EnableSSE 223 | 224 | call "kfun:kernelMain()" 225 | 226 | # If the system has nothing more to do, put the computer into an 227 | # infinite loop. To do that: 228 | # 1) Disable interrupts with cli (clear interrupt enable in eflags). 229 | # They are already disabled by the bootloader, so this is not needed. 230 | # Mind that you might later enable interrupts and return from 231 | # kernel_main (which is sort of nonsensical to do). 232 | # 2) Wait for the next interrupt to arrive with hlt (halt instruction). 233 | # Since they are disabled, this will lock up the computer. 234 | # 3) Jump to the hlt instruction if it ever wakes up due to a 235 | # non-maskable interrupt occurring or due to system management mode. 236 | 237 | EnableSSE: 238 | .code32 239 | #now enable SSE and the like 240 | movl %cr0, %eax 241 | and $0xFFFB, %ax #clear coprocessor emulation CR0.EM 242 | or $0x2, %ax #set coprocessor monitoring CR0.MP 243 | movl %eax, %cr0 244 | movl %cr4, %eax 245 | or $(3 << 9), %ax #set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time 246 | movl %eax, %cr4 247 | ret 248 | abort: 249 | cli 250 | 1: hlt 251 | jmp 1b 252 | 253 | # Set the size of the _start symbol to the current location '.' minus its start. 254 | # This is useful when debugging or when you implement call tracing. 255 | .size _start, . - _start 256 | -------------------------------------------------------------------------------- /kernel/src/asm/loader.s.bak: -------------------------------------------------------------------------------- 1 | .code32 2 | .text 3 | .global loader 4 | # Declare constants for the multiboot header. 5 | .set ALIGN, 1<<0 # align loaded modules on page boundaries 6 | .set MEMINFO, 1<<1 # provide memory map 7 | .set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field 8 | .set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header 9 | .set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot 10 | 11 | # Declare a multiboot header that marks the program as a kernel. These are magic 12 | # values that are documented in the multiboot standard. The bootloader will 13 | # search for this signature in the first 8 KiB of the kernel file, aligned at a 14 | # 32-bit boundary. The signature is in its own section so the header can be 15 | # forced to be within the first 8 KiB of the kernel file. 16 | .section .multiboot 17 | .align 4 18 | .long MAGIC 19 | .long FLAGS 20 | .long CHECKSUM 21 | 22 | # The multiboot standard does not define the value of the stack pointer register 23 | # (esp) and it is up to the kernel to provide a stack. This allocates room for a 24 | # small stack by creating a symbol at the bottom of it, then allocating 16384 25 | # bytes for it, and finally creating a symbol at the top. The stack grows 26 | # downwards on x86. The stack is in its own section so it can be marked nobits, 27 | # which means the kernel file is smaller because it does not contain an 28 | # uninitialized stack. The stack on x86 must be 16-byte aligned according to the 29 | # System V ABI standard and de-facto extensions. The compiler will assume the 30 | # stack is properly aligned and failure to align the stack will result in 31 | # undefined behavior. 32 | .section .bss 33 | .align 16 34 | stack_bottom: 35 | .skip 16384 # 16 KiB 36 | stack_top: 37 | 38 | # The linker script specifies _start as the entry point to the kernel and the 39 | # bootloader will jump to this position once the kernel has been loaded. It 40 | # doesn't make sense to return from this function as the bootloader is gone. 41 | 42 | /*.section rodata 43 | 44 | GDT64: # Global Descriptor Table (64-bit). 45 | #.equ Null, $ - $GDT64 # The null descriptor. 46 | .short 0 # Limit (low). 47 | .short 0 # Base (low). 48 | .byte 0 # Base (middle) 49 | .byte 0 # Access. 50 | .byte 0 # Granularity. 51 | .byte 0 # Base (high). 52 | #.equ Code, $ - $GDT64 # The code descriptor. 53 | .short 0 # Limit (low). 54 | .short 0 # Base (low). 55 | .byte 0 # Base (middle) 56 | .byte 0b10011010 # Access (exec/read). 57 | .byte 0b00100000 # Granularity. 58 | .byte 0 # Base (high). 59 | #.equ Data, $ - $GDT64 # The data descriptor. 60 | .short 0 # Limit (low). 61 | .short 0 # Base (low). 62 | .byte 0 # Base (middle) 63 | .byte 0b10010010 # Access (read/write). 64 | .byte 0b00000000 # Granularity. 65 | .byte 0 # Base (high). 66 | GDTPointer: # The GDT-pointer. 67 | .short (GDTPointer - GDT64 - 1) # Limit. 68 | .quad GDT64 # Base. 69 | */ 70 | 71 | .section .text 72 | .global abort 73 | .type abort, @function 74 | 75 | .global _start 76 | .type _start, @function 77 | 78 | 79 | _start: 80 | # The bootloader has loaded us into 32-bit protected mode on a x86 81 | # machine. Interrupts are disabled. Paging is disabled. The processor 82 | # state is as defined in the multiboot standard. The kernel has full 83 | # control of the CPU. The kernel can only make use of hardware features 84 | # and any code it provides as part of itself. There's no printf 85 | # function, unless the kernel provides its own header and a 86 | # printf implementation. There are no security restrictions, no 87 | # safeguards, no debugging mechanisms, only what the kernel provides 88 | # itself. It has absolute and complete power over the 89 | # machine. 90 | 91 | # To set up a stack, we set the esp register to point to the top of our 92 | # stack (as it grows downwards on x86 systems). This is necessarily done 93 | # in assembly as languages such as C cannot function without a stack. 94 | mov $stack_top, %esp 95 | 96 | # This is a good place to initialize crucial processor state before the 97 | # high-level kernel is entered. It's best to minimize the early 98 | # environment where crucial features are offline. Note that the 99 | # processor is not fully initialized yet: Features such as floating 100 | # point instructions and instruction set extensions are not initialized 101 | # yet. The GDT should be loaded here. Paging should be enabled here. 102 | # C++ features such as global constructors and exceptions will require 103 | # runtime support to work as well. 104 | 105 | # Enter the high-level kernel. The ABI requires the stack is 16-byte 106 | # aligned at the time of the call instruction (which afterwards pushes 107 | # the return pointer of size 4 bytes). The stack was originally 16-byte 108 | # aligned above and we've since pushed a multiple of 16 bytes to the 109 | # stack since (pushed 0 bytes so far) and the alignment is thus 110 | # preserved and the call is well defined. 111 | 112 | /* 113 | add $0x1000,%edi 114 | movl $0x3003,(%edi) 115 | add $0x1000,%edi 116 | movl $0x4003,(%edi) 117 | add $0x1000,%edi 118 | 119 | mov $0x3,%ebx 120 | mov $0x200,%ecx 121 | 122 | 123 | SetEntry: 124 | mov %ebx,(%edi) 125 | add $0x1000,%ebx 126 | add $0x8,%edi 127 | loop SetEntry 128 | 129 | mov %cr4,%eax 130 | or $0x20,%eax 131 | mov %eax,%cr4 132 | 133 | mov $0xc0000080,%ecx 134 | rdmsr 135 | or $0x100,%eax 136 | wrmsr 137 | 138 | mov %cr0,%eax 139 | or $0x80000000,%eax 140 | mov %eax,%cr0 141 | 142 | 143 | Pre64: 144 | lgdt GDTPointer 145 | jmp $0x0008, $Relam64 146 | .code64 147 | 148 | 149 | 150 | Realm64: 151 | cli 152 | mov $0x10,%ax 153 | mov %eax,%ds 154 | mov %eax,%es 155 | mov %eax,%fs 156 | mov %eax,%gs 157 | mov %eax,%ss*/ 158 | 159 | call "kfun:kernelMain()" 160 | 161 | # If the system has nothing more to do, put the computer into an 162 | # infinite loop. To do that: 163 | # 1) Disable interrupts with cli (clear interrupt enable in eflags). 164 | # They are already disabled by the bootloader, so this is not needed. 165 | # Mind that you might later enable interrupts and return from 166 | # kernel_main (which is sort of nonsensical to do). 167 | # 2) Wait for the next interrupt to arrive with hlt (halt instruction). 168 | # Since they are disabled, this will lock up the computer. 169 | # 3) Jump to the hlt instruction if it ever wakes up due to a 170 | # non-maskable interrupt occurring or due to system management mode. 171 | abort: 172 | cli 173 | 1: hlt 174 | jmp 1b 175 | 176 | # Set the size of the _start symbol to the current location '.' minus its start. 177 | # This is useful when debugging or when you implement call tracing. 178 | .size _start, . - _start 179 | -------------------------------------------------------------------------------- /kernel/src/c/hardware/PIC.c: -------------------------------------------------------------------------------- 1 | #include "PIC.h" 2 | #include "io.h" 3 | 4 | void PIC_sendEOI(uint8_t irq) 5 | { 6 | if(irq >= 8) 7 | outb(PIC2_COMMAND,PIC_EOI); 8 | 9 | outb(PIC1_COMMAND,PIC_EOI); 10 | } 11 | 12 | 13 | void PIC_remap(uint8_t offset1, uint8_t offset2) 14 | { 15 | uint8_t a1, a2; 16 | 17 | a1 = inb(PIC1_DATA); // save masks 18 | a2 = inb(PIC2_DATA); 19 | 20 | outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // starts the initialization sequence (in cascade mode) 21 | io_wait(); 22 | outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); 23 | io_wait(); 24 | outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset 25 | io_wait(); 26 | outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset 27 | io_wait(); 28 | outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) 29 | io_wait(); 30 | outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010) 31 | io_wait(); 32 | 33 | outb(PIC1_DATA, ICW4_8086); 34 | io_wait(); 35 | outb(PIC2_DATA, ICW4_8086); 36 | io_wait(); 37 | 38 | outb(PIC1_DATA, a1); // restore saved masks. 39 | outb(PIC2_DATA, a2); 40 | } 41 | -------------------------------------------------------------------------------- /kernel/src/c/hardware/PIC.h: -------------------------------------------------------------------------------- 1 | #ifndef PIC_H 2 | #define PIC_H 3 | 4 | #include 5 | 6 | #define PIC1 0x20 /* IO base address for master PIC */ 7 | #define PIC2 0xA0 /* IO base address for slave PIC */ 8 | #define PIC1_COMMAND PIC1 9 | #define PIC1_DATA (PIC1+1) 10 | #define PIC2_COMMAND PIC2 11 | #define PIC2_DATA (PIC2+1) 12 | 13 | #define PIC_EOI 0x20 /* End-of-interrupt command code */ 14 | 15 | void PIC_sendEOI(uint8_t irq); 16 | 17 | /* reinitialize the PIC controllers, giving them specified vector offsets 18 | rather than 8h and 70h, as configured by default */ 19 | 20 | #define ICW1_ICW4 0x01 /* ICW4 (not) needed */ 21 | #define ICW1_SINGLE 0x02 /* Single (cascade) mode */ 22 | #define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ 23 | #define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ 24 | #define ICW1_INIT 0x10 /* Initialization - required! */ 25 | 26 | #define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ 27 | #define ICW4_AUTO 0x02 /* Auto (normal) EOI */ 28 | #define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ 29 | #define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ 30 | #define ICW4_SFNM 0x10 /* Special fully nested (not) */ 31 | 32 | /* 33 | arguments: 34 | offset1 - vector offset for master PIC 35 | vectors on the master become offset1..offset1+7 36 | offset2 - same for slave PIC: offset2..offset2+7 37 | */ 38 | void PIC_remap(uint8_t offset1, uint8_t offset2); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /kernel/src/c/hardware/io.c: -------------------------------------------------------------------------------- 1 | #include "io.h" 2 | 3 | -------------------------------------------------------------------------------- /kernel/src/c/hardware/io.h: -------------------------------------------------------------------------------- 1 | #ifndef HARDWARE_IO_H 2 | #define HARDWARE_IO_H 3 | 4 | #include 5 | 6 | static inline void outb(uint16_t port, uint8_t val) 7 | { 8 | asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); 9 | /* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint). 10 | * Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint). 11 | * The outb %al, %dx encoding is the only option for all other cases. 12 | * %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */ 13 | } 14 | 15 | 16 | static inline uint8_t inb(uint16_t port) 17 | { 18 | uint8_t ret; 19 | asm volatile ( "inb %1, %0" 20 | : "=a"(ret) 21 | : "Nd"(port) ); 22 | return ret; 23 | } 24 | 25 | 26 | static inline void io_wait(void) 27 | { 28 | /* Port 0x80 is used for 'checkpoints' during POST. */ 29 | /* The Linux kernel seems to think it is free for use :-/ */ 30 | asm volatile ( "outb %%al, $0x80" : : "a"(0) ); 31 | /* %%al instead of %0 makes no difference. TODO: does the register need to be zeroed? */ 32 | } 33 | 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /kernel/src/c/runtime/idt.c: -------------------------------------------------------------------------------- 1 | #include "idt.h" 2 | #include "hardware/PIC.h" 3 | #include "hardware/io.h" 4 | #include "vga/utils.h" 5 | #include "interrupts.h" 6 | #define REGISTER_EX_IRQ(i) fill_idt_entry(entries + i, &handle_ex_##i, 0x0008, 0b10001111) 7 | 8 | 9 | __attribute__ ((interrupt)) 10 | void handle_interrupt(struct interrupt_frame *frame) { 11 | uint8_t irr = inb(0x20); 12 | vga_textmode_print("Unsupported IRQ", 0x7, 80 * 2); 13 | vga_textmode_print_int(irr, 0x7, 80 * 2 + 15); 14 | abort(); 15 | } 16 | 17 | static inline void lidt(void* base, uint16_t size) 18 | { // This function works in 32 and 64bit mode 19 | struct { 20 | uint16_t length; 21 | uint64_t base; 22 | } __attribute__((packed)) IDTR = { size, base }; 23 | 24 | asm ( "lidt %0" : : "m"(IDTR) ); // let the compiler choose an addressing mode 25 | } 26 | 27 | static inline void enable_interrupts() { 28 | asm ("sti"); 29 | } 30 | 31 | void setup_keyboard_interrupt() { 32 | outb(0x21,0xfd); 33 | outb(0xa1,0xff); 34 | enable_interrupts(); 35 | } 36 | 37 | void fill_idt_entry(idt_entry_t *entry, void *handler, uint8_t selector, uint8_t type_attr) { 38 | entry->selector = selector; 39 | entry->type_attr = type_attr; // 1 exists, 00 DPL = ring 0, 0 reserved, 1111 x86 trap gate 40 | 41 | uint64_t isr_ex = handler; 42 | entry->offset_1 = 0xFFFF & isr_ex; 43 | entry->offset_2 = 0xFFFF & (isr_ex >> 16); 44 | } 45 | 46 | void setup_idt() { 47 | PIC_remap(0x20, 0x28); 48 | 49 | idt_entry_t *entries = &idt_first_entry; 50 | 51 | for(idt_entry_t *first = entries + 0x20; first != entries + 0x28 + 8; first++){ 52 | fill_idt_entry(first, &handle_interrupt, 0x0008, 0b10001110); 53 | } 54 | 55 | REGISTER_EX_IRQ(0); 56 | REGISTER_EX_IRQ(1); 57 | REGISTER_EX_IRQ(2); 58 | REGISTER_EX_IRQ(3); 59 | REGISTER_EX_IRQ(4); 60 | REGISTER_EX_IRQ(5); 61 | REGISTER_EX_IRQ(6); 62 | REGISTER_EX_IRQ(7); 63 | REGISTER_EX_IRQ(8); 64 | REGISTER_EX_IRQ(9); 65 | REGISTER_EX_IRQ(10); 66 | REGISTER_EX_IRQ(11); 67 | REGISTER_EX_IRQ(12); 68 | REGISTER_EX_IRQ(13); 69 | REGISTER_EX_IRQ(14); 70 | REGISTER_EX_IRQ(15); 71 | REGISTER_EX_IRQ(16); 72 | REGISTER_EX_IRQ(17); 73 | REGISTER_EX_IRQ(18); 74 | REGISTER_EX_IRQ(19); 75 | REGISTER_EX_IRQ(20); 76 | REGISTER_EX_IRQ(21); 77 | REGISTER_EX_IRQ(22); 78 | REGISTER_EX_IRQ(23); 79 | REGISTER_EX_IRQ(24); 80 | REGISTER_EX_IRQ(25); 81 | REGISTER_EX_IRQ(26); 82 | REGISTER_EX_IRQ(27); 83 | REGISTER_EX_IRQ(28); 84 | REGISTER_EX_IRQ(29); 85 | REGISTER_EX_IRQ(30); 86 | REGISTER_EX_IRQ(31); 87 | 88 | 89 | lidt(entries, 100 * sizeof(idt_entry_t)); 90 | 91 | 92 | outb(0x21,0xfd); 93 | outb(0xa1,0xff); 94 | enable_interrupts(); 95 | 96 | } 97 | 98 | 99 | -------------------------------------------------------------------------------- /kernel/src/c/runtime/idt.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef IDT_H 4 | #define IDT_H 5 | 6 | #include 7 | 8 | typedef struct __attribute__((packed)) { 9 | uint16_t offset_1; // offset bits 0..15 10 | uint16_t selector; // a code segment selector in GDT or LDT 11 | uint8_t ist; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero. 12 | uint8_t type_attr; // type and attributes 13 | uint16_t offset_2; // offset bits 16..31 14 | uint32_t offset_3; // offset bits 32..63 15 | uint32_t zero; // reserved 16 | } idt_entry_t; 17 | 18 | 19 | struct interrupt_frame 20 | { 21 | uint64_t ip; 22 | uint64_t cs; 23 | uint64_t flags; 24 | uint64_t sp; 25 | uint64_t ss; 26 | }; 27 | 28 | 29 | idt_entry_t idt_first_entry; 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /kernel/src/c/runtime/interrupts.c: -------------------------------------------------------------------------------- 1 | #include "interrupts.h" 2 | #include "vga/utils.h" 3 | 4 | __attribute__ ((interrupt)) void handle_ex_0(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 0", 0x7, 80 * 2); abort(); } 5 | __attribute__ ((interrupt)) void handle_ex_1(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 1", 0x7, 80 * 2); abort(); } 6 | __attribute__ ((interrupt)) void handle_ex_2(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 2", 0x7, 80 * 2); abort(); } 7 | __attribute__ ((interrupt)) void handle_ex_3(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 3", 0x7, 80 * 2); abort(); } 8 | __attribute__ ((interrupt)) void handle_ex_4(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 4", 0x7, 80 * 2); abort(); } 9 | __attribute__ ((interrupt)) void handle_ex_5(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 5", 0x7, 80 * 2); abort(); } 10 | __attribute__ ((interrupt)) void handle_ex_6(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 6", 0x7, 80 * 2); abort(); } 11 | __attribute__ ((interrupt)) void handle_ex_7(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 7", 0x7, 80 * 2); abort(); } 12 | __attribute__ ((interrupt)) void handle_ex_8(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 8", 0x7, 80 * 2); abort(); } 13 | __attribute__ ((interrupt)) void handle_ex_9(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 9", 0x7, 80 * 2); abort(); } 14 | __attribute__ ((interrupt)) void handle_ex_10(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 10", 0x7, 80 * 2); abort(); } 15 | __attribute__ ((interrupt)) void handle_ex_11(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 11", 0x7, 80 * 2); abort(); } 16 | __attribute__ ((interrupt)) void handle_ex_12(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 12", 0x7, 80 * 2); abort(); } 17 | __attribute__ ((interrupt)) void handle_ex_13(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 13", 0x7, 80 * 2); abort(); } 18 | __attribute__ ((interrupt)) void handle_ex_14(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 14", 0x7, 80 * 2); abort(); } 19 | __attribute__ ((interrupt)) void handle_ex_15(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 15", 0x7, 80 * 2); abort(); } 20 | __attribute__ ((interrupt)) void handle_ex_16(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 16", 0x7, 80 * 2); abort(); } 21 | __attribute__ ((interrupt)) void handle_ex_17(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 17", 0x7, 80 * 2); abort(); } 22 | __attribute__ ((interrupt)) void handle_ex_18(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 18", 0x7, 80 * 2); abort(); } 23 | __attribute__ ((interrupt)) void handle_ex_19(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 19", 0x7, 80 * 2); abort(); } 24 | __attribute__ ((interrupt)) void handle_ex_20(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 20", 0x7, 80 * 2); abort(); } 25 | __attribute__ ((interrupt)) void handle_ex_21(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 21", 0x7, 80 * 2); abort(); } 26 | __attribute__ ((interrupt)) void handle_ex_22(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 22", 0x7, 80 * 2); abort(); } 27 | __attribute__ ((interrupt)) void handle_ex_23(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 23", 0x7, 80 * 2); abort(); } 28 | __attribute__ ((interrupt)) void handle_ex_24(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 24", 0x7, 80 * 2); abort(); } 29 | __attribute__ ((interrupt)) void handle_ex_25(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 25", 0x7, 80 * 2); abort(); } 30 | __attribute__ ((interrupt)) void handle_ex_26(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 26", 0x7, 80 * 2); abort(); } 31 | __attribute__ ((interrupt)) void handle_ex_27(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 27", 0x7, 80 * 2); abort(); } 32 | __attribute__ ((interrupt)) void handle_ex_28(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 28", 0x7, 80 * 2); abort(); } 33 | __attribute__ ((interrupt)) void handle_ex_29(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 29", 0x7, 80 * 2); abort(); } 34 | __attribute__ ((interrupt)) void handle_ex_30(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 30", 0x7, 80 * 2); abort(); } 35 | __attribute__ ((interrupt)) void handle_ex_31(struct interrupt_frame *frame, uint64_t error_code){ vga_textmode_print("Exception 31", 0x7, 80 * 2); abort(); } 36 | 37 | -------------------------------------------------------------------------------- /kernel/src/c/runtime/interrupts.h: -------------------------------------------------------------------------------- 1 | #ifndef INTERRUPTS_H 2 | #define INTERRUPTS_H 3 | #include "idt.h" 4 | 5 | __attribute__ ((interrupt)) void handle_ex_0(struct interrupt_frame *frame, uint64_t error_code); 6 | __attribute__ ((interrupt)) void handle_ex_1(struct interrupt_frame *frame, uint64_t error_code); 7 | __attribute__ ((interrupt)) void handle_ex_2(struct interrupt_frame *frame, uint64_t error_code); 8 | __attribute__ ((interrupt)) void handle_ex_3(struct interrupt_frame *frame, uint64_t error_code); 9 | __attribute__ ((interrupt)) void handle_ex_4(struct interrupt_frame *frame, uint64_t error_code); 10 | __attribute__ ((interrupt)) void handle_ex_5(struct interrupt_frame *frame, uint64_t error_code); 11 | __attribute__ ((interrupt)) void handle_ex_6(struct interrupt_frame *frame, uint64_t error_code); 12 | __attribute__ ((interrupt)) void handle_ex_7(struct interrupt_frame *frame, uint64_t error_code); 13 | __attribute__ ((interrupt)) void handle_ex_8(struct interrupt_frame *frame, uint64_t error_code); 14 | __attribute__ ((interrupt)) void handle_ex_9(struct interrupt_frame *frame, uint64_t error_code); 15 | __attribute__ ((interrupt)) void handle_ex_10(struct interrupt_frame *frame, uint64_t error_code); 16 | __attribute__ ((interrupt)) void handle_ex_11(struct interrupt_frame *frame, uint64_t error_code); 17 | __attribute__ ((interrupt)) void handle_ex_12(struct interrupt_frame *frame, uint64_t error_code); 18 | __attribute__ ((interrupt)) void handle_ex_13(struct interrupt_frame *frame, uint64_t error_code); 19 | __attribute__ ((interrupt)) void handle_ex_14(struct interrupt_frame *frame, uint64_t error_code); 20 | __attribute__ ((interrupt)) void handle_ex_15(struct interrupt_frame *frame, uint64_t error_code); 21 | __attribute__ ((interrupt)) void handle_ex_16(struct interrupt_frame *frame, uint64_t error_code); 22 | __attribute__ ((interrupt)) void handle_ex_17(struct interrupt_frame *frame, uint64_t error_code); 23 | __attribute__ ((interrupt)) void handle_ex_18(struct interrupt_frame *frame, uint64_t error_code); 24 | __attribute__ ((interrupt)) void handle_ex_19(struct interrupt_frame *frame, uint64_t error_code); 25 | __attribute__ ((interrupt)) void handle_ex_20(struct interrupt_frame *frame, uint64_t error_code); 26 | __attribute__ ((interrupt)) void handle_ex_21(struct interrupt_frame *frame, uint64_t error_code); 27 | __attribute__ ((interrupt)) void handle_ex_22(struct interrupt_frame *frame, uint64_t error_code); 28 | __attribute__ ((interrupt)) void handle_ex_23(struct interrupt_frame *frame, uint64_t error_code); 29 | __attribute__ ((interrupt)) void handle_ex_24(struct interrupt_frame *frame, uint64_t error_code); 30 | __attribute__ ((interrupt)) void handle_ex_25(struct interrupt_frame *frame, uint64_t error_code); 31 | __attribute__ ((interrupt)) void handle_ex_26(struct interrupt_frame *frame, uint64_t error_code); 32 | __attribute__ ((interrupt)) void handle_ex_27(struct interrupt_frame *frame, uint64_t error_code); 33 | __attribute__ ((interrupt)) void handle_ex_28(struct interrupt_frame *frame, uint64_t error_code); 34 | __attribute__ ((interrupt)) void handle_ex_29(struct interrupt_frame *frame, uint64_t error_code); 35 | __attribute__ ((interrupt)) void handle_ex_30(struct interrupt_frame *frame, uint64_t error_code); 36 | __attribute__ ((interrupt)) void handle_ex_31(struct interrupt_frame *frame, uint64_t error_code); 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /kernel/src/c/runtime/mem_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void * memset(void *ptr, int value, uint64_t num) { 4 | uint8_t fill = value; 5 | void* end = ptr + num; 6 | for(uint8_t *tptr = ptr; tptr != end; tptr++) { 7 | *tptr = value; 8 | } 9 | return ptr; 10 | } 11 | 12 | void * memcpy (void * destination, const void * source, uint64_t num) { 13 | for(uint64_t i = 0; i < num; i++) { 14 | ((uint8_t*)destination)[i] = ((uint8_t*)source)[i]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /kernel/src/c/runtime/static_alloc.c: -------------------------------------------------------------------------------- 1 | #include "../vga/utils.h" 2 | 3 | #include "inttypes.h" 4 | 5 | void* static_alloc(void* position) { 6 | return position; 7 | } 8 | 9 | void* free_space_start; 10 | 11 | uint64_t allocPtr = 0; 12 | 13 | void initialize_memory_allocation() { 14 | allocPtr = &free_space_start; 15 | } 16 | 17 | uint64_t allocated = 0; 18 | uint64_t allocations = 0; 19 | 20 | const char* clear_line = " "; 21 | 22 | void printUsedMemory() { 23 | 24 | vga_textmode_print(clear_line, 0x7, 80 * 20); 25 | vga_textmode_print("Used mem: ", 0x7, 80 * 20); 26 | double mem = allocated; 27 | int level = 0; 28 | while (mem > 1024) { 29 | mem /= 1024.0; 30 | level++; 31 | } 32 | 33 | vga_textmode_print_float(mem, 0x7, 80 * 20 + 10); 34 | switch (level) { 35 | case 0: 36 | vga_textmode_print("B", 0x7, 80 * 20 + 18); 37 | break; 38 | case 1: 39 | vga_textmode_print("KiB", 0x7, 80 * 20 + 18); 40 | break; 41 | case 2: 42 | vga_textmode_print("MiB", 0x7, 80 * 20 + 18); 43 | break; 44 | case 3: 45 | vga_textmode_print("GiB", 0x7, 80 * 20 + 18); 46 | break; 47 | case 4: 48 | vga_textmode_print("TiB", 0x7, 80 * 20 + 18); 49 | break; 50 | } 51 | 52 | 53 | vga_textmode_print("Allocations: ", 0x7, 80 * 20 + 30); 54 | vga_textmode_print_int(allocations, 0x7, 80 * 20 + 30 + 13); 55 | 56 | vga_textmode_print("Alloc ", 0x7, 80 * 21); 57 | vga_textmode_print_ptr(allocPtr, 0x7, 80 * 21 + 6); 58 | 59 | } 60 | 61 | uint64_t aligned_alloc(uint64_t size, uint64_t align) { 62 | uint64_t addr = ((allocPtr / align) + 1) * align; 63 | 64 | allocated += addr - allocPtr + size; 65 | allocations++; 66 | allocPtr = addr + size; 67 | printUsedMemory(); 68 | 69 | return addr; 70 | } 71 | 72 | uint64_t malloc(uint64_t size) { 73 | return aligned_alloc(size, 64); 74 | } 75 | 76 | uint64_t calloc(uint64_t size, uint64_t number) { 77 | char* ptr = malloc(size * number); 78 | return memset(ptr, 0, size * number); 79 | } 80 | 81 | 82 | void free(void* ptr) { 83 | vga_textmode_print("Free ", 0x7, 80 * 22); 84 | vga_textmode_print_ptr(ptr, 0x7, 80 * 22 + 5); 85 | } 86 | 87 | void set_pae_table_address(uint32_t addr) { 88 | asm volatile ("movq %%rax, %%cr3" :: "a" (addr)); 89 | } 90 | 91 | uint32_t get_int_at_addr(void* addr) { 92 | return *((uint32_t*)addr); 93 | } 94 | 95 | char* setlocale (int category, const char* locale) { 96 | return 0x1; 97 | } 98 | -------------------------------------------------------------------------------- /kernel/src/c/vga/utils.c: -------------------------------------------------------------------------------- 1 | #include "vga_textmode.h" 2 | #include "utils.h" 3 | #include "inttypes.h" 4 | 5 | static inline int powi(int a, int power) { 6 | int res = 1; 7 | for (int i = 0; i < power; i++) { 8 | res *= a; 9 | } 10 | return res; 11 | } 12 | 13 | void vga_textmode_print_int(int x, uint8_t attr, int pos) { 14 | for (int i = 1; i <= 10; i++) { 15 | uint8_t s = (x / powi(10, 10 - i)) % 10; 16 | if (s > 0 || i == 10) 17 | vga_textmode_write('0' + s, 0x7, pos++); 18 | } 19 | } 20 | 21 | void vga_textmode_print_float(float f, uint8_t attr, int pos) { 22 | int x = (int)f; 23 | for (int i = 1; i <= 10; i++) { 24 | uint8_t s = (x / powi(10, 10 - i)) % 10; 25 | if (s > 0 || i == 10) 26 | vga_textmode_write('0' + s, 0x7, pos++); 27 | } 28 | vga_textmode_write('.', 0x7, pos++); 29 | x = (int)((f - x) * 100); 30 | for (int i = 1; i <= 10; i++) { 31 | uint8_t s = (x / powi(10, 10 - i)) % 10; 32 | if (s > 0 || i == 10) 33 | vga_textmode_write('0' + s, 0x7, pos++); 34 | } 35 | } 36 | 37 | void vga_textmode_print_ptr(uint64_t x, uint8_t attr, int pos) { 38 | 39 | vga_textmode_print("0x", attr, pos); 40 | for (int i = 1; i <= 16; i++) { 41 | uint8_t s = (x >> (64 - i * 4)) & 0xF; 42 | if (s >= 0xA) 43 | vga_textmode_write('A' + (s - 0xA), attr, pos + 1 + i); 44 | else 45 | vga_textmode_write('0' + s, attr, pos + 1 + i); 46 | } 47 | } 48 | 49 | 50 | void vga_textmode_memdump(void* s, void* e, int pos) { 51 | int c = 0; 52 | for (char* p = s; p < e; ++p) { 53 | vga_textmode_print_int(*p, 0x7, (c++ * 4) + pos); 54 | } 55 | } 56 | 57 | void vga_textmode_print(const char* message, uint8_t attr, int pos) { 58 | int i = 0; 59 | while (*(message + i) != 0) { 60 | vga_textmode_write(*(message + i), attr, pos + i); 61 | i++; 62 | } 63 | } 64 | 65 | 66 | 67 | void AssertionFailedPX(const char* location, const char* message) { 68 | vga_textmode_print("Runtime assertion failed:", 0xc, 0); 69 | vga_textmode_print(location, 0xc, 80); 70 | vga_textmode_print(message, 0xc, 160); 71 | abort(); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /kernel/src/c/vga/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef VGA_TEXTMODE_UTILS_H 2 | #define VGA_TEXTMODE_UTILS_H 3 | #include 4 | 5 | 6 | void vga_textmode_memdump(void* s, void* e, int pos); 7 | void vga_textmode_print(const char* message, uint8_t attr, int pos); 8 | void vga_textmode_print_ptr(uint64_t x, uint8_t attr, int pos); 9 | void vga_textmode_print_int(int x, uint8_t attr, int pos); 10 | void vga_textmode_print_float(float x, uint8_t attr, int pos); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /kernel/src/c/vga/vga_textmode.c: -------------------------------------------------------------------------------- 1 | #include "vga_textmode.h" 2 | #include "../../res/resource_data.h" 3 | #include "../../res/font/font_data.h" 4 | #include 5 | 6 | 7 | void vga_textmode_write(char c, char attr, int i) { 8 | if(i > 80 * 25) return; 9 | char* addr = 0xB8000 + i * 2; 10 | *(addr) = c; 11 | *(addr + 1) = attr; 12 | } 13 | 14 | void screen_write(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b) { 15 | uint8_t *addr = 0x400000 + (x * 3) + (y * 1024 * 3); 16 | *(addr) = r; 17 | *(addr + 1) = g; 18 | *(addr + 2) = b; 19 | } 20 | 21 | void screen_write_rgb(uint16_t x, uint16_t y, uint32_t rgb) { 22 | void *addr = 0x400000 + (x * 3) + (y * 1024 * 3); 23 | *((uint8_t*)addr) = (uint8_t)(rgb >> 16); 24 | *((uint8_t*)addr + 1) = (uint8_t)(rgb >> 8); 25 | *((uint8_t*)addr + 2) = (uint8_t)(rgb >> 0); 26 | } 27 | 28 | uint32_t screen_get_rgb(uint16_t x, uint16_t y) { 29 | void *addr = 0x400000 + (x * 3) + (y * 1024 * 3); 30 | return *((uint32_t*)addr) >> 8; 31 | } 32 | 33 | 34 | font_glyph_data_t font_data_remaped[256]; 35 | bool font_ready = false; 36 | 37 | void prepare_font() { 38 | font_data_t data = get_font_data(); 39 | for(int i = 0; i < data.glyph_count; i++) 40 | font_data_remaped[data.glyphs[i].symbol] = data.glyphs[i]; 41 | font_ready = true; 42 | } 43 | 44 | font_glyph_data_t * get_glyph_by_char (char c) { 45 | return &font_data_remaped[c]; 46 | } 47 | 48 | void draw_font_symbol (font_glyph_data_t * data, uint16_t x, uint16_t y, uint32_t color) { 49 | uint8_t *img = get_resource_ptr_by_id(FONT_ID); 50 | 51 | for(int ix = 0; ix < data->w; ix++) { 52 | for(int iy = 0; iy < data->h; iy++) { 53 | uint16_t scx, scy; 54 | scx = x + ix + data->ox; 55 | scy = y + iy + data->oy; 56 | uint32_t p = screen_get_rgb(scx, scy); 57 | uint8_t d = img[data->x + ix + (data->y + iy) * FONT_IMG_WIDTH]; 58 | 59 | uint64_t mix = (color * d + p * (0xFF - d)) / 0xFF; 60 | 61 | screen_write_rgb(scx, scy, mix); 62 | } 63 | } 64 | } 65 | 66 | void draw_text (const char * s, uint16_t x, uint16_t y, uint32_t color) { 67 | uint16_t xadv = 0; 68 | while(*s != 0) { 69 | font_glyph_data_t data = font_data_remaped[*s]; 70 | draw_font_symbol(&data, x + xadv, y, color); 71 | xadv += data.advence; 72 | s++; 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /kernel/src/c/vga/vga_textmode.h: -------------------------------------------------------------------------------- 1 | #ifndef VGA_TEXTMODE_H 2 | #define VGA_TEXTMODE_H 3 | 4 | #include 5 | 6 | 7 | 8 | 9 | void vga_textmode_write(char, char, int); 10 | void screen_write(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b); 11 | 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /kernel/src/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | import konan.SymbolName 2 | import kotlinx.cinterop.* 3 | 4 | 5 | fun kernelMain() { 6 | 7 | setupIDT(); 8 | initializeMemoryAllocation(); 9 | 10 | val runtimeState = initRuntime(); 11 | if(runtimeState == nativeNullPtr) 12 | abort() 13 | 14 | setupPAE() 15 | prepareFont() 16 | 17 | print("Hello, world!", 0x7, 0) 18 | 19 | for(i in 0..10) 20 | print("Meow!", 0x7, 0) 21 | 22 | fillScreenRect(0, 0, 1024, 768, 0xFFFFFF) 23 | drawImage(getResourcePointerById(1), 1024 - 100, 0, 100, 100) 24 | 25 | drawText("Hello, world!", 10, 10, 0x0) 26 | 27 | 28 | hangPlayinWithNumbers() 29 | 30 | } 31 | 32 | fun fillScreenRect(xRange: IntRange, yRange: IntRange, r: Byte, g: Byte, b: Byte) { 33 | for(x in xRange) 34 | for(y in yRange) 35 | screenWrite(x.toShort(), y.toShort(), r, g, b) 36 | } 37 | 38 | val fbAddr = 0x400000L 39 | val fbWidth = 1024 40 | 41 | fun fillScreenRect(sx: Int, sy: Int, w: Int, h: Int, rgb: Int) { 42 | for(y in sy until (sy + h)) 43 | memset(fbAddr + sx * 3 + y * fbWidth * 3, rgb, (w * 3).toLong()) 44 | } 45 | 46 | fun drawImage(dataPtr: NativePtr, x: Int, y: Int, width: Int, height: Int) { 47 | val dataAddr = dataPtr.toLong() 48 | for(iy in 0 until height) { 49 | memcpy(fbAddr + x * 3 + (y + iy) * fbWidth * 3, dataAddr + iy * width * 3, width * 3L) 50 | } 51 | } 52 | 53 | fun setupPAE() { 54 | val pml4tPtr = interpretCPointer(alignedAlloc(PAEEntry.size, 0x1000))!!.apply { pointed.clear() } 55 | val pdptPtr = interpretCPointer(alignedAlloc(PAEEntry.size, 0x1000))!!.apply { pointed.clear() } 56 | val pdtPtr = interpretCPointer(alignedAlloc(PAEEntry.size, 0x1000))!!.apply { pointed.clear() } 57 | 58 | 59 | 60 | fun createPT(base: Long): CPointer { 61 | val ptPtr = interpretCPointer(alignedAlloc(PAEEntry.size, 0x1000))!!.apply { pointed.clear() } 62 | var i = 0 63 | while (i < 512) { 64 | ptPtr.pointed[i] = base + (i * 0x1000) + 3 65 | i++ 66 | } 67 | return ptPtr 68 | } 69 | 70 | 71 | val pt1Ptr = createPT(0x1000 * 0) 72 | val pt2Ptr = createPT(0x1000 * 512) 73 | 74 | 75 | 76 | 77 | pml4tPtr.pointed[0] = pdptPtr.rawValue.toLong() + 1 78 | pdptPtr.pointed[0] = pdtPtr.rawValue.toLong() + 1 79 | pdtPtr.pointed[0] = pt1Ptr.rawValue.toLong() + 3 80 | pdtPtr.pointed[1] = pt2Ptr.rawValue.toLong() + 3 81 | 82 | val ptSPtr = createPT(0xfd000000) 83 | val ptS1Ptr = createPT(0xfd000000 + 0x1000 * 512) 84 | 85 | pdtPtr.pointed[2] = ptSPtr.rawValue.toLong() + 3 86 | pdtPtr.pointed[3] = ptS1Ptr.rawValue.toLong() + 3 87 | 88 | /* 89 | val pdpt3Ptr = interpretCPointer(alignedAlloc(PAEEntry.size, 0x1000))!!.apply { pointed.clear() } 90 | val pdt3_488Ptr = interpretCPointer(alignedAlloc(PAEEntry.size, 0x1000))!!.apply { pointed.clear() } 91 | val ptSPtr = createPT(0xfd000000) 92 | val ptS1Ptr = createPT(0xfd000000 + 0x1000 * 512) 93 | 94 | 95 | for(i in 1..511) { 96 | pml4tPtr.pointed[i] = pdpt3Ptr.rawValue.toLong() + 1 97 | } 98 | 99 | for(i in 0..511) { 100 | pdpt3Ptr.pointed[i] = pdt3_488Ptr.rawValue.toLong() + 1 101 | pdt3_488Ptr.pointed[i] = ptSPtr.rawValue.toLong() + 3 102 | } 103 | 104 | pdt3_488Ptr.pointed[0] = ptSPtr.rawValue.toLong() + 3 105 | pdt3_488Ptr.pointed[1] = ptS1Ptr.rawValue.toLong() + 3*/ 106 | 107 | setPaeTableAddress(pml4tPtr.rawValue) 108 | } 109 | 110 | fun hangPlayinWithNumbers() { 111 | var j = 0 112 | while(true){ 113 | j++; 114 | var k = 0 115 | while(k++ < 10) 116 | vgaTextmodeWrite(' '.toByte(), 0x7, 80 + k) 117 | printNumber64Hex(j.toLong(), 0x7, 80) 118 | } 119 | } 120 | 121 | fun print(s: String, attr: Byte, pos: Int) { 122 | var i = 0 123 | while(i < s.length) { 124 | vgaTextmodeWrite(s[i].toByte(), attr, pos + i++) 125 | } 126 | } 127 | 128 | 129 | class PAEEntry(override val rawPtr: NativePtr) : CStructVar() { 130 | 131 | companion object : Type(8 * 512, 1024) 132 | 133 | fun clear() { 134 | var i = 0 135 | while (i < 512) { 136 | this[i] = 0 137 | i++ 138 | } 139 | } 140 | 141 | operator fun get(i: Int): Long { 142 | return memberAt(i * 8L).value 143 | } 144 | 145 | operator fun set(i: Int, v: Long) { 146 | memberAt(i * 8L).value = v 147 | } 148 | } 149 | 150 | class FontGlyphData(override val rawPtr: NativePtr) : CStructVar() { 151 | 152 | companion object : Type(11, 0x1) 153 | 154 | val advence: Byte 155 | get() = memberAt(11).value 156 | } 157 | 158 | @SymbolName("vga_textmode_write") 159 | external fun vgaTextmodeWrite(c: Byte, attr: Byte, pos: Int) 160 | 161 | @SymbolName("vga_textmode_print_int") 162 | external fun printNumber(i: Int, attr: Byte, pos: Int) 163 | 164 | @SymbolName("vga_textmode_print_ptr") 165 | external fun printNumber64Hex(i: Long, attr: Byte, pos: Int) 166 | 167 | @SymbolName("aligned_alloc") 168 | external fun alignedAlloc(s: Long, a: Int): NativePtr 169 | @SymbolName("malloc") 170 | external fun malloc(s: Long): NativePtr 171 | 172 | @SymbolName("static_alloc") 173 | external fun staticAlloc(addr: Int): NativePtr 174 | 175 | @SymbolName("set_pae_table_address") 176 | external fun setPaeTableAddress(addr: NativePtr) 177 | 178 | @SymbolName("setup_idt") 179 | external fun setupIDT() 180 | @SymbolName("initialize_memory_allocation") 181 | external fun initializeMemoryAllocation() 182 | 183 | @SymbolName("InitRuntime") 184 | external fun initRuntime(): NativePtr 185 | 186 | @SymbolName("abort") 187 | external fun abort() 188 | 189 | @SymbolName("screen_write") 190 | external fun screenWrite(x: Short, y: Short, r: Byte, g: Byte, b: Byte) 191 | @SymbolName("screen_write_rgb") 192 | external fun screenWriteRGB(x: Short, y: Short, rgb: Int) 193 | 194 | @SymbolName("get_resource_ptr_by_id") 195 | external fun getResourcePointerById(id: Int): NativePtr 196 | 197 | @SymbolName("get_int_at_addr") 198 | external fun getInt(l: Long): Int 199 | 200 | @SymbolName("memset") 201 | external fun memset(ptr: Long, v: Int, size: Long): Long 202 | 203 | @SymbolName("memcpy") 204 | external fun memcpy(dst: Long, src: Long, size: Long): Long 205 | 206 | @SymbolName("prepare_font") 207 | external fun prepareFont() 208 | 209 | @SymbolName("draw_text") 210 | external fun drawText(cstr: NativePtr, x: Short, y: Short, rgb: Int) 211 | 212 | fun drawText(text: String, x: Short, y: Short, rgb: Int) { 213 | return memScoped { 214 | val _cstr = text.cstr.getPointer(memScope).rawValue 215 | drawText(_cstr, x, y, rgb) 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /kernel/src/res/font/fira_mono_regular_17.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semoro/KOS/86171e3965a44ec2d150249187180ebcd58123a7/kernel/src/res/font/fira_mono_regular_17.PNG -------------------------------------------------------------------------------- /kernel/src/res/font/font.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semoro/KOS/86171e3965a44ec2d150249187180ebcd58123a7/kernel/src/res/font/font.dat -------------------------------------------------------------------------------- /kernel/src/res/font/font.sfl: -------------------------------------------------------------------------------- 1 | Fira Mono 2 | 17 36 3 | fira_mono_regular_17.PNG 4 | 95 5 | 32 1 27 2 0 -1 36 18 6 | 33 4 6 7 21 6 15 18 7 | 34 12 5 12 8 3 14 18 8 | 35 25 6 18 21 0 15 18 9 | 36 44 1 17 31 1 10 18 10 | 37 62 5 20 23 -1 14 18 11 | 38 83 6 19 21 0 15 18 12 | 39 103 5 6 8 6 14 18 13 | 40 110 1 12 31 2 10 18 14 | 41 123 1 12 31 4 10 18 15 | 42 136 11 16 12 1 20 18 16 | 43 153 12 14 11 2 21 18 17 | 44 168 22 8 10 5 31 18 18 | 45 177 16 14 3 2 25 18 19 | 46 192 22 8 5 5 31 18 20 | 47 201 2 18 29 0 11 18 21 | 48 220 6 16 21 1 15 18 22 | 49 237 6 16 21 1 15 18 23 | 50 254 6 16 21 0 15 18 24 | 51 271 6 17 21 0 15 18 25 | 52 289 5 16 22 1 14 18 26 | 53 306 6 16 21 1 15 18 27 | 54 323 6 16 21 1 15 18 28 | 55 340 6 16 22 1 15 18 29 | 56 357 6 18 21 0 15 18 30 | 57 376 6 16 22 1 15 18 31 | 58 393 11 8 16 5 20 18 32 | 59 402 11 8 21 5 20 18 33 | 60 411 9 16 17 1 18 18 34 | 61 428 14 14 8 2 23 18 35 | 62 443 9 16 17 1 18 18 36 | 63 460 6 16 21 1 15 18 37 | 64 477 6 20 24 -1 15 18 38 | 65 498 6 20 21 -1 15 18 39 | 66 519 6 17 21 1 15 18 40 | 67 537 6 19 21 0 15 18 41 | 68 557 6 17 21 1 15 18 42 | 69 575 6 15 21 2 15 18 43 | 70 591 6 15 21 3 15 18 44 | 71 607 6 18 21 0 15 18 45 | 72 626 6 16 21 1 15 18 46 | 73 643 6 15 21 2 15 18 47 | 74 659 6 16 21 1 15 18 48 | 75 676 6 17 21 2 15 18 49 | 76 694 6 15 21 3 15 18 50 | 77 710 6 20 21 -1 15 18 51 | 78 731 6 16 21 1 15 18 52 | 79 748 6 18 21 0 15 18 53 | 80 767 6 16 21 2 15 18 54 | 81 784 6 19 26 0 15 18 55 | 82 804 6 17 21 2 15 18 56 | 83 822 6 18 21 0 15 18 57 | 84 841 6 18 21 0 15 18 58 | 85 860 6 16 21 1 15 18 59 | 86 877 6 20 21 -1 15 18 60 | 87 898 6 20 21 -1 15 18 61 | 88 919 6 20 21 -1 15 18 62 | 89 940 6 20 21 -1 15 18 63 | 90 961 6 16 21 1 15 18 64 | 91 978 2 11 28 4 11 18 65 | 92 990 2 18 29 0 11 18 66 | 93 1009 2 11 28 3 11 18 67 | 94 1021 1 16 10 1 10 18 68 | 95 1038 29 18 3 0 38 18 69 | 96 1057 3 10 6 4 12 18 70 | 97 1068 11 16 17 1 20 18 71 | 98 1085 4 16 23 2 13 18 72 | 99 1102 11 16 16 1 20 18 73 | 100 1119 4 16 23 1 13 18 74 | 101 1136 11 16 16 1 20 18 75 | 102 1153 5 17 22 1 14 18 76 | 103 1171 9 17 24 1 18 18 77 | 104 1189 4 15 23 2 13 18 78 | 105 1205 4 15 23 2 13 18 79 | 106 1221 4 14 30 1 13 18 80 | 107 1236 4 17 23 2 13 18 81 | 108 1254 5 17 22 0 14 18 82 | 109 1272 11 18 16 0 20 18 83 | 110 1291 11 15 16 2 20 18 84 | 111 1307 11 16 16 1 20 18 85 | 112 1324 11 15 22 2 20 18 86 | 113 1340 11 16 22 1 20 18 87 | 114 1357 11 16 16 2 20 18 88 | 115 1374 11 16 16 1 20 18 89 | 116 1391 7 16 20 1 16 18 90 | 117 1408 11 15 16 2 20 18 91 | 118 1424 11 18 16 0 20 18 92 | 119 1443 11 20 16 -1 20 18 93 | 120 1464 11 18 16 0 20 18 94 | 121 1483 11 18 23 0 20 18 95 | 122 1502 11 15 16 2 20 18 96 | 123 1518 2 13 29 2 11 18 97 | 124 1532 3 6 27 6 12 18 98 | 125 1539 2 13 29 3 11 18 99 | 126 1553 14 18 6 0 23 18 100 | 0 101 | -------------------------------------------------------------------------------- /kernel/src/res/font/font_data.c: -------------------------------------------------------------------------------- 1 | #include "font_data.h" 2 | 3 | font_glyph_data_t font_glyphs[95] = { 4 | {.symbol = 32, .x = 1, .y = 27, .w = 2, .h = 0, .ox = -1, .oy = 36, .advence = 18}, 5 | {.symbol = 33, .x = 4, .y = 6, .w = 7, .h = 21, .ox = 6, .oy = 15, .advence = 18}, 6 | {.symbol = 34, .x = 12, .y = 5, .w = 12, .h = 8, .ox = 3, .oy = 14, .advence = 18}, 7 | {.symbol = 35, .x = 25, .y = 6, .w = 18, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 8 | {.symbol = 36, .x = 44, .y = 1, .w = 17, .h = 31, .ox = 1, .oy = 10, .advence = 18}, 9 | {.symbol = 37, .x = 62, .y = 5, .w = 20, .h = 23, .ox = -1, .oy = 14, .advence = 18}, 10 | {.symbol = 38, .x = 83, .y = 6, .w = 19, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 11 | {.symbol = 39, .x = 103, .y = 5, .w = 6, .h = 8, .ox = 6, .oy = 14, .advence = 18}, 12 | {.symbol = 40, .x = 110, .y = 1, .w = 12, .h = 31, .ox = 2, .oy = 10, .advence = 18}, 13 | {.symbol = 41, .x = 123, .y = 1, .w = 12, .h = 31, .ox = 4, .oy = 10, .advence = 18}, 14 | {.symbol = 42, .x = 136, .y = 11, .w = 16, .h = 12, .ox = 1, .oy = 20, .advence = 18}, 15 | {.symbol = 43, .x = 153, .y = 12, .w = 14, .h = 11, .ox = 2, .oy = 21, .advence = 18}, 16 | {.symbol = 44, .x = 168, .y = 22, .w = 8, .h = 10, .ox = 5, .oy = 31, .advence = 18}, 17 | {.symbol = 45, .x = 177, .y = 16, .w = 14, .h = 3, .ox = 2, .oy = 25, .advence = 18}, 18 | {.symbol = 46, .x = 192, .y = 22, .w = 8, .h = 5, .ox = 5, .oy = 31, .advence = 18}, 19 | {.symbol = 47, .x = 201, .y = 2, .w = 18, .h = 29, .ox = 0, .oy = 11, .advence = 18}, 20 | {.symbol = 48, .x = 220, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 21 | {.symbol = 49, .x = 237, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 22 | {.symbol = 50, .x = 254, .y = 6, .w = 16, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 23 | {.symbol = 51, .x = 271, .y = 6, .w = 17, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 24 | {.symbol = 52, .x = 289, .y = 5, .w = 16, .h = 22, .ox = 1, .oy = 14, .advence = 18}, 25 | {.symbol = 53, .x = 306, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 26 | {.symbol = 54, .x = 323, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 27 | {.symbol = 55, .x = 340, .y = 6, .w = 16, .h = 22, .ox = 1, .oy = 15, .advence = 18}, 28 | {.symbol = 56, .x = 357, .y = 6, .w = 18, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 29 | {.symbol = 57, .x = 376, .y = 6, .w = 16, .h = 22, .ox = 1, .oy = 15, .advence = 18}, 30 | {.symbol = 58, .x = 393, .y = 11, .w = 8, .h = 16, .ox = 5, .oy = 20, .advence = 18}, 31 | {.symbol = 59, .x = 402, .y = 11, .w = 8, .h = 21, .ox = 5, .oy = 20, .advence = 18}, 32 | {.symbol = 60, .x = 411, .y = 9, .w = 16, .h = 17, .ox = 1, .oy = 18, .advence = 18}, 33 | {.symbol = 61, .x = 428, .y = 14, .w = 14, .h = 8, .ox = 2, .oy = 23, .advence = 18}, 34 | {.symbol = 62, .x = 443, .y = 9, .w = 16, .h = 17, .ox = 1, .oy = 18, .advence = 18}, 35 | {.symbol = 63, .x = 460, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 36 | {.symbol = 64, .x = 477, .y = 6, .w = 20, .h = 24, .ox = -1, .oy = 15, .advence = 18}, 37 | {.symbol = 65, .x = 498, .y = 6, .w = 20, .h = 21, .ox = -1, .oy = 15, .advence = 18}, 38 | {.symbol = 66, .x = 519, .y = 6, .w = 17, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 39 | {.symbol = 67, .x = 537, .y = 6, .w = 19, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 40 | {.symbol = 68, .x = 557, .y = 6, .w = 17, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 41 | {.symbol = 69, .x = 575, .y = 6, .w = 15, .h = 21, .ox = 2, .oy = 15, .advence = 18}, 42 | {.symbol = 70, .x = 591, .y = 6, .w = 15, .h = 21, .ox = 3, .oy = 15, .advence = 18}, 43 | {.symbol = 71, .x = 607, .y = 6, .w = 18, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 44 | {.symbol = 72, .x = 626, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 45 | {.symbol = 73, .x = 643, .y = 6, .w = 15, .h = 21, .ox = 2, .oy = 15, .advence = 18}, 46 | {.symbol = 74, .x = 659, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 47 | {.symbol = 75, .x = 676, .y = 6, .w = 17, .h = 21, .ox = 2, .oy = 15, .advence = 18}, 48 | {.symbol = 76, .x = 694, .y = 6, .w = 15, .h = 21, .ox = 3, .oy = 15, .advence = 18}, 49 | {.symbol = 77, .x = 710, .y = 6, .w = 20, .h = 21, .ox = -1, .oy = 15, .advence = 18}, 50 | {.symbol = 78, .x = 731, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 51 | {.symbol = 79, .x = 748, .y = 6, .w = 18, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 52 | {.symbol = 80, .x = 767, .y = 6, .w = 16, .h = 21, .ox = 2, .oy = 15, .advence = 18}, 53 | {.symbol = 81, .x = 784, .y = 6, .w = 19, .h = 26, .ox = 0, .oy = 15, .advence = 18}, 54 | {.symbol = 82, .x = 804, .y = 6, .w = 17, .h = 21, .ox = 2, .oy = 15, .advence = 18}, 55 | {.symbol = 83, .x = 822, .y = 6, .w = 18, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 56 | {.symbol = 84, .x = 841, .y = 6, .w = 18, .h = 21, .ox = 0, .oy = 15, .advence = 18}, 57 | {.symbol = 85, .x = 860, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 58 | {.symbol = 86, .x = 877, .y = 6, .w = 20, .h = 21, .ox = -1, .oy = 15, .advence = 18}, 59 | {.symbol = 87, .x = 898, .y = 6, .w = 20, .h = 21, .ox = -1, .oy = 15, .advence = 18}, 60 | {.symbol = 88, .x = 919, .y = 6, .w = 20, .h = 21, .ox = -1, .oy = 15, .advence = 18}, 61 | {.symbol = 89, .x = 940, .y = 6, .w = 20, .h = 21, .ox = -1, .oy = 15, .advence = 18}, 62 | {.symbol = 90, .x = 961, .y = 6, .w = 16, .h = 21, .ox = 1, .oy = 15, .advence = 18}, 63 | {.symbol = 91, .x = 978, .y = 2, .w = 11, .h = 28, .ox = 4, .oy = 11, .advence = 18}, 64 | {.symbol = 92, .x = 990, .y = 2, .w = 18, .h = 29, .ox = 0, .oy = 11, .advence = 18}, 65 | {.symbol = 93, .x = 1009, .y = 2, .w = 11, .h = 28, .ox = 3, .oy = 11, .advence = 18}, 66 | {.symbol = 94, .x = 1021, .y = 1, .w = 16, .h = 10, .ox = 1, .oy = 10, .advence = 18}, 67 | {.symbol = 95, .x = 1038, .y = 29, .w = 18, .h = 3, .ox = 0, .oy = 38, .advence = 18}, 68 | {.symbol = 96, .x = 1057, .y = 3, .w = 10, .h = 6, .ox = 4, .oy = 12, .advence = 18}, 69 | {.symbol = 97, .x = 1068, .y = 11, .w = 16, .h = 17, .ox = 1, .oy = 20, .advence = 18}, 70 | {.symbol = 98, .x = 1085, .y = 4, .w = 16, .h = 23, .ox = 2, .oy = 13, .advence = 18}, 71 | {.symbol = 99, .x = 1102, .y = 11, .w = 16, .h = 16, .ox = 1, .oy = 20, .advence = 18}, 72 | {.symbol = 100, .x = 1119, .y = 4, .w = 16, .h = 23, .ox = 1, .oy = 13, .advence = 18}, 73 | {.symbol = 101, .x = 1136, .y = 11, .w = 16, .h = 16, .ox = 1, .oy = 20, .advence = 18}, 74 | {.symbol = 102, .x = 1153, .y = 5, .w = 17, .h = 22, .ox = 1, .oy = 14, .advence = 18}, 75 | {.symbol = 103, .x = 1171, .y = 9, .w = 17, .h = 24, .ox = 1, .oy = 18, .advence = 18}, 76 | {.symbol = 104, .x = 1189, .y = 4, .w = 15, .h = 23, .ox = 2, .oy = 13, .advence = 18}, 77 | {.symbol = 105, .x = 1205, .y = 4, .w = 15, .h = 23, .ox = 2, .oy = 13, .advence = 18}, 78 | {.symbol = 106, .x = 1221, .y = 4, .w = 14, .h = 30, .ox = 1, .oy = 13, .advence = 18}, 79 | {.symbol = 107, .x = 1236, .y = 4, .w = 17, .h = 23, .ox = 2, .oy = 13, .advence = 18}, 80 | {.symbol = 108, .x = 1254, .y = 5, .w = 17, .h = 22, .ox = 0, .oy = 14, .advence = 18}, 81 | {.symbol = 109, .x = 1272, .y = 11, .w = 18, .h = 16, .ox = 0, .oy = 20, .advence = 18}, 82 | {.symbol = 110, .x = 1291, .y = 11, .w = 15, .h = 16, .ox = 2, .oy = 20, .advence = 18}, 83 | {.symbol = 111, .x = 1307, .y = 11, .w = 16, .h = 16, .ox = 1, .oy = 20, .advence = 18}, 84 | {.symbol = 112, .x = 1324, .y = 11, .w = 15, .h = 22, .ox = 2, .oy = 20, .advence = 18}, 85 | {.symbol = 113, .x = 1340, .y = 11, .w = 16, .h = 22, .ox = 1, .oy = 20, .advence = 18}, 86 | {.symbol = 114, .x = 1357, .y = 11, .w = 16, .h = 16, .ox = 2, .oy = 20, .advence = 18}, 87 | {.symbol = 115, .x = 1374, .y = 11, .w = 16, .h = 16, .ox = 1, .oy = 20, .advence = 18}, 88 | {.symbol = 116, .x = 1391, .y = 7, .w = 16, .h = 20, .ox = 1, .oy = 16, .advence = 18}, 89 | {.symbol = 117, .x = 1408, .y = 11, .w = 15, .h = 16, .ox = 2, .oy = 20, .advence = 18}, 90 | {.symbol = 118, .x = 1424, .y = 11, .w = 18, .h = 16, .ox = 0, .oy = 20, .advence = 18}, 91 | {.symbol = 119, .x = 1443, .y = 11, .w = 20, .h = 16, .ox = -1, .oy = 20, .advence = 18}, 92 | {.symbol = 120, .x = 1464, .y = 11, .w = 18, .h = 16, .ox = 0, .oy = 20, .advence = 18}, 93 | {.symbol = 121, .x = 1483, .y = 11, .w = 18, .h = 23, .ox = 0, .oy = 20, .advence = 18}, 94 | {.symbol = 122, .x = 1502, .y = 11, .w = 15, .h = 16, .ox = 2, .oy = 20, .advence = 18}, 95 | {.symbol = 123, .x = 1518, .y = 2, .w = 13, .h = 29, .ox = 2, .oy = 11, .advence = 18}, 96 | {.symbol = 124, .x = 1532, .y = 3, .w = 6, .h = 27, .ox = 6, .oy = 12, .advence = 18}, 97 | {.symbol = 125, .x = 1539, .y = 2, .w = 13, .h = 29, .ox = 3, .oy = 11, .advence = 18}, 98 | {.symbol = 126, .x = 1553, .y = 14, .w = 18, .h = 6, .ox = 0, .oy = 23, .advence = 18} 99 | 100 | }; 101 | 102 | 103 | font_data_t font_data = { 104 | .w = 20, 105 | .h = 27, 106 | .glyph_count = 95, 107 | .glyphs = font_glyphs 108 | }; 109 | 110 | font_data_t get_font_data() { 111 | return font_data; 112 | } 113 | -------------------------------------------------------------------------------- /kernel/src/res/font/font_data.h: -------------------------------------------------------------------------------- 1 | #include "font_defs.h" 2 | #ifndef FONT_DATA_H 3 | #define FONT_DATA_H 4 | 5 | #define FONT_IMG_WIDTH 1573 6 | 7 | font_data_t get_font_data(); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /kernel/src/res/font/font_defs.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FONT_DEFS_H 3 | #define FONT_DEFS_H 4 | 5 | #include 6 | 7 | typedef struct { 8 | uint16_t symbol; 9 | uint16_t x, y; 10 | uint8_t w, h; 11 | int8_t ox, oy; 12 | uint8_t advence; 13 | 14 | } font_glyph_data_t; 15 | 16 | typedef struct { 17 | uint8_t w, h; 18 | uint32_t glyph_count; 19 | font_glyph_data_t* glyphs; 20 | } font_data_t; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /kernel/src/res/kotlin.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semoro/KOS/86171e3965a44ec2d150249187180ebcd58123a7/kernel/src/res/kotlin.dat -------------------------------------------------------------------------------- /kernel/src/res/kotlin_250x250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semoro/KOS/86171e3965a44ec2d150249187180ebcd58123a7/kernel/src/res/kotlin_250x250.png -------------------------------------------------------------------------------- /kernel/src/res/resource_data.c: -------------------------------------------------------------------------------- 1 | #include "resource_data.h" 2 | 3 | #define RES_START(name) _binary_##name##_start 4 | #define RES_SIZE(name) _binary_##name##_size 5 | #define RES_START_PTR(name) &RES_START(name) 6 | 7 | #define DEF_RES(name) void* RES_START(name); uint64_t RES_SIZE(name); 8 | 9 | #define RES_PTR_CASE(id, name) case id: return RES_START_PTR(name) 10 | #define RES_SIZE_CASE(id, name) case id: return RES_SIZE(name) 11 | 12 | 13 | DEF_RES(src_res_kotlin_dat) 14 | DEF_RES(src_res_font_font_dat) 15 | 16 | uint64_t get_resource_ptr_by_id(int id) { 17 | switch (id) { 18 | RES_PTR_CASE(KOTLIN_LOGO_ID, src_res_kotlin_dat); 19 | RES_PTR_CASE(FONT_ID, src_res_font_font_dat); 20 | default: 21 | return 0; 22 | } 23 | } 24 | 25 | uint64_t get_resource_size_by_id(int id) { 26 | switch (id) { 27 | RES_SIZE_CASE(KOTLIN_LOGO_ID, src_res_kotlin_dat); 28 | RES_SIZE_CASE(FONT_ID, src_res_font_font_dat); 29 | default: 30 | return 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /kernel/src/res/resource_data.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef RESOURCE_DATA_H 3 | #define RESOURCE_DATA_H 4 | 5 | #include 6 | 7 | #define KOTLIN_LOGO_ID 1 8 | #define FONT_ID 2 9 | 10 | 11 | uint64_t get_resource_ptr_by_id(int id); 12 | 13 | uint64_t get_resource_size_by_id(int id); 14 | 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /kernel/stdlib.kt.bc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semoro/KOS/86171e3965a44ec2d150249187180ebcd58123a7/kernel/stdlib.kt.bc.o -------------------------------------------------------------------------------- /named_breakpoints: -------------------------------------------------------------------------------- 1 | 2 | hbreak handle_ex_6 3 | 4 | hbreak handle_ex_0 5 | hbreak handle_ex_14 6 | -------------------------------------------------------------------------------- /setBreakpoints.py: -------------------------------------------------------------------------------- 1 | import re 2 | import sys 3 | 4 | symbols = {} 5 | 6 | for line in open('build/kernel.lst'): 7 | symbolData = str.split(line) 8 | key = (symbolData[1], symbolData[2]) 9 | value = int(symbolData[0],16) 10 | symbols[key] = value 11 | 12 | 13 | for line in open('breakpoints'): 14 | if line[0] == '#': 15 | continue 16 | regex = re.compile(line.rstrip('\n')) 17 | matched = False 18 | for key in symbols.keys(): 19 | #print(line, key) 20 | if regex.match(key[0] + ' ' + key[1]) or regex.match(key[1]): 21 | print('hbreak ' + '*' + hex(symbols[key])) 22 | matched = True 23 | if not matched: 24 | sys.stderr.write('Could not find symbol matching ' + line.rstrip('\n') + '\n') 25 | exit(1) 26 | --------------------------------------------------------------------------------