feat: ACPI implementation completed
This commit is contained in:
parent
1c92cacbc3
commit
429e396474
59
Cargo.lock
generated
59
Cargo.lock
generated
@ -2,6 +2,20 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
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]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.100"
|
version = "1.0.100"
|
||||||
@ -123,8 +137,10 @@ dependencies = [
|
|||||||
name = "cure-kernel"
|
name = "cure-kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"acpi",
|
||||||
"bootloader_api",
|
"bootloader_api",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"linked_list_allocator",
|
||||||
"raw-cpuid",
|
"raw-cpuid",
|
||||||
"spin 0.10.0",
|
"spin 0.10.0",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
@ -218,6 +234,15 @@ version = "0.2.177"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
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]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@ -270,6 +295,16 @@ version = "1.21.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
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]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.101"
|
version = "1.0.101"
|
||||||
@ -302,11 +337,11 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-cpuid"
|
name = "raw-cpuid"
|
||||||
version = "10.7.0"
|
version = "11.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
|
checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -407,6 +442,24 @@ dependencies = [
|
|||||||
"lock_api",
|
"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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.106"
|
version = "2.0.106"
|
||||||
|
|||||||
22
TODO.txt
Normal file
22
TODO.txt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// 1. 中斷處理
|
||||||
|
// - IDT (中斷描述符表) - OK
|
||||||
|
// - 中斷處理函數 - OK
|
||||||
|
// - ACPI 初始化 - OK
|
||||||
|
// - PIC/APIC 初始化
|
||||||
|
|
||||||
|
// - 滾動
|
||||||
|
|
||||||
|
// 2. 內存管理
|
||||||
|
// - 物理內存分配器
|
||||||
|
// - 虛擬內存分配器
|
||||||
|
// - 堆分配器
|
||||||
|
|
||||||
|
// 3. 頁表管理
|
||||||
|
// - 修改頁表
|
||||||
|
// - 映射新的內存區域
|
||||||
|
// - 取消映射
|
||||||
|
|
||||||
|
// 4. 進程管理
|
||||||
|
// - 任務切換
|
||||||
|
// - 調度器
|
||||||
|
// - 用戶態/內核態切換
|
||||||
@ -8,8 +8,10 @@ bootloader_api = "0.11.12"
|
|||||||
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
|
lazy_static = { version = "1.5.0", features = ["spin_no_std"] }
|
||||||
x86_64 = { version = "0.15.2", features = ["instructions"] }
|
x86_64 = { version = "0.15.2", features = ["instructions"] }
|
||||||
spin = "0.10.0"
|
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]
|
#[package.metadata.bootloader]
|
||||||
map-physical-memory = true
|
#map-physical-memory = true
|
||||||
physical-memory-offset = "0xFFFF800000000000"
|
#physical-memory-offset = "0xFFFF800000000000"
|
||||||
@ -48,8 +48,6 @@ pub struct SgReg {
|
|||||||
pub cs: Reg16,
|
pub cs: Reg16,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ 控制寄存器 ============
|
|
||||||
|
|
||||||
/// 讀取 CR0 暫存器
|
/// 讀取 CR0 暫存器
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -181,8 +179,6 @@ pub fn cpu_get_brand(brand_out: &mut [u8]) -> &str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ CPU 指令 ============
|
|
||||||
|
|
||||||
/// 讀取 CPU 時間戳計數器 (TSC)
|
/// 讀取 CPU 時間戳計數器 (TSC)
|
||||||
///
|
///
|
||||||
/// # 返回
|
/// # 返回
|
||||||
|
|||||||
79
kernel/src/k_init.rs
Normal file
79
kernel/src/k_init.rs
Normal 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
27
kernel/src/k_main.rs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
318
kernel/src/kernel/asm/x86/acpi.rs
Normal file
318
kernel/src/kernel/asm/x86/acpi.rs
Normal 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" });
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
pub mod idt;
|
pub mod idt;
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
|
pub(crate) mod acpi;
|
||||||
// pub mod segment;
|
// pub mod segment;
|
||||||
49
kernel/src/kernel/mm/frame_allocator.rs
Normal file
49
kernel/src/kernel/mm/frame_allocator.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
68
kernel/src/kernel/mm/heap.rs
Normal file
68
kernel/src/kernel/mm/heap.rs
Normal 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
|
||||||
|
}
|
||||||
2
kernel/src/kernel/mm/mod.rs
Normal file
2
kernel/src/kernel/mm/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod frame_allocator;
|
||||||
|
pub mod heap;
|
||||||
@ -1,5 +1,5 @@
|
|||||||
pub mod tty;
|
pub mod tty;
|
||||||
pub mod asm;
|
pub mod asm;
|
||||||
|
pub(crate) mod mm;
|
||||||
// 重新導出由 boot.S 調用的入口點
|
// 重新導出由 boot.S 調用的入口點
|
||||||
// pub use kernel::{_kernel_init, _kernel_main};
|
// pub use kernel::{_kernel_init, _kernel_main};
|
||||||
@ -36,8 +36,6 @@ pub fn init(framebuffer: &'static mut FrameBuffer) {
|
|||||||
state.cursor_x = 0;
|
state.cursor_x = 0;
|
||||||
state.cursor_y = 0;
|
state.cursor_y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(0x000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(color: u32) {
|
pub fn clear(color: u32) {
|
||||||
|
|||||||
@ -2,71 +2,36 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
|
#![feature(alloc_error_handler)]
|
||||||
|
extern crate alloc;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
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 kernel;
|
||||||
mod hal;
|
mod hal;
|
||||||
mod libs;
|
mod libs;
|
||||||
mod logger;
|
mod logger;
|
||||||
|
mod k_init;
|
||||||
|
mod k_main;
|
||||||
|
|
||||||
use kernel::tty::tty;
|
|
||||||
use kernel::asm::x86::{gdt, idt};
|
|
||||||
use hal::cpu;
|
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))]
|
#[cfg(not(test))]
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
fn panic(info: &PanicInfo) -> ! {
|
||||||
@ -78,6 +43,12 @@ fn panic(info: &PanicInfo) -> ! {
|
|||||||
kprintln!("{}", info);
|
kprintln!("{}", info);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
hal::cpu::cpu_halt();
|
cpu::cpu_halt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
#[alloc_error_handler]
|
||||||
|
fn alloc_error_handler(layout: Layout) -> ! {
|
||||||
|
panic!("Allocation error: {:?}", layout)
|
||||||
}
|
}
|
||||||
36
makefile
36
makefile
@ -3,19 +3,16 @@ include config/make-os
|
|||||||
include config/make-cc
|
include config/make-cc
|
||||||
include config/make-debug-tool
|
include config/make-debug-tool
|
||||||
|
|
||||||
# Rust 構建配置
|
|
||||||
BUILD_MODE := release
|
BUILD_MODE := release
|
||||||
CARGO_FLAGS := --release
|
CARGO_FLAGS := --release
|
||||||
ifeq ($(BUILD_MODE),debug)
|
ifeq ($(BUILD_MODE),debug)
|
||||||
CARGO_FLAGS :=
|
CARGO_FLAGS :=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# 目標和輸出
|
|
||||||
RUST_TARGET := x86_64-unknown-none
|
RUST_TARGET := x86_64-unknown-none
|
||||||
BUILDER_PKG := cure-builder
|
BUILDER_PKG := cure-builder
|
||||||
DISK_IMAGE := cure-os.img
|
DISK_IMAGE := cure-os.img
|
||||||
|
|
||||||
# 顏色輸出
|
|
||||||
COLOR_RESET := \033[0m
|
COLOR_RESET := \033[0m
|
||||||
COLOR_GREEN := \033[32m
|
COLOR_GREEN := \033[32m
|
||||||
COLOR_YELLOW := \033[33m
|
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
|
.PHONY: all rust-build run clean debug-bochs debug-qemu help all-debug
|
||||||
|
|
||||||
# 創建目錄(先清理)
|
|
||||||
$(BUILD_DIR):
|
$(BUILD_DIR):
|
||||||
@rm -rf $(BUILD_DIR)
|
@rm -rf $(BUILD_DIR)
|
||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
@ -32,21 +28,17 @@ $(BUILD_DIR):
|
|||||||
$(BIN_DIR):
|
$(BIN_DIR):
|
||||||
@mkdir -p $(BIN_DIR)
|
@mkdir -p $(BIN_DIR)
|
||||||
|
|
||||||
# 默認目標
|
|
||||||
all: clean-build rust-build copy-artifacts
|
all: clean-build rust-build copy-artifacts
|
||||||
|
|
||||||
# 清理 build 目錄
|
|
||||||
clean-build:
|
clean-build:
|
||||||
@echo "$(COLOR_YELLOW)Cleaning build directory...$(COLOR_RESET)"
|
@echo "$(COLOR_YELLOW)Cleaning build directory...$(COLOR_RESET)"
|
||||||
@rm -rf $(BUILD_DIR)
|
@rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
# 構建內核
|
|
||||||
rust-build:
|
rust-build:
|
||||||
@echo "$(COLOR_BLUE)Building CureOS...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Building CureOS...$(COLOR_RESET)"
|
||||||
@cargo build -p $(BUILDER_PKG) $(CARGO_FLAGS)
|
@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)
|
copy-artifacts: $(BUILD_DIR) $(BIN_DIR)
|
||||||
@echo "$(COLOR_BLUE)Copying build artifacts...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Copying build artifacts...$(COLOR_RESET)"
|
||||||
@BIOS_IMG=$$(find target -name "cure-bios.img" -type f | head -1); \
|
@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); \
|
cp "$$KERNEL_BIN" $(BIN_DIR)/$(OS_BIN); \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@echo "$(COLOR_GREEN)✓ Artifacts copied$(COLOR_RESET)"
|
@echo "$(COLOR_GREEN)Artifacts copied$(COLOR_RESET)"
|
||||||
|
|
||||||
# Debug 構建(包含 dump)
|
|
||||||
all-debug: BUILD_MODE := debug
|
all-debug: BUILD_MODE := debug
|
||||||
all-debug: CARGO_FLAGS :=
|
all-debug: CARGO_FLAGS :=
|
||||||
all-debug: clean-build rust-build copy-artifacts dump
|
all-debug: clean-build rust-build copy-artifacts
|
||||||
|
|
||||||
# 生成反彙編 dump
|
|
||||||
dump:
|
dump:
|
||||||
@echo "$(COLOR_BLUE)Generating disassembly dump...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Generating disassembly dump...$(COLOR_RESET)"
|
||||||
@if [ -f "$(BIN_DIR)/$(OS_BIN)" ]; then \
|
@if [ -f "$(BIN_DIR)/$(OS_BIN)" ]; then \
|
||||||
echo "$(COLOR_YELLOW)Dumping to $(BUILD_DIR)/dump.txt$(COLOR_RESET)"; \
|
echo "$(COLOR_YELLOW)Dumping to $(BUILD_DIR)/dump.txt$(COLOR_RESET)"; \
|
||||||
objdump -D $(BIN_DIR)/$(OS_BIN) > $(BUILD_DIR)/dump.txt; \
|
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 \
|
else \
|
||||||
echo "$(COLOR_RED)Error: Kernel binary not found$(COLOR_RESET)"; \
|
echo "$(COLOR_RED)Error: Kernel binary not found$(COLOR_RESET)"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 完全清理
|
|
||||||
clean:
|
clean:
|
||||||
@echo "$(COLOR_YELLOW)Cleaning all build artifacts...$(COLOR_RESET)"
|
@echo "$(COLOR_YELLOW)Cleaning all build artifacts...$(COLOR_RESET)"
|
||||||
@cargo clean
|
@cargo clean
|
||||||
@rm -rf $(BUILD_DIR)
|
@rm -rf $(BUILD_DIR)
|
||||||
@rm -f $(DISK_IMAGE) bochs.log serial.log serial-debug.log bochs-debug.log
|
@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
|
run: all
|
||||||
@echo "$(COLOR_BLUE)Running with QEMU...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Running with QEMU...$(COLOR_RESET)"
|
||||||
@qemu-system-x86_64 -drive format=raw,file=$(BUILD_DIR)/cure-bios.img \
|
@qemu-system-x86_64 -drive format=raw,file=$(BUILD_DIR)/cure-bios.img \
|
||||||
-m 128M \
|
-m 128M \
|
||||||
-serial stdio
|
-serial stdio
|
||||||
|
|
||||||
# 使用 Bochs 運行
|
|
||||||
run-bochs: all
|
run-bochs: all
|
||||||
@echo "$(COLOR_BLUE)Running with Bochs...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Running with Bochs...$(COLOR_RESET)"
|
||||||
@bochs -q -f bochs.cfg
|
@bochs -q -f bochs.cfg
|
||||||
|
|
||||||
# QEMU 調試模式
|
|
||||||
debug-qemu: all-debug
|
debug-qemu: all-debug
|
||||||
@echo "$(COLOR_BLUE)Starting QEMU in debug mode...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Starting QEMU in debug mode...$(COLOR_RESET)"
|
||||||
@qemu-system-x86_64 -drive format=raw,file=$(BUILD_DIR)/cure-bios.img \
|
@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 " (gdb) continue"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
# Bochs 調試模式
|
|
||||||
debug-bochs: all-debug
|
debug-bochs: all-debug
|
||||||
@echo "$(COLOR_BLUE)Running Bochs in debug mode...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Running Bochs in debug mode...$(COLOR_RESET)"
|
||||||
@echo "$(COLOR_YELLOW)Dump file available at: $(BUILD_DIR)/dump.txt$(COLOR_RESET)"
|
@echo "$(COLOR_YELLOW)Dump file available at: $(BUILD_DIR)/dump.txt$(COLOR_RESET)"
|
||||||
@bochs -q -f bochs.cfg
|
@bochs -q -f bochs.cfg
|
||||||
|
|
||||||
# 顯示構建產物位置
|
|
||||||
show-artifacts:
|
show-artifacts:
|
||||||
@echo "$(COLOR_BLUE)Build artifacts:$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Build artifacts:$(COLOR_RESET)"
|
||||||
@echo " Build directory: $(BUILD_DIR)/"
|
@echo " Build directory: $(BUILD_DIR)/"
|
||||||
@ -146,26 +130,22 @@ show-artifacts:
|
|||||||
echo "$(COLOR_YELLOW) (directory doesn't exist)$(COLOR_RESET)"; \
|
echo "$(COLOR_YELLOW) (directory doesn't exist)$(COLOR_RESET)"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 檢查構建
|
|
||||||
check:
|
check:
|
||||||
@echo "$(COLOR_BLUE)Checking code...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Checking code...$(COLOR_RESET)"
|
||||||
@cargo check -p cure-kernel
|
@cargo check -p cure-kernel
|
||||||
@cargo check -p $(BUILDER_PKG)
|
@cargo check -p $(BUILDER_PKG)
|
||||||
@echo "$(COLOR_GREEN)✓ Check complete$(COLOR_RESET)"
|
@echo "$(COLOR_GREEN)Check complete$(COLOR_RESET)"
|
||||||
|
|
||||||
# 格式化代碼
|
|
||||||
fmt:
|
fmt:
|
||||||
@echo "$(COLOR_BLUE)Formatting code...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Formatting code...$(COLOR_RESET)"
|
||||||
@cargo fmt
|
@cargo fmt
|
||||||
@echo "$(COLOR_GREEN)✓ Format complete$(COLOR_RESET)"
|
@echo "$(COLOR_GREEN)Format complete$(COLOR_RESET)"
|
||||||
|
|
||||||
# Clippy 檢查
|
|
||||||
clippy:
|
clippy:
|
||||||
@echo "$(COLOR_BLUE)Running clippy...$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)Running clippy...$(COLOR_RESET)"
|
||||||
@cargo clippy
|
@cargo clippy
|
||||||
@echo "$(COLOR_GREEN)✓ Clippy complete$(COLOR_RESET)"
|
@echo "$(COLOR_GREEN)Clippy complete$(COLOR_RESET)"
|
||||||
|
|
||||||
# 幫助信息
|
|
||||||
help:
|
help:
|
||||||
@echo "$(COLOR_BLUE)CureOS Makefile Commands:$(COLOR_RESET)"
|
@echo "$(COLOR_BLUE)CureOS Makefile Commands:$(COLOR_RESET)"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user