【swupdate文件 一】嵌入式系統的軟體管理
嵌入式系統的軟體管理
嵌入式系統變得越來越複雜, 它們的軟體也反映了這種複雜性的增加。
為了支援新的特性和修復,很有必要讓嵌入式系統上的軟體
能夠以絕對可靠的方式更新。
在基於linux的系統上,我們可以在大多數情況下找到以下元素:
- 引導裝載程式
- 核心和裝置樹
- 根檔案系統
- 其他在後續掛載的檔案系統
- 使用者資料,以裸資料格式存在或者儲存在檔案系統中
- 特定用途的軟體. 如,用於下載到相連線的微控制器的韌體等
一般來說,在大多數情況下是需要更新
核心和根檔案系統,儲存使用者資料-但實際情況各不相同。
僅在少數情況下,還需要更新引導載入程式,
事實上,更新引導載入程式總是很危險的, 因為更新中的失敗會破壞裝置。
在某些情況下,從損壞狀態中恢復是可能的,
但這通常無法由終端使用者完成,即裝置需要返廠維修。
關於軟體更新有很多不同的概念。我將解釋其中的一些概念,
然後解釋為什麼我實施了這個專案。
通過引導載入程式完成更新
引導載入程式所做的工作遠不止啟動核心那麼簡單。
它們有自己的shell,且可以使用處理器的外圍裝置
進行管理,在大多數情況下是通過序列通訊。 它們通常是可執行指令碼的,這使得
實現某種軟體更新機制成為了可能。
然而,我發現這種方法有一些缺點,
這讓我另行尋找基於執行在Linux上的應用程式的解決方案。
引導載入程式對外圍裝置的使用有侷限性
並不是所有核心中支援的裝置都可以在引導載入程式使用。
向核心新增裝置支援是有意義的,因為這可以讓外圍裝置對主應用程式可用,
但將驅動程式移植到引導載入程式中,就並不總是有意義的了。
引導載入程式的驅動程式不會被更新
引導載入程式的驅動程式大多是從Linux核心移植過來的,
但是由於經過調整的原因,它們以後不會被修復或與核心同步,
而bug修復則會定期在Linux核心中進行。
一些外圍裝置可能以不可靠的方式工作,
並且修復問題可能並不容易。引導載入程式中的驅動程式
或多或少是核心中相應驅動程式的復刻(fork)。
例如,用於NAND裝置的UBI/UBIFS在核心中包含
了許多修復程式,這些修復程式並沒有移植回引導載入程式。
USB協議棧也可以找到相同的情況。支援新外圍裝置或協議的工作,
在核心中進行得更好,而不是在引導載入程式中。
簡化版的檔案系統
支援的檔案系統的數量是有限的。
將檔案系統支援移植到引導載入程式需要付出很大的努力。
網路支援有限
網路協議棧是有限的,通常通過一個更新只能通過 UDP但不能通過TCP完成。
與操作人員互動
很難將介面暴露給操作員, 比如瀏覽器中的GUI或顯示器上的GUI。
比起在引導載入程式中,複雜的邏輯可以在應用程式內部更容易實現。
擴充套件引導載入程式是複雜的,因為所有的服務和庫都不可用。
引導載入程式更新的優點
然而,這種方法也有一些優點:
-更新軟體通常更簡單。
-佔用空間更小:即使是一個僅用於軟體管理的獨立應用程式
也需要自己的核心和根檔案系統。即使它們的大小能夠被裁剪,
將更新軟體不需要的部分去掉,它們的大小也是不可忽略的。
通過包管理器更新
所有的Linux發行版都使用包管理器做更新, 為什麼這不適用於嵌入式系統?
我不能說它不能被使用,但是使用這種方法有一個重要的缺點。
嵌入式系統是使用特定的軟體進行過良好測試的。
使用包管理器可能會讓人覺得奇怪,因為軟體本身不再是 原子的 ,
而是分裂成一系列包。
我們怎樣才能保證一個能基於庫版本x.y正常工作的應用程式,
同樣也能基於同一個庫的不同版本工作呢?如何才能成功地做好測試?
對於製造商來說,通常更好的說法是釋出了一個新的軟體版本
(經過測試工程師的良好測試),並且可以更新新的軟體(或韌體)。
對測試人員來說,在包中進行拆分可能會產生噩夢和巨大的工作量。
簡單地替換單個檔案可以加快開發速度,
但是對於客戶站點來說,這是一個軟體版本的噩夢。
如果客戶報告了一個bug,那麼在之前已經向客戶傳送過
一些檔案的補丁時,軟體怎麼可能還算是“2.5版本”呢?
原子更新通常是嵌入式系統的必備特性。
應用程式進行軟體升級的策略
應用程式也可以用於升級系統,而不是使用引導載入程式。
應用程式可以使用作業系統提供的所有服務。
建議的解決方案是一個獨立的軟體,
它遵循客戶規則,執行檢查以確定軟體是否可安裝,
然後將軟體安裝到所需的儲存上。
應用程式可以檢測所提供的新軟體是否適合硬體,
也可以檢查軟體是否由經過驗證的權威機構釋出。
支援的特性範圍可以從小型系統擴充套件到複雜系統,
包括安裝前和安裝後腳本等等。
根據系統的資源,可以使用不同的策略。 下面我將列出其中一些。
雙備份系統 - 支援回退
如果儲存空間足夠儲存整個軟體的兩個副本,
那麼即使軟體更新被中斷或斷電,也可以保證始終有一個可用的副本。
每個副本必須包含核心、根檔案系統和每個可以更新的元件。
需要一種機制來識別正在執行的版本。
SWUpdate應該整合到應用程式軟體中, 當需要更新時,應用程式軟體將觸發它。
SWUpdate的職責是更新備用副本, 不修改正在執行的軟體副本。
與引導載入程式的協作通常是必要的,
因為引導載入程式必須決定應該啟動哪個副本。
同樣,必須能夠在兩個副本之間進行切換。
重新啟動後,引導載入程式決定應該執行哪個副本。
請參閱有關引導載入程式的章節,
瞭解可以實現哪些機制來確保更新後目標不會被破壞。
最明顯的缺點是所需的空間量。 每個副本的可用空間小於儲存空間的一半。
然而,即使在斷電的情況下,更新也總是安全的。
這個專案支援這個策略。
作為該專案一部分的應用程式應該安裝在根檔案系統中,
並根據需要啟動或觸發。不需要額外的核心,
因為這兩個副本保證總是可以升級不執行的副本。
SWUpdate將設定bootloader變數以通知新映像已成功安裝。
單系統 - 以獨立映象形式執行
軟體升級應用程式由核心(可裁剪掉不必要的驅動等)
和一個小的根檔案系統以及應用程式及其庫組成。
整個大小遠遠小於系統軟體的一個副本。
根據設定,這個獨立根檔案系統的大小從 2.5MB 到 8MB 不等。
如果說大小對於小型系統非常重要,
那麼對於具有大量儲存或大容量NAND的系統, 其大小則可以忽略不計。
系統可以進入 "升級" 模式,只需向引導載入程式發出必須啟動升級軟體的訊號。
具體方法可能有所不同,例如設定引導載入程式環境或使用和外部GPIO。
引導載入程式啟動“SWUpdate”,
引導SWUpdate核心並將initrd映像作為根檔案系統。
因為它在RAM中執行,所以可以升級整個儲存。
與雙拷貝策略不同,系統必須重新啟動以將其自身置於更新模式。
這個方案比起使用兩個副本,佔用的儲存空間更少,
但是它不能保證在不再次更新軟體的情況下進行回退。
不過,至少它可以保證,當主應用不存在或損壞時,
以及當升級過程由於某種原因而中斷時,系統自動進入升級模式。
事實上,可以將升級過程視為事務,
只有成功升級後,新軟體才設定為“可引導”。
考慮到這些因素,使用此策略進行升級是安全的: 如果舊軟體損壞或無法執行,
始終確保系統啟動並準備好獲得新軟體。
使用U-Boot作為引導載入程式, SWUpdate能夠管理U-Boot的環境設定變數,
以指示事務的開始和結束,以及包含有效的軟體的儲存區域。
針對GRUB環境塊修改和EFI引導保護的類似特性也已被引入。
SWUpdate主要以如下配置的方式使用。
Yocto生成包含SWUpdate應用程式的initrd映像,
該映像在掛載根檔案系統之後自動啟動。
有些事情出錯了 ?
許多事情都可能出錯,必須保證系統能夠再次執行,
並且可能能夠重新載入新的軟體來修復損壞的映像。
SWUpdate與引導載入程式一起工作,以識別失敗的可能原因。
目前支援U-Boot、GRUB和EFI引導保護。
我們至少可以列出一些常見的原因:
-安裝過程中映象損壞。
: SWUpdate能夠識別它,並且更新過程會被中止。
舊的軟體被儲存下來,沒有任何東西被真正複製到目標的儲存中
- 儲存(flash)中損壞的映象
- 遠端更新由於通訊問題而中斷
- 意外掉電
SWUpdate的工作流程是事務性的。引導載入程式的環境變數“recovery_status”
被設定為向引導載入程式發出更新狀態的訊號。
當然,還可以新增更多變數,用於微調和報告錯誤原因。
recovery_status可以取值為“progress”,“failed”,或者它也可以被取消設定。
當SWUpdate啟動時,它將recovery_status設定為“progress”。
更新成功完成後,變數將被刪除。如果更新以錯誤結束,
recovery_status的值為“failed”。
當更新被中斷時,不管什麼原因,引導載入程式都能識別到,
因為recovery_status變數處於“progress”或“failed”狀態。
然後,引導載入程式可以再次啟動SWUpdate,以再次
載入軟體(單副本情況)或執行應用程式的舊副本(雙副本情況)。
意外掉電
如果發生斷電,必須保證系統能夠再次工作 —— 重新
啟動SWUpdate或恢復軟體的舊副本。
一般情況下,行為可以根據所選擇的場景進行劃分:
單拷貝:SWUpdate被中斷,更新事務沒有以成功結束。
引導載入程式能夠再次啟動SWUpdate,從而有可能再次更新軟體。雙拷貝:SWUpdate沒有在備份系統和當前系統之間做切換。
當前版本的軟體,並沒有被更新觸及到,會再次啟動。
為了完全安全,SWUpdate和引導載入程式需要交換一些資訊。
引導載入程式必須檢測更新是否由於斷電而中斷,
並重新啟動SWUpdate,直到更新成功。
SWUpdate支援U-Boot、GRUB和EFI Boot Guard引導載入程式。 U-Boot和EFI Boot
Guard有用於保證掉電安全的環境變數,
SWUpdate能夠讀取和更改這些變數,以此與引導載入程式通訊。
對於GRUB,則使用固定的1024位元組環境變數塊檔案。
SWUpdate在開始更新系統時設定一個變數作為標誌,
並在完成之後重置同一變數。引導載入程式可以讀取此標誌,
以檢查在上次關機之前是否正在執行更新。
升級SWUpdate本身會如何?
SWUpdate被認為用於整個開發過程,代替定製過程以在開發過程中更新軟體。
在投產前,SWUpdate被針對這個專案進行過很好的測試。
如果SWUpdate本身應該被更新,那麼當儲存中只有一個SWUpdate副本時,
更新就不是安全的。只有當SWUpdate擁有兩個副本時,才能保證安全更新。
如果SWUpdate是升級映像的一部分,則有一些方法可以避免這個問題:
- 有兩份SWUpdate
- 承擔風險,但準備一個在引導載入程式中可使用的救援程式。
升級引導載入程式會如何?
更新引導載入程式在大多數情況下無法做到的。
在大多數SOC上,不存在多個引導載入程式的副本,
當引導載入程式被破壞時,板子就無法引導啟動了。
一些soc允許擁有多個引導載入程式副本。
但同樣,沒有通用的解決方案,因為它是 非常 特定於硬體的。
根據我的經驗,大多數產品不允許更新引導載入程式。
當產品準備好量產時,還必須要更新引導載入程式,這種情況是非常少見的。
以上結論不適用於更新U-Boot環境變數,這是一種常見的情況。
U-Boot提供整個環境變數的兩個副本,從SWUpdate中更新環境是
掉電安全的。其他引導載入程式則不一定具有此功能。
注:
本文地址 https://www.cnblogs.com/zqb-all/p/10090280.html
譯自 swupdate 文件 https://sbabic.github.io/swupdate/overview.html
有更新會在github上釋出 https://zqb-all.github.io/swupdate/overview.html