Skip to content

allow booting without a UEFI graphics output #268

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 3 commits into from
Oct 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
13 changes: 4 additions & 9 deletions api/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,12 @@ pub enum MemoryRegionKind {
#[repr(C)]
pub struct FrameBuffer {
pub(crate) buffer_start: u64,
pub(crate) buffer_byte_len: usize,
pub(crate) info: FrameBufferInfo,
}

impl FrameBuffer {
pub fn new(buffer_start: u64, buffer_byte_len: usize, info: FrameBufferInfo) -> Self {
Self {
buffer_start,
buffer_byte_len,
info,
}
pub fn new(buffer_start: u64, info: FrameBufferInfo) -> Self {
Self { buffer_start, info }
}

/// Returns the raw bytes of the framebuffer as slice.
Expand All @@ -182,11 +177,11 @@ impl FrameBuffer {
}

unsafe fn create_buffer<'a>(&self) -> &'a [u8] {
unsafe { slice::from_raw_parts(self.buffer_start as *const u8, self.buffer_byte_len) }
unsafe { slice::from_raw_parts(self.buffer_start as *const u8, self.info.byte_len) }
}

unsafe fn create_buffer_mut<'a>(&self) -> &'a mut [u8] {
unsafe { slice::from_raw_parts_mut(self.buffer_start as *mut u8, self.buffer_byte_len) }
unsafe { slice::from_raw_parts_mut(self.buffer_start as *mut u8, self.info.byte_len) }
}

/// Returns layout and pixel format information of the framebuffer.
Expand Down
7 changes: 5 additions & 2 deletions bios/stage-4/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use crate::memory_descriptor::MemoryRegion;
use bootloader_api::info::{FrameBufferInfo, PixelFormat};
use bootloader_x86_64_bios_common::{BiosFramebufferInfo, BiosInfo, E820MemoryRegion};
use bootloader_x86_64_common::RawFrameBufferInfo;
use bootloader_x86_64_common::{
legacy_memory_region::LegacyFrameAllocator, load_and_switch_to_kernel, Kernel, PageTables,
SystemInfo,
Expand Down Expand Up @@ -112,8 +113,10 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
let kernel = Kernel::parse(kernel_slice);

let system_info = SystemInfo {
framebuffer_addr: PhysAddr::new(info.framebuffer.region.start),
framebuffer_info,
framebuffer: Some(RawFrameBufferInfo {
addr: PhysAddr::new(info.framebuffer.region.start),
info: framebuffer_info,
}),
rsdp_addr: detect_rsdp(),
};

Expand Down
8 changes: 5 additions & 3 deletions common/src/level_4_entries.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{entropy, BootInfo};
use crate::{entropy, BootInfo, RawFrameBufferInfo};
use bootloader_api::{config, info::MemoryRegion, BootloaderConfig};
use core::{alloc::Layout, iter::Step};
use rand::{
Expand Down Expand Up @@ -31,7 +31,7 @@ impl UsedLevel4Entries {
pub fn new(
max_phys_addr: PhysAddr,
regions_len: usize,
framebuffer_size: usize,
framebuffer: Option<&RawFrameBufferInfo>,
config: &BootloaderConfig,
) -> Self {
let mut used = UsedLevel4Entries {
Expand Down Expand Up @@ -70,7 +70,9 @@ impl UsedLevel4Entries {
}

if let config::Mapping::FixedAddress(framebuffer_address) = config.mappings.framebuffer {
used.mark_range_as_used(framebuffer_address, framebuffer_size);
if let Some(framebuffer) = framebuffer {
used.mark_range_as_used(framebuffer_address, framebuffer.info.byte_len);
}
}

// Mark everything before the dynamic range as unusable.
Expand Down
41 changes: 21 additions & 20 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,21 @@ pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo) {
/// Required system information that should be queried from the BIOS or UEFI firmware.
#[derive(Debug, Copy, Clone)]
pub struct SystemInfo {
/// Start address of the pixel-based framebuffer.
pub framebuffer_addr: PhysAddr,
/// Information about the framebuffer, including layout and pixel format.
pub framebuffer_info: FrameBufferInfo,
/// Information about the (still unmapped) framebuffer.
pub framebuffer: Option<RawFrameBufferInfo>,
/// Address of the _Root System Description Pointer_ structure of the ACPI standard.
pub rsdp_addr: Option<PhysAddr>,
}

/// The physical address of the framebuffer and information about the framebuffer.
#[derive(Debug, Copy, Clone)]
pub struct RawFrameBufferInfo {
/// Start address of the pixel-based framebuffer.
pub addr: PhysAddr,
/// Information about the framebuffer, including layout and pixel format.
pub info: FrameBufferInfo,
}

pub struct Kernel<'a> {
pub elf: ElfFile<'a>,
pub config: BootloaderConfig,
Expand Down Expand Up @@ -100,8 +107,7 @@ where
kernel,
&mut frame_allocator,
&mut page_tables,
system_info.framebuffer_addr,
system_info.framebuffer_info.byte_len,
system_info.framebuffer.as_ref(),
&config,
);
let boot_info = create_boot_info(
Expand Down Expand Up @@ -132,8 +138,7 @@ pub fn set_up_mappings<I, D>(
kernel: Kernel,
frame_allocator: &mut LegacyFrameAllocator<I, D>,
page_tables: &mut PageTables,
framebuffer_addr: PhysAddr,
framebuffer_size: usize,
framebuffer: Option<&RawFrameBufferInfo>,
config: &BootloaderConfig,
) -> Mappings
where
Expand All @@ -145,7 +150,7 @@ where
let mut used_entries = UsedLevel4Entries::new(
frame_allocator.max_phys_addr(),
frame_allocator.len(),
framebuffer_size,
framebuffer,
config,
);

Expand Down Expand Up @@ -220,15 +225,15 @@ where
}

// map framebuffer
let framebuffer_virt_addr = {
let framebuffer_virt_addr = if let Some(framebuffer) = framebuffer {
log::info!("Map framebuffer");

let framebuffer_start_frame: PhysFrame = PhysFrame::containing_address(framebuffer_addr);
let framebuffer_start_frame: PhysFrame = PhysFrame::containing_address(framebuffer.addr);
let framebuffer_end_frame =
PhysFrame::containing_address(framebuffer_addr + framebuffer_size - 1u64);
PhysFrame::containing_address(framebuffer.addr + framebuffer.info.byte_len - 1u64);
let start_page = Page::from_start_address(mapping_addr(
config.mappings.framebuffer,
u64::from_usize(framebuffer_size),
u64::from_usize(framebuffer.info.byte_len),
Size4KiB::SIZE,
&mut used_entries,
))
Expand All @@ -248,6 +253,8 @@ where
}
let framebuffer_virt_addr = start_page.start_address();
Some(framebuffer_virt_addr)
} else {
None
};

let physical_memory_offset = if let Some(mapping) = config.mappings.physical_memory {
Expand Down Expand Up @@ -440,13 +447,7 @@ where
let mut info = BootInfo::new(memory_regions.into());
info.framebuffer = mappings
.framebuffer
.map(|addr| {
FrameBuffer::new(
addr.as_u64(),
system_info.framebuffer_info.byte_len,
system_info.framebuffer_info,
)
})
.map(|addr| FrameBuffer::new(addr.as_u64(), system_info.framebuffer.expect("there shouldn't be a mapping for the framebuffer if there is not framebuffer").info))
.into();
info.physical_memory_offset = mappings.physical_memory_offset.map(VirtAddr::as_u64).into();
info.recursive_index = mappings.recursive_index.map(Into::into).into();
Expand Down
22 changes: 14 additions & 8 deletions uefi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

use crate::memory_descriptor::UefiMemoryDescriptor;
use bootloader_api::{info::FrameBufferInfo, BootloaderConfig};
use bootloader_x86_64_common::{legacy_memory_region::LegacyFrameAllocator, Kernel, SystemInfo};
use bootloader_x86_64_common::{
legacy_memory_region::LegacyFrameAllocator, Kernel, RawFrameBufferInfo, SystemInfo,
};
use core::{arch::asm, cell::UnsafeCell, fmt::Write, mem, panic::PanicInfo, ptr, slice};
use uefi::{
prelude::{entry, Boot, Handle, Status, SystemTable},
Expand Down Expand Up @@ -74,7 +76,7 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {

let kernel = load_kernel(image, &mut st);

let (framebuffer_addr, framebuffer_info) = init_logger(&st, kernel.config);
let framebuffer = init_logger(&st, kernel.config);

// we no longer need the system table for printing panics
unsafe {
Expand All @@ -83,7 +85,9 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {

log::info!("UEFI bootloader started");
log::info!("Reading kernel and configuration from disk was successful");
log::info!("Using framebuffer at {:#x}", framebuffer_addr);
if let Some(framebuffer) = framebuffer {
log::info!("Using framebuffer at {:#x}", framebuffer.addr);
}

let mmap_storage = {
let max_mmap_size =
Expand All @@ -105,8 +109,7 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
let page_tables = create_page_tables(&mut frame_allocator);

let system_info = SystemInfo {
framebuffer_addr,
framebuffer_info,
framebuffer,
rsdp_addr: {
use uefi::table::cfg;
let mut config_entries = system_table.config_table().iter();
Expand Down Expand Up @@ -362,11 +365,11 @@ fn create_page_tables(
}
}

fn init_logger(st: &SystemTable<Boot>, config: BootloaderConfig) -> (PhysAddr, FrameBufferInfo) {
fn init_logger(st: &SystemTable<Boot>, config: BootloaderConfig) -> Option<RawFrameBufferInfo> {
let gop = st
.boot_services()
.locate_protocol::<GraphicsOutput>()
.expect("failed to locate gop");
.ok()?;
let gop = unsafe { &mut *gop.get() };

let mode = {
Expand Down Expand Up @@ -419,7 +422,10 @@ fn init_logger(st: &SystemTable<Boot>, config: BootloaderConfig) -> (PhysAddr, F

bootloader_x86_64_common::init_logger(slice, info);

(PhysAddr::new(framebuffer.as_mut_ptr() as u64), info)
Some(RawFrameBufferInfo {
addr: PhysAddr::new(framebuffer.as_mut_ptr() as u64),
info,
})
}

#[panic_handler]
Expand Down