2023-12-07 12:50:54 +02:00
|
|
|
//! x86-64 architecture implementation
|
2024-12-10 11:52:26 +02:00
|
|
|
use core::{mem::size_of, ops::DerefMut, ptr::null_mut, sync::atomic::Ordering};
|
2023-08-01 11:09:56 +03:00
|
|
|
|
2024-12-10 20:37:47 +02:00
|
|
|
use ::acpi::{mcfg::Mcfg, AcpiTables, HpetInfo, InterruptModel};
|
2023-07-29 19:31:56 +03:00
|
|
|
use abi::error::Error;
|
2025-02-05 21:45:48 +02:00
|
|
|
use alloc::sync::Arc;
|
2024-12-10 11:52:26 +02:00
|
|
|
use apic::{ioapic::IoApic, local::LocalApic};
|
2024-12-10 20:37:47 +02:00
|
|
|
use device_api::device::Device;
|
2024-10-27 12:35:46 +02:00
|
|
|
use kernel_arch_x86::{
|
2024-12-28 12:52:24 +02:00
|
|
|
cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures, ExtEdxFeatures},
|
2025-01-27 18:10:56 +02:00
|
|
|
gdt, intrinsics,
|
2024-10-27 12:35:46 +02:00
|
|
|
};
|
2024-02-08 15:50:25 +02:00
|
|
|
use kernel_arch_x86_64::{
|
|
|
|
mem::{
|
2024-12-28 12:32:14 +02:00
|
|
|
flush_tlb_entry, init_fixed_tables,
|
2024-02-08 15:50:25 +02:00
|
|
|
table::{PageAttributes, PageEntry, PageTable, L1, L2, L3},
|
2024-12-28 12:32:14 +02:00
|
|
|
EarlyMapping, MEMORY_LIMIT, RAM_MAPPING_L1, RAM_MAPPING_OFFSET,
|
2024-02-08 15:50:25 +02:00
|
|
|
},
|
2025-02-13 22:18:33 +02:00
|
|
|
LocalApicInterface, PerCpuData,
|
2024-02-06 12:27:02 +02:00
|
|
|
};
|
2024-12-06 18:03:18 +02:00
|
|
|
use libk::{
|
|
|
|
arch::Cpu,
|
2024-12-17 19:12:39 +02:00
|
|
|
config, debug,
|
2024-12-06 18:03:18 +02:00
|
|
|
device::{
|
2024-12-10 11:52:26 +02:00
|
|
|
display::{fb_console::FramebufferConsole, DriverFlags, PixelFormat},
|
|
|
|
manager::DEVICE_REGISTRY,
|
2024-12-06 18:03:18 +02:00
|
|
|
register_external_interrupt_controller,
|
|
|
|
},
|
2024-12-17 19:12:39 +02:00
|
|
|
fs::devfs,
|
2024-12-06 18:03:18 +02:00
|
|
|
};
|
2024-02-05 12:59:23 +02:00
|
|
|
use libk_mm::{
|
2024-12-10 16:55:27 +02:00
|
|
|
address::PhysicalAddress,
|
2024-02-05 14:45:17 +02:00
|
|
|
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
2024-02-06 16:38:39 +02:00
|
|
|
table::{EntryLevel, EntryLevelExt},
|
2023-12-10 18:52:33 +02:00
|
|
|
};
|
2025-01-27 18:10:56 +02:00
|
|
|
use libk_util::OneTimeInit;
|
2024-12-08 14:49:29 +02:00
|
|
|
use yboot_proto::{
|
|
|
|
v1::{self, AvailableMemoryRegion},
|
|
|
|
LoadProtocolV1,
|
|
|
|
};
|
2025-01-27 18:10:56 +02:00
|
|
|
use ygg_driver_acpi::{AcpiAllocator, AcpiHandlerImpl, EventAction, FixedEvent};
|
2023-12-10 21:25:54 +02:00
|
|
|
use ygg_driver_pci::PciBusManager;
|
2023-09-13 18:21:45 +03:00
|
|
|
|
|
|
|
mod apic;
|
|
|
|
mod boot;
|
|
|
|
mod exception;
|
|
|
|
mod smp;
|
|
|
|
mod syscall;
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2024-12-10 20:37:47 +02:00
|
|
|
use crate::{
|
|
|
|
arch::x86::{self, peripherals::hpet::Hpet},
|
|
|
|
device::display::linear_fb::LinearFramebuffer,
|
2025-02-03 14:48:23 +02:00
|
|
|
util::call_init_array,
|
2024-12-10 20:37:47 +02:00
|
|
|
};
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2024-12-10 11:52:26 +02:00
|
|
|
use self::boot::BootData;
|
2023-08-01 11:09:56 +03:00
|
|
|
|
2025-01-27 18:10:56 +02:00
|
|
|
use super::{x86::InitrdSource, Platform};
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-12-07 12:50:54 +02:00
|
|
|
/// x86-64 architecture implementation
|
2023-07-29 21:11:15 +03:00
|
|
|
pub struct X86_64 {
|
2023-08-21 17:26:44 +03:00
|
|
|
boot_data: OneTimeInit<BootData>,
|
|
|
|
acpi: OneTimeInit<AcpiTables<AcpiHandlerImpl>>,
|
2023-08-01 11:09:56 +03:00
|
|
|
|
2024-12-10 11:52:26 +02:00
|
|
|
fbconsole: OneTimeInit<Arc<FramebufferConsole>>,
|
2023-07-29 21:11:15 +03:00
|
|
|
}
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2023-12-07 12:50:54 +02:00
|
|
|
/// Global x86-64 architecture value
|
2024-02-05 13:44:21 +02:00
|
|
|
pub static PLATFORM: X86_64 = X86_64 {
|
2023-08-21 17:26:44 +03:00
|
|
|
boot_data: OneTimeInit::new(),
|
|
|
|
acpi: OneTimeInit::new(),
|
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
fbconsole: OneTimeInit::new(),
|
2023-08-21 17:26:44 +03:00
|
|
|
};
|
|
|
|
|
2024-02-05 13:44:21 +02:00
|
|
|
impl Platform for X86_64 {
|
2023-07-29 19:31:56 +03:00
|
|
|
const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
2024-02-06 12:27:02 +02:00
|
|
|
type L3 = kernel_arch_x86_64::mem::table::L3;
|
2023-08-21 17:26:44 +03:00
|
|
|
|
2023-09-15 00:02:14 +03:00
|
|
|
unsafe fn start_application_processors(&self) {
|
|
|
|
if let Some(acpi) = self.acpi.try_get() {
|
|
|
|
let Some(pinfo) = acpi
|
|
|
|
.platform_info_in(AcpiAllocator)
|
|
|
|
.ok()
|
|
|
|
.and_then(|p| p.processor_info)
|
|
|
|
else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
smp::start_ap_cores(&pinfo);
|
|
|
|
}
|
|
|
|
}
|
2023-08-21 17:26:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl X86_64 {
|
2023-09-13 18:21:45 +03:00
|
|
|
fn set_boot_data(&self, data: BootData) {
|
|
|
|
match data {
|
2023-08-21 17:26:44 +03:00
|
|
|
BootData::YBoot(data) => {
|
2023-09-13 18:21:45 +03:00
|
|
|
// Reserve the memory map
|
2024-11-01 20:02:28 +02:00
|
|
|
reserve_region(
|
|
|
|
"mmap",
|
|
|
|
PhysicalMemoryRegion {
|
|
|
|
base: PhysicalAddress::from_u64(data.memory_map.address),
|
|
|
|
size: data.memory_map.len as usize * size_of::<AvailableMemoryRegion>(),
|
|
|
|
},
|
|
|
|
);
|
2023-09-13 18:21:45 +03:00
|
|
|
|
|
|
|
// Reserve initrd, if not NULL
|
|
|
|
if data.initrd_address != 0 && data.initrd_size != 0 {
|
|
|
|
let aligned_start = data.initrd_address & !0xFFF;
|
|
|
|
let aligned_end = (data.initrd_address + data.initrd_size + 0xFFF) & !0xFFF;
|
|
|
|
|
2024-11-01 20:02:28 +02:00
|
|
|
reserve_region(
|
|
|
|
"initrd",
|
|
|
|
PhysicalMemoryRegion {
|
|
|
|
base: PhysicalAddress::from_u64(aligned_start),
|
|
|
|
size: (aligned_end - aligned_start) as usize,
|
|
|
|
},
|
|
|
|
);
|
2023-09-13 18:21:45 +03:00
|
|
|
}
|
2023-08-21 17:26:44 +03:00
|
|
|
}
|
|
|
|
}
|
2023-08-03 18:49:29 +03:00
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
self.boot_data.init(data);
|
2023-08-03 18:49:29 +03:00
|
|
|
}
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2024-02-05 14:45:17 +02:00
|
|
|
fn map_physical_memory<I: Iterator<Item = PhysicalMemoryRegion> + Clone>(
|
|
|
|
it: I,
|
|
|
|
_memory_start: PhysicalAddress,
|
|
|
|
memory_end: PhysicalAddress,
|
2024-12-28 12:52:24 +02:00
|
|
|
have_1gib_pages: bool,
|
2024-02-05 14:45:17 +02:00
|
|
|
) -> Result<(), Error> {
|
2024-07-25 11:58:47 +03:00
|
|
|
let end_l1i = memory_end
|
|
|
|
.into_usize()
|
2024-02-05 14:45:17 +02:00
|
|
|
.page_align_up::<L1>()
|
|
|
|
.page_index::<L1>();
|
|
|
|
|
|
|
|
if end_l1i > 512 {
|
2024-11-05 22:00:10 +02:00
|
|
|
panic!(
|
2024-02-05 14:45:17 +02:00
|
|
|
"Cannot handle {}GiB of RAM",
|
|
|
|
end_l1i * L1::SIZE / (1024 * 1024 * 1024)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-07-25 11:58:47 +03:00
|
|
|
MEMORY_LIMIT.store(memory_end.into_usize(), Ordering::Release);
|
2024-02-05 14:45:17 +02:00
|
|
|
|
2024-12-28 12:52:24 +02:00
|
|
|
if have_1gib_pages {
|
|
|
|
// Map RAM a gigabyte at a time
|
|
|
|
for l1i in 0..end_l1i {
|
2024-10-12 20:43:16 +03:00
|
|
|
// TODO NX
|
2024-12-28 12:52:24 +02:00
|
|
|
unsafe {
|
|
|
|
RAM_MAPPING_L1[l1i] = PageEntry::<L1>::block(
|
|
|
|
PhysicalAddress::from_usize(l1i * L1::SIZE),
|
|
|
|
PageAttributes::WRITABLE,
|
|
|
|
);
|
|
|
|
flush_tlb_entry(RAM_MAPPING_OFFSET + (l1i << L1::SHIFT));
|
|
|
|
}
|
2024-02-05 14:45:17 +02:00
|
|
|
}
|
2024-12-28 12:52:24 +02:00
|
|
|
} else {
|
|
|
|
// Allocate the intermediate tables first
|
|
|
|
let l2_tables_start = phys::find_contiguous_region(it, end_l1i)
|
|
|
|
.expect("Could not allocate the memory for RAM mapping L2 tables");
|
|
|
|
|
|
|
|
reserve_region(
|
|
|
|
"ram-l2-tables",
|
|
|
|
PhysicalMemoryRegion {
|
|
|
|
base: l2_tables_start,
|
|
|
|
size: end_l1i * L3::SIZE,
|
|
|
|
},
|
|
|
|
);
|
2024-02-05 14:45:17 +02:00
|
|
|
|
2024-12-28 12:52:24 +02:00
|
|
|
// Fill in the tables
|
|
|
|
for l1i in 0..end_l1i {
|
|
|
|
let l2_phys_addr = l2_tables_start.add(l1i * L3::SIZE);
|
|
|
|
|
|
|
|
// Safety: ok, the mapping is done to the memory obtained from
|
|
|
|
// find_contiguous_region()
|
|
|
|
let mut l2_data =
|
|
|
|
unsafe { EarlyMapping::<[PageEntry<L2>; 512]>::map(l2_phys_addr)? };
|
|
|
|
// Safety: ok, the slice comes from EarlyMapping of a page-aligned region
|
|
|
|
let l2 = unsafe { PageTable::from_raw_slice_mut(l2_data.deref_mut()) };
|
|
|
|
|
|
|
|
for l2i in 0..512 {
|
|
|
|
// TODO NX
|
|
|
|
l2[l2i] = PageEntry::<L2>::block(
|
|
|
|
PhysicalAddress::from_usize((l1i * L1::SIZE) | (l2i * L2::SIZE)),
|
|
|
|
PageAttributes::WRITABLE,
|
|
|
|
);
|
|
|
|
}
|
2024-02-05 14:45:17 +02:00
|
|
|
|
2024-12-28 12:52:24 +02:00
|
|
|
// Point the L1 entry to the L2 table
|
|
|
|
unsafe {
|
|
|
|
RAM_MAPPING_L1[l1i] =
|
|
|
|
PageEntry::<L1>::table(l2_phys_addr, PageAttributes::WRITABLE)
|
|
|
|
};
|
2024-12-28 12:32:14 +02:00
|
|
|
|
2024-12-28 12:52:24 +02:00
|
|
|
unsafe { flush_tlb_entry(RAM_MAPPING_OFFSET + (l1i << L1::SHIFT)) };
|
|
|
|
intrinsics::flush_cpu_cache();
|
|
|
|
// The EarlyMapping is then dropped
|
|
|
|
}
|
|
|
|
}
|
2024-02-05 14:45:17 +02:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-12-28 12:52:24 +02:00
|
|
|
unsafe fn init_physical_memory_from_yboot(
|
|
|
|
data: &LoadProtocolV1,
|
|
|
|
have_1gib_pages: bool,
|
|
|
|
) -> Result<(), Error> {
|
2023-09-13 18:21:45 +03:00
|
|
|
let mmap = EarlyMapping::<AvailableMemoryRegion>::map_slice(
|
2024-07-25 11:58:47 +03:00
|
|
|
PhysicalAddress::from_u64(data.memory_map.address),
|
2023-09-13 18:21:45 +03:00
|
|
|
data.memory_map.len as usize,
|
2023-09-15 23:23:20 +03:00
|
|
|
)?;
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2024-02-05 14:45:17 +02:00
|
|
|
phys::init_from_iter(
|
|
|
|
mmap.as_ref().iter().map(|reg| PhysicalMemoryRegion {
|
2024-07-25 11:58:47 +03:00
|
|
|
base: PhysicalAddress::from_u64(reg.start_address),
|
2024-02-05 14:45:17 +02:00
|
|
|
size: reg.page_count as usize * L3::SIZE,
|
|
|
|
}),
|
2024-12-28 12:52:24 +02:00
|
|
|
|it, start, end| Self::map_physical_memory(it, start, end, have_1gib_pages),
|
2024-02-05 14:45:17 +02:00
|
|
|
)
|
2023-08-05 16:32:12 +03:00
|
|
|
}
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2024-12-28 12:52:24 +02:00
|
|
|
unsafe fn init_memory_management(&self, enabled_features: &CpuFeatures) -> Result<(), Error> {
|
|
|
|
let have_1gib_pages = enabled_features.ext_edx.contains(ExtEdxFeatures::PDPE1GB);
|
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
init_fixed_tables();
|
2023-08-21 17:26:44 +03:00
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
// Reserve lower 4MiB just in case
|
2023-07-30 16:40:30 +03:00
|
|
|
reserve_region(
|
2023-09-13 18:21:45 +03:00
|
|
|
"lowmem",
|
2023-07-30 16:40:30 +03:00
|
|
|
PhysicalMemoryRegion {
|
2023-09-13 18:21:45 +03:00
|
|
|
base: PhysicalAddress::ZERO,
|
|
|
|
size: 4 * 1024 * 1024,
|
2023-07-30 16:40:30 +03:00
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
match self.boot_data.get() {
|
2024-12-28 12:52:24 +02:00
|
|
|
&BootData::YBoot(data) => Self::init_physical_memory_from_yboot(data, have_1gib_pages)?,
|
2023-08-02 19:53:54 +03:00
|
|
|
}
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
Ok(())
|
2023-08-05 16:32:12 +03:00
|
|
|
}
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
unsafe fn init_platform(&'static self, cpu_id: usize) -> Result<(), Error> {
|
2024-12-28 12:32:14 +02:00
|
|
|
let (available_features, enabled_features) = self.init_cpu_features();
|
|
|
|
|
2024-12-10 16:55:27 +02:00
|
|
|
if cpu_id == 0 {
|
|
|
|
PLATFORM
|
2024-12-28 12:52:24 +02:00
|
|
|
.init_memory_management(&enabled_features)
|
2024-12-10 16:55:27 +02:00
|
|
|
.expect("Could not initialize memory management");
|
|
|
|
}
|
|
|
|
|
2025-02-05 21:45:48 +02:00
|
|
|
let local_apic = self.init_local_cpu(cpu_id, available_features, enabled_features);
|
2024-12-10 16:55:27 +02:00
|
|
|
|
|
|
|
if cpu_id == 0 {
|
|
|
|
self.setup_from_boot_data()?;
|
|
|
|
|
2024-12-17 19:12:39 +02:00
|
|
|
// TODO yboot doesn't yet pass any command line options
|
|
|
|
let cmdline = self.boot_data.get().cmdline();
|
|
|
|
let mut early = x86::init_platform_early(cmdline)?;
|
2024-12-10 16:55:27 +02:00
|
|
|
|
2024-12-17 19:12:39 +02:00
|
|
|
if !config::get().x86.disable_boot_fb {
|
|
|
|
if let Err(error) = self.init_framebuffer() {
|
|
|
|
log::error!("Could not initialize boot framebuffer: {error:?}");
|
|
|
|
}
|
2024-12-10 16:55:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(acpi) = self.acpi.try_get() {
|
2025-02-05 21:45:48 +02:00
|
|
|
self.init_platform_from_acpi(acpi, local_apic)?;
|
2024-12-10 16:55:27 +02:00
|
|
|
}
|
|
|
|
|
2024-12-17 19:12:39 +02:00
|
|
|
if !config::get().x86_64.disable_hpet {
|
|
|
|
early.add_preferred_clock_source("hpet", Self::setup_hpet);
|
|
|
|
} else {
|
|
|
|
log::info!("HPET disabled by config");
|
|
|
|
}
|
2024-12-10 20:37:47 +02:00
|
|
|
|
2025-02-03 14:48:23 +02:00
|
|
|
call_init_array();
|
|
|
|
|
2024-12-10 16:55:27 +02:00
|
|
|
x86::init_platform_devices(early);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-12-10 20:37:47 +02:00
|
|
|
fn setup_hpet() -> Result<Arc<dyn Device>, Error> {
|
|
|
|
let acpi = PLATFORM.acpi.try_get().ok_or(Error::DoesNotExist)?;
|
|
|
|
let hpet = HpetInfo::new(acpi).map_err(|_| Error::DoesNotExist)?;
|
|
|
|
let hpet = Hpet::setup_from_acpi(&hpet)?;
|
|
|
|
let timer = hpet.setup_timer(0, 1000, true)?;
|
|
|
|
Ok(timer)
|
|
|
|
}
|
|
|
|
|
2024-12-28 12:32:14 +02:00
|
|
|
unsafe fn init_cpu_features(&self) -> (CpuFeatures, CpuFeatures) {
|
2024-10-12 20:43:16 +03:00
|
|
|
let (have_features, will_features) = cpuid::setup_features(
|
|
|
|
CpuFeatures {
|
|
|
|
ecx: EcxFeatures::SSE3
|
|
|
|
| EcxFeatures::SSE4_1
|
|
|
|
| EcxFeatures::SSE4_2
|
|
|
|
| EcxFeatures::AVX,
|
|
|
|
edx: EdxFeatures::empty(),
|
2024-12-28 12:52:24 +02:00
|
|
|
ext_edx: ExtEdxFeatures::PDPE1GB,
|
2024-10-12 20:43:16 +03:00
|
|
|
},
|
|
|
|
CpuFeatures {
|
|
|
|
ecx: EcxFeatures::XSAVE,
|
|
|
|
edx: EdxFeatures::FXSR
|
|
|
|
| EdxFeatures::SSE
|
|
|
|
| EdxFeatures::PGE
|
|
|
|
| EdxFeatures::PSE
|
|
|
|
| EdxFeatures::FPU,
|
2024-12-28 12:52:24 +02:00
|
|
|
ext_edx: ExtEdxFeatures::empty(),
|
2024-10-12 20:43:16 +03:00
|
|
|
},
|
|
|
|
);
|
|
|
|
let will_features = will_features.expect("Could not initialize CPU features");
|
|
|
|
|
2024-12-28 12:32:14 +02:00
|
|
|
(have_features, will_features)
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn init_local_cpu(
|
|
|
|
&self,
|
|
|
|
cpu_id: usize,
|
|
|
|
available_features: CpuFeatures,
|
|
|
|
enabled_features: CpuFeatures,
|
2025-02-05 21:45:48 +02:00
|
|
|
) -> Arc<LocalApic> {
|
|
|
|
let local_apic = Arc::new(LocalApic::new());
|
2024-12-28 12:32:14 +02:00
|
|
|
let tss_address = gdt::init();
|
|
|
|
exception::init_exceptions(cpu_id);
|
|
|
|
|
2024-02-08 15:50:25 +02:00
|
|
|
let cpu_data = PerCpuData {
|
|
|
|
this: null_mut(),
|
|
|
|
tss_address,
|
|
|
|
tmp_address: 0,
|
2025-02-05 21:45:48 +02:00
|
|
|
local_apic: local_apic.clone(),
|
2024-12-28 12:32:14 +02:00
|
|
|
available_features,
|
|
|
|
enabled_features,
|
2024-02-08 15:50:25 +02:00
|
|
|
};
|
2024-10-12 20:43:16 +03:00
|
|
|
|
2024-02-12 12:09:53 +02:00
|
|
|
Cpu::init_local(Some(cpu_id as _), cpu_data);
|
2024-12-10 11:52:26 +02:00
|
|
|
|
2024-02-08 15:50:25 +02:00
|
|
|
syscall::init_syscall();
|
2025-02-05 21:45:48 +02:00
|
|
|
|
|
|
|
local_apic
|
2023-09-13 18:21:45 +03:00
|
|
|
}
|
|
|
|
|
2024-12-10 16:55:27 +02:00
|
|
|
unsafe fn setup_from_boot_data(&self) -> Result<(), Error> {
|
2023-09-13 18:21:45 +03:00
|
|
|
match self.boot_data.get() {
|
2024-12-10 16:55:27 +02:00
|
|
|
&BootData::YBoot(data) => {
|
|
|
|
// Already reserved in set_boot_data()
|
|
|
|
x86::set_initrd(data, false);
|
|
|
|
|
|
|
|
self.init_acpi_from_rsdp(data.rsdp_address as usize)
|
|
|
|
}
|
2023-09-13 18:21:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
unsafe fn init_acpi_from_rsdp(&self, rsdp: usize) -> Result<(), Error> {
|
|
|
|
let acpi_tables = AcpiTables::from_rsdp(AcpiHandlerImpl, rsdp).map_err(|err| {
|
2024-11-30 23:51:02 +02:00
|
|
|
log::error!("Could not initialize ACPI tables: {:?}", err);
|
2023-09-15 23:23:20 +03:00
|
|
|
Error::InvalidArgument
|
|
|
|
})?;
|
2023-09-13 18:21:45 +03:00
|
|
|
self.acpi.init(acpi_tables);
|
2023-09-15 23:23:20 +03:00
|
|
|
Ok(())
|
2023-09-13 18:21:45 +03:00
|
|
|
}
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
unsafe fn init_platform_from_acpi(
|
|
|
|
&self,
|
|
|
|
acpi: &'static AcpiTables<AcpiHandlerImpl>,
|
2025-02-05 21:45:48 +02:00
|
|
|
local_apic: Arc<LocalApic>,
|
2023-09-15 23:23:20 +03:00
|
|
|
) -> Result<(), Error> {
|
|
|
|
let platform_info = acpi.platform_info_in(AcpiAllocator).map_err(|err| {
|
2024-11-30 23:51:02 +02:00
|
|
|
log::error!("Could not get ACPI platform info: {:?}", err);
|
2023-09-15 23:23:20 +03:00
|
|
|
Error::InvalidArgument
|
|
|
|
})?;
|
2023-09-13 18:21:45 +03:00
|
|
|
|
|
|
|
let InterruptModel::Apic(apic_info) = platform_info.interrupt_model else {
|
2024-12-10 16:55:27 +02:00
|
|
|
unreachable!("The processor does not support APIC");
|
2023-09-13 18:21:45 +03:00
|
|
|
};
|
|
|
|
|
2024-02-08 13:11:29 +02:00
|
|
|
let ioapic = IoApic::from_acpi(&apic_info)?;
|
|
|
|
register_external_interrupt_controller(ioapic);
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2025-01-27 18:10:56 +02:00
|
|
|
if let Err(error) = ygg_driver_acpi::switch_to_acpi(acpi) {
|
|
|
|
log::error!("ACPI initialization error: {error:?}");
|
|
|
|
} else {
|
|
|
|
if let Err(error) =
|
|
|
|
ygg_driver_acpi::add_event_handler(&FixedEvent::POWER_BUTTON, |_| {
|
|
|
|
log::info!("Power button pressed!");
|
|
|
|
EventAction::Nothing
|
|
|
|
})
|
|
|
|
{
|
|
|
|
log::error!("Couldn't set ACPI power button handler: {error:?}");
|
|
|
|
}
|
|
|
|
}
|
2024-12-10 16:55:27 +02:00
|
|
|
|
2023-09-15 00:02:14 +03:00
|
|
|
if let Ok(mcfg) = acpi.find_table::<Mcfg>() {
|
|
|
|
for entry in mcfg.entries() {
|
2025-02-05 21:45:48 +02:00
|
|
|
if let Err(error) = PciBusManager::add_segment_from_mcfg(entry, local_apic.clone())
|
|
|
|
{
|
2024-12-10 16:55:27 +02:00
|
|
|
log::error!("Could not add PCI bus segment: {error:?}");
|
|
|
|
}
|
2023-09-15 00:02:14 +03:00
|
|
|
}
|
|
|
|
}
|
2023-09-15 23:23:20 +03:00
|
|
|
|
|
|
|
Ok(())
|
2023-09-13 18:21:45 +03:00
|
|
|
}
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
unsafe fn init_framebuffer(&'static self) -> Result<(), Error> {
|
2024-12-10 16:55:27 +02:00
|
|
|
DEVICE_REGISTRY.display.set_callback(|device, node| {
|
|
|
|
log::info!("Display registered: {:?}", device.display_name());
|
|
|
|
|
|
|
|
if device
|
|
|
|
.driver_flags()
|
|
|
|
.contains(DriverFlags::REPLACES_BOOT_FRAMEBUFFER)
|
|
|
|
{
|
|
|
|
// Switch fbconsole to the new framebuffer
|
|
|
|
if let Some(fbconsole) = PLATFORM.fbconsole.try_get()
|
|
|
|
&& fbconsole.uses_boot_framebuffer()
|
|
|
|
{
|
|
|
|
if let Err(error) = fbconsole.set_display(device.clone()) {
|
|
|
|
log::error!("Couldn't set fb console display: {error:?}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Switch /dev/fb0 to the new node
|
2024-12-20 23:00:43 +02:00
|
|
|
if let Some((name, _)) = node {
|
|
|
|
devfs::redirect("fb0", name).ok();
|
2024-12-10 16:55:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-12-08 14:49:29 +02:00
|
|
|
let display = match self.boot_data.get() {
|
|
|
|
&BootData::YBoot(data) => {
|
|
|
|
let info = &data.opt_framebuffer;
|
|
|
|
let format = match info.res_format {
|
|
|
|
v1::PIXEL_B8G8R8A8 => PixelFormat::B8G8R8A8,
|
|
|
|
v1::PIXEL_R8G8B8A8 => PixelFormat::R8G8B8A8,
|
|
|
|
// Fallback
|
|
|
|
_ => PixelFormat::R8G8B8A8,
|
|
|
|
};
|
|
|
|
|
|
|
|
let framebuffer = LinearFramebuffer::from_physical_bits(
|
|
|
|
PhysicalAddress::from_u64(info.res_address),
|
|
|
|
info.res_size as usize,
|
|
|
|
info.res_stride as usize,
|
|
|
|
info.res_width,
|
|
|
|
info.res_height,
|
|
|
|
format,
|
|
|
|
)?;
|
|
|
|
|
2024-12-10 11:52:26 +02:00
|
|
|
Some(Arc::new(framebuffer))
|
2024-12-08 14:49:29 +02:00
|
|
|
}
|
|
|
|
};
|
2023-09-15 23:23:20 +03:00
|
|
|
|
2024-12-08 14:49:29 +02:00
|
|
|
let Some(display) = display else {
|
|
|
|
return Ok(());
|
|
|
|
};
|
2024-12-06 18:03:18 +02:00
|
|
|
|
2024-12-08 14:49:29 +02:00
|
|
|
// Register boot display
|
2024-12-10 11:52:26 +02:00
|
|
|
DEVICE_REGISTRY.display.register(display.clone(), true)?;
|
|
|
|
|
|
|
|
let fbconsole = self
|
|
|
|
.fbconsole
|
|
|
|
.init(Arc::new(FramebufferConsole::from_framebuffer(
|
|
|
|
display.clone(),
|
|
|
|
None,
|
|
|
|
true,
|
|
|
|
)?));
|
|
|
|
|
2024-12-17 19:12:39 +02:00
|
|
|
debug::add_sink(fbconsole.clone(), config::get().debug.display_level);
|
2024-12-06 18:03:18 +02:00
|
|
|
|
2024-12-08 14:49:29 +02:00
|
|
|
Ok(())
|
2023-09-13 18:21:45 +03:00
|
|
|
}
|
2025-02-13 22:18:33 +02:00
|
|
|
|
|
|
|
pub(crate) fn cpu_local_apic() -> Arc<dyn LocalApicInterface> {
|
|
|
|
Cpu::local().local_apic.clone()
|
|
|
|
}
|
2024-12-10 16:55:27 +02:00
|
|
|
}
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2024-12-10 16:55:27 +02:00
|
|
|
impl InitrdSource for LoadProtocolV1 {
|
|
|
|
fn start(&self) -> PhysicalAddress {
|
|
|
|
PhysicalAddress::from_u64(self.initrd_address)
|
|
|
|
}
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2024-12-10 16:55:27 +02:00
|
|
|
fn end(&self) -> PhysicalAddress {
|
|
|
|
PhysicalAddress::from_u64(self.initrd_address + self.initrd_size)
|
2023-08-05 16:32:12 +03:00
|
|
|
}
|
|
|
|
}
|