Skip to content

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

Open
JoergZeidler wants to merge 34 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 34 commits intoomnect:mainfrom
JoergZeidler:bootable_omnect_os

Conversation

@JoergZeidler
Copy link

@JoergZeidler JoergZeidler commented Mar 10, 2026

Current Plan for review purpose [PR1 until PR5 reflects this PullRequest]:
rewrite-initramfs-plan.md

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, tested on x86/tauri and rpi

@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.
@JoergZeidler JoergZeidler marked this pull request as draft March 12, 2026 08:18
Adds comprehensive root device detection, supporting the `rootpart=N` kernel command line parameter specific to Omnect-OS, while retaining a fallback to the standard `root=/dev/` format. This improves robustness and alignment with Omnect's boot process.

Reorders bootloader initialization to occur after partition mounting, ensuring the boot partition and the `grubenv` file are accessible for the `GrubBootloader`.

Clarifies the `grub-editenv` detection logic to correctly identify it as an initramfs tool.
Introduces a build script (`build.rs`) to expose key Yocto build-time environment
variables as compile-time constants within the application.

This allows platform-specific parameters such as U-Boot environment offsets,
partition sizes, and bootloader start addresses to be injected directly
into the Rust code. The constants are available as `Option` within
`config::build`, providing `None` for non-Yocto builds or when variables are
absent, which ensures robust local development.
@JoergZeidler JoergZeidler marked this pull request as ready for review March 12, 2026 13:40
Replaces the hardcoded block device probe list with dynamic enumeration of `/sys/block/` for `rootpart=N` detection. This improves hardware compatibility and removes reliance on specific device names.

Implements robust handling for USB boot devices, including waiting for enumeration completion and prioritizing removable disks when multiple devices match the partition number.

Refines `root=/dev/` parsing logic for U-Boot boot paths and provides clearer separation between GRUB and U-Boot detection flows.
Replaces the `sysfs` enumeration and `omnect_rootblk` hint with explicit bootloader contracts.

For GRUB, detects the root device by resolving `bootpart_fsuuid=` via `blkid`, in conjunction with `rootpart=N` from the kernel command line. This provides a more robust and stable identification than prior methods.

Maintains direct parsing for U-Boot's `root=/dev/` parameter.

Removes the `omnect_rootblk` kernel command line variable and simplifies the device probing by eliminating complex sysfs-based enumeration and USB-specific handling.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an initial Rust-based init process intended to run as PID 1 in the initramfs, replacing shell-scripted boot logic with typed, testable Rust modules for device detection, partition/mount setup, overlayfs, bootloader env integration, and switch_root into the real rootfs.

Changes:

  • Add core initramfs boot flow (main.rs) including early mounts, root device detection, partition mounting + fsck, overlayfs setup, ODS runtime file creation, and switch_root.
  • Introduce bootloader abstraction (GRUB/U-Boot), partition detection/layout utilities, mount tracking (RAII), fsck wrapper, and kmsg logging.
  • Add documentation, build script, and initial unit tests across key modules.

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
.gitignore Adds standard Cargo/IDE/build artifact ignores.
Cargo.toml Defines crate metadata, dependencies, features, release profile.
Cargo.lock Locks dependency graph for the initial implementation.
README.md Documents architecture, functionality, build/test commands.
build.rs Generates build-time constants from Yocto env vars into OUT_DIR.
project-context.md Captures system context, constraints, and patterns for contributors.
src/main.rs PID 1 init flow: early mounts, logging, partition/fsck/mount/overlay setup, ODS files, switch_root.
src/lib.rs Exposes library modules + convenience re-exports.
src/error.rs Adds typed error hierarchy for initramfs subsystems.
src/early_init.rs Mounts essential FS early (/dev, /proc, /sys, /run).
src/config/mod.rs Parses /proc/cmdline and rootfs /etc/os-release into runtime config.
src/logging/mod.rs Logging module exports.
src/logging/kmsg.rs Implements /dev/kmsg logger with kernel level prefixes.
src/bootloader/mod.rs Bootloader trait, env var names, GRUB/U-Boot detection, mock bootloader for tests.
src/bootloader/grub.rs GRUB env implementation via grub-editenv + grubenv path handling.
src/bootloader/uboot.rs U-Boot env implementation via fw_printenv/fw_setenv.
src/bootloader/types.rs Bootloader type enum + display impl.
src/filesystem/mod.rs Filesystem module exports (fsck/mount/overlay).
src/filesystem/mount.rs MountManager with tracking/unmount + helper mount APIs.
src/filesystem/overlayfs.rs Overlayfs setup for /etc + /home, bind mounts, raw rootfs mount.
src/filesystem/fsck.rs Fsck wrapper with exit-code handling and printk rate-limit adjustments.
src/partition/mod.rs Partition module exports + Result alias.
src/partition/device.rs Root device detection from kernel cmdline (GRUB fsuuid/part, U-Boot root=).
src/partition/layout.rs Partition-table type detection and partition map construction.
src/partition/symlinks.rs Creates/verifies /dev/omnect/* symlinks for partitions.
src/runtime/mod.rs Runtime module exports (fs-links, ODS runtime files, switch_root).
src/runtime/fs_link.rs Creates symlinks from fs-link JSON configuration.
src/runtime/omnect_device_service.rs Writes /run/omnect-device-service/* runtime state for ODS.
src/runtime/switch_root.rs Moves mounts, MS_MOVE + chroot pattern, locates and execs init.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Reduces project dependencies by removing `anyhow`, `sys-mount`, `base64`, `flate2`, and their transitive crates. This streamlines the build process and minimizes the overall attack surface.

Transitions mount operations to direct usage of the `nix` crate, replacing `sys-mount`.

Refines fsck status handling, storing only the integer exit code in the bootloader environment. Full fsck output is now written to a log file at `/data/var/log/fsck/.log`, improving clarity and efficiency.

Introduces an RAII guard for kernel message rate limiting during fsck, ensuring it is consistently re-enabled after checks.

Enhances error handling by adding a specific `PartitionError::SymlinkRemoveFailed` variant and improving logging for bootloader environment variable retrieval.

Updates `fs-links` configuration paths in documentation.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces the first Rust-based PID1 init process for the initramfs, replacing shell scripts with typed Rust modules for device/partition detection, mounting/fsck, overlays, runtime integration, and switch_root into the real rootfs.

Changes:

  • Add initramfs boot sequence (main.rs) including essential mounts, root device detection (GRUB/U-Boot), fsck + mounts, overlayfs setup, and switch_root.
  • Add supporting subsystems: bootloader abstraction (GRUB/U-Boot), partition layout + /dev/omnect/* symlinks, kmsg logging, ODS runtime file generation, and fs-link support.
  • Add project docs/build scaffolding (README, project context, build.rs, Cargo metadata).

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/runtime/switch_root.rs Implements MS_MOVE + chroot based switch_root and init discovery
src/runtime/omnect_device_service.rs Writes runtime state for omnect-device-service (ODS) into /run
src/runtime/mod.rs Exposes runtime utilities (fs-links, ODS files, switch_root)
src/runtime/fs_link.rs Reads fs-link JSON config(s) and creates symlinks in the mounted rootfs
src/partition/symlinks.rs Creates/removes/verifies /dev/omnect/* partition symlinks
src/partition/mod.rs Partition module exports and Result alias
src/partition/layout.rs Detects GPT/DOS layout and builds partition device map
src/partition/device.rs Detects root device from kernel cmdline (GRUB fsuuid or U-Boot root=)
src/main.rs PID1 entrypoint implementing the initramfs boot flow
src/logging/mod.rs Logging module exports
src/logging/kmsg.rs /dev/kmsg logger implementation
src/lib.rs Library module exports for the binary
src/filesystem/overlayfs.rs Overlayfs setup for /etc and /home + bind mounts
src/filesystem/mount.rs MountManager with mount tracking and cleanup
src/filesystem/mod.rs Filesystem module exports and Result alias
src/filesystem/fsck.rs fsck wrapper with exit-code handling and ratelimit toggling
src/error.rs Central error hierarchy (InitramfsError + subsystem errors)
src/early_init.rs Mounts essential filesystems early (/dev, /proc, /sys, /run)
src/config/mod.rs Parses /proc/cmdline + etc/os-release into runtime Config
src/bootloader/uboot.rs U-Boot env access via fw_printenv/fw_setenv
src/bootloader/types.rs BootloaderType enum
src/bootloader/mod.rs Bootloader trait + auto-detection + test mock
src/bootloader/grub.rs GRUB env access via grub-editenv
project-context.md High-level architecture and development commands
build.rs Generates build-time constants from Yocto env
README.md Project documentation and module overview
Cargo.toml Crate definition, deps, features, and release profile
Cargo.lock Locked dependency graph
.gitignore Repo ignore rules

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Hardens paths to external executables by using absolute `/bin` paths.
Improves `fsck` result interpretation: `CORRECTED` now explicitly implies a reboot is required before mounting and is no longer considered a "clean" state for immediate use.
Removes gzip and base64 encoding for U-Boot fsck status, storing it as a plain integer exit code string.
Adds robust error handling for `blkid`, failing early on non-zero exit to prevent indefinite retries.
Prevents accidental replacement of plain directories with symlinks during initramfs link creation.
Ensures critical mountpoint directories (`dev`, `proc`, `sys`, `run`) exist in the new root before moving mounts during `switch_root`.
Clarifies the purpose of early `is_release_image` detection.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an initial Rust-based init process intended to replace the existing initramfs shell scripts, covering early mounts, root device/partition detection, fsck + mounting + overlays, bootloader env integration, ODS runtime state creation, and the final switch_root + exec init handoff.

Changes:

  • Add core initramfs boot flow in Rust (early init, logging, partition + filesystem setup, switch_root).
  • Introduce GRUB/U-Boot bootloader abstraction plus persistent fsck status reporting (bootloader env + /data logs).
  • Add runtime integrations: ODS runtime files and fs-link symlink creation from JSON config.

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/runtime/switch_root.rs Implements MS_MOVE + chroot + exec root switch and init execution.
src/runtime/omnect_device_service.rs Writes ODS runtime files/status JSON into /run for consumption after root switch.
src/runtime/mod.rs Exposes runtime helpers (fs-links, ODS files, switch_root).
src/runtime/fs_link.rs Creates filesystem symlinks from fs-link configuration JSON files.
src/partition/symlinks.rs Creates/verifies /dev/omnect/* symlinks to block devices/partitions.
src/partition/mod.rs Partition module public API and re-exports.
src/partition/layout.rs Detects partition table type and builds partition map (GPT/DOS).
src/partition/device.rs Root device detection via kernel cmdline for GRUB and U-Boot.
src/main.rs Main initramfs PID1 flow: mounts, logging, fsck+mounts, overlays, integrations, switch_root.
src/logging/mod.rs Logging module exports.
src/logging/kmsg.rs /dev/kmsg logger implementation.
src/lib.rs Library module exports/re-exports for the init implementation.
src/filesystem/overlayfs.rs Overlayfs and bind-mount setup for persistent state.
src/filesystem/mount.rs Mount manager with tracking/cleanup + helpers.
src/filesystem/mod.rs Filesystem module exports and shared result type.
src/filesystem/fsck.rs fsck wrapper + exit code handling + kmsg rate limit control.
src/error.rs Error type hierarchy for subsystems and top-level init errors.
src/early_init.rs Early mounts for /dev, /proc, /sys, /run before logging.
src/config/mod.rs Config parsing from /proc/cmdline and later /etc/os-release.
src/bootloader/uboot.rs U-Boot env access via fw_printenv/fw_setenv.
src/bootloader/types.rs BootloaderType enum.
src/bootloader/mod.rs Bootloader trait + bootloader auto-detection + mock bootloader.
src/bootloader/grub.rs GRUB env access via grub-editenv against grubenv.
project-context.md Documents architecture, patterns, and key files/constraints.
build.rs Generates build-time constants from Yocto env vars.
README.md Project documentation: overview, build/test, architecture.
Cargo.toml Defines crate, dependencies, features, and release profile.
Cargo.lock Dependency lockfile for reproducible builds.
.gitignore Cargo/IDE/build artifact ignore rules.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Modifies the bootloader abstraction to store both the fsck exit code and its full diagnostic output. This data is gzip and base64 encoded using busybox utilities, allowing for full fsck logs to persist across reboots when errors are corrected.

Introduces a dedicated module for bootloader-related types and the encoding/decoding logic.

Enhances security by validating `fs-link` paths, rejecting absolute paths and those containing `..` components. Improves robustness of symlink creation by preventing replacement of existing directories. Corrects the path for grub-editenv detection.
@JoergZeidler
Copy link
Author

@copilot ready for review and use the current plan found in PR body

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an initial Rust-based /init implementation for the initramfs, replacing legacy shell logic with typed modules for device detection, filesystem setup, bootloader integration, runtime integration, and the final switch_root handoff to the real userspace init.

Changes:

  • Add core initramfs boot flow (main.rs) including essential mounts, root device + partition layout detection, fsck + mounting, overlays, and switch_root.
  • Introduce bootloader abstraction (GRUB/U-Boot) and persistence of fsck status/output across reboots.
  • Add runtime integrations (ODS runtime files, fs-link symlinks) plus foundational logging and error types.

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/runtime/switch_root.rs Implements switch_root via MS_MOVE + chroot + exec and includes init-path discovery.
src/runtime/omnect_device_service.rs Writes ODS runtime state into /run so it survives into the real root after root switch.
src/runtime/mod.rs Wires runtime submodules and re-exports runtime entry points.
src/runtime/fs_link.rs Implements fs-link config parsing and symlink creation with basic path safety checks.
src/partition/symlinks.rs Creates/verifies /dev/omnect/* symlinks for consistent partition access.
src/partition/mod.rs Defines the partition module public API and re-exports key types/functions.
src/partition/layout.rs Detects GPT vs DOS layouts and builds a consistent partition map including rootCurrent.
src/partition/device.rs Detects root device from kernel cmdline (GRUB via fsuuid/blkid; U-Boot via root=).
src/main.rs Implements the PID1 initramfs boot sequence and ties together all modules.
src/logging/mod.rs Exposes kmsg logger utilities.
src/logging/kmsg.rs Implements /dev/kmsg logging with kernel-level prefixes and early fatal logging helpers.
src/lib.rs Exposes crate modules and re-exports primary APIs for the binary.
src/filesystem/overlayfs.rs Sets up overlayfs for /etc and /home plus bind mounts and a raw-root bind mount.
src/filesystem/mount.rs Adds a mount manager with tracking/unmount-on-drop and helper mount APIs.
src/filesystem/mod.rs Defines filesystem module API surface and shared result types.
src/filesystem/fsck.rs Wraps fsck, interprets exit codes, and triggers reboot-required error on certain outcomes.
src/error.rs Adds the typed error hierarchy used across subsystems.
src/early_init.rs Mounts /dev, /proc, /sys, /run before logging/device operations.
src/config/mod.rs Loads config from /proc/cmdline and parses os-release once the rootfs is mounted.
src/bootloader/uboot.rs Adds U-Boot env access via fw_printenv/fw_setenv and fsck status persistence.
src/bootloader/types.rs Adds bootloader type enum plus fsck-output encoding/decoding helpers.
src/bootloader/mod.rs Defines the bootloader trait, GRUB/U-Boot detection, and a mock bootloader for tests.
src/bootloader/grub.rs Adds GRUB env access via grub-editenv and fsck status persistence.
project-context.md Documents architecture, patterns, and integration points for reviewers/contributors.
build.rs Generates build-time constants from Yocto env vars into config::build.
README.md Adds project overview, features, build/test instructions, and module layout documentation.
Cargo.toml Introduces the crate manifest, dependencies, features, and release profile settings.
Cargo.lock Adds lockfile for reproducible builds.
.gitignore Adds standard Rust/Cargo and IDE ignore rules.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Distinguishes between an expected "variable not found" exit code and actual command failures for `fw_printenv` operations, improving error detection.

Enhances `fsck` error reporting by capturing and propagating the specific exit code when a filesystem check requires a reboot. This clarifies that both code 1 (errors corrected) and code 2 (fsck requests reboot) mandate a system restart before the filesystem can be safely used.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an initial Rust-based init (/init) for the initramfs, replacing legacy shell scripts and establishing core boot primitives (device/partition detection, mounts/overlays, bootloader env access, runtime integration, and switch_root) for omnect-os.

Changes:

  • Add initramfs PID1 main flow: mount essentials, detect root device/layout, fsck+mount partitions, set up overlays, integrate with omnect-device-service, then switch_root.
  • Implement supporting subsystems: bootloader abstraction (GRUB/U-Boot), filesystem mount tracking + fsck wrapper, partition layout + /dev/omnect/* symlinks, runtime helpers (fs-links, ODS runtime files, switch_root).
  • Add project scaffolding/docs: Cargo config, build.rs generated constants, README/project context, logging to /dev/kmsg.

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/runtime/switch_root.rs Implements MS_MOVE + chroot + exec init switching to final rootfs.
src/runtime/omnect_device_service.rs Writes runtime files under /run/omnect-device-service for ODS consumption.
src/runtime/mod.rs Exposes runtime helpers (fs-links, ODS files, switch_root).
src/runtime/fs_link.rs Reads fs-link configs and creates safe symlinks in the rootfs.
src/partition/symlinks.rs Creates/verifies /dev/omnect/* symlinks for partitions and rootCurrent.
src/partition/mod.rs Partition module API + re-exports and Result alias.
src/partition/layout.rs Detects GPT vs DOS and builds a partition map for the platform.
src/partition/device.rs Detects root device from kernel cmdline (GRUB fsuuid path or U-Boot root= path).
src/main.rs PID1 entrypoint orchestrating the full initramfs boot flow and fatal error handling.
src/logging/mod.rs Logging module exports.
src/logging/kmsg.rs /dev/kmsg logger implementation with kernel level prefixes.
src/lib.rs Library exports for all subsystems used by the binary.
src/filesystem/overlayfs.rs Sets up overlayfs for /etc and /home and bind mounts for persistent paths.
src/filesystem/mount.rs MountManager with tracking + helpers for common mount patterns.
src/filesystem/mod.rs Filesystem module API and Result alias.
src/filesystem/fsck.rs fsck wrapper with exit-code handling + reboot-required propagation.
src/error.rs Typed error hierarchy for initramfs subsystems.
src/early_init.rs Early mounting of /dev, /proc, /sys, /run prior to logging and other ops.
src/config/mod.rs Parses /proc/cmdline, later reads /etc/os-release from mounted rootfs.
src/bootloader/uboot.rs U-Boot env integration via fw_printenv/fw_setenv.
src/bootloader/types.rs Shared bootloader types and fsck output encoding/decoding helpers.
src/bootloader/mod.rs Bootloader trait + runtime detection (GRUB tool presence vs U-Boot).
src/bootloader/grub.rs GRUB env integration via grub-editenv.
project-context.md High-level architecture/context documentation for reviewers and contributors.
build.rs Generates compile-time constants from Yocto env vars into OUT_DIR.
README.md Project overview, features, architecture, and build/test instructions.
Cargo.toml Crate definition, dependencies, features, and release profile.
Cargo.lock Dependency lockfile for reproducible builds.
.gitignore Standard Rust/Cargo and IDE ignores.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +29 to +82
pub fn switch_root(new_root: &Path, init: Option<&str>) -> Result<()> {
let init_path = init.unwrap_or(DEFAULT_INIT);

log::info!(
"Switching root to {} with init {}",
new_root.display(),
init_path
);
if !new_root.exists() {
return Err(InitramfsError::Io(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("New root does not exist: {}", new_root.display()),
)));
}

// Ensure target mountpoint directories exist under new_root.
// MS_MOVE fails with ENOENT if the target directory is missing.
for dir in &["dev", "proc", "sys", "run"] {
fs::create_dir_all(new_root.join(dir)).map_err(|e| {
InitramfsError::Io(std::io::Error::other(format!(
"Failed to create mountpoint {}/{}: {}",
new_root.display(),
dir,
e
)))
})?;
}

// Move critical mounts to new root before switching
move_mount("/dev", &new_root.join("dev"))?;
move_mount("/proc", &new_root.join("proc"))?;
move_mount("/sys", &new_root.join("sys"))?;
// /run must be moved so ODS can read its runtime state after root switching
move_mount("/run", &new_root.join("run"))?;

let init_full_path = find_init(new_root, init_path)?;

chdir(new_root).map_err(|e| {
InitramfsError::Io(std::io::Error::other(format!(
"Failed to chdir to new root: {}",
e
)))
})?;

// MS_MOVE re-mounts the new root at /. This is the correct approach for
// initramfs: ramfs does not support pivot_root (EINVAL). busybox and
// systemd use the same MS_MOVE + chroot pattern.
mount(Some("."), "/", None::<&str>, MsFlags::MS_MOVE, None::<&str>).map_err(|e| {
InitramfsError::Io(std::io::Error::other(format!(
"Failed to MS_MOVE new root to /: {}",
e
)))
})?;

Comment on lines +65 to +100
// Pipe compressed bytes through `base64 -w 0` (no line wrapping).
let base64_result = (|| -> std::io::Result<String> {
let mut b64 = Command::new("/usr/bin/base64")
.args(["-w", "0"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;

b64.stdin
.take()
.ok_or_else(|| std::io::Error::other("no base64 stdin"))?
.write_all(&compressed)?;

let out = b64.wait_with_output()?;
Ok(String::from_utf8_lossy(&out.stdout).trim().to_string())
})();

match base64_result {
Ok(s) => s,
Err(e) => {
log::warn!("encode_fsck_output: base64 failed: {e}");
String::new()
}
}
}

/// Decode a fsck result previously encoded with [`encode_fsck_output`].
///
/// Returns `(exit_code, output)` on success, or `None` if decoding fails.
pub fn decode_fsck_output(encoded: &str) -> Option<(i32, String)> {
// Decode base64 → compressed bytes.
let b64_out = Command::new("/usr/bin/base64")
.args(["-d"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
/// U-Boot bootloader implementation
///
/// Uses `fw_printenv` and `fw_setenv` to access environment variables.
/// Fsck status is stored as a plain integer exit code string.
Comment on lines +24 to +34
// Create partition symlinks
for (name, device_path) in &layout.partitions {
create_symlink(device_path, &symlink_path(name))?;
}

// Create rootCurrent symlink pointing to the active root partition
let root_current_target = layout.root_current();
create_symlink(
&root_current_target,
&symlink_path(partition_names::ROOT_CURRENT),
)?;
Comment on lines +119 to +130
/// Write the main status JSON file
fn write_status_file(ods_dir: &Path, status: &OdsStatus) -> Result<()> {
let status_path = ods_dir.join(ODS_STATUS_FILE);
let json = serde_json::to_string_pretty(status).map_err(|e| {
InitramfsError::Io(std::io::Error::other(format!(
"Failed to serialize ODS status: {}",
e
)))
})?;

fs::write(&status_path, json)?;
log::debug!("Wrote ODS status to {}", status_path.display());
## 6. Key Patterns
- **Error handling:** `thiserror` for typed errors, `Result<T>` everywhere
- **Bootloader abstraction:** `dyn Bootloader` trait for GRUB/U-Boot
- **Compression:** fsck exit code (integer) stored in bootloader env; full output written to `/data/var/log/fsck/<partition>.log`
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.

2 participants