Serenity on Bare Metal
Jun 2, 2019
3 minutes read

While you're reading this, keep in mind that I'm available for hire stupid!


Serenity is an open source operating system created by Andreas Kling. Halfway between Windows 98 and early 2000’s UNIX, it’s described as “a love letter to ‘90s user interfaces, with a custom Unix-like core”. I’ve been poking around at it a little bit, and I’ve decided to take a great big bite and try to run it on actual hardware.

I’ll update this post with more details as I go.


The first thing I had to do was get something to load Serenity outside of qemu’s kernel support mode.

I modified to create a disk image with a partition map using a loopback device and parted, wrote a minimal grub config to load the kernel, and put it all together. This got the kernel running, but it immediately failed trying to mount the root filesystem. This is because the disk driver expects the filesystem to start on the first block of the disk. With an MBR partition header in place, this is not true.

To get the root filesystem mounted, I wrote a DiskDevice implementation that simply translates the read/write indexes by a static offset, and called it OffsetDiskDevice. I’ve hardcoded that to 62 right now, as that’s where I’ve chosen to put the first partition. Later on I’ll write an MBR driver that can read the partition table and create an OffsetDiskDevice according to its contents. We can expose some functions from that MBR loader to the kernel too, so the system can mount additional partitions after boot.

2019-06-02 7:52PM - we’ve decided to rename OffsetDiskDevice to DiskPartition, to prepare for MBR loading support.

2019-06-02 11:02PM - MBRPartitionTable has landed - no more hardcoded offets!

2019-06-03 2:04PM - I sure wish I had an easier way to boot this on real hardware. Right now I have to boot from a USB drive running linux, image the hard drive, then reboot. If I have to go through this too many more times, I’ll set something up on the hard drive to load linux from a different partition and pull the Serenity filesystem image down over the network or something.

2019-08-12 - Text mode works. I had to fix up non-DMA reads and writes in the IDE driver, but that wasn’t too complex.

2019-08-14 - Graphical mode works (mostly). I implemented a simple framebuffer device that piggybacks on GRUB’s VESA mode.

2019-08-18 - Graphical mode works (properly). There was a really weird bug that made the screen content wrap around seemingly at random. It turns out that a combination of behaviours resulted in the TTY subsystem writing to the VGA registers and making it scroll the screen. This was fixed with a small patch.

2019-09-02 - Most stuff works! I got tired of updating this post with each event, but there have been a bunch of changes over the past couple of months. Take a look at the videos in the media log below.

Media Log

2019-06-02 4:33PM - this image is from the first partial boot. The root filesystem was still on a USB drive, so the kernel couldn’t read it.

2019-06-02 5:16PM - this is the second partial boot. The root filesystem is now on the machine’s hard drive, but something is not quite right. The kernel stops while it’s trying to load itself into memory.

2019-06-03 1:36PM - we can see that it’s reading some stuff from the disk correctly.

2019-06-03 1:54PM - apparently we didn’t dump enough content out to the screen. Some of the ksym entries are corrupted, and my guess is that the hex parsing failure is related.

2019-08-12 - pretty close to booting. Non-DMA IDE reads/writes were failing.

2019-08-12 (later) - successful text boot!

2019-08-14 - graphical boot!

2019-08-14 - graphical boot has some problems.

2019-09-01 - cameo appearance in Andreas’s monthly update video.

Back to posts