需求:我的網絡卡驅動在載入時,需要兩個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 正整數轉成二...