Mac OS X on the Wii: How a Shared CPU Family Made the Impossible Merely Very Hard
Source: hackernews
Bryan Keller published a writeup this week on porting Mac OS X to the Nintendo Wii, and it landed near the top of Hacker News with good reason. On the surface it sounds like chaos: a 2006 gaming console running a desktop OS designed for entirely different hardware. But once you understand what the Wii’s CPU actually is, the project stops looking absurd and starts looking like a very targeted exercise in bootloader archaeology.
The CPU Coincidence
The Nintendo Wii uses a processor codenamed Broadway, manufactured by IBM. Broadway is a PowerPC 750CL running at 729 MHz. The PowerPC 750 is the same processor family that Apple shipped in every iMac and PowerBook from 1998 through the early G4 transition years. Apple called it the G3. Under the hood, Broadway and a G3 share the same base instruction set architecture.
Mac OS X shipped with full PowerPC support through version 10.5 Leopard, released in 2007. Leopard’s minimum supported CPU was a G4, but the kernel itself retained G3 compatibility, and earlier versions like 10.4 Tiger ran fine on G3 hardware. The XNU kernel’s PowerPC machine-dependent layer was written against the PowerPC Book E and 32-bit PowerPC architecture specs. Broadway speaks that same ISA.
This means the kernel binary, once you get it loaded into memory, does not need to be recompiled. The instruction set is not the obstacle. Every other layer of the system is.
How the Wii Actually Boots
Understanding what needs to be replaced requires understanding the Wii’s boot chain, which is more complex than most consoles of its era.
The Wii contains two processors. The Broadway PowerPC handles game code and is what most people think of as “the CPU.” A second processor, called Starlet, is an ARM926EJ-S core running at 243 MHz. Starlet runs continuously and handles nearly all hardware I/O: the disc drive, NAND flash, SD card slot, USB ports, and wireless. Nintendo’s IOS firmware, which runs on Starlet, exposes these devices to Broadway through an inter-processor communication protocol over a shared memory region.
The boot sequence goes: mask ROM on Starlet loads boot1 from NAND, boot1 verifies and loads boot2, boot2 initializes IOS on Starlet and launches the System Menu on Broadway. By the time Broadway starts executing code, Starlet is already running and managing hardware on its behalf.
The homebrew ecosystem found cracks in this chain years ago. BootMii, developed by Team Twiizers, can run as boot2, giving unsigned code control over Broadway at the earliest possible point after Starlet initializes. MINI, an open-source replacement for the low-level Starlet firmware, takes this further by replacing the IOS layer entirely with documented, reversible code. A port of Mac OS X needs control at this level, before Nintendo’s firmware can gate hardware access behind signed-binary checks.
What Mac OS X Needs to Start
On original PowerPC Macs, the firmware layer was Open Firmware, an IEEE 1275 standard implementation that Apple extended heavily. Open Firmware provides a device tree describing the hardware to the bootloader. Apple’s second-stage bootloader, BootX, reads that device tree, finds the kernel, loads it into memory, and jumps to it with a specific set of arguments including the device tree pointer.
XNU’s startup sequence then walks that device tree to find memory ranges, interrupt controllers, and bus controllers. The machine_init() path in the PowerPC machine-dependent code sets up the hardware abstraction layer using what Open Firmware described.
The Wii has none of this. There is no Open Firmware. There is no standard device tree. The memory map is completely different: the Wii has 24 MB of MEM1 (fast, used by Broadway for most operations) and 64 MB of MEM2 (slower GDDR3, used for audio, IOS communication, and overflow). The physical addresses, interrupt controller layout, and bus topology are all proprietary.
The porting work is therefore two distinct problems layered on top of each other. First, you need something that can load the kernel and hand it a valid device tree describing Wii hardware. Second, you need the kernel itself to understand what that device tree is describing well enough to initialize.
The Driver Wall
Even with a working bootloader and a kernel that initializes cleanly, Mac OS X cannot do much on Wii hardware without drivers. The graphics processor, Hollywood, has no open specification and no Mac OS X driver. Hollywood is roughly equivalent to ATI’s Flipper architecture extended for the Wii, but it is not any ATI GPU that Apple ever shipped drivers for. Without a framebuffer driver, you have no display.
Storage is equally problematic. Mac OS X’s IOKit driver stack expects ATA, AHCI, or at minimum a USB mass storage stack built on Apple’s own USB host controller drivers. The Wii’s USB and SD access routes through IOS on Starlet, exposed through the IPC protocol. Talking to Starlet requires code that has no precedent in Mac OS X’s driver model.
Serial output is the lifeline in a project like this. The Wii exposes a hardware serial port through the EXI bus that the Homebrew Channel ecosystem uses heavily for debugging. Getting kernel log output over serial is typically the first milestone in a bare-metal port, and it is the difference between debugging blindly and debugging with information.
Memory Is the Other Constraint
Mac OS X 10.4 Tiger’s official minimum was 256 MB of RAM. The Wii has 88 MB total, split across two regions with different access characteristics. Getting the kernel to boot at all in this environment requires stripping the kernel extension set down to an absolute minimum and disabling features like dynamic pager that expect swap space on a local disk.
Linux has been ported to the Wii through the linux-wii project, and it runs on a similarly stripped configuration. The Wii-Linux port is instructive here: it uses a custom bootloader, a minimal device tree, and a kernel configured to avoid anything that requires more memory than the hardware provides. It boots to a shell, and storage works through the IOS IPC layer. Mac OS X’s kernel architecture is more demanding in its early initialization sequence, but the basic approach is the same.
What “Ported” Means in Practice
Projects like this rarely mean the OS is fully functional. A successful port generally means the kernel initializes past machine_init, the scheduler starts, and the system reaches a point where it is waiting for drivers that do not exist. Getting a Darwin shell prompt or seeing the kernel panic message change from a boot failure to a missing-driver complaint counts as real progress.
The value of these projects is not practical utility. It is what they expose. Getting an OS to boot on unexpected hardware requires reading the machine-dependent layer code with the kind of attention you cannot fake: every assumption about memory layout, every hardcoded physical address, every place the kernel trusts firmware to have done something before it runs. The Wii port of Mac OS X is an education in what XNU actually requires underneath the abstraction layers Apple spent years building.
The fact that the CPU instruction set is compatible strips away one enormous variable and lets the work focus on firmware, memory maps, and the device model. That is the interesting part of OS internals anyway, and the PowerPC overlap between the Wii and the pre-Intel Mac era is what made this particular experiment worth attempting.