完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
上一篇我们已经弄明白了整个MiniPC的软件组成,但是并不是很清楚系统启动的细节,所以这一篇就仔细说明一下rk3188 从上电开始到启动内核为止的过程。
再说明一点,这篇有一部分是翻译的内容,但针对翻译的内容,我亲自做了一些实际的实验,所以我还是自己坦白,这篇算是“伪原创”吧。 这个是国外的一个大神做的工作,真是很佩服啊。 那么,有人会问,我们为什么这么费劲的去解析启动部分的内容,第一,我们没有RK3188的datasheet,第二,没有bootloader的源码。而我们的目的是能够自由的开发或移植bootloader到rk3188上,能够启动我们定制的操作系统。如果谁有RK3188的详细datasheet或者bootloader的源码,一定要给我一份啊! 首先,先翻译一下原创的内容吧。绿色的部分是原文没有提及,我自己根据自己的实验猜测的。其中的代码就不拷贝过来了。 如何获取RK3066的BootRom 以下是我的步骤。 首先,我在我的设备的升级包(update.img)中发现了一个RK30xxLoader(L)_V1.18.bin的文件。我用rk29Kitchen把它解包出来。 使用strings 命令(linux下)去查看其中的参考字符串,并没有发现有用的地方,所以我觉得这个文件是经过加密混淆过的。 下一个步骤是使用IDA pro来反汇编RKAndroidTool.exe ---rockchip公司提供的用于烧写升级包的工具。在分解过程中,我发现了loader文件使用了RC4的加密方法。这个文件被分隔成512字节的多个块,每个块都被加密。 所以,我用perl写了unpack_loader.pl 脚本,这样我得到了4个输出文件。 1 14a 321c 30_LPDDR2_300MHz_DD 2 3366 c914 rk30u***plug 4 fc7a 3400 FlashData 4 1307a 1ac00 FlashBoot 幸运的是,这些文件名都是有意义的名字。 30_LPDDR2_300MHz_DD 是一个dram 初始化处理过程。FlashData 是只是30_LPDDR2_300MHz_DD的拷贝,只不过是512字节对齐(flash的块大小)。 rk30u***plug 是负责MaskRom模式下的处理。FlashBoot是从NAND flash启动的第二阶段,里面也包含了DFU模式的处理。 我也反编译了上面所说的4个文件。在FlashBoot中,发现了用于DFU模式下从DDR Ram区域获取数据的指令。所以,我的想法是在FlashBoot中注入代码,把bootrom拷贝到DFU模式下能够访问到的内存地址。但是一个问题是,FlashBoot会覆盖掉从0地址开始的内存 --- 这个地址也是上电时bootrom被加载的地方。所以,我需要做的就是在Flashboot覆盖掉它以前,从0地址拷贝出0x2800个字节(boot rom 的大小)。这个就是我们想要的bootrom.bin。 然后,我写了一系列的工具:patch_loader.sh 帮助 注入代码;pack_loader.pl重新组包,并且用rkcrc签名。 我所有的命令就是以下几个: # perl unpack_loader.pl RK30xxLoader(L)_V1.18.bin write # sh patch_loader.sh FlashBoot.bin # perl pack_loader.pl dram=30_LPDDR2_300MHz_DD.bin boot=FlashBoot.bin.patched data=FlashData.bin u***plug=rk30u***plug.bin out=patchedLoader.bin 用RKAndroidTool.exe把生成的patchedLoader.bin烧写到flash中,然后用以下的命令获取loader。 # rkflashtool m 0x64000000 0x2800 >bootrom.bin 我上传了 bootrom.hex。执行命令xxd -rp bootrom.hex >bootrom.bin 把bootrom.hex变换成二进制文件boot.bin。 现在,loader的所有部分都被破解并且反编译了,现在我们就可以把uboot移植到这个平台上,启动我们想要的任何操作系统。 RK3066 的启动过程 在上电时,rk30在bootrom的0地址开始启动。 Bootrom把自己拷贝到SRAM,然后到idbrom中搜索dram的初始化句柄。 Bootrom加载dram初始化句柄到内存(SRAM),然后执行它。 Bootrom到idbrom中搜索flashboot,加载到内存(DRAM)。 如果没找到flashboot,bootrom继续搜索u***plug然后加载它。 如果找到,flashboot初始化NAND,搜索parameter文件,加载kernel到DRAM,然后启动kernel。 该翻译的已经翻译完了,不知道大家能不能理解,反正我是明白了一部分。对于作者的逆向工程的功底,我真是自叹不如啊。既熟悉Windows平台的可执行文件破解,又熟悉arm架构的机器码和汇编指令,还能开发工具进行代码注入。 下面就是我的实验阶段了。 我没有利用IDA pro进行反编译调试,这部分工作好长时间不做了,很生疏,费时。总之,把作者写的perl脚本下载下来运行,解我的Rk3188的bootloader,是完全行的通的。这说明rk3066和rk3188在启动过程以及架构上没有很大改变。运行结果如下图: 从中我们也能看到3188_LPDDR2_300MHz_ 和FlashData的大小很接近,FlashData是以512字节对齐的。这符合作者的阐述。 其实,以上的这些信息,我们使用winhex也是可以看到的,但不是很直观的。 比较解压完的4个文件的大小,发现跟上面解包过程中提供的信息是一样的,这也能说明这个过程是正确的。 我没有分析3188_LPDDR2_300MHz_ 和rk30u***plug,因为DDR2的初始化是必需的过程,没有必要改动。rk30u***plug是通往MaskRom模式的(其实我是真不懂MaskRom模式是什么模式,做什么用,谁明白细节的告诉我啊),但是在我测试过程中,从没进入过这个模式,所以略过吧。 那么重点就是仔细分析FlashBoot这个模块了。 第一步,反汇编FlashBoot模块。FlashBoot模式是纯的二进制文件,不是我们通常的elf文件,在这里没有段的概念,没有架构的概念,有的只有二进制的代码和地址。先看看反汇编的指令吧。 # arm-linux-gnueabi-objdump -b binary -marmv5 -D FlashBoot.bin > flashboot.asm 每个标准的gcc交叉编译工具链,都很提供一个objdump程序,这是帮助我们做一些debug工作的。我用的arm gcc是从linaro社区下载的,版本是4.7。其中的参数是必须的,binary表示我们的输入是一个纯的二进制文件,marmv5是告诉objdump安装哪种架构来将机器码翻译成汇编语言。因为这个arm objdump不支持armv7的架构,所以先用armv5代替了,虽然有些小的差别,但不会错的天翻地覆。大家可以通过 --help来看看自己的objdump支持什么架构。 这样就得到反汇编得到的汇编语言。下面着重分析这个汇编文件。 从上面的分析得出,第一次拷贝时覆盖了0地址,所以需要在第一次拷贝之前进行代码注入。 那么以下,就分析作者的代码注入原理。 首先,先关注两个重要参数。offset和inject,分别代表注入代码的静态文件偏移和执行时的注入点。 这两个点的选择是有依据的。offset为A0,在这个位置数据全部为0,没有特殊意义,并且有很大的空间来存储注入代码。inject为224,通过上面的分析知道,这个是在第一次拷贝之前,比较早的执行位置。 再来看JUMP1的计算,实际上这里的目标地址是里面的2b0,因为2b0位置是memcpy的代码,从汇编代码看,就是在r0,r1,r2三个寄存器存入合适的数据(传参),然后把0地址的数据拷贝到0x64000000去,个数为0x2800,因为从仅有的手册上看bootrom只有10K。0x64000000是比较高的地址,不会被覆盖掉。但为什么计算过程这么麻烦呢,是因为流水线的缘故,这个大家自己去了解吧。 在执行我们注入代码的最后,是恢复原始环境的代码,就是把注入之前的环境恢复回来。224位置的代码被我们修改了,我们返回的时候,要把224位置的代码重新补回来,然后再跳转到228。224位置原来的意思是:把2D8中的数据存入r0,我们则在注入代码中直接写入10080000,效果是一样的。返回228之后,程序就正常执行了。 JUMP的计算,目的是获得offset位置相对PC的偏移,因为我们的跳转都是相对跳转。当执行到224的时候,要跳转到A0,就要计算向前跳转的偏移。 我们明白这些参数的含义之后,就可以用dd命令完成 flashboot的重新组装。 重组的过程是分解的逆过程,在此不多说了。 rkflashtool在前几篇的链接中有源码,在linux下编译通过,并且可以成功运行。在windows下,可执行文件rkflashtool.exe没法成功运行,不知道为什么,也没仔细调试,大家成功了的话,通知一下我吧。 到现在,我们就明白了注入过程和原理。根据我对kernel代码和上面地址的分析,以下就是我个人的猜测了。 bootrom是CPU内置的ROM,内容无法被修改,启动时会依据硬件设置来选择启动方式。 bootrom把自身拷贝带内部sram,因为内部sram无需初始化,所以非常适合bootrom操作。 我们所说的bootloader,实际上是被烧写在一块神秘的idbrom上。这个rom的特性应该是类似于Nor flash,可以随机的访问,并且能执行代码。这样bootrom在其中找到句柄时,就可以立刻跳转过去执行,而不用先拷贝后执行。idbrom的flash肯定不是NAND flash。这点从烧写工具上就可以看出:windows上的rkandroidtool,bootloader和paramter文件都在0地址,这是一组矛盾。linux上的rkflashtool ,有i选项和r选项,分别对应idb flash和nand flash。 在bootrom的高字节中,包含了CPU的标识ID,通过判断这些ID,就可以知道是什么CPU。 Flashboot中才是我们通常Bootloader的工作。所以获得flashboot的动作属性,是我们后续启动的关键。 动作属性主要包括: 对parameter的解析 对kernel分区的使用 对kernel启动时cmdline的作用 这篇的内容涉及很多底层的知识,搞明白这些真的非常有益。 下一篇讲述 Flashboot的动作属性。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
基于米尔瑞芯微RK3576核心板/开发板的人脸疲劳检测应用方案
739 浏览 0 评论
968 浏览 1 评论
856 浏览 1 评论
2075 浏览 1 评论
3322 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 13:33 , Processed in 0.591510 second(s), Total 40, Slave 34 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号