现代CPU是以光速运行的,以GDK8的RK3328 CPU为例,它的主频是1.5G Hz,这意味着当它以额定频率运行时,每个时钟周期的时间为0.666纳秒。换言之,1纳秒时间里,会有1.5个时钟(clock)。而1纳秒时间里,光只能在真空中行进大约30公分。如果把30公分算作一步距离的话,那么在光行进一步的时间里,RK3328也可以行进1步多。所以,我常常说,现代CPU是以光速运行的。
正因为如此高的速度,所以,我们让电脑做事情的时候,我们常常感受不到它花时间,瞬间就完成了。
但也正因为这个原因,如果电脑背着我们做坏事情,常常也是我们无法察觉的,比如流氓软件在后台悄悄拉流量;比如恶意软件悄悄窃取信息,通过网络发走;比如黑客远程遥控,把我们的电脑当作他做坏事的替罪羊......
因为有如此多的比如,所以我们需要一种手段,把以光速飞奔的电脑停下来,而且是立刻就停,也就是想叫它啥时停,啥时就要立刻停下来,这个反应时间也要是纳秒级别的,这样才可能抓住上面列举的那些邪恶瞬间。
那么,如何让现代CPU在瞬间骤然停止呢?有没有这样的方法呢?
答案是肯定的。而且有两类方法,一类是软件方法,另一类是硬件方法,软件方法常常是有条件和有局限的,而硬件方法则是更加可靠和通用的。硬件方法就是通常所说的JTAG技术。
去年在研发GDK8时,我花了很多时间在JTAG上,也多次请底层经验丰富的格友来一起来攻击这个难关,在五一假期时曾取得了较大的进展,但因为种种原因,始终没有找到完美的产品级解决方案。于是只好在10月份时,改变计划,先发布不包含JTAG调试的基础版本。
基础版本发布后,如何解决JTAG问题,始终是压在我心上的一块石头。每当有相关的资料或者线索时,我总会再试一下。
元旦前,从事安全研究的老朋友leminis联系我,说他想在GDK8上尝试JTAG调试。我听了后,当然很支持,把我知道的信息都告诉他,帮他找转接板,给他发资料,给他提供切换信号的源代码。
为什么需要这么多东西呢?
问题就在这里。与X86的芯片上有专门的JTAG信号,主板上有支持JTAG的专用XTP端口不同,在ARM上,芯片的JTAG信号是与其它信号复用的,在板子上,也没有专门的JTAG口,也是与其它接口复用的。根本原因还是X86系统的价格贵,不那么在乎几个引脚和一个接口的成本,而ARM上,一切都是低成本,能省就省。
以GDK8为例,芯片的JTAG信号是与GPIO和SD卡复用的,在板子上,JTAG信号是与SD卡的卡槽复用的。
这样的复用节约了成本,但却带来了软硬件两方面的麻烦。软件方面,需要写寄存器来切换信号。硬件方面,需要飞线或者做个转接卡来把JTAG信号转出来。
软件好办一些,我写了个函数:
将其放在“刘姥姥”驱动里。
然后在GDK8上编译,使用insmod命令加载,然后通过proc虚文件来触发:
echo jtag | sudo tee -a /proc/llaolao
这样,就可以把复用的信号切换为JTAG用途了。
切换后,向SD卡槽插SD卡,系统没有任何反应了。
硬件方面,要麻烦一些,在我的建议下,leminis从网上买了一根SD卡的延长线,然后他又发挥他的电烙铁技艺,飞了三根线。
对于软件工程师来说,上图这样的电烙铁手艺真的很棒了。
对我来说,因为去年就做这件事情,所以格蠹办公室里早已经做好了一些转接卡。
这些转接卡是我请搞硬件的朋友帮忙做的。
不要小看这个小转接板,它里面的花头也挺多的。在来自瑞芯微官方的电子表里,列了SD卡信号与JTAG信号的对应关系,但这个对应关系不是一套对一套,而是一套对多套。
更捉弄人的是,上面这个表居然没有列出SD信号的7号脚,而我们在去年试验时,恰恰论证出需要信号7,这是为什么上图中有一根白色的飞线。
元旦假期里,leminis多次给我发信息,报告他的进度,这让我很感动。
今天是元旦假期后的第一个工作日,我一大早到办公室后,打开电脑,回复了几封邮件后,我又想到了JTAG的事。
于是我在新一年里的第一个工作日里重整旗鼓,再战JTAG。先恢复之前在GDK7上搭好的工具环境,再找出转接卡,接上一根根跳线。
然后像前面说的那样使用llaolao驱动切换JTAG信号,然后启动OpenOCD进行扫描......
起初几次还是No Luck。OpenOCD给出的错误码是-4。
在-4错误码上面,有根本性的失败原因。
抄录一下这个关键的错误信息:
SWD ack not OK @ 0 JUNK
SWD是ARM发明的两线JTAG(也是为了低成本)技术代号,ack是通信领域的常用语,代表消息确认。归纳一下,前半句是说SWD的确认信号不OK,最后的JUNK直白到底......
看看搜索引擎给出的结果吧 ^_^
换句话说,OpenOCD给出上面的信息就代表,调试器这一方发出了信息后,没有收到合适的确认信号,收到的是“垃圾”数据。这意味着JTAG信号没有接通。
是什么导致信号不通呢?我想拿出万用表量一量,但又想先试试别的方法。
我又把转接卡拿起来仔细看电路板上的走线,因为SD信号一共只有8个,而需要的只有两个,即DATA2和DATA3,也就是SD信号的里的1号和2号。我顺着SD卡信号的源头寻找它的走向。
2号线到另一面了,但是1号线的走向是比较容易看出来的。这一仔细看,发现问题了,转接卡上标注的TMS和TCK根本不是我想要的TMS和TCK。
原来硬件工程师是按上面电子表里的对应关系做的板子和标注,而这个对应关系是不固定的,不同芯片不一样,即使都是瑞芯微的芯片,也是不一样的。
找到这个大问题后,忽视卡上的标注,完全靠信号走向推测,重新连线,然后再上电、加载驱动,切换到JTAG,再运行OpenOCD,发起扫描。
这次居然扫描到了。
-4错误和JUNK抱怨不见了,取而代之的是我盼望已久的从SoC ROM表里读回来的DAP设备信息。
看到这个成功的信息,我长出了一口气,站起来给调试现场拍了个照,留作纪念。
另一个成功的特征是,JTAG扫描仪的红灯反复闪烁,好似拼命的奔跑,它在通过边界扫描方式与目标CPU通信,它很忙碌,因为它在追赶光!
(写文章很辛苦,恳请各位读者点击“在看”,不胜感激)
*************************************************
正心诚意,格物致知,以人文情怀审视软件,以软件技术改变人生
扫描下方二维码或者在微信中搜索“盛格塾”小程序,可以阅读更多文章和有声读物
也欢迎关注格友公众号