Repository navigation
fix: keep the behaviour of the scripted initramfs, remove a stale update validation config - #40
Conversation
A device updated from an init that did not write omnect_first_boot_done has no marker after the update. The init took that boot for the first boot after flashing: it reported first_boot and ran the data resize again. Only the extra-bootargs sync checked for a pending validation, and an update with a new bootloader is not validated at all. detect_first_boot now treats a boot with omnect_validate_update or omnect_bootloader_updated set as no first boot and writes the marker. The extra-bootargs sync gates on first_boot alone again. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
…r-update Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
A read error on omnect_bootloader_updated now counts as not a first boot, so no first-boot step runs on a device in use. detect_first_boot writes the marker itself, so write_first_boot_marker stays private to the normal mode. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
detect_first_boot only reads: a set or unreadable update flag, the rollback flag included, means no first boot. handle_update_validation writes the marker on a boot after an update and keeps omnect_validate_update_failed and omnect_bootloader_updated set until the write works, so a failed write is retried on the next boot. Flash mode no longer writes the marker into the source disk's environment. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
/run moves into the final root and systemd keeps it as it is, so its flags must be set here. The scripted initramfs remounted /run with the same options. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
The scripted initramfs read /etc/omnect/create-fs-links.txt, one '<target> <link>' pair per line, created the links once and deleted the file. Image configuration tools still write this file. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
With persistent-var-log the scripted initramfs kept /var/log in /mnt/data/log, the init keeps it in /mnt/data/var/log. After an update the init moves the old logs once. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
The initramfs files stayed in RAM for the whole uptime. After the switch they are deleted through a file descriptor of the old root, without crossing into mounted filesystems. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
A restored path whose parent directories were removed got them back as root with the default mode. They now get the owner and mode from the backup. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Without -s parted may ask a question and fail on the missing answer. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
GRUB passes an empty value when probe fails. The init then waited for the full timeout with an unclear error. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
A record written by the scripted initramfs has no exit code line, so it never decoded and stayed in the env for good. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
tests/contract holds the status file for every factory reset outcome. omnect-device-service keeps a copy and tests that it parses each one. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
- Merge compute_first_boot into detect_first_boot. - BootEnv::is_first_boot_done and set_first_boot_done keep the marker key and value in one place; both writers use them. - Log an error when an update flag stays set because the marker write failed. - Tests: the clear is gated on the marker write (a per-key set_env error in MockBootEnv), the write order, other or unreadable marker values, a failed write on a validation boot, the log lines, and a two-boot test over one mock for a fresh flash and the three update flags. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Dated corrections in the first-boot, resize-retry, extra-bootargs and legacy-env specs; shorter first_boot row in usage.md, including the validation-boot case where the marker write fails. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
…ly modules Signed-off-by: Jan Zachmann 50990105+JanZachmann@users.noreply.github.com
The fsck logs and the flash mode logs name devices, inodes and files, and nothing but root reads them. Write the files with mode 0600 and the fsck log directory with mode 0700. A log left by an earlier boot gets the new mode too. Signed-off-by: Jan Zachmann 50990105+JanZachmann@users.noreply.github.com
…validation Only a local update writes update_validation_conf.json, right before the reboot into its validation boot. If that boot does not validate, the file stays and a later cloud update would validate as a local one. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
JoergZeidler
left a comment
There was a problem hiding this comment.
Review of 6c8374b against the PR text, the legacy scripts (meta-omnect origin/kirkstone), the meta-omnect#697 head and omnect-device-service main. 31 inline comments, each labelled: Medium 2, Low 29 (two of them Decisions). Nothing Critical, nothing High.
Before merge
- An answer on the
update_validation_conf.jsonremoval (thread onremove_update_validation_conf): the premise is wrong, my recommendation is to dropcb91062. - The real decode path tested (thread on
BootEnv::get_fsck_status). - The wrong statements:
types.rs:16,fs_link.rs:81,usage.md:41.
The rest is Low.
Machine checks on 6c8374b
| Check | Result |
|---|---|
cargo fmt -- --check |
ok |
clippy -D warnings -W items_after_statements -W items_after_test_module, 12 feature sets (the README sets, persistent-var-log in two of them, core,grub,gpt,factory-reset) |
0 warnings |
cargo test, the same 12 sets |
lib 341 / 340 / 329 / 327 / 364 / 352 / 341 / 352 / 658 / 478 / 619 / 392 passed, 0 failed |
armv7 clippy -D warnings, uboot/gpt all modes + persistent-var-log |
ok |
cargo audit |
clean |
Legacy parity, verified
| Claim | Legacy |
|---|---|
/run flags |
fs-mount:57 mode=0755,nodev,nosuid,strictatime |
create-fs-links.txt format, third field ignored, rm after |
fs-link:13-18; a failed ln/rm returned 1 → on_exit_release_image loop |
/mnt/data/log |
common-sh:230-231 |
| initramfs freed | legacy image uses initramfs-framework-base, busybox switch_root deletes the old root |
| restore parents with owner and mode | factory-reset:146 cp --parents -av; the Rust restore runs cp -a without --parents |
| fsck record without exit code line | uboot-sh:34, grub-sh:53 |
empty bootpart_fsuuid= |
PR 697 omnect.inc.in:45-46, probe --set=… then bootpart_fsuuid=${bootpart_fsuuid} |
OMNECT_PART_TABLE ??= "gpt", OMNECT_EARLY_MODULES on i.MX8MM |
PR 697 omnect-os-init.inc:19-20,28, phytec-imx8mm.inc:105 |
Body-only items
- Specs: none contradicts the PR; three statements go stale and need a dated note:
2026-07-29-legacy-env-alignment-design.md§8.1 (second reader, one case now distinguished) and §3.4 (the same reasoning as foromnect_validate_updateapplies to the ODS config file);2026-05-27-first-boot-detection-design.md§2.1 "No migration logic" (the log move is a migration of its own). The flash spec §8 says nothing about the log mode, the resize spec listspartedwithout-s; both fine. - Commits
3f6d564and814f9de:Signed-off-bywithout angle brackets. Three merge commits, moot with the squash. - The contract files are an interface for ODS; the PR names no ODS PR.
Verified, no change needed
decode_fsck_output keeps a production caller under grub (get_fsck_from_file), the file is read and removed in one go. InvalidValue is built only by invalid_fsck_record. create_parent_dirs stops at rootfs or the first existing entry, the backup has every parent with its attributes. delete_contents: symlink_metadata does not follow links, the dev check skips every mount point, /proc is in the new root before /proc/self/fd/N is used, the old rootfs mount-point dir is empty after MS_MOVE; f_type as u32 is right for i32, u32 and i64; RAMFS_MAGIC matches linux/magic.h. parted -s on DOS: nothing in the extended container is mounted before the resize. The conf path matches the ODS default and the var/lib bind mount. create_root_only_file/_dir also fix an existing mode; no non-root reader of the fsck or flash logs in this repo or ODS. EFI entry failure is fatal in every flash mode, as usage.md says. Status codes 0–4 match FactoryResetStatusCode. create_link replaces a file or link and refuses a directory, as usage.md says.
Not verified
A device run of any parity item; the RAM gain and time of the initramfs free; the log move on a device coming from the legacy image; whether omnect-ui or the portal read the fsck or flash logs; the systemd /run limits against the shipped version; i686.
Signed-off-by: Joerg Zeidler 62105035+JoergZeidler@users.noreply.github.com
ODS writes the config only for an update it runs itself and removes it after a successful validation. A failed validation leaves it behind, and the validation of a later ADU update, which does not write the file, reads it. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Such a value stayed in the env and was read again on every boot. drain_fsck_env now clears it like a record without exit code, and logs the text of that record before it drops it. If an applet cannot run, the record is kept and the reason is logged. The trait default and the GRUB env channel share one reader, which a test runs through get_env. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
The error-after-wipe and warning files held values the init cannot write: a Warning has no error, and a failed restore is an Error. Both cases are now built by restore_all and restored_status. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Before, such an entry stayed in /mnt/data/log, so the directory could not be removed and the move was tried again on every boot. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
JoergZeidler
left a comment
There was a problem hiding this comment.
Round 2 on 58b440c. All 31 threads answered, 8 new commits, all with the full trailer.
Machine checks (all exit 0): cargo fmt -- --check; clippy (-D warnings -W clippy::items_after_statements -W clippy::items_after_test_module) and cargo test on 14 feature sets; cargo clippy --target armv7-unknown-linux-gnueabihf on uboot,dos,persistent-var-log,factory-reset,resize-data,test-utils; cargo audit clean.
Feature set (+ test-utils) |
lib tests |
|---|---|
| grub,gpt / grub,dos / uboot,gpt / uboot,dos | 347 / 346 / 335 / 333 |
| grub,gpt,factory-reset / uboot,dos,factory-reset | 472 / 458 |
| grub,gpt,resize-data / uboot,dos,resize-data | 370 / 359 |
| grub,gpt,persistent-var-log / uboot,dos,persistent-var-log,factory-reset,resize-data | 351 / 488 |
| grub,gpt,release-image / uboot,dos,release-image / grub,gpt,resize-data,release-image | 347 / 333 / 370 |
| grub,gpt,early-modules | 391 |
Update validation config: you are right, I withdraw the Medium. My claim held only for updates ODS runs itself. Checked: the ADU handlers (swupdate_handler_v2_grub.sh:824, _u-boot.sh:823) only set omnect_validate_update_part, the validation reads the file (update_validation.rs:184), and a failed validation reboots without removing it (:344). The six contract files in omnect/omnect-device-service#207 (e9488c7) are byte-identical to tests/contract, and b39fbb5 has the doc sentence.
Fixes verified (my own mutation checks on the new tests):
| Thread | Commit | Check |
|---|---|---|
| real decode path untested | f72a389 | get_fsck_env is the one path for the trait default and the GRUB arm. Reverting "does not unpack" to Ok(None): get_fsck_status_rejects_a_value_that_does_not_unpack fails |
Ok(None) never cleared, silent applet failure, dropped text |
f72a389 | invalid + cleared, Err keeps the record with a warning, text logged before the drop, §8.1 note |
tautological /run test |
58b440c | const table, the loop uses it. /run without flags: test fails |
| log move conflict | b7f8894 | <name>.old. Without the rename: migrate_var_log_moves_a_conflicting_entry_to_old fails |
| restore dir before lookup | be85407 | order fixed. No test guards it (old order: all 8 tests pass); fine for a Low |
parted print, -s untested |
1f9b8dd | run_cmd returns stdout, print_args tested |
statfs / read_dir / is_ram_fs / PROC_SELF_FD |
2ac0b5e | done. metadata() instead of symlink_metadata() in delete_contents: two tests fail |
| fsck log dir 0700 | 58b440c | write_fsck_log creates it; without that line the test fails |
| contract strings | 6b2e6cb | built from restore_all and restored_status; the warning shape fix is right |
| comments, wording, specs, usage.md | 58b440c, b7f8894, 833fcb6 | all done |
Kept as parity: the /run size. The fs_link thread stays open for the team decision; it does not block this PR.
New, all Low, no need to hold the PR:
src/bootloader/mod.rs:328: the warn line writes the whole fsck text in one kmsg write.KmsgLogger::logignores the write result, and the kernel rejects a/dev/kmsgwrite above the record limit (about 1 KiB,devkmsg_write; from memory ofprintk.c, not tested on a device). A long legacy record then logs nothing.output_tail(.., FSCK_REASON_LINES)is whatfsck.rs:300uses for the same output.src/early_init.rs:13:struct EssentialMountis declared beforeRUN_FLAGSandESSENTIAL_MOUNTS; the convention putsconstfirst. The compiler does not care about the order.src/filesystem/overlayfs.rs:172: the function-localMIGRATED_LOG_SUFFIXis the only local const outside tests. Your reason (dies with the function) is fair; a const inpaths::next toDATA_LOG_OLDwould die with it too, as a dead-code warning. Optional.2026-07-29-legacy-env-alignment-design.md:5: one line of the new Correction is not wrapped.types.rs:21has a short wrap.
Not verified: a device run of the parity items, the initramfs free on a board, the log move on a device coming from the scripted initramfs.
Signed-off-by: Joerg Zeidler 62105035+JoergZeidler@users.noreply.github.com
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
The scripted initramfs bind-mounts /mnt/data/log to /var/log. Use the same directory, so an update from it needs no log migration. The fsck logs move to /mnt/data/log/fsck with it. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
…act (#207) Closes #205 ## Summary omnect-os moves from the scripted initramfs to [omnect-os-init](https://github.com/omnect/omnect-os-init), an init written in Rust (omnect/meta-omnect#697). The init writes the factory-reset result to `/run/omnect-device-service/omnect-os-initramfs.json` in a new JSON format. This PR makes omnect-device-service read this format and report it to the twin. - Reads the key `factory_reset`. A result under the old key `factory-reset` is unusable: it is logged as an error and reported as `null`. A `null` under the old key is a normal boot. - The status codes have the omnect-os-init names: `0` success, `1` invalid, `2` error, `3` config error, and the new `4` warning (the reset worked, but a partition needed a second `mkfs`). The status is a `u32`, as omnect-os-init writes it. A status code this version does not know is reported as it is, and the raw result is logged as a warning. - `error` and `context` are optional, `paths` defaults to an empty list. `data_wiped` is required: a result without it is unusable and reported as `null`, because a missing value must not read as a safe abort. - Reports `data_wiped`: on error it tells a safe abort from a failure after data was already wiped. - Reports `error` and `context` as `null` instead of leaving them out: twin reports are merge patches, so a missing key would keep the value of a previous result. - The `factory_reset` feature version is 4, because the reported result changed. The crate version is 0.46.1. - Mode 4 is no longer accepted: the init does not support it, so a request with mode 4 would come back as `Invalid`, a reset that never runs. - The test files have the real omnect-os-init output. `testfiles/positive/contract` holds copies of the status files that omnect-os-init writes for every factory reset result (its `tests/contract`, omnect/omnect-os-init#40); a test parses each one and compares every field. - The README says that a result from before feature version 4 stays in the twin until the next reset, and that `preserve` accepts only the reported keys. - README and `update_validation.md` link the initramfs docs in omnect-os-init (`docs/usage.md`) instead of meta-omnect and the legacy scripts. The README documents the result fields, and that `preserve` is mandatory, as the parser already requires. - `update_validation.md` says that omnect-os-init deletes `update_validation_conf.json` on every boot without update validation (omnect/omnect-os-init#40), so a config written by hand is gone after the next reboot. ## Reason The parser did not match the omnect-os-init format: it read the key `factory-reset` and required an `error` string. So the result of the init was unusable and never reached the twin. See #205 for the full list of differences. omnect-os-init tests that it writes exactly the contract files, and this repo tests that it parses them. So a format change on one side fails a test once the copies are updated. omnect-ui reads the published result and must follow the new format and the removed mode 4: omnect/omnect-ui#132. The local web service keeps the channel `FactoryResetV1` and the route `/factory-reset/v1`, although the payload changed and mode 4 is rejected. An omnect-ui without omnect/omnect-ui#132 gets no signal about this. The only safeguard is that this PR, omnect/meta-omnect#697 and omnect/omnect-ui#132 reach a release together; omnect-ui#132 also requires ods `>=0.46.1`. --------- Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
…697) ## Summary omnect-os moves from the scripted initramfs to [omnect-os-init](https://github.com/omnect/omnect-os-init), an init written in Rust. This PR is the main integration step: it builds the init, installs it as `/init` and removes the scripted initramfs (`init.d/*` from `omnect-os-initramfs-scripts`). - `omnect-os-init`: Cargo features follow the machine and distro (`grub` or `uboot`, the partition table from `OMNECT_PART_TABLE`, `factory-reset`, `resize-data`, `persistent-var-log`, `release-image`, `flash-mode-2`, `flash-mode-2-direct` when `OMNECT_FLASH_MODE_2_DIRECT_FLASHING` is `1`, `flash-mode-3`, `rtc` from the machine feature, and `early-modules` when `OMNECT_EARLY_MODULES` is set). The partition and bootloader constants that flash mode 1 needs are exported into the build; for flash mode 2 also the boot partition offset and size and `OMNECT_USER_ID`. - `OMNECT_PART_TABLE` (`gpt` or `dos`, default `gpt`) selects the partition table the init is built for; a machine whose wks file uses `--ptable msdos` sets `dos`. - `OMNECT_USER_ID` (uid and gid of the omnect user) is a distro variable, so the init recipe and `omnect_user.bbclass` share one value. - `omnect-os-initramfs`: installs the tools the init calls (`bash` for the debug shell on non-release images, `e2fsprogs`, `dosfstools`, `util-linux-sfdisk`, `util-linux-blkid` on GRUB machines, `efibootmgr` on EFI machines, `dhcpcd` and `base-passwd` for flash modes 2 and 3, `dropbear` and the omnect user for flash mode 2, `curl` and `ca-certificates` for flash mode 3). It drops the legacy script packages, the initramfs-framework modules, `os-release`, `jq`, `kmod`, `util-linux-uuidgen`, `bmaptool` and `xz`. `dhcpcd` is built without udev: it runs only in the initramfs, where udevd does not run, so it no longer pulls udev into the initramfs. The `fsck.fat` links in `/sbin` are created only when `/sbin` is not merged into `/usr/sbin`; on a merged image they replaced `fsck.fat` with a link to itself, so the boot partition was never checked. - GRUB passes `bootpart_fsuuid` instead of `rootblk`, so the init finds its disk by the filesystem UUID of the boot partition (partition 1, read with `probe`). A flash mode 1 clone gets a new boot volume ID ([omnect-os-init#38](omnect/omnect-os-init#38)); the rootfs UUID would be the same on the clone and its source. - GRUB boots from the disk it was loaded from (taken from `$cmdpath`, which needs the `regexp` module), not from `hd0`. `hd0` is the first disk of the firmware: with a flash mode 1 clone and its source both attached, GRUB read the grubenv of the clone but loaded kernel and rootfs from the source. - U-Boot declares every environment variable the OS writes at runtime as writable (`omnect_first_boot_done`, `omnect_fsck_*`, `omnect_factory_reset_last_error`, `flash-mode-url`, `flash-mode-url-sha256`), so a `saveenv` in `omnect_update_flow` keeps them. `data-mount-options` and `resized-data` are no longer listed, because the init reads neither. - `u-boot-scr`: the boot script no longer appends the literal text `None` to `bootargs` when `OMNECT_APPEND_1ST_BOOT` is unset, as on developer images. - `OMNECT_EARLY_MODULES` lists the kernel modules the init loads before `switch_root` (`imx_sdma` on phytec-imx8mm). It selects the `early-modules` feature, and the new package `omnect-os-init-early-modules` installs the list into the rootfs as `/etc/omnect/early-modules.d/omnect.conf`. The `omnect-os-init` recipe is built per machine, because its features and `build.rs` read machine settings. rpi kernels build compressed modules, so they get `CONFIG_MODULE_DECOMPRESS` when the variable is set. - `omnect-base-files` adds the mount point `/mnt/rootCurrentPrivate`, where the init bind-mounts the root filesystem. Its tmpfiles config creates `/mnt/cert/ca` and `/mnt/cert/priv` (`d` instead of `z`), because the init does not create them. - The busybox `poweroff` config is removed; the init powers off itself. - Removed with the scripted initramfs: - The recipe `omnect-os-initramfs-scripts`. A layer with a `.bbappend` for it no longer parses, and own `init.d` scripts are no longer possible. - Factory reset wipe mode 4, a custom wipe added by such a `.bbappend`. A request with `mode` 4 now gets status 1. - The bootloader variable `data-mount-options`; the data partition is always mounted with the default options. - An optional `preserve`: the factory-reset request must now contain it, else it gets status 3. - `omnect-device-service` reads the factory-reset result the init writes ([omnect-device-service#207](omnect/omnect-device-service#207)). - The expected bootloader checksums of genericx86-64, rpi and phytec-imx8mm follow the changed bootloader inputs. - README and `doc/`: keep the build settings and link to the [omnect-os-init docs](https://github.com/omnect/omnect-os-init/blob/main/docs/usage.md) for the behaviour of flash modes, factory reset, filesystem check and the status file. ## Reason The initramfs moves from shell scripts to one Rust binary, for typed error handling, a defined result contract towards omnect-device-service, and unit tests for the boot, factory-reset and flash paths. - The `omnect-os-init` recipe builds the released version 0.1.0. It contains [omnect-os-init#40](omnect/omnect-os-init#40), which keeps what the scripted initramfs did: `/run` without suid and device files, the links of `create-fs-links.txt`, the persistent logs in `/mnt/data/log`, and the restored directories with their owner and mode. - The `omnect-device-service` recipe builds the released version 0.46.1, which contains [omnect-device-service#207](omnect/omnect-device-service#207). - [omnect-ui#132](omnect/omnect-ui#132) reads the new factory-reset result and no longer offers mode 4. The three PRs have to reach a release together. - The bootloader version changes on every machine, because `omnect_env.h` and the GRUB config are bootloader inputs (on phytec-imx8mm the boot script is one too); devices get a bootloader update with this image. A layer whose bootloader checksum covers `recipes-bsp/u-boot/u-boot/*` needs a new expected value at the same time. --------- Signed-off-by: Jan Zachmann 50990105+JanZachmann@users.noreply.github.com
Summary
Keeps behaviours of the scripted initramfs that the init did not keep, and removes a stale update validation config:
/runis mounted withnosuid,nodev,strictatimeand mode 0755./etc/omnect/create-fs-links.txt(one<target> <link>pair per line) are created once, then the file is deleted.persistent-var-log,/var/logis/mnt/data/log, the directory of the scripted initramfs. The fsck logs are written to/mnt/data/log/fsck.switch_rootthe initramfs files are deleted, so their RAM is freed. The delete does not cross into mounted filesystems, and the number of deleted entries is logged. When/is not a ramfs or tmpfs, the files are kept and the reason is logged.partedruns in script mode, and a failedparted printis an error.bootpart_fsuuid=fails at once with a clear error instead of waiting for the timeout.omnect_validate_update,/mnt/data/var/lib/omnect-device-service/update_validation_conf.jsonis deleted. A missing file is not an error, a failed delete is logged as a warning. On a validation boot the file is kept.tests/contractholds the status file for every factory reset result, and a test checks that the init writes exactly these files.docs/usage.mddescribes the symlinks, the removal of the update validation config, and that a failed EFI boot entry ends a flash mode with a fatal error.docs/usage.mdand the README warn that flash mode 3 does not check TLS certificates on a machine withoutrtc./mnt/cert/caand/mnt/cert/priv, and GRUB probes the boot partition of its own disk.Reason
These are behaviours of the scripted initramfs that the init did not keep, or kept only partly. A device updated from the scripted initramfs would lose its log history and its one-time links, and run with a
/runthat allows suid binaries and device files. omnect/meta-omnect#697 builds the init into omnect-os and needs these fixes.omnect-device-service writes the update validation config before the reboot into the validation boot of an update it runs itself (
set_boot_partition), and removes it after a successful validation. A failed validation reboots without removing it. An ADU update does not go through omnect-device-service: the swupdate handler only setsomnect_validate_update_partand does not write the file, but the validation reads it. So after a failed local validation, the next ADU update is validated as a local one: no IoT Hub connection check, and deviceupdate-agent is not started by omnect-device-service. A config written by hand is also deleted on every boot without validation; omnect/omnect-device-service#207 adds this to the update validation docs.The contract files close a gap that no device test can see: the status file is the interface to omnect-device-service. omnect/omnect-device-service#207 adds a copy of these files and a test that parses each one. The error-after-wipe and warning cases are built by the factory reset status code, so they hold values the init really writes.
Signed-off-by: Jan Zachmann 50990105+JanZachmann@users.noreply.github.com