diff --git a/Cargo.toml b/Cargo.toml index 3046cec0..b2c31837 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,12 +38,19 @@ bootloader_api = { version = "0.11.0", path = "api" } bootloader-x86_64-common = { version = "0.11.0", path = "common" } bootloader-x86_64-bios-common = { version = "0.11.0", path = "bios/common" } + +[features] +default = ["bios", "uefi", "pxe"] +bios = ["mbrman"] +uefi = ["gpt"] +pxe = ["uefi"] + [dependencies] anyhow = "1.0.32" fatfs = "0.3.4" -gpt = "3.0.0" -mbrman = "0.5.1" tempfile = "3.3.0" +mbrman = { version = "0.5.1", optional = true } +gpt = { version = "3.0.0", optional = true } [dev-dependencies] bootloader_test_runner = { path = "tests/runner" } diff --git a/build.rs b/build.rs index 7f04dddf..bb2118c0 100644 --- a/build.rs +++ b/build.rs @@ -3,22 +3,28 @@ use std::{ process::Command, }; -const BOOTLOADER_X86_64_UEFI_VERSION: &str = env!("CARGO_PKG_VERSION"); - -const BOOTLOADER_X86_64_BIOS_BOOT_SECTOR_VERSION: &str = env!("CARGO_PKG_VERSION"); -const BOOTLOADER_X86_64_BIOS_STAGE_2_VERSION: &str = env!("CARGO_PKG_VERSION"); -const BOOTLOADER_X86_64_BIOS_STAGE_3_VERSION: &str = env!("CARGO_PKG_VERSION"); -const BOOTLOADER_X86_64_BIOS_STAGE_4_VERSION: &str = env!("CARGO_PKG_VERSION"); +const BOOTLOADER_VERSION: &str = env!("CARGO_PKG_VERSION"); fn main() { - let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); + #[cfg(any(feature = "uefi", feature = "pxe"))] + uefi_main(); + #[cfg(feature = "bios")] + bios_main(); +} +#[cfg(all(any(feature = "uefi", feature = "pxe"), not(docsrs_dummy_build)))] +fn uefi_main() { + let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let uefi_path = build_uefi_bootloader(&out_dir); println!( "cargo:rustc-env=UEFI_BOOTLOADER_PATH={}", uefi_path.display() ); +} +#[cfg(all(feature = "bios", not(docsrs_dummy_build)))] +fn bios_main() { + let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let bios_boot_sector_path = build_bios_boot_sector(&out_dir); println!( "cargo:rustc-env=BIOS_BOOT_SECTOR_PATH={}", @@ -43,7 +49,7 @@ fn main() { ); } -#[cfg(not(docsrs_dummy_build))] +#[cfg(all(any(feature = "uefi", feature = "pxe"), not(docsrs_dummy_build)))] fn build_uefi_bootloader(out_dir: &Path) -> PathBuf { let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()); let mut cmd = Command::new(cargo); @@ -53,7 +59,7 @@ fn build_uefi_bootloader(out_dir: &Path) -> PathBuf { cmd.arg("--path").arg("uefi"); println!("cargo:rerun-if-changed=uefi"); } else { - cmd.arg("--version").arg(BOOTLOADER_X86_64_UEFI_VERSION); + cmd.arg("--version").arg(BOOTLOADER_VERSION); } cmd.arg("--locked"); cmd.arg("--target").arg("x86_64-unknown-uefi"); @@ -77,7 +83,7 @@ fn build_uefi_bootloader(out_dir: &Path) -> PathBuf { } } -#[cfg(not(docsrs_dummy_build))] +#[cfg(all(feature = "bios", not(docsrs_dummy_build)))] fn build_bios_boot_sector(out_dir: &Path) -> PathBuf { let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()); let mut cmd = Command::new(cargo); @@ -90,8 +96,7 @@ fn build_bios_boot_sector(out_dir: &Path) -> PathBuf { cmd.arg("--path").arg(&local_path); println!("cargo:rerun-if-changed={}", local_path.display()); } else { - cmd.arg("--version") - .arg(BOOTLOADER_X86_64_BIOS_BOOT_SECTOR_VERSION); + cmd.arg("--version").arg(BOOTLOADER_VERSION); } cmd.arg("--locked"); cmd.arg("--target").arg("i386-code16-boot-sector.json"); @@ -120,7 +125,7 @@ fn build_bios_boot_sector(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path) } -#[cfg(not(docsrs_dummy_build))] +#[cfg(all(feature = "bios", not(docsrs_dummy_build)))] fn build_bios_stage_2(out_dir: &Path) -> PathBuf { let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()); let mut cmd = Command::new(cargo); @@ -133,8 +138,7 @@ fn build_bios_stage_2(out_dir: &Path) -> PathBuf { cmd.arg("--path").arg(&local_path); println!("cargo:rerun-if-changed={}", local_path.display()); } else { - cmd.arg("--version") - .arg(BOOTLOADER_X86_64_BIOS_STAGE_2_VERSION); + cmd.arg("--version").arg(BOOTLOADER_VERSION); } cmd.arg("--locked"); cmd.arg("--target").arg("i386-code16-stage-2.json"); @@ -161,7 +165,7 @@ fn build_bios_stage_2(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path) } -#[cfg(not(docsrs_dummy_build))] +#[cfg(all(feature = "bios", not(docsrs_dummy_build)))] fn build_bios_stage_3(out_dir: &Path) -> PathBuf { let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()); let mut cmd = Command::new(cargo); @@ -174,8 +178,7 @@ fn build_bios_stage_3(out_dir: &Path) -> PathBuf { cmd.arg("--path").arg(&local_path); println!("cargo:rerun-if-changed={}", local_path.display()); } else { - cmd.arg("--version") - .arg(BOOTLOADER_X86_64_BIOS_STAGE_3_VERSION); + cmd.arg("--version").arg(BOOTLOADER_VERSION); } cmd.arg("--locked"); cmd.arg("--target").arg("i686-stage-3.json"); @@ -202,7 +205,7 @@ fn build_bios_stage_3(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path) } -#[cfg(not(docsrs_dummy_build))] +#[cfg(all(feature = "bios", not(docsrs_dummy_build)))] fn build_bios_stage_4(out_dir: &Path) -> PathBuf { let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".into()); let mut cmd = Command::new(cargo); @@ -215,8 +218,7 @@ fn build_bios_stage_4(out_dir: &Path) -> PathBuf { cmd.arg("--path").arg(&local_path); println!("cargo:rerun-if-changed={}", local_path.display()); } else { - cmd.arg("--version") - .arg(BOOTLOADER_X86_64_BIOS_STAGE_4_VERSION); + cmd.arg("--version").arg(BOOTLOADER_VERSION); } cmd.arg("--locked"); cmd.arg("--target").arg("x86_64-stage-4.json"); @@ -244,6 +246,7 @@ fn build_bios_stage_4(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path) } +#[cfg(all(feature = "bios", not(docsrs_dummy_build)))] fn convert_elf_to_bin(elf_path: PathBuf) -> PathBuf { let flat_binary_path = elf_path.with_extension("bin"); @@ -273,23 +276,10 @@ fn convert_elf_to_bin(elf_path: PathBuf) -> PathBuf { // dummy implementations because docsrs builds have no network access -#[cfg(docsrs_dummy_build)] -fn build_uefi_bootloader(_out_dir: &Path) -> PathBuf { - PathBuf::new() -} -#[cfg(docsrs_dummy_build)] -fn build_bios_boot_sector(_out_dir: &Path) -> PathBuf { - PathBuf::new() -} -#[cfg(docsrs_dummy_build)] -fn build_bios_stage_2(_out_dir: &Path) -> PathBuf { - PathBuf::new() -} -#[cfg(docsrs_dummy_build)] -fn build_bios_stage_3(_out_dir: &Path) -> PathBuf { - PathBuf::new() -} -#[cfg(docsrs_dummy_build)] -fn build_bios_stage_4(_out_dir: &Path) -> PathBuf { - PathBuf::new() +#[cfg(all(feature = "uefi", docsrs_dummy_build))] +fn uefi_main() { + // stub } + +#[cfg(all(feature = "bios", docsrs_dummy_build))] +fn bios_main() {} diff --git a/src/lib.rs b/src/lib.rs index c8045d38..4f172791 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,15 +12,14 @@ use std::{ use tempfile::NamedTempFile; mod fat; +#[cfg(feature = "uefi")] mod gpt; + +#[cfg(feature = "bios")] mod mbr; const KERNEL_FILE_NAME: &str = "kernel-x86_64"; const RAMDISK_FILE_NAME: &str = "ramdisk"; -const BIOS_STAGE_3: &str = "boot-stage-3"; -const BIOS_STAGE_4: &str = "boot-stage-4"; -const UEFI_BOOT_FILENAME: &str = "efi/boot/bootx64.efi"; -const UEFI_TFTP_BOOT_FILENAME: &str = "bootloader"; struct DiskImageFile<'a> { source: &'a PathBuf, @@ -87,9 +86,11 @@ impl<'a> DiskImageBuilder<'a> { Ok(out_file) } - + #[cfg(feature = "bios")] /// Create an MBR disk image for booting on BIOS systems. pub fn create_bios_image(&self, image_filename: &Path) -> anyhow::Result<()> { + const BIOS_STAGE_3: &str = "boot-stage-3"; + const BIOS_STAGE_4: &str = "boot-stage-4"; let bootsector_path = Path::new(env!("BIOS_BOOT_SECTOR_PATH")); let stage_2_path = Path::new(env!("BIOS_STAGE_2_PATH")); let stage_3_path = Path::new(env!("BIOS_STAGE_3_PATH")); @@ -114,8 +115,11 @@ impl<'a> DiskImageBuilder<'a> { .context("failed to delete FAT partition after disk image creation")?; Ok(()) } + + #[cfg(feature = "uefi")] /// Create a GPT disk image for booting on UEFI systems. pub fn create_uefi_image(&self, image_filename: &Path) -> anyhow::Result<()> { + const UEFI_BOOT_FILENAME: &str = "efi/boot/bootx64.efi"; let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); let mut internal_files = BTreeMap::new(); internal_files.insert(UEFI_BOOT_FILENAME, bootloader_path); @@ -131,8 +135,10 @@ impl<'a> DiskImageBuilder<'a> { Ok(()) } + #[cfg(all(feature = "uefi", feature = "pxe"))] /// Create a folder containing the needed files for UEFI TFTP/PXE booting. pub fn create_uefi_tftp_folder(&self, tftp_path: &Path) -> anyhow::Result<()> { + const UEFI_TFTP_BOOT_FILENAME: &str = "bootloader"; let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); std::fs::create_dir_all(tftp_path) .with_context(|| format!("failed to create out dir at {}", tftp_path.display()))?;