Having built a few bare metal and hobby OS projects over the years, I would not recommend the path taken in this tutorial series.
Because if you want to write an OS, don't write a bootloader first. This article essentially describes a stage 1 bootloader on top of legacy BIOS firmware. It will teach you about historical x86 minutiae, which is nothing but a hindrance if you want to understand OS concepts.
Instead you should try to get a bootable ELF (multiboot) or PE (UEFI) image written in a high level language (C, C++, Rust, Zig, etc) as soon as possible. You can boot it up in QEMU very easily (compared to a boot sector image) and get a real debugger (gdb), system monitor and all the other invaluable tooling up. This will greatly affect the velocity of your project and get to the interesting stuff faster.
Because bare metal/OS projects may be hard to write but they are even harder to debug. You will need all the help you can get.
I think you're totally right from a practical view. Trying to debug 16-bit x86 code is a nightmare, none of the debuggers properly support it.
Leaving practicality aside and focusing on aesthetics...
Normally, for hobby wheel reimplementation projects like this, I find doing it as close to the bare metal as possible, relying on the minimum amount of other people's code, a lot more fun.
But AFAIK, these days legacy BIOS boot is just some emulated compatibility mode running under UEFI anyway. The bootloader already ran and configured the hardware for you, and then it un-configured a bunch of stuff so you can re-do it. It's role-playing as an 80s PC for you. I find that deeply unsatisfying.
UEFI is the bare-metal API, for all intents and purposes. (Unless you want to go completely blobless, writing your own firmware.)
> hobby wheel reimplementation projects like this, I find doing it as close to the bare metal as possible, relying on the minimum amount of other people's code, a lot more fun.
As a chronic wheel reinventor, I can understand this.
But if I felt like scratching this itch now, I would pick some other hardware than x86. The RP2040 could be a nice target, or maybe some ARM or RISC-V SoC.
That said, I totally understand that there's something different to having a bare metal / hobby OS project running on your daily driver computer than some embedded gadget.
I'm speaking from experience here, I've written bare metal projects in the style of this project (first project I did with MS-DOS debug.com, wrote to a floppy disk and rebooted my machine from the floppy) and the "modern" way with compilers, emulators, debuggers etc. The difference in productivity and learning the interesting stuff is huge.
True. Having written a bootloader and also the code for switching to 32-bit protected mode etc, you get to see a lot of esoteric magic which doesn't make a lot of sense and which you can't also remember.
For this it is best to go with the osdev code and then attempt to learn what actually is going on much later.
Are there resources you recommend for that? I feel like I've run into articles that take that approach here on HN but its been so long. Fiddling with making a small OS is something I have wanted to try for a little while. If Rust is fully capable of doing so, I might give it a shot that way. It will be an excuse to finally use Rust for something.
The osdev wiki is the best source for this and they have the bare bones tutorials with all the linker scripts, bootstrap code, makefiles, etc you might need. They have examples for multiboot and UEFI (and BIOS boot sector).
If I were to start a new OS project I would do it in Rust too but as awesome as Rust is, I can't recommend doing a bare metal project as your first foray into the language. Learning two or more things at once doesn't work for me.
I've dived into Rust a few other times, I just can't find something that makes me want to stick to it. Most of my projects are usually reverse engineering related or web apps I don't have the energy to over engineer in Rust. I prefer simple web frameworks that give you the batteries. When "Django for Rust" becomes a thing I will happily fully embrace Rust.
Maybe worth venturing into the embedded land? There are some pretty cool Rust embedded projects (e.g. embassy) which are sort of best of both worlds. You get to do low level hardware tinkering (which arguably requires a systems programming language) and you get a sort of batteries included environment where you can use all the nice Rust high level features (memory safety, async, etc).
Easier to get started with than OSdev and less gruesome legacy hardware details to study to get stuff done.
Next time I need some lights blinking or actuators actuating I'm gonna do it with Rust and rp2040+.
I'd go a step farther and suggest that people start with an existing microkernel instead. Sure, it is not technically your own "OS" but microkernels really are micro, so you don't miss much.
for me the important part of 'roll your own OS' is to banish the idea that there is some magic happening underneath you that was written by machine elves.
Writing an OS doesn't really do that though. At the end of the day, an OS is still just software that is run by the magic machine elves living in the hardware.
Setting aside the fact that modern CPUs essentially JIT your machine code and their real execution model is completely foreign to their instruction set; a lot of OS development is still poke at a memory address to cause hardware to do something that is decidedly not setting bits in ram.
Sure, writing the page table management logic will demystify how shared memory works. But you are still just writing a new page table, invoking a particular processor opcode, then trusting the elves living in the processor to tell the elves living in the MMU to update how they translate memory addresses from the processor to memory addresses on the bus.
Because if you want to write an OS, don't write a bootloader first. This article essentially describes a stage 1 bootloader on top of legacy BIOS firmware. It will teach you about historical x86 minutiae, which is nothing but a hindrance if you want to understand OS concepts.
Instead you should try to get a bootable ELF (multiboot) or PE (UEFI) image written in a high level language (C, C++, Rust, Zig, etc) as soon as possible. You can boot it up in QEMU very easily (compared to a boot sector image) and get a real debugger (gdb), system monitor and all the other invaluable tooling up. This will greatly affect the velocity of your project and get to the interesting stuff faster.
Because bare metal/OS projects may be hard to write but they are even harder to debug. You will need all the help you can get.