10 pontos por GN⁺ 22 일 전 | 3 comentários | Compartilhar no WhatsApp
  • 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:
    1. Portar o Open Firmware
    2. Portar o BootX
    3. 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_args e passado ao kernel
    • Depois disso, o kernel passou a reconhecer corretamente a árvore e prosseguiu com o boot

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: IOPCIBridgeIOPCIDeviceSomeEthernetCardIOEthernetInterface
    • 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 NintendoWiiHollywoodDevice que representam o hardware subordinado
    • Isso permite conectar drivers de dispositivos abaixo dele, como o do cartão SD
  • 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
  • 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() retorna true
    • 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
  • Suporte a entrada USB

    • Houve tentativa de usar AppleUSBOHCI para 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 NintendoWiiHollywoodPCIDevice falso 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

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

 
ffdd270 22 일 전

Que texto delicioso, e que autor incrível....

 
jjpark78 22 일 전

Dizem que os mais nerds entre os nerds são os gringos mesmo...

 
GN⁺ 22 일 전
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

    • Senti algo parecido. Como era minha primeira vez escrevendo um driver, a curva de aprendizado foi íngreme, mas ao ver o sistema ganhar vida consegui entender a abordagem do IOKit
      Não tenho experiência com desenvolvimento de drivers em outras plataformas, então é difícil comparar, mas estruturalmente achei bem atraente
    • Pelo que ouvi, o IOKit foi criado do zero especificamente para o OS X, e na época da NeXT usavam outro modelo chamado DriverKit
      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
    • Há muitos pontos parecidos com a pilha do Linux, então estou pensando em olhar o projeto Linux on Wii para comparar como eles lidaram com o problema do framebuffer
      Ainda é difícil acreditar que tantos sistemas operacionais rodam no Wii
    • A experiência acumulada desde a era do OPENSTEP, mirando várias arquiteturas e sistemas operacionais, provavelmente ajudou nessa abstração
    • Concordo com a frase “é surpreendente como o MacOS é bem abstraído”
      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

    • Para mim já é difícil usar um notebook direito na classe econômica; não consigo acreditar que ele ainda conectou um Wii para depurar
    • Há um anúncio antigo da Apple sobre editar dentro de um avião (link do YouTube)
    • A pessoa sentada ao lado provavelmente estava só olhando para o celular pensando “o que é isso?”. Se fosse eu, não ia conseguir resistir e perguntaria
    • Pela foto, parecia ônibus em uma imagem e avião em outra. De qualquer forma, desenvolver carregando um Wii durante o deslocamento é prova de enorme foco e dedicação
      (Olhando melhor, a primeira foto era no ônibus e a segunda no avião)
    • É impressionante conseguir mergulhar num projeto tão complexo durante uma viagem. Olhei as fotos de novo e talvez pareça trem ou ônibus. De qualquer jeito, é um baita flex
  • 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

    • Seu port foi uma grande inspiração. Obrigado por tantas contribuições nessa área
  • 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

    • Obrigado pelas palavras gentis :)
  • 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

    • Um fato histórico curioso é que o Windows Vista também saiu na América do Norte no mesmo mês em que o Wii foi lançado
      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
    • É engraçado que o menu de configurações do Wii era feito de páginas HTML. Nem um console de 2006 escapou das garras da web
  • 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

    • O valor desses projetos está justamente em eternizar esse tipo de declaração de “absolutamente impossível”
      As pessoas confundem “algo quase impossível” com algo que nunca vai acontecer, e acham que isso faz delas céticas criteriosas
    • Isso me lembrou uma velha piada sobre Linux. Em vez de perguntar “como faço X no Linux?”, bastava dizer “X é impossível no Linux” e alguém aparecia imediatamente para mostrar como fazer
    • Eu também comecei um projeto depois de ver na documentação do MacroPad da Adafruit a frase dizendo que “não dá para adicionar BLE nem Wi‑Fi”
      Pensei “será mesmo?” e reconfigurei a porta UART para conectar um ESP32
    • A cena de depuração em que “tudo está magenta” também foi divertida
    • Muita gente que comenta na internet confunde esse tipo de cinismo com insight
      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

    • Muito legal. O Mac OS 9 tem código-fonte fechado, então parece um desafio ainda maior
    • Não ter o código-fonte do XNU ou do Darwin é uma desvantagem, mas ferramentas como o código-fonte vazado do System 7.1, Ghidra e MCP podem ajudar a compensar isso. Boa sorte
  • O texto foi ótimo, mas usar um vídeo .mov com a tag <video> traz problemas de compatibilidade com navegadores
    Não roda no Chrome nem no Firefox

    • Se não funciona no Chrome e no Firefox, na prática dá para considerar que não funciona em quase navegador nenhum
    • Obrigado! Já corrigi