feat(adapter): init+storage packed into kernel image; drop adapter FAT16 reader + virtio-blk

This commit is contained in:
2026-10-27 16:58:11 +01:00
parent b80303f553
commit 4030dd4315
10 changed files with 43 additions and 265 deletions

View File

@@ -1,6 +1,5 @@
use crate::hw::uart::Uart;
use crate::hw::virtio_blk::VirtioBlk;
use crate::{boot_fs, mmu};
use crate::mmu;
use types::address::VirtualAddress;
use types::budget::Limits;
use types::id::{ProcessId, ThreadId};
@@ -10,7 +9,6 @@ const PAGE_SIZE: usize = mmu::PAGE_SIZE;
const USER_VA_BASE: usize = 0x10000;
/// The stack sits just below the image and stops short of the null page.
const USER_STACK_PAGES: usize = USER_VA_BASE / PAGE_SIZE - 1;
const MAX_FILE_SIZE: usize = 64 * 1024;
pub struct LoadedProcess {
pub pid: ProcessId,
@@ -20,23 +18,11 @@ fn kern() -> &'static mut kernel::Kernel<crate::platform::RiscVPlatform> {
unsafe { &mut *crate::kernel_ptr() }
}
/// Scratch space for reading ELF files, allocated once from the boot heap.
fn elf_buffer() -> &'static mut [u8] {
static mut BUF: usize = 0;
// SAFETY: boot is single threaded; the buffer is kernel-only memory
// from the boot allocator and is never handed to a process.
unsafe {
if BUF == 0 {
BUF = mmu::allocator::alloc_zeroed_page();
for _ in 1..MAX_FILE_SIZE / PAGE_SIZE {
mmu::allocator::alloc_zeroed_page();
}
}
core::slice::from_raw_parts_mut(BUF as *mut u8, MAX_FILE_SIZE)
}
}
/// The two programs boot starts, packed into the kernel image.
pub static INIT_ELF: &[u8] = include_bytes!(env!("KOS_INIT_ELF"));
pub static STORAGE_ELF: &[u8] = include_bytes!(env!("KOS_STORAGE_ELF"));
pub fn load_init(uart: &Uart, blk: &mut VirtioBlk) -> LoadedProcess {
pub fn load_init(uart: &Uart) -> LoadedProcess {
let (pid, tid) = kern()
.boot(
types::bounded::Priority::DEFAULT,
@@ -44,7 +30,7 @@ pub fn load_init(uart: &Uart, blk: &mut VirtioBlk) -> LoadedProcess {
)
.unwrap_or_else(|_| crate::halt(uart, "boot failed"));
let entry = load_elf(uart, blk, pid, b"init.elf");
let entry = load_elf(uart, pid, INIT_ELF);
setup_thread(tid, entry);
uart.write_str("k-os: init loaded\n");
@@ -60,24 +46,18 @@ const STORAGE: Limits = Limits {
regions: 12,
};
pub fn load_server(
uart: &Uart,
blk: &mut VirtioBlk,
init: ProcessId,
filename: &[u8],
label: &str,
) -> LoadedProcess {
/// Storage, which init needs to read anything else, its budget carved
/// from init's.
pub fn load_storage(uart: &Uart, init: ProcessId) -> LoadedProcess {
let pid = kern()
.create_process_internal(init, STORAGE)
.unwrap_or_else(|| crate::halt(uart, "process create failed"));
let entry = load_elf(uart, blk, pid, filename);
let entry = load_elf(uart, pid, STORAGE_ELF);
let tid = kern()
.spawn_thread_internal(pid)
.unwrap_or_else(|| crate::halt(uart, "thread spawn failed"));
setup_thread(tid, entry);
uart.write_str("k-os: ");
uart.write_str(label);
uart.write_str(" loaded\n");
uart.write_str("k-os: storage loaded\n");
LoadedProcess { pid }
}
@@ -127,13 +107,10 @@ fn segment_perms(flags: elf::SegmentFlags) -> Option<PagePerms> {
/// Loads `filename` into `pid` through the kernel's own mapping API, so
/// every page is tracked, charged and checked like any other. Halts on any
/// malformed or overlapping image: boot servers are trusted to be sane.
fn load_elf(uart: &Uart, blk: &mut VirtioBlk, pid: ProcessId, filename: &[u8]) -> usize {
let buf = elf_buffer();
let file_size = boot_fs::read_file_from_disk(blk, filename, buf).unwrap_or(0);
if file_size == 0 {
crate::halt(uart, "ELF not found");
fn load_elf(uart: &Uart, pid: ProcessId, file: &[u8]) -> usize {
if file.is_empty() {
crate::halt(uart, "program missing from the kernel image (make build)");
}
let file = &buf[..file_size];
let elf_info = elf::parse(file).unwrap_or_else(|_| crate::halt(uart, "bad ELF"));
for segment in elf_info.segments() {