Skip to content

control-plane-agent: implement component-get-vpd - #2650

Merged
hawkw merged 28 commits into
masterfrom
eliza/pmbus-vpd-3
Sep 4, 2026
Merged

control-plane-agent: implement component-get-vpd#2650
hawkw merged 28 commits into
masterfrom
eliza/pmbus-vpd-3

Conversation

@hawkw

@hawkw hawkw commented Aug 18, 2026

Copy link
Copy Markdown
Member

Depends on oxidecomputer/management-gateway-service#500.
Depends on #2666.

This branch updates the gateway-messages dependency to pick up the new component-get-vpd API and associated messages for reading the vital product data from a component, and, well, implements that API. While the MGS PR better describes the layout of the various wire types, this is where most of the actual heavy lifting happened. Of the various attempts I've made at adding FRUID VPD to control-plane-agent, this is the first one I'm actually more or less satisfied with.

Fixes #2212.
Closes #2217.
Closes #2220.

Comment thread drv/i2c-types/src/lib.rs Outdated

/// Bitmask for selecting *all* potential VPD register capa
pub const ANY_VPD_REGS: Self = Self(
// XXX(eliza): this might be less gross if we just used the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 from me here

@hawkw hawkw left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some notes for reviewers

Comment thread drv/i2c-devices/src/lib.rs Outdated
Comment on lines +416 to +431
pub struct PmbusVpd<'buf> {
/// `MFR_ID` (PMBus operation 0x99)
pub mfr_id: Option<&'buf [u8]>,
/// `MFR_MODEL` (PMBus operation 0x9A)
pub mfr_model: Option<&'buf [u8]>,
/// `MFR_REVISION` (PMBus operation 0x9B)
pub mfr_revision: Option<&'buf [u8]>,
/// `MFR_LOCATION` (PMBus operation 0x9C)
pub mfr_location: Option<&'buf [u8]>,
/// `MFR_DATE` (PMBus operation 0x9D)
pub mfr_date: Option<&'buf [u8]>,
/// `MFR_SERIAL` (PMBus operation 0x9E)
pub mfr_serial: Option<&'buf [u8]>,
pub ic_device_id: Option<&'buf [u8]>,
pub ic_device_rev: Option<&'buf [u8]>,
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this may look a bit weird; it's designed specifically to let you read all the 32-byte blocks into one statically allocated buffer and then the thing you actually serialize doesn't stack copy any of it.

Comment thread drv/i2c-devices/src/lib.rs
Comment thread drv/i2c-devices/src/lib.rs Outdated
Comment on lines +513 to +552
let mfr_range =
read(PmbusVpdCmd::MfrId, Capabilities::MFR_ID, buf, &mut off)?;
let model_range = read(
PmbusVpdCmd::MfrModel,
Capabilities::MFR_MODEL,
buf,
&mut off,
)?;
let rev_range = read(
PmbusVpdCmd::MfrRevision,
Capabilities::MFR_REVISION,
buf,
&mut off,
)?;
let location_range = read(
PmbusVpdCmd::MfrLocation,
Capabilities::MFR_LOCATION,
buf,
&mut off,
)?;
let date_range =
read(PmbusVpdCmd::MfrDate, Capabilities::MFR_DATE, buf, &mut off)?;
let serial_range = read(
PmbusVpdCmd::MfrSerial,
Capabilities::MFR_SERIAL,
buf,
&mut off,
)?;
let ic_id_range = read(
PmbusVpdCmd::IcDeviceId,
Capabilities::IC_DEVICE_ID,
buf,
&mut off,
)?;
let ic_rev_range = read(
PmbusVpdCmd::IcDeviceRev,
Capabilities::IC_DEVICE_REV,
buf,
&mut off,
)?;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unlike the status bits, we bail if any read attempt fails. i'm open to being talked out of that; my thinking here was mostly that for a lot of devices, values like the serial cannot be meaningfully interpreted without the model number, and so forth

Comment thread drv/i2c-types/src/lib.rs Outdated

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this probably needs to be renamed since it's now for all pmbus

Comment thread drv/i2c-types/src/lib.rs Outdated
Comment on lines +311 to +323
/// Bitmask for selecting *all* potential VPD register capa
pub const ANY_VPD_REGS: Self = Self(
// XXX(eliza): this might be less gross if we just used the
// bitflags crate for this...
Self::MFR_ID.0
| Self::MFR_MODEL.0
| Self::MFR_REVISION.0
| Self::MFR_SERIAL.0
| Self::MFR_LOCATION.0
| Self::MFR_DATE.0
| Self::IC_DEVICE_ID.0
| Self::IC_DEVICE_REV.0,
);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be worth turning this into a bitflags type so that this stuff is less ugly, idk...

Ok(())
}

/// Look at the `pmbus` crate metadata to see if a specific command is "Illegal"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this is a near-verbatim copy of James' code from control-plane-agent's build script, I just moved it in here so we can do it for each PMBus device's DeviceDescription rather than the rail bindings (which now reference this)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just be doing this in build/i2c instead so it's covered by snapshots? If we're using it in both c-p-a and validate, it seems like it might be worth lifting.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c-p-a only depends on it through validate's API codegen, validate itself doesn't actually use most of that codegen. this relationship is kind of weird and confusing, but I would prefer not to address it in this branch.

Comment thread task/control-plane-agent/src/inventory.rs Outdated
@hawkw

hawkw commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

Poking at some devices on Cosmo, it seems the RAA229620As do not like the MFR_LOCATION and MFR_SERIAL commands; for everything else they appear to return some mostly-not-ASCII bytes:

eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C MFR_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x99 MFR_ID                    0xde 0x01 0x00 0x00                     |....
eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C MFR_MODEL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9a MFR_MODEL                 0x01 0x00 0x00 0x00                     |....
eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C MFR_REVISION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9b MFR_REVISION              0x01 0x00 0x00 0x00                     |....
eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C MFR_LOCATION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C MFR_DATE
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9d MFR_DATE                  0x27 0x03 0x25 0x20                     |'.%
eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C MFR_SERIAL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C IC_DEVICE_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0xad IC_DEVICE_ID              0x00 0x9b 0xd2 0x49                     |...I
eliza@jeeves ~ $ pfexec humility pmbus -r VDDCR_CPU0_A0 -C IC_DEVICE_REV
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0xae IC_DEVICE_REV             0x00 0x01 0x00 0x09                     |....
eliza@jeeves ~ $

The ISL68224s don't like MFR_LOCATION and MFR_SERIAL, but otherwise have some also-probably-not-intended-to-be-ASCII bytes to share with us:

eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C MFR_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x99 MFR_ID                    0xde 0x01 0x00 0x00                     |....
eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C MFR_MODEL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9a MFR_MODEL                 0x03 0x00 0x00 0x00                     |....
eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C MFR_REVISION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9b MFR_REVISION              0x01 0x00 0x00 0x00                     |....
eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C MFR_LOCATION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C MFR_DATE
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9d MFR_DATE                  0x27 0x03 0x25 0x20                     |'.%
eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C MFR_SERIAL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C IC_DEVICE_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0xad IC_DEVICE_ID              0x00 0x52 0xd2 0x49                     |.R.I
eliza@jeeves ~ $ pfexec humility pmbus -r V1P1_SP5_A0 -C IC_DEVICE_REV
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0xae IC_DEVICE_REV             0x04 0x00 0x00 0x02                     |....
eliza@jeeves ~ $

(this is also a Renesas part, so we can see that it at least has the same MFR_ID as the RAA229620A, and the other responses look similarish, so I imagine there is a renesas-y way you're supposed to interpret these)

The TPS546B24As dislike MFR_LOCATION and MFR_DATE, but happily return a bunch of mostly nulls for every command other than IC_DEVICE_ID and IC_DEVICE_REV, which are some mostly-ASCII bytes that are probably not ASCII on purpose:

eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C MFR_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x99 MFR_ID                    0x00 0x00 0x00                          |...
eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C MFR_MODEL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9a MFR_MODEL                 0x00 0x00 0x00                          |...
eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C MFR_REVISION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9b MFR_REVISION              0x00 0x00 0x00                          |...
eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C MFR_LOCATION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C MFR_DATE
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C MFR_SERIAL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9e MFR_SERIAL                0x00 0x00 0x00                          |...
eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C IC_DEVICE_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0xad IC_DEVICE_ID              0x54 0x49 0x54 0x6b 0x24 0x41           |TITk$A
eliza@jeeves ~ $ pfexec humility pmbus -r V3P3_SP_A2 -C IC_DEVICE_REV
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0xae IC_DEVICE_REV             0x40 0x00                               |@.
eliza@jeeves ~ $

The BMR491 actually likes talking PMBus and gives us some nice strings; this works so well that the actual MGS request works without having to update things in pmbus to mark some commands as illegal:

eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd U80
Aug 28 18:56:17.381 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 18:56:17.411 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
MFR_ID:       Flex
MFR_MODEL:    BMR4913203851
MFR_REVISION: R1C A
MFR_LOCATION: CB6
MFR_DATE:     2023-02-28
MFR_SERIAL:   FP1C481053
eliza@jeeves ~ $

The LM5066Is are basically only interested in telling us their MFR_ID, MFR_MODEL, and MFR_REVISION, which is a shame, since there's probably nothing in here to uniquely identify that instance of the part:

eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C MFR_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x99 MFR_ID                    0x54 0x49 0x00                          |TI.
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C MFR_MODEL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9a MFR_MODEL                 0x4c 0x4d 0x35 0x30 0x36 0x36 0x49 0x00
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C MFR_REVISION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9b MFR_REVISION              0x41 0x41                               |AA
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C MFR_LOCATION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C MFR_DATE
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C MFR_SERIAL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C IC_DEVICE_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_FAN_EAST -C IC_DEVICE_REV
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $

Using the technique of "knowing that this happens to be a Texas Instruments part" and that the MFR_ID is TI\0, I am guessing that these are intended to be ASCII strings which are...sometimes null-terminated?.

The ADM1272 gives us some rather nice clearly ASCII strings back, but is unwilling to disclose its MFR_LOCATION and MFR_SERIAL, and is also unwilling to share its IC_DEVICE_ID or IC_DEVICE_REV:

eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C MFR_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x99 MFR_ID                    0x41 0x44 0x49                          |ADI
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C MFR_MODEL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9a MFR_MODEL                 0x41 0x44 0x4d 0x31 0x32 0x37 0x32 0x2d |ADM1272-
                               0x32 0x41                               |2A
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C MFR_REVISION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9b MFR_REVISION              0x32 0x35                               |25
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C MFR_LOCATION
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C MFR_DATE
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
0x9d MFR_DATE                  0x32 0x30 0x30 0x34 0x31 0x35           |200415
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C MFR_SERIAL
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C IC_DEVICE_ID
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $ pfexec humility pmbus -r V54P5_IBC_A3 -C IC_DEVICE_REV
humility: WARNING: archive in environment variable overriding archive in environment file
humility: attached to 1fc9:0143:NE5MJWEAVZOK0 via CMSIS-DAP
eliza@jeeves ~ $

So we shall want to go and edit pmbus to mark some of the commands that these devices find distasteful as illegal.

hawkw added a commit to oxidecomputer/pmbus that referenced this pull request Aug 28, 2026
Based on some testing I did on a Cosmo in the lab, there are a variety
of VPD-related `MFR_$whatever` and `IC_DEVICE_{ID, REV}` commands that
various devices dislike. See [this comment][1] for details.

To prevent them from NACKing us and setting `STATUS_CML` a bunch, and to
better support the codegen changes I'm working on in
oxidecomputer/hubris#2650, this commit updates the config files for
those devices to mark the commands they find distasteful as `Illegal`.

[1]: oxidecomputer/hubris#2650 (comment)
@hawkw

hawkw commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

Progress has been made!

eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J200/U2'
Aug 28 22:28:59.698 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:28:59.728 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
0XV2:913-0000026:003:2JHM84Y0
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J209/U2'
Aug 28 22:29:28.415 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:29:28.445 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
0XV2:913-0000026:003:21MVG4F1
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J34/U2'
Aug 28 22:29:55.168 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:29:55.198 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
Error: Error response from SP: unsupported request for this SP component
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J34/U1'
Aug 28 22:30:10.157 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:30:10.187 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
FAN TRAY:  0XV2:991-0000151:003:2W6DXFGF
VPD BOARD: 0XV2:913-0000027:001:BRM40250270
FANS: [
  0XV2:418-0000005:001:FAN3924003S
  0XV2:418-0000005:001:FAN3924003W
  0XV2:418-0000005:001:FAN3924003V
]

eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U32'
Aug 28 22:30:47.567 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:30:47.597 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
0XV2:913-0000023:002:2MX4G4PJ
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U80'
Aug 28 22:31:10.699 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:31:10.729 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
MFR_ID:       Flex
MFR_MODEL:    BMR4913203851
MFR_REVISION: R1C A
MFR_LOCATION: CB6
MFR_DATE:     2023-02-28
MFR_SERIAL:   FP1C481053
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U71'
Aug 28 22:31:13.996 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:31:14.026 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
Error: Error response from SP: vpd: vpd device is unavailable
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U79'
Aug 28 22:31:22.306 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 22:31:22.336 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
Error: Error response from SP: vpd: vpd device is unavailable
eliza@jeeves ~ $

@hawkw hawkw changed the title [wip] generic API for reading PMBus VPD control-plane-agent: implement component-get-vpd Aug 29, 2026
@hawkw

hawkw commented Aug 29, 2026

Copy link
Copy Markdown
Member Author

Testing the latest commit (257c6a5) on mb-0 in the lab:

eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J200/U2'
Aug 28 23:34:19.197 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:34:19.228 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
0XV2:913-0000026:003:2JHM84Y0
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J209/U2'
Aug 28 23:34:28.441 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:34:28.471 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
0XV2:913-0000026:003:21MVG4F1
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J34/U1'
Aug 28 23:34:56.337 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:34:56.367 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
fan tray    : 0XV2:991-0000151:003:2W6DXFGF
  VPD board : 0XV2:913-0000027:001:BRM40250270
  fan 0     : 0XV2:418-0000005:001:FAN3924003S
  fan 1     : 0XV2:418-0000005:001:FAN3924003W
  fan 2     : 0XV2:418-0000005:001:FAN3924003V

eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'J44/U1'
Aug 28 23:36:09.352 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:36:09.383 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
device ID : 0x1701
  EEPROM1 : 0x7aa5
  EEPROM2 : 0x590f
  EEPROM3 : 0x69a4

eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U80'
Aug 28 23:36:24.176 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:36:24.205 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
MFR_ID        : Flex
MFR_MODEL     : BMR4913203851
MFR_REVISION  : R1C A
MFR_LOCATION  : CB6
MFR_DATE      : 2023-02-28
MFR_SERIAL    : FP1C481053
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U71'
Aug 28 23:36:29.635 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:36:29.665 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
MFR_ID        : TI
MFR_MODEL     : LM5066I
MFR_REVISION  : AA
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U79'
Aug 28 23:36:32.660 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:36:32.690 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
MFR_ID        : ADI
MFR_MODEL     : ADM1272-2A
MFR_REVISION  : 25
MFR_DATE      : 200415
eliza@jeeves ~ $ ./faux-mgs-vpd --interface e1000g0 --discovery-addr '[fe80::aa40:25ff:fe04:1200]:11111' component-vpd 'U123'
Aug 28 23:37:09.482 INFO creating SP handle on interface e1000g0, component: faux-mgs
Aug 28 23:37:09.513 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe04:1200%2]:11111, interface: e1000g0, socket: control-plane-agent, component: faux-mgs
MFR_ID        :
MFR_MODEL     :
MFR_REVISION  :
MFR_SERIAL    :
IC_DEVICE_ID  : TITk$A
IC_DEVICE_REV : @
eliza@jeeves ~ $

I still need to test a PSC and a Sidecar, but that'll have to wait until I get some racklette time. The faux-mgs output for the TPS546B24A's PMBus EEPROM is a little bit silly, because it's trying to interpret it as ASCII because it just so happens to be valid ASCII, which is kinda a bummer, but, meh.

@hawkw
hawkw marked this pull request as ready for review August 29, 2026 00:14
@hawkw hawkw added control-plane-agent fault-management Everything related to the Oxide's Fault Management architecture implementation labels Aug 29, 2026
@hawkw

hawkw commented Aug 29, 2026

Copy link
Copy Markdown
Member Author

(To anyone scared about how this branch is adding 3000 lines of code, a lot of it is that I added I2C codegen snapshot tests for gimletlet, since it's representative of boards that don't have any power/pmbus devices and therefore hit some unused arguments in the codegen)

@jamesmunns jamesmunns left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these changes are good to have, I made a variety of nit comments, some of them might be nice to fix, some of them are more just commentary.

Comment thread build/i2c/src/lib.rs
Comment thread build/i2c/src/lib.rs
match index {
0 => Some(
// Front FPGA virtual mux
I2cDevice::new(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not something to fix this PR, but I feel like it would be nice if someday we didn't re-generate the whole I2cDevice::new and instead called the constructor function instead. The optimizer is probably going to do the same anyway, but it would make the snapshots shorter (and probably generate less code for rustc to chew on).

Comment thread task/control-plane-agent/src/inventory.rs Outdated
.map_err(SpError::Vpd)
};
let vpd = Tmp117Identity {
id: read(0x0f_u8)?,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not have driver methods for these register IDs? Slightly magic numbers.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, apparently there is actually a Tmp117::read_eeprom, but host-sp-comms, which I blatantly copied this from...doesn't use them:

*id = dev.read_reg(0x0Fu8)?;
*eeprom1 = dev.read_reg(0x05u8)?;
*eeprom2 = dev.read_reg(0x06u8)?;
*eeprom3 = dev.read_reg(0x08u8)?;

I should probably make this use the driver...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, upon re-considering what §2.11 RDD 360 has to say about this device, I begin to wonder whether whether the way we are currently representing it, which again I stole from hostess-pecans, may in fact be basically the most endianness-confusion-y possible way to represent it...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may in fact be basically the most endianness-confusion-y possible

by which i mean, when i was reading this code, i got confused about what the endianness was

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, upon consulting the git blame, this is just because Bryan appears to have written the TMP117 driver some time before the advent of <u{16, 32, 64}>::from_{be,le}_bytes...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if i rewrite the whole driver

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OOPS I REWROTE THE WHOLE DRIVER (AND ASLSO ALL THE CODE THAT USES IT): 248b890

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that probably should be factored out into its own PR; sorry james

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOL NOTHING ELSE ACTUALLY USES THE Tmp117::read_eeprom FUNCTION ANYWAY so i'm just gonna change it to do what i want it to

UPDATE whoops i was wrong about this, something was using it and it was goddamn DONGLET i hate everthing

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, after #2666, I think this will be a bit nicer, but I'd rather not have this PR depend on that one, if you're okay with that?

self.power_state_impl()
}

fn power_state_with_reason(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this RequestUnsupportedForSp for every instance?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this is a fill-in because #2515 hasn't landed yet.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment here in case this is something to be concerned about: #2515 (comment)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I think we are okay with merging Evan's API unimplemented, since we are not actually using it yet in any other upstack software...

Comment thread task/validate-api/build.rs Outdated
Ok(())
}

/// Look at the `pmbus` crate metadata to see if a specific command is "Illegal"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just be doing this in build/i2c instead so it's covered by snapshots? If we're using it in both c-p-a and validate, it seems like it might be worth lifting.

Comment thread build/i2c/src/lib.rs Outdated
Comment thread build/i2c/src/lib.rs Outdated
pub device_id: Option<String>,
pub name: Option<String>,
pub validate_with_raw_read: bool,
pub vpd: EepromVpd,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, we don't have any snapshot coverage for I2cDeviceDescription or device_descriptions(). We might want a similar snapshot to what we have with I2cSensorsDescription.

@hawkw

hawkw commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Ugh, looks like the code for reading the TMP117 eeproms is endianness-confused:

eliza@castle ~ $ pilot sp exec -e 'component-vpd J71' BRM44220004
Sep 03 19:03:38.008 INFO creating SP handle on interface london_sw0tp0, component: faux-mgs
Sep 03 19:03:38.010 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe05:200%3]:11111, interface: london_sw0tp0, socket: control-plane-agent, component: faux-mgs
device ID : 0x1701
  EEPROM1 : 0x7aa5
  EEPROM2 : 0x8b0f
  EEPROM3 : 0x0000

so actually, we probably should merge #2666 and then update this change to use that.

@hawkw

hawkw commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

Ugh, okay, so having finally gotten as far as testing this on a PSC:

eliza@castle ~ $ pilot sp exec -e 'inventory' BRM11230017
Sep 03 20:43:34.910 INFO creating SP handle on interface london_sw0tp0, component: faux-mgs
Sep 03 20:43:34.913 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe06:108%3]:11111, interface: london_sw0tp0, socket: control-plane-agent, component: faux-mgs
COMPONENT        STATUS       DEVICE           DESCRIPTION (CAPABILITIES)
sp               Present      sp               Service Processor (DeviceCapabilities(1))
system-led       Present      system-led       System attention LED (DeviceCapabilities(8))
U31              Present      tmp116           Temperature sensor (DeviceCapabilities(0))
U32              Present      at24csw080       FRU ID EEPROM (DeviceCapabilities(16))
PSU0/ID          Present      m24c02           PSU 0 EEPROM (DeviceCapabilities(0))
PSU0             Present      mwocp68          PSU 0 MCU (DeviceCapabilities(50))
PSU1/ID          NotPresent   m24c02           PSU 1 EEPROM (DeviceCapabilities(0))
PSU1             NotPresent   mwocp68          PSU 1 MCU (DeviceCapabilities(50))
PSU2/ID          Present      m24c02           PSU 2 EEPROM (DeviceCapabilities(0))
PSU2             Present      mwocp68          PSU 2 MCU (DeviceCapabilities(50))
PSU3/ID          NotPresent   m24c02           PSU 3 EEPROM (DeviceCapabilities(0))
PSU3             NotPresent   mwocp68          PSU 3 MCU (DeviceCapabilities(50))
PSU4/ID          NotPresent   m24c02           PSU 4 EEPROM (DeviceCapabilities(0))
PSU4             NotPresent   mwocp68          PSU 4 MCU (DeviceCapabilities(50))
PSU5/ID          NotPresent   m24c02           PSU 5 EEPROM (DeviceCapabilities(0))
PSU5             NotPresent   mwocp68          PSU 5 MCU (DeviceCapabilities(50))
eliza@castle ~ $ pilot sp exec -e 'component-vpd PSU0' BRM11230017
Sep 03 20:44:10.812 INFO creating SP handle on interface london_sw0tp0, component: faux-mgs
Sep 03 20:44:10.814 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe06:108%3]:11111, interface: london_sw0tp0, socket: control-plane-agent, component: faux-mgs
Error: Error response from SP: vpd: vpd device is unavailable
eliza@castle ~ $ pilot sp exec -e 'component-vpd U31' BRM11230017
Sep 03 20:47:58.429 INFO creating SP handle on interface london_sw0tp0, component: faux-mgs
Sep 03 20:47:58.432 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe06:108%3]:11111, interface: london_sw0tp0, socket: control-plane-agent, component: faux-mgs
Error: Error response from SP: unsupported request for this SP component
eliza@castle ~ $ pilot sp exec -e 'component-vpd U32' BRM11230017
Sep 03 20:48:08.652 INFO creating SP handle on interface london_sw0tp0, component: faux-mgs
Sep 03 20:48:08.655 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe06:108%3]:11111, interface: london_sw0tp0, socket: control-plane-agent, component: faux-mgs
0XV2:913-0000003:009:BRM11230017
eliza@castle ~ $
  • i have clearly screwed up something such that the TMP116 doesn't advertise itself as a VPD device, and it doesn't work
  • we are trying to read at least one command that the MWOCP68 doesn't like and which has not been marked as illegal in pmbus yet
  • i should probably figure out what's actually stored in the M24C02 EEPROMs and whether we should read them...

@hawkw

hawkw commented Sep 3, 2026

Copy link
Copy Markdown
Member Author
  • i should probably figure out what's actually stored in the M24C02 EEPROMs and whether we should read them...

oh good:

impl Validate<Error> for M24C02 {
fn validate(device: &I2cDevice) -> Result<bool, Error> {
// Attempt to read a byte at address 0
//
// TODO: actually check against an expected pattern
device
.read_reg::<u8, u8>(0)
.map_err(|e| Error::BadValidation { code: e })?;
Ok(true)
}
}

@hawkw

hawkw commented Sep 3, 2026

Copy link
Copy Markdown
Member Author
  • we are trying to read at least one command that the MWOCP68 doesn't like and which has not been marked as illegal in pmbus yet

Ah, I think pmbus should mark IC_DEVICE_ID and IC_DEVICE_REG as Illegal for the Murata rectifiers; neither ACAN-114 nor ACAN-157 mention those commands. Opened oxidecomputer/pmbus#39

@hawkw

hawkw commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

Good news: after updating to oxidecomputer/pmbus#39, the MWOCP68s work! Bad news: the temp sensor is still endianness-confused-y?

eliza@castle ~ $ pilot sp exec -e 'component-vpd U31' BRM11230017
Sep 04 17:36:36.365 INFO creating SP handle on interface london_sw0tp0, component: faux-mgs
Sep 04 17:36:36.406 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe06:108%3]:11111, interface: london_sw0tp0, socket: control-plane-agent, component: faux-mgs
device ID : 0x1701
EEPROM1   : 0x7ba5
EEPROM2   : 0x820f
EEPROM3   : 0xc7b1

eliza@castle ~ $ pilot sp exec -e 'component-vpd PSU0' BRM11230017
Sep 04 17:37:01.120 INFO creating SP handle on interface london_sw0tp0, component: faux-mgs
Sep 04 17:37:01.123 INFO initial discovery complete, addr: [fe80::aa40:25ff:fe06:108%3]:11111, interface: london_sw0tp0, socket: control-plane-agent, component: faux-mgs
MFR_ID        : Murata-PS
MFR_MODEL     : MWOCP68-3600-D-RM
MFR_REVISION  : 0762-0701-0000
MFR_LOCATION  : China
MFR_DATE      : 2111
MFR_SERIAL    : LL2111Q9002T
eliza@castle ~ $

@hawkw
hawkw force-pushed the eliza/pmbus-vpd-3 branch 2 times, most recently from 57150bb to c0067fb Compare September 4, 2026 18:20
@hawkw

hawkw commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

turns out the temp sensor endianness mess was much sillier than i thought: 9b3e06b

@hawkw
hawkw force-pushed the eliza/pmbus-vpd-3 branch from 746d161 to 0ac4418 Compare September 4, 2026 20:23
…5df9a38eed1

picks up the merged version from `main`
@hawkw
hawkw enabled auto-merge (squash) September 4, 2026 20:33
@hawkw
hawkw merged commit 0d1ba04 into master Sep 4, 2026
190 checks passed
@hawkw
hawkw deleted the eliza/pmbus-vpd-3 branch September 4, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

control-plane-agent fault-management Everything related to the Oxide's Fault Management architecture implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

control-plane-agent inventory should include FRUID VPD

2 participants