Skip to content

feature: initial version of a rust based init process for the initramfs#3

Open
JoergZeidler wants to merge 26 commits intoomnect:mainfrom
JoergZeidler:bootable_omnect_os
Open

feature: initial version of a rust based init process for the initramfs#3
JoergZeidler wants to merge 26 commits intoomnect:mainfrom
JoergZeidler:bootable_omnect_os

Conversation

@JoergZeidler
Copy link

Know issues:

sporadically not bootable regarding fsck filesystem errors
Remark: Just tested on a rpi4.

Additional changes see: meta-omnect Draft PR: omnect/meta-omnect#636

Sets up basic project structure with a Rust-based init process.

Introduces a bootloader abstraction with GRUB and U-Boot implementations, configuration loading, and kernel message logging.
Introduces functionality to detect the root block device, partition table type (GPT/DOS), and creates consistent symlinks in /dev/omnect for accessing partitions.

This allows the system to dynamically determine the partition layout and provide a stable interface for accessing critical partitions like boot, rootA, rootB, etc., regardless of the underlying storage device (SATA, NVMe, MMC).

Adds error handling for various failure scenarios during partition detection and symlink creation.
Introduces filesystem check (fsck) operations before mounting partitions,
handling exit codes and potential errors.

Provides a MountManager for tracking and unmounting filesystems in
reverse order, ensuring proper cleanup.

Includes mount options and helper functions for common filesystem
types and flags.

Also contains refactoring in partition module to include `crate::` prefixes.
Implements overlayfs functionality for managing configuration and user data persistence.

Sets up overlayfs for the /etc directory, merging factory defaults with persistent changes.
Also configures overlayfs for the /home directory, combining factory defaults with data partition for user data.
Includes bind mounts for /var/lib and /usr/local to persist data.
Adds a raw rootfs mount to provide access to the original root filesystem.
Adds a Rust-based init process for the initramfs, replacing the previous Bash scripts.

This includes mounting partitions, setting up overlays, creating symlinks, and preparing runtime files for omnect-device-service.

The init process also handles update validation and factory reset status.

The `nix` crate is updated to include process features, which are required for the runtime component.
Removes the unused `MountOptions` import from the `filesystem` module.

Also removes `mut` from bootloader variable since it's not being mutated.
Implements root device detection by parsing the kernel command line parameters in `/proc/cmdline`.

This approach offers more robust device detection across different device types and configurations compared to previous sysfs-based lookups.

It parses the `root=/dev/` parameter to determine the root block device and derives the base device path and partition separator.

Also introduces configurable path for cmdline parsing to improve testability.
Simplifies partition detection and symlink creation logic.

Moves partition error definitions to a central error module
for better organization and avoids duplication.

Updates partition layout detection to work with RootDevice struct,
and improves symlink creation to better represent device paths.

Removes unnecessary error variants and streamlines error handling.
Updates the path to the `sfdisk` command.

This ensures the application correctly locates and executes the `sfdisk` utility, which is crucial for partition management. The path is updated to a location where `sfdisk` is typically found in many systems.
Improves early initialization by disabling printk rate limiting to ensure all init messages are logged.

Updates overlayfs setup to use the current rootfs for /home and /etc overlays, and copies from factory only on first boot.

Fixes fsck command path and adds logic to determine the current root partition.
Ensures critical mounts (/dev, /proc, /sys) are moved to the new root filesystem before the switch_root call.

This addresses potential issues where the system could become unstable if these mounts were not available in the new root.

Also, temporarily disables raw rootfs mount and ODS runtime creation.
Mounts tmpfs filesystems for /run and /var/volatile to provide temporary storage.

Adds a new function to MountManager for mounting tmpfs filesystems, improving code clarity.

Waits for the root device to appear before proceeding with mount operations, preventing potential boot failures.
Migrates the root filesystem transition from `chroot` to `pivot_root` for a cleaner
initramfs detachment. This ensures the old root is properly unmounted
from the VFS hierarchy.

Refactors shared compression utilities into a dedicated module, streamlines
release image detection in the main process, and cleans up path handling.

Updates the README with a comprehensive overview of implemented and planned
features, a detailed architecture description, and refined build/test instructions.
The `pivot_root` syscall fails with `EINVAL` when executed from a `ramfs` based initramfs. This commit updates the root switching mechanism to use the `MS_MOVE` mount flag followed by a `chroot`. This approach is widely adopted by other initramfs implementations like `busybox` and `systemd` and correctly handles root transitions.

To ensure essential mounts persist into the new userspace, `MountManager::release()` is introduced. This method clears the manager's tracked mounts, preventing its RAII destructor from unmounting filesystems that must survive the `exec` call into the final root.
Previously, `fsck` results indicating a required reboot were not explicitly handled, potentially leading to the OS operating on a filesystem that had been repaired but still required a clean restart.

Now, errors from filesystem checks are propagated. If `fsck` signals that a reboot is necessary after repairs, the system automatically triggers a reboot, ensuring filesystem integrity.

Updates `Cargo.toml` to include the `reboot` feature for `nix` and refines `serde` crate feature sets.
Eliminates explicit mounting of /run within the new root filesystem.

Clarifies that the initramfs's /run tmpfs is moved into the new root during `switch_root` using `MS_MOVE`. This ensures files written to /run in the initramfs persist after the pivot.

Updates `create_ods_runtime_files` to write directly to the initramfs's /run path, removing the `rootfs_dir` argument. This avoids potential EBUSY errors and data loss from remounting /run.
Defers parsing of `os-release` data until the root filesystem is successfully mounted. Previously, `os-release` attributes were read during early configuration loading, potentially leading to inaccurate information if the rootfs was not yet available.

An early check for `is_release_image` is now performed by inspecting `/proc/cmdline` to ensure correct logging initialization. The full `os-release` parsing, including machine and distro features, is handled by a new `Config::load_os_release()` method called after partitions are mounted.

Additionally, the logic for identifying the root partition is improved to parse numeric suffixes, enhancing reliability on diverse block device naming schemes.
Extracts the logic for parsing the numeric partition suffix into a dedicated `partition_suffix` helper function.

This change resolves an issue where simple string suffix matching (e.g., `ends_with("p2")`) would incorrectly identify partitions on devices with 10 or more partitions. For instance, `nvme0n1p12` would falsely match "p2".

The new helper function ensures robust and accurate identification of root partitions by explicitly parsing the numerical suffix.
@JoergZeidler
Copy link
Author

JoergZeidler commented Mar 10, 2026

@JanZachmann : ready to review, grubenv handling integrated but still not tested on a x86 device

@JoergZeidler JoergZeidler requested review from JanZachmann and removed request for JanZachmann March 10, 2026 13:37
@JoergZeidler JoergZeidler marked this pull request as draft March 10, 2026 13:39
The previous implementation incorrectly parsed partition numbers for devices where the base name contained digits (e.g., `mmcblk0p2`, `nvme0n1p12`). It would find the first digit run rather than the trailing partition number.

Updates the `partition_suffix` function to correctly identify and parse the last sequence of digits at the end of a device name. This ensures accurate extraction of partition numbers for various device naming conventions.

Adds new test cases to validate the improved parsing logic.
@JoergZeidler JoergZeidler marked this pull request as ready for review March 10, 2026 13:57
Reduces the data stored in bootloader environment variables for `fsck` results to only the integer exit code. This conserves bootloader environment block space.

Moves the storage of full `fsck` command output to a dedicated log file on the data partition (`/data/var/log/fsck/.log`). This allows for post-boot inspection without bloating the bootloader environment.

Removes the now-unused compression and base64 encoding/decoding logic from the bootloader module.
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