cfg: allow passing cmdline options to the kernel
This commit is contained in:
parent
cb5814a5ce
commit
49b918e2ac
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
/target
|
/target
|
||||||
/toolchain
|
/toolchain
|
||||||
/xtask.toml
|
/xtask.toml
|
||||||
|
/qemu.toml
|
||||||
|
/etc/boot/yboot.cfg
|
||||||
|
@ -15,6 +15,9 @@ pub struct LoadProtocol {
|
|||||||
|
|
||||||
pub memory_map: MemoryMap,
|
pub memory_map: MemoryMap,
|
||||||
|
|
||||||
|
pub cmdline: u64,
|
||||||
|
pub cmdline_len: u64,
|
||||||
|
|
||||||
pub rsdp_address: u64,
|
pub rsdp_address: u64,
|
||||||
pub initrd_address: u64,
|
pub initrd_address: u64,
|
||||||
pub initrd_size: u64,
|
pub initrd_size: u64,
|
||||||
|
39
boot/yboot/src/config.rs
Normal file
39
boot/yboot/src/config.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use uefi::{
|
||||||
|
proto::media::file::{Directory, File, FileAttribute, FileMode},
|
||||||
|
CStr16, Result, Status,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Config {
|
||||||
|
pub cmdline: [u8; 4096],
|
||||||
|
pub cmdline_len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
cmdline: [0; 4096],
|
||||||
|
cmdline_len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn load(root: &mut Directory, path: &CStr16) -> Result<Self> {
|
||||||
|
let file = match root.open(path, FileMode::Read, FileAttribute::empty()) {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(error) => {
|
||||||
|
root.reset_entry_readout().ok();
|
||||||
|
log::warn!("Couldn't open {path:?}: {error:?}");
|
||||||
|
return Ok(Self::default());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
root.reset_entry_readout().ok();
|
||||||
|
let mut this = Self::default();
|
||||||
|
let mut file = file.into_regular_file().ok_or(Status::INVALID_PARAMETER)?;
|
||||||
|
|
||||||
|
this.cmdline_len = file.read(&mut this.cmdline)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
pub mod config;
|
||||||
pub mod elf;
|
pub mod elf;
|
||||||
pub mod initrd;
|
pub mod initrd;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
@ -9,6 +10,7 @@ pub mod protocol_ext;
|
|||||||
|
|
||||||
use core::{arch::asm, mem::size_of, ops::Deref};
|
use core::{arch::asm, mem::size_of, ops::Deref};
|
||||||
|
|
||||||
|
use config::Config;
|
||||||
use elf::Object;
|
use elf::Object;
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
use uefi::{
|
use uefi::{
|
||||||
@ -17,7 +19,7 @@ use uefi::{
|
|||||||
console::gop::{GraphicsOutput, PixelFormat},
|
console::gop::{GraphicsOutput, PixelFormat},
|
||||||
device_path::DevicePath,
|
device_path::DevicePath,
|
||||||
loaded_image::LoadedImage,
|
loaded_image::LoadedImage,
|
||||||
media::fs::SimpleFileSystem,
|
media::{file::Directory, fs::SimpleFileSystem},
|
||||||
},
|
},
|
||||||
table::{
|
table::{
|
||||||
boot::{AllocateType, MemoryType, ScopedProtocol},
|
boot::{AllocateType, MemoryType, ScopedProtocol},
|
||||||
@ -94,27 +96,45 @@ fn boot_partition(
|
|||||||
bs.open_protocol_exclusive::<SimpleFileSystem>(fs_handle)
|
bs.open_protocol_exclusive::<SimpleFileSystem>(fs_handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn open_root(image: Handle, bs: &BootServices) -> Result<Directory, Error> {
|
||||||
|
let mut boot_partition = boot_partition(image, bs)?;
|
||||||
|
boot_partition.open_volume()
|
||||||
|
}
|
||||||
|
|
||||||
fn load_kernel<'a>(
|
fn load_kernel<'a>(
|
||||||
ih: Handle,
|
config: &Config,
|
||||||
|
root: &mut Directory,
|
||||||
st: &SystemTable<Boot>,
|
st: &SystemTable<Boot>,
|
||||||
) -> Result<(u64, u64, &'a mut LoadProtocolV1), Error> {
|
) -> Result<(u64, u64, &'a mut LoadProtocolV1), Error> {
|
||||||
let bs = st.boot_services();
|
let bs = st.boot_services();
|
||||||
|
|
||||||
let mut fs = boot_partition(ih, bs)?;
|
let mut kernel_obj = Object::open(root, cstr16!("kernel.elf"))?;
|
||||||
let mut root = fs.open_volume()?;
|
|
||||||
|
|
||||||
let mut kernel_obj = Object::open(&mut root, cstr16!("kernel.elf"))?;
|
|
||||||
let loaded_obj = kernel_obj.load(bs)?;
|
let loaded_obj = kernel_obj.load(bs)?;
|
||||||
|
|
||||||
debug!("Loaded object: {:#x?}", loaded_obj);
|
debug!("Loaded object: {:#x?}", loaded_obj);
|
||||||
|
|
||||||
// Load initrd
|
// Load initrd
|
||||||
let (initrd_start, initrd_size) = initrd::load_somewhere(bs, &mut root, cstr16!("initrd.img"))?;
|
let (initrd_start, initrd_size) = initrd::load_somewhere(bs, root, cstr16!("initrd.img"))?;
|
||||||
debug!(
|
debug!(
|
||||||
"Loaded initrd: {:#x?}",
|
"Loaded initrd: {:#x?}",
|
||||||
initrd_start..initrd_start + initrd_size
|
initrd_start..initrd_start + initrd_size
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Load cmdline
|
||||||
|
let cmdline = if config.cmdline_len != 0 {
|
||||||
|
let address = bs.allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, 1)?;
|
||||||
|
|
||||||
|
let dst =
|
||||||
|
unsafe { core::slice::from_raw_parts_mut(address as *mut u8, config.cmdline_len) };
|
||||||
|
dst.copy_from_slice(&config.cmdline[..config.cmdline_len]);
|
||||||
|
|
||||||
|
debug!("Cmdline at {:#x?}", address);
|
||||||
|
|
||||||
|
address
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
// Other versions are not existent yet
|
// Other versions are not existent yet
|
||||||
assert_eq!(loaded_obj.protocol_version, 1);
|
assert_eq!(loaded_obj.protocol_version, 1);
|
||||||
let proto_data = unsafe { &mut *(loaded_obj.protocol_struct_paddr as *mut LoadProtocolV1) };
|
let proto_data = unsafe { &mut *(loaded_obj.protocol_struct_paddr as *mut LoadProtocolV1) };
|
||||||
@ -125,6 +145,9 @@ fn load_kernel<'a>(
|
|||||||
})?;
|
})?;
|
||||||
info!("RSDP at {:#x}", rsdp);
|
info!("RSDP at {:#x}", rsdp);
|
||||||
|
|
||||||
|
proto_data.cmdline = cmdline;
|
||||||
|
proto_data.cmdline_len = config.cmdline_len as _;
|
||||||
|
|
||||||
proto_data.rsdp_address = rsdp;
|
proto_data.rsdp_address = rsdp;
|
||||||
proto_data.initrd_address = initrd_start;
|
proto_data.initrd_address = initrd_start;
|
||||||
proto_data.initrd_size = initrd_size;
|
proto_data.initrd_size = initrd_size;
|
||||||
@ -190,9 +213,35 @@ unsafe fn map_and_enter_kernel(
|
|||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn efi_main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
fn efi_main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
||||||
uefi_services::init(&mut system_table).unwrap();
|
if uefi_services::init(&mut system_table).is_err() {
|
||||||
|
return Status::LOAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
let (entry, mmap_memory, proto_data) = load_kernel(image_handle, &system_table).unwrap();
|
let bs = system_table.boot_services();
|
||||||
|
|
||||||
|
let mut root = match open_root(image_handle, bs) {
|
||||||
|
Ok(root) => root,
|
||||||
|
Err(error) => {
|
||||||
|
error!("Could not open boot partition root: {error:?}");
|
||||||
|
return Status::LOAD_ERROR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = match Config::load(&mut root, cstr16!("yboot.cfg")) {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(error) => {
|
||||||
|
error!("Malformed yboot.cfg: {error:?}");
|
||||||
|
return Status::LOAD_ERROR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (entry, mmap_memory, proto_data) = match load_kernel(&config, &mut root, &system_table) {
|
||||||
|
Ok(e) => e,
|
||||||
|
Err(error) => {
|
||||||
|
error!("Failed to load the kernel/initrd: {error:?}");
|
||||||
|
return Status::LOAD_ERROR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
map_and_enter_kernel(system_table, proto_data, mmap_memory, entry);
|
map_and_enter_kernel(system_table, proto_data, mmap_memory, entry);
|
||||||
|
@ -536,7 +536,7 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
|||||||
for TaskContextImpl<K, PA>
|
for TaskContextImpl<K, PA>
|
||||||
{
|
{
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
log::info!("Drop Context {:#p}", self);
|
log::trace!("Drop Context {:#p}", self);
|
||||||
assert_eq!(self.stack_size % 0x1000, 0);
|
assert_eq!(self.stack_size % 0x1000, 0);
|
||||||
|
|
||||||
for offset in (0..self.stack_size).step_by(0x1000) {
|
for offset in (0..self.stack_size).step_by(0x1000) {
|
||||||
|
@ -18,8 +18,8 @@ use device_api::{
|
|||||||
};
|
};
|
||||||
use drive::NvmeNamespace;
|
use drive::NvmeNamespace;
|
||||||
use libk::{
|
use libk::{
|
||||||
devfs,
|
|
||||||
device::manager::probe_partitions,
|
device::manager::probe_partitions,
|
||||||
|
fs::devfs,
|
||||||
task::{cpu_count, cpu_index, runtime},
|
task::{cpu_count, cpu_index, runtime},
|
||||||
};
|
};
|
||||||
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo, L3_PAGE_SIZE};
|
use libk_mm::{address::PhysicalAddress, device::DeviceMemoryIo, L3_PAGE_SIZE};
|
||||||
|
@ -66,10 +66,9 @@ impl Node {
|
|||||||
|
|
||||||
// Don't even try if `status = "disabled"`
|
// Don't even try if `status = "disabled"`
|
||||||
if let Some(status) = self.property("status") {
|
if let Some(status) = self.property("status") {
|
||||||
let status = status.as_str();
|
let status = status.as_str().unwrap_or("");
|
||||||
match status {
|
if status == "disabled" {
|
||||||
Some("disabled") => return (None, parent_bus),
|
return (None, parent_bus);
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,11 @@ impl<'a> DeviceTree<'a> {
|
|||||||
self.index.root()
|
self.index.root()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dump the device tree into the debug log
|
||||||
|
pub fn dump(&self) {
|
||||||
|
dump(self.root(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
/// Looks up a node by its `/absolute/path`.
|
/// Looks up a node by its `/absolute/path`.
|
||||||
pub fn find_absolute(&'a self, path: &str) -> Option<TNode<'a>> {
|
pub fn find_absolute(&'a self, path: &str) -> Option<TNode<'a>> {
|
||||||
let mut path = path.trim_start_matches('/');
|
let mut path = path.trim_start_matches('/');
|
||||||
@ -159,6 +164,11 @@ impl<'a> DeviceTree<'a> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the value of `/chosen/bootargs` interpreted as a string
|
||||||
|
pub fn chosen_bootargs(&self) -> Option<&str> {
|
||||||
|
self.root().child("chosen")?.prop_string("bootargs")
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the memory regions specified by this device tree
|
/// Returns an iterator over the memory regions specified by this device tree
|
||||||
pub fn memory_regions(&self) -> DeviceTreeMemoryRegionIter {
|
pub fn memory_regions(&self) -> DeviceTreeMemoryRegionIter {
|
||||||
DeviceTreeMemoryRegionIter::new(self)
|
DeviceTreeMemoryRegionIter::new(self)
|
||||||
@ -178,3 +188,103 @@ impl<'a> DeviceTree<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for DeviceTree<'_> {}
|
unsafe impl Sync for DeviceTree<'_> {}
|
||||||
|
|
||||||
|
fn indent(amount: usize) {
|
||||||
|
log::info!(target: "raw", "{0:1$}", "", amount * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_property(node: &TNode, prop: TProp, level: usize) {
|
||||||
|
enum Type {
|
||||||
|
String,
|
||||||
|
Cells,
|
||||||
|
Bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
let node_name = node.name().unwrap_or("");
|
||||||
|
let name = prop.name().unwrap_or("<unknown-prop>");
|
||||||
|
|
||||||
|
indent(level);
|
||||||
|
log::info!(target: "raw", "{name}");
|
||||||
|
|
||||||
|
if prop.len() == 0 {
|
||||||
|
log::info!(target: "raw", ";\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!(target: "raw", " = ");
|
||||||
|
|
||||||
|
let ty = match name {
|
||||||
|
"model" | "compatible" | "clock-output-names" | "clock-names" | "device_type"
|
||||||
|
| "enable-method" | "status" | "label" | "method" => Type::String,
|
||||||
|
"stdout-path" | "bootargs" if node_name == "chosen" => Type::String,
|
||||||
|
_ if node_name == "aliases" => Type::String,
|
||||||
|
_ if prop.len() % size_of::<u32>() == 0 => Type::Cells,
|
||||||
|
_ => Type::Bytes,
|
||||||
|
};
|
||||||
|
|
||||||
|
match ty {
|
||||||
|
Type::String => {
|
||||||
|
// "..."
|
||||||
|
for (i, string) in prop.as_str_list().enumerate() {
|
||||||
|
if i != 0 {
|
||||||
|
log::info!(target: "raw", ", ");
|
||||||
|
}
|
||||||
|
log::info!(target: "raw", "{string:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::Cells => {
|
||||||
|
// <...>
|
||||||
|
log::info!(target: "raw", "<");
|
||||||
|
let mut i = 0;
|
||||||
|
while let Some(value) = prop.read_cell(i, 1) {
|
||||||
|
if i != 0 {
|
||||||
|
log::info!(target: "raw", ", ");
|
||||||
|
}
|
||||||
|
log::info!(target: "raw", "{value:#x}");
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
log::info!(target: "raw", ">");
|
||||||
|
}
|
||||||
|
Type::Bytes => {
|
||||||
|
// <...>
|
||||||
|
log::info!(target: "raw", "<");
|
||||||
|
for (i, byte) in prop.raw().iter().enumerate() {
|
||||||
|
if i != 0 {
|
||||||
|
log::info!(target: "raw", ", ");
|
||||||
|
}
|
||||||
|
log::info!(target: "raw", "{byte:#x}");
|
||||||
|
}
|
||||||
|
log::info!(target: "raw", ">");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!(target: "raw", ";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump(node: TNode, level: usize) {
|
||||||
|
let name = node.name().unwrap_or("<unknown>");
|
||||||
|
|
||||||
|
indent(level);
|
||||||
|
if name.is_empty() {
|
||||||
|
log::info!(target: "raw", "{{\n");
|
||||||
|
} else {
|
||||||
|
log::info!(target: "raw", "{name}: {{\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut do_break = false;
|
||||||
|
for property in node.props() {
|
||||||
|
dump_property(&node, property, level + 1);
|
||||||
|
do_break = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for child in node.children() {
|
||||||
|
if do_break {
|
||||||
|
log::info!(target: "raw", "\n");
|
||||||
|
do_break = false;
|
||||||
|
}
|
||||||
|
dump(child, level + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
indent(level);
|
||||||
|
log::info!(target: "raw", "}}\n");
|
||||||
|
}
|
||||||
|
57
kernel/libk/src/config/general.rs
Normal file
57
kernel/libk/src/config/general.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use core::str::FromStr;
|
||||||
|
|
||||||
|
use crate::debug::LogLevel;
|
||||||
|
|
||||||
|
use super::SetOption;
|
||||||
|
|
||||||
|
/// Debugging/logging-related options
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DebugOptions {
|
||||||
|
/// Default log level used for serial devices
|
||||||
|
pub serial_level: LogLevel,
|
||||||
|
/// Default log level used for proper display devices
|
||||||
|
pub display_level: LogLevel,
|
||||||
|
/// If set, logs produced by the `debug_trace` syscall are ignored
|
||||||
|
pub disable_program_trace: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DebugOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
serial_level: LogLevel::Info,
|
||||||
|
display_level: LogLevel::Info,
|
||||||
|
disable_program_trace: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetOption for DebugOptions {
|
||||||
|
fn set_key_value(&mut self, key: &str, value: &str) -> bool {
|
||||||
|
match key {
|
||||||
|
"serial-level" if let Ok(level) = LogLevel::from_str(value) => {
|
||||||
|
self.serial_level = level;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
"display-level" if let Ok(level) = LogLevel::from_str(value) => {
|
||||||
|
self.display_level = level;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
"log_level" if let Ok(level) = LogLevel::from_str(value) => {
|
||||||
|
self.serial_level = level;
|
||||||
|
self.display_level = level;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_flag(&mut self, value: &str) -> bool {
|
||||||
|
match value {
|
||||||
|
"disable-program-trace" => {
|
||||||
|
self.disable_program_trace = true;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
118
kernel/libk/src/config/mod.rs
Normal file
118
kernel/libk/src/config/mod.rs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
//! Kernel commandline parameters handling
|
||||||
|
|
||||||
|
use alloc::string::String;
|
||||||
|
use libk_util::OneTimeInit;
|
||||||
|
use yggdrasil_abi::error::Error;
|
||||||
|
|
||||||
|
use crate::fs::sysfs::{
|
||||||
|
self,
|
||||||
|
attribute::{StringAttribute, StringAttributeOps},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||||||
|
mod x86;
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||||||
|
pub use x86::X86Options;
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
mod x86_64;
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
pub use x86_64::X86_64Options;
|
||||||
|
|
||||||
|
mod general;
|
||||||
|
pub use general::DebugOptions;
|
||||||
|
|
||||||
|
trait SetOption {
|
||||||
|
fn set_key_value(&mut self, key: &str, value: &str) -> bool;
|
||||||
|
fn set_flag(&mut self, value: &str) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Kernel commandline options
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Options {
|
||||||
|
pub debug: DebugOptions,
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||||||
|
pub x86: X86Options,
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
pub x86_64: X86_64Options,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetOption for Options {
|
||||||
|
fn set_flag(&mut self, value: &str) -> bool {
|
||||||
|
match value {
|
||||||
|
_ if let Some(value) = value.strip_prefix("debug.") => self.debug.set_flag(value),
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||||||
|
_ if let Some(value) = value.strip_prefix("x86.") => self.x86.set_flag(value),
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
_ if let Some(value) = value.strip_prefix("x86_64.") => self.x86_64.set_flag(value),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_key_value(&mut self, key: &str, value: &str) -> bool {
|
||||||
|
match key {
|
||||||
|
_ if let Some(key) = key.strip_prefix("debug.") => self.debug.set_key_value(key, value),
|
||||||
|
#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))]
|
||||||
|
_ if let Some(key) = key.strip_prefix("x86.") => self.x86.set_key_value(key, value),
|
||||||
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
|
_ if let Some(key) = key.strip_prefix("x86_64.") => {
|
||||||
|
self.x86_64.set_key_value(key, value)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static OPTIONS: OneTimeInit<Options> = OneTimeInit::new();
|
||||||
|
static OPTIONS_STRING: OneTimeInit<String> = OneTimeInit::new();
|
||||||
|
|
||||||
|
pub fn get() -> &'static Options {
|
||||||
|
OPTIONS.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_argument(options: &mut Options, arg: &str) -> bool {
|
||||||
|
let arg = arg.trim();
|
||||||
|
|
||||||
|
if let Some((key, value)) = arg.split_once('=') {
|
||||||
|
options.set_key_value(key.trim_end(), value.trim_start())
|
||||||
|
} else {
|
||||||
|
options.set_flag(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets up kernel options from an argument list
|
||||||
|
pub fn parse_boot_argument_list<'a, I: Iterator<Item = &'a str>>(args: I) {
|
||||||
|
let mut options = Default::default();
|
||||||
|
let mut string = String::new();
|
||||||
|
|
||||||
|
args.for_each(|arg| {
|
||||||
|
if parse_argument(&mut options, arg) {
|
||||||
|
string.push_str(arg);
|
||||||
|
string.push('\n');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
OPTIONS.init(options);
|
||||||
|
OPTIONS_STRING.init(string);
|
||||||
|
|
||||||
|
// Add to sysfs
|
||||||
|
if let Some(kernel) = sysfs::kernel() {
|
||||||
|
struct Cmdline;
|
||||||
|
|
||||||
|
impl StringAttributeOps for Cmdline {
|
||||||
|
const NAME: &'static str = "cmdline";
|
||||||
|
const NEWLINE: bool = false;
|
||||||
|
|
||||||
|
fn read(_state: &Self::Data) -> Result<String, Error> {
|
||||||
|
Ok(OPTIONS_STRING.get().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel.add_attribute(StringAttribute::from(Cmdline)).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets up kernel options from an argument string, where options are separated by whitespace
|
||||||
|
pub fn parse_boot_arguments(args: &str) {
|
||||||
|
parse_boot_argument_list(args.trim().split(' '));
|
||||||
|
}
|
30
kernel/libk/src/config/x86.rs
Normal file
30
kernel/libk/src/config/x86.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use super::SetOption;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct X86Options {
|
||||||
|
pub disable_boot_fb: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for X86Options {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
disable_boot_fb: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetOption for X86Options {
|
||||||
|
fn set_flag(&mut self, value: &str) -> bool {
|
||||||
|
match value {
|
||||||
|
"disable-boot-fb" => {
|
||||||
|
self.disable_boot_fb = true;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_key_value(&mut self, _key: &str, _value: &str) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
30
kernel/libk/src/config/x86_64.rs
Normal file
30
kernel/libk/src/config/x86_64.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use super::SetOption;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct X86_64Options {
|
||||||
|
pub disable_hpet: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for X86_64Options {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
disable_hpet: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetOption for X86_64Options {
|
||||||
|
fn set_key_value(&mut self, _key: &str, _value: &str) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_flag(&mut self, value: &str) -> bool {
|
||||||
|
match value {
|
||||||
|
"disable-hpet" => {
|
||||||
|
self.disable_hpet = true;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ use libk_util::{
|
|||||||
use yggdrasil_abi::error::Error;
|
use yggdrasil_abi::error::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
config,
|
||||||
fs::sysfs::{
|
fs::sysfs::{
|
||||||
self,
|
self,
|
||||||
attribute::{StringAttribute, StringAttributeOps},
|
attribute::{StringAttribute, StringAttributeOps},
|
||||||
@ -56,7 +57,7 @@ pub struct RingLoggerSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the severity of the message
|
/// Defines the severity of the message
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum LogLevel {
|
pub enum LogLevel {
|
||||||
/// Very verbose low-level debugging information
|
/// Very verbose low-level debugging information
|
||||||
Trace,
|
Trace,
|
||||||
@ -138,7 +139,14 @@ impl DebugSinkWrapper {
|
|||||||
|
|
||||||
impl log::Log for DebugSinkWrapper {
|
impl log::Log for DebugSinkWrapper {
|
||||||
fn enabled(&self, metadata: &log::Metadata) -> bool {
|
fn enabled(&self, metadata: &log::Metadata) -> bool {
|
||||||
LogLevel::from(metadata.level()) >= self.level()
|
if LogLevel::from(metadata.level()) < self.level() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if metadata.target() == "program" && config::get().debug.disable_program_trace {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log(&self, record: &log::Record) {
|
fn log(&self, record: &log::Record) {
|
||||||
|
@ -9,7 +9,8 @@ use libk_util::{sync::spin_rwlock::IrqSafeRwLock, OneTimeInit};
|
|||||||
use yggdrasil_abi::error::Error;
|
use yggdrasil_abi::error::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
debug::{self, DebugSink, LogLevel},
|
config,
|
||||||
|
debug::{self, DebugSink},
|
||||||
fs::devfs,
|
fs::devfs,
|
||||||
vfs::NodeRef,
|
vfs::NodeRef,
|
||||||
};
|
};
|
||||||
@ -92,12 +93,12 @@ impl SerialTerminalRegistry {
|
|||||||
pub fn register(
|
pub fn register(
|
||||||
&self,
|
&self,
|
||||||
terminal: Arc<dyn CharDevice>,
|
terminal: Arc<dyn CharDevice>,
|
||||||
sink_level: Option<(Arc<dyn DebugSink>, LogLevel)>,
|
sink: Option<Arc<dyn DebugSink>>,
|
||||||
) -> Result<u32, Error> {
|
) -> Result<u32, Error> {
|
||||||
let id = self.registry.register(terminal.clone())?;
|
let id = self.registry.register(terminal.clone())?;
|
||||||
devfs::add_named_char_device(terminal, format!("ttyS{id}")).ok();
|
devfs::add_named_char_device(terminal, format!("ttyS{id}")).ok();
|
||||||
if let Some((sink, sink_level)) = sink_level {
|
if let Some(sink) = sink {
|
||||||
debug::add_serial_sink(sink, sink_level);
|
debug::add_serial_sink(sink, config::get().debug.serial_level);
|
||||||
}
|
}
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ pub trait StringAttributeOps: Sync + Send + 'static {
|
|||||||
const WRITEABLE: bool = false;
|
const WRITEABLE: bool = false;
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
const LIMIT: usize = 4096;
|
const LIMIT: usize = 4096;
|
||||||
|
const NEWLINE: bool = true;
|
||||||
|
|
||||||
fn read(state: &Self::Data) -> Result<String, Error> {
|
fn read(state: &Self::Data) -> Result<String, Error> {
|
||||||
let _ = state;
|
let _ = state;
|
||||||
@ -69,7 +70,9 @@ impl<V: StringAttributeOps> RegularImpl for StringAttributeNode<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut value = V::read(self.object.data())?.into_bytes();
|
let mut value = V::read(self.object.data())?.into_bytes();
|
||||||
|
if V::NEWLINE {
|
||||||
value.push(b'\n');
|
value.push(b'\n');
|
||||||
|
}
|
||||||
|
|
||||||
let instance = StringAttributeState {
|
let instance = StringAttributeState {
|
||||||
value: IrqSafeRwLock::new(value),
|
value: IrqSafeRwLock::new(value),
|
||||||
|
@ -35,6 +35,7 @@ pub use yggdrasil_abi::error;
|
|||||||
pub mod task;
|
pub mod task;
|
||||||
|
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
|
pub mod config;
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
pub mod device;
|
pub mod device;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
@ -18,7 +18,7 @@ use kernel_arch_aarch64::{
|
|||||||
},
|
},
|
||||||
ArchitectureImpl, PerCpuData,
|
ArchitectureImpl, PerCpuData,
|
||||||
};
|
};
|
||||||
use libk::{arch::Cpu, debug, device::external_interrupt_controller};
|
use libk::{arch::Cpu, config, debug, device::external_interrupt_controller};
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::PhysicalAddress,
|
address::PhysicalAddress,
|
||||||
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
phys::{self, reserved::reserve_region, PhysicalMemoryRegion},
|
||||||
@ -252,37 +252,11 @@ impl AArch64 {
|
|||||||
|
|
||||||
atomic::compiler_fence(Ordering::SeqCst);
|
atomic::compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
// TODO
|
|
||||||
// ygg_driver_pci::register_vendor_driver(
|
|
||||||
// "Virtio PCI GPU Device",
|
|
||||||
// 0x1AF4,
|
|
||||||
// 0x1050,
|
|
||||||
// ygg_driver_virtio_gpu::probe,
|
|
||||||
// );
|
|
||||||
// ygg_driver_pci::register_vendor_driver(
|
|
||||||
// "Virtio PCI Network Device",
|
|
||||||
// 0x1AF4,
|
|
||||||
// 0x1000,
|
|
||||||
// ygg_driver_virtio_net::probe,
|
|
||||||
// );
|
|
||||||
// ygg_driver_pci::register_class_driver(
|
|
||||||
// "AHCI SATA Controller",
|
|
||||||
// 0x01,
|
|
||||||
// Some(0x06),
|
|
||||||
// Some(0x01),
|
|
||||||
// ygg_driver_ahci::probe,
|
|
||||||
// );
|
|
||||||
// ygg_driver_pci::register_class_driver(
|
|
||||||
// "USB xHCI",
|
|
||||||
// 0x0C,
|
|
||||||
// Some(0x03),
|
|
||||||
// Some(0x30),
|
|
||||||
// ygg_driver_usb_xhci::probe,
|
|
||||||
// );
|
|
||||||
|
|
||||||
debug::init();
|
debug::init();
|
||||||
|
|
||||||
let dt = self.dt.get();
|
let dt = self.dt.get();
|
||||||
|
let bootargs = dt.chosen_bootargs().unwrap_or("");
|
||||||
|
config::parse_boot_arguments(bootargs);
|
||||||
|
|
||||||
// Create device tree sysfs nodes
|
// Create device tree sysfs nodes
|
||||||
device_tree::util::create_sysfs_nodes(dt);
|
device_tree::util::create_sysfs_nodes(dt);
|
||||||
@ -302,6 +276,7 @@ impl AArch64 {
|
|||||||
log::info!("Running on {machine:?}");
|
log::info!("Running on {machine:?}");
|
||||||
MACHINE_NAME.init(machine.into());
|
MACHINE_NAME.init(machine.into());
|
||||||
}
|
}
|
||||||
|
log::info!("Boot arguments: {bootargs:?}");
|
||||||
|
|
||||||
log::info!("Initializing aarch64 platform");
|
log::info!("Initializing aarch64 platform");
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use core::ffi::CStr;
|
||||||
|
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::{PhysicalAddress, Virtualize},
|
address::{PhysicalAddress, Virtualize},
|
||||||
phys::PhysicalMemoryRegion,
|
phys::PhysicalMemoryRegion,
|
||||||
@ -87,6 +89,16 @@ impl MultibootInfo {
|
|||||||
let base = PhysicalAddress::from_u32(self.mods_addr).virtualize();
|
let base = PhysicalAddress::from_u32(self.mods_addr).virtualize();
|
||||||
unsafe { core::slice::from_raw_parts(base as *const _, self.mods_count as usize) }
|
unsafe { core::slice::from_raw_parts(base as *const _, self.mods_count as usize) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cmdline(&self) -> &str {
|
||||||
|
if self.cmdline == 0 {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
let address = PhysicalAddress::from_u32(self.cmdline).virtualize();
|
||||||
|
let data = unsafe { CStr::from_ptr(core::ptr::with_exposed_provenance(address)) };
|
||||||
|
data.to_str().unwrap_or("")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MultibootMemoryMapEntry {
|
impl MultibootMemoryMapEntry {
|
||||||
|
@ -13,7 +13,7 @@ use kernel_arch_i686::{gdt, mem::table::L3, PerCpuData};
|
|||||||
use kernel_arch_x86::cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures};
|
use kernel_arch_x86::cpuid::{self, CpuFeatures, EcxFeatures, EdxFeatures};
|
||||||
use libk::{
|
use libk::{
|
||||||
arch::Cpu,
|
arch::Cpu,
|
||||||
debug::{self, LogLevel},
|
config, debug,
|
||||||
device::{
|
device::{
|
||||||
display::{
|
display::{
|
||||||
console::{add_console_autoflush, ConsoleWrapper},
|
console::{add_console_autoflush, ConsoleWrapper},
|
||||||
@ -130,7 +130,7 @@ impl I686 {
|
|||||||
80,
|
80,
|
||||||
25,
|
25,
|
||||||
)?);
|
)?);
|
||||||
debug::add_sink(textfb.clone(), LogLevel::Info);
|
debug::add_sink(textfb.clone(), config::get().debug.display_level);
|
||||||
add_console_autoflush(textfb.clone());
|
add_console_autoflush(textfb.clone());
|
||||||
|
|
||||||
let textfb_console = Arc::new(Terminal::from_parts(
|
let textfb_console = Arc::new(Terminal::from_parts(
|
||||||
@ -155,15 +155,20 @@ impl I686 {
|
|||||||
self.init_memory_management(multiboot_info)
|
self.init_memory_management(multiboot_info)
|
||||||
.expect("Could not initialize memory management");
|
.expect("Could not initialize memory management");
|
||||||
|
|
||||||
|
// Set kernel commandline
|
||||||
|
let cmdline = multiboot_info.cmdline();
|
||||||
|
|
||||||
self.init_cpu().expect("Could not initialize CPU");
|
self.init_cpu().expect("Could not initialize CPU");
|
||||||
|
|
||||||
x86::register_pci_drivers();
|
x86::register_pci_drivers();
|
||||||
|
|
||||||
let early = x86::init_platform_devices_early()?;
|
let early = x86::init_platform_early(cmdline)?;
|
||||||
|
|
||||||
|
if !config::get().x86.disable_boot_fb {
|
||||||
if let Err(error) = self.init_framebuffer() {
|
if let Err(error) = self.init_framebuffer() {
|
||||||
log::error!("Could not initialize boot framebuffer: {error:?}");
|
log::error!("Could not initialize boot framebuffer: {error:?}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
x86::add_legacy_pci();
|
x86::add_legacy_pci();
|
||||||
x86::init_platform_devices(early);
|
x86::init_platform_devices(early);
|
||||||
|
@ -5,7 +5,11 @@
|
|||||||
use abi::error::Error;
|
use abi::error::Error;
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
use device_api::{device::Device, interrupt::Irq};
|
use device_api::{device::Device, interrupt::Irq};
|
||||||
use libk::{debug, devfs, task::runtime};
|
use libk::{
|
||||||
|
config, debug,
|
||||||
|
fs::{devfs, sysfs},
|
||||||
|
task::runtime,
|
||||||
|
};
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::{PhysicalAddress, Virtualize},
|
address::{PhysicalAddress, Virtualize},
|
||||||
phys::{self, PhysicalMemoryRegion},
|
phys::{self, PhysicalMemoryRegion},
|
||||||
@ -96,10 +100,13 @@ pub fn register_pci_drivers() {
|
|||||||
// Initialize the bare minimum required to:
|
// Initialize the bare minimum required to:
|
||||||
// * Allocate/manage interrupts
|
// * Allocate/manage interrupts
|
||||||
// * Print debug output
|
// * Print debug output
|
||||||
pub fn init_platform_devices_early() -> Result<EarlyPlatformDevices, Error> {
|
pub fn init_platform_early(cmdline: &str) -> Result<EarlyPlatformDevices, Error> {
|
||||||
|
sysfs::init();
|
||||||
devfs::init();
|
devfs::init();
|
||||||
debug::init();
|
debug::init();
|
||||||
|
|
||||||
|
config::parse_boot_arguments(cmdline);
|
||||||
|
|
||||||
// Initialize async executor queue
|
// Initialize async executor queue
|
||||||
runtime::init_task_queue();
|
runtime::init_task_queue();
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use device_api::{
|
|||||||
interrupt::{InterruptHandler, Irq},
|
interrupt::{InterruptHandler, Irq},
|
||||||
};
|
};
|
||||||
use libk::{
|
use libk::{
|
||||||
debug::{DebugSink, LogLevel},
|
debug::DebugSink,
|
||||||
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
||||||
vfs::{Terminal, TerminalInput, TerminalOutput},
|
vfs::{Terminal, TerminalInput, TerminalOutput},
|
||||||
};
|
};
|
||||||
@ -117,7 +117,7 @@ impl Device for Port {
|
|||||||
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
|
unsafe fn init(self: Arc<Self>) -> Result<(), Error> {
|
||||||
DEVICE_REGISTRY
|
DEVICE_REGISTRY
|
||||||
.serial_terminal
|
.serial_terminal
|
||||||
.register(self.terminal.clone(), Some((self.clone(), LogLevel::Debug)))
|
.register(self.terminal.clone(), Some(self.clone()))
|
||||||
.ok();
|
.ok();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use core::{arch::global_asm, sync::atomic::Ordering};
|
|||||||
|
|
||||||
use kernel_arch_x86::registers::MSR_IA32_KERNEL_GS_BASE;
|
use kernel_arch_x86::registers::MSR_IA32_KERNEL_GS_BASE;
|
||||||
use kernel_arch_x86_64::CPU_COUNT;
|
use kernel_arch_x86_64::CPU_COUNT;
|
||||||
|
use libk_mm::address::{PhysicalAddress, Virtualize};
|
||||||
use tock_registers::interfaces::Writeable;
|
use tock_registers::interfaces::Writeable;
|
||||||
use yboot_proto::{
|
use yboot_proto::{
|
||||||
v1::{FramebufferOption, MemoryMap},
|
v1::{FramebufferOption, MemoryMap},
|
||||||
@ -17,6 +18,29 @@ pub enum BootData {
|
|||||||
YBoot(&'static LoadProtocolV1),
|
YBoot(&'static LoadProtocolV1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BootData {
|
||||||
|
pub fn cmdline(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
&Self::YBoot(data) => {
|
||||||
|
if data.cmdline != 0 && data.cmdline_len != 0 {
|
||||||
|
let address = PhysicalAddress::from_u64(data.cmdline).virtualize();
|
||||||
|
let len = data.cmdline_len as usize;
|
||||||
|
let raw = unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
core::ptr::with_exposed_provenance(address),
|
||||||
|
len,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
core::str::from_utf8(raw).unwrap_or("")
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const BOOT_STACK_SIZE: usize = 1024 * 1024;
|
const BOOT_STACK_SIZE: usize = 1024 * 1024;
|
||||||
|
|
||||||
#[repr(C, align(0x20))]
|
#[repr(C, align(0x20))]
|
||||||
@ -40,6 +64,9 @@ static YBOOT_DATA: LoadProtocolV1 = LoadProtocolV1 {
|
|||||||
|
|
||||||
memory_map: MemoryMap { address: 0, len: 0 },
|
memory_map: MemoryMap { address: 0, len: 0 },
|
||||||
|
|
||||||
|
cmdline: 0,
|
||||||
|
cmdline_len: 0,
|
||||||
|
|
||||||
rsdp_address: 0,
|
rsdp_address: 0,
|
||||||
initrd_address: 0,
|
initrd_address: 0,
|
||||||
initrd_size: 0,
|
initrd_size: 0,
|
||||||
|
@ -21,13 +21,13 @@ use kernel_arch_x86_64::{
|
|||||||
};
|
};
|
||||||
use libk::{
|
use libk::{
|
||||||
arch::Cpu,
|
arch::Cpu,
|
||||||
debug::{self, LogLevel},
|
config, debug,
|
||||||
devfs,
|
|
||||||
device::{
|
device::{
|
||||||
display::{fb_console::FramebufferConsole, DriverFlags, PixelFormat},
|
display::{fb_console::FramebufferConsole, DriverFlags, PixelFormat},
|
||||||
manager::DEVICE_REGISTRY,
|
manager::DEVICE_REGISTRY,
|
||||||
register_external_interrupt_controller,
|
register_external_interrupt_controller,
|
||||||
},
|
},
|
||||||
|
fs::devfs,
|
||||||
};
|
};
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::PhysicalAddress,
|
address::PhysicalAddress,
|
||||||
@ -259,17 +259,25 @@ impl X86_64 {
|
|||||||
|
|
||||||
self.setup_from_boot_data()?;
|
self.setup_from_boot_data()?;
|
||||||
|
|
||||||
let mut early = x86::init_platform_devices_early()?;
|
// 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)?;
|
||||||
|
|
||||||
|
if !config::get().x86.disable_boot_fb {
|
||||||
if let Err(error) = self.init_framebuffer() {
|
if let Err(error) = self.init_framebuffer() {
|
||||||
log::error!("Could not initialize boot framebuffer: {error:?}");
|
log::error!("Could not initialize boot framebuffer: {error:?}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(acpi) = self.acpi.try_get() {
|
if let Some(acpi) = self.acpi.try_get() {
|
||||||
self.init_platform_from_acpi(acpi)?;
|
self.init_platform_from_acpi(acpi)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !config::get().x86_64.disable_hpet {
|
||||||
early.add_preferred_clock_source("hpet", Self::setup_hpet);
|
early.add_preferred_clock_source("hpet", Self::setup_hpet);
|
||||||
|
} else {
|
||||||
|
log::info!("HPET disabled by config");
|
||||||
|
}
|
||||||
|
|
||||||
x86::init_platform_devices(early);
|
x86::init_platform_devices(early);
|
||||||
}
|
}
|
||||||
@ -434,7 +442,7 @@ impl X86_64 {
|
|||||||
true,
|
true,
|
||||||
)?));
|
)?));
|
||||||
|
|
||||||
debug::add_sink(fbconsole.clone(), LogLevel::Info);
|
debug::add_sink(fbconsole.clone(), config::get().debug.display_level);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use device_tree::{
|
|||||||
DeviceTreePropertyRead,
|
DeviceTreePropertyRead,
|
||||||
};
|
};
|
||||||
use libk::{
|
use libk::{
|
||||||
debug::{DebugSink, LogLevel},
|
debug::DebugSink,
|
||||||
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
||||||
vfs::{Terminal, TerminalInput, TerminalOutput},
|
vfs::{Terminal, TerminalInput, TerminalOutput},
|
||||||
};
|
};
|
||||||
@ -170,7 +170,7 @@ impl Device for Bcm2835AuxUart {
|
|||||||
|
|
||||||
DEVICE_REGISTRY
|
DEVICE_REGISTRY
|
||||||
.serial_terminal
|
.serial_terminal
|
||||||
.register(inner.clone(), Some((self.clone(), LogLevel::Debug)))
|
.register(inner.clone(), Some(self.clone()))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -7,7 +7,7 @@ use device_api::{
|
|||||||
};
|
};
|
||||||
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
|
use device_tree::driver::{device_tree_driver, Node, ProbeContext};
|
||||||
use libk::{
|
use libk::{
|
||||||
debug::{DebugSink, LogLevel},
|
debug::DebugSink,
|
||||||
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
device::{external_interrupt_controller, manager::DEVICE_REGISTRY},
|
||||||
vfs::{Terminal, TerminalInput, TerminalOutput},
|
vfs::{Terminal, TerminalInput, TerminalOutput},
|
||||||
};
|
};
|
||||||
@ -158,7 +158,7 @@ impl Device for Pl011 {
|
|||||||
|
|
||||||
DEVICE_REGISTRY
|
DEVICE_REGISTRY
|
||||||
.serial_terminal
|
.serial_terminal
|
||||||
.register(terminal.clone(), Some((self.clone(), LogLevel::Info)))
|
.register(terminal.clone(), Some(self.clone()))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -37,6 +37,7 @@ pub enum CargoBuilder<'e> {
|
|||||||
|
|
||||||
impl<'e> CargoBuilder<'e> {
|
impl<'e> CargoBuilder<'e> {
|
||||||
pub fn run<P: AsRef<Path>, S: AsRef<OsStr>>(self, dir: P, arg: S) -> Result<(), Error> {
|
pub fn run<P: AsRef<Path>, S: AsRef<OsStr>>(self, dir: P, arg: S) -> Result<(), Error> {
|
||||||
|
let arg = arg.as_ref();
|
||||||
let mut command = Command::new("cargo");
|
let mut command = Command::new("cargo");
|
||||||
|
|
||||||
command.current_dir(dir);
|
command.current_dir(dir);
|
||||||
@ -134,12 +135,17 @@ impl<'e> CargoBuilder<'e> {
|
|||||||
.join(env.kernel_triple)
|
.join(env.kernel_triple)
|
||||||
.display()
|
.display()
|
||||||
);
|
);
|
||||||
let artifact_dir_arg =
|
|
||||||
format!("--artifact-dir={}", env.kernel_output_dir.display());
|
|
||||||
|
|
||||||
command.arg(target_spec_arg);
|
command.arg(target_spec_arg);
|
||||||
|
|
||||||
command.arg(target_dir_arg);
|
command.arg(target_dir_arg);
|
||||||
|
|
||||||
|
if arg != "clippy" && arg != "check" {
|
||||||
|
let artifact_dir_arg =
|
||||||
|
format!("--artifact-dir={}", env.kernel_output_dir.display());
|
||||||
command.arg(artifact_dir_arg);
|
command.arg(artifact_dir_arg);
|
||||||
|
}
|
||||||
|
|
||||||
command.args([
|
command.args([
|
||||||
"-Z",
|
"-Z",
|
||||||
"build-std=core,alloc,compiler_builtins",
|
"build-std=core,alloc,compiler_builtins",
|
||||||
|
@ -49,6 +49,7 @@ fn build_uefi_image(
|
|||||||
) -> Result<ImageBuilt, Error> {
|
) -> Result<ImageBuilt, Error> {
|
||||||
log::info!("Building x86-64 UEFI image");
|
log::info!("Building x86-64 UEFI image");
|
||||||
let image_path = env.kernel_output_dir.join("image.fat32");
|
let image_path = env.kernel_output_dir.join("image.fat32");
|
||||||
|
let yboot_cfg = env.workspace_root.join("etc/boot/yboot.cfg");
|
||||||
|
|
||||||
if !image_path.exists() {
|
if !image_path.exists() {
|
||||||
util::run_external_command(
|
util::run_external_command(
|
||||||
@ -81,6 +82,11 @@ fn build_uefi_image(
|
|||||||
copy_into_fat(&boot_dir, &yboot.0, "BootX64.efi")?;
|
copy_into_fat(&boot_dir, &yboot.0, "BootX64.efi")?;
|
||||||
copy_into_fat(&root_dir, &kernel.0 .0, "kernel.elf")?;
|
copy_into_fat(&root_dir, &kernel.0 .0, "kernel.elf")?;
|
||||||
copy_into_fat(&root_dir, &initrd.0, "initrd.img")?;
|
copy_into_fat(&root_dir, &initrd.0, "initrd.img")?;
|
||||||
|
if yboot_cfg.exists() {
|
||||||
|
copy_into_fat(&root_dir, &yboot_cfg, "yboot.cfg")?;
|
||||||
|
} else {
|
||||||
|
root_dir.remove("yboot.cfg").ok();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(ImageBuilt(image_path))
|
Ok(ImageBuilt(image_path))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user