mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 22:02:20 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed226afb7e
|
||
|
|
6cdf5362a4
|
No files matched your search
@@ -26,7 +26,7 @@ jobs:
|
||||
actions: read # Needed to analyze action metadata.
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: setup uv
|
||||
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
||||
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
||||
|
||||
- name: zizmor
|
||||
run: uvx zizmor --pedantic --format sarif . > results.sarif
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
- name: upload
|
||||
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: zizmor
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
name: 'build ${{ matrix.arch }}'
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
name: 'clippy ${{ matrix.arch }}'
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
build-mode: none
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -48,13 +48,13 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: initialize codeql
|
||||
uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
config-file: ./.github/codeql/codeql-config.yaml
|
||||
|
||||
- name: perform codeql analysis
|
||||
uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
artifact-digest: "${{ steps.upload.outputs.artifact-digest }}"
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
- name: 'upload artifacts'
|
||||
id: upload
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: artifacts
|
||||
path: target/assemble/*
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: harden runner
|
||||
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
|
||||
uses: step-security/harden-runner@351661ca32ac09a36dc5ee2d536e3128f2a3c8ed # v2.22.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
subject-path: target/assemble/*
|
||||
|
||||
- name: 'generate cultivator token'
|
||||
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
|
||||
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
||||
id: generate-token
|
||||
with:
|
||||
app-id: "${{ secrets.EDERA_CULTIVATION_APP_ID }}"
|
||||
|
||||
Generated
+16
-16
@@ -80,14 +80,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "edera-sprout-bls"
|
||||
version = "0.0.31"
|
||||
version = "0.0.30"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "edera-sprout-boot"
|
||||
version = "0.0.31"
|
||||
version = "0.0.30"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"edera-sprout-bls",
|
||||
@@ -107,21 +107,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "edera-sprout-build"
|
||||
version = "0.0.31"
|
||||
version = "0.0.30"
|
||||
dependencies = [
|
||||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "edera-sprout-config"
|
||||
version = "0.0.31"
|
||||
version = "0.0.30"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "edera-sprout-eficore"
|
||||
version = "0.0.31"
|
||||
version = "0.0.30"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
@@ -133,7 +133,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "edera-sprout-parsing"
|
||||
version = "0.0.31"
|
||||
version = "0.0.30"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"sha2",
|
||||
@@ -320,18 +320,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.1.2"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c"
|
||||
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.11.1"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19"
|
||||
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
@@ -366,9 +366,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.1.8+spec-1.1.0"
|
||||
version = "1.1.6+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20489e00e4d8741d6be680764cc12e270655e375a20d1011e844a9c3379e678d"
|
||||
checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
@@ -379,18 +379,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053"
|
||||
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.1.5+spec-1.1.0"
|
||||
version = "1.1.3+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c"
|
||||
checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ resolver = "3"
|
||||
|
||||
[workspace.package]
|
||||
license = "Apache-2.0"
|
||||
version = "0.0.31"
|
||||
version = "0.0.30"
|
||||
homepage = "https://sprout.edera.dev"
|
||||
repository = "https://github.com/edera-dev/sprout"
|
||||
edition = "2024"
|
||||
|
||||
+81
-12
@@ -2,20 +2,20 @@ use crate::context::SproutContext;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::format;
|
||||
use alloc::rc::Rc;
|
||||
use alloc::string::String;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec::Vec;
|
||||
use anyhow::{Context, Result};
|
||||
use edera_sprout_config::drivers::{DriverDeclaration, DriverProvides};
|
||||
use eficore::loader::source::ImageSource;
|
||||
use eficore::loader::{ImageLoadRequest, ImageLoader};
|
||||
use log::info;
|
||||
use uefi::boot::SearchType;
|
||||
use uefi::boot::{OpenProtocolAttributes, OpenProtocolParams, SearchType};
|
||||
use uefi::proto::media::block::BlockIO;
|
||||
use uefi::proto::media::disk::{DiskIo, DiskIo2};
|
||||
use uefi::{Handle, Identify};
|
||||
|
||||
/// Loads the driver specified by the `driver` declaration.
|
||||
fn load_driver(context: Rc<SproutContext>, driver: &DriverDeclaration) -> Result<()> {
|
||||
fn load_driver(context: Rc<SproutContext>, driver: &DriverDeclaration) -> Result<Handle> {
|
||||
// Acquire the handle and device path of the loaded image.
|
||||
let sprout_image = uefi::boot::image_handle();
|
||||
|
||||
@@ -36,13 +36,31 @@ fn load_driver(context: Rc<SproutContext>, driver: &DriverDeclaration) -> Result
|
||||
// Start the driver image, this is expected to return control to sprout.
|
||||
// There is no guarantee that the driver will actually return control as it is
|
||||
// just a standard EFI image.
|
||||
info!("starting driver image");
|
||||
uefi::boot::start_image(*image.handle()).context("unable to start driver image")?;
|
||||
info!("driver image returned");
|
||||
|
||||
Ok(())
|
||||
Ok(*image.handle())
|
||||
}
|
||||
|
||||
/// Checks whether the handle is a logical partition rather than a whole disk.
|
||||
fn is_partition(handle: Handle) -> bool {
|
||||
let params = OpenProtocolParams {
|
||||
handle,
|
||||
agent: uefi::boot::image_handle(),
|
||||
controller: None,
|
||||
};
|
||||
// Opening with GetProtocol does not disturb the existing protocol users.
|
||||
let block = unsafe {
|
||||
uefi::boot::open_protocol::<BlockIO>(params, OpenProtocolAttributes::GetProtocol)
|
||||
};
|
||||
block.is_ok_and(|block| block.media().is_logical_partition())
|
||||
}
|
||||
|
||||
/// Locates the handles that are disks or partitions.
|
||||
/// These are the only controllers that filesystem drivers can bind to.
|
||||
/// Filesystem drivers bind to partitions, so whole disks are only returned when
|
||||
/// there are no partitions. Reconnecting a whole disk makes the firmware rebuild
|
||||
/// its partition handles, which hangs on some NVMe firmware.
|
||||
fn locate_storage_handles() -> Result<Vec<Handle>> {
|
||||
let mut storage = Vec::new();
|
||||
for guid in [&BlockIO::GUID, &DiskIo::GUID, &DiskIo2::GUID] {
|
||||
@@ -56,7 +74,32 @@ fn locate_storage_handles() -> Result<Vec<Handle>> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(storage)
|
||||
let partitions: Vec<Handle> = storage
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|handle| is_partition(*handle))
|
||||
.collect();
|
||||
if partitions.is_empty() {
|
||||
return Ok(storage);
|
||||
}
|
||||
Ok(partitions)
|
||||
}
|
||||
|
||||
/// Describes a handle by its device path, for diagnosing hangs.
|
||||
fn describe(handle: Handle) -> String {
|
||||
use uefi::proto::device_path::DevicePath;
|
||||
|
||||
let params = OpenProtocolParams {
|
||||
handle,
|
||||
agent: uefi::boot::image_handle(),
|
||||
controller: None,
|
||||
};
|
||||
match unsafe {
|
||||
uefi::boot::open_protocol::<DevicePath>(params, OpenProtocolAttributes::GetProtocol)
|
||||
} {
|
||||
Ok(path) => path.to_string(),
|
||||
Err(_) => String::from("<no device path>"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reconnects handles to their controllers.
|
||||
@@ -64,7 +107,7 @@ fn locate_storage_handles() -> Result<Vec<Handle>> {
|
||||
/// After we load all the drivers, we need to reconnect their handles
|
||||
/// so that filesystems are recognized again.
|
||||
/// When `provides` is [`DriverProvides::Filesystems`], only disk and partition handles are reconnected.
|
||||
fn reconnect(provides: DriverProvides) -> Result<()> {
|
||||
fn reconnect(provides: DriverProvides, drivers: &[Handle]) -> Result<()> {
|
||||
// Locate the handles to reconnect in the UEFI stack.
|
||||
let handles = match provides {
|
||||
DriverProvides::Any => uefi::boot::locate_handle_buffer(SearchType::AllHandles)
|
||||
@@ -72,13 +115,35 @@ fn reconnect(provides: DriverProvides) -> Result<()> {
|
||||
.iter()
|
||||
.copied()
|
||||
.collect(),
|
||||
DriverProvides::Filesystems => locate_storage_handles()?,
|
||||
DriverProvides::Filesystems => {
|
||||
// Probe in reverse so the first partition is the last to be tried.
|
||||
let mut storage = locate_storage_handles()?;
|
||||
storage.reverse();
|
||||
storage
|
||||
}
|
||||
};
|
||||
|
||||
for handle in handles {
|
||||
// The driver list passed to the firmware must end with a null entry.
|
||||
let driver_list: Vec<Option<Handle>> = drivers
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Some)
|
||||
.chain(core::iter::once(None))
|
||||
.collect();
|
||||
|
||||
let total = handles.len();
|
||||
for (index, handle) in handles.into_iter().enumerate() {
|
||||
info!("reconnecting {}/{}: {}", index + 1, total, describe(handle));
|
||||
// Ignore the result as there is nothing we can do if reconnecting a controller fails.
|
||||
// This is also likely to fail in some cases but should fail safely.
|
||||
let _ = uefi::boot::connect_controller(handle, &[], None, true);
|
||||
// Filesystem drivers are connected directly so the firmware stack is not rebuilt.
|
||||
let _ = match provides {
|
||||
DriverProvides::Any => uefi::boot::connect_controller(handle, &[], None, true),
|
||||
DriverProvides::Filesystems => {
|
||||
uefi::boot::connect_controller(handle, &driver_list, None, false)
|
||||
}
|
||||
};
|
||||
info!("reconnected {}/{}", index + 1, total);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -100,8 +165,12 @@ pub fn load(
|
||||
info!("loading drivers");
|
||||
|
||||
// Load all the drivers in no particular order.
|
||||
let mut loaded = Vec::new();
|
||||
for (name, driver) in drivers {
|
||||
load_driver(context.clone(), driver).context(format!("unable to load driver: {}", name))?;
|
||||
loaded.push(
|
||||
load_driver(context.clone(), driver)
|
||||
.context(format!("unable to load driver: {}", name))?,
|
||||
);
|
||||
}
|
||||
|
||||
// Reconnect everything if any driver can provide anything, otherwise only storage.
|
||||
@@ -113,7 +182,7 @@ pub fn load(
|
||||
} else {
|
||||
DriverProvides::Any
|
||||
};
|
||||
reconnect(provides).context("unable to reconnect drivers")?;
|
||||
reconnect(provides, &loaded).context("unable to reconnect drivers")?;
|
||||
info!("loaded drivers");
|
||||
|
||||
// We've now loaded all the drivers, so we can return.
|
||||
|
||||
Reference in new issue
Block a user