Commit deabdc2
burn/install: route through pod-side fastboot when power=rack (#88)
## Summary
`defib burn` and `defib install` drove the HiSilicon SPL upload from the
host even when the transport went through a rack pod's WiFi-bridged
UART, where the per-frame ACK loop (150 ms × dozens of frames per
upload) doesn't survive the round-trip latency — both commands failed at
the very first PRESTEP0 frame.
Now, when `power_controller` is a `RackController`, the CLI calls the
new `defib.recovery.rack_fastboot.run_rack_fastboot()` helper instead of
`session.run()`. The helper packages profile + SPL + agent into the
binary blob the pod's `POST /fastboot` expects, posts it, and turns the
pod's phase-by-phase JSON into a `RecoveryResult` so the rest of the CLI
(terminal mode, download_process detection, TFTP scripting) stays
unchanged.
The pod takes exclusive UART access during the upload, so the host
transport is opened only **after** fastboot returns.
## Live verification on the prototype
```
$ DEFIB_POWER_TYPE=rack DEFIB_RACK_HOST=10.216.128.69 \
defib burn -c hi3516ev300 -p tcp://10.216.128.69:9000 \
--power-cycle --break
Power: rack pod HTTP API
Pod-side fastboot in progress…
rack fastboot: spl=17408 agent=236195 spl_addr=0x4010500
ddr_addr=0x4013000 uboot_addr=0x41000000
Done! (25678ms)
```
```
$ # camera halted at the freshly-uploaded U-Boot prompt
> version
U-Boot 2016.11-g131d3f2 (May 08 2026 - 11:58:25 +0000) hi3516ev300
OpenIPC #
```
Build `g131d3f2` is **distinct from** the in-flash build
(`g6d2ed0c-dirty`, Mar 2023) — proves the burn landed in RAM and the
chip jumped to the new image rather than falling through to flash.
## Install + restore scope
- **`install`'s Phase 1** (burn-to-RAM) now uses the same fastboot path;
Phase 2 (U-Boot `tftp` + `sf write` scripting) goes over the bridge as
ordinary text commands and is already known to work —
TFTP-through-pod-NAPT was verified during the earlier manual kernel
restore at 167 KB/s.
- **`restore`** has its own shape (frame-blast started before power-on,
then power-on triggers the catch) that doesn't map cleanly onto
fastboot's all-in-one semantics. Left out of scope for this PR; can be a
follow-up if needed.
## Architecture note
The SPL-boundary detection (`HiSiliconStandard._detect_spl_size`) and
the 0xFF-run zeroing (`_zero_long_ff_runs`) stay on the host. The pod
gets ready-to-send bytes. This keeps the pod firmware minimal and
ensures the two paths (host-driven and pod-driven) stay byte-identical
for any chip we test.
## Test plan
- [ ] `uv run pytest tests/ -x -v --ignore=tests/fuzz` (**461 passed / 2
skipped**)
- [ ] `uv run ruff check src/defib/ tests/`
- [ ] `uv run mypy src/defib/cli/app.py
src/defib/recovery/rack_fastboot.py --ignore-missing-imports`
- [ ] 4 new `TestRunRackFastboot` cases cover success path, PRESTEP0
failure attribution, profile-address packing, and the `agent_payload`
override used by agent-flash.
- [ ] Regression: existing local-UART burn / install paths unchanged —
both still go through `session.run` when power controller is RouterOS /
Vectis / None.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Dmitry Ilyin <widgetii@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 004c09d commit deabdc2
3 files changed
Lines changed: 330 additions & 34 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
148 | 155 | | |
149 | 156 | | |
150 | 157 | | |
| |||
163 | 170 | | |
164 | 171 | | |
165 | 172 | | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
176 | 186 | | |
177 | 187 | | |
178 | 188 | | |
179 | 189 | | |
180 | | - | |
| 190 | + | |
181 | 191 | | |
182 | 192 | | |
183 | 193 | | |
| |||
238 | 248 | | |
239 | 249 | | |
240 | 250 | | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
247 | 287 | | |
248 | 288 | | |
249 | 289 | | |
| |||
264 | 304 | | |
265 | 305 | | |
266 | 306 | | |
267 | | - | |
| 307 | + | |
| 308 | + | |
268 | 309 | | |
| 310 | + | |
269 | 311 | | |
270 | 312 | | |
271 | 313 | | |
| |||
1954 | 1996 | | |
1955 | 1997 | | |
1956 | 1998 | | |
| 1999 | + | |
| 2000 | + | |
| 2001 | + | |
| 2002 | + | |
| 2003 | + | |
1957 | 2004 | | |
1958 | 2005 | | |
1959 | 2006 | | |
| |||
1964 | 2011 | | |
1965 | 2012 | | |
1966 | 2013 | | |
1967 | | - | |
| 2014 | + | |
| 2015 | + | |
| 2016 | + | |
1968 | 2017 | | |
1969 | | - | |
1970 | | - | |
1971 | | - | |
1972 | | - | |
1973 | | - | |
1974 | | - | |
1975 | | - | |
1976 | | - | |
| 2018 | + | |
| 2019 | + | |
| 2020 | + | |
| 2021 | + | |
| 2022 | + | |
| 2023 | + | |
| 2024 | + | |
| 2025 | + | |
1977 | 2026 | | |
1978 | 2027 | | |
1979 | 2028 | | |
| |||
1984 | 2033 | | |
1985 | 2034 | | |
1986 | 2035 | | |
1987 | | - | |
1988 | | - | |
1989 | | - | |
1990 | | - | |
1991 | | - | |
1992 | | - | |
| 2036 | + | |
| 2037 | + | |
| 2038 | + | |
| 2039 | + | |
| 2040 | + | |
| 2041 | + | |
| 2042 | + | |
| 2043 | + | |
| 2044 | + | |
| 2045 | + | |
| 2046 | + | |
| 2047 | + | |
| 2048 | + | |
| 2049 | + | |
| 2050 | + | |
| 2051 | + | |
| 2052 | + | |
1993 | 2053 | | |
1994 | 2054 | | |
1995 | 2055 | | |
1996 | | - | |
| 2056 | + | |
| 2057 | + | |
1997 | 2058 | | |
1998 | 2059 | | |
1999 | 2060 | | |
| 2061 | + | |
2000 | 2062 | | |
2001 | 2063 | | |
2002 | 2064 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
0 commit comments