在嵌入式系統(尤其是Rockchip平臺Android設備)中,A/B(Seamless Update)無縫更新是保障系統更新不丟數據、更新失敗可回滾的核心機制。而SPL(Secondary Program Loader,二級程序加載器)作為系統啟動的早期階段,負責初始化硬件、選擇啟動分區,spl_ab.c正是SPL層處理A/B分區啟動的核心代碼。本文將從函數解析、核心流程、開發意義三個維度,徹底拆解這段代碼。
一、A/B分區與SPL的核心作用
A/B分區將系統分為兩個獨立的槽位(Slot A/Slot B),更新時先更新非當前啟動的槽位,更新完成后切換槽位啟動;若啟動失敗,自動回退到原槽位。
SPL是BootLoader的早期階段,執行優先級最高,spl_ab.c的核心目標是:讀取A/B元數據、判斷槽位可啟動性、選擇最優啟動槽位、處理啟動失敗后的嘗試次數遞減與系統重置。
二、核心函數分類解析
代碼中的函數可分為7大類,覆蓋“基礎工具→元數據處理→槽位管理→啟動流程”全鏈路,以下是關鍵函數的作用拆解:
1.基礎工具函數:解決通用問題
|
函數名
|
核心作用
|
|
safe_memcmp
|
安全的內存比較,無數據依賴分支(避免側信道攻擊),返回兩內存區域是否不相等(0=相等,非0=不等)
|
|
htobe32
|
主機字節序→大端字節序轉換(A/B元數據存儲為大端)
|
|
be32toh
|
大端字節序→主機字節序轉換(讀取元數據后適配本地CPU)
|
2. A/B元數據處理:校驗/更新/初始化
A/B元數據(AvbABData)存儲在misc分區,包含槽位優先級、剩余嘗試次數、啟動成功標記等關鍵信息,這組函數是元數據操作的核心:
|
函數名
|
核心作用
|
|
spl_ab_data_verify_and_byteswap
|
校驗元數據合法性:
|
|
spl_ab_data_update_crc_and_byteswap
|
更新元數據的CRC32:先拷貝數據,再計算CRC32并轉換為大端序(用于寫入存儲)
|
|
spl_ab_data_init
|
初始化默認元數據:
|
3.元數據讀寫:對接存儲層
|
函數名
|
核心作用
|
|
spl_read_ab_metadata
|
從misc分區指定偏移讀取元數據到內存(單次讀512字節,適配塊設備讀寫粒度)
|
|
spl_write_ab_metadata
|
將內存中的元數據寫入misc分區指定偏移
|
|
spl_ab_data_read
|
封裝“讀取+校驗”:讀取失敗/校驗失敗時,初始化新元數據并寫入misc分區
|
|
spl_ab_data_write
|
封裝“更新CRC+寫入”:先更新CRC32,再寫入存儲
|
4.槽位選擇:核心決策邏輯
|
函數名
|
核心作用
|
|
spl_slot_is_bootable
|
判斷槽位是否可啟動:優先級>0且(已成功啟動 或 剩余嘗試次數>0)
|
|
spl_get_lastboot
|
獲取上次啟動的槽位索引(0=A,1=B)
|
|
spl_get_current_slot
|
選擇當前要啟動的槽位(核心函數):
|
5.分區名處理:適配槽位后綴
|
函數名
|
核心作用
|
|
spl_ab_append_part_slot
|
給分區名追加槽位后綴(如boot→boot_a);misc分區例外(無后綴);獲取槽位失敗時直接返回原分區名
|
6.槽位狀態管理:處理啟動失敗
|
函數名
|
核心作用
|
|
spl_slot_set_unbootable
|
標記槽位為不可啟動:優先級、剩余嘗試次數、啟動成功標記全置0
|
|
spl_slot_normalize
|
規范化槽位狀態(處理非法場景):
|
|
spl_ab_decrease_tries
|
啟動失敗時減少當前槽位嘗試次數:
|
|
spl_ab_decrease_reset
|
啟動失敗后重置系統:
|
7.啟動參數傳遞:對接內核
|
函數名
|
核心作用
|
|
spl_ab_bootargs_append_slot
|
給設備樹(FDT)的啟動參數(bootargs)追加槽位后綴(如android.slot_suffix=_a),讓內核感知當前啟動槽位
|
三、SPL階段A/B啟動核心流程圖

四、開發者關注這段代碼的核心意義
對于嵌入式開發者(尤其是Rockchip/Android BootLoader開發者),理解spl_ab.c是保障A/B啟動穩定的關鍵,核心價值體現在5個方面:
1.快速定位啟動故障
當設備出現“A/B啟動失敗、卡在SPL階段、槽位切換異常”時,可通過代碼日志(如“CRC32 does not match”“No bootable slots found”)定位根因:
?元數據CRC不匹配:misc分區損壞,spl_ab_data_read會自動初始化元數據;
?無可用槽位:兩槽位嘗試次數耗盡,需手動重置元數據;
?槽位被標記為不可啟動:檢查spl_slot_normalize是否觸發了非法狀態處理。
2.定制A/B更新策略
默認邏輯可根據產品需求調整:
?調整默認優先級/嘗試次數:修改spl_ab_data_init中的AVB_AB_MAX_PRIORITY/AVB_AB_MAX_TRIES_REMAINING;
?自定義槽位選擇規則:修改spl_get_current_slot(如優先級相同時選上次啟動的槽位,而非默認的Slot A);
?調整啟動失敗后的行為:修改spl_ab_decrease_reset(如增加重試次數閾值,或取消自動重置)。
3.適配不同硬件平臺
不同存儲設備(eMMC/NAND/SD卡)的塊設備讀寫(blk_dread/blk_dwrite)邏輯有差異,需確保spl_read/write_ab_metadata適配硬件;不同CPU架構的字節序可能不同,需驗證htobe32/be32toh的正確性。
4.提升系統穩定性
?safe_memcmp避免側信道攻擊,提升元數據比較的安全性;
?spl_save_metadata_if_changed僅在元數據變化時寫入存儲,減少misc分區的寫操作,延長存儲壽命;
?spl_slot_normalize處理非法狀態,避免因元數據異常導致的啟動邏輯崩潰。
5.適配Android無縫更新標準
Android A/B無縫更新的核心是槽位管理,這段代碼是SPL層對接Android A/B規范的關鍵,確保更新后能正確切換槽位啟動,失敗時自動回滾,符合Google的A/B更新標準。
五、總結
spl_ab.c是SPL階段A/B分區啟動的“大腦”,從元數據讀寫、槽位決策到啟動失敗處理,覆蓋了A/B啟動的全核心流程。對于嵌入式開發者而言,理解這段代碼不僅能快速定位啟動故障,還能根據產品需求定制更新策略,保障設備在無縫更新場景下的穩定性與兼容性。
無論是調試A/B啟動問題,還是適配新硬件平臺,spl_ab.c都是必須深入掌握的核心模塊——它是連接硬件初始化與系統啟動的關鍵橋梁,也是保障Android無縫更新落地的基礎。
-
Android
+關注
關注
12文章
4033瀏覽量
134267 -
嵌入式系統
+關注
關注
41文章
3766瀏覽量
133782 -
代碼
+關注
關注
30文章
4974瀏覽量
74210 -
spl
+關注
關注
0文章
22瀏覽量
16784 -
Rockchip
+關注
關注
0文章
92瀏覽量
19635
發布評論請先 登錄
更新 SPL 和 U-Boot的提示和技巧
如何使 i.MX93 上的 U-Boot SPL 和 ATF/BL31輸出靜音呢?
Microchip 93XX56A/B/C系列2K Microwire兼容串行EEPROM深度解析
實戰排障|RK平臺啟動卡死、SPL崩潰,兩行日志直接定位DDR硬件死穴!
Microchip 93XX66A/B/C系列4Kbit低電壓串行EEPROM深度解析
U-Boot SPL核心文件spl.c深度解析:從啟動流程到調試優化
深入解析U-Boot TPL代碼:嵌入式啟動的“第一棒”背后的秘密
德州儀器LM5100A/B/C和LM5101A/B/C系列高壓柵極驅動器的深度解析
Texas Instruments LM5100A/B/C和LM5101A/B/C高壓柵極驅動器深度解析
d1哪吒開發板的啟動流程分析
國產!全志T113-i 雙核Cortex-A7@1.2GHz 工業開發板—eMMC配置核心板使用說明(二)
深度解析SPL階段A/B分區啟動:spl_ab.c代碼全拆解
評論