10 คะแนน โดย GN⁺ 22 일 전 | 3 ความคิดเห็น | แชร์ทาง WhatsApp
  • โปรเจ็กต์พอร์ตที่ทำให้ Mac OS X 10.0 (Cheetah) ทำงานแบบเนทีฟบน ฮาร์ดแวร์ฐาน PowerPC ของ Wii เสร็จสมบูรณ์
  • ปรับแก้ เคอร์เนล Darwin/XNU ให้เข้ากับ Wii และเขียน บูตโหลดเดอร์, device tree, ไดรเวอร์ ขึ้นเองจนบูตเข้า GUI ได้สำเร็จ
  • พัฒนา ไดรเวอร์ IOKit แบบคัสตอมที่รองรับ SD card, framebuffer, อุปกรณ์รับข้อมูลผ่าน USB จนระบบทำงานได้ครบถ้วน
  • สะท้อนโครงสร้างเฉพาะของ Wii เช่น การแก้ปัญหาการชนกันของการตั้งค่า BAT, การสร้างชั้นไดรเวอร์สำหรับ Hollywood SoC, framebuffer แปลง RGB→YUV
  • หลังจากพยายามมานานกว่าสิบปี ก็ทำให้ Mac OS X บูตเต็มรูปแบบและใช้งานได้บน Wii สำเร็จ พร้อมพิสูจน์คุณค่าของการท้าทายในโปรเจ็กต์ที่ดูเหมือนเป็นไปไม่ได้

ภาพรวมโปรเจ็กต์รัน Mac OS X บน Wii

  • ดำเนินโปรเจ็กต์พอร์ต Mac OS X 10.0 (Cheetah) ให้รันแบบเนทีฟบน Nintendo Wii
  • ก่อนหน้านี้ Wii เคยมีกรณีพอร์ต OS อย่าง Linux, NetBSD, Windows NT มาแล้ว และครั้งนี้ได้เพิ่ม Mac OS X เข้ามา
  • ใช้ ฮาร์ดแวร์ฐาน PowerPC ของ Wii เพื่อรัน เคอร์เนล Darwin/XNU และเขียน ไดรเวอร์กับบูตโหลดเดอร์ ที่จำเป็นขึ้นเอง
  • ผลลัพธ์คือสามารถบูต Wii เข้า สภาพแวดล้อม GUI ของ Mac OS X ได้สมบูรณ์ และรองรับอินพุตจากคีย์บอร์ดกับเมาส์

การตรวจสอบความเป็นไปได้

  • CPU PowerPC 750CL ของ Wii เป็นรุ่นต่อจาก PowerPC 750CXe ที่ใช้ใน G3 iMac/iBook จึงไม่มีปัญหาเรื่องความเข้ากันได้ของ CPU
  • RAM 88MB ของ Wii (MEM1 24MB + MEM2 64MB) น้อยกว่าข้อกำหนดทางการ (128MB) แต่ทดสอบด้วย QEMU แล้วยืนยันได้ว่ายังบูตได้แม้มีเพียง 64MB
  • ฮาร์ดแวร์ที่รองรับมี USB Gecko (ดีบักผ่านซีเรียล), SD card, interrupt controller, วิดีโอเอาต์พุตผ่าน framebuffer, พอร์ต USB
  • หากปรับแกนโอเพนซอร์สของ Mac OS X คือ Darwin (เคอร์เนล XNU, IOKit) ให้เข้ากับ Wii ได้ ก็มีโอกาสให้ชั้น GUI ด้านบนทำงานได้เช่นกัน
  • Wii สามารถ รันโค้ดที่พัฒนาเอง ได้ผ่าน Homebrew Channel และ BootMii จึงเหมาะกับการทดลองพอร์ต

แนวทางการพอร์ต

  • เลือกจาก 3 กลยุทธ์การบูต:
    1. พอร์ต Open Firmware
    2. พอร์ต BootX
    3. เขียนบูตโหลดเดอร์คัสตอมขึ้นเอง
  • เขียนบูตโหลดเดอร์เฉพาะสำหรับ Wii ใหม่ เพื่อทำหน้าที่ เริ่มต้นฮาร์ดแวร์, โหลดเคอร์เนล, สร้าง device tree, ส่งต่อการควบคุมให้เคอร์เนล
  • หลังเคอร์เนลเริ่มทำงาน โค้ดของบูตโหลดเดอร์ก็ไม่จำเป็นอีกต่อไป จากนั้นงานจึงเน้นไปที่ การแพตช์เคอร์เนลและเขียนไดรเวอร์

การเขียนบูตโหลดเดอร์

  • ใช้โค้ดตัวอย่าง ppcskel เป็นฐาน แล้วเพิ่มการเริ่มต้นระบบของ Wii และความสามารถด้าน SD card, framebuffer, USB debugging
  • โหลดเคอร์เนล XNU ซึ่งอยู่ในรูปแบบ Mach-O เข้าไปในหน่วยความจำ แล้วกระโดดไปยัง entry point ที่กำหนดเพื่อเริ่มทำงาน
  • เพื่อยืนยันว่าเคอร์เนลเริ่มทำงานจริง มีการใส่ แพตช์ให้ LED กะพริบ เพื่อติดตามขั้นตอนการเข้าเคอร์เนล
  • ย้อนรอยเส้นทางการทำงานของเคอร์เนลแล้วพบว่าเกิด 300 exception ในขั้น device_tree.c → จึงตระหนักว่าจำเป็นต้อง ส่ง device tree ให้เคอร์เนล
  • การสร้างและส่ง device tree

    • สร้าง tree ขั้นต่ำแบบฮาร์ดโค้ด จากโครงสร้างฮาร์ดแวร์คงที่ของ Wii (/cpus, /memory)
    • ใส่ pointer ของ device tree ไว้ในโครงสร้าง boot_args แล้วส่งให้เคอร์เนล
    • หลังจากนั้นเคอร์เนลก็รู้จัก tree ได้ถูกต้องและดำเนินการบูตต่อไป

การแพตช์เคอร์เนล

  • การตั้งค่า BAT (Block Address Translation) ของ XNU ชนกับ memory map ของ Wii จึงจำเป็นต้องแก้ซอร์สของเคอร์เนล
  • จัดเตรียมระบบบิลด์เคอร์เนลในสภาพแวดล้อม Mac OS X Cheetah guest (QEMU)
  • หลัง แก้ BAT และเพิ่มการ redirect เอาต์พุตคอนโซลไปยัง USB Gecko ก็สามารถดีบักได้
  • จากนั้น virtual memory, IOKit, BSD subsystem ก็เริ่มต้นได้ตามปกติ
  • ในล็อกการบูตพบข้อความ “Still waiting for root device” → ยืนยันว่าจำเป็นต้องมี ไดรเวอร์ SD card

การเขียนไดรเวอร์

  • ทำความเข้าใจโครงสร้าง IOKit

    • IOKit เป็นเฟรมเวิร์กส่วนขยายเคอร์เนลที่พัฒนาด้วย C++ และใช้โครงสร้างแบบ driver-nub เพื่อแทนลำดับชั้นของฮาร์ดแวร์
    • ตัวอย่าง: IOPCIBridgeIOPCIDeviceSomeEthernetCardIOEthernetInterface
    • Wii ใช้โครงสร้าง SoC (Hollywood) ไม่ใช่ PCI bus จึงต้องมีไดรเวอร์คัสตอมมาแทน IOPCIFamily
  • ไดรเวอร์ Hollywood

    • เขียนไดรเวอร์ NintendoWiiHollywood ให้จับคู่กับโหนด “hollywood” ใน device tree
    • สร้างและลงทะเบียน nub NintendoWiiHollywoodDevice เพื่อแทนฮาร์ดแวร์ชั้นล่าง
    • ทำให้ไดรเวอร์ของอุปกรณ์ย่อยอย่าง SD card สามารถเชื่อมต่อเข้ามาได้
  • ไดรเวอร์ SD card

    • สืบทอดจาก IOBlockStorageDevice เพื่อทำการเข้าถึง SD card ของ Wii
    • ใช้ คำสั่ง IPC ของ MINI (Starlet coprocessor) (IPC_SDMMC_SIZE, READ, WRITE) ในการสื่อสารกับ SD card
    • แก้ปัญหาเรื่องหน่วยความจำแบบแคชด้วยการใช้ บัฟเฟอร์หน่วยความจำแบบไม่แคช
    • สร้าง IOMedia nub ได้สำเร็จ ทำให้ รู้จัก root filesystem และบูตได้สมบูรณ์
    • ในล็อกการบูตยืนยันด้วย BSD root: disk0s4
  • ไดรเวอร์ framebuffer

    • สืบทอดจาก IOFramebuffer และกำหนด พื้นที่ MEM1 (0x01700000) ของ Wii เป็น framebuffer
    • เพื่อรองรับทั้ง text console ตอนต้นและการสลับไป GUI จึงให้ isConsoleDevice() คืนค่า true
    • ฮาร์ดแวร์วิดีโอของ Wii ใช้ ฟอร์แมต YUV จึงสร้าง double framebuffer สำหรับแปลง RGB→YUV
    • ใช้ลูปแปลงสีที่ 60Hz → แสดงผล GUI ด้วยสีที่ถูกต้องได้สำเร็จ
  • รองรับอินพุตผ่าน USB

    • พยายามใช้ AppleUSBOHCI เพื่อขับ คอนโทรลเลอร์ OHCI USB 1.1 ของ Wii
    • ปัญหา 1: ไม่มีซอร์สของ IOUSBFamily จึงดีบักไม่ได้
    • ปัญหา 2: พึ่งพา IOPCIDevice จึงต้องเขียน NintendoWiiHollywoodPCIDevice ปลอมสำหรับ Wii
    • ปัญหา 3: endianness ไม่ตรงกัน (Wii เป็น reversed-little-endian) จึงต้องเอาการ byte-swap แบบซอฟต์แวร์ออก
    • หลังได้ซอร์ส IOUSBFamily สำหรับ Mac OS X Cheetah ผ่าน IRC ก็สามารถแก้ไขและบิลด์ได้สำเร็จ
    • ผลลัพธ์คือ คีย์บอร์ดและเมาส์ USB ใช้งานได้ ทำให้ Wii ทำงานเป็นระบบ Mac OS X ที่สมบูรณ์

การปรับปรุงบูตโหลดเดอร์และเคอร์เนล

  • การปรับปรุงบูตโหลดเดอร์

    • เพิ่ม การค้นหาพาร์ทิชัน SD card และเมนูบูต พร้อมรองรับการพาร์ส Apple Partition Map (APM)
    • โหลด kernel extension (kext) จากบูตโหลดเดอร์ แล้วลงทะเบียนไว้ในโหนด /chosen/memory-map
    • ทำให้สามารถบูตจาก อิมเมจติดตั้ง Mac OS X ที่ไม่ต้องแก้ไข ได้
  • การทำเคอร์เนลให้ง่ายขึ้น

    • ลดการแก้ไขเคอร์เนลเฉพาะ Wii ให้เหลือน้อยที่สุด:
    • แก้การตั้งค่า BAT
    • รับรู้ I/O address จากโหนด “hollywood”
    • แก้ความสอดคล้องของแคชใน framebuffer
    • แยกไดรเวอร์ออกจากเคอร์เนลเพื่อให้บิลด์ได้มีประสิทธิภาพขึ้นและดูแลรักษาได้ง่ายขึ้น

สรุป

  • โปรเจ็กต์ที่วางแผนไว้ตั้งแต่สมัยมหาวิทยาลัยในปี 2013 ได้สำเร็จหลังผ่านไปกว่าสิบปี
  • ได้แรงบันดาลใจจากกรณีพอร์ต Windows NT ลง Wii แล้วตัดสินใจลงมือท้าทาย
  • สุดท้ายสามารถทำให้ Mac OS X 10.0 บูตเต็มรูปแบบและใช้งาน GUI บน Wii ได้
  • ย้ำบทเรียนว่า “โปรเจ็กต์ที่ดูเหมือนเป็นไปไม่ได้ ยิ่งมีคุณค่าที่จะลองท้าทาย”

3 ความคิดเห็น

 
ffdd270 22 일 전

เป็นบทความที่น่าอ่าน พร้อมผู้เขียนที่ยอดเยี่ยมเลยนะ….

 
jjpark78 22 일 전

ในบรรดาคนที่คลั่งไคล้ ยังต้องยกให้สายฝรั่งเป็นที่สุด..

 
GN⁺ 22 일 전
ความคิดเห็นจาก Hacker News
  • โปรเจ็กต์นี้เป็นงานที่ น่าทึ่งมาก ตัวบทความเองก็เขียนได้น่าติดตามจนอ่านเพลินจนจบ
    โดยเฉพาะตรงที่บอกว่า “WindowServer แสดงอาการไม่พอใจ และเพื่อแก้ปัญหานี้จึงต้องเขียนไดรเวอร์ framebuffer ขึ้นมาเอง” ที่ประทับใจมาก
    รู้สึกทึ่งที่ได้เห็นว่า ชั้น abstraction ของ I/O Kit ทำหน้าที่ของมันได้จริง ขอปรบมือให้เหล่านักพัฒนาของ NeXT

    • ฉันก็รู้สึกคล้ายกัน ในฐานะคนที่เพิ่งเขียนไดรเวอร์เป็นครั้งแรก เส้นโค้งการเรียนรู้นั้นชันมาก แต่พอเห็นระบบเริ่มมีชีวิตขึ้นมาจริง ๆ ก็ทำให้เข้าใจแนวทางของ IOKit มากขึ้น
      ฉันไม่มีประสบการณ์พัฒนาไดรเวอร์บนแพลตฟอร์มอื่นเลยเลยเทียบตรง ๆ ไม่ได้ แต่ในเชิงโครงสร้างมันก็ดูน่าสนใจมาก
    • เท่าที่รู้ IOKit ถูกสร้างขึ้นใหม่ตั้งแต่ต้นสำหรับ OS X ส่วนในยุค NeXT ใช้โมเดลอีกแบบที่ชื่อ DriverKit
      เมื่อก่อนเคยมีนักพัฒนา NetBSD รัน PPC Darwin บนชั้นความเข้ากันได้ของ Mach/IOKit จนเปิด Xquartz ได้ด้วย ที่น่าสนใจคือ NetBSD เป็นฝ่ายแปลการเรียก IOKit
    • มันมีหลายอย่างคล้ายกับสแตกของ Linux เหมือนกัน เลยคิดว่าจะไปดู โปรเจ็กต์ Linux on Wii เพื่อเปรียบเทียบว่าเขาจัดการปัญหา framebuffer กันอย่างไร
      ยังรู้สึกไม่อยู่ว่าจะมี OS มากขนาดนี้รันบน Wii ได้
    • ประสบการณ์ตั้งแต่ยุค OPENSTEP ที่ต้องรองรับทั้งหลายสถาปัตยกรรมและหลายระบบปฏิบัติการ น่าจะช่วยเรื่อง abstraction แบบนี้ได้มาก
    • เห็นด้วยกับคำพูดที่ว่า “น่าทึ่งที่ MacOS ถูกทำ abstraction มาได้ดีแค่ไหน”
      จริง ๆ แล้วความต่างระหว่าง abstraction ที่ดีกับแย่ มักขึ้นอยู่กับว่า มันถูกอธิบายไว้ดีแค่ไหน
  • ตัวงานวิศวกรรมก็น่าทึ่งอยู่แล้ว แต่สิ่งที่ประทับใจจริง ๆ คือผู้เขียนกำลัง พัฒนางานอยู่บนที่นั่งชั้นประหยัด

    • แค่ใช้แล็ปท็อปบนที่นั่งชั้นประหยัดให้สะดวกสำหรับฉันก็ยากแล้ว แต่นี่ถึงขั้นต่อ Wii เข้าไปดีบักด้วย ไม่น่าเชื่อเลย
    • ก่อนหน้านี้ Apple เคยทำโฆษณาเรื่องการตัดต่อบนเครื่องบินด้วย (ลิงก์ YouTube)
    • คนที่นั่งข้าง ๆ คงได้แต่มองแล้วคิดว่า “นั่นมันอะไรน่ะ?” พลางก้มดูมือถือไป ถ้าเป็นฉันคงอดถามไม่ได้
    • ดูจากรูปแล้วเหมือนจะเป็นรถบัสบ้าง เครื่องบินบ้าง ไม่ว่าอย่างไร การหิ้ว Wii ไปพัฒนางานระหว่างเดินทางเป็นหลักฐานของ สมาธิและความทุ่มเทระดับสุดยอด
      (ดูเพิ่มแล้ว รูปแรกเป็นรถบัส รูปที่สองเป็นเครื่องบิน)
    • น่าทึ่งที่สามารถจดจ่อกับโปรเจ็กต์ซับซ้อนแบบนี้ได้ระหว่างเดินทาง ดูรูปอีกทีก็เหมือนจะเป็นรถไฟหรือรถบัสเหมือนกัน ยังไงก็ตาม นี่มันการโชว์ของที่โหดมาก
  • ในฐานะ ผู้เขียนพอร์ต NetBSD Wii และ Wii U ผมขอแสดงความยินดีกับโปรเจ็กต์นี้จากใจจริง
    ต่อจากนี้รอติดตามเลยว่าคุณแก้ปัญหาต่าง ๆ อย่างไรบ้าง

    • พอร์ตของคุณเป็นแรงบันดาลใจสำคัญมาก ขอบคุณสำหรับการมีส่วนร่วมมากมายในสายนี้
  • เมื่อก่อนฉันก็เคยเป็นแฟน Mac สายฮาร์ดคอร์ และเคยทำ “แอป iOS” ยุคแรก ๆ แบบไม่เป็นทางการด้วยการย้อนวิศวกรรม
    แต่โปรเจ็กต์นี้เหนือกว่าสิ่งเหล่านั้นทั้งหมด ไม่ใช่แค่การรัน MacOS บน Wii ที่น่าทึ่งเท่านั้น ตัวบทความเองก็ ประณีตและน่าสนใจมาก

    • ขอบคุณสำหรับคำพูดดี ๆ :)
  • เพิ่งรู้ว่า RAM ของ Wii มีแค่ 88MB เท่านั้น ดีแล้วที่เกมพวกนั้นไม่ได้สร้างด้วย Electron

    • เป็นเกร็ดประวัติศาสตร์ที่น่าสนใจเหมือนกันว่า Wii วางขายในเดือนเดียวกับที่ Windows Vista ออกในอเมริกาเหนือ
      ข้อกำหนดขั้นต่ำของ Vista คือ 512MB แต่พีซีส่วนใหญ่ในตอนนั้นมีหน่วยความจำน้อยกว่านั้น
      เดี๋ยวนี้จากที่ 8GB เริ่มไม่พอ กลายเป็น 16GB กำลังจะเป็นมาตรฐาน โลกเปลี่ยนไปมากจริง ๆ
    • ขำตรงที่เมนูตั้งค่าของ Wii ทำเป็น หน้าเว็บ HTML เครื่องเกมปี 2006 ก็ยังหนีอิทธิพลของเว็บไม่พ้น
  • ก่อนเริ่มโปรเจ็กต์ ฉันลองเช็กก่อนว่า “มันพอจะเป็นไปได้ไหม” แล้วไปเจอคอมเมนต์บน Reddit ปี 2021 ที่บอกว่า “โอกาสเป็นศูนย์เปอร์เซ็นต์
    เห็นแล้วกลับยิ่งมีแรงฮึด เลยเริ่มจากการวิเคราะห์ฮาร์ดแวร์ของ Wii มันตลกดีจริง ๆ

    • คุณค่าของโปรเจ็กต์แบบนี้คือการ ตรึงคำพูดว่าไม่มีวันเป็นไปได้ เอาไว้ตลอดกาล
      ผู้คนมักเหมารวมว่าสิ่งที่ “แทบเป็นไปไม่ได้” จะไม่มีวันเกิดขึ้นจริง พร้อมหลงคิดว่าตัวเองเป็นพวกสงสัยอย่างมีหลักการ
    • ทำให้นึกถึงมุก Linux สมัยก่อนว่า อย่าถามว่า “จะทำ X บน Linux ได้อย่างไร?” แต่ให้พูดว่า “Linux ทำ X ไม่ได้หรอก” แล้วเดี๋ยวจะมีคนโผล่มาโชว์วิธีทำทันที
    • ฉันเองก็เริ่มโปรเจ็กต์หนึ่งหลังจากเห็นในเอกสารของ Adafruit MacroPad เขียนว่า “ไม่สามารถเพิ่ม BLE หรือ WiFi ได้”
      ก็เลยคิดว่า “จริงเหรอ?” แล้วคอนฟิกพอร์ต UART ใหม่เพื่อต่อ ESP32 เข้าไป
    • ฉากดีบักที่บอกว่า “ทุกอย่างเป็นสีมาเจนตา” ก็ฮามาก
    • คนคอมเมนต์ตามอินเทอร์เน็ตจำนวนมากชอบ เข้าใจผิดว่าความประชดถากถางคือความฉลาด
      ปัญหาคือไม่มีใครพูดถึงแนวคิดเรื่องความประชดแบบเกิดจากความไม่รู้นัก
  • การนั่งอยู่บนที่นั่งชั้นประหยัดบนเครื่องบินพร้อมดีบัก kernel panic บน Wii ไปด้วยนั้น เป็นระดับของ สมาธิที่นึกภาพแทบไม่ออก
    คนส่วนใหญ่แค่อ่านหนังสือบนเครื่องบินให้จบสักเล่มยังยากเลย

  • เป็นโปรเจ็กต์ที่เท่มาก ทำให้นึกถึง ยุคทองของการพัฒนาระดับล่าง
    สมัยก่อนการ init VGA แล้ววาดพิกเซลลงไปเป็นเรื่องง่าย และชิปอย่าง 6502 ก็เข้าถึงได้ไม่ยาก
    แต่ทุกวันนี้ระบบซับซ้อนขึ้นมากจนกำแพงในการเริ่มต้นสูงขึ้น
    แถม AI ยังทำท่าเหมือนจะทำให้การพัฒนาง่ายลง แต่จริง ๆ แล้วกลับ ทำให้การเข้าถึงยากขึ้นอีก

  • ฉันเองก็กำลังพยายาม พอร์ต Mac OS 9 ไปลง Wii U อยู่เหมือนกัน
    ดูโปรเจ็กต์นี้แล้วประทับใจมาก และทุกครั้งที่เริ่มคิดว่า “มันเป็นไปไม่ได้” ก็กลับได้กำลังใจขึ้นมาอีก

    • สุดยอดมาก Mac OS 9 เป็น ซอร์สแบบปิด ด้วย น่าจะเป็นความท้าทายที่ยิ่งยากกว่าเดิม
    • การไม่มีซอร์สของ XNU หรือ Darwin นับว่าเสียเปรียบ แต่ก็น่าจะพอชดเชยได้ด้วย ซอร์สที่รั่วของ System 7.1, Ghidra และเครื่องมืออย่าง MCP ขอให้โชคดี
  • ตัวบทความยอดเยี่ยมมาก แต่การใส่วิดีโอ .mov ผ่านแท็ก <video> มีปัญหาเรื่อง ความเข้ากันได้ของเบราว์เซอร์
    มันเล่นไม่ได้บน Chrome หรือ Firefox

    • ถ้าใช้ไม่ได้ทั้งบน Chrome และ Firefox ก็แทบจะเท่ากับใช้ไม่ได้บนเบราว์เซอร์เกือบทั้งหมดแล้ว
    • ขอบคุณ! แก้แล้วเรียบร้อย