Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions src/bios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ impl Bios {
}

// check bios_boot partition on gpt type disk
#[allow(dead_code)]
fn get_bios_boot_partition(&self) -> Option<String> {
match blockdev::get_single_device("/") {
Ok(device) => {
Expand Down Expand Up @@ -147,24 +148,37 @@ impl Component for Bios {
Ok(meta)
}

fn query_adopt(&self) -> Result<Option<Adoptable>> {
fn query_adopt(&self, devices: &Option<Vec<String>>) -> Result<Option<Adoptable>> {
#[cfg(target_arch = "x86_64")]
if crate::efi::is_efi_booted()? && self.get_bios_boot_partition().is_none() {
if crate::efi::is_efi_booted()? && devices.is_none() {
log::debug!("Skip BIOS adopt");
return Ok(None);
}
crate::component::query_adopt_state()
}

fn adopt_update(&self, _: &openat::Dir, update: &ContentMetadata) -> Result<InstalledContent> {
let Some(meta) = self.query_adopt()? else {
fn adopt_update(
&self,
rootcxt: &RootContext,
update: &ContentMetadata,
) -> Result<InstalledContent> {
let bios_devices = blockdev::find_colocated_bios_boot(&rootcxt.devices)?;
let Some(meta) = self.query_adopt(&bios_devices)? else {
anyhow::bail!("Failed to find adoptable system")
};

let target_root = "/";
let device = blockdev::get_single_device(&target_root)?;
self.run_grub_install(target_root, &device)?;
log::debug!("Install grub modules on {device}");
let mut parent_devices = rootcxt.devices.iter();
let Some(parent) = parent_devices.next() else {
anyhow::bail!("Failed to find parent device");
};

if let Some(next) = parent_devices.next() {
anyhow::bail!(
"Found multiple parent devices {parent} and {next}; not currently supported"
);
}
self.run_grub_install(rootcxt.path.as_str(), &parent)?;
log::debug!("Installed grub modules on {parent}");
Ok(InstalledContent {
meta: update.clone(),
filetree: None,
Expand All @@ -176,12 +190,12 @@ impl Component for Bios {
get_component_update(sysroot, self)
}

fn run_update(&self, sysroot: &RootContext, _: &InstalledContent) -> Result<InstalledContent> {
fn run_update(&self, rootcxt: &RootContext, _: &InstalledContent) -> Result<InstalledContent> {
let updatemeta = self
.query_update(&sysroot.sysroot)?
.query_update(&rootcxt.sysroot)?
.expect("update available");

let mut parent_devices = sysroot.devices.iter();
let mut parent_devices = rootcxt.devices.iter();
let Some(parent) = parent_devices.next() else {
anyhow::bail!("Failed to find parent device");
};
Expand All @@ -192,7 +206,7 @@ impl Component for Bios {
);
}

self.run_grub_install(sysroot.path.as_str(), &parent)?;
self.run_grub_install(rootcxt.path.as_str(), &parent)?;
log::debug!("Install grub modules on {parent}");

let adopted_from = None;
Expand Down
37 changes: 17 additions & 20 deletions src/blockdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub fn get_devices<P: AsRef<Path>>(target_root: P) -> Result<Vec<String>> {
}

// Get single device for the target root
#[allow(dead_code)]
pub fn get_single_device<P: AsRef<Path>>(target_root: P) -> Result<String> {
let mut devices = get_devices(&target_root)?.into_iter();
let Some(parent) = devices.next() else {
Expand All @@ -37,7 +38,6 @@ pub fn get_single_device<P: AsRef<Path>>(target_root: P) -> Result<String> {

/// Find esp partition on the same device
/// using sfdisk to get partitiontable
#[allow(dead_code)]
pub fn get_esp_partition(device: &str) -> Result<Option<String>> {
const ESP_TYPE_GUID: &str = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B";
let device_info: PartitionTable = bootc_blockdev::partitions_of(Utf8Path::new(device))?;
Expand All @@ -51,21 +51,20 @@ pub fn get_esp_partition(device: &str) -> Result<Option<String>> {
Ok(None)
}

/// Find all ESP partitions on the devices with mountpoint boot
#[allow(dead_code)]
pub fn find_colocated_esps<P: AsRef<Path>>(target_root: P) -> Result<Vec<String>> {
// first, get the parent device
let devices = get_devices(&target_root).with_context(|| "while looking for colocated ESPs")?;

// now, look for all ESPs on those devices
/// Find all ESP partitions on the devices
pub fn find_colocated_esps(devices: &Vec<String>) -> Result<Option<Vec<String>>> {
// look for all ESPs on those devices
let mut esps = Vec::new();
for device in devices {
if let Some(esp) = get_esp_partition(&device)? {
esps.push(esp)
}
}
log::debug!("Find esp partitions: {esps:?}");
Ok(esps)
if esps.is_empty() {
return Ok(None);
}
log::debug!("Found esp partitions: {esps:?}");
Ok(Some(esps))
}

/// Find bios_boot partition on the same device
Expand All @@ -82,20 +81,18 @@ pub fn get_bios_boot_partition(device: &str) -> Result<Option<String>> {
Ok(None)
}

/// Find all bios_boot partitions on the devices with mountpoint boot
#[allow(dead_code)]
pub fn find_colocated_bios_boot<P: AsRef<Path>>(target_root: P) -> Result<Vec<String>> {
// first, get the parent device
let devices =
get_devices(&target_root).with_context(|| "looking for colocated bios_boot parts")?;

// now, look for all bios_boot parts on those devices
/// Find all bios_boot partitions on the devices
pub fn find_colocated_bios_boot(devices: &Vec<String>) -> Result<Option<Vec<String>>> {
// look for all bios_boot parts on those devices
let mut bios_boots = Vec::new();
for device in devices {
if let Some(bios) = get_bios_boot_partition(&device)? {
bios_boots.push(bios)
}
}
log::debug!("Find bios_boot partitions: {bios_boots:?}");
Ok(bios_boots)
if bios_boots.is_empty() {
return Ok(None);
}
log::debug!("Found bios_boot partitions: {bios_boots:?}");
Ok(Some(bios_boots))
}
21 changes: 18 additions & 3 deletions src/bootupd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ pub(crate) fn adopt_and_update(name: &str, rootcxt: &RootContext) -> Result<Cont
SavedState::acquire_write_lock(sysroot).context("Failed to acquire write lock")?;

let inst = component
.adopt_update(&state_guard.sysroot, &update)
.adopt_update(&rootcxt, &update)
.context("Failed adopt and update")?;
state.installed.insert(component.name().into(), inst);

Expand Down Expand Up @@ -327,8 +327,23 @@ pub(crate) fn status() -> Result<Status> {

// Process the remaining components not installed
log::trace!("Remaining known components: {}", known_components.len());
for (name, component) in known_components {
if let Some(adopt_ver) = component.query_adopt()? {
for (name, _) in known_components {
// To determine if not-installed components can be adopted:
//
// `query_adopt_state()` checks for existing installation state,
// such as a `version` in `/sysroot/.coreos-aleph-version.json`,
// or the presence of `/ostree/deploy`.
//
// `component.query_adopt()` performs additional checks,
// including hardware/device requirements.
// For example, it will skip BIOS adoption if the system is booted via EFI
// and lacks a BIOS_BOOT partition.
//
// Once a component is determined to be adoptable, it is added to the
// adoptable list, and adoption proceeds automatically.
//
// Therefore, calling `query_adopt_state()` alone is sufficient.
if let Some(adopt_ver) = crate::component::query_adopt_state()? {
ret.adoptable.insert(name.to_string(), adopt_ver);
} else {
log::trace!("Not adoptable: {}", name);
Expand Down
6 changes: 3 additions & 3 deletions src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ pub(crate) trait Component {
/// In an operating system whose initially booted disk image is not
/// using bootupd, detect whether it looks like the component exists
/// and "synthesize" content metadata from it.
fn query_adopt(&self) -> Result<Option<Adoptable>>;
fn query_adopt(&self, devices: &Option<Vec<String>>) -> Result<Option<Adoptable>>;

/// Given an adoptable system and an update, perform the update.
fn adopt_update(
&self,
sysroot: &openat::Dir,
rootcxt: &RootContext,
update: &ContentMetadata,
) -> Result<InstalledContent>;

Expand Down Expand Up @@ -66,7 +66,7 @@ pub(crate) trait Component {
/// Used on the client to run an update.
fn run_update(
&self,
sysroot: &RootContext,
rootcxt: &RootContext,
current: &InstalledContent,
) -> Result<InstalledContent>;

Expand Down
Loading