Skip to content

Commit cff5532

Browse files
committed
feat(bootloader-interface): implement support for LoaderImageIdentifier
1 parent d2bef03 commit cff5532

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

src/integrations/bootloader_interface.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::platform::timer::PlatformTimer;
2+
use crate::utils::device_path_subpath;
23
use anyhow::{Context, Result};
4+
use uefi::proto::device_path::DevicePath;
35
use uefi::{CString16, Guid, guid};
46
use uefi_raw::table::runtime::{VariableAttributes, VariableVendor};
57

@@ -28,6 +30,12 @@ impl BootloaderInterface {
2830
Self::set_cstr16(key, &elapsed.as_micros().to_string())
2931
}
3032

33+
/// Tell the system the relative path to the partition root of the current bootloader.
34+
pub fn set_loader_path(path: &DevicePath) -> Result<()> {
35+
let subpath = device_path_subpath(path).context("unable to get loader path subpath")?;
36+
Self::set_cstr16("LoaderImageIdentifier", &subpath)
37+
}
38+
3139
/// Tell the system what the partition GUID of the ESP Sprout was booted from is.
3240
pub fn set_partition_guid(guid: &Guid) -> Result<()> {
3341
Self::set_cstr16("LoaderDevicePartUUID", &guid.to_string())
@@ -39,11 +47,14 @@ impl BootloaderInterface {
3947
// Iterate over the entries and convert them to CString16 placing them into data.
4048
let mut data = Vec::new();
4149
for entry in entries {
42-
// Convert the entry to a CString16.
43-
let entry = CString16::try_from(entry.as_ref())
44-
.context("unable to convert entry to CString16")?;
50+
// Convert the entry to CString16 little endian.
51+
let encoded = entry
52+
.as_ref()
53+
.encode_utf16()
54+
.flat_map(|c| c.to_le_bytes())
55+
.collect::<Vec<u8>>();
4556
// Write the bytes (including the null terminator) into the data buffer.
46-
data.extend_from_slice(entry.as_bytes());
57+
data.extend_from_slice(&encoded);
4758
}
4859
Self::set("LoaderEntries", &data)
4960
}
@@ -91,8 +102,11 @@ impl BootloaderInterface {
91102
/// Set a bootloader interface variable specified by `key` to `value`, converting the value to
92103
/// a [CString16].
93104
fn set_cstr16(key: &str, value: &str) -> Result<()> {
94-
let value =
95-
CString16::try_from(value).context("unable to convert variable value to CString16")?;
96-
Self::set(key, value.as_bytes())
105+
// Encode the value as a CString16 little endian.
106+
let encoded = value
107+
.encode_utf16()
108+
.flat_map(|c| c.to_le_bytes())
109+
.collect::<Vec<u8>>();
110+
Self::set(key, &encoded)
97111
}
98112
}

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ fn run() -> Result<()> {
112112
.context("unable to set partition guid in bootloader interface")?;
113113
}
114114

115+
// Tell the bootloader interface what the loaded image path is.
116+
BootloaderInterface::set_loader_path(&loaded_image_path)
117+
.context("unable to set loader path in bootloader interface")?;
118+
115119
// Create the root context.
116120
let mut root = RootContext::new(loaded_image_path, timer, options);
117121

0 commit comments

Comments
 (0)