世界を動かす技術を、日本語で。

Qualcomm/SnapdragonデバイスのUSBポートに隠されたJTAG

概要

QualcommがEUD(Embedded USB Debug)のソースコードを公開。 EUDはQualcomm SoCの深いデバッグ機能をUSB経由で提供。 OpenOCDとの統合が進み、一般開発者も利用可能に。 セットアップやツール対応に課題は残るが、低レベルデバッグの大幅な進化。 今後のツール・ドライバ統合や利用事例の拡大に期待。

Qualcomm EUDソースコード公開の意義

  • 2024年2月、 QualcommEUD(Embedded USB Debug) のソースコードを静かに公開。
  • EUD は2018年以降のほぼ全ての Qualcomm SoC に搭載、SoC内部のCPUやHexagon DSP等のデバッグ機能を提供。
  • 開発ボードなどの非製品端末で、 レジスタ操作とUSB phy起動 でEUDが有効化。
  • PC側には7ポートUSBハブとして認識され、 EUDコントロールインターフェース が1ポートに出現。
  • 適切なUSBコマンドで SWD(Serial Wire Debug)インターフェース が出現、外部ツールや高価なデバッガ不要。

EUDの技術的特徴と使い方

  • JTAGSWD は、CPUコアのデバッグ(ブレークポイント、レジスタ参照等)を可能にする仕組み。
  • QualcommがCodeLinaro上で OpenOCDのEUD対応フォーク を公開していたが、以前は内部ライブラリ依存だった。
  • デバイス側のEUD有効化は Linuxカーネルに一部実装済み、新SoC向けの追加対応も進行中。
  • ソース公開により、 誰でもビルド・修正が可能 に。Ubuntu 20.10 + Qualcomm GCC 8.xでビルド想定だが、一般的な環境では修正が必要。
  • 修正済みコードや .gitignore 追加済みリポジトリが公開中。

OpenOCDとの統合と今後の課題

  • OpenOCD 0.12.0 ベースでEUD対応パッチが追加、HexagonデバッグやLLDB向け改善も含む。
  • 2年以上のOpenOCD本流の差分があり、 リベース作業 が必要。
  • Snapdragon 845/855/865 で動作確認済み、新SoC(例:SM8450)は追加対応要。
  • SMP(マルチコア)対応が未成熟、 maxcpus=1 での運用推奨。
  • デバッグベースアドレスやCTIベースレジスタがSoCごとに異なるため、 動作報告やフィードバック が求められる。

実用面と今後の展望

  • Linus Torvaldsはカーネルデバッガ利用に否定的だが、 U-Bootセキュアワールド 向けデバッグ需要は増加傾向。
  • Trusted Substrate 経由でTF-A, OP-TEE, U-Bootを含むBSP統合デバッグが容易化。
  • SWD以外にも UART相当のCOMペリフェラルトレースペリフェラル も存在、さらなる用途拡大が期待。
  • 製品端末ではEUDが無効化されている場合が多いが、 デバッグポリシー 次第で例外も存在。
  • EL2以上の実行レベル制御は不可、 カーネルレベルでのデバッグ用途 が主。

コミュニティへの呼びかけとまとめ

  • 各SoCでの EUD有効化手順や動作報告 をlinux-msmリポジトリで募集。
  • PRSRレジスタのsticky reset bitやSMP未対応等、 技術的課題 の解決に協力呼びかけ。
  • EUD公開により、 高価なデバッグ機器不要・リモートデバッグ容易化 など大きなメリット。
  • Qualcommの 開発者体験向上・オープン化推進 の好例、今後のツール統合や事例拡大に期待。

Hackerたちの意見

これは、前のQualcommのデバッグ体験よりもずっと良いですね。前はUSB経由で公開されていた手作りの読み書き実行のプリミティブセットだったから、めちゃくちゃセキュリティが甘かったんです。何人かは、いろんなQualcommモデルでルート権限を簡単に取得できちゃいました。真面目な話、これらのデバッグポートはほとんどのモバイルチップセットでかなり不足してます。MediaTekはまだ多くのデバイスで古いスタイルのアプローチを取っていて、USB経由でシリアルを公開するためのいくつかの呪文が必要なんですが、思ってるのとは違って、USBピン経由のシリアルなんです!モバイルチップセットとセキュリティに関してたくさんの仕事をしてきましたが、やっとこの機能がアクセス可能になる道を歩み始めたようです。ただ、ほとんどの場所でこれが標準でサポートされてないと驚かないでください。ほとんどのOEMは、ブートローダーを適応させたらこれを無効にするでしょうから。大手Gはエンドユーザーのデバイスでデバッグ可能なのを好まないんです。

ほとんどのボードには、別の物理的なJTAGコネクタがあります(少なくとも開発キットでは、この記事によると生産システムではJTAG over USBが無効になっているので、そこは変わらないですけど)。それが、低レベルのデバッグに使うことを期待されているものです。JTAGプローブは約1,000ドルで、エンジニア1人のフルコスト1日分くらいです。ハードウェアトレースやタイムトラベルデバッグを可能にするフル機能のプローブでも、エンジニア1人の1週間分のコストくらいです。

Googleは、すべてのPixelデバイスでSBUピン経由でシリアルを公開しています。

MediaTekはまだ多くのデバイスで古いスタイルのアプローチを取っていて、USB経由でシリアルを公開するための呪文が必要なんだけど、思ってるのとはちょっと違うんだよね。USBピンを使ったシリアルなんだ!それって昔のフィーチャーフォン(MT62xx)のSoCだけじゃなかったっけ?スマホのやつは、少なくともMT657x以降は、BootROMとプリローダーでUSB CDCを使ってると思うけど。

QXDMを使ってた青春時代を思い出させてくれるね。電話が壊れないように助けてくれたし、初めてのインターンシップでMDM9x50デバイスに関わった時もそうだった。

仕事では「USB-Cデバッグアクセサリーモード」に適応したんだけど、これはみんなが従うべき標準だと思う。

「セキュリティが甘い」って言うけど、私は「人々が自分が買ったものを所有できるようにする」って言いたい。

どの生産デバイスでこれが有効になるのか、すごく興味深いですね。少なくともOnePlus 6が言及されていて、これはフューズアウトされているけど、まだアクセス可能です。編集:生産版のOnePlus 6でeFusesをどうやって読み取っているんでしょう?Qualcommが署名したEL3 EDLローダーを持っているのかな?私が持っている(残念ながら生産版の)SM4350デバイスのデバイステーブルにqcom,msm-eudとして存在していて、eud_enable_regもあります。/dev/memでカーネルを再コンパイルする時が来たかも。

そう、ここにいくつかの生産デバイス用のEDLローダーが存在するよ [0]。アンブリックガイドなどのXDAフォーラムの投稿でももっと情報がある。知らない人のために言っておくと [0]: https://github.com/bkerler/Loaders

うーん、運がないな。デバイステーブルで見たのは(抜粋):qcom,msm-eud@1628000 { compatible = "qcom,msm-eud"; interrupt-names = "eud_irq"; interrupts = ; reg = ; reg-names = "eud_base", "eud_mode_mgr2", "eud_tcsr_check_reg"; qcom,secure-eud-en; qcom,eud-tcsr-check-enable; status = "ok"; }; qusb@162b000 { compatible = "qcom,qusb2phy-v2"; reg = ; reg-names = "qusb_phy_base", "efuse_addr", "refgen_north_bg_reg_addr", "eud_enable_reg"; qcom,efuse-bit-pos = ; qcom,efuse-num-bits = ; でもdevmem 0x162A000 4 0x1を実行するとシステムがロックアップして、以下のようなメッセージがramoopsに表示されます:[ 433.720232] msm_watchdog f410000.qcom,wdt: QCOMアプリウォッチドッグが発動しました! [ 433.727381] msm_watchdog f410000.qcom,wdt: Wdog - STS: 0xb01a6, CTL: 0x3, BARK TIME: 0x57fdf, BITE TIME: 0x6ffd6 これの解釈は全然わからないけど、efuse_addrの読み取り(特定のものはEL0から読み取れるのかな?)は0x0e000000で、ビット25-27がセットされていて、QFPROMのフューズはQualcommのドキュメントによると1の値が吹き飛ばされているみたいだから、フューズアウトされているかも?

つまり、Qualcommはカスタムシリコンの一部を持っていて、レジスタで制御される周辺機器として、これを有効にするとARMのUSBピンをそれを通して再ルーティングするんですね(その間にUSBハブを追加して)。そのハブにはSWDプログラマーとARMコアのIOに接続されるシリアルポートが追加されるってこと?すごい!

Appleの魔法のUSBのトリック、例えばChimp Cableについて知ったら驚くよ! https://www.theiphonewiki.com/wiki/Chimp_Cable

このUSBベースのデバッグアプローチは、SoCベンダー間で標準的な手法になりつつあるね(MediaTekのプリローダーやAppleの特別なケーブルみたいに)。専用のデバッグヘッダーを排除しつつ、eFuseで制御された認証を維持できるから。

別の話だけど、QualcommがUSBオーディオオフロードを実現するためにどれだけ努力してるかに感動したよ。オーディオデバイスがデータをUSBホストコントローラーに転送して、それがUSBオーディオデバイスに送るっていう仕組み。こんなに最適化に力を入れるのは変な感じだけど、見るとすごく面白いね。 https://www.phoronix.com/news/Linux-6.16-USB-Audio-Offload

この機能は、USBオーディオストリームがシステムの他の部分がスリープしている間も流れ続けることで、組み込みデバイスの大幅な省電力を実現します。バッテリー駆動のデバイスには本当に重要なことだね。実際にUSBをオーディオに使ってるデバイスはどれくらいあるんだろう?ほとんどのスマホやタブレット、ノートパソコンがUSBオーディオをサポートしてると思ってたけど、これはニッチなパワーユーザー向けの機能で、メインのデバイススピーカーが接続される方法ではないよね。同じシステムでBluetoothオーディオオフロードがあって、システムが数分間スリープできるようになってるのかな?(こっちの方が一般的な使い方っぽいけど)

いくつかのSoCではETMポートにアクセスできて、しかも並列だったんだよね(ピンの無駄遣いだなぁ;)。少しクロックを下げれば、フルプログラムトレースが出せるよ。つまり、Lauterbachを使ってアプリケーションとOS、すべてのドライバーを単一のアセンブラ命令レベルまでデバッグできる。