feat: raw framebuffer fallback for fbbootlogd when DRM unavailable

- Add RawFb struct: direct framebuffer rendering via physmap
- Add RawTextScreen: simple text renderer using orbclient font
- Fallback in FbbootlogScheme::new() when V2GraphicsHandle fails
- Reads FRAMEBUFFER_ADDR/WIDTH/HEIGHT/STRIDE from bootloader env
- Scroll via ptr::copy on pixel rows, clear bottom line
- No DRM, no shadow buffer, no GPU required — like MS-DOS text mode
- Add common dependency to fbbootlogd Cargo.toml
This commit is contained in:
2026-05-17 14:56:50 +03:00
parent 20853c41f5
commit 2bfe4b427b
58 changed files with 1691 additions and 3602 deletions
@@ -74,16 +74,14 @@ impl MemoryEntry {
}
struct MemoryMap {
entries: [MemoryEntry; 1024],
entries: [MemoryEntry; 512],
size: usize,
}
impl MemoryMap {
fn register(&mut self, base: usize, size: usize, kind: BootloaderMemoryKind) {
if self.size >= self.entries.len() {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
unsafe { core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'!', options(nostack, preserves_flags)); }
panic!("Early memory map overflow at entry {} (max {})", self.size, self.entries.len());
panic!("Early memory map overflow!");
}
let start = if kind == BootloaderMemoryKind::Free {
align_up(base)
@@ -136,7 +134,7 @@ static MEMORY_MAP: SyncUnsafeCell<MemoryMap> = SyncUnsafeCell::new(MemoryMap {
start: 0,
end: 0,
kind: BootloaderMemoryKind::Null,
}; 1024],
}; 512],
size: 0,
});
@@ -325,16 +323,7 @@ unsafe fn map_memory<A: Arch>(areas: &[MemoryArea], mut bump_allocator: &mut Bum
}
}
let kernel_area = match (*MEMORY_MAP.get()).kernel() {
Some(area) => area,
None => {
println!("FATAL: kernel memory area not found in boot memory map");
println!("Cannot determine kernel base address. Halting.");
loop {
core::hint::spin_loop();
}
}
};
let kernel_area = (*MEMORY_MAP.get()).kernel().unwrap();
let kernel_base = kernel_area.start;
let kernel_size = kernel_area.end.saturating_sub(kernel_area.start);
// Map kernel at KERNEL_OFFSET
+3 -10
View File
@@ -149,15 +149,6 @@ static BOOTSTRAP: spin::Once<Bootstrap> = spin::Once::new();
pub(crate) static AP_READY: AtomicBool = AtomicBool::new(false);
static BSP_READY: AtomicBool = AtomicBool::new(false);
#[cold]
fn halt_boot(message: &str) -> ! {
print!("{message}");
println!("Kernel boot cannot continue. Halting.");
loop {
hint::spin_loop();
}
}
/// This is the kernel entry point for the primary CPU. The arch crate is responsible for calling this
pub(crate) fn kmain(bootstrap: Bootstrap) -> ! {
let mut token = unsafe { CleanLockToken::new() };
@@ -189,7 +180,9 @@ pub(crate) fn kmain(bootstrap: Bootstrap) -> ! {
context.euid = 0;
context.egid = 0;
}
Err(_err) => halt_boot("FATAL: failed to spawn first userspace process userspace_init\n"),
Err(err) => {
panic!("failed to spawn userspace_init: {:?}", err);
}
}
run_userspace(&mut token)