RFC-0167:早期使用者空間啟動程序套件

RFC-0167:使用者空間早期開機載入中的套件
狀態已接受
領域
  • 元件架構
說明

BootFS 和開機解析套件簡介。

問題
毛皮變化
作者
審查人員
提交日期 (年-月-日)2022-05-10
審查日期 (年-月-日)2022-06-13

摘要

此 RFC 提出啟動檔案系統的套件簡介。這樣就能 落後使用者模式對套件隔離和命名間距的好處 啟動及移除攔截器,進行第三方驅動程式庫開發作業。

提振精神

早期啟動可執行組件和沙箱就存在於 元件架構具備穩固的封裝架構,至今尚未 投注心力在早期啟動階段提供現今使用者空間可用的工具。 因此,使用者空間開機程序發現自己面臨多個問題, 而是為瞭解決例如程序沙箱、可驗證 內容,以及變數程式庫版本

這些早期啟動問題呈現出非預期的複雜情況和效率低落 都能與啟動檔案系統映像檔互動 所以在早期啟動階段就應包裝包裝材料,這樣就能大幅避開這類狀況。包裝 早期啟動階段能帶來改善系統健康狀態的機會 而非解決現有問題將內容 ID 標準化 可執行檔和程式庫,讓我們重複使用 像是啟動檔案系統和 blobfs 等先前不連續的儲存體中的對等資料

元件架構含有「套件」主要概念是 fuchsia-pkg;元件架構和封裝系統 這兩個情境各自獨立,彼此緊密結合 組成和打包世界有利於合作。

近期工作 (例如在使用者啟動程序後首次執行元件管理員時執行的作業) 也推動越來越多「元件將逐步落水」這個架構的簡短總覽 即使是早期啟動執行檔 (例如檔案系統和裝置驅動程式) Fuchsia 元件,或目前正在遷移至該模型。現在正是時候 將這個系統元件化與 "packages-all-the-way-down"擷取所有 值 激勵使用者進行引導式包裝

更確切地說,當啟動檔案系統中缺少套件名稱間距,就會變成 樹狀結構外驅動程式庫的開發,由於 產生有效的 fuchsia 映像檔,其中編碼的可執行檔在啟動檔案系統中, 共用 lib deps 中的版本偏差另外,當今的啟動檔案系統映像檔外洩 ABI。駕駛人可根據是否在啟動期間,變更應用程式啟動期間的行為, 不使用其他驅動程式,例如選擇使用較新的程式庫 可以在不明確定義其他驅動程式庫的依附元件的情況下 執行這些操作 同樣地,由於驅動程式全都位於啟動檔案系統中的同一個資料夾, 驅動程式名稱形成了 ABI。這類使用者可能會誤會 只要使用時間較長,ABI 就更難淘汰 這類行為的先例 (Windows 驅動程式和電玩遊戲) DRM 驅動程式公開這種無意間的 ABI。

相關人員

Facilitator:hjfreyer@google.com

審查人員:geb@google.com、mcgrathr@google.com、surajmalhotra@google.com、 aaronwood@google.com、galbanum@google.com、wittrock@google.com、 jfsulliv@google.com

諮詢:

社交:我們透過設計文件與相關人員探討這個主題, 則在 RFC 前開放 tq-eng 進行一般討論。

設計

這項變更涉及啟動檔案系統和 /boot 目錄 BootResolver、BootUrl 和產品組合

啟動檔案系統變更

圖片變更

Fuchsia 啟動檔案系統套件會以啟動檔案系統中的中繼.far 檔案表示, 啟動檔案系統目錄項目的名稱會是 blob/<merkle root of meta.far>每次 套件資訊清單中的 blob 會接收新的目錄項目, 啟動檔案系統、blob/<merkle root of the dependency>

  1. 我們已在執行階段計算默克爾文以驗證內容,而且速度很快 所以在 zbi 創作等流程中 這麼做是足夠的做法 壓縮圖片時則沒有對稱
  2. 本提案已採用新的圖像製作程序 會在實際的圖片建構步驟之前,先決定內容識別資訊,因此如 填入中繼.far 檔案。也就是根據內容排除重複 大多已發生在 產生資訊清單的程序 推動圖像建構步驟這應該相當簡單明瞭 只是確認這個階段所有可能的重複資料都已完成

當我們討論在 /blob 下的啟動檔案系統中新增項目時,我們只 是指新增參照相同的啟動檔案系統目錄項目 基礎檔案 (基本上是硬連結)。

位於名為「pkg_map」的啟動檔案系統中的新檔案都會從 一般使用者可理解的套件名稱 套件。

這會隨著新增的中繼.fars 和新的 pkg_map 檔案而變大。 所有其他項目都只適用於 。這些啟動檔案系統會以保守態度增加約 70KiB 的壓縮檔 會在 x64 架構上部署

/boot 變更

新的子目錄將導入 /boot,稱為 /blob。位於 名稱前置字串為 /blob 的啟動檔案系統映像檔會放置於該映像檔。時間 將啟動檔案系統中的所有元件遷移至套件的作業已完成 level 目錄只會包含核心 vmos、shell 指令碼和 需要將 /boot 設為「命名空間」元件管理員的 YAML 設定檔

元件管理員命名空間一開始是 /boot 的子目錄 「除臭」所有依附元件的預期位置我們的最終目標 甚至將元件管理員組合成一種採用 用於解析度的 SWD 堆疊。

BootResolver 變更

套件名稱間距啟動啟動檔案系統元件的核心工作「經常」與 套件完成設定必須對應人類可讀的套件名稱 到 content-id 的中繼.far 中,Meta.far 必須已解碼,以及其內容檔案 必須用於建構命名空間因此,設計旨在重複使用 許多現有的套件解析邏輯。

如要重複使用套件解析器的邏輯,最簡單的進入點為 package-directory::serve ,直接在 Google Cloud 控制台實際操作。這個進入點會採用 BlobFS 和 content-id 識別中繼.far、開啟中繼.far、剖析其中繼/內容檔案,以及 ,並依檔案編碼方式提供命名空間。我們可以重複使用 只要您能提供啟動檔案系統支援的目錄 將 blob 傳送至 API,做為 BlobFS 用戶端。

    let (proxy, server) =
        fidl::endpoints::create_proxy().map_err(ResolverError::CreateEndpoints)?;
    let () = package_directory::serve(
        package_directory::ExecutionScope::new(),
        <some blobfs::Client-like view on top of the bootfs blobs>,
        <meta.far hash>,
        fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_EXECUTABLE,
        server,
    )
    .await
    .map_err(ResolverError::ServePackageDirectory)?;

blobfs::Client 只會包裝 fio::DirectoryProxy,也就是啟動檔案系統 也就是元件管理員我們只需使用 Cloud 啟動檔案系統的 Blobfs 用戶端,並將其傳遞至 package_directory::Serve 呼叫。有些微小 必須進行變更,以確保特定 blobfs::Client API 失敗 優雅地坐在啟動檔案系統上 (也就是需要可變動的容器),例如 open_blob_for_write、delete_blob),但在 package_directory::serve 執行。

BootUrl 變更

BootUrl 目前不會使用網址的主機或路徑部分,因為 不必使用存放區或封裝進行編碼也就是說 新的網址配置和解析器,我們可以改為導入新元件載入 ,在現有的 BootResolver 中插入現有 BootResolver存在 或網址中沒有套件路徑時, 「BootResolver 變更」所述的解析途徑。

例如:

fuchsia-boot:///#my_component.cm 啟動解析器會將這個網址解讀為 未封裝的元件,其命名空間已在 /boot 目錄。

fuchsia-boot:///my_package#my_component.cm 啟動解析器會解讀 這個網址做為封裝元件,從「my_package」取得對應加入 my_package 的中繼.far 根根層級已存在,應用於 建構專屬於「my_package」命名空間的命名空間。

產品/圖片組裝變更

Bootfs 映像檔建構是透過兩階段完成的工作完成 然後是映像檔組合系統

首先,我們會推出名為 bootfs_packages 的新 gn 變數。 這個清單會在 product.gni 中宣告,並指派給 名為 bootfs_package_labels 的叫用者變數會傳遞給任何 指派 build/input:bootfsassemble_system 叫用 變更為 bootfs_labels 變數

要將啟動檔案系統元件從無套件編碼遷移至 多個啟動檔案系統套件,我們會將它從包含以下程式碼的群組依附元件中移除 將其新增至 bootfs_labels 依附元件集中,並新增至 bootfs_packages 設定。

接下來,在產生映像檔組合設定時,我們會使用 list_package_manifests 個範本,用於從套件收集套件資訊清單 呼叫器的 bootfs_package_labels 變數中定義。

接著,映像檔組件會從建構週遊中取得資訊清單,並用來 呼叫 zbi 等工具,將建構目錄中的檔案套件至映像檔。 套件資訊清單格式包含一份「blob」清單這些物件 建立後,系統就會將 blob/<merkle_root> 個具名檔案加入 啟動啟動檔案系統映像檔

反覆處理這些 blob 物件時,我們將查看哪些 blob 是套件 Meta.far 的 ID,並會新增從 將套件名稱新增至對應中 Meta.far 的 Merkle 根層級啟動檔案系統映像檔結束時 建立後,地圖會以 JSON 格式寫入「pkg_map」描述檔案 一文。

我們選擇在圖像組合層級實作此轉換 原因:

  • ProductAssembly 只會合併 套裝組合。

  • ImageAssemblyConfig 驗證依然簡單。

  • 驗證「套件」產品組件中的驗證情形持續 會在「套件」上運作

實作

功能實作

映像檔組件變更、啟動檔案系統變更、BootResolver 變更 和 BootUrl 變更都可以同時完成。

為了確保您不會看見 完成實作程序中的 bootfs_package_labels 作業, 我們將從「圖片組合」開始著手我們會 只要在啟動檔案系統套件資訊清單之前實作這項功能 ,我們將會進行建構時間檢查,確認該集為空白。

BootUrl 的語意會因 3 個 CL 而異。首先 將 BootUrl 變更為第一個啟動檔案系統元件 如果項目包含套件路徑或存放區,則會視為無效 ( 我們仍會保留套件路徑的可用性 解決策略)。第二,與遷移後的第一個啟動檔案系統元件 fuchsia_package 我們將允許在 fuchsia-boot 網址中使用套件路徑。第三,隨著 而最後一個啟動檔案系統元件遷移至 fuchsia_package 時,系統將禁止 不包含套件的啟動網址。

遷移

完整實作這些功能後,我們將遷移啟動檔案系統元件 特定元件的遷移作業如下:

  1. 我們會找到元件中未封裝依附元件的位置 (.cml 檔案、二進位檔等) 會新增至 bootfs_labels deps。
  2. 我們會將未封裝的 dep 檔案轉換為 fuchsia_package gn 目標。
  3. 我們會將套件從現有的 bootfs_labels 群組中移除,並新增 新增至 bootfs_package_labels 群組。
  4. 我們會將 Bootstrap.cml 檔案中元件的網址更新為 請納入套件名稱

成效

系統大小

這個啟動檔案系統映像檔會以保守的方式增加約 70KiB 的壓縮後 會在 x64 架構上部署這是因為所有元件都遷移至 套件的大小也會根據新增的 Meta.fars 參數 更新 pkg_map 檔案。其他用途只是重新命名 封裝之前的啟動檔案系統檔案目錄項目。

執行階段影響

目前,整個啟動檔案系統會集中在 component_manager 的目錄 啟動。遷移完成後,我們最終會將剖析工作延後到與 在 /boot 內設定元件的命名空間,直到元件啟動為止。

除了先前剖析的剖析作業外 啟動檔案系統標頭就必須剖析 Meta.far

ZBI 已簽署,因此目前我們不會驗證 Zbi 中的啟動檔案系統檔案,只驗證 Zbi 本身。如果我們 未在啟動檔案系統中驗證 blob 的執行階段驗證, 跟我們現今的相同安全位置

出現啟動檔案系統目前可以找到的潛在問題 組件可能會錯誤地將來源檔案放在 錯誤。Bootfs 出現 blob 之後 透過執行啟動檔案系統的執行階段驗證 blob。我們一開始不打算進行這項操作。

建構時間影響

Zbi 建構的建構時間效能維持不變;遷移後 而不必針對每個包含的依附元件 執行目的地項目資訊清單 ,我們會改為指示 blob 編碼的套件資訊清單。於 實際練習的成果數量也相同

回溯相容性

本提案涉及的許多變更都是在啟動檔案系統中獨立完成。 更新前幾列的執行單元 一次就好比整個啟動檔案系統因此避免有系統風險 提供的啟動檔案系統封裝實作不完整 元件。

圖片組合器是潛在的回溯相容性問題之一 還發現了包含舊版啟動檔案系統映像檔和新元件 隸屬於同一個 zbi 存放區。如果發生這種情況,請在遷移作業完成後 以及未封裝的元件則不受啟動檔案系統規範 發生錯誤。考量到產品組裝如何建構啟動檔案系統 這個狀態在今天又難免

同樣地,對功能 導入作業不會與功能不同 。

安全性考量

套件名稱使用速度/程序沙箱機制十分重視執行階段安全性, 降低程序可存取的構件

此啟動檔案系統映像檔必須經過簽署且唯讀,因此成為主要的安全性問題 是圖片組譯工具是否值得信任,與格式無關 圖片的部分如果有的話,請在 如果我們決定 必須能夠以漸進方式更新啟動檔案系統映像檔

隱私權注意事項

無。

測試

元件解析器和產品組合的測試做法良好 並進一步擴充內容,以納入新功能。

系統會在語意變更的 3 個階段新增 BootUrl 剖析器測試 ,表示系統強制執行網址的預期行為。

說明文件

使用者空間開機程序的 API 說明文件及相關說明文件 需要更新啟動檔案系統映像檔組件。

缺點、替代方案和未知

重複使用 bootfs_labels 與推出新標籤。

今天,意外將套件加入依附元件清單 在 bootfs_labels 清單中,此為免人工管理。經過這項異動後, 套件的存在會具有語意顯著性。所以 我們必須「清理」意外納入 bootfs_labels 命名空間。

這裡唯一的複雜度涉及 fuchsia_driver_packages。 fuchsia_driver_package 是獨特的建構範本;如何組裝產品 與 fuchsia_driver_package 的互動情形取決於驅動程式庫是否 放置在啟動檔案系統或 blobf 中放在 bootfs_labels 中時,產品 組裝到驅動程式庫套件,以給予驅動程式庫般的體驗 依附元件;當放在 blobf 中時,系統會透過以下方式正確封裝驅動程式庫: metadata.far.這種做法是為了讓單一驅動程式庫目標可在啟動檔案系統之間切換 視產品而定這種模式過去有效,是因為啟動檔案系統 產品組件並未賦予任何重要意義 解碼器的 deps 圖不過,使用啟動檔案系統套件名稱時, 說明 Fuchsia_package 是否存在 (及其相關聯的 package_manifest) 當做宣告,以放置中繼.far 將套件命名空間編碼成啟動檔案系統

如果我們今天要推出啟動檔案系統名稱使用速度功能,約有 20 名驅動程式 都放在啟動檔案系統中為未封裝的 deps,並且在啟動檔案系統中編碼為 相關聯的中繼.far 和相關 blob;驅動程式庫的中繼.far 編碼 會一直使用,直到 drive_manager 的執行元件器變更為止。不要使用膨脹 我們要將未使用包裝的啟動檔案系統 然後逐步將目標遷移至適當的封裝。三 就會選擇清除 fuchsia_driver_packages 的 package_manifests 導入新的 gn 中繼資料屏障,防止 list_package_manifests 跑到健身車駕駛服務這樣做並不會分割每個驅動程式庫 使用 fuchsia_driver_package 做為啟動檔案系統目標和 blobf 目標; 因為可大幅降低驅動程式庫產品組件的複雜度 邏輯。此外,一個建構中,一個 因此能避免在分割各個字詞時 然後移除所有「僅限舊啟動檔案系統」虛擬套件

不過,其複雜性不同,舉例來說,在 而真正的 fuchsia_package 目標則不向使用者顯示。這會 與其他現有及進行中的工作不相容,例如: 驗證裝置上的所有套件資訊清單是否如預期命名。 或產品組合工作,要求標籤會產生套件索引 只會直接參照套件目標本身

因此,幹擾性較低的方法是直接加上新標籤 如要將元件從早期啟動程序遷移至套件,請將元件從舊版 放入新標籤中最後,我們需要合併這些名單 如果駕駛尚未遷移至適當的元件,我們便會 就必須修改 Fuchsia-驅動程式庫-套件範本的複雜度。

在產品或圖像組裝作業中實作

  • 如要剖析啟動檔案系統元件的套件資訊清單,請在 產品組裝或圖片組裝層級?換句話說,我們 就會解析資訊清單,直到在呼叫 kubectl 時 透過 zbi 工具實際建構啟動檔案系統?
    • ProductAssembly (ffx 組裝產品)
    • 優點:
      • ImageAssembly 專注於產生圖片檔案 (zbi、blobf 等)
      • ImageAssemblyConfig 包含所有啟動檔案系統檔案清單。
    • 缺點:
      • 我們需要更複雜的驗證 用於產生舊版組合輸入的 ImageAssemblyConfig 組合符合 ProductAssembly 所建立的 ImageAssemblyConfig (或需要捨棄/削弱驗證)。
      • 在產品組合結束時完成的驗證需要知道 找出啟動檔案系統中元件的「packages」(套件) (例如 已對結構化設定進行存在驗證)。
    • ImageAssembly (ffx 組合建立系統)
    • 優點:
      • ProductAssembly 只會合併 套裝組合
      • ImageAssemblyConfig 驗證依然簡單
      • 繼續在產品組件中驗證「套件」 會在「套件」上運作
    • 缺點:
      • ImageAssemblyConfig 不再包含啟動檔案系統的完整內容 檔案。
      • Image Assembly 必須執行套件 ->項目對應 所以在建立 Zbi 之前。

在啟動檔案系統中對 Meta.fars 進行編碼,或是在建立啟動映像檔時設定命名空間?

替代方法是將「命名空間」啟動後 建構映像檔,讓 /boot 下的每個元件都有自己的 做為元件命名空間根目錄的子目錄

在將啟動檔案系統編碼的中繼.fars 中,我們可以提高早期啟動的依附元件, 在啟動解析器中導入 SWD 套件解析程式庫的依附元件 這個檔案的存在,是解譯 Meta.far 格式,並聘請人員及維護 但隨著 Meta.far 格式有所變更。

在建構映像檔期間設定命名空間時, 學習如何解讀產品的 package-manifest/meta.far 格式,然後編寫程式碼來翻譯中繼.far 轉換為啟動檔案系統映像檔中的套件-命名空間這代表新的程式碼 讓第二組變成「從事業務」的 解讀 Meta.fars 必須負責確保產品與現況相符SWD 團隊 表示擔心新團隊必須採用中繼.far 的依附元件 格式,而且只要合併至單一套件即可完全避免 並重複使用 SWD 維護的工具 格式。

這兩種策略的資源影響幾乎都等同 ( KiBs)。

最後,套件不僅是其編碼的命名空間。中繼資料位於 平台等執行階段功能需要中繼.fars (例如套件版本) 以及版本管理如未使用中繼.fars,我們就需要介紹其他新方法 先將這些「額外資訊」編碼擷取及教導 服務,例如元件管理員 中繼資料。