# Entity-Manager HW ID: VPD Discovery via Device-Tree Properties
Author: Christopher Sides (citysides)
Other contributors:
Created: September 14, 2023
## Problem Description
BMC needs a process to identify and handle HPE GXP baseboards that provide HW ID
data via non-I2C channels and in a proprietary format that is not covered by
Entity-Manager's 'fru-device' daemon that most platforms rely on.
This proposal describes a method of handling for hardware where HW ID data is
gathered from device tree file paths for Entity-Manager consumption.
## Background and References
Typical platforms provide HW ID data - often referred to as 'vital product data'
(VPD) - for the baseboard as a FRU storage blob held in a physical EEPROM.
[As described in Entity-Manager documentation](https://github.com/openbmc/entity-manager/blob/master/docs/my_first_sensors.md),
this blob is discovered and read over I2C, then is decoded before the data is
copied to D-Bus as properties of the `xyz.openbmc_project.FruDevice` interface
by Entity-Manager's fru-device daemon. The current FRU-device daemon is able to
decode IPMI-FRU storage formatted blobs, as well as the Tyan data format.
Additionally, a separate daemon for handling OpenPower format VPD is hosted in
the 'openpower-vpd-parser' subproject. This daemon is relied on for the
identification of certain IBM-supported hardware.
HPE hardware uses different channels and data formats from the above, relying on
modifications to the device-tree to output properties as one file handle per
attribute.
Once VPD is made available on D-Bus, it can be referenced by the Entity-Manager
configuration 'probe' statements that are used as hardware/configuration
detection triggers.
HPE platforms provide the following properties for baseboard VPD:
- server_id (platform model id)
- pca_part_number (baseboard part no)
- pca_serial_number (baseboard serial no)
- part_number (platform product no, set at assembly by factory)
- serial_number (system serial no, assigned at assembly by factory)
- mac0 (if present: MAC address for dedicated BMC network interface)
- mac1 (if present: MAC address for secondary network interface that may or may
not be shared with host)
HPE platforms in Gen 10 and earlier provided VPD through a standard
I2C-accessible EEPROM (but still in a proprietary data format). That avenue is
no longer available on newer HPE systems.
For GXP-based Gen 11 HPE platforms, proprietary HPE-controlled bootblock
firmware communicates with a secure element to provide necessary VPD. This
process uses a driver whose implementation is strictly license-controlled and
cannot be publicly released. The open source portions of the boot chain must
adapt to the bootblock's reserved memory application binary interface (ABI) for
providing VPD from the secure element.
Early in the boot process, an HPE-proprietary bootblock is validated, then an
HPE-specific bootloader in the block fetches the VPD blob from the secure
element via third party driver. From here, the data blob is copied to a
predetermined location in RAM, where it is retrieved and parsed by HPE-specific
code in u-Boot (open-sourced, and available at
https://github.com/HewlettPackard/gxp-uboot). In the future, we'll be aiming to
upstream as much 'HPE-critical' u-boot code as needed so that an HPE-specific
u-boot fork will not be needed to boot HPE hardware.
Additionally, code in u-Boot gathers MAC addresses for the BMC's network
interfaces, along with retrieving a 'server_id' value from an embedded
CPLD-based memory device. This value is unique to each model of HPE platform,
and will be used for platform-wide identification. In comparison, the data in
the aforementioned blob may be used for recognizing finer details like specific
board revisions for a given platform.
The HPE process described above relies on shared memory instead of u-boot env
variables because the HPE bootloader does not know that u-boot will run next,
and does not know where the u-boot variable store is, if it exists at all --
since a customer could decide to use something other than u-boot, or to store
their environmental variables in a different place or format.
After that, u-Boot makes relevant data available to Linux via modifications to
the flattened device tree, setting the values for ['/model' and
'/serial-number,' which both have well-known paths in the device tree
root][dt-spec-chap3-root-node], along with ['local-mac-address,' a property
provided by the network binding][dt-spec-chap4-device-bindings].
[dt-spec-chap3-root-node]:
https://github.com/devicetree-org/devicetree-specification/blob/main/source/chapter3-devicenodes.rst#root-node
[dt-spec-chap4-device-bindings]:
https://github.com/devicetree-org/devicetree-specification/blob/main/source/chapter4-device-bindings.rst#local-mac-address-property
From there, the GXP product data must be published to D-Bus, or there will be no
way for Entity-Manager to reference it during the probe evaluations used in
detecting supported hardware configurations. The contents of 'device-tree/model'
being made available on D-Bus will be enough to enable basic Entity-Manager
identification of HPE baseboard hardware.
In the future, HPE's behind-the-scenes reliance on u-Boot for this process may
be reduced or removed entirely, but but those implementation details should not
affect how a service would collect data from the device-tree passed to the
kernel from u-Boot. One alternative to modifying the flat device-tree would be
to have values like 'model' set in the platform's device-tree source at image
build time.
This document discusses leveraging a 'device-tree -> D-Bus' daemon in
Entity-Manager to enable BMC detection and handling of HPE Gen 11 hardware (and
potentially for other hardware as well).
## Requirements
- Vital product data must be parsed and published to D-Bus
- D-Bus properties for interface(s) at path `xyz/openbmc_project/MachineContext`
may be populated using retrieved VPD values as appropriate to offer a D-Bus
path for common specific model identifying details.
- Vital product data properties should be referenced in Entity-Manager config
'probe' statement(s) in order to key configuration enablement off them.
## Proposed Design
High Level Flow:
- At boot, a proprietary HPE bootblock is validated, then HPE GXP-bootloader
code (proprietary) included in the block retrieves data from a secure element.
Specific hardware identifying information is transferred into a pre-determined
memory location in RAM for pickup.
- u-Boot code (via an
[open source, but HPE-specific process](https://github.com/HewlettPackard/gxp-uboot))
gathers MAC addresses and moves product data from the RAM location, plus a
CPLD-based memory device, and exposes it in Linux under /proc/device-tree/
- A daemon in DeviceTree-VPD-Parser retrieves product data from known device
tree paths, then parses and publishes to D-Bus
- Entity-Manager probes that reference properties from the
`xyz.openbmc_project.Inventory.Decorator.Asset` (.Model & .SerialNumber
properties) interface on D-Bus can key off GXP hardware data and react
accordingly.
## Alternatives Considered
### Entity-Manager probes are extended to handle reading data from arbitrary
device-tree nodes
#### Pros:
1. No new daemon required
#### Cons:
1. May encourage undesired device-tree exploitation
### A reserved-memory node in device-tree is used for transport of
'serial-number' and 'model' ID data
#### Pros:
1. Reserved-memory is commonly used for passing data from firmware
#### Cons:
1. Has no well-known handles for common properties like /model or /serial-number
like device-tree does; makes more sense for keeping arbitrary data instead of
'well-known' properties
2. The critical identifier HPE wants to rely on for platform identification
(/model) comes from a different behind-the-scenes source vs. the rest of the
data planned for output through reserved-memory. Using reserved-memory for
'model' instead of the well known device-tree /model handle would add
additional complexity.
3. Since /model is well described in device-tree documentation, there is
potential for non-HPE platform to make easy use of it. Relying on 'model' as
an arbitrary property in reserved-memory has less potential to be useful
outside of HPE-specific applications.
### All VPD is exposed as devicetree attributes under /chosen/
#### Pros:
1. Is a well-established device-tree node
2. Is not being used by other BMC platforms, so easy to enable/disable service
based on whether or not 'chosen' path exists
3. Values can be set from u-Boot via modifications to the flattened device tree
available to it (applicable to arbitrary device-tree paths)
#### Cons:
1. Not a 'usual' location for passing this kind HW-tied data. Unlikely to ever
be used for moving product data by other entities, so such a daemon would be
defacto HPE-specific code.
2. Presenting HW-specific data here appears to go against the intended use of
'chosen' node
### Vital product data is published to u-Boot environment variables, then
transferred to D-Bus
#### Pros:
1. Would increase code reuse and testing
#### Cons:
1. Potential issues with limited writes to memory where u-boot env variables are
stored in memory.
2. HPE component that retrieves VPD from HPE's secure element has no
knowledge/ability to alter u-boot environmental variables
### Use an HPE-specific daemon instead of a generalized'[channel]-> D-Bus'
daemon
#### Pros:
1. Simpler (slightly?) code
2. Would only fire for HPE platforms
3. Better abstraction
#### Cons:
1. Doesn't save much effort compared to a generalized non-HPE-specific solution
2. Harder to leverage code for potential future cases
### Service is hosted in Entity-Manager [ACCEPTED after TOF re-examination]
#### Pros:
1. Would operate in parallel to existing Fru_Device daemon
#### Cons:
1. Community doesn't want to host VPD -> DBus daemons in Entity-Manager repo
Follow-up: A Technical Oversight Forum discussion has reached consensus that it
would be better to host this device-tree VPD daemon in Entity-Manager alongside
the existing fru-device daemon rather than to create a dedicated repo for a
daemon as simple as this one, or to force into another even less-related repo.
https://github.com/openbmc/technical-oversight-forum/issues/38
### Service is hosted in Phosphor-u-boot-env-mgr
#### Pros:
1. Repo is already associated with u-boot operations
#### Cons:
1. Current repo maintainer feels the service doesn't fit this repo because the
purpose is explicitly to deal with manipulation of u-boot env variables,
which this service is not involved with.
https://gerrit.openbmc.org/c/openbmc/phosphor-u-boot-env-mgr/+/71512
### Addendum: Rejected D-Bus interfaces for pending device-tree -> D-Bus
daemon
#### Existing interfaces (rejected):
1. Proposal: xyz.openbmc_project.Decorator.\*
Rejection: "doesn't represent anything about the physical board" -Ed Tanous
Followup: Phosphor-dbus-interfaces maintenance (Patrick Williams) has
rejected hosting an interface with properties like 'Model' and 'SerialNumber'
that already exist as part of other interfaces, and has specifically
suggested relying on xyz.openbmc_project.Inventory.Decorator.Asset (for
.model and .serialnumber properties) along with
xyz.openbmc_project.Inventory.Item.NetworkInterface (for .MACAddress
property).
Discussion @
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/73260/comment/e0226ae4_d7e514dd/
Follow-up 2: Sticking with Inventory.Decorator.Asset, but removing MAC
address properties to reduce unneeded complexity.
2. Proposal: xyz.openbmc_project.FRUDevice
Rejection: The data is not coming from a FRU device
#### Proposed interfaces (rejected):
1. Proposal: xyz.openbmc_project.DeviceTree
2. Proposal: xyz.openbmc_project.uBootHWID
3. Proposal: xyz.openbmc_project.GXPFRU
Rejection: Above interfaces do not reflect underlying hardware
4. Proposal: xyz.openbmc_project.BMCPrebootContext
Rejection: Arguably doesn't represent a hardware concept.
5. Proposal: xyz.openbmc_project.UbootDeviceModel
Rejection: There are ongoing efforts to enable dynamic device-tree
modifications post-u-boot. The nodes this daemon reads are unlikely to be
affected, but there's no guarantee of that.
6. Proposal: xyz.openbmc_project.Platform
Rejection: Some attributes like serial-number or MAC don't apply across a
given platform
7. Proposal: xyz.openbmc_project.Machine
Rejection: Promising, but the name seems vague re: its purpose.
xyz.openbmc_project.MachineContext has been offered as an alternative.
8. Proposal: xyz.openbmc_project.MachineContext
Rejection: "We have all this stuff [.Model, .SerialNumber, ect. properties] defined
already. I'm not going to accept a new "bunch of random properties HPe thinks
are important [today] globbed into a new interface" interface"
- Patrick Williams, Phosphor-dbus-interfaces maintainer.
Counter-proposal: "Reuse the existing dbus interfaces and put them at a
well-defined location? Inventory.Decorator.[Asset] = Model
Inventory.Decorator.Asset = SerialNumber Inventory.Item.NetworkInterace =
MACAddress.." - Patrick Williams
Discussion @
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/73260/comment/e0226ae4_d7e514dd/
Follow-up: Landed on interface: xyz.openbmc_project.Inventory.Decorator.Asset
@ path xyz/openbmc_project/MachineContext
## Impacts
The above-described process is only intended to scan selected paths -if they
exist- once during initial service startup.
If the path(s) in question do not exist (device-tree/model or
device-tree/serial-number), no further work will be done, so there is expected
to be no noticeable performance or functional impact to platforms that don't
rely on this service for Entity-Manager HW/config detection.
## Organizational:
### Does this design require a new repository?
No. After some discussion, a Technical Oversight Forum consensus was reached to
have the device-tree VPD parser daemon hosted in the Entity-Manager repo
alongside the existing fru-device daemon.
### Which repositories are expected to be modified to execute this design?
Technical Oversight Forums consensus has been reached that this device-tree VPD
daemon will be hosted in Entity-Manager alongside the existing FRU-device VPD
daemon.
Entity-Manager will also have configuration files added for HPE hardware that
make use of the new interface properties via probe statements.
## Testing
Any platform that has a device-tree 'model' or 'serial-number' node populated in
Device-Tree (this can be done by hardcoding a value into the DTS file before
building an image, if desired) can be checked by confirming the contents of the
device-tree/model and/or serial-number node matches the contents of 'model' and
'serial-number' properties of D-Bus interface at D-Bus path
'xyz/openbmc_project/MachineContext'
Practically, the whole of the service stack (including Entity-Manager probe
validation) of the new D-Bus path can be validated on an HPE system by setting
an Entity-Manager config's probe to trigger on match with a known HPE-HW
identifying property, then by confirming
`busctl tree xyz.openbmc_project.EntityManager` shows a listing of objects that
matches what's described in the modified EM config file.
At this time, HPE hardware requires forked (publicly available) OBMC components
to fully boot, so automated testing of HPE hardware against 'mainstream' OBMC
images is not yet a viable option. Enabling this type of testing is a longer
term goal.