Skip to content

Fix loading of boot configuration #342

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 30, 2023
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
4 changes: 4 additions & 0 deletions api/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ pub struct BootInfo {
pub ramdisk_addr: Optional<u64>,
/// Ramdisk image size, set to 0 if addr is None
pub ramdisk_len: u64,

#[doc(hidden)]
pub _test_sentinel: u64,
}

impl BootInfo {
Expand All @@ -73,6 +76,7 @@ impl BootInfo {
tls_template: Optional::None,
ramdisk_addr: Optional::None,
ramdisk_len: 0,
_test_sentinel: 0,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions bios/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub struct BiosInfo {
pub kernel: Region,
pub ramdisk: Region,
pub config_file: Region,
pub last_used_addr: u64,
pub framebuffer: BiosFramebufferInfo,
pub memory_map_addr: u32,
pub memory_map_len: u16,
Expand Down
3 changes: 2 additions & 1 deletion bios/stage-2/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
}
let config_file_start = ramdisk_start.wrapping_add(ramdisk_len.try_into().unwrap());
let config_file_len = try_load_file(
"config.json",
"boot.json",
config_file_start,
&mut fs,
&mut disk,
Expand Down Expand Up @@ -161,6 +161,7 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
start: config_file_start as u64,
len: config_file_len,
},
last_used_addr: config_file_start as u64 + config_file_len - 1,
memory_map_addr: memory_map.as_mut_ptr() as u32,
memory_map_len: memory_map.len().try_into().unwrap(),
framebuffer: BiosFramebufferInfo {
Expand Down
11 changes: 2 additions & 9 deletions bios/stage-4/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,7 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
PhysAddr::new(info.kernel.start)
};
let kernel_size = info.kernel.len;
let next_free_frame = match info.ramdisk.len {
0 => PhysFrame::containing_address(kernel_start + kernel_size - 1u64) + 1,
_ => {
PhysFrame::containing_address(PhysAddr::new(
info.ramdisk.start + info.ramdisk.len - 1u64,
)) + 1
}
};
let next_free_frame = PhysFrame::containing_address(PhysAddr::new(info.last_used_addr)) + 1;
let mut frame_allocator = LegacyFrameAllocator::new_starting_at(
next_free_frame,
memory_map.iter().copied().map(MemoryRegion),
Expand Down Expand Up @@ -173,7 +166,7 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
ramdisk_len: info.ramdisk.len,
};

load_and_switch_to_kernel(kernel, frame_allocator, page_tables, system_info);
load_and_switch_to_kernel(kernel, config, frame_allocator, page_tables, system_info);
}

fn init_logger(
Expand Down
3 changes: 3 additions & 0 deletions common/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub struct BootConfig {
///
/// Enabled by default.
pub serial_logging: bool,

pub _test_sentinel: u64,
}

impl Default for BootConfig {
Expand All @@ -31,6 +33,7 @@ impl Default for BootConfig {
log_level: Default::default(),
frame_buffer_logging: true,
serial_logging: true,
_test_sentinel: 0,
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use bootloader_api::{
info::{FrameBuffer, FrameBufferInfo, MemoryRegion, TlsTemplate},
BootInfo, BootloaderConfig,
};
use bootloader_boot_config::LevelFilter;
use bootloader_boot_config::{BootConfig, LevelFilter};
use core::{alloc::Layout, arch::asm, mem::MaybeUninit, slice};
use level_4_entries::UsedLevel4Entries;
use usize_conversions::FromUsize;
Expand Down Expand Up @@ -125,6 +125,7 @@ impl<'a> Kernel<'a> {
/// directly to these functions, so see their docs for more info.
pub fn load_and_switch_to_kernel<I, D>(
kernel: Kernel,
boot_config: BootConfig,
mut frame_allocator: LegacyFrameAllocator<I, D>,
mut page_tables: PageTables,
system_info: SystemInfo,
Expand All @@ -144,6 +145,7 @@ where
);
let boot_info = create_boot_info(
&config,
&boot_config,
frame_allocator,
&mut page_tables,
&mut mappings,
Expand Down Expand Up @@ -435,6 +437,7 @@ pub struct Mappings {
/// are taken from the given `frame_allocator`.
pub fn create_boot_info<I, D>(
config: &BootloaderConfig,
boot_config: &BootConfig,
mut frame_allocator: LegacyFrameAllocator<I, D>,
page_tables: &mut PageTables,
mappings: &mut Mappings,
Expand Down Expand Up @@ -539,6 +542,7 @@ where
.map(|addr| addr.as_u64())
.into();
info.ramdisk_len = mappings.ramdisk_slice_len;
info._test_sentinel = boot_config._test_sentinel;
info
});

Expand Down
1 change: 1 addition & 0 deletions src/uefi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ impl UefiBoot {
bootloader_path,
self.kernel.as_path(),
self.ramdisk.as_deref(),
self.config.as_deref(),
out_path,
)
.context("failed to create UEFI PXE tftp folder")?;
Expand Down
7 changes: 7 additions & 0 deletions src/uefi/pxe.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::path::Path;

use anyhow::Context;
use bootloader_boot_config::BootConfig;

pub fn create_uefi_tftp_folder(
bootloader_path: &Path,
kernel_binary: &Path,
ramdisk_path: Option<&Path>,
boot_config: Option<&str>,
out_path: &Path,
) -> anyhow::Result<()> {
std::fs::create_dir_all(out_path)
Expand Down Expand Up @@ -39,5 +41,10 @@ pub fn create_uefi_tftp_folder(
})?;
}

if let Some(config) = boot_config {
let to = out_path.join("boot.json");
std::fs::write(to, config).context("failed to write boot.json")?;
}

Ok(())
}
12 changes: 6 additions & 6 deletions tests/config_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@ use bootloader_test_runner::run_test_kernel_internal;
use bootloader::BootConfig;

#[test]
fn basic_boot() {
let config: BootConfig = Default::default();
fn default_config() {
run_test_kernel_internal(
env!("CARGO_BIN_FILE_TEST_KERNEL_CONFIG_FILE_basic_boot"),
env!("CARGO_BIN_FILE_TEST_KERNEL_CONFIG_FILE_no_config"),
None,
None,
Some(&config),
);
}

#[test]
fn custom_options_boot() {
fn custom_boot_config() {
let config = BootConfig {
frame_buffer: Default::default(),
log_level: Default::default(),
frame_buffer_logging: false,
serial_logging: true,
_test_sentinel: 0xb001b001b001,
};
run_test_kernel_internal(
env!("CARGO_BIN_FILE_TEST_KERNEL_CONFIG_FILE_basic_boot_broken_config_file"),
env!("CARGO_BIN_FILE_TEST_KERNEL_CONFIG_FILE_custom_config"),
None,
Some(&config),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ entry_point!(kernel_main);

fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
writeln!(serial(), "Entered kernel with boot info: {boot_info:?}").unwrap();
assert_eq!(boot_info._test_sentinel, 0xb001b001b001);
exit_qemu(QemuExitCode::Success);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ entry_point!(kernel_main);

fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
writeln!(serial(), "Entered kernel with boot info: {boot_info:?}").unwrap();
assert_eq!(boot_info._test_sentinel, 0);
exit_qemu(QemuExitCode::Success);
}

Expand Down
24 changes: 13 additions & 11 deletions uefi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
}

let mut boot_mode = BootMode::Disk;

let mut kernel = load_kernel(image, &mut st, boot_mode);
if kernel.is_none() {
// Try TFTP boot
boot_mode = BootMode::Tftp;
kernel = load_kernel(image, &mut st, boot_mode);
}
let kernel = kernel.expect("Failed to load kernel");

let config_file = load_config_file(image, &mut st, boot_mode);
let mut error_loading_config: Option<serde_json_core::de::Error> = None;
let mut config: BootConfig = match config_file
Expand All @@ -87,14 +96,6 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
}
};

let mut kernel = load_kernel(image, &mut st, boot_mode);
if kernel.is_none() {
// Try TFTP boot
boot_mode = BootMode::Tftp;
kernel = load_kernel(image, &mut st, boot_mode);
}
let kernel = kernel.expect("Failed to load kernel");

#[allow(deprecated)]
if config.frame_buffer.minimum_framebuffer_height.is_none() {
config.frame_buffer.minimum_framebuffer_height =
Expand All @@ -105,7 +106,7 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
config.frame_buffer.minimum_framebuffer_width =
kernel.config.frame_buffer.minimum_framebuffer_width;
}
let framebuffer = init_logger(image, &st, config);
let framebuffer = init_logger(image, &st, &config);

unsafe {
*SYSTEM_TABLE.get() = None;
Expand Down Expand Up @@ -193,6 +194,7 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {

bootloader_x86_64_common::load_and_switch_to_kernel(
kernel,
config,
frame_allocator,
page_tables,
system_info,
Expand All @@ -218,7 +220,7 @@ fn load_config_file(
st: &mut SystemTable<Boot>,
boot_mode: BootMode,
) -> Option<&'static mut [u8]> {
load_file_from_boot_method(image, st, "config.json\0", boot_mode)
load_file_from_boot_method(image, st, "boot.json\0", boot_mode)
}

fn load_kernel(
Expand Down Expand Up @@ -473,7 +475,7 @@ fn create_page_tables(
fn init_logger(
image_handle: Handle,
st: &SystemTable<Boot>,
config: BootConfig,
config: &BootConfig,
) -> Option<RawFrameBufferInfo> {
let gop_handle = st
.boot_services()
Expand Down