1. 程式人生 > >[從0到1搭嵌入式工程]編譯打包和升級的實現

[從0到1搭嵌入式工程]編譯打包和升級的實現

工程編譯:

我們以nand分割槽,分為bootloader、kernel、rootfs、homefs為例。
rootfs是linux系統必須的檔案目錄系統和工具的集合,掛載在跟目錄/下,homefs可以認為是我們自己的應用程式、自己的依賴庫,放在homefs中,放在/home目錄中。

那麼編譯打包的過程,就是把韌體執行所需的全部檔案,打成一個包, 在升級時,由升級程式把這個包拆開,把相應的檔案儲存在對應的分割槽上。

要完成整個包的編譯,要先編出bootloader、kernel和rootfs的整個目錄。
生成之後,放在out目錄中,開始編我們自己的應用程式。
1:先編譯我們自己程式碼的公共庫, 生成.a,放在對應的目錄;
2:編譯各個模組的應用程式, 並把生成的可執行檔案,cp到out/home/app 下供後面打包用;
3:依賴的.a庫,已經在編譯時編進可執行檔案了,依賴的.so庫,還需要cp到out/home/lib中;
4:韌體需要的工具和檔案,比如sd格式化工具, 升級工具,加密工具,提示音檔案等等 cp到相應的目錄下。
等所有執行需要的檔案都放到out目錄以後,此時,bootloader和kernel是可執行檔案,rootfs和homefs還只是目錄和檔案,需要我們製作成檔案系統。
這裡採用jffs2檔案系統, 使用mkfs.jffs2工具,把rootfs和home目錄下的所有檔案,分別製作成 rootfs.jffs2和home.jffs2。
然後把四個獨立的檔案,使用dd工具再次打包,dd if=boot.bin of=bootimg bs=xx count=xx , dd kernel.img -> sysimg, dd rootfs.jffs2 -> sysimg seek=xxx, 指定offset,把kernel和rootfs打包到一起成sysimg。 同樣,把home.jffs2 打包成homeimg。這是打了三個不同部分的img包。
再把boot.bin kernel.img rootfs.jffs2 home.jffs2 使用dd和偏移量, 打包到allimg中。這個包是完整包。
這樣就有了四個img, 根據需要升級的部分,決定使用哪個img進行升級。

在home目錄下,使用7za工具,對home目錄進行 加密 壓縮, 壓縮成homeimg_m.7z
密碼從哪裡來?
從0--z中隨機生成32位長度的密碼。

對homeimg_m.7z 執行md5sum, 
把這幾個檔案cat到一個檔案中
cat md5 password ver homeimg_m.7z > home1
dd if home1 of keyrsa bs=980 count=1 把home1檔案的前面777位元組放在keyrsa中,當做加密的key。
dd if home1 of home2 bs=980 skip=1 把home1中剩下的放在home2

使用keyrsa 生成公鑰, enc_keyrsa, 
cat ver enc_keyrsa home2 > home_m

至此,韌體打包完成,主要韌體有bootimg/sysimg/home_m/allimg。

升級:

從SD卡升級allimg,
從SD卡升級,是在boot階段進行的, uboot在監測到SD卡之後, 讀取檔名,將檔案讀取到ram中, 計算檔案的crc校驗,和從裝置flash上讀取的對應的crc進行比對, 如果是一致的,就不進行升級。
如果不一致,說明需要升級,這個時候,根據包的型別,是allimg的話,擦除allimg整個區域,如果是bootimg,擦除boot區域,其他一樣, 然後把檔案整塊的資料,寫入對應的flash區域,然後把新的crc作為新的環境變數,寫入特定的flash區域。重啟裝置,就是在新的韌體下運行了。

網路升級:網路升級的韌體一般是經過加密壓縮的home_m。
trigger韌體進行升級, 韌體從伺服器端,獲取最新的韌體的下載url,和韌體本身的md5用於校驗下載完整性,傳送請求,把home_m下載到記憶體中/tmp/downloadloadimg/home_m, 下載的過程,可以根據ls -l出來的檔案大小,與總檔案大小的比值,確定下載的百分比。下載成功以後,執行md5sum,和伺服器發下來的md5比較,一致為ok。這時,把/tmp/downloadloadimg/home_m mv 到/home/home_m, access 到這個檔案,說明下載成功100%。 reboo重啟裝置。
這個時候,線上升級已經完成了一半。

在kernel啟動之後,執行的init.sh指令碼中,我們判斷/home/home_m , 就開始去進行解壓升級。
dd if /home/home_m of /tmp/newver bs=22 count=1, 也就是把韌體的前22位取出來,根據打包的順序, 前面是韌體版本號, 和當前的版本號比較,不同就升級。
用工具對home_m 進行解包。
建立 /tmp/update 目錄,把home_m放到記憶體中去,把rsa解碼工具 和 7ZA工具也cp過來,開始解。
dd if home_m of ver bs=22 count=1 版本號
dd if home_m of home1 bs=22 skip=1 count=9999999  除了版本號之外的部分
刪掉home_m 因為記憶體可能不夠了
dd if home1 of enc_key bs=1024 count=1   取出加密部分
dd if home1 of home2 bs=1024 skip=1 count=9999999  剩餘部分
rm home1

使用rsa_pub_dec enc_key dec_enc_key 解密出來,如果dec_enc_key 檔案的大小是128, 正確繼續,否則退出。
 cat dec_enc_key home2 > home3
 rm home2
  
 dd if home3 of home4 bs=66 skip=1 count=9999999  前66位
 dd if home3 of md5 bs=33 count=1     取 md5
 dd if home3 of pwd bs=33 skip=1 count=1  取 密碼
 dd if home4 of verin bs=22 count=1     取版本
 
 dd if home4 of home_m.7z bs=22 skip=1 count=999999999
 
 判斷剛才得到的幾個版本號是否有問題
 用得到的解壓密碼,用7za工具解壓home_m.7z,
 
在/home/目錄下,分目錄對比version,如果version不一致, 就把/home/xxx目錄下的檔案都刪掉,然後把/tmp/update/home/目錄下對應的目錄copy過去。
 
 用md5 對比/tmp目錄和/home目錄中的md5, 全部都對上 OK。
 把版本檔案cp過去, over, 最終升級成功。要比SD卡升要複雜好多。
 

相關推薦

[0到1嵌入式工程]編譯打包升級實現

工程編譯:我們以nand分割槽,分為bootloader、kernel、rootfs、homefs為例。rootfs是linux系統必須的檔案目錄系統和工具的集合,掛載在跟目錄/下,homefs可以認為是我們自己的應用程式、自己的依賴庫,放在homefs中,放在/home目錄

[0到1嵌入式工程]嵌入式應用層判斷SD卡是否存在,獲取大小剩餘空間

1,判斷是否存在     如果sd卡裝置存在, 在生成/sys/block/mmcblk0/device/cid檔案,存放sd卡的cid資訊, 同目錄下type檔案可以判斷卡型別,如果裝置只支援sd卡,就不需要判斷型別了。     在程式碼中使用popen執行命令:cat /

[0到1嵌入式工程]嵌入式編譯工具鏈命名規則&四大架構&openwrt簡介

對於韌體應用開發來說,編譯工具鏈都是sdk供應商提供的,不同的專案,就有了多種編譯鏈,不同的編譯鏈有什麼區別呢?例如 arm-linux-gnueabihf-xx,mipsel-openwrt-linux-xx 。交叉編譯工具鏈,從授權上,分為免費授權版和付費授權版。免費版目

[0到1嵌入式工程]計算程序佔用的記憶體大小

指令碼內容:     # cat get_process_mem.sh      pid=$(ps|grep myprocess|grep -v grep|awk '{print $1}')     cat /proc/$pid/status|grep VmRSS|awk

[0到1嵌入式工程]監測外網連線情況gethostbyname

裝置要想實時監測外網連線情況,肯定是需要在外網上有一個點,可以讓你一直監測裝置與這個點之間的連線情況。這個點,就肯定是處在外網中的伺服器。 1,DNS伺服器 180.76.76.76 (百度DNS)、 114.114.114.114(國內移動、電信和聯通通用的DNS)、8

[0到1嵌入式工程]對shell命令的呼叫

在linux的應用程式中,呼叫system()和popen()可以執行shell命令。system()命令是序列執行,是阻塞的,等到shell執行結束後,返回, system不能直接返回執行結果。popen()是平行的,不等執行完成,函式就會返回, 繼續往下執行。popen會

[0到1嵌入式工程]啟動韌體

介紹三種應用程式的啟動方式。第一種是init程序linux 核心啟動之後,會執行1號使用者程序init,然後由它來啟動後面的任務,掛載檔案系統,啟動服務等,init會執行init.rc檔案, 最後由init.rc執行到我們的init.sh指令碼。init作為1號程序,預設的啟

一鍵完成androidsvn拉取程式碼編譯打包

記錄一下這兩天研究的東西-----在windows一鍵完成拉取svn上的安卓原始碼並自動打包。 準備:ant打包工具,android sdk,以及ant拉取程式碼所依賴的一個jar包svnant.jar,放到ant目錄下的lib目錄下即可。 ant是apache的一個編譯工

史上最全phpwind版本,phpwind1.0到phpwind8所有版本升級補丁包

none 社區 http 建站系統 style 數據 延伸 系統 edi phpwind提供開源論壇與移動社區APP建站系統,基於成熟穩定的領先技術與服務支持,實現社區產品從PC到手機的移動化延伸,數據融合互通,一站式交付,多終端覆蓋,從社區互動到移動社交,用戶體驗自然過渡

maven項目打包編譯跳過單元測試javadoc

註釋 代碼 無法 打包 ins AD 情況 install clean 代碼中可能由於單元測試、註釋(方法中的參數)或者maven javadoc插件的問題導致無法打包,影響工作,為避免這兩種情況可以在打包時輸入命令: mvn clean install -Dmaven.t

Iar工程編譯下載的使用教程

Iar工程編譯和下載的使用教程 [email protected] 安裝iar6.4 解壓CD-EWARM-6401-3812.zip按預設進行安裝 解壓key.zip進行註冊 安裝 j-link4.2 執行Setup_JLin

1、dubbo入門到放棄 dubbo-admin本地編譯打包

因為zookeeper只是一個黑框,我們無法看到是否存在了什麼提供者或消費者,這時就要藉助Dubbo-Admin管理平臺來實時的檢視,也可以通過這個平臺來管理提者和消費者。         dubbo-admin.war強烈建議自己編譯一個,網上找的基本都不行

Idea使用Maven編譯scala打包jar

下面Maven的pom檔案 <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compil

Mac下反編譯重新編譯打包APK

反編譯APK需要的工具如下: - dex2jar 這個工具用於將dex檔案轉換成jar檔案 下載地址:http://sourceforge.net/projects/dex2jar/files/

01揹包學習貪心演算法動態規劃

從01揹包學習貪心演算法和動態規劃: 演算法的思路其實很大程度上都是相通的,比如在提升演算法執行時間的不斷探索中,我們用分治的思想來將一個大問題分解為很多小問題進行求解,並且這些子問題與原問題的結構是一樣的,比如歸併排序,比如第i層是排四個數,第i+1層則是排八個數,問題的規模發生變化但結

ionic+angluar vscode開發環境搭建流程專案編譯打包 真機除錯

沒搞過ionic專案 中間遇見了很多坑,記錄下環境搭建及專案編譯備日後用的時候參考 整個過程: 編譯器:vscode 需要安裝的環境: node.js ,java jdk, gradle ,android sdk ,ionic  cordova  

maven聚合工程的建立聚合工程打包

第一步:建立父工程millery-manage,如圖: 右擊空白處,new建立新maven工程: 這裡跳過預設的骨架,使用自動義的骨架   這裡父工程必須使用pom打包方式   第二步:建立子工程 右擊父工程,建立maven module工程:   跳骨預設骨架,輸入子工

嵌入式Linux編譯系統的設計——Bootloader, 核心,驅動,檔案系統,升級映象等自動化編譯打包

專案簡介 嵌入式系統的開發過程較為複雜,編譯,裁剪,定製等如果沒有一套規範的流程將會難於管理和控制。本專案的目的是設計一個嵌入式Linux編譯系統,實現程式碼的編譯,定製和裁剪。Bootloader, 核心,驅動,檔案系統,升級映象等都可以自動化編譯,打包。 本專案git

gcc編譯: 打包若干.o.a檔案為新的.a檔案

使用場景: gcc編譯cpp的時候會生成.o , 然後若干.o檔案會打包生成.a檔案 但是有的時候是需要, 若干.o和多個.a, 打包生成 最終的一個.a檔案 *.o  --------\ xxx.a              --------->  des.a  

android 反編譯打包出現java.lang.VerifyError錯誤的原因解決

在安卓開發中經常要用到逆向工程,所以需要反編譯修改程式碼然後再重新打包。有時候會出現如下錯誤 java.lang.VerifyError: Rejecting class com.samsung.a