解決引導內核遇到undefined instruction的錯誤


其實在上一篇隨筆之前,就是在啟動linux 內核的時候,出了點問題

剛Starting kernel ...就出現了undefined instrction,這是什么問題呢?

在網上也搜了不少資料,有兩篇很有啟發

http://www.latelee.org/porting-uboot/u-boot-porting-booting-kernel.html

http://blog.csdn.net/liangkaiming/article/details/5986680

就是這兩篇。

 

我們先來了解下mkimage這個命令,重要關注loadaddress和entry address

./mkimage -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type'
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)
-n ==> set image name to 'name'
-d ==> use image data from 'datafile'
-x ==> set XIP (execute in place)

mkimage是將zImage之前加上64字節的鏡像頭

所以如果使用mkimage生成內核鏡像文件的話,會在內核的前頭加上了64byte的信息,供建立tag之用。bootm命令會首先判斷bootm xxxx 這個指定的地址xxxx是否與-a指定的加載地址是否相同。
(1)如果不同的話會從這個地址開始提取出這個64byte的頭部,對其進行分析,然后把去掉頭部的內核復制到-a指定的load地址中去運行之
(2)如果相同的話那就讓其原封不同的放在那,但-e指定的入口地址會推后64byte,以跳過這64byte的頭部。

 

我們來看看這三個地址的不同情況:

1> mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 
30008040 -n linux-2.6.18.8 -d zImage uImage2.6.18.8-8040 
這種情況 ,只能把 uImage download到 30008000的位置上,否則 從 30008040
是啟動不了的。

原因:如果將uImage(加了頭的鏡像文件)下載到不同於指定加載地址的地方,則會進行上面的操作,將去掉頭部的內核拷貝到指定的加載地址,此時加載地址和入口地址需要是相同的,因為已經沒有鏡像頭了,所以此時入口地址也應該為30008000,而不應該再加上64個字節

所以在構建鏡像頭部中的加載地址和入口地址時千萬要考慮下載的地址,否則將會啟動不了。
2> mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 
30008000 -n linux-2.6.18.8 -d zImage uImage2.6.18.8-8000 
這種情況download地址隨便。 還是按上面說的,因為將加載地址和入口地址設置成同樣的地址,在下載到任意地址時,將去掉頭部的內核鏡像拷貝到指定加載地址后,可以直接從加載地址開始啟動。但是要是下載地址和指定加載地址相同呢?也就是下面的:


如果 tftp 下載地址==0x30008000 , 此時因為下載地址和指定加載地址相同,所以就不會搬動,內核直接從指定加載地址自解壓啦,但是因為指定的入口地址也是0x30008000,還是在鏡像頭處,可以看到上面的代碼,如果相同沒有做任何事,只是打印了提示信息,所以還得將入口地址往后推后64個字節還是從 0x30008040 啟動就肯定OK 。

 

所以在制作鏡像頭以及下載地址就有兩種情況:

1,mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage zImage.img

加載地址和入口地址相同

tftp 0x31000000 zImage.img

bootm 0x31000000

下載地址可以任意放。

 

2,mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage zImage.img

入口地址在加載地址后面64個字節

tftp 0x30008000 zImage.img

bootm 0x30008000

下載地址一定要在指定的加載地址上。

 

所以,我在制作鏡像頭的時候沒有自己動手制作,而是make uImage ARCH=arm CROSS_COMPILE=arm-linux-直接一步到位,所以啟動的時候應該在0x30008040的位置啟動!

看到這個圖片還是很高興的!!!

打賞

免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號  © 2018-2021 CODEPRJ.COM