Conversation
The other half of an update, behind the `apply` feature. It takes a validated bundle and a resident-fat volume and writes every entry where its path says. The order is the crate's, not the bundle's: ordinary files, then Raspberry Pi firmware, then config.txt, then the kernel. That is the "write the live boot file last" rule stated as an order over roles now that a bundle can replace the firmware and config.txt too, and the crate imposes it for the same reason the kernel became a role rather than a position -- a bundle packed in another order must not be able to change which failures leave a board that still boots. The kernel is last because while there is one boot image that write is the commit; it stops being either once there are two slots and rewriting config.txt takes both jobs over. Entries the card already holds are read and not rewritten. One function answers both halves of that question -- before a write it decides whether to write at all, and after one it is the verification -- so a skipped entry is checked exactly as strictly as a written one, which is the property that would otherwise rot. On hardware, re-applying an unchanged bundle costs 1055 ms and no card writes at all, against 3724 ms to write the same six entries in full. A bundle carrying the Pi firmware carries 3 MB of it and that changes about once a year. Timing stays with the caller, through Progress. The water sensor keeps producing the figures it always did -- milliseconds and card commands for the write and the read-back separately -- and this crate never learns that embassy_time or a command counter exist. The tests build FAT32 volumes with mkfs.vfat and judge them with fsck.vfat, because a check written here could only agree with the code it is checking. Two things about that oracle are worth knowing, since both produce a test that cannot fail: fsck.vfat -n exits 0 even when it finds faults, so the assertion is on its output rather than its status; and an 8 MB image is not really FAT32 at 16,100 clusters against a 65,525 minimum, which resident-fat accepts because it enforces only a maximum. Confirmed the oracle bites by removing the final sync -- five tests fail with "Dirty bit is set" and "Free cluster summary wrong". tests/ is excluded from the published crate: it needs dosfstools and fails rather than skips without it, so shipping it would ship something that cannot run from the tarball it arrives in. CI installs the tools.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The other half of an update, behind the
applyfeature. It takes a validated bundle and a resident-fat volume and writes every entry where its path says.The order is the crate's, not the bundle's: ordinary files, then Raspberry Pi firmware, then config.txt, then the kernel. That is the "write the live boot file last" rule stated as an order over roles now that a bundle can replace the firmware and config.txt too, and the crate imposes it for the same reason the kernel became a role rather than a position -- a bundle packed in another order must not be able to change which failures leave a board that still boots. The kernel is last because while there is one boot image that write is the commit; it stops being either once there are two slots and rewriting config.txt takes both jobs over.
Entries the card already holds are read and not rewritten. One function answers both halves of that question -- before a write it decides whether to write at all, and after one it is the verification -- so a skipped entry is checked exactly as strictly as a written one, which is the property that would otherwise rot. On hardware, re-applying an unchanged bundle costs 1055 ms and no card writes at all, against 3724 ms to write the same six entries in full. A bundle carrying the Pi firmware carries 3 MB of it and that changes about once a year.
Timing stays with the caller, through Progress. The water sensor keeps producing the figures it always did -- milliseconds and card commands for the write and the read-back separately -- and this crate never learns that embassy_time or a command counter exist.
The tests build FAT32 volumes with mkfs.vfat and judge them with fsck.vfat, because a check written here could only agree with the code it is checking. Two things about that oracle are worth knowing, since both produce a test that cannot fail: fsck.vfat -n exits 0 even when it finds faults, so the assertion is on its output rather than its status; and an 8 MB image is not really FAT32 at 16,100 clusters against a 65,525 minimum, which resident-fat accepts because it enforces only a maximum. Confirmed the oracle bites by removing the final sync -- five tests fail with "Dirty bit is set" and "Free cluster summary wrong".
tests/ is excluded from the published crate: it needs dosfstools and fails rather than skips without it, so shipping it would ship something that cannot run from the tarball it arrives in. CI installs the tools.