Darwin on Broadway: The Open Firmware Problem at the Heart of the Wii Mac OS X Port
Source: hackernews
Bryan Keller’s port of Mac OS X to the Nintendo Wii hit Hacker News this week and pulled nearly 1,900 points, which tells you something about how deeply this kind of project resonates with people who have spent time thinking about how operating systems actually boot. The surface-level reaction is “that’s a funny joke hardware project.” The deeper reaction, once you start tracing through the boot chain, is that this required dismantling and rebuilding every layer of trust an Apple OS puts in its firmware environment.
The reason the project is even plausible at all comes down to a hardware coincidence. The Wii’s CPU, IBM’s PowerPC 750CL (codenamed Broadway), runs at 729 MHz and belongs to the same 750 family that Apple shipped in the iBook G3 and eMac. Mac OS X Tiger (10.4) officially supports G3-class hardware. Apple’s XNU kernel identifies the CPU by reading the Processor Version Register; the 750CL reports a PVR of 0x7000xxxx, which falls squarely in the 750-class range that Tiger recognizes. So at the ISA level, the Wii CPU and an iBook’s CPU are speaking the same language.
There is one twist: the 750CL added AltiVec support, which was absent from earlier 750-series chips. AltiVec is normally associated with the G4, so finding it in a G3-class processor is unexpected. The problem is that XNU identifies AltiVec capability by CPU family, not by probing the hardware directly. Without patching the PVR detection logic to account for the 750CL’s unusual feature set, the kernel will skip all AltiVec code paths. The Wii also has Nintendo and IBM’s custom “paired singles” floating-point extension in the 750CL, a two-float SIMD unit used heavily in GameCube and Wii game code, but Mac OS X has no knowledge of it and will simply never use it.
The Open Firmware Wall
Architectural compatibility is the easy part. The genuinely hard problem is that Mac OS X was designed to assume Open Firmware exists.
Open Firmware (IEEE 1275) is a Forth-based firmware environment that Apple used on all New World PowerPC Macs from the 1998 iMac onward. It enumerates hardware, builds a device tree, and exposes a Client Interface (CI) that the bootloader uses to query that tree at runtime. BootX, Apple’s second-stage bootloader, calls into the OF CI with functions like getprop, peer, and child to walk the device tree, extract clock frequencies, memory ranges, and video parameters, and then flatten all of that into the boot_args structure it hands to the XNU kernel.
The Wii has none of this. Its boot chain is entirely Nintendo proprietary: the boot ROM on the Starlet ARM core initializes hardware, validates and loads Nintendo’s IOS, and eventually hands control to PowerPC code. There is no IEEE 1275 firmware, no finddevice call, no OF heap. BootX, run unmodified, would attempt its first OF CI call, get nothing back, and die before reading a single hardware property.
This is where the wii-linux project history is instructive. Linux ported to the Wii around 2008-2009, shortly after the Homebrew Channel made arbitrary code execution reliable. The approach was to skip Open Firmware entirely and pass the kernel a pre-built Flattened Device Tree blob instead. A small PowerPC stub loader, built around BootMii and MINI (an open-source Starlet firmware replacement), sets register r3 to the address of the blob and jumps to the kernel entry point. The kernel detects the FDT magic value 0xD00DFEED at that address and takes the embedded device tree path rather than trying to call into OF.
The DTB for wii-linux encoded the Wii’s memory layout explicitly:
memory@0 {
device_type = "memory";
reg = <0x00000000 0x01800000 /* MEM1: 24 MB */
0x10000000 0x04000000>; /* MEM2: 64 MB */
};
The Wii’s 88 MB of RAM is split across two non-contiguous ranges: 24 MB of 1T-SRAM at 0x00000000 (MEM1) and 64 MB of GDDR3 at 0x10000000 (MEM2), with a gap between them. Linux handles this naturally because its memory subsystem is designed for fragmented physical maps. The FDT just describes both ranges, the kernel registers them as separate memblocks, and everything proceeds.
Darwin requires a different approach because BootX does not speak FDT; it speaks OF CI. To boot Mac OS X on the Wii without rewriting BootX entirely, the bootloader needs to either implement a minimal OF CI shim in memory, presenting synthesized device tree data through the standard function-call interface, or bypass BootX altogether and jump directly into the XNU kernel with a pre-built boot_args structure and a flattened Apple-format device tree (which is not the same binary format as Linux’s DTB).
Memory, RAM, and What Tiger Actually Needs
The memory situation is tight. Apple’s official minimum for Tiger is 256 MB, but the kernel itself needs roughly 30-50 MB of wired memory for its own structures, leaving the rest for userspace. Tiger has been documented booting on 128 MB, reaching the Finder but essentially unusable due to constant swapping. The Wii’s 88 MB total, spread across two disjoint ranges, puts this port well below the “functional” threshold for a full desktop OS experience.
This matters for the boot itself because the Mach VM subsystem at startup makes decisions about zone sizes and wired memory allocations based on the available RAM. With only 24 MB accessible in the contiguous MEM1 range at early boot (before MEM2 is mapped), the kernel may hit allocation failures during IOKit device enumeration before it ever draws anything to screen. A port that survives to userspace on this hardware is genuinely squeezing.
The Starlet Gatekeeper and the IOKit Driver Gap
Even if you solve the boot plumbing, you face a structural hardware problem unique to the Wii: the Starlet.
Embedded inside the Hollywood GPU chip is an 88 MHz ARM926EJ-S core that Nintendo calls Starlet. It runs IOS, Nintendo’s proprietary I/O operating system, and acts as the gatekeeper for virtually all hardware: SD card, USB, Bluetooth, WiFi, NAND flash, and the disc drive. The Broadway PowerPC CPU communicates with Starlet through an IPC mechanism using two memory-mapped registers and a shared buffer in MEM1, typically around physical address 0x13000000. Broadway cannot talk directly to the SD controller or USB host; it must request operations from Starlet via IPC and wait for a response.
Mac OS X has zero IOKit drivers for any of this. There is no Wii platform expert (AppleMacRISC2PE expects a specific machine model string from the OF device tree root), no Wii audio driver, no Starlet IPC layer, nothing. For the port to produce video output at minimum, you need either a Hollywood-specific framebuffer driver or a path through the generic AppleBootDisplay fallback, which can claim a dumb linear framebuffer described in boot_args.Video with base address, width, height, bit depth, and row bytes. BootX normally fills this structure from OF’s video device properties. Synthetic boot args can fill it manually if you know the Wii’s framebuffer address and format.
This is the same approach wii-linux uses for its framebuffer: tell the kernel where the Wii’s external framebuffer (XFB) lives and let the generic framebuffer driver draw pixels directly, bypassing any Hollywood-specific acceleration entirely.
What This Port Is Really Demonstrating
The interesting thing about this project is not that Mac OS X runs well on a Wii, because it almost certainly does not. At 88 MB of total RAM with no swap device, no native storage driver, and a 729 MHz CPU from the early 2000s, “runs” means something closer to “reaches a recognizable state of the OS before running out of RAM or blocking on missing hardware.”
What the port demonstrates is the degree to which every desktop OS boot sequence is really a negotiation with firmware. BootX’s entire job is to translate an Open Firmware device tree into the structures XNU expects. Linux’s prom_init.c does the same thing in a more portable way. The Wii’s wii-linux port already solved this problem for Linux by synthesizing a static DTB; the Darwin port has to solve it again for a bootloader that speaks a completely different protocol.
The fact that Bryan Keller got this far at all means he rebuilt that firmware translation layer from scratch for hardware that Apple never intended to run its OS. That requires understanding not just the XNU source tree but the full boot contract between Open Firmware, BootX, and the kernel, at the level of individual boot_args fields and property encoding conventions.
For anyone who wants to read the XNU source side of this, the boot_args structure lives in pexpert/ppc/boot.h in Apple’s Darwin open source drops, and the OF device tree parsing BootX does before calling the kernel is in the BootX source tree (vintage BootX-59 through BootX-81). The wii-linux platform code in arch/powerpc/platforms/embedded6xx/ is the most direct prior art for what a synthetic Wii device tree looks like in practice.
Porting an OS to hardware it was never designed for is almost always an exercise in understanding the OS better than the original developers expected anyone to need to. This one is no different.