Lessons along the EndBOX journey

About six months ago, during one of my long runs, I had a wild idea: what if I built an OS disk image that booted straight into EndBASIC, bundled it with a Raspberry Pi, a display, a custom 3D-printed case, and made a tiny, self-contained retro BASIC computer? Fast-forward to today and such an idea exists in the form of “the EndBOX prototype”!

This article isn’t the product announcement though—that’s elsewhere. What I want to do here is look back at the Blog System/5 articles I’ve written over the past months because what might have seemed like scattered topics were actually stepping stones toward the EndBOX.

Let’s look at what I learned along the way and why, even though developing EndBASIC may sound like a “useless waste of time”, it’s a great playground and the source of inspiration for the articles you’ve come to appreciate here.

June 17, 2025 · Tags: blogsystem5, endbasic
Continue reading (about 8 minutes)

A blog on operating systems, programming languages, testing, build systems, my own software projects and even personal productivity. Specifics include FreeBSD, Linux, Rust, Bazel and EndBASIC.

0 subscribers

Whatever happened to sandboxfs?

Back in 2017–2020, while I was on the Blaze team at Google, I took on a 20% project that turned into a bit of an obsession: sandboxfs. Born out of my work supporting iOS development, it was my attempt to solve a persistent pain point that frustrated both internal teams and external users alike: Bazel’s poor sandboxing performance on macOS.

sandboxfs was a user-space file system designed to efficiently create virtual file hierarchies backed by real files—a faster alternative to the “symlink forests” that Bazel uses to prepare per-action sandboxes. The idea was simple: if we could lower sandbox creation overhead, we could make Bazel’s sandboxing actually usable on macOS.

Unfortunately, things didn’t play out as I dreamed. Today, sandboxfs is effectively abandoned, and macOS sandboxing performance remains an unsolved problem. In this post, I’ll walk you through why I built sandboxfs, what worked, what didn’t, and why—despite its failure—I still think the core idea holds promise.

June 11, 2025 · Tags: bazel, blogsystem5, sandboxfs
Continue reading (about 10 minutes)

Beginning 3D printing

Hello readers and sorry for the 2-month radio silence. I’ve been pretty busy at work, traveling during school breaks, hacking on EndBASIC when time permitted, and… as of two weeks ago… tinkering with 3D printing as a complete beginner. So, today, I’d like to walk you through the latter because it has been a really fun and rewarding journey, albeit frustrating at times.

You’d think that to use a 3D printer, you’d design a 3D model and then… just… send it to the printer? That’s almost true, but it ignores the realities of producing a physical object from an “abstract” model: when designing such a model, you need to take into account the limitations of 3D printing and you need to translate your model into something the 3D printer can understand via a process called slicing.

Let’s take a brief peek at all of these steps. I’ll assume you are a complete beginner like I am. The pictures I’ll show are all for a “first project” I did to remake the bars of a bird cage I have, as the birds had fully destroyed the previous ones.

May 28, 2025 · Tags: blogsystem5, hardware
Continue reading (about 13 minutes)

The next generation of Bazel builds

Today marks the 10th anniversary of Bazel’s public announcement so this is the perfect moment to reflect on what the next generation of build systems in the Bazel ecosystem may look like.

I write this with the inspiration that comes from attending the first ever conference on Buildbarn, one of the many remote execution systems for Bazel. In the conference, Ed Schouten, the creator of Buildbarn, presented Bonanza: a skunkworks reimagination of Bazel for truly large builds.

March 24, 2025 · Tags: bazel, blogsystem5
Continue reading (about 12 minutes)

Bazel at Snowflake two years in

Two and a half years ago, I joined Snowflake to help their mission of migrating to Bazel. I spent the first year of this period as an Individual Contributor (IC) diving deep into the migration tasks, and then I took over the Tech Lead (TL) role of the team to see the project through completion.

This week, we publicly announced that we completed our migration to Bazel for the largest part of our codebase and we provided details on our journey. I did not publish that article here for obvious reasons, so… today’s entry is going to be a light one: all I want to do is point you at our announcement as well as the various other related articles that came before it.

March 14, 2025 · Tags: bazel, blogsystem5, snowflake
Continue reading (about 4 minutes)

Hardware discovery: ACPI & Device Tree

If you grew up in the PC scene during the 1980s or early 1990s, you know how painful it was to get hardware to work. And if you did not witness that (lucky you) here is how it went: every piece of hardware in your PC—say a sound card or a network card—had physical switches or jumpers in it. These switches configured the card’s I/O address space, interrupts, and DMA ports, and you had to be careful to select values that did not overlap with other cards.

But that wasn’t all. Once you had configured the physical switches, you had to tell the operating system and/or software which specific cards you had and how you had configured them. Remember SET BLASTER=A220 I5 D1 H5? This DOS environment variable told programs which specific Sound Blaster you had installed and which I/O settings you had selected via its jumpers.

Not really fun. It was common to have hardware conflicts that yielded random lock-ups, and thus ISA “Plug and Play”, or PnP for short, was born in the early 1990s—a protocol for the legacy ISA bus to enumerate its devices and to configure their settings via software. Fast-forward to today’s scene where we just attach devices to external USB connectors and things “magically work”.

But how? How does the kernel know which physical devices exist and how does it know which of the many device drivers it contains can handle each device? Enter the world of hardware discovery.

February 28, 2025 · Tags: blogsystem5, hardware, unix
Continue reading (about 16 minutes)

ioctls from Rust

In Unix-like systems, “everything is a file and a file is defined as a byte stream you can open, read from, write to, and ultimately close”… right? Right? Well, not quite. It’s better to say file descriptors provide access to almost every system that the kernel provides, but not that they can all be manipulated with the same quartet of system calls, nor that they all behave as byte streams.

Because you see: network connections are manipulated via file descriptors indeed, but you don’t open them: you bind, listen/accept and/or connect to them. And then you don’t read from and write to network connections: you somehow send to and recv from them. Device drivers are similar: yes, hardware devices are represented as “virtual files” in the /dev hierarchy and many support read and write… but these two system calls are not sufficient to access the breath of functionality that the hardware drivers provide. No, you need ioctl.

ioctl is the poster child of the system call that breaks Unix’s “everything is a file” paradigm. ioctl is the API that allows out-of-band communication with the kernel side of an open file descriptor. To see cool examples, refer back to my previous article where I demonstrated how to drive graphics from the console without X11: in that post, we had to open the console device, but then we had to use ioctl to obtain the properties of the framebuffer, and then we had to mmap the device’s content for direct access: no reads nor writes involved.

All the code I showed you in that earlier post was written in C to keep the graphics article to-the-point, but the code I’m really working on is part of EndBASIC, and thus it is all Rust. And the thing is, ioctls are not easy to issue from Rust. In fact, after 7 years of Rust-ing, it’s the first time I’ve had to reach for unsafe code blocks, and there was no good documentation on how to deal with ioctl. So this posts aims to fix that by presenting what ways there are to call ioctls from Rust… and, of course, diving a bit deeper into what ioctls actually are.

February 13, 2025 · Tags: blogsystem5, rust, unix
Continue reading (about 14 minutes)

Hands-on graphics without X11

If you have been following the development of EndBASIC, you know its console can display both text and graphics at once. What you may not know is that, now, it can also achieve this feat on the NetBSD console without using X11 at all. This is done by directly rendering to the wsdisplay framebuffer, and this article presents a crash course on direct graphics and keyboard access via NetBSD’s wscons framework.

January 17, 2025 · Tags: blogsystem5, endbasic, netbsd
Continue reading (about 13 minutes)

Self-documenting Makefiles

Make, as arcane as a build tool can be, may still be a good first fit for certain scenarios. “Heresy!”, you say, as you hear a so-called “Bazel expert” utter these words.

The specific problem I’m facing is that I need to glue together the NetBSD build system, a quilt patch set, EndBASIC’s Cargo-based Rust build, and a couple of QEMU invocations to produce a Frankenstein disk image for a Raspberry Pi. And the thing is: Make allows doing this sort of stitching with relative ease. Sure, Make is not the best option because the overall build performance is “meh” and because incremental builds are almost-impossible to get right… but adopting Bazel for this project would be an almost-infinite time sink.

Anyway. When using Make in this manner, you often end up with what’s essentially a “command dispatcher” and, over time, the number of commands grows and it’s hard to make sense of which one to use for what. Sure, you can write a README.md with instructions, but I guarantee you that the text will get out of sync faster than you can read this article. There is a better way, though.

January 10, 2025 · Tags: blogsystem5, unix
Continue reading (about 7 minutes)

Revisiting the NetBSD build system

I recently picked up an embedded project in which I needed to build a highly customized full system image with minimal boot times. As I explored my options, I came to the conclusion that NetBSD, the often-forgotten BSD variant, was the best viable choice for my project.

One reason for this choice is NetBSD’s build system. Once you look and get past the fact that it feels frozen in time since 2002, you realize it is still one of the most advanced build systems you can find for an OS. And it shows: the NetBSD build system allows you to build the full OS from scratch, on pretty much any host POSIX platform, while targeting any hardware architecture supported by NetBSD. All without root privileges.

Another reason for this choice is that NetBSD was my daily workhorse for many years and I’m quite familiar with its internals, which is useful knowledge to quickly achieve the goals I have in mind. In fact, I was a NetBSD Developer with capital D: I had commit access to the project from about 2002 through 2012 or so, and I have just revived my account in service of this project. jmmv@ is back!

So, strap onto your seats and let’s see how today’s NetBSD build system looks like and what makes it special. I’ll add my own critique at the end, because it ain’t perfect, but overall it continues to deliver on its design goals set in the late 1990s.

December 28, 2024 · Tags: blogsystem5, netbsd
Continue reading (about 16 minutes)

A blog on operating systems, programming languages, testing, build systems, my own software projects and even personal productivity. Specifics include FreeBSD, Linux, Rust, Bazel and EndBASIC.

0 subscribers