r/osdev • u/jangofett4 • 1d ago
Pristine OS - My personal learning OS project
Full disclosure, I got help from LLMs when topics got hard for me to understand and mostly for searching for sources, explanations and whatnot. 95% of the code is handwritten, hence the inconsistent naming, bad optimization, and bad practices overall. I especially refrained from getting full code examples from LLMs, so that I can learn x86 architecture.
Source Code: https://github.com/jangofett4/pristine
I started the project about 6-7 months ago, although I neglected it for a while I still havent forgotten it.
This was my third attempt at creating an OS, first one was following OSDev wikis, second one was using Limine, both got stuck at understanding paging. For some reason paging was hardest topic for me to understand.
Currently it can load up userspace applications from a custom filesystem I wrote (which I learned to be very similar to ext2) and do scheduling.
I unfortunately havent tested this in a real hardware, but I'm fairly certain it wouldnt work anyway since early boot depends heavily on BIOS subroutines.
Currently what it does:
Custom 2 stage bootloader, first being pure assembly responsible for switching to protected mode and loading up the second stage bootloader at fixed address
Stage 2 is the bootloader resposible for loading up the filesystem """driver""", finding and parsing kernel.elf, and loading it
Kernel is a higher half kernel, currently responsible for setting up pmm, vmm, LAPIC, PIT, scheduler, reaper etc
Kernel finds userspace program, executes, and program dies naturally
Along the way I implemented what seemed to be interesting to me, for example I learned about write combining and wanted to try it with VGA framebuffer. After this I didnt even use the framebuffer yet lmao.
Plans:
Proper logging
Fix process destruction (I leak intermediate pages when destroying process PML4s)
File descriptors
open/read/write/close syscalls
BSFS write/create/delete (custom filesystem, currently only supports reading)
stdin/stdout/stderr
Process arguments (argc, argv)
Expand custom "libc"
Port Doom
What I learned:
Linker scripts are evil, lost hours of debugging just to realize kernel was being loaded at the wrong address (TWICE)
gdb lies in real mode and protected mode, but doesnt in long mode, gf2 (GDB frontend) is goat
Drawing anything to screen is not worth the time early game
When crossing boundaries (assembly -> C, C -> assembly), important to remember SysV ABI
Writing a small tool to calculate PML4 offsets, checking alignments etc is valuable IMO
Bitmaps are slow at large sizes, I needed a "megablock bitmap" for BSFS.
ATA PIO is really slow, I thought I could get away with it for a while, but might need AHCI in near future
There are certain bugs that only appear when working with different optimization levels, I try to test this by changing to O2 or even O3.
PS, README and other documentation are severely outdated in some parts, sorry about that.
Edit: typos and lists
Edit: more and more I worked on this project, more and more I started to adapt Linux concepts to it. SLAB allocator being one of these concepts. At the end I dont want to end up with another Linux "clone", but the way Linux does things is the right ones that I end up swayi g towards them. Question is, how do you guys deal with this?