二手安卓终端分析定制¶
简介¶
从咸鱼平台购得一台安卓终端设备,从买家提供的信息可以确定设备的主控为RK3368,剩余信息未知,需要对设备的详细接口信息进行分析。
基础信息分析¶
板卡外观如下
供电及各端口连接关系分析¶
根据电源RK808的走线,逐级向上测量供电来源,最终确认了供电端口以及供电电压。
已经连接设备的端口很容易确认相应的功能,悬空的端口根据布局、外围元器件以及PCB走线方向也基本可以确定其连接关系,目前可以确认的接口如下。
详细的IO顺序(可能有错误)见这里中的PFC元件部分。
系统信息获取及备份¶
Rockchip平台的调试串口一般情况下使用的是UART2,这组串口的默认复用通常在TF卡的D0与D1引脚,这个安卓终端有TF卡槽位置,但是并未焊接,使用USB转串口连接探针直接连接到D0/D1脚可以观察到有日志输出,随后补焊TF卡槽及相应的0欧电阻后便可以使用0.8mm厚度的TF PCB转接板进行连接了。
系统启动后串口终端可以直接使用su
命令切换到root
用户,随后使用U盘或者网络对原机系统进行整体备份(使用dd命令或者相应的网络拷贝命令),并单独导出boot分区以便导出设备树进行分析。
一般情况下,消费市场的Rockchip平台安卓终端普遍使用的是厂商提供的SDK,因此uboot等镜像均为rk格式的镜像。
导出的boot分区为标准的Android boot image
,在Linux平台中可以使用abootimg
工具来对boot.img进行解包,解包后的文件一般包括内核、initramfs以及second stage,这里的second stage文件是rk格式的资源文件,里面一般包含了bmp格式的logo图片以及dtb文件。
$ ls
boot.bin
$ abootimg -x boot.bin
writing boot image config in bootimg.cfg
extracting kernel in zImage
extracting ramdisk in initrd.img
extracting second stage image in stage2.img
$ ls
boot.bin bootimg.cfg initrd.img stage2.img zImage
$ /opt/rkbin/tools/resource_tool --unpack --image=stage2.img
Dump header:
partition version:0.0
header size:1
index tbl:
offset:1 entry size:1 entry num:3
Dump Index table:
entry(0):
path:rk-kernel.dtb
offset:4 size:100651
entry(1):
path:logo.bmp
offset:201 size:170326
entry(2):
path:logo_kernel.bmp
offset:534 size:19160
Unack stage2.img to out successed!
$ ls out
logo.bmp logo_kernel.bmp rk-kernel.dtb
经过以上步骤,便获取到了该终端设备的设备树,使用dtc
命令反编译即可得到源文件,通过对源文件进行分析,进一步得到外设及IO的使用分布情况,原始dts文件在这里。
外设 | 模块 |
---|---|
I2C0 | RK808 |
I2C1 | ES8316 |
I2C2 | gslx680 |
UART0 | bluetooth |
EMMC | EMMC |
SDMMC | TF Card |
SDIO | WIFI |
功能 | IO |
---|---|
usb host drv gpio | gpio0, 0x04 |
usb otg drv gpio | gpio0, 0x05 |
power key | gpio0, 0x02 |
lcd rst gpio | gpio0, 0x13 |
lcd backlight enable | gpio0, 0x19 |
lcd backlight bright | pwm1: pwm@ff680010 |
eth reset gpio | gpio3, 0x0c |
es8316 spk gpio | gpio0, 0x1c |
es8316 i2c | gpio2, 0x15 |
es8316 i2c | gpio2, 0x16 |
gslx680 i2c | gpio3, 0x1f |
gslx680 i2c | gpio0, 0x09 |
gslx680 touch | gpio0, 0x0c |
gslx680 reset | gpio0, 0x0b |
WIFI,poweren_gpio | gpio3, 4 |
WIFI,host_wake_irq | gpio3, 6 |
BT,power_gpio | gpio3, 3 |
BT,reset_gpio | gpio3, 5 |
BT,wake_gpio | gpio3, 2 |
BT,wake_host_irq | gpio3, 7 |
BT,uart rts gpio | gpio2, 0x1b |
主线U-Boot支持¶
U-Boot主线代码已经提供了RK3368的基础支持,理论上是可以直接使用的,但是主线代码只提供了基础外设的驱动支持,并且驱动中存在许多的错误,此外除RK3399这类使用范围广、用户量大的平台外,基本不包含屏幕显示等相关外设的驱动支持「即便如此,在查看了相关驱动代码后,主线U-Boot能否不做改动直接在RK3399平台上点亮屏幕也依然存疑」。
适配主线U-Boot最大的挑战来自于显示部分,Rockchip提供的数据手册并没有这部分外设及硬件架构的详细描述,因此只能从其开源的内核代码、Uboot代码以及主线代码并结合同系列其他SOC的实现来推测其结构以及驱动方法。
主线代码的clk和emmc驱动中存在功能缺失和错误,需要使能U-Boot的调试输出,逐一定位启动过程中的报错信息,对照下游内核或者U-Boot的源码分析排除。
通过查阅上述源码中的设备树源文件以及驱动代码,推测RK3368中显示部分的整体结构如下:SOC提供一个VOP单元,其规格为VOPB;VOP对外连接到MIPI-DSI、LVDS、RGB、HDMI以及eDP,提供显示接口;根据设备树以及驱动猜测,MIPI-DSI、LVDS以及RGB三者共用一个combo phy,这个phy ip来自于inno,这应该也意味着这三种接口的使用是互斥的。
VOP部分的驱动修改参考了这个仓库,我自己的修改思路和这个仓库中使用的方法基本相同,所以基于此仓库进行了略微改动,由于U-Boot不像内核一样提供simple-panel驱动,所以这里参考了现有驱动添加了一个panel驱动,panel驱动所需的屏幕初始化序列可以从上述提取出的dts获取。
主线U-Boot的代码来看起来是支持RK3368的TPL和SPL的,但是我实际测试发现使用rkdeveloptool rd
命令进行热复位时板卡可以正常启动到U-Boot命令行,而直接冷启动则会在TF-A跳转U-Boot这一步骤卡死,并且没有抛出任何异常,难以分析和定位,于是转而使用Rockchip提供的闭源miniloader来进行启动。
经过上述修改,EMMC和屏幕便可以正常工作了,相关补丁见这个分支,下一步便可以尝试使用主线内核进行启动了。
待续...