RP1チップをJTAGでデバッグしてみよう

はじめに

こんにちは、tnishinagaです。
今回はRP1のJTAGデバッグ方法を見つけたので、ご紹介します。

注意

本記事ではRP1が想定していない操作を行うため、本内容の実施によりRP1含めRaspberry Pi 5が故障する可能性があります。
十分ご注意の上、実施される際は自己責任のもとでお願いします。

要約

overview in english

RP1とリバースエンジニアリング

RP1はRaspberry Pi 5に搭載されているサウスブリッジ的なチップです。
Pi 5のIOのほぼすべてをこのRP1が担っているため、RP1を自由に制御できればPi5を自由に制御できると言えるのではと勝手に思っています。

このRP1のペリフェラルマニュアルは公開されていますが、中で動いているコードや一部仕様については非公開となっています。
そのため自由に扱うにはリバースエンジニアリングが必要であり、私を含め国内外で数人が取り組んでいるようです。

リバースエンジニアリングでは、人間がコンピューターの状態をなんとかして知る手段の確保が重要です。
その中でもとくにJTAGデバッガーが利用可能になると、プロセッサの制御を自由に行えて大変嬉しいです。
どこかに使えるJTAG端子は生えていないでしょうか?

RP1のJTAGを探す旅

RP1のペリフェラルマニュアルを読んでみると、6ページのFigure2にARM DEBUGと書かれた部分があり、少なくともプロセッサコアからJTAG端子が出ているとわかります。

画像はRP1のペリフェラルマニュアル, pp.6, Figure2より引用

また、特殊電子回路株式会社のなひたふさんの解析結果より、Pi 5のUSB端子の下にあるフレキシブルケーブル用のパターンからRP1のJTAG端子が出ていることが確認されています。

実際に自分も0.5mmピッチのフレキシブルケーブルと端子を購入してJTAGデバッガーとつなげて様子を見てみたところ、Raspberry Pi Trading LtdのTAPが見つかりました。

~/p/t/r/pi5_jtag ❯❯❯ openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -c 'transport select jtag'
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
jtag
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Warn : An adapter speed is not selected in the init scripts. OpenOCD will try to run the adapter at the low speed (100 kHz)
Warn : To remove this warnings and achieve reasonable communication speed with the target, set "adapter speed" or "jtag_rclk" in the init scripts.
Warn : libusb_detach_kernel_driver() failed with LIBUSB_ERROR_ACCESS, trying to continue anyway
Info : clock speed 100 kHz
Warn : There are no enabled taps.  AUTO PROBING MIGHT NOT WORK!!
Info : JTAG tap: auto0.tap tap/device found: 0x20001927 (mfg: 0x493 (Raspberry Pi Trading Ltd), part: 0x0001, ver: 0x2)
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 5 -expected-id 0x20001927"
Warn : gdb services need one or more targets defined

これがRP1のCortex-M3コアのTAPと考えてDAPの接続等を試行しましたが、うまくいきませんでした。
Arm Debug Interfaceでは命令ビット長は4または8bitと決められていますが、OpenOCDがAutoProbeで見つけた命令ビット長は5bitなので、合っていません。
よって、Cortex-M3以外の何らかのTAPが見えていると考えられます。

※Arm Debug Interfaceの仕様やデバッグの詳細については手前味噌ですがこちらの資料をご覧ください。

隠しコマンド、発見

TAPID 0x20001927へのDAP接続試行を何度か試していたところ、たまに違うTAPIDが見つかる事がありました。

# 当時のログを再現
Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : JTAG tap: auto1.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 4 -expected-id 0x4ba00477"
Warn : AUTO auto1.tap - use "jtag newtap auto1 tap -irlen 4 -expected-id 0x4ba00477"

最初はTAPのStateがおかしくなったのかなと思っていたのですが、よく見るとTAP IDのManufacturer ID Code部がArm Ltdとなっています。
もしやと思って出てきたTAPに対しDAPの接続を試したところ、Cortex-M3のDebug Unitが見えました。

そしてさらに調査を行ったところ、以下の操作を行うことでRP1のCortex-M3のTAPが見えるようになることを見つけました。

  • IRに0x1dをセットする
  • DRに0を128bit送る

どうやら隠しコマンドを見つけてしまったようです。
もしかすると他にも似たような隠しコマンドがあるかもしれません。

RP1にJTAG接続する方法

ここでやり方をまとめましょう。

ハードウェアの準備

Raspberry Pi 5のUSB下にあるフレキケーブル端子のパターン、またはテストポイントからJTAGに使う以下の線を引き出してください。
(端子とテストポイントの対応はなひたふさんのブログ記事を参考)

  • TDI : TP53
  • TDO : TP54
  • TCK : TP55
  • TMS : TP56
  • GND : GPIO端子等
  • 3.3V: GPIO端子等

引き出したらJTAGデバッガーと接続します。
私の使用したARM-USB-TINY-Hというデバッガーと接続するための回路図を共有しますので、ARM JTAG 20のピン配置を確認しつつ接続を行ってください。

ARM JTAG 20のピン配置はなひたふさんの解説がわかりやすくてオススメです。

私はつなぎ間違えが怖いので基板を作りました。

隠しコマンドの発行

JTAGデバッガーをつなぎ、OpenOCDを入れたマシンに以下のスクリプトを保存し、実行します。
これで次回のOpenOCD実行時からCortex-M3のTAPが見えるようになります。

# SPDX-License-Identifier: GPL-2.0-or-later
# Toshifumi Nishinaga<tnishinaga.dev@gmail.com>

# rp1_init.cfg
transport select jtag
adapter speed 1

jtag newtap cpu0 cpu -expected-id 0x20001927 -irlen 5

init

pathmove IRSHIFT
irscan cpu0.cpu 0x1d 

pathmove DRSHIFT
drscan cpu0.cpu 8 0
openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f rp1_init.cfg

Cortex-M3コアへの接続

先ほどと同様に、以下のファイルを作ってからopenocdを実行してください。

# rp1.cfg
# This file is based on target/bcm2711.cfg
# SPDX-License-Identifier: GPL-2.0-or-later
# Toshifumi Nishinaga<tnishinaga.dev@gmail.com>

transport select jtag
adapter speed 100

jtag newtap cpu0 cpu -expected-id 0x4ba00477 -irlen 4
jtag newtap cpu1 cpu -expected-id 0x4ba00477 -irlen 4

dap create cpu0.dap -chain-position cpu0.cpu
dap create cpu1.dap -chain-position cpu1.cpu

# cpu0
target create cpu0.ap mem_ap -dap cpu0.dap -ap-num 0
target create cpu0 cortex_m -dap cpu0.dap -ap-num 0 -dbgbase 0xe000e000
# cpu1
target create cpu1.ap mem_ap -dap cpu1.dap -ap-num 0
target create cpu1 cortex_m -dap cpu1.dap -ap-num 0 -dbgbase 0xe000e000
openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f rp1.cfg

以下のようなログが出たら成功です。

~/p/t/r/pi5_jtag ❯❯❯ openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f rp1.cfg
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
3758153728
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Warn : libusb_detach_kernel_driver() failed with LIBUSB_ERROR_ACCESS, trying to continue anyway
Info : clock speed 100 kHz
Info : JTAG tap: cpu0.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : JTAG tap: cpu1.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : [cpu0] Cortex-M3 r2p1 processor detected
Info : [cpu0] target has 6 breakpoints, 4 watchpoints
Info : [cpu1] Cortex-M3 r2p1 processor detected
Info : [cpu1] target has 6 breakpoints, 4 watchpoints
Info : gdb port disabled
Info : starting gdb server for cpu0 on 3333
Info : Listening on port 3333 for gdb connections
Info : gdb port disabled
Info : starting gdb server for cpu1 on 3334
Info : Listening on port 3334 for gdb connections

あとはgdbでTCP 3333や3334番につなぐとRP1を自由に操作できます。

(gdb) tar remote :3334

(gdb) i r
r0             0x676e6f6c          1735290732
r1             0x77207265          1998615141
r2             0x696b726f          1768649327
r3             0x1                 1
r4             0x34                52
r5             0x100029b0          268446128
r6             0x34                52
r7             0x20003990          536885648
r8             0x200057d0          536893392
r9             0x10002010          268443664
r10            0x200057d8          536893400
r11            0x200057d4          536893396
r12            0x0                 0
sp             0x10002980          0x10002980
lr             0x100002dd          268436189
pc             0x100003ae          0x100003ae
xPSR           0x81000000          -2130706432
msp            0x10002980          0x10002980
psp            0x0                 0x0
primask        0x0                 0
basepri        0x0                 0
faultmask      0x0                 0
control        0x0                 0

試しにRP1のcore1に接続してレジスタを眺めたところ、PCがProc Local ISRAMの領域を指している様子が伺えました。

以上です。
Happy Hacking!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です