Logran ejecutar Mac OS X 10.0 (Cheetah) en una Nintendo Wii
(bryankeller.github.io)- Se completó un proyecto de port para ejecutar Mac OS X 10.0 (Cheetah) de forma nativa usando el hardware basado en PowerPC de la Wii
- Se modificó el kernel Darwin/XNU para adaptarlo a la Wii y se escribieron desde cero el bootloader, el device tree y los drivers, logrando arrancar incluso el entorno GUI
- Se implementaron drivers personalizados de IOKit con soporte para tarjeta SD, framebuffer y dispositivos de entrada USB, consiguiendo un sistema completamente funcional
- Se reflejaron características propias de la Wii, como la corrección de conflictos en la configuración BAT, la creación de una capa de drivers para el SoC Hollywood y un framebuffer con conversión RGB→YUV
- Tras más de 10 años de intentos, se logró el arranque completo y la operación de Mac OS X en la Wii, demostrando el valor de asumir proyectos que parecen imposibles
Resumen del proyecto para ejecutar Mac OS X en Wii
- Se llevó a cabo un proyecto de port para ejecutar Mac OS X 10.0 (Cheetah) de forma nativa en Nintendo Wii
- La Wii ya había tenido ports de sistemas como Linux, NetBSD y Windows NT, y ahora se suma Mac OS X
- Aprovechando el hardware basado en PowerPC de la Wii, se ejecutó el kernel Darwin/XNU y se escribieron directamente los drivers y el bootloader necesarios
- Como resultado, se logró el arranque completo de Mac OS X hasta su entorno gráfico en la Wii, con soporte incluso para teclado y mouse
Investigación de viabilidad
- El CPU PowerPC 750CL de la Wii es sucesor del PowerPC 750CXe usado en la G3 iMac/iBook, por lo que no había problemas de compatibilidad de CPU
- Los 88 MB de RAM de la Wii (MEM1 24 MB + MEM2 64 MB) son menos que el requisito oficial (128 MB), pero pruebas con QEMU confirmaron que podía arrancar incluso con 64 MB
- El hardware soportado incluye USB Gecko (depuración serial), tarjeta SD, controlador de interrupciones, salida de video por framebuffer y puertos USB
- Si se adaptaba a la Wii el núcleo open source de Mac OS X, Darwin (kernel XNU, IOKit), también era posible hacer funcionar la capa gráfica superior
- La Wii permite la ejecución de código propio mediante Homebrew Channel y BootMii, lo que la hace adecuada para experimentar con ports
Enfoque del port
- Se eligió entre tres estrategias de arranque:
- Portar Open Firmware
- Portar BootX
- Escribir directamente un bootloader personalizado
- Se escribió un nuevo bootloader específico para Wii que realiza la inicialización de hardware, la carga del kernel, la creación del device tree y la transferencia de control al kernel
- Una vez que el kernel arranca, el código del bootloader deja de ser necesario, y el trabajo posterior se centra en parches al kernel y desarrollo de drivers
Escritura del bootloader
- Se implementaron la inicialización de la Wii y funciones para tarjeta SD, framebuffer y depuración USB basándose en código de ejemplo de ppcskel
- El kernel XNU en formato Mach-O se carga en memoria y se ejecuta saltando a su entry point especificado
- Para verificar si el kernel estaba entrando en ejecución, se insertó un parche de parpadeo de LED para rastrear esa etapa
- Al rastrear en reversa la ruta de ejecución del kernel, se confirmó que ocurría una excepción 300 en la etapa device_tree.c → se identificó la necesidad de pasar un device tree
-
Creación y entrega del device tree
- Se construyó un árbol mínimo hardcodeado basado en la estructura fija del hardware de la Wii (
/cpus,/memory) - Se incluyó un puntero al device tree en la estructura
boot_argspara pasarlo al kernel - Después de eso, el kernel reconoció correctamente el árbol y continuó el arranque
- Se construyó un árbol mínimo hardcodeado basado en la estructura fija del hardware de la Wii (
Parches al kernel
- La configuración de BAT (Block Address Translation) en XNU entraba en conflicto con el mapa de memoria de la Wii, por lo que fue necesario modificar el código fuente del kernel
- Se montó un entorno de compilación del kernel dentro de un guest de Mac OS X Cheetah (QEMU)
- Gracias a la corrección de BAT y al agregado de redirección de salida de consola hacia USB Gecko, fue posible depurar
- Después, se inicializaron correctamente la memoria virtual, IOKit y el subsistema BSD
- En el log de arranque apareció el mensaje “Still waiting for root device” → se confirmó la necesidad de un driver para la tarjeta SD
Escritura de drivers
-
Comprender la estructura de IOKit
- IOKit es un framework de extensiones de kernel basado en C++ que representa las capas de hardware mediante una estructura de driver-nub
- Ejemplo:
IOPCIBridge→IOPCIDevice→SomeEthernetCard→IOEthernetInterface - Como la Wii usa una estructura SoC (Hollywood) y no un bus PCI, hizo falta un driver personalizado que reemplazara a IOPCIFamily
-
Driver de Hollywood
- Se escribió el driver
NintendoWiiHollywood, que hace match con el nodo “hollywood” del device tree - Se creó y registró el nub
NintendoWiiHollywoodDevicepara representar el hardware subordinado - Gracias a esto, pudieron conectarse drivers de dispositivos inferiores, como el de la tarjeta SD
- Se escribió el driver
-
Driver de tarjeta SD
- Se implementó el acceso a la tarjeta SD de la Wii heredando de
IOBlockStorageDevice - La comunicación con la tarjeta SD se realiza usando los comandos IPC de MINI (coprocesador Starlet):
IPC_SDMMC_SIZE,READ,WRITE - Para resolver problemas con memoria cacheada, se usó un buffer de memoria no cacheada
- Se generó con éxito un nub
IOMedia, permitiendo el reconocimiento del sistema de archivos raíz y el arranque completo - En el log de arranque se confirmó
BSD root: disk0s4
- Se implementó el acceso a la tarjeta SD de la Wii heredando de
-
Driver de framebuffer
- Heredando de
IOFramebuffer, se asignó como framebuffer la región MEM1 de la Wii (0x01700000) - Para permitir la transición entre la consola de texto inicial y la GUI,
isConsoleDevice()devuelvetrue - Como el hardware de video de la Wii usa formato YUV, se implementó un framebuffer doble para conversión RGB→YUV
- Mediante un loop de conversión se realizó la conversión de color a 60 Hz → se logró salida GUI con colores correctos
- Heredando de
-
Soporte de entrada USB
- Se intentó usar
AppleUSBOHCIpara manejar el controlador USB 1.1 OHCI de la Wii - Problema 1: no había código fuente de IOUSBFamily, así que no se podía depurar
- Problema 2: existía una dependencia de IOPCIDevice, por lo que se escribió un
NintendoWiiHollywoodPCIDevicefalso para la Wii - Problema 3: había una incompatibilidad de endianess (la Wii usa reversed-little-endian), por lo que fue necesario eliminar el byte swap por software
- Tras conseguir por IRC el código fuente de IOUSBFamily para Mac OS X Cheetah, se pudo modificar y compilar con éxito
- Como resultado, funcionaron el teclado y el mouse USB, y la Wii pasó a comportarse como un sistema Mac OS X completo
- Se intentó usar
Mejoras al bootloader y al kernel
-
Mejoras al bootloader
- Se añadieron búsqueda de particiones en la tarjeta SD y menú de arranque, además de implementar el parseo de Apple Partition Map (APM)
- El bootloader carga extensiones de kernel (kext) y las registra en el nodo
/chosen/memory-map - Gracias a esto, se puede arrancar usando una imagen de instalación de Mac OS X sin modificar
-
Simplificación del kernel
- Se minimizaron los cambios específicos para Wii en el kernel:
- corrección de la configuración BAT
- reconocimiento de direcciones de I/O basado en el nodo “hollywood”
- corrección de coherencia de caché del framebuffer
- separar los drivers fuera del kernel mejoró la eficiencia de compilación y la mantenibilidad
Cierre
- Se completó, después de más de 10 años, un proyecto concebido originalmente en la universidad en 2013
- El desafío estuvo inspirado por un caso de port de Windows NT a Wii
- Como resultado final, se logró el arranque completo de Mac OS X 10.0 y el manejo de su GUI en la Wii
- Se enfatiza la lección de que “los proyectos que parecen imposibles son precisamente los que vale la pena intentar”
3 comentarios
Qué texto tan bueno, y qué gran autor....
Dicen que entre los fans, los más fans son los gringos...
Opiniones en Hacker News
Este proyecto fue un trabajo realmente asombroso. El texto en sí también fue muy atrapante y me mantuvo enganchado hasta el final
En particular, me impresionó la parte de “WindowServer se quejaba, y para resolverlo hubo que escribir directamente un controlador de framebuffer”
Me sorprendió ver que la capa de abstracción I/O Kit de MacOS realmente cumple su función. Mis aplausos para los desarrolladores de NeXT
No me resulta fácil compararlo porque no tengo experiencia desarrollando controladores en otras plataformas, pero estructuralmente me pareció bastante atractivo
Hace tiempo incluso hubo desarrolladores de NetBSD que lograron ejecutar PPC Darwin sobre una capa de compatibilidad Mach/IOKit y levantar hasta Xquartz. Es interesante que NetBSD tradujera las llamadas de IOKit
Todavía me cuesta creer que se puedan ejecutar tantos sistemas operativos sobre una Wii
En realidad, la diferencia entre una buena abstracción y una mala suele depender de qué tan bien esté explicada
La ingeniería en sí ya es impresionante, pero lo que de verdad me impactó es que el autor estaba desarrollando en clase económica
(Luego vi un poco más y sí: la primera foto era en un bus, la segunda en un avión)
Como autor del port de NetBSD para Wii y Wii U, quiero felicitar sinceramente este proyecto
Tengo muchas ganas de ver qué problemas fueron apareciendo y cómo los resolvieron
Antes yo también era un fanático hardcore de Mac, e incluso llegué a hacer por ingeniería inversa algunas “apps de iOS” no oficiales de los primeros tiempos
Pero este proyecto supera todo eso. Ya de por sí ejecutar MacOS en una Wii es increíble, pero además el texto está muy bien elaborado y es muy interesante
No sabía hasta ahora que la Wii solo tiene 88 MB de RAM. Menos mal que los juegos no eran a base de electrones
El requisito mínimo de Vista era 512 MB, pero la mayoría de las PC tenían menos memoria que eso
Hoy ver que 8 GB van quedando atrás y 16 GB se vuelven el estándar demuestra cuánto ha cambiado el mundo
Antes de empezar el proyecto, quise comprobar si esto siquiera era posible, y en un comentario de Reddit de 2021 alguien decía que tenía “0% de probabilidad”
Ver eso más bien me motivó. Así que empecé analizando el hardware de la Wii. Fue realmente gracioso
Hay gente que da por hecho que algo “casi imposible” nunca va a ocurrir y se convence de que eso los vuelve escépticos rigurosos
Pensé “¿ah, sí?” y reconfiguré el puerto UART para conectarle un ESP32
El problema es que ni siquiera reconocen la idea de un cinismo ignorante
Estar sentado en clase económica de un avión depurando un kernel panic en una Wii implica un nivel de concentración que ni me imagino
A la mayoría ya le cuesta terminar un solo libro en un vuelo
Fue un proyecto realmente genial. Me hizo recordar la época dorada del desarrollo de bajo nivel
Antes era fácil inicializar VGA y dibujar píxeles, y chips como el 6502 también eran mucho más accesibles
Pero hoy los sistemas se han vuelto tan complejos que la barrera de entrada subió muchísimo
Y encima la IA, fingiendo simplificar el desarrollo, en realidad está reduciendo todavía más la accesibilidad
Yo también estoy intentando algo parecido: portar Mac OS 9 a Wii U
Ver este proyecto me dejó totalmente impresionado, y cada vez que pienso “esto es imposible”, me devuelve el ánimo
El texto estuvo muy bueno, pero insertar el video
.movcon una etiqueta<video>trae problemas de compatibilidad entre navegadoresNo se reproduce ni en Chrome ni en Firefox