jetson-validate-image
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseValidate BSP Image
验证BSP镜像
Status: the DUT-access contract is stable; the rest of the validation procedure is a skeleton.
状态: DUT访问协议已稳定;其余验证流程为框架性内容。
Purpose
目的
Confirm that a freshly customized BSP landed correctly — both as a
static artifact on disk and as a running system on the target —
without re-promoting or re-flashing. Forms the validation tail of
Deploy in the Setup → Customize → Build → Deploy pipeline (see
for the pipeline view) and is independently re-runnable.
../../context/bsp-customization-workflow.md确认刚定制的BSP已正确部署——包括作为磁盘上的静态工件,以及作为目标设备上的运行系统——无需重新推广或重新烧录。构成Setup → Customize → Build → Deploy流程中Deploy环节的验证收尾步骤(查看了解流程视图),且可独立重新运行。
../../context/bsp-customization-workflow.mdPrerequisites
前提条件
- Active target-platform profile with resolved (run
bsp_image:first)./jetson-init-image - For static-only scope: nothing further; the skill reads
directly.
<bsp_image.root_path> - For on-target scope:
- already pushed the staged BSP to the DUT.
/jetson-flash-image - block authored in the active profile (or filled interactively at runtime — see
dut_access:).## DUT access - Host tooling per transport: +
sshfor SSH; Python 3.6+ withsshpassfor UART.pyserial - Required env vars resolvable on the host when or
auth=password(sudo.method=password/password_envname the env var; never inline the secret in YAML).sudo.password_env
- 已解析的活跃目标平台配置文件(先运行
bsp_image:)。/jetson-init-image - 仅静态检查场景:无需额外条件;该工具直接读取。
<bsp_image.root_path> - 目标端检查场景:
- 已将预部署的BSP推送至DUT。
/jetson-flash-image - 活跃配置文件中已编写块(或在运行时交互式补充——查看
dut_access:)。## DUT访问 - 对应传输方式的主机工具:SSH方式需+
ssh;UART方式需Python 3.6+及sshpass库。pyserial - 当或
auth=password时,主机需可解析所需环境变量(sudo.method=password/password_env指定环境变量名称;切勿在YAML中直接写入密钥)。sudo.password_env
When to invoke
调用时机
- After has put the BSP onto a target.
jetson-flash-image - The user explicitly asks to validate, test, or run smoke / regression checks on a flashed device.
- As a CI gate before declaring a customization batch shippable.
- 在已将BSP烧录至目标设备之后。
jetson-flash-image - 用户明确要求对已烧录设备进行验证、测试,或运行冒烟/回归检查时。
- 作为CI关卡,用于确认定制批次可交付之前。
Instructions
操作步骤
The procedure below is a skeleton.
- Read the active target per the prerequisite contract.
- Choose validation scope — static (against on disk, no DUT needed) and/or on-target (DUT must be booted from the just-flashed image).
bsp_image - Static checks (if in scope):
- Required artifacts present at expected paths in
.
<bsp_image.root_path>/Linux_for_Tegra/ - DTB / module checksum or signature verification.
- Partition-layout sanity vs. the per-board 's XML.
.conf - Cross-check overlay-staged outputs against (they should be identical post-promotion).
bsp_image - Initramfs ↔ kernel + rootfs module coherence. Extract
and
<bsp_image>/Linux_for_Tegra/bootloader/l4t_initrd.img; verify three invariants against the promoted<bsp_image>/Linux_for_Tegra/rootfs/boot/initrdstate: (a)bsp_imagematches<bsp_image>/Linux_for_Tegra/kernel/Imagebyte-for- byte — drift here means the "Mirror kernel Image into rootfs" step was skipped and any subsequent initramfs refresh built against the previous kernel. (b) for each module path the two initrd images ship, the bytes / md5 match the file under<bsp_image>/Linux_for_Tegra/rootfs/boot/Image— any drift means modules will be shadowed at early boot. (c) the vermagic stamped on every initramfs<bsp_image>/Linux_for_Tegra/rootfs/lib/modules/<ver>/matches the*.koreachable fromUTS_RELEASE(e.g. parse the<bsp_image>/Linux_for_Tegra/kernel/Imagestring withLinux version …) — a vermagic skew means the kernelstringswas refreshed without rerunningImage, and modules will fail to load with "disagrees about version of symbol …". All three failure modes are closed byl4t_update_initrd.sh's gate on either/jetson-promote-imageorkernel/Imageplus the kernel-Image mirror; surface drift here and route the user back to a clean promote. Seerootfs/lib/modules/.../jetson-promote-image/SKILL.md
- Required artifacts present at expected paths in
- On-target checks (if in scope):
- Connect to the DUT per the section below — resolve transport (ssh / uart), credentials, and sudo method from the active profile's
## DUT accessblock (with interactive fallback when fields are missing / markeddut_access:), then run the connection probe and refuse if it fails.prompt - Confirm boot reached userspace.
- Run the selected test suite (smoke, regression, focused per-customization, ad-hoc).
- Loaded-module srcversion drift. For modules a
customization is known to have rebuilt, compare
on the DUT against the
cat /sys/module/<name>/srcversionreading. A mismatch means the kernel is running an older copy than the rootfs ships — almost always a stale initramfs (the bootloader-side initrd shipped a pre-customize module, it loaded first, and the rootfs copy cannot replace a live module). Recommend re-runningmodinfo /lib/modules/$(uname -r)/.../<name>.ko | awk '/srcversion/ {print $2}'and re-flashing. Note: some modules don't emit/jetson-promote-image; fall back to an md5 check against the binary the kernel loaded by extracting the region undersrcversionor by comparing behaviorally (printk / sysfs nodes / DT properties the new version is known to expose)./sys/module/<name>/sections/ - Running kernel vs. rootfs kernel . Compare
Image(orcat /proc/version) on the DUT against theuname -vstring extracted fromLinux version …(/boot/Image). A mismatch — usually the build timestamp /strings /boot/Image | grep -m1 'Linux version'— means the bootloader is running an older kernelLOCALVERSIONthan the rootfs holds, almost certainly because a freshImagewas promoted but the initramfs /Image/ QSPI boot partition wasn't refreshed. Modules in the rootfs will then have a different vermagic and any subsequentextlinux.confof a built-against-the-new-kernelmodprobewill fail. Recommend.koand re-flash./jetson-promote-image - Userspace dmesg readability. Ubuntu 22.04 sets
; non-root
kernel.dmesg_restrict=1reads return "Operation not permitted" and silently zero hits. Everydmesg-based check must run withdmesg(or temporarily lower the restriction viasudo). Surfacing this in the validate layer keeps printk-based customization checks honest.sudo sysctl kernel.dmesg_restrict=0 - Collect results, logs, artifacts.
- Connect to the DUT per the
- Summary: per-check pass/fail, overall verdict, where logs and artifacts landed.
以下流程为框架性内容。
- 读取活跃目标配置:遵循前提条件中的协议。
- 选择验证范围——静态检查(针对磁盘上的,无需DUT)和/或目标端检查(DUT必须从刚烧录的镜像启动)。
bsp_image - 静态检查(若包含在范围内):
- 确认下的预期路径中存在必需的工件。
<bsp_image.root_path>/Linux_for_Tegra/ - DTB/模块校验和或签名验证。
- 分区布局与对应板卡的文件中的XML是否一致。
.conf - 交叉检查预部署的覆盖输出与(推广后两者应完全一致)。
bsp_image - Initramfs ↔ 内核 + rootfs模块一致性。提取和
<bsp_image>/Linux_for_Tegra/bootloader/l4t_initrd.img;针对已推广的<bsp_image>/Linux_for_Tegra/rootfs/boot/initrd状态验证三个不变量: (a)bsp_image与<bsp_image>/Linux_for_Tegra/kernel/Image逐字节匹配——若此处存在差异,说明“将内核Image镜像至rootfs”步骤被跳过,后续任何initramfs刷新都是基于旧内核构建的。 (b) 对于两个initrd镜像中的每个模块路径,其字节/md5值需与<bsp_image>/Linux_for_Tegra/rootfs/boot/Image下的文件匹配——若存在差异,说明模块在早期启动时会被覆盖。 (c) 每个initramfs<bsp_image>/Linux_for_Tegra/rootfs/lib/modules/<ver>/文件上的vermagic需与*.ko中的<bsp_image>/Linux_for_Tegra/kernel/Image匹配(例如,使用UTS_RELEASE解析strings字符串)——vermagic不匹配说明内核Linux version …已刷新但未重新运行Image,模块加载时会失败并提示“disagrees about version of symbol …”。这三种失败模式均可通过l4t_update_initrd.sh在/jetson-promote-image或kernel/Image变更时的关卡,以及内核Image镜像步骤来避免;若此处发现差异,需引导用户重新执行完整的推广流程。查看rootfs/lib/modules/。../jetson-promote-image/SKILL.md
- 确认
- 目标端检查(若包含在范围内):
- 连接至DUT:按照下文部分的说明——从活跃配置文件的
## DUT访问块解析传输方式(ssh/uart)、凭据和sudo方法(当字段缺失或标记为dut_access:时,交互式补充),然后运行连接探测,若失败则终止操作。prompt - 确认设备已启动至用户空间。
- 运行选定的测试套件(冒烟测试、回归测试、定制专项测试、临时测试)。
- 已加载模块的srcversion差异:对于定制过程中已知已重建的模块,将DUT上的输出与
cat /sys/module/<name>/srcversion的读取结果进行比较。若不匹配,说明内核运行的是旧版本模块,而rootfs中是新版本——几乎总是因为initramfs过期(bootloader端的initrd包含定制前的模块,先加载了该模块,rootfs中的副本无法替换已加载的模块)。建议重新运行modinfo /lib/modules/$(uname -r)/.../<name>.ko | awk '/srcversion/ {print $2}'并重新烧录。注意:部分模块不会输出/jetson-promote-image;可通过提取srcversion下的区域,或通过行为对比(新版本已知会输出的printk信息、sysfs节点、DT属性)来替代md5校验。/sys/module/<name>/sections/ - 运行中的内核与rootfs内核对比:将DUT上的
Image(或cat /proc/version)输出与uname -v中提取的/boot/Image字符串(Linux version …)进行比较。若不匹配——通常是构建时间戳/strings /boot/Image | grep -m1 'Linux version'不同——说明bootloader运行的内核LOCALVERSION比rootfs中的旧,几乎可以肯定是因为新的Image已推广但initramfs/Image/QSPI启动分区未刷新。此时rootfs中的模块vermagic会不同,后续任何针对新内核构建的extlinux.conf文件执行.ko都会失败。建议运行modprobe并重新烧录。/jetson-promote-image - 用户空间dmesg可读性:Ubuntu 22.04设置了;非root用户执行
kernel.dmesg_restrict=1会返回“Operation not permitted”且无输出。所有基于dmesg的检查必须以dmesg运行(或通过sudo临时降低限制)。在验证层中明确这一点,可确保基于printk的定制检查准确有效。sudo sysctl kernel.dmesg_restrict=0 - 收集结果、日志和工件。
- 连接至DUT:按照下文
- 总结:每个检查项的通过/失败状态、整体结论,以及日志和工件的存储位置。
DUT access
DUT访问
The on-target leg needs a way to reach the just-flashed DUT.
Two transports are supported as full peers: (primary) and
(fallback for DUTs with no network).
sshuartThe contract is locked in but lives in
to keep this
SKILL.md under the agent-routing budget. That reference covers:
references/dut-access.md- The profile schema (ssh, uart, sudo, workdir).
dut_access: - Resolution order (profile → env var → interactive prompt) with the full refusal-trigger table.
- The mandatory connection probe (+
uname -r) and its output-validation rules.cat /etc/nv_tegra_release - File transfer per transport (vs. base64-over-tty, with the >100 KB warning).
scp - Sudo invocation matrix per × transport.
sudo.method - UART implementation contract that honors (state machines for login / exec / push / pull, exit codes, robustness notes).
scripts/uart_session.py - Security notes (password handling, host-key pinning).
目标端检查环节需要连接至刚烧录的DUT。支持两种传输方式:(首选)和(无网络DUT的备选方案)。
sshuart相关协议已锁定,详情请查看,以控制本SKILL.md的代理路由预算。该文档涵盖:
references/dut-access.md- 配置文件 schema(ssh、uart、sudo、工作目录)。
dut_access: - 解析顺序(配置文件→环境变量→交互式提示)及完整的终止触发规则表。
- 强制连接探测(+
uname -r)及其输出验证规则。cat /etc/nv_tegra_release - 对应传输方式的文件传输(vs 基于tty的base64,包含大于100 KB的警告)。
scp - 基于× 传输方式的sudo调用矩阵。
sudo.method - 需遵循的UART实现协议(登录/执行/推送/拉取的状态机、退出码、健壮性说明)。
scripts/uart_session.py - 安全注意事项(密码处理、主机密钥固定)。
Available Scripts
可用脚本
| Script | Purpose | Arguments |
|---|---|---|
| UART transport black box for the on-target leg: login, command exec (with optional sudo), and base64-over-tty file transfer. Replaces ssh when the DUT has no network or ssh is broken. | |
Invocation (the skill calls scripts as a subprocess —
in agent-runtime terminology):
run_script()bash
undefined| 脚本 | 用途 | 参数 |
|---|---|---|
| 目标端环节的UART传输黑盒:登录、命令执行(可选sudo)、基于tty的base64文件传输。当DUT无网络或ssh故障时替代ssh。 | |
调用方式(工具以子进程形式调用脚本——在代理运行时术语中为):
run_script()bash
undefinedrun_script: probe the DUT over UART
run_script: 通过UART探测DUT
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
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
DUT_UART_PASSWORD_ENV=DUT_UART_PWD
DUT_UART_PWD="$(read -rs -p 'UART登录密码: '; echo "$REPLY")"
scripts/uart_session.py
--tty /dev/ttyACM0 --baud 115200
--user ubuntu --password-env DUT_UART_PASSWORD_ENV
probe
DUT_UART_PWD="$(read -rs -p 'UART登录密码: '; 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
run_script: 执行sudo命令并捕获退出码
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'
--password-env DUT_UART_PASSWORD_ENV
--sudo-password-env DUT_SUDO_PWD
exec --use-sudo 'dmesg | tail -200'
The script's exit code is the contract — see the exit-code table in
[`UART implementation contract`](references/dut-access.md#uart-implementation-contract).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'
--password-env DUT_UART_PASSWORD_ENV
--sudo-password-env DUT_SUDO_PWD
exec --use-sudo 'dmesg | tail -200'
脚本的退出码为协议的一部分——查看[`UART实现协议`](references/dut-access.md#uart-implementation-contract)中的退出码表。Examples
示例
Static-only validation (no DUT needed):
/jetson-validate-image
> static checks only against the staged BSPOn-target validation over SSH after a freshly flashed DUT:
/jetson-flash-image
↓
/jetson-validate-image
> on-target checks via dut_access.sshOn-target validation over UART (no network on the DUT):
/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):
/jetson-validate-image
> 仅对预部署的BSP执行静态检查已烧录DUT后的SSH目标端验证:
/jetson-flash-image
↓
/jetson-validate-image
> 通过dut_access.ssh执行目标端检查UART目标端验证(DUT无网络):
/jetson-validate-image
> 使用/dev/ttyACM0的uart传输方式;配置文件中的dut_access.uart块已设置好tty和login_password_envLimitations
局限性
- Placeholder skill — only the DUT-access contract and the
helper are locked in. The static-check list, test-suite selection, result-sink layout, and pass/fail policy are tracked under
uart_session.pyand may change.## Open items - UART file transfer is byte-banged base64 at ~10 KB/s on 115200 baud — emits a warning for sources > 100 KB but proceeds. For high-volume transfers, switch to the SSH transport.
- opens and closes the tty per subcommand invocation (~1–2 s login per call). Validation passes running
uart_session.py10 commands amortize poorly on UART; prefer SSH. - SSH uses with a per-profile
StrictHostKeyChecking=accept-newfile. A fingerprint change refuses — typically means the DUT was reflashed (host keys regenerated) or the IP was reassigned. Remove the per-profile entry manually rather than auto-accepting.known_hosts - Passwords are never inlined in the profile YAML — only
(env-var name) is persisted.
password_env/auth=promptexposes the password in the conversation log, which is the user's responsibility to manage.sudo.method=prompt - with
transport=uartis not implemented (would require sending control characters that could corrupt the holder's state).lock_strategy=steal
- 框架性工具——仅DUT访问协议和辅助工具已锁定。静态检查列表、测试套件选择、结果存储布局及通过/失败策略在
uart_session.py中跟踪,可能会变更。## 待办事项 - UART文件传输为字节流base64,在115200波特率下约为10 KB/s——当源文件大于100 KB时会发出警告但仍会继续。对于大体积传输,建议切换至SSH传输方式。
- 每次子命令调用都会打开并关闭tty(每次调用约1-2秒登录时间)。若验证需运行超过10个命令,UART方式的耗时会很高;优先选择SSH。
uart_session.py - SSH使用及每个配置文件对应的
StrictHostKeyChecking=accept-new文件。若指纹变更则会终止操作——通常意味着DUT已重新烧录(主机密钥重新生成)或IP已重新分配。需手动删除配置文件对应的条目,而非自动接受。known_hosts - 密码永远不会内嵌在配置文件YAML中——仅(环境变量名称)会被持久化。
password_env/auth=prompt会在对话日志中暴露密码,用户需自行负责管理。sudo.method=prompt - 搭配
transport=uart未实现(需要发送控制字符,可能会破坏当前持有者的状态)。lock_strategy=steal
Troubleshooting
故障排除
| Error | Cause | Solution |
|---|---|---|
| On-target scope requested but | Author |
| | |
| | Close the holding process ( |
| UART transport selected but | |
| SSH fingerprint refused | DUT's host keys changed since the per-profile | Remove the matching line from |
| UART probe couldn't match a login or shell prompt within timeout | Confirm the DUT is powered + booted to userspace; check |
| | Re-run |
| | Set |
| Long-running DUT command exceeded the script's timeout | Run the command directly via |
| 错误 | 原因 | 解决方案 |
|---|---|---|
| 请求目标端范围但 | 在活跃配置文件中编写 |
| | 在调用工具前执行 |
| | 关闭占用进程(仅当你清楚进程用途时使用 |
| 选择了UART传输方式,但工具的Python环境中未安装 | 执行 |
| SSH指纹被拒绝 | 自配置文件的 | 从 |
| UART探测在超时内未匹配到登录或shell提示符 | 确认DUT已通电并启动至用户空间;若DUT使用非标准 |
| DUT上的 | 重新运行 |
| 向 | 在配置文件中设置 |
| DUT上的长运行命令超出了脚本的超时时间 | 通过 |
References
参考文档
- — full DUT-access contract: profile schema, resolution order, probe, file transfer, sudo, UART implementation, security.
references/dut-access.md - — target-platform contract.
../../context/target-platform-contract.md - — Workspace edit protocol (this skill is the Deploy tail).
../../context/bsp-customization-workflow.md - — Build builder; produces the artifacts this skill validates.
../jetson-build-source/SKILL.md
- — 完整的DUT访问协议:配置文件schema、解析顺序、探测、文件传输、sudo、UART实现、安全。
references/dut-access.md - — 目标平台协议。
../../context/target-platform-contract.md - — 工作区编辑协议(本工具为Deploy环节的收尾步骤)。
../../context/bsp-customization-workflow.md - — 构建工具;生成本工具验证的工件。
../jetson-build-source/SKILL.md