§1名詞表
這個專案橫跨磁碟、開機、kernel、晶片四個層次,名詞會一直冒出來。 這裡只收會重複出現的,每條一句話,附上「跟這個專案有什麼關係」。
磁碟與分割
| 名詞 | 是什麼 | 跟你的關係 |
|---|---|---|
| 分割區 | 硬碟上切出來的一塊空間,大小固定 | — |
| APFS container | 分割區裡的一大塊硬碟空間,裡面的 volume 共用它、不用事先切死大小 | 裝第二份 macOS 時會建一個新的 |
| volume | container 裡的一個檔案系統 | — |
| volume group | System + Data + Preboot + Recovery 的組合 = 一個 macOS 安裝 | hypervisor 要的 14.8.3 需要一整組,不是單一 volume |
| Preboot | 存放「主系統掛載前就需要的東西」的 volume,每個安裝一個 UUID 資料夾 | 韌體、開機政策、kernelcache 都在這裡 —— 你要挖 kernelcache 就是去這 |
| stub | Asahi 安裝時建的約 2.5GB 迷你 macOS,有殼沒肉、不能開機進去用 | 裡面有韌體 + m1n1 + 開機政策。刪掉 Asahi 就開不了機 |
| ESP(EFI 分割區) | FAT32 分割區,掛在 /boot/efi | 放 GRUB 和 vendorfw/。kernel 不在這裡,在 /boot |
開機鏈
| 名詞 | 是什麼 | 跟你的關係 |
|---|---|---|
| Boot ROM | 燒在矽晶片裡的第一棒,永遠不可改 | 信任鏈的根,你碰不到 |
| iBoot 第一階段 | Apple 韌體,全機共用一份。初始化記憶體、儲存、DFU | — |
| iBoot 第二階段 | 每個 OS 安裝各自一份。載入該 OS 的韌體組、執行它的安全政策 | 這就是為什麼 Asahi 能降安全等級而 macOS 26 不受影響 |
| m1n1 | Asahi 的開機載入器,被註冊成 stub 那個「OS 的 kernel」 | 現在就在你的開機鏈裡。hypervisor 是它的另一種模式,不是新裝的東西 |
| U-Boot | 把 Apple 的特殊環境轉成標準 Linux 開機介面(內含 UEFI 實作) | — |
| GRUB | 讀開機項目清單、顯示選單、載入你選的 kernel | 動手前先讓它顯示出來,否則新 kernel 開不起來沒地方退回 |
| DFU 模式 | 用另一台 Mac 重刷韌體的救援模式,分兩種: revive 只重刷韌體、保留資料;restore 才會清空整顆硬碟 | 最後的安全網。先試 revive,restore 是最後手段(所以還是要備份) |
| ADT | Apple 自己的 device tree 格式,由 iBoot 提供 | m1n1 讀它來認機型、抓執行期數值 |
kernel 與檔案
| 名詞 | 是什麼 | 跟你的關係 |
|---|---|---|
| vmlinuz | 編譯好的 kernel 本體(壓縮過) | 在 /boot/vmlinuz-<版本> |
| initramfs | 開機用的暫時根目錄,讓 kernel 有辦法掛載真正的 rootfs | 必須在 target 機器上產生,不能在 macOS 上做 |
| device tree | 一份硬體清單,告訴 kernel「有哪些區塊、在哪個位址、用哪條中斷」 | ARM 的硬體無法自我介紹,所以必須有人寫下來。DTS 就是逆向成果的存放處 |
| DTB | device tree 編譯後的二進位檔 | 裝 kernel 一定要連 DTB 一起裝,否則新 driver 永遠不會被實體化 |
| BLS / loader entries | /boot/loader/entries/,一顆 kernel 一個 .conf | 裝完看這裡有沒有多一項 = 最快的驗證 |
.config | kernel 的編譯設定檔,幾千個選項 | 一定要從 /boot/config-$(uname -r) 複製當起點 |
| 16K page | 記憶體分頁大小。TLB 涵蓋範圍大四倍,Apple 硬體照這個設計 | 編錯成 4K 會壞掉 —— 從現有 config 起手就自動正確 |
| fairydust | Asahi 的實驗分支,含 USB-C DP 輸出的程式碼 | 官方明說「strictly as-is」,只給開發者、不提供支援。 但 USB-C 出圖只有這裡有 —— #601 的結論就是「換到這個分支就好了」 |
晶片內部
| 名詞 | 是什麼 | 跟你的關係 |
|---|---|---|
| AP | Application Processor —— 跑作業系統的主 CPU 核心 | 「AP call」= 協處理器反過來呼叫作業系統 |
| 協處理器 | SoC 裡的其他 CPU,各自跑自己的韌體 | 一顆 M1 Pro 裡有十幾顆 |
| DCP | 顯示協處理器。在 Mac 裡,跑 Apple 韌體,實際操作顯示硬體 | 斷點 2 的對話對象。你只能透過 mailbox 跟它講話 |
| A13 | 在 Studio Display 裡的一整顆 SoC,管面板、hub、攝影機 | 斷點 2 要叫醒的是它,但做這件事的是 DCP,不是你 |
| atcphy | Type-C PHY,把訊號送上線。driver 直接讀寫它的暫存器 | 斷點 1 的位置(phy/apple/atc.c)。
stable kernel 沒有 DP 這條路,fairydust 有 |
| tipd | USB-PD 控制器,負責協商模式與供電 | 決定協商到 DP Alt Mode 還是 TB |
| ACIO | Apple Converged I/O —— Thunderbolt 那組硬體(含 Cortex-M3) | 路線 B 的核心,Sven 的 22 個 patch 在處理 |
| RTKit | Apple 協處理器共用的通訊協定 | 已逆向完成,多個 driver 共用 |
| DART | Apple 的 IOMMU(記憶體存取保護) | 已上游,16K 粒度 |
| mailbox / AP call | AP 與協處理器之間的雙向訊息機制 | 兩邊都能發起。call 20 是 DCP 問你,不是你問它 |
「韌體」的三種意思
| 種類 | 存在哪 | 例子 |
|---|---|---|
| 燒在矽晶片裡 | 不可改,永久 | Boot ROM |
| 裝置自帶 | 裝置自己的快閃記憶體,可更新但持久 | Studio Display 的 A13、SSD 控制器 |
| 開機時載入 | 平常是磁碟上的檔案,每次開機載進協處理器 | DCP、WiFi、ACIO |
第三種是 Asahi 要從你的 macOS 抓出來的那種,也是「OS-paired firmware」的意思 —— 你的 DCP 韌體來自 macOS 26,跟其他回報者不同。
這個專案的專用說法
| 名詞 | 意思 |
|---|---|
| t8103 / t600x | SoC 代號。t8103 = 原版 M1(你的 mini);t600x = M1 Pro/Max(你的 MBP) |
| target | 被觀測的機器。螢幕插這台,m1n1 和 macOS guest 都在這台 |
| host | 旁觀者。只跑 Python、收資料、印 trace,不影響 target |
| DP Alt Mode | 把 Type-C 的實體通道直接改接成 DisplayPort。不是降級版的 TB,是另一套協定 |
| DSC | Display Stream Compression,顯示串流壓縮。頻寬不夠時靠它擠出高解析度 |
| 斷點 1 / 斷點 2 | 斷點 1 = atcphy 切不進 DP 模式 (已解:換 fairydust,#601 closed);斷點 2 = DCP 的 call 20 沒人會回 (未解,#579 open)。舊版本頁面稱它們為 Bug 1 / Bug 2 |
§2連結索引
兩個斷點(狀態為 2026-09-23 查證)
- #601 —— M1 Pro
atcphy_mux_set/ Failed to lock pipehandler —— closed(2026-09-07,completed)。 同型機(MacBookPro18,3)回報者換到 fairydust 後 USB-C 螢幕點亮; 結論是 stable kernel 的功能缺口,不是 bug。- 他的
.config直接拿現在跑的那顆(/proc/config.gz),需要的符號本來就都開著:CONFIG_DRM_APPLE、CONFIG_PHY_APPLE_ATC、CONFIG_PHY_APPLE_DPTX、CONFIG_MUX_APPLE_DPXBAR、CONFIG_TYPEC_DP_ALTMODE - 裝成獨立的並存 package,stable kernel 留在 GRUB 當退路
- 冷插比熱插可靠 —— 開機前就把螢幕插著
- 他的
- #579 —— Studio Display unhandled AP call 20 —— open,4 則討論。 2026-08-24 由 M2 13"(t8112)回報;thejamescollins 在 M1 Max 16"(t6001)重現, 並在同機用 USB-C→HDMI 轉接頭跑到 4096x2160@60;chadmed 要求的 「full-spec 非 Thunderbolt USB-C 線」測試還沒有人做。
相關 PR(都沒 merge)
- #622 —— Fix external display hotplug on DP alt mode —— closed。關閉理由原文:「developed with LLM assistance (see the Assisted-by: trailers), which the Asahi Generative AI Policy forbids」。程式碼你自己機器上要用沒問題,但不能當成自己的成果送上游。
- #503 —— Fix/atcphy pipehandler —— 仍 open,零討論
- #476 —— dts: Enable dp-altmode for M1 Pro/Max MacBook Pro
—— closed 未 merge。已經不需要了:
fairydust 的
t600x-j314-j316.dtsi本身就#define ENABLE_DCPEXT_TYPEC並接好了typec1。
工具與現成方案
- asahi-fairydust-display —— Fedora Asahi 的自動化 build
- omarchy-fairydust-kernel —— 含 #622 的
-dp622target(Arch,可參考) - Studio Display 的 HDMI 轉接鏈 —— 過渡方案,但只有 4K、預設無音訊
- malik-na/omadora —— 你 MBP 上的環境(Fedora Asahi Remix + Hyprland),內有 External monitor discussion
官方文件
- Running macOS under the m1n1 hypervisor
- m1n1 User Guide
- M1 Series Feature Support
- Contribute(三份政策的入口)
- Generative AI Policy
- kernel-16k 討論
§3材料清單
硬體
- MacBook Pro 14" M1 Pro(
MacBookPro18,3,t600x)—— host, 跑 python proxyclient,同時是最終要修好的那台。 host 只需要能跑 python 和認到 USB 序列裝置;官方文件是以 host OS(macOS / Linux) 區分裝置節點名稱,沒有對 host 的 CPU 設限。你的 host 跑 Linux,所以裝置是/dev/ttyACM0。 - Mac mini M1(t8103)—— target,被觀測的那台。 macOS 14.8.3、降安全模型、關 SIP 都發生在這台。
- Apple Studio Display —— 最終目標。trace 時插在 target(mini)上
- host ↔ target 的 USB 線:先試 Apple 原廠 USB-C 充電線(C-to-C,不要用 Thunderbolt 線); 不順就換 USB-C→USB-A(m1n1 文件建議這種,插 host 的 USB-A 孔)
- 一條 full-spec 非 Thunderbolt 的 USB-C 線 —— 接 Studio Display 用,優先度最高。 chadmed 在 #579 點名要這種線的測試結果,至今沒人做得出來(回報者手上沒有)。 不要 Thunderbolt 線、不要充電線;要標示支援 USB 3.2 / DP Alt Mode 的全規格線。
- ThinkPad X1 Gen 9(可選的 host)—— host 是純終端機,
x86 和 arm64 沒有差別,Asahi 開發者多數就是用 x86 Linux 當 host。
唯一差別是編譯 m1n1 要裝交叉編譯器(
gcc-aarch64-linux-gnu), 而在 Mac 上一樣要裝裸機工具鏈。用它當 host 可以把 MBP 空出來當日常機。 注意:萬一 target 需要 DFU revive,那只能用 Mac 做。 - 一台「笨」螢幕 —— 用來確認「斷點 1 在你機器上真的沒了」,也是階段 3 的對照組。
建議挑同時有 USB-C(DP Alt Mode)和 HDMI 輸入的: USB-C 那孔驗證 fairydust 的 DP 路徑,HDMI 那孔測內建 HDMI 在 macOS 26 韌體下還會不會動,平常還能當第二螢幕。- 必要:USB-C 輸入要標明支援 DP Alt Mode(有些 USB-C 孔只供電或只傳資料)
- ❌ 避開 DisplayLink:它走 USB 資料由 CPU 算圖,完全繞過 DP 路徑 —— 可能真的會出圖,但你什麼都沒測到,還會誤判 DP 路徑已經通了
- ❌ 不要 Apple 的顯示器:有內建處理器就會觸發斷點 2,失去當對照組的意義
- ❌ 沒有「Thunderbolt 專用」這種規格,買普通的就好
- 加分:#601 的回報者就是用 ARZOPA Z1FC 16"(純供電模式)在 M1 Pro 上成功的。 買同一台,等於直接複製一個已知會成功的實驗
- 替代方案:USB-C → HDMI 轉接頭 + 現有的電視,最便宜,一樣避開 DisplayLink
- 外接 SSD(選配)—— 放測試用的 macOS volume,不佔內建空間
軟體與帳號
- Fedora Asahi Remix(已裝,在 host 上)
- macOS 14.8.3(備案 13.5),裝在 target(Mac mini)上一個完整的獨立 volume group。 不要用你現在的 macOS 安裝。你的兩台機器出廠版本都夠舊,macOS 26 不會擋住這件事(見方向 §5)
- m1n1 repo + python proxyclient 相依套件(裝在 host,也就是 MBP 上)
img4tool—— 解 kernelcache- GitHub 帳號 —— 留言、送 PR
- Apple Developer 帳號(選配)—— 下載 KDK 取得帶符號的 kernel。第一次可以不用
firmware 版本要對齊。
Asahi 直接載入 macOS 安裝裡的 DCP firmware,而協議會隨 firmware 版本改變
(driver 裡有針對不同版本的 struct layout)。錄 trace 的版本要跟你 Linux 下跑的同一版。
這是一般 Linux 驅動開發者不會遇到的概念,但它會解釋掉你之後看到的一半怪現象。
要補的知識地圖
MMIO(記憶體映射 I/O)· 中斷 · DMA / IOMMU · clock 與 power domain · device tree · bus 列舉 · 協處理器的 mailbox / RPC · firmware 版本化的 ABI(Asahi 特有)
語言
這個社群大多數人母語都不是英文;你的貢獻內容 —— dmesg、trace dump、
「這樣會動/不會動」—— 是語言中性的;issue tracker 是非同步的,一則訊息花一小時寫沒人在意。
用翻譯工具處理你自己要講的話跟查字典一樣,不涉及 trace 解讀,碰不到政策那條線。
§4日誌
每次動手記一筆:做了什麼、量到什麼、發現什麼、哪裡做得不好、下次從哪裡接。最新的在最上面。
技術細節不寫在這裡 —— 那些整理進實作頁,這裡只留當下的過程和判斷。
2026-09-23 晚 ~ 09-24 凌晨 · 第一次動手
從「這份計畫書該怎麼修」開始,結果一路做到外接螢幕點亮。
一句話結論
冷插完全正常;熱插拔畫面回不來,但套了 #622 之後不會再卡住整台電腦。
剩下的卡點在合成器:一個永遠等不到完成的 page flip 把 aquamarine 鎖死了。
做了什麼
- 查證計畫書的前提,發現 #601 已在 2026-09-07 結案 —— 原本「兩個 bug、先解 Bug 1」的框架不成立了。 整份計畫書依此改寫,六張圖用 archify 重新產生
- 讀完 build 腳本(600 行)。確認 kernel 原始碼是執行時從上游 clone、
.config抄本機的、README 講的第 9 步在main()裡是註解掉的 - 跑 build。第一次
--filter=blob:none的 clone 空等三分鐘零 bytes(GitHub 在算 pack), 改用--depth 1才動。編譯本身 60~90 分鐘 - 開機設定:
asahi-bless --set-boot fedora(預設不再開進 macOS)、grubby --set-default指到 fairydust、把 GRUB 選單叫回來 - 第一次插螢幕沒反應 —— 插到左後那孔了。查 device tree 的 connector label
才確認 DP 只在
usb-pd@3f= USB-C Left Front - 換孔,亮了。MSI MAG161V,1920x1080@60,Hyprland 正常接手
- 測熱插拔 → 不亮,而且整台卡住幾十秒
- 診斷後找到 #622,確認能乾淨套用到現在的 tree
- 白做了一輪:中途跑過
git apply -R把 patch 退掉卻沒發現, 裝上去的是沒 patch 的模組,測出來當然跟原本一樣 - 重套、驗證
.ko裡真的有 patch 的字串、重裝、重測 - 結果:不卡了,但畫面還是回不來。追到
hyprland.log才看清楚原因
量到的東西
| 指標 | #622 前 | #622 後 |
|---|---|---|
| 冷插(開機前就插著)會不會亮 | ✅ 會 | ✅ 會 |
atcphy_mux_set WARNING | 有 | 沒有了 |
flip_done timed out | 2 次 | 0 次 |
AFK[ep:28]: too many enabled services! | 有 | 沒有了,改成正常的 new service DCPDPService on channel 17/19 |
| 熱插拔後畫面回來 | ❌ | ❌ 還是不會 |
| 熱插拔時整台卡住 | 卡數十秒 | 不卡 |
也就是 #622 在 t600x 上確實有效,只是沒有把問題解完。 這是目前 #579 上沒有的資料點。
發現了什麼
- 斷點 1 對這台機器不存在。換到 fairydust 就有 USB-C DP 輸出,不用改任何程式碼
- DP 只有一個孔(左前),插錯孔完全沒有反應,而且不會有任何錯誤訊息
- #622 在 t600x 上有效但沒解完:WARNING 和
flip_done timed out都消失、 不再卡住整台電腦,但熱插拔的畫面仍然回不來。量化數字見上面「量到的東西」 - 真正的卡點在合成器:一張永遠等不到完成的 page flip,讓 aquamarine 之後拒絕所有 commit
(
Cannot commit when a page-flip is awaiting,出現 14 次)。 Hyprland 不是沒反應 —— 它有偵測到、有列模式、有嘗試 modeset - 單獨跑
make install會把/boot/dtb指歪,這次真的發生了。 只改模組的話根本不需要它 - 驗證要驗二進位檔。
git diff和時間戳都可能騙人, 要strings *.ko | grep確認編出來的東西裡有
當時的狀態快照不留在這裡 —— 會變的東西只住在入口一份。 那晚實測的增量編譯是 38 秒。
沒做到 / 做得不好的地方
- 整晚幾乎都是「跑腳本、套別人的 patch、看結論」,沒有寫過一行 C,也沒碰過任何暫存器。 這不是計畫的問題 —— 階段 0 本來就不是學習關卡 —— 但要記得它不算數
- #622 兩塊改動的原理當下沒搞懂,是事後才補寫進流程 §3 的
git apply -R那一輪白測,浪費約 20 分鐘
明天要幹嘛
- 先一起寫一份學習計畫(不是由 Claude 單方面寫完丟過來)
- 把兩個 patch 逐行看懂 —— 0001(內建 HDMI resume,11 行,暖身用)和 #622(兩塊,42 行)
- 討論熱插拔。重點不只是修好,是搞懂那些探測手段:
udevadm monitor、/sys/class/drm、journalctl -k、hyprland.log各自在講哪一層,輸出怎麼讀 - 然後才動
iomfb.c。程式由自己寫,Claude 負責解釋機制、指路、讀結果、review
兩分鐘就能做、但還沒做的事:把 Studio Display 插上去冷開機一次。
到目前為止正主都還沒上場,很可能會看到
acking unhandled call 20 ——
那是跟今天完全不同的一條線(斷點 2),先知道它長什麼樣,排優先順序會比較有依據。