XX教你玩 MiniPC (五) Mk908 bootimg分析

文章写到现在,似乎在刚刚切入正题。但自己也感觉,如果有所有的源码,自己所写的就有点滑稽了。不管怎么样,还是秉着一种钻研的精神,从反向的角度来玩MiniPC吧。也希望一些玩家能从我的每步尝试中获得灵感,学到一些东西。

承上一篇,我们得知,bootloader并不care kernel分区的内容,而是关心bootimg。在bootimg中包含了kernel和ramdisk。想要自由的玩转MiniPC,在当前的bootloader下,就要弄明白bootimg内部的一些原理。

一,bootimg的解包。

在网上有几个解包工具,以下是我总结的链接。

unpack-bootimg.pl  http://pan.baidu.com/s/1kspZM

bootimg.py http://pan.baidu.com/s/1BwA39

但这两个工具(bootimg.py被我修改过)都无法完全解开我们的bootimg。

unpack-bootimg.pl是按照ramdisk的gzip magic来解包的,所以解包完后kernel的开始部分由很多无效数据。

bootimg.py 在解包时,会出现assert问题,主要是因为rockchip的bootimg中的 kernel addr,initrd addr,tags addr以及second addr不是按照android代码 mkbootimg中的偏移来分布的。

XX教你玩 MiniPC (五) Mk908 bootimg分析_第1张图片

rockchip的偏移分布为

XX教你玩 MiniPC (五) Mk908 bootimg分析_第2张图片

导致了bootimg.py 运行错误。根据地址偏移,修改了bootimg.py,这样就可以将bootimg解包了。

二,bootimg组包

这个过程花费了很长时间,因为组包完毕后的bootimg没法启动,bootloader提示SHA error。

组包工具最初当然是选择android默认的工具mkbootimg了。按照惯例,修改源码mkbootimg.c,把其中的地址偏移修改成上图的rockchip offset。然后重新编译,生成新的mkbootimg。这个过程不多说了,相信大家都会做。

# mkbootimg --kernel kernel --ramdisk ramdisk.gz --base 60400000 --pagesize 16384 --ramdiskaddr 62000000 -o boot.img其中kernel和ramdisk.gz是上面解包的结果,我们的目的是把这两个包重新组包,然后烧写至boot分区,看看能否成功启动。但是很遗憾,bootloader提示SHA error,无法启动。这就迫使我们必须使用二进制比较工具来查看原来的bootimg和重组后的bootimg的差别了。

# xxd boot.img.orig > bootimg.orig.txt

# xxd boot.img.new > bootimg.new.txt

# vim -d bootimg.orig.txt bootimg.new.txt

唉,没有当时操作的截图了,大家自己来比较吧。通过比较我们发现,只有0x240~0x25F之间的字节不同,这些字节到底是什么意思呢?在bootimg的header结构体里,我们可以得到这个区域是 ID。通过代码mkbootimg.c,发现ID区域的值是经过对kernel,ramdisk等信息进行运算得到的,在头文件里的注释中,能看到ID区域是用来确保bootimg的唯一性的。而 SHA error的错误提示,也证明了我们的ID是错误的。这也从侧面说明了flashboot 在启动时会对bootimg包含的数据重新计算SHA,并跟ID区域的数据进行对比,如果不同则会提示 SHA error。这解释了bootloader在启动内核之前,有2s的停顿,显然是在进行着校验运算。

可是利用android自带的mkbootimg生成的bootimg跟原始的bootimg ID部分不同,这说明两者的加密方法不同。得知这个消息时,我真是觉得太坑爹了,因为加密方法千种万种,如果不知道的加密方法的话,自己的内核就无法自由的运行在MK908之上。在伤心沮丧中,先停止了bootimg的继续debug。

在搜索时,我惊喜的发现了从rockchip 流出的mkbootimg的源码!https://github.com/olegk0/tools.git

通过比较,可以看到rockchip和android两者在mkbootimg.c中SHA加密时的不同。

XX教你玩 MiniPC (五) Mk908 bootimg分析_第3张图片

但是,虽然我们知道了rockchip的加密方法,还是无法利用当前的mkbootimg.c生成的工具来组包,因为其中各个部分的offset还是不正确或者不完全,修改完后,再编译就可以了。

发一个修改完后的mkbootimg.c   http://pan.baidu.com/s/1zlsNl

最终,通过二进制的比较,重组后的bootimg和原始的bootimg没有差异了,烧写后,自然也就成功了。


这一篇看起来比较简短,但实际过程中耗费了很长时间来实验和分析。

另外一个方面,rockchip的bootloader限制了整个系统的启动,如果哪天bootloader的加密方式改变了,并且不开放了,那么任何人都无法自由的玩了。也能看出,rockchip只要抓住了bootloader,其他资源都公开也无妨。

下一篇 讲一下定制的内核和rootfs吧。





你可能感兴趣的:(linux,开发日记)