diff --git a/src/generators/bls.rs b/src/generators/bls.rs index a9572b2..ed8bab3 100644 --- a/src/generators/bls.rs +++ b/src/generators/bls.rs @@ -4,6 +4,7 @@ use crate::generators::bls::entry::BlsEntry; use crate::utils; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; +use std::cmp::Ordering; use std::rc::Rc; use std::str::FromStr; use uefi::cstr16; @@ -40,6 +41,55 @@ fn quirk_initrd_remove_tuned(input: String) -> String { input.replace("$tuned_initrd", "").trim().to_string() } +/// Sorts two entries according to the BLS sort system. +/// Reference: https://uapi-group.org/specifications/specs/boot_loader_specification/#sorting +fn sort_entries(a: &(BlsEntry, BootableEntry), b: &(BlsEntry, BootableEntry)) -> Ordering { + // Grab the components of both entries. + let (a_bls, a_boot) = a; + let (b_bls, b_boot) = b; + + // Grab the sort keys from both entries. + let a_sort_key = a_bls.sort_key(); + let b_sort_key = b_bls.sort_key(); + + // Compare the sort keys of both entries. + match a_sort_key.cmp(&b_sort_key) { + // If A and B sort keys are equal, sort by machine-id. + Ordering::Equal => { + // Grab the machine-id from both entries. + let a_machine_id = a_bls.machine_id(); + let b_machine_id = b_bls.machine_id(); + + // Compare the machine-id of both entries. + match a_machine_id.cmp(&b_machine_id) { + // If both machine-id values are equal, sort by version. + Ordering::Equal => { + // Grab the version from both entries. + let a_version = a_bls.version(); + let b_version = b_bls.version(); + + // Compare the version of both entries, sorting newer versions first. + match b_version.cmp(&a_version) { + // If both versions are equal, sort by file name in reverse order. + Ordering::Equal => { + // Grab the file name from both entries. + let a_name = a_boot.name(); + let b_name = b_boot.name(); + + // Compare the file names of both entries, sorting newer entries first. + b_name.cmp(a_name) + } + other => other, + } + } + other => other, + } + } + + other => other, + } +} + /// 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(context: Rc, bls: &BlsConfiguration) -> Result> { @@ -132,9 +182,11 @@ pub fn generate(context: Rc, bls: &BlsConfiguration) -> Result, bls: &BlsConfiguration) -> Result, /// The path to an EFI image. pub efi: Option, + /// The sort key for the entry. + pub sort_key: Option, + /// The version of the entry. + pub version: Option, + /// The machine id of the entry. + pub machine_id: Option, } /// Parser for a BLS entry. @@ -30,6 +36,9 @@ impl FromStr for BlsEntry { let mut linux: Option = None; let mut initrd: Option = None; let mut efi: Option = None; + let mut sort_key: Option = None; + let mut version: Option = None; + let mut machine_id: Option = None; // Iterate over each line in the input and parse it. for line in input.lines() { @@ -74,6 +83,18 @@ impl FromStr for BlsEntry { efi = Some(value.trim().to_string()); } + "sort-key" => { + sort_key = Some(value.trim().to_string()); + } + + "version" => { + version = Some(value.trim().to_string()); + } + + "machine-id" => { + machine_id = Some(value.trim().to_string()); + } + // Ignore any other key. _ => { continue; @@ -88,6 +109,9 @@ impl FromStr for BlsEntry { linux, initrd, efi, + sort_key, + version, + machine_id, }) } } @@ -125,4 +149,19 @@ impl BlsEntry { pub fn title(&self) -> Option { self.title.clone() } + + /// Fetches the sort key of the entry, if any. + pub fn sort_key(&self) -> Option { + self.sort_key.clone() + } + + /// Fetches the version of the entry, if any. + pub fn version(&self) -> Option { + self.version.clone() + } + + /// Fetches the machine id of the entry, if any. + pub fn machine_id(&self) -> Option { + self.machine_id.clone() + } }