Mac OS X 10.0 (Cheetah) roda com sucesso no Nintendo Wii
(bryankeller.github.io)- Concluído um projeto de port para executar Mac OS X 10.0 (Cheetah) nativamente usando o hardware baseado em PowerPC do Wii
- O kernel Darwin/XNU foi adaptado ao Wii, e bootloader, device tree e drivers foram escritos do zero, conseguindo inicializar até o ambiente gráfico
- Foram implementados drivers IOKit customizados com suporte a cartão SD, framebuffer e dispositivos de entrada USB, alcançando o funcionamento completo do sistema
- O projeto incorpora particularidades da arquitetura do Wii, como correção de conflitos na configuração BAT, camada de drivers para o SoC Hollywood e framebuffer com conversão RGB→YUV
- Após mais de 10 anos de tentativas, foi possível inicializar e operar completamente o Mac OS X no Wii, provando o valor de encarar projetos que pareciam impossíveis
Visão geral do projeto de executar Mac OS X no Wii
- Foi realizado um projeto de port para executar Mac OS X 10.0 (Cheetah) nativamente no Nintendo Wii
- O Wii já havia recebido ports de sistemas como Linux, NetBSD e Windows NT, e agora Mac OS X entra nessa lista
- Aproveitando o hardware baseado em PowerPC do Wii, o projeto executa o kernel Darwin/XNU e implementa manualmente os drivers e o bootloader necessários
- Como resultado, foi possível inicializar completamente até a interface gráfica do Mac OS X no Wii, com suporte também a teclado e mouse
Investigação de viabilidade
- A CPU PowerPC 750CL do Wii é sucessora da PowerPC 750CXe usada em G3 iMac/iBook, portanto não há problema de compatibilidade de CPU
- Os 88 MB de RAM do Wii (MEM1 24MB + MEM2 64MB) ficam abaixo do requisito oficial (128MB), mas testes em QEMU confirmaram que o boot também era possível com 64MB
- O hardware suportado inclui USB Gecko (depuração serial), cartão SD, controlador de interrupções, saída de vídeo por framebuffer e portas USB
- Adaptando o núcleo open source do Mac OS X, o Darwin (kernel XNU, IOKit), ao Wii, também seria possível fazer as camadas gráficas superiores funcionarem
- Como o Wii permite execução de código próprio via Homebrew Channel e BootMii, ele era adequado para experimentos de port
Abordagem do port
- Entre três estratégias de boot possíveis, foi escolhida uma:
- Portar o Open Firmware
- Portar o BootX
- Escrever diretamente um bootloader customizado
- Foi criado um novo bootloader específico para o Wii, responsável por inicialização de hardware, carregamento do kernel, geração da device tree e transferência de controle ao kernel
- Após o kernel entrar em execução, o código do bootloader deixa de ser necessário, e o foco passa a ser patches no kernel e escrita de drivers
Escrita do bootloader
- Com base no código de exemplo ppcskel, foram implementadas a inicialização do Wii e funções de cartão SD, framebuffer e depuração via USB
- O kernel XNU em formato Mach-O é carregado na memória e executado por salto para o entry point especificado
- Para verificar se o kernel estava realmente executando, foi inserido um patch de piscar LED para rastrear a etapa de entrada no kernel
- Ao rastrear o caminho de execução do kernel, confirmou-se a ocorrência da exceção 300 na etapa device_tree.c → reconhecimento da necessidade de fornecer uma device tree
-
Geração e envio da device tree
- Foi montada uma árvore mínima hardcoded com base na estrutura fixa de hardware do Wii (
/cpus,/memory) - O ponteiro da device tree foi incluído na estrutura
boot_argse passado ao kernel - Depois disso, o kernel passou a reconhecer corretamente a árvore e prosseguiu com o boot
- Foi montada uma árvore mínima hardcoded com base na estrutura fixa de hardware do Wii (
Patches no kernel
- A configuração BAT (Block Address Translation) do XNU entrava em conflito com o mapa de memória do Wii, exigindo modificação no código-fonte do kernel
- Foi montado um ambiente de build do kernel dentro de um guest Mac OS X Cheetah (QEMU)
- Com a correção do BAT e a adição de redirecionamento da saída de console para o USB Gecko, a depuração passou a ser possível
- Depois disso, memória virtual, IOKit e subsistema BSD passaram a inicializar corretamente
- Nos logs de boot apareceu a mensagem “Still waiting for root device” → confirmação da necessidade de um driver para cartão SD
Escrita de drivers
-
Entendendo a estrutura do IOKit
- O IOKit é um framework de extensões de kernel baseado em C++ que representa a camada de hardware por meio de uma estrutura driver-nub
- Exemplo:
IOPCIBridge→IOPCIDevice→SomeEthernetCard→IOEthernetInterface - Como o Wii usa uma estrutura SoC (Hollywood) e não um barramento PCI, foi necessário um driver customizado para substituir a IOPCIFamily
-
Driver Hollywood
- Foi escrito o driver
NintendoWiiHollywood, que faz correspondência com o nó “hollywood” na device tree - Ele cria e registra nubs
NintendoWiiHollywoodDeviceque representam o hardware subordinado - Isso permite conectar drivers de dispositivos abaixo dele, como o do cartão SD
- Foi escrito o driver
-
Driver de cartão SD
- O acesso ao cartão SD do Wii foi implementado herdando de
IOBlockStorageDevice - A comunicação com o cartão SD usa os comandos IPC do MINI (coprocessador Starlet):
IPC_SDMMC_SIZE,READ,WRITE - Para resolver problemas com memória em cache, foram usados buffers de memória não cacheada
- Com sucesso, foi criado um nub
IOMedia, permitindo o reconhecimento do sistema de arquivos raiz e o boot completo - O log de boot passou a mostrar
BSD root: disk0s4
- O acesso ao cartão SD do Wii foi implementado herdando de
-
Driver de framebuffer
- Herdando de
IOFramebuffer, a área MEM1 (0x01700000) do Wii foi definida como framebuffer - Para permitir a transição entre o console de texto inicial e a GUI,
isConsoleDevice()retornatrue - Como o hardware de vídeo do Wii usa formato YUV, foi implementado um framebuffer duplo para conversão RGB→YUV
- Um loop de conversão faz a transformação de cores a 60Hz → saída gráfica com cores corretas funcionando com sucesso
- Herdando de
-
Suporte a entrada USB
- Houve tentativa de usar
AppleUSBOHCIpara acionar o controlador USB 1.1 OHCI do Wii - Problema 1: ausência do código-fonte de IOUSBFamily, impossibilitando a depuração
- Problema 2: dependência de IOPCIDevice, exigindo a criação de um
NintendoWiiHollywoodPCIDevicefalso para o Wii - Problema 3: incompatibilidade de endianness (o Wii usa reversed-little-endian), exigindo remover o byte swap por software
- Depois de obter via IRC o código-fonte do IOUSBFamily para Mac OS X Cheetah, foi possível modificá-lo e compilá-lo com sucesso
- Como resultado, teclado e mouse USB funcionam, e o Wii passa a operar como um sistema Mac OS X completo
- Houve tentativa de usar
Melhorias no bootloader e no kernel
-
Melhorias no bootloader
- Foram adicionados busca de partições no cartão SD e menu de boot, com implementação do parser de Apple Partition Map (APM)
- As extensões de kernel (kext) passaram a ser carregadas no bootloader e registradas no nó
/chosen/memory-map - Com isso, tornou-se possível inicializar a partir de uma imagem de instalação do Mac OS X sem modificações
-
Simplificação do kernel
- As alterações específicas para o Wii no kernel foram reduzidas ao mínimo:
- correção da configuração BAT
- reconhecimento de endereços de I/O com base no nó “hollywood”
- correção de consistência de cache do framebuffer
- Os drivers foram separados para fora do kernel, melhorando a eficiência de build e a manutenção
Encerramento
- Um projeto imaginado na época da faculdade, em 2013, foi concluído mais de 10 anos depois
- O desafio foi inspirado por um caso de port do Windows NT para o Wii
- Como resultado final, foi alcançado o boot completo e a operação da GUI do Mac OS X 10.0 no Wii
- A lição destacada é que “quanto mais impossível um projeto parece, mais vale a pena desafiá-lo”
3 comentários
Que texto delicioso, e que autor incrível....
Dizem que os mais nerds entre os nerds são os gringos mesmo...
Comentários do Hacker News
Este projeto foi um trabalho realmente impressionante. O texto em si também era tão envolvente que fiquei vidrado até o fim
Em especial, a parte “o WindowServer reclamou, e para resolver isso foi preciso escrever manualmente um driver de framebuffer” foi marcante
Fiquei surpreso ao ver a camada de abstração do I/O Kit realmente cumprindo seu papel. Palmas para os desenvolvedores da NeXT
Não tenho experiência com desenvolvimento de drivers em outras plataformas, então é difícil comparar, mas estruturalmente achei bem atraente
No passado, desenvolvedores do NetBSD chegaram a rodar o PPC Darwin sobre uma camada de compatibilidade Mach/IOKit e até subir o Xquartz. Acho interessante que o NetBSD traduzia as chamadas do IOKit
Ainda é difícil acreditar que tantos sistemas operacionais rodam no Wii
Na verdade, a diferença entre uma boa abstração e uma abstração ruim depende de quão bem ela foi explicada
A engenharia em si já é incrível, mas o que realmente me impressionou foi o fato de o autor estar desenvolvendo na classe econômica
(Olhando melhor, a primeira foto era no ônibus e a segunda no avião)
Como autor do port do NetBSD para Wii e Wii U, envio meus sinceros parabéns por este projeto
Estou ansioso para ver quais problemas surgiram e como foram resolvidos
Antigamente eu também era um fã hardcore de Mac e até cheguei a criar “apps de iOS” não oficiais nos primórdios por engenharia reversa
Mas este projeto supera tudo isso. Não é só surpreendente ver o MacOS rodando no Wii; o próprio texto é extremamente refinado e interessante
Foi a primeira vez que descobri que o Wii tem só 88 MB de RAM. Ainda bem que os jogos não eram baseados em elétrons
O requisito mínimo do Vista era 512 MB, mas a maioria dos PCs tinha menos memória do que isso
Hoje em dia, 8 GB já está ficando para trás e 16 GB está virando padrão; o mundo realmente mudou bastante
Antes de começar o projeto, fui verificar se “isso sequer era possível”, e encontrei um comentário no Reddit de 2021 dizendo que havia “0% de chance”
Aquilo acabou me motivando ainda mais. Então comecei analisando o hardware do Wii. Foi realmente engraçado
As pessoas confundem “algo quase impossível” com algo que nunca vai acontecer, e acham que isso faz delas céticas criteriosas
Pensei “será mesmo?” e reconfigurei a porta UART para conectar um ESP32
O problema é que parece não existir o conceito de cinismo ignorante
Estar sentado na classe econômica de um avião depurando um kernel panic no Wii é um nível de concentração que eu nem consigo imaginar
A maioria das pessoas mal consegue ler um livro inteiro no avião
Foi um projeto realmente muito legal. Me lembrou a antiga era de ouro do desenvolvimento de baixo nível
Antigamente era fácil inicializar VGA e desenhar pixels, e chips como o 6502 também eram bem acessíveis
Mas hoje os sistemas ficaram complexos demais, então a barreira de entrada aumentou muito
Além disso, a IA, ao fingir simplificar o desenvolvimento, acaba reduzindo ainda mais a acessibilidade
Eu também estou tentando algo parecido, portando o Mac OS 9 para o Wii U
Fiquei totalmente impressionado com este projeto e sempre que penso “isso é impossível”, volto a ganhar coragem
O texto foi ótimo, mas usar um vídeo
.movcom a tag<video>traz problemas de compatibilidade com navegadoresNão roda no Chrome nem no Firefox