[Rockchip] OTA 更新 firmware images

更新 FW(firmware) 也就是將 FW images 寫入磁區中,而磁區指的是在磁碟中的分區。

本文中,會先對磁碟分區作簡單介紹,接著說明如何以燒錄程式燒錄 FW,再說明如何進行 OTA 更新

 

磁碟分區

Rockchip 預設的磁區分區名稱、對應的 image 及說明如下:
[Rockchip] OTA 更新 firmware ima

Rockchip 系統平台使用 parameter.txt 文件來配置一些系統參數,例如 firmware 版本 及 磁碟分區信息,parameter.txt 最大不能超過 64KB。

parameter.txt 支援兩種磁碟分區格式: GPT 和 傳統的 CMDLINE 格式。

以 RK3326 為例,其 GPT 格式的 parameter.txt 內容如下:

FIRMWARE_VER:9.0
MACHINE_MODEL:RK3326
MACHINE_ID:007
MANUFACTURER: RK3326
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 3326
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE:mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(trust),0x00002000@0x00008000(misc),0x00002000@0x0000a000(dtb),0x00002000@0x0000c000(dtbo),0x00000800@0x0000e000(vbmeta),0x00010000@0x0000e800(boot),0x00030000@0x0001e800(recovery),0x00028000@0x0004e800(backup),0x00002000@0x00076800(security),0x00070000@0x00078800(cache),0x002d0000@0x000e8800(system),0x00008000@0x003b8800(metadata),0x00070000@0x003c0800(vendor),0x00020000@0x00430800(oem),0x00000400@0x00450800(frp),-@0x00450c00(userdata:grow)
uuid:system=af01642c-9b84-11e8-9b2a-234eb5e198a0

 

 而 RK3326 傳統分割格式(CMDLINE)的 parameter.txt 內容如下:

FIRMWARE_VER:9.0
MACHINE_MODEL:RK3326
MACHINE_ID:007
MANUFACTURER: RK3326
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 3326
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
CMDLINE:console=ttyFIQ0 androidboot.console=ttyFIQ0 initrd=0x62000000,0x00800000
mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(trust),0x00002000@0x00008000(misc),0x00002000@0x0000a000(dtb),0x00002000@0x0000c000(dtbo),0x00000800@0x0000e000(vbmeta),0x00010000@0x0000e800(boot),0x00030000@0x0001e800(recovery),0x00028000@0x0004e800(backup),0x00002000@0x00076800(security),0x00070000@0x00078800(cache),0x002d0000@0x000e8800(system),0x00008000@0x003b8800(metadata),0x00070000@0x003c0800(vendor),0x00020000@0x00430800(oem),0x00000400@0x00450800(frp),-@0x00450c00(userdata)

 

GPT 分區 相對於 傳統的分區方式,在 parameter.txt 的主要差異如下:
1、
TYPE: GPT
2、最後一個分區有 
grow 標示。
3、指定 system 或 rootfs 的 UUID(Universal Unique Identifier)。
4、parameter.txt 並不會被當成 image 燒錄,只會用 mtdparts 的分區定義及 UUID 作重新切割磁區的依據,其餘訊息只是為了給升級工具參考。

 

parameter.txt 的幾個重要的欄位說明如下:

FIRMWARE_VER: 打包 updata.img 時會使用到,升級工具會根據這個識別 FW 版本號。

MACHINE_MODEL、MACHINE_ID、在 recovery 里面升級固件時,可以用於判斷 FW 是否匹配。

console=ttyFIQ0 androidboot.console=ttyFIQ0 ,串口定義。

initrd=0x62000000,0x00800000 ,第一個參數是 RAMDISK 加載到 DDR 的位置,第二個參數為RAMDISK 的大小,目前 RAMDISK 大小沒有限制。

androidboot.xxx 的定義在 android 啟動時使用,有些平台會在 kernel 的 dts 里面定義,這部分定義一般不用修改,只用用發布 SDK 默認的就可以了。

MTD 分區定義說明如下:
1、為了兼容性,目前所有 AP 都是用 rk29xxnand 做標識。
2、單個分區說明,以 0x00002000@0x00008000(boot) 為例:
      @符號之前的數值是分區大小,@符號之後的數值是分區的起始位置,
      括號里面的字符是分區的名字。所有數值的單位是 sector ,1個 sector 為512Bytes。
      也就是說,boot 分區起始位置為 0x8000 sectors 位置,大小為 0x2000 sectors,也就是 0x2000 x 512 Bytes = 8192 x 512 Bytes = 4 x 1024 x 1024 Bytes = 4 MB).
3、為了性能,每個分區起始地址需要 32KB(64 sectors)對齊,大小也需要 32KB 的整數倍。
4、如果使用 sparse 格式的鏡像,升級時會擦除數據,為了兼容性更好,對應的分區最好按 4MB 對齊,大小也按 4MB 整數倍配置。

 

 

 

燒錄程式燒錄 FW

FW 燒錄程式介面如下:
[Rockchip] OTA 更新 firmware ima

在 Windows 端開啟燒錄程式後,透過 USB 與裝置進行連接,看到左下方有 "發現一個 MASKROM 設備" 或 "發現一個 LOADER 設備" 的字樣時,表示裝置已進入 MASKROM / LOADER 模式,可以隨時進行燒錄,點選 "執行" 後,即開始燒錄。

燒錄之前,需要依照所分割磁區,設定相對應的 FW Image 路徑,如:
loader => MiniLoaderAll.bin,first bootloader
parameter => parameter.txt,供規劃磁區欄位使用,不單獨寫入磁區
uboot => uboot.img,second bootloader
misc => misc.img,引導參數分區
boot => boot.img,kernel+dtb
recovery => recovery.img,kernel+dtb+ramdisk 组成的根文件系统
rootfs => rootfs.img,根文件系统
oem => oem.img,OEM 廠商可讀寫區
userdata => userdata.img、作業系統儲存資料區

 

 

 

OTA 更新 FW

最一開始的程式開發,都是透過燒錄程式直接與板端對接,進行 FW 燒錄。
而另一種與透過燒錄程式不同的更新方式,是可以從遠端進行更新,不必與板端進行實體的對接,而是透過網路,也就是所謂的 OTA(Over The Air)。

Rockchip Linux 平台支援兩種啟動方案,Recovery 模式和Linux A/B 模式:
1. Recovery 模式,設備上有一個單獨的分區(recovery)用於升級操作。
2. Linux A/B 模式,設備上的磁區分割有兩套完整的系統,可切換使用。

本文中,只會針對 Recovery 模式進行說明。

要支援 Recovery 模式,需要在設備磁區上多規劃一個 Recovery 分區,該分區的 image 由 kernel + resource + ramdisk 組成,主要用於升級時使用

在啟動時,u-boot 會根據 misc 分區存放的字串來判斷接下來要引導的系統是 Normal 系統還是 Recovery 系統。

由於 Recovery 系統的獨立性,所以 Recovery 模式能保證升級的完整性,也就是說,如果升級過程被中斷,例如發生異常掉電,則上電後,升級仍然能繼續執行。

進行 OTA 更新的升級工具 - updateEngine 是透過在 build recovery.img 時,隨之產生的:
$ ./build.sh recovery
檔案預設路徑如下:
buildroot/output/rockchip_rk3588_recovery/build/recovery-develop/updateEngine

用來燒錄的 FW - update.img,則是需要另外 build:
$ ./build.sh updateimg
在 build 的過程,會依據 package-file 的描述,決定要將哪些磁區的 fw image 包到 update.img 中。

在板端,可以進行 OTA 升級時,透過網路位址下載 update.img,指令如下:
updateEngine --image_url=http://172.16.21.110:8080/linuxab/update.img --misc=update --savepath=/userdata/update.img --reboot

如果 update.img 已先下載於板端,則直接更新即可:
updateEngine --image_url=/userdata/update.img --misc=update --savepath=/userdata/update.img --reboot
需要特別注意的是,在上述指令中,其 update.img 的路徑必須為絕對路徑,否則在進入 Recovery 系統後,會無法依相對路徑找到所指定的檔案。

在 OTA 過程中,如有遇到問題,可以在重開機後,查看 log 檔,預設路徑為:
/userdata/recovery/Log

 

OTA 流程

按 log 及測試結果來分析,在執行 updateEngine 的指令後,依 --partition 的參數,其更新步驟分為兩種:
1、更新的磁區有包含 recovery 分區。
2、更新的磁區不包含 recovery 分區。

 

1、如果在 --partition 的參數中,其指定要更新的磁區有包含 recovery 分區,則其更新的步驟如下:

1-1、對 recovery 分區進行更新,將 update.img 中的 recovery.img,更新到板端的 recovery 分區中,並將參數 - boot-recovery 寫入 misc 磁區。

1-2、接著重新啟動裝置,uboot 依 misc 磁區的參數設定,以更新過的 recovery 分區啟動 Recovery 模式。

1-3、在 Recovery 模式下,依 --partition 參數指定的磁區名稱(預設值為 0x3FFC00),將 update.img 的 FW images 更新到指定的磁區。

1-4、最後清空 misc 分區,重新啟動機器,uboot 依 misc 磁區的參數設定,啟動 Normal 模式,也就是一般的系統。

按上述的流程來看,如果在更新 loader 或 uboot 分區時,剛好掉電,導致 loader 或 uboot 分區毀損,則此時系統會死當,因為 loader 及 uboot 都只有一份。
只是 loader 及 uboot 的檔案小,遇到剛好掉電的機率非常低:
$ ll u-boot/rk3588_spl_loader_v1.09.111.bin u-boot/uboot.img
-rw-rw-r-- 1 keith keith  455104 Nov  9 11:52 u-boot/rk3588_spl_loader_v1.09.111.bin
-rw-rw-r-- 1 keith keith 4194304 Nov  9 11:52 u-boot/uboot.img

另依 RK OTA 文件中的說明,OTA 不支援更新的磁區有兩個,分別是 loader 磁區 及 parameter 磁區,所以系統死當的風險,只在於對 uboot 更新的時間點。

如果是在更新 kernel 或 rootfs 分區時,遇到掉電,則完全不會有問題。
復電後,uboot 仍然會根據 misc 分區存放的字串進入 Recovery 模式,再次嘗試燒錄 FW 到其它的分區。

如果是在更新 recovery 分區時,遇到掉電,則重啟後,因為還沒設定 misc 磁區,所以會進入 Normal 模式。

 

2、如果在 --partition 的參數中,其指定要更新的磁區不包含 recovery 分區,則其更新的步驟如下:

2-1、直接依 --partition 參數指定的磁區名稱(預設值為 0x3FFC00),將 update.img 的 FW images 更新到指定的磁區。

2-2、重新啟動機器。

在這個方式下,無法更新 rootfs 磁區,但程式沒有作防呆。
如果把 update.img 放在 userdata 磁區,則也無法更新 userdata 磁區,但程式也沒有作防呆。

 

--partition 參數所代表的磁區

--partition 參數是用來指定要更新的磁區,每個磁區都由一個特定的 bit 代表,如下:
1000 0000 0000 0000 0000 0000: Upgrade loader
0100 0000 0000 0000 0000 0000: Upgrade parameter
0010 0000 0000 0000 0000 0000: Upgrade uboot
0001 0000 0000 0000 0000 0000: Upgrade trust
0000 1000 0000 0000 0000 0000: Upgrade boot
0000 0100 0000 0000 0000 0000: Upgrade recovery
0000 0010 0000 0000 0000 0000: Upgrade rootfs
0000 0001 0000 0000 0000 0000: Upgrade oem
0000 0000 1000 0000 0000 0000: Upgrade uboot_a
0000 0000 0100 0000 0000 0000: Upgrade uboot_b
0000 0000 0010 0000 0000 0000: Upgrade boot_a
0000 0000 0001 0000 0000 0000: Upgrade boot_b
0000 0000 0000 1000 0000 0000: Upgrade system_a
0000 0000 0000 0100 0000 0000: Upgrade system_b
0000 0000 0000 0010 0000 0000: Upgrade misc
0000 0000 0000 0001 0000 0000: Upgrade userdata

如果沒有指定 --partition,則其預設為 3FFC00,為 0011 1111 1111 1100 0000 0000.,也就是對以下磁區(如果該磁區存在的話)進行更新:
uboot, trust, boot, recovery, rootfs, oem, uboot_a, uboot_b, boot_a, boot_b, system_a, system_b

舉例來說,指令可以是:(更新:uboottrustbootrecoveryrootfsoem、)
# ./updateEngine --image_url=/userdata/update.img --partition=0x3F0000 --misc=update --savepath=/userdata/update.img --reboot

有個怪異的現象是,以測試結果來看,如果更新了 recovery 分區,就算不指定更新 rootfs 分區,則 rootfs 分區也會自動被一併更新。

 

 

解析 package-file

package-file 的路徑為:
tools/linux/Linux_Pack_Firmware/rockdev/package-file
預設的內容如下:

# NAME        Relative path
#
#HWDEF        HWDEF
package-file    package-file
bootloader    Image/MiniLoaderAll.bin
parameter    Image/parameter.txt
#trust        Image/trust.img
uboot        Image/uboot.img
misc        Image/misc.img
#resource    Image/resource.img
#kernel        Image/kernel.img
boot        Image/boot.img
recovery    Image/recovery.img
rootfs        Image/rootfs.img
oem        Image/oem.img
userdata    Image/userdata.img
# 要写入backup分区的文件就是自身(update.img)
# SELF 是关键字,表示升级文件(update.img)自身
# 在生成升级文件时,不加入SELF文件的内容,但在头部信息中有记录
# 在解包升级文件时,不解包SELF文件的内容。
backup        RESERVED
#update-script    update-script
#recover-script    recover-script

每一列就是一個磁區的說明,第一個欄位是磁區名稱,第二個欄位即是該磁區名稱所對應的 FW image。
如此就可以依磁區的名稱,將所對應的 image 加到 update.img 中。
如果不需要該磁區,則移除該列或在該列前加上 # 符號即可。

 

 

檔案磁區

更新 File System 磁區後,如果遇到容量不符合預期的情況,可以利用 resize2fs 指令來恢復容量:
# resize2fs /dev/mmcblk2p6

 

 

 

Reference

Rockchip_Introduction_Partition_CN.pdf - V1.5.0

Rockchip_Developer_Guide_Linux_Upgrade_CN.pdf - V1.1.0

 

 

 

文字內容 或 影像內容 部份參考、引用自網路,如有侵權,請告知。

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 silverwind1982 的頭像
    silverwind1982

    拾人牙慧

    silverwind1982 發表在 痞客邦 留言(0) 人氣()