* [PATCH 00/22] Aspeed: TMP421 and TMP1075 sensors, and the Clemente BMC machine
@ 2026-10-15 11:57 ` Emmanuel Blot via qemu development
0 siblings, 0 replies; 49+ messages in thread
From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell,
Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery,
Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier,
Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot
Add the clemente-bmc machine and the temperature sensors it needs.
The TMP421 variants are now described by a class descriptor instead
of a lookup table. Channel enablement, register write masks, the
one-shot trigger and the per-channel N-factor registers are modelled,
reset follows Resettable API, and the variant type names move to a
header so boards stop open-coding the strings.
The TMP1075 is a TMP105 with a 16-bit Config register and a read-only
device ID.
The new TMP421 state is stored in optional subsections.
The clemente-bmc machine is derived from the platform device tree and
instantiates every device that is supported in QEMU. FRU EEPROMs are
sanitised images taken from real hardware.
New qtest for the TMP421 family, plus TMP105 cases for the TMP1075.
Both check a migration round trip.
Based-on: <20261015-bmc-minerva-v3-0-7d50c8a108e5@free.fr>
Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr>
---
Emmanuel Blot (22):
hw/sensor: tmp421: do not report a stale errno on a parse failure
hw/sensor: tmp421: name the parent object field parent_obj
hw/sensor: tmp421: implement Resettable reset
hw/sensor: tmp421: model device variants with a class descriptor
hw/sensor: tmp421: honor per-variant channels and channel enablement
hw/sensor: tmp421: implement register write masks, one-shot and N-factor
hw/sensor: tmp421: describe the temperature properties
hw/sensor: tmp421: keep the measurement across a range change
hw/sensor: tmp421: migrate the exact measurement
hw/sensor: tmp421: publish the variant type names
hw/arm/aspeed: use the TMP421 type-name macros
tests/qtest: tmp421: cover device IDs and reset defaults
tests/qtest: tmp421: cover temperature encoding and range
tests/qtest: tmp421: cover per-variant channels and enablement
tests/qtest: tmp421: cover software reset and N-factor registers
tests/qtest: tmp421: cover the register form of the migration stream
hw/sensor: tmp105: add the TMP1075 variant
tests/qtest: tmp105: cover the TMP1075 device ID and reset defaults
tests/qtest: tmp105: cover the TMP1075 config register width
tests/qtest: tmp105: cover the Config low byte across a migration
hw/arm: clemente: add Facebook Clemente BMC machine
hw/arm: clemente: populate the FRU EEPROMs
docs/system/arm/aspeed.rst | 1 +
hw/arm/aspeed_ast2400_palmetto.c | 3 +-
hw/arm/aspeed_ast2400_supermicrox11.c | 3 +-
hw/arm/aspeed_ast2500_supermicro-x11spi.c | 3 +-
hw/arm/aspeed_ast2500_tiogapass.c | 10 +-
hw/arm/aspeed_ast2500_witherspoon.c | 7 +-
hw/arm/aspeed_ast2500_yosemitev2.c | 10 +-
hw/arm/aspeed_ast2600_bletchley.c | 3 +-
hw/arm/aspeed_ast2600_catalina.c | 3 +-
hw/arm/aspeed_ast2600_clemente.c | 1154 +++++++++++++++++++++++++++++
hw/arm/aspeed_ast2600_fby35.c | 2 +-
hw/arm/aspeed_ast2600_fuji.c | 3 +-
hw/arm/aspeed_ast2600_rainier.c | 13 +-
hw/arm/meson.build | 1 +
hw/sensor/tmp105.c | 85 ++-
hw/sensor/tmp421.c | 429 ++++++++---
include/hw/sensor/tmp105.h | 2 +
include/hw/sensor/tmp105_regs.h | 5 +
include/hw/sensor/tmp421.h | 19 +
tests/qtest/meson.build | 1 +
tests/qtest/tmp105-test.c | 111 +++
tests/qtest/tmp421-test.c | 326 ++++++++
22 files changed, 2050 insertions(+), 144 deletions(-)
---
base-commit: 615ece3c406b262996e569f29ea6eed0d81c4d8d
change-id: 20260907-bmc-clemente-0056d6676717
prerequisite-message-id: <20261015-bmc-minerva-v3-0-7d50c8a108e5@free.fr>
prerequisite-patch-id: 5aae2c14351eb51fea0cb307bedf21021730debd
prerequisite-patch-id: 4d9a408b21353dda070052227302e799e4c01726
prerequisite-patch-id: 01470b3e3d522778ea23f39f03a3b82a2a0f2d3e
prerequisite-patch-id: 11d0a41b1b3009d95ddf51d9bde960658c924ac1
prerequisite-patch-id: f1072c7d99e462e1c85ecace78eef33bc6e8778a
prerequisite-patch-id: 8897466a7505261a1060243ca01572c3a8874068
prerequisite-patch-id: f35c864317c68dd2b9ca969bec243fafd80497e6
prerequisite-patch-id: 8b05ecb9c1191509e7e4cc76944c88f4f7891ca2
prerequisite-patch-id: 78155b4352683ffc03826038c3d8160b788c29ff
prerequisite-patch-id: e0af745b421c39fd47311ca21576c510bc961526
prerequisite-patch-id: c14af0a372dcb314ef92a04a47e5bedc846281c8
prerequisite-patch-id: 684f5ec9f4ac0640438d1eead20832c529d67508
prerequisite-patch-id: e09c684b2002e30ae14a11bfe409869478d104bd
prerequisite-patch-id: 09afec3682584cbda09b00c0ac87dc60835454d7
prerequisite-patch-id: a89dfec61a795b84c3cf02927fd7c40bc6f694ae
prerequisite-patch-id: 6a23cb3b1362aaf70fe73f554d9d5fcf2e72c3ec
prerequisite-patch-id: 7c11c16803a5b96be5653a05acf8b46a3020e8d9
prerequisite-patch-id: b9251deb99859cc30a9c67b5dba3066124f32033
prerequisite-patch-id: 87291d7798b6bddde6242c651f0e03deb96ab559
prerequisite-patch-id: caac35561ca8b2bdd86101f943e93aa7bcd3a90c
prerequisite-patch-id: 27b0b37242fba900f982f9bcaca36f48c6a115bb
prerequisite-patch-id: 1259c5fbfeb5d2bf1760e7b12df59f182528cee6
prerequisite-patch-id: 2654532e955554fbae6ffcdf6ff3b38bb03fbbd5
prerequisite-patch-id: ff0505a46b3604ba502834d3f5bf17ab85b3c5fa
prerequisite-patch-id: 250958c152f11026aa98d334892132f9ab7467db
prerequisite-patch-id: f3d938264fb2f0c2c292dbb4fb218e5b8d22c3d9
prerequisite-patch-id: 06602fc849e499131998af486ae455497a4245c1
prerequisite-patch-id: d857ee22db2d62a98f4f2054d1966cce7ed39452
prerequisite-patch-id: 7909e49ac93573ebd56424a556d4e4872e9778eb
prerequisite-patch-id: 53cd0411fed556e85f6557cab6fc32056c24bddc
prerequisite-patch-id: 71752a32c10eacd296f62bcc94c09db5d54007c3
prerequisite-patch-id: 7a21b5fabeddff9c08d6b532b2a398737f375a06
prerequisite-patch-id: c6154dd1e7a48decd770f062fb57f32cfb2e1826
prerequisite-patch-id: b94e4e3d83aa013ffd05267e20d48d6813ca2d7c
prerequisite-patch-id: 23716ee3fbb2395d0fc33922433fb6d708081fae
prerequisite-patch-id: 2e57dc2effacfdfb8adb93f5e33bfefdb7c28dc0
prerequisite-patch-id: 2400063e36ca403574b812436fef8c38608e6005
prerequisite-patch-id: 557a2e98bce9c59d1d4513207e021e217d9dcc59
prerequisite-patch-id: db5ca53f9dccded71da127446b4870678640c86f
prerequisite-patch-id: ddf5d85c6eb13a9121342263b6f0ee9902b40d06
prerequisite-patch-id: d9e3e31b88133c8d2ffac7c931d9ab153cf20af7
prerequisite-patch-id: 7ed25d5dc6b899645ef98cdb591344042b77c41f
prerequisite-patch-id: 6c70cb570c5c6bfe0d61cb4c5260e6d8f195f383
prerequisite-patch-id: 3caea8b32b51fa447ee21565594b6465d2e51670
prerequisite-patch-id: 758236b35dcee46e176a7167e703048e11f6e634
prerequisite-patch-id: 0521a46d473cad9f3924b4e0f86473fe237c1982
prerequisite-patch-id: 819077eedcc252ade342c8288af2d57e0c8ece6f
prerequisite-patch-id: 913f8260d8274a1c1706d09915cf75c0dd11061c
prerequisite-patch-id: b0913e3e23d3bd41ffb248a3afecdbfe93b4915d
prerequisite-patch-id: ef2e1478aad5f5722a2d021b424803d7cb2cdc4c
Best regards,
--
Emmanuel Blot <emmanuel.blot@free.fr>
^ permalink raw reply [flat|nested] 49+ messages in thread* [PATCH 00/22] Aspeed: TMP421 and TMP1075 sensors, and the Clemente BMC machine @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Add the clemente-bmc machine and the temperature sensors it needs. The TMP421 variants are now described by a class descriptor instead of a lookup table. Channel enablement, register write masks, the one-shot trigger and the per-channel N-factor registers are modelled, reset follows Resettable API, and the variant type names move to a header so boards stop open-coding the strings. The TMP1075 is a TMP105 with a 16-bit Config register and a read-only device ID. The new TMP421 state is stored in optional subsections. The clemente-bmc machine is derived from the platform device tree and instantiates every device that is supported in QEMU. FRU EEPROMs are sanitised images taken from real hardware. New qtest for the TMP421 family, plus TMP105 cases for the TMP1075. Both check a migration round trip. Based-on: <20261015-bmc-minerva-v3-0-7d50c8a108e5@free.fr> Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- Emmanuel Blot (22): hw/sensor: tmp421: do not report a stale errno on a parse failure hw/sensor: tmp421: name the parent object field parent_obj hw/sensor: tmp421: implement Resettable reset hw/sensor: tmp421: model device variants with a class descriptor hw/sensor: tmp421: honor per-variant channels and channel enablement hw/sensor: tmp421: implement register write masks, one-shot and N-factor hw/sensor: tmp421: describe the temperature properties hw/sensor: tmp421: keep the measurement across a range change hw/sensor: tmp421: migrate the exact measurement hw/sensor: tmp421: publish the variant type names hw/arm/aspeed: use the TMP421 type-name macros tests/qtest: tmp421: cover device IDs and reset defaults tests/qtest: tmp421: cover temperature encoding and range tests/qtest: tmp421: cover per-variant channels and enablement tests/qtest: tmp421: cover software reset and N-factor registers tests/qtest: tmp421: cover the register form of the migration stream hw/sensor: tmp105: add the TMP1075 variant tests/qtest: tmp105: cover the TMP1075 device ID and reset defaults tests/qtest: tmp105: cover the TMP1075 config register width tests/qtest: tmp105: cover the Config low byte across a migration hw/arm: clemente: add Facebook Clemente BMC machine hw/arm: clemente: populate the FRU EEPROMs docs/system/arm/aspeed.rst | 1 + hw/arm/aspeed_ast2400_palmetto.c | 3 +- hw/arm/aspeed_ast2400_supermicrox11.c | 3 +- hw/arm/aspeed_ast2500_supermicro-x11spi.c | 3 +- hw/arm/aspeed_ast2500_tiogapass.c | 10 +- hw/arm/aspeed_ast2500_witherspoon.c | 7 +- hw/arm/aspeed_ast2500_yosemitev2.c | 10 +- hw/arm/aspeed_ast2600_bletchley.c | 3 +- hw/arm/aspeed_ast2600_catalina.c | 3 +- hw/arm/aspeed_ast2600_clemente.c | 1154 +++++++++++++++++++++++++++++ hw/arm/aspeed_ast2600_fby35.c | 2 +- hw/arm/aspeed_ast2600_fuji.c | 3 +- hw/arm/aspeed_ast2600_rainier.c | 13 +- hw/arm/meson.build | 1 + hw/sensor/tmp105.c | 85 ++- hw/sensor/tmp421.c | 429 ++++++++--- include/hw/sensor/tmp105.h | 2 + include/hw/sensor/tmp105_regs.h | 5 + include/hw/sensor/tmp421.h | 19 + tests/qtest/meson.build | 1 + tests/qtest/tmp105-test.c | 111 +++ tests/qtest/tmp421-test.c | 326 ++++++++ 22 files changed, 2050 insertions(+), 144 deletions(-) --- base-commit: 615ece3c406b262996e569f29ea6eed0d81c4d8d change-id: 20260907-bmc-clemente-0056d6676717 prerequisite-message-id: <20261015-bmc-minerva-v3-0-7d50c8a108e5@free.fr> prerequisite-patch-id: 5aae2c14351eb51fea0cb307bedf21021730debd prerequisite-patch-id: 4d9a408b21353dda070052227302e799e4c01726 prerequisite-patch-id: 01470b3e3d522778ea23f39f03a3b82a2a0f2d3e prerequisite-patch-id: 11d0a41b1b3009d95ddf51d9bde960658c924ac1 prerequisite-patch-id: f1072c7d99e462e1c85ecace78eef33bc6e8778a prerequisite-patch-id: 8897466a7505261a1060243ca01572c3a8874068 prerequisite-patch-id: f35c864317c68dd2b9ca969bec243fafd80497e6 prerequisite-patch-id: 8b05ecb9c1191509e7e4cc76944c88f4f7891ca2 prerequisite-patch-id: 78155b4352683ffc03826038c3d8160b788c29ff prerequisite-patch-id: e0af745b421c39fd47311ca21576c510bc961526 prerequisite-patch-id: c14af0a372dcb314ef92a04a47e5bedc846281c8 prerequisite-patch-id: 684f5ec9f4ac0640438d1eead20832c529d67508 prerequisite-patch-id: e09c684b2002e30ae14a11bfe409869478d104bd prerequisite-patch-id: 09afec3682584cbda09b00c0ac87dc60835454d7 prerequisite-patch-id: a89dfec61a795b84c3cf02927fd7c40bc6f694ae prerequisite-patch-id: 6a23cb3b1362aaf70fe73f554d9d5fcf2e72c3ec prerequisite-patch-id: 7c11c16803a5b96be5653a05acf8b46a3020e8d9 prerequisite-patch-id: b9251deb99859cc30a9c67b5dba3066124f32033 prerequisite-patch-id: 87291d7798b6bddde6242c651f0e03deb96ab559 prerequisite-patch-id: caac35561ca8b2bdd86101f943e93aa7bcd3a90c prerequisite-patch-id: 27b0b37242fba900f982f9bcaca36f48c6a115bb prerequisite-patch-id: 1259c5fbfeb5d2bf1760e7b12df59f182528cee6 prerequisite-patch-id: 2654532e955554fbae6ffcdf6ff3b38bb03fbbd5 prerequisite-patch-id: ff0505a46b3604ba502834d3f5bf17ab85b3c5fa prerequisite-patch-id: 250958c152f11026aa98d334892132f9ab7467db prerequisite-patch-id: f3d938264fb2f0c2c292dbb4fb218e5b8d22c3d9 prerequisite-patch-id: 06602fc849e499131998af486ae455497a4245c1 prerequisite-patch-id: d857ee22db2d62a98f4f2054d1966cce7ed39452 prerequisite-patch-id: 7909e49ac93573ebd56424a556d4e4872e9778eb prerequisite-patch-id: 53cd0411fed556e85f6557cab6fc32056c24bddc prerequisite-patch-id: 71752a32c10eacd296f62bcc94c09db5d54007c3 prerequisite-patch-id: 7a21b5fabeddff9c08d6b532b2a398737f375a06 prerequisite-patch-id: c6154dd1e7a48decd770f062fb57f32cfb2e1826 prerequisite-patch-id: b94e4e3d83aa013ffd05267e20d48d6813ca2d7c prerequisite-patch-id: 23716ee3fbb2395d0fc33922433fb6d708081fae prerequisite-patch-id: 2e57dc2effacfdfb8adb93f5e33bfefdb7c28dc0 prerequisite-patch-id: 2400063e36ca403574b812436fef8c38608e6005 prerequisite-patch-id: 557a2e98bce9c59d1d4513207e021e217d9dcc59 prerequisite-patch-id: db5ca53f9dccded71da127446b4870678640c86f prerequisite-patch-id: ddf5d85c6eb13a9121342263b6f0ee9902b40d06 prerequisite-patch-id: d9e3e31b88133c8d2ffac7c931d9ab153cf20af7 prerequisite-patch-id: 7ed25d5dc6b899645ef98cdb591344042b77c41f prerequisite-patch-id: 6c70cb570c5c6bfe0d61cb4c5260e6d8f195f383 prerequisite-patch-id: 3caea8b32b51fa447ee21565594b6465d2e51670 prerequisite-patch-id: 758236b35dcee46e176a7167e703048e11f6e634 prerequisite-patch-id: 0521a46d473cad9f3924b4e0f86473fe237c1982 prerequisite-patch-id: 819077eedcc252ade342c8288af2d57e0c8ece6f prerequisite-patch-id: 913f8260d8274a1c1706d09915cf75c0dd11061c prerequisite-patch-id: b0913e3e23d3bd41ffb248a3afecdbfe93b4915d prerequisite-patch-id: ef2e1478aad5f5722a2d021b424803d7cb2cdc4c Best regards, -- Emmanuel Blot <emmanuel.blot@free.fr> ^ permalink raw reply [flat|nested] 49+ messages in thread
* [PATCH 01/22] hw/sensor: tmp421: do not report a stale errno on a parse failure 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The temperature property accessors decode the channel index out of the property name and report a failure with error_setg_errno(). sscanf() does not set errno when it matches fewer items than expected, so the message is suffixed with whatever unrelated error was left behind by an earlier call. The bounds check right below already uses plain error_setg() for the same condition. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 127edd0ba5..fde41b2323 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -117,7 +117,7 @@ static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name, int tempid; if (sscanf(name, "temperature%d", &tempid) != 1) { - error_setg_errno(errp, errno, "error reading %s", name); + error_setg(errp, "error reading %s", name); return; } @@ -154,7 +154,7 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, } if (sscanf(name, "temperature%d", &tempid) != 1) { - error_setg_errno(errp, errno, "error reading %s", name); + error_setg(errp, "error reading %s", name); return; } -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 01/22] hw/sensor: tmp421: do not report a stale errno on a parse failure @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The temperature property accessors decode the channel index out of the property name and report a failure with error_setg_errno(). sscanf() does not set errno when it matches fewer items than expected, so the message is suffixed with whatever unrelated error was left behind by an earlier call. The bounds check right below already uses plain error_setg() for the same condition. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 127edd0ba5..fde41b2323 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -117,7 +117,7 @@ static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name, int tempid; if (sscanf(name, "temperature%d", &tempid) != 1) { - error_setg_errno(errp, errno, "error reading %s", name); + error_setg(errp, "error reading %s", name); return; } @@ -154,7 +154,7 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, } if (sscanf(name, "temperature%d", &tempid) != 1) { - error_setg_errno(errp, errno, "error reading %s", name); + error_setg(errp, "error reading %s", name); return; } -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 02/22] hw/sensor: tmp421: name the parent object field parent_obj 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Follow the QOM convention for the embedded I2CSlave, matching the other hw/sensor I2C devices. No functional change. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index fde41b2323..e7927699ce 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -51,7 +51,7 @@ static const DeviceInfo devices[] = { struct TMP421State { /*< private >*/ - I2CSlave i2c; + I2CSlave parent_obj; /*< public >*/ int16_t temperature[4]; @@ -298,7 +298,7 @@ static const VMStateDescription vmstate_tmp421 = { VMSTATE_UINT8(status, TMP421State), VMSTATE_UINT8(rate, TMP421State), VMSTATE_INT16_ARRAY(temperature, TMP421State, 4), - VMSTATE_I2C_SLAVE(i2c, TMP421State), + VMSTATE_I2C_SLAVE(parent_obj, TMP421State), VMSTATE_END_OF_LIST() } }; @@ -334,7 +334,7 @@ static void tmp421_realize(DeviceState *dev, Error **errp) { TMP421State *s = TMP421(dev); - tmp421_reset(&s->i2c); + tmp421_reset(&s->parent_obj); } static void tmp421_class_init(ObjectClass *klass, const void *data) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 02/22] hw/sensor: tmp421: name the parent object field parent_obj @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Follow the QOM convention for the embedded I2CSlave, matching the other hw/sensor I2C devices. No functional change. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index fde41b2323..e7927699ce 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -51,7 +51,7 @@ static const DeviceInfo devices[] = { struct TMP421State { /*< private >*/ - I2CSlave i2c; + I2CSlave parent_obj; /*< public >*/ int16_t temperature[4]; @@ -298,7 +298,7 @@ static const VMStateDescription vmstate_tmp421 = { VMSTATE_UINT8(status, TMP421State), VMSTATE_UINT8(rate, TMP421State), VMSTATE_INT16_ARRAY(temperature, TMP421State, 4), - VMSTATE_I2C_SLAVE(i2c, TMP421State), + VMSTATE_I2C_SLAVE(parent_obj, TMP421State), VMSTATE_END_OF_LIST() } }; @@ -334,7 +334,7 @@ static void tmp421_realize(DeviceState *dev, Error **errp) { TMP421State *s = TMP421(dev); - tmp421_reset(&s->i2c); + tmp421_reset(&s->parent_obj); } static void tmp421_class_init(ObjectClass *klass, const void *data) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 03/22] hw/sensor: tmp421: implement Resettable reset 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Wire the reset through the Resettable hold phase instead of only calling it from realize, so bus and system resets re-initialise the device. The measured temperatures are no longer cleared on reset: they represent the physical input the ADC re-samples, and boards may preset them before the machine-wide power-on reset. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index e7927699ce..a9d15601cb 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -224,7 +224,7 @@ static void tmp421_read(TMP421State *s) } } -static void tmp421_reset(I2CSlave *i2c); +static void tmp421_reset(TMP421State *s); static void tmp421_write(TMP421State *s) { @@ -239,7 +239,7 @@ static void tmp421_write(TMP421State *s) s->config[1] = s->buf[0]; break; case TMP421_RESET: - tmp421_reset(I2C_SLAVE(s)); + tmp421_reset(s); break; } } @@ -303,17 +303,18 @@ static const VMStateDescription vmstate_tmp421 = { } }; -static void tmp421_reset(I2CSlave *i2c) +static void tmp421_reset(TMP421State *s) { - TMP421State *s = TMP421(i2c); TMP421Class *sc = TMP421_GET_CLASS(s); - memset(s->temperature, 0, sizeof(s->temperature)); + /* + * The measured temperatures are not cleared: they model the physical + * input the ADC re-samples after reset, and boards may preset them. + */ s->pointer = 0; + s->config[0] = 0; - s->config[0] = 0; /* TMP421_CONFIG_RANGE */ - - /* resistance correction and channel enablement */ + /* resistance correction and channel enablement */ switch (sc->dev->model) { case TMP421_DEVICE_ID: s->config[1] = 0x1c; @@ -330,23 +331,22 @@ static void tmp421_reset(I2CSlave *i2c) s->status = 0; } -static void tmp421_realize(DeviceState *dev, Error **errp) +static void tmp421_reset_hold(Object *obj, ResetType type) { - TMP421State *s = TMP421(dev); - - tmp421_reset(&s->parent_obj); + tmp421_reset(TMP421(obj)); } static void tmp421_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); TMP421Class *sc = TMP421_CLASS(klass); - dc->realize = tmp421_realize; k->event = tmp421_event; k->recv = tmp421_rx; k->send = tmp421_tx; + rc->phases.hold = tmp421_reset_hold; dc->vmsd = &vmstate_tmp421; sc->dev = (DeviceInfo *) data; -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 03/22] hw/sensor: tmp421: implement Resettable reset @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Wire the reset through the Resettable hold phase instead of only calling it from realize, so bus and system resets re-initialise the device. The measured temperatures are no longer cleared on reset: they represent the physical input the ADC re-samples, and boards may preset them before the machine-wide power-on reset. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index e7927699ce..a9d15601cb 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -224,7 +224,7 @@ static void tmp421_read(TMP421State *s) } } -static void tmp421_reset(I2CSlave *i2c); +static void tmp421_reset(TMP421State *s); static void tmp421_write(TMP421State *s) { @@ -239,7 +239,7 @@ static void tmp421_write(TMP421State *s) s->config[1] = s->buf[0]; break; case TMP421_RESET: - tmp421_reset(I2C_SLAVE(s)); + tmp421_reset(s); break; } } @@ -303,17 +303,18 @@ static const VMStateDescription vmstate_tmp421 = { } }; -static void tmp421_reset(I2CSlave *i2c) +static void tmp421_reset(TMP421State *s) { - TMP421State *s = TMP421(i2c); TMP421Class *sc = TMP421_GET_CLASS(s); - memset(s->temperature, 0, sizeof(s->temperature)); + /* + * The measured temperatures are not cleared: they model the physical + * input the ADC re-samples after reset, and boards may preset them. + */ s->pointer = 0; + s->config[0] = 0; - s->config[0] = 0; /* TMP421_CONFIG_RANGE */ - - /* resistance correction and channel enablement */ + /* resistance correction and channel enablement */ switch (sc->dev->model) { case TMP421_DEVICE_ID: s->config[1] = 0x1c; @@ -330,23 +331,22 @@ static void tmp421_reset(I2CSlave *i2c) s->status = 0; } -static void tmp421_realize(DeviceState *dev, Error **errp) +static void tmp421_reset_hold(Object *obj, ResetType type) { - TMP421State *s = TMP421(dev); - - tmp421_reset(&s->parent_obj); + tmp421_reset(TMP421(obj)); } static void tmp421_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); TMP421Class *sc = TMP421_CLASS(klass); - dc->realize = tmp421_realize; k->event = tmp421_event; k->recv = tmp421_rx; k->send = tmp421_tx; + rc->phases.hold = tmp421_reset_hold; dc->vmsd = &vmstate_tmp421; sc->dev = (DeviceInfo *) data; -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 04/22] hw/sensor: tmp421: model device variants with a class descriptor 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Replace the ad-hoc DeviceInfo table and its manual type-registration loop with per-variant fields on the device class, set by a dedicated class_init for each part and registered through DEFINE_TYPES. This drops the abstract base type in favour of the TMP421 acting as the base for its TMP422/TMP423 supersets. The three instantiable type names are unchanged, but TYPE_TMP421 now spells "tmp421" rather than the abstract "tmp421-generic", which no longer exists, and a TMP421 cast now succeeds for the two supersets. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 98 +++++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index a9d15601cb..7f0e3b3214 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -38,17 +38,6 @@ #define TMP422_DEVICE_ID 0x22 #define TMP423_DEVICE_ID 0x23 -typedef struct DeviceInfo { - int model; - const char *name; -} DeviceInfo; - -static const DeviceInfo devices[] = { - { TMP421_DEVICE_ID, "tmp421" }, - { TMP422_DEVICE_ID, "tmp422" }, - { TMP423_DEVICE_ID, "tmp423" }, -}; - struct TMP421State { /*< private >*/ I2CSlave parent_obj; @@ -68,10 +57,14 @@ struct TMP421State { struct TMP421Class { I2CSlaveClass parent_class; - const DeviceInfo *dev; + + uint8_t device_id; + uint8_t config2_reset; }; -#define TYPE_TMP421 "tmp421-generic" +#define TYPE_TMP421 "tmp421" +#define TYPE_TMP422 "tmp422" +#define TYPE_TMP423 "tmp423" OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) @@ -177,7 +170,7 @@ static void tmp421_read(TMP421State *s) s->buf[s->len++] = TMP421_MANUFACTURER_ID; break; case TMP421_DEVICE_ID_REG: - s->buf[s->len++] = sc->dev->model; + s->buf[s->len++] = sc->device_id; break; case TMP421_CONFIG_REG_1: s->buf[s->len++] = s->config[0]; @@ -313,20 +306,7 @@ static void tmp421_reset(TMP421State *s) */ s->pointer = 0; s->config[0] = 0; - - /* resistance correction and channel enablement */ - switch (sc->dev->model) { - case TMP421_DEVICE_ID: - s->config[1] = 0x1c; - break; - case TMP422_DEVICE_ID: - s->config[1] = 0x3c; - break; - case TMP423_DEVICE_ID: - s->config[1] = 0x7c; - break; - } - + s->config[1] = sc->config2_reset; s->rate = 0x7; /* 8Hz */ s->status = 0; } @@ -348,7 +328,9 @@ static void tmp421_class_init(ObjectClass *klass, const void *data) k->send = tmp421_tx; rc->phases.hold = tmp421_reset_hold; dc->vmsd = &vmstate_tmp421; - sc->dev = (DeviceInfo *) data; + + sc->device_id = TMP421_DEVICE_ID; + sc->config2_reset = 0x1c; object_class_property_add(klass, "temperature0", "int", tmp421_get_temperature, @@ -364,28 +346,40 @@ static void tmp421_class_init(ObjectClass *klass, const void *data) tmp421_set_temperature, NULL, NULL); } -static const TypeInfo tmp421_info = { - .name = TYPE_TMP421, - .parent = TYPE_I2C_SLAVE, - .instance_size = sizeof(TMP421State), - .class_size = sizeof(TMP421Class), - .abstract = true, +static void tmp422_class_init(ObjectClass *klass, const void *data) +{ + TMP421Class *sc = TMP421_CLASS(klass); + + sc->device_id = TMP422_DEVICE_ID; + sc->config2_reset = 0x3c; +} + +static void tmp423_class_init(ObjectClass *klass, const void *data) +{ + TMP421Class *sc = TMP421_CLASS(klass); + + sc->device_id = TMP423_DEVICE_ID; + sc->config2_reset = 0x7c; +} + +static const TypeInfo tmp421_types[] = { + { + .name = TYPE_TMP421, + .parent = TYPE_I2C_SLAVE, + .instance_size = sizeof(TMP421State), + .class_size = sizeof(TMP421Class), + .class_init = tmp421_class_init, + }, + { + .name = TYPE_TMP422, + .parent = TYPE_TMP421, + .class_init = tmp422_class_init, + }, + { + .name = TYPE_TMP423, + .parent = TYPE_TMP421, + .class_init = tmp423_class_init, + }, }; -static void tmp421_register_types(void) -{ - int i; - - type_register_static(&tmp421_info); - for (i = 0; i < ARRAY_SIZE(devices); ++i) { - TypeInfo ti = { - .name = devices[i].name, - .parent = TYPE_TMP421, - .class_init = tmp421_class_init, - .class_data = &devices[i], - }; - type_register_static(&ti); - } -} - -type_init(tmp421_register_types) +DEFINE_TYPES(tmp421_types) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 04/22] hw/sensor: tmp421: model device variants with a class descriptor @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Replace the ad-hoc DeviceInfo table and its manual type-registration loop with per-variant fields on the device class, set by a dedicated class_init for each part and registered through DEFINE_TYPES. This drops the abstract base type in favour of the TMP421 acting as the base for its TMP422/TMP423 supersets. The three instantiable type names are unchanged, but TYPE_TMP421 now spells "tmp421" rather than the abstract "tmp421-generic", which no longer exists, and a TMP421 cast now succeeds for the two supersets. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 98 +++++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index a9d15601cb..7f0e3b3214 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -38,17 +38,6 @@ #define TMP422_DEVICE_ID 0x22 #define TMP423_DEVICE_ID 0x23 -typedef struct DeviceInfo { - int model; - const char *name; -} DeviceInfo; - -static const DeviceInfo devices[] = { - { TMP421_DEVICE_ID, "tmp421" }, - { TMP422_DEVICE_ID, "tmp422" }, - { TMP423_DEVICE_ID, "tmp423" }, -}; - struct TMP421State { /*< private >*/ I2CSlave parent_obj; @@ -68,10 +57,14 @@ struct TMP421State { struct TMP421Class { I2CSlaveClass parent_class; - const DeviceInfo *dev; + + uint8_t device_id; + uint8_t config2_reset; }; -#define TYPE_TMP421 "tmp421-generic" +#define TYPE_TMP421 "tmp421" +#define TYPE_TMP422 "tmp422" +#define TYPE_TMP423 "tmp423" OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) @@ -177,7 +170,7 @@ static void tmp421_read(TMP421State *s) s->buf[s->len++] = TMP421_MANUFACTURER_ID; break; case TMP421_DEVICE_ID_REG: - s->buf[s->len++] = sc->dev->model; + s->buf[s->len++] = sc->device_id; break; case TMP421_CONFIG_REG_1: s->buf[s->len++] = s->config[0]; @@ -313,20 +306,7 @@ static void tmp421_reset(TMP421State *s) */ s->pointer = 0; s->config[0] = 0; - - /* resistance correction and channel enablement */ - switch (sc->dev->model) { - case TMP421_DEVICE_ID: - s->config[1] = 0x1c; - break; - case TMP422_DEVICE_ID: - s->config[1] = 0x3c; - break; - case TMP423_DEVICE_ID: - s->config[1] = 0x7c; - break; - } - + s->config[1] = sc->config2_reset; s->rate = 0x7; /* 8Hz */ s->status = 0; } @@ -348,7 +328,9 @@ static void tmp421_class_init(ObjectClass *klass, const void *data) k->send = tmp421_tx; rc->phases.hold = tmp421_reset_hold; dc->vmsd = &vmstate_tmp421; - sc->dev = (DeviceInfo *) data; + + sc->device_id = TMP421_DEVICE_ID; + sc->config2_reset = 0x1c; object_class_property_add(klass, "temperature0", "int", tmp421_get_temperature, @@ -364,28 +346,40 @@ static void tmp421_class_init(ObjectClass *klass, const void *data) tmp421_set_temperature, NULL, NULL); } -static const TypeInfo tmp421_info = { - .name = TYPE_TMP421, - .parent = TYPE_I2C_SLAVE, - .instance_size = sizeof(TMP421State), - .class_size = sizeof(TMP421Class), - .abstract = true, +static void tmp422_class_init(ObjectClass *klass, const void *data) +{ + TMP421Class *sc = TMP421_CLASS(klass); + + sc->device_id = TMP422_DEVICE_ID; + sc->config2_reset = 0x3c; +} + +static void tmp423_class_init(ObjectClass *klass, const void *data) +{ + TMP421Class *sc = TMP421_CLASS(klass); + + sc->device_id = TMP423_DEVICE_ID; + sc->config2_reset = 0x7c; +} + +static const TypeInfo tmp421_types[] = { + { + .name = TYPE_TMP421, + .parent = TYPE_I2C_SLAVE, + .instance_size = sizeof(TMP421State), + .class_size = sizeof(TMP421Class), + .class_init = tmp421_class_init, + }, + { + .name = TYPE_TMP422, + .parent = TYPE_TMP421, + .class_init = tmp422_class_init, + }, + { + .name = TYPE_TMP423, + .parent = TYPE_TMP421, + .class_init = tmp423_class_init, + }, }; -static void tmp421_register_types(void) -{ - int i; - - type_register_static(&tmp421_info); - for (i = 0; i < ARRAY_SIZE(devices); ++i) { - TypeInfo ti = { - .name = devices[i].name, - .parent = TYPE_TMP421, - .class_init = tmp421_class_init, - .class_data = &devices[i], - }; - type_register_static(&ti); - } -} - -type_init(tmp421_register_types) +DEFINE_TYPES(tmp421_types) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 05/22] hw/sensor: tmp421: honor per-variant channels and channel enablement 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Each part exposes a different number of temperature channels; register only the temperature properties that exist and gate the temperature register reads on both channel presence and the configuration enable bits. A disabled or absent channel now reads back zero instead of stale data, resolving the long-standing FIXME. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 100 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 7f0e3b3214..8bacd7d05e 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -59,6 +59,7 @@ struct TMP421Class { I2CSlaveClass parent_class; uint8_t device_id; + uint8_t nchannels; /* local + remote */ uint8_t config2_reset; }; @@ -159,12 +160,50 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset; } +static bool tmp421_channel_enabled(TMP421State *s, unsigned channel) +{ + TMP421Class *sc = TMP421_GET_CLASS(s); + + return channel < sc->nchannels && + (s->config[1] & (1 << (3 + channel))); +} + +/* + * A disabled or absent channel reads back zero. The low byte carries the + * temperature fraction in its upper nibble. + */ +static uint8_t tmp421_temp_high(TMP421State *s, unsigned channel) +{ + uint16_t reg = s->temperature[channel]; + + return tmp421_channel_enabled(s, channel) ? reg >> 8 : 0; +} + +static uint8_t tmp421_temp_low(TMP421State *s, unsigned channel) +{ + uint16_t reg = s->temperature[channel]; + + return tmp421_channel_enabled(s, channel) ? reg & 0xf0 : 0; +} + static void tmp421_read(TMP421State *s) { TMP421Class *sc = TMP421_GET_CLASS(s); s->len = 0; + if (s->pointer <= TMP421_TEMP_MSB3) { + /* high byte read latches the paired low byte from one conversion */ + unsigned channel = s->pointer - TMP421_TEMP_MSB0; + s->buf[s->len++] = tmp421_temp_high(s, channel); + s->buf[s->len++] = tmp421_temp_low(s, channel); + return; + } + if (s->pointer >= TMP421_TEMP_LSB0 && s->pointer <= TMP421_TEMP_LSB3) { + s->buf[s->len++] = tmp421_temp_low(s, s->pointer - TMP421_TEMP_LSB0); + return; + } + switch (s->pointer) { case TMP421_MANUFACTURER_ID_REG: s->buf[s->len++] = TMP421_MANUFACTURER_ID; @@ -184,35 +223,8 @@ static void tmp421_read(TMP421State *s) case TMP421_STATUS_REG: s->buf[s->len++] = s->status; break; - - /* FIXME: check for channel enablement in config registers */ - case TMP421_TEMP_MSB0: - s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0; - break; - case TMP421_TEMP_MSB1: - s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0; - break; - case TMP421_TEMP_MSB2: - s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0; - break; - case TMP421_TEMP_MSB3: - s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB0: - s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB1: - s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB2: - s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB3: - s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0; + default: + s->buf[s->len++] = 0; break; } } @@ -316,6 +328,19 @@ static void tmp421_reset_hold(Object *obj, ResetType type) tmp421_reset(TMP421(obj)); } +static void tmp421_initfn(Object *obj) +{ + TMP421Class *sc = TMP421_GET_CLASS(obj); + + for (unsigned channel = 0; channel < sc->nchannels; channel++) { + g_autofree char *name = g_strdup_printf("temperature%u", channel); + + object_property_add(obj, name, "int", + tmp421_get_temperature, + tmp421_set_temperature, NULL, NULL); + } +} + static void tmp421_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -331,19 +356,7 @@ static void tmp421_class_init(ObjectClass *klass, const void *data) sc->device_id = TMP421_DEVICE_ID; sc->config2_reset = 0x1c; - - object_class_property_add(klass, "temperature0", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); - object_class_property_add(klass, "temperature1", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); - object_class_property_add(klass, "temperature2", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); - object_class_property_add(klass, "temperature3", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); + sc->nchannels = 2; } static void tmp422_class_init(ObjectClass *klass, const void *data) @@ -352,6 +365,7 @@ static void tmp422_class_init(ObjectClass *klass, const void *data) sc->device_id = TMP422_DEVICE_ID; sc->config2_reset = 0x3c; + sc->nchannels = 3; } static void tmp423_class_init(ObjectClass *klass, const void *data) @@ -360,6 +374,7 @@ static void tmp423_class_init(ObjectClass *klass, const void *data) sc->device_id = TMP423_DEVICE_ID; sc->config2_reset = 0x7c; + sc->nchannels = 4; } static const TypeInfo tmp421_types[] = { @@ -367,6 +382,7 @@ static const TypeInfo tmp421_types[] = { .name = TYPE_TMP421, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(TMP421State), + .instance_init = tmp421_initfn, .class_size = sizeof(TMP421Class), .class_init = tmp421_class_init, }, -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 05/22] hw/sensor: tmp421: honor per-variant channels and channel enablement @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Each part exposes a different number of temperature channels; register only the temperature properties that exist and gate the temperature register reads on both channel presence and the configuration enable bits. A disabled or absent channel now reads back zero instead of stale data, resolving the long-standing FIXME. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 100 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 7f0e3b3214..8bacd7d05e 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -59,6 +59,7 @@ struct TMP421Class { I2CSlaveClass parent_class; uint8_t device_id; + uint8_t nchannels; /* local + remote */ uint8_t config2_reset; }; @@ -159,12 +160,50 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset; } +static bool tmp421_channel_enabled(TMP421State *s, unsigned channel) +{ + TMP421Class *sc = TMP421_GET_CLASS(s); + + return channel < sc->nchannels && + (s->config[1] & (1 << (3 + channel))); +} + +/* + * A disabled or absent channel reads back zero. The low byte carries the + * temperature fraction in its upper nibble. + */ +static uint8_t tmp421_temp_high(TMP421State *s, unsigned channel) +{ + uint16_t reg = s->temperature[channel]; + + return tmp421_channel_enabled(s, channel) ? reg >> 8 : 0; +} + +static uint8_t tmp421_temp_low(TMP421State *s, unsigned channel) +{ + uint16_t reg = s->temperature[channel]; + + return tmp421_channel_enabled(s, channel) ? reg & 0xf0 : 0; +} + static void tmp421_read(TMP421State *s) { TMP421Class *sc = TMP421_GET_CLASS(s); s->len = 0; + if (s->pointer <= TMP421_TEMP_MSB3) { + /* high byte read latches the paired low byte from one conversion */ + unsigned channel = s->pointer - TMP421_TEMP_MSB0; + s->buf[s->len++] = tmp421_temp_high(s, channel); + s->buf[s->len++] = tmp421_temp_low(s, channel); + return; + } + if (s->pointer >= TMP421_TEMP_LSB0 && s->pointer <= TMP421_TEMP_LSB3) { + s->buf[s->len++] = tmp421_temp_low(s, s->pointer - TMP421_TEMP_LSB0); + return; + } + switch (s->pointer) { case TMP421_MANUFACTURER_ID_REG: s->buf[s->len++] = TMP421_MANUFACTURER_ID; @@ -184,35 +223,8 @@ static void tmp421_read(TMP421State *s) case TMP421_STATUS_REG: s->buf[s->len++] = s->status; break; - - /* FIXME: check for channel enablement in config registers */ - case TMP421_TEMP_MSB0: - s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0; - break; - case TMP421_TEMP_MSB1: - s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0; - break; - case TMP421_TEMP_MSB2: - s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0; - break; - case TMP421_TEMP_MSB3: - s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 8); - s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB0: - s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB1: - s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB2: - s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0; - break; - case TMP421_TEMP_LSB3: - s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0; + default: + s->buf[s->len++] = 0; break; } } @@ -316,6 +328,19 @@ static void tmp421_reset_hold(Object *obj, ResetType type) tmp421_reset(TMP421(obj)); } +static void tmp421_initfn(Object *obj) +{ + TMP421Class *sc = TMP421_GET_CLASS(obj); + + for (unsigned channel = 0; channel < sc->nchannels; channel++) { + g_autofree char *name = g_strdup_printf("temperature%u", channel); + + object_property_add(obj, name, "int", + tmp421_get_temperature, + tmp421_set_temperature, NULL, NULL); + } +} + static void tmp421_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -331,19 +356,7 @@ static void tmp421_class_init(ObjectClass *klass, const void *data) sc->device_id = TMP421_DEVICE_ID; sc->config2_reset = 0x1c; - - object_class_property_add(klass, "temperature0", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); - object_class_property_add(klass, "temperature1", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); - object_class_property_add(klass, "temperature2", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); - object_class_property_add(klass, "temperature3", "int", - tmp421_get_temperature, - tmp421_set_temperature, NULL, NULL); + sc->nchannels = 2; } static void tmp422_class_init(ObjectClass *klass, const void *data) @@ -352,6 +365,7 @@ static void tmp422_class_init(ObjectClass *klass, const void *data) sc->device_id = TMP422_DEVICE_ID; sc->config2_reset = 0x3c; + sc->nchannels = 3; } static void tmp423_class_init(ObjectClass *klass, const void *data) @@ -360,6 +374,7 @@ static void tmp423_class_init(ObjectClass *klass, const void *data) sc->device_id = TMP423_DEVICE_ID; sc->config2_reset = 0x7c; + sc->nchannels = 4; } static const TypeInfo tmp421_types[] = { @@ -367,6 +382,7 @@ static const TypeInfo tmp421_types[] = { .name = TYPE_TMP421, .parent = TYPE_I2C_SLAVE, .instance_size = sizeof(TMP421State), + .instance_init = tmp421_initfn, .class_size = sizeof(TMP421Class), .class_init = tmp421_class_init, }, -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 06/22] hw/sensor: tmp421: implement register write masks, one-shot and N-factor 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Mask out reserved and absent-channel bits on writes to the two configuration registers and the conversion rate, accept the one-shot trigger, and back the per-remote-channel N-factor correction registers with real storage. The N-factor state migrates through an optional subsection. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 8bacd7d05e..9e1249afb8 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -22,6 +22,16 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Limitations: + * - Conversions are instantaneous. The conversion-rate register and the + * shutdown bit are stored but do not decide when a measurement appears, + * and a one-shot write is accepted without scheduling anything: a read + * always returns a fresh value. + * - The N-factor correction registers are stored and never applied. The model + * has no ideality factor to correct for. + * - The sensor-fault OPEN bit and the PVLD bit of the temperature low byte are + * never set, so neither an open circuit nor a low supply is reported. */ #include "qemu/osdep.h" @@ -44,6 +54,7 @@ struct TMP421State { /*< public >*/ int16_t temperature[4]; + uint8_t n_correct[3]; /* remote channels only */ uint8_t status; uint8_t config[2]; @@ -85,6 +96,8 @@ OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_ONE_SHOT 0x0F +#define TMP421_N_CORRECT 0x21 + #define TMP421_RESET 0xFC #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF @@ -203,6 +216,11 @@ static void tmp421_read(TMP421State *s) s->buf[s->len++] = tmp421_temp_low(s, s->pointer - TMP421_TEMP_LSB0); return; } + if (s->pointer >= TMP421_N_CORRECT && s->pointer < TMP421_N_CORRECT + 3) { + unsigned idx = s->pointer - TMP421_N_CORRECT; + s->buf[s->len++] = idx + 1 < sc->nchannels ? s->n_correct[idx] : 0; + return; + } switch (s->pointer) { case TMP421_MANUFACTURER_ID_REG: @@ -233,15 +251,29 @@ static void tmp421_reset(TMP421State *s); static void tmp421_write(TMP421State *s) { + TMP421Class *sc = TMP421_GET_CLASS(s); + + if (s->pointer >= TMP421_N_CORRECT && s->pointer < TMP421_N_CORRECT + 3) { + unsigned idx = s->pointer - TMP421_N_CORRECT; + if (idx + 1 < sc->nchannels) { + s->n_correct[idx] = s->buf[0]; + } + return; + } + switch (s->pointer) { - case TMP421_CONVERSION_RATE_REG: - s->rate = s->buf[0]; - break; case TMP421_CONFIG_REG_1: - s->config[0] = s->buf[0]; + s->config[0] = s->buf[0] & + (TMP421_CONFIG_RANGE | TMP421_CONFIG_SHUTDOWN); break; case TMP421_CONFIG_REG_2: - s->config[1] = s->buf[0]; + s->config[1] = s->buf[0] & sc->config2_reset; + break; + case TMP421_CONVERSION_RATE_REG: + s->rate = s->buf[0] & 0x07; + break; + case TMP421_ONE_SHOT: + /* starts a conversion in shutdown; conversions are immediate here */ break; case TMP421_RESET: tmp421_reset(s); @@ -291,6 +323,24 @@ static int tmp421_event(I2CSlave *i2c, enum i2c_event event) return 0; } +static bool tmp421_n_correct_needed(void *opaque) +{ + TMP421State *s = opaque; + + return s->n_correct[0] || s->n_correct[1] || s->n_correct[2]; +} + +static const VMStateDescription vmstate_tmp421_n_correct = { + .name = "TMP421/n-correct", + .version_id = 1, + .minimum_version_id = 1, + .needed = tmp421_n_correct_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINT8_ARRAY(n_correct, TMP421State, 3), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_tmp421 = { .name = "TMP421", .version_id = 0, @@ -305,6 +355,10 @@ static const VMStateDescription vmstate_tmp421 = { VMSTATE_INT16_ARRAY(temperature, TMP421State, 4), VMSTATE_I2C_SLAVE(parent_obj, TMP421State), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * const []) { + &vmstate_tmp421_n_correct, + NULL } }; @@ -316,6 +370,7 @@ static void tmp421_reset(TMP421State *s) * The measured temperatures are not cleared: they model the physical * input the ADC re-samples after reset, and boards may preset them. */ + memset(s->n_correct, 0, sizeof(s->n_correct)); s->pointer = 0; s->config[0] = 0; s->config[1] = sc->config2_reset; -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 06/22] hw/sensor: tmp421: implement register write masks, one-shot and N-factor @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Mask out reserved and absent-channel bits on writes to the two configuration registers and the conversion rate, accept the one-shot trigger, and back the per-remote-channel N-factor correction registers with real storage. The N-factor state migrates through an optional subsection. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 8bacd7d05e..9e1249afb8 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -22,6 +22,16 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Limitations: + * - Conversions are instantaneous. The conversion-rate register and the + * shutdown bit are stored but do not decide when a measurement appears, + * and a one-shot write is accepted without scheduling anything: a read + * always returns a fresh value. + * - The N-factor correction registers are stored and never applied. The model + * has no ideality factor to correct for. + * - The sensor-fault OPEN bit and the PVLD bit of the temperature low byte are + * never set, so neither an open circuit nor a low supply is reported. */ #include "qemu/osdep.h" @@ -44,6 +54,7 @@ struct TMP421State { /*< public >*/ int16_t temperature[4]; + uint8_t n_correct[3]; /* remote channels only */ uint8_t status; uint8_t config[2]; @@ -85,6 +96,8 @@ OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_ONE_SHOT 0x0F +#define TMP421_N_CORRECT 0x21 + #define TMP421_RESET 0xFC #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF @@ -203,6 +216,11 @@ static void tmp421_read(TMP421State *s) s->buf[s->len++] = tmp421_temp_low(s, s->pointer - TMP421_TEMP_LSB0); return; } + if (s->pointer >= TMP421_N_CORRECT && s->pointer < TMP421_N_CORRECT + 3) { + unsigned idx = s->pointer - TMP421_N_CORRECT; + s->buf[s->len++] = idx + 1 < sc->nchannels ? s->n_correct[idx] : 0; + return; + } switch (s->pointer) { case TMP421_MANUFACTURER_ID_REG: @@ -233,15 +251,29 @@ static void tmp421_reset(TMP421State *s); static void tmp421_write(TMP421State *s) { + TMP421Class *sc = TMP421_GET_CLASS(s); + + if (s->pointer >= TMP421_N_CORRECT && s->pointer < TMP421_N_CORRECT + 3) { + unsigned idx = s->pointer - TMP421_N_CORRECT; + if (idx + 1 < sc->nchannels) { + s->n_correct[idx] = s->buf[0]; + } + return; + } + switch (s->pointer) { - case TMP421_CONVERSION_RATE_REG: - s->rate = s->buf[0]; - break; case TMP421_CONFIG_REG_1: - s->config[0] = s->buf[0]; + s->config[0] = s->buf[0] & + (TMP421_CONFIG_RANGE | TMP421_CONFIG_SHUTDOWN); break; case TMP421_CONFIG_REG_2: - s->config[1] = s->buf[0]; + s->config[1] = s->buf[0] & sc->config2_reset; + break; + case TMP421_CONVERSION_RATE_REG: + s->rate = s->buf[0] & 0x07; + break; + case TMP421_ONE_SHOT: + /* starts a conversion in shutdown; conversions are immediate here */ break; case TMP421_RESET: tmp421_reset(s); @@ -291,6 +323,24 @@ static int tmp421_event(I2CSlave *i2c, enum i2c_event event) return 0; } +static bool tmp421_n_correct_needed(void *opaque) +{ + TMP421State *s = opaque; + + return s->n_correct[0] || s->n_correct[1] || s->n_correct[2]; +} + +static const VMStateDescription vmstate_tmp421_n_correct = { + .name = "TMP421/n-correct", + .version_id = 1, + .minimum_version_id = 1, + .needed = tmp421_n_correct_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINT8_ARRAY(n_correct, TMP421State, 3), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_tmp421 = { .name = "TMP421", .version_id = 0, @@ -305,6 +355,10 @@ static const VMStateDescription vmstate_tmp421 = { VMSTATE_INT16_ARRAY(temperature, TMP421State, 4), VMSTATE_I2C_SLAVE(parent_obj, TMP421State), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * const []) { + &vmstate_tmp421_n_correct, + NULL } }; @@ -316,6 +370,7 @@ static void tmp421_reset(TMP421State *s) * The measured temperatures are not cleared: they model the physical * input the ADC re-samples after reset, and boards may preset them. */ + memset(s->n_correct, 0, sizeof(s->n_correct)); s->pointer = 0; s->config[0] = 0; s->config[1] = sc->config2_reset; -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 07/22] hw/sensor: tmp421: describe the temperature properties 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Attach a description to each temperature property so it shows up in qom-list-properties. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 9e1249afb8..ec3a9a9760 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -393,6 +393,8 @@ static void tmp421_initfn(Object *obj) object_property_add(obj, name, "int", tmp421_get_temperature, tmp421_set_temperature, NULL, NULL); + object_property_set_description(obj, name, + "Temperature, in millidegrees Celsius"); } } -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 07/22] hw/sensor: tmp421: describe the temperature properties @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Attach a description to each temperature property so it shows up in qom-list-properties. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 9e1249afb8..ec3a9a9760 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -393,6 +393,8 @@ static void tmp421_initfn(Object *obj) object_property_add(obj, name, "int", tmp421_get_temperature, tmp421_set_temperature, NULL, NULL); + object_property_set_description(obj, name, + "Temperature, in millidegrees Celsius"); } } -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 08/22] hw/sensor: tmp421: keep the measurement across a range change 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The model stored temperatures in their register form, which carries the extended-range offset. Leaving that range therefore reinterpreted the stored value and shifted the reported temperature by 64 degrees, whether the range bit was cleared by a configuration write or by a reset. The encoding was wrong at both ends too: the extended range is offset binary, so it does not fit a signed register above +64 C, and neither range saturated where the datasheet says it should. Hold the measurement in millidegrees and derive the register from it on each read, which is what the range bit selects: an encoding, not a new measurement. The stream keeps carrying the register form, which is what a released QEMU writes and expects, so it stays loadable both ways; the measurement is converted to and from it on save and load. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 96 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index ec3a9a9760..1e061045cb 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -53,9 +53,13 @@ struct TMP421State { I2CSlave parent_obj; /*< public >*/ - int16_t temperature[4]; + /* Measured temperature, millidegrees Celsius */ + int32_t temp_mc[4]; uint8_t n_correct[3]; /* remote channels only */ + /* migration only: the register form the stream carries */ + int16_t temperature[4]; + uint8_t status; uint8_t config[2]; uint8_t rate; @@ -114,12 +118,51 @@ OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) static const int32_t mins[2] = { -40000, -55000 }; static const int32_t maxs[2] = { 127000, 150000 }; +/* + * Register form of a measurement (datasheet Table 1): whole degrees in the + * high byte, the fraction in the upper nibble of the low byte. The standard + * range is two's complement and saturates at -64 C (C0h) and +127 C (7Fh); + * the extended range is unsigned with a -64 C offset, spanning -64 C (00h) to + * +191 C (FFh). The range only selects an encoding: the measurement itself is + * held apart, so switching range re-reads the same temperature. + */ +#define TMP421_EXT_OFFSET (64 * 256) +#define TMP421_STD_REG_MIN (-64 * 256) /* C0h, -64 C */ +#define TMP421_STD_REG_MAX (127 * 256 + 0xf0) /* 7Fh, +127 C */ +#define TMP421_EXT_REG_MAX (255 * 256 + 0xf0) /* FFh, +191 C offset */ + +static uint16_t tmp421_encode(const TMP421State *s, unsigned channel) +{ + bool ext_range = s->config[0] & TMP421_CONFIG_RANGE; + int raw = s->temp_mc[channel] * 256 / 1000; + + if (ext_range) { + raw = MAX(0, MIN(TMP421_EXT_REG_MAX, raw + TMP421_EXT_OFFSET)); + } else { + raw = MAX(TMP421_STD_REG_MIN, MIN(TMP421_STD_REG_MAX, raw)); + } + + return raw; +} + +/* + * The inverse of tmp421_encode(). Only the standard range is signed: the + * extended one spans the whole byte, so its top bit is a temperature, not a + * sign. Rounding follows the sign so that every register value the encoder + * can produce decodes back to the measurement it came from. + */ +static int32_t tmp421_decode(const TMP421State *s, int16_t reg) +{ + bool ext_range = s->config[0] & TMP421_CONFIG_RANGE; + int32_t raw = ext_range ? (uint16_t)reg - TMP421_EXT_OFFSET : reg; + + return (raw * 1000 + (raw < 0 ? -128 : 128)) / 256; +} + static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { TMP421State *s = TMP421(obj); - bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE); - int offset = ext_range * 64 * 256; int64_t value; int tempid; @@ -133,21 +176,18 @@ static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name, return; } - value = ((s->temperature[tempid] - offset) * 1000 + 128) / 256; + value = s->temp_mc[tempid]; visit_type_int(v, name, &value, errp); } -/* Units are 0.001 centigrades relative to 0 C. s->temperature is 8.8 - * fixed point, so units are 1/256 centigrades. A simple ratio will do. - */ +/* Units are 0.001 centigrades relative to 0 C. */ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { TMP421State *s = TMP421(obj); int64_t temp; bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE); - int offset = ext_range * 64 * 256; int tempid; if (!visit_type_int(v, name, &temp, errp)) { @@ -170,7 +210,7 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, return; } - s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset; + s->temp_mc[tempid] = temp; } static bool tmp421_channel_enabled(TMP421State *s, unsigned channel) @@ -187,16 +227,14 @@ static bool tmp421_channel_enabled(TMP421State *s, unsigned channel) */ static uint8_t tmp421_temp_high(TMP421State *s, unsigned channel) { - uint16_t reg = s->temperature[channel]; - - return tmp421_channel_enabled(s, channel) ? reg >> 8 : 0; + return tmp421_channel_enabled(s, channel) ? + tmp421_encode(s, channel) >> 8 : 0; } static uint8_t tmp421_temp_low(TMP421State *s, unsigned channel) { - uint16_t reg = s->temperature[channel]; - - return tmp421_channel_enabled(s, channel) ? reg & 0xf0 : 0; + return tmp421_channel_enabled(s, channel) ? + tmp421_encode(s, channel) & 0xf0 : 0; } static void tmp421_read(TMP421State *s) @@ -341,10 +379,38 @@ static const VMStateDescription vmstate_tmp421_n_correct = { } }; +/* + * The stream carries the register form of the measurement: that is what a + * QEMU predating the millidegree state writes, and what it expects back. + */ +static int tmp421_pre_save(void *opaque) +{ + TMP421State *s = opaque; + + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { + s->temperature[channel] = tmp421_encode(s, channel); + } + + return 0; +} + +static int tmp421_post_load(void *opaque, int version_id) +{ + TMP421State *s = opaque; + + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { + s->temp_mc[channel] = tmp421_decode(s, s->temperature[channel]); + } + + return 0; +} + static const VMStateDescription vmstate_tmp421 = { .name = "TMP421", .version_id = 0, .minimum_version_id = 0, + .pre_save = tmp421_pre_save, + .post_load = tmp421_post_load, .fields = (const VMStateField[]) { VMSTATE_UINT8(len, TMP421State), VMSTATE_UINT8_ARRAY(buf, TMP421State, 2), -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 08/22] hw/sensor: tmp421: keep the measurement across a range change @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The model stored temperatures in their register form, which carries the extended-range offset. Leaving that range therefore reinterpreted the stored value and shifted the reported temperature by 64 degrees, whether the range bit was cleared by a configuration write or by a reset. The encoding was wrong at both ends too: the extended range is offset binary, so it does not fit a signed register above +64 C, and neither range saturated where the datasheet says it should. Hold the measurement in millidegrees and derive the register from it on each read, which is what the range bit selects: an encoding, not a new measurement. The stream keeps carrying the register form, which is what a released QEMU writes and expects, so it stays loadable both ways; the measurement is converted to and from it on save and load. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 96 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index ec3a9a9760..1e061045cb 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -53,9 +53,13 @@ struct TMP421State { I2CSlave parent_obj; /*< public >*/ - int16_t temperature[4]; + /* Measured temperature, millidegrees Celsius */ + int32_t temp_mc[4]; uint8_t n_correct[3]; /* remote channels only */ + /* migration only: the register form the stream carries */ + int16_t temperature[4]; + uint8_t status; uint8_t config[2]; uint8_t rate; @@ -114,12 +118,51 @@ OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) static const int32_t mins[2] = { -40000, -55000 }; static const int32_t maxs[2] = { 127000, 150000 }; +/* + * Register form of a measurement (datasheet Table 1): whole degrees in the + * high byte, the fraction in the upper nibble of the low byte. The standard + * range is two's complement and saturates at -64 C (C0h) and +127 C (7Fh); + * the extended range is unsigned with a -64 C offset, spanning -64 C (00h) to + * +191 C (FFh). The range only selects an encoding: the measurement itself is + * held apart, so switching range re-reads the same temperature. + */ +#define TMP421_EXT_OFFSET (64 * 256) +#define TMP421_STD_REG_MIN (-64 * 256) /* C0h, -64 C */ +#define TMP421_STD_REG_MAX (127 * 256 + 0xf0) /* 7Fh, +127 C */ +#define TMP421_EXT_REG_MAX (255 * 256 + 0xf0) /* FFh, +191 C offset */ + +static uint16_t tmp421_encode(const TMP421State *s, unsigned channel) +{ + bool ext_range = s->config[0] & TMP421_CONFIG_RANGE; + int raw = s->temp_mc[channel] * 256 / 1000; + + if (ext_range) { + raw = MAX(0, MIN(TMP421_EXT_REG_MAX, raw + TMP421_EXT_OFFSET)); + } else { + raw = MAX(TMP421_STD_REG_MIN, MIN(TMP421_STD_REG_MAX, raw)); + } + + return raw; +} + +/* + * The inverse of tmp421_encode(). Only the standard range is signed: the + * extended one spans the whole byte, so its top bit is a temperature, not a + * sign. Rounding follows the sign so that every register value the encoder + * can produce decodes back to the measurement it came from. + */ +static int32_t tmp421_decode(const TMP421State *s, int16_t reg) +{ + bool ext_range = s->config[0] & TMP421_CONFIG_RANGE; + int32_t raw = ext_range ? (uint16_t)reg - TMP421_EXT_OFFSET : reg; + + return (raw * 1000 + (raw < 0 ? -128 : 128)) / 256; +} + static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { TMP421State *s = TMP421(obj); - bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE); - int offset = ext_range * 64 * 256; int64_t value; int tempid; @@ -133,21 +176,18 @@ static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name, return; } - value = ((s->temperature[tempid] - offset) * 1000 + 128) / 256; + value = s->temp_mc[tempid]; visit_type_int(v, name, &value, errp); } -/* Units are 0.001 centigrades relative to 0 C. s->temperature is 8.8 - * fixed point, so units are 1/256 centigrades. A simple ratio will do. - */ +/* Units are 0.001 centigrades relative to 0 C. */ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { TMP421State *s = TMP421(obj); int64_t temp; bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE); - int offset = ext_range * 64 * 256; int tempid; if (!visit_type_int(v, name, &temp, errp)) { @@ -170,7 +210,7 @@ static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name, return; } - s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset; + s->temp_mc[tempid] = temp; } static bool tmp421_channel_enabled(TMP421State *s, unsigned channel) @@ -187,16 +227,14 @@ static bool tmp421_channel_enabled(TMP421State *s, unsigned channel) */ static uint8_t tmp421_temp_high(TMP421State *s, unsigned channel) { - uint16_t reg = s->temperature[channel]; - - return tmp421_channel_enabled(s, channel) ? reg >> 8 : 0; + return tmp421_channel_enabled(s, channel) ? + tmp421_encode(s, channel) >> 8 : 0; } static uint8_t tmp421_temp_low(TMP421State *s, unsigned channel) { - uint16_t reg = s->temperature[channel]; - - return tmp421_channel_enabled(s, channel) ? reg & 0xf0 : 0; + return tmp421_channel_enabled(s, channel) ? + tmp421_encode(s, channel) & 0xf0 : 0; } static void tmp421_read(TMP421State *s) @@ -341,10 +379,38 @@ static const VMStateDescription vmstate_tmp421_n_correct = { } }; +/* + * The stream carries the register form of the measurement: that is what a + * QEMU predating the millidegree state writes, and what it expects back. + */ +static int tmp421_pre_save(void *opaque) +{ + TMP421State *s = opaque; + + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { + s->temperature[channel] = tmp421_encode(s, channel); + } + + return 0; +} + +static int tmp421_post_load(void *opaque, int version_id) +{ + TMP421State *s = opaque; + + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { + s->temp_mc[channel] = tmp421_decode(s, s->temperature[channel]); + } + + return 0; +} + static const VMStateDescription vmstate_tmp421 = { .name = "TMP421", .version_id = 0, .minimum_version_id = 0, + .pre_save = tmp421_pre_save, + .post_load = tmp421_post_load, .fields = (const VMStateField[]) { VMSTATE_UINT8(len, TMP421State), VMSTATE_UINT8_ARRAY(buf, TMP421State, 2), -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 09/22] hw/sensor: tmp421: migrate the exact measurement 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The register form the stream carries only resolves a sixteenth of a degree, so a temperature set through the property does not survive a round trip unless it happens to fall on that grid. Add a subsection holding the measurement itself, sent only when the register form cannot reproduce it. A stream from a sensor holding an expressible value -- the usual case, boards preset whole degrees -- therefore stays loadable by a QEMU that knows nothing of it. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 1e061045cb..e391bb20e1 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -59,6 +59,7 @@ struct TMP421State { /* migration only: the register form the stream carries */ int16_t temperature[4]; + bool temp_mc_loaded; uint8_t status; uint8_t config[2]; @@ -379,6 +380,56 @@ static const VMStateDescription vmstate_tmp421_n_correct = { } }; +/* + * That form only resolves a sixteenth of a degree, so the measurement itself + * travels in a subsection -- sent only when the register form cannot + * reproduce it, which leaves the usual stream loadable by a QEMU that does + * not know the subsection. + */ +static bool tmp421_temp_mc_needed(void *opaque) +{ + TMP421State *s = opaque; + bool ext_range = s->config[0] & TMP421_CONFIG_RANGE; + int32_t offset = ext_range ? TMP421_EXT_OFFSET : 0; + + /* + * The register form reproduces a measurement when the conversion divides + * exactly and the encoder had nothing to clamp. Asking the decoder + * instead would settle the question with the function whose result the + * subsection exists to protect, and hide any error it has. + */ + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { + int32_t scaled = s->temp_mc[channel] * 256; + + if (scaled % 1000 || + (uint16_t)(scaled / 1000 + offset) != tmp421_encode(s, channel)) { + return true; + } + } + + return false; +} + +static int tmp421_temp_mc_post_load(void *opaque, int version_id) +{ + TMP421State *s = opaque; + + s->temp_mc_loaded = true; + return 0; +} + +static const VMStateDescription vmstate_tmp421_temp_mc = { + .name = "TMP421/temperature-mc", + .version_id = 1, + .minimum_version_id = 1, + .needed = tmp421_temp_mc_needed, + .post_load = tmp421_temp_mc_post_load, + .fields = (const VMStateField[]) { + VMSTATE_INT32_ARRAY(temp_mc, TMP421State, 4), + VMSTATE_END_OF_LIST() + } +}; + /* * The stream carries the register form of the measurement: that is what a * QEMU predating the millidegree state writes, and what it expects back. @@ -398,9 +449,13 @@ static int tmp421_post_load(void *opaque, int version_id) { TMP421State *s = opaque; - for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { - s->temp_mc[channel] = tmp421_decode(s, s->temperature[channel]); + if (!s->temp_mc_loaded) { + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); + channel++) { + s->temp_mc[channel] = tmp421_decode(s, s->temperature[channel]); + } } + s->temp_mc_loaded = false; return 0; } @@ -423,6 +478,7 @@ static const VMStateDescription vmstate_tmp421 = { VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * const []) { + &vmstate_tmp421_temp_mc, &vmstate_tmp421_n_correct, NULL } -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 09/22] hw/sensor: tmp421: migrate the exact measurement @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The register form the stream carries only resolves a sixteenth of a degree, so a temperature set through the property does not survive a round trip unless it happens to fall on that grid. Add a subsection holding the measurement itself, sent only when the register form cannot reproduce it. A stream from a sensor holding an expressible value -- the usual case, boards preset whole degrees -- therefore stays loadable by a QEMU that knows nothing of it. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index 1e061045cb..e391bb20e1 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -59,6 +59,7 @@ struct TMP421State { /* migration only: the register form the stream carries */ int16_t temperature[4]; + bool temp_mc_loaded; uint8_t status; uint8_t config[2]; @@ -379,6 +380,56 @@ static const VMStateDescription vmstate_tmp421_n_correct = { } }; +/* + * That form only resolves a sixteenth of a degree, so the measurement itself + * travels in a subsection -- sent only when the register form cannot + * reproduce it, which leaves the usual stream loadable by a QEMU that does + * not know the subsection. + */ +static bool tmp421_temp_mc_needed(void *opaque) +{ + TMP421State *s = opaque; + bool ext_range = s->config[0] & TMP421_CONFIG_RANGE; + int32_t offset = ext_range ? TMP421_EXT_OFFSET : 0; + + /* + * The register form reproduces a measurement when the conversion divides + * exactly and the encoder had nothing to clamp. Asking the decoder + * instead would settle the question with the function whose result the + * subsection exists to protect, and hide any error it has. + */ + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { + int32_t scaled = s->temp_mc[channel] * 256; + + if (scaled % 1000 || + (uint16_t)(scaled / 1000 + offset) != tmp421_encode(s, channel)) { + return true; + } + } + + return false; +} + +static int tmp421_temp_mc_post_load(void *opaque, int version_id) +{ + TMP421State *s = opaque; + + s->temp_mc_loaded = true; + return 0; +} + +static const VMStateDescription vmstate_tmp421_temp_mc = { + .name = "TMP421/temperature-mc", + .version_id = 1, + .minimum_version_id = 1, + .needed = tmp421_temp_mc_needed, + .post_load = tmp421_temp_mc_post_load, + .fields = (const VMStateField[]) { + VMSTATE_INT32_ARRAY(temp_mc, TMP421State, 4), + VMSTATE_END_OF_LIST() + } +}; + /* * The stream carries the register form of the measurement: that is what a * QEMU predating the millidegree state writes, and what it expects back. @@ -398,9 +449,13 @@ static int tmp421_post_load(void *opaque, int version_id) { TMP421State *s = opaque; - for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); channel++) { - s->temp_mc[channel] = tmp421_decode(s, s->temperature[channel]); + if (!s->temp_mc_loaded) { + for (unsigned channel = 0; channel < ARRAY_SIZE(s->temp_mc); + channel++) { + s->temp_mc[channel] = tmp421_decode(s, s->temperature[channel]); + } } + s->temp_mc_loaded = false; return 0; } @@ -423,6 +478,7 @@ static const VMStateDescription vmstate_tmp421 = { VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * const []) { + &vmstate_tmp421_temp_mc, &vmstate_tmp421_n_correct, NULL } -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 10/22] hw/sensor: tmp421: publish the variant type names 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Move TYPE_TMP421/TYPE_TMP422/TYPE_TMP423 from tmp421.c into a new include/hw/sensor/tmp421.h, so boards instantiating the device share one definition instead of repeating the type strings locally. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 4 +--- include/hw/sensor/tmp421.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index e391bb20e1..5c04960b29 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -41,6 +41,7 @@ #include "qapi/visitor.h" #include "qemu/module.h" #include "qom/object.h" +#include "hw/sensor/tmp421.h" /* Manufacturer / Device ID's */ #define TMP421_MANUFACTURER_ID 0x55 @@ -79,9 +80,6 @@ struct TMP421Class { uint8_t config2_reset; }; -#define TYPE_TMP421 "tmp421" -#define TYPE_TMP422 "tmp422" -#define TYPE_TMP423 "tmp423" OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) diff --git a/include/hw/sensor/tmp421.h b/include/hw/sensor/tmp421.h new file mode 100644 index 0000000000..fbfdd87b7a --- /dev/null +++ b/include/hw/sensor/tmp421.h @@ -0,0 +1,19 @@ +/* + * Texas Instruments TMP421/TMP422/TMP423 temperature sensor + * + * Browse the data sheet: + * + * https://www.ti.com/lit/gpn/tmp421 + * + * Copyright (c) 2016 IBM Corporation. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_SENSOR_TMP421_H +#define HW_SENSOR_TMP421_H + +#define TYPE_TMP421 "tmp421" +#define TYPE_TMP422 "tmp422" +#define TYPE_TMP423 "tmp423" + +#endif -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 10/22] hw/sensor: tmp421: publish the variant type names @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Move TYPE_TMP421/TYPE_TMP422/TYPE_TMP423 from tmp421.c into a new include/hw/sensor/tmp421.h, so boards instantiating the device share one definition instead of repeating the type strings locally. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp421.c | 4 +--- include/hw/sensor/tmp421.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c index e391bb20e1..5c04960b29 100644 --- a/hw/sensor/tmp421.c +++ b/hw/sensor/tmp421.c @@ -41,6 +41,7 @@ #include "qapi/visitor.h" #include "qemu/module.h" #include "qom/object.h" +#include "hw/sensor/tmp421.h" /* Manufacturer / Device ID's */ #define TMP421_MANUFACTURER_ID 0x55 @@ -79,9 +80,6 @@ struct TMP421Class { uint8_t config2_reset; }; -#define TYPE_TMP421 "tmp421" -#define TYPE_TMP422 "tmp422" -#define TYPE_TMP423 "tmp423" OBJECT_DECLARE_TYPE(TMP421State, TMP421Class, TMP421) diff --git a/include/hw/sensor/tmp421.h b/include/hw/sensor/tmp421.h new file mode 100644 index 0000000000..fbfdd87b7a --- /dev/null +++ b/include/hw/sensor/tmp421.h @@ -0,0 +1,19 @@ +/* + * Texas Instruments TMP421/TMP422/TMP423 temperature sensor + * + * Browse the data sheet: + * + * https://www.ti.com/lit/gpn/tmp421 + * + * Copyright (c) 2016 IBM Corporation. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef HW_SENSOR_TMP421_H +#define HW_SENSOR_TMP421_H + +#define TYPE_TMP421 "tmp421" +#define TYPE_TMP422 "tmp422" +#define TYPE_TMP423 "tmp423" + +#endif -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 11/22] hw/arm/aspeed: use the TMP421 type-name macros 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Include the new tmp421.h and refer to the sensor variants through TYPE_TMP421/TYPE_TMP422/TYPE_TMP423 instead of open-coded string literals and per-board local defines. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/arm/aspeed_ast2400_palmetto.c | 3 ++- hw/arm/aspeed_ast2400_supermicrox11.c | 3 ++- hw/arm/aspeed_ast2500_supermicro-x11spi.c | 3 ++- hw/arm/aspeed_ast2500_tiogapass.c | 10 +++++++--- hw/arm/aspeed_ast2500_witherspoon.c | 7 +++++-- hw/arm/aspeed_ast2500_yosemitev2.c | 10 +++++++--- hw/arm/aspeed_ast2600_bletchley.c | 3 +-- hw/arm/aspeed_ast2600_catalina.c | 3 +-- hw/arm/aspeed_ast2600_fby35.c | 2 +- hw/arm/aspeed_ast2600_fuji.c | 3 +-- hw/arm/aspeed_ast2600_rainier.c | 13 +++++++++---- 11 files changed, 38 insertions(+), 22 deletions(-) diff --git a/hw/arm/aspeed_ast2400_palmetto.c b/hw/arm/aspeed_ast2400_palmetto.c index 185185f0bb..7b165394c2 100644 --- a/hw/arm/aspeed_ast2400_palmetto.c +++ b/hw/arm/aspeed_ast2400_palmetto.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp421.h" /* Palmetto hardware value: 0x120CE416 */ #define PALMETTO_BMC_HW_STRAP1 ( \ @@ -45,7 +46,7 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc) /* add a TMP423 temperature sensor */ dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), - "tmp423", 0x4c)); + TYPE_TMP423, 0x4c)); object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); diff --git a/hw/arm/aspeed_ast2400_supermicrox11.c b/hw/arm/aspeed_ast2400_supermicrox11.c index 051e072c5a..fd2fda9290 100644 --- a/hw/arm/aspeed_ast2400_supermicrox11.c +++ b/hw/arm/aspeed_ast2400_supermicrox11.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp421.h" /* TODO: Find the actual hardware value */ #define SUPERMICROX11_BMC_HW_STRAP1 ( \ @@ -45,7 +46,7 @@ static void supermicrox11_bmc_i2c_init(AspeedMachineState *bmc) /* add a TMP423 temperature sensor */ dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), - "tmp423", 0x4c)); + TYPE_TMP423, 0x4c)); object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); diff --git a/hw/arm/aspeed_ast2500_supermicro-x11spi.c b/hw/arm/aspeed_ast2500_supermicro-x11spi.c index dc0248422d..1ea61348f6 100644 --- a/hw/arm/aspeed_ast2500_supermicro-x11spi.c +++ b/hw/arm/aspeed_ast2500_supermicro-x11spi.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp421.h" /* TODO: Find the actual hardware value */ #define SUPERMICRO_X11SPI_BMC_HW_STRAP1 ( \ @@ -41,7 +42,7 @@ static void supermicro_x11spi_bmc_i2c_init(AspeedMachineState *bmc) /* add a TMP423 temperature sensor */ dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), - "tmp423", 0x4c)); + TYPE_TMP423, 0x4c)); object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); diff --git a/hw/arm/aspeed_ast2500_tiogapass.c b/hw/arm/aspeed_ast2500_tiogapass.c index 6cb567526c..5433198abd 100644 --- a/hw/arm/aspeed_ast2500_tiogapass.c +++ b/hw/arm/aspeed_ast2500_tiogapass.c @@ -11,6 +11,7 @@ #include "hw/arm/aspeed.h" #include "hw/arm/aspeed_soc.h" #include "hw/nvram/eeprom_at24c.h" +#include "hw/sensor/tmp421.h" /* value: 0xF100C2E6 */ #define TIOGAPASS_BMC_HW_STRAP1 (( \ @@ -54,9 +55,12 @@ static void tiogapass_bmc_i2c_init(AspeedMachineState *bmc) at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 6), 0x54, 128 * KiB, tiogapass_bmc_fruid, tiogapass_bmc_fruid_len); /* TMP421 */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "tmp421", 0x1f); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp421", 0x4f); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp421", 0x4e); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), + TYPE_TMP421, 0x1f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), + TYPE_TMP421, 0x4f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), + TYPE_TMP421, 0x4e); } static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, diff --git a/hw/arm/aspeed_ast2500_witherspoon.c b/hw/arm/aspeed_ast2500_witherspoon.c index c69065846c..385deb2154 100644 --- a/hw/arm/aspeed_ast2500_witherspoon.c +++ b/hw/arm/aspeed_ast2500_witherspoon.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/misc/led.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/gpio/pca9552.h" #include "hw/rtc/ds1338.h" @@ -60,8 +61,10 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) } i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "dps310", 0x76); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "max31785", 0x52); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), + TYPE_TMP423, 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), + TYPE_TMP423, 0x4c); /* The Witherspoon expects a TMP275 but a TMP105 is compatible */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), TYPE_TMP105, diff --git a/hw/arm/aspeed_ast2500_yosemitev2.c b/hw/arm/aspeed_ast2500_yosemitev2.c index 3ba1ed5f6f..3dd0d37175 100644 --- a/hw/arm/aspeed_ast2500_yosemitev2.c +++ b/hw/arm/aspeed_ast2500_yosemitev2.c @@ -11,6 +11,7 @@ #include "hw/arm/aspeed.h" #include "hw/arm/aspeed_soc.h" #include "hw/nvram/eeprom_at24c.h" +#include "hw/sensor/tmp421.h" /* value: 0xF100C2E6 */ #define YOSEMITEV2_BMC_HW_STRAP1 (( \ @@ -54,9 +55,12 @@ static void yosemitev2_bmc_i2c_init(AspeedMachineState *bmc) at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 128 * KiB, yosemitev2_bmc_fruid, yosemitev2_bmc_fruid_len); /* TMP421 */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "tmp421", 0x1f); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp421", 0x4e); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp421", 0x4f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), + TYPE_TMP421, 0x1f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP421, 0x4e); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP421, 0x4f); } diff --git a/hw/arm/aspeed_ast2600_bletchley.c b/hw/arm/aspeed_ast2600_bletchley.c index 0e746055a2..536e910229 100644 --- a/hw/arm/aspeed_ast2600_bletchley.c +++ b/hw/arm/aspeed_ast2600_bletchley.c @@ -13,8 +13,7 @@ #include "hw/gpio/pca9552.h" #include "hw/nvram/eeprom_at24c.h" #include "hw/rtc/ds1338.h" - -#define TYPE_TMP421 "tmp421" +#include "hw/sensor/tmp421.h" /* Bletchley hardware value */ #define BLETCHLEY_BMC_HW_STRAP1 0x00002000 #define BLETCHLEY_BMC_HW_STRAP2 0x00000801 diff --git a/hw/arm/aspeed_ast2600_catalina.c b/hw/arm/aspeed_ast2600_catalina.c index b15d932086..13dca7a846 100644 --- a/hw/arm/aspeed_ast2600_catalina.c +++ b/hw/arm/aspeed_ast2600_catalina.c @@ -16,14 +16,13 @@ #include "hw/nvram/eeprom_at24c.h" #include "hw/rtc/ds1338.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" /* Catalina hardware value */ #define CATALINA_BMC_HW_STRAP1 0x00002002 #define CATALINA_BMC_HW_STRAP2 0x00000800 #define CATALINA_BMC_RAM_SIZE (2 * GiB) -#define TYPE_TMP421 "tmp421" - /* * "BMC Storage Module" FRU data. Generated with frugen. * diff --git a/hw/arm/aspeed_ast2600_fby35.c b/hw/arm/aspeed_ast2600_fby35.c index 28c9c143d8..25f39d5135 100644 --- a/hw/arm/aspeed_ast2600_fby35.c +++ b/hw/arm/aspeed_ast2600_fby35.c @@ -12,10 +12,10 @@ #include "hw/arm/aspeed_soc.h" #include "hw/nvram/eeprom_at24c.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" #include "system/reset.h" #define TYPE_LM75 TYPE_TMP105 -#define TYPE_TMP421 "tmp421" #define FBY35_BMC_RAM_SIZE (2 * GiB) static const uint8_t fby35_nic_fruid[] = { diff --git a/hw/arm/aspeed_ast2600_fuji.c b/hw/arm/aspeed_ast2600_fuji.c index 08d809b2fd..526494ecfe 100644 --- a/hw/arm/aspeed_ast2600_fuji.c +++ b/hw/arm/aspeed_ast2600_fuji.c @@ -12,10 +12,9 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/i2c_mux_pca954x.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" #include "hw/nvram/eeprom_at24c.h" -#define TYPE_TMP422 "tmp422" - /* Fuji hardware value */ #define FUJI_BMC_HW_STRAP1 0x00000000 #define FUJI_BMC_HW_STRAP2 0x00000000 diff --git a/hw/arm/aspeed_ast2600_rainier.c b/hw/arm/aspeed_ast2600_rainier.c index 43a8f01a9e..bdbc78aee7 100644 --- a/hw/arm/aspeed_ast2600_rainier.c +++ b/hw/arm/aspeed_ast2600_rainier.c @@ -13,6 +13,7 @@ #include "hw/nvram/eeprom_at24c.h" #include "hw/i2c/i2c_mux_pca954x.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" /* Rainier hardware value: (QEMU prototype) */ #define RAINIER_BMC_HW_STRAP1 (0x00422016 | SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC) @@ -137,12 +138,16 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) /* Bus 8: ucd90320@b */ /* Bus 8: ucd90320@c */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4d); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP423, 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP423, 0x4d); at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 9), 0x50, 128 * KiB); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4d); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), + TYPE_TMP423, 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), + TYPE_TMP423, 0x4d); at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 10), 0x50, 128 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105, -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 11/22] hw/arm/aspeed: use the TMP421 type-name macros @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Include the new tmp421.h and refer to the sensor variants through TYPE_TMP421/TYPE_TMP422/TYPE_TMP423 instead of open-coded string literals and per-board local defines. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/arm/aspeed_ast2400_palmetto.c | 3 ++- hw/arm/aspeed_ast2400_supermicrox11.c | 3 ++- hw/arm/aspeed_ast2500_supermicro-x11spi.c | 3 ++- hw/arm/aspeed_ast2500_tiogapass.c | 10 +++++++--- hw/arm/aspeed_ast2500_witherspoon.c | 7 +++++-- hw/arm/aspeed_ast2500_yosemitev2.c | 10 +++++++--- hw/arm/aspeed_ast2600_bletchley.c | 3 +-- hw/arm/aspeed_ast2600_catalina.c | 3 +-- hw/arm/aspeed_ast2600_fby35.c | 2 +- hw/arm/aspeed_ast2600_fuji.c | 3 +-- hw/arm/aspeed_ast2600_rainier.c | 13 +++++++++---- 11 files changed, 38 insertions(+), 22 deletions(-) diff --git a/hw/arm/aspeed_ast2400_palmetto.c b/hw/arm/aspeed_ast2400_palmetto.c index 185185f0bb..7b165394c2 100644 --- a/hw/arm/aspeed_ast2400_palmetto.c +++ b/hw/arm/aspeed_ast2400_palmetto.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp421.h" /* Palmetto hardware value: 0x120CE416 */ #define PALMETTO_BMC_HW_STRAP1 ( \ @@ -45,7 +46,7 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc) /* add a TMP423 temperature sensor */ dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), - "tmp423", 0x4c)); + TYPE_TMP423, 0x4c)); object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); diff --git a/hw/arm/aspeed_ast2400_supermicrox11.c b/hw/arm/aspeed_ast2400_supermicrox11.c index 051e072c5a..fd2fda9290 100644 --- a/hw/arm/aspeed_ast2400_supermicrox11.c +++ b/hw/arm/aspeed_ast2400_supermicrox11.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp421.h" /* TODO: Find the actual hardware value */ #define SUPERMICROX11_BMC_HW_STRAP1 ( \ @@ -45,7 +46,7 @@ static void supermicrox11_bmc_i2c_init(AspeedMachineState *bmc) /* add a TMP423 temperature sensor */ dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), - "tmp423", 0x4c)); + TYPE_TMP423, 0x4c)); object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); diff --git a/hw/arm/aspeed_ast2500_supermicro-x11spi.c b/hw/arm/aspeed_ast2500_supermicro-x11spi.c index dc0248422d..1ea61348f6 100644 --- a/hw/arm/aspeed_ast2500_supermicro-x11spi.c +++ b/hw/arm/aspeed_ast2500_supermicro-x11spi.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp421.h" /* TODO: Find the actual hardware value */ #define SUPERMICRO_X11SPI_BMC_HW_STRAP1 ( \ @@ -41,7 +42,7 @@ static void supermicro_x11spi_bmc_i2c_init(AspeedMachineState *bmc) /* add a TMP423 temperature sensor */ dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), - "tmp423", 0x4c)); + TYPE_TMP423, 0x4c)); object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); diff --git a/hw/arm/aspeed_ast2500_tiogapass.c b/hw/arm/aspeed_ast2500_tiogapass.c index 6cb567526c..5433198abd 100644 --- a/hw/arm/aspeed_ast2500_tiogapass.c +++ b/hw/arm/aspeed_ast2500_tiogapass.c @@ -11,6 +11,7 @@ #include "hw/arm/aspeed.h" #include "hw/arm/aspeed_soc.h" #include "hw/nvram/eeprom_at24c.h" +#include "hw/sensor/tmp421.h" /* value: 0xF100C2E6 */ #define TIOGAPASS_BMC_HW_STRAP1 (( \ @@ -54,9 +55,12 @@ static void tiogapass_bmc_i2c_init(AspeedMachineState *bmc) at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 6), 0x54, 128 * KiB, tiogapass_bmc_fruid, tiogapass_bmc_fruid_len); /* TMP421 */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "tmp421", 0x1f); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp421", 0x4f); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp421", 0x4e); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), + TYPE_TMP421, 0x1f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), + TYPE_TMP421, 0x4f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), + TYPE_TMP421, 0x4e); } static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, diff --git a/hw/arm/aspeed_ast2500_witherspoon.c b/hw/arm/aspeed_ast2500_witherspoon.c index c69065846c..385deb2154 100644 --- a/hw/arm/aspeed_ast2500_witherspoon.c +++ b/hw/arm/aspeed_ast2500_witherspoon.c @@ -12,6 +12,7 @@ #include "hw/arm/aspeed_soc.h" #include "hw/misc/led.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" #include "hw/i2c/smbus_eeprom.h" #include "hw/gpio/pca9552.h" #include "hw/rtc/ds1338.h" @@ -60,8 +61,10 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) } i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "dps310", 0x76); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "max31785", 0x52); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), + TYPE_TMP423, 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), + TYPE_TMP423, 0x4c); /* The Witherspoon expects a TMP275 but a TMP105 is compatible */ i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), TYPE_TMP105, diff --git a/hw/arm/aspeed_ast2500_yosemitev2.c b/hw/arm/aspeed_ast2500_yosemitev2.c index 3ba1ed5f6f..3dd0d37175 100644 --- a/hw/arm/aspeed_ast2500_yosemitev2.c +++ b/hw/arm/aspeed_ast2500_yosemitev2.c @@ -11,6 +11,7 @@ #include "hw/arm/aspeed.h" #include "hw/arm/aspeed_soc.h" #include "hw/nvram/eeprom_at24c.h" +#include "hw/sensor/tmp421.h" /* value: 0xF100C2E6 */ #define YOSEMITEV2_BMC_HW_STRAP1 (( \ @@ -54,9 +55,12 @@ static void yosemitev2_bmc_i2c_init(AspeedMachineState *bmc) at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 128 * KiB, yosemitev2_bmc_fruid, yosemitev2_bmc_fruid_len); /* TMP421 */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "tmp421", 0x1f); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp421", 0x4e); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp421", 0x4f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), + TYPE_TMP421, 0x1f); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP421, 0x4e); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP421, 0x4f); } diff --git a/hw/arm/aspeed_ast2600_bletchley.c b/hw/arm/aspeed_ast2600_bletchley.c index 0e746055a2..536e910229 100644 --- a/hw/arm/aspeed_ast2600_bletchley.c +++ b/hw/arm/aspeed_ast2600_bletchley.c @@ -13,8 +13,7 @@ #include "hw/gpio/pca9552.h" #include "hw/nvram/eeprom_at24c.h" #include "hw/rtc/ds1338.h" - -#define TYPE_TMP421 "tmp421" +#include "hw/sensor/tmp421.h" /* Bletchley hardware value */ #define BLETCHLEY_BMC_HW_STRAP1 0x00002000 #define BLETCHLEY_BMC_HW_STRAP2 0x00000801 diff --git a/hw/arm/aspeed_ast2600_catalina.c b/hw/arm/aspeed_ast2600_catalina.c index b15d932086..13dca7a846 100644 --- a/hw/arm/aspeed_ast2600_catalina.c +++ b/hw/arm/aspeed_ast2600_catalina.c @@ -16,14 +16,13 @@ #include "hw/nvram/eeprom_at24c.h" #include "hw/rtc/ds1338.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" /* Catalina hardware value */ #define CATALINA_BMC_HW_STRAP1 0x00002002 #define CATALINA_BMC_HW_STRAP2 0x00000800 #define CATALINA_BMC_RAM_SIZE (2 * GiB) -#define TYPE_TMP421 "tmp421" - /* * "BMC Storage Module" FRU data. Generated with frugen. * diff --git a/hw/arm/aspeed_ast2600_fby35.c b/hw/arm/aspeed_ast2600_fby35.c index 28c9c143d8..25f39d5135 100644 --- a/hw/arm/aspeed_ast2600_fby35.c +++ b/hw/arm/aspeed_ast2600_fby35.c @@ -12,10 +12,10 @@ #include "hw/arm/aspeed_soc.h" #include "hw/nvram/eeprom_at24c.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" #include "system/reset.h" #define TYPE_LM75 TYPE_TMP105 -#define TYPE_TMP421 "tmp421" #define FBY35_BMC_RAM_SIZE (2 * GiB) static const uint8_t fby35_nic_fruid[] = { diff --git a/hw/arm/aspeed_ast2600_fuji.c b/hw/arm/aspeed_ast2600_fuji.c index 08d809b2fd..526494ecfe 100644 --- a/hw/arm/aspeed_ast2600_fuji.c +++ b/hw/arm/aspeed_ast2600_fuji.c @@ -12,10 +12,9 @@ #include "hw/arm/aspeed_soc.h" #include "hw/i2c/i2c_mux_pca954x.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" #include "hw/nvram/eeprom_at24c.h" -#define TYPE_TMP422 "tmp422" - /* Fuji hardware value */ #define FUJI_BMC_HW_STRAP1 0x00000000 #define FUJI_BMC_HW_STRAP2 0x00000000 diff --git a/hw/arm/aspeed_ast2600_rainier.c b/hw/arm/aspeed_ast2600_rainier.c index 43a8f01a9e..bdbc78aee7 100644 --- a/hw/arm/aspeed_ast2600_rainier.c +++ b/hw/arm/aspeed_ast2600_rainier.c @@ -13,6 +13,7 @@ #include "hw/nvram/eeprom_at24c.h" #include "hw/i2c/i2c_mux_pca954x.h" #include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" /* Rainier hardware value: (QEMU prototype) */ #define RAINIER_BMC_HW_STRAP1 (0x00422016 | SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC) @@ -137,12 +138,16 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) /* Bus 8: ucd90320@b */ /* Bus 8: ucd90320@c */ - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4d); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP423, 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), + TYPE_TMP423, 0x4d); at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 9), 0x50, 128 * KiB); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c); - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4d); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), + TYPE_TMP423, 0x4c); + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), + TYPE_TMP423, 0x4d); at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 10), 0x50, 128 * KiB); i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105, -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* Re: [PATCH 11/22] hw/arm/aspeed: use the TMP421 type-name macros 2026-10-15 11:57 ` Emmanuel Blot via (?) @ 2026-10-16 5:19 ` 林建明 -1 siblings, 0 replies; 49+ messages in thread From: 林建明 @ 2026-10-16 5:19 UTC (permalink / raw) To: Emmanuel Blot Cc: qemu-devel, Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier Emmanuel Blot via qemu development <qemu-devel@nongnu.org> 於 2026年10月15日週四 下午11:12寫道: > > Include the new tmp421.h and refer to the sensor variants through > TYPE_TMP421/TYPE_TMP422/TYPE_TMP423 instead of open-coded string > literals and per-board local defines. > > Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> > --- > hw/arm/aspeed_ast2400_palmetto.c | 3 ++- > hw/arm/aspeed_ast2400_supermicrox11.c | 3 ++- > hw/arm/aspeed_ast2500_supermicro-x11spi.c | 3 ++- > hw/arm/aspeed_ast2500_tiogapass.c | 10 +++++++--- > hw/arm/aspeed_ast2500_witherspoon.c | 7 +++++-- > hw/arm/aspeed_ast2500_yosemitev2.c | 10 +++++++--- > hw/arm/aspeed_ast2600_bletchley.c | 3 +-- > hw/arm/aspeed_ast2600_catalina.c | 3 +-- > hw/arm/aspeed_ast2600_fby35.c | 2 +- > hw/arm/aspeed_ast2600_fuji.c | 3 +-- > hw/arm/aspeed_ast2600_rainier.c | 13 +++++++++---- > 11 files changed, 38 insertions(+), 22 deletions(-) > > diff --git a/hw/arm/aspeed_ast2400_palmetto.c b/hw/arm/aspeed_ast2400_palmetto.c > index 185185f0bb..7b165394c2 100644 > --- a/hw/arm/aspeed_ast2400_palmetto.c > +++ b/hw/arm/aspeed_ast2400_palmetto.c > @@ -12,6 +12,7 @@ > #include "hw/arm/aspeed_soc.h" > #include "hw/i2c/smbus_eeprom.h" > #include "hw/rtc/ds1338.h" > +#include "hw/sensor/tmp421.h" > > /* Palmetto hardware value: 0x120CE416 */ > #define PALMETTO_BMC_HW_STRAP1 ( \ > @@ -45,7 +46,7 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc) > > /* add a TMP423 temperature sensor */ > dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), > - "tmp423", 0x4c)); > + TYPE_TMP423, 0x4c)); > object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); > object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); > object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); > diff --git a/hw/arm/aspeed_ast2400_supermicrox11.c b/hw/arm/aspeed_ast2400_supermicrox11.c > index 051e072c5a..fd2fda9290 100644 > --- a/hw/arm/aspeed_ast2400_supermicrox11.c > +++ b/hw/arm/aspeed_ast2400_supermicrox11.c > @@ -12,6 +12,7 @@ > #include "hw/arm/aspeed_soc.h" > #include "hw/i2c/smbus_eeprom.h" > #include "hw/rtc/ds1338.h" > +#include "hw/sensor/tmp421.h" > > /* TODO: Find the actual hardware value */ > #define SUPERMICROX11_BMC_HW_STRAP1 ( \ > @@ -45,7 +46,7 @@ static void supermicrox11_bmc_i2c_init(AspeedMachineState *bmc) > > /* add a TMP423 temperature sensor */ > dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), > - "tmp423", 0x4c)); > + TYPE_TMP423, 0x4c)); > object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); > object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); > object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); > diff --git a/hw/arm/aspeed_ast2500_supermicro-x11spi.c b/hw/arm/aspeed_ast2500_supermicro-x11spi.c > index dc0248422d..1ea61348f6 100644 > --- a/hw/arm/aspeed_ast2500_supermicro-x11spi.c > +++ b/hw/arm/aspeed_ast2500_supermicro-x11spi.c > @@ -12,6 +12,7 @@ > #include "hw/arm/aspeed_soc.h" > #include "hw/i2c/smbus_eeprom.h" > #include "hw/rtc/ds1338.h" > +#include "hw/sensor/tmp421.h" > > /* TODO: Find the actual hardware value */ > #define SUPERMICRO_X11SPI_BMC_HW_STRAP1 ( \ > @@ -41,7 +42,7 @@ static void supermicro_x11spi_bmc_i2c_init(AspeedMachineState *bmc) > > /* add a TMP423 temperature sensor */ > dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2), > - "tmp423", 0x4c)); > + TYPE_TMP423, 0x4c)); > object_property_set_int(OBJECT(dev), "temperature0", 31000, &error_abort); > object_property_set_int(OBJECT(dev), "temperature1", 28000, &error_abort); > object_property_set_int(OBJECT(dev), "temperature2", 20000, &error_abort); > diff --git a/hw/arm/aspeed_ast2500_tiogapass.c b/hw/arm/aspeed_ast2500_tiogapass.c > index 6cb567526c..5433198abd 100644 > --- a/hw/arm/aspeed_ast2500_tiogapass.c > +++ b/hw/arm/aspeed_ast2500_tiogapass.c > @@ -11,6 +11,7 @@ > #include "hw/arm/aspeed.h" > #include "hw/arm/aspeed_soc.h" > #include "hw/nvram/eeprom_at24c.h" > +#include "hw/sensor/tmp421.h" > > /* value: 0xF100C2E6 */ > #define TIOGAPASS_BMC_HW_STRAP1 (( \ > @@ -54,9 +55,12 @@ static void tiogapass_bmc_i2c_init(AspeedMachineState *bmc) > at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 6), 0x54, 128 * KiB, > tiogapass_bmc_fruid, tiogapass_bmc_fruid_len); > /* TMP421 */ > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "tmp421", 0x1f); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp421", 0x4f); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), "tmp421", 0x4e); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), > + TYPE_TMP421, 0x1f); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), > + TYPE_TMP421, 0x4f); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 6), > + TYPE_TMP421, 0x4e); > } > > static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, > diff --git a/hw/arm/aspeed_ast2500_witherspoon.c b/hw/arm/aspeed_ast2500_witherspoon.c > index c69065846c..385deb2154 100644 > --- a/hw/arm/aspeed_ast2500_witherspoon.c > +++ b/hw/arm/aspeed_ast2500_witherspoon.c > @@ -12,6 +12,7 @@ > #include "hw/arm/aspeed_soc.h" > #include "hw/misc/led.h" > #include "hw/sensor/tmp105.h" > +#include "hw/sensor/tmp421.h" > #include "hw/i2c/smbus_eeprom.h" > #include "hw/gpio/pca9552.h" > #include "hw/rtc/ds1338.h" > @@ -60,8 +61,10 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc) > } > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "dps310", 0x76); > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "max31785", 0x52); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 4), > + TYPE_TMP423, 0x4c); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 5), > + TYPE_TMP423, 0x4c); > > /* The Witherspoon expects a TMP275 but a TMP105 is compatible */ > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), TYPE_TMP105, > diff --git a/hw/arm/aspeed_ast2500_yosemitev2.c b/hw/arm/aspeed_ast2500_yosemitev2.c > index 3ba1ed5f6f..3dd0d37175 100644 > --- a/hw/arm/aspeed_ast2500_yosemitev2.c > +++ b/hw/arm/aspeed_ast2500_yosemitev2.c > @@ -11,6 +11,7 @@ > #include "hw/arm/aspeed.h" > #include "hw/arm/aspeed_soc.h" > #include "hw/nvram/eeprom_at24c.h" > +#include "hw/sensor/tmp421.h" > > /* value: 0xF100C2E6 */ > #define YOSEMITEV2_BMC_HW_STRAP1 (( \ > @@ -54,9 +55,12 @@ static void yosemitev2_bmc_i2c_init(AspeedMachineState *bmc) > at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 128 * KiB, > yosemitev2_bmc_fruid, yosemitev2_bmc_fruid_len); > /* TMP421 */ > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "tmp421", 0x1f); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp421", 0x4e); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp421", 0x4f); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), > + TYPE_TMP421, 0x1f); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), > + TYPE_TMP421, 0x4e); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), > + TYPE_TMP421, 0x4f); > > } > > diff --git a/hw/arm/aspeed_ast2600_bletchley.c b/hw/arm/aspeed_ast2600_bletchley.c > index 0e746055a2..536e910229 100644 > --- a/hw/arm/aspeed_ast2600_bletchley.c > +++ b/hw/arm/aspeed_ast2600_bletchley.c > @@ -13,8 +13,7 @@ > #include "hw/gpio/pca9552.h" > #include "hw/nvram/eeprom_at24c.h" > #include "hw/rtc/ds1338.h" > - > -#define TYPE_TMP421 "tmp421" > +#include "hw/sensor/tmp421.h" > /* Bletchley hardware value */ > #define BLETCHLEY_BMC_HW_STRAP1 0x00002000 > #define BLETCHLEY_BMC_HW_STRAP2 0x00000801 > diff --git a/hw/arm/aspeed_ast2600_catalina.c b/hw/arm/aspeed_ast2600_catalina.c > index b15d932086..13dca7a846 100644 > --- a/hw/arm/aspeed_ast2600_catalina.c > +++ b/hw/arm/aspeed_ast2600_catalina.c > @@ -16,14 +16,13 @@ > #include "hw/nvram/eeprom_at24c.h" > #include "hw/rtc/ds1338.h" > #include "hw/sensor/tmp105.h" > +#include "hw/sensor/tmp421.h" > > /* Catalina hardware value */ > #define CATALINA_BMC_HW_STRAP1 0x00002002 > #define CATALINA_BMC_HW_STRAP2 0x00000800 > #define CATALINA_BMC_RAM_SIZE (2 * GiB) > > -#define TYPE_TMP421 "tmp421" > - > /* > * "BMC Storage Module" FRU data. Generated with frugen. > * > diff --git a/hw/arm/aspeed_ast2600_fby35.c b/hw/arm/aspeed_ast2600_fby35.c > index 28c9c143d8..25f39d5135 100644 > --- a/hw/arm/aspeed_ast2600_fby35.c > +++ b/hw/arm/aspeed_ast2600_fby35.c > @@ -12,10 +12,10 @@ > #include "hw/arm/aspeed_soc.h" > #include "hw/nvram/eeprom_at24c.h" > #include "hw/sensor/tmp105.h" > +#include "hw/sensor/tmp421.h" > #include "system/reset.h" > > #define TYPE_LM75 TYPE_TMP105 > -#define TYPE_TMP421 "tmp421" > #define FBY35_BMC_RAM_SIZE (2 * GiB) > > static const uint8_t fby35_nic_fruid[] = { > diff --git a/hw/arm/aspeed_ast2600_fuji.c b/hw/arm/aspeed_ast2600_fuji.c > index 08d809b2fd..526494ecfe 100644 > --- a/hw/arm/aspeed_ast2600_fuji.c > +++ b/hw/arm/aspeed_ast2600_fuji.c > @@ -12,10 +12,9 @@ > #include "hw/arm/aspeed_soc.h" > #include "hw/i2c/i2c_mux_pca954x.h" > #include "hw/sensor/tmp105.h" > +#include "hw/sensor/tmp421.h" > #include "hw/nvram/eeprom_at24c.h" > > -#define TYPE_TMP422 "tmp422" > - > /* Fuji hardware value */ > #define FUJI_BMC_HW_STRAP1 0x00000000 > #define FUJI_BMC_HW_STRAP2 0x00000000 > diff --git a/hw/arm/aspeed_ast2600_rainier.c b/hw/arm/aspeed_ast2600_rainier.c > index 43a8f01a9e..bdbc78aee7 100644 > --- a/hw/arm/aspeed_ast2600_rainier.c > +++ b/hw/arm/aspeed_ast2600_rainier.c > @@ -13,6 +13,7 @@ > #include "hw/nvram/eeprom_at24c.h" > #include "hw/i2c/i2c_mux_pca954x.h" > #include "hw/sensor/tmp105.h" > +#include "hw/sensor/tmp421.h" > > /* Rainier hardware value: (QEMU prototype) */ > #define RAINIER_BMC_HW_STRAP1 (0x00422016 | SCU_AST2600_HW_STRAP_BOOT_SRC_EMMC) > @@ -137,12 +138,16 @@ static void rainier_bmc_i2c_init(AspeedMachineState *bmc) > /* Bus 8: ucd90320@b */ > /* Bus 8: ucd90320@c */ > > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4d); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), > + TYPE_TMP423, 0x4c); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9), > + TYPE_TMP423, 0x4d); > at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 9), 0x50, 128 * KiB); > > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c); > - i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4d); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), > + TYPE_TMP423, 0x4c); > + i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 10), > + TYPE_TMP423, 0x4d); > at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 10), 0x50, 128 * KiB); > > i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), TYPE_TMP105, > > -- > 2.53.0-Meta > > Reviewed-by: Jamin Lin <jaminlin1207@gmail.com> ^ permalink raw reply [flat|nested] 49+ messages in thread
* [PATCH 12/22] tests/qtest: tmp421: cover device IDs and reset defaults 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Add a qgraph test that instantiates each variant and checks the manufacturer and device identification bytes and the reset values of the configuration and conversion-rate registers. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/meson.build | 1 + tests/qtest/tmp421-test.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 7005509d4d..5042ae52b2 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -349,6 +349,7 @@ qos_test_ss.add( 'sdhci-test.c', 'spapr-phb-test.c', 'tmp105-test.c', + 'tmp421-test.c', 'emc141x-test.c', 'usb-hcd-ohci-test.c', 'virtio-test.c', diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c new file mode 100644 index 0000000000..2307e5f603 --- /dev/null +++ b/tests/qtest/tmp421-test.c @@ -0,0 +1,84 @@ +/* + * QTest testcase for the TMP421/TMP422/TMP423 temperature sensor + * + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "libqtest-single.h" +#include "libqos/qgraph.h" +#include "libqos/i2c.h" +#include "qobject/qdict.h" + +/* + * TMP421 register map, per the datasheet. Kept here rather than + * shared with the model, so the test states the values it expects + * independently of the implementation it is checking. + */ +#define TMP421_CONFIG_REG_1 0x09 +#define TMP421_CONFIG_REG_2 0x0A +#define TMP421_CONVERSION_RATE_REG 0x0B +#define TMP421_MANUFACTURER_ID_REG 0xFE +#define TMP421_DEVICE_ID_REG 0xFF +#define TMP421_MANUFACTURER_ID 0x55 + +#define TMP421_TEST_ID "tmp421-test" +#define TMP422_TEST_ID "tmp422-test" +#define TMP423_TEST_ID "tmp423-test" + +/* + * Per-variant expectations, passed as the qos test payload so a single test + * body can cover all three parts. + */ +typedef struct TMP421Variant { + const char *id; + uint8_t device_id; + uint8_t config2_reset; + unsigned nchannels; +} TMP421Variant; + +static const TMP421Variant tmp421_variant = { TMP421_TEST_ID, 0x21, 0x1c, 2 }; +static const TMP421Variant tmp422_variant = { TMP422_TEST_ID, 0x22, 0x3c, 3 }; +static const TMP421Variant tmp423_variant = { TMP423_TEST_ID, 0x23, 0x7c, 4 }; + +static void test_ids(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + g_assert_cmphex(i2c_get8(i2cdev, TMP421_MANUFACTURER_ID_REG), ==, + TMP421_MANUFACTURER_ID); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_DEVICE_ID_REG), ==, var->device_id); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_1), ==, 0); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_2), ==, + var->config2_reset); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONVERSION_RATE_REG), ==, 0x07); +} + +static void tmp421_register_node(const TMP421Variant *var, const char *type, + uint8_t addr) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = g_strdup_printf("id=%s,address=0x%02x", + var->id, addr), + }; + + add_qi2c_address(&opts, &(QI2CAddress) { addr }); + qos_node_create_driver(type, i2c_device_create); + qos_node_consumes(type, "i2c-bus", &opts); + + qos_add_test("ids", type, test_ids, + &(QOSGraphTestOptions) { .arg = (void *)var }); +} + +static void tmp421_register_nodes(void) +{ + tmp421_register_node(&tmp421_variant, "tmp421", 0x4c); + tmp421_register_node(&tmp422_variant, "tmp422", 0x4d); + tmp421_register_node(&tmp423_variant, "tmp423", 0x4e); +} + +libqos_init(tmp421_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 12/22] tests/qtest: tmp421: cover device IDs and reset defaults @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Add a qgraph test that instantiates each variant and checks the manufacturer and device identification bytes and the reset values of the configuration and conversion-rate registers. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/meson.build | 1 + tests/qtest/tmp421-test.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 7005509d4d..5042ae52b2 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -349,6 +349,7 @@ qos_test_ss.add( 'sdhci-test.c', 'spapr-phb-test.c', 'tmp105-test.c', + 'tmp421-test.c', 'emc141x-test.c', 'usb-hcd-ohci-test.c', 'virtio-test.c', diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c new file mode 100644 index 0000000000..2307e5f603 --- /dev/null +++ b/tests/qtest/tmp421-test.c @@ -0,0 +1,84 @@ +/* + * QTest testcase for the TMP421/TMP422/TMP423 temperature sensor + * + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "libqtest-single.h" +#include "libqos/qgraph.h" +#include "libqos/i2c.h" +#include "qobject/qdict.h" + +/* + * TMP421 register map, per the datasheet. Kept here rather than + * shared with the model, so the test states the values it expects + * independently of the implementation it is checking. + */ +#define TMP421_CONFIG_REG_1 0x09 +#define TMP421_CONFIG_REG_2 0x0A +#define TMP421_CONVERSION_RATE_REG 0x0B +#define TMP421_MANUFACTURER_ID_REG 0xFE +#define TMP421_DEVICE_ID_REG 0xFF +#define TMP421_MANUFACTURER_ID 0x55 + +#define TMP421_TEST_ID "tmp421-test" +#define TMP422_TEST_ID "tmp422-test" +#define TMP423_TEST_ID "tmp423-test" + +/* + * Per-variant expectations, passed as the qos test payload so a single test + * body can cover all three parts. + */ +typedef struct TMP421Variant { + const char *id; + uint8_t device_id; + uint8_t config2_reset; + unsigned nchannels; +} TMP421Variant; + +static const TMP421Variant tmp421_variant = { TMP421_TEST_ID, 0x21, 0x1c, 2 }; +static const TMP421Variant tmp422_variant = { TMP422_TEST_ID, 0x22, 0x3c, 3 }; +static const TMP421Variant tmp423_variant = { TMP423_TEST_ID, 0x23, 0x7c, 4 }; + +static void test_ids(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + g_assert_cmphex(i2c_get8(i2cdev, TMP421_MANUFACTURER_ID_REG), ==, + TMP421_MANUFACTURER_ID); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_DEVICE_ID_REG), ==, var->device_id); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_1), ==, 0); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_2), ==, + var->config2_reset); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONVERSION_RATE_REG), ==, 0x07); +} + +static void tmp421_register_node(const TMP421Variant *var, const char *type, + uint8_t addr) +{ + QOSGraphEdgeOptions opts = { + .extra_device_opts = g_strdup_printf("id=%s,address=0x%02x", + var->id, addr), + }; + + add_qi2c_address(&opts, &(QI2CAddress) { addr }); + qos_node_create_driver(type, i2c_device_create); + qos_node_consumes(type, "i2c-bus", &opts); + + qos_add_test("ids", type, test_ids, + &(QOSGraphTestOptions) { .arg = (void *)var }); +} + +static void tmp421_register_nodes(void) +{ + tmp421_register_node(&tmp421_variant, "tmp421", 0x4c); + tmp421_register_node(&tmp422_variant, "tmp422", 0x4d); + tmp421_register_node(&tmp423_variant, "tmp423", 0x4e); +} + +libqos_init(tmp421_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 13/22] tests/qtest: tmp421: cover temperature encoding and range 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Set a temperature over QMP and read it back through the two-byte and single-byte register paths, checking the fixed-point encoding and the extended-range offset. A second case pins the saturation: a temperature the standard range cannot express reads back clamped, without harming the measurement itself. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 2307e5f603..390f17b6b2 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -18,9 +18,13 @@ * shared with the model, so the test states the values it expects * independently of the implementation it is checking. */ +#define TMP421_TEMP_MSB0 0x00 #define TMP421_CONFIG_REG_1 0x09 +#define TMP421_CONFIG_RANGE (1 << 2) #define TMP421_CONFIG_REG_2 0x0A #define TMP421_CONVERSION_RATE_REG 0x0B +#define TMP421_TEMP_LSB0 0x10 +#define TMP421_RESET 0xFC #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF #define TMP421_MANUFACTURER_ID 0x55 @@ -44,6 +48,36 @@ static const TMP421Variant tmp421_variant = { TMP421_TEST_ID, 0x21, 0x1c, 2 }; static const TMP421Variant tmp422_variant = { TMP422_TEST_ID, 0x22, 0x3c, 3 }; static const TMP421Variant tmp423_variant = { TMP423_TEST_ID, 0x23, 0x7c, 4 }; +static QDict *qmp_get_temperature(const char *id, unsigned channel) +{ + g_autofree char *prop = g_strdup_printf("temperature%u", channel); + + return qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, " + "'property': %s } }", id, prop); +} + +static int get_temperature(const char *id, unsigned channel) +{ + QDict *response = qmp_get_temperature(id, channel); + int ret; + + g_assert(qdict_haskey(response, "return")); + ret = qdict_get_int(response, "return"); + qobject_unref(response); + return ret; +} + +static void set_temperature(const char *id, unsigned channel, int value) +{ + g_autofree char *prop = g_strdup_printf("temperature%u", channel); + QDict *response; + + response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, " + "'property': %s, 'value': %d } }", id, prop, value); + g_assert(qdict_haskey(response, "return")); + qobject_unref(response); +} + static void test_ids(void *obj, void *data, QGuestAllocator *alloc) { const TMP421Variant *var = data; @@ -58,6 +92,70 @@ static void test_ids(void *obj, void *data, QGuestAllocator *alloc) g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONVERSION_RATE_REG), ==, 0x07); } +static void test_temperature(void *obj, void *data, QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = obj; + + /* A whole degree lands on a whole register value, fraction cleared. */ + set_temperature(TMP421_TEST_ID, 0, 25000); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1900); + + /* The standard range is two's complement below 0 C. */ + set_temperature(TMP421_TEST_ID, 0, -25000); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xE700); + + /* A temperature the register form represents exactly. */ + set_temperature(TMP421_TEST_ID, 0, 25063); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1910); + + /* A lone low-byte read returns the same conversion as the pair. */ + g_assert_cmphex(i2c_get8(i2cdev, TMP421_TEMP_LSB0), ==, 0x10); + + /* Extended range encodes the same measurement with a +64 C offset. */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x5910); + + /* Leaving it, whether by a write or a reset, reports the same value */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, 0); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1910); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x5910); + i2c_set8(i2cdev, TMP421_RESET, 0); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1910); + + /* The extended range is unsigned: it reaches past +64 C (Table 1). */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 100063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xA410); +} + +/* + * A temperature the standard range cannot express saturates at +127 C (7Fh) + * instead of wrapping, and the extended range still reports it in full: the + * range picks an encoding, it does not alter the measurement. + */ +static void test_range_saturation(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = obj; + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 149938); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xD5F0); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, 0); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x7FF0); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 149938); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xD5F0); +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -79,6 +177,10 @@ static void tmp421_register_nodes(void) tmp421_register_node(&tmp421_variant, "tmp421", 0x4c); tmp421_register_node(&tmp422_variant, "tmp422", 0x4d); tmp421_register_node(&tmp423_variant, "tmp423", 0x4e); + + /* Temperature encoding is variant-independent; exercise it once. */ + qos_add_test("temperature", "tmp421", test_temperature, NULL); + qos_add_test("range-saturation", "tmp421", test_range_saturation, NULL); } libqos_init(tmp421_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 13/22] tests/qtest: tmp421: cover temperature encoding and range @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Set a temperature over QMP and read it back through the two-byte and single-byte register paths, checking the fixed-point encoding and the extended-range offset. A second case pins the saturation: a temperature the standard range cannot express reads back clamped, without harming the measurement itself. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 2307e5f603..390f17b6b2 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -18,9 +18,13 @@ * shared with the model, so the test states the values it expects * independently of the implementation it is checking. */ +#define TMP421_TEMP_MSB0 0x00 #define TMP421_CONFIG_REG_1 0x09 +#define TMP421_CONFIG_RANGE (1 << 2) #define TMP421_CONFIG_REG_2 0x0A #define TMP421_CONVERSION_RATE_REG 0x0B +#define TMP421_TEMP_LSB0 0x10 +#define TMP421_RESET 0xFC #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF #define TMP421_MANUFACTURER_ID 0x55 @@ -44,6 +48,36 @@ static const TMP421Variant tmp421_variant = { TMP421_TEST_ID, 0x21, 0x1c, 2 }; static const TMP421Variant tmp422_variant = { TMP422_TEST_ID, 0x22, 0x3c, 3 }; static const TMP421Variant tmp423_variant = { TMP423_TEST_ID, 0x23, 0x7c, 4 }; +static QDict *qmp_get_temperature(const char *id, unsigned channel) +{ + g_autofree char *prop = g_strdup_printf("temperature%u", channel); + + return qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, " + "'property': %s } }", id, prop); +} + +static int get_temperature(const char *id, unsigned channel) +{ + QDict *response = qmp_get_temperature(id, channel); + int ret; + + g_assert(qdict_haskey(response, "return")); + ret = qdict_get_int(response, "return"); + qobject_unref(response); + return ret; +} + +static void set_temperature(const char *id, unsigned channel, int value) +{ + g_autofree char *prop = g_strdup_printf("temperature%u", channel); + QDict *response; + + response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, " + "'property': %s, 'value': %d } }", id, prop, value); + g_assert(qdict_haskey(response, "return")); + qobject_unref(response); +} + static void test_ids(void *obj, void *data, QGuestAllocator *alloc) { const TMP421Variant *var = data; @@ -58,6 +92,70 @@ static void test_ids(void *obj, void *data, QGuestAllocator *alloc) g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONVERSION_RATE_REG), ==, 0x07); } +static void test_temperature(void *obj, void *data, QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = obj; + + /* A whole degree lands on a whole register value, fraction cleared. */ + set_temperature(TMP421_TEST_ID, 0, 25000); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1900); + + /* The standard range is two's complement below 0 C. */ + set_temperature(TMP421_TEST_ID, 0, -25000); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xE700); + + /* A temperature the register form represents exactly. */ + set_temperature(TMP421_TEST_ID, 0, 25063); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1910); + + /* A lone low-byte read returns the same conversion as the pair. */ + g_assert_cmphex(i2c_get8(i2cdev, TMP421_TEMP_LSB0), ==, 0x10); + + /* Extended range encodes the same measurement with a +64 C offset. */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x5910); + + /* Leaving it, whether by a write or a reset, reports the same value */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, 0); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1910); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x5910); + i2c_set8(i2cdev, TMP421_RESET, 0); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 25063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x1910); + + /* The extended range is unsigned: it reaches past +64 C (Table 1). */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 100063); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xA410); +} + +/* + * A temperature the standard range cannot express saturates at +127 C (7Fh) + * instead of wrapping, and the extended range still reports it in full: the + * range picks an encoding, it does not alter the measurement. + */ +static void test_range_saturation(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = obj; + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 149938); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xD5F0); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, 0); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0x7FF0); + g_assert_cmpint(get_temperature(TMP421_TEST_ID, 0), ==, 149938); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xD5F0); +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -79,6 +177,10 @@ static void tmp421_register_nodes(void) tmp421_register_node(&tmp421_variant, "tmp421", 0x4c); tmp421_register_node(&tmp422_variant, "tmp422", 0x4d); tmp421_register_node(&tmp423_variant, "tmp423", 0x4e); + + /* Temperature encoding is variant-independent; exercise it once. */ + qos_add_test("temperature", "tmp421", test_temperature, NULL); + qos_add_test("range-saturation", "tmp421", test_range_saturation, NULL); } libqos_init(tmp421_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 14/22] tests/qtest: tmp421: cover per-variant channels and enablement 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Check that each variant exposes only its own temperature properties, that writing an absent channel's enable bit is ignored, and that disabling a present channel makes it read back as zero. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 390f17b6b2..04f9252188 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -22,6 +22,7 @@ #define TMP421_CONFIG_REG_1 0x09 #define TMP421_CONFIG_RANGE (1 << 2) #define TMP421_CONFIG_REG_2 0x0A +#define TMP421_CONFIG_REN (1 << 4) #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_TEMP_LSB0 0x10 #define TMP421_RESET 0xFC @@ -78,6 +79,15 @@ static void set_temperature(const char *id, unsigned channel, int value) qobject_unref(response); } +static bool has_temperature(const char *id, unsigned channel) +{ + QDict *response = qmp_get_temperature(id, channel); + bool present = qdict_haskey(response, "return"); + + qobject_unref(response); + return present; +} + static void test_ids(void *obj, void *data, QGuestAllocator *alloc) { const TMP421Variant *var = data; @@ -156,6 +166,31 @@ static void test_range_saturation(void *obj, void *data, g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xD5F0); } +static void test_channels(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + /* Only the variant's own channels expose a temperature property. */ + for (unsigned ch = 0; ch < 4; ch++) { + g_assert_true(has_temperature(var->id, ch) == (ch < var->nchannels)); + } + + /* Absent channel enables and reserved bits are dropped on write. */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, 0xff); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_2), ==, + var->config2_reset); + + /* Disabling remote channel 1 makes it read back as zero. */ + set_temperature(var->id, 1, 25001); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0x1900); + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, + var->config2_reset & ~TMP421_CONFIG_REN); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0); + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, var->config2_reset); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0x1900); +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -170,6 +205,8 @@ static void tmp421_register_node(const TMP421Variant *var, const char *type, qos_add_test("ids", type, test_ids, &(QOSGraphTestOptions) { .arg = (void *)var }); + qos_add_test("channels", type, test_channels, + &(QOSGraphTestOptions) { .arg = (void *)var }); } static void tmp421_register_nodes(void) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 14/22] tests/qtest: tmp421: cover per-variant channels and enablement @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Check that each variant exposes only its own temperature properties, that writing an absent channel's enable bit is ignored, and that disabling a present channel makes it read back as zero. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 390f17b6b2..04f9252188 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -22,6 +22,7 @@ #define TMP421_CONFIG_REG_1 0x09 #define TMP421_CONFIG_RANGE (1 << 2) #define TMP421_CONFIG_REG_2 0x0A +#define TMP421_CONFIG_REN (1 << 4) #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_TEMP_LSB0 0x10 #define TMP421_RESET 0xFC @@ -78,6 +79,15 @@ static void set_temperature(const char *id, unsigned channel, int value) qobject_unref(response); } +static bool has_temperature(const char *id, unsigned channel) +{ + QDict *response = qmp_get_temperature(id, channel); + bool present = qdict_haskey(response, "return"); + + qobject_unref(response); + return present; +} + static void test_ids(void *obj, void *data, QGuestAllocator *alloc) { const TMP421Variant *var = data; @@ -156,6 +166,31 @@ static void test_range_saturation(void *obj, void *data, g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xD5F0); } +static void test_channels(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + /* Only the variant's own channels expose a temperature property. */ + for (unsigned ch = 0; ch < 4; ch++) { + g_assert_true(has_temperature(var->id, ch) == (ch < var->nchannels)); + } + + /* Absent channel enables and reserved bits are dropped on write. */ + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, 0xff); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_2), ==, + var->config2_reset); + + /* Disabling remote channel 1 makes it read back as zero. */ + set_temperature(var->id, 1, 25001); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0x1900); + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, + var->config2_reset & ~TMP421_CONFIG_REN); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0); + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, var->config2_reset); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0x1900); +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -170,6 +205,8 @@ static void tmp421_register_node(const TMP421Variant *var, const char *type, qos_add_test("ids", type, test_ids, &(QOSGraphTestOptions) { .arg = (void *)var }); + qos_add_test("channels", type, test_channels, + &(QOSGraphTestOptions) { .arg = (void *)var }); } static void tmp421_register_nodes(void) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 15/22] tests/qtest: tmp421: cover software reset and N-factor registers 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Check that the software-reset register restores the configuration and conversion-rate defaults, and that the N-factor correction registers are writable only on the remote channels each variant provides. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 04f9252188..6c5332211b 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -25,6 +25,7 @@ #define TMP421_CONFIG_REN (1 << 4) #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_TEMP_LSB0 0x10 +#define TMP421_N_CORRECT 0x21 #define TMP421_RESET 0xFC #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF @@ -191,6 +192,38 @@ static void test_channels(void *obj, void *data, QGuestAllocator *alloc) g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0x1900); } +static void test_soft_reset(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, 0); + i2c_set8(i2cdev, TMP421_CONVERSION_RATE_REG, 0); + + i2c_set8(i2cdev, TMP421_RESET, 0); + + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_1), ==, 0); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_2), ==, + var->config2_reset); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONVERSION_RATE_REG), ==, 0x07); +} + +static void test_n_correct(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + for (unsigned remote = 0; remote < 3; remote++) { + uint8_t reg = TMP421_N_CORRECT + remote; + + i2c_set8(i2cdev, reg, 0x7f); + /* Registers exist only for the variant's remote channels. */ + g_assert_cmphex(i2c_get8(i2cdev, reg), ==, + remote + 1 < var->nchannels ? 0x7f : 0); + } +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -207,6 +240,10 @@ static void tmp421_register_node(const TMP421Variant *var, const char *type, &(QOSGraphTestOptions) { .arg = (void *)var }); qos_add_test("channels", type, test_channels, &(QOSGraphTestOptions) { .arg = (void *)var }); + qos_add_test("soft-reset", type, test_soft_reset, + &(QOSGraphTestOptions) { .arg = (void *)var }); + qos_add_test("n-correct", type, test_n_correct, + &(QOSGraphTestOptions) { .arg = (void *)var }); } static void tmp421_register_nodes(void) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 15/22] tests/qtest: tmp421: cover software reset and N-factor registers @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Check that the software-reset register restores the configuration and conversion-rate defaults, and that the N-factor correction registers are writable only on the remote channels each variant provides. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 04f9252188..6c5332211b 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -25,6 +25,7 @@ #define TMP421_CONFIG_REN (1 << 4) #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_TEMP_LSB0 0x10 +#define TMP421_N_CORRECT 0x21 #define TMP421_RESET 0xFC #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF @@ -191,6 +192,38 @@ static void test_channels(void *obj, void *data, QGuestAllocator *alloc) g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0 + 1), ==, 0x1900); } +static void test_soft_reset(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + i2c_set8(i2cdev, TMP421_CONFIG_REG_2, 0); + i2c_set8(i2cdev, TMP421_CONVERSION_RATE_REG, 0); + + i2c_set8(i2cdev, TMP421_RESET, 0); + + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_1), ==, 0); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONFIG_REG_2), ==, + var->config2_reset); + g_assert_cmphex(i2c_get8(i2cdev, TMP421_CONVERSION_RATE_REG), ==, 0x07); +} + +static void test_n_correct(void *obj, void *data, QGuestAllocator *alloc) +{ + const TMP421Variant *var = data; + QI2CDevice *i2cdev = obj; + + for (unsigned remote = 0; remote < 3; remote++) { + uint8_t reg = TMP421_N_CORRECT + remote; + + i2c_set8(i2cdev, reg, 0x7f); + /* Registers exist only for the variant's remote channels. */ + g_assert_cmphex(i2c_get8(i2cdev, reg), ==, + remote + 1 < var->nchannels ? 0x7f : 0); + } +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -207,6 +240,10 @@ static void tmp421_register_node(const TMP421Variant *var, const char *type, &(QOSGraphTestOptions) { .arg = (void *)var }); qos_add_test("channels", type, test_channels, &(QOSGraphTestOptions) { .arg = (void *)var }); + qos_add_test("soft-reset", type, test_soft_reset, + &(QOSGraphTestOptions) { .arg = (void *)var }); + qos_add_test("n-correct", type, test_n_correct, + &(QOSGraphTestOptions) { .arg = (void *)var }); } static void tmp421_register_nodes(void) -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 16/22] tests/qtest: tmp421: cover the register form of the migration stream 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot A stream with no measurement subsection has the shape of every stream written before that subsection existed; loading one exercises the conversion back from the register form. The temperature is picked so that form reproduces it exactly, and picked in the extended range, where the top register bit is part of the value rather than a sign. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 6c5332211b..5be2abc822 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -8,6 +8,8 @@ #include "qemu/osdep.h" +#include <glib/gstdio.h> +#include "libqtest.h" #include "libqtest-single.h" #include "libqos/qgraph.h" #include "libqos/i2c.h" @@ -224,6 +226,69 @@ static void test_n_correct(void *obj, void *data, QGuestAllocator *alloc) } } +static int qtest_get_temperature(QTestState *qts, const char *id, + unsigned channel) +{ + g_autofree char *prop = g_strdup_printf("temperature%u", channel); + QDict *response; + int ret; + + response = qtest_qmp(qts, "{ 'execute': 'qom-get', 'arguments': " + "{ 'path': %s, 'property': %s } }", id, prop); + g_assert(qdict_haskey(response, "return")); + ret = qdict_get_int(response, "return"); + qobject_unref(response); + return ret; +} + +/* + * A stream written before the measurement was held in millidegrees carries + * only the register form. The subsection holding the measurement is left out + * whenever that form can reproduce it, so an exactly representable extended + * range temperature -- whose register value has its top bit set, and is not + * a negative number -- travels the same path such a stream takes. + */ +static void test_migration(void *obj, void *data, QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = obj; + g_autofree char *tmpfs = NULL; + g_autofree char *mig_path = NULL; + g_autofree char *uri = NULL; + GString *dest_cmdline; + GError *err = NULL; + QTestState *to; + QDict *rsp; + + tmpfs = g_dir_make_tmp("tmp421-test-XXXXXX", &err); + g_assert_no_error(err); + g_assert(tmpfs); + + mig_path = g_strdup_printf("%s/socket.mig", tmpfs); + uri = g_strdup_printf("unix:%s", mig_path); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 100000); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xA400); + + dest_cmdline = g_string_new(qos_get_current_command_line()); + g_string_append_printf(dest_cmdline, " -incoming %s", uri); + to = qtest_init(dest_cmdline->str); + + rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri); + g_assert(qdict_haskey(rsp, "return")); + qobject_unref(rsp); + + qmp_eventwait("STOP"); + qtest_qmp_eventwait(to, "RESUME"); + + g_assert_cmpint(qtest_get_temperature(to, TMP421_TEST_ID, 0), ==, 100000); + + qtest_quit(to); + g_unlink(mig_path); + g_rmdir(tmpfs); + g_string_free(dest_cmdline, true); +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -255,6 +320,7 @@ static void tmp421_register_nodes(void) /* Temperature encoding is variant-independent; exercise it once. */ qos_add_test("temperature", "tmp421", test_temperature, NULL); qos_add_test("range-saturation", "tmp421", test_range_saturation, NULL); + qos_add_test("migration", "tmp421", test_migration, NULL); } libqos_init(tmp421_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 16/22] tests/qtest: tmp421: cover the register form of the migration stream @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot A stream with no measurement subsection has the shape of every stream written before that subsection existed; loading one exercises the conversion back from the register form. The temperature is picked so that form reproduces it exactly, and picked in the extended range, where the top register bit is part of the value rather than a sign. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp421-test.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/qtest/tmp421-test.c b/tests/qtest/tmp421-test.c index 6c5332211b..5be2abc822 100644 --- a/tests/qtest/tmp421-test.c +++ b/tests/qtest/tmp421-test.c @@ -8,6 +8,8 @@ #include "qemu/osdep.h" +#include <glib/gstdio.h> +#include "libqtest.h" #include "libqtest-single.h" #include "libqos/qgraph.h" #include "libqos/i2c.h" @@ -224,6 +226,69 @@ static void test_n_correct(void *obj, void *data, QGuestAllocator *alloc) } } +static int qtest_get_temperature(QTestState *qts, const char *id, + unsigned channel) +{ + g_autofree char *prop = g_strdup_printf("temperature%u", channel); + QDict *response; + int ret; + + response = qtest_qmp(qts, "{ 'execute': 'qom-get', 'arguments': " + "{ 'path': %s, 'property': %s } }", id, prop); + g_assert(qdict_haskey(response, "return")); + ret = qdict_get_int(response, "return"); + qobject_unref(response); + return ret; +} + +/* + * A stream written before the measurement was held in millidegrees carries + * only the register form. The subsection holding the measurement is left out + * whenever that form can reproduce it, so an exactly representable extended + * range temperature -- whose register value has its top bit set, and is not + * a negative number -- travels the same path such a stream takes. + */ +static void test_migration(void *obj, void *data, QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = obj; + g_autofree char *tmpfs = NULL; + g_autofree char *mig_path = NULL; + g_autofree char *uri = NULL; + GString *dest_cmdline; + GError *err = NULL; + QTestState *to; + QDict *rsp; + + tmpfs = g_dir_make_tmp("tmp421-test-XXXXXX", &err); + g_assert_no_error(err); + g_assert(tmpfs); + + mig_path = g_strdup_printf("%s/socket.mig", tmpfs); + uri = g_strdup_printf("unix:%s", mig_path); + + i2c_set8(i2cdev, TMP421_CONFIG_REG_1, TMP421_CONFIG_RANGE); + set_temperature(TMP421_TEST_ID, 0, 100000); + g_assert_cmphex(i2c_get16(i2cdev, TMP421_TEMP_MSB0), ==, 0xA400); + + dest_cmdline = g_string_new(qos_get_current_command_line()); + g_string_append_printf(dest_cmdline, " -incoming %s", uri); + to = qtest_init(dest_cmdline->str); + + rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri); + g_assert(qdict_haskey(rsp, "return")); + qobject_unref(rsp); + + qmp_eventwait("STOP"); + qtest_qmp_eventwait(to, "RESUME"); + + g_assert_cmpint(qtest_get_temperature(to, TMP421_TEST_ID, 0), ==, 100000); + + qtest_quit(to); + g_unlink(mig_path); + g_rmdir(tmpfs); + g_string_free(dest_cmdline, true); +} + static void tmp421_register_node(const TMP421Variant *var, const char *type, uint8_t addr) { @@ -255,6 +320,7 @@ static void tmp421_register_nodes(void) /* Temperature encoding is variant-independent; exercise it once. */ qos_add_test("temperature", "tmp421", test_temperature, NULL); qos_add_test("range-saturation", "tmp421", test_range_saturation, NULL); + qos_add_test("migration", "tmp421", test_migration, NULL); } libqos_init(tmp421_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 17/22] hw/sensor: tmp105: add the TMP1075 variant 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The TMP1075 is register-compatible with the xx75 family but widens the Config register to 16 bits and adds a read-only Device ID register. Model it as a new variant of the shared TMP105 device: the control bits keep the legacy layout in the upper byte, the lower byte has no function of its own but is writable, and single-byte access stays compatible with the 8-bit parts. The converter is fixed at 12 bits and the fault queue matches the TMP75. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp105.c | 85 ++++++++++++++++++++++++++++++++++++++++- include/hw/sensor/tmp105.h | 2 + include/hw/sensor/tmp105_regs.h | 5 +++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/hw/sensor/tmp105.c b/hw/sensor/tmp105.c index ece0650d70..c5aa553d9a 100644 --- a/hw/sensor/tmp105.c +++ b/hw/sensor/tmp105.c @@ -1,5 +1,5 @@ /* - * Texas Instruments TMP105/TMP75/TMP175/LM75B temperature sensor. + * Texas Instruments TMP105/TMP75/TMP175/TMP1075/LM75B temperature sensor. * * Copyright (C) 2008 Nokia Corporation * Written by Andrzej Zaborowski <andrew@openedhand.com> @@ -51,6 +51,7 @@ struct TMP105State { uint8_t pointer; uint8_t config; + uint8_t config_lsb; int16_t temperature; int16_t limit[2]; uint8_t faults; @@ -76,6 +77,12 @@ struct TMP105State { * @fixed_res: converter resolution field pinned by the device, or -1 when it is * software-selectable. * @limit_lsb_mask: low-byte mask applied to the T_LOW/T_HIGH limit registers. + * @config16: the Config register is 16 bits wide over I2C. Its control bits + * occupy the upper byte (mirroring the 8-bit layout); the lower byte has no + * function of its own but is writable, and comes up as 0xff. Single-byte + * access stays compatible with the 8-bit parts. + * @die_id: value of the read-only Device ID register, or 0 when the device has + * none. */ struct TMP105Class { I2CSlaveClass parent_class; @@ -84,6 +91,8 @@ struct TMP105Class { int8_t fixed_res; uint8_t limit_lsb_mask; bool tm_change_clears_alert; + bool config16; + uint16_t die_id; }; FIELD(CONFIG, SHUTDOWN_MODE, 0, 1) @@ -185,6 +194,13 @@ static void tmp105_read(TMP105State *s) tmp105_interrupt_update(s); } + if (tc->die_id && (s->pointer & 0x0f) == TMP105_REG_DIE_ID) { + s->buf[s->len++] = tc->die_id >> 8; + s->buf[s->len++] = tc->die_id & 0xff; + trace_tmp105_read(s->parent_obj.address, s->pointer); + return; + } + switch (s->pointer & 3) { case TMP105_REG_TEMPERATURE: res = tc->fixed_res >= 0 ? tc->fixed_res : @@ -196,6 +212,9 @@ static void tmp105_read(TMP105State *s) case TMP105_REG_CONFIG: s->buf[s->len++] = s->config; + if (tc->config16) { + s->buf[s->len++] = s->config_lsb; + } break; case TMP105_REG_T_LOW: @@ -220,11 +239,29 @@ static void tmp105_write(TMP105State *s) trace_tmp105_write(s->parent_obj.address, s->pointer); + if (tc->die_id && (s->pointer & 0x0f) == TMP105_REG_DIE_ID) { + return; /* Device ID register is read-only */ + } + switch (s->pointer & 3) { case TMP105_REG_TEMPERATURE: break; case TMP105_REG_CONFIG: + /* + * The control bits live in the first data byte for every variant (the + * upper byte of the TMP1075 16-bit register); a second byte is the low + * byte, which drives nothing but keeps what it is given. + */ + if (s->len == 3) { + if (tc->config16) { + s->config_lsb = s->buf[1]; + } + break; + } + if (s->len != 2) { + break; + } config = s->buf[0] & tc->config_wmask; if (FIELD_EX8(config & ~s->config, CONFIG, SHUTDOWN_MODE)) { trace_tmp105_write_shutdown(s->parent_obj.address); @@ -334,6 +371,13 @@ static bool fault_count_needed(void *opaque) return s->fault_count != 0; } +static bool config_lsb_needed(void *opaque) +{ + TMP105State *s = opaque; + + return TMP105_GET_CLASS(s)->config16 && s->config_lsb != 0xff; +} + static const VMStateDescription vmstate_tmp105_detect_falling = { .name = "TMP105/detect-falling", .version_id = 1, @@ -356,6 +400,17 @@ static const VMStateDescription vmstate_tmp105_fault_count = { } }; +static const VMStateDescription vmstate_tmp105_config_lsb = { + .name = "TMP105/config-lsb", + .version_id = 1, + .minimum_version_id = 1, + .needed = config_lsb_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINT8(config_lsb, TMP105State), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_tmp105 = { .name = "TMP105", .version_id = 0, @@ -375,6 +430,7 @@ static const VMStateDescription vmstate_tmp105 = { .subsections = (const VMStateDescription * const []) { &vmstate_tmp105_detect_falling, &vmstate_tmp105_fault_count, + &vmstate_tmp105_config_lsb, NULL } }; @@ -387,6 +443,7 @@ static void tmp105_reset_hold(Object *obj, ResetType type) s->temperature = 0; s->pointer = 0; s->config = 0; + s->config_lsb = tc->config16 ? 0xff : 0; s->faults = tc->faultq[FIELD_EX8(s->config, CONFIG, FAULT_QUEUE)]; s->fault_count = 0; s->alarm = 0; @@ -447,6 +504,8 @@ static void tmp105_class_init(ObjectClass *klass, const void *data) tc->fixed_res = -1; tc->limit_lsb_mask = 0xf0; tc->tm_change_clears_alert = false; + tc->config16 = false; + tc->die_id = 0; } static void tmp175_class_init(ObjectClass *klass, const void *data) @@ -482,6 +541,25 @@ static void lm75b_class_init(ObjectClass *klass, const void *data) tc->tm_change_clears_alert = false; } +/* + * The TMP1075 fixes the converter at 12 bits (its R1:R0 bits select the + * conversion rate instead, which this instantaneous model does not track), uses + * the TMP75 fault-queue mapping, exposes a 16-bit Config register and answers + * the Device ID register with 0x7500. + */ +static void tmp1075_class_init(ObjectClass *klass, const void *data) +{ + TMP105Class *tc = TMP105_CLASS(klass); + + tc->faultq = tmp105_faultq[1]; + tc->config_wmask = 0xff; + tc->fixed_res = 3; + tc->limit_lsb_mask = 0xf0; + tc->tm_change_clears_alert = true; + tc->config16 = true; + tc->die_id = TMP1075_DEVICE_ID; +} + static const TypeInfo tmp105_types[] = { { .name = TYPE_TMP105, @@ -506,6 +584,11 @@ static const TypeInfo tmp105_types[] = { .parent = TYPE_TMP105, .class_init = lm75b_class_init, }, + { + .name = TYPE_TMP1075, + .parent = TYPE_TMP105, + .class_init = tmp1075_class_init, + }, }; DEFINE_TYPES(tmp105_types) diff --git a/include/hw/sensor/tmp105.h b/include/hw/sensor/tmp105.h index 0698aeead7..6a30504c7c 100644 --- a/include/hw/sensor/tmp105.h +++ b/include/hw/sensor/tmp105.h @@ -19,5 +19,7 @@ #define TYPE_TMP175 "tmp175" #define TYPE_TMP75 "tmp75" #define TYPE_LM75B "lm75b" +/* TMP1075 adds a 16-bit Config register and a Device ID register. */ +#define TYPE_TMP1075 "tmp1075" #endif diff --git a/include/hw/sensor/tmp105_regs.h b/include/hw/sensor/tmp105_regs.h index ef015ee5cf..ecd0510c2e 100644 --- a/include/hw/sensor/tmp105_regs.h +++ b/include/hw/sensor/tmp105_regs.h @@ -21,6 +21,7 @@ * @TMP105_REG_CONFIG: Configuration register * @TMP105_REG_T_LOW: Low temperature register (also known as T_hyst) * @TMP105_REG_T_HIGH: High temperature register (also known as T_OS) + * @TMP105_REG_DIE_ID: Device ID register (TMP1075 only) * * The following temperature sensors are * compatible with the TMP105 registers: @@ -46,6 +47,10 @@ typedef enum TMP105Reg { TMP105_REG_CONFIG, TMP105_REG_T_LOW, TMP105_REG_T_HIGH, + TMP105_REG_DIE_ID = 0x0f, } TMP105Reg; +/* Value returned by the TMP1075 Device ID register. */ +#define TMP1075_DEVICE_ID 0x7500 + #endif -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 17/22] hw/sensor: tmp105: add the TMP1075 variant @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The TMP1075 is register-compatible with the xx75 family but widens the Config register to 16 bits and adds a read-only Device ID register. Model it as a new variant of the shared TMP105 device: the control bits keep the legacy layout in the upper byte, the lower byte has no function of its own but is writable, and single-byte access stays compatible with the 8-bit parts. The converter is fixed at 12 bits and the fault queue matches the TMP75. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/sensor/tmp105.c | 85 ++++++++++++++++++++++++++++++++++++++++- include/hw/sensor/tmp105.h | 2 + include/hw/sensor/tmp105_regs.h | 5 +++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/hw/sensor/tmp105.c b/hw/sensor/tmp105.c index ece0650d70..c5aa553d9a 100644 --- a/hw/sensor/tmp105.c +++ b/hw/sensor/tmp105.c @@ -1,5 +1,5 @@ /* - * Texas Instruments TMP105/TMP75/TMP175/LM75B temperature sensor. + * Texas Instruments TMP105/TMP75/TMP175/TMP1075/LM75B temperature sensor. * * Copyright (C) 2008 Nokia Corporation * Written by Andrzej Zaborowski <andrew@openedhand.com> @@ -51,6 +51,7 @@ struct TMP105State { uint8_t pointer; uint8_t config; + uint8_t config_lsb; int16_t temperature; int16_t limit[2]; uint8_t faults; @@ -76,6 +77,12 @@ struct TMP105State { * @fixed_res: converter resolution field pinned by the device, or -1 when it is * software-selectable. * @limit_lsb_mask: low-byte mask applied to the T_LOW/T_HIGH limit registers. + * @config16: the Config register is 16 bits wide over I2C. Its control bits + * occupy the upper byte (mirroring the 8-bit layout); the lower byte has no + * function of its own but is writable, and comes up as 0xff. Single-byte + * access stays compatible with the 8-bit parts. + * @die_id: value of the read-only Device ID register, or 0 when the device has + * none. */ struct TMP105Class { I2CSlaveClass parent_class; @@ -84,6 +91,8 @@ struct TMP105Class { int8_t fixed_res; uint8_t limit_lsb_mask; bool tm_change_clears_alert; + bool config16; + uint16_t die_id; }; FIELD(CONFIG, SHUTDOWN_MODE, 0, 1) @@ -185,6 +194,13 @@ static void tmp105_read(TMP105State *s) tmp105_interrupt_update(s); } + if (tc->die_id && (s->pointer & 0x0f) == TMP105_REG_DIE_ID) { + s->buf[s->len++] = tc->die_id >> 8; + s->buf[s->len++] = tc->die_id & 0xff; + trace_tmp105_read(s->parent_obj.address, s->pointer); + return; + } + switch (s->pointer & 3) { case TMP105_REG_TEMPERATURE: res = tc->fixed_res >= 0 ? tc->fixed_res : @@ -196,6 +212,9 @@ static void tmp105_read(TMP105State *s) case TMP105_REG_CONFIG: s->buf[s->len++] = s->config; + if (tc->config16) { + s->buf[s->len++] = s->config_lsb; + } break; case TMP105_REG_T_LOW: @@ -220,11 +239,29 @@ static void tmp105_write(TMP105State *s) trace_tmp105_write(s->parent_obj.address, s->pointer); + if (tc->die_id && (s->pointer & 0x0f) == TMP105_REG_DIE_ID) { + return; /* Device ID register is read-only */ + } + switch (s->pointer & 3) { case TMP105_REG_TEMPERATURE: break; case TMP105_REG_CONFIG: + /* + * The control bits live in the first data byte for every variant (the + * upper byte of the TMP1075 16-bit register); a second byte is the low + * byte, which drives nothing but keeps what it is given. + */ + if (s->len == 3) { + if (tc->config16) { + s->config_lsb = s->buf[1]; + } + break; + } + if (s->len != 2) { + break; + } config = s->buf[0] & tc->config_wmask; if (FIELD_EX8(config & ~s->config, CONFIG, SHUTDOWN_MODE)) { trace_tmp105_write_shutdown(s->parent_obj.address); @@ -334,6 +371,13 @@ static bool fault_count_needed(void *opaque) return s->fault_count != 0; } +static bool config_lsb_needed(void *opaque) +{ + TMP105State *s = opaque; + + return TMP105_GET_CLASS(s)->config16 && s->config_lsb != 0xff; +} + static const VMStateDescription vmstate_tmp105_detect_falling = { .name = "TMP105/detect-falling", .version_id = 1, @@ -356,6 +400,17 @@ static const VMStateDescription vmstate_tmp105_fault_count = { } }; +static const VMStateDescription vmstate_tmp105_config_lsb = { + .name = "TMP105/config-lsb", + .version_id = 1, + .minimum_version_id = 1, + .needed = config_lsb_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINT8(config_lsb, TMP105State), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_tmp105 = { .name = "TMP105", .version_id = 0, @@ -375,6 +430,7 @@ static const VMStateDescription vmstate_tmp105 = { .subsections = (const VMStateDescription * const []) { &vmstate_tmp105_detect_falling, &vmstate_tmp105_fault_count, + &vmstate_tmp105_config_lsb, NULL } }; @@ -387,6 +443,7 @@ static void tmp105_reset_hold(Object *obj, ResetType type) s->temperature = 0; s->pointer = 0; s->config = 0; + s->config_lsb = tc->config16 ? 0xff : 0; s->faults = tc->faultq[FIELD_EX8(s->config, CONFIG, FAULT_QUEUE)]; s->fault_count = 0; s->alarm = 0; @@ -447,6 +504,8 @@ static void tmp105_class_init(ObjectClass *klass, const void *data) tc->fixed_res = -1; tc->limit_lsb_mask = 0xf0; tc->tm_change_clears_alert = false; + tc->config16 = false; + tc->die_id = 0; } static void tmp175_class_init(ObjectClass *klass, const void *data) @@ -482,6 +541,25 @@ static void lm75b_class_init(ObjectClass *klass, const void *data) tc->tm_change_clears_alert = false; } +/* + * The TMP1075 fixes the converter at 12 bits (its R1:R0 bits select the + * conversion rate instead, which this instantaneous model does not track), uses + * the TMP75 fault-queue mapping, exposes a 16-bit Config register and answers + * the Device ID register with 0x7500. + */ +static void tmp1075_class_init(ObjectClass *klass, const void *data) +{ + TMP105Class *tc = TMP105_CLASS(klass); + + tc->faultq = tmp105_faultq[1]; + tc->config_wmask = 0xff; + tc->fixed_res = 3; + tc->limit_lsb_mask = 0xf0; + tc->tm_change_clears_alert = true; + tc->config16 = true; + tc->die_id = TMP1075_DEVICE_ID; +} + static const TypeInfo tmp105_types[] = { { .name = TYPE_TMP105, @@ -506,6 +584,11 @@ static const TypeInfo tmp105_types[] = { .parent = TYPE_TMP105, .class_init = lm75b_class_init, }, + { + .name = TYPE_TMP1075, + .parent = TYPE_TMP105, + .class_init = tmp1075_class_init, + }, }; DEFINE_TYPES(tmp105_types) diff --git a/include/hw/sensor/tmp105.h b/include/hw/sensor/tmp105.h index 0698aeead7..6a30504c7c 100644 --- a/include/hw/sensor/tmp105.h +++ b/include/hw/sensor/tmp105.h @@ -19,5 +19,7 @@ #define TYPE_TMP175 "tmp175" #define TYPE_TMP75 "tmp75" #define TYPE_LM75B "lm75b" +/* TMP1075 adds a 16-bit Config register and a Device ID register. */ +#define TYPE_TMP1075 "tmp1075" #endif diff --git a/include/hw/sensor/tmp105_regs.h b/include/hw/sensor/tmp105_regs.h index ef015ee5cf..ecd0510c2e 100644 --- a/include/hw/sensor/tmp105_regs.h +++ b/include/hw/sensor/tmp105_regs.h @@ -21,6 +21,7 @@ * @TMP105_REG_CONFIG: Configuration register * @TMP105_REG_T_LOW: Low temperature register (also known as T_hyst) * @TMP105_REG_T_HIGH: High temperature register (also known as T_OS) + * @TMP105_REG_DIE_ID: Device ID register (TMP1075 only) * * The following temperature sensors are * compatible with the TMP105 registers: @@ -46,6 +47,10 @@ typedef enum TMP105Reg { TMP105_REG_CONFIG, TMP105_REG_T_LOW, TMP105_REG_T_HIGH, + TMP105_REG_DIE_ID = 0x0f, } TMP105Reg; +/* Value returned by the TMP1075 Device ID register. */ +#define TMP1075_DEVICE_ID 0x7500 + #endif -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 18/22] tests/qtest: tmp105: cover the TMP1075 device ID and reset defaults 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Add a TMP1075 node and check its power-on Config, limit and Device ID register values, including that the Device ID register is read-only. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp105-test.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/qtest/tmp105-test.c b/tests/qtest/tmp105-test.c index 504f6b7202..426c4f9ae7 100644 --- a/tests/qtest/tmp105-test.c +++ b/tests/qtest/tmp105-test.c @@ -28,6 +28,8 @@ #define LM75B_TEST_ID "lm75b-test" #define LM75B_TEST_PATH "/machine/peripheral/" LM75B_TEST_ID +#define TMP1075_TEST_ID "tmp1075-test" + #define TMP105_CONFIG_POL (1 << 2) /* ALERT active-high when set */ #define TMP105_CONFIG_TM (1 << 1) /* interrupt (thermostat) mode */ #define TMP105_CONFIG_FQ_1 (0 << 3) /* fault queue: 1 consecutive fault */ @@ -419,6 +421,26 @@ static void test_lm75b_shutdown_clears_alert(void *obj, void *data, g_assert_false(get_irq(0)); } +/* + * The TMP1075 answers a read-only Device ID register and powers up with the + * modern reset defaults. + */ +static void test_tmp1075_device_id(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = (QI2CDevice *)obj; + + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x00ff); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_LOW), ==, 0x4b00); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_HIGH), ==, 0x5000); + + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_DIE_ID), ==, + TMP1075_DEVICE_ID); + i2c_set16(i2cdev, TMP105_REG_DIE_ID, 0x1234); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_DIE_ID), ==, + TMP1075_DEVICE_ID); +} + static void tmp105_register_nodes(void) { QOSGraphEdgeOptions opts = { @@ -475,5 +497,16 @@ static void tmp105_register_nodes(void) qos_add_test("limits", "lm75b", test_lm75b_limits, NULL); qos_add_test("shutdown-clears-alert", "lm75b", test_lm75b_shutdown_clears_alert, NULL); + + /* TMP1075: 16-bit Config register and a Device ID register. */ + QOSGraphEdgeOptions tmp1075_opts = { + .extra_device_opts = "id=" TMP1075_TEST_ID ",address=0x4d" + }; + add_qi2c_address(&tmp1075_opts, &(QI2CAddress) { 0x4d }); + + qos_node_create_driver("tmp1075", i2c_device_create); + qos_node_consumes("tmp1075", "i2c-bus", &tmp1075_opts); + + qos_add_test("device-id", "tmp1075", test_tmp1075_device_id, NULL); } libqos_init(tmp105_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 18/22] tests/qtest: tmp105: cover the TMP1075 device ID and reset defaults @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Add a TMP1075 node and check its power-on Config, limit and Device ID register values, including that the Device ID register is read-only. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp105-test.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/qtest/tmp105-test.c b/tests/qtest/tmp105-test.c index 504f6b7202..426c4f9ae7 100644 --- a/tests/qtest/tmp105-test.c +++ b/tests/qtest/tmp105-test.c @@ -28,6 +28,8 @@ #define LM75B_TEST_ID "lm75b-test" #define LM75B_TEST_PATH "/machine/peripheral/" LM75B_TEST_ID +#define TMP1075_TEST_ID "tmp1075-test" + #define TMP105_CONFIG_POL (1 << 2) /* ALERT active-high when set */ #define TMP105_CONFIG_TM (1 << 1) /* interrupt (thermostat) mode */ #define TMP105_CONFIG_FQ_1 (0 << 3) /* fault queue: 1 consecutive fault */ @@ -419,6 +421,26 @@ static void test_lm75b_shutdown_clears_alert(void *obj, void *data, g_assert_false(get_irq(0)); } +/* + * The TMP1075 answers a read-only Device ID register and powers up with the + * modern reset defaults. + */ +static void test_tmp1075_device_id(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = (QI2CDevice *)obj; + + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x00ff); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_LOW), ==, 0x4b00); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_T_HIGH), ==, 0x5000); + + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_DIE_ID), ==, + TMP1075_DEVICE_ID); + i2c_set16(i2cdev, TMP105_REG_DIE_ID, 0x1234); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_DIE_ID), ==, + TMP1075_DEVICE_ID); +} + static void tmp105_register_nodes(void) { QOSGraphEdgeOptions opts = { @@ -475,5 +497,16 @@ static void tmp105_register_nodes(void) qos_add_test("limits", "lm75b", test_lm75b_limits, NULL); qos_add_test("shutdown-clears-alert", "lm75b", test_lm75b_shutdown_clears_alert, NULL); + + /* TMP1075: 16-bit Config register and a Device ID register. */ + QOSGraphEdgeOptions tmp1075_opts = { + .extra_device_opts = "id=" TMP1075_TEST_ID ",address=0x4d" + }; + add_qi2c_address(&tmp1075_opts, &(QI2CAddress) { 0x4d }); + + qos_node_create_driver("tmp1075", i2c_device_create); + qos_node_consumes("tmp1075", "i2c-bus", &tmp1075_opts); + + qos_add_test("device-id", "tmp1075", test_tmp1075_device_id, NULL); } libqos_init(tmp105_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 19/22] tests/qtest: tmp105: cover the TMP1075 config register width 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Nothing pinned the 16-bit Config register: neither its single-byte compatibility nor the low byte, which drives nothing but keeps what it is given. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp105-test.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/qtest/tmp105-test.c b/tests/qtest/tmp105-test.c index 426c4f9ae7..b21deb1128 100644 --- a/tests/qtest/tmp105-test.c +++ b/tests/qtest/tmp105-test.c @@ -441,6 +441,33 @@ static void test_tmp1075_device_id(void *obj, void *data, TMP1075_DEVICE_ID); } +/* + * The Config register is 16 bits wide but stays compatible with 8-bit access: + * the control bits are the upper byte, the lower byte drives nothing. + */ +static void test_tmp1075_config_width(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = (QI2CDevice *)obj; + + /* A single-byte write reaches the control byte and leaves the rest. */ + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x60); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x60ff); + + /* A word write keeps both bytes. */ + i2c_set16(i2cdev, TMP105_REG_CONFIG, 0x6200); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x6200); + + /* The low byte survives a single-byte write to the control byte. */ + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x6000); + + /* The one-shot bit always reads back as zero. */ + i2c_set8(i2cdev, TMP105_REG_CONFIG, TMP105_CONFIG_OS); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x00); +} + static void tmp105_register_nodes(void) { QOSGraphEdgeOptions opts = { @@ -508,5 +535,6 @@ static void tmp105_register_nodes(void) qos_node_consumes("tmp1075", "i2c-bus", &tmp1075_opts); qos_add_test("device-id", "tmp1075", test_tmp1075_device_id, NULL); + qos_add_test("config-width", "tmp1075", test_tmp1075_config_width, NULL); } libqos_init(tmp105_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 19/22] tests/qtest: tmp105: cover the TMP1075 config register width @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Nothing pinned the 16-bit Config register: neither its single-byte compatibility nor the low byte, which drives nothing but keeps what it is given. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp105-test.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/qtest/tmp105-test.c b/tests/qtest/tmp105-test.c index 426c4f9ae7..b21deb1128 100644 --- a/tests/qtest/tmp105-test.c +++ b/tests/qtest/tmp105-test.c @@ -441,6 +441,33 @@ static void test_tmp1075_device_id(void *obj, void *data, TMP1075_DEVICE_ID); } +/* + * The Config register is 16 bits wide but stays compatible with 8-bit access: + * the control bits are the upper byte, the lower byte drives nothing. + */ +static void test_tmp1075_config_width(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = (QI2CDevice *)obj; + + /* A single-byte write reaches the control byte and leaves the rest. */ + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x60); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x60ff); + + /* A word write keeps both bytes. */ + i2c_set16(i2cdev, TMP105_REG_CONFIG, 0x6200); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x6200); + + /* The low byte survives a single-byte write to the control byte. */ + i2c_set8(i2cdev, TMP105_REG_CONFIG, 0x60); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x6000); + + /* The one-shot bit always reads back as zero. */ + i2c_set8(i2cdev, TMP105_REG_CONFIG, TMP105_CONFIG_OS); + g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x00); +} + static void tmp105_register_nodes(void) { QOSGraphEdgeOptions opts = { @@ -508,5 +535,6 @@ static void tmp105_register_nodes(void) qos_node_consumes("tmp1075", "i2c-bus", &tmp1075_opts); qos_add_test("device-id", "tmp1075", test_tmp1075_device_id, NULL); + qos_add_test("config-width", "tmp1075", test_tmp1075_config_width, NULL); } libqos_init(tmp105_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 20/22] tests/qtest: tmp105: cover the Config low byte across a migration 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The byte rides in an optional subsection, so a dropped field or a wrong needed() gate would have gone unnoticed. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp105-test.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/qtest/tmp105-test.c b/tests/qtest/tmp105-test.c index b21deb1128..1bb7dcc265 100644 --- a/tests/qtest/tmp105-test.c +++ b/tests/qtest/tmp105-test.c @@ -9,6 +9,9 @@ #include "qemu/osdep.h" +#include <glib/gstdio.h> + +#include "libqtest.h" #include "libqtest-single.h" #include "libqos/qgraph.h" #include "libqos/i2c.h" @@ -468,6 +471,52 @@ static void test_tmp1075_config_width(void *obj, void *data, g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x00); } +/* The low byte of the Config register rides in an optional subsection. */ +static void test_tmp1075_migration(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = (QI2CDevice *)obj; + g_autofree char *tmpfs = NULL; + g_autofree char *mig_path = NULL; + g_autofree char *uri = NULL; + GString *dest_cmdline; + GError *err = NULL; + QTestState *from, *to; + QDict *rsp; + + tmpfs = g_dir_make_tmp("tmp1075-test-XXXXXX", &err); + g_assert_no_error(err); + g_assert(tmpfs); + + mig_path = g_strdup_printf("%s/socket.mig", tmpfs); + uri = g_strdup_printf("unix:%s", mig_path); + + /* A low byte away from its reset value, so the subsection is emitted. */ + i2c_set16(i2cdev, TMP105_REG_CONFIG, 0x605a); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x605a); + + dest_cmdline = g_string_new(qos_get_current_command_line()); + g_string_append_printf(dest_cmdline, " -incoming %s", uri); + to = qtest_init(dest_cmdline->str); + + rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri); + g_assert(qdict_haskey(rsp, "return")); + qobject_unref(rsp); + + qmp_eventwait("STOP"); + qtest_qmp_eventwait(to, "RESUME"); + + from = i2cdev->bus->qts; + i2cdev->bus->qts = to; + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x605a); + i2cdev->bus->qts = from; + + qtest_quit(to); + g_unlink(mig_path); + g_rmdir(tmpfs); + g_string_free(dest_cmdline, true); +} + static void tmp105_register_nodes(void) { QOSGraphEdgeOptions opts = { @@ -536,5 +585,6 @@ static void tmp105_register_nodes(void) qos_add_test("device-id", "tmp1075", test_tmp1075_device_id, NULL); qos_add_test("config-width", "tmp1075", test_tmp1075_config_width, NULL); + qos_add_test("migration", "tmp1075", test_tmp1075_migration, NULL); } libqos_init(tmp105_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 20/22] tests/qtest: tmp105: cover the Config low byte across a migration @ 2026-10-15 11:57 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot The byte rides in an optional subsection, so a dropped field or a wrong needed() gate would have gone unnoticed. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- tests/qtest/tmp105-test.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/qtest/tmp105-test.c b/tests/qtest/tmp105-test.c index b21deb1128..1bb7dcc265 100644 --- a/tests/qtest/tmp105-test.c +++ b/tests/qtest/tmp105-test.c @@ -9,6 +9,9 @@ #include "qemu/osdep.h" +#include <glib/gstdio.h> + +#include "libqtest.h" #include "libqtest-single.h" #include "libqos/qgraph.h" #include "libqos/i2c.h" @@ -468,6 +471,52 @@ static void test_tmp1075_config_width(void *obj, void *data, g_assert_cmphex(i2c_get8(i2cdev, TMP105_REG_CONFIG), ==, 0x00); } +/* The low byte of the Config register rides in an optional subsection. */ +static void test_tmp1075_migration(void *obj, void *data, + QGuestAllocator *alloc) +{ + QI2CDevice *i2cdev = (QI2CDevice *)obj; + g_autofree char *tmpfs = NULL; + g_autofree char *mig_path = NULL; + g_autofree char *uri = NULL; + GString *dest_cmdline; + GError *err = NULL; + QTestState *from, *to; + QDict *rsp; + + tmpfs = g_dir_make_tmp("tmp1075-test-XXXXXX", &err); + g_assert_no_error(err); + g_assert(tmpfs); + + mig_path = g_strdup_printf("%s/socket.mig", tmpfs); + uri = g_strdup_printf("unix:%s", mig_path); + + /* A low byte away from its reset value, so the subsection is emitted. */ + i2c_set16(i2cdev, TMP105_REG_CONFIG, 0x605a); + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x605a); + + dest_cmdline = g_string_new(qos_get_current_command_line()); + g_string_append_printf(dest_cmdline, " -incoming %s", uri); + to = qtest_init(dest_cmdline->str); + + rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri); + g_assert(qdict_haskey(rsp, "return")); + qobject_unref(rsp); + + qmp_eventwait("STOP"); + qtest_qmp_eventwait(to, "RESUME"); + + from = i2cdev->bus->qts; + i2cdev->bus->qts = to; + g_assert_cmphex(i2c_get16(i2cdev, TMP105_REG_CONFIG), ==, 0x605a); + i2cdev->bus->qts = from; + + qtest_quit(to); + g_unlink(mig_path); + g_rmdir(tmpfs); + g_string_free(dest_cmdline, true); +} + static void tmp105_register_nodes(void) { QOSGraphEdgeOptions opts = { @@ -536,5 +585,6 @@ static void tmp105_register_nodes(void) qos_add_test("device-id", "tmp1075", test_tmp1075_device_id, NULL); qos_add_test("config-width", "tmp1075", test_tmp1075_config_width, NULL); + qos_add_test("migration", "tmp1075", test_tmp1075_migration, NULL); } libqos_init(tmp105_register_nodes); -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 21/22] hw/arm: clemente: add Facebook Clemente BMC machine 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Add the 'clemente-bmc' machine type, an AST2600-based BMC, modelled from its device tree (aspeed-bmc-facebook-clemente.dts). The board uses TMP75, TMP1075, LM75B and TMP421 temperature sensors, PCA9535, PCA9554 and PCA9555 IO expanders, PCA9546 and PCA9548 I2C muxes, AT24C EEPROMs and a DS1338 RTC. Every device the Clemente device tree describes and QEMU already models is instantiated. The remaining ones (LM5066I power monitors, MAX31790 fan controllers, MAX1363 ADCs, RAA228004 voltage regulators, the SLB9670 SPI TPM, SSIF-BMC and MCTP) have no QEMU model and are left documented as comments. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- docs/system/arm/aspeed.rst | 1 + hw/arm/aspeed_ast2600_clemente.c | 232 +++++++++++++++++++++++++++++++++++++++ hw/arm/meson.build | 1 + 3 files changed, 234 insertions(+) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index bbd3d9cdf4..db0035189b 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -34,6 +34,7 @@ AST2600 SoC based machines : - ``bletchley-bmc`` Facebook Bletchley BMC - ``fby35-bmc`` Facebook fby35 BMC - ``catalina-bmc`` Facebook Catalina BMC +- ``clemente-bmc`` Facebook Clemente BMC - ``sanmiguel-bmc`` Facebook SanMiguel BMC - ``anacapa-bmc`` Facebook Anacapa BMC - ``minerva-bmc`` Facebook Minerva BMC diff --git a/hw/arm/aspeed_ast2600_clemente.c b/hw/arm/aspeed_ast2600_clemente.c new file mode 100644 index 0000000000..bf5a13bc49 --- /dev/null +++ b/hw/arm/aspeed_ast2600_clemente.c @@ -0,0 +1,232 @@ +/* + * Facebook Clemente BMC + * + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Current limitations: the following devices from the device tree have no + * QEMU model and are therefore not emulated: + * - ti,lm5066i power monitors + * - maxim,max31790 fan controllers + * - maxim,max1363 ADCs (leak sensors) + * - renesas,raa228004 voltage regulators + * - infineon,slb9670 TPM (SPI) + * - ssif-bmc SSIF interface + * - mctp-i2c-controller MCTP endpoints + */ + +#include "qemu/osdep.h" +#include "hw/arm/aspeed.h" +#include "hw/arm/aspeed_soc.h" +#include "hw/i2c/i2c_mux_pca954x.h" +#include "hw/gpio/pca9552.h" +#include "hw/gpio/pca9554.h" +#include "hw/nvram/eeprom_at24c.h" +#include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" + +/* Clemente hardware values. */ +#define CLEMENTE_BMC_HW_STRAP1 0x00002002 +#define CLEMENTE_BMC_HW_STRAP2 0x00000800 +#define CLEMENTE_BMC_RAM_SIZE (2 * GiB) + +/* + * E1.S backplane hanging off a PCA9546 channel: an FRU EEPROM plus a + * second PCA9546 fronting per-drive NVMe SSD FRU EEPROMs. + */ +static void clemente_e1s_backplane_init(I2CBus *bus) +{ + /* eeprom@56 - atmel,24c128 */ + at24c_eeprom_init(bus, 0x56, 16 * KiB); + + /* i2c-mux@74 - PCA9546 */ + I2CSlave *mux = i2c_slave_create_simple(bus, TYPE_PCA9546, 0x74); + /* eeprom@53 - atmel,24c02, channels 0 and 2 */ + at24c_eeprom_init(pca954x_i2c_get_bus(mux, 0), 0x53, 256); + at24c_eeprom_init(pca954x_i2c_get_bus(mux, 2), 0x53, 256); +} + +/* + * IO Mezzanine hanging off a PCA9546 channel: an I/O expander plus the + * mezzanine and OSFP FRU EEPROMs. + */ +static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr) +{ + /* gpio@20/21 - nxp,pca9535 */ + i2c_slave_create_simple(bus, TYPE_PCA9535, exp_addr); + /* eeprom@50 - atmel,24c64 (mezzanine FRU) */ + at24c_eeprom_init(bus, 0x50, 8 * KiB); + /* eeprom@52 - atmel,24c128 (OSFP FRU) */ + at24c_eeprom_init(bus, 0x52, 16 * KiB); +} + +static void clemente_bmc_i2c_init(AspeedMachineState *bmc) +{ + /* Reference: aspeed-bmc-facebook-clemente.dts */ + + AspeedSoCState *soc = bmc->soc; + I2CBus *i2c[16] = {}; + I2CSlave *i2c_mux; + + for (unsigned idx = 0; idx < ARRAY_SIZE(i2c); idx++) { + i2c[idx] = aspeed_i2c_get_bus(&soc->i2c, idx); + } + + /* &i2c0 */ + /* i2c-mux@71 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71); + /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + + /* i2c-mux@72 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72); + /* channel 1 - IO Mezz 0 (io_expander7 @20) */ + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20); + + /* i2c-mux@73 (PCA9546) - channels empty */ + i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73); + + /* i2c-mux@75 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75); + /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + + /* i2c-mux@76 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76); + /* channel 1 - IO Mezz 1 (io_expander8 @21) */ + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21); + + /* i2c-mux@77 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77); + /* channel 1 - boot drive FRU eeprom@53 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256); + + /* &i2c1 */ + /* power-monitor@12/14 - ti,lm5066i (no model) */ + /* fan-controller@20/23/2c/2f - maxim,max31790 (no model) */ + /* adc@34/35 - maxim,max1363 (no model) */ + /* temperature-sensor@4e - ti,tmp1075 */ + i2c_slave_create_simple(i2c[1], TYPE_TMP1075, 0x4e); + /* eeprom@50 - atmel,24c02 (PDB FRU) */ + at24c_eeprom_init(i2c[1], 0x50, 256); + /* vrm@60/61 - renesas,raa228004 (no model) */ + /* i2c-mux@70 (PCA9548) - interposer */ + i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70); + /* channel 5 - interposer */ + /* temperature-sensor@4f - ti,tmp75 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f); + /* eeprom@54 - atmel,24c64 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB); + /* channel 6 - io_expander5 gpio@27 - nxp,pca9554 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), + TYPE_PCA9554, 0x27); + /* channel 7 - FIO */ + /* temperature-sensor@4b - ti,tmp75 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b); + /* eeprom@51 - atmel,24c64 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, 8 * KiB); + + /* &i2c2 */ + /* gpio@20/21/27 - nxp,pca9555 */ + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x20); + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x21); + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x27); + /* eeprom@50/51 - atmel,24c64 (module aux) */ + at24c_eeprom_init(i2c[2], 0x50, 8 * KiB); + at24c_eeprom_init(i2c[2], 0x51, 8 * KiB); + + /* &i2c3 - empty */ + /* &i2c4 - empty */ + /* &i2c5 - empty */ + + /* &i2c6 */ + /* gpio@21 - nxp,pca9555 */ + i2c_slave_create_simple(i2c[6], TYPE_PCA9555, 0x21); + /* rtc@6f - nuvoton,nct3018y */ + i2c_slave_create_simple(i2c[6], TYPE_DS1338, 0x6f); + + /* &i2c7 - empty */ + /* &i2c8 - empty */ + + /* &i2c9 */ + /* temperature-sensor@4b - national,lm75b */ + i2c_slave_create_simple(i2c[9], TYPE_LM75B, 0x4b); + /* gpio@4f - nxp,pca9555 */ + i2c_slave_create_simple(i2c[9], TYPE_PCA9555, 0x4f); + /* eeprom@50 - atmel,24c64 (SCM FRU) */ + at24c_eeprom_init(i2c[9], 0x50, 8 * KiB); + /* eeprom@56 - atmel,24c64 (BSM FRU) */ + at24c_eeprom_init(i2c[9], 0x56, 8 * KiB); + + /* &i2c10 */ + /* mctp@10 - mctp-i2c-controller (no model) */ + /* temperature-sensor@1f - ti,tmp421 (OCP NIC0) */ + i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f); + /* eeprom@50 - atmel,24c64 (OCP NIC0 FRU) */ + at24c_eeprom_init(i2c[10], 0x50, 8 * KiB); + + /* &i2c11 */ + /* ssif-bmc@10 - ssif-bmc (no model) */ + + /* &i2c12 */ + /* eeprom@50 - atmel,24c64 (HPM 1 FRU) */ + at24c_eeprom_init(i2c[12], 0x50, 8 * KiB); + /* eeprom@54/55 - atmel,24c02 (CBC 2/3 FRU) */ + at24c_eeprom_init(i2c[12], 0x54, 256); + at24c_eeprom_init(i2c[12], 0x55, 256); + + /* &i2c13 */ + /* eeprom@50 - atmel,24c64 (HPM FRU) */ + at24c_eeprom_init(i2c[13], 0x50, 8 * KiB); + /* eeprom@54/55 - atmel,24c02 (CBC 0/1 FRU) */ + at24c_eeprom_init(i2c[13], 0x54, 256); + at24c_eeprom_init(i2c[13], 0x55, 256); + /* eeprom@57 - atmel,24c02 (HMC FRU) */ + at24c_eeprom_init(i2c[13], 0x57, 256); + + /* &i2c14 */ + /* gpio@10/11/12/13/14 - nxp,pca9555 (PDB CPLD) */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x10); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x11); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x12); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x13); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x14); + + /* &i2c15 */ + /* mctp@10 - mctp-i2c-controller (no model) */ + /* temperature-sensor@1f - ti,tmp421 (OCP NIC1) */ + i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f); + /* eeprom@52 - atmel,24c64 (OCP NIC1 FRU) */ + at24c_eeprom_init(i2c[15], 0x52, 8 * KiB); +} + +static void aspeed_machine_clemente_class_init(ObjectClass *oc, + const void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Facebook Clemente BMC (Cortex-A7)"; + amc->soc_name = "ast2600-a3"; + amc->hw_strap1 = CLEMENTE_BMC_HW_STRAP1; + amc->hw_strap2 = CLEMENTE_BMC_HW_STRAP2; + amc->fmc_model = "mx66l1g45g"; + amc->spi_model = NULL; + amc->num_cs = 2; + amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON; + amc->i2c_init = clemente_bmc_i2c_init; + mc->default_ram_size = CLEMENTE_BMC_RAM_SIZE; + aspeed_machine_class_init_cpus_defaults(mc); +} + +static const TypeInfo aspeed_ast2600_clemente_types[] = { + { + .name = MACHINE_TYPE_NAME("clemente-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_clemente_class_init, + } +}; + +DEFINE_TYPES(aspeed_ast2600_clemente_types) diff --git a/hw/arm/meson.build b/hw/arm/meson.build index a9e8270b85..4189de2aaa 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -59,6 +59,7 @@ arm_common_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_ast2600_anacapa.c', 'aspeed_ast2600_bletchley.c', 'aspeed_ast2600_catalina.c', + 'aspeed_ast2600_clemente.c', 'aspeed_ast2600_evb.c', 'aspeed_ast2600_fby35.c', 'aspeed_ast2600_fuji.c', -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 21/22] hw/arm: clemente: add Facebook Clemente BMC machine @ 2026-10-15 11:57 ` Emmanuel Blot via qemu development 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:57 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Add the 'clemente-bmc' machine type, an AST2600-based BMC, modelled from its device tree (aspeed-bmc-facebook-clemente.dts). The board uses TMP75, TMP1075, LM75B and TMP421 temperature sensors, PCA9535, PCA9554 and PCA9555 IO expanders, PCA9546 and PCA9548 I2C muxes, AT24C EEPROMs and a DS1338 RTC. Every device the Clemente device tree describes and QEMU already models is instantiated. The remaining ones (LM5066I power monitors, MAX31790 fan controllers, MAX1363 ADCs, RAA228004 voltage regulators, the SLB9670 SPI TPM, SSIF-BMC and MCTP) have no QEMU model and are left documented as comments. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- docs/system/arm/aspeed.rst | 1 + hw/arm/aspeed_ast2600_clemente.c | 232 +++++++++++++++++++++++++++++++++++++++ hw/arm/meson.build | 1 + 3 files changed, 234 insertions(+) diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index bbd3d9cdf4..db0035189b 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -34,6 +34,7 @@ AST2600 SoC based machines : - ``bletchley-bmc`` Facebook Bletchley BMC - ``fby35-bmc`` Facebook fby35 BMC - ``catalina-bmc`` Facebook Catalina BMC +- ``clemente-bmc`` Facebook Clemente BMC - ``sanmiguel-bmc`` Facebook SanMiguel BMC - ``anacapa-bmc`` Facebook Anacapa BMC - ``minerva-bmc`` Facebook Minerva BMC diff --git a/hw/arm/aspeed_ast2600_clemente.c b/hw/arm/aspeed_ast2600_clemente.c new file mode 100644 index 0000000000..bf5a13bc49 --- /dev/null +++ b/hw/arm/aspeed_ast2600_clemente.c @@ -0,0 +1,232 @@ +/* + * Facebook Clemente BMC + * + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Current limitations: the following devices from the device tree have no + * QEMU model and are therefore not emulated: + * - ti,lm5066i power monitors + * - maxim,max31790 fan controllers + * - maxim,max1363 ADCs (leak sensors) + * - renesas,raa228004 voltage regulators + * - infineon,slb9670 TPM (SPI) + * - ssif-bmc SSIF interface + * - mctp-i2c-controller MCTP endpoints + */ + +#include "qemu/osdep.h" +#include "hw/arm/aspeed.h" +#include "hw/arm/aspeed_soc.h" +#include "hw/i2c/i2c_mux_pca954x.h" +#include "hw/gpio/pca9552.h" +#include "hw/gpio/pca9554.h" +#include "hw/nvram/eeprom_at24c.h" +#include "hw/rtc/ds1338.h" +#include "hw/sensor/tmp105.h" +#include "hw/sensor/tmp421.h" + +/* Clemente hardware values. */ +#define CLEMENTE_BMC_HW_STRAP1 0x00002002 +#define CLEMENTE_BMC_HW_STRAP2 0x00000800 +#define CLEMENTE_BMC_RAM_SIZE (2 * GiB) + +/* + * E1.S backplane hanging off a PCA9546 channel: an FRU EEPROM plus a + * second PCA9546 fronting per-drive NVMe SSD FRU EEPROMs. + */ +static void clemente_e1s_backplane_init(I2CBus *bus) +{ + /* eeprom@56 - atmel,24c128 */ + at24c_eeprom_init(bus, 0x56, 16 * KiB); + + /* i2c-mux@74 - PCA9546 */ + I2CSlave *mux = i2c_slave_create_simple(bus, TYPE_PCA9546, 0x74); + /* eeprom@53 - atmel,24c02, channels 0 and 2 */ + at24c_eeprom_init(pca954x_i2c_get_bus(mux, 0), 0x53, 256); + at24c_eeprom_init(pca954x_i2c_get_bus(mux, 2), 0x53, 256); +} + +/* + * IO Mezzanine hanging off a PCA9546 channel: an I/O expander plus the + * mezzanine and OSFP FRU EEPROMs. + */ +static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr) +{ + /* gpio@20/21 - nxp,pca9535 */ + i2c_slave_create_simple(bus, TYPE_PCA9535, exp_addr); + /* eeprom@50 - atmel,24c64 (mezzanine FRU) */ + at24c_eeprom_init(bus, 0x50, 8 * KiB); + /* eeprom@52 - atmel,24c128 (OSFP FRU) */ + at24c_eeprom_init(bus, 0x52, 16 * KiB); +} + +static void clemente_bmc_i2c_init(AspeedMachineState *bmc) +{ + /* Reference: aspeed-bmc-facebook-clemente.dts */ + + AspeedSoCState *soc = bmc->soc; + I2CBus *i2c[16] = {}; + I2CSlave *i2c_mux; + + for (unsigned idx = 0; idx < ARRAY_SIZE(i2c); idx++) { + i2c[idx] = aspeed_i2c_get_bus(&soc->i2c, idx); + } + + /* &i2c0 */ + /* i2c-mux@71 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71); + /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + + /* i2c-mux@72 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72); + /* channel 1 - IO Mezz 0 (io_expander7 @20) */ + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20); + + /* i2c-mux@73 (PCA9546) - channels empty */ + i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73); + + /* i2c-mux@75 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75); + /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + + /* i2c-mux@76 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76); + /* channel 1 - IO Mezz 1 (io_expander8 @21) */ + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21); + + /* i2c-mux@77 (PCA9546) */ + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77); + /* channel 1 - boot drive FRU eeprom@53 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256); + + /* &i2c1 */ + /* power-monitor@12/14 - ti,lm5066i (no model) */ + /* fan-controller@20/23/2c/2f - maxim,max31790 (no model) */ + /* adc@34/35 - maxim,max1363 (no model) */ + /* temperature-sensor@4e - ti,tmp1075 */ + i2c_slave_create_simple(i2c[1], TYPE_TMP1075, 0x4e); + /* eeprom@50 - atmel,24c02 (PDB FRU) */ + at24c_eeprom_init(i2c[1], 0x50, 256); + /* vrm@60/61 - renesas,raa228004 (no model) */ + /* i2c-mux@70 (PCA9548) - interposer */ + i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70); + /* channel 5 - interposer */ + /* temperature-sensor@4f - ti,tmp75 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f); + /* eeprom@54 - atmel,24c64 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB); + /* channel 6 - io_expander5 gpio@27 - nxp,pca9554 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), + TYPE_PCA9554, 0x27); + /* channel 7 - FIO */ + /* temperature-sensor@4b - ti,tmp75 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b); + /* eeprom@51 - atmel,24c64 */ + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, 8 * KiB); + + /* &i2c2 */ + /* gpio@20/21/27 - nxp,pca9555 */ + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x20); + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x21); + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x27); + /* eeprom@50/51 - atmel,24c64 (module aux) */ + at24c_eeprom_init(i2c[2], 0x50, 8 * KiB); + at24c_eeprom_init(i2c[2], 0x51, 8 * KiB); + + /* &i2c3 - empty */ + /* &i2c4 - empty */ + /* &i2c5 - empty */ + + /* &i2c6 */ + /* gpio@21 - nxp,pca9555 */ + i2c_slave_create_simple(i2c[6], TYPE_PCA9555, 0x21); + /* rtc@6f - nuvoton,nct3018y */ + i2c_slave_create_simple(i2c[6], TYPE_DS1338, 0x6f); + + /* &i2c7 - empty */ + /* &i2c8 - empty */ + + /* &i2c9 */ + /* temperature-sensor@4b - national,lm75b */ + i2c_slave_create_simple(i2c[9], TYPE_LM75B, 0x4b); + /* gpio@4f - nxp,pca9555 */ + i2c_slave_create_simple(i2c[9], TYPE_PCA9555, 0x4f); + /* eeprom@50 - atmel,24c64 (SCM FRU) */ + at24c_eeprom_init(i2c[9], 0x50, 8 * KiB); + /* eeprom@56 - atmel,24c64 (BSM FRU) */ + at24c_eeprom_init(i2c[9], 0x56, 8 * KiB); + + /* &i2c10 */ + /* mctp@10 - mctp-i2c-controller (no model) */ + /* temperature-sensor@1f - ti,tmp421 (OCP NIC0) */ + i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f); + /* eeprom@50 - atmel,24c64 (OCP NIC0 FRU) */ + at24c_eeprom_init(i2c[10], 0x50, 8 * KiB); + + /* &i2c11 */ + /* ssif-bmc@10 - ssif-bmc (no model) */ + + /* &i2c12 */ + /* eeprom@50 - atmel,24c64 (HPM 1 FRU) */ + at24c_eeprom_init(i2c[12], 0x50, 8 * KiB); + /* eeprom@54/55 - atmel,24c02 (CBC 2/3 FRU) */ + at24c_eeprom_init(i2c[12], 0x54, 256); + at24c_eeprom_init(i2c[12], 0x55, 256); + + /* &i2c13 */ + /* eeprom@50 - atmel,24c64 (HPM FRU) */ + at24c_eeprom_init(i2c[13], 0x50, 8 * KiB); + /* eeprom@54/55 - atmel,24c02 (CBC 0/1 FRU) */ + at24c_eeprom_init(i2c[13], 0x54, 256); + at24c_eeprom_init(i2c[13], 0x55, 256); + /* eeprom@57 - atmel,24c02 (HMC FRU) */ + at24c_eeprom_init(i2c[13], 0x57, 256); + + /* &i2c14 */ + /* gpio@10/11/12/13/14 - nxp,pca9555 (PDB CPLD) */ + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x10); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x11); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x12); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x13); + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x14); + + /* &i2c15 */ + /* mctp@10 - mctp-i2c-controller (no model) */ + /* temperature-sensor@1f - ti,tmp421 (OCP NIC1) */ + i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f); + /* eeprom@52 - atmel,24c64 (OCP NIC1 FRU) */ + at24c_eeprom_init(i2c[15], 0x52, 8 * KiB); +} + +static void aspeed_machine_clemente_class_init(ObjectClass *oc, + const void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Facebook Clemente BMC (Cortex-A7)"; + amc->soc_name = "ast2600-a3"; + amc->hw_strap1 = CLEMENTE_BMC_HW_STRAP1; + amc->hw_strap2 = CLEMENTE_BMC_HW_STRAP2; + amc->fmc_model = "mx66l1g45g"; + amc->spi_model = NULL; + amc->num_cs = 2; + amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON; + amc->i2c_init = clemente_bmc_i2c_init; + mc->default_ram_size = CLEMENTE_BMC_RAM_SIZE; + aspeed_machine_class_init_cpus_defaults(mc); +} + +static const TypeInfo aspeed_ast2600_clemente_types[] = { + { + .name = MACHINE_TYPE_NAME("clemente-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_clemente_class_init, + } +}; + +DEFINE_TYPES(aspeed_ast2600_clemente_types) diff --git a/hw/arm/meson.build b/hw/arm/meson.build index a9e8270b85..4189de2aaa 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -59,6 +59,7 @@ arm_common_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_ast2600_anacapa.c', 'aspeed_ast2600_bletchley.c', 'aspeed_ast2600_catalina.c', + 'aspeed_ast2600_clemente.c', 'aspeed_ast2600_evb.c', 'aspeed_ast2600_fby35.c', 'aspeed_ast2600_fuji.c', -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* Re: [PATCH 21/22] hw/arm: clemente: add Facebook Clemente BMC machine 2026-10-15 11:57 ` Emmanuel Blot via qemu development (?) @ 2026-10-16 9:34 ` Jamin Lin -1 siblings, 0 replies; 49+ messages in thread From: Jamin Lin @ 2026-10-16 9:34 UTC (permalink / raw) To: Emmanuel Blot Cc: qemu-devel, Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier On Thu, Oct 15, 2026 at 01:57:59PM +0200, Emmanuel Blot via qemu development wrote: > Add the 'clemente-bmc' machine type, an AST2600-based BMC, modelled > from its device tree (aspeed-bmc-facebook-clemente.dts). > > The board uses TMP75, TMP1075, LM75B and TMP421 temperature sensors, > PCA9535, PCA9554 and PCA9555 IO expanders, PCA9546 and PCA9548 I2C > muxes, AT24C EEPROMs and a DS1338 RTC. > > Every device the Clemente device tree describes and QEMU already models > is instantiated. The remaining ones (LM5066I power monitors, MAX31790 > fan controllers, MAX1363 ADCs, RAA228004 voltage regulators, the > SLB9670 SPI TPM, SSIF-BMC and MCTP) have no QEMU model and are left > documented as comments. > > Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> > --- > docs/system/arm/aspeed.rst | 1 + > hw/arm/aspeed_ast2600_clemente.c | 232 +++++++++++++++++++++++++++++++++++++++ > hw/arm/meson.build | 1 + > 3 files changed, 234 insertions(+) > > diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst > index bbd3d9cdf4..db0035189b 100644 > --- a/docs/system/arm/aspeed.rst > +++ b/docs/system/arm/aspeed.rst > @@ -34,6 +34,7 @@ AST2600 SoC based machines : > - ``bletchley-bmc`` Facebook Bletchley BMC > - ``fby35-bmc`` Facebook fby35 BMC > - ``catalina-bmc`` Facebook Catalina BMC > +- ``clemente-bmc`` Facebook Clemente BMC > - ``sanmiguel-bmc`` Facebook SanMiguel BMC > - ``anacapa-bmc`` Facebook Anacapa BMC > - ``minerva-bmc`` Facebook Minerva BMC > diff --git a/hw/arm/aspeed_ast2600_clemente.c b/hw/arm/aspeed_ast2600_clemente.c > new file mode 100644 > index 0000000000..bf5a13bc49 > --- /dev/null > +++ b/hw/arm/aspeed_ast2600_clemente.c > @@ -0,0 +1,232 @@ > +/* > + * Facebook Clemente BMC > + * > + * Copyright (c) 2026 Meta Platforms, Inc. and affiliates. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * Current limitations: the following devices from the device tree have no > + * QEMU model and are therefore not emulated: > + * - ti,lm5066i power monitors > + * - maxim,max31790 fan controllers > + * - maxim,max1363 ADCs (leak sensors) > + * - renesas,raa228004 voltage regulators > + * - infineon,slb9670 TPM (SPI) > + * - ssif-bmc SSIF interface > + * - mctp-i2c-controller MCTP endpoints > + */ > + > +#include "qemu/osdep.h" > +#include "hw/arm/aspeed.h" > +#include "hw/arm/aspeed_soc.h" > +#include "hw/i2c/i2c_mux_pca954x.h" > +#include "hw/gpio/pca9552.h" > +#include "hw/gpio/pca9554.h" > +#include "hw/nvram/eeprom_at24c.h" > +#include "hw/rtc/ds1338.h" > +#include "hw/sensor/tmp105.h" > +#include "hw/sensor/tmp421.h" > + > +/* Clemente hardware values. */ > +#define CLEMENTE_BMC_HW_STRAP1 0x00002002 > +#define CLEMENTE_BMC_HW_STRAP2 0x00000800 > +#define CLEMENTE_BMC_RAM_SIZE (2 * GiB) > + > +/* > + * E1.S backplane hanging off a PCA9546 channel: an FRU EEPROM plus a > + * second PCA9546 fronting per-drive NVMe SSD FRU EEPROMs. > + */ > +static void clemente_e1s_backplane_init(I2CBus *bus) > +{ > + /* eeprom@56 - atmel,24c128 */ > + at24c_eeprom_init(bus, 0x56, 16 * KiB); > + > + /* i2c-mux@74 - PCA9546 */ > + I2CSlave *mux = i2c_slave_create_simple(bus, TYPE_PCA9546, 0x74); > + /* eeprom@53 - atmel,24c02, channels 0 and 2 */ > + at24c_eeprom_init(pca954x_i2c_get_bus(mux, 0), 0x53, 256); > + at24c_eeprom_init(pca954x_i2c_get_bus(mux, 2), 0x53, 256); > +} > + > +/* > + * IO Mezzanine hanging off a PCA9546 channel: an I/O expander plus the > + * mezzanine and OSFP FRU EEPROMs. > + */ > +static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr) > +{ > + /* gpio@20/21 - nxp,pca9535 */ > + i2c_slave_create_simple(bus, TYPE_PCA9535, exp_addr); > + /* eeprom@50 - atmel,24c64 (mezzanine FRU) */ > + at24c_eeprom_init(bus, 0x50, 8 * KiB); > + /* eeprom@52 - atmel,24c128 (OSFP FRU) */ > + at24c_eeprom_init(bus, 0x52, 16 * KiB); > +} > + > +static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > +{ > + /* Reference: aspeed-bmc-facebook-clemente.dts */ > + > + AspeedSoCState *soc = bmc->soc; > + I2CBus *i2c[16] = {}; > + I2CSlave *i2c_mux; > + > + for (unsigned idx = 0; idx < ARRAY_SIZE(i2c); idx++) { > + i2c[idx] = aspeed_i2c_get_bus(&soc->i2c, idx); > + } > + > + /* &i2c0 */ > + /* i2c-mux@71 (PCA9546) */ > + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71); > + /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ > + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); > + > + /* i2c-mux@72 (PCA9546) */ > + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72); > + /* channel 1 - IO Mezz 0 (io_expander7 @20) */ > + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20); > + > + /* i2c-mux@73 (PCA9546) - channels empty */ > + i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73); > + > + /* i2c-mux@75 (PCA9546) */ > + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75); > + /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ > + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); > + > + /* i2c-mux@76 (PCA9546) */ > + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76); > + /* channel 1 - IO Mezz 1 (io_expander8 @21) */ > + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21); > + > + /* i2c-mux@77 (PCA9546) */ > + i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77); > + /* channel 1 - boot drive FRU eeprom@53 */ > + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256); > + > + /* &i2c1 */ > + /* power-monitor@12/14 - ti,lm5066i (no model) */ > + /* fan-controller@20/23/2c/2f - maxim,max31790 (no model) */ > + /* adc@34/35 - maxim,max1363 (no model) */ > + /* temperature-sensor@4e - ti,tmp1075 */ > + i2c_slave_create_simple(i2c[1], TYPE_TMP1075, 0x4e); > + /* eeprom@50 - atmel,24c02 (PDB FRU) */ > + at24c_eeprom_init(i2c[1], 0x50, 256); > + /* vrm@60/61 - renesas,raa228004 (no model) */ > + /* i2c-mux@70 (PCA9548) - interposer */ > + i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70); > + /* channel 5 - interposer */ > + /* temperature-sensor@4f - ti,tmp75 */ > + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f); > + /* eeprom@54 - atmel,24c64 */ > + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB); > + /* channel 6 - io_expander5 gpio@27 - nxp,pca9554 */ > + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), > + TYPE_PCA9554, 0x27); > + /* channel 7 - FIO */ > + /* temperature-sensor@4b - ti,tmp75 */ > + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b); > + /* eeprom@51 - atmel,24c64 */ > + at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, 8 * KiB); > + > + /* &i2c2 */ > + /* gpio@20/21/27 - nxp,pca9555 */ > + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x20); > + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x21); > + i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x27); > + /* eeprom@50/51 - atmel,24c64 (module aux) */ > + at24c_eeprom_init(i2c[2], 0x50, 8 * KiB); > + at24c_eeprom_init(i2c[2], 0x51, 8 * KiB); > + > + /* &i2c3 - empty */ > + /* &i2c4 - empty */ > + /* &i2c5 - empty */ > + > + /* &i2c6 */ > + /* gpio@21 - nxp,pca9555 */ > + i2c_slave_create_simple(i2c[6], TYPE_PCA9555, 0x21); > + /* rtc@6f - nuvoton,nct3018y */ > + i2c_slave_create_simple(i2c[6], TYPE_DS1338, 0x6f); > + > + /* &i2c7 - empty */ > + /* &i2c8 - empty */ > + > + /* &i2c9 */ > + /* temperature-sensor@4b - national,lm75b */ > + i2c_slave_create_simple(i2c[9], TYPE_LM75B, 0x4b); > + /* gpio@4f - nxp,pca9555 */ > + i2c_slave_create_simple(i2c[9], TYPE_PCA9555, 0x4f); > + /* eeprom@50 - atmel,24c64 (SCM FRU) */ > + at24c_eeprom_init(i2c[9], 0x50, 8 * KiB); > + /* eeprom@56 - atmel,24c64 (BSM FRU) */ > + at24c_eeprom_init(i2c[9], 0x56, 8 * KiB); > + > + /* &i2c10 */ > + /* mctp@10 - mctp-i2c-controller (no model) */ > + /* temperature-sensor@1f - ti,tmp421 (OCP NIC0) */ > + i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f); > + /* eeprom@50 - atmel,24c64 (OCP NIC0 FRU) */ > + at24c_eeprom_init(i2c[10], 0x50, 8 * KiB); > + > + /* &i2c11 */ > + /* ssif-bmc@10 - ssif-bmc (no model) */ > + > + /* &i2c12 */ > + /* eeprom@50 - atmel,24c64 (HPM 1 FRU) */ > + at24c_eeprom_init(i2c[12], 0x50, 8 * KiB); > + /* eeprom@54/55 - atmel,24c02 (CBC 2/3 FRU) */ > + at24c_eeprom_init(i2c[12], 0x54, 256); > + at24c_eeprom_init(i2c[12], 0x55, 256); > + > + /* &i2c13 */ > + /* eeprom@50 - atmel,24c64 (HPM FRU) */ > + at24c_eeprom_init(i2c[13], 0x50, 8 * KiB); > + /* eeprom@54/55 - atmel,24c02 (CBC 0/1 FRU) */ > + at24c_eeprom_init(i2c[13], 0x54, 256); > + at24c_eeprom_init(i2c[13], 0x55, 256); > + /* eeprom@57 - atmel,24c02 (HMC FRU) */ > + at24c_eeprom_init(i2c[13], 0x57, 256); > + > + /* &i2c14 */ > + /* gpio@10/11/12/13/14 - nxp,pca9555 (PDB CPLD) */ > + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x10); > + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x11); > + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x12); > + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x13); > + i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x14); > + > + /* &i2c15 */ > + /* mctp@10 - mctp-i2c-controller (no model) */ > + /* temperature-sensor@1f - ti,tmp421 (OCP NIC1) */ > + i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f); > + /* eeprom@52 - atmel,24c64 (OCP NIC1 FRU) */ > + at24c_eeprom_init(i2c[15], 0x52, 8 * KiB); > +} > + > +static void aspeed_machine_clemente_class_init(ObjectClass *oc, > + const void *data) > +{ > + MachineClass *mc = MACHINE_CLASS(oc); > + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); > + > + mc->desc = "Facebook Clemente BMC (Cortex-A7)"; > + amc->soc_name = "ast2600-a3"; > + amc->hw_strap1 = CLEMENTE_BMC_HW_STRAP1; > + amc->hw_strap2 = CLEMENTE_BMC_HW_STRAP2; > + amc->fmc_model = "mx66l1g45g"; > + amc->spi_model = NULL; > + amc->num_cs = 2; > + amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON; > + amc->i2c_init = clemente_bmc_i2c_init; > + mc->default_ram_size = CLEMENTE_BMC_RAM_SIZE; > + aspeed_machine_class_init_cpus_defaults(mc); > +} > + > +static const TypeInfo aspeed_ast2600_clemente_types[] = { > + { > + .name = MACHINE_TYPE_NAME("clemente-bmc"), > + .parent = TYPE_ASPEED_MACHINE, > + .class_init = aspeed_machine_clemente_class_init, > + } > +}; > + > +DEFINE_TYPES(aspeed_ast2600_clemente_types) > diff --git a/hw/arm/meson.build b/hw/arm/meson.build > index a9e8270b85..4189de2aaa 100644 > --- a/hw/arm/meson.build > +++ b/hw/arm/meson.build > @@ -59,6 +59,7 @@ arm_common_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( > 'aspeed_ast2600_anacapa.c', > 'aspeed_ast2600_bletchley.c', > 'aspeed_ast2600_catalina.c', > + 'aspeed_ast2600_clemente.c', > 'aspeed_ast2600_evb.c', > 'aspeed_ast2600_fby35.c', > 'aspeed_ast2600_fuji.c', > > -- > 2.53.0-Meta > > Reviewed-by: Jamin Lin <jaminlin1207@gmail.com> ^ permalink raw reply [flat|nested] 49+ messages in thread
* [PATCH 22/22] hw/arm: clemente: populate the FRU EEPROMs 2026-10-15 11:57 ` Emmanuel Blot via qemu development @ 2026-10-15 11:58 ` Emmanuel Blot via -1 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via qemu development @ 2026-10-15 11:58 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Back 24 of the 27 FRU EEPROMs with images read from hardware, so guest firmware can identify the boards, the compute and management modules, the network adapters, the I/O mezzanines and the drive backplanes instead of finding them blank. Two EEPROMs were erased on the sampled chassis and one was absent, so those three stay blank. The drive backplane and I/O mezzanine helpers each serve two instances carrying different images, so both now take a descriptor naming the EEPROMs they install. The content is sanitized: part and serial numbers masked, dates fixed, asset tags replaced, distinct originals kept distinct. Several images carry OEM MultiRecords whose contents are undocumented; the records are kept and their bodies zeroed. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/arm/aspeed_ast2600_clemente.c | 974 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 948 insertions(+), 26 deletions(-) diff --git a/hw/arm/aspeed_ast2600_clemente.c b/hw/arm/aspeed_ast2600_clemente.c index bf5a13bc49..7937097c5b 100644 --- a/hw/arm/aspeed_ast2600_clemente.c +++ b/hw/arm/aspeed_ast2600_clemente.c @@ -32,34 +32,937 @@ #define CLEMENTE_BMC_HW_STRAP2 0x00000800 #define CLEMENTE_BMC_RAM_SIZE (2 * GiB) +/* + * FRU images read back from hardware and sanitized: part and serial + * numbers are masked, manufacturing dates fixed and asset tags replaced, + * so the layout stays faithful while the identifying data is not real. + * + * Names are kept as programmed. The Board Info Area names the board, the + * Product Info Area the system it is installed in, so the boards sourced + * from a third party name their own vendor rather than the platform. + */ + +/* + * FRU: i2c1 @0x50 (PDB) + * Board mfg: Ingrasys + * Board product: Clemente PDB PVT2 + * Board part: 0A00AA000-001-A + * Board serial: 0A00AA00A0000A001 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_1_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x50, 0x44, 0x42, + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, + 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0xcf, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x31, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xbd, + 0x01, 0x09, 0x19, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, +}; + +/* + * FRU: i2c9 @0x50 (SCM) + * Board mfg: Ingrasys + * Board product: Clemente SCM PVT2 + * Board part: 0A00AA000-002-A + * Board serial: 0A00AA00A000002AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_9_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x53, 0x43, 0x4d, + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, + 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, 0x41, 0xcf, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x32, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x9d, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c9 @0x56 (BSM) + * Board mfg: Ingrasys + * Board product: BMC Storage Module PVT2 + * Board part: 0A00AAA00-003-A + * Board serial: 0A00AAA0A0000A003 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_9_0056[] = { + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd7, + 0x42, 0x4d, 0x43, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, + 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, + 0x30, 0x41, 0x30, 0x30, 0x33, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0x2d, 0x41, 0xce, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, + 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x01, 0x09, 0x00, 0xc8, + 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xcb, 0x43, 0x49, 0x2d, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0xcf, 0x30, 0x41, 0x30, + 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0x2d, 0x41, + 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xc1, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c10 @0x50 (OCP NIC0) + * Board mfg: Nvidia + * Board product: Nvidia ConnectX-7 OCP3.0 + * Board part: AA00004AAA-AAAA_AA + * Board serial: AA0000A004AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: Nvidia ConnectX-7 OCP3.0 + * Product part: AA00002AAA-AAAA_AA + * Product version: A2 + * Product serial: AA0000A002AA + * Product asset: QEMU + * OEM records: 1 (53 bytes, zeroed) + */ +static const uint8_t fru_10_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x0e, 0x1c, 0x00, 0xd4, 0x01, 0x0d, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd8, 0x4e, 0x76, + 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, 0x33, 0x2e, 0x30, 0xd8, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x34, 0x41, 0x41, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd5, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x34, 0x41, 0x41, 0x41, 0x2d, 0x41, + 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0xbf, 0x01, 0x0e, 0x19, 0xc6, 0x4e, 0x76, 0x69, 0x64, + 0x69, 0x61, 0xd8, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, + 0x33, 0x2e, 0x30, 0xd5, 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, + 0x41, 0x41, 0x2d, 0x41, 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, + 0x20, 0xd3, 0x41, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd8, 0x41, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x32, 0x41, 0x41, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0xfb, 0xc0, 0x82, 0x35, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c12 @0x50 (HPM 1) + * Board mfg: NVIDIA + * Board product: PG548 + * Board part: 000-0A000-0000-A05 + * Board serial: 0000000000005 + * Board mfg date: 2026-01-01T00:00:00Z + * Product mfg: NVIDIA + * Product name: GB300 1CPU:2GPU Board PC + * Product part: 000-0A000-0000-003 + * Product version: C07 + * Product serial: 0000000000003 + * Product asset: QEMU + */ +static const uint8_t fru_12_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf6, 0x01, 0x07, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc5, 0x50, 0x47, + 0x35, 0x34, 0x38, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x35, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x41, 0x30, 0x35, + 0xc0, 0xc1, 0x00, 0xd8, 0x01, 0x0c, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, + 0x49, 0x41, 0xd8, 0x47, 0x42, 0x33, 0x30, 0x30, 0x20, 0x31, 0x43, 0x50, + 0x55, 0x3a, 0x32, 0x47, 0x50, 0x55, 0x20, 0x42, 0x6f, 0x61, 0x72, 0x64, + 0x20, 0x50, 0x43, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0xc3, 0x43, + 0x30, 0x37, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x33, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x33, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0x0d, +}; + +/* + * FRU: i2c12 @0x54 (CBC 2) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000006 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000004 + * Product asset: QEMU + */ +static const uint8_t fru_12_0054[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe7, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x39, +}; + +/* + * FRU: i2c12 @0x55 (CBC 3) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000007 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000005 + * Product asset: QEMU + */ +static const uint8_t fru_12_0055[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe6, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x35, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x38, +}; + +/* + * FRU: i2c13 @0x50 (HPM) + * Board mfg: NVIDIA + * Board product: PG548 + * Board part: 000-0A000-0000-A05 + * Board serial: 0000000000008 + * Board mfg date: 2026-01-01T00:00:00Z + * Product mfg: NVIDIA + * Product name: GB300 1CPU:2GPU Board PC + * Product part: 000-0A000-0000-003 + * Product version: C07 + * Product serial: 0000000000006 + * Product asset: QEMU + */ +static const uint8_t fru_13_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf6, 0x01, 0x07, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc5, 0x50, 0x47, + 0x35, 0x34, 0x38, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x38, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x41, 0x30, 0x35, + 0xc0, 0xc1, 0x00, 0xd5, 0x01, 0x0c, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, + 0x49, 0x41, 0xd8, 0x47, 0x42, 0x33, 0x30, 0x30, 0x20, 0x31, 0x43, 0x50, + 0x55, 0x3a, 0x32, 0x47, 0x50, 0x55, 0x20, 0x42, 0x6f, 0x61, 0x72, 0x64, + 0x20, 0x50, 0x43, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0xc3, 0x43, + 0x30, 0x37, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x36, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x33, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0x0a, +}; + +/* + * FRU: i2c13 @0x54 (CBC 0) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000009 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000007 + * Product asset: QEMU + */ +static const uint8_t fru_13_0054[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe4, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x36, +}; + +/* + * FRU: i2c13 @0x55 (CBC 1) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000010 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000008 + * Product asset: QEMU + */ +static const uint8_t fru_13_0055[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x15, 0x01, 0x00, 0xc1, 0x00, 0xca, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xec, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x35, +}; + +/* + * FRU: i2c13 @0x57 (HMC) + * Board mfg: NVIDIA + * Board product: P4764-A02 + * Board part: 000-00000-0000-007 + * Board serial: 0000000000011 + * Board mfg date: 2026-01-01T00:00:00Z + * Product mfg: NVIDIA + * Product name: HMC for GB200 NVL72 + * Product part: 000-00000-0000-005 + * Product version: A1 + * Product serial: 0000000000009 + * Product asset: QEMU + */ +static const uint8_t fru_13_0057[] = { + 0x01, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0xf5, 0x01, 0x08, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc9, 0x50, 0x34, + 0x37, 0x36, 0x34, 0x2d, 0x41, 0x30, 0x32, 0xcd, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0xd2, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x37, 0xc0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x01, 0x0b, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xd3, 0x48, + 0x4d, 0x43, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x42, 0x32, 0x30, 0x30, + 0x20, 0x4e, 0x56, 0x4c, 0x37, 0x32, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x35, 0xc2, 0x41, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, + 0x46, 0x52, 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x32, + 0xc1, 0x00, 0x00, 0xcb, +}; + +/* + * FRU: i2c15 @0x52 (OCP NIC1) + * Board mfg: Nvidia + * Board product: Nvidia ConnectX-7 OCP3.0 + * Board part: AA00004AAA-AAAA_AA + * Board serial: AA0000A0012A + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: Nvidia ConnectX-7 OCP3.0 + * Product part: AA00002AAA-AAAA_AA + * Product version: A2 + * Product serial: AA0000A0010A + * Product asset: QEMU + * OEM records: 1 (53 bytes, zeroed) + */ +static const uint8_t fru_15_0052[] = { + 0x01, 0x00, 0x00, 0x01, 0x0e, 0x1c, 0x00, 0xd4, 0x01, 0x0d, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd8, 0x4e, 0x76, + 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, 0x33, 0x2e, 0x30, 0xd8, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0x32, 0x41, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd5, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x34, 0x41, 0x41, 0x41, 0x2d, 0x41, + 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0xd1, 0x01, 0x0e, 0x19, 0xc6, 0x4e, 0x76, 0x69, 0x64, + 0x69, 0x61, 0xd8, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, + 0x33, 0x2e, 0x30, 0xd5, 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, + 0x41, 0x41, 0x2d, 0x41, 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, + 0x20, 0xd3, 0x41, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd8, 0x41, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0x30, 0x41, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0x0d, 0xc0, 0x82, 0x35, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c21 @0x54 (interposer) + * Board mfg: Ingrasys + * Board product: Clemente Interposer PVT2 + * Board part: 0A00AA000-008-A + * Board serial: 0A00AA00A0001A3AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_21_0054[] = { + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd8, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x20, 0x50, 0x56, 0x54, 0x32, + 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, + 0x30, 0x31, 0x41, 0x33, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x38, 0x2d, 0x41, 0xce, 0x46, + 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, + 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x09, 0x00, 0xc8, + 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xcb, 0x43, 0x49, 0x2d, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0xcf, 0x30, 0x41, 0x30, + 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0x2d, 0x41, + 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xc1, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c23 @0x51 (FIO) + * Board mfg: Ingrasys + * Board product: Clemente FIO PVT2 + * Board part: 0A00A0A00-009-A + * Board serial: 0A00A0A0A0000A14A + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_23_0051[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x46, 0x49, 0x4f, + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, + 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x31, 0x34, 0x41, 0xcf, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x39, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c25 @0x56 (E1.S backplane 0) + * Board mfg: Ingrasys + * Board product: Clemente E1.S BP PVT2 + * Board part: 0A00AA000-010-A + * Board serial: 0A00AA00A0001A5AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_25_0056[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd5, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x45, 0x31, 0x2e, + 0x53, 0x20, 0x42, 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, + 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x31, 0x41, + 0x35, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x31, 0x30, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0xbf, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c29 @0x50 (IO mezzanine 0) + * Board mfg: Nvidia + * Board product: ConnectX-8 800GE 2P NIC + * Board part: 000-0A00A-A1AA-AA1 + * Board serial: AA0000001AA6 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: ConnectX-8 800GE 2P NIC + * Product part: 000-0A00A-A0AA-AA6 + * Product version: A1 + * Product serial: AA0000001AA1 + * Product asset: QEMU + * OEM records: 1 (25 bytes, zeroed) + */ +static const uint8_t fru_29_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x15, 0x2a, 0x00, 0xbf, 0x01, 0x14, 0x19, 0xc0, + 0xc6, 0xf0, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, 0x50, + 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0xdd, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, + 0x41, 0x31, 0x41, 0x41, 0x2d, 0x41, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, 0x00, 0xd4, + 0x01, 0x15, 0x19, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, + 0x50, 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, 0x41, 0x30, 0x41, 0x41, 0x2d, + 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0xc7, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x41, 0x31, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x75, + 0xd0, 0x82, 0x19, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c29 @0x52 (IO mezzanine 0 OSFP) + * Board mfg: Ingrasys + * Board product: Clemente OSFP PVT2 + * Board part: 0A00AAA00-012-A + * Board serial: 0A00AAA0A000017AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_29_0052[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd2, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x4f, 0x53, 0x46, + 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x37, 0x41, 0x41, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x31, 0x32, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, + 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x1e, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c37 @0x56 (E1.S backplane 1) + * Board mfg: Ingrasys + * Board product: Clemente E1.S BP PVT2 + * Board part: 0A00AA000-010-A + * Board serial: 0A00AA00A0001A8AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_37_0056[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd5, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x45, 0x31, 0x2e, + 0x53, 0x20, 0x42, 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, + 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x31, 0x41, + 0x38, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x31, 0x30, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0xbc, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c41 @0x50 (IO mezzanine 1) + * Board mfg: Nvidia + * Board product: ConnectX-8 800GE 2P NIC + * Board part: 000-0A00A-A1AA-AA1 + * Board serial: AA0000019AAA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: ConnectX-8 800GE 2P NIC + * Product part: 000-0A00A-A0AA-AA6 + * Product version: A1 + * Product serial: AA0000012AAA + * Product asset: QEMU + * OEM records: 1 (25 bytes, zeroed) + */ +static const uint8_t fru_41_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x15, 0x2a, 0x00, 0xbf, 0x01, 0x14, 0x19, 0xc0, + 0xc6, 0xf0, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, 0x50, + 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x31, 0x39, 0x41, 0x41, 0x41, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0xdd, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, + 0x41, 0x31, 0x41, 0x41, 0x2d, 0x41, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, 0x00, 0xc0, + 0x01, 0x15, 0x19, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, + 0x50, 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, 0x41, 0x30, 0x41, 0x41, 0x2d, + 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0xc7, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x32, 0x41, 0x41, 0x41, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x63, + 0xd0, 0x82, 0x19, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c45 @0x53 (boot drive) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-07AAA + * Product version: + * Product serial: A0AAAA0A000013 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_45_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x37, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c48 @0x53 (E1.S backplane 0 drive 0) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000014 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_48_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x34, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c50 @0x53 (E1.S backplane 0 drive 2) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000015 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_50_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c52 @0x53 (E1.S backplane 1 drive 0) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000016 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_52_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x36, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c54 @0x53 (E1.S backplane 1 drive 2) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000017 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_54_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x37, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +typedef struct ClementeFru { + const uint8_t *data; + size_t size; +} ClementeFru; + +/* The images an E1.S backplane needs: its own FRU and its two drives. */ +typedef struct ClementeE1sFru { + ClementeFru backplane; /* @0x56 */ + ClementeFru drive0; /* mux channel 0 @0x53 */ + ClementeFru drive2; /* mux channel 2 @0x53 */ +} ClementeE1sFru; + +static const ClementeE1sFru clemente_e1s_fru[] = { + { + .backplane = { fru_25_0056, sizeof(fru_25_0056) }, + .drive0 = { fru_48_0053, sizeof(fru_48_0053) }, + .drive2 = { fru_50_0053, sizeof(fru_50_0053) }, + }, + { + .backplane = { fru_37_0056, sizeof(fru_37_0056) }, + .drive0 = { fru_52_0053, sizeof(fru_52_0053) }, + .drive2 = { fru_54_0053, sizeof(fru_54_0053) }, + }, +}; + +/* The images an IO mezzanine needs: its own FRU and the OSFP one. */ +typedef struct ClementeIoMezzFru { + ClementeFru mezzanine; /* @0x50 */ + ClementeFru osfp; /* @0x52 */ +} ClementeIoMezzFru; + +static const ClementeIoMezzFru clemente_io_mezz_fru[] = { + { + .mezzanine = { fru_29_0050, sizeof(fru_29_0050) }, + .osfp = { fru_29_0052, sizeof(fru_29_0052) }, + }, + { + .mezzanine = { fru_41_0050, sizeof(fru_41_0050) }, + /* the OSFP FRU was absent from the sampled chassis */ + }, +}; + /* * E1.S backplane hanging off a PCA9546 channel: an FRU EEPROM plus a * second PCA9546 fronting per-drive NVMe SSD FRU EEPROMs. */ -static void clemente_e1s_backplane_init(I2CBus *bus) +static void clemente_e1s_backplane_init(I2CBus *bus, + const ClementeE1sFru *fru) { /* eeprom@56 - atmel,24c128 */ - at24c_eeprom_init(bus, 0x56, 16 * KiB); + at24c_eeprom_init_rom(bus, 0x56, 16 * KiB, + fru->backplane.data, fru->backplane.size); /* i2c-mux@74 - PCA9546 */ I2CSlave *mux = i2c_slave_create_simple(bus, TYPE_PCA9546, 0x74); /* eeprom@53 - atmel,24c02, channels 0 and 2 */ - at24c_eeprom_init(pca954x_i2c_get_bus(mux, 0), 0x53, 256); - at24c_eeprom_init(pca954x_i2c_get_bus(mux, 2), 0x53, 256); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(mux, 0), 0x53, 256, + fru->drive0.data, fru->drive0.size); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(mux, 2), 0x53, 256, + fru->drive2.data, fru->drive2.size); } /* * IO Mezzanine hanging off a PCA9546 channel: an I/O expander plus the * mezzanine and OSFP FRU EEPROMs. */ -static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr) +static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr, + const ClementeIoMezzFru *fru) { /* gpio@20/21 - nxp,pca9535 */ i2c_slave_create_simple(bus, TYPE_PCA9535, exp_addr); /* eeprom@50 - atmel,24c64 (mezzanine FRU) */ - at24c_eeprom_init(bus, 0x50, 8 * KiB); + at24c_eeprom_init_rom(bus, 0x50, 8 * KiB, + fru->mezzanine.data, fru->mezzanine.size); /* eeprom@52 - atmel,24c128 (OSFP FRU) */ - at24c_eeprom_init(bus, 0x52, 16 * KiB); + at24c_eeprom_init_rom(bus, 0x52, 16 * KiB, + fru->osfp.data, fru->osfp.size); } static void clemente_bmc_i2c_init(AspeedMachineState *bmc) @@ -78,12 +981,14 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* i2c-mux@71 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71); /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ - clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1), + &clemente_e1s_fru[0]); /* i2c-mux@72 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72); /* channel 1 - IO Mezz 0 (io_expander7 @20) */ - clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20); + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20, + &clemente_io_mezz_fru[0]); /* i2c-mux@73 (PCA9546) - channels empty */ i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73); @@ -91,17 +996,20 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* i2c-mux@75 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75); /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ - clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1), + &clemente_e1s_fru[1]); /* i2c-mux@76 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76); /* channel 1 - IO Mezz 1 (io_expander8 @21) */ - clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21); + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21, + &clemente_io_mezz_fru[1]); /* i2c-mux@77 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77); /* channel 1 - boot drive FRU eeprom@53 */ - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256, + fru_45_0053, sizeof(fru_45_0053)); /* &i2c1 */ /* power-monitor@12/14 - ti,lm5066i (no model) */ @@ -110,7 +1018,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@4e - ti,tmp1075 */ i2c_slave_create_simple(i2c[1], TYPE_TMP1075, 0x4e); /* eeprom@50 - atmel,24c02 (PDB FRU) */ - at24c_eeprom_init(i2c[1], 0x50, 256); + at24c_eeprom_init_rom(i2c[1], 0x50, 256, fru_1_0050, + sizeof(fru_1_0050)); /* vrm@60/61 - renesas,raa228004 (no model) */ /* i2c-mux@70 (PCA9548) - interposer */ i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70); @@ -118,7 +1027,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@4f - ti,tmp75 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f); /* eeprom@54 - atmel,24c64 */ - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, + 8 * KiB, fru_21_0054, sizeof(fru_21_0054)); /* channel 6 - io_expander5 gpio@27 - nxp,pca9554 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), TYPE_PCA9554, 0x27); @@ -126,7 +1036,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@4b - ti,tmp75 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b); /* eeprom@51 - atmel,24c64 */ - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, 8 * KiB); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, + 8 * KiB, fru_23_0051, sizeof(fru_23_0051)); /* &i2c2 */ /* gpio@20/21/27 - nxp,pca9555 */ @@ -156,35 +1067,45 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* gpio@4f - nxp,pca9555 */ i2c_slave_create_simple(i2c[9], TYPE_PCA9555, 0x4f); /* eeprom@50 - atmel,24c64 (SCM FRU) */ - at24c_eeprom_init(i2c[9], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[9], 0x50, 8 * KiB, fru_9_0050, + sizeof(fru_9_0050)); /* eeprom@56 - atmel,24c64 (BSM FRU) */ - at24c_eeprom_init(i2c[9], 0x56, 8 * KiB); + at24c_eeprom_init_rom(i2c[9], 0x56, 8 * KiB, fru_9_0056, + sizeof(fru_9_0056)); /* &i2c10 */ /* mctp@10 - mctp-i2c-controller (no model) */ /* temperature-sensor@1f - ti,tmp421 (OCP NIC0) */ i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f); /* eeprom@50 - atmel,24c64 (OCP NIC0 FRU) */ - at24c_eeprom_init(i2c[10], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[10], 0x50, 8 * KiB, fru_10_0050, + sizeof(fru_10_0050)); /* &i2c11 */ /* ssif-bmc@10 - ssif-bmc (no model) */ /* &i2c12 */ /* eeprom@50 - atmel,24c64 (HPM 1 FRU) */ - at24c_eeprom_init(i2c[12], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[12], 0x50, 8 * KiB, fru_12_0050, + sizeof(fru_12_0050)); /* eeprom@54/55 - atmel,24c02 (CBC 2/3 FRU) */ - at24c_eeprom_init(i2c[12], 0x54, 256); - at24c_eeprom_init(i2c[12], 0x55, 256); + at24c_eeprom_init_rom(i2c[12], 0x54, 256, fru_12_0054, + sizeof(fru_12_0054)); + at24c_eeprom_init_rom(i2c[12], 0x55, 256, fru_12_0055, + sizeof(fru_12_0055)); /* &i2c13 */ /* eeprom@50 - atmel,24c64 (HPM FRU) */ - at24c_eeprom_init(i2c[13], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[13], 0x50, 8 * KiB, fru_13_0050, + sizeof(fru_13_0050)); /* eeprom@54/55 - atmel,24c02 (CBC 0/1 FRU) */ - at24c_eeprom_init(i2c[13], 0x54, 256); - at24c_eeprom_init(i2c[13], 0x55, 256); + at24c_eeprom_init_rom(i2c[13], 0x54, 256, fru_13_0054, + sizeof(fru_13_0054)); + at24c_eeprom_init_rom(i2c[13], 0x55, 256, fru_13_0055, + sizeof(fru_13_0055)); /* eeprom@57 - atmel,24c02 (HMC FRU) */ - at24c_eeprom_init(i2c[13], 0x57, 256); + at24c_eeprom_init_rom(i2c[13], 0x57, 256, fru_13_0057, + sizeof(fru_13_0057)); /* &i2c14 */ /* gpio@10/11/12/13/14 - nxp,pca9555 (PDB CPLD) */ @@ -199,7 +1120,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@1f - ti,tmp421 (OCP NIC1) */ i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f); /* eeprom@52 - atmel,24c64 (OCP NIC1 FRU) */ - at24c_eeprom_init(i2c[15], 0x52, 8 * KiB); + at24c_eeprom_init_rom(i2c[15], 0x52, 8 * KiB, fru_15_0052, + sizeof(fru_15_0052)); } static void aspeed_machine_clemente_class_init(ObjectClass *oc, -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* [PATCH 22/22] hw/arm: clemente: populate the FRU EEPROMs @ 2026-10-15 11:58 ` Emmanuel Blot via 0 siblings, 0 replies; 49+ messages in thread From: Emmanuel Blot via @ 2026-10-15 11:58 UTC (permalink / raw) To: qemu-devel Cc: Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier, Emmanuel Blot Back 24 of the 27 FRU EEPROMs with images read from hardware, so guest firmware can identify the boards, the compute and management modules, the network adapters, the I/O mezzanines and the drive backplanes instead of finding them blank. Two EEPROMs were erased on the sampled chassis and one was absent, so those three stay blank. The drive backplane and I/O mezzanine helpers each serve two instances carrying different images, so both now take a descriptor naming the EEPROMs they install. The content is sanitized: part and serial numbers masked, dates fixed, asset tags replaced, distinct originals kept distinct. Several images carry OEM MultiRecords whose contents are undocumented; the records are kept and their bodies zeroed. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> --- hw/arm/aspeed_ast2600_clemente.c | 974 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 948 insertions(+), 26 deletions(-) diff --git a/hw/arm/aspeed_ast2600_clemente.c b/hw/arm/aspeed_ast2600_clemente.c index bf5a13bc49..7937097c5b 100644 --- a/hw/arm/aspeed_ast2600_clemente.c +++ b/hw/arm/aspeed_ast2600_clemente.c @@ -32,34 +32,937 @@ #define CLEMENTE_BMC_HW_STRAP2 0x00000800 #define CLEMENTE_BMC_RAM_SIZE (2 * GiB) +/* + * FRU images read back from hardware and sanitized: part and serial + * numbers are masked, manufacturing dates fixed and asset tags replaced, + * so the layout stays faithful while the identifying data is not real. + * + * Names are kept as programmed. The Board Info Area names the board, the + * Product Info Area the system it is installed in, so the boards sourced + * from a third party name their own vendor rather than the platform. + */ + +/* + * FRU: i2c1 @0x50 (PDB) + * Board mfg: Ingrasys + * Board product: Clemente PDB PVT2 + * Board part: 0A00AA000-001-A + * Board serial: 0A00AA00A0000A001 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_1_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x50, 0x44, 0x42, + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, + 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0xcf, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x31, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xbd, + 0x01, 0x09, 0x19, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, +}; + +/* + * FRU: i2c9 @0x50 (SCM) + * Board mfg: Ingrasys + * Board product: Clemente SCM PVT2 + * Board part: 0A00AA000-002-A + * Board serial: 0A00AA00A000002AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_9_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x53, 0x43, 0x4d, + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, + 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, 0x41, 0xcf, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x32, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x9d, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c9 @0x56 (BSM) + * Board mfg: Ingrasys + * Board product: BMC Storage Module PVT2 + * Board part: 0A00AAA00-003-A + * Board serial: 0A00AAA0A0000A003 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_9_0056[] = { + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd7, + 0x42, 0x4d, 0x43, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, + 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, + 0x30, 0x41, 0x30, 0x30, 0x33, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0x2d, 0x41, 0xce, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, + 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x01, 0x09, 0x00, 0xc8, + 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xcb, 0x43, 0x49, 0x2d, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0xcf, 0x30, 0x41, 0x30, + 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0x2d, 0x41, + 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xc1, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c10 @0x50 (OCP NIC0) + * Board mfg: Nvidia + * Board product: Nvidia ConnectX-7 OCP3.0 + * Board part: AA00004AAA-AAAA_AA + * Board serial: AA0000A004AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: Nvidia ConnectX-7 OCP3.0 + * Product part: AA00002AAA-AAAA_AA + * Product version: A2 + * Product serial: AA0000A002AA + * Product asset: QEMU + * OEM records: 1 (53 bytes, zeroed) + */ +static const uint8_t fru_10_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x0e, 0x1c, 0x00, 0xd4, 0x01, 0x0d, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd8, 0x4e, 0x76, + 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, 0x33, 0x2e, 0x30, 0xd8, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x34, 0x41, 0x41, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd5, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x34, 0x41, 0x41, 0x41, 0x2d, 0x41, + 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0xbf, 0x01, 0x0e, 0x19, 0xc6, 0x4e, 0x76, 0x69, 0x64, + 0x69, 0x61, 0xd8, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, + 0x33, 0x2e, 0x30, 0xd5, 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, + 0x41, 0x41, 0x2d, 0x41, 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, + 0x20, 0xd3, 0x41, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd8, 0x41, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x32, 0x41, 0x41, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0xfb, 0xc0, 0x82, 0x35, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c12 @0x50 (HPM 1) + * Board mfg: NVIDIA + * Board product: PG548 + * Board part: 000-0A000-0000-A05 + * Board serial: 0000000000005 + * Board mfg date: 2026-01-01T00:00:00Z + * Product mfg: NVIDIA + * Product name: GB300 1CPU:2GPU Board PC + * Product part: 000-0A000-0000-003 + * Product version: C07 + * Product serial: 0000000000003 + * Product asset: QEMU + */ +static const uint8_t fru_12_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf6, 0x01, 0x07, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc5, 0x50, 0x47, + 0x35, 0x34, 0x38, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x35, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x41, 0x30, 0x35, + 0xc0, 0xc1, 0x00, 0xd8, 0x01, 0x0c, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, + 0x49, 0x41, 0xd8, 0x47, 0x42, 0x33, 0x30, 0x30, 0x20, 0x31, 0x43, 0x50, + 0x55, 0x3a, 0x32, 0x47, 0x50, 0x55, 0x20, 0x42, 0x6f, 0x61, 0x72, 0x64, + 0x20, 0x50, 0x43, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0xc3, 0x43, + 0x30, 0x37, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x33, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x33, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0x0d, +}; + +/* + * FRU: i2c12 @0x54 (CBC 2) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000006 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000004 + * Product asset: QEMU + */ +static const uint8_t fru_12_0054[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe7, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x39, +}; + +/* + * FRU: i2c12 @0x55 (CBC 3) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000007 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000005 + * Product asset: QEMU + */ +static const uint8_t fru_12_0055[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe6, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x35, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x38, +}; + +/* + * FRU: i2c13 @0x50 (HPM) + * Board mfg: NVIDIA + * Board product: PG548 + * Board part: 000-0A000-0000-A05 + * Board serial: 0000000000008 + * Board mfg date: 2026-01-01T00:00:00Z + * Product mfg: NVIDIA + * Product name: GB300 1CPU:2GPU Board PC + * Product part: 000-0A000-0000-003 + * Product version: C07 + * Product serial: 0000000000006 + * Product asset: QEMU + */ +static const uint8_t fru_13_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf6, 0x01, 0x07, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc5, 0x50, 0x47, + 0x35, 0x34, 0x38, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x38, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x41, 0x30, 0x35, + 0xc0, 0xc1, 0x00, 0xd5, 0x01, 0x0c, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, + 0x49, 0x41, 0xd8, 0x47, 0x42, 0x33, 0x30, 0x30, 0x20, 0x31, 0x43, 0x50, + 0x55, 0x3a, 0x32, 0x47, 0x50, 0x55, 0x20, 0x42, 0x6f, 0x61, 0x72, 0x64, + 0x20, 0x50, 0x43, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0xc3, 0x43, + 0x30, 0x37, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x36, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x33, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0x0a, +}; + +/* + * FRU: i2c13 @0x54 (CBC 0) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000009 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000007 + * Product asset: QEMU + */ +static const uint8_t fru_13_0054[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe4, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x36, +}; + +/* + * FRU: i2c13 @0x55 (CBC 1) + * Chassis type: Blade Enclosure + * Chassis part: 000-00000-0000-001 + * Chassis serial: 000AAAA000001 + * Board mfg: Nvidia + * Board product: 18x1RU CBL Cartridge + * Board part: 000-0000-006 + * Board serial: 0000000000010 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: HS33172S03 + * Product name: 18x1RU CBL Cartridge + * Product part: 000-00000-0000-004 + * Product version: E.4 + * Product serial: 0000000000008 + * Product asset: QEMU + */ +static const uint8_t fru_13_0055[] = { + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, + 0x02, 0x80, 0x15, 0x01, 0x00, 0xc1, 0x00, 0xca, 0x01, 0x0a, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0xcc, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xec, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x35, +}; + +/* + * FRU: i2c13 @0x57 (HMC) + * Board mfg: NVIDIA + * Board product: P4764-A02 + * Board part: 000-00000-0000-007 + * Board serial: 0000000000011 + * Board mfg date: 2026-01-01T00:00:00Z + * Product mfg: NVIDIA + * Product name: HMC for GB200 NVL72 + * Product part: 000-00000-0000-005 + * Product version: A1 + * Product serial: 0000000000009 + * Product asset: QEMU + */ +static const uint8_t fru_13_0057[] = { + 0x01, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0xf5, 0x01, 0x08, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc9, 0x50, 0x34, + 0x37, 0x36, 0x34, 0x2d, 0x41, 0x30, 0x32, 0xcd, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0xd2, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x30, 0x37, 0xc0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x01, 0x0b, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xd3, 0x48, + 0x4d, 0x43, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x42, 0x32, 0x30, 0x30, + 0x20, 0x4e, 0x56, 0x4c, 0x37, 0x32, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x35, 0xc2, 0x41, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, + 0x46, 0x52, 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x32, + 0xc1, 0x00, 0x00, 0xcb, +}; + +/* + * FRU: i2c15 @0x52 (OCP NIC1) + * Board mfg: Nvidia + * Board product: Nvidia ConnectX-7 OCP3.0 + * Board part: AA00004AAA-AAAA_AA + * Board serial: AA0000A0012A + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: Nvidia ConnectX-7 OCP3.0 + * Product part: AA00002AAA-AAAA_AA + * Product version: A2 + * Product serial: AA0000A0010A + * Product asset: QEMU + * OEM records: 1 (53 bytes, zeroed) + */ +static const uint8_t fru_15_0052[] = { + 0x01, 0x00, 0x00, 0x01, 0x0e, 0x1c, 0x00, 0xd4, 0x01, 0x0d, 0x19, 0xc0, + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd8, 0x4e, 0x76, + 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, 0x33, 0x2e, 0x30, 0xd8, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0x32, 0x41, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd5, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x34, 0x41, 0x41, 0x41, 0x2d, 0x41, + 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, + 0x00, 0x00, 0x00, 0xd1, 0x01, 0x0e, 0x19, 0xc6, 0x4e, 0x76, 0x69, 0x64, + 0x69, 0x61, 0xd8, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, + 0x33, 0x2e, 0x30, 0xd5, 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, + 0x41, 0x41, 0x2d, 0x41, 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, + 0x20, 0xd3, 0x41, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd8, 0x41, 0x41, + 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0x30, 0x41, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0x0d, 0xc0, 0x82, 0x35, 0x00, + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c21 @0x54 (interposer) + * Board mfg: Ingrasys + * Board product: Clemente Interposer PVT2 + * Board part: 0A00AA000-008-A + * Board serial: 0A00AA00A0001A3AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_21_0054[] = { + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd8, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x20, 0x50, 0x56, 0x54, 0x32, + 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, + 0x30, 0x31, 0x41, 0x33, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x38, 0x2d, 0x41, 0xce, 0x46, + 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, + 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x09, 0x00, 0xc8, + 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xcb, 0x43, 0x49, 0x2d, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0xcf, 0x30, 0x41, 0x30, + 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0x2d, 0x41, + 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xc1, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c23 @0x51 (FIO) + * Board mfg: Ingrasys + * Board product: Clemente FIO PVT2 + * Board part: 0A00A0A00-009-A + * Board serial: 0A00A0A0A0000A14A + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_23_0051[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x46, 0x49, 0x4f, + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, + 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x31, 0x34, 0x41, 0xcf, + 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, + 0x39, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c25 @0x56 (E1.S backplane 0) + * Board mfg: Ingrasys + * Board product: Clemente E1.S BP PVT2 + * Board part: 0A00AA000-010-A + * Board serial: 0A00AA00A0001A5AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_25_0056[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd5, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x45, 0x31, 0x2e, + 0x53, 0x20, 0x42, 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, + 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x31, 0x41, + 0x35, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x31, 0x30, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0xbf, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c29 @0x50 (IO mezzanine 0) + * Board mfg: Nvidia + * Board product: ConnectX-8 800GE 2P NIC + * Board part: 000-0A00A-A1AA-AA1 + * Board serial: AA0000001AA6 + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: ConnectX-8 800GE 2P NIC + * Product part: 000-0A00A-A0AA-AA6 + * Product version: A1 + * Product serial: AA0000001AA1 + * Product asset: QEMU + * OEM records: 1 (25 bytes, zeroed) + */ +static const uint8_t fru_29_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x15, 0x2a, 0x00, 0xbf, 0x01, 0x14, 0x19, 0xc0, + 0xc6, 0xf0, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, 0x50, + 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0xdd, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, + 0x41, 0x31, 0x41, 0x41, 0x2d, 0x41, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, 0x00, 0xd4, + 0x01, 0x15, 0x19, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, + 0x50, 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, 0x41, 0x30, 0x41, 0x41, 0x2d, + 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0xc7, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x41, 0x31, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x75, + 0xd0, 0x82, 0x19, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c29 @0x52 (IO mezzanine 0 OSFP) + * Board mfg: Ingrasys + * Board product: Clemente OSFP PVT2 + * Board part: 0A00AAA00-012-A + * Board serial: 0A00AAA0A000017AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_29_0052[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd2, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x4f, 0x53, 0x46, + 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x37, 0x41, 0x41, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x31, 0x32, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, + 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x1e, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c37 @0x56 (E1.S backplane 1) + * Board mfg: Ingrasys + * Board product: Clemente E1.S BP PVT2 + * Board part: 0A00AA000-010-A + * Board serial: 0A00AA00A0001A8AA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver. 0.05A + * Product mfg: Ingrasys + * Product name: CI-Clemente + * Product part: 0A00A0A00-001-A + * Product version: PVT2 + * Product serial: 0AAA00000001 + * Product asset: QEMU + */ +static const uint8_t fru_37_0056[] = { + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd5, + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x45, 0x31, 0x2e, + 0x53, 0x20, 0x42, 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, + 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x31, 0x41, + 0x38, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x2d, 0x30, 0x31, 0x30, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0xbc, + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, +}; + +/* + * FRU: i2c41 @0x50 (IO mezzanine 1) + * Board mfg: Nvidia + * Board product: ConnectX-8 800GE 2P NIC + * Board part: 000-0A00A-A1AA-AA1 + * Board serial: AA0000019AAA + * Board mfg date: 2026-01-01T00:00:00Z + * Board file ID: FRU Ver 0.01 + * Product mfg: Nvidia + * Product name: ConnectX-8 800GE 2P NIC + * Product part: 000-0A00A-A0AA-AA6 + * Product version: A1 + * Product serial: AA0000012AAA + * Product asset: QEMU + * OEM records: 1 (25 bytes, zeroed) + */ +static const uint8_t fru_41_0050[] = { + 0x01, 0x00, 0x00, 0x01, 0x15, 0x2a, 0x00, 0xbf, 0x01, 0x14, 0x19, 0xc0, + 0xc6, 0xf0, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, 0x50, + 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, 0x41, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x31, 0x39, 0x41, 0x41, 0x41, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0xdd, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, + 0x41, 0x31, 0x41, 0x41, 0x2d, 0x41, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, 0x55, 0x20, + 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, 0x00, 0xc0, + 0x01, 0x15, 0x19, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, + 0x50, 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x30, 0x30, 0x30, + 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, 0x41, 0x30, 0x41, 0x41, 0x2d, + 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0xc7, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, + 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x32, 0x41, 0x41, 0x41, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x63, + 0xd0, 0x82, 0x19, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c45 @0x53 (boot drive) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-07AAA + * Product version: + * Product serial: A0AAAA0A000013 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_45_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x37, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c48 @0x53 (E1.S backplane 0 drive 0) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000014 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_48_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x34, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c50 @0x53 (E1.S backplane 0 drive 2) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000015 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_50_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c52 @0x53 (E1.S backplane 1 drive 0) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000016 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_52_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x36, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* + * FRU: i2c54 @0x53 (E1.S backplane 1 drive 2) + * Product mfg: Samsung + * Product name: PM9D3a + * Product part: AAAA00A0AAAA-08AAA + * Product version: + * Product serial: A0A0AA0A000017 + * OEM records: 3 (91 bytes, zeroed) + */ +static const uint8_t fru_54_0053[] = { + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x37, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +typedef struct ClementeFru { + const uint8_t *data; + size_t size; +} ClementeFru; + +/* The images an E1.S backplane needs: its own FRU and its two drives. */ +typedef struct ClementeE1sFru { + ClementeFru backplane; /* @0x56 */ + ClementeFru drive0; /* mux channel 0 @0x53 */ + ClementeFru drive2; /* mux channel 2 @0x53 */ +} ClementeE1sFru; + +static const ClementeE1sFru clemente_e1s_fru[] = { + { + .backplane = { fru_25_0056, sizeof(fru_25_0056) }, + .drive0 = { fru_48_0053, sizeof(fru_48_0053) }, + .drive2 = { fru_50_0053, sizeof(fru_50_0053) }, + }, + { + .backplane = { fru_37_0056, sizeof(fru_37_0056) }, + .drive0 = { fru_52_0053, sizeof(fru_52_0053) }, + .drive2 = { fru_54_0053, sizeof(fru_54_0053) }, + }, +}; + +/* The images an IO mezzanine needs: its own FRU and the OSFP one. */ +typedef struct ClementeIoMezzFru { + ClementeFru mezzanine; /* @0x50 */ + ClementeFru osfp; /* @0x52 */ +} ClementeIoMezzFru; + +static const ClementeIoMezzFru clemente_io_mezz_fru[] = { + { + .mezzanine = { fru_29_0050, sizeof(fru_29_0050) }, + .osfp = { fru_29_0052, sizeof(fru_29_0052) }, + }, + { + .mezzanine = { fru_41_0050, sizeof(fru_41_0050) }, + /* the OSFP FRU was absent from the sampled chassis */ + }, +}; + /* * E1.S backplane hanging off a PCA9546 channel: an FRU EEPROM plus a * second PCA9546 fronting per-drive NVMe SSD FRU EEPROMs. */ -static void clemente_e1s_backplane_init(I2CBus *bus) +static void clemente_e1s_backplane_init(I2CBus *bus, + const ClementeE1sFru *fru) { /* eeprom@56 - atmel,24c128 */ - at24c_eeprom_init(bus, 0x56, 16 * KiB); + at24c_eeprom_init_rom(bus, 0x56, 16 * KiB, + fru->backplane.data, fru->backplane.size); /* i2c-mux@74 - PCA9546 */ I2CSlave *mux = i2c_slave_create_simple(bus, TYPE_PCA9546, 0x74); /* eeprom@53 - atmel,24c02, channels 0 and 2 */ - at24c_eeprom_init(pca954x_i2c_get_bus(mux, 0), 0x53, 256); - at24c_eeprom_init(pca954x_i2c_get_bus(mux, 2), 0x53, 256); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(mux, 0), 0x53, 256, + fru->drive0.data, fru->drive0.size); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(mux, 2), 0x53, 256, + fru->drive2.data, fru->drive2.size); } /* * IO Mezzanine hanging off a PCA9546 channel: an I/O expander plus the * mezzanine and OSFP FRU EEPROMs. */ -static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr) +static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr, + const ClementeIoMezzFru *fru) { /* gpio@20/21 - nxp,pca9535 */ i2c_slave_create_simple(bus, TYPE_PCA9535, exp_addr); /* eeprom@50 - atmel,24c64 (mezzanine FRU) */ - at24c_eeprom_init(bus, 0x50, 8 * KiB); + at24c_eeprom_init_rom(bus, 0x50, 8 * KiB, + fru->mezzanine.data, fru->mezzanine.size); /* eeprom@52 - atmel,24c128 (OSFP FRU) */ - at24c_eeprom_init(bus, 0x52, 16 * KiB); + at24c_eeprom_init_rom(bus, 0x52, 16 * KiB, + fru->osfp.data, fru->osfp.size); } static void clemente_bmc_i2c_init(AspeedMachineState *bmc) @@ -78,12 +981,14 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* i2c-mux@71 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71); /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ - clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1), + &clemente_e1s_fru[0]); /* i2c-mux@72 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72); /* channel 1 - IO Mezz 0 (io_expander7 @20) */ - clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20); + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20, + &clemente_io_mezz_fru[0]); /* i2c-mux@73 (PCA9546) - channels empty */ i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73); @@ -91,17 +996,20 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* i2c-mux@75 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75); /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ - clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1), + &clemente_e1s_fru[1]); /* i2c-mux@76 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76); /* channel 1 - IO Mezz 1 (io_expander8 @21) */ - clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21); + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21, + &clemente_io_mezz_fru[1]); /* i2c-mux@77 (PCA9546) */ i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77); /* channel 1 - boot drive FRU eeprom@53 */ - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256, + fru_45_0053, sizeof(fru_45_0053)); /* &i2c1 */ /* power-monitor@12/14 - ti,lm5066i (no model) */ @@ -110,7 +1018,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@4e - ti,tmp1075 */ i2c_slave_create_simple(i2c[1], TYPE_TMP1075, 0x4e); /* eeprom@50 - atmel,24c02 (PDB FRU) */ - at24c_eeprom_init(i2c[1], 0x50, 256); + at24c_eeprom_init_rom(i2c[1], 0x50, 256, fru_1_0050, + sizeof(fru_1_0050)); /* vrm@60/61 - renesas,raa228004 (no model) */ /* i2c-mux@70 (PCA9548) - interposer */ i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70); @@ -118,7 +1027,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@4f - ti,tmp75 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f); /* eeprom@54 - atmel,24c64 */ - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, + 8 * KiB, fru_21_0054, sizeof(fru_21_0054)); /* channel 6 - io_expander5 gpio@27 - nxp,pca9554 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), TYPE_PCA9554, 0x27); @@ -126,7 +1036,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@4b - ti,tmp75 */ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b); /* eeprom@51 - atmel,24c64 */ - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, 8 * KiB); + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, + 8 * KiB, fru_23_0051, sizeof(fru_23_0051)); /* &i2c2 */ /* gpio@20/21/27 - nxp,pca9555 */ @@ -156,35 +1067,45 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* gpio@4f - nxp,pca9555 */ i2c_slave_create_simple(i2c[9], TYPE_PCA9555, 0x4f); /* eeprom@50 - atmel,24c64 (SCM FRU) */ - at24c_eeprom_init(i2c[9], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[9], 0x50, 8 * KiB, fru_9_0050, + sizeof(fru_9_0050)); /* eeprom@56 - atmel,24c64 (BSM FRU) */ - at24c_eeprom_init(i2c[9], 0x56, 8 * KiB); + at24c_eeprom_init_rom(i2c[9], 0x56, 8 * KiB, fru_9_0056, + sizeof(fru_9_0056)); /* &i2c10 */ /* mctp@10 - mctp-i2c-controller (no model) */ /* temperature-sensor@1f - ti,tmp421 (OCP NIC0) */ i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f); /* eeprom@50 - atmel,24c64 (OCP NIC0 FRU) */ - at24c_eeprom_init(i2c[10], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[10], 0x50, 8 * KiB, fru_10_0050, + sizeof(fru_10_0050)); /* &i2c11 */ /* ssif-bmc@10 - ssif-bmc (no model) */ /* &i2c12 */ /* eeprom@50 - atmel,24c64 (HPM 1 FRU) */ - at24c_eeprom_init(i2c[12], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[12], 0x50, 8 * KiB, fru_12_0050, + sizeof(fru_12_0050)); /* eeprom@54/55 - atmel,24c02 (CBC 2/3 FRU) */ - at24c_eeprom_init(i2c[12], 0x54, 256); - at24c_eeprom_init(i2c[12], 0x55, 256); + at24c_eeprom_init_rom(i2c[12], 0x54, 256, fru_12_0054, + sizeof(fru_12_0054)); + at24c_eeprom_init_rom(i2c[12], 0x55, 256, fru_12_0055, + sizeof(fru_12_0055)); /* &i2c13 */ /* eeprom@50 - atmel,24c64 (HPM FRU) */ - at24c_eeprom_init(i2c[13], 0x50, 8 * KiB); + at24c_eeprom_init_rom(i2c[13], 0x50, 8 * KiB, fru_13_0050, + sizeof(fru_13_0050)); /* eeprom@54/55 - atmel,24c02 (CBC 0/1 FRU) */ - at24c_eeprom_init(i2c[13], 0x54, 256); - at24c_eeprom_init(i2c[13], 0x55, 256); + at24c_eeprom_init_rom(i2c[13], 0x54, 256, fru_13_0054, + sizeof(fru_13_0054)); + at24c_eeprom_init_rom(i2c[13], 0x55, 256, fru_13_0055, + sizeof(fru_13_0055)); /* eeprom@57 - atmel,24c02 (HMC FRU) */ - at24c_eeprom_init(i2c[13], 0x57, 256); + at24c_eeprom_init_rom(i2c[13], 0x57, 256, fru_13_0057, + sizeof(fru_13_0057)); /* &i2c14 */ /* gpio@10/11/12/13/14 - nxp,pca9555 (PDB CPLD) */ @@ -199,7 +1120,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) /* temperature-sensor@1f - ti,tmp421 (OCP NIC1) */ i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f); /* eeprom@52 - atmel,24c64 (OCP NIC1 FRU) */ - at24c_eeprom_init(i2c[15], 0x52, 8 * KiB); + at24c_eeprom_init_rom(i2c[15], 0x52, 8 * KiB, fru_15_0052, + sizeof(fru_15_0052)); } static void aspeed_machine_clemente_class_init(ObjectClass *oc, -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 49+ messages in thread
* Re: [PATCH 22/22] hw/arm: clemente: populate the FRU EEPROMs 2026-10-15 11:58 ` Emmanuel Blot via (?) @ 2026-10-16 9:34 ` Jamin Lin -1 siblings, 0 replies; 49+ messages in thread From: Jamin Lin @ 2026-10-16 9:34 UTC (permalink / raw) To: Emmanuel Blot Cc: qemu-devel, Philippe Mathieu-Daudé, Cédric Le Goater, Peter Maydell, Steven Lee, Troy Lee, Jamin Lin, Kane Chen, Andrew Jeffery, Joel Stanley, qemu-arm, Fabiano Rosas, Laurent Vivier, Paolo Bonzini, Pierrick Bouvier On Thu, Oct 15, 2026 at 01:58:00PM +0200, Emmanuel Blot via wrote: > Back 24 of the 27 FRU EEPROMs with images read from hardware, so guest > firmware can identify the boards, the compute and management modules, > the network adapters, the I/O mezzanines and the drive backplanes > instead of finding them blank. Two EEPROMs were erased on the sampled > chassis and one was absent, so those three stay blank. > > The drive backplane and I/O mezzanine helpers each serve two instances > carrying different images, so both now take a descriptor naming the > EEPROMs they install. > > The content is sanitized: part and serial numbers masked, dates fixed, > asset tags replaced, distinct originals kept distinct. Several images > carry OEM MultiRecords whose contents are undocumented; the records are > kept and their bodies zeroed. > > Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> > --- > hw/arm/aspeed_ast2600_clemente.c | 974 +++++++++++++++++++++++++++++++++++++-- > 1 file changed, 948 insertions(+), 26 deletions(-) > > diff --git a/hw/arm/aspeed_ast2600_clemente.c b/hw/arm/aspeed_ast2600_clemente.c > index bf5a13bc49..7937097c5b 100644 > --- a/hw/arm/aspeed_ast2600_clemente.c > +++ b/hw/arm/aspeed_ast2600_clemente.c > @@ -32,34 +32,937 @@ > #define CLEMENTE_BMC_HW_STRAP2 0x00000800 > #define CLEMENTE_BMC_RAM_SIZE (2 * GiB) > > +/* > + * FRU images read back from hardware and sanitized: part and serial > + * numbers are masked, manufacturing dates fixed and asset tags replaced, > + * so the layout stays faithful while the identifying data is not real. > + * > + * Names are kept as programmed. The Board Info Area names the board, the > + * Product Info Area the system it is installed in, so the boards sourced > + * from a third party name their own vendor rather than the platform. > + */ > + > +/* > + * FRU: i2c1 @0x50 (PDB) > + * Board mfg: Ingrasys > + * Board product: Clemente PDB PVT2 > + * Board part: 0A00AA000-001-A > + * Board serial: 0A00AA00A0000A001 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_1_0050[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x50, 0x44, 0x42, > + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, > + 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0xcf, > + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x31, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, > + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xbd, > + 0x01, 0x09, 0x19, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, > + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, > + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, > + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, > +}; > + > +/* > + * FRU: i2c9 @0x50 (SCM) > + * Board mfg: Ingrasys > + * Board product: Clemente SCM PVT2 > + * Board part: 0A00AA000-002-A > + * Board serial: 0A00AA00A000002AA > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_9_0050[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x53, 0x43, 0x4d, > + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, > + 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, 0x41, 0xcf, > + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x32, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, > + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x9d, > + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, > + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, > + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, > + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, > +}; > + > +/* > + * FRU: i2c9 @0x56 (BSM) > + * Board mfg: Ingrasys > + * Board product: BMC Storage Module PVT2 > + * Board part: 0A00AAA00-003-A > + * Board serial: 0A00AAA0A0000A003 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_9_0056[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd7, > + 0x42, 0x4d, 0x43, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, > + 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, > + 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, > + 0x30, 0x41, 0x30, 0x30, 0x33, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, > + 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0x2d, 0x41, 0xce, 0x46, 0x52, > + 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, > + 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x01, 0x09, 0x00, 0xc8, > + 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xcb, 0x43, 0x49, 0x2d, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0xcf, 0x30, 0x41, 0x30, > + 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0x2d, 0x41, > + 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xc1, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, > +}; > + > +/* > + * FRU: i2c10 @0x50 (OCP NIC0) > + * Board mfg: Nvidia > + * Board product: Nvidia ConnectX-7 OCP3.0 > + * Board part: AA00004AAA-AAAA_AA > + * Board serial: AA0000A004AA > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver 0.01 > + * Product mfg: Nvidia > + * Product name: Nvidia ConnectX-7 OCP3.0 > + * Product part: AA00002AAA-AAAA_AA > + * Product version: A2 > + * Product serial: AA0000A002AA > + * Product asset: QEMU > + * OEM records: 1 (53 bytes, zeroed) > + */ > +static const uint8_t fru_10_0050[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0e, 0x1c, 0x00, 0xd4, 0x01, 0x0d, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd8, 0x4e, 0x76, > + 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, > + 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, 0x33, 0x2e, 0x30, 0xd8, 0x41, > + 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x34, 0x41, 0x41, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd5, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x34, 0x41, 0x41, 0x41, 0x2d, 0x41, > + 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, > + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, > + 0x00, 0x00, 0x00, 0xbf, 0x01, 0x0e, 0x19, 0xc6, 0x4e, 0x76, 0x69, 0x64, > + 0x69, 0x61, 0xd8, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, > + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, > + 0x33, 0x2e, 0x30, 0xd5, 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, > + 0x41, 0x41, 0x2d, 0x41, 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, > + 0x20, 0xd3, 0x41, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd8, 0x41, 0x41, > + 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x32, 0x41, 0x41, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0xfb, 0xc0, 0x82, 0x35, 0x00, > + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c12 @0x50 (HPM 1) > + * Board mfg: NVIDIA > + * Board product: PG548 > + * Board part: 000-0A000-0000-A05 > + * Board serial: 0000000000005 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Product mfg: NVIDIA > + * Product name: GB300 1CPU:2GPU Board PC > + * Product part: 000-0A000-0000-003 > + * Product version: C07 > + * Product serial: 0000000000003 > + * Product asset: QEMU > + */ > +static const uint8_t fru_12_0050[] = { > + 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf6, 0x01, 0x07, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc5, 0x50, 0x47, > + 0x35, 0x34, 0x38, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x35, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x41, 0x30, 0x35, > + 0xc0, 0xc1, 0x00, 0xd8, 0x01, 0x0c, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, > + 0x49, 0x41, 0xd8, 0x47, 0x42, 0x33, 0x30, 0x30, 0x20, 0x31, 0x43, 0x50, > + 0x55, 0x3a, 0x32, 0x47, 0x50, 0x55, 0x20, 0x42, 0x6f, 0x61, 0x72, 0x64, > + 0x20, 0x50, 0x43, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, > + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0xc3, 0x43, > + 0x30, 0x37, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x33, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, > + 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x33, 0xc1, 0x00, > + 0x00, 0x00, 0x00, 0x0d, > +}; > + > +/* > + * FRU: i2c12 @0x54 (CBC 2) > + * Chassis type: Blade Enclosure > + * Chassis part: 000-00000-0000-001 > + * Chassis serial: 000AAAA000001 > + * Board mfg: Nvidia > + * Board product: 18x1RU CBL Cartridge > + * Board part: 000-0000-006 > + * Board serial: 0000000000006 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: HS33172S03 > + * Product name: 18x1RU CBL Cartridge > + * Product part: 000-00000-0000-004 > + * Product version: E.4 > + * Product serial: 0000000000004 > + * Product asset: QEMU > + */ > +static const uint8_t fru_12_0054[] = { > + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, > + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, > + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, > + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0xcc, 0x30, 0x30, 0x30, > + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, > + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0xe7, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, > + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, > + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, > + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, > + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x39, > +}; > + > +/* > + * FRU: i2c12 @0x55 (CBC 3) > + * Chassis type: Blade Enclosure > + * Chassis part: 000-00000-0000-001 > + * Chassis serial: 000AAAA000001 > + * Board mfg: Nvidia > + * Board product: 18x1RU CBL Cartridge > + * Board part: 000-0000-006 > + * Board serial: 0000000000007 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: HS33172S03 > + * Product name: 18x1RU CBL Cartridge > + * Product part: 000-00000-0000-004 > + * Product version: E.4 > + * Product serial: 0000000000005 > + * Product asset: QEMU > + */ > +static const uint8_t fru_12_0055[] = { > + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, > + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, > + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, > + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0xcc, 0x30, 0x30, 0x30, > + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, > + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0xe6, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, > + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, > + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, > + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x35, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, > + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x38, > +}; > + > +/* > + * FRU: i2c13 @0x50 (HPM) > + * Board mfg: NVIDIA > + * Board product: PG548 > + * Board part: 000-0A000-0000-A05 > + * Board serial: 0000000000008 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Product mfg: NVIDIA > + * Product name: GB300 1CPU:2GPU Board PC > + * Product part: 000-0A000-0000-003 > + * Product version: C07 > + * Product serial: 0000000000006 > + * Product asset: QEMU > + */ > +static const uint8_t fru_13_0050[] = { > + 0x01, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xf6, 0x01, 0x07, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc5, 0x50, 0x47, > + 0x35, 0x34, 0x38, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x38, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x41, 0x30, 0x35, > + 0xc0, 0xc1, 0x00, 0xd5, 0x01, 0x0c, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, > + 0x49, 0x41, 0xd8, 0x47, 0x42, 0x33, 0x30, 0x30, 0x20, 0x31, 0x43, 0x50, > + 0x55, 0x3a, 0x32, 0x47, 0x50, 0x55, 0x20, 0x42, 0x6f, 0x61, 0x72, 0x64, > + 0x20, 0x50, 0x43, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, > + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x33, 0xc3, 0x43, > + 0x30, 0x37, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x36, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, > + 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x33, 0xc1, 0x00, > + 0x00, 0x00, 0x00, 0x0a, > +}; > + > +/* > + * FRU: i2c13 @0x54 (CBC 0) > + * Chassis type: Blade Enclosure > + * Chassis part: 000-00000-0000-001 > + * Chassis serial: 000AAAA000001 > + * Board mfg: Nvidia > + * Board product: 18x1RU CBL Cartridge > + * Board part: 000-0000-006 > + * Board serial: 0000000000009 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: HS33172S03 > + * Product name: 18x1RU CBL Cartridge > + * Product part: 000-00000-0000-004 > + * Product version: E.4 > + * Product serial: 0000000000007 > + * Product asset: QEMU > + */ > +static const uint8_t fru_13_0054[] = { > + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, > + 0x02, 0x80, 0x12, 0x02, 0x00, 0xc1, 0x00, 0xcc, 0x01, 0x0a, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, > + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, > + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0xcc, 0x30, 0x30, 0x30, > + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, > + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0xe4, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, > + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, > + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, > + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, > + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x36, > +}; > + > +/* > + * FRU: i2c13 @0x55 (CBC 1) > + * Chassis type: Blade Enclosure > + * Chassis part: 000-00000-0000-001 > + * Chassis serial: 000AAAA000001 > + * Board mfg: Nvidia > + * Board product: 18x1RU CBL Cartridge > + * Board part: 000-0000-006 > + * Board serial: 0000000000010 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: HS33172S03 > + * Product name: 18x1RU CBL Cartridge > + * Product part: 000-00000-0000-004 > + * Product version: E.4 > + * Product serial: 0000000000008 > + * Product asset: QEMU > + */ > +static const uint8_t fru_13_0055[] = { > + 0x01, 0x00, 0x01, 0x07, 0x11, 0x00, 0x00, 0xe6, 0x01, 0x06, 0x1d, 0xd2, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x08, 0x02, 0x00, 0x03, > + 0x02, 0x80, 0x15, 0x01, 0x00, 0xc1, 0x00, 0xca, 0x01, 0x0a, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd4, 0x31, 0x38, > + 0x78, 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, > + 0x74, 0x72, 0x69, 0x64, 0x67, 0x65, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0xcc, 0x30, 0x30, 0x30, > + 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x36, 0xca, 0x48, 0x53, > + 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0xec, 0x01, 0x0a, 0x19, 0xc0, 0xd4, 0x31, 0x38, 0x78, > + 0x31, 0x52, 0x55, 0x20, 0x43, 0x42, 0x4c, 0x20, 0x43, 0x61, 0x72, 0x74, > + 0x72, 0x69, 0x64, 0x67, 0x65, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x34, > + 0xc3, 0x45, 0x2e, 0x34, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xca, > + 0x48, 0x53, 0x33, 0x33, 0x31, 0x37, 0x32, 0x53, 0x30, 0x33, 0xc1, 0x35, > +}; > + > +/* > + * FRU: i2c13 @0x57 (HMC) > + * Board mfg: NVIDIA > + * Board product: P4764-A02 > + * Board part: 000-00000-0000-007 > + * Board serial: 0000000000011 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Product mfg: NVIDIA > + * Product name: HMC for GB200 NVL72 > + * Product part: 000-00000-0000-005 > + * Product version: A1 > + * Product serial: 0000000000009 > + * Product asset: QEMU > + */ > +static const uint8_t fru_13_0057[] = { > + 0x01, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0xf5, 0x01, 0x08, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xc9, 0x50, 0x34, > + 0x37, 0x36, 0x34, 0x2d, 0x41, 0x30, 0x32, 0xcd, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0xd2, 0x30, 0x30, > + 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, > + 0x2d, 0x30, 0x30, 0x37, 0xc0, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, > + 0x01, 0x0b, 0x19, 0xc6, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0xd3, 0x48, > + 0x4d, 0x43, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x42, 0x32, 0x30, 0x30, > + 0x20, 0x4e, 0x56, 0x4c, 0x37, 0x32, 0xd2, 0x30, 0x30, 0x30, 0x2d, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x35, 0xc2, 0x41, 0x31, 0xcd, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x39, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, > + 0x46, 0x52, 0x55, 0x5f, 0x56, 0x65, 0x72, 0x5f, 0x30, 0x2e, 0x30, 0x32, > + 0xc1, 0x00, 0x00, 0xcb, > +}; > + > +/* > + * FRU: i2c15 @0x52 (OCP NIC1) > + * Board mfg: Nvidia > + * Board product: Nvidia ConnectX-7 OCP3.0 > + * Board part: AA00004AAA-AAAA_AA > + * Board serial: AA0000A0012A > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver 0.01 > + * Product mfg: Nvidia > + * Product name: Nvidia ConnectX-7 OCP3.0 > + * Product part: AA00002AAA-AAAA_AA > + * Product version: A2 > + * Product serial: AA0000A0010A > + * Product asset: QEMU > + * OEM records: 1 (53 bytes, zeroed) > + */ > +static const uint8_t fru_15_0052[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0e, 0x1c, 0x00, 0xd4, 0x01, 0x0d, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc6, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0xd8, 0x4e, 0x76, > + 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, > + 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, 0x33, 0x2e, 0x30, 0xd8, 0x41, > + 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0x32, 0x41, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd5, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x34, 0x41, 0x41, 0x41, 0x2d, 0x41, > + 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, > + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, > + 0x00, 0x00, 0x00, 0xd1, 0x01, 0x0e, 0x19, 0xc6, 0x4e, 0x76, 0x69, 0x64, > + 0x69, 0x61, 0xd8, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x43, 0x6f, > + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x58, 0x2d, 0x37, 0x20, 0x4f, 0x43, 0x50, > + 0x33, 0x2e, 0x30, 0xd5, 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x32, 0x41, > + 0x41, 0x41, 0x2d, 0x41, 0x41, 0x41, 0x41, 0x5f, 0x41, 0x41, 0x20, 0x20, > + 0x20, 0xd3, 0x41, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd8, 0x41, 0x41, > + 0x30, 0x30, 0x30, 0x30, 0x41, 0x30, 0x30, 0x31, 0x30, 0x41, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc0, 0xc1, 0x00, 0x00, 0x0d, 0xc0, 0x82, 0x35, 0x00, > + 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c21 @0x54 (interposer) > + * Board mfg: Ingrasys > + * Board product: Clemente Interposer PVT2 > + * Board part: 0A00AA000-008-A > + * Board serial: 0A00AA00A0001A3AA > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_21_0054[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd8, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x49, 0x6e, 0x74, > + 0x65, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x20, 0x50, 0x56, 0x54, 0x32, > + 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, > + 0x30, 0x31, 0x41, 0x33, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, > + 0x41, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x38, 0x2d, 0x41, 0xce, 0x46, > + 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, > + 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01, 0x09, 0x00, 0xc8, > + 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xcb, 0x43, 0x49, 0x2d, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0xcf, 0x30, 0x41, 0x30, > + 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, 0x31, 0x2d, 0x41, > + 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xc1, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, > +}; > + > +/* > + * FRU: i2c23 @0x51 (FIO) > + * Board mfg: Ingrasys > + * Board product: Clemente FIO PVT2 > + * Board part: 0A00A0A00-009-A > + * Board serial: 0A00A0A0A0000A14A > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_23_0051[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd1, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x46, 0x49, 0x4f, > + 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, > + 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x41, 0x31, 0x34, 0x41, 0xcf, > + 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, 0x30, > + 0x39, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, 0x2e, > + 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x98, > + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, > + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, > + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, > + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, > +}; > + > +/* > + * FRU: i2c25 @0x56 (E1.S backplane 0) > + * Board mfg: Ingrasys > + * Board product: Clemente E1.S BP PVT2 > + * Board part: 0A00AA000-010-A > + * Board serial: 0A00AA00A0001A5AA > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_25_0056[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd5, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x45, 0x31, 0x2e, > + 0x53, 0x20, 0x42, 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, > + 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x31, 0x41, > + 0x35, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, > + 0x30, 0x2d, 0x30, 0x31, 0x30, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, > + 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0xbf, > + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, > + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, > + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, > + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, > +}; > + > +/* > + * FRU: i2c29 @0x50 (IO mezzanine 0) > + * Board mfg: Nvidia > + * Board product: ConnectX-8 800GE 2P NIC > + * Board part: 000-0A00A-A1AA-AA1 > + * Board serial: AA0000001AA6 > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver 0.01 > + * Product mfg: Nvidia > + * Product name: ConnectX-8 800GE 2P NIC > + * Product part: 000-0A00A-A0AA-AA6 > + * Product version: A1 > + * Product serial: AA0000001AA1 > + * Product asset: QEMU > + * OEM records: 1 (25 bytes, zeroed) > + */ > +static const uint8_t fru_29_0050[] = { > + 0x01, 0x00, 0x00, 0x01, 0x15, 0x2a, 0x00, 0xbf, 0x01, 0x14, 0x19, 0xc0, > + 0xc6, 0xf0, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, > + 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, 0x50, > + 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, 0x41, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0xdd, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, > + 0x41, 0x31, 0x41, 0x41, 0x2d, 0x41, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, 0x55, 0x20, > + 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, 0x00, 0xd4, > + 0x01, 0x15, 0x19, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, > + 0x74, 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, > + 0x50, 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x30, 0x30, 0x30, > + 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, 0x41, 0x30, 0x41, 0x41, 0x2d, > + 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0xc7, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, > + 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x41, 0x41, 0x31, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, > + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x75, > + 0xd0, 0x82, 0x19, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c29 @0x52 (IO mezzanine 0 OSFP) > + * Board mfg: Ingrasys > + * Board product: Clemente OSFP PVT2 > + * Board part: 0A00AAA00-012-A > + * Board serial: 0A00AAA0A000017AA > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_29_0052[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd2, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x4f, 0x53, 0x46, > + 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, 0x30, 0x30, 0x41, > + 0x41, 0x41, 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x37, 0x41, 0x41, > + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x41, 0x30, 0x30, 0x2d, 0x30, > + 0x31, 0x32, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, 0x56, 0x65, 0x72, > + 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x1e, > + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, > + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, > + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, > + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, > +}; > + > +/* > + * FRU: i2c37 @0x56 (E1.S backplane 1) > + * Board mfg: Ingrasys > + * Board product: Clemente E1.S BP PVT2 > + * Board part: 0A00AA000-010-A > + * Board serial: 0A00AA00A0001A8AA > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver. 0.05A > + * Product mfg: Ingrasys > + * Product name: CI-Clemente > + * Product part: 0A00A0A00-001-A > + * Product version: PVT2 > + * Product serial: 0AAA00000001 > + * Product asset: QEMU > + */ > +static const uint8_t fru_37_0056[] = { > + 0x01, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0xf2, 0x01, 0x0b, 0x19, 0xc0, > + 0xc6, 0xf0, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, 0xd5, > + 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x20, 0x45, 0x31, 0x2e, > + 0x53, 0x20, 0x42, 0x50, 0x20, 0x50, 0x56, 0x54, 0x32, 0xd1, 0x30, 0x41, > + 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x30, 0x30, 0x31, 0x41, > + 0x38, 0x41, 0x41, 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x41, 0x30, 0x30, > + 0x30, 0x2d, 0x30, 0x31, 0x30, 0x2d, 0x41, 0xce, 0x46, 0x52, 0x55, 0x20, > + 0x56, 0x65, 0x72, 0x2e, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x41, 0xc1, 0xbc, > + 0x01, 0x09, 0x00, 0xc8, 0x49, 0x6e, 0x67, 0x72, 0x61, 0x73, 0x79, 0x73, > + 0xcb, 0x43, 0x49, 0x2d, 0x43, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, > + 0xcf, 0x30, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x30, 0x30, 0x2d, 0x30, > + 0x30, 0x31, 0x2d, 0x41, 0xc4, 0x50, 0x56, 0x54, 0x32, 0xcc, 0x30, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0xc4, 0x51, > + 0x45, 0x4d, 0x55, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, > +}; > + > +/* > + * FRU: i2c41 @0x50 (IO mezzanine 1) > + * Board mfg: Nvidia > + * Board product: ConnectX-8 800GE 2P NIC > + * Board part: 000-0A00A-A1AA-AA1 > + * Board serial: AA0000019AAA > + * Board mfg date: 2026-01-01T00:00:00Z > + * Board file ID: FRU Ver 0.01 > + * Product mfg: Nvidia > + * Product name: ConnectX-8 800GE 2P NIC > + * Product part: 000-0A00A-A0AA-AA6 > + * Product version: A1 > + * Product serial: AA0000012AAA > + * Product asset: QEMU > + * OEM records: 1 (25 bytes, zeroed) > + */ > +static const uint8_t fru_41_0050[] = { > + 0x01, 0x00, 0x00, 0x01, 0x15, 0x2a, 0x00, 0xbf, 0x01, 0x14, 0x19, 0xc0, > + 0xc6, 0xf0, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, > + 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, 0x50, > + 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, 0x41, 0x30, 0x30, > + 0x30, 0x30, 0x30, 0x31, 0x39, 0x41, 0x41, 0x41, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0xdd, 0x30, 0x30, 0x30, 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, > + 0x41, 0x31, 0x41, 0x41, 0x2d, 0x41, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xcc, 0x46, 0x52, 0x55, 0x20, > + 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x00, 0x00, 0xc0, > + 0x01, 0x15, 0x19, 0xd9, 0x4e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0xf2, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, > + 0x74, 0x58, 0x2d, 0x38, 0x20, 0x38, 0x30, 0x30, 0x47, 0x45, 0x20, 0x32, > + 0x50, 0x20, 0x4e, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x30, 0x30, 0x30, > + 0x2d, 0x30, 0x41, 0x30, 0x30, 0x41, 0x2d, 0x41, 0x30, 0x41, 0x41, 0x2d, > + 0x41, 0x41, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0xc7, 0x41, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0xdd, 0x41, > + 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x32, 0x41, 0x41, 0x41, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, > + 0x20, 0x20, 0x20, 0x20, 0xc4, 0x51, 0x45, 0x4d, 0x55, 0xcc, 0x46, 0x52, > + 0x55, 0x20, 0x56, 0x65, 0x72, 0x20, 0x30, 0x2e, 0x30, 0x31, 0xc1, 0x63, > + 0xd0, 0x82, 0x19, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c45 @0x53 (boot drive) > + * Product mfg: Samsung > + * Product name: PM9D3a > + * Product part: AAAA00A0AAAA-07AAA > + * Product version: > + * Product serial: A0AAAA0A000013 > + * OEM records: 3 (91 bytes, zeroed) > + */ > +static const uint8_t fru_45_0053[] = { > + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, > + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, > + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, > + 0x37, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, > + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x33, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, > + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, > + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c48 @0x53 (E1.S backplane 0 drive 0) > + * Product mfg: Samsung > + * Product name: PM9D3a > + * Product part: AAAA00A0AAAA-08AAA > + * Product version: > + * Product serial: A0A0AA0A000014 > + * OEM records: 3 (91 bytes, zeroed) > + */ > +static const uint8_t fru_48_0053[] = { > + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, > + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, > + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, > + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, > + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x34, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, > + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, > + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c50 @0x53 (E1.S backplane 0 drive 2) > + * Product mfg: Samsung > + * Product name: PM9D3a > + * Product part: AAAA00A0AAAA-08AAA > + * Product version: > + * Product serial: A0A0AA0A000015 > + * OEM records: 3 (91 bytes, zeroed) > + */ > +static const uint8_t fru_50_0053[] = { > + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, > + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, > + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, > + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, > + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, > + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, > + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c52 @0x53 (E1.S backplane 1 drive 0) > + * Product mfg: Samsung > + * Product name: PM9D3a > + * Product part: AAAA00A0AAAA-08AAA > + * Product version: > + * Product serial: A0A0AA0A000016 > + * OEM records: 3 (91 bytes, zeroed) > + */ > +static const uint8_t fru_52_0053[] = { > + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, > + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, > + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, > + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, > + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x36, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, > + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, > + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +/* > + * FRU: i2c54 @0x53 (E1.S backplane 1 drive 2) > + * Product mfg: Samsung > + * Product name: PM9D3a > + * Product part: AAAA00A0AAAA-08AAA > + * Product version: > + * Product serial: A0A0AA0A000017 > + * OEM records: 3 (91 bytes, zeroed) > + */ > +static const uint8_t fru_54_0053[] = { > + 0x01, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0xef, 0x01, 0x0e, 0x19, 0xc8, > + 0x53, 0x61, 0x6d, 0x73, 0x75, 0x6e, 0x67, 0x00, 0xd8, 0x50, 0x4d, 0x39, > + 0x44, 0x33, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x41, 0x41, > + 0x41, 0x41, 0x30, 0x30, 0x41, 0x30, 0x41, 0x41, 0x41, 0x41, 0x2d, 0x30, > + 0x38, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0xc2, 0x00, 0x00, 0xd4, 0x41, 0x30, 0x41, 0x30, 0x41, 0x41, > + 0x30, 0x41, 0x30, 0x30, 0x30, 0x30, 0x31, 0x37, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, > + 0x0b, 0x02, 0x3b, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x0b, 0x00, 0xe7, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x82, 0x15, 0x00, > + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, > +}; > + > +typedef struct ClementeFru { > + const uint8_t *data; > + size_t size; > +} ClementeFru; > + > +/* The images an E1.S backplane needs: its own FRU and its two drives. */ > +typedef struct ClementeE1sFru { > + ClementeFru backplane; /* @0x56 */ > + ClementeFru drive0; /* mux channel 0 @0x53 */ > + ClementeFru drive2; /* mux channel 2 @0x53 */ > +} ClementeE1sFru; > + > +static const ClementeE1sFru clemente_e1s_fru[] = { > + { > + .backplane = { fru_25_0056, sizeof(fru_25_0056) }, > + .drive0 = { fru_48_0053, sizeof(fru_48_0053) }, > + .drive2 = { fru_50_0053, sizeof(fru_50_0053) }, > + }, > + { > + .backplane = { fru_37_0056, sizeof(fru_37_0056) }, > + .drive0 = { fru_52_0053, sizeof(fru_52_0053) }, > + .drive2 = { fru_54_0053, sizeof(fru_54_0053) }, > + }, > +}; > + > +/* The images an IO mezzanine needs: its own FRU and the OSFP one. */ > +typedef struct ClementeIoMezzFru { > + ClementeFru mezzanine; /* @0x50 */ > + ClementeFru osfp; /* @0x52 */ > +} ClementeIoMezzFru; > + > +static const ClementeIoMezzFru clemente_io_mezz_fru[] = { > + { > + .mezzanine = { fru_29_0050, sizeof(fru_29_0050) }, > + .osfp = { fru_29_0052, sizeof(fru_29_0052) }, > + }, > + { > + .mezzanine = { fru_41_0050, sizeof(fru_41_0050) }, > + /* the OSFP FRU was absent from the sampled chassis */ > + }, > +}; > + > /* > * E1.S backplane hanging off a PCA9546 channel: an FRU EEPROM plus a > * second PCA9546 fronting per-drive NVMe SSD FRU EEPROMs. > */ > -static void clemente_e1s_backplane_init(I2CBus *bus) > +static void clemente_e1s_backplane_init(I2CBus *bus, > + const ClementeE1sFru *fru) > { > /* eeprom@56 - atmel,24c128 */ > - at24c_eeprom_init(bus, 0x56, 16 * KiB); > + at24c_eeprom_init_rom(bus, 0x56, 16 * KiB, > + fru->backplane.data, fru->backplane.size); > > /* i2c-mux@74 - PCA9546 */ > I2CSlave *mux = i2c_slave_create_simple(bus, TYPE_PCA9546, 0x74); > /* eeprom@53 - atmel,24c02, channels 0 and 2 */ > - at24c_eeprom_init(pca954x_i2c_get_bus(mux, 0), 0x53, 256); > - at24c_eeprom_init(pca954x_i2c_get_bus(mux, 2), 0x53, 256); > + at24c_eeprom_init_rom(pca954x_i2c_get_bus(mux, 0), 0x53, 256, > + fru->drive0.data, fru->drive0.size); > + at24c_eeprom_init_rom(pca954x_i2c_get_bus(mux, 2), 0x53, 256, > + fru->drive2.data, fru->drive2.size); > } > > /* > * IO Mezzanine hanging off a PCA9546 channel: an I/O expander plus the > * mezzanine and OSFP FRU EEPROMs. > */ > -static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr) > +static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr, > + const ClementeIoMezzFru *fru) > { > /* gpio@20/21 - nxp,pca9535 */ > i2c_slave_create_simple(bus, TYPE_PCA9535, exp_addr); > /* eeprom@50 - atmel,24c64 (mezzanine FRU) */ > - at24c_eeprom_init(bus, 0x50, 8 * KiB); > + at24c_eeprom_init_rom(bus, 0x50, 8 * KiB, > + fru->mezzanine.data, fru->mezzanine.size); > /* eeprom@52 - atmel,24c128 (OSFP FRU) */ > - at24c_eeprom_init(bus, 0x52, 16 * KiB); > + at24c_eeprom_init_rom(bus, 0x52, 16 * KiB, > + fru->osfp.data, fru->osfp.size); > } > > static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > @@ -78,12 +981,14 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > /* i2c-mux@71 (PCA9546) */ > i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71); > /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ > - clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); > + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1), > + &clemente_e1s_fru[0]); > > /* i2c-mux@72 (PCA9546) */ > i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72); > /* channel 1 - IO Mezz 0 (io_expander7 @20) */ > - clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20); > + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20, > + &clemente_io_mezz_fru[0]); > > /* i2c-mux@73 (PCA9546) - channels empty */ > i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73); > @@ -91,17 +996,20 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > /* i2c-mux@75 (PCA9546) */ > i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75); > /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */ > - clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1)); > + clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1), > + &clemente_e1s_fru[1]); > > /* i2c-mux@76 (PCA9546) */ > i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76); > /* channel 1 - IO Mezz 1 (io_expander8 @21) */ > - clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21); > + clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21, > + &clemente_io_mezz_fru[1]); > > /* i2c-mux@77 (PCA9546) */ > i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77); > /* channel 1 - boot drive FRU eeprom@53 */ > - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256); > + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256, > + fru_45_0053, sizeof(fru_45_0053)); > > /* &i2c1 */ > /* power-monitor@12/14 - ti,lm5066i (no model) */ > @@ -110,7 +1018,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > /* temperature-sensor@4e - ti,tmp1075 */ > i2c_slave_create_simple(i2c[1], TYPE_TMP1075, 0x4e); > /* eeprom@50 - atmel,24c02 (PDB FRU) */ > - at24c_eeprom_init(i2c[1], 0x50, 256); > + at24c_eeprom_init_rom(i2c[1], 0x50, 256, fru_1_0050, > + sizeof(fru_1_0050)); > /* vrm@60/61 - renesas,raa228004 (no model) */ > /* i2c-mux@70 (PCA9548) - interposer */ > i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70); > @@ -118,7 +1027,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > /* temperature-sensor@4f - ti,tmp75 */ > i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f); > /* eeprom@54 - atmel,24c64 */ > - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB); > + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, > + 8 * KiB, fru_21_0054, sizeof(fru_21_0054)); > /* channel 6 - io_expander5 gpio@27 - nxp,pca9554 */ > i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), > TYPE_PCA9554, 0x27); > @@ -126,7 +1036,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > /* temperature-sensor@4b - ti,tmp75 */ > i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b); > /* eeprom@51 - atmel,24c64 */ > - at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, 8 * KiB); > + at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, > + 8 * KiB, fru_23_0051, sizeof(fru_23_0051)); > > /* &i2c2 */ > /* gpio@20/21/27 - nxp,pca9555 */ > @@ -156,35 +1067,45 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > /* gpio@4f - nxp,pca9555 */ > i2c_slave_create_simple(i2c[9], TYPE_PCA9555, 0x4f); > /* eeprom@50 - atmel,24c64 (SCM FRU) */ > - at24c_eeprom_init(i2c[9], 0x50, 8 * KiB); > + at24c_eeprom_init_rom(i2c[9], 0x50, 8 * KiB, fru_9_0050, > + sizeof(fru_9_0050)); > /* eeprom@56 - atmel,24c64 (BSM FRU) */ > - at24c_eeprom_init(i2c[9], 0x56, 8 * KiB); > + at24c_eeprom_init_rom(i2c[9], 0x56, 8 * KiB, fru_9_0056, > + sizeof(fru_9_0056)); > > /* &i2c10 */ > /* mctp@10 - mctp-i2c-controller (no model) */ > /* temperature-sensor@1f - ti,tmp421 (OCP NIC0) */ > i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f); > /* eeprom@50 - atmel,24c64 (OCP NIC0 FRU) */ > - at24c_eeprom_init(i2c[10], 0x50, 8 * KiB); > + at24c_eeprom_init_rom(i2c[10], 0x50, 8 * KiB, fru_10_0050, > + sizeof(fru_10_0050)); > > /* &i2c11 */ > /* ssif-bmc@10 - ssif-bmc (no model) */ > > /* &i2c12 */ > /* eeprom@50 - atmel,24c64 (HPM 1 FRU) */ > - at24c_eeprom_init(i2c[12], 0x50, 8 * KiB); > + at24c_eeprom_init_rom(i2c[12], 0x50, 8 * KiB, fru_12_0050, > + sizeof(fru_12_0050)); > /* eeprom@54/55 - atmel,24c02 (CBC 2/3 FRU) */ > - at24c_eeprom_init(i2c[12], 0x54, 256); > - at24c_eeprom_init(i2c[12], 0x55, 256); > + at24c_eeprom_init_rom(i2c[12], 0x54, 256, fru_12_0054, > + sizeof(fru_12_0054)); > + at24c_eeprom_init_rom(i2c[12], 0x55, 256, fru_12_0055, > + sizeof(fru_12_0055)); > > /* &i2c13 */ > /* eeprom@50 - atmel,24c64 (HPM FRU) */ > - at24c_eeprom_init(i2c[13], 0x50, 8 * KiB); > + at24c_eeprom_init_rom(i2c[13], 0x50, 8 * KiB, fru_13_0050, > + sizeof(fru_13_0050)); > /* eeprom@54/55 - atmel,24c02 (CBC 0/1 FRU) */ > - at24c_eeprom_init(i2c[13], 0x54, 256); > - at24c_eeprom_init(i2c[13], 0x55, 256); > + at24c_eeprom_init_rom(i2c[13], 0x54, 256, fru_13_0054, > + sizeof(fru_13_0054)); > + at24c_eeprom_init_rom(i2c[13], 0x55, 256, fru_13_0055, > + sizeof(fru_13_0055)); > /* eeprom@57 - atmel,24c02 (HMC FRU) */ > - at24c_eeprom_init(i2c[13], 0x57, 256); > + at24c_eeprom_init_rom(i2c[13], 0x57, 256, fru_13_0057, > + sizeof(fru_13_0057)); > > /* &i2c14 */ > /* gpio@10/11/12/13/14 - nxp,pca9555 (PDB CPLD) */ > @@ -199,7 +1120,8 @@ static void clemente_bmc_i2c_init(AspeedMachineState *bmc) > /* temperature-sensor@1f - ti,tmp421 (OCP NIC1) */ > i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f); > /* eeprom@52 - atmel,24c64 (OCP NIC1 FRU) */ > - at24c_eeprom_init(i2c[15], 0x52, 8 * KiB); > + at24c_eeprom_init_rom(i2c[15], 0x52, 8 * KiB, fru_15_0052, > + sizeof(fru_15_0052)); > } > > static void aspeed_machine_clemente_class_init(ObjectClass *oc, > > -- > 2.53.0-Meta > > Reviewed-by: Jamin Lin <jaminlin1207@gmail.com> ^ permalink raw reply [flat|nested] 49+ messages in thread
end of thread, other threads:[~2026-10-16 9:35 UTC | newest] Thread overview: 49+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-15 11:57 [PATCH 00/22] Aspeed: TMP421 and TMP1075 sensors, and the Clemente BMC machine Emmanuel Blot via 2026-10-15 11:57 ` Emmanuel Blot via qemu development 2026-10-15 11:57 ` [PATCH 01/22] hw/sensor: tmp421: do not report a stale errno on a parse failure Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 02/22] hw/sensor: tmp421: name the parent object field parent_obj Emmanuel Blot via 2026-10-15 11:57 ` Emmanuel Blot via qemu development 2026-10-15 11:57 ` [PATCH 03/22] hw/sensor: tmp421: implement Resettable reset Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 04/22] hw/sensor: tmp421: model device variants with a class descriptor Emmanuel Blot via 2026-10-15 11:57 ` Emmanuel Blot via qemu development 2026-10-15 11:57 ` [PATCH 05/22] hw/sensor: tmp421: honor per-variant channels and channel enablement Emmanuel Blot via 2026-10-15 11:57 ` Emmanuel Blot via qemu development 2026-10-15 11:57 ` [PATCH 06/22] hw/sensor: tmp421: implement register write masks, one-shot and N-factor Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 07/22] hw/sensor: tmp421: describe the temperature properties Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 08/22] hw/sensor: tmp421: keep the measurement across a range change Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 09/22] hw/sensor: tmp421: migrate the exact measurement Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 10/22] hw/sensor: tmp421: publish the variant type names Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 11/22] hw/arm/aspeed: use the TMP421 type-name macros Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-16 5:19 ` 林建明 2026-10-15 11:57 ` [PATCH 12/22] tests/qtest: tmp421: cover device IDs and reset defaults Emmanuel Blot via 2026-10-15 11:57 ` Emmanuel Blot via qemu development 2026-10-15 11:57 ` [PATCH 13/22] tests/qtest: tmp421: cover temperature encoding and range Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 14/22] tests/qtest: tmp421: cover per-variant channels and enablement Emmanuel Blot via 2026-10-15 11:57 ` Emmanuel Blot via qemu development 2026-10-15 11:57 ` [PATCH 15/22] tests/qtest: tmp421: cover software reset and N-factor registers Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 16/22] tests/qtest: tmp421: cover the register form of the migration stream Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 17/22] hw/sensor: tmp105: add the TMP1075 variant Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 18/22] tests/qtest: tmp105: cover the TMP1075 device ID and reset defaults Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 19/22] tests/qtest: tmp105: cover the TMP1075 config register width Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 20/22] tests/qtest: tmp105: cover the Config low byte across a migration Emmanuel Blot via qemu development 2026-10-15 11:57 ` Emmanuel Blot via 2026-10-15 11:57 ` [PATCH 21/22] hw/arm: clemente: add Facebook Clemente BMC machine Emmanuel Blot via 2026-10-15 11:57 ` Emmanuel Blot via qemu development 2026-10-16 9:34 ` Jamin Lin 2026-10-15 11:58 ` [PATCH 22/22] hw/arm: clemente: populate the FRU EEPROMs Emmanuel Blot via qemu development 2026-10-15 11:58 ` Emmanuel Blot via 2026-10-16 9:34 ` Jamin Lin
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.