- 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 Channel và BootMii, 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:
- Port Open Firmware
- Port BootX
- 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 BAT và chuyể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ụ:
IOPCIBridge → IOPCIDevice → SomeEthernetCard → IOEthernetInterface
- 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 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
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ị
Vẫn thật khó tin là có nhiều hệ điều hành chạy được trên Wii đế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
(Xem kỹ lại thì ảnh đầu là xe buýt, ảnh thứ hai là máy bay)
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
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
Đâ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ử
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
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
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 đã nghĩ “thật vậy sao?” rồi cấu hình lại cổng UART để gắn ESP32 vào
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
Bài viết rất hay, nhưng việc nhúng video
.movbằng thẻ<video>có vấn đề về tương thích trình duyệtNó không phát được trên Chrome hay Firefox