jetson-promote-image について
jetson-promote-imageは、カスタマイズとビルドの成果物を設定済みのbsp_imageへコピーし、後続のフラッシュや確認に備えるスキルです。overlayとビルドマニフェストを統合し、同一ファイルを除外します。カーネルやモジュールの変更時にはinitramfsを更新します。
主な機能
- 01overlayとビルドマニフェストの成果物を統合
- 02同一内容のファイルをコピー対象から除外
- 03変更されたカーネルImageをrootfsへ反映
- 04カーネルまたはモジュール変更後のinitramfs更新
- 05ビルドの鮮度とoverlayの競合を確認
活用シーン
- 01Jetsonのフラッシュ前にBSP成果物を配置
- 02フラッシュせずに確認用のbsp_imageを更新
- 03別のフラッシュ用ホストに渡すイメージを準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nvidia/ skills --skill jetson-promote-imageインストール後、Claude Code で/jetson-promote-imageを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdskill-card.mdskill.oms.sigevals/evals.jsonreferences/build-source-freshness-gate.mdcopy-pass-snippets.mdkernel-image-and-initramfs.md詳細
BSP イメージのプロモート
目的
すべての Customize-* と Build の出力を bsp_image にステージングし、/jetson-flash-image ですぐに使える状態にします。これは Deploy のプロモート工程です。ファイルをコピーするだけで、フラッシュもビルドもしません。
前提条件
source:とbsp_image:の両方が解決済みの、アクティブなターゲットプラットフォームプロファイル(先に/jetson-init-sourceと/jetson-init-imageを実行してください)。<source.root_path>/Linux_for_Tegra/が git リポジトリ(オーバーレイトラッカー)として初期化され、ワーキングツリーがクリーンであること。<bsp_image.root_path>/Linux_for_Tegra/が BSP tarball から展開済みで、apply_binaries.shも実行済みであること。- ホストに
git、yq、cmp、および(rootfs/*のコピー先用に)sudoがあること。 /jetson-build-sourceによる<source.root_path>/.build-manifest.yamlと.build-state.yaml(カーネル側のリポジトリに customize-* のコミットがある場合に必要)。
概要
これは Deploy のプロモート工程です。パイプラインの概要は
../../context/bsp-customization-workflow.md
を参照してください。このスキルがたどる 2 つの経路は次のとおりです。
| 経路 | ソース | 搬送元 | 管理者 |
|---|---|---|---|
| オーバーレイトラッカー | <source.root_path>/Linux_for_Tegra/(HEAD にある git リポジトリ) | ビルド不要の Customize-* 出力(例:nvfancontrol.conf、nvpmodel.conf、BPMP DTB の手動編集) | Customize customize-* スキルがここにコミット |
| ビルドマニフェスト | <source.root_path>/.build-manifest.yaml | 再ビルドされたカーネル Image、ツリー内の .ko、OOT .ko、NVIDIA DTB | Build jetson-build-source がここに書き込み |
このスキルは、コピー対象ファイルの和集合を算出し、差分を確認して同一ファイルのコピーをスキップするロジックで、それぞれを <bsp_image.root_path>/Linux_for_Tegra/ に書き込みます。コピー処理でカーネル Image または rootfs/lib/modules/ 配下のファイルに触れた場合は、NVIDIA の tools/l4t_update_initrd.sh を使って initramfs も再構築し、新たにプロモートされたカーネルとモジュールを、ブートローダーが実際に読み込む initrd に含めます。処理の完了後、bsp_image にはすべての Customize と Build の出力が揃います。このスキルはフラッシュを行わず、ワークスペースも変更しません。
実行するタイミング
- 一般的な Deploy チェーンの最初の工程
jetson-promote-image → jetson-flash-image → jetson-validate-image。 - ユーザーが
bsp_imageを更新したいものの、まだフラッシュの準備ができていない場合に単独で実行します(例:解決済みファイルの確認、bsp_imageを読み込む範囲外のビルドの実行、またはbsp_imageを別のフラッシュ用ホストに渡す場合)。
手順
アクティブなターゲットとパスを解決する
../../context/target-platform-contract.md
の契約に従って、アクティブなプロファイルを解決します。
次の場合は拒否し、適切な処理先に案内します。
| 条件 | 拒否時の案内 |
|---|---|
アクティブなプロファイルがない、または active: NA | /jetson-set-target または /jetson-init-target に案内します。 |
プロファイルに bsp_image: がない | /jetson-init-image に案内します。 |
<bsp_image.root_path>/Linux_for_Tegra/ がない | /jetson-init-image に案内します。 |
<source.root_path>/Linux_for_Tegra/ がない、または git リポジトリではない | /jetson-init-source に案内します。 |
パスを解決します。
<workspace>= アクティブなプロファイルのtarget-platform/ディレクトリの親ディレクトリ(読み込み時に検出)。<bsp_image.root_path>は、bsp_image.root_path:があればその値、なければ<workspace>/Image。<source.root_path>は、source.root_path:があればその値、なければ<workspace>/Source。
以降の手順で使うシェル変数を設定します。
LFT_SRC="<source.root_path>/Linux_for_Tegra" # overlay tracker
LFT_DST="<bsp_image.root_path>/Linux_for_Tegra"
MANIFEST="<source.root_path>/.build-manifest.yaml" # build outputs
2 つの経路を検証する
このスキルを実行するには、少なくとも 1 つの経路にデータが必要です。オーバーレイトラッカーに未コミットの変更がある場合(status --porcelain が空でない場合)、$MANIFEST が存在するものの YAML として解析できない場合、または両方の経路が空の場合は拒否します。後続の手順で使う OVERLAY_HAS_COMMITS/OVERLAY_HEAD と MANIFEST_PRESENT を記録します。
シェルスニペットと拒否時のメッセージについては、references/copy-pass-snippets.md を参照してください。
ビルドソースの鮮度を確認する
.build-state.yaml で、最後の /jetson-build-source 以降に
Source/bsp_sources/ 内のカーネル側リポジトリが変更されていることが
示されている場合は、処理を拒否します。そうしないと、コピー処理で
古い成果物が気付かれないまま出荷されてしまいます。
検出ルールとシェルスニペットについては、
references/build-source-freshness-gate.mdを参照してください。
BUILD_FRESH=1 を記録します。
昇格前の衝突チェック(オーバーレイのみ)
オーバーレイがリモートを追跡している場合、上流に未取得のコミットが
あれば処理を拒否します。リモートが設定されていない場合は、
適切にスキップします(jetson-init-source によるデフォルトの
空の git init トラッカー)。
マニフェストチャネルには git リモートの概念がないため、このチェックは
オーバーレイのみに適用されます。Summary 用に COLLISION_CHECK を記録します。
シェルスニペットについては、
references/copy-pass-snippets.md
を参照してください。
ソースの列挙(両方のチャネル)
チャネル A — オーバーレイ:$LFT_SRC に対する git ls-files を
信頼できる情報源とします(source.repos.Linux_for_Tegra が
オーバーライドされている場合、シンボリックリンクマウントにも対応し、
未追跡ファイルや .gitignore 対象ファイルは除外します)。各エントリは
src = $LFT_SRC/<rel> → dst = $LFT_DST/<rel> に対応します。
チャネル B — マニフェスト:$MANIFEST から
artifacts[].{src,dst} を解析します。src がディスク上に存在しない場合は
処理を拒否します(ビルドが中断されたか、マニフェストが古くなっています。
/jetson-build-source を再実行してください)。
マニフェストのスキーマは
jetson-build-source v0.2.0
によって書き込まれます。
両方のシェルスニペットとマニフェストの YAML スキーマについては、
references/copy-pass-snippets.md
を参照してください。
差分を考慮した bsp_image へのコピー
オーバーレイファイルとマニフェストエントリの和集合を反復処理します。
各 dst について、バイト単位で同一の場合はスキップし、それ以外は
cp -p でコピーします(サンプル rootfs が root として展開された
rootfs/* のコピー先には sudo を使用します)。rootfs/lib/modules/* または
kernel/Image への書き込みがあれば INITRD_DIRTY=1 を設定します。
「initramfs の更新」ステップはこのフラグを条件として実行されます。
件数/FIRST/LAST は Summary 用に記録されます。
フェイルファスト:cp が失敗した場合は、失敗したパスを示して停止します。
bsp_image は部分的に更新された状態になる場合がありますが、原因を
修正して再実行すれば、差分を考慮したスキップによって処理を再開できます。
チャネルの順序は、まずオーバーレイ、次にマニフェストです。dst が
衝突した場合は、マニフェストが優先されます(古いオーバーレイのコピーより、
新しくビルドされた成果物が優先されます)。
copy_one() 関数と、処理を実行する 2 つのループについては、
references/copy-pass-snippets.md
を参照してください。
カーネルが変更された場合の、カーネル Image の rootfs へのミラーリング
カーネル Image は bsp_image 内の 2 つのパスに存在します。
<LFT_DST>/kernel/Image(フラッシュツールが読み取ります)と
<LFT_DST>/rootfs/boot/Image(rootfs 側のコピーで、更新ツールが実行される
rootfs の chroot 内からは /boot/Image として見えます)です。
ビルドマニフェストに含まれるのは kernel/Image の dst のみであるため、
このステップでは kernel/Image → rootfs/boot/Image をミラーリングします
(差分を考慮し、すでに同期されている場合は何もしません)。これにより、
chroot 内で実行される更新ツールは古い rootfs のコピーではなく、新しく
昇格されたバイナリを使ってカーネルを解決します。このミラーリングでは
INITRD_DIRTY=1 も設定されるため、カーネルのみの昇格
(rootfs/lib/modules/* への書き込みなし)でも更新が実行されます。
シェルスニペット、この処理で防止される障害、および INITRD_DIRTY の
特殊ケースについては、
references/kernel-image-and-initramfs.md
を参照してください。
initramfs を更新する(カーネルまたはモジュールが変更された場合)
INITRD_DIRTY=1(上記の差分対応コピーまたはミラーステップによって設定された場合)は、<LFT_DST>/ から tools/l4t_update_initrd.sh を実行します。このツールは rootfs/ に chroot し、NVIDIA の nv-update-initrd を実行して、<LFT_DST>/bootloader/l4t_initrd.img(フラッシュツールで使用)と <LFT_DST>/rootfs/boot/initrd(DUT 上の /boot/initrd)の両方を書き込みます。冪等で、所要時間は約 30 秒です。INITRD_DIRTY=0 の場合(オーバーレイのみの編集)はスキップします。DUT 側での回避策(update-initramfs -u と手動の cp)は対象外です。フラッシュ時に整合性のあるイメージが使われるよう、ここで問題を解決してください。
シェルのスニペット、拒否するパス、再ビルドによって解消される「モジュールのシャドーイング」と「vermagic の不整合」の障害モード、および別のファイルである bootloader/initrd をそのままにする理由については、references/kernel-image-and-initramfs.md を参照してください。
概要
以下を報告します。
- オーバーレイの範囲:
overlay HEAD ($OVERLAY_HEAD)または「(空)」。 - マニフェストの範囲:
mode=<...>, bsp_version=<...>, rebuilt_at=<...>, N artifactsまたは「(なし)」。 - 衝突チェック:
$COLLISION_CHECK。 - 件数:
- オーバーレイ:
$COPIED_OVERLAY copied, $IDENTICAL_OVERLAY identical - マニフェスト:
$COPIED_MANIFEST copied, $IDENTICAL_MANIFEST identical
- オーバーレイ:
- カーネル Image のミラー:
$KIMG_MIRRORED、initramfs:$INITRD_STATUS(kernel/Imageまたはrootfs/lib/modules/*への書き込みによって実行された場合はcopied …/rebuilt、それ以外はskipped …)。 - コピーした最初と最後のパス(
COPIEDの合計が両方とも 0 の場合は省略)。 - 解決済みの
<source.root_path>、<bsp_image.root_path>。 - 次のステップ:
/jetson-flash-image(ユーザーが確認または静的検証のためにbsp_imageの更新のみを希望した場合は/jetson-validate-image)。
制限事項
- 2 つのチャネルで 1 つの出力先を共有します。
bsp_image/Linux_for_Tegra/には両方のパスから書き込みます。オーバーレイは customize-* の出力 (nvfancontrol.conf のようなオーバーレイのみの編集)を引き継ぎ、 マニフェストは再ビルドされたバイナリ(カーネル/OOT/DT)を引き継ぎます。 2 つは設計上、互いに重複しません。ビルド出力は オーバーレイに入らず、ビルド対象外ファイルへの customize-* による編集は マニフェストに入りません。 - ビルドマニフェストは、トレースと変更の対応関係を保証します。 マニフェスト内の
項目はすべて、変更のあったソースリポジトリから生成されています
(
jetson-build-sourceの「Write the build manifest」ステップのトレースポリシーに従います)。そのため、マニフェストの 昇格は安全です。各項目はカスタマイズを含む 成果物であり、ツールチェーンの差異によるノイズではありません。このスキルは トレースを再導出せず、マニフェストを信頼します。 - マニフェストの項目は、ビルド出力がなくなった後も残ることがあります。 ユーザーが
jetson-build-sourceとjetson-promote-imageの実行の間にSource/.build/またはbsp_sources/のビルド成果物を 削除すると、マニフェストは存在しないファイルを参照します。その場合、「Enumerate sources (both channels)」ステップは処理を拒否し、再ビルドするために/jetson-build-sourceを実行するようユーザーに案内します。 - オーバーレイのみを編集した場合、マニフェストがなくても問題ありません。
オーバーレイ側のみのカスタマイズ(例:
customize-fan)では ビルド出力は生成されず、マニフェストも書き込まれません。「Enumerate sources (both channels)」ステップは 何もせず、「Diff-aware copy into bsp_image」ステップはオーバーレイファイルのみを 昇格します。このスキルは概要に「manifest: (absent)」と出力して、 処理を続行します。 - 差分を考慮し、冪等です。 前回の昇格以降にオーバーレイのコミットや マニフェストの変更がなければ、再実行しても何も行われません(すべての ファイルが同一です)。副作用なしで bsp_image が同期されていることを 確認できます。
- シンボリックリンクマウントを透過的に扱います。
jetson-init-sourceでsource.repos.Linux_for_Tegraが上書きされている場合、正規マウントは<source.root_path>/.repos/Linux_for_Tegra/<subdir>へのシンボリックリンクです。git -C、cp -p、cmp -sはすべて透過的にこれをたどるため、このレイヤーで特別な 処理は不要です。マニフェストのsrcパスは絶対パスなので、bsp_sources/配下のシンボリックリンクはマニフェストチャネルに 影響しません。 sudoの使用はrootfs/宛ての処理に限定されます。rootfs/配下のファイルはjetson-init-imageがsudo tar xpjfで展開したもので、root の所有権と、フラッシュ用ツールチェーンが読み取る特別な モードビットを保持しています。sudo cp -pでそれらを保持できます。それ以外(bootloader/、kernel/、kernel/dtb/、tools/など)はユーザー所有なので、sudoは不要です。これは両方のチャネルに適用されます。- チャネル間で重複した場合の優先順位。 同じ
dstが オーバーレイとマニフェストの両方にある場合、マニフェストが優先されます(「Diff-aware copy into bsp_image」ステップの ループで後に処理されるためです)。これが意図した動作です。マニフェストの項目は 新たにビルドされたもので、オーバーレイの項目は古い状態の可能性があります。バイナリファイルを オーバーレイに手作業で編集することは推奨されません(ビルドの役割は 再ビルドすることです)。この優先順位により、そのような誤りから復旧できます。 - Deploy の外では
bsp_imageは読み取り専用です。 通常のフローでは、このスキルのみが 書き込みを行います(ワークフローの不変条件と一致します)。 Deploy の外で<bsp_image.root_path>/Linux_for_Tegra/を手作業で 編集すると、同じパスがいずれかのチャネルに存在する場合、次回の昇格実行時に 予告なく上書きされます。一方、対応する項目がなければ 元に戻されません。どちらも差分の追跡を損なうため、上流を手作業で編集しないでください。 - 対象範囲はオーバーレイの HEAD のみです(チャネル A)。 名前付きタグ/
マニフェスト/コミット範囲は後回しです(下記参照)。過去の状態を
昇格するには、まず
git -C $LFT_SRC checkout <ref>を実行してから、 再実行してください。マニフェストチャネルには範囲指定がなく、jetson-build-sourceの前回実行で生成された内容を反映します。 - 部分的な失敗が起きても、自動ロールバックは行いません。
cpが途中で失敗すると、bsp_imageは中間状態のままになります。根本原因(通常は権限またはディスク容量不足)を 解消してから再実行してください。「Diff-aware copy into bsp_image」ステップは、すでに昇格したファイルをスキップして 処理を再開します。 - カーネル
Imageのミラーと initramfs の更新。 コピー処理でkernel/Imageまたはrootfs/lib/modules/*への書き込みがあった場合にのみ実行します。ミラーは更新処理の chroot に 使用されます。どちらも差分を考慮し、オーバーレイのみの編集ではスキップされます。bsp_imageにtools/l4t_update_initrd.shが存在する必要があります (apply_binaries.shに同梱されています)。ツールが見つからない場合は処理を拒否し、/jetson-init-imageを案内します。契約と失敗時の動作については、references/kernel-image-and-initramfs.mdを参照してください。
トラブルシューティング
| エラー | 原因 | 解決策 |
|---|---|---|
Overlay has uncommitted changes at <LFT_SRC> | promote の前に Customize-* の編集がコミットされていません | git -C $LFT_SRC commit(または stash)を実行してから、再実行してください。 |
origin has N unpulled commits on <upstream> | リモートのオーバーレイがローカルと分岐しています | git -C $LFT_SRC pull を実行し、競合を解決してから再実行してください。 |
Both overlay and manifest are empty — nothing to promote | Customize-* のコミットも Build マニフェストもありません | 先に customize-* スキルまたは /jetson-build-source を実行してください。 |
Kernel-side source(s) changed since last /jetson-build-source | freshness gate が Source/bsp_sources/ 配下の未処理の customize-* 編集を検出しました | 保留中の編集をコミットし、/jetson-build-source を実行してから promote を再実行してください。 |
Manifest entry references missing build output: <src> | bsp_sources/ のビルド出力が削除されているか、マニフェストが古くなっています | /jetson-build-source を再実行して再生成してください。 |
Build manifest at <MANIFEST> is not valid YAML | マニフェストが手動編集されたか、書き込みが途中で終了しています | /jetson-build-source を再実行してマニフェストを書き直してください。 |
rootfs/ 配下で cp: permission denied | ホストで sudo 権限がありません | sudo cp を実行できるアカウントで実行してください。再実行すると差分を考慮したコピーから再開します。 |
プロファイルに bsp_image: / source: がありません | ワークスペースが初期化されていません | /jetson-init-image および/または /jetson-init-source を実行してください。 |
tool not found at <LFT_DST>/tools/l4t_update_initrd.sh | tools/ が削除されたか、bsp_image が NVIDIA 以外の tarball から展開されています | /jetson-init-image を再実行して補充してください。 |
l4t_update_initrd.sh exited non-zero | sudo 権限不足、rootfs の破損(lib/modules/<ver>/modules.dep がない)、または /tmp の空き容量不足です | まず rootfs に対して depmod -a -b <LFT_DST>/rootfs <ver> を実行し、/tmp の空き容量を確認してから promote を再実行してください。 |
promote 後に DUT が古いカーネル/モジュールで起動する、モジュールの読み込みが disagrees about version of symbol … で失敗する、または refresh の実行後も initramfs にカスタマイズ前のモジュールが含まれる | ミラー/refresh gate が作動していません(スキル外で <LFT_DST> 配下を手動編集した場合など)。または rootfs/boot/Image が kernel/Image と異なり、chroot 内の refresh が古いカーネルを使ってビルドしました | sudo touch <LFT_DST>/kernel/Image を実行して gate を強制し、promote を再実行してください。または、次の 2 つの手順を手動で実行してください:sudo cp -p <LFT_DST>/kernel/Image <LFT_DST>/rootfs/boot/Image && cd <LFT_DST> && sudo ./tools/l4t_update_initrd.sh。その後、再フラッシュしてください。詳細は references/kernel-image-and-initramfs.md を参照してください。 |
仕様のステータス
v0.2.0 で確定:
- 2 チャネルのスコープ — オーバーレイの HEAD とビルドマニフェストの両方を対象とします。どちらも差分を考慮し、
<bsp_image.root_path>/Linux_for_Tegra/にコピーします。 - チャネル間で重複した場合の優先順位 —
dstが競合した場合はマニフェストを優先します。 - ソースリポジトリの競合チェック — オーバーレイのみが対象です。マニフェストにはリモートの概念がなく、
bsp_sources/配下のソースリポジトリは取得されません(jetson-build-sourceがマニフェストを書き込んだ時点で、その状態が固定されているためです)。 - アトミック性 — 最初のエラーで処理を停止し、ロールバックは行いません。差分を考慮したコピーにより、自然に再開できます。
- 監査証跡 — 昇格時は標準出力のみを使用します。オーバーレイのトラッカーの Git ログがチャネル A の正式な記録であり、マニフェスト自体がチャネル B の正式な記録です。
- カーネル Image のミラーリングと initramfs の更新。 ペアで行うステップとして確定しました。コピー処理で
kernel/Imageに触れた場合は、ミラーリングによってkernel/Imageをrootfs/boot/Imageにコピーします。kernel/Imageまたはいずれかのrootfs/lib/modules/*が昇格された場合は、更新処理でtools/l4t_update_initrd.shを実行し、bootloader/l4t_initrd.imgとrootfs/boot/initrdの両方を再ビルドします。更新処理はrootfs/に chroot し、/boot/Image経由でカーネルを解決するため、ミラーリングを先に実行する必要があり、両者は切り離せません。これにより、モジュールのシャドーイングと vermagic の不整合による両方の障害モードを解消します。どちらも差分を考慮し、オーバーレイのみの編集ではスキップされます。詳しい仕様については、references/kernel-image-and-initramfs.mdを参照してください。
引き続き保留:
- オーバーレイチャネルでの タグ名/コミット範囲のスコープ。「リリース X を昇格する」ユースケースが現れたら再検討します。
- マニフェストの履歴。 現在は直近のビルドのマニフェストのみが存在します。ユーザーが
bsp_imageを以前のビルド状態に戻したい場合は、以前のコミットで/jetson-build-sourceを再実行する必要があります。ビルドモードごと、またはコミットごとにマニフェストを保存してアーカイブすれば、再ビルドせずにロールバックできるようになります。 bsp_image内のサイドカーマニフェスト。 オーバーレイのトラッカーリポジトリ(またはワークスペースのマニフェストファイル)にアクセスできないホストで昇格処理を行うようになったら、再検討します。
参考資料
references/kernel-image-and-initramfs.md— カーネルImageのミラーリングとl4t_update_initrd.shによる更新の詳細な仕様。シェルスニペット、障害モード、ツールの動作、出力ファイル名を記載しています。../../context/target-platform-contract.md— ターゲットプラットフォームの仕様。../../context/bsp-customization-workflow.md— ワークスペースの編集プロトコル(このスキルは Deploy の昇格工程です)。../jetson-init-source/SKILL.md— Setup。 このスキルが読み込むオーバーレイトラッカー(チャネル A)を生成し、source.toolchainを作成します。../jetson-build-source/SKILL.md— ビルドビルダー。このスキルが読み込む.build-manifest.yamlを書き込みます(チャネル B)。../jetson-flash-image/SKILL.md— 次の工程。昇格したばかりのbsp_imageを DUT に書き込みます。../jetson-validate-image/SKILL.md— 最終工程。静的検証とターゲット上での検証を行います。