2023-12-07 12:50:54 +02:00
|
|
|
//! x86-64 architecture implementation
|
2023-10-03 10:17:13 +03:00
|
|
|
use core::{mem::size_of, ops::DerefMut, sync::atomic::Ordering};
|
2023-08-01 11:09:56 +03:00
|
|
|
|
2023-07-29 19:31:56 +03:00
|
|
|
use abi::error::Error;
|
2023-09-15 00:02:14 +03:00
|
|
|
use acpi_lib::{mcfg::Mcfg, AcpiTables, InterruptModel};
|
2023-08-21 17:26:44 +03:00
|
|
|
use alloc::boxed::Box;
|
2024-02-08 13:11:29 +02:00
|
|
|
use device_api::{interrupt::Irq, timer::MonotonicTimestampProviderDevice, Device};
|
2023-08-05 16:32:12 +03:00
|
|
|
use git_version::git_version;
|
2024-02-06 12:27:02 +02:00
|
|
|
use kernel_arch_x86_64::mem::{
|
|
|
|
init_fixed_tables, map_heap_block,
|
|
|
|
table::{PageAttributes, PageEntry, PageTable, L1, L2, L3},
|
|
|
|
EarlyMapping, HEAP_MAPPING_OFFSET, MEMORY_LIMIT, RAM_MAPPING_L1,
|
|
|
|
};
|
2024-01-04 21:22:18 +02:00
|
|
|
use kernel_fs::devfs;
|
2024-02-08 13:11:29 +02:00
|
|
|
use libk::device::register_external_interrupt_controller;
|
2024-02-05 12:59:23 +02:00
|
|
|
use libk_mm::{
|
2024-02-06 12:27:02 +02:00
|
|
|
address::{FromRaw, IntoRaw, PhysicalAddress, Virtualize},
|
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
|
|
|
};
|
2024-02-05 12:59:23 +02:00
|
|
|
use libk_util::{sync::SpinFence, OneTimeInit};
|
2023-09-13 18:21:45 +03:00
|
|
|
use yboot_proto::{v1::AvailableMemoryRegion, LoadProtocolV1};
|
2023-12-10 21:25:54 +02:00
|
|
|
use ygg_driver_pci::PciBusManager;
|
2023-09-13 18:21:45 +03:00
|
|
|
|
|
|
|
mod acpi;
|
|
|
|
mod apic;
|
|
|
|
mod boot;
|
|
|
|
pub mod context;
|
|
|
|
pub mod cpu;
|
|
|
|
mod cpuid;
|
|
|
|
mod exception;
|
|
|
|
mod gdt;
|
|
|
|
mod intrinsics;
|
|
|
|
mod peripherals;
|
|
|
|
mod smp;
|
|
|
|
mod syscall;
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2023-07-29 21:11:15 +03:00
|
|
|
use crate::{
|
2024-02-07 13:06:17 +02:00
|
|
|
arch::x86_64::{
|
|
|
|
apic::ioapic::ISA_IRQ_OFFSET,
|
|
|
|
intrinsics::{IoPort, IoPortAccess},
|
|
|
|
},
|
2023-08-07 09:53:47 +03:00
|
|
|
debug::{self, LogLevel},
|
2023-07-29 21:11:15 +03:00
|
|
|
device::{
|
2023-08-21 17:26:44 +03:00
|
|
|
self,
|
2023-08-22 10:00:56 +03:00
|
|
|
display::{console, fb_console::FramebufferConsole, linear_fb::LinearFramebuffer},
|
2023-08-01 11:09:56 +03:00
|
|
|
},
|
2023-12-10 23:22:21 +02:00
|
|
|
fs::{Initrd, INITRD_DATA},
|
2024-02-06 16:38:39 +02:00
|
|
|
mem::heap,
|
2023-07-29 21:11:15 +03:00
|
|
|
};
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2023-08-01 11:09:56 +03:00
|
|
|
use self::{
|
2023-08-31 13:40:17 +03:00
|
|
|
acpi::{AcpiAllocator, AcpiHandlerImpl},
|
2023-09-13 18:21:45 +03:00
|
|
|
apic::{ioapic::IoApic, local::LocalApic},
|
|
|
|
boot::BootData,
|
|
|
|
cpu::Cpu,
|
|
|
|
cpuid::{ProcessorFeatures, PROCESSOR_FEATURES},
|
|
|
|
peripherals::{i8253::I8253, ps2::PS2Controller, serial::ComPort},
|
2023-08-05 16:32:12 +03:00
|
|
|
smp::CPU_COUNT,
|
2023-08-01 11:09:56 +03:00
|
|
|
};
|
|
|
|
|
2024-02-08 13:11:29 +02:00
|
|
|
use super::{IpiMessage, 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
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
// Display
|
2023-08-21 17:26:44 +03:00
|
|
|
framebuffer: OneTimeInit<LinearFramebuffer>,
|
2023-09-13 18:21:45 +03:00
|
|
|
fbconsole: OneTimeInit<FramebufferConsole>,
|
2023-08-02 19:53:54 +03:00
|
|
|
|
2023-09-07 11:59:20 +03:00
|
|
|
timer: OneTimeInit<I8253>,
|
2023-07-29 21:11:15 +03:00
|
|
|
}
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
static SHUTDOWN_FENCE: SpinFence = SpinFence::new();
|
|
|
|
|
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(),
|
|
|
|
|
|
|
|
framebuffer: OneTimeInit::new(),
|
2023-09-13 18:21:45 +03:00
|
|
|
fbconsole: OneTimeInit::new(),
|
2023-08-21 17:26:44 +03:00
|
|
|
|
|
|
|
timer: OneTimeInit::new(),
|
|
|
|
};
|
|
|
|
|
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-09-13 18:21:45 +03:00
|
|
|
fn cpu_count() -> usize {
|
|
|
|
CPU_COUNT.load(Ordering::Acquire)
|
2023-07-29 19:31:56 +03:00
|
|
|
}
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
fn monotonic_timer(&'static self) -> &'static dyn MonotonicTimestampProviderDevice {
|
|
|
|
self.timer.get()
|
|
|
|
}
|
2023-08-21 17:26:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl X86_64 {
|
2024-02-07 13:06:17 +02:00
|
|
|
unsafe fn handle_ipi(&self, _msg: IpiMessage) {
|
2023-10-01 16:58:46 +03:00
|
|
|
warnln!("Received an IPI");
|
2023-12-07 10:16:44 +02:00
|
|
|
todo!();
|
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
|
|
|
|
unsafe {
|
|
|
|
reserve_region(
|
|
|
|
"mmap",
|
|
|
|
PhysicalMemoryRegion {
|
|
|
|
base: PhysicalAddress::from_raw(data.memory_map.address),
|
|
|
|
size: data.memory_map.len as usize * size_of::<AvailableMemoryRegion>(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
reserve_region(
|
|
|
|
"initrd",
|
|
|
|
PhysicalMemoryRegion {
|
|
|
|
base: PhysicalAddress::from_raw(aligned_start),
|
|
|
|
size: (aligned_end - aligned_start) as usize,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
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,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
let end_l1i = IntoRaw::<usize>::into_raw(memory_end)
|
|
|
|
.page_align_up::<L1>()
|
|
|
|
.page_index::<L1>();
|
|
|
|
|
|
|
|
if end_l1i > 512 {
|
|
|
|
todo!(
|
|
|
|
"Cannot handle {}GiB of RAM",
|
|
|
|
end_l1i * L1::SIZE / (1024 * 1024 * 1024)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-02-06 12:27:02 +02:00
|
|
|
MEMORY_LIMIT.store(memory_end.into_raw(), Ordering::Release);
|
2024-02-05 14:45:17 +02:00
|
|
|
|
|
|
|
// Check if 1GiB pages are supported
|
|
|
|
if PROCESSOR_FEATURES
|
|
|
|
.get()
|
|
|
|
.contains(ProcessorFeatures::PDPE1GB)
|
|
|
|
{
|
|
|
|
// Just map gigabytes of RAM
|
|
|
|
for l1i in 0..end_l1i {
|
|
|
|
// TODO NX
|
|
|
|
unsafe {
|
|
|
|
RAM_MAPPING_L1[l1i] = PageEntry::<L1>::block(
|
|
|
|
PhysicalAddress::from_raw(l1i * L1::SIZE),
|
|
|
|
PageAttributes::WRITABLE,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} 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");
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
reserve_region(
|
|
|
|
"ram-l2-tables",
|
|
|
|
PhysicalMemoryRegion {
|
|
|
|
base: l2_tables_start,
|
|
|
|
size: end_l1i * L3::SIZE,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in the tables
|
|
|
|
for l1i in 0..end_l1i {
|
|
|
|
let l2_phys_addr = l2_tables_start.add(l1i * L3::SIZE);
|
|
|
|
|
|
|
|
// TODO (minor) the slice is uninitialized, maybe find some way to deal with that
|
|
|
|
// case nicely
|
|
|
|
// 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_raw((l1i * L1::SIZE) | (l2i * L2::SIZE)),
|
|
|
|
PageAttributes::WRITABLE,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Point the L1 entry to the L2 table
|
|
|
|
unsafe {
|
|
|
|
RAM_MAPPING_L1[l1i] =
|
|
|
|
PageEntry::<L1>::table(l2_phys_addr, PageAttributes::WRITABLE)
|
|
|
|
};
|
|
|
|
|
|
|
|
intrinsics::flush_cpu_cache();
|
|
|
|
// The EarlyMapping is then dropped
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
unsafe fn init_physical_memory_from_yboot(data: &LoadProtocolV1) -> Result<(), Error> {
|
2023-09-13 18:21:45 +03:00
|
|
|
let mmap = EarlyMapping::<AvailableMemoryRegion>::map_slice(
|
|
|
|
PhysicalAddress::from_raw(data.memory_map.address),
|
|
|
|
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 {
|
|
|
|
base: PhysicalAddress::from_raw(reg.start_address),
|
|
|
|
size: reg.page_count as usize * L3::SIZE,
|
|
|
|
}),
|
|
|
|
Self::map_physical_memory,
|
|
|
|
)
|
2023-08-05 16:32:12 +03:00
|
|
|
}
|
2023-07-28 14:26:39 +03:00
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
unsafe fn init_memory_management(&self) -> Result<(), Error> {
|
2023-09-13 18:21:45 +03:00
|
|
|
const HEAP_PAGES: usize = 16;
|
2023-08-21 17:26:44 +03:00
|
|
|
|
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() {
|
2023-09-15 23:23:20 +03:00
|
|
|
&BootData::YBoot(data) => Self::init_physical_memory_from_yboot(data)?,
|
2023-08-02 19:53:54 +03:00
|
|
|
}
|
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
// Setup heap
|
|
|
|
for i in 0..HEAP_PAGES {
|
|
|
|
// Allocate in 2MiB chunks
|
2023-09-15 23:23:20 +03:00
|
|
|
let l2_page = phys::alloc_2m_page()?;
|
2023-08-01 11:09:56 +03:00
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
map_heap_block(i, l2_page);
|
2023-08-21 17:26:44 +03:00
|
|
|
}
|
2023-08-01 11:09:56 +03:00
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
heap::init_heap(HEAP_MAPPING_OFFSET, HEAP_PAGES * L2::SIZE);
|
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> {
|
2023-08-21 17:26:44 +03:00
|
|
|
Cpu::init_local(LocalApic::new(), cpu_id as _);
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
if cpu_id == 0 {
|
2023-12-10 21:25:54 +02:00
|
|
|
// Register the PCI drivers
|
|
|
|
// TODO make this implicit init
|
|
|
|
ygg_driver_pci::register_class_driver(
|
|
|
|
"NVMe Host Controller",
|
|
|
|
0x01,
|
|
|
|
Some(0x08),
|
|
|
|
Some(0x02),
|
2023-12-10 23:22:21 +02:00
|
|
|
ygg_driver_nvme::probe,
|
2023-12-10 21:25:54 +02:00
|
|
|
);
|
2023-12-12 18:34:21 +02:00
|
|
|
ygg_driver_pci::register_class_driver(
|
|
|
|
"AHCI SATA Controller",
|
|
|
|
0x01,
|
|
|
|
Some(0x06),
|
|
|
|
Some(0x01),
|
|
|
|
ygg_driver_ahci::probe,
|
|
|
|
);
|
2024-01-20 19:40:27 +02:00
|
|
|
ygg_driver_pci::register_vendor_driver(
|
|
|
|
"Virtio PCI Network Device",
|
|
|
|
0x1AF4,
|
|
|
|
0x1000,
|
|
|
|
ygg_driver_virtio_net::probe,
|
|
|
|
);
|
2023-12-10 21:25:54 +02:00
|
|
|
|
2023-09-13 18:21:45 +03:00
|
|
|
match self.boot_data.get() {
|
|
|
|
&BootData::YBoot(data) => {
|
|
|
|
let start = PhysicalAddress::from_raw(data.initrd_address);
|
|
|
|
Self::init_initrd(start, start.add(data.initrd_size as usize));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
self.init_acpi_from_boot_data()?;
|
2023-09-07 11:59:20 +03:00
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
Self::disable_8259();
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-09-07 11:59:20 +03:00
|
|
|
self.timer.init(I8253::new());
|
|
|
|
|
2024-02-07 13:06:17 +02:00
|
|
|
let com1_3 = Box::leak(Box::new(ComPort::new(
|
|
|
|
0x3F8,
|
|
|
|
0x3E8,
|
|
|
|
Irq::External(ISA_IRQ_OFFSET + 4),
|
|
|
|
)));
|
2023-08-21 17:26:44 +03:00
|
|
|
debug::add_sink(com1_3.port_a(), LogLevel::Debug);
|
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
self.init_framebuffer()?;
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2023-08-22 10:00:56 +03:00
|
|
|
debug::init();
|
2023-08-21 17:26:44 +03:00
|
|
|
|
2023-11-06 10:29:53 +02:00
|
|
|
infoln!(
|
|
|
|
"Yggdrasil v{} ({})",
|
|
|
|
env!("CARGO_PKG_VERSION"),
|
|
|
|
git_version!()
|
|
|
|
);
|
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
let ps2 = Box::leak(Box::new(PS2Controller::new(
|
2024-02-07 13:06:17 +02:00
|
|
|
Irq::External(ISA_IRQ_OFFSET + 1),
|
|
|
|
Irq::External(ISA_IRQ_OFFSET + 12),
|
2023-08-21 17:26:44 +03:00
|
|
|
0x64,
|
|
|
|
0x60,
|
|
|
|
)));
|
2023-09-15 23:23:20 +03:00
|
|
|
ps2.init()?;
|
2023-08-21 17:26:44 +03:00
|
|
|
|
|
|
|
if let Some(acpi) = self.acpi.try_get() {
|
2023-09-15 23:23:20 +03:00
|
|
|
self.init_platform_from_acpi(acpi)?;
|
2023-08-21 17:26:44 +03:00
|
|
|
}
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
self.timer.get().init_irq()?;
|
2023-12-28 10:37:35 +02:00
|
|
|
// ps2.connect(self.tty.get());
|
2023-09-15 23:23:20 +03:00
|
|
|
ps2.init_irq()?;
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
device::register_device(ps2);
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
PciBusManager::setup_bus_devices()?;
|
2023-09-13 18:21:45 +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_acpi_from_boot_data(&self) -> Result<(), Error> {
|
2023-09-13 18:21:45 +03:00
|
|
|
match self.boot_data.get() {
|
|
|
|
&BootData::YBoot(data) => self.init_acpi_from_rsdp(data.rsdp_address as usize),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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| {
|
|
|
|
errorln!("Could not initialize ACPI tables: {:?}", err);
|
|
|
|
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>,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
let platform_info = acpi.platform_info_in(AcpiAllocator).map_err(|err| {
|
|
|
|
errorln!("Could not get ACPI platform info: {:?}", err);
|
|
|
|
Error::InvalidArgument
|
|
|
|
})?;
|
2023-09-13 18:21:45 +03:00
|
|
|
|
|
|
|
let InterruptModel::Apic(apic_info) = platform_info.interrupt_model else {
|
|
|
|
panic!("The processor does not support APIC");
|
|
|
|
};
|
|
|
|
|
2024-02-08 13:11:29 +02:00
|
|
|
let ioapic = IoApic::from_acpi(&apic_info)?;
|
|
|
|
let ioapic = Box::leak(Box::new(ioapic));
|
|
|
|
register_external_interrupt_controller(ioapic);
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2023-10-03 10:17:13 +03:00
|
|
|
// acpi::init_acpi(acpi).unwrap();
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2023-09-15 00:02:14 +03:00
|
|
|
if let Ok(mcfg) = acpi.find_table::<Mcfg>() {
|
|
|
|
for entry in mcfg.entries() {
|
2023-09-15 23:23:20 +03:00
|
|
|
PciBusManager::add_segment_from_mcfg(entry)?;
|
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> {
|
2023-09-13 18:21:45 +03:00
|
|
|
match self.boot_data.get() {
|
|
|
|
&BootData::YBoot(data) => {
|
|
|
|
let info = &data.opt_framebuffer;
|
2023-09-04 11:27:16 +03:00
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
self.framebuffer.init(LinearFramebuffer::from_physical_bits(
|
|
|
|
PhysicalAddress::from_raw(info.res_address),
|
|
|
|
info.res_size as usize,
|
|
|
|
info.res_stride as usize,
|
|
|
|
info.res_width,
|
|
|
|
info.res_height,
|
|
|
|
)?);
|
2023-08-21 17:26:44 +03:00
|
|
|
}
|
|
|
|
}
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2023-09-15 23:23:20 +03:00
|
|
|
self.fbconsole.init(FramebufferConsole::from_framebuffer(
|
|
|
|
self.framebuffer.get(),
|
|
|
|
None,
|
|
|
|
)?);
|
2023-09-13 18:21:45 +03:00
|
|
|
debug::add_sink(self.fbconsole.get(), LogLevel::Info);
|
|
|
|
|
2023-12-28 10:37:35 +02:00
|
|
|
// self.tty.init(CombinedTerminal::new(self.fbconsole.get()));
|
2023-09-13 18:21:45 +03:00
|
|
|
|
2023-12-26 22:12:47 +02:00
|
|
|
devfs::add_named_block_device(self.framebuffer.get(), "fb0")?;
|
2023-12-28 10:37:35 +02:00
|
|
|
// devfs::add_char_device(self.tty.get(), CharDeviceType::TtyRegular)?;
|
2023-09-13 18:21:45 +03:00
|
|
|
console::add_console_autoflush(self.fbconsole.get());
|
2023-09-15 23:23:20 +03:00
|
|
|
|
|
|
|
Ok(())
|
2023-09-13 18:21:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn init_initrd(initrd_start: PhysicalAddress, initrd_end: PhysicalAddress) {
|
|
|
|
if initrd_start.is_zero() || initrd_end <= initrd_start {
|
|
|
|
infoln!("No initrd loaded");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let start_aligned = initrd_start.page_align_down::<L3>();
|
|
|
|
let end_aligned = initrd_start.page_align_up::<L3>();
|
|
|
|
|
|
|
|
let data = unsafe {
|
|
|
|
core::slice::from_raw_parts(
|
2024-02-06 12:27:02 +02:00
|
|
|
start_aligned.virtualize() as *const u8,
|
2023-09-13 18:21:45 +03:00
|
|
|
initrd_end - initrd_start,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let initrd = Initrd {
|
|
|
|
phys_page_start: start_aligned,
|
|
|
|
phys_page_len: end_aligned - start_aligned,
|
|
|
|
data,
|
|
|
|
};
|
|
|
|
|
|
|
|
INITRD_DATA.init(initrd);
|
2023-08-05 16:32:12 +03:00
|
|
|
}
|
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
unsafe fn disable_8259() {
|
|
|
|
infoln!("Disabling i8259 PIC");
|
|
|
|
// TODO should I make a module for 8259 if I don't even use it?
|
2023-08-31 09:21:24 +03:00
|
|
|
let pic_master_cmd = IoPort::<u8>::new(0x20);
|
|
|
|
let pic_master_data = IoPort::<u8>::new(0x21);
|
|
|
|
let pic_slave_cmd = IoPort::<u8>::new(0xA0);
|
|
|
|
let pic_slave_data = IoPort::<u8>::new(0xA1);
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
// Remap PIC IRQ vectors to 32..
|
|
|
|
pic_master_cmd.write(0x11);
|
|
|
|
pic_slave_cmd.write(0x11);
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
pic_master_data.write(32);
|
|
|
|
pic_slave_data.write(32 + 8);
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
pic_slave_data.write(0xFF);
|
|
|
|
pic_master_data.write(0xFF);
|
2023-08-05 16:32:12 +03:00
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
pic_master_cmd.write(0x20);
|
|
|
|
pic_slave_cmd.write(0x20);
|
2023-08-05 16:32:12 +03:00
|
|
|
}
|
|
|
|
}
|