diff --git a/kernel/src/k_init.rs b/kernel/src/k_init.rs index 114c2a4..67ccd66 100644 --- a/kernel/src/k_init.rs +++ b/kernel/src/k_init.rs @@ -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, 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 前調用,做最後的清理工作 + // 比如刷新緩衝區、保存日誌等 } \ No newline at end of file diff --git a/kernel/src/kernel/asm/x86/acpi.rs b/kernel/src/kernel/asm/x86/acpi.rs index fab5fe2..4f2027b 100644 --- a/kernel/src/kernel/asm/x86/acpi.rs +++ b/kernel/src/kernel/asm/x86/acpi.rs @@ -213,7 +213,8 @@ pub fn init(rsdp_addr: u64, physical_memory_offset: u64) -> Option { } } }; - + // kprintln!(" ACPI Revision: {}", tables.rsdp_revision); + let platform = match AcpiPlatform::new(tables, handler) { Ok(platform) => platform, Err(e) => { diff --git a/kernel/src/kernel/tty/tty.rs b/kernel/src/kernel/tty/tty.rs index be88ace..deff8e6 100644 --- a/kernel/src/kernel/tty/tty.rs +++ b/kernel/src/kernel/tty/tty.rs @@ -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, + 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 = 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) { + 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) { - 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; diff --git a/kernel/src/main.rs b/kernel/src/main.rs index a706a66..36239be 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -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(); }