feature: initial version of a rust based init process for the initramfs#3
feature: initial version of a rust based init process for the initramfs#3JoergZeidler wants to merge 34 commits intoomnect:mainfrom
Conversation
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.
|
@JanZachmann : ready to review, tested on x86/tauri and rpi |
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.
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.
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.
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.
There was a problem hiding this comment.
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, andswitch_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.
There was a problem hiding this comment.
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, andswitch_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.
There was a problem hiding this comment.
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 +
/datalogs). - Add runtime integrations: ODS runtime files and
fs-linksymlink 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.
|
@copilot ready for review and use the current plan found in PR body |
There was a problem hiding this comment.
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, andswitch_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.
There was a problem hiding this comment.
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.
| 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 | ||
| ))) | ||
| })?; | ||
|
|
| // 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. |
| // 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), | ||
| )?; |
| /// 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` |
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