feat: implement staged kernel initialization with memory management and TTY scrolling

This commit is contained in:
ParrotXray 2025-10-12 10:41:12 +08:00
parent 429e396474
commit ac199eabe2
4 changed files with 327 additions and 187 deletions

View File

@ -6,74 +6,146 @@ use crate::kernel::mm::{heap, frame_allocator};
use crate::kernel::tty::tty;
use crate::kprintln;
use crate::k_main;
use crate::hal::cpu;
fn _critical_init() {
gdt::init();
idt::init();
}
fn _memory_init(
memory_regions: &'static bootloader_api::info::MemoryRegions,
physical_memory_offset: u64
) -> (OffsetPageTable<'static>, frame_allocator::BootInfoFrameAllocator) {
let phys_mem_offset = VirtAddr::new(physical_memory_offset);
let mut mapper = unsafe {
OffsetPageTable::new(heap::get_level_4_table(phys_mem_offset), phys_mem_offset)
};
let mut frame_allocator = unsafe {
frame_allocator::BootInfoFrameAllocator::init(memory_regions)
};
heap::init_heap(&mut mapper, &mut frame_allocator)
.expect("Heap initialization failed");
(mapper, frame_allocator)
}
fn _display_init(framebuffer: &'static mut bootloader_api::info::FrameBuffer) {
tty::init(framebuffer);
tty::clear(0x000000);
kprintln!("========================================");
kprintln!(" CureOS Kernel v0.1.0" );
kprintln!("========================================");
kprintln!();
}
fn _boot_report(memory_regions: &bootloader_api::info::MemoryRegions, physical_memory_offset: u64) {
kprintln!("[INIT] Stage 1: Critical Hardware");
kprintln!(" [OK] GDT initialized");
gdt::print_info();
kprintln!();
kprintln!(" [OK] IDT initialized");
idt::print_info();
kprintln!();
kprintln!("[INIT] Stage 2: Memory Management");
kprintln!(" [OK] Physical Memory Offset: {:#x}", physical_memory_offset);
kprintln!(" [OK] Memory Regions:");
let mut total_usable = 0u64;
for region in memory_regions.iter() {
use bootloader_api::info::MemoryRegionKind;
let kind_str = match region.kind {
MemoryRegionKind::Usable => {
total_usable += region.end - region.start;
"Usable"
},
MemoryRegionKind::Bootloader => "Bootloader",
MemoryRegionKind::UnknownBios(_) => "Unknown",
MemoryRegionKind::UnknownUefi(_) => "UEFI Reserved",
_ => "Reserved",
};
kprintln!(" {:#016x} - {:#016x} ({})",
region.start, region.end, kind_str);
}
kprintln!(" [INFO] Total Usable Memory: {} MiB", total_usable / (1024 * 1024));
kprintln!();
kprintln!("[INIT] Stage 3: Heap Allocator");
kprintln!(" [OK] Heap Start: {:#x}", heap::HEAP_START);
kprintln!(" [OK] Heap Size: {} KiB", heap::HEAP_SIZE / 1024);
}
fn _acpi_init(rsdp_addr: Option<u64>, physical_memory_offset: u64) {
kprintln!();
kprintln!("[INIT] Stage 4: ACPI");
if let Some(rsdp) = rsdp_addr {
kprintln!(" [INFO] RSDP Address: {:#x}", rsdp);
if let Some(acpi_info) = acpi::init(rsdp, physical_memory_offset) {
acpi::print_info(&acpi_info);
} else {
kprintln!(" [WARN] ACPI initialization failed");
}
} else {
kprintln!(" [WARN] RSDP not provided by bootloader");
}
}
fn _post_init() {
kprintln!();
kprintln!("[INIT] Stage 5: Post Initialization");
// TODO: 釋放 bootloader 佔用的內存
// TODO: 釋放初始化代碼段(.init 段)
kprintln!(" [INFO] Cleanup completed");
}
/// 主初始化入口
pub fn kernel_init(boot_info: &'static mut BootInfo) -> ! {
if let Some(framebuffer) = boot_info.framebuffer.as_mut() {
tty::init(framebuffer);
tty::clear(0x000000);
kprintln!("CureOS Booting...");
kprintln!("Framebuffer initialized");
_critical_init();
let physical_memory_offset = boot_info
.physical_memory_offset
.into_option()
.expect("Physical memory offset not provided");
let rsdp_addr = boot_info.rsdp_addr.into_option();
let (_mapper, _frame_allocator) = _memory_init(
&boot_info.memory_regions,
physical_memory_offset
);
_display_init(framebuffer);
_boot_report(&boot_info.memory_regions, physical_memory_offset);
_acpi_init(rsdp_addr, physical_memory_offset);
_post_init();
kprintln!();
kprintln!("Initializing GDT...");
gdt::init();
kprintln!("GDT initialized");
gdt::print_info();
kprintln!("========================================");
kprintln!(" Kernel Initialization Complete!");
kprintln!("========================================");
kprintln!();
kprintln!("Initializing IDT...");
idt::init();
kprintln!("IDT initialized");
idt::print_info();
kprintln!();
tty::clear(0x000000);
let physical_memory_offset = if let Some(offset) = boot_info.physical_memory_offset.into_option() {
kprintln!("Physical Memory Offset: {:#x}", offset);
offset
} else {
panic!("Physical memory offset not provided by bootloader");
};
let phys_mem_offset = VirtAddr::new(physical_memory_offset);
let mut mapper = unsafe {
OffsetPageTable::new(heap::get_level_4_table(phys_mem_offset), phys_mem_offset)
};
let mut frame_allocator = unsafe {
frame_allocator::BootInfoFrameAllocator::init(&boot_info.memory_regions)
};
kprintln!("Initializing heap allocator...");
heap::init_heap(&mut mapper, &mut frame_allocator)
.expect("heap initialization failed");
kprintln!("Heap allocator initialized");
kprintln!("Heap Start: {:#x}", heap::HEAP_START);
kprintln!("Heap Size: {} KiB", heap::HEAP_SIZE / 1024);
kprintln!();
if let Some(rsdp) = boot_info.rsdp_addr.into_option() {
kprintln!("RSDP Address: {:#x}", rsdp);
kprintln!("Initializing ACPI...");
if let Some(acpi_info) = acpi::init(*&rsdp, physical_memory_offset) {
acpi::print_info(&acpi_info);
} else {
kprintln!("Warning: ACPI initialization failed");
}
} else {
kprintln!("Warning: RSDP not provided");
}
k_main::kernel_main();
} else {
loop {
cpu::cpu_halt();
}
panic!("No framebuffer provided by bootloader");
}
}
#[allow(dead_code)]
pub fn kernel_emergency_cleanup() {
// 在 panic 前調用,做最後的清理工作
// 比如刷新緩衝區、保存日誌等
}

View File

@ -213,7 +213,8 @@ pub fn init(rsdp_addr: u64, physical_memory_offset: u64) -> Option<AcpiInfo> {
}
}
};
// kprintln!(" ACPI Revision: {}", tables.rsdp_revision);
let platform = match AcpiPlatform::new(tables, handler) {
Ok(platform) => platform,
Err(e) => {

View File

@ -1,67 +1,224 @@
use bootloader_api::info::{FrameBuffer, FrameBufferInfo, PixelFormat};
use crate::kernel::tty::font::FONT_BASIC;
use core::ptr::{addr_of, addr_of_mut};
use spin::Mutex;
pub struct TTYState {
framebuffer: *mut u8,
fb_len: usize,
info: Option<FrameBufferInfo>,
info: FrameBufferInfo,
cursor_x: usize,
cursor_y: usize,
}
unsafe impl Send for TTYState {}
impl TTYState {
const fn new() -> Self {
const fn new_empty() -> Self {
Self {
framebuffer: core::ptr::null_mut(),
fb_len: 0,
info: None,
info: FrameBufferInfo {
byte_len: 0,
width: 0,
height: 0,
pixel_format: PixelFormat::Rgb,
bytes_per_pixel: 0,
stride: 0,
},
cursor_x: 0,
cursor_y: 0,
}
}
fn init(&mut self, framebuffer: *mut u8, fb_len: usize, info: FrameBufferInfo) {
self.framebuffer = framebuffer;
self.fb_len = fb_len;
self.info = info;
self.cursor_x = 0;
self.cursor_y = 0;
}
fn is_initialized(&self) -> bool {
!self.framebuffer.is_null()
}
fn clear(&mut self, color: u32) {
if !self.is_initialized() {
return;
}
let (r, g, b) = u32_to_rgb(color);
let buffer = unsafe {
core::slice::from_raw_parts_mut(self.framebuffer, self.fb_len)
};
for pixel in buffer.chunks_exact_mut(self.info.bytes_per_pixel) {
write_pixel(&self.info, pixel, r, g, b);
}
self.cursor_x = 0;
self.cursor_y = 0;
}
fn draw_pixel(&mut self, x: usize, y: usize, color: u32) {
if !self.is_initialized() {
return;
}
if x >= self.info.width || y >= self.info.height {
return;
}
let pixel_offset = (y * self.info.stride + x) * self.info.bytes_per_pixel;
let (r, g, b) = u32_to_rgb(color);
let buffer = unsafe {
core::slice::from_raw_parts_mut(self.framebuffer, self.fb_len)
};
if let Some(pixel) = buffer.get_mut(pixel_offset..pixel_offset + self.info.bytes_per_pixel) {
write_pixel(&self.info, pixel, r, g, b);
}
}
fn scroll_up(&mut self) {
const CHAR_HEIGHT: usize = 16;
if !self.is_initialized() {
return;
}
let buffer = unsafe {
core::slice::from_raw_parts_mut(self.framebuffer, self.fb_len)
};
let bytes_per_pixel = self.info.bytes_per_pixel;
let stride = self.info.stride;
let width = self.info.width;
let height = self.info.height;
for y in CHAR_HEIGHT..height {
let src_offset = y * stride * bytes_per_pixel;
let dst_offset = (y - CHAR_HEIGHT) * stride * bytes_per_pixel;
let row_size = width * bytes_per_pixel;
if src_offset + row_size <= buffer.len() && dst_offset + row_size <= buffer.len() {
buffer.copy_within(src_offset..src_offset + row_size, dst_offset);
}
}
for y in (height.saturating_sub(CHAR_HEIGHT))..height {
for x in 0..width {
let pixel_offset = (y * stride + x) * bytes_per_pixel;
if let Some(pixel) = buffer.get_mut(pixel_offset..pixel_offset + bytes_per_pixel) {
write_pixel(&self.info, pixel, 0, 0, 0);
}
}
}
self.cursor_x = 0;
self.cursor_y = height.saturating_sub(CHAR_HEIGHT);
}
fn draw_char(&mut self, c: char, color: u32) {
const CHAR_WIDTH: usize = 8;
const CHAR_HEIGHT: usize = 16;
if !self.is_initialized() {
return;
}
if c == '\n' {
self.cursor_x = 0;
self.cursor_y += CHAR_HEIGHT;
if self.cursor_y + CHAR_HEIGHT > self.info.height {
self.scroll_up();
}
return;
}
if self.cursor_x + CHAR_WIDTH > self.info.width {
self.cursor_x = 0;
self.cursor_y += CHAR_HEIGHT;
}
if self.cursor_y + CHAR_HEIGHT > self.info.height {
self.scroll_up();
}
let idx = c as usize;
if idx >= FONT_BASIC.len() {
return;
}
let glyph = &FONT_BASIC[idx];
let cursor_x = self.cursor_x;
let cursor_y = self.cursor_y;
for (y, row) in glyph.iter().enumerate() {
for x in 0..8 {
if (row >> (7 - x)) & 1 == 1 {
self.draw_pixel(cursor_x + x, cursor_y + y, color);
}
}
}
self.cursor_x += CHAR_WIDTH;
}
fn write_str(&mut self, s: &str, color: u32) {
for c in s.chars() {
self.draw_char(c, color);
}
}
pub fn get_cursor_pos(&self) -> (usize, usize) {
(self.cursor_x, self.cursor_y)
}
pub fn set_cursor_pos(&mut self, x: usize, y: usize) {
self.cursor_x = x;
self.cursor_y = y;
}
}
static mut TTY_STATE: TTYState = TTYState::new();
static TTY: Mutex<TTYState> = Mutex::new(TTYState::new_empty());
pub fn init(framebuffer: &'static mut FrameBuffer) {
let info = framebuffer.info();
let buffer = framebuffer.buffer_mut();
unsafe {
let state = &mut *addr_of_mut!(TTY_STATE);
state.framebuffer = buffer.as_mut_ptr();
state.fb_len = buffer.len();
state.info = Some(info);
state.cursor_x = 0;
state.cursor_y = 0;
}
TTY.lock().init(buffer.as_mut_ptr(), buffer.len(), info);
}
pub fn clear(color: u32) {
unsafe {
let state = &*addr_of!(TTY_STATE);
TTY.lock().clear(color);
}
if state.framebuffer.is_null() {
return;
}
pub fn draw_pixel(x: usize, y: usize, color: u32) {
TTY.lock().draw_pixel(x, y, color);
}
let info = match state.info.as_ref() {
Some(i) => i,
None => return,
};
pub fn draw_char(c: char, color: u32) {
TTY.lock().draw_char(c, color);
}
let (r, g, b) = u32_to_rgb(color);
let buffer = core::slice::from_raw_parts_mut(state.framebuffer, state.fb_len);
pub fn write_str(s: &str, color: u32) {
TTY.lock().write_str(s, color);
}
for pixel in buffer.chunks_exact_mut(info.bytes_per_pixel) {
write_pixel(info, pixel, r, g, b);
}
pub fn tty_put_str(s: &str, color: Option<u32>) {
let c = color.unwrap_or(0xFFFFFF);
write_str(s, c);
}
let state_mut = &mut *addr_of_mut!(TTY_STATE);
state_mut.cursor_x = 0;
state_mut.cursor_y = 0;
}
pub fn get_cursor_pos() -> (usize, usize) {
TTY.lock().get_cursor_pos()
}
pub fn set_cursor_pos(x: usize, y: usize) {
TTY.lock().set_cursor_pos(x, y);
}
fn write_pixel(info: &FrameBufferInfo, pixel: &mut [u8], r: u8, g: u8, b: u8) {
@ -80,102 +237,6 @@ fn write_pixel(info: &FrameBufferInfo, pixel: &mut [u8], r: u8, g: u8, b: u8) {
}
}
pub fn draw_pixel(x: usize, y: usize, color: u32) {
unsafe {
let state = &*addr_of!(TTY_STATE);
if state.framebuffer.is_null() {
return;
}
let info = match state.info.as_ref() {
Some(i) => i,
None => return,
};
if x >= info.width || y >= info.height {
return;
}
let pixel_offset = (y * info.stride + x) * info.bytes_per_pixel;
let (r, g, b) = u32_to_rgb(color);
let buffer = core::slice::from_raw_parts_mut(state.framebuffer, state.fb_len);
if let Some(pixel) = buffer.get_mut(pixel_offset..pixel_offset + info.bytes_per_pixel) {
write_pixel(info, pixel, r, g, b);
}
}
}
pub fn draw_char(c: char, color: u32) {
const CHAR_WIDTH: usize = 8;
const CHAR_HEIGHT: usize = 16;
unsafe {
let state = &*addr_of!(TTY_STATE);
if state.framebuffer.is_null() {
return;
}
let info = match state.info.as_ref() {
Some(i) => i,
None => return,
};
let state_mut = &mut *addr_of_mut!(TTY_STATE);
if c == '\n' {
state_mut.cursor_x = 0;
state_mut.cursor_y += CHAR_HEIGHT;
return;
}
if state_mut.cursor_x + CHAR_WIDTH > info.width {
state_mut.cursor_x = 0;
state_mut.cursor_y += CHAR_HEIGHT;
}
if state_mut.cursor_y + CHAR_HEIGHT > info.height {
state_mut.cursor_y = 0;
}
let idx = c as usize;
if idx >= FONT_BASIC.len() {
return;
}
let glyph = &FONT_BASIC[idx];
let cursor_x = state_mut.cursor_x;
let cursor_y = state_mut.cursor_y;
for (y, row) in glyph.iter().enumerate() {
for x in 0..8 {
if (row >> (7 - x)) & 1 == 1 {
draw_pixel(cursor_x + x, cursor_y + y, color);
}
}
}
state_mut.cursor_x += CHAR_WIDTH;
}
}
pub fn write_str(s: &str, color: u32) {
for c in s.chars() {
draw_char(c, color);
}
}
pub fn tty_put_str(s: &str, color: Option<u32>) {
if let Some(c) = color {
write_str(s, c);
} else {
write_str(s, 0xFFFFFF);
}
}
fn u32_to_rgb(color: u32) -> (u8, u8, u8) {
let r = ((color >> 16) & 0xFF) as u8;
let g = ((color >> 8) & 0xFF) as u8;

View File

@ -41,7 +41,13 @@ fn panic(info: &PanicInfo) -> ! {
kprintln!("================================");
kprintln!();
kprintln!("{}", info);
kprintln!();
kprintln!("Control Registers:");
kprintln!(" CR0: 0x{:016x}", cpu::cpu_r_cr0().bits());
kprintln!(" CR2: 0x{:016x}", cpu::cpu_r_cr2());
kprintln!(" CR3: 0x{:016x}", cpu::cpu_r_cr3());
kprintln!(" CR4: 0x{:016x}", cpu::cpu_r_cr4().bits());
loop {
cpu::cpu_halt();
}