玩客云Amlogic S805 适配Win10 arm32记录 – 3

3. 从零开始

是的,你没有看错,之前的都是热身,对要做的项目进行初步的理解,现在才是正式开始做准备工作,前面说了一堆,其实跟玩客云这个硬件一毛钱关系都没有,通过混恩山论坛,我了解了玩客云的一些基本信息:

Soc为晶晨的S805,四核Cortex-A5架构,ARMv7指令集,开发代号为m8baby

1GB DDR3内存,内存颗粒H5TQ4G63CFR-RDC

8G EMMC 型号KLM8G1GEME

千兆网卡RT 8211F

USB 2.0 x2

支持HDMI 2.0

硬件分为两个版本 V1.0 和V1.3

再经过一段时间的查找,我收获了:

S805_Datasheet V0.8 20150126(感谢HardKernel,这个应该是内部资料吧)虽然说不全,但是对开发起了很大帮助

KLM8G1GEME-B041(eMMC5.1+1ynm+based+e_MMC)1.0

ddr_H5TQ4G63CFR-RDC-datasheet

从github上找到了可以使用的u-boot:https://github.com/not-aml/openlinux-amlogic-uboot

和Linux内核:https://github.com/150balbes/Amlogic_s8xx-kernel

还了解了玩客云的系统刷入方式——短接(之前怀疑短接有效的原因是在于短接了Emmc的供电,导致RomCode检测不到Emmc,从而进入Usbburn Mode,后来才发现,即使是短接状态也是能正常读写Emmc的,结合自己的发现,发现原因应该是短接修改了片选信号,导致系统从SD卡启动了),这算是有了最基本的准备,然而要下手,还是很难,首先U-Boot和UEFI的关系是什么?是同级的还是U-Boot要底层一些?两个难道不都是BIOS吗?又是经过一堆骚操作,终于搞明白了,原来之前的作者是将UEFI作为2nd的Bootloader,先启动U-Boot,再启动LittleKernel,最后启动UEFI,这样的启动方式,相当于架空了U-Boot,理论上,光靠一个UEFI就可以直接引导系统,初步的想法就是抛弃U-Boot的方式,适配原生的UEFI,但是启动地址又是什么?网上很多说法:Arm处理器启动方式为启动之后从地址0x0读取数据,又有很多资料说是从0x8xxx启动,到底是哪一个(后续证实均不是),为此我专门研究了玩客云U-Boot的启动方式:

S805内置了RomCode,这段code会读取前16KB私有的 Firmware 到Sram中(跟U-Boot的SPL类似),然后从SRAM中执行,然后初始化内存,复制U-Boot到内存的0x10000000,然后从0x10000000开始运行,UEFI支持XIP(片内执行),这点我还没有测试过,经过我猜测估计是不行的,因为RomCode不是直接将PC指针放到0x0开始运行的,而是不管三七二十一直接复制前16k到SRAM中运行,UEFI没有SPL类似的机制,强行复制前16K运行会导致出问题。晶晨的U-Boot经过了很复杂的封装,编译出来有u-boot u-boot.bin u-boot.bin.aml u-boot.bin.aml.efuse u-boot.bin.aml.encrypt u-boot-comp.bin u-boot-orig.bin u-boot-usb.bin u-boot-usb.bin.aml u-boot-usb.bin.aml.encrypt u-boot-usb.bin.aml.encrypt.usb.start 具体都是干什么用的后面再慢慢分析,同时晶晨还有个客制化工具,能解包刷机ROM,解包出来的东西和上述有些类似。由于拿不到内部的开发文档,这些耗费了很长的时间,一个个查makefile很费时间,特别是makefile这种东西晦涩难懂,一堆参数搞得云里雾里,需要你慢慢一个参数一个参数分析,把所有的include,宏定义都拿出来看,慢慢看,还是能看懂的。

静态分析还是有很大局限性的,makefile这种东西我目前是没有找到比较好的可视化调试方式(如果有人知道,请务必告诉我),最主要的动态调试手段还是查编译输出,最后用WinHex查文件结构,查lds文件,查链接地址,将U-Boot用 objdump 反汇编后查具体指令。

这里吐槽一下Amlogic的U-Boot的代码质量真的是一言难尽,相比于edk2,就像一个半成品,注释一会有一会没有,有些时候好,有些时候差,参差不齐,各种宏定义满天飞,变量命名也非常乱,还有就是层次过多的封装,一个宏定义你封装一两次也就行了,就一个东西能封装个五六次,重复的定义也是多到飞起,一个串口输出,Debug都被封装了不知道多少种形式,各种平台的代码(从m1-m9平台)混在一起,剪不断理还乱,代码复用是上去了,但是真心乱啊,还有就是U-Boot的开发规范在这里好像就是不存在一样,根本没按照U-Boot的框架来写,随意建文件夹,源文件想放哪就放哪,还有改了个名字,内容却雷同的文件,最终到底调用的是哪一份也不得而知。还有一些则是直接复制内核中的代码,写法也不愿意改改,又继续封装加重冗余。

相较于U-Boot kernel的质量就好了很多,至少是能拿出手的等级,但是注释做得也不到位,相比较于UEFI每个方法都有方法注释,参数说明,还需要努力。

就目前的开发所看过的源码来说,感觉冗余的代码还是偏多,一个驱动里面一个文件几千行代码不是吹的,还不止一个文件,不但是脑力活,更是体力活,真正有用的也就那么几行操作硬件的关键代码,但是你想要搞清楚原理,首先得把整个运行流程梳理出来,再根据这个流程重写UEFI驱动。

目前能得到的资料也偏少,Datasheet 不全,也没有原理图,主板还是黑色的,密密麻麻的走线,特别是跟到CPU下面,或者是有过孔的地方,跟着跟着就跟丢了,后面也突然发现由于没有S805的针脚点位图,即使没有跟丢,也没有多大作用了,最后只能说是去看代码推原理图,这些都对开发造成了很大的阻碍。

未完待续

参考阅读:

Uboot启动内核命令详解:https://www.jianshu.com/p/181e45afdafe

《玩客云Amlogic S805 适配Win10 arm32记录 – 3》有2条留言

  1. 你好,我最近在使用S805安装openwrt,但是如果CPU负荷过高,就会强制重启。感觉是因为WDT导致的,但是相关接触的东西确实太少。目前思路是,修改u-boot中关于WDT的设置,让其失效。
    但是如何生成对应的uboot一头雾水。但是我看记录中,描述的似乎可行。但是还是不太明白,若能抽空帮忙解答不胜感激。

    回复
    • 机器有问题吧,我也用过一段时间的openwrt,也没遇到强制重启的问题啊,如果要关闭watchdog可以查看https://github.com/pig-world/OneCloudPkg/blob/main/Drivers/WatchdogDxe/Watchdog.c我这里的实现,简单来说就是往0xc1109900和0xc1109904这两个地址写0就行。

      回复

留下评论