From 69596a1388ecd81c0582320e8d56e00f97ac51d2 Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Wed, 18 Oct 2023 02:25:59 +1100 Subject: [PATCH 1/9] Initial commit --- Cargo.toml | 1 + src/lib.rs | 100 +++++++++++++++++++++++++++++++++++++++++++++-------- src/mbr.rs | 60 +++++++++++++++++++++++++++----- 3 files changed, 138 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 49dfb111..42e5c124 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ bootloader-x86_64-bios-common = { version = "0.11.4", path = "bios/common" } default = ["bios", "uefi"] bios = ["dep:mbrman"] uefi = ["dep:gpt"] +embedded_binaries = [] [dependencies] anyhow = "1.0.32" diff --git a/src/lib.rs b/src/lib.rs index 179f1d10..ea620d2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,6 +41,18 @@ const KERNEL_FILE_NAME: &str = "kernel-x86_64"; const RAMDISK_FILE_NAME: &str = "ramdisk"; const CONFIG_FILE_NAME: &str = "boot.json"; +#[cfg(all(feature = "embedded_binaries", feature = "uefi"))] +static UEFI_BOOTLOADER: &'static [u8] = include_bytes!(env!("UEFI_BOOTLOADER_PATH")); + +#[cfg(all(feature = "embedded_binaries", feature = "bios"))] +static BIOS_BOOT_SECTOR: &'static [u8] = include_bytes!(env!("BIOS_BOOT_SECTOR_PATH")); +#[cfg(all(feature = "embedded_binaries", feature = "bios"))] +static BIOS_STAGE_2: &'static [u8] = include_bytes!(env!("BIOS_STAGE_2_PATH")); +#[cfg(all(feature = "embedded_binaries", feature = "bios"))] +static BIOS_STAGE_3: &'static [u8] = include_bytes!(env!("BIOS_STAGE_3_PATH")); +#[cfg(all(feature = "embedded_binaries", feature = "bios"))] +static BIOS_STAGE_4: &'static [u8] = include_bytes!(env!("BIOS_STAGE_4_PATH")); + /// Allows creating disk images for a specified set of files. /// /// It can currently create `MBR` (BIOS), `GPT` (UEFI), and `TFTP` (UEFI) images. @@ -95,22 +107,22 @@ impl DiskImageBuilder { self.set_file_source(destination.into(), FileDataSource::File(file_path)) } - #[cfg(feature = "bios")] + #[cfg(all(feature = "bios", not(feature = "embedded_binaries")))] /// Create an MBR disk image for booting on BIOS systems. pub fn create_bios_image(&self, image_path: &Path) -> anyhow::Result<()> { - const BIOS_STAGE_3: &str = "boot-stage-3"; - const BIOS_STAGE_4: &str = "boot-stage-4"; + const BIOS_STAGE_3_NAME: &str = "boot-stage-3"; + const BIOS_STAGE_4_NAME: &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")); let stage_4_path = Path::new(env!("BIOS_STAGE_4_PATH")); let mut internal_files = BTreeMap::new(); internal_files.insert( - BIOS_STAGE_3, + BIOS_STAGE_3_NAME, FileDataSource::File(stage_3_path.to_path_buf()), ); internal_files.insert( - BIOS_STAGE_4, + BIOS_STAGE_4_NAME, FileDataSource::File(stage_4_path.to_path_buf()), ); @@ -131,15 +143,58 @@ impl DiskImageBuilder { Ok(()) } + #[cfg(all(feature = "bios", feature = "embedded_binaries"))] + /// Create an MBR disk image for booting on BIOS systems. + pub fn create_bios_image(&self, image_path: &Path) -> anyhow::Result<()> { + const BIOS_STAGE_3_NAME: &str = "boot-stage-3"; + const BIOS_STAGE_4_NAME: &str = "boot-stage-4"; + let stage_3 = FileDataSource::Data(BIOS_STAGE_3.to_vec()); + let stage_4 = FileDataSource::Data(BIOS_STAGE_4.to_vec()); + let mut internal_files = BTreeMap::new(); + internal_files.insert( + BIOS_STAGE_3_NAME, + stage_3, + ); + internal_files.insert( + BIOS_STAGE_4_NAME, + stage_4, + ); + let fat_partition = self + .create_fat_filesystem_image(internal_files) + .context("failed to create FAT partition")?; + mbr::create_mbr_disk( + BIOS_BOOT_SECTOR, + BIOS_STAGE_2, + fat_partition.path(), + image_path, + ) + .context("failed to create BIOS MBR disk image")?; + + fat_partition + .close() + .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_path: &Path) -> anyhow::Result<()> { const UEFI_BOOT_FILENAME: &str = "efi/boot/bootx64.efi"; - let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); + + #[cfg(feature = "embedded_binaries")] + fn get_uefi_bootloader() -> FileDataSource { + FileDataSource::Data(UEFI_BOOTLOADER.to_vec()) + } + #[cfg(not(feature = "embedded_binaries"))] + fn get_uefi_bootloader() -> FileDataSource { + let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); + FileDataSource::File(bootloader_path.to_path_buf()) + } + let mut internal_files = BTreeMap::new(); internal_files.insert( UEFI_BOOT_FILENAME, - FileDataSource::File(bootloader_path.to_path_buf()), + get_uefi_bootloader(), ); let fat_partition = self .create_fat_filesystem_image(internal_files) @@ -158,19 +213,34 @@ impl DiskImageBuilder { pub fn create_uefi_tftp_folder(&self, tftp_path: &Path) -> anyhow::Result<()> { use std::{fs, ops::Deref}; + #[cfg(feature = "embedded_binaries")] + fn write_uefi_bootloader(to: &PathBuf) -> anyhow::Result<()> { + fs::write(to, UEFI_BOOTLOADER).with_context(|| { + format!( + "failed to copy bootloader from the embedded binary to {}", + to.display() + ) + }) + } + #[cfg(not(feature = "embedded_binaries"))] + fn write_uefi_bootloader(to: &PathBuf) -> anyhow::Result<()> { + let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); + fs::copy(bootloader_path, &to).map(|_| ()).with_context(|| { + format!( + "failed to copy bootloader from {} to {}", + bootloader_path.display(), + to.display() + ) + }) + } + const UEFI_TFTP_BOOT_FILENAME: &str = "bootloader"; - let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); fs::create_dir_all(tftp_path) .with_context(|| format!("failed to create out dir at {}", tftp_path.display()))?; let to = tftp_path.join(UEFI_TFTP_BOOT_FILENAME); - fs::copy(bootloader_path, &to).with_context(|| { - format!( - "failed to copy bootloader from {} to {}", - bootloader_path.display(), - to.display() - ) - })?; + write_uefi_bootloader(&to)?; + for f in &self.files { let to = tftp_path.join(f.0.deref()); diff --git a/src/mbr.rs b/src/mbr.rs index 6c7a9f0d..36922224 100644 --- a/src/mbr.rs +++ b/src/mbr.rs @@ -2,18 +2,65 @@ use anyhow::Context; use mbrman::BOOT_ACTIVE; use std::{ fs::{self, File}, - io::{self, Seek, SeekFrom}, + io::{self, Read, Seek, SeekFrom}, path::Path, }; + const SECTOR_SIZE: u32 = 512; +#[cfg(not(feature = "embedded_binaries"))] pub fn create_mbr_disk( bootsector_path: &Path, second_stage_path: &Path, boot_partition_path: &Path, out_mbr_path: &Path, ) -> anyhow::Result<()> { - let mut boot_sector = File::open(bootsector_path).context("failed to open boot sector")?; + let second_stage = File::open(second_stage_path).context("failed to open second stage binary")?; + create_mbr_disk_with_readers( + File::open(bootsector_path).context("failed to open boot sector")?, + SecondStageData { + size: second_stage.metadata() + .context("failed to read file metadata of second stage")? + .len(), + reader: second_stage + }, + boot_partition_path, + out_mbr_path + ) +} + +#[cfg(feature = "embedded_binaries")] +pub fn create_mbr_disk( + bootsector_binary: &[u8], + second_stage_binary: &[u8], + boot_partition_path: &Path, + out_mbr_path: &Path, +) -> anyhow::Result<()> { + use std::io::Cursor; + create_mbr_disk_with_readers( + Cursor::new(bootsector_binary), + SecondStageData { + size: second_stage_binary.len() as u64, + reader: Cursor::new(second_stage_binary), + }, + boot_partition_path, + out_mbr_path + ) +} + +struct SecondStageData { + size: u64, + reader: R, +} + +fn create_mbr_disk_with_readers( + bootsector_reader: R, + second_stage_data: SecondStageData, + boot_partition_path: &Path, + out_mbr_path: &Path, +) -> anyhow::Result<()> { + // let mut boot_sector = File::open(bootsector_path).context("failed to open boot sector")?; + let mut boot_sector = bootsector_reader; let mut mbr = mbrman::MBR::read_from(&mut boot_sector, SECTOR_SIZE).context("failed to read MBR")?; @@ -23,12 +70,9 @@ pub fn create_mbr_disk( } } - let mut second_stage = - File::open(second_stage_path).context("failed to open second stage binary")?; - let second_stage_size = second_stage - .metadata() - .context("failed to read file metadata of second stage")? - .len(); + let mut second_stage = second_stage_data.reader; + let second_stage_size = second_stage_data.size; + let second_stage_start_sector = 1; let second_stage_sectors = ((second_stage_size - 1) / u64::from(SECTOR_SIZE) + 1) .try_into() From 8be25883dbb4ac87707f9af318482a5a2b57c19c Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Wed, 18 Oct 2023 02:41:16 +1100 Subject: [PATCH 2/9] Run cargo fmt --- src/lib.rs | 16 +++------------- src/mbr.rs | 16 +++++++++------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ea620d2c..84dbdbaf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,14 +151,8 @@ impl DiskImageBuilder { let stage_3 = FileDataSource::Data(BIOS_STAGE_3.to_vec()); let stage_4 = FileDataSource::Data(BIOS_STAGE_4.to_vec()); let mut internal_files = BTreeMap::new(); - internal_files.insert( - BIOS_STAGE_3_NAME, - stage_3, - ); - internal_files.insert( - BIOS_STAGE_4_NAME, - stage_4, - ); + internal_files.insert(BIOS_STAGE_3_NAME, stage_3); + internal_files.insert(BIOS_STAGE_4_NAME, stage_4); let fat_partition = self .create_fat_filesystem_image(internal_files) .context("failed to create FAT partition")?; @@ -192,10 +186,7 @@ impl DiskImageBuilder { } let mut internal_files = BTreeMap::new(); - internal_files.insert( - UEFI_BOOT_FILENAME, - get_uefi_bootloader(), - ); + internal_files.insert(UEFI_BOOT_FILENAME, get_uefi_bootloader()); let fat_partition = self .create_fat_filesystem_image(internal_files) .context("failed to create FAT partition")?; @@ -240,7 +231,6 @@ impl DiskImageBuilder { let to = tftp_path.join(UEFI_TFTP_BOOT_FILENAME); write_uefi_bootloader(&to)?; - for f in &self.files { let to = tftp_path.join(f.0.deref()); diff --git a/src/mbr.rs b/src/mbr.rs index 36922224..4298a602 100644 --- a/src/mbr.rs +++ b/src/mbr.rs @@ -15,17 +15,19 @@ pub fn create_mbr_disk( boot_partition_path: &Path, out_mbr_path: &Path, ) -> anyhow::Result<()> { - let second_stage = File::open(second_stage_path).context("failed to open second stage binary")?; + let second_stage = + File::open(second_stage_path).context("failed to open second stage binary")?; create_mbr_disk_with_readers( File::open(bootsector_path).context("failed to open boot sector")?, SecondStageData { - size: second_stage.metadata() - .context("failed to read file metadata of second stage")? - .len(), - reader: second_stage + size: second_stage + .metadata() + .context("failed to read file metadata of second stage")? + .len(), + reader: second_stage, }, boot_partition_path, - out_mbr_path + out_mbr_path, ) } @@ -44,7 +46,7 @@ pub fn create_mbr_disk( reader: Cursor::new(second_stage_binary), }, boot_partition_path, - out_mbr_path + out_mbr_path, ) } From 12e3331c93050f9a2079c6af27c451a4c7b10e10 Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:30:53 +1100 Subject: [PATCH 3/9] Removed unnecessary reference --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 84dbdbaf..1da501aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -216,7 +216,7 @@ impl DiskImageBuilder { #[cfg(not(feature = "embedded_binaries"))] fn write_uefi_bootloader(to: &PathBuf) -> anyhow::Result<()> { let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); - fs::copy(bootloader_path, &to).map(|_| ()).with_context(|| { + fs::copy(bootloader_path, to).map(|_| ()).with_context(|| { format!( "failed to copy bootloader from {} to {}", bootloader_path.display(), From 0f90f100ed45333f2e9422dae7331a268a5b2406 Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Sat, 28 Oct 2023 16:56:25 +1100 Subject: [PATCH 4/9] Removed feature gate --- Cargo.toml | 1 - src/lib.rs | 61 ------------------------------------------------------ src/mbr.rs | 55 ++++-------------------------------------------- 3 files changed, 4 insertions(+), 113 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 42e5c124..49dfb111 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,6 @@ bootloader-x86_64-bios-common = { version = "0.11.4", path = "bios/common" } default = ["bios", "uefi"] bios = ["dep:mbrman"] uefi = ["dep:gpt"] -embedded_binaries = [] [dependencies] anyhow = "1.0.32" diff --git a/src/lib.rs b/src/lib.rs index 1da501aa..fe71651e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,16 +41,10 @@ const KERNEL_FILE_NAME: &str = "kernel-x86_64"; const RAMDISK_FILE_NAME: &str = "ramdisk"; const CONFIG_FILE_NAME: &str = "boot.json"; -#[cfg(all(feature = "embedded_binaries", feature = "uefi"))] static UEFI_BOOTLOADER: &'static [u8] = include_bytes!(env!("UEFI_BOOTLOADER_PATH")); - -#[cfg(all(feature = "embedded_binaries", feature = "bios"))] static BIOS_BOOT_SECTOR: &'static [u8] = include_bytes!(env!("BIOS_BOOT_SECTOR_PATH")); -#[cfg(all(feature = "embedded_binaries", feature = "bios"))] static BIOS_STAGE_2: &'static [u8] = include_bytes!(env!("BIOS_STAGE_2_PATH")); -#[cfg(all(feature = "embedded_binaries", feature = "bios"))] static BIOS_STAGE_3: &'static [u8] = include_bytes!(env!("BIOS_STAGE_3_PATH")); -#[cfg(all(feature = "embedded_binaries", feature = "bios"))] static BIOS_STAGE_4: &'static [u8] = include_bytes!(env!("BIOS_STAGE_4_PATH")); /// Allows creating disk images for a specified set of files. @@ -107,43 +101,6 @@ impl DiskImageBuilder { self.set_file_source(destination.into(), FileDataSource::File(file_path)) } - #[cfg(all(feature = "bios", not(feature = "embedded_binaries")))] - /// Create an MBR disk image for booting on BIOS systems. - pub fn create_bios_image(&self, image_path: &Path) -> anyhow::Result<()> { - const BIOS_STAGE_3_NAME: &str = "boot-stage-3"; - const BIOS_STAGE_4_NAME: &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")); - let stage_4_path = Path::new(env!("BIOS_STAGE_4_PATH")); - let mut internal_files = BTreeMap::new(); - internal_files.insert( - BIOS_STAGE_3_NAME, - FileDataSource::File(stage_3_path.to_path_buf()), - ); - internal_files.insert( - BIOS_STAGE_4_NAME, - FileDataSource::File(stage_4_path.to_path_buf()), - ); - - let fat_partition = self - .create_fat_filesystem_image(internal_files) - .context("failed to create FAT partition")?; - mbr::create_mbr_disk( - bootsector_path, - stage_2_path, - fat_partition.path(), - image_path, - ) - .context("failed to create BIOS MBR disk image")?; - - fat_partition - .close() - .context("failed to delete FAT partition after disk image creation")?; - Ok(()) - } - - #[cfg(all(feature = "bios", feature = "embedded_binaries"))] /// Create an MBR disk image for booting on BIOS systems. pub fn create_bios_image(&self, image_path: &Path) -> anyhow::Result<()> { const BIOS_STAGE_3_NAME: &str = "boot-stage-3"; @@ -175,15 +132,9 @@ impl DiskImageBuilder { pub fn create_uefi_image(&self, image_path: &Path) -> anyhow::Result<()> { const UEFI_BOOT_FILENAME: &str = "efi/boot/bootx64.efi"; - #[cfg(feature = "embedded_binaries")] fn get_uefi_bootloader() -> FileDataSource { FileDataSource::Data(UEFI_BOOTLOADER.to_vec()) } - #[cfg(not(feature = "embedded_binaries"))] - fn get_uefi_bootloader() -> FileDataSource { - let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); - FileDataSource::File(bootloader_path.to_path_buf()) - } let mut internal_files = BTreeMap::new(); internal_files.insert(UEFI_BOOT_FILENAME, get_uefi_bootloader()); @@ -204,7 +155,6 @@ impl DiskImageBuilder { pub fn create_uefi_tftp_folder(&self, tftp_path: &Path) -> anyhow::Result<()> { use std::{fs, ops::Deref}; - #[cfg(feature = "embedded_binaries")] fn write_uefi_bootloader(to: &PathBuf) -> anyhow::Result<()> { fs::write(to, UEFI_BOOTLOADER).with_context(|| { format!( @@ -213,17 +163,6 @@ impl DiskImageBuilder { ) }) } - #[cfg(not(feature = "embedded_binaries"))] - fn write_uefi_bootloader(to: &PathBuf) -> anyhow::Result<()> { - let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH")); - fs::copy(bootloader_path, to).map(|_| ()).with_context(|| { - format!( - "failed to copy bootloader from {} to {}", - bootloader_path.display(), - to.display() - ) - }) - } const UEFI_TFTP_BOOT_FILENAME: &str = "bootloader"; fs::create_dir_all(tftp_path) diff --git a/src/mbr.rs b/src/mbr.rs index 4298a602..3328a07f 100644 --- a/src/mbr.rs +++ b/src/mbr.rs @@ -2,36 +2,12 @@ use anyhow::Context; use mbrman::BOOT_ACTIVE; use std::{ fs::{self, File}, - io::{self, Read, Seek, SeekFrom}, + io::{self, Seek, SeekFrom}, path::Path, }; const SECTOR_SIZE: u32 = 512; -#[cfg(not(feature = "embedded_binaries"))] -pub fn create_mbr_disk( - bootsector_path: &Path, - second_stage_path: &Path, - boot_partition_path: &Path, - out_mbr_path: &Path, -) -> anyhow::Result<()> { - let second_stage = - File::open(second_stage_path).context("failed to open second stage binary")?; - create_mbr_disk_with_readers( - File::open(bootsector_path).context("failed to open boot sector")?, - SecondStageData { - size: second_stage - .metadata() - .context("failed to read file metadata of second stage")? - .len(), - reader: second_stage, - }, - boot_partition_path, - out_mbr_path, - ) -} - -#[cfg(feature = "embedded_binaries")] pub fn create_mbr_disk( bootsector_binary: &[u8], second_stage_binary: &[u8], @@ -39,30 +15,7 @@ pub fn create_mbr_disk( out_mbr_path: &Path, ) -> anyhow::Result<()> { use std::io::Cursor; - create_mbr_disk_with_readers( - Cursor::new(bootsector_binary), - SecondStageData { - size: second_stage_binary.len() as u64, - reader: Cursor::new(second_stage_binary), - }, - boot_partition_path, - out_mbr_path, - ) -} - -struct SecondStageData { - size: u64, - reader: R, -} - -fn create_mbr_disk_with_readers( - bootsector_reader: R, - second_stage_data: SecondStageData, - boot_partition_path: &Path, - out_mbr_path: &Path, -) -> anyhow::Result<()> { - // let mut boot_sector = File::open(bootsector_path).context("failed to open boot sector")?; - let mut boot_sector = bootsector_reader; + let mut boot_sector = Cursor::new(bootsector_binary); let mut mbr = mbrman::MBR::read_from(&mut boot_sector, SECTOR_SIZE).context("failed to read MBR")?; @@ -72,8 +25,8 @@ fn create_mbr_disk_with_readers( } } - let mut second_stage = second_stage_data.reader; - let second_stage_size = second_stage_data.size; + let mut second_stage = Cursor::new(second_stage_binary); + let second_stage_size = second_stage_binary.len() as u64; let second_stage_start_sector = 1; let second_stage_sectors = ((second_stage_size - 1) / u64::from(SECTOR_SIZE) + 1) From 0f5e3d90b0d9b8b80fe5f9a87a4e6b2704152690 Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Sat, 28 Oct 2023 16:58:03 +1100 Subject: [PATCH 5/9] Changed static to const and removed unnecessary lifetime --- src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fe71651e..db8a6514 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,11 +41,11 @@ const KERNEL_FILE_NAME: &str = "kernel-x86_64"; const RAMDISK_FILE_NAME: &str = "ramdisk"; const CONFIG_FILE_NAME: &str = "boot.json"; -static UEFI_BOOTLOADER: &'static [u8] = include_bytes!(env!("UEFI_BOOTLOADER_PATH")); -static BIOS_BOOT_SECTOR: &'static [u8] = include_bytes!(env!("BIOS_BOOT_SECTOR_PATH")); -static BIOS_STAGE_2: &'static [u8] = include_bytes!(env!("BIOS_STAGE_2_PATH")); -static BIOS_STAGE_3: &'static [u8] = include_bytes!(env!("BIOS_STAGE_3_PATH")); -static BIOS_STAGE_4: &'static [u8] = include_bytes!(env!("BIOS_STAGE_4_PATH")); +const UEFI_BOOTLOADER: &[u8] = include_bytes!(env!("UEFI_BOOTLOADER_PATH")); +const BIOS_BOOT_SECTOR: &[u8] = include_bytes!(env!("BIOS_BOOT_SECTOR_PATH")); +const BIOS_STAGE_2: &[u8] = include_bytes!(env!("BIOS_STAGE_2_PATH")); +const BIOS_STAGE_3: &[u8] = include_bytes!(env!("BIOS_STAGE_3_PATH")); +const BIOS_STAGE_4: &[u8] = include_bytes!(env!("BIOS_STAGE_4_PATH")); /// Allows creating disk images for a specified set of files. /// From 580cb424413884db151bb5afdb509dfb87fedca3 Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Sat, 28 Oct 2023 17:13:05 +1100 Subject: [PATCH 6/9] Added new variant for FileDataSource Added new variant for FileDataSource and inlined now unnecessary functions --- src/file_data_source.rs | 9 +++++++++ src/lib.rs | 26 +++++++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/file_data_source.rs b/src/file_data_source.rs index 3e1128b3..229cb20e 100644 --- a/src/file_data_source.rs +++ b/src/file_data_source.rs @@ -11,6 +11,7 @@ use std::{fs, io}; pub enum FileDataSource { File(PathBuf), Data(Vec), + Bytes(&'static [u8]), } impl Debug for FileDataSource { @@ -22,6 +23,9 @@ impl Debug for FileDataSource { FileDataSource::Data(d) => { f.write_fmt(format_args!("data source: {} raw bytes ", d.len())) } + FileDataSource::Bytes(b) => { + f.write_fmt(format_args!("data source: {} raw bytes ", b.len())) + } } } } @@ -34,6 +38,7 @@ impl FileDataSource { .with_context(|| format!("failed to read metadata of file `{}`", path.display()))? .len(), FileDataSource::Data(v) => v.len() as u64, + FileDataSource::Bytes(s) => s.len() as u64, }) } /// Copy this data source to the specified target that implements io::Write @@ -51,6 +56,10 @@ impl FileDataSource { let mut cursor = Cursor::new(contents); io::copy(&mut cursor, target)?; } + FileDataSource::Bytes(contents) => { + let mut cursor = Cursor::new(contents); + io::copy(&mut cursor, target)?; + }, }; Ok(()) diff --git a/src/lib.rs b/src/lib.rs index db8a6514..d7e003a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,8 +105,8 @@ impl DiskImageBuilder { pub fn create_bios_image(&self, image_path: &Path) -> anyhow::Result<()> { const BIOS_STAGE_3_NAME: &str = "boot-stage-3"; const BIOS_STAGE_4_NAME: &str = "boot-stage-4"; - let stage_3 = FileDataSource::Data(BIOS_STAGE_3.to_vec()); - let stage_4 = FileDataSource::Data(BIOS_STAGE_4.to_vec()); + let stage_3 = FileDataSource::Bytes(BIOS_STAGE_3); + let stage_4 = FileDataSource::Bytes(BIOS_STAGE_4); let mut internal_files = BTreeMap::new(); internal_files.insert(BIOS_STAGE_3_NAME, stage_3); internal_files.insert(BIOS_STAGE_4_NAME, stage_4); @@ -132,12 +132,8 @@ impl DiskImageBuilder { pub fn create_uefi_image(&self, image_path: &Path) -> anyhow::Result<()> { const UEFI_BOOT_FILENAME: &str = "efi/boot/bootx64.efi"; - fn get_uefi_bootloader() -> FileDataSource { - FileDataSource::Data(UEFI_BOOTLOADER.to_vec()) - } - let mut internal_files = BTreeMap::new(); - internal_files.insert(UEFI_BOOT_FILENAME, get_uefi_bootloader()); + internal_files.insert(UEFI_BOOT_FILENAME, FileDataSource::Bytes(UEFI_BOOTLOADER)); let fat_partition = self .create_fat_filesystem_image(internal_files) .context("failed to create FAT partition")?; @@ -155,21 +151,17 @@ impl DiskImageBuilder { pub fn create_uefi_tftp_folder(&self, tftp_path: &Path) -> anyhow::Result<()> { use std::{fs, ops::Deref}; - fn write_uefi_bootloader(to: &PathBuf) -> anyhow::Result<()> { - fs::write(to, UEFI_BOOTLOADER).with_context(|| { - format!( - "failed to copy bootloader from the embedded binary to {}", - to.display() - ) - }) - } - const UEFI_TFTP_BOOT_FILENAME: &str = "bootloader"; fs::create_dir_all(tftp_path) .with_context(|| format!("failed to create out dir at {}", tftp_path.display()))?; let to = tftp_path.join(UEFI_TFTP_BOOT_FILENAME); - write_uefi_bootloader(&to)?; + fs::write(&to, UEFI_BOOTLOADER).with_context(|| { + format!( + "failed to copy bootloader from the embedded binary to {}", + to.display() + ) + })?; for f in &self.files { let to = tftp_path.join(f.0.deref()); From 3b312fc6a9a2d03b1a4d57870827b79fcf25be84 Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Sat, 28 Oct 2023 17:17:12 +1100 Subject: [PATCH 7/9] Ran cargo fmt Removed an unnecessary comma --- src/file_data_source.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/file_data_source.rs b/src/file_data_source.rs index 229cb20e..5724d96f 100644 --- a/src/file_data_source.rs +++ b/src/file_data_source.rs @@ -59,7 +59,7 @@ impl FileDataSource { FileDataSource::Bytes(contents) => { let mut cursor = Cursor::new(contents); io::copy(&mut cursor, target)?; - }, + } }; Ok(()) From 7bedb9cb5f4dd0e2ad8bb66cee84e118e6a8e6e0 Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Sat, 28 Oct 2023 17:27:24 +1100 Subject: [PATCH 8/9] Re-added multiple mistakenly deleted #[cfg(feature)] Re-added multipl #[cfg(feature = "bios")] and #[cfg(feature = "uefi")] --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index d7e003a1..cb3805e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,10 +41,15 @@ const KERNEL_FILE_NAME: &str = "kernel-x86_64"; const RAMDISK_FILE_NAME: &str = "ramdisk"; const CONFIG_FILE_NAME: &str = "boot.json"; +#[cfg(feature = "uefi")] const UEFI_BOOTLOADER: &[u8] = include_bytes!(env!("UEFI_BOOTLOADER_PATH")); +#[cfg(feature = "bios")] const BIOS_BOOT_SECTOR: &[u8] = include_bytes!(env!("BIOS_BOOT_SECTOR_PATH")); +#[cfg(feature = "bios")] const BIOS_STAGE_2: &[u8] = include_bytes!(env!("BIOS_STAGE_2_PATH")); +#[cfg(feature = "bios")] const BIOS_STAGE_3: &[u8] = include_bytes!(env!("BIOS_STAGE_3_PATH")); +#[cfg(feature = "bios")] const BIOS_STAGE_4: &[u8] = include_bytes!(env!("BIOS_STAGE_4_PATH")); /// Allows creating disk images for a specified set of files. @@ -101,6 +106,7 @@ impl DiskImageBuilder { self.set_file_source(destination.into(), FileDataSource::File(file_path)) } + #[cfg(feature = "bios")] /// Create an MBR disk image for booting on BIOS systems. pub fn create_bios_image(&self, image_path: &Path) -> anyhow::Result<()> { const BIOS_STAGE_3_NAME: &str = "boot-stage-3"; From 99a6e544fa6cafd8d425b7c66549d1bd3294d46c Mon Sep 17 00:00:00 2001 From: mysteriouslyseeing <61419567+mysteriouslyseeing@users.noreply.github.com> Date: Sat, 28 Oct 2023 19:25:31 +1100 Subject: [PATCH 9/9] Changed build.rs to place dummy files in out_dir when under the "docsrs_dummy_build" cfg directive Changed build.rs to place dummy files in out_dir when under the "docsrs_dummy_build" cfg directive. --- build.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 13 deletions(-) diff --git a/build.rs b/build.rs index d40373d4..3f543d3f 100644 --- a/build.rs +++ b/build.rs @@ -21,7 +21,6 @@ async fn bios_main() { // BIOS crates don't have enough dependencies to utilize all cores on modern // CPUs. So by running the build commands in parallel, we increase the number // of utilized cores.) - #[cfg(not(docsrs_dummy_build))] let (bios_boot_sector_path, bios_stage_2_path, bios_stage_3_path, bios_stage_4_path) = ( build_bios_boot_sector(&out_dir), build_bios_stage_2(&out_dir), @@ -30,14 +29,6 @@ async fn bios_main() { ) .join() .await; - // dummy implementations because docsrs builds have no network access - #[cfg(docsrs_dummy_build)] - let (bios_boot_sector_path, bios_stage_2_path, bios_stage_3_path, bios_stage_4_path) = ( - PathBuf::new(), - PathBuf::new(), - PathBuf::new(), - PathBuf::new(), - ); println!( "cargo:rustc-env=BIOS_BOOT_SECTOR_PATH={}", bios_boot_sector_path.display() @@ -60,11 +51,7 @@ async fn bios_main() { async fn uefi_main() { let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); - #[cfg(not(docsrs_dummy_build))] let uefi_path = build_uefi_bootloader(&out_dir).await; - // dummy implementation because docsrs builds have no network access - #[cfg(docsrs_dummy_build)] - let uefi_path = PathBuf::new(); println!( "cargo:rustc-env=UEFI_BOOTLOADER_PATH={}", @@ -109,6 +96,26 @@ async fn build_uefi_bootloader(out_dir: &Path) -> PathBuf { } } +// dummy implementation because docsrs builds have no network access. +// This will put an empty file in out_dir and return its path. +#[cfg(docsrs_dummy_build)] +#[cfg(feature = "uefi")] +async fn build_uefi_bootloader(out_dir: &Path) -> PathBuf { + use std::fs::File; + + let path = out_dir.join("bootloader-dummy-bootloader-uefi"); + + if File::create(&path).is_err() { + panic!("Failed to create dummy uefi bootloader"); + } + assert!( + path.exists(), + "uefi bootloader dummy file does not exist after file creation" + ); + + path +} + #[cfg(not(docsrs_dummy_build))] #[cfg(feature = "bios")] async fn build_bios_boot_sector(out_dir: &Path) -> PathBuf { @@ -153,6 +160,26 @@ async fn build_bios_boot_sector(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path).await } +// dummy implementation because docsrs builds have no network access. +// This will put an empty file in out_dir and return its path. +#[cfg(docsrs_dummy_build)] +#[cfg(feature = "bios")] +async fn build_bios_boot_sector(out_dir: &Path) -> PathBuf { + use std::fs::File; + + let path = out_dir.join("bootloader-dummy-bios-boot-sector"); + + if File::create(&path).is_err() { + panic!("Failed to create dummy bios boot sector"); + } + assert!( + path.exists(), + "bios boot sector dummy file does not exist after file creation" + ); + + path +} + #[cfg(not(docsrs_dummy_build))] #[cfg(feature = "bios")] async fn build_bios_stage_2(out_dir: &Path) -> PathBuf { @@ -199,6 +226,26 @@ async fn build_bios_stage_2(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path).await } +// dummy implementation because docsrs builds have no network access. +// This will put an empty file in out_dir and return its path. +#[cfg(docsrs_dummy_build)] +#[cfg(feature = "bios")] +async fn build_bios_stage_2(out_dir: &Path) -> PathBuf { + use std::fs::File; + + let path = out_dir.join("bootloader-dummy-bios-stage-2"); + + if File::create(&path).is_err() { + panic!("Failed to create dummy bios second stage"); + } + assert!( + path.exists(), + "bios second stage dummy file does not exist after file creation" + ); + + path +} + #[cfg(not(docsrs_dummy_build))] #[cfg(feature = "bios")] async fn build_bios_stage_3(out_dir: &Path) -> PathBuf { @@ -241,6 +288,26 @@ async fn build_bios_stage_3(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path).await } +// dummy implementation because docsrs builds have no network access. +// This will put an empty file in out_dir and return its path. +#[cfg(docsrs_dummy_build)] +#[cfg(feature = "bios")] +async fn build_bios_stage_3(out_dir: &Path) -> PathBuf { + use std::fs::File; + + let path = out_dir.join("bootloader-dummy-bios-stage-3"); + + if File::create(&path).is_err() { + panic!("Failed to create dummy bios stage-3"); + } + assert!( + path.exists(), + "bios stage-3 dummy file does not exist after file creation" + ); + + path +} + #[cfg(not(docsrs_dummy_build))] #[cfg(feature = "bios")] async fn build_bios_stage_4(out_dir: &Path) -> PathBuf { @@ -284,6 +351,26 @@ async fn build_bios_stage_4(out_dir: &Path) -> PathBuf { convert_elf_to_bin(elf_path).await } +// dummy implementation because docsrs builds have no network access. +// This will put an empty file in out_dir and return its path. +#[cfg(docsrs_dummy_build)] +#[cfg(feature = "bios")] +async fn build_bios_stage_4(out_dir: &Path) -> PathBuf { + use std::fs::File; + + let path = out_dir.join("bootloader-dummy-bios-stage-4"); + + if File::create(&path).is_err() { + panic!("Failed to create dummy bios stage-4"); + } + assert!( + path.exists(), + "bios stage-4 dummy file does not exist after file creation" + ); + + path +} + #[cfg(not(docsrs_dummy_build))] #[cfg(feature = "bios")] async fn convert_elf_to_bin(elf_path: PathBuf) -> PathBuf {