feat: ACPI implementation completed

This commit is contained in:
ParrotXray 2025-10-11 22:01:52 +08:00
parent 1c92cacbc3
commit 429e396474
15 changed files with 663 additions and 97 deletions

59
Cargo.lock generated
View File

@ -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"

22
TODO.txt Normal file
View File

@ -0,0 +1,22 @@
// 1. 中斷處理
// - IDT (中斷描述符表) - OK
// - 中斷處理函數 - OK
// - ACPI 初始化 - OK
// - PIC/APIC 初始化
// - 滾動
// 2. 內存管理
// - 物理內存分配器
// - 虛擬內存分配器
// - 堆分配器
// 3. 頁表管理
// - 修改頁表
// - 映射新的內存區域
// - 取消映射
// 4. 進程管理
// - 任務切換
// - 調度器
// - 用戶態/內核態切換

View File

@ -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"
#[package.metadata.bootloader]
#map-physical-memory = true
#physical-memory-offset = "0xFFFF800000000000"

View File

@ -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)
///
/// # 返回

79
kernel/src/k_init.rs Normal file
View File

@ -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();
}
}
}

27
kernel/src/k_main.rs Normal file
View File

@ -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();
}
}

View File

@ -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<T>(
&self,
physical_address: usize,
size: usize,
) -> PhysicalMapping<Self, T> {
// 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<T>(region: &PhysicalMapping<Self, T>) {
//
}
fn read_u8(&self, address: usize) -> u8 {
unsafe {
let ptr = self.map_physical_region::<u8>(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::<u16>(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::<u32>(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::<u64>(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::<u8>(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::<u16>(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::<u32>(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::<u64>(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<u32>,
pub cpu_count: usize,
pub has_apic: bool,
pub has_hpet: bool,
}
pub fn init(rsdp_addr: u64, physical_memory_offset: u64) -> Option<AcpiInfo> {
let handler = CureAcpiHandler::new(physical_memory_offset);
let rsdp_mapping = unsafe {
handler.map_physical_region::<Rsdp>(rsdp_addr as usize, mem::size_of::<Rsdp>())
};
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" });
}

View File

@ -1,4 +1,5 @@
pub mod gdt;
pub mod idt;
pub mod interrupt;
pub(crate) mod acpi;
// pub mod segment;

View File

@ -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<Item = PhysFrame> {
// 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<Size4KiB> for BootInfoFrameAllocator {
fn allocate_frame(&mut self) -> Option<PhysFrame> {
let frame = self.usable_frames().nth(self.next);
self.next += 1;
frame
}
}

View File

@ -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<Size4KiB>,
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
) -> Result<(), MapToError<Size4KiB>> {
// 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
}

View File

@ -0,0 +1,2 @@
pub mod frame_allocator;
pub mod heap;

View File

@ -1,5 +1,5 @@
pub mod tty;
pub mod asm;
pub(crate) mod mm;
// 重新導出由 boot.S 調用的入口點
// pub use kernel::{_kernel_init, _kernel_main};

View File

@ -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) {

View File

@ -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)
}

View File

@ -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 ""