Repository navigation
fix(httpboot): validate ELF and loader architectures before handoff - #217
Conversation
There was a problem hiding this comment.
本 PR 修复 axloader v5 的多架构 EFI 入口选择与 HTTP 响应体读取,并让发现页创建板卡时携带设备架构、编辑器识别既有串口身份别名。改动主要影响 HTTP Boot 交接和 board editor;没有改变 REST/API 数据模型,PXE、U-Boot 及既有串口身份配置契约看起来保持不变。历史 PR 搜索找到 #194、#198、#206,分别是相关启动载荷、v5 和自动串口绑定的前序工作,没有发现重复的同类待审改动。
验证:固定 head 47a103d 的较早 CI run 41818170621 全部通过,包括 fmt、clippy、build、Rust 单测、Web UI 单测/build、e2e 和 publish dry-run。较新的 run 41830890755 失败时 annotation 明确为 GitHub runner 写入自身日志时 No space left on device,发生在 Unit test 步骤运行期间;这是 runner 环境故障而非 PR 代码失败。git diff --check 和 reviewer clone/head 校验通过;本地 cargo fmt --check 与 pnpm --dir ostool-server/webui test 因当前环境没有 cargo/pnpm 而无法运行。当前 head 没有既有 review、inline review comments 或 PR issue comments,因此没有历史审查意见需要追踪。
仍有一个阻塞问题,见下方 inline comment:不支持架构的拒绝发生在串口交接之后,可能使活动会话停留在没有 boot status 的半完成状态。
Powered by gpt-6-luna
| let epoch = observed.boot_epoch.as_str(); | ||
| let observed_boot_id = observed.boot.as_ref().map(|boot| boot.boot_id.as_str()); | ||
| let manifest = v5_boot_manifest(command); | ||
| let manifest = v5_boot_manifest(command)?; |
There was a problem hiding this comment.
对 AArch64/Other 的 bail! 目前是在 push_boot() 中才触发,但 reconcile() 已先完成 /serial/continue 和 serial_runtime.confirm()。随后错误只被记录为 handoff warning,未将 runtime/session 标记失败;SerialGrant 仅异步撤销设备 binding,因此不支持架构会先进入物理串口交接,再被本地拒绝并可能留下半完成的活动会话。请把 manifest 架构校验移到这次串口交接之前(或在发布 boot command 时拒绝),并覆盖该失败路径。
47a103d to
ea44de5
Compare
There was a problem hiding this comment.
本 PR 修复了 axloader v5 的 HTTP Boot ELF 入口选择、完整读取设备响应体后再推进启动事务,并在串口交接前拒绝不支持的架构;Web UI 现在传递发现设备架构,并能按 USB ID/by-path/序列号别名显示与保留既有串口选择。影响范围主要是 ostool-server 的 HTTP Boot 交接与 board editor;没有改变 REST 模型或已保存的配置字段,U-Boot/PXE 等流程看起来未受影响。
我检查了先前针对 device.rs 的 review comment:它指出不支持架构是在 /serial/continue 后才拒绝,这个问题合理;当前 head 已在串口绑定和交接前构造并校验 BootRequest,失败时标记运行时失败,且新增测试覆盖 AArch64/Other 的无交接路径。PR issue comments 为空。相似的已合并 PR #215(稳定串口身份)和 #206(axloader v6 自动串口绑定)属于相关前序工作,没有发现重复的待审改动。
验证:git diff --check origin/main...HEAD 通过;本地无法运行 cargo fmt --check、pnpm UI tests/build,因为环境没有安装 cargo 和 pnpm。针对精确 head ea44de5 的 GitHub check 有一项已通过,另一项仍在运行,未见失败的 check。未发现未解决的代码阻塞问题;LoongArch 等其他架构的实体启动验证范围仍有限,且第二项 CI 尚未完成。
Powered by gpt-6-luna
ea44de5 to
7497c50
Compare
ZR233
left a comment
There was a problem hiding this comment.
Request changes:HTTP Boot 架构信息应以 ELF 与 axloader 实际状态为准
PR #217 修复了多架构 EFI 入口、串口交接前拒绝不支持架构、HTTP 响应体读取以及串口身份展示等问题,这些改动方向正确。但目前“发现设备后将 arch 写入板卡 boot_arch,再检查两者一致”的设计仍然维持了一份不必要的持久化架构副本,建议在本 PR 中一并调整,避免多架构功能建立在容易失配的配置上。
当前问题(已核对代码)
- axloader 已上报架构,不需要用户再配置一次。
httpboot-protocol::LoaderAnnouncement.arch和LoaderDeviceStatus.arch已存在,ostool-server/src/loader.rs已在发现/状态核对后保存架构;x86_64 和 LoongArch 的 axloader 实现也已填入架构。PR 目前只在Boards.tsx、BoardEditor.tsx将这个值复制到持久化UefiHttpProfile.boot_arch,属于重复状态。 - CLI 仍信任板卡配置,而不是内核文件。
ostool/src/run/httpboot_board.rs使用profile.boot_arch.unwrap_or(X86_64)生成X-HttpBoot-Arch;但ostool/src/artifact/runtime.rs已使用object::File检测 ELF 架构并保存到运行时状态。配置缺省为 x86_64 并不意味着设备/内核就是 x86_64。 - 架构不匹配时静默跳过启动。
ostool-server/src/device.rs的if command.arch != observed.arch { return Ok(()); }会让会话无明确失败原因地不再推进。应在串口绑定/continue 前明确报错并走现有会话失败、释放流程。 - OTA 也依赖同一个配置。
ostool-server/src/api/ota.rs::queue_job以boot_arch == x86_64 || None作为升级许可条件;离线或配置过期时会误判。应区分镜像的真实目标架构与设备实际上报架构。
建议修改(明确数据所有权,不再叠兜底)
- 移除 HTTP Boot 的手工
boot_arch配置。UefiHttpProfile不再持久化架构,Board Editor 删除架构下拉框、URL 传参/同步/一致性校验;发现页或详情页继续只读展示当前 axloader 上报的arch。设备未上线时显示“未知”,不要默认为 x86_64。旧板卡 TOML 中已有boot_arch需有明确的一次性兼容读取/迁移方案(当前deny_unknown_fields,不可直接删字段使已有配置加载失败),最终不保留长期双来源。 - 内核架构由 ELF 确定。
ostoolCLI 利用已有 ELF 解析结果生成上传的X-HttpBoot-Arch,不再通过boot-profile获取板卡架构;可以暂时保留现有 HTTP header /SessionBootCommand.arch/DeviceBootJob.arch的协议形状,减少无关改动。上传端/服务端在合理边界校验声明与 ELFe_machine一致(无法识别或不支持则明确失败)。 - 设备架构由 axloader 确定。 server 在发现/状态核对后使用本次有效
observed.arch与内核架构匹配;不匹配则返回明确错误、标记本次启动失败并终止会话,不允许进入串口绑定/continue 或下发内核。EFI 入口选择继续按实际目标架构的既有契约(x86_64:__x86_64_efi_pe_entry;LoongArch64/RISC-V64:efi_pe_entry),不使用持久化配置决定入口。设备离线时允许先准备会话和内核,但不能凭默认 x86_64 认定校验通过;设备上线后再校验。 - 同步修正 OTA 判断。 在上传/排队或实际下发的适当阶段识别并校验 EFI PE Machine;当前若仅支持 x86_64 OTA,就明确限制为 x86_64 镜像,并在设备实际在线时核对
observed.arch,不再以boot_arch == None等同 x86_64。离线任务可保留排队,但必须在下发前完成设备匹配校验;不一致时明确报告/失败,不发送错误镜像。 - 测试与文档:覆盖 x86_64、RISC-V64、LoongArch64 的 ELF→上传→清单架构链路;配置缺失/旧字段、设备离线后上线、内核与设备不一致的显式失败且无串口交接、OTA 架构不符的拒绝;更新
docs/axloader-network-control.md、docs/api.md、docs/admin-ui.md和相关 CLI/UI 测试。
需要保留的区别:DeviceBootJob.arch 是启动协议的必要字段,应保留;删除的是板卡配置里人工维护的 boot_arch。如果未来 CI 在设备离线时必须按架构分配板卡,应使用现有 board_type/tags 或单独的 调度期望属性,不能拿它覆盖 axloader 实际架构。
这样形成明确的单一来源:内核架构来自 ELF,设备架构来自 axloader,server 只负责校验和下发。请按这一方向调整后再请求复审。
There was a problem hiding this comment.
本 PR 修复了 axloader v5 的多架构 EFI 入口选择和 HTTP 响应体读取,并让发现页将设备架构带入板卡编辑器、补充既有串口身份别名识别。主要影响 HTTP Boot 交接与 board editor;没有改变 REST/API 数据模型或已保存字段,PXE/U-Boot 和其它串口流程看起来未受影响。
验证与 CI: 已通过 helper 的 7 项测试,git diff --check origin/main...HEAD、精确 head/clone 校验通过。本地无法运行 cargo fmt --check、clippy、Rust tests 或 pnpm UI tests/build,因为环境缺少 cargo 和 pnpm。同一 head 的 GitHub Actions 有两次结果:run 41841840119 的完整流程(fmt、clippy、build、Rust tests、UI tests/build、e2e、publish dry-run)全部通过;run 41841847816 在 Unit test 步骤以 exit 101 失败,annotation 未给出测试级原因。通过的结果降低了该失败是稳定回归的可能性,但仍无法据现有日志判定失败原因,且本地无法复现。
先前审查意见: 先前针对 device.rs 的意见指出不支持架构在 /serial/continue 后才被拒绝,该问题合理;当前 BootRequest::new() 已在绑定/continue 前校验支持的架构,失败时标记 runtime,新增测试覆盖 AArch64/Other,因此该意见已解决。PR issue comments 为空。另一份同 head 审查提出架构来源与实际内核可能不一致;我确认 CLI 将持久化 boot_arch 用作 X-HttpBoot-Arch,上传端未校验 ELF e_machine,详见下方阻塞 inline comment。相似的既有工作包括 #198、#206;搜索未发现重复的待审 PR。
仍有一个阻塞问题:入口预检只验证声明架构,不验证内核 ELF 架构。声明与 ELF 不一致时仍会先串口 continue,后续设备事务才会发现不匹配,而当前错误路径只记录 warning,没有将 session/runtime 标为失败。请按 inline comment 在串口绑定前校验 ELF、声明与设备架构一致,并显式失败。
另有一项非阻塞文档遗漏:docs/api.md:694,1072、README.md:336 和 README.en.md:360 仍说入口固定为 __x86_64_efi_pe_entry,与本 PR 对 LoongArch64/RISC-V64 使用 efi_pe_entry 的实现不符;请同步更新。
Powered by gpt-6-luna
|
|
||
| impl<'a> BootRequest<'a> { | ||
| fn new(command: &'a SessionBootCommand) -> anyhow::Result<Self> { | ||
| let entry_symbol = match command.arch { |
There was a problem hiding this comment.
command.arch 在这里直接决定 manifest 入口,但当前它来自持久化 boot_arch / X-HttpBoot-Arch,而上传端没有核对 kernel ELF 的 e_machine。若配置与实际 ELF 架构不一致,BootRequest::new() 仍会通过,服务端随后先执行串口 continue 并上传镜像,直到后续设备事务校验才发现不匹配;该错误只被记录为 handoff warning,不会把 session/runtime 标记为失败。请在串口绑定前校验 ELF 架构与声明及设备架构一致,并将不匹配作为显式失败处理。
7497c50 to
bfce43c
Compare
There was a problem hiding this comment.
本 PR 将 HTTP Boot 的内核架构改为从 ELF 推导,并在上传与串口交接前核验 ELF、声明和 axloader 实际架构;同时选择多架构 EFI 入口、限制 OTA 镜像为 x86_64 PE32+,并移除持久化 boot_arch(旧 TOML 兼容读取后迁移)。影响 HTTP Boot 启动、板卡 boot profile/API 和 OTA;U-Boot、PXE 与既有串口身份配置未见受影响。boot_arch 不再由 profile 返回,旧 CLI/服务端需配套升级。
验证:当前精确 head 的两个 GitHub Actions check 均已完成并通过;review helper 的 7 项测试和 git diff --check origin/main...HEAD 通过。本地因未安装 cargo 和 pnpm,无法运行 Rust fmt/clippy/tests 或 Web UI tests/build;未进行 RISC-V/LoongArch 实体板验证。未见当前 head 上由 PR 引起的失败 CI。
此前关于架构拒绝发生在 /serial/continue 之后的意见合理,现已通过在绑定/continue 前校验设备架构和 ELF 并使 session 失败来修复;关于 boot_arch 重复来源、ELF 校验及文档入口说明的意见也已落实。相关前序工作包括 #198 和 #206,未发现重复的待审改动。剩余建议见下方 inline comment:预检错误目前对 CLI 只呈现为通用的 WebSocket/session closed,而未传递具体架构不匹配原因。
Powered by gpt-6-luna
| let request = match preflight { | ||
| Ok(request) => request, | ||
| Err(error) => { | ||
| session.serial_runtime.fail(format!("{error:#}")); |
There was a problem hiding this comment.
架构预检失败时这里仅调用 serial_runtime.fail(),但 CLI 的 monitor_loader_status() 只读取 /loader-status;这个分支发生在任何 update_loader_status() 之前,之后 WebSocket 关闭只会让 CLI 得到通用的 session/WebSocket closed 错误。请把具体的 ELF/device 架构不匹配发布到 loader status(或让 CLI 监控 serial runtime error),并测试客户端能显示实际失败原因。
bfce43c to
f4db43a
Compare
There was a problem hiding this comment.
审查结论
本 PR 将 HTTP Boot 内核架构改为从 ELF 推导,并在上传和串口交接前核验 ELF、声明及 axloader 实际架构;按架构选择 EFI 入口;移除板卡 profile 中的持久化 boot_arch 并兼容迁移旧 TOML;将 OTA 限定为 x86_64 PE32+ EFI;同时修复设备 HTTP 响应体未读完即继续交接,以及串口身份别名展示问题。
影响集中在 HTTP Boot、OTA 及其板卡配置/API/CLI/UI 契约。旧 boot_arch 配置会迁移,profile 不再返回该字段;部署时 CLI 与 server 需配套升级。未发现对 PXE、U-Boot 启动或其它串口配置流程的回归。
验证: 精确 head f4db43a8 的两个 GitHub Actions check 均已完成并通过;git diff --check 和 review helper 的 7 项测试通过。本地无法运行 Rust fmt/clippy/tests 或 Web UI tests/build:环境未安装 cargo 和 pnpm。当前没有因本 PR 失败的 CI。没有进行 RISC-V64/LoongArch64 实体板验证。
既有意见: 先前关于不支持架构在串口交接后才拒绝、内核架构仅由 boot_arch 声明,以及 CLI 无法看到具体预检失败原因的意见均合理;当前版本已在串口绑定前核验 ELF/声明/设备架构,发布 boot_preflight_failed 和具体错误,并覆盖 CLI 通过 WebSocket/状态轮询接收原因的测试。移除重复架构配置及相关文档修订也已落实。相关已合并工作包括 #198(axloader HTTP 控制/OTA)和 #206(自动串口绑定);未找到其它开放的同类 PR。
未发现当前 head 仍成立的阻塞问题。剩余验证局限是本地 Rust/Web 工具不可用及未进行多架构实体板启动测试;CI 已通过。
Powered by gpt-6-luna
ZR233
left a comment
There was a problem hiding this comment.
Request changes:OTA 的镜像兼容性应由 axloader 判定,server 不应硬编码 CPU 架构
基于当前 head f4db43a8 复核。此前关于 HTTP Boot 的 boot_arch 去重、ELF 架构来源及失败信息传递已经落实;这次要求修改的是 axloader 自身 OTA 的职责边界,不要撤销普通 HTTP Boot 的内核预检。
现在 OTA 的 server 代码重复了设备能力判断:
ostool-server/src/ota.rs::validate_efi_image()将 EFIMachine固定为 AMD640x8664,上传镜像时即拒绝其他架构;push_ota_image()、旧下载路径又重复校验。ota.rs::reject_device_architecture()、OtaStore::decide(..., arch)、device.rs::reconcile()会根据observed.arch != X86_64将已排队任务直接标为永久 Failed。api/ota.rs::{queue_job,download_image}及旧api/router.rspoll 路径有相同白名单;BoardEditor.tsx使用arch === "x86_64"决定是否允许 OTA。- 但 axloader 已有校验:x86_64
ota/disk.rs::verify_efi_image()校验 EFI PE 并在finish_update()通过 UEFILoadImage验证;LoongArch64axstd_loader/ota.rs::stage_image()通过LoadedPe::validate()检查该架构 PE 镜像。设备端已可通过 HTTP 拒绝不兼容镜像。server 的固定 AMD64 规则反而阻断多架构 OTA,将来每新增一种 axloader 架构都要改 server。
目标与所有权(定为实施约束)
OTA 镜像视为对 server 不透明的字节对象:server 负责限额、保存、SHA-256、板卡绑定、任务排队、租约、传输、超时/重试、A/B 确认流程与错误展示;axloader 独占 PE/COFF 格式、Machine、EFI Subsystem、加载/内存平台限制、固件可兼容性及 A/B 试运行判断。server 可展示设备上报的 arch,但不得用它决定 OTA 镜像是否合法,不增加 server 的 PE 解析器/架构映射/白名单。
注意:普通内核 HTTP Boot 的 elf_arch、SessionBootCommand.arch、DeviceBootJob.arch、串口交接前内核与设备架构核对属于另一条启动链路,保持本 PR 的修复不变。
明确修改点(不再增设中间适配层)
ostool-server/src/ota.rs:移除validate_efi_image()的固定 AMD64 格式/架构逻辑,并从write_image()删除对它的调用;去掉reject_device_architecture()、reject_incompatible_device()、Decision::Reject中仅为架构构造的路径,以及decide(..., arch)的额外参数。保留并复用现有镜像长度上限、SHA-256、磁盘读写/摘要校验、设备试运行与事务状态机。不要新增一个支持架构列表。ostool-server/src/api/ota.rs:upload_image只验证请求合法性、大小和存储,不解析 PE Machine;queue_job只验证 HTTP Boot 板卡、绑定 MAC、租约及 OTA 作业约束;download_image保留板卡/MAC/在线身份与冲突检查、任务许可及文件完整性校验,但删除 x86_64 条件和 PE 架构校验。ostool-server/src/device.rs:reconcile不因架构不同拒绝 OTA;push_ota_image仅确认本地镜像大小/摘要后 PUT 到当前设备/api/v1/ota/image,以设备响应判断是否被接受。保留X-Boot-Epoch、X-Image-Sha256、X-Update-Id、X-Update-Source、Content-Length和完整读取响应体等现有协议。- 旧 poll OTA:
api/router.rs的 poll 指派及api/ota.rs::download_image删除同一 x86 白名单;保留注册代次/MAC/租约/任务绑定。镜像有效性由实际下载它的旧 axloader 验证并使用既有ota-status回报;如果某旧协议固件缺失设备端校验,应按可验证的协议能力决定是否提供 OTA,而不是根据 CPU 架构臆测。 - UI:
BoardEditor.tsx去掉canUpdate={!boundLoader?.online || boundLoader.arch === "x86_64"};BoardOta不用 CPU 架构控制按钮。在线时可根据既有LoaderDeviceStatus.ota != None/ 实际能力提示“OTA 不可用”,离线仍允许排队;显示真实设备失败原因。 - 文档与测试:同步更改中英文 README、
docs/api.md、docs/admin-ui.md、docs/axloader-network-control.md,移除“OTA 只支持 x86_64、server 解析 EFI Machine”的陈旧契约。
固定 HTTP 错误契约(axloader → server)
复用现有 PUT /api/v1/ota/image,不新增专用架构检查端点,不要求服务器知道设备支持哪些 Machine。保持原有 header 与成功返回语义。
- 202 Accepted:镜像摘要、格式/架构、设备可加载性及暂存已通过,进入现有 A/B 试运行流程;不代表升级最终成功,成功只能在新槽实际运行、确认且摘要匹配后登记。
- 400 Bad Request:请求本身不合法(缺少/错误头、参数),server 将本次作业置为 Failed、原样记录设备错误。
- 413 Payload Too Large:超出设备限额,本次作业 Failed,不再重复发送相同镜像。
- 422 Unprocessable Content:摘要错误、PE 格式/架构/入口或平台兼容性验证失败,本次作业 Failed,不重试相同镜像。设备不得提交活动槽或重启到无效镜像。
- 409 Conflict:OTA trial、设备忙、状态/epoch 冲突;先刷新实际设备状态/代次,视条件等待再次尝试,不把它当作镜像架构失败;避免紧密重试。
- 503 Service Unavailable:设备当前没有 OTA 存储/能力;保持可见的等待/不可用原因,不应因架构或次数直接判定镜像格式错误,不持续重复推送。
- 网络中断、超时、5xx:现有有限次数重试和失败记录;在结果不确定时先核对设备 OTA 状态/更新 ID,避免已暂存却重复下发。
建议统一设备错误体(兼容已有 {"error":"..."}):例如
{"error":"unsupported_image_arch","message":"EFI PE Machine is not supported by this loader"}error 是稳定机器码,message 是可直接展示的简短文本;可使用 invalid_efi_image、image_digest_mismatch、ota_state_conflict、ota_storage_failed 等码。server 依据 HTTP 状态分类处理,不按 unsupported_image_arch 枚举架构,也不解析/复制设备的 PE 校验器。 兼容旧设备 422 { }:仍按 422 确定性拒绝,在 Job.error 至少保存 HTTP 422 和设备返回体;不将其误作网络失败重试三次。
server 状态机落地约束
- 现在
push_ota_image()的所有非 202 都走record_delivery_failure(),该函数累计投递次数,最终三次 Failed。请拆分 设备已明确拒绝的确定性错误 与 传输不确定的可重试错误:可复用OtaStore::report(..., Phase::Failed, Some(error), ...)的既有合法状态转移(从 Downloading),或添加一个单一的fail_rejected_delivery(...)方法;不要让 422 继续累计三次重传。任务错误应包含 HTTP status + 设备error/message,经现有 API/SSE 直达 UI。 - 仍以现有
board_id + MAC + update_id + epoch防止串板、旧结果污染新作业;缺失ota状态时禁止盲目下发,保持等待/不可用,而非认定为架构不兼容。重复/旧代次设备报告不能覆盖终态。 - 旧 poll 下载/上报同理遵循设备端决定,不在服务器加入新的 CPU 架构分支。
设备仓库配合(rcore-os/tgoskits,保持协议一致)
设备端目前已经验证 PE Machine/格式:x86 UEFI ota/disk.rs + ota/runtime.rs,LoongArch axstd_loader/ota.rs + efi_image.rs。原则上复用这些校验,不重新造架构枚举或 server 端验证。只需补强对应 HTTP adapter 的错误回传:x86 当前 422 返回 {},LoongArch 当前把 digest 和 EFI 错误合成 image_digest_or_efi_validation_failed;建议细化成上述稳定码,失败时返回 422、保证未提交新 trial,server 保存其 error/message。这部分若需单独 TGOSKits PR,请在本 PR 描述中明确关联;server 必须能兼容旧响应体,不以设备端升级作为删除架构白名单的唯一前置条件。
必须补齐的回归测试
- 仓库/队列:任意架构 PE 镜像(含 LoongArch64 PE Machine
0x6264)可上传并排队;镜像内容缺陷由设备返回结果决定。x86_64 镜像也仍可正常升级。 - 发现与下发:非 x86_64 的真实
observed.arch可以进入同一 OTA 下发流程,旧 poll/下载路径没有硬编码的 x86 限制;MAC 冲突、错误 update_id、epoch 和缺失 OTA 能力仍被拒绝/等待。 - 设备拒绝:fake axloader 返回 422 + 机器码 / 旧版 422 +
{},作业一次变为 Failed,错误可通过 API/UI 读取,同一镜像不再重发;400/413 类似。 - 可恢复错误:409、503、超时/5xx 不被误作 PE 架构错误,不触发错误的永久失败或无节制重传;202 后继续现有试运行→确认→成功/回滚状态流程。
- 设备测试:x86 和 LoongArch 各自用正确/错误 Machine 验证设备接收/422 拒绝;设备拒绝时活动槽不变,OTA trial 不被错误开启。
验收标准:今后 axloader 扩展 RISC-V64/AArch64 或新的固件校验契约,只需要变更设备自身实现;只要保持同一 OTA HTTP/状态协议,ostool-server 和 Web UI 无须新增架构分支即可直接使用。 请按以上形状修改并补测试后重新请求复审。
f4db43a to
d2ced95
Compare
There was a problem hiding this comment.
本 PR 将 HTTP Boot 内核架构改为从 ELF 推导,并在串口交接前校验 ELF、声明与 axloader 实际架构;按架构选择 EFI 入口,同时移除持久化 boot_arch、迁移旧配置,并修复串口身份别名及启动并发/错误传递。影响 HTTP Boot 的 CLI、板卡 profile/API、配置迁移、管理 UI 与 OTA 契约;U-Boot、PXE 和既有手动串口流程未见受到影响,部署端需要配套更新 CLI 与 server。
验证: 精确 head d2ced95677aa06953add94cd38e0fa66c254ff24 的两个 GitHub Actions check 均已完成并通过;git diff --check origin/main...HEAD 通过,review helper 的 7 项测试通过。本地未能执行 Rust fmt/clippy/tests 或 pnpm UI test/build:环境缺少 cargo 和 pnpm。没有发现当前 head 上由 PR 引起的失败 CI。
既有意见: 先前关于架构错误应在串口交接前拒绝、ELF 架构应为上传依据、旧 boot_arch 兼容迁移以及 CLI 应获得具体预检错误的意见,已在当前代码中落实并有相应测试。PR issue comments 为空。相关前序工作包括已合并的 #198(axloader HTTP/OTA)和 #206(自动串口绑定);搜索未发现重复的开放 PR。
仍有一项阻塞问题:OTA 仍由 server/UI 按 CPU 架构硬编码限制,而不是由设备自身决定镜像兼容性;具体证据和修复建议见下方 inline comment。
Powered by gpt-6-luna
| } | ||
|
|
||
| fn reject_device_architecture(job: &mut Job, arch: BootArch) -> Option<String> { | ||
| if arch == BootArch::X86_64 || job.phase.is_terminal() { |
There was a problem hiding this comment.
OTA 兼容性仍由 server 在这里硬编码:除 x86_64 外,排队任务会被永久标记为失败;api/ota.rs 和 BoardEditor.tsx 也有相应的 x86-only 限制。这样即使 axloader 自身支持并能验证该 EFI 镜像,RISC-V64/LoongArch64 设备也无法收到 OTA,新增测试还将这一拒绝固定为预期行为。请保留 server 侧的大小/摘要、MAC/epoch 和任务状态校验,让设备 OTA 接口决定镜像是否可加载。
内核架构来自 ELF,设备架构来自 axloader;上传和串口交接前核对文件、声明及实际设备架构,按目标选择 EFI 入口。移除持久化 boot_arch,兼容读取并原子迁移旧 TOML,前端只读展示在线设备架构,允许离线准备会话和内核。
串行处理内核写入、命令发布和交接,优先响应电源换代及会话停止;完整读取设备 HTTP 响应体,保留串口、loader status、WebSocket 和 CLI 中的具体失败原因。
OTA 镜像对服务端是不透明字节,格式及平台兼容性由 axloader 校验。移除服务端和 UI 的 CPU 架构限制,保留大小、摘要、MAC、任务、注册代次和租约检查。确定性 HTTP 拒绝一次失败,409 延迟重试,503 等待实际状态或代次变化;响应不确定时先核对设备暂存和试运行状态,避免重复下发或错误耗尽重试。缺少 OTA 能力时保持可见等待并允许普通 HTTP Boot;终态和首条失败原因不被旧报告覆盖。
保留串口身份别名、共享序列号歧义提示及 usb_id 等既有配置;已成功加载的板卡不再重复显示历史配置隔离错误。同步中英文 README、API、管理 UI 和网络启动文档。
验证:回归在错误实现上失败、修复后通过;服务端 198 项、前端 40 项、完整浏览器 E2E 2 项通过。格式、差异、构建和 Clippy 检查完成,Clippy 仅有未修改代码的既有警告;7 份现有板卡配置加载正常。
真实 x86 QEMU 验证普通 HTTP Boot 和 OTA:错误 Machine 返回旧版 422 {},服务端保留错误且活动槽不变;正确镜像完成暂存、重启试运行及确认。axloader 宿主 35 项通过,含 LoongArch PE 校验;LoongArch 实际 HTTP OTA 未验证。
BananaPi 通过实体 U 盘 axloader、网络内核及 initramfs、ArceOS 四项启动标记,以及错误架构在交接前拒绝的实板验证。板端 ota=null,任务正确等待且不阻断普通启动,未声称完成实体 OTA 刷写。负向首轮无固件 UART,明确冷复位后重试通过,物理原因未确认。正式安装后的新版服务再次完成正向启动,CLI 退出 0,会话释放、租约 idle、配置不变。
d2ced95 to
52a17ca
Compare
There was a problem hiding this comment.
审查结论
本 PR 将 HTTP Boot 内核架构改为从 ELF 推导,上传及串口交接前核验 ELF、声明与 axloader 实际架构,并按架构选择 EFI 入口;同时移除持久化 boot_arch(旧 TOML 经验证后迁移),修复启动取消/错误传递和串口身份别名处理。OTA 镜像改为服务端不透明字节,由 axloader 验证格式与平台兼容性,服务端按 HTTP 状态调度重试与试运行确认。
影响范围: 主要涉及 HTTP Boot 的 CLI、服务器、板卡配置/API 和管理 UI,以及 OTA 状态机/UI;旧 CLI 与 server 需配套升级。未见 PXE、U-Boot 启动或既有串口身份配置契约受影响。配置迁移保留旧 boot_arch 兼容读取,并继续拒绝其他未知字段。
验证: 精确 head 52a17ca622b086c528329b872aa06995b07b4094 的两个 GitHub Actions check 均已完成并通过;review helper 的 7 项测试、clone/head 校验和 git diff --check origin/main...HEAD 通过。本地未能运行 Rust fmt/clippy/tests 或 Web UI tests/build:当前环境没有 cargo 和 pnpm。PR 描述记录了 QEMU 与 RISC-V 实机验证,本审查未独立复跑硬件测试。
先前审查意见: 不支持架构在串口交接后才拒绝、boot_arch/ELF 架构来源失配、CLI 无法得到预检失败原因,以及 OTA 由 server/UI 按 x86_64 限制等意见均有依据;当前版本分别通过交接前预检与明确错误状态、ELF 校验和架构配置迁移、WebSocket/loader 状态错误传递,以及移除 OTA 架构门控予以解决。相关前序 PR 包括 #194、#198、#206 和 #215;搜索未发现重复的开放改动。
未发现当前 head 仍成立的阻塞问题或需单独提出的建议。剩余验证限制是本审查环境无法本地运行 Cargo/pnpm 检查,且未独立进行实体板复测;CI 均通过。
Powered by gpt-6-luna
当前问题
HTTP Boot 原先依赖板卡配置中的
boot_arch决定上传声明和 EFI 入口,缺省为 x86_64,未核对内核 ELF。配置、内核与设备架构不一致时,可能静默等待,或在串口交接后才失败。OTA 的服务端和前端也存在 x86_64 限制,重复了 axloader 自身的镜像校验职责,阻止其他架构使用相同升级协议。此外,HTTP 响应读取、启动取消和错误传递存在缺口,影响故障定位;串口身份别名及历史配置隔离提示也需要修正。
修改方案
boot_arch和前端手动架构设置。在线只读展示设备架构,离线显示未知,允许先准备会话与内核。旧字段兼容读取后丢弃,合法旧 TOML 原子迁移;迁移失败保留源文件,其他未知字段仍拒绝。CLI 与服务端需配套升级。arch字段。x86_64 使用__x86_64_efi_pe_entry,RISC-V64、LoongArch64 使用efi_pe_entry。完整读取设备 HTTP 响应体后再推进事务,保留命令行、initramfs 和过期任务替换行为。usb_id、usb_path、serial_number等既有配置兼容。测试验证
验证源码与提交
52a17ca一致。cargo test -p ostool-server:198 项通过;默认忽略的 1 项真实 QEMU 测试已单独执行通过。pnpm --dir ostool-server/webui test:40 项通过;生产构建通过。cargo fmt --all -- --check、git diff --check、服务端构建通过;Clippy 完成,仅有未修改代码中的既有警告。unknown variant usb_id的配置,无需改写有效的串口身份类型。422 {},服务端保留错误且活动槽不变;正确镜像完成暂存、重启试运行和确认。axloader 宿主测试 35 项通过,包含 LoongArch PE 校验。UEFI → 实体 FAT32 U 盘 axloader → 网络下载内核及 initramfs → ArceOS,CLI 退出码为 0,BOOT_RESOURCES_PASSED、HOST_CMDLINE、HOST_INITRAMFS_PASSED和Hello, world!均出现。错误架构内核在交接前被拒绝,CLI 返回具体原因。idle,板卡配置未改动。