diff --git a/Cargo.lock b/Cargo.lock index 2e0cc92..ac36aac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "anyhow" version = "1.0.100" @@ -25,12 +19,6 @@ dependencies = [ "syn", ] -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - [[package]] name = "bit_field" version = "0.10.3" @@ -52,18 +40,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bytemuck" -version = "1.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" - -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - [[package]] name = "bytes" version = "1.10.1" @@ -85,15 +61,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -120,7 +87,6 @@ version = "0.0.17" dependencies = [ "anyhow", "bitflags", - "image", "log", "serde", "sha256", @@ -135,25 +101,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "flate2" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - [[package]] name = "generic-array" version = "0.14.9" @@ -176,19 +123,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "image" -version = "0.25.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png", -] - [[package]] name = "indexmap" version = "2.12.0" @@ -211,47 +145,6 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "moxcms" -version = "0.7.6" -source = "git+https://github.com/edera-dev/sprout-patched-deps.git?rev=2c4fcc84b50d40c28f540d4271109ea0ca7e1268#2c4fcc84b50d40c28f540d4271109ea0ca7e1268" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "png" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" -dependencies = [ - "bitflags", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "proc-macro2" version = "1.0.103" @@ -281,15 +174,6 @@ dependencies = [ "syn", ] -[[package]] -name = "pxfm" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" -dependencies = [ - "num-traits", -] - [[package]] name = "quote" version = "1.0.41" @@ -361,11 +245,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "git+https://github.com/edera-dev/sprout-patched-deps.git?rev=2c4fcc84b50d40c28f540d4271109ea0ca7e1268#2c4fcc84b50d40c28f540d4271109ea0ca7e1268" - [[package]] name = "syn" version = "2.0.108" @@ -476,9 +355,9 @@ checksum = "0c8352f8c05e47892e7eaf13b34abd76a7f4aeaf817b716e88789381927f199c" [[package]] name = "unicode-ident" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "version_check" diff --git a/Cargo.toml b/Cargo.toml index 904fed3..266ce71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,42 +1,8 @@ -[package] -name = "edera-sprout" -description = "Modern UEFI bootloader" -license = "Apache-2.0" -version = "0.0.17" -homepage = "https://sprout.edera.dev" -repository = "https://github.com/edera-dev/sprout" -edition = "2024" - -[dependencies] -anyhow = "1.0.100" -bitflags = "2.10.0" -toml = "0.9.8" -log = "0.4.28" - -[dependencies.image] -version = "0.25.8" -default-features = false -features = ["png"] -optional = true - -[dependencies.serde] -version = "1.0.228" -features = ["derive"] - -[dependencies.sha256] -version = "1.6.0" -default-features = false - -[dependencies.uefi] -version = "0.36.0" -features = ["alloc", "logger"] - -[dependencies.uefi-raw] -version = "0.12.0" - -[features] -default = ["splash"] -splash = ["dep:image"] +[workspace] +members = [ + "crates/sprout", +] +resolver = "3" [profile.dev] # We have to compile for opt-level = 2 due to optimization passes @@ -57,15 +23,3 @@ inherits = "dev" strip = "debuginfo" debug = 0 opt-level = 2 - -[patch.crates-io.simd-adler32] -git = "https://github.com/edera-dev/sprout-patched-deps.git" -rev = "2c4fcc84b50d40c28f540d4271109ea0ca7e1268" - -[patch.crates-io.moxcms] -git = "https://github.com/edera-dev/sprout-patched-deps.git" -rev = "2c4fcc84b50d40c28f540d4271109ea0ca7e1268" - -[[bin]] -name = "sprout" -path = "src/main.rs" diff --git a/crates/sprout/Cargo.toml b/crates/sprout/Cargo.toml new file mode 100644 index 0000000..fe6fbe9 --- /dev/null +++ b/crates/sprout/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "edera-sprout" +description = "Modern UEFI bootloader" +license = "Apache-2.0" +version = "0.0.17" +homepage = "https://sprout.edera.dev" +repository = "https://github.com/edera-dev/sprout" +edition = "2024" + +[dependencies] +anyhow = "1.0.100" +bitflags = "2.10.0" +toml = "0.9.8" +log = "0.4.28" + +[dependencies.serde] +version = "1.0.228" +features = ["derive"] + +[dependencies.sha256] +version = "1.6.0" +default-features = false + +[dependencies.uefi] +version = "0.36.0" +features = ["alloc", "logger"] + +[dependencies.uefi-raw] +version = "0.12.0" + +[[bin]] +name = "sprout" +path = "src/main.rs" diff --git a/crates/sprout/README.md b/crates/sprout/README.md new file mode 100644 index 0000000..817df6a --- /dev/null +++ b/crates/sprout/README.md @@ -0,0 +1,3 @@ +# Sprout Bootloader + +The main bootable crate of the Sprout bootloader. diff --git a/build.rs b/crates/sprout/build.rs similarity index 100% rename from build.rs rename to crates/sprout/build.rs diff --git a/src/actions.rs b/crates/sprout/src/actions.rs similarity index 86% rename from src/actions.rs rename to crates/sprout/src/actions.rs index e20c951..af7740a 100644 --- a/src/actions.rs +++ b/crates/sprout/src/actions.rs @@ -10,10 +10,6 @@ pub mod edera; /// EFI console print action. pub mod print; -/// Splash screen action. -#[cfg(feature = "splash")] -pub mod splash; - /// Declares an action that sprout can execute. /// Actions allow configuring sprout's internal runtime mechanisms with values /// that you can specify via other concepts. @@ -29,10 +25,6 @@ pub struct ActionDeclaration { /// Print a string to the EFI console. #[serde(default)] pub print: Option, - /// Show an image as a fullscreen splash screen. - #[serde(default)] - #[cfg(feature = "splash")] - pub splash: Option, /// Boot the Edera hypervisor and the root operating system. /// This action is an extension on top of the Xen EFI stub that /// is specific to Edera. @@ -67,12 +59,6 @@ pub fn execute(context: Rc, name: impl AsRef) -> Result<()> return Ok(()); } - #[cfg(feature = "splash")] - if let Some(splash) = &action.splash { - splash::splash(context.clone(), splash)?; - return Ok(()); - } - // If we reach here, we don't know how to execute the action that was configured. // This is likely unreachable, but we should still return an error just in case. bail!("unknown action configuration"); diff --git a/src/actions/chainload.rs b/crates/sprout/src/actions/chainload.rs similarity index 100% rename from src/actions/chainload.rs rename to crates/sprout/src/actions/chainload.rs diff --git a/src/actions/edera.rs b/crates/sprout/src/actions/edera.rs similarity index 100% rename from src/actions/edera.rs rename to crates/sprout/src/actions/edera.rs diff --git a/src/actions/print.rs b/crates/sprout/src/actions/print.rs similarity index 100% rename from src/actions/print.rs rename to crates/sprout/src/actions/print.rs diff --git a/src/autoconfigure.rs b/crates/sprout/src/autoconfigure.rs similarity index 100% rename from src/autoconfigure.rs rename to crates/sprout/src/autoconfigure.rs diff --git a/src/autoconfigure/bls.rs b/crates/sprout/src/autoconfigure/bls.rs similarity index 100% rename from src/autoconfigure/bls.rs rename to crates/sprout/src/autoconfigure/bls.rs diff --git a/src/autoconfigure/linux.rs b/crates/sprout/src/autoconfigure/linux.rs similarity index 100% rename from src/autoconfigure/linux.rs rename to crates/sprout/src/autoconfigure/linux.rs diff --git a/src/autoconfigure/windows.rs b/crates/sprout/src/autoconfigure/windows.rs similarity index 100% rename from src/autoconfigure/windows.rs rename to crates/sprout/src/autoconfigure/windows.rs diff --git a/src/config.rs b/crates/sprout/src/config.rs similarity index 100% rename from src/config.rs rename to crates/sprout/src/config.rs diff --git a/src/config/loader.rs b/crates/sprout/src/config/loader.rs similarity index 100% rename from src/config/loader.rs rename to crates/sprout/src/config/loader.rs diff --git a/src/context.rs b/crates/sprout/src/context.rs similarity index 100% rename from src/context.rs rename to crates/sprout/src/context.rs diff --git a/src/drivers.rs b/crates/sprout/src/drivers.rs similarity index 100% rename from src/drivers.rs rename to crates/sprout/src/drivers.rs diff --git a/src/entries.rs b/crates/sprout/src/entries.rs similarity index 100% rename from src/entries.rs rename to crates/sprout/src/entries.rs diff --git a/src/extractors.rs b/crates/sprout/src/extractors.rs similarity index 100% rename from src/extractors.rs rename to crates/sprout/src/extractors.rs diff --git a/src/extractors/filesystem_device_match.rs b/crates/sprout/src/extractors/filesystem_device_match.rs similarity index 100% rename from src/extractors/filesystem_device_match.rs rename to crates/sprout/src/extractors/filesystem_device_match.rs diff --git a/src/generators.rs b/crates/sprout/src/generators.rs similarity index 100% rename from src/generators.rs rename to crates/sprout/src/generators.rs diff --git a/src/generators/bls.rs b/crates/sprout/src/generators/bls.rs similarity index 100% rename from src/generators/bls.rs rename to crates/sprout/src/generators/bls.rs diff --git a/src/generators/bls/entry.rs b/crates/sprout/src/generators/bls/entry.rs similarity index 100% rename from src/generators/bls/entry.rs rename to crates/sprout/src/generators/bls/entry.rs diff --git a/src/generators/list.rs b/crates/sprout/src/generators/list.rs similarity index 100% rename from src/generators/list.rs rename to crates/sprout/src/generators/list.rs diff --git a/src/generators/matrix.rs b/crates/sprout/src/generators/matrix.rs similarity index 100% rename from src/generators/matrix.rs rename to crates/sprout/src/generators/matrix.rs diff --git a/src/integrations.rs b/crates/sprout/src/integrations.rs similarity index 100% rename from src/integrations.rs rename to crates/sprout/src/integrations.rs diff --git a/src/integrations/bootloader_interface.rs b/crates/sprout/src/integrations/bootloader_interface.rs similarity index 100% rename from src/integrations/bootloader_interface.rs rename to crates/sprout/src/integrations/bootloader_interface.rs diff --git a/src/integrations/bootloader_interface/bitflags.rs b/crates/sprout/src/integrations/bootloader_interface/bitflags.rs similarity index 100% rename from src/integrations/bootloader_interface/bitflags.rs rename to crates/sprout/src/integrations/bootloader_interface/bitflags.rs diff --git a/src/integrations/shim.rs b/crates/sprout/src/integrations/shim.rs similarity index 100% rename from src/integrations/shim.rs rename to crates/sprout/src/integrations/shim.rs diff --git a/src/integrations/shim/hook.rs b/crates/sprout/src/integrations/shim/hook.rs similarity index 100% rename from src/integrations/shim/hook.rs rename to crates/sprout/src/integrations/shim/hook.rs diff --git a/src/main.rs b/crates/sprout/src/main.rs similarity index 100% rename from src/main.rs rename to crates/sprout/src/main.rs diff --git a/src/menu.rs b/crates/sprout/src/menu.rs similarity index 100% rename from src/menu.rs rename to crates/sprout/src/menu.rs diff --git a/src/options.rs b/crates/sprout/src/options.rs similarity index 100% rename from src/options.rs rename to crates/sprout/src/options.rs diff --git a/src/options/parser.rs b/crates/sprout/src/options/parser.rs similarity index 100% rename from src/options/parser.rs rename to crates/sprout/src/options/parser.rs diff --git a/src/phases.rs b/crates/sprout/src/phases.rs similarity index 100% rename from src/phases.rs rename to crates/sprout/src/phases.rs diff --git a/src/platform.rs b/crates/sprout/src/platform.rs similarity index 100% rename from src/platform.rs rename to crates/sprout/src/platform.rs diff --git a/src/platform/timer.rs b/crates/sprout/src/platform/timer.rs similarity index 100% rename from src/platform/timer.rs rename to crates/sprout/src/platform/timer.rs diff --git a/src/platform/timer/aarch64.rs b/crates/sprout/src/platform/timer/aarch64.rs similarity index 100% rename from src/platform/timer/aarch64.rs rename to crates/sprout/src/platform/timer/aarch64.rs diff --git a/src/platform/timer/x86_64.rs b/crates/sprout/src/platform/timer/x86_64.rs similarity index 100% rename from src/platform/timer/x86_64.rs rename to crates/sprout/src/platform/timer/x86_64.rs diff --git a/src/platform/tpm.rs b/crates/sprout/src/platform/tpm.rs similarity index 100% rename from src/platform/tpm.rs rename to crates/sprout/src/platform/tpm.rs diff --git a/src/sbat.rs b/crates/sprout/src/sbat.rs similarity index 100% rename from src/sbat.rs rename to crates/sprout/src/sbat.rs diff --git a/src/sbat.template.csv b/crates/sprout/src/sbat.template.csv similarity index 100% rename from src/sbat.template.csv rename to crates/sprout/src/sbat.template.csv diff --git a/src/secure.rs b/crates/sprout/src/secure.rs similarity index 100% rename from src/secure.rs rename to crates/sprout/src/secure.rs diff --git a/src/setup.rs b/crates/sprout/src/setup.rs similarity index 100% rename from src/setup.rs rename to crates/sprout/src/setup.rs diff --git a/src/utils.rs b/crates/sprout/src/utils.rs similarity index 100% rename from src/utils.rs rename to crates/sprout/src/utils.rs diff --git a/src/utils/framebuffer.rs b/crates/sprout/src/utils/framebuffer.rs similarity index 100% rename from src/utils/framebuffer.rs rename to crates/sprout/src/utils/framebuffer.rs diff --git a/src/utils/media_loader.rs b/crates/sprout/src/utils/media_loader.rs similarity index 100% rename from src/utils/media_loader.rs rename to crates/sprout/src/utils/media_loader.rs diff --git a/src/utils/media_loader/constants.rs b/crates/sprout/src/utils/media_loader/constants.rs similarity index 100% rename from src/utils/media_loader/constants.rs rename to crates/sprout/src/utils/media_loader/constants.rs diff --git a/src/utils/variables.rs b/crates/sprout/src/utils/variables.rs similarity index 100% rename from src/utils/variables.rs rename to crates/sprout/src/utils/variables.rs diff --git a/src/utils/vercmp.rs b/crates/sprout/src/utils/vercmp.rs similarity index 100% rename from src/utils/vercmp.rs rename to crates/sprout/src/utils/vercmp.rs diff --git a/hack/dev/assets/edera-splash.png b/hack/dev/assets/edera-splash.png deleted file mode 100644 index 2919b9d..0000000 Binary files a/hack/dev/assets/edera-splash.png and /dev/null differ diff --git a/src/actions/splash.rs b/src/actions/splash.rs deleted file mode 100644 index 4fbd8c7..0000000 --- a/src/actions/splash.rs +++ /dev/null @@ -1,166 +0,0 @@ -use crate::context::SproutContext; -use crate::utils::framebuffer::Framebuffer; -use crate::utils::read_file_contents; -use anyhow::{Context, Result, bail}; -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::GraphicsOutput; - -/// We set the default splash time to zero, as this makes it so any logging shows up -/// on top of the splash and does not hold up the boot process. -const DEFAULT_SPLASH_TIME: u32 = 0; - -/// The configuration of the splash action. -#[derive(Serialize, Deserialize, Debug, Default, Clone)] -pub struct SplashConfiguration { - /// The path to the image to display. - /// Currently, only PNG images are supported. - pub image: String, - /// The time to display the splash image without interruption, in seconds. - /// The default value is `0` which will display the image and let everything - /// continue. - #[serde(default = "default_splash_time")] - pub time: u32, -} - -fn default_splash_time() -> u32 { - DEFAULT_SPLASH_TIME -} - -/// Acquire the [GraphicsOutput]. We will find the first graphics output only. -fn setup_graphics() -> Result> { - // Grab the handle for the graphics output protocol. - let gop_handle = uefi::boot::get_handle_for_protocol::() - .context("unable to get graphics output")?; - // Open the graphics output protocol exclusively. - uefi::boot::open_protocol_exclusive::(gop_handle) - .context("unable to open graphics output") -} - -/// Produces a [Rect] that fits the `image` inside the specified `frame`. -/// The output [Rect] should be used to resize the image. -fn fit_to_frame(image: &DynamicImage, frame: Rect) -> Rect { - // Convert the image dimensions to a [Rect]. - let input = Rect { - x: 0, - y: 0, - width: image.width(), - height: image.height(), - }; - - // Handle the case where the image is zero-sized. - if input.height == 0 || input.width == 0 { - return input; - } - - // Calculate the ratio of the image dimensions. - let input_ratio = input.width as f32 / input.height as f32; - - // Calculate the ratio of the frame dimensions. - let frame_ratio = frame.width as f32 / frame.height as f32; - - // Create [Rect] to store the output dimensions. - let mut output = Rect { - x: 0, - y: 0, - width: frame.width, - height: frame.height, - }; - - // Handle the case where the output is zero-sized. - if output.height == 0 || output.width == 0 { - return output; - } - - if input_ratio < frame_ratio { - output.width = (frame.height as f32 * input_ratio).floor() as u32; - output.height = frame.height; - output.x = frame.x + (frame.width - output.width) / 2; - output.y = frame.y; - } else { - output.width = frame.width; - output.height = (frame.width as f32 / input_ratio).floor() as u32; - output.x = frame.x; - output.y = frame.y + (frame.height - output.height) / 2; - } - - output -} - -/// Resize the input `image` to fit the `frame`. -fn resize_to_fit(image: &DynamicImage, frame: Rect) -> ImageBuffer, Vec> { - let image = image.to_rgba8(); - resize(&image, frame.width, frame.height, FilterType::Lanczos3) -} - -/// Draw the `image` on the screen using [GraphicsOutput]. -fn draw(image: DynamicImage) -> Result<()> { - // Acquire the [GraphicsOutput] protocol. - let mut gop = setup_graphics()?; - - // Acquire the current screen size. - let (width, height) = gop.current_mode_info().resolution(); - - // Create a display frame. - let display_frame = Rect { - x: 0, - y: 0, - width: width as _, - height: height as _, - }; - - // Fit the image to the display frame. - let fit = fit_to_frame(&image, display_frame); - - // If the image is zero-sized, then we should bail with an error. - if fit.width == 0 || fit.height == 0 { - bail!("calculated frame size is zero"); - } - - // Resize the image to fit the display frame. - let image = resize_to_fit(&image, fit); - - // Create a framebuffer to draw the image on. - let mut framebuffer = - Framebuffer::new(width, height).context("unable to create framebuffer")?; - - // Iterate over the pixels in the image and put them on the framebuffer. - for (x, y, pixel) in image.enumerate_pixels() { - let Some(fb) = framebuffer.pixel((x + fit.x) as usize, (fit.y + y) as usize) else { - continue; - }; - fb.red = pixel[0]; - fb.green = pixel[1]; - fb.blue = pixel[2]; - } - - // Blit the framebuffer to the screen. - framebuffer.blit(&mut gop)?; - Ok(()) -} - -/// Runs the splash action with the specified `configuration` inside the provided `context`. -pub fn splash(context: Rc, configuration: &SplashConfiguration) -> Result<()> { - // Stamp the image path value. - let image = context.stamp(&configuration.image); - // Read the image contents. - let image = read_file_contents(Some(context.root().loaded_image_path()?), &image)?; - // Decode the image as a PNG. - let image = ImageReader::with_format(Cursor::new(image), ImageFormat::Png) - .decode() - .context("unable to decode splash image")?; - // Draw the image on the screen. - draw(image)?; - - // Sleep for the specified time. - std::thread::sleep(Duration::from_secs(configuration.time as u64)); - - // Return control to sprout. - Ok(()) -}