10 điểm bởi GN⁺ 13 ngày trước | 3 bình luận | Chia sẻ qua WhatsApp
  • Hoàn tất dự án port chạy Mac OS X 10.0 (Cheetah) nguyên bản trên phần cứng dựa trên PowerPC của Wii
  • Đã chỉnh sửa nhân Darwin/XNU cho phù hợp với Wii, đồng thời tự viết bootloader, device tree và driver để khởi động thành công tới cả môi trường GUI
  • Triển khai các driver IOKit tùy biến hỗ trợ thẻ SD, framebuffer và thiết bị nhập USB, đạt được hoạt động hệ thống hoàn chỉnh
  • Phản ánh các đặc trưng riêng của Wii như sửa xung đột cấu hình BAT, xây dựng lớp driver cho SoC Hollywood, và framebuffer chuyển đổi RGB→YUV
  • Sau hơn 10 năm thử nghiệm, dự án đã hiện thực hóa việc khởi động và điều khiển hoàn chỉnh Mac OS X trên Wii, chứng minh giá trị của những dự án tưởng như bất khả thi

Tổng quan dự án chạy Mac OS X trên Wii

  • Tiến hành dự án port để chạy Mac OS X 10.0 (Cheetah) nguyên bản trên Nintendo Wii
  • Trước đó Wii đã từng có các bản port như Linux, NetBSD, Windows NT, và lần này được bổ sung thêm Mac OS X
  • Tận dụng phần cứng dựa trên PowerPC của Wii để chạy nhân Darwin/XNU, đồng thời tự viết các driver và bootloader cần thiết
  • Kết quả là đã khởi động hoàn chỉnh tới môi trường GUI của Mac OS X trên Wii, hỗ trợ cả nhập liệu bằng bàn phím và chuột

Khảo sát tính khả thi

  • CPU PowerPC 750CL của Wii là phiên bản kế nhiệm của PowerPC 750CXe từng dùng trong G3 iMac/iBook, nên không có vấn đề về tương thích CPU
  • 88MB RAM của Wii (MEM1 24MB + MEM2 64MB) thấp hơn yêu cầu chính thức (128MB), nhưng qua thử nghiệm QEMU đã xác nhận có thể khởi động ngay cả với 64MB
  • Phần cứng được hỗ trợ gồm USB Gecko (debug serial), thẻ SD, bộ điều khiển ngắt, xuất hình framebuffer, và cổng USB
  • Nếu chỉnh sửa lõi mã nguồn mở Darwin của Mac OS X (nhân XNU, IOKit) cho phù hợp với Wii thì các lớp GUI phía trên cũng có thể hoạt động
  • Wii cho phép chạy mã tự viết thông qua Homebrew ChannelBootMii, nên rất phù hợp cho thí nghiệm port

Cách tiếp cận port

  • Lựa chọn giữa ba chiến lược khởi động:
    1. Port Open Firmware
    2. Port BootX
    3. Tự viết bootloader tùy biến
  • Đã viết mới một bootloader dành riêng cho Wii để thực hiện khởi tạo phần cứng, nạp nhân, tạo device tree, và chuyển quyền điều khiển cho nhân
  • Sau khi nhân bắt đầu chạy, mã bootloader không còn cần thiết; các bước tiếp theo tập trung chủ yếu vào vá nhân và viết driver

Viết bootloader

  • Dựa trên mã ví dụ ppcskel để triển khai khởi tạo Wii cùng các chức năng thẻ SD, framebuffer và debug USB
  • Nạp nhân XNU ở định dạng Mach-O vào bộ nhớ rồi nhảy tới entry point được chỉ định để thực thi
  • Chèn bản vá nhấp nháy LED để theo dõi giai đoạn đi vào nhân và xác nhận nhân có thực sự chạy hay không
  • Lần theo đường thực thi của nhân và xác nhận phát sinh ngoại lệ 300 ở bước device_tree.c → nhận ra cần phải truyền device tree
  • Tạo và truyền device tree

    • Xây dựng cây tối thiểu hardcode dựa trên cấu trúc phần cứng cố định của Wii (/cpus, /memory)
    • Bao gồm con trỏ device tree trong cấu trúc boot_args để truyền cho nhân
    • Sau đó nhân nhận diện cây đúng cách và tiếp tục khởi động bình thường

Vá nhân

  • Thiết lập BAT (Block Address Translation) của XNU xung đột với sơ đồ bộ nhớ của Wii nên cần sửa mã nguồn nhân
  • Dựng hệ thống build nhân trong môi trường khách Mac OS X Cheetah (QEMU)
  • Thêm chỉnh sửa BATchuyển hướng đầu ra console sang USB Gecko để phục vụ debug
  • Sau đó bộ nhớ ảo, IOKit và hệ thống con BSD đều khởi tạo bình thường
  • Trong log khởi động xuất hiện thông báo “Still waiting for root device” → xác nhận cần có driver thẻ SD

Viết driver

  • Tìm hiểu cấu trúc IOKit

    • IOKit là framework mở rộng nhân dựa trên C++, biểu diễn phân tầng phần cứng qua cấu trúc driver-nub
    • Ví dụ: IOPCIBridgeIOPCIDeviceSomeEthernetCardIOEthernetInterface
    • Wii dùng cấu trúc SoC (Hollywood) chứ không phải bus PCI, nên cần driver tùy biến thay thế IOPCIFamily
  • Driver Hollywood

    • Viết driver NintendoWiiHollywood, khớp với node “hollywood” trong device tree
    • Tạo và đăng ký nub NintendoWiiHollywoodDevice để biểu diễn phần cứng cấp dưới
    • Nhờ đó các driver thiết bị con như thẻ SD có thể gắn vào
  • Driver thẻ SD

    • Kế thừa IOBlockStorageDevice để hiện thực truy cập thẻ SD trên Wii
    • Giao tiếp với thẻ SD bằng các lệnh IPC của MINI (đồng xử lý Starlet) như IPC_SDMMC_SIZE, READ, WRITE
    • Dùng bộ đệm bộ nhớ không cache để giải quyết vấn đề bộ nhớ cache
    • Đã tạo thành công nub IOMedia, cho phép nhận diện filesystem gốc và khởi động hoàn chỉnh
    • Xác nhận BSD root: disk0s4 trong log khởi động
  • Driver framebuffer

    • Kế thừa IOFramebuffer và chỉ định vùng MEM1 (0x01700000) của Wii làm framebuffer
    • Trả về true cho isConsoleDevice() để chuyển giữa console văn bản ban đầu và GUI
    • Phần cứng video của Wii dùng định dạng YUV, nên đã triển khai framebuffer kép để chuyển đổi RGB→YUV
    • Vòng lặp chuyển đổi màu chạy ở 60Hz → xuất GUI với màu sắc chính xác thành công
  • Hỗ trợ nhập USB

    • Thử sử dụng AppleUSBOHCI để điều khiển bộ điều khiển USB 1.1 OHCI của Wii
    • Vấn đề 1: không có mã nguồn IOUSBFamily nên không thể debug
    • Vấn đề 2: phụ thuộc vào IOPCIDevice, nên phải viết NintendoWiiHollywoodPCIDevice giả cho Wii
    • Vấn đề 3: khác biệt endian (Wii là reversed-little-endian), nên cần bỏ phần byte-swap bằng phần mềm
    • Sau khi tìm được mã nguồn IOUSBFamily cho Mac OS X Cheetah qua IRC, dự án đã sửa và build thành công
    • Kết quả là bàn phím và chuột USB hoạt động, biến Wii thành một hệ thống Mac OS X hoàn chỉnh

Cải tiến bootloader và nhân

  • Cải tiến bootloader

    • Thêm quét phân vùng thẻ SD và menu khởi động, hiện thực phân tích Apple Partition Map (APM)
    • Nạp kernel extension (kext) từ bootloader và đăng ký vào node /chosen/memory-map
    • Nhờ đó có thể khởi động bằng ảnh cài đặt Mac OS X chưa chỉnh sửa
  • Đơn giản hóa nhân

    • Giảm thiểu các chỉnh sửa đặc thù cho Wii trong nhân:
    • sửa cấu hình BAT
    • nhận diện địa chỉ I/O dựa trên node “hollywood”
    • sửa tính nhất quán cache của framebuffer
    • tách driver ra ngoài nhân để cải thiện hiệu quả build và khả năng bảo trì

Kết thúc

  • Dự án được ấp ủ từ thời đại học năm 2013 và hoàn thành sau hơn 10 năm
  • Thử thách này được truyền cảm hứng từ trường hợp port Windows NT lên Wii
  • Kết quả cuối cùng là đạt được khởi động hoàn chỉnh Mac OS X 10.0 và thao tác GUI trên Wii
  • Nhấn mạnh bài học rằng “những dự án càng có vẻ bất khả thi thì càng đáng để thử sức”

3 bình luận

 

Bài viết hấp dẫn, mà người viết cũng thật tuyệt vời….

 

Đúng là fan cuồng trong các fan cuồng thì phải là dân Tây mới ghê..

 
Ý kiến trên Hacker News
  • Dự án này thực sự là một công trình đáng kinh ngạc. Bài viết cũng cuốn hút đến mức đọc say mê từ đầu đến cuối
    Đặc biệt ấn tượng với đoạn: “WindowServer tỏ ra không hài lòng, và để giải quyết điều đó thì phải tự viết driver framebuffer”
    Tôi ngạc nhiên khi thấy lớp trừu tượng hóa I/O Kit của macOS thực sự làm đúng vai trò của nó. Xin dành lời khen cho các nhà phát triển NeXT

    • Tôi cũng có cảm giác tương tự. Với tư cách là người lần đầu viết driver, đường cong học tập khá dốc, nhưng khi thấy hệ thống thực sự sống dậy thì tôi đã hiểu được cách tiếp cận của IOKit
      Tôi không có kinh nghiệm phát triển driver trên nền tảng khác nên khó so sánh, nhưng về mặt cấu trúc thì nó khá hấp dẫn
    • Tôi được biết IOKit là thứ được xây mới hoàn toàn cho OS X, còn thời NeXT thì họ dùng một mô hình khác là DriverKit
      Trước đây, các nhà phát triển NetBSD từng chạy được PPC Darwin trên lớp tương thích Mach/IOKit và còn khởi chạy cả Xquartz. Việc NetBSD dịch các lệnh gọi IOKit là một điểm rất thú vị
    • Nó cũng có nhiều điểm tương đồng với stack của Linux, nên tôi định xem qua dự án Linux on Wii để so sánh cách họ xử lý vấn đề framebuffer
      Vẫn thật khó tin là có nhiều hệ điều hành chạy được trên Wii đến vậy
    • Có lẽ kinh nghiệm từ thời OPENSTEP, khi phải nhắm đến nhiều kiến trúc và hệ điều hành khác nhau, đã giúp ích cho kiểu trừu tượng hóa này
    • Tôi đồng ý với nhận xét rằng “thật đáng kinh ngạc khi MacOS được trừu tượng hóa tốt đến vậy”
      Thực ra khác biệt giữa một lớp trừu tượng tốt và một lớp trừu tượng tệ nằm ở chỗ nó được giải thích tốt đến mức nào
  • Bản thân công trình kỹ thuật đã quá ấn tượng, nhưng điều thực sự khiến tôi kinh ngạc là tác giả lại phát triển dự án khi ngồi ghế phổ thông

    • Với tôi thì ngay cả việc dùng laptop tử tế trên ghế phổ thông còn khó, huống chi lại còn kết nối cả Wii để debug, thật không thể tin nổi
    • Trước đây Apple từng làm một quảng cáo về việc chỉnh sửa video trên máy bay (liên kết YouTube)
    • Người ngồi cạnh chắc chỉ liếc qua rồi nghĩ “cái gì thế kia nhỉ?” và tiếp tục nhìn điện thoại. Nếu là tôi thì chắc không nhịn được mà phải hỏi
    • Nhìn ảnh thì giống xe buýt mà cũng giống máy bay. Dù sao đi nữa, việc mang theo Wii để phát triển khi đang di chuyển là bằng chứng của sự tập trung và cống hiến phi thường
      (Xem kỹ lại thì ảnh đầu là xe buýt, ảnh thứ hai là máy bay)
    • Thật đáng kinh ngạc khi có thể đắm chìm vào một dự án phức tạp như vậy trong lúc đang di chuyển. Tôi xem lại ảnh thì thấy cũng có thể là tàu hoặc xe buýt. Dù thế nào thì vẫn là một màn khoe đẳng cấp quá mạnh
  • Với tư cách là tác giả bản port NetBSD cho Wii và Wii U, tôi xin gửi lời chúc mừng chân thành tới dự án này
    Tôi rất mong được xem họ đã giải quyết các vấn đề như thế nào

    • Bản port của bạn là nguồn cảm hứng rất lớn. Cảm ơn vì đã đóng góp nhiều cho lĩnh vực này
  • Trước đây tôi cũng từng là một fan Mac cực kỳ hardcore, thậm chí còn từng tạo ra những “ứng dụng iOS” không chính thức thời kỳ đầu bằng kỹ thuật reverse engineering
    Nhưng dự án lần này vượt xa tất cả những điều đó. Không chỉ việc chạy MacOS trên Wii đã đáng kinh ngạc, mà bản thân bài viết còn cực kỳ tinh tế và lôi cuốn

    • Cảm ơn những lời tốt đẹp :)
  • Đây là lần đầu tôi biết Wii chỉ có 88MB RAM. May mà game không chạy bằng điện tử

    • Một chi tiết lịch sử thú vị là Windows Vista cũng ra mắt ở Bắc Mỹ đúng vào cùng tháng Wii phát hành
      Cấu hình tối thiểu của Vista là 512MB, trong khi phần lớn PC lúc đó còn có ít RAM hơn mức đó
      Bây giờ thì 8GB đang dần trở nên ít, còn 16GB lại thành tiêu chuẩn, đúng là thời thế đã thay đổi nhiều
    • Thật buồn cười khi menu cài đặt của Wii lại là các trang web HTML. Ngay cả console năm 2006 cũng không thoát khỏi bàn tay của web
  • Trước khi bắt đầu dự án, tôi đã kiểm tra xem “liệu chuyện này có khả thi không?”, thì thấy một bình luận trên Reddit năm 2021 nói là “khả năng 0%
    Thấy vậy lại càng có động lực hơn. Thế là tôi bắt đầu bằng cách phân tích phần cứng của Wii. Thật sự rất buồn cười

    • Giá trị của những dự án như thế này là ở chỗ chúng đóng khung vĩnh viễn các tuyên bố kiểu “hoàn toàn không thể”
      Mọi người thường nhầm lẫn giữa ‘một việc gần như bất khả thi’ với ‘một việc chắc chắn sẽ không bao giờ xảy ra’, rồi tưởng mình chỉ đang hoài nghi có nguyên tắc
    • Tôi nhớ tới một câu đùa cũ về Linux. Đừng hỏi “làm X trên Linux thế nào?”, mà hãy nói “trên Linux không thể làm X”, rồi sẽ có ai đó lập tức chỉ cho bạn cách làm
    • Tôi cũng bắt đầu một dự án vì nhìn thấy câu “không thể thêm BLE hay WiFi” trong tài liệu của Adafruit MacroPad
      Tôi đã nghĩ “thật vậy sao?” rồi cấu hình lại cổng UART để gắn ESP32 vào
    • Cảnh debug kiểu “mọi thứ đều màu magenta” cũng rất buồn cười
    • Rất nhiều người bình luận trên internet kiểu này nhầm lẫn sự mỉa mai với sự sắc sảo trí tuệ
      Vấn đề là họ không thừa nhận rằng tồn tại kiểu mỉa mai đến từ thiếu hiểu biết
  • Việc vừa debug kernel panic trên Wii vừa ngồi ở ghế phổ thông trên máy bay cho thấy một mức độ tập trung khó mà tưởng tượng nổi
    Đa số mọi người còn thấy khó để đọc hết một cuốn sách trên máy bay nữa là

  • Dự án thật sự quá tuyệt. Nó gợi nhớ tới thời hoàng kim của phát triển cấp thấp
    Ngày xưa việc khởi tạo VGA rồi vẽ pixel khá dễ, còn những con chip như 6502 cũng rất dễ tiếp cận
    Nhưng ngày nay hệ thống đã trở nên quá phức tạp nên rào cản gia nhập cao hơn nhiều
    Hơn nữa, AI còn đang giả vờ đơn giản hóa việc phát triển trong khi thực tế lại làm giảm tính tiếp cận hơn nữa

  • Tôi cũng đang thử port Mac OS 9 sang Wii U
    Xem dự án này xong tôi thực sự bị truyền cảm hứng, và mỗi khi nghĩ rằng “chuyện này là không thể” thì tôi lại có thêm can đảm

    • Quá tuyệt. Mac OS 9 là mã nguồn đóng, nên chắc đây sẽ là một thử thách còn khó hơn nữa
    • Việc không có mã nguồn XNU hay Darwin đúng là bất lợi, nhưng có thể bù đắp bằng mã nguồn System 7.1 bị rò rỉ, Ghidra và các công cụ như MCP. Chúc may mắn
  • Bài viết rất hay, nhưng việc nhúng video .mov bằng thẻ <video> có vấn đề về tương thích trình duyệt
    Nó không phát được trên Chrome hay Firefox

    • Nếu Chrome và Firefox đều không chạy được thì coi như gần như không chạy được trên mọi trình duyệt rồi
    • Cảm ơn! Tôi đã sửa rồi