Skip to content

Commit

Permalink
boot+kernel+x86_64: remove oro-id requirements and use paths instead
Browse files Browse the repository at this point in the history
  • Loading branch information
Qix- committed Jan 23, 2025
1 parent baa415d commit 78b5502
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ limine-x86_64-baremetal = "build --target oro-arch-x86_64/x86_64-unknown-oro.jso

limine-aarch64 = "build --target oro-arch-aarch64/aarch64-unknown-oro.json --features oro-debug/pl011 --bin oro-limine-aarch64 -Zunstable-options -Zbuild-std=core,compiler_builtins,alloc -Zbuild-std-features=compiler-builtins-mem"

oro-clippy = "clippy --target ./oro-arch-x86_64/x86_64-unknown-oro.json --target oro-arch-aarch64/aarch64-unknown-oro.json -p oro-boot-protocol -p oro-mem -p oro-debug -p oro-elf -p oro-kernel -p oro-macro -p oro-macro-proc -p oro-sync -p oro-id -p oro-sysabi -p oro -p oro-std -Zunstable-options -Zbuild-std=core,compiler_builtins,alloc -Zbuild-std-features=compiler-builtins-mem"
oro-clippy = "clippy --target ./oro-arch-x86_64/x86_64-unknown-oro.json --target oro-arch-aarch64/aarch64-unknown-oro.json -p oro-boot-protocol -p oro-mem -p oro-debug -p oro-elf -p oro-kernel -p oro-macro -p oro-macro-proc -p oro-sync -p oro-sysabi -p oro -p oro-std -Zunstable-options -Zbuild-std=core,compiler_builtins,alloc -Zbuild-std-features=compiler-builtins-mem"

oro-clippy-x86_64 = "clippy --target ./oro-arch-x86_64/x86_64-unknown-oro.json --features oro-debug/uart16550 --bin oro-kernel-x86_64 --bin oro-limine-x86_64 -Zunstable-options -Zbuild-std=core,compiler_builtins,alloc -Zbuild-std-features=compiler-builtins-mem"

Expand Down
31 changes: 3 additions & 28 deletions dbgutil/oro_debug_suite/cmd/boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,31 +72,6 @@ class BootCmdLimine(gdb.Command):
with the `-m` command line option (described above), or they can be
listed in the `ORO_ROOT_MODULES` environment variable as a semi-colon
separated list of module specifications.
A module must arrive at the kernel with an Oro ID (see the `oro-id` crate).
These are 128-bit IDs - the 3 upper bits indicate the ID type (currently,
1=module, 2=port_type, all others reserved), and the remaining 125 bits
are the ID itself, encoded in a human-friendly base32 format (5 bits per
character).
Bits [60:32] must be something other than 0x0, as IDs with those bits
cleared are reserved for kernel modules, and will be rejected by
either the kernel or the bootloader (whichever sees it first).
An example module ID: M-6397GTPH5MWJH6P0P4JGAGPAZ
An example port type ID: P-M33FKEGA218J0G1VPMK3800UV
You can generate random module/port IDs using a script in the `oro-id` crate:
./oro-id/script/randgen.rs --help
./oro-id/script/randgen.rs --module
./oro-id/script/randgen.rs --port-type
./oro-id/script/randgen.rs -m --internal
./oro-id/script/randgen.rs -m -n 10
When specifying modules, you can use either the `id=path` form, where `id`
is the module ID and `path` is a path to the module file, or just `path`
on its own, in which case the module ID is the basename (and must be valid).
"""

def __init__(self):
Expand Down Expand Up @@ -356,15 +331,15 @@ def copyfile(src, dst):
/Oro Operating System
protocol: limine
path: boot():/oro-limine
path: boot():/oro-limine-{kernel_arch}
serial: yes
kasler: no
{module_config}
"""
)

copyfile(kernel_path, path.join(iso_dir, "oro-kernel"))
copyfile(limine_path, path.join(iso_dir, "oro-limine"))
copyfile(kernel_path, path.join(iso_dir, f"oro-kernel-{kernel_arch}"))
copyfile(limine_path, path.join(iso_dir, f"oro-limine-{kernel_arch}"))

if efi_basename:
copyfile(
Expand Down
1 change: 0 additions & 1 deletion oro-arch-x86_64/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ oro-elf.workspace = true
oro-debug.workspace = true
oro-dbgutil.workspace = true
oro-acpi.workspace = true
oro-id.workspace = true
oro-sync.workspace = true
oro-sysabi.workspace = true

Expand Down
33 changes: 7 additions & 26 deletions oro-arch-x86_64/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use core::{arch::asm, cell::UnsafeCell, mem::MaybeUninit};

use oro_debug::{dbg, dbg_err, dbg_warn};
use oro_debug::{dbg, dbg_err};
use oro_elf::{ElfSegment, ElfSegmentType};
use oro_kernel::{
KernelState, instance::Instance, module::Module, scheduler::Switch, thread::Thread,
Expand Down Expand Up @@ -84,28 +84,9 @@ pub unsafe fn initialize_primary(lapic: Lapic) {

next = core::ptr::read_volatile(&module.next);

let id = oro_id::AnyId::from_high_low(module.id_high, module.id_low);
dbg!("loading module: {:016X} ({})", module.base, module.length);

let Ok(id) = oro_id::Id::<{ oro_id::IdType::Module }>::try_from(id) else {
dbg_warn!(
"skipping module; not a valid module ID: {:?}",
id.as_bytes()
);
continue;
};

if id.is_internal() {
dbg_warn!("skipping module; internal module ID: {:?}", id.as_bytes());
continue;
}

dbg!(
"loading module: {id} @ {:016X} ({})",
module.base,
module.length
);

let module_handle = Module::new(id.clone()).expect("failed to create root ring module");
let module_handle = Module::new().expect("failed to create root ring module");

let entry_point = module_handle.with(|module_lock| {
let mapper = module_lock.mapper();
Expand All @@ -125,22 +106,22 @@ pub unsafe fn initialize_primary(lapic: Lapic) {
ElfSegmentType::Ignored => return None,
ElfSegmentType::Invalid { flags, ptype } => {
dbg_err!(
"root ring module {id} has invalid segment; skipping: \
ptype={ptype:?} flags={flags:?}",
"root ring module has invalid segment; skipping: ptype={ptype:?} \
flags={flags:?}",
);
return None;
}
ElfSegmentType::ModuleCode => AddressSpaceLayout::user_code(),
ElfSegmentType::ModuleData => AddressSpaceLayout::user_data(),
ElfSegmentType::ModuleRoData => AddressSpaceLayout::user_rodata(),
ty => {
dbg_err!("root ring module {id} has invalid segment {ty:?}; skipping",);
dbg_err!("root ring module has invalid segment {ty:?}; skipping",);
return None;
}
};

dbg!(
"{id}: loading {:?} segment: {:016X} {:016X} -> {:016X} ({})",
"loading {:?} segment: {:016X} {:016X} -> {:016X} ({})",
segment.ty(),
segment.load_address(),
segment.load_size(),
Expand Down
39 changes: 20 additions & 19 deletions oro-boot-protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,30 +202,31 @@ macros::oro_boot_protocol! {

/// A module to load into the kernel on the root ring.
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
#[derive(Debug, Clone, Copy)]
pub struct Module {
/// The highest 64 bits of the module 128 bit ID.
///
/// The module ID **must not** be reserved, or
/// the kernel will reject loading it.
///
/// See the `oro-id` crate for more information.
pub id_high: u64,
/// The lowest 64 bits of the module 128 bit ID.
///
/// The module ID **must not** be reserved, or
/// the kernel will reject loading it.
///
/// See the `oro-id` crate for more information.
/// The physical base address of the module.
pub id_low: u64,
/// The path to the module from the boot medium.
/// This may not be a "path" per se, but rather a unique
/// identifier for the module. The kernel does not
/// interpret this value beyond storing it.
pub path: [u8; 128],
/// The physical start address of the module.
pub base: u64,
pub base: u64,
/// The length of the module.
pub length: u64,
pub length: u64,
/// The physical address of the next module in the list,
/// or `0` if this is the last module.
pub next: u64,
pub next: u64,
}

impl Default for Module {
fn default() -> Self {
Self {
path: [0; 128],
base: 0,
length: 0,
next: 0,
}
}
}

#[cfg(feature = "utils")]
Expand Down
13 changes: 11 additions & 2 deletions oro-boot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,12 @@ impl<M: Into<oro_boot_protocol::MemoryMapEntry> + Clone, I: Iterator<Item = M> +
///
/// # Safety
/// Can only be used once per boot.
#[expect(clippy::needless_pass_by_value)]
pub unsafe fn bootstrap(
linear_offset: u64,
stack_pages: usize,
iter: I,
kernel_module: oro_boot_protocol::Module,
kernel: Kernel,
) -> Result<Self> {
// Tell the memory subsystem where our linear offset is.
// SAFETY: We indicate in the safety requirements of this method that
Expand All @@ -142,7 +143,7 @@ impl<M: Into<oro_boot_protocol::MemoryMapEntry> + Clone, I: Iterator<Item = M> +
.ok_or(Error::MapError(MapError::OutOfMemory))?;

let (kernel_entry, scanner) =
self::map::map_kernel_to_supervisor_space(&mut pfa, &supervisor_space, kernel_module)?;
self::map::map_kernel_to_supervisor_space(&mut pfa, &supervisor_space, &kernel)?;

// Map in a stack
let stack_addr = self::map::map_kernel_stack(&mut pfa, &supervisor_space, stack_pages)?;
Expand Down Expand Up @@ -290,3 +291,11 @@ where
}
}
}

/// Represents the kernel, loaded into memory as an ELF.
pub struct Kernel {
/// The kernel module's base physical address.
pub base: u64,
/// The kernel module's size, in bytes.
pub length: u64,
}
6 changes: 3 additions & 3 deletions oro-boot/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ pub fn map_kernel_to_supervisor_space<
>(
pfa: &mut crate::pfa::PrebootPfa<M, I>,
supervisor_space: &<crate::target::AddressSpace as AddressSpace>::SupervisorHandle,
kernel_module: oro_boot_protocol::Module,
kernel: &crate::Kernel,
) -> crate::Result<(usize, oro_boot_protocol::util::RequestScanner)> {
// Parse the kernel ELF module.
// SAFETY(qix-): We can assume the kernel module is valid given that it's
// SAFETY(qix-): been loaded by the bootloader.
let kernel_elf = unsafe {
Elf::parse(
Phys::from_address_unchecked(kernel_module.base).as_ptr_unchecked(),
usize::try_from(kernel_module.length).unwrap(),
Phys::from_address_unchecked(kernel.base).as_ptr_unchecked(),
usize::try_from(kernel.length).unwrap(),
ELF_ENDIANNESS,
ELF_CLASS,
ELF_MACHINE,
Expand Down
1 change: 0 additions & 1 deletion oro-bootloader-limine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ doc = false
oro-boot.workspace = true
oro-boot-protocol.workspace = true
oro-debug.workspace = true
oro-id.workspace = true
limine.workspace = true

[lints]
Expand Down
60 changes: 17 additions & 43 deletions oro-bootloader-limine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#![no_std]
#![cfg_attr(doc, feature(doc_cfg, doc_auto_cfg))]

use core::{ffi::CStr, str::FromStr};
use core::ffi::CStr;

#[cfg(debug_assertions)]
use limine::request::StackSizeRequest;
Expand All @@ -34,7 +34,10 @@ const KERNEL_STACK_PAGES: usize = 16;
/// The path to where the Oro kernel is expected.
/// The bootloader does **not** expect it to be listed
/// as a module (but it can be).
const KERNEL_PATH: &CStr = limine::cstr!("/oro-kernel");
#[cfg(target_arch = "x86_64")]
const KERNEL_PATH: &CStr = limine::cstr!("/oro-kernel-x86_64");
#[cfg(target_arch = "aarch64")]
const KERNEL_PATH: &CStr = limine::cstr!("/oro-kernel-aarch64");

/// The path to where the DeviceTree blob is expected,
/// if provided. The bootloader does **not** expect it to be
Expand Down Expand Up @@ -160,8 +163,6 @@ pub unsafe fn init() -> ! {
})
},
{
use oro_boot_protocol::Module;

let module_response = get_response!(REQ_MODULES, "module listing");
let kernel_module = module_response
.modules()
Expand All @@ -172,13 +173,9 @@ pub unsafe fn init() -> ! {
panic!("failed to find kernel module: {KERNEL_PATH:?}");
};

Module {
id_high: 0,
id_low: 0,
base: u64::try_from(kernel_module.addr() as usize).unwrap()
- hhdm_offset,
length: kernel_module.size(),
next: 0,
oro_boot::Kernel {
base: u64::try_from(kernel_module.addr() as usize).unwrap() - hhdm_offset,
length: kernel_module.size(),
}
},
)?;
Expand Down Expand Up @@ -232,43 +229,20 @@ pub unsafe fn init() -> ! {
return None;
};

let any_id = match oro_id::AnyId::from_str(id_str) {
Ok(id) => id,
Err(err) => {
dbg_err!(
"failed to parse module path as Oro ID: {err:?}: \
{id_str:?}"
);
return None;
}
};

if any_id.ty() != Some(oro_id::IdType::Module) {
dbg_err!(
"failed to parse module path as Oro ID (not a module ID): \
{id_str:?}"
);
return None;
};

if any_id.is_internal() {
dbg_err!(
"failed to parse module path as Oro ID (internal module ID): \
{id_str:?}"
);
if id_str.len() > 128 {
dbg_err!("module path too long: {id_str:?}");
return None;
};
}

let high = any_id.high_bits();
let low = any_id.low_bits();
let mut path_bytes = [0; 128];
path_bytes[..id_str.len()].copy_from_slice(id_str.as_bytes());

Some(oro_boot_protocol::Module {
id_high: high,
id_low: low,
base: u64::try_from(module.addr() as usize).unwrap()
path: path_bytes,
base: u64::try_from(module.addr() as usize).unwrap()
- hhdm_offset,
length: module.size(),
next: 0, // will be written by the serializer
length: module.size(),
next: 0, // will be written by the serializer
})
}),
)?;
Expand Down
1 change: 0 additions & 1 deletion oro-kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ debug-tombs = []
[dependencies]
oro-mem.workspace = true
oro-macro.workspace = true
oro-id.workspace = true
oro-debug.workspace = true
oro-sync.workspace = true
oro-sysabi.workspace = true
Expand Down
Loading

0 comments on commit 78b5502

Please sign in to comment.