diff --git a/.DS_Store b/.DS_Store index ac1416d..acadee7 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Makefile b/Makefile deleted file mode 100644 index 9ef9ff5..0000000 --- a/Makefile +++ /dev/null @@ -1,112 +0,0 @@ -ASM = nasm -CC = gcc -BOOTSTRAP_FILE = bootstrap.asm -SIMPLE_KERNEL = simple_kernel.asm -INIT_KERNEL_FILES = starter.asm -KERNEL_FILES = main.c - -# -m32 means generate 32-bit code. See "Machine-Dependent Options" section in gcc man page for details. Under "x86 Options" section "-m flag". -# -# -Wall: -# "This enables all the warnings about constructions that some -# users consider questionable, and that are easy to avoid (or -# modify to prevent the warning), even in conjunction with -# macros. This also enables some language-specific warnings -# described in C++ Dialect Options and Objective-C and -# Objective-C++ Dialect Options." -# ~ GCC man page -# -# -c: -# "If any of these options is used [-c, -S, -E], then the linker is not run, and object file names should not be used as arguments." -# ~ GCC man page -# -# -ffreestanding: -# "Assert that compilation targets a freestanding environment. -# This implies -fno-builtin. A freestanding environment is one -# in which the standard library may not exist, and program -# startup may not necessarily be at "main". The most obvious -# example is an OS kernel. This is equivalent to -fno-hosted." -# ~ GCC man page -# -# -no-pie: -# "Don't produce a dynamically linked position independent executable." -# ~ GCC man page -# -# -g: -# "To tell GCC to emit extra information for use by a debugger, in almost all cases you need only to add -g to your other options." -# ~ GCC man page -# -# -std= -# "Determine the language standard. This option is currently only supported when compiling C or C++." -# gnu99: "GNU dialect of ISO C99. The name gnu9x is deprecated." -# gnu18: "GNU dialect of ISO C17. This is the default for C code." -# ~ GCC man page -#-std=gnu99 # -c -Wall -no-pie -g -std=gnu99 -KERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie -# -O1 -fno-pie -KERNEL_OBJECT = -o kernel.elf - -build: - echo Please Choose Type - -kernel: $(BOOTSTRAP_FILE) $(KERNEL_FILE) - $(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o - $(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o - $(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT) - $(CC) $(KERNEL_FLAGS) screen.c -o screen.elf - $(CC) $(KERNEL_FLAGS) process.c -o process.elf - $(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf - ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf -o minios.elf - objcopy -O binary minios.elf minios.bin - dd if=bootstrap.o of=kernel.img - dd seek=1 conv=sync if=minios.bin of=kernel.img bs=512 count=8 - dd seek=9 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046 - #bochs -f bochs - -run: - qemu-system-x86_64 -s kernel.img - -debug: $(BOOTSTRAP_FILE) $(KERNEL_FILE) - $(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o - $(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o - $(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT) - $(CC) $(KERNEL_FLAGS) screen.c -o screen.elf - $(CC) $(KERNEL_FLAGS) process.c -o process.elf - $(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf - ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf -o minios.elf - objcopy -O binary minios.elf minios.bin - dd if=bootstrap.o of=kernel.img - dd seek=1 conv=sync if=minios.bin of=kernel.img bs=512 count=8 - dd seek=9 conv=sync if=/dev/zero of=kernel.img bs=512 count=2045 - bochs -f bochs - #qemu-system-x86_64 -s kernel.img - -fromgas: $(BOOTSTRAP_FILE) $(KERNEL_FILE) - $(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o - $(ASM) -f bin $(INIT_KERNEL_FILES) -o starter.o - #$(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT) - as --32 main.s -o kernel.elf - objcopy -O binary kernel.elf kernel.o - ld -Ttext 0x0900 -b binary --oformat=binary starter.o kernel.o -o minios.bin - dd if=bootstrap.o of=kernel.img - dd seek=1 conv=sync if=minios.bin of=kernel.img bs=512 - dd seek=2 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046 - #bochs -f bochs - #qemu-system-x86_64 -s kernel.img - -asm: $(KERNEL_FILE) - $(CC) $(KERNEL_FLAGS) -S $(KERNEL_FILES) - -simplekernel: $(BOOTSTRAP_FILE) $(SIMPLE_KERNEL) - $(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o - $(ASM) -f bin $(SIMPLE_KERNEL) -o kernel.o - dd if=bootstrap.o of=kernel.img - dd seek=1 conv=sync if=kernel.o of=kernel.img bs=512 - qemu-system-x86_64 -s kernel.img - - -clean: - rm -f *.o - rm -f *.elf - rm -f *.img - rm -f *.bin diff --git a/asset/v3.png b/asset/v3.png new file mode 100644 index 0000000..70f4ae5 Binary files /dev/null and b/asset/v3.png differ diff --git a/bootstrap.asm b/bootstrap.asm deleted file mode 100644 index 5ed6b82..0000000 --- a/bootstrap.asm +++ /dev/null @@ -1,170 +0,0 @@ -start: - ; When a the boot sector is loaded by BIOS. It will be loaded on the location 07C0h in the memory. - ; What we do here is setting the register "ds" to the value "07C0" which is the same of the memory address we are on now. - ; Our variable "hello_string" will be loaded as a part of the bootloader, when we use it in the line "mov si, hello_string" - ; we're actually loading the memory address of the first character, let's assume that this memory address is (1000). Because - ; it is considered as a "data" by the processor. This offset (the memory address of "hello_string") will be added to the data segment - ; selector which resides in the register "ds". According to "Protected Mode Software Architecture", the initial value of "ds" is 0000h, - ; so, if we keep "ds" as it is, the CPU is going to load the data from the memory 00001000, BUT we are actually on 07C0, so the data - ; segment selector should be 07C0h so we can get the correct address of "hello_string" which is 07C01000 and not 00001000. - ; For backward compatibility, when the bootloader starts, the execution environment will be in "Real Mode", 16-bit. - mov ax, 07C0h - mov ds, ax - - ; ... ; - - ; == Printing == ; - - mov si, title_string - call print_string ; "CALL" is used instead of "JMP" because we would like to return to the next instruction after "print_string" finishes. - - mov si, message_string - call print_string - - ; ... ; - - ; === Loading the Kernel === ; - - call load_kernel_from_disk - - ; If the loading has been performed correctly. Jump to the kernel's code which resides on 0900h:0000 according - ; to ES:BX values before calling (int 13h). - ; - ; There is a difference between "JMP" and "CALL" inctructions. The first one doesn't store returning information - ; in the stack while the later does. Because we are not going to return from kernel to the bootloader, we don't - ; need to store return information. - - jmp 0900h:0000 - -; ... ; -; ... ; - -load_kernel_from_disk: - ; BIOS provides disk services through intrrupt 13h. The value of the register "ah" decides which disk service that we are requesting from BIOS. - - ; The Disk Service "02h" loads sectors to the memory. The memory location that we would like to load our kernel in should be decided - ; before calling "int 13h". There are two parts of this location. The first part (segment selector) resides in the register "ES" while - ; the other part (offset) resides in the register "BX". - ; - ; x86 Segment Registers: CS: for code segment. - ; DS, ES, FS, and GS: for 4 data segments. - ; SS: for stack segment. - ; They are 16-bit registers that hold "segment selectors" - mov ax, [curr_sector_to_load] - sub ax, 2 - mov bx, 512d - mul bx - mov bx, ax - - mov ax, 0900h - mov es, ax - - mov ah, 02h ; Requesting the service of reading disk sectors - mov al, 1h ; Number of sectors to read (How many sectors to read?) - mov ch, 0h ; Track number - mov cl, [curr_sector_to_load] ; Sector number - mov dh, 0h ; Head number - mov dl, 80h ; Drive to read from. (0 = Floppy. 80h = Drive #0. 81h = Drive #1) - int 13h ; BIOS Disk Services - - - ; The instruction "jc" jumps to a memory location when CF = 1 (jc = jump if carry). - ; CF (or carry flag) is the first bit of EFLAG register in x86. The BIOS service (13h,02h) - ; clear CF (that is, put 0 in CF) when everything is fine. But if there is some error - ; it's going to set CF (that is, put 1 in CF). Error code will be in "ah". - ; - ; If any error happens in loading our kernel. The bootloader is going to jump to the label "kernel_load_error". - jc kernel_load_error - - sub byte [number_of_sectors_to_load], 1 - add byte [curr_sector_to_load], 1 - cmp byte [number_of_sectors_to_load], 0 - - jne load_kernel_from_disk - - ret - -; When the bootloader fails to load the kernel. A nice message is printted for the user. -kernel_load_error: - mov si, load_error_string - call print_string - - ; "$" is a special expression in NASM. It means the starting memory address (or assembly position?) of current instruction, that means - ; the following instruction is going to loop forever. - jmp $ - -; ... ; -; ... ; - -; BIOS provides video services through intrrupt 10h. The value of the register "ah" decides which video service that we are requesting from BIOS. -; Those BIOS services are only available on Real Mode (https://stackoverflow.com/questions/26448480/bios-interrupts-in-protected-mode) -; -; ah = 0Eh means that we wish to print a character in TTY mode. -; For an example of using service "0Eh" to print "Hello" character by character, please refer to "../examples/bootstrap/1/". - -print_string: - mov ah, 0Eh - -print_char: - ; [MQH] 26 Nov 2019 - ; It's known that a byte = 8 bits. In x86 there are more two units: a "word" = 16 bits and "doubleword" = 32 bits. Some x86 instructions have multiple variants that work - ; with a specific aforementioned unit. "lods" is an example of these instructions, there is "lodsb" which works with a byte, "lodsw" which works with a word and "lodsd" which - ; works with doubleword. - ; - ; The instruction "lods" uses the value which is stored in register "si" (when using lodsb or loadsw) or register "esi" (when using lodsw) and assume that this - ; value as memory location. Then according to the used unit a (b)yte (8-bits), (w)ord (16-bits) or (d)oubleword (32-bit) will be read from the memory location DS:(E)SI - ; and store these bits in al, ax or eax according to the size of read data. - lodsb - - cmp al, 0 - je printing_finished - - int 10h - - jmp print_char - -printing_finished: - mov al, 10d ; Print new line - int 10h - - ; Move the cursor to the beginning - mov ah, 03h - mov bh, 0 - int 10h - - mov ah, 02h - mov dl, 0 - int 10h - - ; print_string is a procedure (or function), therefore we should return. It is called by using "CALL" instead of "JMP". - ret - -; ... ; - -; "DB" is one of pseudo-instructions which is provided by NASM. A source line in NASM follows the following format -; label: instruction operands ; comment -; The label is optional and even the colon after the label is optional. -; "DB" is used to declare initialized data. The "B" in "DB" means byte. -; the part ", 0" means that the last byte will be 0. In some way resembles -; nul character in C strings. -; -; Put the string in the output of this assembly file. Byte by byte, and the address of -; this string will be in the label, so we can reach the string inside the assembly source code. -title_string db 'The Bootloader of 539kernel.', 0 -message_string db 'The kernel is loading...', 0 -load_error_string db 'The kernel cannot be loaded', 0 -number_of_sectors_to_load db 10d ; 255 sectors = 127.5KB ; [MQH] NEW 4 July 2021 -curr_sector_to_load db 2d - -; "TIMES" is an NASM pseudo-instruction which repeats an instruction a number of specific times. -; The first operand of "TIMES" is the number of repetitions. -; As we mentioned before "$" means the starting address (or assembly position?) of current instruction. -; "$$" is another special expression which means the starting address (or assembly position?) of current section. -; So, we know that the size of bootstrap should be 512 byte. Two bytes are represent the magic code in the last line -; so 510 bytes remains for us. Our code starts from position $$ and we reached position $. Therefore, $ - $$ gives -; us the size of our code. So, 510 - ( $ - $$ ) gives us the remaining size of the 512 bytes and fills it with zeros -; by using "DB". -times 510-($-$$) db 0 - -; Put the magic code of bootloader in the end of assembly file's output. "W" means word. -dw 0xAA55 diff --git a/kernel.elf b/kernel.elf deleted file mode 100644 index 3e71ce5..0000000 Binary files a/kernel.elf and /dev/null differ diff --git a/notes/v4_notes.md b/notes/v4_notes.md new file mode 100644 index 0000000..90886bb --- /dev/null +++ b/notes/v4_notes.md @@ -0,0 +1,123 @@ +# Memory Management + +One of the main responsibility of kernel is to manage memory: processes should not interfere with each other's memory (unless by design e.g. IPC) + protect kernel memory + +Memory model: +- Flat memory model: logical memory = physical memory +- Segmentation +- Paging + +## Paging Theory + +Logical memory is divided into a number of fixed size blocks known as pages +Physical memory is divided into blocks of the same size known as page frames + +Page table: data structure which maps pages and page frame + +Memory Management Unit (MMU) -> responsible for memory address translation + +Provides memory protection -> since all accesses is seen by the kernel + +## Virtual Memory + +Aside from protection, memory management -> utilize as much CPU as possible + +Main problem -> program takes up memory space but lie idle (esp. true for big software, not everything is developed) + +Virtual memory! + +Demand paging -> only load starter code, load only wen needed, swap when useless + +Page replacement algorithm: FIFO, LRU, etc. + +Page table can store metadata e.g. if page is present in memory or is in disk + +Page fault: exception that memory of process is not loaded, need to load + + +## Paging in x86 + +paging is not available by default on real mode, can only be used in 32-bit environment (unlike segmentation) + +How to enable paging? + +Go to protected mode, enably by changing control register CR0 of x86 last bit from 0 to 1 + +Types of paging? + +There are 2 more bits to change paging mode: +- first one is PAE bit (fifth bit of CR4) -> 1 PEA enabled 0 PEA disabled +- second bit is LME in a register called IA32_EFER -> 1 switch fro protected mode 32 bit to long wode 64 bit, when PAE bit is 1 then 4-level mode is enabled + +(in 64 bit architecture, paging is available for both protected and long mode) + +In 32 bit, there are 2 available sizes for a page: 4KB and 4MB + 4GB memory is addressable in this mode + +### Structure of Linear Memory Address + +32 bits: +- [22, 31]: Page Group Entry -> Page Group Address (1024 page groups) +- [12, 21]: Page Table Entry -> Page address (1024 pages) +- [0, 11]: Offset + +Any memory address generated by executing code is logical address -> need to be translated to get the real address + +First step: use segment descriptor to translate a logical address to a linear address by using the mechanism we have mentioned + +When paging is disabled, the resulted linear address will be the physical (real) address that can be sent to the main memory to get the required data + +When paging is enabled, the linear address needs further translation to obtain physical address -> page table is required + +Multi-level Paging -> save memory -> only need to load the needed parts of page table instead of whole page table into the memory + +### Page Directory + +Can hold up to 1024 entries -> each entry points to a page table and each one can hold up to 1024 entries + +How to find page directory? +- use register CR3 which stores the base physical memory address of current page directory +- first part of a linear address is an offset within the page directory, when an addition operation is performed between the first part of a linear address and the value on CR3, the result will be the base memory address of the entry that represents a page table table that contains an entry which represents the page that contains the required data + +### Page Directory Entry +- 4 Bytes +- represent the physical memory address of the page table this entry represents +- not all page tables that a page directory points to should be loaded into the main memory -> only the needed page tables, the rest are stored in secondary storage until they are needed +- we need some place to store a flag that tells us whether the page table in question is laoded into the main memory -> the job of bit 0: 1 present 0 need to load + +Protection Scheme: +- Bit 1 in page directory entry -> 0: read only 1: writable +- Bit 2: 0: only privilege level 0, 1, 2 can access 1: PL 3 can access + +Caching: +- Cache hit, cache miss +- In memory -> use TLB +- Bit 4 of page directory entry: 1: no caching 0: caching (why disable caching? testing, debugging, some software faster w/o caching) +- write policy -> if cache has change how to save it to memory/ disk: 1. write-through -> write in both cache and source 2. write0back -> only on cache and save later on + +More configurations +- Bit 3 decides writing policy: 1: write through 0: write back +- Bit 5 access bits: 1 -> processor set value 1 when page table is accessed 0 -> set 0 is responsibility of kernel +- Bit 7: 0 -> page size 4KB 1 -> page size 4MB + +### Page Table + +In 4KB page environment, page table is referred to by an entry in the page directory + +Each page table -> hold 1024 entries + +Find base page table address -> add page table entry -> get base memory address -> add offset -> get memory address + +Entry of page table -> exactly the same as entry of page directory, its size is 4 bytes + +Some diff: +- Bit 7: ignored (used to decide page size in page directory) +- Bit 6: dirty bit (ignored in page directory) -> indicate we need to change, this is old entry -> because we don't delete old entry just set dirty bit to 1 (1: is dirty 0: is not dirty) + +## Implementing Memory Management + +We need memory managemetn so we can allocate memory dynammically + +Paging: +- valid page directory should be initialized, its address should be loaded in the register CR3 +- paging should be enabled by modfying the value of CR0 -> tell processor to start using paging and translate linear address (instead of interpreting linear address as physical address) +- We need to implement paging for each process, but here we only implement paging for kernel \ No newline at end of file diff --git a/process.elf b/process.elf deleted file mode 100644 index e1c3efb..0000000 Binary files a/process.elf and /dev/null differ diff --git a/bootstrap.o b/sample_build/bootstrap.o similarity index 100% rename from bootstrap.o rename to sample_build/bootstrap.o diff --git a/sample_build/git_logs.txt b/sample_build/git_logs.txt new file mode 100644 index 0000000..c8091f2 --- /dev/null +++ b/sample_build/git_logs.txt @@ -0,0 +1,451 @@ +commit f929627cab69620f2ae9b39fd6edaf839daee4a1 +Author: Albert Ariel Widiaatmaja +Date: Sun Aug 20 12:06:01 2023 +0800 + + feat: add content about memory management + +commit ff0a5e5465bb5aabc27a9350a38778a09d6939ef +Author: Albert Ariel Widiaatmaja +Date: Sun Aug 20 01:25:46 2023 +0800 + + fix: add correct screenshot for v3 + +commit b606e5c9e2a01b4ca0e0dd2d7900094e43756299 +Author: Albert Ariel Widiaatmaja +Date: Sun Aug 20 00:26:10 2023 +0800 + + feat: add missing files + +commit 7d36caaa51c0695cdd1dd9013d7b8267ffe0f353 +Merge: 47d071f f2a8179 +Author: Albert Ariel Widiaatmaja +Date: Sun Aug 20 00:24:59 2023 +0800 + + merge: v3 + +commit 47d071fecd9f7b05bbfeba6c7923abb37925cfe0 +Author: Albert Ariel Widiaatmaja +Date: Sun Aug 20 00:21:51 2023 +0800 + + chore: remove old file + +commit f2a8179f244be4fc0d406ed2a7d04f02462e1eb5 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 23:59:18 2023 +0800 + + chore: remove useless files + +commit 84cd6af038601991f0a515c1346da1d205523b0e +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 23:55:10 2023 +0800 + + fix: printed char not printing to screen + +commit 8f3f3060276bdc525f3291dbf831ed4e7bcd0265 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 22:37:12 2023 +0800 + + fix: linker multiple definition error + +commit ec150ddfd21d2784d227a0e7fd5cef2c28ef18a5 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 22:07:21 2023 +0800 + + feat: update makefile + +commit f67420109a692e9e5b749e01141970701a677a17 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 22:06:31 2023 +0800 + + feat: add dummy processes, move screen related functions from main.c to screen.c + +commit 278b8bd72dc47e1e44999b8d536ace0a21305fc6 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 22:02:02 2023 +0800 + + feat: interrupt for process scheduling + +commit 50522bc12359c6f48151c89061dc7e447f2a1998 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 21:21:26 2023 +0800 + + feat: add scheduler and run_next_process to starter.asm + +commit 9adc08718e5d395bbdd6baf1c2e33e978b067d75 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 21:13:41 2023 +0800 + + feat: add process scheduler implementation + +commit 4656a3f1dbda60656b55410e4943b75e5c62f0e6 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 19:34:03 2023 +0800 + + feat: adds abstaction for processes + +commit 4b852836a3d1bffaba0c7a8c30eaa8a56d72f19e +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 15:52:27 2023 +0800 + + feat: separate screen initialization logic + +commit b07140eb137fd9a1b199432691c3958cedf0ce2c +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 15:50:18 2023 +0800 + + feat: add notes on how to implement process management + +commit 3165109ea675205d63916e0cfc47ac5089a4abcf +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 15:43:59 2023 +0800 + + feat: add notes on how to implement process management + +commit 21e81d539c6ea886fc1871f1971f5c06afdd3140 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 00:38:48 2023 +0800 + + feat: separate build and run from makefile, add screenshot for v2 + +commit 3dd54ec631e5bf08bfa3ba8f7117cbd4af4b8174 +Author: Albert Ariel Widiaatmaja +Date: Sat Aug 19 00:26:00 2023 +0800 + + feat: separate makefile processes into smaller parts + +commit fd7e984fd675677884d77bed2c990b68d8b57887 +Merge: 9f8bbe9 9721f24 +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sun Jul 9 19:06:20 2023 +0800 + + Merge pull request #10 from albertarielw/v2 + + V2 + +commit 9721f24fdd2c4e8513b5b169cb8c620203fe999e +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 9 19:05:43 2023 +0800 + + fix: makefile wrong folder for run + +commit 8e1d8d0cf3301483937ca664647faf35073cac2b +Author: albertarielw +Date: Sun Jul 9 19:04:55 2023 +0800 + + feat: tidy up folder, update makefile + +commit 3eb3cd847fad20228cf995e5c050e79b816d110c +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 9 18:54:03 2023 +0800 + + feat: update make file + +commit 3726e3b214a40b199bd90c00cb53fd3eef14b4a1 +Author: albertarielw +Date: Sun Jul 9 15:42:19 2023 +0800 + + test: separate build + +commit ed10fc0116ad2a413ff997aed4d75e38e500b983 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 9 15:40:20 2023 +0800 + + test: compile + +commit b4939a8d24b3a289c7a5c4da0e7df1bad874bea2 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 9 15:39:13 2023 +0800 + + test: separate build into compile link run + +commit 41250207c475a98eda7ab0aa918a8b1837075d6e +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 9 15:31:20 2023 +0800 + + refactor: change string values + +commit 46358ea757fe008476c4b47a9389a611a8192181 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 9 01:32:14 2023 +0800 + + feat: adds screenshot of v2 + +commit 9f8bbe9249662bd5646e2ad75935743293b9a117 +Merge: 922e4ac b6e83ff +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sun Jul 9 01:29:58 2023 +0800 + + Merge pull request #9 from albertarielw/v2 + + V2 + +commit b6e83ff882753e5454ac75bc2cc959456bb92248 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 9 01:29:39 2023 +0800 + + fix: find out build issue, it is due to linker issue on mac, need to do linker on WSL + +commit 7afa4a005ea9125d7cdb529b98111ec6ca28b2c6 +Merge: 148dcd6 922e4ac +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sun Jul 2 15:51:02 2023 +0800 + + Merge pull request #8 from albertarielw/main + + Synch with main + +commit 922e4acea2d36ec2b8db720e788bae763fafca5e +Merge: 7471da3 148dcd6 +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sun Jul 2 15:43:02 2023 +0800 + + Merge pull request #7 from albertarielw/v2 + + V2 + +commit 148dcd6b5a286d48c6412a9604902800f58e8d66 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:51:33 2023 +0800 + + chore: tidy up folder + +commit 8b64bf491cd2fa5e0ba2dc4d2c231bd1b5d89d0c +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:51:00 2023 +0800 + + chore: remove build file + +commit e3a97faeaa613254e4da023f7a456db3f1f8996c +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:50:29 2023 +0800 + + update gitignore + +commit 74d3fef6e7d6879d4243b991a3e53c13249d6ab1 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:41:47 2023 +0800 + + fix: merge start_kernel.asm to starter.asm + +commit c607fb44c3317b82ad241c687cea4891dd4ec777 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:37:50 2023 +0800 + + fix: check main.c + +commit e9e52403be365a8a4041eaab18048c76e1a5bafe +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:35:45 2023 +0800 + + fix: check gdt.asm + +commit 65c15dbccb1ef44f53406354af9c902783d282be +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:34:49 2023 +0800 + + fix: check bootstrap logic + +commit c9b34442267c6e05845d2fdfe4dc42f282217c48 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:28:52 2023 +0800 + + chore: tidy up makefile + +commit 22b21d4e5e52d188201a9c2f24e9bb0f6b53cf46 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 14:26:27 2023 +0800 + + feat: setup interrupt handler + +commit b5d71721c10304dbda785b592efedd87dfe81e24 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 03:16:06 2023 +0800 + + feat: adds basic main_kernel in C which prints text to string + +commit 187d670f033d952a1f791d8e1346c35c83e8b066 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 02:16:50 2023 +0800 + + feat: adds start_kernel to intialize segment registers and call main kernel, include start_kernel and gdt in starter + +commit e3bae2ede2d5fa32392dbe68cf8d8bfd6199913f +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 02:13:05 2023 +0800 + + chore: adds comments for gdt + +commit ad96d5341fdab7f0f6f52c084f8e8f7320a9b36e +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 02:06:06 2023 +0800 + + feat: adds init video mode + +commit b11462ff057d3225f16e05d5375d9b501b8fed33 +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 01:05:16 2023 +0800 + + feat: adds gdt descriptor and routine to enter protected mode + +commit a6bbb423969c1411c9a8f4fda17ac4aa01fb04ac +Author: Albert Ariel Widiaatmaja +Date: Sun Jul 2 00:38:24 2023 +0800 + + feat: adds load_gdt + +commit 9653820e92593d1444e4f6b29e8e7ce8ff2da44f +Author: Albert Ariel Widiaatmaja +Date: Sat Jul 1 21:10:00 2023 +0800 + + feat: update bootstrap to load >1 sector from the disk to memory + +commit 79aa6194efa87964d3ebea276432b306f48c0b4b +Author: Albert Ariel Widiaatmaja +Date: Sat Jul 1 20:43:35 2023 +0800 + + feat: update makefile + +commit ab0a08d3d4e3771970175d238ee8c3f12b1f1a50 +Author: Albert Ariel Widiaatmaja +Date: Sat Jul 1 20:34:15 2023 +0800 + + feat: updates makefile and adds linker file + +commit c75fc70400d51009cced1d15c1a65d41ff8a31b7 +Author: Albert Ariel Widiaatmaja +Date: Sat Jul 1 19:48:29 2023 +0800 + + feat: adds note about intro to progenitor os + +commit 7471da301439f0a2eeb24ee6114251d3e5e618bf +Merge: 8d7bca7 1fa3b34 +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sat Jul 1 12:55:48 2023 +0800 + + Merge pull request #6 from albertarielw/v2 + + V2 + +commit 8d7bca76f1a6fe2437df27f6cd9a2deb3e19e248 +Merge: c072de5 5cb3f13 +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sat Jul 1 12:54:57 2023 +0800 + + Merge pull request #5 from albertarielw/revert-4-v2 + + Revert "V2.1" + +commit 5cb3f13f9744ed6657171256ef3cbeb82401a76c +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sat Jul 1 12:54:45 2023 +0800 + + Revert "V2.1 (#4)" + + This reverts commit c072de50f3afe779d439a172d938dcb32493a0ff. + +commit c072de50f3afe779d439a172d938dcb32493a0ff +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sat Jul 1 12:54:13 2023 +0800 + + V2.1 (#4) + + * feat: adds notes until page 54 + + * feat: adds notes until x86 segmentation + + * feat: adds notes about run-time stack and interrupts + + * feat: adds more content to x86 run time stack and interrupt, finish summary of x86 architecture + + --------- + + Co-authored-by: Albert Ariel Widiaatmaja + +commit 1fa3b34c1f3a98c3670c3b0f44f810b1204e3a5f +Author: Albert Ariel Widiaatmaja +Date: Sat Jul 1 12:52:47 2023 +0800 + + feat: adds more content to x86 run time stack and interrupt, finish summary of x86 architecture + +commit bf4674a7ec906d45df27d2f82a8b11a029dae2b3 +Author: Albert Ariel Widiaatmaja +Date: Sat Jul 1 01:51:15 2023 +0800 + + feat: adds notes about run-time stack and interrupts + +commit 9a4d101282bb1d2f92b6ee7a029069554afab3e7 +Author: Albert Ariel Widiaatmaja +Date: Fri Jun 30 01:50:11 2023 +0800 + + feat: adds notes until x86 segmentation + +commit 504e58eb9fd725be07f4732c711b5495c4a06d8d +Author: Albert Ariel Widiaatmaja +Date: Fri Jun 30 01:13:13 2023 +0800 + + feat: adds notes until page 54 + +commit 1001dd4667167f1b3953b4c8b998f3fa91c6a032 +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sun Jun 25 22:57:02 2023 +0800 + + feat: added learning notes related to v1 (#3) + + Co-authored-by: Albert Ariel Widiaatmaja + +commit d3bde8cecdb8c35a0f00874a4d97009252ba6689 +Merge: 984352e 0e43e6c +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sun Jun 25 11:31:39 2023 +0800 + + Merge pull request #1 from albertarielw/v1 + + V1 + +commit 0e43e6caa0d2f455b6455dc0a95cfe5281c01ad3 +Author: Albert Ariel Widiaatmaja +Date: Sun Jun 25 11:30:27 2023 +0800 + + update: change makefile to clean files in build directory instead of current directory + +commit b91b4e77b2dbd547a0fd2f18dee5218b26cb17ff +Author: Albert Ariel Widiaatmaja +Date: Sun Jun 25 11:25:16 2023 +0800 + + enhancement: update gitignore to ignore build folder and everything in it including subdirectories + +commit 842c47954540deeaa358f94c91dd573eee969aa8 +Author: Albert Ariel Widiaatmaja +Date: Sun Jun 25 11:22:28 2023 +0800 + + feat: adds gitignore to ignore build files + +commit d21d70666691c2b81179d3fdfec437729b05eafa +Author: Albert Ariel Widiaatmaja +Date: Sun Jun 25 11:21:25 2023 +0800 + + chore: remove build up from repo + +commit a681eed83c6d885bf9d4afed4210bab240a6142e +Author: Albert Ariel Widiaatmaja +Date: Sun Jun 25 11:20:42 2023 +0800 + + enhancement: tody up make file to separate src and build + +commit 67cef3a1046c54127c3179310239353b37316c63 +Author: Albert Ariel Widiaatmaja +Date: Sat Jun 24 22:07:51 2023 +0800 + + feat: basic os which says hello world + +commit 984352e4d83c8f6994f36326482993ecbe5d8ba6 +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Sat Jun 24 18:12:04 2023 +0800 + + Update README.md + +commit 0f6d74fe39474c8fab489520171fe8731c59cae2 +Author: Albert Ariel W <101498658+albertarielw@users.noreply.github.com> +Date: Fri Jun 23 19:03:13 2023 +0800 + + Initial commit diff --git a/sample_build/heap.elf b/sample_build/heap.elf new file mode 100644 index 0000000..77ec09e Binary files /dev/null and b/sample_build/heap.elf differ diff --git a/sample_build/kernel.elf b/sample_build/kernel.elf new file mode 100644 index 0000000..2770f50 Binary files /dev/null and b/sample_build/kernel.elf differ diff --git a/kernel.img b/sample_build/kernel.img similarity index 99% rename from kernel.img rename to sample_build/kernel.img index 53ef06d..075b4d7 100644 Binary files a/kernel.img and b/sample_build/kernel.img differ diff --git a/sample_build/kernel.img.zip b/sample_build/kernel.img.zip new file mode 100644 index 0000000..6c8c96d Binary files /dev/null and b/sample_build/kernel.img.zip differ diff --git a/linker.ld b/sample_build/linker.ld similarity index 100% rename from linker.ld rename to sample_build/linker.ld diff --git a/minios.bin b/sample_build/minios.bin old mode 100755 new mode 100644 similarity index 100% rename from minios.bin rename to sample_build/minios.bin diff --git a/minios.elf b/sample_build/minios.elf old mode 100755 new mode 100644 similarity index 100% rename from minios.elf rename to sample_build/minios.elf diff --git a/sample_build/minos.bin b/sample_build/minos.bin new file mode 100755 index 0000000..4b387ab Binary files /dev/null and b/sample_build/minos.bin differ diff --git a/sample_build/minos.elf b/sample_build/minos.elf new file mode 100755 index 0000000..0b186ea Binary files /dev/null and b/sample_build/minos.elf differ diff --git a/sample_build/paging.elf b/sample_build/paging.elf new file mode 100644 index 0000000..f6df2d7 Binary files /dev/null and b/sample_build/paging.elf differ diff --git a/sample_build/process.elf b/sample_build/process.elf new file mode 100644 index 0000000..6d7ee4f Binary files /dev/null and b/sample_build/process.elf differ diff --git a/sample_build/scheduler.elf b/sample_build/scheduler.elf new file mode 100644 index 0000000..c72895c Binary files /dev/null and b/sample_build/scheduler.elf differ diff --git a/screen.elf b/sample_build/screen.elf similarity index 74% rename from screen.elf rename to sample_build/screen.elf index 930d574..f522fa9 100644 Binary files a/screen.elf and b/sample_build/screen.elf differ diff --git a/sample_build/starter.o b/sample_build/starter.o new file mode 100644 index 0000000..f11e2d4 Binary files /dev/null and b/sample_build/starter.o differ diff --git a/scheduler.elf b/scheduler.elf deleted file mode 100644 index a8192cc..0000000 Binary files a/scheduler.elf and /dev/null differ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..9148636 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,26 @@ +ASM = nasm +CC = gcc +BOOTSTRAP_FILE = bootstrap.asm +SIMPLE_KERNEL = simple_kernel.asm +INIT_KERNEL_FILES = starter.asm +KERNEL_FILES = main.c +KERNEL_FLAGS = -Wall -m32 -c -ffreestanding -fno-asynchronous-unwind-tables -fno-pie +KERNEL_OBJECT = -o kernel.elf + +build: $(BOOTSTRAP_FILE) $(KERNEL_FILE) + $(ASM) -f bin $(BOOTSTRAP_FILE) -o bootstrap.o + $(ASM) -f elf32 $(INIT_KERNEL_FILES) -o starter.o + $(CC) $(KERNEL_FLAGS) $(KERNEL_FILES) $(KERNEL_OBJECT) + $(CC) $(KERNEL_FLAGS) screen.c -o screen.elf + $(CC) $(KERNEL_FLAGS) process.c -o process.elf + $(CC) $(KERNEL_FLAGS) scheduler.c -o scheduler.elf + $(CC) $(KERNEL_FLAGS) heap.c -o heap.elf + $(CC) $(KERNEL_FLAGS) paging.c -o paging.elf + ld -melf_i386 -Tlinker.ld starter.o kernel.elf screen.elf process.elf scheduler.elf heap.elf paging.elf -o minos.elf + objcopy -O binary minos.elf minos.bin + dd if=bootstrap.o of=kernel.img + dd seek=1 conv=sync if=minos.bin of=kernel.img bs=512 count=8 + dd seek=9 conv=sync if=/dev/zero of=kernel.img bs=512 count=2046 + +run: + qemu-system-x86_64 -s kernel.img \ No newline at end of file diff --git a/src/bootstrap.asm b/src/bootstrap.asm new file mode 100644 index 0000000..66ceb45 --- /dev/null +++ b/src/bootstrap.asm @@ -0,0 +1,138 @@ +; start indicates starting point of the execution +start: + + ; we want to move 07C0h to ds (why? it will be explained in later segment) + ; we cannot mov ds, 0x08C0 directly because ds (segment register) cannot be loaded with value directly in x86 + ; further details: https://stackoverflow.com/questions/19074666/8086-why-cant-we-move-an-immediate-data-into-segment-register + mov ax, 07C0h + mov ds, ax + + + ; define si to be title_string or message_string + ; call print_string which prints to screen the values saved in si + mov si, title_string + call print_string ; "CALL" is used instead of "JMP" because we would like to return to the next instruction after "print_string" finishes. + + mov si, message_string + call print_string + + + call load_kernel_from_disk + + ; gives control to kernel by jumping to the start of the kernel + ; 0900h is the same value we have loaded in the register es in the beginning of load_kernel_from_disk + ; 0000 is the offset we have specified in the register bx in load_kernel_from_disk before calling 02h:13h + jmp 0900h:0000 + +; BIOS service 13h:02h loads the required sector into the memory address es:bx +; So, the value 0900h which has been set to es in the code above will be the starting memory address of the kernel +; Previously, it was enough to set bx = 0 since we only load 1 sector -> the code will reside from offset 0 to 511 +; Now we are loading > 1 sector so we need to increment bx +load_kernel_from_disk: + ; increment bx by 1 sector to load the next sector + mov ax, [curr_sector_to_load] + sub ax, 2 + mov bx, 512d + mul bx + mov bx, ax + + mov ax, 0900h + mov es, ax + + ; service number 02h is specified to register ah + ; it reads sectors from the hard disk and loads them into the memory + mov ah, 02h + + ; 01h is the number of sector we ants to read (since simple_kernel.asm is < 512 bytes, 1 sector is enough) + mov al, 1h + + ; 0h is the track number we would like to read (track 0) + mov ch, 0h + + ; 02h is the sector number we would like to read (sector 2) + mov cl, [curr_sector_to_load] + + ; 0h is the head number (of the disk) + ; specifies the type of disk + ; 0h means floppy disk, 80h means hard disk #0, 81h means hard disk #1, etc. + ; the value of bx is the memory address that the content will be loaded into + ; we are reading one sector and the content will be stored on memory address 0h + mov dh, 0h + mov dl, 80h ; Drive to read from. (0 = Floppy. 80h = Drive #0. 81h = Drive #1) + int 13h ; BIOS Disk Services + + ; when the content is loaded successfully, BIOS service 13h:02h set carry flag to 0, otherwise 1 and stores error code in ax + ; if cf is 1 jc will jump + jc kernel_load_error + + ; increment curr_sector_to_load, decrement number_of_sectors_to_load + sub byte [number_of_sectors_to_load], 1 + add byte [curr_sector_to_load], 1 + cmp byte [number_of_sectors_to_load], 0 + + jne load_kernel_from_disk + + ret + +; When the bootloader fails to load the kernel. A nice message is printted for the user. +kernel_load_error: + mov si, load_error_string + call print_string + + ; "$" is a special expression in NASM. It means the starting memory address (or assembly position?) of current instruction, that means + ; the following instruction is going to loop forever. + jmp $ + +; ... ; +; ... ; + +; BIOS provides video services through intrrupt 10h. The value of the register "ah" decides which video service that we are requesting from BIOS. +; Those BIOS services are only available on Real Mode (https://stackoverflow.com/questions/26448480/bios-interrupts-in-protected-mode) +; +; ah = 0Eh means that we wish to print a character in TTY mode. +; For an example of using service "0Eh" to print "Hello" character by character, please refer to "../examples/bootstrap/1/". + +print_string: + ; specify function for printing character + mov ah, 0Eh + +print_char: + ; char to print is passed via si + ; lodsb will transfer first character of the string to the register al and increase value of si by 1 byte + lodsb + + cmp al, 0 + je printing_finished + + int 10h + + jmp print_char + +printing_finished: + mov al, 10d ; print new line 10d = ENDL + int 10h + + ; reading current cursor position + mov ah, 03h ; specify service for reading current position of cursor + mov bh, 0 + int 10h + + ; move the cursor to the beginning + mov ah, 02h ; specify service for setting cursor to position 0 + mov dl, 0 ; position to be set is passed to dl + int 10h + + ; print_string is a procedure (or function), therefore we should return. It is called by using "CALL" instead of "JMP". + ret + +title_string db 'The Bootloader of 539kernel.', 0 +message_string db 'The kernel is loading...', 0 +load_error_string db 'The kernel cannot be loaded', 0 +number_of_sectors_to_load db 10d ; 255 sectors = 127.5KB ; [MQH] NEW 4 July 2021 +curr_sector_to_load db 2d + +; write the magic signature 0xAA55 +times 510-($-$$) db 0 + +; pad with 0 so magic signature is at loc 510-511 (0-based) +dw 0xAA55 diff --git a/gdt.asm b/src/gdt.asm similarity index 75% rename from gdt.asm rename to src/gdt.asm index 4d6ee63..e9fbf0b 100644 --- a/gdt.asm +++ b/src/gdt.asm @@ -1,15 +1,22 @@ ; The values of the decriptors from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel) gdt: + + ; in x86, first entry is null descriptor null_descriptor : dw 0, 0, 0, 0 + + ; code and data segment of kernel kernel_code_descriptor : dw 0xffff, 0x0000, 9a00h, 0x00cf kernel_data_descriptor : dw 0xffff, 0x0000, 0x9200, 0x00cf + + ; code and data segment of user application userspace_code_descriptor : dw 0xffff, 0x0000, 0xfa00, 0x00cf userspace_data_descriptor : dw 0xffff, 0x0000, 0xf200, 0x00cf + ; DON'T FORGET TO CHANGE THE SIZE OF THE GDT - ; TODO: I think the limit isn't correct tss_descriptor : dw tss + 3, tss, 0x8900, 0x0000 gdtr: + ; size: 6 entries, each 8 byte gdt_size_in_bytes : dw ( 6 * 8 ) ;= 28h gdt_base_address : dd gdt diff --git a/src/heap.c b/src/heap.c new file mode 100644 index 0000000..21f55dc --- /dev/null +++ b/src/heap.c @@ -0,0 +1,19 @@ +#include "heap.h" + +unsigned int heap_base; + +void heap_init() +{ + heap_base = 0x100000; +} + +// memory allocator, similar to malloc +// currently very simple but cannot free memory -> we need a way to know how to free memory +int kalloc(int bytes) +{ + unsigned int new_object_address = heap_base; + + heap_base += bytes; + + return new_object_address; +} \ No newline at end of file diff --git a/src/heap.h b/src/heap.h new file mode 100644 index 0000000..3531fd7 --- /dev/null +++ b/src/heap.h @@ -0,0 +1,5 @@ +// base of heap from which we will allocate some memory for functions +extern unsigned int heap_base; + +void heap_init(); +int kalloc( int ); \ No newline at end of file diff --git a/idt.asm b/src/idt.asm similarity index 93% rename from idt.asm rename to src/idt.asm index 5ad1b16..063d2cc 100644 --- a/idt.asm +++ b/src/idt.asm @@ -1,376 +1,379 @@ -isr_0: - cli - push 0 - jmp isr_basic - -isr_1: - cli - push 1 - jmp isr_basic - -isr_2: - cli - push 2 - jmp isr_basic - -isr_3: - cli - push 3 - jmp isr_basic - -isr_4: - cli - push 4 - jmp isr_basic - -isr_5: - cli - push 5 - jmp isr_basic - -isr_6: - cli - push 6 - jmp isr_basic - -isr_7: - cli - push 7 - jmp isr_basic - -isr_8: - cli - push 8 - jmp isr_basic - -isr_9: - cli - push 9 - jmp isr_basic - -isr_10: - cli - push 10 - jmp isr_basic - -isr_11: - cli - push 11 - jmp isr_basic - -isr_12: - cli - push 12 - jmp isr_basic - -isr_13: - cli - push 13 - jmp isr_basic - -isr_14: - cli - push 14 - jmp isr_basic - -isr_15: - cli - push 15 - jmp isr_basic - -isr_16: - cli - push 16 - jmp isr_basic - -isr_17: - cli - push 17 - jmp isr_basic - -isr_18: - cli - push 18 - jmp isr_basic - -isr_19: - cli - push 19 - jmp isr_basic - -isr_20: - cli - push 20 - jmp isr_basic - -isr_21: - cli - push 21 - jmp isr_basic - -isr_22: - cli - push 22 - jmp isr_basic - -isr_23: - cli - push 23 - jmp isr_basic - -isr_24: - cli - push 24 - jmp isr_basic - -isr_25: - cli - push 25 - jmp isr_basic - -isr_26: - cli - push 26 - jmp isr_basic - -isr_27: - cli - push 27 - jmp isr_basic - -isr_28: - cli - push 28 - jmp isr_basic - -isr_29: - cli - push 29 - jmp isr_basic - -isr_30: - cli - push 30 - jmp isr_basic - -isr_31: - cli - push 31 - jmp isr_basic - -; System Timer -isr_32: - ; part 1 - - cli ; step 1 disable interrupt (when handling interrupt, btetter to not receive any other interrupt) - - ; step 2 and 3 - ; when this interrupt handler is called, context of the processor is the context of suspended process - ; we define ISRs gate descriptors as interrupt gates in IDT - ; -> if we define as task gates, the context of the suspended gates in the IDT table will not be available directly on processor's registers - - ; since context is reachable, we store in the stack (useful when scheduler needs to copy the context of the suspended process to the memory) - ; push into the stack also provides 2 benefits - ; 1. we can use register in current code as we wont lose the suspended process context - ; 2. method of passing parameters - - pusha ; step 2 pusha pushes values of all general registers in the order: EAX, ECX, EDX, EBX, ESP, EBP, ESI and EDI - - - ; step 3 to push EIP - - ; Curr EIP is a pointer to curr instruction, not the one we want to suspend - - ; Suppose A is running - ; We want to suspend A, so ISR32 is called - ; Return address to where A suspended is stored at the top of the stack (based on calling convention) - ; Then we run ISR32 - ; At this point, ISR32 has put 8 registers to the stack (because of pusha) - ; ESP points to top of stack, to find return address of A (EIP of A) simply use esp + 32 - mov eax, [esp + 32] - push eax - - call scheduler ; step 4 - - ; ... ; - - ; part 2 - - ; step 5 - - ; after scheduler, tell PIC we finish handling IRQ by send end of interrupt command to PIC - mov al, 0x20 - out 0x20, al - - ; step 6 - - ; jump to memory address in which the selected process were suspended - ; exploit calling convention again - - ; remove all values added to stack by adding 40 (8 general register + EIP + 4 to get to the start of return address added) - add esp, 40d - push run_next_process - - iret ; step 7 - -isr_33: - cli - push 33 - jmp irq_basic - -isr_34: - cli - push 34 - jmp irq_basic - -isr_35: - cli - push 35 - jmp irq_basic - -isr_36: - cli - push 36 - jmp irq_basic - -isr_37: - cli - push 37 - jmp irq_basic - -isr_38: - cli - push 38 - jmp irq_basic - -isr_39: - cli - push 39 - jmp irq_basic - -isr_40: - cli - push 40 - jmp irq_basic - -isr_41: - cli - push 41 - jmp irq_basic - -isr_42: - cli - push 42 - jmp irq_basic - -isr_43: - cli - push 43 - jmp irq_basic - -isr_44: - cli - push 44 - jmp irq_basic - -isr_45: - cli - push 45 - jmp irq_basic - -isr_46: - cli - push 46 - jmp irq_basic - -isr_47: - cli - push 47 - jmp irq_basic - -isr_48: - cli - push 48 - jmp irq_basic - -isr_basic: -; cli - call interrupt_handler - - pop eax - sti - iret - -irq_basic: -; cli - call interrupt_handler - - mov al, 0x20 - out 0x20, al - - cmp byte [esp], 40d ; Interrupt number - jnge irq_basic_end - - mov al, 0xa0 - out 0x20, al - - irq_basic_end: - pop eax - sti - iret - -; The value of the flags from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel) -idt: - dw isr_0, 8, 0x8e00, 0x0000 - dw isr_1, 8, 0x8e00, 0x0000 - dw isr_2, 8, 0x8e00, 0x0000 - dw isr_3, 8, 0x8e00, 0x0000 - dw isr_4, 8, 0x8e00, 0x0000 - dw isr_5, 8, 0x8e00, 0x0000 - dw isr_6, 8, 0x8e00, 0x0000 - dw isr_7, 8, 0x8e00, 0x0000 - dw isr_8, 8, 0x8e00, 0x0000 - dw isr_9, 8, 0x8e00, 0x0000 - dw isr_10, 8, 0x8e00, 0x0000 - dw isr_11, 8, 0x8e00, 0x0000 - dw isr_12, 8, 0x8e00, 0x0000 - dw isr_13, 8, 0x8e00, 0x0000 - dw isr_14, 8, 0x8e00, 0x0000 - dw isr_15, 8, 0x8e00, 0x0000 - dw isr_16, 8, 0x8e00, 0x0000 - dw isr_17, 8, 0x8e00, 0x0000 - dw isr_18, 8, 0x8e00, 0x0000 - dw isr_19, 8, 0x8e00, 0x0000 - dw isr_20, 8, 0x8e00, 0x0000 - dw isr_21, 8, 0x8e00, 0x0000 - dw isr_22, 8, 0x8e00, 0x0000 - dw isr_23, 8, 0x8e00, 0x0000 - dw isr_24, 8, 0x8e00, 0x0000 - dw isr_25, 8, 0x8e00, 0x0000 - dw isr_26, 8, 0x8e00, 0x0000 - dw isr_27, 8, 0x8e00, 0x0000 - dw isr_28, 8, 0x8e00, 0x0000 - dw isr_29, 8, 0x8e00, 0x0000 - dw isr_30, 8, 0x8e00, 0x0000 - dw isr_31, 8, 0x8e00, 0x0000 - dw isr_32, 8, 0x8e00, 0x0000 - dw isr_33, 8, 0x8e00, 0x0000 - dw isr_34, 8, 0x8e00, 0x0000 - dw isr_35, 8, 0x8e00, 0x0000 - dw isr_36, 8, 0x8e00, 0x0000 - dw isr_37, 8, 0x8e00, 0x0000 - dw isr_38, 8, 0x8e00, 0x0000 - dw isr_39, 8, 0x8e00, 0x0000 - dw isr_40, 8, 0x8e00, 0x0000 - dw isr_41, 8, 0x8e00, 0x0000 - dw isr_42, 8, 0x8e00, 0x0000 - dw isr_43, 8, 0x8e00, 0x0000 - dw isr_44, 8, 0x8e00, 0x0000 - dw isr_45, 8, 0x8e00, 0x0000 - dw isr_46, 8, 0x8e00, 0x0000 - dw isr_47, 8, 0x8e00, 0x0000 - dw isr_48, 8, 0x8e00, 0x0000 - -idtr: - idt_size_in_bytes : dw idtr - idt - idt_base_address : dd idt +isr_0: + cli + ; push number of current interrupt into the stack + push 0 + jmp isr_basic + +isr_1: + cli + push 1 + jmp isr_basic + +isr_2: + cli + push 2 + jmp isr_basic + +isr_3: + cli + push 3 + jmp isr_basic + +isr_4: + cli + push 4 + jmp isr_basic + +isr_5: + cli + push 5 + jmp isr_basic + +isr_6: + cli + push 6 + jmp isr_basic + +isr_7: + cli + push 7 + jmp isr_basic + +isr_8: + cli + push 8 + jmp isr_basic + +isr_9: + cli + push 9 + jmp isr_basic + +isr_10: + cli + push 10 + jmp isr_basic + +isr_11: + cli + push 11 + jmp isr_basic + +isr_12: + cli + push 12 + jmp isr_basic + +isr_13: + cli + push 13 + jmp isr_basic + +isr_14: + cli + push 14 + jmp isr_basic + +isr_15: + cli + push 15 + jmp isr_basic + +isr_16: + cli + push 16 + jmp isr_basic + +isr_17: + cli + push 17 + jmp isr_basic + +isr_18: + cli + push 18 + jmp isr_basic + +isr_19: + cli + push 19 + jmp isr_basic + +isr_20: + cli + push 20 + jmp isr_basic + +isr_21: + cli + push 21 + jmp isr_basic + +isr_22: + cli + push 22 + jmp isr_basic + +isr_23: + cli + push 23 + jmp isr_basic + +isr_24: + cli + push 24 + jmp isr_basic + +isr_25: + cli + push 25 + jmp isr_basic + +isr_26: + cli + push 26 + jmp isr_basic + +isr_27: + cli + push 27 + jmp isr_basic + +isr_28: + cli + push 28 + jmp isr_basic + +isr_29: + cli + push 29 + jmp isr_basic + +isr_30: + cli + push 30 + jmp isr_basic + +isr_31: + cli + push 31 + jmp isr_basic + +; System Timer +isr_32: + ; part 1 + + cli ; step 1 disable interrupt (when handling interrupt, btetter to not receive any other interrupt) + + ; step 2 and 3 + ; when this interrupt handler is called, context of the processor is the context of suspended process + ; we define ISRs gate descriptors as interrupt gates in IDT + ; -> if we define as task gates, the context of the suspended gates in the IDT table will not be available directly on processor's registers + + ; since context is reachable, we store in the stack (useful when scheduler needs to copy the context of the suspended process to the memory) + ; push into the stack also provides 2 benefits + ; 1. we can use register in current code as we wont lose the suspended process context + ; 2. method of passing parameters + + pusha ; step 2 pusha pushes values of all general registers in the order: EAX, ECX, EDX, EBX, ESP, EBP, ESI and EDI + + + ; step 3 to push EIP + + ; Curr EIP is a pointer to curr instruction, not the one we want to suspend + + ; Suppose A is running + ; We want to suspend A, so ISR32 is called + ; Return address to where A suspended is stored at the top of the stack (based on calling convention) + ; Then we run ISR32 + ; At this point, ISR32 has put 8 registers to the stack (because of pusha) + ; ESP points to top of stack, to find return address of A (EIP of A) simply use esp + 32 + mov eax, [esp + 32] + push eax + + call scheduler ; step 4 + + ; ... ; + + ; part 2 + + ; step 5 + + ; after scheduler, tell PIC we finish handling IRQ by send end of interrupt command to PIC + mov al, 0x20 + out 0x20, al + + ; step 6 + + ; jump to memory address in which the selected process were suspended + ; exploit calling convention again + + ; remove all values added to stack by adding 40 (8 general register + EIP + 4 to get to the start of return address added) + add esp, 40d + push run_next_process + + iret ; step 7 + +isr_33: + cli + push 33 + jmp irq_basic + +isr_34: + cli + push 34 + jmp irq_basic + +isr_35: + cli + push 35 + jmp irq_basic + +isr_36: + cli + push 36 + jmp irq_basic + +isr_37: + cli + push 37 + jmp irq_basic + +isr_38: + cli + push 38 + jmp irq_basic + +isr_39: + cli + push 39 + jmp irq_basic + +isr_40: + cli + push 40 + jmp irq_basic + +isr_41: + cli + push 41 + jmp irq_basic + +isr_42: + cli + push 42 + jmp irq_basic + +isr_43: + cli + push 43 + jmp irq_basic + +isr_44: + cli + push 44 + jmp irq_basic + +isr_45: + cli + push 45 + jmp irq_basic + +isr_46: + cli + push 46 + jmp irq_basic + +isr_47: + cli + push 47 + jmp irq_basic + +isr_48: + cli + push 48 + jmp irq_basic + +isr_basic: + ; call C function interrput_handler + call interrupt_handler + + ; clean stack frame: pop stack frame and save popped value in eax (chosen arbitrarily) + pop eax + sti + iret + +irq_basic: +; cli + call interrupt_handler + + mov al, 0x20 + out 0x20, al + + cmp byte [esp], 40d ; Interrupt number + jnge irq_basic_end + + mov al, 0xa0 + out 0x20, al + + irq_basic_end: + pop eax + sti + iret + +; The value of the flags from Basekernel (kernelcode.S) (https://github.com/dthain/basekernel) +idt: + ; handler_name, segment_selector, present, privilege_level, descriptor_size, gate_type (in this case interrupt) + dw isr_0, 8, 0x8e00, 0x0000 + dw isr_1, 8, 0x8e00, 0x0000 + dw isr_2, 8, 0x8e00, 0x0000 + dw isr_3, 8, 0x8e00, 0x0000 + dw isr_4, 8, 0x8e00, 0x0000 + dw isr_5, 8, 0x8e00, 0x0000 + dw isr_6, 8, 0x8e00, 0x0000 + dw isr_7, 8, 0x8e00, 0x0000 + dw isr_8, 8, 0x8e00, 0x0000 + dw isr_9, 8, 0x8e00, 0x0000 + dw isr_10, 8, 0x8e00, 0x0000 + dw isr_11, 8, 0x8e00, 0x0000 + dw isr_12, 8, 0x8e00, 0x0000 + dw isr_13, 8, 0x8e00, 0x0000 + dw isr_14, 8, 0x8e00, 0x0000 + dw isr_15, 8, 0x8e00, 0x0000 + dw isr_16, 8, 0x8e00, 0x0000 + dw isr_17, 8, 0x8e00, 0x0000 + dw isr_18, 8, 0x8e00, 0x0000 + dw isr_19, 8, 0x8e00, 0x0000 + dw isr_20, 8, 0x8e00, 0x0000 + dw isr_21, 8, 0x8e00, 0x0000 + dw isr_22, 8, 0x8e00, 0x0000 + dw isr_23, 8, 0x8e00, 0x0000 + dw isr_24, 8, 0x8e00, 0x0000 + dw isr_25, 8, 0x8e00, 0x0000 + dw isr_26, 8, 0x8e00, 0x0000 + dw isr_27, 8, 0x8e00, 0x0000 + dw isr_28, 8, 0x8e00, 0x0000 + dw isr_29, 8, 0x8e00, 0x0000 + dw isr_30, 8, 0x8e00, 0x0000 + dw isr_31, 8, 0x8e00, 0x0000 + dw isr_32, 8, 0x8e00, 0x0000 + dw isr_33, 8, 0x8e00, 0x0000 + dw isr_34, 8, 0x8e00, 0x0000 + dw isr_35, 8, 0x8e00, 0x0000 + dw isr_36, 8, 0x8e00, 0x0000 + dw isr_37, 8, 0x8e00, 0x0000 + dw isr_38, 8, 0x8e00, 0x0000 + dw isr_39, 8, 0x8e00, 0x0000 + dw isr_40, 8, 0x8e00, 0x0000 + dw isr_41, 8, 0x8e00, 0x0000 + dw isr_42, 8, 0x8e00, 0x0000 + dw isr_43, 8, 0x8e00, 0x0000 + dw isr_44, 8, 0x8e00, 0x0000 + dw isr_45, 8, 0x8e00, 0x0000 + dw isr_46, 8, 0x8e00, 0x0000 + dw isr_47, 8, 0x8e00, 0x0000 + dw isr_48, 8, 0x8e00, 0x0000 + +idtr: + idt_size_in_bytes : dw idtr - idt + idt_base_address : dd idt diff --git a/main.c b/src/main.c similarity index 88% rename from main.c rename to src/main.c index b424644..50487f1 100644 --- a/main.c +++ b/src/main.c @@ -1,5 +1,8 @@ +#include "heap.h" +#include "paging.h" #include "screen.h" #include "scheduler.h" + /* There are two VGA modes: text and grapics To show on screen, entities (pixel or char) should be loaded to video memory (a part of main memory) @@ -16,14 +19,12 @@ void kernel_main() { process_t p1, p2, p3, p4; - // ... // - + heap_init(); + paging_init(); screen_init(); process_init(); scheduler_init(); - // ... // - // video[0] = 'A'; // video[2] = 'B' why not video[1]? this is because the byte after char contains color information // Each memory location corresponds to Cartesian coordinate [k * 2] = (k % max_x, k / max_x) e.g. [0] = (0, 0), [2] = (1, 0) @@ -32,12 +33,10 @@ void kernel_main() print( "We are now in Protected-mode" ); println(); - // ... // - - process_create( &processA, &p1 ); - process_create( &processB, &p2 ); - process_create( &processC, &p3 ); - process_create( &processD, &p4 ); + process_create( &processA ); + process_create( &processB ); + process_create( &processC ); + process_create( &processD ); asm( "sti" ); diff --git a/src/paging.c b/src/paging.c new file mode 100644 index 0000000..24164d5 --- /dev/null +++ b/src/paging.c @@ -0,0 +1,50 @@ +#include "paging.h" +unsigned int *page_directory; +int create_page_entry( int base_address, char present, char writable, char privilege_level, char cache_enabled, char +write_through_cache, char accessed, char page_size, char dirty ) +{ + // each parameter is a field in PTE + // other than base address, they values are binary (0 or 1) + // + + int entry = 0; + + entry |= present; + entry |= writable << 1; + entry |= privilege_level << 2; + entry |= write_through_cache << 3; + entry |= cache_enabled << 4; + entry |= accessed << 5; + entry |= dirty << 6; + entry |= page_size << 7; + + return base_address | entry; +} + +void paging_init() +{ + // PART 1 + + // First we allocate 4 * 1024 from the kernel's heap for the page directory + // that's because the size of each entry is 4 bytes + // note: while we need 3 entries, we are allocating 1024 + // -> because base memory address of a page table and page frame both should be page-aligned + + unsigned int curr_page_frame = 0; + page_directory = kalloc(4 * 1024); + + for (int currPDE = 0; currPDE < PDE_NUM; currPDE++) { + unsigned int *pagetable = kalloc(4 * PTE_NUM); + + for (int currPTE = 0; currPTE < PTE_NUM; currPTE++, curr_page_frame++) { + pagetable[currPTE] = create_page_entry(curr_page_frame * 4096, 1, 0, 0, 1, 1, 0, 0, 0); + + page_directory[currPDE] = create_page_entry(pagetable, 1, 0, 0, 1, 1, 0, 0, 0); + } + } + + // PART 2 + + load_page_directory(); + enable_paging(); +} \ No newline at end of file diff --git a/src/paging.h b/src/paging.h new file mode 100644 index 0000000..50963c8 --- /dev/null +++ b/src/paging.h @@ -0,0 +1,15 @@ +#ifndef PAGING_H +#define PAGING_H + +#define PDE_NUM 3 // page directory entry +#define PTE_NUM 1024 // each page holds 1024 entry + +extern void load_page_directory(); +extern void enable_paging(); + +extern unsigned int *page_directory; + +void paging_init(); +int create_page_entry( int, char, char, char, char, char, char, char, char ); + +#endif // PAGING_H \ No newline at end of file diff --git a/process.c b/src/process.c similarity index 89% rename from process.c rename to src/process.c index 1ffef3f..f1bf59c 100644 --- a/process.c +++ b/src/process.c @@ -9,8 +9,9 @@ void process_init() curr_pid = 0; } -void process_create( int *base_address, process_t *process ) +process_t *process_create( int *base_address) { + process_t *process = kalloc(sizeof(process_t)); // new id is assigned to new process process->pid = curr_pid++; // initialize context diff --git a/process.h b/src/process.h similarity index 92% rename from process.h rename to src/process.h index 69bf6bf..4600792 100644 --- a/process.h +++ b/src/process.h @@ -37,4 +37,4 @@ extern int processes_count; // number of process -> for modulo in round robin extern int curr_pid; void process_init(); -void process_create( int *, process_t * ); // params: pointer to base address of process, pointer to PCB \ No newline at end of file +process_t *process_create( int * ); // params: pointer to base address of process, pointer to PCB \ No newline at end of file diff --git a/scheduler.c b/src/scheduler.c similarity index 100% rename from scheduler.c rename to src/scheduler.c diff --git a/scheduler.h b/src/scheduler.h similarity index 100% rename from scheduler.h rename to src/scheduler.h diff --git a/screen.c b/src/screen.c similarity index 100% rename from screen.c rename to src/screen.c diff --git a/screen.h b/src/screen.h similarity index 100% rename from screen.h rename to src/screen.h diff --git a/starter.asm b/src/starter.asm similarity index 65% rename from starter.asm rename to src/starter.asm index 04ffeef..a011c67 100644 --- a/starter.asm +++ b/src/starter.asm @@ -1,148 +1,172 @@ -; runs in 16 bits -; to prepare proper environment for main kernel by: -; - init and load GDT -; - set interrupts -; - set video mode -; - change 16 bit real mode to 32 bit protected mode - -; tell NASM to generate 16 bit code since we will be using 16 bit real mode -; in the bootloader don't need to do this because: for flat binary the default is 16 bit but we use ELF32 -bits 16 -; extern tells NASM that there is a function/ variable define outside this code, it will be figured out by the linker - -extern kernel_main -extern interrupt_handler -extern scheduler -extern run_next_process - -start: - mov ax, cs - mov ds, ax - - ; --- ; - - call load_gdt - call init_video_mode - call enter_protected_mode - call setup_interrupts - call load_task_register - - ; --- ; - - call 08h:start_kernel - -load_gdt: - cli - lgdt [gdtr - start] - - ret - -setup_interrupts: - call remap_pic - call load_idt - - ret - -init_video_mode: - ;; Set Video Mode - mov ah, 0h - mov al, 03h ; 03h For Text Mode. 13h For Graphics Mode. - int 10h - - ;; Disable Text Cursor - mov ah, 01h - mov cx, 2000h - int 10h - - ret - -enter_protected_mode: - mov eax, cr0 - or eax, 1 - mov cr0, eax - - ret - -remap_pic: - mov al, 11h - - send_init_cmd_to_pic_master: - out 0x20, al - - send_init_cmd_to_pic_slave: - out 0xa0, al - - ; ... ; - - make_irq_starts_from_intr_32_in_pic_master: - mov al, 32d - out 0x21, al - - make_irq_starts_from_intr_40_in_pic_slave: - mov al, 40d - out 0xa1, al - - ; ... ; - - tell_pic_master_where_pic_slave_is_connected: - mov al, 04h - out 0x21, al - - tell_pic_slave_where_pic_master_is_connected: - mov al, 02h - out 0xa1, al - - ; ... ; - - mov al, 01h - - tell_pic_master_the_arch_is_x86: - out 0x21, al - - tell_pic_slave_the_arch_is_x86: - out 0xa1, al - - ; ... ; - - mov al, 0h - - make_pic_master_enables_all_irqs: - out 0x21, al - - make_pic_slave_enables_all_irqs: - out 0xa1, al - - ; ... ; - - ret - -load_idt: - lidt [idtr - start] - ret - -load_task_register: - mov ax, 40d - ltr ax - - ret - -bits 32 -start_kernel: - mov eax, 10h - mov ds, eax - mov ss, eax - - mov eax, 0h - mov es, eax - mov fs, eax - mov gs, eax - - ;sti - - call kernel_main - -%include "gdt.asm" -%include "idt.asm" - -tss: - dd 0 \ No newline at end of file +; runs in 16 bits +; to prepare proper environment for main kernel by: +; - init and load GDT +; - set interrupts +; - set video mode +; - change 16 bit real mode to 32 bit protected mode + +; tell NASM to generate 16 bit code since we will be using 16 bit real mode +; in the bootloader don't need to do this because: for flat binary the default is 16 bit but we use ELF32 +bits 16 +; extern tells NASM that there is a function/ variable define outside this code, it will be figured out by the linker +extern kernel_main +extern interrupt_handler +extern scheduler +extern run_next_process +extern page_directory + +global load_page_directory +global enable_paging + +start: + mov ax, cs ; set proper memory address of ds depending on the value of cs + mov ds, ax + + call load_gdt + call init_video_mode + call enter_protected_mode + call setup_interrupts + call load_task_register + + call 08h:start_kernel + +load_gdt: + ; turn off interrupts (recommended by x86) + cli + ; substract address of start from gdtr, take this resulting address and load the content there + ; why gdtr - start instead of gdtr? + ; in real mode, gdtr -> is seen as offset from segment register instead of full address + lgdt [gdtr - start] + + ret + +setup_interrupts: + call remap_pic + call load_idt + + ret + +; cannot use BIOS to print to screen anymore, so we need to use vga +init_video_mode: + ; Set Video Mode + ; call BIOS service 10h:0h to set video mode to number passed in register al + mov ah, 0h + + ; 03h -> text mode with 16 colors, 13h is graphic mode with 256 colors + mov al, 03h + int 10h + + ; call BIOS service 10h:01h to disable text cursor + mov ah, 01h + mov cx, 2000h + int 10h + + ret + +enter_protected_mode: + ; x86 has cr0-cr7 control register + mov eax, cr0 + + ; last bit of cr0 -> 0: disable protected mode, 1: enable protected mode + or eax, 1 + mov cr0, eax + + ret + +remap_pic: + mov al, 11h + + ; out port_number, value + send_init_cmd_to_pic_master: + out 0x20, al + + send_init_cmd_to_pic_slave: + out 0xa0, al + + ; ... ; + + make_irq_starts_from_intr_32_in_pic_master: + mov al, 32d + out 0x21, al + + make_irq_starts_from_intr_40_in_pic_slave: + mov al, 40d + out 0xa1, al + + ; ... ; + + tell_pic_master_where_pic_slave_is_connected: + mov al, 04h + out 0x21, al + + tell_pic_slave_where_pic_master_is_connected: + mov al, 02h + out 0xa1, al + + ; ... ; + + mov al, 01h + + tell_pic_master_the_arch_is_x86: + out 0x21, al + + tell_pic_slave_the_arch_is_x86: + out 0xa1, al + + ; ... ; + + mov al, 0h + + make_pic_master_enables_all_irqs: + out 0x21, al + + make_pic_slave_enables_all_irqs: + out 0xa1, al + + ; ... ; + + ret + +load_idt: + lidt [idtr - start] + ret + +load_task_register: + mov ax, 40d + ltr ax + + ret + +bits 32 +load_page_directory: + mov eax, [page_directory] + mov cr3, eax + + ret + +enable_paging: + mov eax, cr0 + or eax, 80000000h + mov cr0, eax + + ret + +start_kernel: + mov eax, 10h + mov ds, eax + mov ss, eax + + mov eax, 0h + mov es, eax + mov fs, eax + mov gs, eax + + ;sti + + call kernel_main + +%include "gdt.asm" +%include "idt.asm" + +tss: + dd 0 diff --git a/starter.o b/starter.o deleted file mode 100644 index bad2e69..0000000 Binary files a/starter.o and /dev/null differ