Skip to content

Commit 0368a17

Browse files
authored
Merge pull request #25 from edera-dev/azenla/shim-support
feat(boot): basic support for secure boot via shim
2 parents 2093269 + f593f5a commit 0368a17

File tree

14 files changed

+565
-53
lines changed

14 files changed

+565
-53
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ existing UEFI bootloader or booted by the hardware directly.
1818

1919
Sprout is licensed under Apache 2.0 and is open to modifications and contributions.
2020

21-
**IMPORTANT WARNING**: Sprout does not support UEFI Secure Boot yet.
21+
**IMPORTANT WARNING**: Sprout does not support all of UEFI Secure Boot yet.
2222
See [this issue](https://github.com/edera-dev/sprout/issues/20) for updates.
2323

2424
## Background
@@ -65,13 +65,13 @@ The boot menu mechanism is very rudimentary.
6565
- [x] Load Linux initrd from disk
6666
- [x] Basic boot menu
6767
- [x] BLS autoconfiguration support
68+
- [x] [Secure Boot support](https://github.com/edera-dev/sprout/issues/20): partial
6869

6970
### Roadmap
7071

7172
- [ ] [Bootloader interface support](https://github.com/edera-dev/sprout/issues/21)
7273
- [ ] [BLS specification conformance](https://github.com/edera-dev/sprout/issues/2)
7374
- [ ] [Full-featured boot menu](https://github.com/edera-dev/sprout/issues/1)
74-
- [ ] [Secure Boot support](https://github.com/edera-dev/sprout/issues/20): work in progress
7575
- [ ] [UKI support](https://github.com/edera-dev/sprout/issues/6): partial
7676
- [ ] [multiboot2 support](https://github.com/edera-dev/sprout/issues/7)
7777
- [ ] [Linux boot protocol (boot without EFI stub)](https://github.com/edera-dev/sprout/issues/7)

docs/windows-setup.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Prerequisites
44

5-
- Secure Boot disabled
5+
- Secure Boot is disabled or configured to allow Sprout
66
- UEFI Windows installation
77

88
## Step 1: Base Installation

src/actions/chainload.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::context::SproutContext;
22
use crate::integrations::bootloader_interface::BootloaderInterface;
3+
use crate::integrations::shim::{ShimInput, ShimSupport};
34
use crate::utils;
45
use crate::utils::media_loader::MediaLoaderHandle;
56
use crate::utils::media_loader::constants::linux::LINUX_EFI_INITRD_MEDIA_GUID;
@@ -35,20 +36,14 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
3536

3637
// Resolve the path to the image to chainload.
3738
let resolved = utils::resolve_path(
38-
context.root().loaded_image_path()?,
39+
Some(context.root().loaded_image_path()?),
3940
&context.stamp(&configuration.path),
4041
)
4142
.context("unable to resolve chainload path")?;
4243

43-
// Load the image to chainload.
44-
let image = uefi::boot::load_image(
45-
sprout_image,
46-
uefi::boot::LoadImageSource::FromDevicePath {
47-
device_path: &resolved.full_path,
48-
boot_policy: uefi::proto::BootPolicy::ExactMatch,
49-
},
50-
)
51-
.context("unable to load image")?;
44+
// Load the image to chainload using the shim support integration.
45+
// It will determine if the image needs to be loaded via the shim or can be loaded directly.
46+
let image = ShimSupport::load(sprout_image, ShimInput::ResolvedPath(&resolved))?;
5247

5348
// Open the LoadedImage protocol of the image to chainload.
5449
let mut loaded_image_protocol = uefi::boot::open_protocol_exclusive::<LoadedImage>(image)
@@ -95,8 +90,9 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
9590
// If an initrd is provided, register it with the EFI stack.
9691
let mut initrd_handle = None;
9792
if let Some(linux_initrd) = initrd {
98-
let content = utils::read_file_contents(context.root().loaded_image_path()?, &linux_initrd)
99-
.context("unable to read linux initrd")?;
93+
let content =
94+
utils::read_file_contents(Some(context.root().loaded_image_path()?), &linux_initrd)
95+
.context("unable to read linux initrd")?;
10096
let handle =
10197
MediaLoaderHandle::register(LINUX_EFI_INITRD_MEDIA_GUID, content.into_boxed_slice())
10298
.context("unable to register linux initrd")?;

src/actions/edera.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ fn register_media_loader_file(
9898
// Stamp the path to the file.
9999
let path = context.stamp(path);
100100
// Read the file contents.
101-
let content = utils::read_file_contents(context.root().loaded_image_path()?, &path)
101+
let content = utils::read_file_contents(Some(context.root().loaded_image_path()?), &path)
102102
.context(format!("unable to read {} file", what))?;
103103
// Register the media loader.
104104
let handle = MediaLoaderHandle::register(guid, content.into_boxed_slice())

src/actions/splash.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ pub fn splash(context: Rc<SproutContext>, configuration: &SplashConfiguration) -
143143
// Stamp the image path value.
144144
let image = context.stamp(&configuration.image);
145145
// Read the image contents.
146-
let image = read_file_contents(context.root().loaded_image_path()?, &image)?;
146+
let image = read_file_contents(Some(context.root().loaded_image_path()?), &image)?;
147147
// Decode the image as a PNG.
148148
let image = ImageReader::with_format(Cursor::new(image), ImageFormat::Png)
149149
.decode()

src/config/loader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn load_raw_config(options: &SproutOptions) -> Result<Vec<u8>> {
1919
info!("configuration file: {}", options.config);
2020

2121
// Read the contents of the sprout config file.
22-
let content = utils::read_file_contents(&path, &options.config)
22+
let content = utils::read_file_contents(Some(&path), &options.config)
2323
.context("unable to read sprout config file")?;
2424
// Return the contents of the sprout config file.
2525
Ok(content)

src/drivers.rs

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use crate::context::SproutContext;
2+
use crate::integrations::shim::{ShimInput, ShimSupport};
23
use crate::utils;
34
use anyhow::{Context, Result};
45
use log::info;
56
use serde::{Deserialize, Serialize};
67
use std::collections::BTreeMap;
78
use std::rc::Rc;
89
use uefi::boot::SearchType;
9-
use uefi::proto::device_path::LoadedImageDevicePath;
1010

1111
/// Declares a driver configuration.
1212
/// Drivers allow extending the functionality of Sprout.
@@ -23,28 +23,17 @@ pub struct DriverDeclaration {
2323
fn load_driver(context: Rc<SproutContext>, driver: &DriverDeclaration) -> Result<()> {
2424
// Acquire the handle and device path of the loaded image.
2525
let sprout_image = uefi::boot::image_handle();
26-
let image_device_path_protocol =
27-
uefi::boot::open_protocol_exclusive::<LoadedImageDevicePath>(sprout_image)
28-
.context("unable to open loaded image device path protocol")?;
2926

30-
// Get the device path root of the sprout image.
31-
let mut full_path = utils::device_path_root(&image_device_path_protocol)?;
32-
33-
// Push the path of the driver from the root.
34-
full_path.push_str(&context.stamp(&driver.path));
35-
36-
// Convert the path to a device path.
37-
let device_path = utils::text_to_device_path(&full_path)?;
38-
39-
// Load the driver image.
40-
let image = uefi::boot::load_image(
41-
sprout_image,
42-
uefi::boot::LoadImageSource::FromDevicePath {
43-
device_path: &device_path,
44-
boot_policy: uefi::proto::BootPolicy::ExactMatch,
45-
},
27+
// Resolve the path to the driver image.
28+
let resolved = utils::resolve_path(
29+
Some(context.root().loaded_image_path()?),
30+
&context.stamp(&driver.path),
4631
)
47-
.context("unable to load image")?;
32+
.context("unable to resolve path to driver")?;
33+
34+
// Load the driver image using the shim support integration.
35+
// It will determine if the image needs to be loaded via the shim or can be loaded directly.
36+
let image = ShimSupport::load(sprout_image, ShimInput::ResolvedPath(&resolved))?;
4837

4938
// Start the driver image, this is expected to return control to sprout.
5039
// There is no guarantee that the driver will actually return control as it is

src/generators/bls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub fn generate(context: Rc<SproutContext>, bls: &BlsConfiguration) -> Result<Ve
4949
let path = context.stamp(&bls.path);
5050

5151
// Resolve the path to the BLS directory.
52-
let bls_resolved = utils::resolve_path(context.root().loaded_image_path()?, &path)
52+
let bls_resolved = utils::resolve_path(Some(context.root().loaded_image_path()?), &path)
5353
.context("unable to resolve bls path")?;
5454

5555
// Construct a filesystem path to the BLS entries directory.

src/integrations.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
/// Implements support for the bootloader interface specification.
22
pub mod bootloader_interface;
3+
/// Implements support for the shim loader application for Secure Boot.
4+
pub mod shim;

0 commit comments

Comments
 (0)