mcpField
J
jetson-validate-image

jetson-validate-image

github.com/nvidiaテスト・品質3.8k1.1k 回インストール今日更新
リポジトリ

jetson-validate-image について

カスタマイズ済み Jetson BSP イメージを検証するためのプレースホルダー型スキルです。ディスク上の成果物やフラッシュ直後のデバイスを確認するエンジニア向けで、DUT のアクセス仕様と UART ヘルパー以外の手順は未完成です。

主な機能

  1. 01BSP 成果物の静的チェック
  2. 02SSH と UART による DUT 接続
  3. 03起動状態とモジュールの整合性確認
  4. 04テスト結果とログの集約

活用シーン

  1. 01フラッシュ前の BSP イメージ確認
  2. 02フラッシュ直後の Jetson の検証
  3. 03スモークテストや回帰テストの実行
  4. 04CI でカスタマイズ成果を判定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/nvidia/skills --skill jetson-validate-image

インストール後、Claude Code で/jetson-validate-imageを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

BENCHMARK.md
skill-card.md
skill.oms.sig
evals/
evals.json
references/
dut-access.md
scripts/
uart_session.py

詳細

BSP イメージの検証

ステータス: DUT へのアクセス契約は安定していますが、検証手順の残りの部分は骨組みです。

目的

新たにカスタマイズした BSP が正しく適用されたことを、ディスク上の静的な成果物として、またターゲット上の実行中のシステムとして確認します。再プロモートや再フラッシュは行いません。Setup → Customize → Build → Deploy パイプライン(パイプラインの概要については ../../context/bsp-customization-workflow.md を参照)の Deploy の検証工程を担い、個別に再実行できます。

前提条件

  • bsp_image: が解決済みの、アクティブなターゲットプラットフォームプロファイル(最初に /jetson-init-image を実行してください)。
  • 静的な検証のみの場合:追加の要件はありません。このスキルは <bsp_image.root_path> を直接読み取ります。
  • ターゲット上で検証する場合:
    • /jetson-flash-image によって、ステージング済みの BSP がすでに DUT に書き込まれていること。
    • アクティブなプロファイルに dut_access: ブロックが記述されていること(または実行時に対話形式で入力すること。詳細は ## DUT access を参照)。
    • トランスポートに応じたホストツール:SSH の場合は ssh と sshpass、UART の場合は pyserial を使用できる Python 3.6 以降。
    • auth=password または sudo.method=password の場合、必要な環境変数をホスト上で解決できること(password_env / sudo.password_env には環境変数名を指定してください。シークレットを YAML に直接記述しないでください)。

実行するタイミング

  • jetson-flash-image で BSP をターゲットに書き込んだ後。
  • ユーザーから、フラッシュ済みデバイスの検証、テスト、スモークテスト/回帰チェックの実行を明示的に依頼されたとき。
  • カスタマイズ一式を出荷可能と判断する前の CI ゲートとして。

手順

以下の手順は骨組みです。

  1. 前提条件の契約に従って、アクティブなターゲットを読み取ります。
  2. 検証範囲を選択します — 静的検証(ディスク上の bsp_image を対象とし、DUT は不要)および/またはターゲット上での検証(DUT はフラッシュ直後のイメージから起動している必要があります)。
  3. 静的チェック(範囲に含まれる場合):
    • 想定されるパス <bsp_image.root_path>/Linux_for_Tegra/ に必要なアーティファクトが存在すること。
    • DTB/モジュールのチェックサムまたは署名の検証。
    • ボードごとの .conf にある XML とパーティションレイアウトの整合性確認。
    • オーバーレイにステージされた出力と bsp_image を照合します(昇格後は同一である必要があります)。
    • Initramfs ↔ カーネル + rootfs モジュールの整合性。 <bsp_image>/Linux_for_Tegra/bootloader/l4t_initrd.img と <bsp_image>/Linux_for_Tegra/rootfs/boot/initrd を抽出し、昇格済みの bsp_image の状態に対して次の 3 つの不変条件を検証します。 (a) <bsp_image>/Linux_for_Tegra/kernel/Image と <bsp_image>/Linux_for_Tegra/rootfs/boot/Image がバイト単位で一致すること。この不一致は、「カーネル Image を rootfs にミラーする」手順が省略され、その後の initramfs の更新が以前のカーネルに対して行われたことを意味します。 (b) 2 つの initrd イメージに含まれる各モジュールパスについて、バイト列/md5 が <bsp_image>/Linux_for_Tegra/rootfs/lib/modules/<ver>/ 内のファイルと一致すること。不一致があると、起動初期にモジュールが別のものに隠されます。 (c) すべての initramfs *.ko に記録された vermagic が、<bsp_image>/Linux_for_Tegra/kernel/Image から取得できる UTS_RELEASE と一致すること(たとえば、strings で Linux version … 文字列を解析します)。vermagic の不一致は、l4t_update_initrd.sh を再実行せずにカーネル Image を更新したことを意味し、モジュールの読み込み時に「disagrees about version of symbol …」というエラーが発生します。3 つの失敗モードはいずれも、/jetson-promote-image の kernel/Image または rootfs/lib/modules/ とカーネル Image のミラーを対象とするゲートで防止されます。ここで不一致を明らかにし、ユーザーにクリーンな昇格を再実行するよう案内してください。詳しくは ../jetson-promote-image/SKILL.md を参照してください。
  4. ターゲット上のチェック(範囲に含まれる場合):
    • 以下の ## DUT access セクションに従って DUT に接続します — アクティブなプロファイルの dut_access: ブロックから接続方式(ssh/uart)、認証情報、sudo の方法を解決し(フィールドが未指定、または prompt と指定されている場合は対話的に確認)、接続プローブを実行します。失敗した場合は続行しないでください。
    • 起動がユーザー空間まで到達したことを確認します。
    • 選択したテストスイート(スモーク、回帰、カスタマイズごとの重点テスト、アドホック)を実行します。
    • ロード済みモジュールの srcversion の不一致。 カスタマイズによって再ビルドされたことが判明しているモジュールについて、DUT 上の cat /sys/module/<name>/srcversion の値と、modinfo /lib/modules/$(uname -r)/.../<name>.ko | awk '/srcversion/ {print $2}' の出力を比較します。不一致は、カーネルが rootfs にあるものより古いコピーを実行していることを意味します。これはほぼ常に initramfs が古いことが原因です(ブートローダー側の initrd にカスタマイズ前のモジュールが含まれ、それが先にロードされるため、rootfs 側のコピーではロード済みモジュールを置き換えられません)。/jetson-promote-image を再実行して再フラッシュするよう案内してください。注:srcversion を出力しないモジュールもあります。その場合は、/sys/module/<name>/sections/ 以下の領域を抽出してカーネルがロードしたバイナリと md5 を照合するか、振る舞い(printk、sysfs ノード、新バージョンで公開されることが判明している DT プロパティ)で比較してください。
    • 実行中のカーネルと rootfs のカーネル Image。 DUT 上の cat /proc/version(または uname -v)と、/boot/Image から抽出した Linux version … 文字列(strings /boot/Image | grep -m1 'Linux version')を比較します。不一致は、通常、ビルド時刻または LOCALVERSION の違いを示します。これは、ブートローダーが rootfs にあるものより古いカーネル Image を実行していることを意味し、ほぼ確実に、新しい Image を昇格した後に initramfs/extlinux.conf/QSPI ブートパーティションが更新されていないことが原因です。その場合、rootfs のモジュールは異なる vermagic を持つため、新しいカーネルに対してビルドされた .ko をその後 modprobe すると失敗します。/jetson-promote-image を実行して再フラッシュするよう案内してください。
    • ユーザー空間からの dmesg の読み取り。 Ubuntu 22.04 では kernel.dmesg_restrict=1 が設定されています。root 以外のユーザーによる dmesg の読み取りは「Operation not permitted」を返し、ヒット数が暗黙に 0 になります。dmesg に基づくすべてのチェックは sudo を使用して実行する必要があります(または sudo sysctl kernel.dmesg_restrict=0 で一時的に制限を緩和してください)。この点を検証レイヤーで明示することで、printk に基づくカスタマイズチェックの信頼性を保てます。
    • 結果、ログ、アーティファクトを収集します。
  5. 概要:チェックごとの合否、全体の判定、ログとアーティファクトの保存先。

DUT アクセス

オンターゲット側では、フラッシュ直後の DUT にアクセスする方法が必要です。 完全に対等なトランスポートとして、ssh(優先)と uart(ネットワークのない DUT 向けのフォールバック)をサポートしています。

契約は確定していますが、この SKILL.md がエージェントルーティングの予算を超えないよう、 references/dut-access.md に記載されています。このリファレンスでは、以下を扱います。

  • dut_access: プロファイルのスキーマ(ssh、uart、sudo、workdir)。
  • 解決順序(プロファイル → 環境変数 → 対話型プロンプト)と、 拒否条件を網羅した表。
  • 必須の接続プローブ(uname -r + cat /etc/nv_tegra_release)とその出力検証ルール。
  • トランスポートごとのファイル転送(scp と base64-over-tty、および

    100 KB の警告)。

  • sudo.method × トランスポートごとの sudo 呼び出しマトリックス。
  • scripts/uart_session.py が遵守する UART 実装契約 (login / exec / push / pull のステートマシン、終了コード、堅牢性に関する注意点)。
  • セキュリティに関する注意点(パスワードの取り扱い、ホストキーのピン留め)。

利用可能なスクリプト

スクリプト用途引数
scripts/uart_session.pyオンターゲット側の UART トランスポートのブラックボックス:login、コマンド実行(sudo は任意)、base64-over-tty によるファイル転送。DUT にネットワークがない場合、または ssh が動作しない場合に ssh を置き換えます。--tty <dev> [--baud <n>] --user <name> --password-env <ENVVAR> [--sudo-password-env <ENVVAR>] [--shell-prompt <regex>] [--lock-strategy refuse|wait] <probe|exec|push|pull> [...]

呼び出し(スキルはサブプロセスとしてスクリプトを呼び出します — エージェントランタイムの用語では run_script()):

# run_script: probe the DUT over UART
DUT_UART_PASSWORD_ENV=DUT_UART_PWD \
DUT_UART_PWD="$(read -rs -p 'UART login pw: '; echo "$REPLY")" \
  scripts/uart_session.py \
    --tty /dev/ttyACM0 --baud 115200 \
    --user ubuntu --password-env DUT_UART_PASSWORD_ENV \
    probe

# run_script: exec a sudo command and capture exit code
scripts/uart_session.py --tty /dev/ttyACM0 --user ubuntu \
  --password-env DUT_UART_PASSWORD_ENV \
  --sudo-password-env DUT_SUDO_PWD \
  exec --use-sudo 'dmesg | tail -200'

スクリプトの終了コードが契約となります — 終了コードの表は UART implementation contract を参照してください。

例

静的チェックのみの検証(DUT は不要):

/jetson-validate-image
> static checks only against the staged BSP

フラッシュ直後の DUT に対する SSH 経由のオンターゲット検証:

/jetson-flash-image
   ↓
/jetson-validate-image
> on-target checks via dut_access.ssh

DUT にネットワークがない場合の UART 経由のオンターゲット検証:

/jetson-validate-image
> use the uart transport at /dev/ttyACM0; the dut_access.uart block
  in the profile already has the tty and login_password_env wired up

制限事項

  • プレースホルダースキルです — DUT アクセス契約と uart_session.py ヘルパーのみが確定しています。静的チェックの一覧、 テストスイートの選択、結果の格納先の構成、合否ポリシーは ## Open items で管理されており、変更される可能性があります。
  • UART ファイル転送は 115200 baud で約 10 KB/s のビットバンギングによる base64 転送です — 100 KB を超えるソースには警告を出しますが、転送は続行します。 大容量の転送には SSH トランスポートに切り替えてください。
  • uart_session.py はサブコマンドの呼び出しごとに tty を開閉します (呼び出しごとにログインに約 1~2 秒かかります)。10 個を超えるコマンドを実行する検証パスでは UART の効率が大幅に低下するため、SSH を推奨します。
  • SSH はプロファイルごとの known_hosts ファイルを使用し、StrictHostKeyChecking=accept-new を設定します。フィンガープリントが変更されると拒否されます — 通常、DUT の再フラッシュ(ホストキーの再生成)または IP の再割り当てを意味します。自動的に受け入れるのではなく、プロファイルごとのエントリを手動で削除してください。
  • パスワードをプロファイル YAML に直接記述することはありません — 保存されるのは password_env(環境変数名)のみです。auth=prompt / sudo.method=prompt では会話ログにパスワードが表示されます。管理はユーザーの責任です。
  • lock_strategy=steal を指定した transport=uart は 実装されていません (ロック保持者の状態を破損させる可能性がある制御文字を送信する必要があるためです)。

トラブルシューティング

エラー原因解決方法
no DUT transport configured (拒否)オンターゲットのスコープが要求されましたが、プロファイル/環境変数/対話型プロンプトを通じて dut_access.transport を解決できませんでしたアクティブなプロファイルに dut_access: を記述するか、静的のみのスコープで再実行してください。
$PASSWORD_ENV is unset (拒否)auth=password(または sudo.method=password)で指定された環境変数が、ホストでエクスポートされていませんスキルを実行する前に export <ENVVAR>=... を実行してください。YAML にパスワードを直接記述してはいけません。
tty held by another process (拒否、終了コード 3)lock_strategy=refuse が設定されており、fuser が別のプロセス(minicom、picocom、getty)による使用を検出しました使用中のプロセスを終了してください(状況を把握している場合に限り sudo fuser -k <tty> を実行してください)。または lock_strategy=wait を指定して再実行してください。
pyserial import failed (終了コード 4)UART トランスポートが選択されていますが、スキルの Python 環境に pyserial がインストールされていませんapt install python3-serial または pip install pyserial を実行してください。
SSH フィンガープリントが拒否されましたプロファイルごとに固定された known_hosts の設定後に、DUT のホストキーが変更されました(通常は再フラッシュが原因です)<workspace>/target-platform/<profile-stem>.known_hosts から該当する行を削除して再実行してください。次回の接続時に新しいキーが受け入れられます。
login failed (終了コード 128)UART プローブが、タイムアウトまでにログインプロンプトまたはシェルプロンプトを認識できませんでしたDUT の電源が入り、ユーザー空間まで起動していることを確認してください。DUT に通常とは異なる PS1 が設定されている場合は --shell-prompt の上書きを確認し、--user が実在するアカウントと一致していることを確認してください。
DUT not booted from the just-flashed BSP (警告/拒否)DUT 上の /etc/nv_tegra_release が bsp_image.version と一致しません/jetson-flash-image を再実行し、DUT が以前の BSP ではなく、新しい BSP で実際に電源再投入されて起動したことを確認してください。
sudo prompt detected but no sudo password configured (終了コード 130)uart_session.py exec に --use-sudo が渡されましたが、--sudo-password-env が設定されておらず、DUT ユーザーにも NOPASSWD がありませんプロファイルで sudo.method=password と sudo.password_env を設定するか、/etc/sudoers.d/ を通じて DUT に NOPASSWD を設定してください。
command timed out (終了コード 129)実行時間の長い DUT コマンドがスクリプトのタイムアウトを超えましたssh トランスポートを使ってコマンドを直接実行するか、短い手順に分割してください。

参考資料

コメント