武柯安,李庭勝,吳傳偉
(中國電子科技集團公司第三十研究所 四川 成都 610041)
一種無操作系統下SOC軟件增量升級方法
武柯安,李庭勝,吳傳偉
(中國電子科技集團公司第三十研究所 四川 成都610041)
無操作系統下,SOC的軟件升級一般采用整體替換的方式,無法獨立升級特定的軟件模塊。通過深入分析SOC目標代碼結構以及目標代碼間的鏈接機制,提出了一種軟件增量升級的方法。首先,開發者獨立編譯待升級模塊并按照一定的格式修改其目標文件,生成升級數據包。之后,SOC接收該數據包,根據協議規范,加載并修改相關指令,完成最終的升級工作。經實驗驗證分析,方案可有效地實現無操作系統下SOC軟件模塊的增量升級。
嵌入式系統;增量升級;動態鏈接;地址無關編碼
無操作系統下的嵌入式處理器一般通過整體替換原代碼以實現軟件升級維護[1]。由于沒有操作系統的支撐,SOC上的軟件模塊無法通過更換動態鏈接庫的方式獨立升級。因此,即使對原始版本的軟件只進行了很小的改動,開發端也必須重新編譯整個工程。為此,文中通過深入分析SOC目標代碼結構以及目標代碼間的鏈接機制,提出了一種針對軟件模塊進行增量升級的新技術。與傳統的整體升級技術相比,這種增量升級技術具有以下幾方面的優點:
1)設備升級過程對用戶完全透明,用戶只需接收設備維護人員遠程分發的升級數據包即可,顯著降低了設備升級維護難度;
2)在一定程度上實現了上層功能軟件與底層硬件無關,提高了代碼的可重用性;
3)可有效減小升級數據包的大小,從而降低了對信道資源的開銷,提高了較低信道帶寬下的升級效率和一次成功率;
文中實驗中采用的處理器為某國產SOC,其CPU為32 位RSIC內核CK520,編譯器兼容gcc 4.5.1版本。對于開發環境兼容GNU工具鏈的大部分處理器而言,本文提出的技術手段均適用。
程序編譯通常包括預處理、編譯、匯編和鏈接4個步驟。編譯器根據語法規則以及處理器的指令集,將每個源代碼文件編譯成對應的目標文件。鏈接器對這些目標文件中的符號進行重定位,將幾個獨立的目標文件鏈接為最終的可執行文件。鏈接分為靜態鏈接和動態鏈接兩種。靜態鏈接由編譯工具在編譯過程中完成。動態鏈接則由操作系統在程序運行過程中完成[2]。
文中提出的一種基于軟件模塊動態加載模型的SOC增量升級技術綜合使用了靜態鏈接和動態鏈接技術,從而有效避免了僅升級部分軟件時對整機軟件的整體替換。
1.1靜態鏈接
目標文件一般按照可執行鏈接格式 (Executable and Linking Format,ELF)進行格式化存儲[4]。ELF文件起始處為大小固定的ELF Header,該字段給出了節頭表(Section Header Table)相對文件起始處的偏移地址。而節頭表中則以結構體數組的形式存儲了ELF文件中所有段的信息,包括段名稱、段類型、段的偏移地址等。在所有段中,一個比較重要的段是“.symtab段”。該段保存了模塊中所有符號的信息,包括符號名、符號類型、符號相對段起始位置的偏移等。對于可被靜態鏈接的目標文件而言,還有一類以.rela為前綴的重定位段,如“.rela.text段”、“.rela.data段”等。這些段存儲了目標文件中所有符號的重定位信息,包括符號名、符號類型、符號重定位入口(即該目標文件在此位置引用了需重定位的符號)。ELF文件結構如下圖所示。

圖1 ELF文件的存儲結構Fig.1 The structure of ELF files
匯編完成后,各目標文件中所有被引用的外部全局符號的地址均被置為虛地址。靜態鏈接時,鏈接器將所有目標文件的相似段進行合并,同時分配加載存儲地址(Load Memory Address,LMA)和虛擬存儲地址 (Virtual Memory Address,VMA)即代碼在SRAM中的加載地址[3]。此時,所有全局符號在程序運行時的地址均已確定。之后,鏈接器根據各目標文件的“.rela.text”、“.rela.data”等重定位段獲取重定位入口,再根據“.symtab段”調整重定位入口處的相關指令即可完成各符號的重定位,從而實現各目標文件的靜態鏈接。
1.2動態鏈接
動態鏈接的模塊可能被加載到任意位置。編譯時鏈接器無法確定模塊中各符號的VMA。因此,動態鏈接一般延遲到模塊被加載時才執行。
動態鏈接模塊一般采用地址無關編碼(Positionindependent Code,PIC)技術。PIC的代碼中,對目標符號的訪問包括以下兩種情形:
1)訪問模塊內定義的符號
以CK520的匯編指令集為例,程序先通過如下指令獲取“.got段”地址:

其中 bsr指令將下一條指令(即指令 next:lrw r14,offset1)的VMA傳給r15。offset1為當前指令相對“.got段”的偏移量,其值在模塊編譯時已確定。然后程序再通過如下指令,將目標符號的絕對地址存入r7:

其中offset2為目標符號相對“.got段”的偏移量,編譯時offset2的值也已確定。這樣,不論該模塊被加載到何位置,目標符號的地址總能被計算出來并存入r7。顯然,模塊內定義的符號的尋址代碼與模塊的加載地址無關。
2)訪問模塊外定義的符號
如圖2所示,訪問模塊外定義的符號時采用了間接尋址的方式。

圖2 模塊間符號的尋址方式Fig.2 Addressing method for symbols between modules
以模塊2訪問模塊1中定義的符號func1為例,相應的匯編指令如下:

首先通過“PC指針+offset1”獲取“.got段”的地址。“.got段”中存放了所有外部符號的指針。模塊被加載時,動態鏈接器自動更新“.got段”,以確保每個指針所指向的地址都正確。通過 offset2即可獲取目標符號的指針。同樣的,編譯時offset1和offset2的值已確定。
可動態鏈接的目標文件也采用ELF格式對各個段進行格式化存儲[5]。兩個比較重要的段是“.reloc段”和“.dynsym段”。其中“.dynsym段”保存了需重定位符號的信息,包括符號名、符號類型、符號重定位入口等。“.reloc段”保存了符號重定位入口。動態鏈接時,只需根據“.reloc段”和“.dynsym段”中的信息,修改“.got段”中各符號指針的值即可。
1.3軟件模塊的動態加載模型
假設SOC整機軟件進行了良好的模塊化設計。模塊高內聚、低耦合,每個模塊有若干全局函數作為入口,模塊內其余函數均為靜態函數。整機軟件通過調用這些模塊實現某些功能[6]。這種情況下,待升級軟件可被細化為若干獨立的軟件模塊。這些軟件模塊可以是某應用程序的專用子模塊,如數據包處理協議,也可以是某些應用程序共用的子模塊,如硬件驅動程序。此時,對SOC的軟件進行增量升級就可以抽象為加載并鏈接與待升級應用程序相關的軟件模塊。
圖3給出了鏈接時可能遇到的5種情況。結合前文對兩種鏈接機制的分析,下面對這些情況分別進行討論。

圖3 新模塊替換原模塊示意圖Fig.3 Sketch of new module replacing the original one
1)升級模塊替換原工程中的函數
通過對原工程ELF文件的分析,獲得原工程中函數Global_Fun1()的LMA,改寫此處值為0x00007001(無條件轉移指令機器碼),并在其后寫入升級模塊中函數Global_Fun1()的VMA,這樣就將升級模塊的入口函數靜態鏈接到了原模塊中。
2)升級模塊訪問原工程中的全局函數
函數Global_Fun2()需在升級模塊中以類似c++中虛函數的方式定義為外部全局函數。鏈接時只需修改升級模塊“. got段”中Global_Fun2()的指針為原工程中Global_Fun2()的VMA即可。這樣就將原模塊中的全局函數動態鏈接到了該升級模塊中。
3)升級模塊訪問原工程文件中的全局變量Global_Var1
升級模塊需定義該全局變量并初始化。為保證升級模塊和原工程文件模塊中同名全局變量的一致性,動態鏈接器需修改升級模塊“.got段”中的Global_Var1的指針,使其指向原工程文件中的Global_Var1。
4)升級模塊訪問模塊內的靜態函數
升級模塊采用PIC編譯技術,對模塊內定義的靜態函數的尋址代碼與模塊加載地址無關,因此無需對該函數重定位。
5)升級模塊訪問模塊內的靜態變量
同(4),PIC的代碼對模塊內定義的靜態變量的尋址代碼與模塊的加載地址無關,無需重定位。
以某SOC為例,系統啟動時,Bootloader將Flash中從0x000000開始的代碼段一次性加載到從0x06000000開始的SRAM中,然后跳轉到SRAM中指定地址開始執行。因此可以將Flash的高位地址空間,如從0x7F0000開始到0x800000 的64KB作為升級代碼的存儲空間,將相應大小的SRAM的高位地址空間,如從0x6040000開始到0x6050000的64KB作為升級代碼的加載空間。因此,需修改原Bootloader,使系統啟動時加載 Flash中的原始代碼和升級代碼到相應的SRAM中。
當調用原工程中被升級的軟件模塊時,靜態鏈接指令將該模塊的入口地址直接轉移到升級代碼加載區中新模塊的入口處。同時由于新模塊內部采用了PIC等動態鏈接技術,因此新模塊中的尋址指令和加載地址無關,模塊可正常工作。這樣就實現了軟件模塊的部分升級。
如前文所述,為實現軟件模塊的增量升級,SOC既要將升級模塊的入口函數靜態鏈接到原模塊中,又要將原模塊中的全局符號動態鏈接到升級模塊中。因此SOC需要解析原工程文件和升級工程文件,并根據SRAM的使用狀態為升級代碼分配加載空間。為了減少SOC端的工作量,實現設備升級過程對用戶完全透明,可考慮將這些工作放在開發端進行。這就要求開發端生成的升級數據包中包含完整的鏈接信息,以便SOC端的升級程序可以根據這些鏈接信息自動實現待加載機器碼的鏈接、存儲和加載。
2.1升級數據包格式定義
升級數據包的文件格式設計如圖4所示。

圖4 升級數據包格式Fig.4 The format of upgrade data packet
其中“靜態鏈接信息”給出了加載該升級包后需靜態鏈接的符號數及各符號的地址。“升級模塊存儲區域調整信息”給出了Flash中需要搬移的代碼起始地址和長度。“新模塊存儲地址信息”給出了待加載機器碼的存儲地址及長度。
2.2開發端生成升級數據包流程
開發端先解析原工程目標文件,記錄原工程中的所有函數和變量名稱以及地址等信息。然后再解析單獨編譯的升級模塊目標文件。在完成合法性檢驗(如是否和目標平臺匹配、代碼是否地址無關等)后,根據嵌入式終端當前 Flash和SRAM的使用狀態,為模塊分配加載地址和運行地址。然后再解析目標文件的重定位信息,生成靜態鏈接指令并完成原模塊中全局符號的動態鏈接。最后開發端將相關數據打包,生成最終的升級數據包。其工作流程如下圖所示。
2.3嵌入式終端處理流程
考慮模塊可能被多次升級,每次的升級包中代碼長度可能不同,因此嵌入式終端需進行代碼存儲空間的維護工作,處理流程如圖6所示。
如圖 7所示,假設 SOC已加載了 Module1、Module2、Module3共3個模塊,模塊的實際大小分別為Size1、Size2、Size3,開發端預分配的空間大小分別為 Block1、Block2、Block3。為了盡量避免模塊升級時因升級代碼變長而占用后續模塊的存儲空間,因此,每個模塊預分配的空間一般略大于其實際大小。在這種情況下,嵌入式終端新接收了一個升級模塊Module4,其實際大小為Size4,開發端為其分配空間為Block4。

圖5 開發端生成升級數據包流程Fig.5 Flowchart of generating upgrade data packet by upper machine

圖6 嵌入式終端處理流程Fig.6 Flowchart of SoC dealing with the upgrade data packet

圖7 新模塊加載示意圖Fig.7 Sketch of loading a new module
結合圖6所述處理流程,嵌入式終端針對不同情況采取的操作如下:
當Module4為新模塊時,將該模塊直接加載到Module3之后并將模塊中的入口函數靜態鏈接到原工程文件中即可。
當Module4為Module2的更新,且Size4<Block2時,用Module4覆蓋Module2,并完成Module4中入口函數的靜態鏈接即可。
當Module4為Module2的更新,且Size4>Block2時,需將Module3向前移動Block2大小,覆蓋原Module2,然后加載Module4。最后完成Module3和Module4中入口函數的靜態鏈接即可。
無操作系統下嵌入式處理器軟件增量升級方法分開發端和嵌入式終端兩部分,其中升級模塊的鏈接工作主要集中在開發端進行,嵌入式終端只需接收升級數據包,并自動調用軟件升級子程序即可完成軟件升級。因此,設備升級過程對用戶完全透明。同時,當模塊間的接口固定后,頂層模塊和子模塊可單獨編譯,當整機軟件固化后,如需對子模塊進行改動,獨立加載新的子模塊即可,頂層模塊無需修改。因此,這種增量升級技術在一定程度上實現了上層功能軟件與底層硬件無關,提高了代碼的可重用性。此外,由于每次僅對部分模塊進行升級更換,無需替換整機代碼,因此增量升級技術還能有效地減小升級數據包的大小和信道資源的開銷,從而提高了較小信道帶寬下的升級效率和一次成功率。
經實驗驗證分析,本文提出的設計方案可有效地實現無操作系統下SOC軟件模塊的增量升級。
[1]黃繩雄,張榮芬.嵌入式設備遠程在線升級技術的研究[J].電子設計工程,2012,20(9):172-173.
[2]張藍博,張善從,陳蔚薇.嵌入式系統中的代碼動態鏈接模型[J].計算機工程與設計,2008,29(16):4115-4117.
[3]張和君,張躍.基于GNU工具的嵌入式Bootloader設計與開發[J].計算機工程,2006,32(15):277-279.
[4]陳宇,廖湘科,李慰.靜態鏈接動態庫的ELF文件軟件設計[J].微計算機信息,2008,24(3):162-164.
[5]John R.LevineLinkers&Loaders[M].San Francisco:Morgan Kaufman,1999.
[6]鄧偉,許揚婧.一種基于TI TMS320 DSP的軟件動態鏈接技術[J].電子設計工程,2012,20(11):167-169.
An incremental upgrade method for SOC without OS
WU Ke-an,LI Ting-sheng,WU Chuan-wei
(The No.30 Institute of China Electronic Technology Corporation,Chengdu 610041,China)
Generally,software on SOC without OS is upgraded by overwriting the whole codes.Modules cannot be upgraded independently.Therefore the structure and the linking procedure of object files are analyzed.According to the analyses,an incremental upgrade method for SOC without OS is presented.Firstly,the programmer compiles the new module independently.And then the object files are modified according the certain format which will be the final upgrade data packet.After that SOC receives the packet,loads and modifies the codes according to the protocol defined by the package.Experiments show that this method can upgrade software modules on SOC without OS independently and effectively.
embedded system;incremental update;dynamic link;position-independent code
TN492
A
1674-6236(2016)02-0161-04
2015-03-17稿件編號:201503228
武柯安(1990—),男,山西孝義人,碩士研究生。研究方向:信息安全與保密通信、嵌入式系統。