Skip to content

Commit 29b9912

Browse files
authored
Merge pull request #268 from Freax13/optional-framebuffer
allow booting without a UEFI graphics output
2 parents c78a2f5 + d6e0d2b commit 29b9912

File tree

5 files changed

+49
-42
lines changed

5 files changed

+49
-42
lines changed

api/src/info.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -158,17 +158,12 @@ pub enum MemoryRegionKind {
158158
#[repr(C)]
159159
pub struct FrameBuffer {
160160
pub(crate) buffer_start: u64,
161-
pub(crate) buffer_byte_len: usize,
162161
pub(crate) info: FrameBufferInfo,
163162
}
164163

165164
impl FrameBuffer {
166-
pub fn new(buffer_start: u64, buffer_byte_len: usize, info: FrameBufferInfo) -> Self {
167-
Self {
168-
buffer_start,
169-
buffer_byte_len,
170-
info,
171-
}
165+
pub fn new(buffer_start: u64, info: FrameBufferInfo) -> Self {
166+
Self { buffer_start, info }
172167
}
173168

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

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

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

192187
/// Returns layout and pixel format information of the framebuffer.

bios/stage-4/src/main.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use crate::memory_descriptor::MemoryRegion;
55
use bootloader_api::info::{FrameBufferInfo, PixelFormat};
66
use bootloader_x86_64_bios_common::{BiosFramebufferInfo, BiosInfo, E820MemoryRegion};
7+
use bootloader_x86_64_common::RawFrameBufferInfo;
78
use bootloader_x86_64_common::{
89
legacy_memory_region::LegacyFrameAllocator, load_and_switch_to_kernel, Kernel, PageTables,
910
SystemInfo,
@@ -112,8 +113,10 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
112113
let kernel = Kernel::parse(kernel_slice);
113114

114115
let system_info = SystemInfo {
115-
framebuffer_addr: PhysAddr::new(info.framebuffer.region.start),
116-
framebuffer_info,
116+
framebuffer: Some(RawFrameBufferInfo {
117+
addr: PhysAddr::new(info.framebuffer.region.start),
118+
info: framebuffer_info,
119+
}),
117120
rsdp_addr: detect_rsdp(),
118121
};
119122

common/src/level_4_entries.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{entropy, BootInfo};
1+
use crate::{entropy, BootInfo, RawFrameBufferInfo};
22
use bootloader_api::{config, info::MemoryRegion, BootloaderConfig};
33
use core::{alloc::Layout, iter::Step};
44
use rand::{
@@ -31,7 +31,7 @@ impl UsedLevel4Entries {
3131
pub fn new(
3232
max_phys_addr: PhysAddr,
3333
regions_len: usize,
34-
framebuffer_size: usize,
34+
framebuffer: Option<&RawFrameBufferInfo>,
3535
config: &BootloaderConfig,
3636
) -> Self {
3737
let mut used = UsedLevel4Entries {
@@ -70,7 +70,9 @@ impl UsedLevel4Entries {
7070
}
7171

7272
if let config::Mapping::FixedAddress(framebuffer_address) = config.mappings.framebuffer {
73-
used.mark_range_as_used(framebuffer_address, framebuffer_size);
73+
if let Some(framebuffer) = framebuffer {
74+
used.mark_range_as_used(framebuffer_address, framebuffer.info.byte_len);
75+
}
7476
}
7577

7678
// Mark everything before the dynamic range as unusable.

common/src/lib.rs

+21-20
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,21 @@ pub fn init_logger(framebuffer: &'static mut [u8], info: FrameBufferInfo) {
4545
/// Required system information that should be queried from the BIOS or UEFI firmware.
4646
#[derive(Debug, Copy, Clone)]
4747
pub struct SystemInfo {
48-
/// Start address of the pixel-based framebuffer.
49-
pub framebuffer_addr: PhysAddr,
50-
/// Information about the framebuffer, including layout and pixel format.
51-
pub framebuffer_info: FrameBufferInfo,
48+
/// Information about the (still unmapped) framebuffer.
49+
pub framebuffer: Option<RawFrameBufferInfo>,
5250
/// Address of the _Root System Description Pointer_ structure of the ACPI standard.
5351
pub rsdp_addr: Option<PhysAddr>,
5452
}
5553

54+
/// The physical address of the framebuffer and information about the framebuffer.
55+
#[derive(Debug, Copy, Clone)]
56+
pub struct RawFrameBufferInfo {
57+
/// Start address of the pixel-based framebuffer.
58+
pub addr: PhysAddr,
59+
/// Information about the framebuffer, including layout and pixel format.
60+
pub info: FrameBufferInfo,
61+
}
62+
5663
pub struct Kernel<'a> {
5764
pub elf: ElfFile<'a>,
5865
pub config: BootloaderConfig,
@@ -100,8 +107,7 @@ where
100107
kernel,
101108
&mut frame_allocator,
102109
&mut page_tables,
103-
system_info.framebuffer_addr,
104-
system_info.framebuffer_info.byte_len,
110+
system_info.framebuffer.as_ref(),
105111
&config,
106112
);
107113
let boot_info = create_boot_info(
@@ -132,8 +138,7 @@ pub fn set_up_mappings<I, D>(
132138
kernel: Kernel,
133139
frame_allocator: &mut LegacyFrameAllocator<I, D>,
134140
page_tables: &mut PageTables,
135-
framebuffer_addr: PhysAddr,
136-
framebuffer_size: usize,
141+
framebuffer: Option<&RawFrameBufferInfo>,
137142
config: &BootloaderConfig,
138143
) -> Mappings
139144
where
@@ -145,7 +150,7 @@ where
145150
let mut used_entries = UsedLevel4Entries::new(
146151
frame_allocator.max_phys_addr(),
147152
frame_allocator.len(),
148-
framebuffer_size,
153+
framebuffer,
149154
config,
150155
);
151156

@@ -220,15 +225,15 @@ where
220225
}
221226

222227
// map framebuffer
223-
let framebuffer_virt_addr = {
228+
let framebuffer_virt_addr = if let Some(framebuffer) = framebuffer {
224229
log::info!("Map framebuffer");
225230

226-
let framebuffer_start_frame: PhysFrame = PhysFrame::containing_address(framebuffer_addr);
231+
let framebuffer_start_frame: PhysFrame = PhysFrame::containing_address(framebuffer.addr);
227232
let framebuffer_end_frame =
228-
PhysFrame::containing_address(framebuffer_addr + framebuffer_size - 1u64);
233+
PhysFrame::containing_address(framebuffer.addr + framebuffer.info.byte_len - 1u64);
229234
let start_page = Page::from_start_address(mapping_addr(
230235
config.mappings.framebuffer,
231-
u64::from_usize(framebuffer_size),
236+
u64::from_usize(framebuffer.info.byte_len),
232237
Size4KiB::SIZE,
233238
&mut used_entries,
234239
))
@@ -248,6 +253,8 @@ where
248253
}
249254
let framebuffer_virt_addr = start_page.start_address();
250255
Some(framebuffer_virt_addr)
256+
} else {
257+
None
251258
};
252259

253260
let physical_memory_offset = if let Some(mapping) = config.mappings.physical_memory {
@@ -440,13 +447,7 @@ where
440447
let mut info = BootInfo::new(memory_regions.into());
441448
info.framebuffer = mappings
442449
.framebuffer
443-
.map(|addr| {
444-
FrameBuffer::new(
445-
addr.as_u64(),
446-
system_info.framebuffer_info.byte_len,
447-
system_info.framebuffer_info,
448-
)
449-
})
450+
.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))
450451
.into();
451452
info.physical_memory_offset = mappings.physical_memory_offset.map(VirtAddr::as_u64).into();
452453
info.recursive_index = mappings.recursive_index.map(Into::into).into();

uefi/src/main.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

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

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

77-
let (framebuffer_addr, framebuffer_info) = init_logger(&st, kernel.config);
79+
let framebuffer = init_logger(&st, kernel.config);
7880

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

8486
log::info!("UEFI bootloader started");
8587
log::info!("Reading kernel and configuration from disk was successful");
86-
log::info!("Using framebuffer at {:#x}", framebuffer_addr);
88+
if let Some(framebuffer) = framebuffer {
89+
log::info!("Using framebuffer at {:#x}", framebuffer.addr);
90+
}
8791

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

107111
let system_info = SystemInfo {
108-
framebuffer_addr,
109-
framebuffer_info,
112+
framebuffer,
110113
rsdp_addr: {
111114
use uefi::table::cfg;
112115
let mut config_entries = system_table.config_table().iter();
@@ -362,11 +365,11 @@ fn create_page_tables(
362365
}
363366
}
364367

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

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

420423
bootloader_x86_64_common::init_logger(slice, info);
421424

422-
(PhysAddr::new(framebuffer.as_mut_ptr() as u64), info)
425+
Some(RawFrameBufferInfo {
426+
addr: PhysAddr::new(framebuffer.as_mut_ptr() as u64),
427+
info,
428+
})
423429
}
424430

425431
#[panic_handler]

0 commit comments

Comments
 (0)