From e68f6c482abafa8b99725e4d5cb0d02b0acb8693 Mon Sep 17 00:00:00 2001 From: Hamed Akhondzadeh Date: Fri, 24 Jul 2026 11:11:05 -0700 Subject: [PATCH 1/4] fix(vera_rubin): normalize BootOrder entries for BootOption GET/PATCH Vera Rubin host BMC firmware reports BootOrder strings like "Boot0019: Ubuntu" while BootOption resources live at bare Ids. Strip the display-name suffix before GET and preserve firmware format when reordering boot options. --- src/model/boot.rs | 55 ++++++++++++++++++++++++++++++++++++++++ src/nvidia_vera_rubin.rs | 29 ++++++++++++++++++--- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/model/boot.rs b/src/model/boot.rs index beae265e1..082ec5710 100644 --- a/src/model/boot.rs +++ b/src/model/boot.rs @@ -145,3 +145,58 @@ impl std::fmt::Display for TrustedModuleRequiredToBoot { std::fmt::Debug::fmt(self, f) } } + +/// Extracts the BootOption resource Id from a `BootOrder` entry. +/// +/// Vera Rubin host BMC firmware reports entries like `Boot0019: Ubuntu` while +/// BootOption resources are addressed at `/BootOptions/Boot0019`. +pub fn boot_order_entry_boot_option_id(entry: &str) -> &str { + entry.split_once(": ").map(|(id, _)| id).unwrap_or(entry) +} + +/// Formats a BootOrder entry the way Vera Rubin firmware exposes it. +pub fn boot_order_entry_with_display_name(id: &str, display_name: &str) -> String { + format!("{id}: {display_name}") +} + +/// Returns true when the BMC uses `Id: DisplayName` strings in `BootOrder`. +pub fn boot_order_uses_display_name_suffix(entries: &[String]) -> bool { + entries.iter().any(|entry| entry.contains(": ")) +} + +#[cfg(test)] +mod boot_order_entry_tests { + use super::{ + boot_order_entry_boot_option_id, boot_order_entry_with_display_name, + boot_order_uses_display_name_suffix, + }; + + #[test] + fn boot_order_entry_boot_option_id_strips_display_name_suffix() { + assert_eq!( + boot_order_entry_boot_option_id("Boot0019: Ubuntu"), + "Boot0019" + ); + assert_eq!(boot_order_entry_boot_option_id("Boot0010"), "Boot0010"); + } + + #[test] + fn boot_order_entry_with_display_name_formats_like_firmware() { + assert_eq!( + boot_order_entry_with_display_name("Boot0019", "Ubuntu"), + "Boot0019: Ubuntu" + ); + } + + #[test] + fn boot_order_uses_display_name_suffix_detects_firmware_format() { + assert!(boot_order_uses_display_name_suffix(&[ + "Boot0019: Ubuntu".to_string(), + "Boot0010: UEFI HTTPv4 (MAC:F4204D494ECC)".to_string(), + ])); + assert!(!boot_order_uses_display_name_suffix(&[ + "Boot0019".to_string(), + "Boot0010".to_string(), + ])); + } +} diff --git a/src/nvidia_vera_rubin.rs b/src/nvidia_vera_rubin.rs index ccd23e064..b26c1b6ce 100644 --- a/src/nvidia_vera_rubin.rs +++ b/src/nvidia_vera_rubin.rs @@ -1399,14 +1399,26 @@ impl Bmc { let boot_options = self.s.get_system().await?.boot.boot_order; let actual_first_boot_option = if let Some(first) = boot_options.first() { - Some(self.s.get_boot_option(first.as_str()).await?.display_name) + Some( + self.s + .get_boot_option(crate::model::boot::boot_order_entry_boot_option_id( + first.as_str(), + )) + .await? + .display_name, + ) } else { None }; let mut expected_first_boot_option = None; for member in &boot_options { - let b = self.s.get_boot_option(member.as_str()).await?; + let b = self + .s + .get_boot_option(crate::model::boot::boot_order_entry_boot_option_id( + member.as_str(), + )) + .await?; if b.display_name.starts_with(&boot_option_name) { expected_first_boot_option = Some(b.display_name); break; @@ -1473,11 +1485,20 @@ impl Bmc { }; let target_id = target.id.clone(); + let uses_display_name_suffix = + crate::model::boot::boot_order_uses_display_name_suffix(&system.boot.boot_order); + let first_entry = if uses_display_name_suffix { + crate::model::boot::boot_order_entry_with_display_name(&target_id, &target.display_name) + } else { + target_id.clone() + }; // Prepend the found option to the front of the existing boot order let mut ordered = system.boot.boot_order; - ordered.retain(|id| id != &target_id); - ordered.insert(0, target_id); + ordered.retain(|entry| { + crate::model::boot::boot_order_entry_boot_option_id(entry) != target_id.as_str() + }); + ordered.insert(0, first_entry); Ok(ordered) } From 513c6ba0c8f5601ecbbfca601fbd9f91c753ae91 Mon Sep 17 00:00:00 2001 From: Hamed Akhondzadeh Date: Fri, 24 Jul 2026 12:33:58 -0700 Subject: [PATCH 2/4] refine(vera_rubin): extract boot_order_prepend_first and add patch tests Add boot_order_prepend_first helper with unit tests for the PATCH path, simplify vera_rubin boot-order reordering, and fix stale GB200 error text. --- src/model/boot.rs | 62 ++++++++++++++++++++++++++++++++++++++-- src/nvidia_vera_rubin.rs | 24 ++++------------ 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/model/boot.rs b/src/model/boot.rs index 082ec5710..e021dfa13 100644 --- a/src/model/boot.rs +++ b/src/model/boot.rs @@ -161,14 +161,34 @@ pub fn boot_order_entry_with_display_name(id: &str, display_name: &str) -> Strin /// Returns true when the BMC uses `Id: DisplayName` strings in `BootOrder`. pub fn boot_order_uses_display_name_suffix(entries: &[String]) -> bool { - entries.iter().any(|entry| entry.contains(": ")) + entries + .iter() + .any(|entry| boot_order_entry_boot_option_id(entry) != entry.as_str()) +} + +/// Prepends a boot option to `BootOrder`, preserving Vera Rubin firmware entry format. +pub fn boot_order_prepend_first( + boot_order: &[String], + target_id: &str, + target_display_name: &str, +) -> Vec { + let first_entry = if boot_order_uses_display_name_suffix(boot_order) { + boot_order_entry_with_display_name(target_id, target_display_name) + } else { + target_id.to_string() + }; + + let mut ordered = boot_order.to_vec(); + ordered.retain(|entry| boot_order_entry_boot_option_id(entry) != target_id); + ordered.insert(0, first_entry); + ordered } #[cfg(test)] mod boot_order_entry_tests { use super::{ boot_order_entry_boot_option_id, boot_order_entry_with_display_name, - boot_order_uses_display_name_suffix, + boot_order_prepend_first, boot_order_uses_display_name_suffix, }; #[test] @@ -199,4 +219,42 @@ mod boot_order_entry_tests { "Boot0010".to_string(), ])); } + + #[test] + fn boot_order_prepend_first_uses_id_colon_display_name_when_firmware_requires_it() { + let current = vec![ + "Boot0010: UEFI HTTPv4 (MAC:AA)".to_string(), + "Boot0019: Ubuntu".to_string(), + ]; + + let ordered = boot_order_prepend_first(¤t, "Boot0019", "UEFI"); + + assert_eq!(ordered[0], "Boot0019: UEFI"); + assert_eq!(ordered.len(), 2); + assert_eq!(ordered[1], "Boot0010: UEFI HTTPv4 (MAC:AA)"); + } + + #[test] + fn boot_order_prepend_first_uses_bare_id_for_legacy_boot_order_format() { + let current = vec!["Boot0010".to_string(), "Boot0019".to_string()]; + + let ordered = boot_order_prepend_first(¤t, "Boot0019", "UEFI"); + + assert_eq!(ordered[0], "Boot0019"); + assert_eq!(ordered[1], "Boot0010"); + } + + #[test] + fn boot_order_prepend_first_replaces_existing_entry_for_same_boot_option_id() { + let current = vec![ + "Boot0019: Ubuntu".to_string(), + "Boot0010: UEFI HTTPv4 (MAC:AA)".to_string(), + ]; + + let ordered = boot_order_prepend_first(¤t, "Boot0019", "UEFI"); + + assert_eq!(ordered[0], "Boot0019: UEFI"); + assert_eq!(ordered.len(), 2); + assert!(!ordered.contains(&"Boot0019: Ubuntu".to_string())); + } } diff --git a/src/nvidia_vera_rubin.rs b/src/nvidia_vera_rubin.rs index b26c1b6ce..1825164aa 100644 --- a/src/nvidia_vera_rubin.rs +++ b/src/nvidia_vera_rubin.rs @@ -954,7 +954,7 @@ impl Redfish for Bmc { ) -> crate::RedfishFuture<'a, Result> { Box::pin(async move { Err(RedfishError::NotSupported(format!( - "GB200 doesn't have Systems EthernetInterface {id}" + "Vera Rubin doesn't have Systems EthernetInterface {id}" ))) }) } @@ -1484,23 +1484,11 @@ impl Bmc { }); }; - let target_id = target.id.clone(); - let uses_display_name_suffix = - crate::model::boot::boot_order_uses_display_name_suffix(&system.boot.boot_order); - let first_entry = if uses_display_name_suffix { - crate::model::boot::boot_order_entry_with_display_name(&target_id, &target.display_name) - } else { - target_id.clone() - }; - - // Prepend the found option to the front of the existing boot order - let mut ordered = system.boot.boot_order; - ordered.retain(|entry| { - crate::model::boot::boot_order_entry_boot_option_id(entry) != target_id.as_str() - }); - ordered.insert(0, first_entry); - - Ok(ordered) + Ok(crate::model::boot::boot_order_prepend_first( + &system.boot.boot_order, + &target.id, + &target.display_name, + )) } async fn get_system_event_log(&self) -> Result, RedfishError> { From bbfcecfc525cb81200840716669949693d1ec1aa Mon Sep 17 00:00:00 2001 From: Hamed Akhondzadeh Date: Fri, 24 Jul 2026 14:30:24 -0700 Subject: [PATCH 3/4] Fix: move some helper function from boot.rs to vera_rubin.rs --- src/model/boot.rs | 117 +++--------------------------------- src/nvidia_vera_rubin.rs | 125 +++++++++++++++++++++++++++++---------- 2 files changed, 100 insertions(+), 142 deletions(-) diff --git a/src/model/boot.rs b/src/model/boot.rs index e021dfa13..703c2d2d6 100644 --- a/src/model/boot.rs +++ b/src/model/boot.rs @@ -146,115 +146,12 @@ impl std::fmt::Display for TrustedModuleRequiredToBoot { } } -/// Extracts the BootOption resource Id from a `BootOrder` entry. +/// Returns the boot option reference embedded in a `BootOrder` entry. /// -/// Vera Rubin host BMC firmware reports entries like `Boot0019: Ubuntu` while -/// BootOption resources are addressed at `/BootOptions/Boot0019`. -pub fn boot_order_entry_boot_option_id(entry: &str) -> &str { - entry.split_once(": ").map(|(id, _)| id).unwrap_or(entry) -} - -/// Formats a BootOrder entry the way Vera Rubin firmware exposes it. -pub fn boot_order_entry_with_display_name(id: &str, display_name: &str) -> String { - format!("{id}: {display_name}") -} - -/// Returns true when the BMC uses `Id: DisplayName` strings in `BootOrder`. -pub fn boot_order_uses_display_name_suffix(entries: &[String]) -> bool { - entries - .iter() - .any(|entry| boot_order_entry_boot_option_id(entry) != entry.as_str()) -} - -/// Prepends a boot option to `BootOrder`, preserving Vera Rubin firmware entry format. -pub fn boot_order_prepend_first( - boot_order: &[String], - target_id: &str, - target_display_name: &str, -) -> Vec { - let first_entry = if boot_order_uses_display_name_suffix(boot_order) { - boot_order_entry_with_display_name(target_id, target_display_name) - } else { - target_id.to_string() - }; - - let mut ordered = boot_order.to_vec(); - ordered.retain(|entry| boot_order_entry_boot_option_id(entry) != target_id); - ordered.insert(0, first_entry); - ordered -} - -#[cfg(test)] -mod boot_order_entry_tests { - use super::{ - boot_order_entry_boot_option_id, boot_order_entry_with_display_name, - boot_order_prepend_first, boot_order_uses_display_name_suffix, - }; - - #[test] - fn boot_order_entry_boot_option_id_strips_display_name_suffix() { - assert_eq!( - boot_order_entry_boot_option_id("Boot0019: Ubuntu"), - "Boot0019" - ); - assert_eq!(boot_order_entry_boot_option_id("Boot0010"), "Boot0010"); - } - - #[test] - fn boot_order_entry_with_display_name_formats_like_firmware() { - assert_eq!( - boot_order_entry_with_display_name("Boot0019", "Ubuntu"), - "Boot0019: Ubuntu" - ); - } - - #[test] - fn boot_order_uses_display_name_suffix_detects_firmware_format() { - assert!(boot_order_uses_display_name_suffix(&[ - "Boot0019: Ubuntu".to_string(), - "Boot0010: UEFI HTTPv4 (MAC:F4204D494ECC)".to_string(), - ])); - assert!(!boot_order_uses_display_name_suffix(&[ - "Boot0019".to_string(), - "Boot0010".to_string(), - ])); - } - - #[test] - fn boot_order_prepend_first_uses_id_colon_display_name_when_firmware_requires_it() { - let current = vec![ - "Boot0010: UEFI HTTPv4 (MAC:AA)".to_string(), - "Boot0019: Ubuntu".to_string(), - ]; - - let ordered = boot_order_prepend_first(¤t, "Boot0019", "UEFI"); - - assert_eq!(ordered[0], "Boot0019: UEFI"); - assert_eq!(ordered.len(), 2); - assert_eq!(ordered[1], "Boot0010: UEFI HTTPv4 (MAC:AA)"); - } - - #[test] - fn boot_order_prepend_first_uses_bare_id_for_legacy_boot_order_format() { - let current = vec!["Boot0010".to_string(), "Boot0019".to_string()]; - - let ordered = boot_order_prepend_first(¤t, "Boot0019", "UEFI"); - - assert_eq!(ordered[0], "Boot0019"); - assert_eq!(ordered[1], "Boot0010"); - } - - #[test] - fn boot_order_prepend_first_replaces_existing_entry_for_same_boot_option_id() { - let current = vec![ - "Boot0019: Ubuntu".to_string(), - "Boot0010: UEFI HTTPv4 (MAC:AA)".to_string(), - ]; - - let ordered = boot_order_prepend_first(¤t, "Boot0019", "UEFI"); - - assert_eq!(ordered[0], "Boot0019: UEFI"); - assert_eq!(ordered.len(), 2); - assert!(!ordered.contains(&"Boot0019: Ubuntu".to_string())); - } +/// Some BMC firmware reports entries like `Boot0019: Ubuntu` while BootOption +/// GET URLs use the reference prefix (`Boot0019`). +pub fn boot_order_entry_reference(entry: &str) -> &str { + entry + .split_once(": ") + .map_or(entry, |(reference, _)| reference) } diff --git a/src/nvidia_vera_rubin.rs b/src/nvidia_vera_rubin.rs index 1825164aa..92b60e8d3 100644 --- a/src/nvidia_vera_rubin.rs +++ b/src/nvidia_vera_rubin.rs @@ -92,6 +92,26 @@ enum BootOptionMatchField { UefiDevicePath, } +fn boot_order_entry_reference(entry: &str) -> &str { + crate::model::boot::boot_order_entry_reference(entry) +} + +fn promote_boot_order_entry_first( + boot_order: &mut Vec, + target_reference: &str, +) -> Result<(), RedfishError> { + let target_index = boot_order + .iter() + .position(|entry| boot_order_entry_reference(entry) == target_reference) + .ok_or_else(|| RedfishError::GenericError { + error: format!("Boot option {target_reference} is not present in BootOrder"), + })?; + // Preserve the exact entry returned by Vera Rubin firmware. + let target_entry = boot_order.remove(target_index); + boot_order.insert(0, target_entry); + Ok(()) +} + impl BootOptionMatchField { #[allow(dead_code)] fn to_string(self) -> &'static str { @@ -1092,14 +1112,30 @@ impl Redfish for Bmc { let mac_address = address.replace(':', "").to_uppercase(); let boot_option_name = format!("{} (MAC:{})", BootOptionName::Http.to_string(), mac_address); - let boot_array = self - .get_boot_options_ids_with_first( - BootOptionName::Http, - BootOptionMatchField::DisplayName, - Some(&boot_option_name), - ) - .await?; - self.change_boot_order(boot_array).await?; + let system = self.s.get_system().await?; + let boot_options_id = + system + .boot + .boot_options + .clone() + .ok_or_else(|| RedfishError::MissingKey { + key: "boot.boot_options".to_string(), + url: system.odata.odata_id.clone(), + })?; + let boot_options: Vec = self + .get_collection(boot_options_id) + .await + .and_then(|collection| collection.try_get::())? + .members; + let target = boot_options + .iter() + .find(|option| option.display_name.starts_with(&boot_option_name)) + .ok_or_else(|| RedfishError::GenericError { + error: format!("Could not find boot option matching {boot_option_name}"), + })?; + let mut boot_order = system.boot.boot_order; + promote_boot_order_entry_first(&mut boot_order, &target.boot_option_reference)?; + self.change_boot_order(boot_order).await?; Ok(None) }) } @@ -1396,31 +1432,21 @@ impl Bmc { let boot_option_name = format!("{} (MAC:{})", BootOptionName::Http.to_string(), mac_address); - let boot_options = self.s.get_system().await?.boot.boot_order; + let boot_order = self.s.get_system().await?.boot.boot_order; - let actual_first_boot_option = if let Some(first) = boot_options.first() { - Some( - self.s - .get_boot_option(crate::model::boot::boot_order_entry_boot_option_id( - first.as_str(), - )) - .await? - .display_name, - ) + let actual_first_boot_option = if let Some(first) = boot_order.first() { + let reference = boot_order_entry_reference(first.as_str()); + Some(self.s.get_boot_option(reference).await?.display_name) } else { None }; let mut expected_first_boot_option = None; - for member in &boot_options { - let b = self - .s - .get_boot_option(crate::model::boot::boot_order_entry_boot_option_id( - member.as_str(), - )) - .await?; - if b.display_name.starts_with(&boot_option_name) { - expected_first_boot_option = Some(b.display_name); + for entry in &boot_order { + let reference = boot_order_entry_reference(entry.as_str()); + let option = self.s.get_boot_option(reference).await?; + if option.display_name.starts_with(&boot_option_name) { + expected_first_boot_option = Some(option.display_name); break; } } @@ -1484,11 +1510,9 @@ impl Bmc { }); }; - Ok(crate::model::boot::boot_order_prepend_first( - &system.boot.boot_order, - &target.id, - &target.display_name, - )) + let mut boot_order = system.boot.boot_order; + promote_boot_order_entry_first(&mut boot_order, &target.boot_option_reference)?; + Ok(boot_order) } async fn get_system_event_log(&self) -> Result, RedfishError> { @@ -1572,6 +1596,43 @@ impl UpdateParameters { mod tests { use super::*; + #[test] + fn boot_order_entry_reference_strips_display_name_suffix() { + assert_eq!(boot_order_entry_reference("Boot0019: Ubuntu"), "Boot0019"); + assert_eq!(boot_order_entry_reference("Boot0010"), "Boot0010"); + } + + #[test] + fn promote_boot_order_entry_first_preserves_exact_firmware_entry() { + let mut boot_order = vec![ + "Boot0019: Ubuntu".to_string(), + "Boot0010: UEFI HTTPv4 (MAC:AA)".to_string(), + ]; + + promote_boot_order_entry_first(&mut boot_order, "Boot0010").unwrap(); + + assert_eq!(boot_order[0], "Boot0010: UEFI HTTPv4 (MAC:AA)"); + assert_eq!(boot_order[1], "Boot0019: Ubuntu"); + } + + #[test] + fn promote_boot_order_entry_first_works_with_bare_references() { + let mut boot_order = vec!["Boot0019".to_string(), "Boot0010".to_string()]; + + promote_boot_order_entry_first(&mut boot_order, "Boot0010").unwrap(); + + assert_eq!(boot_order[0], "Boot0010"); + assert_eq!(boot_order[1], "Boot0019"); + } + + #[test] + fn promote_boot_order_entry_first_errors_when_reference_missing() { + let mut boot_order = vec!["Boot0019: Ubuntu".to_string()]; + + let err = promote_boot_order_entry_first(&mut boot_order, "Boot0010").unwrap_err(); + assert!(matches!(err, RedfishError::GenericError { .. })); + } + #[test] fn test_update_parameters_targets_all_variants() { let cases: Vec<(ComponentType, Option>)> = vec![ From 24a34b03824049ac21d00fc260db5cfc0f333ea1 Mon Sep 17 00:00:00 2001 From: Hamed Akhondzadeh Date: Fri, 24 Jul 2026 15:31:21 -0700 Subject: [PATCH 4/4] fix: match boot string instead of prefix match --- src/nvidia_vera_rubin.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/nvidia_vera_rubin.rs b/src/nvidia_vera_rubin.rs index 92b60e8d3..b3f844435 100644 --- a/src/nvidia_vera_rubin.rs +++ b/src/nvidia_vera_rubin.rs @@ -96,6 +96,12 @@ fn boot_order_entry_reference(entry: &str) -> &str { crate::model::boot::boot_order_entry_reference(entry) } +fn dpu_http_boot_display_name_matches(display_name: &str, boot_option_name: &str) -> bool { + // Vera Rubin firmware can expose duplicate HTTP entries such as + // "UEFI HTTPv4 (MAC:…)" and "UEFI HTTPv4 (MAC:…) 2"; prefix match is ambiguous. + display_name == boot_option_name +} + fn promote_boot_order_entry_first( boot_order: &mut Vec, target_reference: &str, @@ -1129,7 +1135,9 @@ impl Redfish for Bmc { .members; let target = boot_options .iter() - .find(|option| option.display_name.starts_with(&boot_option_name)) + .find(|option| { + dpu_http_boot_display_name_matches(&option.display_name, &boot_option_name) + }) .ok_or_else(|| RedfishError::GenericError { error: format!("Could not find boot option matching {boot_option_name}"), })?; @@ -1445,7 +1453,7 @@ impl Bmc { for entry in &boot_order { let reference = boot_order_entry_reference(entry.as_str()); let option = self.s.get_boot_option(reference).await?; - if option.display_name.starts_with(&boot_option_name) { + if dpu_http_boot_display_name_matches(&option.display_name, &boot_option_name) { expected_first_boot_option = Some(option.display_name); break; } @@ -1596,6 +1604,19 @@ impl UpdateParameters { mod tests { use super::*; + #[test] + fn dpu_http_boot_display_name_requires_exact_match() { + let boot_option_name = "UEFI HTTPv4 (MAC:F4204D494ECC)"; + assert!(dpu_http_boot_display_name_matches( + "UEFI HTTPv4 (MAC:F4204D494ECC)", + boot_option_name, + )); + assert!(!dpu_http_boot_display_name_matches( + "UEFI HTTPv4 (MAC:F4204D494ECC) 2", + boot_option_name, + )); + } + #[test] fn boot_order_entry_reference_strips_display_name_suffix() { assert_eq!(boot_order_entry_reference("Boot0019: Ubuntu"), "Boot0019");