Some device discovery support
This commit is contained in:
parent
154c9512dc
commit
24524c104f
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -87,6 +87,11 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fdt"
|
||||||
|
version = "0.2.0-alpha1"
|
||||||
|
source = "git+https://github.com/repnop/fdt#059bb2383873f8001959456e36ec123228f67642"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flagset"
|
name = "flagset"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
@ -99,6 +104,7 @@ version = "0.3.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"acpi",
|
"acpi",
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
|
"fdt",
|
||||||
"flagset",
|
"flagset",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"limine",
|
"limine",
|
||||||
|
@ -6,6 +6,7 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
acpi = "5.1.0"
|
acpi = "5.1.0"
|
||||||
enumflags2 = "0.7.11"
|
enumflags2 = "0.7.11"
|
||||||
|
fdt = { git = "https://github.com/repnop/fdt", version = "0.2.0-alpha1" }
|
||||||
flagset = "0.4.7"
|
flagset = "0.4.7"
|
||||||
lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] }
|
lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] }
|
||||||
limine = "0.4.0"
|
limine = "0.4.0"
|
||||||
|
@ -30,6 +30,16 @@ PROFILE = "dev"
|
|||||||
PROFILEDIR = "debug"
|
PROFILEDIR = "debug"
|
||||||
ARTIFACTDIR = "target/${TARGET}/${PROFILEDIR}"
|
ARTIFACTDIR = "target/${TARGET}/${PROFILEDIR}"
|
||||||
|
|
||||||
|
[env.dev]
|
||||||
|
PROFILE = "dev"
|
||||||
|
PROFILEDIR = "debug"
|
||||||
|
ARTIFACTDIR = "target/${TARGET}/${PROFILEDIR}"
|
||||||
|
|
||||||
|
[env.debug]
|
||||||
|
PROFILE = "dev"
|
||||||
|
PROFILEDIR = "debug"
|
||||||
|
ARTIFACTDIR = "target/${TARGET}/${PROFILEDIR}"
|
||||||
|
|
||||||
[env.release]
|
[env.release]
|
||||||
PROFILE = "release"
|
PROFILE = "release"
|
||||||
PROFILEDIR = "release"
|
PROFILEDIR = "release"
|
||||||
|
@ -47,6 +47,7 @@ Licensed under the GNU Public License v3. See [LICENSE](LICENSE) for details.
|
|||||||
- [arch/](src/kernel/arch/): Architecture specific features like the display, serial, and interrupts. Each architecture is a subfolder, containing a file or module for each feature.
|
- [arch/](src/kernel/arch/): Architecture specific features like the display, serial, and interrupts. Each architecture is a subfolder, containing a file or module for each feature.
|
||||||
- [boot.rs](src/kernel/boot.rs): Handles bootloader-managed data structures. Gila uses Limine. Other bootloaders are NOT supported.
|
- [boot.rs](src/kernel/boot.rs): Handles bootloader-managed data structures. Gila uses Limine. Other bootloaders are NOT supported.
|
||||||
- [constants.rs](src/kernel/constants.rs): Constants referenced elsewhere in the kernel.
|
- [constants.rs](src/kernel/constants.rs): Constants referenced elsewhere in the kernel.
|
||||||
|
- [device.rs](src/kernel/device.rs): Functions for discovering hardware and assigning drivers.
|
||||||
- [log.rs](src/kernel/log.rs): Logging structures, macros, and singletons for logging to serial or the display.
|
- [log.rs](src/kernel/log.rs): Logging structures, macros, and singletons for logging to serial or the display.
|
||||||
- [main.rs](src/kernel/main.rs): The entry point that gets called by the bootloader.
|
- [main.rs](src/kernel/main.rs): The entry point that gets called by the bootloader.
|
||||||
- [memory.rs](src/kernel/memory.rs): Types relating to memory regions and allocation.
|
- [memory.rs](src/kernel/memory.rs): Types relating to memory regions and allocation.
|
||||||
|
@ -4,6 +4,9 @@ use lazy_static::lazy_static;
|
|||||||
|
|
||||||
use super::asm::*;
|
use super::asm::*;
|
||||||
|
|
||||||
|
use crate::{log_trace, format};
|
||||||
|
use crate::log::{LogLevel, LOGGER};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref GDT: GlobalDescriptorTable = {
|
pub static ref GDT: GlobalDescriptorTable = {
|
||||||
let mut gdt = GlobalDescriptorTable::new();
|
let mut gdt = GlobalDescriptorTable::new();
|
||||||
@ -17,6 +20,10 @@ pub fn setup_gdt() {
|
|||||||
interrupt_disable();
|
interrupt_disable();
|
||||||
}
|
}
|
||||||
GDT.load();
|
GDT.load();
|
||||||
|
log_trace!(
|
||||||
|
"GDT: Setting up global descriptor table at 0x{:x}",
|
||||||
|
core::ptr::addr_of!(GDT) as usize
|
||||||
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
interrupt_enable();
|
interrupt_enable();
|
||||||
}
|
}
|
||||||
|
@ -35,3 +35,6 @@ pub static FRAMEBUFFER_REQUEST: FramebufferRequest = limine::request::Framebuffe
|
|||||||
#[used]
|
#[used]
|
||||||
#[unsafe(link_section = ".requests")]
|
#[unsafe(link_section = ".requests")]
|
||||||
pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new();
|
pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest::new();
|
||||||
|
#[used]
|
||||||
|
#[unsafe(link_section = ".requests")]
|
||||||
|
pub static DTB_REQUEST: DeviceTreeBlobRequest = limine::request::DeviceTreeBlobRequest::new();
|
||||||
|
24
src/kernel/device.rs
Normal file
24
src/kernel/device.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use fdt::*;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use limine::response::{DeviceTreeBlobResponse, RsdpResponse};
|
||||||
|
|
||||||
|
use crate::boot::{DTB_REQUEST, RSDP_REQUEST};
|
||||||
|
use crate::log::{LOGGER, LogLevel};
|
||||||
|
use crate::{format, log_trace};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref DTB: Option<&'static DeviceTreeBlobResponse> = DTB_REQUEST.get_response();
|
||||||
|
pub static ref RDSP: Option<&'static RsdpResponse> = RSDP_REQUEST.get_response();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn device_tree_parsed() -> Option<Fdt<'static>> {
|
||||||
|
if let Some(ok_dtb) = *DTB
|
||||||
|
&& let Ok(ok_parsed_dt) = unsafe { fdt::Fdt::from_ptr(ok_dtb.dtb_ptr() as *const u8) }
|
||||||
|
{
|
||||||
|
log_trace!("Device: Parsed device tree");
|
||||||
|
Some(ok_parsed_dt)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -10,18 +10,21 @@ use alloc::string::*;
|
|||||||
use alloc::vec::*;
|
use alloc::vec::*;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! log_info {
|
macro_rules! log_info {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
LOGGER.log(LogLevel::Info, &format!($($arg)*))
|
LOGGER.log(LogLevel::Info, &format!($($arg)*))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! log_trace {
|
macro_rules! log_trace {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
LOGGER.log(LogLevel::Trace, &format!($($arg)*))
|
LOGGER.log(LogLevel::Trace, &format!($($arg)*))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
macro_rules! log_warning {
|
macro_rules! log_warning {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
@ -29,6 +32,7 @@ macro_rules! log_warning {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
macro_rules! log_error {
|
macro_rules! log_error {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
@ -36,6 +40,7 @@ macro_rules! log_error {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
#[allow(unused_macros)]
|
#[allow(unused_macros)]
|
||||||
macro_rules! log_critical {
|
macro_rules! log_critical {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
@ -71,10 +76,10 @@ pub struct EnumParseError {}
|
|||||||
|
|
||||||
pub struct LoggerInner {
|
pub struct LoggerInner {
|
||||||
pub level: LogLevel,
|
pub level: LogLevel,
|
||||||
pub subscriber: Vec<Mutex<Box<dyn LogSubscriber + Send + Sync>>>,
|
pub subscriber: Vec<Mutex<Box<dyn LogSubscriber>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait LogSubscriber {
|
pub trait LogSubscriber: Send + Sync {
|
||||||
fn write(&self, msg: &str);
|
fn write(&self, msg: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
mod arch;
|
mod arch;
|
||||||
mod boot;
|
mod boot;
|
||||||
mod constants;
|
mod constants;
|
||||||
|
mod device;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod log;
|
mod log;
|
||||||
mod memory;
|
mod memory;
|
||||||
@ -16,12 +17,12 @@ mod panic;
|
|||||||
mod params;
|
mod params;
|
||||||
mod process;
|
mod process;
|
||||||
mod resources;
|
mod resources;
|
||||||
mod syscall_runner;
|
|
||||||
|
|
||||||
use core::ptr;
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use arch::x86_64::gdt;
|
||||||
use arch::x86_64::gdt::{self, GDT};
|
#[cfg(target_arch = "x86_64")]
|
||||||
use arch::x86_64::serial::Serialport;
|
use arch::x86_64::serial::Serialport;
|
||||||
|
|
||||||
use boot::*;
|
use boot::*;
|
||||||
use constants::*;
|
use constants::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
@ -38,9 +39,6 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
// Assert supported bootloader version
|
// Assert supported bootloader version
|
||||||
assert!(BASE_REVISION.is_supported());
|
assert!(BASE_REVISION.is_supported());
|
||||||
|
|
||||||
// TODO: This is hacky and will not work on any other machine.
|
|
||||||
let qemu_serial = Serialport::new(0x3f8);
|
|
||||||
|
|
||||||
let executable_file_response = FILE_REQUEST
|
let executable_file_response = FILE_REQUEST
|
||||||
.get_response()
|
.get_response()
|
||||||
.expect("Bootloader did not return executable data");
|
.expect("Bootloader did not return executable data");
|
||||||
@ -61,7 +59,9 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
// Append display console to log subs
|
// Append display console to log subs
|
||||||
}
|
}
|
||||||
if log_device_list.contains(&"serial") {
|
if log_device_list.contains(&"serial") {
|
||||||
LOGGER.add_subscriber(qemu_serial);
|
// TODO: Set up device discovery
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
LOGGER.add_subscriber(Serialport::new(0x3f8));
|
||||||
}
|
}
|
||||||
log_trace!("Boot: Configured kernel logging devices");
|
log_trace!("Boot: Configured kernel logging devices");
|
||||||
}
|
}
|
||||||
@ -101,7 +101,17 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _rsdp_response = RSDP_REQUEST.get_response();
|
// Try to obtain ACPI information first. If not available, fall back to
|
||||||
|
// flattened device tree.
|
||||||
|
let rsdp_response = RSDP_REQUEST.get_response();
|
||||||
|
let dtb_response = DTB_REQUEST.get_response();
|
||||||
|
if let Some(rdsp) = rsdp_response {
|
||||||
|
log_info!("Boot: RDSP response received");
|
||||||
|
log_trace!("Boot: RDSP located at 0x{:x}", rdsp.address());
|
||||||
|
} else if let Some(dtb) = dtb_response {
|
||||||
|
log_info!("Boot: DTB response received");
|
||||||
|
log_trace!("Boot: DTB located at 0x{:x}", dtb.dtb_ptr() as usize)
|
||||||
|
}
|
||||||
|
|
||||||
let module_response = MODULE_REQUEST
|
let module_response = MODULE_REQUEST
|
||||||
.get_response()
|
.get_response()
|
||||||
@ -142,80 +152,80 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
}
|
}
|
||||||
.expect("initramfs not found in modules list");
|
.expect("initramfs not found in modules list");
|
||||||
|
|
||||||
if let Some(mmap_response) = MEMMAP_REQUEST.get_response() {
|
// Panic if this is absent. It's needed to set up the GDT and paging
|
||||||
log_info!("Boot: Memory map received");
|
let mmap_response = MEMMAP_REQUEST.get_response().expect("Bootloader did not supply memory map");
|
||||||
if !mmap_response.entries().is_empty() {
|
log_info!("Boot: Memory map received");
|
||||||
let mut log_msg: String = String::from("Boot: Memory map:");
|
if !mmap_response.entries().is_empty() {
|
||||||
let mut usable: u64 = 0;
|
let mut log_msg: String = String::from("Boot: Memory map:");
|
||||||
let mut reclaimable: u64 = 0;
|
let mut usable: u64 = 0;
|
||||||
let mut hardware: u64 = 0;
|
let mut reclaimable: u64 = 0;
|
||||||
let mut unusable: u64 = 0;
|
let mut hardware: u64 = 0;
|
||||||
for entry in mmap_response.entries() {
|
let mut unusable: u64 = 0;
|
||||||
log_msg.push_str(&format!(
|
for entry in mmap_response.entries() {
|
||||||
"\n\t\t0x{:x} bytes @ 0x{:x}: {}",
|
log_msg.push_str(&format!(
|
||||||
entry.length,
|
"\n\t\t0x{:x} bytes @ 0x{:x}: {}",
|
||||||
entry.base,
|
entry.length,
|
||||||
match entry.entry_type {
|
entry.base,
|
||||||
EntryType::ACPI_NVS => {
|
match entry.entry_type {
|
||||||
hardware += entry.length;
|
EntryType::ACPI_NVS => {
|
||||||
"ACPI (reserved)"
|
hardware += entry.length;
|
||||||
}
|
"ACPI (reserved)"
|
||||||
EntryType::ACPI_RECLAIMABLE => {
|
|
||||||
reclaimable += entry.length;
|
|
||||||
"ACPI (reclaimable)"
|
|
||||||
}
|
|
||||||
EntryType::BAD_MEMORY => {
|
|
||||||
unusable += entry.length;
|
|
||||||
"damaged/unusable"
|
|
||||||
}
|
|
||||||
EntryType::BOOTLOADER_RECLAIMABLE => {
|
|
||||||
reclaimable += entry.length;
|
|
||||||
"bootloader (reclaimable)"
|
|
||||||
}
|
|
||||||
#[allow(unreachable_patterns, deprecated)]
|
|
||||||
EntryType::EXECUTABLE_AND_MODULES | EntryType::KERNEL_AND_MODULES => {
|
|
||||||
unusable += entry.length;
|
|
||||||
"executable & modules"
|
|
||||||
}
|
|
||||||
EntryType::FRAMEBUFFER => {
|
|
||||||
hardware += entry.length;
|
|
||||||
"framebuffer"
|
|
||||||
}
|
|
||||||
EntryType::RESERVED => {
|
|
||||||
unusable += entry.length;
|
|
||||||
"reserved"
|
|
||||||
}
|
|
||||||
EntryType::USABLE => {
|
|
||||||
usable += entry.length;
|
|
||||||
"usable"
|
|
||||||
}
|
|
||||||
_ => "unidentified",
|
|
||||||
}
|
}
|
||||||
));
|
EntryType::ACPI_RECLAIMABLE => {
|
||||||
}
|
reclaimable += entry.length;
|
||||||
log_trace!("{log_msg}");
|
"ACPI (reclaimable)"
|
||||||
let total = usable + reclaimable + hardware + unusable;
|
}
|
||||||
log_info!(
|
EntryType::BAD_MEMORY => {
|
||||||
"Boot: Memory report:\n\t\tFree: {usable}\n\t\tAvailable: {reclaimable}\n\t\tUsable: {}\n\t\tHardware: {hardware}\n\t\tUnusable: {unusable}\n\t\tTotal: {}",
|
unusable += entry.length;
|
||||||
usable + reclaimable,
|
"damaged/unusable"
|
||||||
total
|
}
|
||||||
);
|
EntryType::BOOTLOADER_RECLAIMABLE => {
|
||||||
|
reclaimable += entry.length;
|
||||||
|
"bootloader (reclaimable)"
|
||||||
|
}
|
||||||
|
#[allow(unreachable_patterns, deprecated)]
|
||||||
|
EntryType::EXECUTABLE_AND_MODULES | EntryType::KERNEL_AND_MODULES => {
|
||||||
|
unusable += entry.length;
|
||||||
|
"executable & modules"
|
||||||
|
}
|
||||||
|
EntryType::FRAMEBUFFER => {
|
||||||
|
hardware += entry.length;
|
||||||
|
"framebuffer"
|
||||||
|
}
|
||||||
|
EntryType::RESERVED => {
|
||||||
|
unusable += entry.length;
|
||||||
|
"reserved"
|
||||||
|
}
|
||||||
|
EntryType::USABLE => {
|
||||||
|
usable += entry.length;
|
||||||
|
"usable"
|
||||||
|
}
|
||||||
|
_ => "unidentified",
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
log_trace!("{log_msg}");
|
||||||
|
let total = usable + reclaimable + hardware + unusable;
|
||||||
|
log_info!(
|
||||||
|
"Boot: Memory report:\n\t\tFree: {usable}\n\t\tAvailable: {reclaimable}\n\t\tUsable: {}\n\t\tHardware: {hardware}\n\t\tUnusable: {unusable}\n\t\tTotal: {}",
|
||||||
|
usable + reclaimable,
|
||||||
|
total
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
panic!("Memory map contains no entries");
|
||||||
}
|
}
|
||||||
|
|
||||||
log_trace!(
|
#[cfg(target_arch = "x86_64")]
|
||||||
"GDT: Setting up global descriptor table at 0x{:x}",
|
|
||||||
ptr::addr_of!(GDT) as usize
|
|
||||||
);
|
|
||||||
gdt::setup_gdt();
|
gdt::setup_gdt();
|
||||||
|
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
loop {
|
loop {
|
||||||
for _i in 0..50000000 {
|
for _i in 0..50000000u64 {
|
||||||
unsafe {
|
unsafe {
|
||||||
core::arch::asm!("nop");
|
core::arch::asm!("nop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
core::hint::black_box(());
|
||||||
log_trace!("Heartbeat");
|
log_trace!("Heartbeat");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user