又一次败北了。

起因

这个机顶盒我之前已经折腾过了,不过当时退了一步,仅仅是破解了一下,它现在可以随意安装应用了,但是,它的安卓版本迷之低,只有4.0多(记不清了呢),软件都装不上,我拿终端的包管理器也装不上。

这样也就只能放在那里吃灰了。

但是,我闲的也是闲的,想顺便学学嵌入式开发,于是,折腾又开始了。

试探

我想呢,给它刷一个更高版本的Android系统,这样就能装很多软件了。

adb一直没有找到连接的方法,首先双头usb不识别,其次网络adb似乎也不管用。

我在阴差阳错中使用了 netstat 命令,它把主机上的监听端口都显示出来了,adbd服务监听的端口不是默认的5555,而是25555。

连上adb之后,我离谱的发现,之前刷入破解的Android,不能进入fastboot模式、recovery模式。

走进了死胡同,之后我拿着shell到处乱跑。

有一个叫 init 的文件,这是 linux 的第一个用户进程的文件,我想,如果我运行它会发生什么呢。

我把 init 运行了,设备莫名奇妙重启了,莫名其妙显示 ‘Android正在更新’。

终于,它变砖了。

引导

bootloader什么的都正常,但是引导到安卓上之后就一直只显示logo。(我怀疑是启动器(相当于桌面,用来点开其他应用的)应用被删除了,启动之后就停在logo上,不过我没有再研究这个Android)

在Uboot自动引导之前会等待1秒,此时通过串口按下任意键就可以进入uboot的shell。

这个uboot是精简过的uboot,很多功能都没有,比如说网络,但是基本功能都是有的。

uboot在启动时会读取环境变量,这些环境变量中有一些是单纯的环境变量,有些是脚本,脚本的语法就是uboot shell的语法,自动引导会执行某个环境变量。执行环境变量用 run 环境变量

默认会在emmc(它的内置存储)上引导启动,当U盘插入时会引导factory.img,似乎是工厂测试用的。

这个机顶盒的CPU是晶晨的s905l2b(CPU上面有散热片,我怕拆下来装不好,这个芯片型号是搜索机顶盒型号得到的),我在github上搜索s905,找到了 armbian 这个linux发行版,有人专门给机顶盒编译了。

我把这个系统安装在SD卡里。

fatload 命令加载U盘里的linux核心,然后试图引导,不管怎么弄都失败了。

正当我不知所措时,又一个阴差阳错,我发现有叫做 boot-usb、boot-sd之类的环境变量,随手run了一下,linux核心成功引导了。

run之后似乎自动存了环境变量,之后的启动都是默认从外设启动。

引导进Linux

linux核心成功引导了,但也仅仅是成功引导,核心似乎并没有正确启动。

抱着试试的心态,在启动U盘里面打开了一些文件,想看看有什么值得注意的地方,有一个叫做 uEnv.txt 的文件,这里面明确指定了DTB文件(设备树文件,用于告诉操作系统,设备的引脚号之类的信息),同时核心的启动参数也在这里面,这是SD卡引导时的Uboot环境变量。

引导SD卡里面有很多DTB文件,但是没有一个能和我的芯片对应的,我挑了一个接近的,启动成功了。

但新的问题又出现了,启动到一半时就开始刷SD卡插入,SD卡拔出的死循环,盲猜是SD卡兼容性的问题,果断插读卡器然后成功进系统。原本12M/S的读取速度变成1.8M/S

armbian自带了个写入emmc的命令,写入之后就不用插这个U盘了,其中有一步是选择写入的Uboot,这个我不知道该选哪个,没敢选,决定先把别的东西弄好再说。

到这里就算是成功了吧?

不,在我打算把其他东西弄好时,我发现了大问题。

串口

一直都是用串口与电脑通信的,但是在linux启动成功之后显示登录时就出问题了,输入和输出都乱码。

环境变量里面的这段启动参数引起了我的注意 console=ttyAML0,115200n8 console=tty0 no_console_suspend

为了让它不要乱码,我把波特率从115200改到了1200,结果是,串口输出慢了很多,系统启动瓶颈在串口速率上面,最终还是乱码。

为了让USBHub够得到机顶盒,串口连接线用了两段线连接,很长,撤去一段,挪动USBHub,消除了偶尔乱码的问题,但最终依然还是乱码。

这个启动参数里有两个一模一样的 console=,于是我把它变成了 console=ttyAML0,115200n8 no_console_suspend 这样就解决问题了。

提取DTB文件

目前的系统可以使用的硬件有这些:SD卡槽、两个USB口、串口、CPU、内存。

然后就没了。以太网啦、蓝牙啦、HDMI啦,都不能用。

我想把它当服务器用,所以给它刷系统,现在告诉我以太网和Wifi都不能用?

绝对不行,至少要让以太网能用啊。

从emmc中提取boot.img文件,我不会,但是我有之前用的刷机包,刷机包里面有boot.img文件。

费了好大力气找到了Android Image Kitchen这个工具,把boot.img解包了。

我拿十六进制编辑器挨个文件打开找dtb文件的文件特征(文件头、设备名等),在一个叫做boot.img-second的文件里找到了疑似dtb的文件内容,这个文件文件头看起来有文件名的样子,我把它直接托给了压缩软件,成功打开,里面有个叫dt.img的文件。

这个dt.img里面存了dtb文件,但是不止一个。

dt.img文件的结构非常简单,文件头写了这些dtb文件的名称、起始地址、长度。

十六进制编辑器

我把它们全部都提取出来了。

提取之后的文件

结果只需要一个,利用变砖系统的shell看了dtb的文件名(在/proc/device-tree/amlogic-dt-id里写着)。

然后复制到启动U盘,成功地启动失败了。

DTB文件存在的目的是为了让同一个linux核心能够在不同的板子上运行,所以,前提得是同一个linux核心。

修改DTB文件

linux上带了各种命令行工具,其中有个叫dtc的工具,这个东西是可以把dtb和dts格式相互转换,dtb是二进制文件,dts是纯文本文件。

说来惭愧,我没有装linux系统。

但是这个启动U盘不就是Linux嘛,果然,启动之后可以用dtc工具。

为了不拔启动U盘导致终端刷错误,我找了另一个U盘,这是用来装系统的U盘,exFat分区格式。

我把原来系统的dtb和现在启动U盘用的dtb拿去转换。

dts文件的转换十分成功,可惜这个U盘在linux挂载之后插在windows上变成只读了。(似乎是一种错误,可以用windows的错误检查工具修复)

这两个dts完全不一样,我想把一边的数据复制到另一半,但是完全看不懂。

dts文件

最后搜索eth,修改了以太网的引脚,中断什么的,以为可以成功。

结果转回dtb之后启动无果。

总结

这下无计可施了,再一次败北了。

但是,是学到很多东西的,感觉上已经入门嵌入式开发了··· 幻想

这块转头我会留着,择日再战!

我能想到的,最大的成功就是无愧于自己的心。