mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-19 17:10:17 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
029e59b209
|
|||
| bde1cd01c8 | |||
|
0017d7874d
|
|||
|
1c2acdc568
|
|||
|
1f322ff4bf
|
|||
|
0bb7d7ccb1
|
|||
|
74b6a8deb3
|
|||
|
3e5d54913c
|
|||
|
b616e75e96
|
|||
|
069f858e95
|
17
.github/workflows/publish.yml
vendored
17
.github/workflows/publish.yml
vendored
@@ -27,6 +27,8 @@ jobs:
|
|||||||
name: artifacts
|
name: artifacts
|
||||||
permissions:
|
permissions:
|
||||||
contents: write # Needed to upload artifacts.
|
contents: write # Needed to upload artifacts.
|
||||||
|
id-token: write # Needed for attestation.
|
||||||
|
attestations: write # Needed for attestations.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: harden runner
|
- name: harden runner
|
||||||
@@ -46,14 +48,15 @@ jobs:
|
|||||||
- name: 'assemble artifacts'
|
- name: 'assemble artifacts'
|
||||||
run: ./hack/assemble.sh
|
run: ./hack/assemble.sh
|
||||||
|
|
||||||
- name: 'upload sprout-x86_64.efi artifact'
|
- name: 'upload artifacts'
|
||||||
|
id: upload
|
||||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: sprout-x86_64.efi
|
name: artifacts
|
||||||
path: target/assemble/sprout-x86_64.efi
|
path: target/assemble/*
|
||||||
|
|
||||||
- name: 'upload sprout-aarch64.efi artifact'
|
- name: 'attest artifacts'
|
||||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
|
||||||
with:
|
with:
|
||||||
name: sprout-aarch64.efi
|
subject-name: artifacts.zip
|
||||||
path: target/assemble/sprout-aarch64.efi
|
subject-digest: "sha256:${{ steps.upload.outputs.artifact-digest }}"
|
||||||
|
|||||||
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@@ -20,6 +20,8 @@ jobs:
|
|||||||
name: release
|
name: release
|
||||||
permissions:
|
permissions:
|
||||||
contents: write # Needed to upload release assets.
|
contents: write # Needed to upload release assets.
|
||||||
|
id-token: write # Needed for attestation.
|
||||||
|
attestations: write # Needed for attestations.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: harden runner
|
- name: harden runner
|
||||||
@@ -36,9 +38,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cargo version
|
cargo version
|
||||||
|
|
||||||
- name: 'assemble artifacts'
|
- name: 'assemble release artifacts'
|
||||||
run: ./hack/assemble.sh
|
run: ./hack/assemble.sh
|
||||||
|
|
||||||
|
- name: 'attest release artifacts'
|
||||||
|
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0
|
||||||
|
with:
|
||||||
|
subject-path: target/assemble/*
|
||||||
|
|
||||||
- name: 'generate cultivator token'
|
- name: 'generate cultivator token'
|
||||||
uses: actions/create-github-app-token@bf559f85448f9380bcfa2899dbdc01eb5b37be3a # v3.0.0-beta.2
|
uses: actions/create-github-app-token@bf559f85448f9380bcfa2899dbdc01eb5b37be3a # v3.0.0-beta.2
|
||||||
id: generate-token
|
id: generate-token
|
||||||
|
|||||||
66
Cargo.lock
generated
66
Cargo.lock
generated
@@ -66,7 +66,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "edera-sprout"
|
name = "edera-sprout"
|
||||||
version = "0.0.18"
|
version = "0.0.21"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
@@ -74,6 +74,8 @@ dependencies = [
|
|||||||
"hex",
|
"hex",
|
||||||
"log",
|
"log",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
"shlex",
|
||||||
|
"spin",
|
||||||
"toml",
|
"toml",
|
||||||
"uefi",
|
"uefi",
|
||||||
"uefi-raw",
|
"uefi-raw",
|
||||||
@@ -81,17 +83,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "edera-sprout-config"
|
name = "edera-sprout-config"
|
||||||
version = "0.0.18"
|
version = "0.0.21"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "equivalent"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.9"
|
version = "0.14.9"
|
||||||
@@ -102,34 +98,27 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hex"
|
name = "hex"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indexmap"
|
|
||||||
version = "2.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
|
|
||||||
dependencies = [
|
|
||||||
"equivalent",
|
|
||||||
"hashbrown",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.177"
|
version = "0.2.177"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.28"
|
version = "0.4.28"
|
||||||
@@ -174,6 +163,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
@@ -224,6 +219,21 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.108"
|
version = "2.0.108"
|
||||||
@@ -241,12 +251,10 @@ version = "0.9.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8"
|
checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
|
||||||
"serde_core",
|
"serde_core",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"toml_parser",
|
"toml_parser",
|
||||||
"toml_writer",
|
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -268,12 +276,6 @@ dependencies = [
|
|||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_writer"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
|
|||||||
35
Cargo.toml
35
Cargo.toml
@@ -7,22 +7,45 @@ resolver = "3"
|
|||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
version = "0.0.18"
|
version = "0.0.21"
|
||||||
homepage = "https://sprout.edera.dev"
|
homepage = "https://sprout.edera.dev"
|
||||||
repository = "https://github.com/edera-dev/sprout"
|
repository = "https://github.com/edera-dev/sprout"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.100"
|
|
||||||
bitflags = "2.10.0"
|
bitflags = "2.10.0"
|
||||||
hex = "0.4.3"
|
|
||||||
log = "0.4.28"
|
log = "0.4.28"
|
||||||
serde = "1.0.228"
|
spin = "0.10.0"
|
||||||
sha2 = "0.10.9"
|
|
||||||
toml = "0.9.8"
|
|
||||||
uefi = "0.36.0"
|
uefi = "0.36.0"
|
||||||
uefi-raw = "0.12.0"
|
uefi-raw = "0.12.0"
|
||||||
|
|
||||||
|
[workspace.dependencies.anyhow]
|
||||||
|
version = "1.0.100"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[workspace.dependencies.hex]
|
||||||
|
version = "0.4.3"
|
||||||
|
default-features = false
|
||||||
|
features = ["alloc"]
|
||||||
|
|
||||||
|
[workspace.dependencies.serde]
|
||||||
|
version = "1.0.228"
|
||||||
|
default-features = false
|
||||||
|
features = ["alloc", "derive"]
|
||||||
|
|
||||||
|
[workspace.dependencies.sha2]
|
||||||
|
version = "0.10.9"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[workspace.dependencies.shlex]
|
||||||
|
version = "1.3.0"
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[workspace.dependencies.toml]
|
||||||
|
version = "0.9.8"
|
||||||
|
default-features = false
|
||||||
|
features = ["serde", "parse"]
|
||||||
|
|
||||||
# Common build profiles
|
# Common build profiles
|
||||||
# NOTE: We have to compile everything for opt-level = 2 due to optimization passes
|
# NOTE: We have to compile everything for opt-level = 2 due to optimization passes
|
||||||
# which don't handle the UEFI target properly.
|
# which don't handle the UEFI target properly.
|
||||||
|
|||||||
@@ -5,11 +5,7 @@ This guide is a work in progress.
|
|||||||
## Development Setup
|
## Development Setup
|
||||||
|
|
||||||
You can use any Rust development environment to develop Sprout.
|
You can use any Rust development environment to develop Sprout.
|
||||||
|
|
||||||
Rustup is recommended as the Rust toolchain manager to manage Rust versions and targets.
|
Rustup is recommended as the Rust toolchain manager to manage Rust versions and targets.
|
||||||
|
|
||||||
Sprout currently requires Rust nightly to support uefi_std. See [uefi_std](https://doc.rust-lang.org/beta/rustc/platform-support/unknown-uefi.html) for more details.
|
|
||||||
|
|
||||||
We currently only support `x86_64-unknown-uefi` and `aarch64-unknown-uefi` targets.
|
We currently only support `x86_64-unknown-uefi` and `aarch64-unknown-uefi` targets.
|
||||||
|
|
||||||
To test your changes in QEMU, please run `./hack/dev/boot.sh`, you can specify `x86_64` or `aarch64`
|
To test your changes in QEMU, please run `./hack/dev/boot.sh`, you can specify `x86_64` or `aarch64`
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ edition.workspace = true
|
|||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
workspace = true
|
workspace = true
|
||||||
features = ["derive"]
|
default-features = false
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "edera_sprout_config"
|
name = "edera_sprout_config"
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// The configuration of the chainload action.
|
/// The configuration of the chainload action.
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// The configuration of the edera action which boots the Edera hypervisor.
|
/// The configuration of the edera action which boots the Edera hypervisor.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use alloc::string::String;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// The configuration of the print action.
|
/// The configuration of the print action.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use alloc::string::String;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Declares a driver configuration.
|
/// Declares a driver configuration.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
/// Declares a boot entry to display in the boot menu.
|
/// Declares a boot entry to display in the boot menu.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use alloc::string::String;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// The filesystem device match extractor.
|
/// The filesystem device match extractor.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::entries::EntryDeclaration;
|
use crate::entries::EntryDeclaration;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// The default path to the BLS directory.
|
/// The default path to the BLS directory.
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::entries::EntryDeclaration;
|
use crate::entries::EntryDeclaration;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
/// List generator configuration.
|
/// List generator configuration.
|
||||||
/// The list generator produces multiple entries based
|
/// The list generator produces multiple entries based
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::entries::EntryDeclaration;
|
use crate::entries::EntryDeclaration;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
/// Matrix generator configuration.
|
/// Matrix generator configuration.
|
||||||
/// The matrix generator produces multiple entries based
|
/// The matrix generator produces multiple entries based
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
//! Sprout configuration descriptions.
|
//! Sprout configuration descriptions.
|
||||||
//! This crate provides all the configuration structures for Sprout.
|
//! This crate provides all the configuration structures for Sprout.
|
||||||
|
#![no_std]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
use crate::actions::ActionDeclaration;
|
use crate::actions::ActionDeclaration;
|
||||||
use crate::drivers::DriverDeclaration;
|
use crate::drivers::DriverDeclaration;
|
||||||
@@ -7,8 +9,9 @@ use crate::entries::EntryDeclaration;
|
|||||||
use crate::extractors::ExtractorDeclaration;
|
use crate::extractors::ExtractorDeclaration;
|
||||||
use crate::generators::GeneratorDeclaration;
|
use crate::generators::GeneratorDeclaration;
|
||||||
use crate::phases::PhasesConfiguration;
|
use crate::phases::PhasesConfiguration;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::String;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
pub mod actions;
|
pub mod actions;
|
||||||
pub mod drivers;
|
pub mod drivers;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
/// Configures the various phases of the boot process.
|
/// Configures the various phases of the boot process.
|
||||||
/// This allows hooking various phases to run actions.
|
/// This allows hooking various phases to run actions.
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ bitflags.workspace = true
|
|||||||
edera-sprout-config.path = "../config"
|
edera-sprout-config.path = "../config"
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
sha2.workspace = true
|
sha2.workspace = true
|
||||||
|
shlex.workspace = true
|
||||||
|
spin.workspace = true
|
||||||
toml.workspace = true
|
toml.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
|
||||||
[dependencies.uefi]
|
[dependencies.uefi]
|
||||||
workspace = true
|
workspace = true
|
||||||
features = ["alloc", "logger"]
|
features = ["alloc", "global_allocator", "logger", "panic_handler"]
|
||||||
|
|
||||||
[dependencies.uefi-raw]
|
[dependencies.uefi-raw]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
|
use alloc::rc::Rc;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// EFI chainloader action.
|
/// EFI chainloader action.
|
||||||
pub mod chainload;
|
pub mod chainload;
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ use crate::integrations::shim::{ShimInput, ShimSupport};
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
use crate::utils::media_loader::MediaLoaderHandle;
|
use crate::utils::media_loader::MediaLoaderHandle;
|
||||||
use crate::utils::media_loader::constants::linux::LINUX_EFI_INITRD_MEDIA_GUID;
|
use crate::utils::media_loader::constants::linux::LINUX_EFI_INITRD_MEDIA_GUID;
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::rc::Rc;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use edera_sprout_config::actions::chainload::ChainloadConfiguration;
|
use edera_sprout_config::actions::chainload::ChainloadConfiguration;
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::rc::Rc;
|
|
||||||
use uefi::CString16;
|
use uefi::CString16;
|
||||||
use uefi::proto::loaded_image::LoadedImage;
|
use uefi::proto::loaded_image::LoadedImage;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
actions,
|
actions,
|
||||||
context::SproutContext,
|
context::SproutContext,
|
||||||
@@ -13,6 +11,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::{format, vec};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use edera_sprout_config::actions::chainload::ChainloadConfiguration;
|
use edera_sprout_config::actions::chainload::ChainloadConfiguration;
|
||||||
use edera_sprout_config::actions::edera::EderaConfiguration;
|
use edera_sprout_config::actions::edera::EderaConfiguration;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
|
use alloc::rc::Rc;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use edera_sprout_config::actions::print::PrintConfiguration;
|
use edera_sprout_config::actions::print::PrintConfiguration;
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// Executes the print action with the specified `configuration` inside the provided `context`.
|
/// Executes the print action with the specified `configuration` inside the provided `context`.
|
||||||
pub fn print(context: Rc<SproutContext>, configuration: &PrintConfiguration) -> Result<()> {
|
pub fn print(context: Rc<SproutContext>, configuration: &PrintConfiguration) -> Result<()> {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use alloc::{format, vec};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use edera_sprout_config::RootConfiguration;
|
use edera_sprout_config::RootConfiguration;
|
||||||
use edera_sprout_config::actions::ActionDeclaration;
|
use edera_sprout_config::actions::ActionDeclaration;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
use crate::utils::vercmp;
|
use crate::utils::vercmp;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use alloc::{format, vec};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use edera_sprout_config::RootConfiguration;
|
use edera_sprout_config::RootConfiguration;
|
||||||
use edera_sprout_config::actions::ActionDeclaration;
|
use edera_sprout_config::actions::ActionDeclaration;
|
||||||
@@ -7,7 +11,6 @@ use edera_sprout_config::actions::chainload::ChainloadConfiguration;
|
|||||||
use edera_sprout_config::entries::EntryDeclaration;
|
use edera_sprout_config::entries::EntryDeclaration;
|
||||||
use edera_sprout_config::generators::GeneratorDeclaration;
|
use edera_sprout_config::generators::GeneratorDeclaration;
|
||||||
use edera_sprout_config::generators::list::ListConfiguration;
|
use edera_sprout_config::generators::list::ListConfiguration;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use uefi::CString16;
|
use uefi::CString16;
|
||||||
use uefi::fs::{FileSystem, Path, PathBuf};
|
use uefi::fs::{FileSystem, Path, PathBuf};
|
||||||
use uefi::proto::device_path::DevicePath;
|
use uefi::proto::device_path::DevicePath;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use alloc::{format, vec};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use edera_sprout_config::RootConfiguration;
|
use edera_sprout_config::RootConfiguration;
|
||||||
use edera_sprout_config::actions::ActionDeclaration;
|
use edera_sprout_config::actions::ActionDeclaration;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::options::SproutOptions;
|
use crate::options::SproutOptions;
|
||||||
use crate::platform::tpm::PlatformTpm;
|
use crate::platform::tpm::PlatformTpm;
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
|
use core::ops::Deref;
|
||||||
use edera_sprout_config::{RootConfiguration, latest_version};
|
use edera_sprout_config::{RootConfiguration, latest_version};
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::ops::Deref;
|
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
use uefi::proto::device_path::LoadedImageDevicePath;
|
use uefi::proto::device_path::LoadedImageDevicePath;
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
use crate::options::SproutOptions;
|
use crate::options::SproutOptions;
|
||||||
use crate::platform::timer::PlatformTimer;
|
use crate::platform::timer::PlatformTimer;
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::collections::{BTreeMap, BTreeSet};
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use anyhow::{Result, bail};
|
use anyhow::{Result, bail};
|
||||||
|
use core::cmp::Reverse;
|
||||||
use edera_sprout_config::actions::ActionDeclaration;
|
use edera_sprout_config::actions::ActionDeclaration;
|
||||||
use std::cmp::Reverse;
|
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use uefi::proto::device_path::DevicePath;
|
use uefi::proto::device_path::DevicePath;
|
||||||
|
|
||||||
/// The maximum number of iterations that can be performed in [SproutContext::finalize].
|
/// The maximum number of iterations that can be performed in [SproutContext::finalize].
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
use crate::integrations::shim::{ShimInput, ShimSupport};
|
use crate::integrations::shim::{ShimInput, ShimSupport};
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::String;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
pub(crate) use edera_sprout_config::drivers::DriverDeclaration;
|
use edera_sprout_config::drivers::DriverDeclaration;
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use uefi::boot::SearchType;
|
use uefi::boot::SearchType;
|
||||||
|
|
||||||
/// Loads the driver specified by the `driver` declaration.
|
/// Loads the driver specified by the `driver` declaration.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
use edera_sprout_config::entries::EntryDeclaration;
|
use edera_sprout_config::entries::EntryDeclaration;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// Represents an entry that is stamped and ready to be booted.
|
/// Represents an entry that is stamped and ready to be booted.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::String;
|
||||||
use anyhow::{Result, bail};
|
use anyhow::{Result, bail};
|
||||||
use edera_sprout_config::extractors::ExtractorDeclaration;
|
use edera_sprout_config::extractors::ExtractorDeclaration;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// The filesystem device match extractor.
|
/// The filesystem device match extractor.
|
||||||
pub mod filesystem_device_match;
|
pub mod filesystem_device_match;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::String;
|
||||||
use anyhow::{Context, Result, anyhow, bail};
|
use anyhow::{Context, Result, anyhow, bail};
|
||||||
|
use core::ops::Deref;
|
||||||
|
use core::str::FromStr;
|
||||||
use edera_sprout_config::extractors::filesystem_device_match::FilesystemDeviceMatchExtractor;
|
use edera_sprout_config::extractors::filesystem_device_match::FilesystemDeviceMatchExtractor;
|
||||||
use std::ops::Deref;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use uefi::fs::{FileSystem, Path};
|
use uefi::fs::{FileSystem, Path};
|
||||||
use uefi::proto::device_path::DevicePath;
|
use uefi::proto::device_path::DevicePath;
|
||||||
use uefi::proto::media::file::{File, FileSystemVolumeLabel};
|
use uefi::proto::media::file::{File, FileSystemVolumeLabel};
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
use crate::entries::BootableEntry;
|
use crate::entries::BootableEntry;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use edera_sprout_config::generators::GeneratorDeclaration;
|
use edera_sprout_config::generators::GeneratorDeclaration;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// The BLS generator.
|
/// The BLS generator.
|
||||||
pub mod bls;
|
pub mod bls;
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ use crate::entries::BootableEntry;
|
|||||||
use crate::generators::bls::entry::BlsEntry;
|
use crate::generators::bls::entry::BlsEntry;
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
use crate::utils::vercmp;
|
use crate::utils::vercmp;
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
use core::cmp::Ordering;
|
||||||
|
use core::str::FromStr;
|
||||||
use edera_sprout_config::generators::bls::BlsConfiguration;
|
use edera_sprout_config::generators::bls::BlsConfiguration;
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use uefi::cstr16;
|
use uefi::cstr16;
|
||||||
use uefi::fs::{FileSystem, PathBuf};
|
use uefi::fs::{FileSystem, PathBuf};
|
||||||
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
|
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
use alloc::string::{String, ToString};
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use std::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
/// Represents a parsed BLS entry.
|
/// Represents a parsed BLS entry.
|
||||||
/// Fields unrelated to Sprout are not included.
|
/// Fields unrelated to Sprout are not included.
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
use crate::entries::BootableEntry;
|
use crate::entries::BootableEntry;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use edera_sprout_config::generators::list::ListConfiguration;
|
use edera_sprout_config::generators::list::ListConfiguration;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// Generates a set of entries using the specified `list` configuration in the `context`.
|
/// Generates a set of entries using the specified `list` configuration in the `context`.
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
use crate::entries::BootableEntry;
|
use crate::entries::BootableEntry;
|
||||||
use crate::generators::list;
|
use crate::generators::list;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::rc::Rc;
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use edera_sprout_config::generators::list::ListConfiguration;
|
use edera_sprout_config::generators::list::ListConfiguration;
|
||||||
use edera_sprout_config::generators::matrix::MatrixConfiguration;
|
use edera_sprout_config::generators::matrix::MatrixConfiguration;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// Builds out multiple generations of `input` based on a matrix style.
|
/// Builds out multiple generations of `input` based on a matrix style.
|
||||||
/// For example, if input is: {"x": ["a", "b"], "y": ["c", "d"]}
|
/// For example, if input is: {"x": ["a", "b"], "y": ["c", "d"]}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ use crate::integrations::bootloader_interface::bitflags::LoaderFeatures;
|
|||||||
use crate::platform::timer::PlatformTimer;
|
use crate::platform::timer::PlatformTimer;
|
||||||
use crate::utils::device_path_subpath;
|
use crate::utils::device_path_subpath;
|
||||||
use crate::utils::variables::{VariableClass, VariableController};
|
use crate::utils::variables::{VariableClass, VariableController};
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use uefi::proto::device_path::DevicePath;
|
use uefi::proto::device_path::DevicePath;
|
||||||
use uefi::{Guid, guid};
|
use uefi::{Guid, guid};
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ use crate::secure::SecureBoot;
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
use crate::utils::ResolvedPath;
|
use crate::utils::ResolvedPath;
|
||||||
use crate::utils::variables::{VariableClass, VariableController};
|
use crate::utils::variables::{VariableClass, VariableController};
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result, anyhow, bail};
|
use anyhow::{Context, Result, anyhow, bail};
|
||||||
|
use core::ffi::c_void;
|
||||||
|
use core::pin::Pin;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use std::ffi::c_void;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use uefi::Handle;
|
use uefi::Handle;
|
||||||
use uefi::boot::LoadImageSource;
|
use uefi::boot::LoadImageSource;
|
||||||
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
|
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use crate::integrations::shim::{ShimInput, ShimSupport, ShimVerificationOutput};
|
use crate::integrations::shim::{ShimInput, ShimSupport, ShimVerificationOutput};
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result};
|
||||||
|
use core::slice;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use std::sync::{LazyLock, Mutex};
|
use spin::{Lazy, Mutex};
|
||||||
use uefi::proto::device_path::FfiDevicePath;
|
use uefi::proto::device_path::FfiDevicePath;
|
||||||
use uefi::proto::unsafe_protocol;
|
use uefi::proto::unsafe_protocol;
|
||||||
use uefi::{Guid, guid};
|
use uefi::{Guid, guid};
|
||||||
@@ -45,8 +46,7 @@ struct SecurityHookState {
|
|||||||
|
|
||||||
/// Global state for the security hook.
|
/// Global state for the security hook.
|
||||||
/// This is messy, but it is safe given the mutex.
|
/// This is messy, but it is safe given the mutex.
|
||||||
static GLOBAL_HOOK_STATE: LazyLock<Mutex<Option<SecurityHookState>>> =
|
static GLOBAL_HOOK_STATE: Lazy<Mutex<Option<SecurityHookState>>> = Lazy::new(|| Mutex::new(None));
|
||||||
LazyLock::new(|| Mutex::new(None));
|
|
||||||
|
|
||||||
/// Security hook helper.
|
/// Security hook helper.
|
||||||
pub struct SecurityHook;
|
pub struct SecurityHook;
|
||||||
@@ -110,24 +110,13 @@ impl SecurityHook {
|
|||||||
// Verify the input, if it fails, call the original hook.
|
// Verify the input, if it fails, call the original hook.
|
||||||
if !Self::verify(input) {
|
if !Self::verify(input) {
|
||||||
// Acquire the global hook state to grab the original hook.
|
// Acquire the global hook state to grab the original hook.
|
||||||
let function = match GLOBAL_HOOK_STATE.lock() {
|
let function = match GLOBAL_HOOK_STATE.lock().as_ref() {
|
||||||
// We have acquired the lock, so we can find the original hook.
|
// The hook state is available, so we can acquire the original hook.
|
||||||
Ok(state) => match state.as_ref() {
|
Some(state) => state.original_hook.file_authentication_state,
|
||||||
// The hook state is available, so we can acquire the original hook.
|
|
||||||
Some(state) => state.original_hook.file_authentication_state,
|
|
||||||
|
|
||||||
// The hook state is not available, so we can't call the original hook.
|
// The hook state is not available, so we can't call the original hook.
|
||||||
None => {
|
None => {
|
||||||
warn!("global hook state is not available, unable to call original hook");
|
warn!("global hook state is not available, unable to call original hook");
|
||||||
return Status::LOAD_ERROR;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Err(error) => {
|
|
||||||
warn!(
|
|
||||||
"unable to acquire global hook state lock to call original hook: {}",
|
|
||||||
error,
|
|
||||||
);
|
|
||||||
return Status::LOAD_ERROR;
|
return Status::LOAD_ERROR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -161,7 +150,7 @@ impl SecurityHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct a slice out of the file buffer and size.
|
// Construct a slice out of the file buffer and size.
|
||||||
let buffer = unsafe { std::slice::from_raw_parts(file_buffer, file_size) };
|
let buffer = unsafe { slice::from_raw_parts(file_buffer, file_size) };
|
||||||
|
|
||||||
// Construct a shim input from the path.
|
// Construct a shim input from the path.
|
||||||
let input = ShimInput::SecurityHookBuffer(Some(path), buffer);
|
let input = ShimInput::SecurityHookBuffer(Some(path), buffer);
|
||||||
@@ -169,24 +158,13 @@ impl SecurityHook {
|
|||||||
// Verify the input, if it fails, call the original hook.
|
// Verify the input, if it fails, call the original hook.
|
||||||
if !Self::verify(input) {
|
if !Self::verify(input) {
|
||||||
// Acquire the global hook state to grab the original hook.
|
// Acquire the global hook state to grab the original hook.
|
||||||
let function = match GLOBAL_HOOK_STATE.lock() {
|
let function = match GLOBAL_HOOK_STATE.lock().as_ref() {
|
||||||
// We have acquired the lock, so we can find the original hook.
|
// The hook state is available, so we can acquire the original hook.
|
||||||
Ok(state) => match state.as_ref() {
|
Some(state) => state.original_hook2.file_authentication,
|
||||||
// The hook state is available, so we can acquire the original hook.
|
|
||||||
Some(state) => state.original_hook2.file_authentication,
|
|
||||||
|
|
||||||
// The hook state is not available, so we can't call the original hook.
|
// The hook state is not available, so we can't call the original hook.
|
||||||
None => {
|
None => {
|
||||||
warn!("global hook state is not available, unable to call original hook");
|
warn!("global hook state is not available, unable to call original hook");
|
||||||
return Status::LOAD_ERROR;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Err(error) => {
|
|
||||||
warn!(
|
|
||||||
"unable to acquire global hook state lock to call original hook: {}",
|
|
||||||
error
|
|
||||||
);
|
|
||||||
return Status::LOAD_ERROR;
|
return Status::LOAD_ERROR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -237,9 +215,7 @@ impl SecurityHook {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Acquire the lock to the global state and replace it.
|
// Acquire the lock to the global state and replace it.
|
||||||
let Ok(mut global_state) = GLOBAL_HOOK_STATE.lock() else {
|
let mut global_state = GLOBAL_HOOK_STATE.lock();
|
||||||
bail!("unable to acquire global hook state lock");
|
|
||||||
};
|
|
||||||
global_state.replace(state);
|
global_state.replace(state);
|
||||||
|
|
||||||
// Install the hooks into the UEFI stack.
|
// Install the hooks into the UEFI stack.
|
||||||
@@ -276,9 +252,7 @@ impl SecurityHook {
|
|||||||
.context("unable to open security arch2 protocol")?;
|
.context("unable to open security arch2 protocol")?;
|
||||||
|
|
||||||
// Acquire the lock to the global state.
|
// Acquire the lock to the global state.
|
||||||
let Ok(mut global_state) = GLOBAL_HOOK_STATE.lock() else {
|
let mut global_state = GLOBAL_HOOK_STATE.lock();
|
||||||
bail!("unable to acquire global hook state lock");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Take the state and replace the original functions.
|
// Take the state and replace the original functions.
|
||||||
let Some(state) = global_state.take() else {
|
let Some(state) = global_state.take() else {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![feature(uefi_std)]
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
/// The delay to wait for when an error occurs in Sprout.
|
extern crate alloc;
|
||||||
const DELAY_ON_ERROR: Duration = Duration::from_secs(10);
|
|
||||||
|
|
||||||
use crate::context::{RootContext, SproutContext};
|
use crate::context::{RootContext, SproutContext};
|
||||||
use crate::entries::BootableEntry;
|
use crate::entries::BootableEntry;
|
||||||
@@ -14,13 +14,18 @@ use crate::platform::timer::PlatformTimer;
|
|||||||
use crate::platform::tpm::PlatformTpm;
|
use crate::platform::tpm::PlatformTpm;
|
||||||
use crate::secure::SecureBoot;
|
use crate::secure::SecureBoot;
|
||||||
use crate::utils::PartitionGuidForm;
|
use crate::utils::PartitionGuidForm;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
|
use core::ops::Deref;
|
||||||
|
use core::time::Duration;
|
||||||
use edera_sprout_config::RootConfiguration;
|
use edera_sprout_config::RootConfiguration;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use std::collections::BTreeMap;
|
use uefi::entry;
|
||||||
use std::ops::Deref;
|
|
||||||
use std::time::Duration;
|
|
||||||
use uefi::proto::device_path::LoadedImageDevicePath;
|
use uefi::proto::device_path::LoadedImageDevicePath;
|
||||||
|
use uefi_raw::Status;
|
||||||
|
|
||||||
/// actions: Code that can be configured and executed by Sprout.
|
/// actions: Code that can be configured and executed by Sprout.
|
||||||
pub mod actions;
|
pub mod actions;
|
||||||
@@ -73,6 +78,9 @@ pub mod options;
|
|||||||
/// utils: Utility functions that are used by other parts of Sprout.
|
/// utils: Utility functions that are used by other parts of Sprout.
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
/// The delay to wait for when an error occurs in Sprout.
|
||||||
|
const DELAY_ON_ERROR: Duration = Duration::from_secs(10);
|
||||||
|
|
||||||
/// Run Sprout, returning an error if one occurs.
|
/// Run Sprout, returning an error if one occurs.
|
||||||
fn run() -> Result<()> {
|
fn run() -> Result<()> {
|
||||||
// For safety reasons, we will note that Secure Boot is in beta on Sprout.
|
// For safety reasons, we will note that Secure Boot is in beta on Sprout.
|
||||||
@@ -373,9 +381,14 @@ fn run() -> Result<()> {
|
|||||||
/// The main entrypoint of sprout.
|
/// The main entrypoint of sprout.
|
||||||
/// It is possible this function will not return if actions that are executed
|
/// It is possible this function will not return if actions that are executed
|
||||||
/// exit boot services or do not return control to sprout.
|
/// exit boot services or do not return control to sprout.
|
||||||
fn main() -> Result<()> {
|
#[entry]
|
||||||
|
fn efi_main() -> Status {
|
||||||
// Initialize the basic UEFI environment.
|
// Initialize the basic UEFI environment.
|
||||||
setup::init()?;
|
// If initialization fails, we will return ABORTED.
|
||||||
|
if let Err(error) = setup::init() {
|
||||||
|
error!("unable to initialize environment: {}", error);
|
||||||
|
return Status::ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
// Run Sprout, then handle the error.
|
// Run Sprout, then handle the error.
|
||||||
let result = run();
|
let result = run();
|
||||||
@@ -387,9 +400,10 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
// Sleep to allow the user to read the error.
|
// Sleep to allow the user to read the error.
|
||||||
uefi::boot::stall(DELAY_ON_ERROR);
|
uefi::boot::stall(DELAY_ON_ERROR);
|
||||||
|
return Status::ABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sprout doesn't necessarily guarantee anything was booted.
|
// Sprout doesn't necessarily guarantee anything was booted.
|
||||||
// If we reach here, we will exit back to whoever called us.
|
// If we reach here, we will exit back to whoever called us.
|
||||||
Ok(())
|
Status::SUCCESS
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use crate::entries::BootableEntry;
|
use crate::entries::BootableEntry;
|
||||||
use crate::integrations::bootloader_interface::BootloaderInterface;
|
use crate::integrations::bootloader_interface::BootloaderInterface;
|
||||||
use crate::platform::timer::PlatformTimer;
|
use crate::platform::timer::PlatformTimer;
|
||||||
|
use alloc::vec;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
|
use core::time::Duration;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use std::time::Duration;
|
|
||||||
use uefi::ResultExt;
|
use uefi::ResultExt;
|
||||||
use uefi::boot::TimerTrigger;
|
use uefi::boot::TimerTrigger;
|
||||||
use uefi::proto::console::text::{Input, Key, ScanCode};
|
use uefi::proto::console::text::{Input, Key, ScanCode};
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
use crate::options::parser::{OptionDescription, OptionForm, OptionsRepresentable};
|
use crate::options::parser::{OptionDescription, OptionForm, OptionsRepresentable};
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
/// Acquire arguments from UEFI environment.
|
||||||
|
pub mod env;
|
||||||
|
|
||||||
/// The Sprout options parser.
|
/// The Sprout options parser.
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|||||||
77
crates/sprout/src/options/env.rs
Normal file
77
crates/sprout/src/options/env.rs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use anyhow::{Context, Result, bail};
|
||||||
|
use uefi::proto::loaded_image::{LoadOptionsError, LoadedImage};
|
||||||
|
|
||||||
|
/// Loads the command-line arguments passed to Sprout.
|
||||||
|
pub fn args() -> Result<Vec<String>> {
|
||||||
|
// Acquire the image handle of Sprout.
|
||||||
|
let handle = uefi::boot::image_handle();
|
||||||
|
|
||||||
|
// Open the LoadedImage protocol for Sprout.
|
||||||
|
let loaded_image = uefi::boot::open_protocol_exclusive::<LoadedImage>(handle)
|
||||||
|
.context("unable to open loaded image protocol for sprout")?;
|
||||||
|
|
||||||
|
// Load the command-line argument string.
|
||||||
|
let options = match loaded_image.load_options_as_cstr16() {
|
||||||
|
// Load options were passed. We will return them for processing.
|
||||||
|
Ok(options) => options,
|
||||||
|
|
||||||
|
// No load options were passed. We will return an empty vector.
|
||||||
|
Err(LoadOptionsError::NotSet) => {
|
||||||
|
return Ok(Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(LoadOptionsError::NotAligned) => {
|
||||||
|
bail!("load options are not properly aligned");
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(LoadOptionsError::InvalidString(error)) => {
|
||||||
|
bail!("load options are not a valid string: {}", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert the options to a string.
|
||||||
|
let options = options.to_string();
|
||||||
|
|
||||||
|
// Use shlex to parse the options.
|
||||||
|
// If shlex fails, we will fall back to a simple whitespace split.
|
||||||
|
let mut args = shlex::split(&options).unwrap_or_else(|| {
|
||||||
|
options
|
||||||
|
.split_ascii_whitespace()
|
||||||
|
.map(|string| string.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
// If there is a first argument, check if it is not an option.
|
||||||
|
// If it is not, we will assume it is the path to the executable and remove it.
|
||||||
|
if let Some(arg) = args.first()
|
||||||
|
&& !arg.starts_with('-')
|
||||||
|
{
|
||||||
|
args.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Correct firmware that may add invalid arguments at the start.
|
||||||
|
// Witnessed this on a Dell Precision 5690 when direct booting.
|
||||||
|
loop {
|
||||||
|
// Grab the first argument or break.
|
||||||
|
let Some(arg) = args.first() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the argument is a valid character.
|
||||||
|
// If it is not, remove it and continue.
|
||||||
|
let Some(first_character) = arg.chars().next() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the character is not a printable character or a backtick, remove it and continue.
|
||||||
|
if first_character < 0x1f as char || first_character == '`' {
|
||||||
|
args.remove(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(args)
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
|
use crate::options::env;
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
|
use core::ptr::null_mut;
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::collections::BTreeMap;
|
use uefi_raw::Status;
|
||||||
|
|
||||||
/// The type of option. This disambiguates different behavior
|
/// The type of option. This disambiguates different behavior
|
||||||
/// of how options are handled.
|
/// of how options are handled.
|
||||||
@@ -47,23 +51,7 @@ pub trait OptionsRepresentable {
|
|||||||
|
|
||||||
// Collect all the arguments to Sprout.
|
// Collect all the arguments to Sprout.
|
||||||
// Skip the first argument, which is the path to our executable.
|
// Skip the first argument, which is the path to our executable.
|
||||||
let mut args = std::env::args().skip(1).collect::<Vec<_>>();
|
let args = env::args()?;
|
||||||
|
|
||||||
// Correct firmware that may add invalid arguments at the start.
|
|
||||||
// Witnessed this on a Dell Precision 5690 when direct booting.
|
|
||||||
loop {
|
|
||||||
// Grab the first argument or break.
|
|
||||||
let Some(arg) = args.first() else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
// If the argument starts with a tilde, remove it.
|
|
||||||
if arg.starts_with("`") {
|
|
||||||
args.remove(0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Represent options as key-value pairs.
|
// Represent options as key-value pairs.
|
||||||
let mut options = BTreeMap::new();
|
let mut options = BTreeMap::new();
|
||||||
@@ -77,7 +65,7 @@ pub trait OptionsRepresentable {
|
|||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the doesn't start with --, that is invalid.
|
// If the option doesn't start with --, that is invalid.
|
||||||
if !option.starts_with("--") {
|
if !option.starts_with("--") {
|
||||||
bail!("invalid option: {option}");
|
bail!("invalid option: {option}");
|
||||||
}
|
}
|
||||||
@@ -144,7 +132,9 @@ pub trait OptionsRepresentable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Exit because the help has been displayed.
|
// Exit because the help has been displayed.
|
||||||
std::process::exit(0);
|
unsafe {
|
||||||
|
uefi::boot::exit(uefi::boot::image_handle(), Status::SUCCESS, 0, null_mut());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the option and the value into the map.
|
// Insert the option and the value into the map.
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use crate::actions;
|
use crate::actions;
|
||||||
use crate::context::SproutContext;
|
use crate::context::SproutContext;
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::rc::Rc;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use edera_sprout_config::phases::PhaseConfiguration;
|
use edera_sprout_config::phases::PhaseConfiguration;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
/// Executes the specified [phase] of the boot process.
|
/// Executes the specified [phase] of the boot process.
|
||||||
/// The value [phase] should be a reference of a specific phase in the [PhasesConfiguration].
|
/// The value [phase] should be a reference of a specific phase in the [PhasesConfiguration].
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Referenced https://github.com/sheroz/tick_counter (MIT license) as a baseline.
|
// Referenced https://github.com/sheroz/tick_counter (MIT license) as a baseline.
|
||||||
// Architecturally modified to support UEFI and remove x86 (32-bit) support.
|
// Architecturally modified to support UEFI and remove x86 (32-bit) support.
|
||||||
|
|
||||||
use std::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
/// Support for aarch64 timers.
|
/// Support for aarch64 timers.
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::platform::timer::TickFrequency;
|
use crate::platform::timer::TickFrequency;
|
||||||
use std::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
/// Reads the cntvct_el0 counter and returns the value.
|
/// Reads the cntvct_el0 counter and returns the value.
|
||||||
pub fn ticks() -> u64 {
|
pub fn ticks() -> u64 {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::platform::timer::TickFrequency;
|
use crate::platform::timer::TickFrequency;
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use std::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
/// We will measure the frequency of the timer based on 1000 microseconds.
|
/// We will measure the frequency of the timer based on 1000 microseconds.
|
||||||
/// This will result in a call to BS->Stall(1000) in the end.
|
/// This will result in a call to BS->Stall(1000) in the end.
|
||||||
|
|||||||
@@ -1,27 +1,8 @@
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use std::os::uefi as uefi_std;
|
|
||||||
|
|
||||||
/// Initializes the UEFI environment.
|
/// Initializes the UEFI environment.
|
||||||
///
|
|
||||||
/// This fetches the system table and current image handle from uefi_std and injects
|
|
||||||
/// them into the uefi crate.
|
|
||||||
pub fn init() -> Result<()> {
|
pub fn init() -> Result<()> {
|
||||||
// Acquire the system table and image handle from the uefi_std environment.
|
// Initialize the uefi internals.
|
||||||
let system_table = uefi_std::env::system_table();
|
|
||||||
let image_handle = uefi_std::env::image_handle();
|
|
||||||
|
|
||||||
// SAFETY: The UEFI variables above come from the Rust std.
|
|
||||||
// These variables are not-null and calling the uefi crates with these values is validated
|
|
||||||
// to be corrected by hand.
|
|
||||||
unsafe {
|
|
||||||
// Set the system table and image handle.
|
|
||||||
uefi::table::set_system_table(system_table.as_ptr().cast());
|
|
||||||
let handle = uefi::Handle::from_ptr(image_handle.as_ptr().cast())
|
|
||||||
.context("unable to resolve image handle")?;
|
|
||||||
uefi::boot::set_image_handle(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the uefi logger mechanism and other helpers.
|
|
||||||
uefi::helpers::init().context("unable to initialize uefi")?;
|
uefi::helpers::init().context("unable to initialize uefi")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
use alloc::borrow::ToOwned;
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
|
use core::ops::Deref;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::ops::Deref;
|
|
||||||
use uefi::boot::SearchType;
|
use uefi::boot::SearchType;
|
||||||
use uefi::fs::{FileSystem, Path};
|
use uefi::fs::{FileSystem, Path};
|
||||||
use uefi::proto::device_path::text::{AllowShortcuts, DevicePathFromText, DisplayOnly};
|
use uefi::proto::device_path::text::{AllowShortcuts, DevicePathFromText, DisplayOnly};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput};
|
use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use std::ffi::c_void;
|
use core::ffi::c_void;
|
||||||
|
use core::ptr;
|
||||||
use uefi::proto::device_path::DevicePath;
|
use uefi::proto::device_path::DevicePath;
|
||||||
use uefi::proto::device_path::build::DevicePathBuilder;
|
use uefi::proto::device_path::build::DevicePathBuilder;
|
||||||
use uefi::proto::device_path::build::media::Vendor;
|
use uefi::proto::device_path::build::media::Vendor;
|
||||||
@@ -261,8 +264,7 @@ impl MediaLoaderHandle {
|
|||||||
let protocol = Box::from_raw(self.protocol);
|
let protocol = Box::from_raw(self.protocol);
|
||||||
|
|
||||||
// Retrieve a box for the data we passed in.
|
// Retrieve a box for the data we passed in.
|
||||||
let slice =
|
let slice = ptr::slice_from_raw_parts_mut(protocol.address as *mut u8, protocol.length);
|
||||||
std::ptr::slice_from_raw_parts_mut(protocol.address as *mut u8, protocol.length);
|
|
||||||
let data = Box::from_raw(slice);
|
let data = Box::from_raw(slice);
|
||||||
|
|
||||||
// Drop all the allocations explicitly, as we don't want to leak them.
|
// Drop all the allocations explicitly, as we don't want to leak them.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
use alloc::format;
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use alloc::vec::Vec;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use uefi::{CString16, guid};
|
use uefi::{CString16, guid};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use std::iter::Peekable;
|
use core::iter::Peekable;
|
||||||
|
|
||||||
/// Handles single character advancement and comparison.
|
/// Handles single character advancement and comparison.
|
||||||
macro_rules! handle_single_char {
|
macro_rules! handle_single_char {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly"
|
channel = "1.91.0"
|
||||||
components = ["rustfmt", "rust-std", "clippy"]
|
components = ["rustfmt", "clippy"]
|
||||||
targets = ["x86_64-unknown-uefi", "aarch64-unknown-uefi"]
|
targets = ["x86_64-unknown-uefi", "aarch64-unknown-uefi"]
|
||||||
|
|||||||
Reference in New Issue
Block a user