文章写到现在,似乎在刚刚切入正题。但自己也感觉,如果有所有的源码,自己所写的就有点滑稽了。不管怎么样,还是秉着一种钻研的精神,从反向的角度来玩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中的偏移来分布的。
而rockchip的偏移分布为
这导致了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加密时的不同。
但是,虽然我们知道了rockchip的加密方法,还是无法利用当前的mkbootimg.c生成的工具来组包,因为其中各个部分的offset还是不正确或者不完全,修改完后,再编译就可以了。
发一个修改完后的mkbootimg.c http://pan.baidu.com/s/1zlsNl
最终,通过二进制的比较,重组后的bootimg和原始的bootimg没有差异了,烧写后,自然也就成功了。
这一篇看起来比较简短,但实际过程中耗费了很长时间来实验和分析。
另外一个方面,rockchip的bootloader限制了整个系统的启动,如果哪天bootloader的加密方式改变了,并且不开放了,那么任何人都无法自由的玩了。也能看出,rockchip只要抓住了bootloader,其他资源都公开也无妨。
下一篇 讲一下定制的内核和rootfs吧。