support for configuration files

This commit is contained in:
2025-10-01 18:25:49 -07:00
parent 17ca11f239
commit 3fdaad42ad
9 changed files with 176 additions and 8 deletions

108
Cargo.lock generated
View File

@@ -20,6 +20,28 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "hashbrown"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
[[package]]
name = "indexmap"
version = "2.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.28" version = "0.4.28"
@@ -64,10 +86,51 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_spanned"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee"
dependencies = [
"serde_core",
]
[[package]] [[package]]
name = "sprout" name = "sprout"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"serde",
"toml",
"uefi", "uefi",
] ]
@@ -82,6 +145,45 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "toml"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
dependencies = [
"indexmap",
"serde_core",
"serde_spanned",
"toml_datetime",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml_datetime"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_parser"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109"
[[package]] [[package]]
name = "ucs2" name = "ucs2"
version = "0.3.3" version = "0.3.3"
@@ -139,3 +241,9 @@ name = "unicode-ident"
version = "1.0.19" version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
name = "winnow"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"

View File

@@ -3,6 +3,13 @@ name = "sprout"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies]
toml = "0.9.7"
[dependencies.serde]
version = "1.0.228"
features = ["derive"]
[dependencies.uefi] [dependencies.uefi]
version = "0.35.0" version = "0.35.0"
features = ["alloc"] features = ["alloc"]

View File

@@ -6,6 +6,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
WORKDIR /work WORKDIR /work
COPY sprout.efi /work/${EFI_NAME}.EFI COPY sprout.efi /work/${EFI_NAME}.EFI
COPY sprout.toml /work/SPROUT.TOML
COPY kernel.efi /work/KERNEL.EFI COPY kernel.efi /work/KERNEL.EFI
RUN truncate -s256MiB sprout.img && \ RUN truncate -s256MiB sprout.img && \
parted --script sprout.img mklabel gpt > /dev/null 2>&1 && \ parted --script sprout.img mklabel gpt > /dev/null 2>&1 && \
@@ -16,6 +17,7 @@ RUN truncate -s256MiB sprout.img && \
mmd -i sprout.img ::/EFI/BOOT && \ mmd -i sprout.img ::/EFI/BOOT && \
mcopy -i sprout.img ${EFI_NAME}.EFI ::/EFI/BOOT/ && \ mcopy -i sprout.img ${EFI_NAME}.EFI ::/EFI/BOOT/ && \
mcopy -i sprout.img KERNEL.EFI ::/EFI/BOOT/ && \ mcopy -i sprout.img KERNEL.EFI ::/EFI/BOOT/ && \
mcopy -i sprout.img SPROUT.TOML ::/ && \
mv sprout.img /sprout.img mv sprout.img /sprout.img
FROM scratch AS final FROM scratch AS final

View File

@@ -40,6 +40,7 @@ if [ "${SKIP_KERNEL_BUILD}" != "1" ]; then
docker run --rm -i \ docker run --rm -i \
--mount="type=image,source=${DOCKER_PREFIX}/sprout-kernel-${TARGET_ARCH}:${DOCKER_TAG},target=/image" \ --mount="type=image,source=${DOCKER_PREFIX}/sprout-kernel-${TARGET_ARCH}:${DOCKER_TAG},target=/image" \
"${DOCKER_PREFIX}/sprout-utils-copy:${DOCKER_TAG}" cat /image/kernel.efi >"${FINAL_DIR}/kernel.efi" "${DOCKER_PREFIX}/sprout-utils-copy:${DOCKER_TAG}" cat /image/kernel.efi >"${FINAL_DIR}/kernel.efi"
cp hack/configs/kernel.sprout.toml "${FINAL_DIR}/sprout.toml"
fi fi
if [ "${SKIP_VM_BUILD}" != "1" ]; then if [ "${SKIP_VM_BUILD}" != "1" ]; then
@@ -61,6 +62,7 @@ if [ "${SKIP_SPROUT_BUILD}" != "1" ]; then
if [ -f "${FINAL_DIR}/kernel.efi" ]; then if [ -f "${FINAL_DIR}/kernel.efi" ]; then
cp "${FINAL_DIR}/kernel.efi" "${FINAL_DIR}/efi/EFI/BOOT/KERNEL.EFI" cp "${FINAL_DIR}/kernel.efi" "${FINAL_DIR}/efi/EFI/BOOT/KERNEL.EFI"
fi fi
cp "hack/configs/kernel.sprout.toml" "${FINAL_DIR}/efi/SPROUT.TOML"
fi fi
if [ "${SKIP_BOOT_BUILD}" != "1" ]; then if [ "${SKIP_BOOT_BUILD}" != "1" ]; then

View File

@@ -0,0 +1,2 @@
[[modules]]
chainloader = { path = "\\EFI\\BOOT\\KERNEL.EFI" }

33
src/config.rs Normal file
View File

@@ -0,0 +1,33 @@
use serde::{Deserialize, Serialize};
use uefi::cstr16;
use uefi::fs::{FileSystem, Path};
use uefi::proto::media::fs::SimpleFileSystem;
#[derive(Serialize, Deserialize, Default)]
pub struct RootConfiguration {
#[serde(default)]
pub modules: Vec<ModuleConfiguration>,
}
#[derive(Serialize, Deserialize, Default)]
pub struct ModuleConfiguration {
#[serde(default)]
pub chainloader: Option<ChainloaderConfiguration>,
}
#[derive(Serialize, Deserialize, Default)]
pub struct ChainloaderConfiguration {
pub path: String,
}
pub fn load() -> RootConfiguration {
let fs = uefi::boot::open_protocol_exclusive::<SimpleFileSystem>(
uefi::boot::get_handle_for_protocol::<SimpleFileSystem>().expect("no filesystem protocol"),
)
.expect("unable to open filesystem protocol");
let mut fs = FileSystem::new(fs);
let content = fs
.read(Path::new(cstr16!("sprout.toml")))
.expect("unable to read sprout.toml file");
toml::from_slice(&content).expect("unable to parse sprout.toml file")
}

View File

@@ -1,10 +1,11 @@
#![feature(uefi_std)] #![feature(uefi_std)]
pub mod chainload; pub mod config;
pub mod modules;
pub mod setup; pub mod setup;
const CHAINLOADER_TARGET: &str = "\\EFI\\BOOT\\KERNEL.efi";
fn main() { fn main() {
setup::init(); setup::init();
chainload::chainload(CHAINLOADER_TARGET);
let config = config::load();
modules::execute(config.modules);
} }

13
src/modules.rs Normal file
View File

@@ -0,0 +1,13 @@
use crate::config::ModuleConfiguration;
pub mod chainloader;
pub fn execute(modules: Vec<ModuleConfiguration>) {
for module in modules {
if let Some(chainloader) = module.chainloader {
chainloader::chainloader(chainloader);
} else {
panic!("unknown module configuration");
}
}
}

View File

@@ -1,3 +1,4 @@
use crate::config::ChainloaderConfiguration;
use uefi::{ use uefi::{
CString16, CString16,
proto::device_path::{ proto::device_path::{
@@ -19,7 +20,7 @@ fn text_to_device_path(path: &str) -> PoolDevicePath {
.expect("unable to convert text to device path") .expect("unable to convert text to device path")
} }
pub fn chainload(path: &str) { pub fn chainloader(configuration: ChainloaderConfiguration) {
let sprout_image = uefi::boot::image_handle(); let sprout_image = uefi::boot::image_handle();
let image_device_path_protocol = let image_device_path_protocol =
uefi::boot::open_protocol_exclusive::<LoadedImageDevicePath>(sprout_image) uefi::boot::open_protocol_exclusive::<LoadedImageDevicePath>(sprout_image)
@@ -42,9 +43,9 @@ pub fn chainload(path: &str) {
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("/"); .join("/");
full_path.push('/'); full_path.push('/');
full_path.push_str(path); full_path.push_str(&configuration.path);
println!("chainload: {}", full_path); println!("chainloader: path={}", full_path);
let device_path = text_to_device_path(&full_path); let device_path = text_to_device_path(&full_path);
@@ -57,5 +58,4 @@ pub fn chainload(path: &str) {
) )
.expect("failed to load image"); .expect("failed to load image");
uefi::boot::start_image(image).expect("failed to start image"); uefi::boot::start_image(image).expect("failed to start image");
panic!("chainloaded image exited");
} }