Skip to content
41 changes: 29 additions & 12 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ fn main() {

#[cfg(feature = "binary")]
mod binary {
use proc_macro2::TokenStream;
use quote::quote;
use std::convert::TryInto;

Expand Down Expand Up @@ -281,19 +282,29 @@ mod binary {
};

// Write config to file
let file_path = out_dir.join("bootloader_config.rs");
let mut file = File::create(file_path).expect("failed to create bootloader_config.rs");
file.write_all(
quote::quote! {
mod parsed_config {
use crate::config::Config;
pub const CONFIG: Config = #config;
let write_config = |path: &str, import: TokenStream| {
let file_path = out_dir.join(path);
let mut file = File::create(file_path).expect("failed to create config file");
file.write_all(
quote::quote! {
mod parsed_config {
use #import;
pub const CONFIG: Config = #config;
}
}
}
.to_string()
.as_bytes(),
)
.expect("write to bootloader_config.rs failed");
.to_string()
.as_bytes(),
)
.expect("writing config failed");
};
write_config(
"bootloader_config.rs",
quote::quote! { crate::config::Config },
);
write_config(
"kernel_bootloader_config.rs",
quote::quote! { bootloader::Config },
);

println!("cargo:rerun-if-env-changed=KERNEL");
println!("cargo:rerun-if-env-changed=KERNEL_MANIFEST");
Expand Down Expand Up @@ -326,6 +337,8 @@ mod binary {
pub kernel_stack_address: Option<AlignedAddress>,
pub boot_info_address: Option<AlignedAddress>,
pub framebuffer_address: Option<AlignedAddress>,
pub desired_framebuffer_height: Option<usize>,
pub desired_framebuffer_width: Option<usize>,
}

/// Convert to tokens suitable for initializing the `Config` struct.
Expand All @@ -344,6 +357,8 @@ mod binary {
let kernel_stack_address = optional(self.kernel_stack_address);
let boot_info_address = optional(self.boot_info_address);
let framebuffer_address = optional(self.framebuffer_address);
let desired_framebuffer_height = optional(self.desired_framebuffer_height);
let desired_framebuffer_width = optional(self.desired_framebuffer_width);

tokens.extend(quote! { Config {
map_physical_memory: #map_physical_memory,
Expand All @@ -355,6 +370,8 @@ mod binary {
kernel_stack_address: #kernel_stack_address,
boot_info_address: #boot_info_address,
framebuffer_address: #framebuffer_address,
desired_framebuffer_height: #desired_framebuffer_height,
desired_framebuffer_width: #desired_framebuffer_width
}});
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/bin/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

// Defines the constants `KERNEL_BYTES` (array of `u8`) and `KERNEL_SIZE` (`usize`).
include!(concat!(env!("OUT_DIR"), "/kernel_info.rs"));
// Contains the bootloader configuration specified by the kernel crate (needed for GOP configuration)
include!(concat!(env!("OUT_DIR"), "/kernel_bootloader_config.rs"));

static KERNEL: PageAligned<[u8; KERNEL_SIZE]> = PageAligned(KERNEL_BYTES);

Expand All @@ -18,10 +20,12 @@ use bootloader::{
boot_info::FrameBufferInfo,
};
use core::{mem, panic::PanicInfo, slice};
use parsed_config::CONFIG;
use uefi::{
prelude::{entry, Boot, Handle, ResultExt, Status, SystemTable},
proto::console::gop::{GraphicsOutput, PixelFormat},
table::boot::{MemoryDescriptor, MemoryType},
Completion,
};
use x86_64::{
structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB},
Expand Down Expand Up @@ -149,6 +153,25 @@ fn init_logger(st: &SystemTable<Boot>) -> (PhysAddr, FrameBufferInfo) {
.expect_success("failed to locate gop");
let gop = unsafe { &mut *gop.get() };

let mode = {
let modes = gop.modes().map(Completion::unwrap);
match (
CONFIG.desired_framebuffer_height,
CONFIG.desired_framebuffer_width,
) {
(Some(height), Some(width)) => modes
.filter(|m| m.info().resolution() == (width, height))
.last(),
(Some(height), None) => modes.filter(|m| m.info().resolution().1 == height).last(),
(None, Some(width)) => modes.filter(|m| m.info().resolution().0 == width).last(),
_ => None,
}
};
if let Some(mode) = mode {
gop.set_mode(&mode)
.expect_success("failed to apply gop mode");
}

let mode_info = gop.current_mode_info();
let mut framebuffer = gop.frame_buffer();
let slice = unsafe { slice::from_raw_parts_mut(framebuffer.as_mut_ptr(), framebuffer.size()) };
Expand Down
12 changes: 12 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,16 @@ pub struct Config {
///
/// Only considered if `map_framebuffer` is `true`.
pub framebuffer_address: Option<u64>,
/// Desired height of the framebuffer mode when running in UEFI mode.
///
/// Defaults to using the default mode if neither `desired_framebuffer_height` or
/// `desired_framebuffer_width` is supplied, and using the last available mode that
/// fits them if 1 or more is set.
pub desired_framebuffer_height: Option<usize>,
/// Desired width of the framebuffer mode when running in UEFI mode.
///
/// Defaults to using the default mode if neither `desired_framebuffer_height` or
/// `desired_framebuffer_width` is supplied, and using the last available mode that
/// fits them if 1 or more is set.
pub desired_framebuffer_width: Option<usize>,
}