diff --git a/src/actions.rs b/src/actions.rs index 71f4477..b13ebb3 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -1,4 +1,5 @@ use crate::context::Context; +use serde::{Deserialize, Serialize}; use std::rc::Rc; pub mod chainload; @@ -7,6 +8,17 @@ pub mod print; #[cfg(feature = "splash")] pub mod splash; +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct ActionDeclaration { + #[serde(default)] + pub chainload: Option, + #[serde(default)] + pub print: Option, + #[serde(default)] + #[cfg(feature = "splash")] + pub splash: Option, +} + pub fn execute(context: Rc, name: impl AsRef) { let Some(action) = context.root().actions().get(name.as_ref()) else { panic!("unknown action: {}", name.as_ref()); diff --git a/src/actions/chainload.rs b/src/actions/chainload.rs index c96ce6e..cba5a06 100644 --- a/src/actions/chainload.rs +++ b/src/actions/chainload.rs @@ -1,12 +1,19 @@ -use crate::config::ChainloadConfiguration; use crate::context::Context; use crate::utils; use log::info; +use serde::{Deserialize, Serialize}; use std::rc::Rc; use uefi::CString16; use uefi::proto::device_path::LoadedImageDevicePath; use uefi::proto::loaded_image::LoadedImage; +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct ChainloadConfiguration { + pub path: String, + #[serde(default)] + pub options: Vec, +} + pub fn chainload(context: Rc, configuration: &ChainloadConfiguration) { let sprout_image = uefi::boot::image_handle(); let image_device_path_protocol = diff --git a/src/actions/print.rs b/src/actions/print.rs index 719a1e9..8259808 100644 --- a/src/actions/print.rs +++ b/src/actions/print.rs @@ -1,7 +1,13 @@ -use crate::config::PrintConfiguration; use crate::context::Context; +use serde::{Deserialize, Serialize}; use std::rc::Rc; +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct PrintConfiguration { + #[serde(default)] + pub text: String, +} + pub fn print(context: Rc, configuration: &PrintConfiguration) { println!("{}", context.stamp(&configuration.text)); } diff --git a/src/actions/splash.rs b/src/actions/splash.rs index 112055c..c61c697 100644 --- a/src/actions/splash.rs +++ b/src/actions/splash.rs @@ -1,43 +1,25 @@ -use crate::config::SplashConfiguration; use crate::context::Context; +use crate::utils::framebuffer::Framebuffer; use crate::utils::read_file_contents; use image::imageops::{FilterType, resize}; use image::math::Rect; use image::{DynamicImage, ImageBuffer, ImageFormat, ImageReader, Rgba}; +use serde::{Deserialize, Serialize}; use std::io::Cursor; use std::rc::Rc; use std::time::Duration; use uefi::boot::ScopedProtocol; -use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput}; +use uefi::proto::console::gop::GraphicsOutput; -struct Framebuffer { - width: usize, - height: usize, - pixels: Vec, +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct SplashConfiguration { + pub image: String, + #[serde(default = "default_splash_time")] + pub time: u32, } -impl Framebuffer { - fn new(width: usize, height: usize) -> Self { - Framebuffer { - width, - height, - pixels: vec![BltPixel::new(0, 0, 0); width * height], - } - } - - fn pixel(&mut self, x: usize, y: usize) -> Option<&mut BltPixel> { - self.pixels.get_mut(y * self.width + x) - } - - fn blit(&self, gop: &mut GraphicsOutput) { - gop.blt(BltOp::BufferToVideo { - buffer: &self.pixels, - src: BltRegion::Full, - dest: (0, 0), - dims: (self.width, self.height), - }) - .expect("failed to blit framebuffer"); - } +pub fn default_splash_time() -> u32 { + 5 } fn setup_graphics() -> ScopedProtocol { diff --git a/src/config.rs b/src/config.rs index e7357e2..9f26b65 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,5 @@ +use crate::actions::ActionDeclaration; +use crate::generators::GeneratorDeclaration; use crate::utils; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -18,17 +20,6 @@ pub struct RootConfiguration { pub phases: PhasesConfiguration, } -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct ActionDeclaration { - #[serde(default)] - pub chainload: Option, - #[serde(default)] - pub print: Option, - #[serde(default)] - #[cfg(feature = "splash")] - pub splash: Option, -} - #[derive(Serialize, Deserialize, Default, Clone)] pub struct EntryDeclaration { pub title: String, @@ -38,12 +29,6 @@ pub struct EntryDeclaration { pub values: BTreeMap, } -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct GeneratorDeclaration { - #[serde(default)] - pub matrix: Option, -} - #[derive(Serialize, Deserialize, Default, Clone)] pub struct PhasesConfiguration { #[serde(default)] @@ -58,40 +43,6 @@ pub struct PhaseConfiguration { pub values: BTreeMap, } -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct MatrixConfiguration { - #[serde(default)] - pub entry: EntryDeclaration, - #[serde(default)] - pub values: BTreeMap>, -} - -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct ChainloadConfiguration { - pub path: String, - #[serde(default)] - pub options: Vec, -} - -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct PrintConfiguration { - #[serde(default)] - pub text: String, -} - -#[cfg(feature = "splash")] -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct SplashConfiguration { - pub image: String, - #[serde(default = "default_splash_time")] - pub time: u32, -} - -#[cfg(feature = "splash")] -pub fn default_splash_time() -> u32 { - 5 -} - pub fn load() -> RootConfiguration { let content = utils::read_file_contents("sprout.toml"); toml::from_slice(&content).expect("unable to parse sprout.toml file") diff --git a/src/context.rs b/src/context.rs index cad804d..ded6c63 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,11 +1,10 @@ -use crate::config::{ActionDeclaration, EntryDeclaration}; +use crate::actions::ActionDeclaration; use std::collections::{BTreeMap, BTreeSet}; use std::rc::Rc; #[derive(Default)] pub struct RootContext { actions: BTreeMap, - entries: BTreeMap, EntryDeclaration)>, } impl RootContext { @@ -20,14 +19,6 @@ impl RootContext { pub fn actions_mut(&mut self) -> &mut BTreeMap { &mut self.actions } - - pub fn entries(&self) -> &BTreeMap, EntryDeclaration)> { - &self.entries - } - - pub fn entries_mut(&mut self) -> &mut BTreeMap, EntryDeclaration)> { - &mut self.entries - } } pub struct Context { diff --git a/src/generators.rs b/src/generators.rs index 5858122..4e7c300 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1,9 +1,17 @@ -use crate::config::{EntryDeclaration, GeneratorDeclaration}; +use crate::config::EntryDeclaration; use crate::context::Context; +use crate::generators::matrix::MatrixConfiguration; +use serde::{Deserialize, Serialize}; use std::rc::Rc; pub mod matrix; +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct GeneratorDeclaration { + #[serde(default)] + pub matrix: Option, +} + pub fn generate( context: Rc, generator: &GeneratorDeclaration, diff --git a/src/generators/matrix.rs b/src/generators/matrix.rs index 08c4224..cf5cace 100644 --- a/src/generators/matrix.rs +++ b/src/generators/matrix.rs @@ -1,8 +1,17 @@ -use crate::config::{EntryDeclaration, MatrixConfiguration}; +use crate::config::EntryDeclaration; use crate::context::Context; +use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::rc::Rc; +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct MatrixConfiguration { + #[serde(default)] + pub entry: EntryDeclaration, + #[serde(default)] + pub values: BTreeMap>, +} + fn build_matrix(input: &BTreeMap>) -> Vec> { let items: Vec<(String, Vec)> = input.clone().into_iter().collect(); let mut result: Vec> = vec![BTreeMap::new()]; diff --git a/src/utils.rs b/src/utils.rs index 2a04f06..9037654 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -4,6 +4,8 @@ use uefi::proto::device_path::text::{AllowShortcuts, DevicePathFromText, Display use uefi::proto::device_path::{DevicePath, PoolDevicePath}; use uefi::proto::media::fs::SimpleFileSystem; +pub mod framebuffer; + pub fn text_to_device_path(path: &str) -> PoolDevicePath { let path = CString16::try_from(path).expect("unable to convert path to CString16"); let device_path_from_text = uefi::boot::open_protocol_exclusive::( diff --git a/src/utils/framebuffer.rs b/src/utils/framebuffer.rs new file mode 100644 index 0000000..c65132f --- /dev/null +++ b/src/utils/framebuffer.rs @@ -0,0 +1,31 @@ +use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput}; + +pub struct Framebuffer { + width: usize, + height: usize, + pixels: Vec, +} + +impl Framebuffer { + pub fn new(width: usize, height: usize) -> Self { + Framebuffer { + width, + height, + pixels: vec![BltPixel::new(0, 0, 0); width * height], + } + } + + pub fn pixel(&mut self, x: usize, y: usize) -> Option<&mut BltPixel> { + self.pixels.get_mut(y * self.width + x) + } + + pub fn blit(&self, gop: &mut GraphicsOutput) { + gop.blt(BltOp::BufferToVideo { + buffer: &self.pixels, + src: BltRegion::Full, + dest: (0, 0), + dims: (self.width, self.height), + }) + .expect("failed to blit framebuffer"); + } +}