17 Commits

Author SHA1 Message Date
b59626888e add bls quirk to support fedora out of the box 2025-10-20 11:33:33 -07:00
e3bae1dc63 repair fedora setup guide to include copying grub modules 2025-10-20 11:24:42 -07:00
3cd3491df0 fix bad autocomplete in fedora setup guide 2025-10-20 10:37:28 -07:00
e08f6e629f add fedora setup guide 2025-10-20 10:34:55 -07:00
398be12ac4 fix release tag 2025-10-20 09:26:03 -07:00
7407150bff attempt new release mechanism using draft releases and manual job 2025-10-20 09:24:27 -07:00
c23b11469d attempt at codeql config for the right target 2025-10-20 09:08:29 -07:00
29529ddacd remove broken codeql configs, will figure this out later 2025-10-20 01:51:20 -07:00
d2f47dcad6 attempt to configure rust extractor for the right target 2025-10-20 01:44:27 -07:00
f3b7007432 codeql advanced support 2025-10-20 01:29:03 -07:00
4f30d51bb2 make sure rust toolchain is from rust-toolchain.toml in github workflows 2025-10-20 01:18:28 -07:00
48e3644977 fix pull request actions 2025-10-20 01:14:08 -07:00
345e1c800c Merge pull request #11 from edera-dev/dependabot/cargo/cargo-updates-d94e05c250
Bump toml from 0.9.7 to 0.9.8 in the cargo-updates group
2025-10-20 00:33:30 -07:00
e5ae612398 Merge pull request #10 from edera-dev/dependabot/docker/docker-updates-d0b0844295
Bump rustlang/rust from `b8107fa` to `141e9a7` in the docker-updates group
2025-10-20 00:31:54 -07:00
dependabot[bot]
f0427faab2 Bump toml from 0.9.7 to 0.9.8 in the cargo-updates group
Bumps the cargo-updates group with 1 update: [toml](https://github.com/toml-rs/toml).


Updates `toml` from 0.9.7 to 0.9.8
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.9.7...toml-v0.9.8)

---
updated-dependencies:
- dependency-name: toml
  dependency-version: 0.9.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-20 07:29:29 +00:00
dependabot[bot]
6278274288 Bump rustlang/rust in the docker-updates group
Bumps the docker-updates group with 1 update: rustlang/rust.


Updates `rustlang/rust` from `b8107fa` to `141e9a7`

---
updated-dependencies:
- dependency-name: rustlang/rust
  dependency-version: nightly-alpine
  dependency-type: direct:production
  dependency-group: docker-updates
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-20 07:29:15 +00:00
4cd27a5010 add docker to dependabot 2025-10-20 00:17:49 -07:00
11 changed files with 276 additions and 33 deletions

5
.github/codeql/codeql-config.yaml vendored Normal file
View File

@@ -0,0 +1,5 @@
name: "codeql-config"
extractor-options:
rust:
cargo_target: x86_64-unknown-uefi

View File

@@ -26,3 +26,16 @@ updates:
cargo-dev-updates:
dependency-type: development
applies-to: version-updates
- package-ecosystem: docker
directory: /
schedule:
interval: weekly
cooldown:
default-days: 7
groups:
docker-updates:
dependency-type: production
applies-to: version-updates
docker-dev-updates:
dependency-type: development
applies-to: version-updates

View File

@@ -26,10 +26,9 @@ jobs:
with:
persist-credentials: false
- name: 'install nightly rust toolchain with rustfmt'
- name: 'install rust toolchain with rustfmt'
run: |
rustup update --no-self-update nightly
rustup default nightly
cargo version
rustup component add rustfmt
- name: 'cargo fmt'
@@ -57,10 +56,9 @@ jobs:
with:
persist-credentials: false
- name: 'install nightly rust toolchain'
- name: 'install rust toolchain'
run: |
rustup update --no-self-update nightly
rustup default nightly
cargo version
- name: cargo build
run: cargo build --target "${TARGET_ARCH}-unknown-uefi"
@@ -87,10 +85,9 @@ jobs:
with:
persist-credentials: false
- name: 'install nightly rust toolchain with clippy'
- name: 'install rust toolchain with clippy'
run: |
rustup update --no-self-update nightly
rustup default stable
cargo version
rustup component add clippy
- name: cargo clippy

53
.github/workflows/codeql.yaml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: codeql
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '33 16 * * 0'
permissions:
contents: read # Needed to checkout the repository.
jobs:
analyze:
name: analyze (${{ matrix.language }})
runs-on: 'ubuntu-latest'
permissions:
security-events: write # Needed to upload results.
packages: read # Needed to fetch internal or private CodeQL packs.
actions: read # Needed to read workflows.
contents: read # Needed to checkout the repository.
strategy:
fail-fast: false
matrix:
include:
- language: actions
build-mode: none
- language: rust
build-mode: none
steps:
- name: harden runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
with:
egress-policy: audit
- name: checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
persist-credentials: false
- name: initialize codeql
uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 #v4
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@16140ae1a102900babc80a33c44059580f687047 #v4
with:
category: "/language:${{matrix.language}}"

View File

@@ -1,9 +1,12 @@
name: publish
on:
release:
types:
- created
workflow_dispatch:
inputs:
release-tag:
description: 'Release Tag'
required: true
type: string
push:
branches:
@@ -39,10 +42,9 @@ jobs:
with:
persist-credentials: false
- name: 'install nightly rust toolchain'
- name: 'install rust toolchain'
run: |
rustup update --no-self-update nightly
rustup default nightly
cargo version
- name: 'assemble artifacts'
run: ./hack/assemble.sh
@@ -65,10 +67,18 @@ jobs:
with:
app-id: "${{ secrets.EDERA_CULTIVATION_APP_ID }}"
private-key: "${{ secrets.EDERA_CULTIVATION_APP_PRIVATE_KEY }}"
if: ${{ github.event.inputs.release-tag != '' }}
- name: 'upload release artifacts'
run: ./hack/ci/upload-release-assets.sh
env:
GITHUB_TOKEN: "${{ steps.generate-token.outputs.token }}"
RELEASE_TAG: "${{ github.event.release.tag_name }}"
if: ${{ github.event_name == 'release' }}
RELEASE_TAG: "${{ github.event.inputs.release-tag }}"
if: ${{ github.event.inputs.release-tag != '' }}
- name: 'mark release as published'
run: gh release edit "${RELEASE_TAG}" --draft=false --verify-tag
env:
GITHUB_TOKEN: "${{ steps.generate-token.outputs.token }}"
RELEASE_TAG: "${{ github.event.inputs.release-tag }}"
if: ${{ github.event.inputs.release-tag != '' }}

20
Cargo.lock generated
View File

@@ -252,9 +252,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee"
checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392"
dependencies = [
"serde_core",
]
@@ -277,9 +277,9 @@ dependencies = [
[[package]]
name = "toml"
version = "0.9.7"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8"
dependencies = [
"indexmap",
"serde_core",
@@ -292,27 +292,27 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "0.7.2"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1"
checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_parser"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109"
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
[[package]]
name = "ucs2"

View File

@@ -9,7 +9,7 @@ edition = "2024"
[dependencies]
anyhow = "1.0.100"
toml = "0.9.7"
toml = "0.9.8"
log = "0.4.28"
[dependencies.image]

View File

@@ -2,7 +2,7 @@
ARG RUST_PROFILE=release
ARG RUST_TARGET_SUBDIR=release
FROM --platform=$BUILDPLATFORM rustlang/rust:nightly-alpine@sha256:b8107fa66d3e5ad7f729d3347c7feedbd3f4b60b01006edce39eb6b994ff00bd AS build
FROM --platform=$BUILDPLATFORM rustlang/rust:nightly-alpine@sha256:141e9a7f13f77237dd4d462364c3a1b21cb8a6791d8924c409573e77b788af5e AS build
RUN apk --no-cache add musl-dev busybox-static
ARG RUST_PROFILE
RUN adduser -S -s /bin/sh build

View File

@@ -18,6 +18,15 @@ existing UEFI bootloader or booted by the hardware directly.
Sprout is licensed under Apache 2.0 and is open to modifications and contributions.
## Documentation
- [Fedora Setup Guide]
- [Development Guide]
- [Contributing Guide]
- [Sprout License]
- [Code of Conduct]
- [Security Policy]
## Features
NOTE: Currently, Sprout is experimental and is not intended for production use. For example, it doesn't currently
@@ -116,3 +125,10 @@ chainload.path = "$boot\\$chainload"
chainload.options = ["$options"]
chainload.linux-initrd = "$boot\\$initrd"
```
[Fedora Setup Guide]: ./docs/fedora-setup.md
[Development Guide]: ./DEVELOPMENT.md
[Contributing Guide]: ./CONTRIBUTING.md
[Sprout License]: ./LICENSE
[Code of Conduct]: ./CODE_OF_CONDUCT.md
[Security Policy]: ./SECURITY.md

134
docs/fedora-setup.md Normal file
View File

@@ -0,0 +1,134 @@
# Sprout on Fedora
## Prerequisites
- Modern Fedora release: tested on Fedora Workstation 42 and 43
- EFI System Partition mounted on `/boot/efi` (the default)
- ext4 or FAT32/exFAT formatted `/boot` partition
## Step 1: Base Installation
Download the latest sprout.efi release from the [GitHub releases page](https://github.com/edera-dev/sprout/releases).
For x86_64 systems, download the `sprout-x86_64.efi` file, and for ARM systems, download the `sprout-aarch64.efi` file.
Copy the downloaded `sprout.efi` file to `/boot/efi/EFI/BOOT/sprout.efi` on your EFI System Partition.
Additionally, you will want to install the `edk2-ext4` package, which provides the ext4 filesystem support for Sprout.
```bash
# Install the edk2-ext4 package which provides ext4 support for Sprout.
$ sudo dnf install edk2-ext4
# Create a directory for sprout drivers.
$ sudo mkdir -p /boot/efi/sprout/drivers
# For x86_64 systems, copy the ext4x64.efi driver to the sprout drivers directory.
$ sudo cp /usr/share/edk2/drivers/ext4x64.efi /boot/efi/sprout/drivers/ext4.efi
# For ARM64 systems, copy the ext4aa64.efi driver to the sprout drivers directory.
$ sudo cp /usr/share/edk2/drivers/ext4aa64.efi /boot/efi/sprout/drivers/ext4.efi
```
## Step 2: Configure Sprout
Since Fedora uses the BLS specification, you can use the `bls` generator to autoconfigure Sprout for Fedora.
Write the following file to `/boot/efi/sprout.toml`:
```toml
# sprout configuration: version 1
version = 1
# load an EFI driver for ext4.
[drivers.ext4]
path = "\\sprout\\drivers\\ext4.efi"
# extract the full path of the first filesystem
# that contains \loader\entries as a directory
# into the value called "boot"
[extractors.boot.filesystem-device-match]
has-item = "\\loader\\entries"
# use the sprout bls module to scan a bls
# directory for entries and load them as boot
# entries in sprout, using the entry template
# as specified here. the bls action below will
# be passed the extracted values from bls.
[generators.boot.bls]
path = "$boot\\loader\\entries"
entry.title = "$title"
entry.actions = ["bls"]
# the action that is used for each bls entry above.
[actions.bls]
chainload.path = "$boot\\$chainload"
chainload.options = ["$options"]
chainload.linux-initrd = "$boot\\$initrd"
```
## Step 3, Option 1: Configure GRUB to load Sprout (recommended)
You can configure GRUB to add a boot entry for Sprout, so you can continue to use GRUB without interruption.
GRUB needs to be configured with the chainloader module to load Sprout.
### x86_64
```bash
# Install x86_64 GRUB modules.
$ sudo dnf install grub2-efi-x64-modules
# Copy x86_64 GRUB modules to /boot/grub2 for use by GRUB if it isn't installed already.
$ [ ! -d /boot/grub2/x86_64-efi ] && sudo cp -r /usr/lib/grub/x86_64-efi /boot/grub2/x86_64-efi
```
### ARM64
```bash
# Install ARM64 GRUB modules.
$ sudo dnf install grub2-efi-aa64-modules
# Copy ARM64 GRUB modules to /boot/grub2 for use by GRUB if it isn't installed already.
$ [ ! -d /boot/grub2/arm64-efi ] && sudo cp -r /usr/lib/grub/arm64-efi /boot/grub2/x86_64-efi
```
You will need to find the UUID of your EFI System Partition. You can do this by running the following command:
```bash
$ grep "/boot/efi" /etc/fstab | awk '{print $1}' | awk -F '=' '{print $2}'
SAMPLE-VALUE
```
The GRUB configuration for Sprout is as follows, replace `SAMPLE-VALUE` with the UUID of your EFI System Partition:
```grub
menuentry 'Sprout' $menuentry_id_option 'sprout' {
insmod part_gpt
insmod fat
insmod chain
search --no-floppy --fs-uuid --set=root SAMPLE-VALUE
chainloader /EFI/BOOT/sprout.efi
}
```
You can append this to `/etc/grub.d/40_custom` and run the following command to update your configuration:
```bash
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
```
To update your GRUB configuration.
Make sure to update your GRUB environment to show the menu:
```bash
$ sudo grub2-editenv - set menu_auto_hide=0
```
You may now reboot your system and select Sprout from the GRUB menu.
## Step 3, Option 2: Configure your EFI firmware for Sprout
You can configure your EFI boot menu to show Sprout as an option.
To do so, please find the partition device of your EFI System Partition and run the following:
```bash
$ sudo efibootmgr -d /dev/esp_partition_here -C -L 'Sprout' -l '\EFI\BOOT\sprout.efi'
```
This will add a new entry to your EFI boot menu called `Sprout` that will boot Sprout with your configuration.
Now if you boot into your UEFI firmware, you should see Sprout as an option to boot.

View File

@@ -33,6 +33,13 @@ fn default_bls_path() -> String {
BLS_TEMPLATE_PATH.to_string()
}
// TODO(azenla): remove this once variable substitution is implemented.
/// This function is used to remove the `tuned_initrd` variable from entry values.
/// Fedora uses tuned which adds an initrd that shouldn't be used.
fn quirk_initrd_remove_tuned(input: String) -> String {
input.replace("$tuned_initrd", "").trim().to_string()
}
/// Generates entries from the BLS entries directory using the specified `bls` configuration and
/// `context`. The BLS conversion is best-effort and will ignore any unsupported entries.
pub fn generate(
@@ -108,10 +115,18 @@ pub fn generate(
// Produce a new sprout context for the entry with the extracted values.
let mut context = context.fork();
context.set("title", entry.title().unwrap_or(name));
context.set("chainload", entry.chainload_path().unwrap_or_default());
context.set("options", entry.options().unwrap_or_default());
context.set("initrd", entry.initrd_path().unwrap_or_default());
let title = entry.title().unwrap_or(name);
let chainload = entry.chainload_path().unwrap_or_default();
let options = entry.options().unwrap_or_default();
// Put the initrd through a quirk modifier to support Fedora.
let initrd = quirk_initrd_remove_tuned(entry.initrd_path().unwrap_or_default());
context.set("title", title);
context.set("chainload", chainload);
context.set("options", options);
context.set("initrd", initrd);
// Add the entry to the list with a frozen context.
entries.push((context.freeze(), bls.entry.clone()));