Skip to content

Commit 6bb45d0

Browse files
authored
feat: minimal SMC GB300 support (#111)
This PR adds minimal support for OpenBMC-based Supermicro GB300 systems, including machine setup attributes and handling for unsupported Secure Boot configuration. Validated on real hardware. Part of: NVIDIA/infra-controller#1909
1 parent 5bf822b commit 6bb45d0

2 files changed

Lines changed: 75 additions & 11 deletions

File tree

src/model/service_root.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ impl ServiceRoot {
114114
_ => RedfishVendor::NvidiaDpu,
115115
},
116116
"wiwynn" => RedfishVendor::NvidiaGBx00,
117-
"supermicro" => RedfishVendor::Supermicro,
117+
"supermicro" => match self.product.as_deref() {
118+
Some("GB NVL") => RedfishVendor::NvidiaGBx00,
119+
_ => RedfishVendor::Supermicro,
120+
},
118121
"lite-on technology corp." => RedfishVendor::LiteOnPowerShelf,
119122
"delta" => RedfishVendor::DeltaPowerShelf,
120123
_ => RedfishVendor::Unknown,
@@ -156,6 +159,16 @@ mod test {
156159
assert_eq!(result.vendor().unwrap(), RedfishVendor::NvidiaGBx00);
157160
}
158161

162+
#[test]
163+
fn test_supermicro_gb300_service_root() {
164+
let result = ServiceRoot {
165+
vendor: Some("Supermicro".to_string()),
166+
product: Some("GB NVL".to_string()),
167+
..Default::default()
168+
};
169+
assert_eq!(result.vendor().unwrap(), RedfishVendor::NvidiaGBx00);
170+
}
171+
159172
#[test]
160173
fn test_nvidia_bluefield_service_root() {
161174
let result = ServiceRoot {

src/nvidia_gbx00.rs

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ impl Bmc {
6666
pub fn new(s: RedfishStandard) -> Result<Bmc, RedfishError> {
6767
Ok(Bmc { s })
6868
}
69+
70+
async fn is_gb300(&self) -> Result<bool, RedfishError> {
71+
let systems = self
72+
.s
73+
.get_collection(ODataId::from("/redfish/v1/Systems"))
74+
.await?
75+
.try_get::<ComputerSystem>()?;
76+
Ok(systems.members.iter().any(|system| {
77+
system
78+
.model
79+
.as_deref()
80+
.is_some_and(|model| model.contains("GB300"))
81+
}))
82+
}
6983
}
7084

7185
#[derive(Copy, Clone)]
@@ -527,9 +541,15 @@ impl Redfish for Bmc {
527541
>,
528542
) -> crate::RedfishFuture<'a, Result<Option<String>, RedfishError>> {
529543
Box::pin(async move {
530-
self.disable_secure_boot().await?;
544+
let is_gb300 = self.is_gb300().await?;
531545

532-
let bios_attrs = self.machine_setup_attrs().await?;
546+
// The Supermicro GB300 SecureBoot resource does not expose
547+
// SecureBootEnable, so there is no supported setting to change.
548+
if !is_gb300 {
549+
self.disable_secure_boot().await?;
550+
}
551+
552+
let bios_attrs = self.machine_setup_attrs(is_gb300).await?;
533553
let mut attrs = HashMap::new();
534554
attrs.extend(bios_attrs);
535555
let body = HashMap::from([("Attributes", attrs)]);
@@ -846,11 +866,25 @@ impl Redfish for Bmc {
846866
}
847867

848868
fn enable_secure_boot<'a>(&'a self) -> crate::RedfishFuture<'a, Result<(), RedfishError>> {
849-
Box::pin(async move { self.s.enable_secure_boot().await })
869+
Box::pin(async move {
870+
if self.is_gb300().await? {
871+
return Err(RedfishError::NotSupported(
872+
"Supermicro GB300 does not expose SecureBootEnable".to_string(),
873+
));
874+
}
875+
self.s.enable_secure_boot().await
876+
})
850877
}
851878

852879
fn disable_secure_boot<'a>(&'a self) -> crate::RedfishFuture<'a, Result<(), RedfishError>> {
853-
Box::pin(async move { self.s.disable_secure_boot().await })
880+
Box::pin(async move {
881+
if self.is_gb300().await? {
882+
return Err(RedfishError::NotSupported(
883+
"Supermicro GB300 does not expose SecureBootEnable".to_string(),
884+
));
885+
}
886+
self.s.disable_secure_boot().await
887+
})
854888
}
855889

856890
fn get_secure_boot_certificate<'a>(
@@ -1178,6 +1212,11 @@ impl Redfish for Bmc {
11781212

11791213
fn enable_infinite_boot<'a>(&'a self) -> crate::RedfishFuture<'a, Result<(), RedfishError>> {
11801214
Box::pin(async move {
1215+
if self.is_gb300().await? {
1216+
return Err(RedfishError::NotSupported(
1217+
"Supermicro GB300 does not expose EmbeddedUefiShell".to_string(),
1218+
));
1219+
}
11811220
let attrs: HashMap<String, serde_json::Value> =
11821221
HashMap::from([("EmbeddedUefiShell".to_string(), "Disabled".into())]);
11831222
let body = HashMap::from([("Attributes", attrs)]);
@@ -1190,6 +1229,9 @@ impl Redfish for Bmc {
11901229
&'a self,
11911230
) -> crate::RedfishFuture<'a, Result<Option<bool>, RedfishError>> {
11921231
Box::pin(async move {
1232+
if self.is_gb300().await? {
1233+
return Ok(None);
1234+
}
11931235
let embedded_uefi_shell = self.get_embedded_uefi_shell_status().await?;
11941236
// Infinite boot is enabled when EmbeddedUefiShell is disabled
11951237
Ok(Some(embedded_uefi_shell == EnabledDisabled::Disabled))
@@ -1368,7 +1410,8 @@ impl Bmc {
13681410
}
13691411

13701412
let bios = self.s.bios_attributes().await?;
1371-
let expected_attrs = self.machine_setup_attrs().await?;
1413+
let is_gb300 = self.is_gb300().await?;
1414+
let expected_attrs = self.machine_setup_attrs(is_gb300).await?;
13721415
for (key, expected) in expected_attrs {
13731416
let Some(actual) = bios.get(&key) else {
13741417
diffs.push(MachineSetupDiff {
@@ -1497,14 +1540,22 @@ impl Bmc {
14971540
Ok(log_entries)
14981541
}
14991542

1500-
async fn machine_setup_attrs(&self) -> Result<Vec<(String, serde_json::Value)>, RedfishError> {
1543+
async fn machine_setup_attrs(
1544+
&self,
1545+
is_gb300: bool,
1546+
) -> Result<Vec<(String, serde_json::Value)>, RedfishError> {
15011547
let mut bios_attrs: Vec<(String, serde_json::Value)> = vec![];
15021548

1503-
// Enabled TPM
1504-
bios_attrs.push(("TPM".into(), "Enabled".into()));
1549+
if is_gb300 {
1550+
// This platform exposes the TPM through the AMI BIOS name.
1551+
bios_attrs.push(("SecurityDeviceSupport".into(), "Enabled".into()));
1552+
} else {
1553+
// Enable TPM.
1554+
bios_attrs.push(("TPM".into(), "Enabled".into()));
15051555

1506-
// Disabled EmbeddedUefiShell (infinite boot workaround)
1507-
bios_attrs.push(("EmbeddedUefiShell".into(), "Disabled".into()));
1556+
// Disable EmbeddedUefiShell (infinite boot workaround).
1557+
bios_attrs.push(("EmbeddedUefiShell".into(), "Disabled".into()));
1558+
}
15081559

15091560
// Enable Option ROM so that the DPU will show up in the Host's network devce list
15101561
// Otherwise, we will never see the DPU's Host PF MAC in the boot option list

0 commit comments

Comments
 (0)