Skip to content

Commit 1c732a1

Browse files
committed
feat(bootloader-interface): add support for LoaderEntryDefault and LoaderEntryOneShot
1 parent 08b9e25 commit 1c732a1

File tree

3 files changed

+71
-8
lines changed

3 files changed

+71
-8
lines changed

src/entries.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ impl BootableEntry {
9494
self.default = true;
9595
}
9696

97+
// Unmark this entry as the default entry.
98+
pub fn unmark_default(&mut self) {
99+
self.default = false;
100+
}
101+
97102
/// Mark this entry as being pinned, which prevents prefixing.
98103
pub fn mark_pin_name(&mut self) {
99104
self.pin_name = true;

src/integrations/bootloader_interface.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ impl BootloaderInterface {
4545
| LoaderFeatures::ConfigTimeout
4646
| LoaderFeatures::ConfigTimeoutOneShot
4747
| LoaderFeatures::MenuDisable
48+
| LoaderFeatures::EntryDefault
49+
| LoaderFeatures::EntryOneShot
4850
}
4951

5052
/// Tell the system that Sprout was initialized at the current time.
@@ -275,4 +277,32 @@ impl BootloaderInterface {
275277
// We provide the unspecified value instead.
276278
Ok(BootloaderInterfaceTimeout::Unspecified)
277279
}
280+
281+
/// Get the default entry set by the bootloader interface.
282+
pub fn get_default_entry() -> Result<Option<String>> {
283+
Self::VENDOR
284+
.get_cstr16("LoaderEntryDefault")
285+
.context("unable to get default entry from bootloader interface")
286+
}
287+
288+
/// Get the oneshot entry set by the bootloader interface.
289+
/// This should be the entry we boot.
290+
pub fn get_oneshot_entry() -> Result<Option<String>> {
291+
// Acquire the value of the LoaderEntryOneShot variable.
292+
// If it is not set, return None.
293+
let Some(value) = Self::VENDOR
294+
.get_cstr16("LoaderEntryOneShot")
295+
.context("unable to get oneshot entry from bootloader interface")?
296+
else {
297+
return Ok(None);
298+
};
299+
300+
// Remove the oneshot entry from the bootloader interface.
301+
Self::VENDOR
302+
.remove("LoaderEntryOneShot")
303+
.context("unable to remove oneshot entry")?;
304+
305+
// Return the oneshot value.
306+
Ok(Some(value))
307+
}
278308
}

src/main.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,13 +262,6 @@ fn run() -> Result<()> {
262262
}
263263
}
264264

265-
// If no entries were the default, pick the first entry as the default entry.
266-
if entries.iter().all(|entry| !entry.is_default())
267-
&& let Some(entry) = entries.first_mut()
268-
{
269-
entry.mark_default();
270-
}
271-
272265
// Tell the bootloader interface what entries are available.
273266
BootloaderInterface::set_entries(entries.iter().map(|entry| entry.name()))
274267
.context("unable to set entries in bootloader interface")?;
@@ -280,8 +273,16 @@ fn run() -> Result<()> {
280273
let bootloader_interface_timeout =
281274
BootloaderInterface::get_timeout().context("unable to get bootloader interface timeout")?;
282275

276+
// Acquire the default entry from the bootloader interface.
277+
let bootloader_interface_default_entry = BootloaderInterface::get_default_entry()
278+
.context("unable to get bootloader interface default entry")?;
279+
280+
// Acquire the oneshot entry from the bootloader interface.
281+
let bootloader_interface_oneshot_entry = BootloaderInterface::get_oneshot_entry()
282+
.context("unable to get bootloader interface oneshot entry")?;
283+
283284
// If --boot is specified, boot that entry immediately.
284-
let force_boot_entry = context.root().options().boot.as_ref();
285+
let mut force_boot_entry = context.root().options().boot.clone();
285286
// If --force-menu is specified, show the boot menu regardless of the value of --boot.
286287
let mut force_boot_menu = context.root().options().force_menu;
287288

@@ -320,6 +321,33 @@ fn run() -> Result<()> {
320321
}
321322
}
322323

324+
// Apply bootloader interface default entry settings.
325+
if let Some(ref bootloader_interface_default_entry) = bootloader_interface_default_entry {
326+
// Iterate over all the entries and mark the default entry as the one specified.
327+
for entry in &mut entries {
328+
// Mark the entry as the default entry if it matches the specified entry.
329+
// If the entry does not match the specified entry, unmark it as the default entry.
330+
if entry.is_match(bootloader_interface_default_entry) {
331+
entry.mark_default();
332+
} else {
333+
entry.unmark_default();
334+
}
335+
}
336+
}
337+
338+
// Apply bootloader interface oneshot entry settings.
339+
// If set, we will force booting the oneshot entry.
340+
if let Some(ref bootloader_interface_oneshot_entry) = bootloader_interface_oneshot_entry {
341+
force_boot_entry = Some(bootloader_interface_oneshot_entry.clone());
342+
}
343+
344+
// If no entries were the default, pick the first entry as the default entry.
345+
if entries.iter().all(|entry| !entry.is_default())
346+
&& let Some(entry) = entries.first_mut()
347+
{
348+
entry.mark_default();
349+
}
350+
323351
// Convert the menu timeout to a duration.
324352
let menu_timeout = Duration::from_secs(menu_timeout);
325353

0 commit comments

Comments
 (0)