Skip to content

Commit

Permalink
Skip UEFI or BIOS on none hybrid partition layout
Browse files Browse the repository at this point in the history
- When booting with `BIOS` and no `ESP` device detected, skip `UEFI`
checking
- When booting with `UEFI` and no `bios_boot` partition found, skip
`BIOS` checking

Fixes #717
  • Loading branch information
HuijingHei committed Sep 20, 2024
1 parent 7aa06b6 commit b1ca767
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 18 deletions.
53 changes: 51 additions & 2 deletions src/bios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,23 @@ use crate::packagesystem;
use anyhow::{bail, Result};

use crate::util;
use serde::{Deserialize, Serialize};

// grub2-install file path
pub(crate) const GRUB_BIN: &str = "usr/sbin/grub2-install";

#[derive(Serialize, Deserialize, Debug)]
struct BlockDevice {
path: String,
pttype: String,
parttypename: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Devices {
blockdevices: Vec<BlockDevice>,
}

#[derive(Default)]
pub(crate) struct Bios {}

Expand All @@ -22,12 +35,11 @@ impl Bios {
#[cfg(target_arch = "x86_64")]
{
// find /boot partition
let boot_dir = Path::new("/").join("boot");
cmd = Command::new("findmnt");
cmd.arg("--noheadings")
.arg("--output")
.arg("SOURCE")
.arg(boot_dir);
.arg("/boot");
let partition = util::cmd_output(&mut cmd)?;

// lsblk to find parent device
Expand Down Expand Up @@ -81,6 +93,38 @@ impl Bios {
}
Ok(())
}

// check bios_boot partition on gpt type disk
fn get_bios_boot_partition(&self) -> Result<Option<String>> {
let target = self.get_device()?;
// lsblk to list children with bios_boot
let output = Command::new("lsblk")
.args([
"--json",
"--output",
"PATH,PTTYPE,PARTTYPENAME",
target.trim(),
])
.output()?;
if !output.status.success() {
std::io::stderr().write_all(&output.stderr)?;
bail!("Failed to run lsblk");
}

let output = String::from_utf8(output.stdout)?;
// Parse the JSON string into the `Devices` struct
let devices: Devices = serde_json::from_str(&output).expect("JSON was not well-formatted");

// Find the device with the parttypename "BIOS boot"
for device in devices.blockdevices {
if let Some(parttypename) = &device.parttypename {
if parttypename == "BIOS boot" && device.pttype == "gpt" {
return Ok(Some(device.path));
}
}
}
Ok(None)
}
}

impl Component for Bios {
Expand Down Expand Up @@ -120,6 +164,11 @@ impl Component for Bios {
}

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

Expand Down
6 changes: 1 addition & 5 deletions src/bootupd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,11 +380,7 @@ pub(crate) fn print_status(status: &Status) -> Result<()> {

#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
{
let boot_method = if Path::new("/sys/firmware/efi").exists() {
"EFI"
} else {
"BIOS"
};
let boot_method = if efi::is_efi_booted()? { "EFI" } else { "BIOS" };
println!("Boot method: {}", boot_method);
}

Expand Down
35 changes: 24 additions & 11 deletions src/efi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ impl Efi {
}

fn open_esp_optional(&self) -> Result<Option<openat::Dir>> {
if !is_efi_booted()? && self.get_esp_device().is_none() {
log::debug!("Skip EFI");
return Ok(None);
}
let sysroot = openat::Dir::open("/")?;
let esp = sysroot.sub_dir_optional(&self.esp_path()?)?;
Ok(esp)
Expand All @@ -75,6 +79,20 @@ impl Efi {
Ok(esp)
}

fn get_esp_device(&self) -> Option<PathBuf> {
let esp_devices = [COREOS_ESP_PART_LABEL, ANACONDA_ESP_PART_LABEL]
.into_iter()
.map(|p| Path::new("/dev/disk/by-partlabel/").join(p));
let mut esp_device = None;
for path in esp_devices {
if path.exists() {
esp_device = Some(path);
break;
}
}
return esp_device;
}

pub(crate) fn ensure_mounted_esp(&self, root: &Path) -> Result<PathBuf> {
let mut mountpoint = self.mountpoint.borrow_mut();
if let Some(mountpoint) = mountpoint.as_deref() {
Expand All @@ -94,17 +112,9 @@ impl Efi {
return Ok(mnt);
}

let esp_devices = [COREOS_ESP_PART_LABEL, ANACONDA_ESP_PART_LABEL]
.into_iter()
.map(|p| Path::new("/dev/disk/by-partlabel/").join(p));
let mut esp_device = None;
for path in esp_devices {
if path.exists() {
esp_device = Some(path);
break;
}
}
let esp_device = esp_device.ok_or_else(|| anyhow::anyhow!("Failed to find ESP device"))?;
let esp_device = self
.get_esp_device()
.ok_or_else(|| anyhow::anyhow!("Failed to find ESP device"))?;
for &mnt in ESP_MOUNTS.iter() {
let mnt = root.join(mnt);
if !mnt.exists() {
Expand Down Expand Up @@ -386,6 +396,9 @@ impl Component for Efi {
}

fn validate(&self, current: &InstalledContent) -> Result<ValidationResult> {
if !is_efi_booted()? && self.get_esp_device().is_none() {
return Ok(ValidationResult::Skip);
}
let currentf = current
.filetree
.as_ref()
Expand Down

0 comments on commit b1ca767

Please sign in to comment.