Skip to content

Document the format and what the apply path costs - #15

Merged
joeferner merged 1 commit into
mainfrom
ota-docs
Sep 3, 2026
Merged

joeferner merged 1 commit into
mainfrom
ota-docs

Conversation

@joeferner

Copy link
Copy Markdown
Owner

ota/README.md opened by describing the container this crate replaced:
"a kernel image and the files that ship beside it... the kernel goes to
the boot partition, the rest alongside it". That was version 1. Version 2
is a list of (path, role, bytes) where each entry says where it lands, and
a bundle need not carry a kernel at all -- which is how a website is
updated without rewriting an image that has not changed. Being the first
paragraph of the crates.io page, it was the most-read wrong sentence in
the project.

Added to it: the container layout, the rules both directions enforce, the
roles, and the order apply writes them in with the reason the kernel is
last. Not the manifest -- that is the CLI's, and repeating a format
description in a second place is the exact failure this crate exists to
prevent, so the README says where to look instead.

bootcode.bin gets named as the one entry with no way back, because a
reader deciding whether to put the Pi firmware in a bundle should meet
that before writing the manifest rather than after a failed write.

apply's module documentation gains the measurements. They were in a
consumer's OTA module, which is the wrong home now that the rules they
argue for are here: one write_file per entry with the length known up
front, and reading an entry back rather than rewriting it. Without the
numbers those look like preferences. With them -- 17.5 ms for a
single-block write against 26 ms for a 128-block one, 99,683 ms against
928 ms for the same kernel, 1055 ms and zero writes for a bundle already
on the card -- they are the whole difference between an update measured in
seconds and one measured in minutes.

Also recorded: the ~250 ms per-entry floor, which is mostly allocation
table flushes doubled by FAT32 keeping two copies. It is the honest limit
of the current design and says where the next problem is -- cost scales
with the number of entries, not their size.

`ota/README.md` opened by describing the container this crate replaced:
"a kernel image and the files that ship beside it... the kernel goes to
the boot partition, the rest alongside it". That was version 1. Version 2
is a list of (path, role, bytes) where each entry says where it lands, and
a bundle need not carry a kernel at all -- which is how a website is
updated without rewriting an image that has not changed. Being the first
paragraph of the crates.io page, it was the most-read wrong sentence in
the project.

Added to it: the container layout, the rules both directions enforce, the
roles, and the order `apply` writes them in with the reason the kernel is
last. Not the manifest -- that is the CLI's, and repeating a format
description in a second place is the exact failure this crate exists to
prevent, so the README says where to look instead.

`bootcode.bin` gets named as the one entry with no way back, because a
reader deciding whether to put the Pi firmware in a bundle should meet
that before writing the manifest rather than after a failed write.

`apply`'s module documentation gains the measurements. They were in a
consumer's OTA module, which is the wrong home now that the rules they
argue for are here: one `write_file` per entry with the length known up
front, and reading an entry back rather than rewriting it. Without the
numbers those look like preferences. With them -- 17.5 ms for a
single-block write against 26 ms for a 128-block one, 99,683 ms against
928 ms for the same kernel, 1055 ms and zero writes for a bundle already
on the card -- they are the whole difference between an update measured in
seconds and one measured in minutes.

Also recorded: the ~250 ms per-entry floor, which is mostly allocation
table flushes doubled by FAT32 keeping two copies. It is the honest limit
of the current design and says where the next problem is -- cost scales
with the number of entries, not their size.
@joeferner
joeferner merged commit 2796a36 into main Sep 3, 2026
5 checks passed
@joeferner
joeferner deleted the ota-docs branch September 3, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant