【swupdate文檔 三】SWUpdate: 嵌入式系統的軟件升級


SWUpdate: 嵌入式系統的軟件升級
轉自:https://www.cnblogs.com/zqb-all/p/10090280.html
概述
本項目被認為有助於從存儲媒體或網絡更新嵌入式系統。但是,它應該主要作為一個框架來考慮,在這個框架中可以方便地向應用程序添加更多的協議或安裝程序(在SWUpdate中稱為處理程序)。
一個用例是從外部本地媒體(如USB-Pen或sd卡)進行更新。在這種情況下,更新是在沒有操作員干預的情況下完成的:它被認為是“一鍵更新”,軟件在復位時啟動,只需按下一個鍵(或者以任何目標可以識別的方式),自動進行所有檢查。最后,更新過程只向操作員報告狀態(成功或失敗)。
輸出可以使用幀緩沖設備顯示在LCD上,也可以定向到串行通訊端口上(Linux控制台)。
它通常用於單拷貝方案中,在initrd中運行(用Yocto提供的配方生成)。但是,通過使用軟件集合( collections ),可以在雙拷貝方案中使用它。
如果啟動了遠程更新,SWUpdate將啟動嵌入式web服務器並等待請求。操作者必須上傳一個合適的映像,然后SWUpdate會進行檢查並安裝。所有輸出都通過AJAX通知的方式通知操作人員的瀏覽器。
功能
總體概覽
安裝在嵌入式介質上(eMMC、SD、Raw NAND、NOR、SPI-NOR flash)
檢查鏡像是否可用。鏡像以指定的格式(cpio)構建,它必須包含一個描述文件,以描述必須更新的軟件。
SWUpdate被認為可以更新設備上的UBI卷(主要用於NAND,但不限於NAND)和鏡像。傳遞整個鏡像仍然用於對SD卡上的分區或MTD分區進行更新。
新分區模式。這與UBI容量有關。SWUpdate可以重新創建UBI卷,調整它們的大小並復制新軟件。一個名為“data”的特殊UBI卷在重新分區時,用於保存和恢復數據,以保持好用戶數據。
使用zlib庫支持壓縮鏡像。支持tarball (tgz文件)。
支持帶分區的USB-pen或未分區盤(主要用於Windows)。
支持更新文件系統中的單個文件。必須明確描述該文件所在的文件系統位置。
支持圖像中單個組件的校驗和
使用結構化語言來描述鏡像。 這是使用 libconfig庫作為缺省解析器完成的,它使用一種類似json的描述。
使用自定義的方式來描述鏡像。可以使用Lua語言編寫自己的解析器。examples目錄中提供了一個使用Lua中的XML描述的示例。
支持設置/刪除U-Boot變量
支持設置/擦除 GRUB環境塊變量
支持設置/刪除 EFI Boot Guard 變量
使用嵌入式web服務器的網絡安裝程序(在Lua許可下的版本中選擇了Mongoose服務器)。可以使用不同的web服務器。
多種獲取軟件的接口 : - 本地存儲: USB, SD, UART,..
OTA / 遠程 : - 集成的網絡服務器 
從遠程服務器拉取(HTTP, HTTPS, ..)
使用后端。SWUpdate是開放的,可以與后端服務器進行通信,以推出軟件更新。當前版本支持Hawkbit服務器,但可以添加其他后端。
可以配置為檢查軟件和硬件之間的兼容性。軟件映像必須包含條目,聲明這個軟件可在什么版本硬件上運行。如果沒有通過兼容性驗證,SWUpdate將拒絕安裝。
支持鏡像提取。制造商用一個映像包含用於多個設備的軟件。這簡化了制造商的管理,並降低了單一軟件產品的管理成本。SWUpdate以流的形式接收軟件,不進行臨時存儲,並只提取需要安裝的設備組件。
允許自定義處理器,通過自定義協議安裝FPGA固件,微控制器固件。
使用“make menuconfig”啟用/禁用特性。(Kbuild繼承自busybox項目)
鏡像在安裝之前經過身份認證和校驗
掉電安全
交付單一鏡像
主要概念是制造商提供單個大圖像。所有單個的鏡像都被打包在一起(選擇cpio是因為它的簡單性和可流式處理),同時打包的還有另一個文件(sw-description),該文件包含每個獨立鏡像的元信息。
sw-description的格式是可定制的:可以將SWUpdate配置為使用其內部解析器(基於libconfig),或者在調用外部的lua解析器。
 
可以使用外部解析器,改變對鏡像的接受規則,以擴展支持新的鏡像類型,指明它們需要如何安裝。實際上,解析器就是檢索必須安裝哪些單個的鏡像以及如何安裝。
SWUpdate使用“處理程序”來安裝單個鏡像:有用於將鏡像安裝到UBI卷或SD卡、CFI閃存等的處理程序。如果需要特殊的安裝程序,那么也可以很容易地添加自己的處理程序。
例如,我們可以考慮一個帶有主處理器和一個或幾個微控制器的項目。為了簡單起見,我們假設主處理器使用專用協議通過UARTS與微控制器通信。微控制器上的軟件可以使用專用協議進行更新。
可以擴展swuodate,編寫一個處理程序,實現專用協議的一部分來對微控制器進行升級。解析器必須識別哪個鏡像必須用新的處理程序來安裝,隨后SWUpdate將在安裝過程中調用該處理程序。
流式更新功能
SWUpdate被認為能夠將接收到的鏡像直接流式更新到目標中,而不需要任何臨時副本。實際上,單個安裝程序(處理程序)會接收一個文件描述符作為輸入,該文件描述符設置在必須安裝的圖像的開始處。
該特性可以基於鏡像進行設置,這意味着用戶可以決定鏡像的哪些部分應該流式處理。如果沒有流式處理(請參見installed-direct標志),文件將臨時提取到環境變量 TMPDIR 指向的目錄中,如果沒有 設置 TMPDIR,則默認使用 /tmp 。當然,使用流式處理,則不可能在安裝之前檢查整個交付的軟件。臨時副本僅在從網絡更新時使用。 當映像存儲在外部存儲上時,不需要該副本。
完全流式更新鏡像
在遠程更新的情況下,SWUpdate從流中提取相關圖像,並將它們復制 到環境變量TMPDIR (如果未設置,則復制到 /tmp )指向的目錄中,然后調用處理程序。這確保只有在所有部件都存在且正確時才會啟動更新。
但是,在一些資源較少的系統上,用於復制鏡像的RAM空間可能不足,例如,如果必須更新附加SD卡上的文件系統的話。在這種情況下,如果圖像能由相應的處理程序直接作為流安裝,而不需要臨時副本的話,則會很有幫助。並非所有處理程序都支持直接流式更新目標。零拷貝流是通過在單個鏡像像的描述中設置“installed-directly”標志來啟用的。
配置和構建
需求
編譯SWUpdate只需要依賴幾個庫。
mtd-utils: mtd-utils在內部生成libmtd和libubi。它們通常不導出也不安裝,但是SWUpdate將鏈接它們,以便重用相同的功能來升級MTD和UBI卷。
openssl: web服務器需要。
Lua: liblua和開發頭文件。
libz和libcrypto總是需要被鏈接。
libconfig: 被默認解析器使用。
libarchive (可選的)用於存檔處理程序。
libjson (可選的)用於JSON解析器和Hawkbit。
libubootenv (可選的) 如果啟用了對U-Boot的支持則需要。
libebgenv (可選的) 如果啟用了對EFI Boot Guard的支持則需要。
libcurl 用於網絡通訊。
新的處理程序可以向需求列表中添加一些其他的庫
-當出現構建錯誤時,檢查是否需要所有的處理程序,然后刪除其中不需要的部分。
在Yocto中進行構建
提供了一個 metasswupdate 層.它包含了mtd-utils和生成Lua所需的更改。
使用meta-SWUpdate只需一些簡單的步驟。
首先,克隆 meta-swupdate.
git clone https://github.com/sbabic/meta-swupdate.git
像往常一樣向 bblayer.conf 添加 meta-swupdate。 你還需要將 meta-oe 添加到list中。
在meta-swupdate中,有一個配方,用於生成帶有swupdate的initrd救援系統。
使用:
MACHINE=<your machine> bitbake swupdate-image
你將在 tmp/deploy/<your machine> 目錄中找到生成的結果。
如何安裝和啟動initrd是跟具體目標強相關的 - 請查閱你的引導加載程序的文檔。
libubootenv呢 ?
這是構建SWUpdate時常見的問題。SWUpdate依賴於這個庫,它是從U-Boot源碼生成的。
這個庫允許安全地修改U-Boot環境變量。如果不使用U-Boot作為引導加載程序,則不需要它。
如果無法SWUpdate正常鏈接,則你使用的是舊版本的U-Boot(你至少需要2016.05以上的版本)。
如果是這樣,你可以為包u-boot-fw-utils添加自己的配方,以添加這個庫的代碼。
重要的是,包u-boot-fw-utils是用相同的引導加載程序源碼和相同的機器構建的。
事實上,設備可以使用一份直接鏈接到uboot中的默認環境變量,而不需要保存在存儲器上。
SWUpdate應該知道這一點,因為它不能讀取這份環境變量:默認的這份環境變量也必須被鏈接到SWUpdate中。這是在libubootenv內部完成的。
如果構建的時候選擇了不同的機器,SWUpdate將在第一次嘗試更改環境變量時破壞環境變量。實際上,使用了錯誤的默認環境后,你的板子將不能再次被引導啟動。
配置SWUpdate
SWUpdate可以通過“make menuconfig”配置。使用內部解析器和禁用web服務器可以達到較小的內存占用。每個選項都有描述其用法的小幫助說明。 在默認配置中,許多選項已經被激活。
要配置選項請執行:
make menuconfig
構建
要進行交叉編譯,請在運行make之前設置CC和CXX變量。 也可以使用make menuconfig將交叉編譯器前綴設置為選項。
生成代碼
make
結果是一個二進制文件“swupdate”。第二個構建的二進制文件是"process",但這並非嚴格要求的。這是一個示例,演示如何構建自己的SWUpdate接口來在HMI上顯示進度條或任何你想要的東西。具體到這個示例,則是簡單地在控制台打印更新的當前狀態。
在Yocto構建系統中,:
bitbake swupdate
這將進行包的構建
bitbake swupdate-image
這將構建一個救援鏡像。 結果是一個可以由引導加載程序直接加載的Ramdisk。要在雙拷貝模式下使用SWUpdate的話,則將包swupdate放到你的rootfs中。檢查你的鏡像配方文件,並簡單地將其添加到安裝包的列表中。
例如,如果我們想將它添加到標准的“core-image-full-cmdline”鏡像中,我們可以添加一個
recipes-extended/images/core-image-full-cmdline.bbappend
IMAGE_INSTALL += " \
                        swupdate \
                        swupdate-www \
                 "
swupdate-www是一個帶有網站的軟件包,你可以用自己的logo、模板和風格進行定制。
編譯一個debian包
SWUpdate被認為是用於嵌入式系統的,在嵌入式發行版中構建是首要的情況。但是除了最常用的嵌入式構建系統Yocto或Buildroot之外,在某些情況下還會使用標准的Linux發行版。不僅如此,發行版包還允許為了測試目的在Linux PC上運行SWUpdate,而不必與依賴項做斗爭。使用debhelper工具,可以生成debian包。
編譯一個debian包的步驟
./debian/rules clean
./debian/rules build
fakeroot debian/rules binary
結果是一個存儲在父目錄中的“deb”包。
對源包簽名的替代方法
你可以使用dpkg-buildpackage:
dpkg-buildpackage -us -uc
debsign -k <keyId>
運行SWUpdate
運行一次swupdate可以期望得到什么
SWUpdate的運行主要包括以下步驟:
檢查介質(usb pen)
檢查鏡像文件。擴展名必須是.swu
從鏡像中提取sw-description並驗證它,它解析sw-description,在RAM中創建關於必須執行的活動的原始描述。
讀取cpio歸檔文件並驗證每個文件的校驗和,如果歸檔文件未完全通過驗證,SWUpdate將停止執行。
檢查硬件-軟件兼容性,如果有的話,從硬件中讀取硬件修改,並與sw-description中的表做匹配。
檢查在sw-description中描述的所有組件是否真的在cpio歸檔中。
如果需要,修改分區。這包含UBI卷的大小調整,而不是MTD分區的大小調整。一個名為“data”的卷被用於在調整大小時保存和恢復數據。
執行預運行腳本
遍歷所有鏡像並調用相應的處理程序以便在目標上安裝。
執行安裝后腳本
如果在sw-description中指定了更改,則更新引導加載程序環境變量。
向操作人員報告狀態(stdout)
有一個步驟失敗,則會停止整個過程並報告錯誤。
運行SWUpdate從文件中獲取鏡像:
swupdate -i <filename>
帶着嵌入式服務器啟動:
swupdate -w "<web server options>"
web服務器主要的重要參數是"document-root"和"port"。
swupdate -w "--document-root ./www --port 8080"
嵌入式web服務器取自Mongoose項目。
檢索所有選項列表:
swupdate -h
這個完整使用隨着代碼交付的也沒。當然,它們可以定制和替換。網站使用AJAX與SWUpdate進行通信,並向操作人員顯示更新的進度。
web服務器的默認端口是8080。你可以從如下網址連接到目標設備:
http://<target_ip>:8080
如果它正常工作,則開始頁面應該顯示如下圖所示。
 
如果下載了正確的鏡像,SWUpdate將開始處理接收到的鏡像。所有通知都被發送回瀏覽器。SWUpdate提供了一種機制,可以將安裝進度發送給接收方。實際上,SWUpdate接受一個對象列表,這些對象在應用程序中注冊了自身,在調用notify()函數時就會通知它們。
這也允許自行編寫處理程序通知上層錯誤條件或簡單地返回狀態。這使得可以簡單地添加一個自己的接收器,以實現以自定義的方式顯示結果:在LCD上顯示(如果設備上有的話),或者通過網絡發送 回另一個設備。
發送回瀏覽器的通知示例如下圖所示:
 
軟件集合可以通過傳遞 --select 命令行選項來指定。 假設 sw-description文件包含一個名為 stable 的集合, 加上 alt 的安裝位置,則可以這樣調用SWUpdate
swupdate --select stable,alt
命令行參數
Parameter
Type
描述
-f 
string
要使用的SWUpdate配置文件
-b 
string
只有當選上CONFIG_UBIATTACH時才有效, 它在SWUpdate搜索UBI卷時將MTDs列入黑名單。 示例:MTD0-1中的U-BOOT和環境變量 swupdate -b “0 1”
-e 
string
sel 的格式為 , 它允許在sw-description文件中找到一個規則 的子集。有了這個選項就可以使用多重規則了 一種常見用法是在雙拷貝模式下。例如: -e “stable, copy1” ==> install on copy1 -e “stable, copy2” ==> install on copy2
-h
 
使用幫助
-k
string
選中 CONFIG_SIGNED 時可用 指定公鑰文件
-l 
int
設置log級別
-L
 
將log輸出到 syslog(local)
-i 
string
使用本地.swu文件運行SWUpdate
-n
 
在模擬(dry-run)模式下運行SWUpdate
-N
string
傳入當前安裝的軟件版本。這將用於檢查 新軟件版本一起檢查,禁止升級到舊版本。 版本號由4個數字組成: major.minor.rev.build 每個字段都要在0..65535的范圍內
-o 
string
將流(SWU)保存到一個文件中
-v
 
激活詳細的輸出信息
-w 
string
啟動內部webserver並將命令行字符串傳遞給它
-u 
string
啟動內部suricatta客戶端守護進程, 並將命令行字符串傳遞給它 詳見suricatta的文檔
-H 
string
設置板名和硬件版本
-c
 
這個選項將檢查 *.swu 文件的內部。 它確保sw-description中引用的文件是存在的。 使用方法: swupdate -c -i 
-p
string
執行安裝后命令
-d 
string
選中 CONFIG_DOWNLOAD 時可用 啟動內部下載程序客戶端, 並將命令行字符串傳遞給它。 請參閱下載程序的內部命令行參數
-u 
string
這是提取新軟件的URL。 URL是指向有效.swu鏡像的鏈接
-r 
integer
下載失敗前重試的次數。使用“-r 0”,則 SWUpdate在加載到有效軟件之前不會停止
-t 
integer
判斷下載連接丟失的超時時間
-a 
string
發送用於基本身份驗證的用戶名和密碼
systemd集成
SWUpdate 具有可選的systemd支持,是由編譯配置開關 CONFIG_SYSTEMD
控制的。如果啟用,SWUpdate將向systemd發送關於啟動完成的信號,並可以可選地使用systemd的socket-based activation功能。
一個systemd服務單元文件的示例 /etc/systemd/system/swupdate.service以suricatta守護進程模式啟動SWUpdate,可能看起來像以下的樣子:
[Unit]
Description=SWUpdate daemon
Documentation=https://github.com/sbabic/swupdate
Documentation=https://sbabic.github.io/swupdate
 
[Service]
Type=notify
ExecStart=/usr/bin/swupdate -u '-t default -u http://localhost -i 25'
 
[Install]
WantedBy=multi-user.target
通過 systemctl start swupdate.service 進行啟動, SWUpdate在啟動時(重新)創建套接字。為了使用socket-based activation,還必須附帶一個systemd套接字單元文件 /etc/systemd/system/swupdate.socket :
[Unit]
Description=SWUpdate socket listener
Documentation=https://github.com/sbabic/swupdate
Documentation=https://sbabic.github.io/swupdate
 
[Socket]
ListenStream=/tmp/sockinstctrl
ListenStream=/tmp/swupdateprog
 
[Install]
WantedBy=sockets.target
在 swupdate.socket 被啟動后, systemd創建套接字文件,並在SWupdate啟動時將它們交給SWUpdate. 例如,當與 /tmp/swupdateprog對話時,systemd啟動 swupdate.service 並移交套接字文件。 在以systemctl start swupdate.service "常規"啟動SWupdate時也會傳遞Socket文件。
注意,兩個 ListenStream= 指令中的套接字路徑 必須與SWUpdate配置中的CONFIG_SOCKET_CTRL_PATH 和 CONFIG_SOCKET_PROGRESS_PATH
中的套接字路徑匹配。 這里描述了缺省套接字路徑配置。
引導啟動程序的修改
SWUpdate 包含了內核和一個根文件系統(鏡像),這必須由一個引導加載程序來啟動。如果使用U-Boot, 可以實現以下機制:
U-Boot檢查是否需要進行軟件更新(檢查gpio、串行控制台等)。
腳本“altbootcmd”設置啟動SWUpdate的規則
當需要SWUpdate時, U-boot運行腳本"altbootcmd"
更改U-Boot環境變量是安全的嗎?是的,但是必須正確配置U-Boot。Uboot支持雙備份環境變量,這可以使得更新器件掉電是安全的。板子的配置文件必須定義CONFIG_ENV_OFFSET_REDUND或CONFIG_ENV_ADDR_REDUND。查閱U-Boot文檔了解這些常量的作用以及如何使用它們。
還有一些可選的增強可以集成到U-boot中,以使系統更安全。其中我會建議的最重要的一個,是添加啟動技術支持到uboot中(文檔在uboot的docs路徑下)。這講允許U-Boot追蹤對成功啟動應用的嘗試。如果啟動計數超過了限制,則可以自動啟動SWupdate,以替代損壞了的軟件。
GRUB默認情況下不像U-Boot那樣支持環境變量的雙副本。這意味着,在環境塊更新期間斷電時,環境塊有可能損壞。
為了最小化風險,我們沒有直接修改原始環境塊。而是將變量寫入臨時文件,並在操作成功后調用rename指令。
構建一個單個的鏡像
cpio由於其簡單性而被用作容器。由此可以很簡單地生成鏡像。描述鏡像的文件(默認是"sw-description",但是名稱是可以配置的)必須是cpio歸檔中的第一個文件。 要生成鏡像,可以使用以下腳本:
CONTAINER_VER="1.0"
PRODUCT_NAME="my-software"
FILES="sw-description image1.ubifs \
       image2.gz.u-boot uImage.bin myfile sdcard.img"
for i in $FILES;do
    echo $i;done | cpio -ov -H crc > ${PRODUCT_NAME}_${CONTAINER_VER}.swu
單個的子圖像可以在cpio容器中按任意順序放置,除了sw-description,它必須是第一個子鏡像。要檢查生成的鏡像,可以運行以下命令:
swupdate -c -i my-software_1.0.swu
對復合鏡像的支持
在Yocto中可以自動生成單個鏡像。 meta-swupdate使用swupdate類擴展了類。配方應該繼承它,並添加自己的sw-description文件來生成鏡像。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM