Skip to content

add UEFI PXE support #237

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 6 commits into from
Jun 6, 2022
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
34 changes: 17 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ use std::{
mod fat;
mod gpt;
mod mbr;
mod pxe;

const KERNEL_FILE_NAME: &str = "kernel-x86_64";

Expand Down Expand Up @@ -121,3 +122,17 @@ pub fn create_bios_disk_image(

Ok(())
}

/// Prepare a folder for use with booting over UEFI_PXE.
///
/// This places the bootloader executable under the path "bootloader". The
/// DHCP server should set the filename option to that path, otherwise the
/// bootloader won't be found.
pub fn create_uefi_pxe_tftp_folder(kernel_binary: &Path, out_path: &Path) -> anyhow::Result<()> {
let bootloader_path = Path::new(env!("UEFI_BOOTLOADER_PATH"));

pxe::create_uefi_tftp_folder(bootloader_path, kernel_binary, out_path)
.context("failed to create UEFI PXE tftp folder")?;

Ok(())
}
32 changes: 32 additions & 0 deletions src/pxe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::path::Path;

use anyhow::Context;

pub fn create_uefi_tftp_folder(
bootloader_path: &Path,
kernel_binary: &Path,
out_path: &Path,
) -> anyhow::Result<()> {
std::fs::create_dir_all(out_path)
.with_context(|| format!("failed to create out dir at {}", out_path.display()))?;

let to = out_path.join("bootloader");
std::fs::copy(bootloader_path, &to).with_context(|| {
format!(
"failed to copy bootloader from {} to {}",
bootloader_path.display(),
to.display()
)
})?;

let to = out_path.join("kernel-x86_64");
std::fs::copy(kernel_binary, &to).with_context(|| {
format!(
"failed to copy kernel from {} to {}",
kernel_binary.display(),
to.display()
)
})?;

Ok(())
}
38 changes: 36 additions & 2 deletions tests/runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ const QEMU_ARGS: &[&str] = &[
];

pub fn run_test_kernel(kernel_binary_path: &str) {
run_test_kernel_on_uefi(kernel_binary_path);
run_test_kernel_on_uefi_pxe(kernel_binary_path);
// TODO: run tests with BIOS bootloader too
}

pub fn run_test_kernel_on_uefi(kernel_binary_path: &str) {
let kernel_path = Path::new(kernel_binary_path);
let out_fat_path = kernel_path.with_extension("fat");
bootloader::create_boot_partition(kernel_path, &out_fat_path).unwrap();
Expand All @@ -19,8 +25,6 @@ pub fn run_test_kernel(kernel_binary_path: &str) {
let out_mbr_path = kernel_path.with_extension("mbr");
bootloader::create_bios_disk_image(&out_fat_path, &out_mbr_path).unwrap();

// TODO: run tests with BIOS bootloader too

let mut run_cmd = Command::new("qemu-system-x86_64");
run_cmd
.arg("-drive")
Expand All @@ -42,3 +46,33 @@ pub fn run_test_kernel(kernel_binary_path: &str) {
other => panic!("Test failed with unexpected exit code `{:?}`", other),
}
}

pub fn run_test_kernel_on_uefi_pxe(kernel_binary_path: &str) {
let kernel_path = Path::new(kernel_binary_path);
let out_tftp_path = kernel_path.with_extension(".tftp");

bootloader::create_uefi_pxe_tftp_folder(kernel_path, &out_tftp_path).unwrap();

let mut run_cmd = Command::new("qemu-system-x86_64");
run_cmd.arg("-netdev").arg(format!(
"user,id=net0,net=192.168.17.0/24,tftp={},bootfile=bootloader,id=net0",
out_tftp_path.display()
));
run_cmd.arg("-device").arg("virtio-net-pci,netdev=net0");
run_cmd.args(QEMU_ARGS);
run_cmd.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi());

let child_output = run_cmd.output().unwrap();
strip_ansi_escapes::Writer::new(std::io::stderr())
.write_all(&child_output.stderr)
.unwrap();
strip_ansi_escapes::Writer::new(std::io::stderr())
.write_all(&child_output.stdout)
.unwrap();

match child_output.status.code() {
Some(33) => {} // success
Some(35) => panic!("Test failed"),
other => panic!("Test failed with unexpected exit code `{:?}`", other),
}
}
2 changes: 1 addition & 1 deletion uefi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ license = "MIT/Apache-2.0"
bootloader_api = { version = "0.1.0-alpha.0", path = "../api" }
bootloader-x86_64-common = { version = "0.1.0-alpha.0", path = "../common" }
log = "0.4.14"
uefi = "0.13.0"
uefi = "0.16.0"
x86_64 = "0.14.8"
Loading