fastboop-schema 0.0.1-rc.21

Schema types for fastboop device and boot profiles.
Documentation
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;

use gibblox_pipeline::bin::PipelineSourceBin;

use serde::{Deserialize, Serialize};

use crate::{
    Boot, BootProfile, BootProfileArtifactPathSource, BootProfileArtifactSource, BootProfileDevice,
    BootProfileDeviceStage0, BootProfileRootfs, BootProfileRootfsErofsSource,
    BootProfileRootfsExt4Source, BootProfileRootfsFatSource, BootProfileRootfsFilesystemSource,
    BootProfileRootfsOstreeSource, BootProfileStage0, DeviceProfile, ExistsFlag, FastbootGetvarEq,
    FastbootGetvarExists, FastbootGetvarNotEq, FastbootGetvarNotExists, FastbootGetvarStartsWith,
    InjectMac, MatchRule, NotExistsFlag, ProbeStep,
};

// v0 wire formats are intentionally unstable while fastboop is unreleased.
pub const BOOT_PROFILE_BIN_FORMAT_V0: u16 = 0;
pub const BOOT_PROFILE_BIN_V0_MAGIC: [u8; 8] = *b"FBOOPROF";
pub const BOOT_PROFILE_BIN_V0_HEADER_LEN: usize = 10;

// v0 wire formats are intentionally unstable while fastboop is unreleased.
pub const DEV_PROFILE_BIN_FORMAT_V0: u16 = 0;
pub const DEV_PROFILE_BIN_V0_MAGIC: [u8; 8] = *b"FBOODEVP";
pub const DEV_PROFILE_BIN_V0_HEADER_LEN: usize = 10;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BootProfileBin {
    pub id: String,
    pub display_name: Option<String>,
    pub rootfs: BootProfileRootfsBin,
    pub kernel: Option<BootProfileArtifactPathSourceBin>,
    pub dtbs: Option<BootProfileArtifactPathSourceBin>,
    pub dt_overlays: Vec<Vec<u8>>,
    pub extra_cmdline: Option<String>,
    pub stage0: BootProfileStage0Bin,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BootProfileArtifactPathSourceBin {
    pub path: String,
    pub source: BootProfileRootfsBin,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum BootProfileRootfsBin {
    Ostree {
        source: BootProfileRootfsFilesystemBin,
    },
    Erofs {
        source: PipelineSourceBin,
    },
    Ext4 {
        source: PipelineSourceBin,
    },
    Fat {
        source: PipelineSourceBin,
    },
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum BootProfileRootfsFilesystemBin {
    Erofs { source: PipelineSourceBin },
    Ext4 { source: PipelineSourceBin },
    Fat { source: PipelineSourceBin },
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BootProfileStage0Bin {
    pub kernel_modules: Vec<String>,
    pub devices: BTreeMap<String, BootProfileDeviceBin>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BootProfileDeviceBin {
    pub dt_overlays: Vec<Vec<u8>>,
    pub extra_cmdline: Option<String>,
    pub stage0: BootProfileDeviceStage0Bin,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BootProfileDeviceStage0Bin {
    pub kernel_modules: Vec<String>,
    pub inject_mac: Option<InjectMacBin>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceProfileBin {
    pub id: String,
    pub display_name: Option<String>,
    pub devicetree_name: String,
    pub r#match: Vec<MatchRule>,
    pub probe: Vec<ProbeStepBin>,
    pub boot: Boot,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum ProbeStepBin {
    FastbootGetvarEq { name: String, equals: String },
    FastbootGetvarStartsWith { name: String, starts_with: String },
    FastbootGetvarNotEq { name: String, not_equals: String },
    FastbootGetvarExists { name: String },
    FastbootGetvarNotExists { name: String },
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InjectMacBin {
    pub wifi: Option<String>,
    pub bluetooth: Option<String>,
}

impl From<DeviceProfile> for DeviceProfileBin {
    fn from(profile: DeviceProfile) -> Self {
        Self {
            id: profile.id,
            display_name: profile.display_name,
            devicetree_name: profile.devicetree_name,
            r#match: profile.r#match,
            probe: profile.probe.into_iter().map(ProbeStepBin::from).collect(),
            boot: profile.boot,
        }
    }
}

impl From<DeviceProfileBin> for DeviceProfile {
    fn from(profile: DeviceProfileBin) -> Self {
        Self {
            id: profile.id,
            display_name: profile.display_name,
            devicetree_name: profile.devicetree_name,
            r#match: profile.r#match,
            probe: profile.probe.into_iter().map(ProbeStep::from).collect(),
            boot: profile.boot,
        }
    }
}

impl From<ProbeStep> for ProbeStepBin {
    fn from(step: ProbeStep) -> Self {
        match step {
            ProbeStep::FastbootGetvarEq(FastbootGetvarEq { name, equals }) => {
                ProbeStepBin::FastbootGetvarEq { name, equals }
            }
            ProbeStep::FastbootGetvarStartsWith(FastbootGetvarStartsWith { name, starts_with }) => {
                ProbeStepBin::FastbootGetvarStartsWith { name, starts_with }
            }
            ProbeStep::FastbootGetvarNotEq(FastbootGetvarNotEq { name, not_equals }) => {
                ProbeStepBin::FastbootGetvarNotEq { name, not_equals }
            }
            ProbeStep::FastbootGetvarExists(FastbootGetvarExists { name, .. }) => {
                ProbeStepBin::FastbootGetvarExists { name }
            }
            ProbeStep::FastbootGetvarNotExists(FastbootGetvarNotExists { name, .. }) => {
                ProbeStepBin::FastbootGetvarNotExists { name }
            }
        }
    }
}

impl From<ProbeStepBin> for ProbeStep {
    fn from(step: ProbeStepBin) -> Self {
        match step {
            ProbeStepBin::FastbootGetvarEq { name, equals } => {
                ProbeStep::FastbootGetvarEq(FastbootGetvarEq { name, equals })
            }
            ProbeStepBin::FastbootGetvarStartsWith { name, starts_with } => {
                ProbeStep::FastbootGetvarStartsWith(FastbootGetvarStartsWith { name, starts_with })
            }
            ProbeStepBin::FastbootGetvarNotEq { name, not_equals } => {
                ProbeStep::FastbootGetvarNotEq(FastbootGetvarNotEq { name, not_equals })
            }
            ProbeStepBin::FastbootGetvarExists { name } => {
                ProbeStep::FastbootGetvarExists(FastbootGetvarExists {
                    name,
                    exists: Some(ExistsFlag),
                })
            }
            ProbeStepBin::FastbootGetvarNotExists { name } => {
                ProbeStep::FastbootGetvarNotExists(FastbootGetvarNotExists {
                    name,
                    not_exists: Some(NotExistsFlag),
                })
            }
        }
    }
}

impl From<InjectMac> for InjectMacBin {
    fn from(mac: InjectMac) -> Self {
        Self {
            wifi: mac.wifi,
            bluetooth: mac.bluetooth,
        }
    }
}

impl From<InjectMacBin> for InjectMac {
    fn from(mac: InjectMacBin) -> Self {
        Self {
            wifi: mac.wifi,
            bluetooth: mac.bluetooth,
        }
    }
}

impl From<BootProfile> for BootProfileBin {
    fn from(profile: BootProfile) -> Self {
        Self {
            id: profile.id,
            display_name: profile.display_name,
            rootfs: BootProfileRootfsBin::from(profile.rootfs),
            kernel: profile.kernel.map(BootProfileArtifactPathSourceBin::from),
            dtbs: profile.dtbs.map(BootProfileArtifactPathSourceBin::from),
            dt_overlays: profile.dt_overlays,
            extra_cmdline: profile.extra_cmdline,
            stage0: BootProfileStage0Bin::from(profile.stage0),
        }
    }
}

impl From<BootProfileBin> for BootProfile {
    fn from(profile: BootProfileBin) -> Self {
        Self {
            id: profile.id,
            display_name: profile.display_name,
            rootfs: BootProfileRootfs::from(profile.rootfs),
            kernel: profile.kernel.map(BootProfileArtifactPathSource::from),
            dtbs: profile.dtbs.map(BootProfileArtifactPathSource::from),
            dt_overlays: profile.dt_overlays,
            extra_cmdline: profile.extra_cmdline,
            stage0: BootProfileStage0::from(profile.stage0),
        }
    }
}

impl From<BootProfileArtifactPathSource> for BootProfileArtifactPathSourceBin {
    fn from(source: BootProfileArtifactPathSource) -> Self {
        Self {
            path: source.path,
            source: BootProfileRootfsBin::from(source.source),
        }
    }
}

impl From<BootProfileArtifactPathSourceBin> for BootProfileArtifactPathSource {
    fn from(source: BootProfileArtifactPathSourceBin) -> Self {
        Self {
            path: source.path,
            source: BootProfileRootfs::from(source.source),
        }
    }
}

impl From<BootProfileRootfs> for BootProfileRootfsBin {
    fn from(rootfs: BootProfileRootfs) -> Self {
        match rootfs {
            BootProfileRootfs::Ostree(BootProfileRootfsOstreeSource { ostree }) => Self::Ostree {
                source: BootProfileRootfsFilesystemBin::from(ostree),
            },
            BootProfileRootfs::Erofs(BootProfileRootfsErofsSource { erofs }) => Self::Erofs {
                source: PipelineSourceBin::from(erofs),
            },
            BootProfileRootfs::Ext4(BootProfileRootfsExt4Source { ext4 }) => Self::Ext4 {
                source: PipelineSourceBin::from(ext4),
            },
            BootProfileRootfs::Fat(BootProfileRootfsFatSource { fat }) => Self::Fat {
                source: PipelineSourceBin::from(fat),
            },
        }
    }
}

impl From<BootProfileRootfsBin> for BootProfileRootfs {
    fn from(rootfs: BootProfileRootfsBin) -> Self {
        match rootfs {
            BootProfileRootfsBin::Ostree { source } => {
                Self::Ostree(BootProfileRootfsOstreeSource {
                    ostree: BootProfileRootfsFilesystemSource::from(source),
                })
            }
            BootProfileRootfsBin::Erofs { source } => Self::Erofs(BootProfileRootfsErofsSource {
                erofs: BootProfileArtifactSource::from(source),
            }),
            BootProfileRootfsBin::Ext4 { source } => Self::Ext4(BootProfileRootfsExt4Source {
                ext4: BootProfileArtifactSource::from(source),
            }),
            BootProfileRootfsBin::Fat { source } => Self::Fat(BootProfileRootfsFatSource {
                fat: BootProfileArtifactSource::from(source),
            }),
        }
    }
}

impl From<BootProfileRootfsFilesystemSource> for BootProfileRootfsFilesystemBin {
    fn from(source: BootProfileRootfsFilesystemSource) -> Self {
        match source {
            BootProfileRootfsFilesystemSource::Erofs(BootProfileRootfsErofsSource { erofs }) => {
                Self::Erofs {
                    source: PipelineSourceBin::from(erofs),
                }
            }
            BootProfileRootfsFilesystemSource::Ext4(BootProfileRootfsExt4Source { ext4 }) => {
                Self::Ext4 {
                    source: PipelineSourceBin::from(ext4),
                }
            }
            BootProfileRootfsFilesystemSource::Fat(BootProfileRootfsFatSource { fat }) => {
                Self::Fat {
                    source: PipelineSourceBin::from(fat),
                }
            }
        }
    }
}

impl From<BootProfileRootfsFilesystemBin> for BootProfileRootfsFilesystemSource {
    fn from(source: BootProfileRootfsFilesystemBin) -> Self {
        match source {
            BootProfileRootfsFilesystemBin::Erofs { source } => {
                Self::Erofs(BootProfileRootfsErofsSource {
                    erofs: BootProfileArtifactSource::from(source),
                })
            }
            BootProfileRootfsFilesystemBin::Ext4 { source } => {
                Self::Ext4(BootProfileRootfsExt4Source {
                    ext4: BootProfileArtifactSource::from(source),
                })
            }
            BootProfileRootfsFilesystemBin::Fat { source } => {
                Self::Fat(BootProfileRootfsFatSource {
                    fat: BootProfileArtifactSource::from(source),
                })
            }
        }
    }
}

impl From<BootProfileStage0> for BootProfileStage0Bin {
    fn from(stage0: BootProfileStage0) -> Self {
        Self {
            kernel_modules: stage0.kernel_modules,
            devices: stage0
                .devices
                .into_iter()
                .map(|(device_id, device)| (device_id, BootProfileDeviceBin::from(device)))
                .collect(),
        }
    }
}

impl From<BootProfileStage0Bin> for BootProfileStage0 {
    fn from(stage0: BootProfileStage0Bin) -> Self {
        Self {
            kernel_modules: stage0.kernel_modules,
            devices: stage0
                .devices
                .into_iter()
                .map(|(device_id, device)| (device_id, BootProfileDevice::from(device)))
                .collect(),
        }
    }
}

impl From<BootProfileDevice> for BootProfileDeviceBin {
    fn from(device: BootProfileDevice) -> Self {
        Self {
            dt_overlays: device.dt_overlays,
            extra_cmdline: device.extra_cmdline,
            stage0: BootProfileDeviceStage0Bin::from(device.stage0),
        }
    }
}

impl From<BootProfileDeviceBin> for BootProfileDevice {
    fn from(device: BootProfileDeviceBin) -> Self {
        Self {
            dt_overlays: device.dt_overlays,
            extra_cmdline: device.extra_cmdline,
            stage0: BootProfileDeviceStage0::from(device.stage0),
        }
    }
}

impl From<BootProfileDeviceStage0> for BootProfileDeviceStage0Bin {
    fn from(stage0: BootProfileDeviceStage0) -> Self {
        Self {
            kernel_modules: stage0.kernel_modules,
            inject_mac: stage0.inject_mac.map(InjectMacBin::from),
        }
    }
}

impl From<BootProfileDeviceStage0Bin> for BootProfileDeviceStage0 {
    fn from(stage0: BootProfileDeviceStage0Bin) -> Self {
        Self {
            kernel_modules: stage0.kernel_modules,
            inject_mac: stage0.inject_mac.map(InjectMac::from),
        }
    }
}