Jetson Image-based OTA:DevKit 从零跑通官方 Demo 实操指南(R36.4.x)

📅 发布时间:2026/7/7 14:51:45 👁️ 浏览次数:
Jetson Image-based OTA:DevKit 从零跑通官方 Demo 实操指南(R36.4.x)
B站博主个人介绍博主书籍-京东购买链接*Yocto项目实战教程加博主微信进技术交流群jerrydevJetson Image-based OTADevKit 从零跑通官方 Demo 实操指南R36.4.x目标用NVIDIA 官方提供的 OTA tools payload在一块 Jetson DevKit 上完整跑通一次 image-based OTAHost 生成 payload → 设备侧触发 → reboot 进入 recovery kernel → 更新完成。说明本文重点是“跑通官方 demo”。你会看到服务器端只在产品化时才必需做 demo 可以先用scp/USB/本地 HTTP代替“服务器下载”。0. 先把话说清楚你要跑通的“Image-based OTA demo”到底是什么Jetson 的image-based OTA不是apt upgrade那种“装几个软件包”式升级。它的本质是在 Host 上把目标版本 BSP 需要更新的分区镜像bootloader/kernel/rootfs 等打包成一个ota_payload_package.tar.gz。在目标设备上用nv_ota_start.sh触发升级。设备重启后进入recovery kernel由 recovery 环境完成真正的分区写入与切换。你最终得到的不是“升级了某个包”而是“设备被升级到一套一致的 BSP 版本快照”。这也是 image-based OTA 的工程价值一致性更强、可控性更强、适合 BSP/分区级升级。1. 你现在找不到l4t_generate_ota_package.sh的原因最常见坑很多人第一次按目录去找脚本都会懵你在Linux_for_Tegra/里能看到tools/但找不到tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh。这是正常的✅l4t_generate_ota_package.sh并不一定在“裸 Driver Package”里。它来自ota_tools_rel_aarch64.tbz2这个 OTA tools 包。也就是说你必须先下载ota_tools_rel_aarch64.tbz2然后解压到Linux_for_Tegra的上一级目录让它把tools/ota_tools/...放进 BSP 目录解压完成后脚本才会出现。快速自检# 在你的 Linux_for_Tegra 目录执行lstools/ota_tools/version_upgrade/l4t_generate_ota_package.sh# 如果提示不存在说明 OTA tools 还没解压到位2. Demo 跑通一次 OTA你需要准备哪些东西2.1 你至少需要“两份 BSP”为了生成“从旧版升级到新版”的 OTA payload你至少需要BASE_BSP设备当前运行的旧版本 BSPbase releaseTARGET_BSP你想升级到的新版本 BSPtarget release初学者最推荐的 demo用同一大版本线内的 point release例如 R36.4.3 → R36.4.4来跑通流程变量更少排错更轻松。2.2 你需要的两个交付物最终要放到设备侧ota_tools_rel_aarch64.tbz2工具包ota_payload_package.tar.gz分区镜像 payload做 demo 时你可以先把它们拷到板子上。产品化时它们通常会放到你的 OTA server由设备端 OTA client 下载。2.3 设备侧空间要求ota_payload_package.tar.gz解压 处理需要设备侧有足够空闲空间。经验上你至少要准备7GB 以上默认 rootfs 的 payload 本身常见在数 GB 级别具体取决于你 rootfs 大小。2.4 你需要知道设备的 rootfs 在哪里eMMC 还是 NVMe在目标设备上运行findmnt / lsblk看到/挂载在/dev/nvme0n1pX说明你是 NVMe rootfs看到/dev/mmcblk0pX说明你是 eMMC/SD rootfs。这会影响你后面生成 payload 时是否需要--external-device、-S等参数。3. 学习路线与方法从“跑通”到“能做产品”这一章是本文的“升级版核心”。很多初学者会卡在两个点只会照命令跑一次但不知道哪些信息是关键证据、哪些变量会影响结果。不知道下一步怎么学NVMe、A/B、UEFI Secure Boot、Disk Encryption、数据保留、自定义任务链到底怎么插进整体框架。下面给你一套可复用的学习方法3.1 三层学习目标建议按顺序完成第 1 层跑通链路Demo 级目标Host 能生成 payloadDevice 能触发并完成升级能验证版本变化。输出物Host 侧payload 文件路径与大小ota_payload_package.tar.gzDevice 侧升级前后/etc/nv_tegra_release、uname -a、日志成功/失败第 2 层可控与可观测工程级目标知道“升级过程在哪执行”“失败在哪里看”“如何复现”。输出物关键日志打包与归档策略故障注入复现记录比如中途重启/断电一次关键检查点checkpoints列表第 3 层产品化框架产品级目标把 OTA 从“手动脚本”变成“守护进程 manifest 安全校验 上报 灰度”。输出物OTA client/service 的状态机manifest 设计版本、兼容性、hash/signature、策略server 端目录结构与访问鉴权方案3.2 四个视角帮助你“理解而不是背命令”你学 OTA 时建议同时从四个视角看同一个流程数据流Data Flowpayload 是怎么生成、怎么传输、怎么落盘、怎么被消费的控制流Control Flow谁发起、谁切换到 recovery、谁真正写分区一致性Consistency哪些分区必须一起升级哪些场景可以只更 bootloader / 只更 rootfs恢复策略Recovery失败后在哪里停住如何重试如何回滚只要这四个视角建立起来后面加 Secure Boot / Encryption / NVMe / A/B 只是“多一些参数与约束”不会把你打回原点。3.3 学习方法用“证据驱动”的笔记法我建议你每跑一次 OTA都固定保存下面这些“证据”这样你会越来越快设备升级前后cat /etc/nv_tegra_releaseuname -alsblkfindmnt /确认 rootfs 载体Host 侧生成命令完整参数payload 的sha256sum与文件大小使用的 BASE_BSP/TARGET_BSP 路径与版本Device 侧日志/ota_logs/目录打包失败时一定要留如果启用RESERVE_LOGStrue保留/last_ota_update_log这样做的好处你以后遇到任何升级异常不是“感觉不对”而是“有证据能定位”。3.4 学习路线建议按模块递进建议你不要一上来就把所有高级特性叠加。最稳的顺序是最小 Demo内部存储 rootfs 无 secure boot 无加密本文主流程可观测性增强保留成功日志 故障注入一次NVMe rootfs--external-device与-S数据保留nv_ota_preserve_data.sh 文件清单自定义任务链nv_ota_customer.conf的OTA_TASKSUEFI Secure Boot--uefi-keys/UUID/overlay 包Disk EncryptionROOTFS_ENC1、EKS/EKB 一致性每加一个模块你只需要回答一个问题它引入了哪些新输入参数/文件/密钥/UUID它改变了流程中的哪一步生成 payload / 触发 / recovery 任务链 / 分区写入4. 全局流程框架图控制流 数据流下面这张图建议你反复看。它把“demo”和“产品化”放在同一框架里┌────────────────────────────┐ │ Host │ │ (build / generate payload)│ └──────────────┬─────────────┘ │ │ 生成 │ - ota_payload_package.tar.gz │ - (可选) UEFI overlay 等 ▼ ┌───────────────────────────┐ │ Artifacts/Repo │ │ (文件落地位置/制品库) │ └──────────────┬────────────┘ │ demo: scp/USB │ product: OTA Server/CDN ▼ ┌────────────────────────────────────┐ │ Device │ │ OTA client/service你自己实现 │ │ - 下载 tools/payload │ │ - 校验hash/sign/encrypt │ │ - 调用 nv_ota_start.sh │ └──────────────┬─────────────────────┘ │ │ 触发后重启 ▼ ┌────────────────────────────────────┐ │ Recovery Kernel │ │ - nv_ota_run_tasks.sh 任务链 │ │ - 写分区/切换/验证/失败处理 │ │ - 产生 /ota_logs/ │ └──────────────┬─────────────────────┘ │ │ 完成后重启 ▼ ┌────────────────────────────────────┐ │ Updated System │ │ - 版本验证 │ │ - 上报结果成功/失败/日志 │ └────────────────────────────────────┘这张图里你要记住两句话真正写分区的工作是在 Recovery Kernel 里完成的。服务器端与 OTA client 是“产品化的必需品”但 Demo 可以先不用。5. 一张流程图把整个 demo 拆成 8 个动作Host 端 (1) 准备 BASE_BSP / TARGET_BSP (2) TARGET_BSP: 解压 sample rootfs apply_binaries (3) 解压 ota_tools_rel_aarch64.tbz2 到 TARGET_BSP 上一级 (4) 运行 l4t_generate_ota_package.sh 生成 ota_payload_package.tar.gz 传输 (5) 把 ota_tools_rel_aarch64.tbz2 ota_payload_package.tar.gz 拷到设备 Device 端 (6) 解压 ota_tools 到 WORKDIR (7) 把 payload 放到 /ota/执行 nv_ota_start.sh (8) reboot → recovery kernel 自动执行 OTA → 回到系统验证4. Host 端生成 OTA payload一步一步照着做下面我用一个“最接近官方文档的写法”来讲。你可以把路径换成你自己的目录。4.1 准备目录与变量假设你的工作目录结构像这样~/ota_demo/ ├── base_R36.4.3/Linux_for_Tegra/ ├── target_R36.4.4/Linux_for_Tegra/ ├── ota_tools_R36.4.4_aarch64.tbz2 └── (样例 rootfs tbz2)设置环境变量exportBASE_BSP~/ota_demo/base_R36.4.3/Linux_for_TegraexportTARGET_BSP~/ota_demo/target_R36.4.4/Linux_for_Tegra注意BASE_BSP/TARGET_BSP要指向Linux_for_Tegra目录本身。4.2 在 TARGET_BSP 准备 rootfssample rootfs apply_binaries进入目标 BSPcd$TARGET_BSP# 进入 rootfs 目录把 sample rootfs 解压进去cdrootfssudotarxpf../../Tegra_Linux_Sample-Root-Filesystem_rel_aarch64.tbz2cd..# 把 NVIDIA 的二进制组件合入 rootfssudo./apply_binaries.sh如果你已经用自己的 rootfs定制过替换了 sample rootfs也可以但初学 demo 强烈建议先用 sample rootfs 跑通。4.3 解压 OTA tools让脚本出现在tools/ota_tools/...这是你现在最可能缺的步骤。在Linux_for_Tegra的上一级执行解压cd${TARGET_BSP}/..# tbz2 常见写法-j 表示 bzip2sudotarxjpf ota_tools_rel_aarch64.tbz2解压后你应该能看到ls${TARGET_BSP}/tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh如果这一步仍然找不到通常原因只有两类你解压的位置不对没有解压到${TARGET_BSP}/..你下载的ota_tools_rel_aarch64.tbz2与目标 BSP 版本不匹配4.4 选择正确的target_boardDevKit 最常用官方把不同设备映射到target_board名称也就是你平时flash.sh用的那个板级名。常见 Orin 系列Jetson AGX Orin DevKitjetson-agx-orin-devkitJetson AGX Orin Industrialjetson-agx-orin-devkit-industrialJetson Orin NX / Orin Nano很多情况下都用jetson-orin-nano-devkit你可以通过以下方式辅助确认# Linux_for_Tegra 下有大量 *.confls*.conf# 你也可以看你曾经 flash 时用的是哪一个# 比如 jetson-orin-nano-devkit.conf / jetson-orin-nano-devkit-nvme.conf4.5 运行l4t_generate_ota_package.sh生成 payload进入目标 BSP 根目录cd$TARGET_BSP生成命令结构是sudo-E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh\[options]target_boardbsp_versionbsp_version是“base BSP 的大版本线”格式像R36-4、R35-5这种。如果你的 base 设备当前是 36.4.x那么这里一般用R36-4。最小 demo内部存储 rootfs无加密、无 secure bootsudo-E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh\jetson-orin-nano-devkit R36-4说明这个脚本默认会基于Linux_for_Tegra/rootfs/生成 rootfs 镜像再把需要更新的分区镜像都打进 payload。生成结果在哪里通常会生成在${TARGET_BSP}/bootloader/target_board/ota_payload_package.tar.gz你可以这样确认ls-lh${TARGET_BSP}/bootloader/jetson-orin-nano-devkit/ota_payload_package.tar.gz4.6可选如果你的 rootfs 在 NVMe添加--external-device与-S如果你是 NVMe 启动/根文件系统在 NVMe通常需要类似sudo-E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh\--external-device nvme0n1 -Srootfs_size\jetson-orin-nano-devkit R36-4--external-device nvme0n1表示外置设备-S用于指定 rootfs 分区大小具体取值与你的分区规划有关初学 demo你可以先用“内部存储 rootfs”的设备跑通一次再挑战 NVMe 场景。5. 把文件拷到 DevKitdemo 不需要正式服务器你需要拷两个文件到板子上ota_tools_rel_aarch64.tbz2ota_payload_package.tar.gz最常用做法用scp# Host 上执行scpota_tools_R36.4.4_aarch64.tbz2 ubuntuJETSON_IP:~/scp${TARGET_BSP}/bootloader/jetson-orin-nano-devkit/ota_payload_package.tar.gz ubuntuJETSON_IP:~/也可以用 U 盘或局域网临时 HTTP。再强调一次跑 demo 不需要服务器。服务器端是“产品化 OTA”规模化分发、鉴权、安全、灰度才必须的。6. 设备侧触发 OTA最关键的 10 分钟6.1 安装依赖并检查空间在 Jetson 上sudoapt-getupdatesudoapt-getinstall-y efibootmgr nvme-clidf-h /确认/有足够空闲空间建议 7GB。6.2 准备 WORKDIR 并解压 OTA toolsmkdir-p ~/ota_workexportWORKDIR~/ota_workcd$WORKDIRsudotarxjpf ~/ota_tools_rel_aarch64.tbz2解压后你应该能看到ls$WORKDIR/Linux_for_Tegra/tools/ota_tools/version_upgrade/nv_ota_start.sh6.3 准备 /ota/ 并放入 payloadsudomkdir-p /otasudocp~/ota_payload_package.tar.gz /ota/如果你启用了 UEFI secure boot并且生成了 overlay 包也需要一并放进去# 仅当你确实启用 UEFI secure boot 时sudocp~/uefi_secureboot_overlay_multi_specs.tar.gz /ota/6.4 执行 nv_ota_start.sh 并 rebootcd$WORKDIR/Linux_for_Tegra/tools/ota_tools/version_upgrade# 触发 OTA 预处理sudo./nv_ota_start.sh /ota/ota_payload_package.tar.gz# 没报错就重启sudoreboot重启后通常现象设备会进入 recovery kernel 环境屏幕可能黑一段时间/或显示不同的启动过程这取决于平台与配置更新完成后自动重启回系统6.5 验证升级是否成功回到系统后做三个验证查看 L4T 版本cat/etc/nv_tegra_release查看内核版本uname-a如果你启用了 A/B可以看 slot 信息不同版本工具略有差异# 可能存在nvbootctrl dump-slots-info||truenvbootctrl get-current-slot||true7. 你最可能遇到的 12 个问题以及一眼能懂的处理方式Q1Host 上找不到 l4t_generate_ota_package.sh原因 99%没解压 ota_tools 包到正确位置。你需要在${TARGET_BSP}/..执行cd${TARGET_BSP}/..sudotarxjpf ota_tools_rel_aarch64.tbz2然后脚本才会出现在${TARGET_BSP}/tools/ota_tools/version_upgrade/l4t_generate_ota_package.shQ2生成 payload 很慢像“卡住”l4t_generate_ota_package.sh默认会生成多 spec 的 payload覆盖多个设备/配置这会显著拉长时间。思路先确认你只需要某个 devkit 的 spec按官方建议可以通过ota_board_specs.conf注释掉不需要的 spec 来加速Q3设备侧报空间不足/解压失败检查df -h /清理无用文件、docker 镜像、旧日志确保你把 payload 放在一个有足够空间的文件系统上Q4设备重启后进了 recovery shell 或更新失败失败日志会在/ota_logs/把日志打包出来最有效sudotarczf ota_logs.tgz /ota_logsQ5成功了但日志没了默认成功会自动删日志。如果你想保留成功日志需要在配置里打开RESERVE_LOGStrue属于 customization 话题后面会提。Q6我启用了 Secure BootOTA 后进 UEFI Shell这通常说明UEFI payload / 证书链 / overlay 包处理不完整或者 boot 配置/UUID 不匹配建议你先用“不启用 secure boot”的最小 demo 跑通再逐层加 secure boot。Q7NVMe rootfs 升级不对/升级后找不到 rootfs最常见原因Host 端生成 payload 时没有带--external-device nvme0n1与-S先跑通 internal rootfs再来 NVMe会更顺。Q8想保留用户数据怎么办官方提供了“APP 分区文件备份/恢复”脚本nv_ota_preserve_data.shota_backup_files_list.txt你可以把要保留的路径列进去相对根目录的写法。Q9我用的是自定义 rootfs不是 sample rootfs两条路简单路先把你的 rootfs 直接放到Linux_for_Tegra/rootfs/再生成稍复杂用-o指定 rootfs updater用-f指定你的 rootfs image初学者建议先用 sample rootfs 把链路跑通。Q10我只想更新 bootloader 或只想更新 rootfs脚本支持-b只更新 bootloader通常在无布局变化时有意义-r只更新 rootfs同上Q11我想做断电恢复/重试OTA 在 recovery kernel 中执行。如果断电重启系统可能会回到 recovery kernel 并继续。重试次数由OTA_MAX_RETRY_COUNT控制默认 0。Q12我到底需不需要服务器端跑 demo不需要拷贝文件即可产品化需要版本管理、鉴权、安全策略、灰度、监控8. 从“demo”到“产品 OTA”你还缺哪些模块官方文档把边界说得很清楚NVIDIA 提供“更新工具链”但完整的 OTA 解决方案需要你补齐。你至少要补OTA server存放 payload 与 toolsOTA client/service设备端守护进程周期性检查更新下载 payload/tools校验签名/哈希/版本白名单触发nv_ota_start.sh上报结果成功/失败原因/日志安全策略payload 签名/加密server 鉴权mTLS/Token防回滚策略至少要版本 gate发布策略灰度、分批、回滚如果你希望尽快把“服务器端 client”做起来可以参考行业里常见的三类做法设备管理平台型例如把 payload 上传到某些设备管理平台由平台分发OTA 专业平台型例如集成专业 OTA 平台自研极简型Nginx manifest systemd service9. 真实世界的“全网实例”别人是怎么把官方 OTA 做成可用方案的下面这些内容的共同点是payload 仍然是 NVIDIA 的ota_payload_package.tar.gz设备侧触发仍然依赖nv_ota_start.sh差异只在“服务器与客户端”如何封装、如何安全分发与监控你可以把它们当作“从 demo 走向产品”的参考路线Allxon/Seeed 的 Jetson OTA 指南强调把 OTA payload 上传到管理平台然后平台下发到设备触发更新。Memfault 的 Jetson OTA 实践重点在把 Jetson Linux 镜像更新接入到 Memfault 的 OTA 工作流解决远程批量更新与可观测性。Mender 社区对 Jetson 的集成讨论更偏工程集成rootfs updater、golden image、与现有 OTA 框架结合。这些实例不等同于“官方 demo”但很适合你理解NVIDIA 给的是底层更新机制生态里在其上叠加了 server/client/安全/观测。10. 一页纸 Checklist照着做不容易漏Host 端准备 BASE_BSP 与 TARGET_BSP两份 Linux_for_TegraTARGET_BSProotfs 解压 apply_binaries.sh下载并解压ota_tools_rel_aarch64.tbz2到${TARGET_BSP}/..确认脚本存在tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh选择target_boardDevKit 常见jetson-orin-nano-devkit等运行脚本生成 payload找到 payload 路径${TARGET_BSP}/bootloader/target_board/ota_payload_package.tar.gzDevice 端df -h /确认空间建议 7GB安装efibootmgr、nvme-cli准备WORKDIR解压ota_tools_rel_aarch64.tbz2准备/ota/放入ota_payload_package.tar.gz执行nv_ota_start.shreboot等待更新完成验证cat /etc/nv_tegra_release11. 结语你跑通 demo 之后下一步最该做什么跑通一次官方 demo 的意义是你确认了payload 生成链路是 OK 的Host 工具链 BSP 制品你确认了设备进入 recovery kernel 更新分区这条链路是 OK 的执行环境与日志路径你拿到了“失败/成功”的证据入口后续才谈得上可靠性与产品化为了让你的学习更系统我建议你在跑通之后做一次“结构化复盘”11.1 用一个“状态机”描述设备侧 OTA非常推荐把你的 OTA client哪怕现在只是手动操作抽象为下面 7 个状态IDLE ↓ (发现更新) CHECK_COMPAT (机型/版本/存储形态/白名单) ↓ DOWNLOAD (tools payload) ↓ VERIFY (hash/signature/decrypt) ↓ STAGE (放到 /ota/准备 WORKDIR) ↓ TRIGGER (nv_ota_start.sh) ↓ (reboot) RECOVERY_UPDATE (recovery kernel 中执行) ↓ REPORT (成功/失败/日志上传)这样做的好处是你以后接入 server、做灰度、做失败重试都只是“给状态机加事件与策略”。你排障时也更容易定位卡在哪个状态哪一步输入不符合11.2 画一张“脚本调用链图”帮助你快速定位问题当你看到nv_ota_start.sh时不要把它当成“一个脚本”。它更像是“触发器”。你可以用下面这张简化调用链来理解Host: l4t_generate_ota_package.sh └─ 产出 ota_payload_package.tar.gz Device (正常系统): nv_ota_start.sh ├─ 解包/准备/校验按配置 └─ 触发进入 recovery kernel Device (recovery kernel): nv_ota_run_tasks.sh ├─ 任务1必要的环境/挂载/检查 ├─ 任务2分区写入/切换 ├─ 任务3验证与清理 └─ 失败写入 /ota_logs/ 并停留/重试当你遇到问题时先回答一个问题问题发生在“正常系统”阶段还是“recovery kernel”阶段如果是后者直接抓/ota_logs/往往比你在正常系统里猜更有效。11.3 下一步最推荐的学习任务按优先级把成功日志也保留下来便于对照做一次“可控故障注入”中途重启/断电观察是否能继续/如何失败引入最简 server例如 Nginx 静态文件 manifestjson hash 校验再逐步叠加NVMe → 数据保留 → 自定义任务链 → Secure Boot → Encryption你会发现一旦你把“框架”搭好了后面的高级特性都是“在框架内加约束”。附录 A最常用命令速查# Host解压 ota_tools 到 TARGET_BSP 的上一级cd${TARGET_BSP}/..sudotarxjpf ota_tools_rel_aarch64.tbz2# Host生成 payloadcd${TARGET_BSP}sudo-E ./tools/ota_tools/version_upgrade/l4t_generate_ota_package.sh\jetson-orin-nano-devkit R36-4# Device准备并触发sudoapt-getinstall-y efibootmgr nvme-climkdir-p ~/ota_workexportWORKDIR~/ota_workcd$WORKDIRsudotarxjpf ~/ota_tools_rel_aarch64.tbz2sudomkdir-p /otasudocp~/ota_payload_package.tar.gz /ota/cd$WORKDIR/Linux_for_Tegra/tools/ota_tools/version_upgradesudo./nv_ota_start.sh /ota/ota_payload_package.tar.gzsudoreboot# 验证cat/etc/nv_tegra_releaseuname-aB站博主个人介绍博主书籍-京东购买链接*Yocto项目实战教程加博主微信进技术交流群jerrydev