轉載:更換zImage中的initramfs

From: http://blog.csdn.net/linuxaxis/article/details/8769722html

好吧,折騰了兩三個星期,USB的問題沒搞定,看來功夫還不到家,看了下efuse中有不少的位能夠配置相關的參數,linux

也許智器在那裏面作了不少的工做,使我一直都不能有所突破,這個問題暫時就放放吧,之後有時間再來研究研究。android

其實話又說回來,國內的公司仍是真垃圾,自己就是用開源的東西,不開源就算了,還搞這麼多噁心的東西,真垃圾...測試

 

 

        以前說的一塊兒作這個事情的哥們也一直不見動靜,看來只有本身來作了。這樣的話,不得不修改策略,先用最少的spa

時間,最少的資源,最快的速度完成最主要的功能。乾脆底層的驅動就用現成的kernel鏡像了,把主要精力放在上層功能.net

的修改和定製上吧。若是要用原始的android源碼,必需要能用x7的kernel啓動android系統,這中間就有不少的問題須要code

處理了,也就是清明三天+今天全部作的工做。htm

 

        智器仍是很噁心的,把andriod的ramdisk的原始目錄靜態編譯到zImage中,這樣就很難把這個initramfs剔除出來。blog

一開始想了不少的啓動配置參數來修改啓動的路徑,可否繞過initramfs,從而從sd卡啓動android系統,結果不行,主要ip

測試了以下的相關啓動參數:

rdinit, 一開始發現這個參數感受一陣驚喜,覺得有所突破。將這個值設置爲:rdinit=/init1,這樣,若是在ramdisk中找不到

init1的話,就跳出ramdisk啓動,走其餘的路徑,經過設置root=/dev/mmcblk1p2來修改root的路徑,結果不行。一樣,還有

其餘的不少,如:rootfstype=ext4, rootdelay=5, noinitrd等等,結果都沒有任何效果,因而就放棄了這條路。

 

        因而就把更多的精力放在瞭如何把編譯到zImage中的initramfs剔除出來,或者換成我從android源碼裏面編譯出來的root.

結果,在苦思冥想了好幾天,再加今天上班時候的靈感觸發,和今天下班回家以後,老婆作的飯香薰陶下,終於成功了,小小

興奮了一陣。流程以下:

 

1:從uImage中提取zImage

dd if=uImage of=zImage bs=64 skip=1

這步以後,就獲得了沒有uboot頭得zImage鏡像

2:從zImage中提取沒有解壓縮的頭程序

先將zImage dump成十六進制的文本顯示:

hexdump -C zImage > zImage.txt

在這個文本文件中,能夠看到一個LZO的字符,這個是lzo壓縮文件的頭標識符。其實內核也就支持了那幾種壓縮格式,我也是

一個個的對出來的,沒有什麼好辦法。

只要從這個頭開始,後面的數據就是linux Image用lzo壓縮的數據。好提取從.lzo開始的部分

dd if=zImage of=Image.lzo bs=6212 skip=1

3: 獲得Image

 

lzop -d Image.lzo -o Image

這個Image就是不包含解壓的程序,原始的Linux編譯的二進制結果

 

4:  找到image中的initramfs的起點和終點

這個能夠看原始的linux編譯出來的initramfs_data.cpio,把這個文件dump出來,能夠看到cpio問題的頭和結束的標識符。

 

kernel作出來的cpio文件頭和尾標識,根據這兩個特色,就能在image中直接找到哪一個區間段是initramfs了。其實這是沒有壓縮的initramfs的特色,若是是壓縮了的話,

就根據壓縮格式所用問的標識符。智器之因此以前zImage用lzo格式的壓縮,以及在這裏的initramfs不用壓縮,還有不少不少別的,一切的一切只是爲了加快開機時間,

其實這塊他們仍是作了挺多工做的。

對於 這個文件提取,我用了下面兩步,獲得兩個文件:

dd if=image bs=141392 of=new/head count=1
dd if=image of=new/end bs=472144 skip=1

head爲initramfs以前的image鏡像,end爲initramfs以後的image鏡像。

這裏有點要補充的是:kernel的cpio文件的大小是512對齊的。

 

5:獲得與原始zImage中initramfs等大小的ramdisk文件

 

根據第四點中相關的信息 獲得原始zImage中的initramfs大小爲:330752字節,

將android編譯出來的root設置到Linux的INITRAMFS_SOURCE中,編譯,將會生成一個initramfs_data.cpio文件,

我這裏的到得這個文件大小爲:292352字節,利用這個文件來製做一個與以前在zimage中的initramfs等大的initramfs:

dd if=/dev/zeor of=pad bs=512 count=75

cat initramfs_data.cpio > panda.ramdisk

cat pad >> panda.ramdisk

這樣就獲得了一個能夠用的ramdisk了,

 

6:從新生成Image

cat head > new_image

cat panda.ramdisk >> new_image

cat end >> new_image

7: 製做u-Image

mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 -n linux-2.6.13 -d new_image u_image

這樣,就能夠經過uboot將u_image拷貝到內存中,再經過bootm來啓動。其實,new_image也能夠直接啓動了,只是uboot的

參數沒法傳遞了。

地址的選擇:這時用的地址已經不是平時作uImage的地址了,這個地址是一個絕對地址,不在須要作任何拷貝動做,CPU直接跳轉

到這個地址直接執行內核代碼,不須要搬移,不須要解壓。這個地址能夠在arch/arm/mach-oma2/Makefile.boot中找到。對於咱們

從SD卡拷貝到內存中的地址選擇能夠是任意的。

 

          以前遇到一個比較想固然的錯誤,覺得把initramfs從image中去掉,就能夠直接當成一個沒有編譯進initramfs那樣直接能夠啓動

的鏡像,結果倒是在啓動的時候沒有任何反應,今天研究了下相關的代碼纔有所領悟:

initrafs_data.S

[plain]  view plain copy
 
    1. .section <span style="color:#FF0000;">.init.ramfs</span>,"a"  
    2. __irf_start:  
    3. .incbin __stringify(INITRAMFS_IMAGE)  
    4. __irf_end:  
    5. .section .<span style="color:#FF0000;">init.ramfs.info</span>,"a"  
    6. .globl VMLINUX_SYMBOL(__initramfs_size)  
    7. VMLINUX_SYMBOL(__initramfs_size):  
    8.   
    9.   
    10.  vmlinux.lds  
    11.   
    12. <pre name="code" class="plain"><pre name="code" class="html">  __con_initcall_start = .; *(.con_initcall.init) __con_initcall_end = .;  
    13.   __security_initcall_start = .; *(.security_initcall.init) __security_initcall_end = .;  
    14.   . = ALIGN(4); <span style="color:#FF0000;">__initramfs_start</span> = .; *(.init.ramfs) . = ALIGN(8); *(.init.ramfs.info)  
    15.   __init_begin = _stext;  
    16.   *(.init.data) *(.meminit.data) *(.init.rodata) *(.meminit.rodata) . = ALIGN(32); __dtb_start = .; *(.dtb.init.rodata) __dtb_end = .;  
    17. </pre><br>  
    18. <pre></pre>  
    19. initramfs.c<br>  
    20. <br>  
    21. static int __init populate_rootfs(void)<br>  
    22. {<br>  
    23.     char *err = unpack_to_rootfs(<span style="color:#FF0000">__initramfs_start</span>, __initramfs_size);<br>  
    24.     if (err)<br>  
    25.         panic(err);    /* Failed to decompress INTERNAL initramfs */<br>  
    26.     if (initrd_start) {<br>  
    27. #ifdef CONFIG_BLK_DEV_RAM<br>  
    28.         int fd;<br>  
    29.         printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");<br>  
    30.         err = unpack_to_rootfs((char *)initrd_start,<br>  
    31.             initrd_end - initrd_start);<br>  
    32.         if (!err) {<br>  
    33.             free_initrd();<br>  
    34.             return 0;<br>  
    35.         } else {<br>  
    36.             clean_rootfs();<br>  
    37.             unpack_to_rootfs(__initramfs_start, __initramfs_size);<br>  
    38.         }<br>  
    39.         printk(KERN_INFO "rootfs image is not initramfs (%s)"<br>  
    40.                 "; looks like an initrd\n", err);<br>  
    41.         fd = sys_open((const char __user __force *) "/initrd.image",<br>  
    42.                   O_WRONLY|O_CREAT, 0700);<br>  
    43.         if (fd >= 0) {<br>  
    44.             sys_write(fd, (char *)initrd_start,<br>  
    45.                     initrd_end - initrd_start);<br>  
    46.             sys_close(fd);<br>  
    47.             free_initrd();<br>  
    48.         }<br>  
    49. #else<br>  
    50.         printk(KERN_INFO "Unpacking initramfs...\n");<br>  
    51.         err = unpack_to_rootfs((char *)initrd_start,<br>  
    52.             initrd_end - initrd_start);<br>  
    53.         if (err)<br>  
    54.             printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);<br>  
    55.         free_initrd();<br>  
    56. #endif<br>  
    57.     }<br>  
    58. <br>  
    59. <br>  
    60.    
    61. <pre></pre>  
    62. <p></p>  
    63.   
    64. </pre>  
相關文章
相關標籤/搜索