本文將討論在連接的設備中更新引導加載程序的問題。所討論的原則適用于任何軟件系統,我們將專門討論運行 Linux 的系統。
現代電子設備越來越復雜,并且互聯網連接。作為一般規則,復雜性與安全性背道而馳,不安全的互聯網連接設備已經成熟,罪魁禍首會被濫用。在設計這些系統時,我們必須假設所有軟件都會有錯誤,其中一些錯誤將是可利用的漏洞。解決這些問題的第一步是確保軟件更新可以交付到您的系統,最好是自動和無線 (OTA)。歐盟“消費者物聯網網絡安全:基線要求(ETSI EN 303 645)”標準草案特別將及時自動更新作為其要求之一。它確實為不可變的第一階段引導加載程序提供了一個例外,以最大程度地降低將設備留在現場處于非引導狀態的風險(也稱為“磚塊”“板)。
本文將討論在連接的設備中更新引導加載程序的問題。請注意,雖然這里討論的原則適用于任何軟件系統,但我們將專門討論運行 Linux 的系統。使用更小、更自定義設計的系統可能會提供更多這些系統獨有的選項。
系統設計
圖 1 顯示了一個通用的 Linux 系統,其中包含可能更新的主要組件。存儲介質將是某種塊設備,例如 eMMC 或 SATA 硬盤驅動器。在該設備中,將有引導加載程序、內核、設備樹(取決于正在使用的 CPU)和一個根文件系統,其中包含構建系統所需的所有文件。在某些情況下會使用更復雜的架構,但出于本討論的目的,我們將它限制在最簡單的情況下。
系統更新實用程序,如Mender[2],軟件更新[3],其他人能夠開箱即用地更新內核、設備樹和根文件系統,在許多情況下,這種級別的可更新性就足夠了。
引導加載程序是系統的組件,負責在開機時初始化系統,從 CPU 重置指令開始。它負責以下任務:
?初始化和清理內存
?將所有外圍設備設置為已知和靜止狀態,以避免意外中斷。
?加載并啟動 Linux 內核
如前所述,所有軟件都有錯誤,因此我們可以假設也會有引導加載程序錯誤。我們可以通過最小化引導加載程序的功能來減少攻擊面,但是我們可以完全消除錯誤的風險。為什么更新引導加載程序比更新系統的其他組件更復雜?如果我們嘗試,會有什么風險?如果我們不嘗試,會有什么風險?
支持無線的系統
此框圖顯示了能夠進行可靠的無線 (OTA) 更新的系統的基本系統設計。[4]引導加載程序負責系統初始化并與 OTA 客戶端交互,以選擇要使用的內核、設備樹和根文件系統。通過對正在運行的 Linux 映像所需的組件進行完全冗余來提供健壯性。這可確保在 OTA 更新損壞的情況下始終有已知良好的映像要回滾。此外,這可確保完全原子更新,因為更新客戶端是系統中唯一知道更新正在進行中的組件,直到更新完成并準備好運行。
任何更新 OTA 的組件都可能導致設備無法正常工作,因此系統的穩健性與引導加載程序處理回滾到先前已知良好的配置的能力直接相關。這意味著系統中必須有一個組件,該組件是不可變的,可以正確處理錯誤的更新。
引導加載程序更新
在大多數情況下,處理回滾的不可變組件_是_引導加載程序。在典型的嵌入式Linux應用程序中是Das U-Boot[5]。如果我們嘗試更新引導加載程序,由于沒有冗余,我們就有使主板變磚的風險。如果開發板在我們開始寫入新的引導加載程序映像之后,但在寫入完成之前重新啟動,則我們的映像包含舊版本的一部分和新版本的一部分。在這種情況下,行為是未定義的,唯一的緩解措施是能夠物理訪問設備,以便編寫正確的引導加載程序,通常使用 USB 或其他硬連線連接。
但是我們為什么要更新引導加載程序呢?至少,引導加載程序只是用作初始化硬件的一種手段,然后將控制權傳遞給 Linux 內核。由于功能有限,引導加載程序出現問題的風險被降至最低。
對于許多設計來說,這種風險水平是可以接受的,架構師可以決定不在其部署的設備中提供OTA引導加載程序更新。使用硬連線機制仍然是最后的手段。
然而,對于許多設計,這種風險水平被認為是不可接受的,必須為引導加載程序的OTA更新提供一些機制。此外,許多設計在引導加載程序中添加了更多功能;諸如系統診斷或其他特定于應用程序的要求之類的內容可能會在引導加載程序中實現,從而導致需要更新的可能性更大。那么我們如何處理呢?
用于提供引導加載程序更新的選項
有許多選項允許更新引導加載程序。本討論并非旨在提供完整的解決方案,而是對可能適用于您的設計的方法進行高級描述。每個都有其權衡。
選項 1:無冗余
如果磚砌板的風險對于特定應用程序來說是可以接受的,那么您可以簡單地嘗試部署引導加載程序更新 OTA,并在發生時處理后果。如果您的隊列規模較小,并且物理訪問設備的成本較低,那么這可能效果很好。如果需要引導加載程序更新,并且 OTA 嘗試失敗,那么您的嘗試也不會更糟。OTA 引導加載程序更新失敗的情況與沒有 OTA 引導加載程序更新功能的情況相同。即,您必須獲得對設備的物理訪問權限,并使用制造商提供的機制來重新刷新引導加載程序。
選項 2:多階段引導加載程序
此體系結構將引導加載程序功能分為兩個階段(或更多階段,具體取決于設計的復雜性)。最終,這仍然需要在階段 1 中提供一段不可變的代碼。您在更新階段 2 時確實具有冗余和健壯性,因此如果您仔細選擇實現功能的位置,則可以提供引導加載程序功能的 OTA 更新。這是一個不錯的選擇,因為不可變階段 1 二進制文件中的代碼量減少了,從而降低了總體風險。
U-Boot 使用 SPL(輔助程序加載器)和 TPL(第三程序加載器)實現多階段引導。引入此機制是為了允許支持具有單獨引導 ROM 的系統,這些引導 ROM 太小而無法存儲完整的 U-Boot 映像。在這種情況下,U-Boot SPL 映像將包含足夠的初始化代碼來加載和啟動完整的 U-Boot 映像,通常是從大型塊設備(如 MMC)啟動。SPL 需要能夠初始化足夠的 RAM 和包含完整 U-Boot 映像的設備。
即使對于沒有小引導ROM限制的設備,我們也可以利用這種架構在第2階段實現我們的可更新功能,同時在第1階段保留最低限度,包括正確處理冗余塊。
第 1 階段存在問題的風險,需要物理訪問才能解決。鑒于第 1 階段的功能減少,在許多情況下,這種風險水平是可以接受的。
選項 3:并行引導加載程序
許多主板提供從多個設備啟動的功能。例如,許多主板可以從板載 eMMC 或可移動 SD/MMC 卡啟動。或者,他們可以為引導加載程序使用專用的 NOR 閃存設備,但仍能夠在 eMMC 塊介質之外運行引導加載程序。
這些類型的主板可以配置為將不可變引導加載程序存儲在其中一個受支持的設備中,然后將 OTA 可更新引導加載程序存儲在另一個設備中。通常,可更新的引導加載程序將與根文件系統位于同一介質(即eMMC)中,因此很容易更新。由于“備用”媒體中的引導加載程序是不可變的,因此可以依靠它從“標準”位置引導加載程序的損壞 OTA 更新中恢復。
這種方法的問題在于,引導設備的選擇通常需要物理訪問電路板才能移動跳線或更改開關設置。如果您的設備位于最終用戶可以訪問它們的位置,這可能是一個可行的選項,因為最終用戶可以在發生故障時選擇恢復媒體。這可以通過文檔或支持人員的指示完成。
某些系統使用外部硬件來選擇引導加載程序。運行RTOS的小型MCU可以監控正確的系統活動,并在Linux系統未運行時選擇備用引導加載程序。使用外部源正確檢測可能很棘手,但切換 GPIO 引腳或寫入共享內存的看門狗計時器可能就足夠了。這也是一個更復雜的設計,需要根據您的系統要求進行考慮。請注意,您可能需要考慮對MCU固件映像進行OTA更新,這是另一個復雜程度。
選項 4:eMMC 啟動分區
eMMC 的 4.3 版[6]規范需要 2 個單獨的硬件引導分區。這些分區通常每個為 4MB,用于存儲引導加載程序。這些分區可以從 Linux 用戶空間讀取和寫入,但默認情況下它們是只讀的;讀寫功能是通過寫入 /sys 偽文件系統中的文件來啟用的:
然后可以使用dd實用程序將引導加載程序寫入這些分區
eMMC 設備用作啟動塊的分區由設備本身內設置的參數確定。這可以從 U-Boot 提示符下完成:
或者從 Linux 用戶空間:
曼德的方法
利用 eMMC 引導分區,對分區的更新是原子的,并且獨立于對根文件系統的更新。eMMC 啟動分區之間沒有自動故障轉移,因此這不會減輕由于啟動加載程序更新失敗而導致磚塊設備的擔憂。但是,這確實可以輕松向引導加載程序提供更新,而無需為根文件系統提供任何特定的調整。
由于提供引導加載程序更新時存在磚砌板的風險和 OTA 更新過程的魯棒性降低,Mender[7]不提供現成的引導加載程序更新。如前所述,很難以通用方式完成,并且最終可能會非常特定于應用程序和硬件。更新模塊框架[8]允許插件架構支持自定義更新類型。Mender 可以使用自定義更新模塊支持任意有效負載類型。此插件架構允許提供處理特定有效負載類型的自定義腳本。允許在特定系統中進行引導加載程序更新可以使用更新模塊來實現。根據應用程序的需求以及正在使用的硬件的功能,可以使用上述任何方法。
總結
在現場部署的設備中上傳系統引導加載程序存在許多風險。在不合時宜的時間斷電可能會使設備在現場變磚,從而導致潛在的代價高昂的召回過程。但是,不提供引導加載程序更新機制可能會帶來不可接受的風險,具體取決于特定應用程序的配置文件。我們介紹了許多允許引導加載程序更新的方法,并討論了每種方法的優缺點。作為系統設計人員,這將有望讓您為系統做出適當的選擇,并幫助您在適當了解設計風險的情況下快速進入市場。
審核編輯:郭婷
-
物聯網
+關注
關注
2910文章
44752瀏覽量
374590 -
Linux
+關注
關注
87文章
11320瀏覽量
209849
發布評論請先 登錄
相關推薦
評論