Back to Home

Port Mac OS X Cheetah to Wii: XNU and device tree

Developer ported Mac OS X Cheetah to Nintendo Wii using a custom bootloader based on ppcskel. Steps for parsing Mach-O, patching XNU for debugging and creating device tree are described. The project demonstrates compatibility with PowerPC 750CL and 88 MB RAM.

Mac OS X on Wii: from Mach-O to XNU debugging
Advertisement 728x90

Running Mac OS X Cheetah on Nintendo Wii: Porting Deep Dive

A developer has successfully booted the original Mac OS X Cheetah on a Nintendo Wii using its PowerPC 750CL processor. This chip evolved from the PowerPC 750CXe found in iBook G3 and iMac G3 models, delivering solid CPU-level compatibility.

The Wii packs 88 MB of RAM: 24 MB 1T-SRAM (MEM1) and 64 MB GDDR3 (MEM2). Cheetah officially calls for 128 MB, but QEMU tests proved it runs fine on 64 MB. Key features supported include:

  • Serial output via USB Gecko;
  • Booting from SD card;
  • Interrupt controllers;
  • Video output to framebuffer;
  • USB for mouse and keyboard.

Darwin's open-source XNU kernel and IOKit handle drivers seamlessly. Closed-source bits like Quartz and Finder fire up without patches once the kernel's rolling.

Google AdInline article slot

Boot Process: From Open Firmware to Wii

On PowerPC Macs, booting flows through Open Firmware, which builds the device tree, then BootX loads the Mach-O kernel. The Wii leans on homebrew via Homebrew Channel and BootMii.

The approach uses a custom ppcskel-based bootloader: Wii init, load XNU from SD, build device tree, jump to kernel. Skipping a full Open Firmware or BootX port kept things lean by ditching multi-hardware support.

Mach-O Parsing and Kernel Launch

The bootloader dissects Mach-O load commands and maps segments:

Google AdInline article slot
0x00000000: Exception vectors
0x00011000: LC_SEGMENT __TEXT
0x002e0000: LC_SEGMENT __DATA
0x00367000: LC_SEGMENT __KLD
0x00395000: LC_SEGMENT __LINKEDIT
0x00434000: LC_SEGMENT __SYMTAB
0x004d3000: LC_SEGMENT __HEADER

Launch call: ((void ()())kernel_entry_point)(boot_args_address, MAC_OS_X_SIGNATURE);. Screen goes black—kernel's in charge.

Debugging via patching: Swap instructions to toggle Wii's LED at 0x0D8000C0:

lis    r5, 0xd80
ori    r5, r5, 0xc0
lwz    r4, (r5)
sync
xori   r4, r4, 0x20
stw    r4, (r5)

Hopper disassembler mapped XNU functions. Init sequence:

Google AdInline article slot
  • start.s: start
  • start.s: allStart
  • start.s: nextPVR
  • start.s: donePVR
  • start.s: doOurInit
  • start.s: noFloat
  • start.s: noVector
  • start.s: noSMP
  • start.s: noThermometer
  • ppc_init.c: ppcInit
  • pe_init.c: PE_INIT_PLATFORM
  • device_tree.c: find_entry (crash 300)

Crash on exception 300: missing device tree.

Device Tree and boot_args

Device tree is a hierarchical hardware map. For Wii, a hardcoded version from Wii Linux starts minimal:

/
├── cpus
│   └── PowerPC,750
└── memory

Expanded as needed. Boot_args structure:

typedef struct boot_args {
    u16 Revision;
    u16 Version;
    // ... (full structure passed to kernel)
};

Bootloader patches kernel on-the-fly for testing.

Key Takeaways

  • Wii's PowerPC 750CL runs Cheetah stock, no CPU tweaks needed;
  • 88 MB RAM suffices for basic boot, QEMU-verified;
  • Custom ppcskel bootloader cuts overhead;
  • Mach-O parsing and LED patching unlock XNU debugging;
  • Hardcoded device tree speeds boot on fixed hardware.

— Editorial Team

Advertisement 728x90

Read Next