jtag引脚定义_硬件学习之通过树莓派操控 jtag
作者:Hcamael@知道创宇404实验室时间:2019年10月21日
最近在搞路由器的时候,不小心把CFE给刷挂了,然后发现能通过jtag进行救砖,所以就对jtag进行了一波研究。
最开始只是想救砖,并没有想深入研究的想法。
救砖尝试
新加坡安全研究员Awakened在他的博客中发布
变砖的路由器型号为:LinkSys wrt54g v8
CPU 型号为:BCM5354
Flash型号为:K8D6316UBM
首先通过jtagulator得到了设备上jtag接口的顺序。
正好公司有一个jlink,但是参试了一波失败,识别不了设备。
随后通过Google搜到发现了一个工具叫: tjtag-pi[1]
可以通树莓派来控制jtag,随后学习了一波树莓派的操作。
树莓派 Pins
新加坡安全研究员Awakened在他的博客中发布
我使用的是rpi3,其接口编号图如下:
或者在树莓派3中可以使用gpio readall
查看各个接口的状态:
rpi3中的Python有一个RPi.GPIO
模块,可以控制这些接口。
举个例子:
>>> from RPi import GPIO>>> GPIO.setmode(GPIO.BCM)>>> GPIO.setup(2, GPIO.OUT)>>> GPIO.setup(3, GPIO.IN)
首先是需要进行初始化GPIO的模式,BCM模式对应的针脚排序是上面图中橙色的部门。
然后可以对各个针脚进行单独设置,比如上图中,把2号针脚设置为输出,3号针脚设置为输入。
>>> GPIO.output(2, 1)>>> GPIO.output(2, 0)
使用output函数进行二进制输出
>>> GPIO.input(3)1
使用input函数获取针脚的输入。
我们可以用线把两个针脚连起来测试上面的代码。
将树莓派对应针脚和路由器的连起来以后,可以运行tjtag-pi程序。但是在运行的过程中却遇到了问题,经常会卡在写flash的时候。通过调整配置,有时是可以写成功的,但是CFE并没有被救回来,备份flash的数据,发现并没有成功写入数据。
因为使用轮子失败,所以我只能自己尝试研究和造轮子了。
jtag
新加坡安全研究员Awakened在他的博客中发布
首先是针脚,我见过的设备给jtag一般是提供了5 * 2以上的引脚。其中有一般都是接地引脚,另一半只要知道4个最重要的引脚。
这四个引脚一般情况下的排序是:
TDITDOTMSTCK
TDI表示输入,TDO表示输出,TMS控制位,TCK时钟输入。
jtag大致架构如上图所示,其中TAP-Controller的架构如下图所示:
根据上面这两个架构,对jtag的原理进行讲解。
jtag的核心是TAP-Controller,通过解析TMS数据,来决定输入和输出的关系。所以我们先来看看TAP-Controller的架构。
从上面的图中我们可以发现,在任何状态下,输出5次1,都会回到TEST LOGIC RESET
状态下。所以在使用jtag前,我们先通过TMS端口,发送5次为1的数据,jtag的状态机将会进入到RESET的复原状态。
当TAP进入到SHIFT-IR
的状态时,Instruction Register
将会开始接收TDI传入的数据,当输入结束后,进入到UPDATE-IR
状态时将会解析指令寄存器的值,随后决定输出什么数据。
SHIFT-DR
则是控制数据寄存器,一般是在读写数据的时候需要使用。
讲到这里,就出现一个问题了,TMS就一个端口,jtag如何知道TMS每次输入的值是多少呢?这个时候就需要用到TCK端口了,该端口可以称为时钟指令。当TCK从低频变到高频时,获取一比特TMS/TDI输入,TDO输出1比特。
比如我们让TAP进行一次复位操作:
for x in range(5): TCK 0 TMS 1 TCK 1
再比如,我们需要给指令寄存器传入0b10:
1.复位
2.进入RUN-TEST/IDLE状态
TCK 0TMS 0TCK 1
3.进入SELECT-DR-SCAN状态
TCK 0TMS 1TCK 1
4.进入SELECT-IR-SCAN状态
TCK 0TMS 1TCK 1
5.进入CAPTURE-IR状态
TCK 0TMS 0TCK 1
6.进入SHIFT-IR状态
TCK 0TMS 0 TCK 1
7.输入0b10
TCK 0TMS 0TDI 0TCK 1TCK 0TMS 1TDI 1TCK 0
随后就是进入EXIT-IR -> UPDATE-IR
根据上面的理论我们就可以通过写一个设置IR的函数:
def clock(tms, tdi): tms = 1 if tms else 0 tdi = 1 if tdi else 0 GPIO.output(TCK, 0) GPIO.output(TMS, tms) GPIO.output(TDI, tdi) GPIO.output(TCK, 1) return GPIO.input(TDO)def reset(): clock(1, 0) clock(1, 0) clock(1, 0) clock(1, 0) clock(1, 0) clock(0, 0)def set_instr(instr): clock(1, 0) clock(1, 0) clock(0, 0) clock(0, 0) for i in range(INSTR_LENGTH): clock(i==(INSTR_LENGTH - 1), (instr>>i)&1) clock(1, 0) clock(0, 0)
把上面的代码理解清楚后,基本就理解了TAP的逻辑。接下来就是指令的问题了,指令寄存器的长度是多少?指令寄存器的值为多少时是有意义的?
不同的CPU对于上面的答案都不一样,通过我在网上搜索的结果,每个CPU应该都有一个bsd(boundary scan description)文件。本篇文章研究的CPU型号是BCM5354
,但是我并没有在网上找到该型号CPU的bsd文件。我只能找了一个相同厂商不同型号的CPU的bsd文件进行参考。
bcm53101m.bsd[2]
在该文件中我们能看到jtag端口在cpu端口的位置:
"tck : B46 , " &"tdi : A57 , " &"tdo : B47 , " &"tms : A58 , " &"trst_b : A59 , " &attribute TAP_SCAN_RESET of trst_b : signal is true;attribute TAP_SCAN_IN of tdi : signal is true;attribute TAP_SCAN_MODE of tms : signal is true;attribute TAP_SCAN_OUT of tdo : signal is true;attribute TAP_SCAN_CLOCK of tck : signal is (2.5000000000000000000e+07, BOTH);
能找到指令长度的定义:
attribute INSTRUCTION_LENGTH of top: entity is 32;
能找到指令寄存器的有效值:
attribute INSTRUCTION_OPCODE of top: entity is "IDCODE (11111111111111111111111111111110)," & "BYPASS (00000000000000000000000000000000, 11111111111111111111111111111111)," & "EXTEST (11111111111111111111111111101000)," & "SAMPLE (11111111111111111111111111111000)," & "PRELOAD (11111111111111111111111111111000)," & "HIGHZ (11111111111111111111111111001111)," & "CLAMP (11111111111111111111111111101111) " ;
当指令寄存器的值为IDCODE
的时候,IDCODE寄存器的输出通道开启,我们来看看IDCODE寄存器:
attribute IDCODE_REGISTER of top: entity is "0000" & -- version "0000000011011111" & -- part number "00101111111" & -- manufacturer's identity "1"; -- required by 1149.1
从这里我们能看出IDCODE寄存器的固定输出为: 0b00000000000011011111001011111111
那我们怎么获取TDO的输出呢?这个时候数据寄存器DR就发挥作用了。
1.TAP状态机切换到SHIFT-IR2.输出IDCODE到IR中3.切换到SHIFT-DR4.获取INSTRUCTION_LENGTH长度的TDO输出值5.退出
用代码形式的表示如下:
def ReadWriteData(data): out_data = 0 clock(1, 0) clock(0, 0) clock(0, 0) for i in range(32): out_bit = clock((i == 31), ((data >> i) & 1)) out_data = out_data | (out_bit << i) clock(1,0) clock(0,0) return out_datadef ReadData(): return ReadWriteData(0)def WriteData(data): ReadWriteData(data)def idcode(): set_instr(INSTR_IDCODE) print(hex(self.ReadData()))
因为我也是个初学者,边界扫描描述文件中的内容并不是都能看得懂,比如在边界扫描文件中并不能看出BYPASS指令是做什么的。但是在其他文档中,得知BYPASS寄存器一般是用来做测试的,在该寄存器中,输入和输出是直连,可以通过比较输入和输出的值,来判断端口是否连接正确。
另外还有边界扫描寄存器一大堆数据,也没完全研究透,相关的资料少的可怜。而且也找不到对应CPU的文档。
当研究到这里的时候,我只了解了jtag的基本原理,只会使用两个基本的指令(IDCODE, BYPASS)。但是对我修砖没任何帮助。
没办法,我又回头来看tjtag的源码,在tjtag中定义了几个指令寄存器的OPCODE:
INSTR_ADDRESS = 0x08INSTR_DATA = 0x09INSTR_CONTROL = 0x0A
照抄着tjtag中flash AMD的操作,可以成功对flash进行擦除,写入操作读取操作。但是却不知其原理。
这里分享下我的脚本:jtag.py[3]
flash文档:https://www.dataman.com/media/datasheet/Samsung/K8D6x16UTM_K8D6x16UBM_rev16.pdf
接下来将会对该flash文档进行研究,并在之后的文章中分享我后续的研究成果。
往 期 热 门
(点击图片跳转)
觉得不错点个“在看”哦
jtag引脚定义_硬件学习之通过树莓派操控 jtag相关推荐
- jtag引脚定义_从逆向分析的角度学习硬件调试技巧JTAG,SSD和固件提取
我想从逆向的角度做了深入了解JTAG,JTAG是许多嵌入式CPU使用的硬件级别调试机制,我希望通过这篇文章从逆向工程师的角度解释如何使用JTAG,并在此过程中提供一些实际示例. 0x01 研究目标 通 ...
- 4接口引脚定义_浅谈USB Type-C接口
笔者前段时间做了一款STM32下载器,为了与新时代接轨,在设计电路板的时候首次使用了USBType-C接口,后来发现其确实很好用.就在今天又设计制作了一款USB-hub,在硬件上我又使用了Type-C ...
- rj45接口引脚定义_简单修复数控主机网络接口通讯故障
中国电路板维修人关注平台:技术分享.学习交流.案例视频.行业招聘资讯 [案例:某品牌数控主机网络接口无法通讯故障维修] 故障现象:网络接口无法使用,IP地址为192.168.1.101 解决方法: 此 ...
- 伺服驱动器cn1引脚定义_伺服驱动器CN1引脚定义,和面板操作设置,跪求高手指点。说明书弄丢了。...
展开全部 伺服驱动器CN1引脚定义,和面板操作设置? 根据所给图可知这个636f707962616964757a686964616f31333431353961是通惠伺服放大器型号为TH-100HA, ...
- vbyone接口引脚定义_一文了解A、B、C、D、E 5 种HDMI接口类型!网友:今天总算明白了...
如今在电脑中,VGA模拟接口.DVI数字接口逐渐淘汰,而高清的HDMI已经成为目前主流视频接口.那么什么是HDMI接口?它有什么用?有哪些版本?有几种类型?HDMI接口的针脚是什么?带着众多问题下面帝 ...
- 伺服驱动器cn1引脚定义_英威腾伺服
英威腾伺服基本操作 英威腾伺服命名规则 伺服点动等辅助功能的使用 注:英威腾的伺服开机需设电机码,否则出现各种问题,使电机与驱动配对 伺服开关量配置 引脚定义 DA200 EtherCAT 机型的IO ...
- rj45接口引脚定义_布线知识:各种接口RJ45接口针脚定义解析
RJ45接口信号定义,以及网线连接头信号安排 以太网 10/100Base-T 接口: Pin Name Description 1 TX+ Tranceive Data+ (发信号+) 2 TX- ...
- fpga的jtag接口扫不到器件_FPGA相关知识点9——JTAG接口的教训
简介: JTAG(Joint Test Action Group,联合测试工作组)是一种国际标准测试协议,主要用于芯片内部测试.标准的JTAG接口是4线:TMS.TCK.TDI.TDO,分别为模式选择 ...
- 硬件接口引脚定义(持续更新)
英文各类硬件接口定义网站:https://pinouts.ru/conn/ 1.SATA接口引脚定义 2.mSATA接口引脚定义 3.各类USB接口引脚定义 引脚 功能 接线颜色 备注 1 VCC 红 ...
最新文章
- 【Paper】Origin绘制误差棒图(标准差围绕均值)
- C++构造与析构(18) - 静态对象(static object)何时销毁
- Codeforces 1209D Cow and Snacks
- error:use of undeclared identifier
- .NET Core剪裁器升级瘦身引擎,并支持剪裁计划的录制和回放
- 产生的DLL (VS2005, MATLAB7.5, mwArray)
- html的表单图形验证码怎么做,django中简单图形验证码实现
- You have tried to change the API from what has been previously approved
- 基于cygwin构建u-boot(三)make错误忽视
- AMD Catalyst 14.4 Linux带来完整的 OpenGL 4.4 支持
- 泰安本地话听不懂,为何后来能勉强听懂?
- Mangos与mmorpg(转自百科)
- putty怎么进入文件夹_putty常用命令
- 一种很轻松的Excel关键字方式进行网页Web自动化测试(Java+Selenium+TestNG+Excel)
- get inkey、get input中,7 bit default 字符与ucs2字符的差异
- python实现3d扫描_三维激光扫描建模仪(基于树莓派)
- 常见的NoSQL数据库有哪些
- 配置SQLServer允许远程连接
- 关联规则挖掘Apriori算法的实现
- 为了更有效率地偷钱,Android root木马开始试水短信扣费诈骗