如何將elf 二進位制 韌體編譯進核心

2021-07-28 04:50:38 字數 3236 閱讀 3925

需求:我的網絡卡驅動在載入時,需要兩個elf格式的韌體。sdk的做法是將這兩個韌體放置到跟檔案系統中的/lib/firmware目錄下,核心啟動的時候在根檔案系統中尋找。這樣做,核心和根檔案系統就出現了乙個強相關的關係。客戶提出,在核心不要和根檔案系統較強聯絡,不要出現這種情況:編譯出的kernel和此根檔案系統啟動後,ok沒有問題!!!而換了乙個根檔案系統,居然網路都不能用了!!!

根據客戶的需求,我將sdk的elf韌體編譯進核心。

那麼問題來了。。。如何elf韌體編譯進核心??

開啟核心原始碼,在頂層目錄中,有乙個名為firmware的目錄,對就是它就是那個韌體目錄。

在此目錄下,有很多hex檔案,這些檔案都不是原始碼檔案,那這些檔案是做什麼用的楠?

閱讀/firmware/makefile,我們可以知道kernel中已有的編譯韌體到核心的方法是(如dd.fw.hex):通過dd.fw檔案生成相應二進位制韌體檔案,將對應二進位制檔案通過quiet_cmd_fwbin規則包含進dd.fw.s檔案,將dd.fw.s檔案編譯成對應的dd.fw.o檔案,鏈結進核心映象中。

那麼這下來將兩個elf檔案編譯進核心(a.elf, b.elf)。理清了上面原理,我們可以很容易的將elf檔案編譯進核心。

fw-shipped-y = a.elf , b.elf
通過上面的一行makefile語句,將a.elf b.elf編譯進核心。

到這裡就接受了麼?

你會發現乙個奇怪的問題:每次make arch=*** cross_compile=*** clean 或者distclean後,這兩個elf都會被刪除!再次編譯編譯失敗:a.elf not found。

因為我們將之定義為目標,在每次make clean時都會將生成目標全部刪除,核心中其他的目標都是通過ihex檔案生成,所以刪除了無關緊要,而我們的elf檔案,刪除了就沒有了。a.elf -> a.o 過程依賴a.elf。a.elf檔案不存在出現編譯失敗!

解決的方法很簡單:clean 或 distclean 不將elf檔案刪除!

在/firmware/makefile檔案新增下面行:

no-clean-fils=a.elf b.elf
現在clean 或 distclean時,將不會刪除elf檔案。

我們再次深入,你將會發現還有問題:make arch=*** cross_compile=*** o=$(dir) 編譯失敗,錯誤還是為:a.elf b.elf not found (解決此問題需要對此makefile有一定的深入了解)

a.elf 編譯進核心的路徑為:a.elf -> a.s -> a.o -> vmlinux

dd.fw 編譯進核心的路徑為:dd.fw.ihex -> dd.fw -> dd.fw.s -> dd.fw.o -> vmlinux

這兩個檔案編譯進核心的方式,除了第一步就沒有其他的區別!對!就是第一步導致編譯的失敗!

make 的o=(d

ir)的

意思是:

將mak

e過程中

的中間文

件都到 (dir)目錄下。從a.elf到a.s通過quiet_cmd_fwbin規則實現!.s檔案中使用彙編偽指令.incbin將elf檔案直接包含到.s檔案中。只要你開啟.s檔案你就明白了這裡為什麼會出錯了。使用了相對路徑!!!而elf檔案在原始碼路徑,而不在obj路徑中,所以相對路徑下找不到elf檔案導致編譯失敗。(大家想想為什麼dd.fw 又沒有問題?)。

給出我的修改方法,僅供參考:

quiet_cmd_fwbin = mk_fw   $@

cmd_fwbin = fwname="$(patsubst firmware/%.gen.s,%,$@)"; \

fwstr="$(subst /,_,$(subst .,_,$(subst -,_,$(patsubst \

firmware/%.gen.s,%,$@))))"; \

asm_word=$(if $(config_64bit),.quad,.long); \

asm_align=$(if $(config_64bit),3,2); \

progbits=$(if $(config_arm),%,@)progbits; \

echo

"/* generated by firmware/makefile */" > $@;\

echo

" .section .rodata" >>$@;\

echo

" .p2align $$" >>$@;\

echo

"_fw_$$_bin:" >>$@;\

echo

" .incbin \"<$(srctree)/$(2)\"" >>$@;\

echo

"_fw_end:" >>$@;\

echo

" .section .rodata.str,\"ams\",$$,1" >>$@;\

echo

" .p2align $$" >>$@;\

echo

"_fw_$$_name:" >>$@;\

echo

" .string \"$$fwname\"" >>$@;\

echo

" .section .builtin_fw,\"a\",$$" >>$@;\

echo

" .p2align $$" >>$@;\

echo

" $$ _fw_$$_name" >>$@;\

echo

" $$ _fw_$$_bin" >>$@;\

echo

" $$ _fw_end - _fw_$$_bin" >>$@;

note:

linux kernel中: (s

rctr

ee)表

示核心源

碼目錄。

(objtree)表示核心編譯生成目錄,包括中間檔案。

如何將負數轉換為二進位制

我們已經知道計算機中,所有資料最終都是使用二進位制數表達。我們也已經學會如何將乙個10進製數如何轉換為二進位制數。不過,我們仍然沒有學習乙個負數如何用二進位制表達。比如,假設有一 int 型別的數,值為5,那麼,我們知道它在計算機中表示為 00000000 00000000 00000000 000...

操作二進位制寫入二進

操作二進位制 寫入二進位制 1 宣告變數 sqlite3 stmt stat 2 把sql語句解析到stat結構中去 sqlite3 prepare 3 繫結替換 sqlite3 bind blob 4 儲存到資料庫 int result sqlite3 step 5 釋放stat結構 sqlite...

二進位制如何轉十進位制,十進位制如何轉二進位制

學計算機的朋友剛開始學習時都要接觸進製之間的轉換,二進位制 十進位制 八進位制 十六進製制等,這個是很枯燥的,轉來轉去就轉矇圈了,別蒙別蒙,今天咱們乙個乙個搞定,看看二進位制和十進位制之間如何相互轉換的。轉成二進位制主要有以下幾種 正整數轉二進位制,負整數轉二進位制,小數轉二進位制 1 正整數轉成二...