USB4 和 Thunderbolt

USB4 是基於 Thunderbolt 3 協議的公共規範,但在暫存器級別和其他方面存在一些差異。連線管理器是在主機路由器(主機控制器)上執行的實體,負責列舉路由器並建立隧道。連線管理器可以在韌體或軟體中實現。通常,PC 配備用於 Thunderbolt 3 和早期支援 USB4 的系統的韌體連線管理器。另一方面,Apple 系統使用軟體連線管理器,後來的 USB4 相容裝置也遵循這種做法。

Linux Thunderbolt 驅動程式同時支援這兩種實現,並且可以在執行時檢測要使用哪種連線管理器實現。為了安全起見,Linux 中的軟體連線管理器還宣傳 user 安全級別,這意味著預設情況下停用 PCIe 隧道。以下文件適用於這兩種實現,但軟體連線管理器僅支援 user 安全級別,並且預計會伴隨基於 IOMMU 的 DMA 保護。

安全級別以及如何使用它們

這裡提供的介面不是為終端使用者設計的。相反,應該有一個使用者空間工具來處理所有底層細節,維護授權裝置資料庫,並提示使用者建立新連線。

有關 Thunderbolt 裝置的 sysfs 介面的更多詳細資訊,請參見 ABI 檔案測試/sysfs-bus-thunderbolt

那些只想連線任何裝置而無需任何手動操作的使用者可以將以下行新增到 /etc/udev/rules.d/99-local.rules

ACTION=="add", SUBSYSTEM=="thunderbolt", ATTR{authorized}=="0", ATTR{authorized}="1"

這將自動授權所有出現的裝置。但是,請記住,這會繞過安全級別,並使系統容易受到 DMA 攻擊。

從 Intel Falcon Ridge Thunderbolt 控制器開始,有 4 個安全級別可用。 Intel Titan Ridge 增加了一個安全級別(usbonly)。原因是連線的裝置可以是 DMA 主裝置,從而可以在 CPU 和作業系統不知情的情況下讀取主機記憶體的內容。可以透過設定 IOMMU 來防止這種情況,但由於各種原因,IOMMU 並非始終可用。

一些 USB4 系統具有停用 PCIe 隧道的 BIOS 設定。 這被視為另一個安全級別 (nopcie)。

安全級別如下

none

所有裝置都由韌體自動連線。 不需要使用者批准。 在 BIOS 設定中,這通常稱為傳統模式

user

詢問使用者是否允許連線裝置。 基於透過 /sys/bus/thunderbolt/devices 提供的裝置識別資訊,使用者可以做出決定。 在 BIOS 設定中,這通常稱為唯一 ID

secure

詢問使用者是否允許連線裝置。 除了 UUID 之外,裝置(如果它支援安全連線)還會收到一個挑戰,該挑戰應與基於寫入 key sysfs 屬性的隨機金鑰的預期挑戰相匹配。 在 BIOS 設定中,這通常稱為一次儲存金鑰

dponly

韌體自動為 Display Port 和 USB 建立隧道。 不執行 PCIe 隧道。 在 BIOS 設定中,這通常稱為僅顯示埠

usbonly

韌體自動在擴充套件塢中為 USB 控制器和 Display Port 建立隧道。 所有擴充套件塢下游的 PCIe 鏈路都將被刪除。

nopcie

PCIe 隧道已從 BIOS 中停用/禁止。 在一些 USB4 系統中可用。

當前的安全級別可以從 /sys/bus/thunderbolt/devices/domainX/security 讀取,其中 domainX 是主機控制器管理的 Thunderbolt 域。 每個 Thunderbolt 主機控制器通常有一個域。

如果安全級別顯示為 usersecure,則必須先由使用者授權連線的裝置,然後才能建立 PCIe 隧道(例如,出現 PCIe 裝置)。

每個插入的 Thunderbolt 裝置都將出現在 /sys/bus/thunderbolt/devices 下的 sysfs 中。 裝置目錄包含可用於識別特定裝置的資訊,包括其名稱和 UUID。

當安全級別為 usersecure 時授權裝置

插入裝置時,它將如下所示出現在 sysfs 中

/sys/bus/thunderbolt/devices/0-1/authorized   - 0
/sys/bus/thunderbolt/devices/0-1/device       - 0x8004
/sys/bus/thunderbolt/devices/0-1/device_name  - Thunderbolt to FireWire Adapter
/sys/bus/thunderbolt/devices/0-1/vendor       - 0x1
/sys/bus/thunderbolt/devices/0-1/vendor_name  - Apple, Inc.
/sys/bus/thunderbolt/devices/0-1/unique_id    - e0376f00-0300-0100-ffff-ffffffffffff

authorized 屬性讀取 0,這意味著尚未建立任何 PCIe 隧道。 使用者只需輸入即可授權裝置

# echo 1 > /sys/bus/thunderbolt/devices/0-1/authorized

這將建立 PCIe 隧道,並且該裝置現在已連線。

如果裝置支援安全連線,並且域安全級別設定為 secure,則它具有一個附加屬性 key,該屬性可以儲存用於授權和挑戰未來連線中的裝置的隨機 32 位元組值

/sys/bus/thunderbolt/devices/0-3/authorized   - 0
/sys/bus/thunderbolt/devices/0-3/device       - 0x305
/sys/bus/thunderbolt/devices/0-3/device_name  - AKiTiO Thunder3 PCIe Box
/sys/bus/thunderbolt/devices/0-3/key          -
/sys/bus/thunderbolt/devices/0-3/vendor       - 0x41
/sys/bus/thunderbolt/devices/0-3/vendor_name  - inXtron
/sys/bus/thunderbolt/devices/0-3/unique_id    - dc010000-0000-8508-a22d-32ca6421cb16

請注意,預設情況下金鑰為空。

如果使用者不想使用安全連線,則只需將 echo 1authorized 屬性,並且將以與 user 安全級別相同的方式建立 PCIe 隧道。

如果使用者想使用安全連線,則首次插入裝置時,需要建立金鑰並將其傳送到裝置

# key=$(openssl rand -hex 32)
# echo $key > /sys/bus/thunderbolt/devices/0-3/key
# echo 1 > /sys/bus/thunderbolt/devices/0-3/authorized

現在裝置已連線(已建立 PCIe 隧道),此外,金鑰儲存在裝置 NVM 上。

下次插入裝置時,使用者可以使用相同的金鑰驗證(挑戰)裝置

# echo $key > /sys/bus/thunderbolt/devices/0-3/key
# echo 2 > /sys/bus/thunderbolt/devices/0-3/authorized

如果裝置返回的挑戰與我們基於金鑰期望的挑戰匹配,則該裝置已連線,並且已建立 PCIe 隧道。 但是,如果挑戰失敗,則不會建立任何隧道,並且會將錯誤返回給使用者。

如果使用者仍然想要連線該裝置,則他們可以批准該裝置而不使用金鑰,或者寫入一個新金鑰,並將 1 寫入 authorized 檔案,以使新金鑰儲存在裝置 NVM 上。

取消授權裝置

可以透過將 0 寫入裝置的 authorized 屬性來取消授權裝置。 這需要連線管理器實現的支援,並且可以透過讀取域 deauthorization 屬性來檢查。 如果它讀取 1,則表示支援該功能。

取消授權裝置後,從父裝置 PCIe 下游(或根)埠到裝置 PCIe 上游埠的 PCIe 隧道將被拆除。 這本質上與 PCIe 熱移除相同,並且在再次授權該裝置之前,將無法再訪問相關 PCIe 拓撲。 如果涉及到 NVMe 或類似儲存裝置,則如果該儲存裝置上的檔案系統未正確關閉,則存在資料丟失的風險。 您已被警告!

利用 IOMMU 進行 DMA 保護

從 2018 年開始及以後的帶有 Thunderbolt 埠的最新系統可能本機支援 IOMMU。 這意味著 Thunderbolt 安全由 IOMMU 處理,因此連線的裝置無法訪問驅動程式為其分配的記憶體區域之外的記憶體區域。 當 Linux 在此類系統上執行時,如果使用者尚未啟用 IOMMU,則會自動啟用 IOMMU。 可以透過從 /sys/bus/thunderbolt/devices/domainX/iommu_dma_protection 屬性讀取 1 來識別這些系統。

在這種情況下,驅動程式不會執行任何特殊操作,但是由於 DMA 保護由 IOMMU 處理,因此安全級別(如果已設定)是冗餘的。 因此,某些系統在將安全級別設定為 none 的情況下發貨。 其他系統將安全級別設定為 user,以便支援降級到舊作業系統,因此希望在啟用 IOMMU DMA 保護時自動授權裝置的使用者可以使用以下 udev 規則

ACTION=="add", SUBSYSTEM=="thunderbolt", ATTRS{iommu_dma_protection}=="1", ATTR{authorized}=="0", ATTR{authorized}="1"

升級 Thunderbolt 裝置、主機或中繼器上的 NVM

由於大多數功能是在主機控制器或裝置上執行的韌體中處理的,因此重要的是可以升級韌體到最新的版本,其中已修復了其中的可能錯誤。 通常,OEM 會從其支援站點提供此韌體。

還有一箇中心站點,其中包含用於下載某些機器的韌體的連結

在升級裝置、主機或中繼器上的韌體之前,請確保它是合適的升級。 如果不這樣做,可能會使裝置處於無法再正常使用的狀態,而無需特殊工具!

不支援在 Apple Mac 上進行主機 NVM 升級。

下載 NVM 映像後,您需要插入 Thunderbolt 裝置,以便主機控制器出現。 連線哪個裝置無關緊要(除非您正在升級裝置上的 NVM - 那麼您需要連線該特定裝置)。

請注意,OEM 特定的控制器加電方法(“強制加電”)可能適用於您的系統,在這種情況下,無需插入 Thunderbolt 裝置。

之後,我們可以將韌體寫入主機或裝置的 NVM 的非活動部分。 例如,以下是如何升級 Intel NUC6i7KYK (Skull Canyon) Thunderbolt 控制器 NVM 的方法

# dd if=KYK_TBT_FW_0018.bin of=/sys/bus/thunderbolt/devices/0-0/nvm_non_active0/nvmem

操作完成後,我們可以觸發 NVM 身份驗證和升級過程,如下所示

# echo 1 > /sys/bus/thunderbolt/devices/0-0/nvm_authenticate

如果未返回任何錯誤,則主機控制器會很快消失。 驅動程式在返回後會注意到它,並啟動完整的電源週期。 過一段時間後,主機控制器再次出現,此時它應該是完全可以正常使用的。

我們可以透過執行以下命令來驗證新的 NVM 韌體是否已啟用

# cat /sys/bus/thunderbolt/devices/0-0/nvm_authenticate
0x0
# cat /sys/bus/thunderbolt/devices/0-0/nvm_version
18.0

如果 nvm_authenticate 包含除 0x0 以外的任何內容,則它是上次身份驗證週期的錯誤程式碼,這意味著 NVM 映像的身份驗證失敗。

請注意,NVMem 裝置的名稱 nvm_activeNnvm_non_activeN 取決於它們在 NVMem 子系統中註冊的順序。 名稱中的 N 是 NVMem 子系統新增的識別符號。

在沒有連線電纜的情況下升級板載中繼器 NVM

如果平臺支援,即使沒有連線到 USB4 埠,也可以升級中繼器 NVM 韌體。 在這種情況下,usb4_portX 裝置具有兩個特殊屬性:offlinerescan。 升級韌體的方法是首先將 USB4 埠置於離線模式

# echo 1 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/offline

此步驟可確保埠不響應任何熱插拔事件,並確保中繼器已通電。 下一步是掃描中繼器

# echo 1 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/rescan

這將列舉並新增板載中繼器。 現在可以像連線電纜一樣升級中繼器 NVM(請參閱上一節)。 但是,中繼器未斷開連線(因為我們處於離線模式),因此在將 1 寫入 nvm_authenticate 之後,應等待 5 秒或更長時間,然後再再次執行重新掃描

# echo 1 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/rescan

如果一切順利,則可以將埠恢復到正常工作狀態

# echo 0 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/offline

在主機控制器處於安全模式時升級 NVM

如果現有的 NVM 未經過正確身份驗證(或丟失),則主機控制器將進入安全模式,這意味著唯一可用的功能是重新整理新的 NVM 映像。 在此模式下,讀取 nvm_version 會因 ENODATA 而失敗,並且缺少裝置識別資訊。

要從此模式恢復,需要以與上一章中相同的方式將有效的 NVM 映像重新整理到主機控制器。

隧道事件

thunderbolt_domain 中發生隧道更改時,驅動程式會將 KOBJ_CHANGE 事件傳送到使用者空間。 通知攜帶以下環境變數

TUNNEL_EVENT=<EVENT>
TUNNEL_DETAILS=0:12 <-> 1:20 (USB3)

<EVENT> 的可能值為

activated

隧道已啟用(建立)。

changed

此隧道中發生了更改。 例如,頻寬分配已更改。

deactivated

隧道已拆除。

low bandwidth

隧道沒有獲得最佳頻寬。

insufficient bandwidth

當前隧道要求沒有足夠的頻寬。

僅當隧道已知時才提供 TUNNEL_DETAILS。 例如,對於韌體連線管理器,此資訊缺失或未提供完整的隧道資訊。 對於軟體連線管理器,這包括完整的隧道詳細資訊。 當前的格式與驅動程式記錄時使用的格式匹配。 隨著時間的推移,這可能會發生變化。

透過 Thunderbolt 電纜進行網路連線

Thunderbolt 技術允許透過 Thunderbolt 電纜連線的兩個主機之間進行軟體通訊。

可以透過 Thunderbolt 鏈路隧道傳輸任何型別的流量,但目前我們僅支援 Apple ThunderboltIP 協議。

如果另一臺主機執行的是 Windows 或 macOS,則您唯一需要做的就是在兩臺主機之間連線 Thunderbolt 電纜; thunderbolt-net 驅動程式會自動載入。 如果另一臺主機也是 Linux,則應在一臺主機上手動載入 thunderbolt-net(哪一臺主機無關緊要)

# modprobe thunderbolt-net

這會自動觸發另一臺主機上的模組載入。 如果驅動程式已構建到核心映像中,則無需執行任何操作。

驅動程式將為每個 Thunderbolt 埠建立一個虛擬乙太網介面,這些介面的名稱類似於 thunderbolt0 等。 從這一點開始,您可以要麼使用標準的 使用者空間工具(例如 ifconfig)來配置介面,要麼讓您的 GUI 自動處理它。

強制加電

許多 OEM 都包含一種方法,可用於強制 Thunderbolt 控制器的電源進入“開啟”狀態,即使未連線任何裝置。 如果您的計算機支援,則將透過 WMI 匯流排公開此功能,並帶有一個名為“force_power”的 sysfs 屬性。

例如,intel-wmi-thunderbolt 驅動程式在以下位置公開此屬性

/sys/bus/wmi/devices/86CCFD48-205E-4A77-9C48-2021CBEDE341/force_power

要強制電源開啟,請將 1 寫入此屬性檔案。 要停用強制電源,請將 0 寫入此屬性檔案。

注意:目前無法查詢平臺的強制電源狀態。