diff --git a/Cargo.lock b/Cargo.lock index de27815..c16372d 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,20 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "acpi" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c85d96f36022f650ee6f184f1353d077124754cecf6a3e91085a708495c6f5a" +dependencies = [ + "bit_field", + "bitflags 2.9.4", + "byteorder", + "log", + "pci_types", + "spinning_top 0.3.0", +] + [[package]] name = "anyhow" version = "1.0.100" @@ -123,8 +137,10 @@ dependencies = [ name = "cure-kernel" version = "0.1.0" dependencies = [ + "acpi", "bootloader_api", "lazy_static", + "linked_list_allocator", "raw-cpuid", "spin 0.10.0", "x86_64", @@ -218,6 +234,15 @@ version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" +dependencies = [ + "spinning_top 0.2.5", +] + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -270,6 +295,16 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "pci_types" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4325c6aa3cca3373503b1527e75756f9fbfe5fd76be4b4c8a143ee47430b8e0" +dependencies = [ + "bit_field", + "bitflags 2.9.4", +] + [[package]] name = "proc-macro2" version = "1.0.101" @@ -302,11 +337,11 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "raw-cpuid" -version = "10.7.0" +version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.4", ] [[package]] @@ -407,6 +442,24 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spinning_top" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "syn" version = "2.0.106" diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..ef82997 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,22 @@ +// 1. 中斷處理 +// - IDT (中斷描述符表) - OK +// - 中斷處理函數 - OK +// - ACPI 初始化 - OK +// - PIC/APIC 初始化 + +// - 滾動 + +// 2. 內存管理 +// - 物理內存分配器 +// - 虛擬內存分配器 +// - 堆分配器 + +// 3. 頁表管理 +// - 修改頁表 +// - 映射新的內存區域 +// - 取消映射 + +// 4. 進程管理 +// - 任務切換 +// - 調度器 +// - 用戶態/內核態切換 \ No newline at end of file diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 288789d..d5e86b7 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -8,8 +8,10 @@ bootloader_api = "0.11.12" lazy_static = { version = "1.5.0", features = ["spin_no_std"] } x86_64 = { version = "0.15.2", features = ["instructions"] } spin = "0.10.0" -raw-cpuid = "10.7.0" +raw-cpuid = "11.6.0" +acpi = "6.0.1" +linked_list_allocator = "0.10.5" -[package.metadata.bootloader] -map-physical-memory = true -physical-memory-offset = "0xFFFF800000000000" \ No newline at end of file +#[package.metadata.bootloader] +#map-physical-memory = true +#physical-memory-offset = "0xFFFF800000000000" \ No newline at end of file diff --git a/kernel/src/hal/cpu.rs b/kernel/src/hal/cpu.rs index f8ab091..81f2adc 100644 --- a/kernel/src/hal/cpu.rs +++ b/kernel/src/hal/cpu.rs @@ -48,8 +48,6 @@ pub struct SgReg { pub cs: Reg16, } -// ============ 控制寄存器 ============ - /// 讀取 CR0 暫存器 #[allow(dead_code)] #[inline] @@ -181,8 +179,6 @@ pub fn cpu_get_brand(brand_out: &mut [u8]) -> &str { } } -// ============ CPU 指令 ============ - /// 讀取 CPU 時間戳計數器 (TSC) /// /// # 返回 diff --git a/kernel/src/k_init.rs b/kernel/src/k_init.rs new file mode 100644 index 0000000..114c2a4 --- /dev/null +++ b/kernel/src/k_init.rs @@ -0,0 +1,79 @@ +use bootloader_api::BootInfo; +use x86_64::structures::paging::OffsetPageTable; +use x86_64::VirtAddr; +use crate::kernel::asm::x86::{gdt, idt, acpi}; +use crate::kernel::mm::{heap, frame_allocator}; +use crate::kernel::tty::tty; +use crate::kprintln; +use crate::k_main; +use crate::hal::cpu; + +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"); + + kprintln!(); + kprintln!("Initializing GDT..."); + gdt::init(); + kprintln!("GDT initialized"); + gdt::print_info(); + + 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(); + } + } +} \ No newline at end of file diff --git a/kernel/src/k_main.rs b/kernel/src/k_main.rs new file mode 100644 index 0000000..97ad1c1 --- /dev/null +++ b/kernel/src/k_main.rs @@ -0,0 +1,27 @@ +use crate::hal::cpu; +use crate::kprintln; + +pub fn kernel_main() -> ! { + kprintln!("Welcome to CureOS!"); + + let mut brand_buf = [0u8; 64]; + let mut model_buf = [0u8; 16]; + kprintln!("CPU: {} ({})", + cpu::cpu_get_brand(&mut brand_buf), + cpu::cpu_get_model(&mut model_buf) + ); + + 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()); + + kprintln!(); + kprintln!("Kernel initialized successfully!"); + + loop { + cpu::cpu_halt(); + } +} \ No newline at end of file diff --git a/kernel/src/kernel/asm/x86/acpi.rs b/kernel/src/kernel/asm/x86/acpi.rs new file mode 100644 index 0000000..fab5fe2 --- /dev/null +++ b/kernel/src/kernel/asm/x86/acpi.rs @@ -0,0 +1,318 @@ +use acpi::{aml, AcpiTables, Handle, Handler, PciAddress, PhysicalMapping}; +use acpi::platform::{AcpiPlatform, interrupt::InterruptModel, PciConfigRegions}; +use acpi::sdt::hpet::HpetInfo; +use acpi::rsdp::Rsdp; +use core::ptr::NonNull; +use core::mem; +use crate::kprintln; + +#[derive(Clone, Copy)] +pub struct CureAcpiHandler { + physical_memory_offset: u64, +} + +impl CureAcpiHandler { + pub const fn new(physical_memory_offset: u64) -> Self { + Self { + physical_memory_offset, + } + } +} + +impl Handler for CureAcpiHandler { + unsafe fn map_physical_region( + &self, + physical_address: usize, + size: usize, + ) -> PhysicalMapping { + // Bootloader 已經映射了所有物理記憶體 + let virtual_address = physical_address as u64 + self.physical_memory_offset; + let virtual_start = NonNull::new((virtual_address) as *mut T).unwrap(); + + PhysicalMapping { + physical_start: physical_address, + virtual_start, + region_length: size, + mapped_length: size, + handler: *self, + } + } + + fn unmap_physical_region(region: &PhysicalMapping) { + // + } + + fn read_u8(&self, address: usize) -> u8 { + unsafe { + let ptr = self.map_physical_region::(address, 1); + core::ptr::read_volatile(ptr.virtual_start.as_ptr()) + } + } + + fn read_u16(&self, address: usize) -> u16 { + unsafe { + let ptr = self.map_physical_region::(address, 2); + core::ptr::read_volatile(ptr.virtual_start.as_ptr()) + } + } + + fn read_u32(&self, address: usize) -> u32 { + unsafe { + let ptr = self.map_physical_region::(address, 4); + core::ptr::read_volatile(ptr.virtual_start.as_ptr()) + } + } + + fn read_u64(&self, address: usize) -> u64 { + unsafe { + let ptr = self.map_physical_region::(address, 8); + core::ptr::read_volatile(ptr.virtual_start.as_ptr()) + } + } + + fn write_u8(&self, address: usize, value: u8) { + unsafe { + let ptr = self.map_physical_region::(address, 1); + core::ptr::write_volatile(ptr.virtual_start.as_ptr(), value); + } + } + + fn write_u16(&self, address: usize, value: u16) { + unsafe { + let ptr = self.map_physical_region::(address, 2); + core::ptr::write_volatile(ptr.virtual_start.as_ptr(), value); + } + } + + fn write_u32(&self, address: usize, value: u32) { + unsafe { + let ptr = self.map_physical_region::(address, 4); + core::ptr::write_volatile(ptr.virtual_start.as_ptr(), value); + } + } + + fn write_u64(&self, address: usize, value: u64) { + unsafe { + let ptr = self.map_physical_region::(address, 8); + core::ptr::write_volatile(ptr.virtual_start.as_ptr(), value); + } + } + + fn read_io_u8(&self, port: u16) -> u8 { + unsafe { crate::hal::io::io_port_rb(port) } + } + + fn read_io_u16(&self, port: u16) -> u16 { + unsafe { crate::hal::io::io_port_rw(port) } + } + + fn read_io_u32(&self, port: u16) -> u32 { + unsafe { crate::hal::io::io_port_rl(port) } + } + + fn write_io_u8(&self, port: u16, value: u8) { + unsafe { crate::hal::io::io_port_wb(port, value) }; + } + + fn write_io_u16(&self, port: u16, value: u16) { + unsafe { crate::hal::io::io_port_ww(port, value) }; + } + + fn write_io_u32(&self, port: u16, value: u32) { + unsafe { crate::hal::io::io_port_wl(port, value) }; + } + + fn read_pci_u8(&self, address: PciAddress, offset: u16) -> u8 { + // TODO: 實作 PCI 配置空間讀取 + 0xFF + } + + fn read_pci_u16(&self, address: PciAddress, offset: u16) -> u16 { + // TODO: 實作 PCI 配置空間讀取 + 0xFFFF + } + + fn read_pci_u32(&self, address: PciAddress, offset: u16) -> u32 { + // TODO: 實作 PCI 配置空間讀取 + 0xFFFFFFFF + } + + fn write_pci_u8(&self, address: PciAddress, offset: u16, value: u8) { + // TODO: 實作 PCI 配置空間寫入 + } + + fn write_pci_u16(&self, address: PciAddress, offset: u16, value: u16) { + // TODO: 實作 PCI 配置空間寫入 + } + + fn write_pci_u32(&self, address: PciAddress, offset: u16, value: u32) { + // TODO: 實作 PCI 配置空間寫入 + } + + fn nanos_since_boot(&self) -> u64 { + // TODO: 實作高精度計時器 (需要 HPET 或 TSC) + // 目前返回 0 + 0 + } + + fn stall(&self, _microseconds: u64) { + // TODO: 實作微秒級延遲 + // 簡單的忙等待實作 + for _ in 0..(_microseconds * 1000) { + crate::hal::cpu::cpu_pause(); + } + } + + fn sleep(&self, _milliseconds: u64) { + // TODO: 實作毫秒級睡眠 + // 簡單的忙等待實作 + self.stall(_milliseconds * 1000); + } + + fn create_mutex(&self) -> acpi::Handle { + // TODO: 實作 Mutex + // 目前返回一個假的 handle + acpi::Handle(0) + } + + fn acquire(&self, mutex: Handle, timeout: u16) -> Result<(), aml::AmlError> { + // TODO: 實作 Mutex 獲取 + // 暫時直接返回成功 + Ok(()) + } + + fn release(&self, _handle: acpi::Handle) { + // TODO: 實作 Mutex 釋放 + } +} + +pub struct AcpiInfo { + pub revision: u8, + pub boot_processor: Option, + pub cpu_count: usize, + pub has_apic: bool, + pub has_hpet: bool, +} + +pub fn init(rsdp_addr: u64, physical_memory_offset: u64) -> Option { + + let handler = CureAcpiHandler::new(physical_memory_offset); + + let rsdp_mapping = unsafe { + handler.map_physical_region::(rsdp_addr as usize, mem::size_of::()) + }; + let revision = rsdp_mapping.revision(); + kprintln!(" ACPI Revision: {}", revision); + + let tables = unsafe { + match AcpiTables::from_rsdp(handler, rsdp_addr as usize) { + Ok(tables) => tables, + Err(e) => { + kprintln!(" Failed to parse ACPI tables: {:?}", e); + return None; + } + } + }; + + let platform = match AcpiPlatform::new(tables, handler) { + Ok(platform) => platform, + Err(e) => { + kprintln!(" Failed to create ACPI platform: {:?}", e); + return None; + } + }; + + kprintln!(" Platform Info:"); + kprintln!(" Power Profile: {:?}", platform.power_profile); + + let (boot_processor, cpu_count) = if let Some(proc_info) = &platform.processor_info { + let boot_proc = Some(proc_info.boot_processor.processor_uid); + let cpu_cnt = proc_info.application_processors.len() + 1; + + kprintln!(" Boot Processor UID: {:?}", boot_proc); + kprintln!(" Total CPU Count: {}", cpu_cnt); + + (boot_proc, cpu_cnt) + } else { + kprintln!(" No processor info found"); + (None, 0) + }; + + // 檢查中斷模型 + let has_apic = match &platform.interrupt_model { + InterruptModel::Apic(apic) => { + kprintln!(" Interrupt Model: APIC"); + kprintln!(" Local APIC Address: {:#x}", apic.local_apic_address); + kprintln!(" IO APICs: {} controller(s)", apic.io_apics.len()); + + for (i, io_apic) in apic.io_apics.iter().enumerate() { + kprintln!(" IO APIC {}: ID={}, Address={:#x}, GSI Base={}", + i, io_apic.id, io_apic.address, io_apic.global_system_interrupt_base); + } + + true + } + InterruptModel::Unknown => { + kprintln!(" Interrupt Model: Unknown (not APIC)"); + false + } + _ => { + kprintln!(" Interrupt Model: Other"); + false + } + }; + + // 檢查 HPET (High Precision Event Timer) + let has_hpet = match HpetInfo::new(&platform.tables) { + Ok(hpet) => { + kprintln!(" HPET (High Precision Event Timer):"); + kprintln!(" Base Address: {:#x}", hpet.base_address); + kprintln!(" Hardware Rev: {}", hpet.hardware_rev); + kprintln!(" Comparator Count: {}", hpet.num_comparators); + kprintln!(" Counter Size: {} bit", if hpet.main_counter_is_64bits { 64 } else { 32 }); + kprintln!(" Legacy IRQ Capable: {}", hpet.legacy_irq_capable); + kprintln!(" PCI Vendor ID: {:#x}", hpet.pci_vendor_id); + true + } + Err(_) => { + kprintln!(" HPET: Not available"); + false + } + }; + + if let Ok(mcfg) = PciConfigRegions::new(&platform.tables) { + kprintln!(" PCI Express Configuration:"); + for (i, entry) in mcfg.regions.iter().enumerate() { + let segment_group = entry.pci_segment_group; + let base_addr = entry.base_address; + let bus_start = entry.bus_number_start; + let bus_end = entry.bus_number_end; + + kprintln!(" Entry {}: Segment Group {}", i, segment_group); + kprintln!(" Base Address: {:#x}", base_addr); + kprintln!(" Bus Range: {}-{}", bus_start, bus_end); + } + } + + kprintln!(" ACPI initialized successfully!"); + + Some(AcpiInfo { + revision, + boot_processor, + cpu_count, + has_apic, + has_hpet, + }) +} + +pub fn print_info(info: &AcpiInfo) { + kprintln!(); + kprintln!("ACPI Summary:"); + kprintln!(" Revision: ACPI {}.0", info.revision); + kprintln!(" CPUs: {} processor(s)", info.cpu_count); + if let Some(boot_proc) = info.boot_processor { + kprintln!(" Boot Processor: UID {}", boot_proc); + } + kprintln!(" APIC: {}", if info.has_apic { "Available " } else { "Not available" }); + kprintln!(" HPET: {}", if info.has_hpet { "Available " } else { "Not available" }); +} \ No newline at end of file diff --git a/kernel/src/kernel/asm/x86/mod.rs b/kernel/src/kernel/asm/x86/mod.rs index dce898d..3d8d4af 100644 --- a/kernel/src/kernel/asm/x86/mod.rs +++ b/kernel/src/kernel/asm/x86/mod.rs @@ -1,4 +1,5 @@ pub mod gdt; pub mod idt; pub mod interrupt; +pub(crate) mod acpi; // pub mod segment; \ No newline at end of file diff --git a/kernel/src/kernel/mm/frame_allocator.rs b/kernel/src/kernel/mm/frame_allocator.rs new file mode 100644 index 0000000..4e488c0 --- /dev/null +++ b/kernel/src/kernel/mm/frame_allocator.rs @@ -0,0 +1,49 @@ + +// kernel/src/mm/frame_allocator.rs +use bootloader_api::info::{MemoryRegion, MemoryRegionKind, MemoryRegions}; +use x86_64::{ + structures::paging::{FrameAllocator, PhysFrame, Size4KiB}, + PhysAddr, +}; + +pub struct BootInfoFrameAllocator { + memory_regions: &'static MemoryRegions, + next: usize, +} + +impl BootInfoFrameAllocator { + /// Create a FrameAllocator from the memory map provided by the bootloader. + /// + /// # Safety + /// The caller must ensure that the memory map passed in is valid. + /// In particular, all frames marked `USABLE` must actually be unused. + pub unsafe fn init(memory_regions: &'static MemoryRegions) -> Self { + BootInfoFrameAllocator { + memory_regions, + next: 0, + } + } + + fn usable_frames(&self) -> impl Iterator { + // Get the available memory area + let regions = self.memory_regions.iter(); + let usable_regions = regions.filter(|r| r.kind == MemoryRegionKind::Usable); + + // Map each region to its address range + let addr_ranges = usable_regions.map(|r| r.start..r.end); + + // Convert to an iterator of the frame start address + let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); + + // Create `PhysFrame` type from the starting address + frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) + } +} + +unsafe impl FrameAllocator for BootInfoFrameAllocator { + fn allocate_frame(&mut self) -> Option { + let frame = self.usable_frames().nth(self.next); + self.next += 1; + frame + } +} \ No newline at end of file diff --git a/kernel/src/kernel/mm/heap.rs b/kernel/src/kernel/mm/heap.rs new file mode 100644 index 0000000..4ea647a --- /dev/null +++ b/kernel/src/kernel/mm/heap.rs @@ -0,0 +1,68 @@ +// kernel/src/mm/heap.rs +use linked_list_allocator::LockedHeap; +use x86_64::{ + structures::paging::{ + mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB, + }, + VirtAddr, +}; +use x86_64::structures::paging::PageTable; +use crate::hal::cpu; + +#[global_allocator] +static ALLOCATOR: LockedHeap = LockedHeap::empty(); + +/// 堆的起始虛擬位址 +pub const HEAP_START: usize = 0x_4444_4444_0000; +/// 堆的大小(100 KiB) +pub const HEAP_SIZE: usize = 100 * 1024; + +/// Initialize the heap +/// +/// This function will: +/// 1. Allocate physical frames for the heap +/// 2. Map these frames in the page table +/// 3. Initialize the heap allocator +pub fn init_heap( + mapper: &mut impl Mapper, + frame_allocator: &mut impl FrameAllocator, +) -> Result<(), MapToError> { + // Calculate the page range required for the heap + let page_range = { + let heap_start = VirtAddr::new(HEAP_START as u64); + let heap_end = heap_start + HEAP_SIZE as u64 - 1u64; + let heap_start_page = Page::containing_address(heap_start); + let heap_end_page = Page::containing_address(heap_end); + Page::range_inclusive(heap_start_page, heap_end_page) + }; + + // Allocate a physical frame for each page and map it + for page in page_range { + // Allocate a physical frame + let frame = frame_allocator + .allocate_frame() + .ok_or(MapToError::FrameAllocationFailed)?; + + // Set page flags: exists + writable + let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; + + // Map page to frame + unsafe { + mapper.map_to(page, frame, flags, frame_allocator)?.flush(); + } + } + + // Initialize the heap allocator + unsafe { + ALLOCATOR.lock().init(HEAP_START as *mut u8, HEAP_SIZE); + } + + Ok(()) +} + +pub unsafe fn get_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable { + let virt = physical_memory_offset + cpu::cpu_r_cr3(); + let page_table_ptr: *mut PageTable = virt.as_mut_ptr(); + + &mut *page_table_ptr +} diff --git a/kernel/src/kernel/mm/mod.rs b/kernel/src/kernel/mm/mod.rs new file mode 100644 index 0000000..8990591 --- /dev/null +++ b/kernel/src/kernel/mm/mod.rs @@ -0,0 +1,2 @@ +pub mod frame_allocator; +pub mod heap; \ No newline at end of file diff --git a/kernel/src/kernel/mod.rs b/kernel/src/kernel/mod.rs index 61cec37..6ba9f90 100644 --- a/kernel/src/kernel/mod.rs +++ b/kernel/src/kernel/mod.rs @@ -1,5 +1,5 @@ pub mod tty; pub mod asm; - +pub(crate) mod mm; // 重新導出由 boot.S 調用的入口點 // pub use kernel::{_kernel_init, _kernel_main}; \ No newline at end of file diff --git a/kernel/src/kernel/tty/tty.rs b/kernel/src/kernel/tty/tty.rs index 026e0e2..be88ace 100644 --- a/kernel/src/kernel/tty/tty.rs +++ b/kernel/src/kernel/tty/tty.rs @@ -36,8 +36,6 @@ pub fn init(framebuffer: &'static mut FrameBuffer) { state.cursor_x = 0; state.cursor_y = 0; } - - clear(0x000000); } pub fn clear(color: u32) { diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 66373d4..a706a66 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -2,71 +2,36 @@ #![no_std] #![no_main] #![feature(abi_x86_interrupt)] +#![feature(alloc_error_handler)] +extern crate alloc; +use alloc::vec::Vec; use core::panic::PanicInfo; -use bootloader_api::{entry_point, BootInfo}; +use core::alloc::Layout; +use bootloader_api::{config, entry_point, BootInfo, BootloaderConfig}; +use x86_64::structures::paging::OffsetPageTable; +use x86_64::{ + structures::paging::PageTable, + VirtAddr, +}; mod kernel; mod hal; mod libs; mod logger; +mod k_init; +mod k_main; -use kernel::tty::tty; -use kernel::asm::x86::{gdt, idt}; use hal::cpu; +const CONFIG: BootloaderConfig = { + let mut config = BootloaderConfig::new_default(); + config.mappings.physical_memory = Some(config::Mapping::Dynamic); + config +}; + +entry_point!(k_init::kernel_init, config = &CONFIG); -entry_point!(kernel_main); - -fn kernel_main(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"); - - kprintln!("Initializing GDT..."); - gdt::init(); - kprintln!("GDT initialized"); - gdt::print_info(); - kprintln!(); - - kprintln!("Initializing IDT..."); - idt::init(); - kprintln!("IDT initialized"); - idt::print_info(); - kprintln!(); - - kprintln!("Welcome to CureOS!"); - - let mut brand_buf = [0u8; 64]; - let mut model_buf = [0u8; 16]; - kprintln!("CPU: {} ({})", - cpu::cpu_get_brand(&mut brand_buf), - cpu::cpu_get_model(&mut model_buf) - ); - - kprintln!(); - kprintln!("Control Registers:"); - kprintln!(" CR0: 0x{:016x}", hal::cpu::cpu_r_cr0().bits()); - kprintln!(" CR2: 0x{:016x}", hal::cpu::cpu_r_cr2()); - kprintln!(" CR3: 0x{:016x}", hal::cpu::cpu_r_cr3()); - kprintln!(" CR4: 0x{:016x}", hal::cpu::cpu_r_cr4().bits()); - - kprintln!(); - kprintln!("Kernel initialized successfully!"); - - } else { - loop { - hal::cpu::cpu_halt(); - } - } - - loop { - hal::cpu::cpu_halt(); - } -} #[cfg(not(test))] #[panic_handler] fn panic(info: &PanicInfo) -> ! { @@ -78,6 +43,12 @@ fn panic(info: &PanicInfo) -> ! { kprintln!("{}", info); loop { - hal::cpu::cpu_halt(); + cpu::cpu_halt(); } +} + +#[cfg(not(test))] +#[alloc_error_handler] +fn alloc_error_handler(layout: Layout) -> ! { + panic!("Allocation error: {:?}", layout) } \ No newline at end of file diff --git a/makefile b/makefile index 8cd1f19..d8a4068 100644 --- a/makefile +++ b/makefile @@ -3,19 +3,16 @@ include config/make-os include config/make-cc include config/make-debug-tool -# Rust 構建配置 BUILD_MODE := release CARGO_FLAGS := --release ifeq ($(BUILD_MODE),debug) CARGO_FLAGS := endif -# 目標和輸出 RUST_TARGET := x86_64-unknown-none BUILDER_PKG := cure-builder DISK_IMAGE := cure-os.img -# 顏色輸出 COLOR_RESET := \033[0m COLOR_GREEN := \033[32m COLOR_YELLOW := \033[33m @@ -24,7 +21,6 @@ COLOR_RED := \033[31m .PHONY: all rust-build run clean debug-bochs debug-qemu help all-debug -# 創建目錄(先清理) $(BUILD_DIR): @rm -rf $(BUILD_DIR) @mkdir -p $(BUILD_DIR) @@ -32,21 +28,17 @@ $(BUILD_DIR): $(BIN_DIR): @mkdir -p $(BIN_DIR) -# 默認目標 all: clean-build rust-build copy-artifacts -# 清理 build 目錄 clean-build: @echo "$(COLOR_YELLOW)Cleaning build directory...$(COLOR_RESET)" @rm -rf $(BUILD_DIR) -# 構建內核 rust-build: @echo "$(COLOR_BLUE)Building CureOS...$(COLOR_RESET)" @cargo build -p $(BUILDER_PKG) $(CARGO_FLAGS) - @echo "$(COLOR_GREEN)✓ Build complete$(COLOR_RESET)" + @echo "$(COLOR_GREEN)Build complete$(COLOR_RESET)" -# 複製構建產物到 build/ 目錄 copy-artifacts: $(BUILD_DIR) $(BIN_DIR) @echo "$(COLOR_BLUE)Copying build artifacts...$(COLOR_RESET)" @BIOS_IMG=$$(find target -name "cure-bios.img" -type f | head -1); \ @@ -65,46 +57,40 @@ copy-artifacts: $(BUILD_DIR) $(BIN_DIR) cp "$$KERNEL_BIN" $(BIN_DIR)/$(OS_BIN); \ fi - @echo "$(COLOR_GREEN)✓ Artifacts copied$(COLOR_RESET)" + @echo "$(COLOR_GREEN)Artifacts copied$(COLOR_RESET)" -# Debug 構建(包含 dump) all-debug: BUILD_MODE := debug all-debug: CARGO_FLAGS := -all-debug: clean-build rust-build copy-artifacts dump +all-debug: clean-build rust-build copy-artifacts -# 生成反彙編 dump dump: @echo "$(COLOR_BLUE)Generating disassembly dump...$(COLOR_RESET)" @if [ -f "$(BIN_DIR)/$(OS_BIN)" ]; then \ echo "$(COLOR_YELLOW)Dumping to $(BUILD_DIR)/dump.txt$(COLOR_RESET)"; \ objdump -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/dump.txt; \ - echo "$(COLOR_GREEN)✓ Dump complete$(COLOR_RESET)"; \ + echo "$(COLOR_GREEN)Dump complete$(COLOR_RESET)"; \ else \ echo "$(COLOR_RED)Error: Kernel binary not found$(COLOR_RESET)"; \ exit 1; \ fi -# 完全清理 clean: @echo "$(COLOR_YELLOW)Cleaning all build artifacts...$(COLOR_RESET)" @cargo clean @rm -rf $(BUILD_DIR) @rm -f $(DISK_IMAGE) bochs.log serial.log serial-debug.log bochs-debug.log - @echo "$(COLOR_GREEN)✓ Clean complete$(COLOR_RESET)" + @echo "$(COLOR_GREEN)Clean complete$(COLOR_RESET)" -# 使用 QEMU 運行 run: all @echo "$(COLOR_BLUE)Running with QEMU...$(COLOR_RESET)" @qemu-system-x86_64 -drive format=raw,file=$(BUILD_DIR)/cure-bios.img \ -m 128M \ -serial stdio -# 使用 Bochs 運行 run-bochs: all @echo "$(COLOR_BLUE)Running with Bochs...$(COLOR_RESET)" @bochs -q -f bochs.cfg -# QEMU 調試模式 debug-qemu: all-debug @echo "$(COLOR_BLUE)Starting QEMU in debug mode...$(COLOR_RESET)" @qemu-system-x86_64 -drive format=raw,file=$(BUILD_DIR)/cure-bios.img \ @@ -120,13 +106,11 @@ debug-qemu: all-debug @echo " (gdb) continue" @echo "" -# Bochs 調試模式 debug-bochs: all-debug @echo "$(COLOR_BLUE)Running Bochs in debug mode...$(COLOR_RESET)" @echo "$(COLOR_YELLOW)Dump file available at: $(BUILD_DIR)/dump.txt$(COLOR_RESET)" @bochs -q -f bochs.cfg -# 顯示構建產物位置 show-artifacts: @echo "$(COLOR_BLUE)Build artifacts:$(COLOR_RESET)" @echo " Build directory: $(BUILD_DIR)/" @@ -146,26 +130,22 @@ show-artifacts: echo "$(COLOR_YELLOW) (directory doesn't exist)$(COLOR_RESET)"; \ fi -# 檢查構建 check: @echo "$(COLOR_BLUE)Checking code...$(COLOR_RESET)" @cargo check -p cure-kernel @cargo check -p $(BUILDER_PKG) - @echo "$(COLOR_GREEN)✓ Check complete$(COLOR_RESET)" + @echo "$(COLOR_GREEN)Check complete$(COLOR_RESET)" -# 格式化代碼 fmt: @echo "$(COLOR_BLUE)Formatting code...$(COLOR_RESET)" @cargo fmt - @echo "$(COLOR_GREEN)✓ Format complete$(COLOR_RESET)" + @echo "$(COLOR_GREEN)Format complete$(COLOR_RESET)" -# Clippy 檢查 clippy: @echo "$(COLOR_BLUE)Running clippy...$(COLOR_RESET)" @cargo clippy - @echo "$(COLOR_GREEN)✓ Clippy complete$(COLOR_RESET)" + @echo "$(COLOR_GREEN)Clippy complete$(COLOR_RESET)" -# 幫助信息 help: @echo "$(COLOR_BLUE)CureOS Makefile Commands:$(COLOR_RESET)" @echo ""