From 1bf7e6b7cba57bf24c6cfffaa03a5d5157230c0e Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Tue, 8 Sep 2026 11:18:25 -0700 Subject: [PATCH 1/8] gateway: update MGS, a whole bunch of barcode stuff --- Cargo.lock | 251 ++++++++++++---- Cargo.toml | 6 +- gateway-api/src/lib.rs | 1 + .../src/component_vpd/component_vpd.rs | 76 +++++ .../versions/src/component_vpd/mod.rs | 9 + .../versions/src/impls/component_vpd.rs | 274 ++++++++++++++++++ gateway-types/versions/src/impls/mod.rs | 1 + gateway-types/versions/src/latest.rs | 7 + gateway-types/versions/src/lib.rs | 2 + 9 files changed, 574 insertions(+), 53 deletions(-) create mode 100644 gateway-types/versions/src/component_vpd/component_vpd.rs create mode 100644 gateway-types/versions/src/component_vpd/mod.rs create mode 100644 gateway-types/versions/src/impls/component_vpd.rs diff --git a/Cargo.lock b/Cargo.lock index d65c05264e3..9162963ba18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3797,7 +3797,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4250,7 +4250,7 @@ dependencies = [ "clap", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-types", "omicron-uuid-kinds", "omicron-workspace-hack", @@ -4277,7 +4277,7 @@ dependencies = [ "chrono", "daft", "ereport-types", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-types", "omicron-uuid-kinds", "omicron-workspace-hack", @@ -4293,6 +4293,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "gateway-ereport-messages" +version = "0.1.0" +source = "git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1#438cd185666d5f164548885873f0f5df9a38eed1" +dependencies = [ + "hubpack", + "serde", + "zerocopy 0.8.55", +] + [[package]] name = "gateway-ereport-messages" version = "0.1.0" @@ -4302,6 +4312,25 @@ dependencies = [ "zerocopy 0.8.55", ] +[[package]] +name = "gateway-messages" +version = "0.1.0" +source = "git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1#438cd185666d5f164548885873f0f5df9a38eed1" +dependencies = [ + "bitflags 2.11.0", + "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "hubpack", + "serde", + "serde-big-array", + "serde_repr", + "smoltcp 0.9.1", + "static_assertions", + "strum 0.27.2", + "strum_macros 0.27.2", + "uuid", + "zerocopy 0.8.55", +] + [[package]] name = "gateway-messages" version = "0.1.0" @@ -4323,18 +4352,18 @@ dependencies = [ [[package]] name = "gateway-sp-comms" version = "0.1.2" -source = "git+https://github.com/oxidecomputer/management-gateway-service?rev=6c0aca2545a73fd75536e149d29faa7108be5862#6c0aca2545a73fd75536e149d29faa7108be5862" +source = "git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1#438cd185666d5f164548885873f0f5df9a38eed1" dependencies = [ "async-trait", "backoff", "base64 0.22.1", "futures", "fxhash", - "gateway-ereport-messages", - "gateway-messages", + "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "hex", "hubpack", - "hubtools 0.4.7 (git+https://github.com/oxidecomputer/hubtools.git?rev=2b1ef9b38d75563ea800baa3b17327eec17b1b7a)", + "hubtools 0.4.9", "lru-cache", "lzss", "nix 0.27.1", @@ -4350,13 +4379,13 @@ dependencies = [ "socket2 0.6.3", "string_cache", "thiserror 2.0.18", - "tlvc 0.3.1 (git+https://github.com/oxidecomputer/tlvc.git?branch=main)", + "tlvc 0.4.1 (git+https://github.com/oxidecomputer/tlvc.git?branch=main)", "tokio", "usdt 0.5.0", "uuid", "version_check", "zerocopy 0.8.55", - "zip 0.6.6", + "zip 8.6.0", ] [[package]] @@ -4366,7 +4395,7 @@ dependencies = [ "camino", "dropshot", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-types", "omicron-gateway", "omicron-test-utils", @@ -4393,7 +4422,7 @@ version = "0.1.0" dependencies = [ "daft", "dropshot", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "hex", "omicron-uuid-kinds", "omicron-workspace-hack", @@ -4759,6 +4788,9 @@ name = "hashbrown" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +dependencies = [ + "foldhash 0.2.0", +] [[package]] name = "headers" @@ -5202,14 +5234,14 @@ source = "git+https://github.com/oxidecomputer/hubtools.git?branch=main#2b1ef9b3 dependencies = [ "digest 0.10.7", "hex", - "lpc55_areas", - "lpc55_sign", + "lpc55_areas 0.2.5 (git+https://github.com/oxidecomputer/lpc55_support)", + "lpc55_sign 0.3.5 (git+https://github.com/oxidecomputer/lpc55_support)", "object 0.30.4", - "path-slash", + "path-slash 0.1.5", "rsa 0.9.10", "thiserror 1.0.69", - "tlvc 0.3.1 (git+https://github.com/oxidecomputer/tlvc)", - "tlvc-text", + "tlvc 0.3.1", + "tlvc-text 0.3.0", "toml 0.7.8", "x509-cert", "zerocopy 0.6.6", @@ -5223,20 +5255,41 @@ source = "git+https://github.com/oxidecomputer/hubtools.git?rev=2b1ef9b38d75563e dependencies = [ "digest 0.10.7", "hex", - "lpc55_areas", - "lpc55_sign", + "lpc55_areas 0.2.5 (git+https://github.com/oxidecomputer/lpc55_support)", + "lpc55_sign 0.3.5 (git+https://github.com/oxidecomputer/lpc55_support)", "object 0.30.4", - "path-slash", + "path-slash 0.1.5", "rsa 0.9.10", "thiserror 1.0.69", - "tlvc 0.3.1 (git+https://github.com/oxidecomputer/tlvc)", - "tlvc-text", + "tlvc 0.3.1", + "tlvc-text 0.3.0", "toml 0.7.8", "x509-cert", "zerocopy 0.6.6", "zip 0.6.6", ] +[[package]] +name = "hubtools" +version = "0.4.9" +source = "git+https://github.com/oxidecomputer/hubtools.git?rev=87881bd389025f7c5692c0be153452c11ae3312e#87881bd389025f7c5692c0be153452c11ae3312e" +dependencies = [ + "digest 0.11.3", + "hex", + "lpc55_areas 0.2.5 (git+https://github.com/oxidecomputer/lpc55_support?rev=fc64732faf5511850b35f1734d572b9953d73374)", + "lpc55_sign 0.3.5 (git+https://github.com/oxidecomputer/lpc55_support?rev=fc64732faf5511850b35f1734d572b9953d73374)", + "object 0.39.1", + "path-slash 0.2.1", + "rsa 0.9.10", + "thiserror 2.0.18", + "tlvc 0.4.1 (git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d8601ffd68853957da3)", + "tlvc-text 0.4.0", + "toml 1.1.2+spec-1.1.0", + "x509-cert", + "zerocopy 0.8.55", + "zip 8.6.0", +] + [[package]] name = "humantime" version = "2.3.0" @@ -6044,7 +6097,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6703,6 +6756,17 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "lpc55_areas" +version = "0.2.5" +source = "git+https://github.com/oxidecomputer/lpc55_support?rev=fc64732faf5511850b35f1734d572b9953d73374#fc64732faf5511850b35f1734d572b9953d73374" +dependencies = [ + "bitfield", + "clap", + "packed_struct", + "serde", +] + [[package]] name = "lpc55_areas" version = "0.2.5" @@ -6714,6 +6778,31 @@ dependencies = [ "serde", ] +[[package]] +name = "lpc55_sign" +version = "0.3.5" +source = "git+https://github.com/oxidecomputer/lpc55_support?rev=fc64732faf5511850b35f1734d572b9953d73374#fc64732faf5511850b35f1734d572b9953d73374" +dependencies = [ + "byteorder", + "const-oid 0.9.6", + "crc-any", + "der 0.7.10", + "env_logger", + "hex", + "log", + "lpc55_areas 0.2.5 (git+https://github.com/oxidecomputer/lpc55_support?rev=fc64732faf5511850b35f1734d572b9953d73374)", + "num-traits", + "packed_struct", + "pem-rfc7468 0.7.0", + "rsa 0.9.10", + "serde", + "serde-hex", + "sha2 0.10.9", + "thiserror 2.0.18", + "x509-cert", + "zerocopy 0.8.55", +] + [[package]] name = "lpc55_sign" version = "0.3.5" @@ -6726,7 +6815,7 @@ dependencies = [ "env_logger", "hex", "log", - "lpc55_areas", + "lpc55_areas 0.2.5 (git+https://github.com/oxidecomputer/lpc55_support)", "num-traits", "packed_struct", "pem-rfc7468 0.7.0", @@ -6908,7 +6997,7 @@ dependencies = [ "clap", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "libc", "omicron-gateway", @@ -7618,7 +7707,7 @@ dependencies = [ "fmd-adm-sys", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "gateway-types", "httpmock", @@ -7750,7 +7839,7 @@ dependencies = [ "dropshot", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "gateway-types", "http", @@ -8168,7 +8257,7 @@ dependencies = [ "dropshot", "fmd-adm-sys", "futures", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "headers", "hickory-resolver 0.25.2", @@ -8681,6 +8770,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +dependencies = [ + "crc32fast", + "hashbrown 0.17.0", + "indexmap 2.14.0", + "memchr", +] + [[package]] name = "olpc-cjson" version = "0.1.4" @@ -9013,7 +9114,7 @@ dependencies = [ "futures", "gateway-api", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-sp-comms", "gateway-test-utils", "gateway-types", @@ -9189,7 +9290,7 @@ dependencies = [ "fmd-adm-sys", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "gateway-types", "headers", @@ -9412,7 +9513,7 @@ dependencies = [ "fmd-adm-sys", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "gateway-types", "http", @@ -9923,8 +10024,8 @@ dependencies = [ "futures-sink", "futures-task", "futures-util", - "gateway-ereport-messages", - "gateway-messages", + "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=6c0aca2545a73fd75536e149d29faa7108be5862)", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=6c0aca2545a73fd75536e149d29faa7108be5862)", "generic-array 0.14.7", "getrandom 0.2.17", "getrandom 0.4.3", @@ -11041,6 +11142,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498a099351efa4becc6a19c72aa9270598e8fd274ca47052e37455241c88b696" +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + [[package]] name = "path-tree" version = "0.8.3" @@ -12180,7 +12287,7 @@ dependencies = [ "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -13138,7 +13245,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -13205,7 +13312,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -14468,7 +14575,7 @@ dependencies = [ "either", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "gateway-types", "http", @@ -14958,8 +15065,8 @@ dependencies = [ "clap", "dropshot", "futures", - "gateway-ereport-messages", - "gateway-messages", + "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-types", "hex", "hubtools 0.4.7 (git+https://github.com/oxidecomputer/hubtools.git?rev=2b1ef9b38d75563ea800baa3b17327eec17b1b7a)", @@ -15635,10 +15742,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.3.4", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -15940,7 +16047,7 @@ dependencies = [ [[package]] name = "tlvc" version = "0.3.1" -source = "git+https://github.com/oxidecomputer/tlvc.git?branch=main#e644a21a7ca973ed31499106ea926bd63ebccc6f" +source = "git+https://github.com/oxidecomputer/tlvc#e644a21a7ca973ed31499106ea926bd63ebccc6f" dependencies = [ "byteorder", "crc", @@ -15949,12 +16056,24 @@ dependencies = [ [[package]] name = "tlvc" -version = "0.3.1" -source = "git+https://github.com/oxidecomputer/tlvc#e644a21a7ca973ed31499106ea926bd63ebccc6f" +version = "0.4.1" +source = "git+https://github.com/oxidecomputer/tlvc.git?branch=main#7a96eab94c8aec9120412d8601ffd68853957da3" dependencies = [ - "byteorder", "crc", - "zerocopy 0.6.6", + "thiserror 2.0.18", + "zerocopy 0.8.55", + "zerocopy-derive 0.8.55", +] + +[[package]] +name = "tlvc" +version = "0.4.1" +source = "git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d8601ffd68853957da3#7a96eab94c8aec9120412d8601ffd68853957da3" +dependencies = [ + "crc", + "thiserror 2.0.18", + "zerocopy 0.8.55", + "zerocopy-derive 0.8.55", ] [[package]] @@ -15964,10 +16083,21 @@ source = "git+https://github.com/oxidecomputer/tlvc#e644a21a7ca973ed31499106ea92 dependencies = [ "ron", "serde", - "tlvc 0.3.1 (git+https://github.com/oxidecomputer/tlvc)", + "tlvc 0.3.1", "zerocopy 0.6.6", ] +[[package]] +name = "tlvc-text" +version = "0.4.0" +source = "git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d8601ffd68853957da3#7a96eab94c8aec9120412d8601ffd68853957da3" +dependencies = [ + "ron", + "serde", + "tlvc 0.4.1 (git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d8601ffd68853957da3)", + "zerocopy 0.8.55", +] + [[package]] name = "tofino" version = "0.1.0" @@ -16286,7 +16416,7 @@ dependencies = [ "tempfile", "tokio", "tokio-util", - "typed-path", + "typed-path 0.9.3", "untrusted 0.7.1", "url", "walkdir", @@ -16319,7 +16449,7 @@ dependencies = [ "tempfile", "tokio", "tokio-util", - "typed-path", + "typed-path 0.9.3", "untrusted 0.7.1", "url", "walkdir", @@ -16909,6 +17039,12 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82205ffd44a9697e34fc145491aa47310f9871540bb7909eaa9365e0a9a46607" +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typed-rng" version = "0.1.0" @@ -17754,7 +17890,7 @@ dependencies = [ "fs-err 3.3.0", "futures", "gateway-client", - "gateway-messages", + "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", "gateway-test-utils", "gateway-types", "hex", @@ -17771,7 +17907,7 @@ dependencies = [ "internal-dns-resolver", "internal-dns-types", "itertools 0.14.0", - "lpc55_areas", + "lpc55_areas 0.2.5 (git+https://github.com/oxidecomputer/lpc55_support)", "maplit", "omicron-certificates", "omicron-common", @@ -18769,6 +18905,21 @@ dependencies = [ "zstd", ] +[[package]] +name = "zip" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" +dependencies = [ + "bzip2 0.6.1", + "crc32fast", + "flate2", + "indexmap 2.14.0", + "memchr", + "typed-path 0.12.3", + "zopfli", +] + [[package]] name = "zlib-rs" version = "0.6.2" diff --git a/Cargo.toml b/Cargo.toml index 304268defd3..ff36369367e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -548,9 +548,9 @@ gateway-client = { path = "clients/gateway-client" } # compatibility, but will mean that faux-mgs might be missing new # functionality.) # -gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6c0aca2545a73fd75536e149d29faa7108be5862", default-features = false, features = ["debug-impls"] } -gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6c0aca2545a73fd75536e149d29faa7108be5862", default-features = false, features = ["std"] } -gateway-sp-comms = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6c0aca2545a73fd75536e149d29faa7108be5862" } +gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "438cd185666d5f164548885873f0f5df9a38eed1", default-features = false, features = ["debug-impls"] } +gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "438cd185666d5f164548885873f0f5df9a38eed1", default-features = false, features = ["std"] } +gateway-sp-comms = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "438cd185666d5f164548885873f0f5df9a38eed1" } gateway-test-utils = { path = "gateway-test-utils" } gateway-types = { path = "gateway-types" } gateway-types-versions = { path = "gateway-types/versions" } diff --git a/gateway-api/src/lib.rs b/gateway-api/src/lib.rs index f0e9f34f005..2f9474b896a 100644 --- a/gateway-api/src/lib.rs +++ b/gateway-api/src/lib.rs @@ -24,6 +24,7 @@ api_versions!([ // | example for the next person. // v // (next_int, IDENT), + (4, COMPONENT_VPD), (3, NEWTYPE_UUID_BUMP), (2, COSMO), (1, INITIAL), diff --git a/gateway-types/versions/src/component_vpd/component_vpd.rs b/gateway-types/versions/src/component_vpd/component_vpd.rs new file mode 100644 index 00000000000..6dcd5e2bb3f --- /dev/null +++ b/gateway-types/versions/src/component_vpd/component_vpd.rs @@ -0,0 +1,76 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + JsonSchema, +)] +pub struct OxideBarcode { + pub part_number: String, + pub revision: u32, + pub serial_number: String, +} + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + JsonSchema, +)] +pub struct Mpn1Barcode { + pub manufacturer: String, + pub part_number: String, + pub revision: String, + pub serial_number: String, +} + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + JsonSchema, +)] +pub enum Barcode { + Oxide(OxideBarcode), + Mpn1(Mpn1Barcode), +} + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + JsonSchema, +)] +pub struct SledFanTray { + pub identity: OxideBarcode, + pub vpd_board_identity: OxideBarcode, + pub fan0: Barcode, + pub fan1: Barcode, + pub fan2: Barcode, +} diff --git a/gateway-types/versions/src/component_vpd/mod.rs b/gateway-types/versions/src/component_vpd/mod.rs new file mode 100644 index 00000000000..2348385d614 --- /dev/null +++ b/gateway-types/versions/src/component_vpd/mod.rs @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +//! Version `COMPONENT_VPD` of the Gateway API. +//! +//! This version adds APIs for reading vital product data from an SP component. + +pub mod component_vpd; diff --git a/gateway-types/versions/src/impls/component_vpd.rs b/gateway-types/versions/src/impls/component_vpd.rs new file mode 100644 index 00000000000..30ef36aec12 --- /dev/null +++ b/gateway-types/versions/src/impls/component_vpd.rs @@ -0,0 +1,274 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +use crate::latest::component_vpd::{ + Barcode, Mpn1Barcode, OxideBarcode, SledFanTray, +}; +use gateway_messages::vpd as gw; +use std::num::ParseIntError; +use std::str::FromStr; + +#[derive(thiserror::Error, Debug)] +pub enum ParseBarcodeError { + #[error("barcode received from SP was not UTF-8")] + // TODO(eliza): t'would be nice to format the invalid bytes in a nice-ish + // way so you can see what the garbled message was... + NotUtf8, + #[error("missing barcode version (expected {expected})")] + MissingVersion { expected: &'static str }, + #[error("missing part number")] + MissingPartNumber, + #[error("missing revision")] + MissingRevision, + #[error("missing serial number")] + MissingSerialNumber, + #[error("missing MPN1 manufacturer string")] + MissingManufacturer, + #[error("unexpected fields")] + UnexpectedFields, + #[error("unknown barcode version {version:?} (expected {expected})")] + UnknownVersion { version: String, expected: &'static str }, + #[error("invalid Oxide barcode revision {revision}")] + BadRevision { + revision: String, + #[source] + error: ParseIntError, + }, +} + +#[derive(thiserror::Error, Debug)] +#[error("invalid {which_barcode} barcode")] +pub struct InvalidAssemblyBarcode { + which_barcode: &'static str, + #[source] + error: ParseBarcodeError, +} + +impl InvalidAssemblyBarcode { + fn mk(which_barcode: &'static str) -> impl Fn(ParseBarcodeError) -> Self { + move |error| Self { which_barcode, error } + } +} + +impl Barcode { + const EXPECTED_VERSION: &str = + "one of '0XV1', 'OXV1', '0XV2', 'OXV2', or 'MPN1'"; + + /// Borrows the manufacturer string for this barcode, if this is an `MPN1` + /// barcode. Otherwise, if this is an Oxide-issued barcode, this returns + /// `None`. + pub fn manufacturer(&self) -> Option<&str> { + match self { + Self::Mpn1(Mpn1Barcode { manufacturer, .. }) => { + Some(manufacturer.as_str()) + } + _ => None, + } + } + + /// Borrows the serial number portion of this barcode. + pub fn serial_number(&self) -> &str { + match self { + Self::Mpn1(Mpn1Barcode { serial_number, .. }) => { + serial_number.as_str() + } + Self::Oxide(OxideBarcode { serial_number, .. }) => { + serial_number.as_str() + } + } + } + + /// Borrows the part number portion of this barcode. + pub fn part_number(&self) -> &str { + match self { + Self::Mpn1(Mpn1Barcode { part_number, .. }) => part_number.as_str(), + Self::Oxide(OxideBarcode { part_number, .. }) => { + part_number.as_str() + } + } + } +} + +impl TryFrom for Barcode { + type Error = ParseBarcodeError; + fn try_from(value: gw::Barcode) -> Result { + value.as_str().ok_or(ParseBarcodeError::NotUtf8)?.parse() + } +} + +impl FromStr for Barcode { + type Err = ParseBarcodeError; + + fn from_str(s: &str) -> Result { + let mut parts = s.split(':'); + let version = + parts.next().ok_or(ParseBarcodeError::MissingVersion { + expected: Self::EXPECTED_VERSION, + })?; + match version { + "0XV1" | "OXV1" | "0XV2" | "OXV2" => { + OxideBarcode::from_parts(version, parts).map(Self::Oxide) + } + "MPN1" => Mpn1Barcode::from_parts(parts).map(Self::Mpn1), + version => Err(ParseBarcodeError::UnknownVersion { + version: version.to_string(), + expected: Self::EXPECTED_VERSION, + }), + } + } +} + +impl TryFrom for OxideBarcode { + type Error = ParseBarcodeError; + fn try_from(value: gw::Barcode) -> Result { + value.as_str().ok_or(ParseBarcodeError::NotUtf8)?.parse() + } +} + +impl FromStr for OxideBarcode { + type Err = ParseBarcodeError; + + fn from_str(s: &str) -> Result { + let mut parts = s.split(':'); + let version = + parts.next().ok_or(ParseBarcodeError::MissingVersion { + expected: Self::EXPECTED_VERSION, + })?; + Self::from_parts(version, parts) + } +} + +impl OxideBarcode { + const EXPECTED_VERSION: &str = "one of '0XV1', 'OXV1', '0XV2', or 'OXV2'"; + + fn from_parts<'parts>( + version: &'parts str, + mut parts: impl Iterator + 'parts, + ) -> Result { + let part_number = + parts.next().ok_or(ParseBarcodeError::MissingPartNumber)?; + let revision = + parts.next().ok_or(ParseBarcodeError::MissingRevision)?; + let serial_number = + parts.next().ok_or(ParseBarcodeError::MissingSerialNumber)?; + if parts.next().is_some() { + return Err(ParseBarcodeError::UnexpectedFields); + } + let part_number = match version { + "0XV1" | "OXV1" => { + // V1 does not include the hyphen in the part number when stored + // in an EEPROM, so we need to insert it. + let pn_chars = part_number.chars(); + let mut part_number = String::with_capacity(11); + for (i, ch) in pn_chars.enumerate() { + if i == 4 && ch != '-' { + part_number.push('-'); + } + part_number.push(ch); + } + part_number + } + "0XV2" | "OXV2" => part_number.to_string(), + _ => { + return Err(ParseBarcodeError::UnknownVersion { + version: version.to_string(), + expected: Self::EXPECTED_VERSION, + }); + } + }; + let revision = revision.parse().map_err(|error| { + ParseBarcodeError::BadRevision { + revision: revision.to_string(), + error, + } + })?; + + Ok(Self { + part_number, + revision, + serial_number: serial_number.to_owned(), + }) + } +} + +impl TryFrom for Mpn1Barcode { + type Error = ParseBarcodeError; + fn try_from(value: gw::Barcode) -> Result { + value.as_str().ok_or(ParseBarcodeError::NotUtf8)?.parse() + } +} + +impl FromStr for Mpn1Barcode { + type Err = ParseBarcodeError; + + fn from_str(s: &str) -> Result { + let mut parts = s.split(':'); + let version = + parts.next().ok_or(ParseBarcodeError::MissingVersion { + expected: Self::EXPECTED_VERSION, + })?; + if version != Self::EXPECTED_VERSION { + return Err(ParseBarcodeError::UnknownVersion { + version: version.to_string(), + expected: Self::EXPECTED_VERSION, + }); + } + Self::from_parts(parts) + } +} + +impl Mpn1Barcode { + const EXPECTED_VERSION: &str = "MPN1"; + + fn from_parts<'parts>( + mut parts: impl Iterator + 'parts, + ) -> Result { + let manufacturer = + parts.next().ok_or(ParseBarcodeError::MissingManufacturer)?; + let part_number = + parts.next().ok_or(ParseBarcodeError::MissingPartNumber)?; + let revision = + parts.next().ok_or(ParseBarcodeError::MissingRevision)?; + let serial_number = + parts.next().ok_or(ParseBarcodeError::MissingSerialNumber)?; + if parts.next().is_some() { + return Err(ParseBarcodeError::UnexpectedFields); + } + + Ok(Self { + manufacturer: manufacturer.to_owned(), + part_number: part_number.to_owned(), + revision: revision.to_owned(), + serial_number: serial_number.to_owned(), + }) + } +} + +impl TryFrom for SledFanTray { + type Error = InvalidAssemblyBarcode; + fn try_from(value: gw::SledFanTrayVpd) -> Result { + let gw::SledFanTrayVpd { + identity, + vpd_board_identity, + fans: [fan0, fan1, fan2], + } = value; + Ok(Self { + identity: identity + .try_into() + .map_err(InvalidAssemblyBarcode::mk("fan tray"))?, + vpd_board_identity: vpd_board_identity + .try_into() + .map_err(InvalidAssemblyBarcode::mk("VPD board"))?, + fan0: fan0 + .try_into() + .map_err(InvalidAssemblyBarcode::mk("fan 0"))?, + fan1: fan1 + .try_into() + .map_err(InvalidAssemblyBarcode::mk("fan 1"))?, + fan2: fan2 + .try_into() + .map_err(InvalidAssemblyBarcode::mk("fan 2"))?, + }) + } +} diff --git a/gateway-types/versions/src/impls/mod.rs b/gateway-types/versions/src/impls/mod.rs index aa0fab64d3c..81d67a3e439 100644 --- a/gateway-types/versions/src/impls/mod.rs +++ b/gateway-types/versions/src/impls/mod.rs @@ -9,6 +9,7 @@ mod component; mod component_details; +mod component_vpd; mod host; mod ignition; mod rot; diff --git a/gateway-types/versions/src/latest.rs b/gateway-types/versions/src/latest.rs index 4c102e7fd22..aaad26cd586 100644 --- a/gateway-types/versions/src/latest.rs +++ b/gateway-types/versions/src/latest.rs @@ -46,6 +46,13 @@ pub mod component_details { pub use crate::v1::component_details::UnsupportedComponentDetails; } +pub mod component_vpd { + pub use crate::v4::component_vpd::Barcode; + pub use crate::v4::component_vpd::Mpn1Barcode; + pub use crate::v4::component_vpd::OxideBarcode; + pub use crate::v4::component_vpd::SledFanTray; +} + pub mod host { pub use crate::v1::host::ComponentFirmwareHashStatus; pub use crate::v1::host::HostStartupOptions; diff --git a/gateway-types/versions/src/lib.rs b/gateway-types/versions/src/lib.rs index 2909130f1b3..ef36c03d856 100644 --- a/gateway-types/versions/src/lib.rs +++ b/gateway-types/versions/src/lib.rs @@ -35,3 +35,5 @@ pub mod latest; pub mod v1; #[path = "cosmo/mod.rs"] pub mod v2; +#[path = "component_vpd/mod.rs"] +pub mod v4; From a0d289b2eeb94e2f5dcd7922f3414092a25e9f7a Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 9 Sep 2026 09:16:21 -0700 Subject: [PATCH 2/8] gateway: formatting, parsing roundtrip tests, etc --- .../versions/src/impls/component_vpd.rs | 233 +++++++++++++++++- 1 file changed, 224 insertions(+), 9 deletions(-) diff --git a/gateway-types/versions/src/impls/component_vpd.rs b/gateway-types/versions/src/impls/component_vpd.rs index 30ef36aec12..6362e39650f 100644 --- a/gateway-types/versions/src/impls/component_vpd.rs +++ b/gateway-types/versions/src/impls/component_vpd.rs @@ -6,10 +6,11 @@ use crate::latest::component_vpd::{ Barcode, Mpn1Barcode, OxideBarcode, SledFanTray, }; use gateway_messages::vpd as gw; +use std::fmt; use std::num::ParseIntError; use std::str::FromStr; -#[derive(thiserror::Error, Debug)] +#[derive(thiserror::Error, Debug, Eq, PartialEq)] pub enum ParseBarcodeError { #[error("barcode received from SP was not UTF-8")] // TODO(eliza): t'would be nice to format the invalid bytes in a nice-ish @@ -110,7 +111,7 @@ impl FromStr for Barcode { "0XV1" | "OXV1" | "0XV2" | "OXV2" => { OxideBarcode::from_parts(version, parts).map(Self::Oxide) } - "MPN1" => Mpn1Barcode::from_parts(parts).map(Self::Mpn1), + Mpn1Barcode::MPN1 => Mpn1Barcode::from_parts(parts).map(Self::Mpn1), version => Err(ParseBarcodeError::UnknownVersion { version: version.to_string(), expected: Self::EXPECTED_VERSION, @@ -119,6 +120,15 @@ impl FromStr for Barcode { } } +impl fmt::Display for Barcode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Oxide(oxide) => oxide.fmt(f), + Self::Mpn1(mpn1) => mpn1.fmt(f), + } + } +} + impl TryFrom for OxideBarcode { type Error = ParseBarcodeError; fn try_from(value: gw::Barcode) -> Result { @@ -157,12 +167,12 @@ impl OxideBarcode { } let part_number = match version { "0XV1" | "OXV1" => { - // V1 does not include the hyphen in the part number when stored - // in an EEPROM, so we need to insert it. + // V1 does not include the hyphen after the first three digits + // of the part number, so we need to insert it. let pn_chars = part_number.chars(); let mut part_number = String::with_capacity(11); for (i, ch) in pn_chars.enumerate() { - if i == 4 && ch != '-' { + if i == 3 && ch != '-' { part_number.push('-'); } part_number.push(ch); @@ -206,20 +216,27 @@ impl FromStr for Mpn1Barcode { let mut parts = s.split(':'); let version = parts.next().ok_or(ParseBarcodeError::MissingVersion { - expected: Self::EXPECTED_VERSION, + expected: Self::MPN1, })?; - if version != Self::EXPECTED_VERSION { + if version != Self::MPN1 { return Err(ParseBarcodeError::UnknownVersion { version: version.to_string(), - expected: Self::EXPECTED_VERSION, + expected: Self::MPN1, }); } Self::from_parts(parts) } } +impl fmt::Display for OxideBarcode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { part_number, revision, serial_number } = self; + write!(f, "0XV2:{part_number}:{revision:03}:{serial_number}") + } +} + impl Mpn1Barcode { - const EXPECTED_VERSION: &str = "MPN1"; + const MPN1: &str = "MPN1"; fn from_parts<'parts>( mut parts: impl Iterator + 'parts, @@ -245,6 +262,17 @@ impl Mpn1Barcode { } } +impl fmt::Display for Mpn1Barcode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { manufacturer, part_number, revision, serial_number } = self; + write!( + f, + "{}:{manufacturer}:{part_number}:{revision:}:{serial_number}", + Self::MPN1 + ) + } +} + impl TryFrom for SledFanTray { type Error = InvalidAssemblyBarcode; fn try_from(value: gw::SledFanTrayVpd) -> Result { @@ -272,3 +300,190 @@ impl TryFrom for SledFanTray { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + // Most of the tests for barcode parsing in this module are lifted from + // the ones in Hubris' `oxide-barcode` crate. + // https://github.com/oxidecomputer/hubris/blob/0d1ba0453a5d80470f07ea9949eb82bc3c291e01/lib/oxide-barcode/src/lib.rs#L363-L614 + + #[track_caller] + fn check_parse_oxide(input: &str, expected: OxideBarcode) { + let parsed = dbg!(input).parse::(); + dbg!(&parsed); + + assert_eq!( + parsed.as_ref(), + Ok(dbg!(&expected)), + "parsing Oxide barcodestring: {input}" + ); + + let formatted = parsed.as_ref().unwrap().to_string(); + assert_eq!( + parsed, + dbg!(formatted).parse::(), + "parsed Oxide barcode for string {input} should round-trip through \ + `fmt::Display`", + ); + + // We accept barcode strings that start with both leading zero and + // leading capital-O. Permute our input from one of these to the other + // to make sure both forms parse equivalently. + let mut copy = input.to_owned(); + match copy.as_bytes()[0] { + b'0' => copy.replace_range(0..1, "O"), + b'O' => copy.replace_range(0..1, "0"), + c => panic!("unexpected leading character: {}", c as char), + } + + let parsed = dbg!(©).parse::(); + + assert_eq!( + dbg!(&parsed).as_ref(), + Ok(&expected), + "parsing Oxide barcode string: {copy}" + ); + + let formatted = parsed.as_ref().unwrap().to_string(); + assert_eq!( + parsed, + dbg!(formatted).parse::(), + "parsed Oxide barcode for string {copy} should round-trip through \ + `fmt::Display`", + ); + } + + #[test] + fn parse_oxv1() { + check_parse_oxide( + "0XV1:1230000456:023:TST01234567", + OxideBarcode { + part_number: "123-0000456".to_owned(), + revision: 23, + serial_number: "TST01234567".to_owned(), + }, + ); + } + + #[test] + fn parse_oxv2() { + check_parse_oxide( + "0XV2:123-0000456:023:TST01234567", + OxideBarcode { + part_number: "123-0000456".to_owned(), + revision: 23, + serial_number: "TST01234567".to_owned(), + }, + ); + } + + #[test] + fn parse_oxv2_shorter_serial() { + check_parse_oxide( + "0XV2:123-0000456:023:TST0123456", + OxideBarcode { + part_number: "123-0000456".to_owned(), + revision: 23, + serial_number: "TST0123456".to_owned(), + }, + ); + } + + #[test] + fn parse_oxv2_shorter_part() { + check_parse_oxide( + "0XV2:123-000045:023:TST01234567", + OxideBarcode { + part_number: "123-000045".to_owned(), + revision: 23, + serial_number: "TST01234567".to_owned(), + }, + ); + } + + #[track_caller] + fn check_parse_mpn1(input: &str, expected: Mpn1Barcode) { + let parsed = dbg!(input).parse::(); + dbg!(&parsed); + + assert_eq!( + parsed.as_ref(), + Ok(dbg!(&expected)), + "parsing MPN1 identity {input}" + ); + let formatted = parsed.as_ref().unwrap().to_string(); + assert_eq!( + dbg!(formatted).parse::().as_ref(), + Ok(&expected), + "parsed MPN1 barcode {input} should round-trip through \ + `fmt::Display`", + ); + } + + #[test] + fn parse_mpn1() { + check_parse_mpn1( + "MPN1:ABC:ASDF-1000:032:123456789", + Mpn1Barcode { + manufacturer: "ABC".to_owned(), + part_number: "ASDF-1000".to_owned(), + revision: "032".to_owned(), + serial_number: "123456789".to_owned(), + }, + ); + } + + #[test] + fn parse_mpn1_empty() { + check_parse_mpn1( + "MPN1::::", + Mpn1Barcode { + manufacturer: String::new(), + part_number: String::new(), + revision: String::new(), + serial_number: String::new(), + }, + ); + } + + #[test] + fn parse_mpn1_no_mpn_rev() { + check_parse_mpn1( + "MPN1:XYZ:::12345ABCD", + Mpn1Barcode { + manufacturer: "XYZ".to_owned(), + part_number: String::new(), + revision: String::new(), + serial_number: "12345ABCD".to_owned(), + }, + ); + } + + #[test] + fn parse_mpn1_no_serial() { + check_parse_mpn1( + "MPN1:XYZ:1234ABC:420:", + Mpn1Barcode { + manufacturer: "XYZ".to_owned(), + part_number: "1234ABC".to_owned(), + revision: "420".to_owned(), + serial_number: String::new(), + }, + ); + } + + #[test] + fn parse_mpn1_from_andy() { + check_parse_mpn1( + "MPN1:SYD:9CRA0848P8G012:C:WWYY1SSS", + Mpn1Barcode { + manufacturer: "SYD".to_owned(), + part_number: "9CRA0848P8G012".to_owned(), + revision: "C".to_owned(), + serial_number: "WWYY1SSS".to_owned(), + }, + ); + } +} From be1b6a60edc27545a2011907aa97e659c9105a7f Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 9 Sep 2026 09:30:33 -0700 Subject: [PATCH 3/8] wip --- gateway-api/src/lib.rs | 15 ++++++ .../src/component_vpd/component_vpd.rs | 52 +++++++++++++++++++ gateway-types/versions/src/impls/mod.rs | 2 +- gateway-types/versions/src/latest.rs | 5 ++ 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/gateway-api/src/lib.rs b/gateway-api/src/lib.rs index 2f9474b896a..07135658be4 100644 --- a/gateway-api/src/lib.rs +++ b/gateway-api/src/lib.rs @@ -335,6 +335,21 @@ pub trait GatewayApi { body: TypedBody, ) -> Result; + /// Get the vital product data (VPD) identity of a component. + /// + /// Not all components have VPD. This endpoint will return an error if the + /// requested component does not advertise the `HAS_VPD` DeviceCapability + /// bit. + #[endpoint { + method = GET, + path = "/sp/{type}/{slot}/component/{component}/vpd", + versions = COMPONENT_VPD.., + }] + async fn sp_component_vpd_get( + rqctx: RequestContext, + path: Path, + ) -> Result, HttpError>; + /// Read the CMPA from a root of trust. /// /// This endpoint is only valid for the `rot` component. diff --git a/gateway-types/versions/src/component_vpd/component_vpd.rs b/gateway-types/versions/src/component_vpd/component_vpd.rs index 6dcd5e2bb3f..795c56cb9ec 100644 --- a/gateway-types/versions/src/component_vpd/component_vpd.rs +++ b/gateway-types/versions/src/component_vpd/component_vpd.rs @@ -5,6 +5,26 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + JsonSchema, +)] +#[serde(tag = "type", rename_all = "snake_case")] +pub enum ComponentVpd { + OxideBarcode(OxideBarcode), + Mpn1Barcode(Mpn1Barcode), + SledFanTray(SledFanTray), + Tmp11x(Tmp11x), + Pmbus(PmbusDevice), +} + #[derive( Debug, Clone, @@ -51,6 +71,7 @@ pub struct Mpn1Barcode { Serialize, JsonSchema, )] +#[serde(tag = "type", rename_all = "snake_case")] pub enum Barcode { Oxide(OxideBarcode), Mpn1(Mpn1Barcode), @@ -74,3 +95,34 @@ pub struct SledFanTray { pub fan1: Barcode, pub fan2: Barcode, } + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + JsonSchema, +)] +pub struct Tmp11x { + pub device_id: u16, + pub eeprom1: u16, + pub eeprom2: u16, + pub eeprom3: u16, +} + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + Deserialize, + Serialize, + JsonSchema, +)] +pub struct PmbusDevice {} diff --git a/gateway-types/versions/src/impls/mod.rs b/gateway-types/versions/src/impls/mod.rs index 81d67a3e439..c274ba204ff 100644 --- a/gateway-types/versions/src/impls/mod.rs +++ b/gateway-types/versions/src/impls/mod.rs @@ -9,7 +9,7 @@ mod component; mod component_details; -mod component_vpd; +pub(crate) mod component_vpd; mod host; mod ignition; mod rot; diff --git a/gateway-types/versions/src/latest.rs b/gateway-types/versions/src/latest.rs index aaad26cd586..1d92fa46f28 100644 --- a/gateway-types/versions/src/latest.rs +++ b/gateway-types/versions/src/latest.rs @@ -51,6 +51,11 @@ pub mod component_vpd { pub use crate::v4::component_vpd::Mpn1Barcode; pub use crate::v4::component_vpd::OxideBarcode; pub use crate::v4::component_vpd::SledFanTray; + + // These error types are not part of the actual API, and are therefore not + // versioned. They are returned by `TryFrom` and similar. + pub use crate::impls::component_vpd::InvalidAssemblyBarcode; + pub use crate::impls::component_vpd::ParseBarcodeError; } pub mod host { From 8857f1ec67c2a8035b44ee879e725af4562c3840 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 9 Sep 2026 11:53:40 -0700 Subject: [PATCH 4/8] draw the rest of the owl --- clients/gateway-client/src/lib.rs | 7 + gateway-api/src/lib.rs | 2 +- gateway-types/src/component_vpd.rs | 5 + gateway-types/src/lib.rs | 1 + .../src/component_vpd/component_vpd.rs | 25 +- .../versions/src/impls/component_vpd.rs | 61 ++- gateway-types/versions/src/latest.rs | 4 + gateway/src/error.rs | 62 +++ gateway/src/http_entrypoints.rs | 28 ++ gateway/src/metrics.rs | 8 +- .../tests/integration_tests/serial_console.rs | 6 +- .../gateway/gateway-3.0.0-dacda2.json.gitstub | 1 + ...-dacda2.json => gateway-4.0.0-428501.json} | 383 +++++++++++++++++- openapi/gateway/gateway-latest.json | 2 +- sp-sim/src/gimlet.rs | 55 +++ sp-sim/src/sidecar.rs | 55 +++ 16 files changed, 687 insertions(+), 18 deletions(-) create mode 100644 gateway-types/src/component_vpd.rs create mode 100644 openapi/gateway/gateway-3.0.0-dacda2.json.gitstub rename openapi/gateway/{gateway-3.0.0-dacda2.json => gateway-4.0.0-428501.json} (91%) diff --git a/clients/gateway-client/src/lib.rs b/clients/gateway-client/src/lib.rs index 3ffdd8e3743..9531ac803ea 100644 --- a/clients/gateway-client/src/lib.rs +++ b/clients/gateway-client/src/lib.rs @@ -75,7 +75,14 @@ progenitor::generate_api!( }, replace = { + Barcode = gateway_types::component_vpd::Barcode, + ComponentVpd = gateway_types::component_vpd::ComponentVpd, + Mpn1Barcode = gateway_types::component_vpd::Mpn1Barcode, + OxideBarcode = gateway_types::component_vpd::OxideBarcode, + PmbusDevice = gateway_types::component_vpd::PmbusDevice, RotSlot = gateway_types::rot::RotSlot, + SledFanTray = gateway_types::component_vpd::SledFanTray, + Tmp11x = gateway_types::component_vpd::Tmp11x, RotState = gateway_types::rot::RotState, RotImageError = gateway_types::rot::RotImageError, Ena = ereport_types::Ena, diff --git a/gateway-api/src/lib.rs b/gateway-api/src/lib.rs index 07135658be4..6d768ebd043 100644 --- a/gateway-api/src/lib.rs +++ b/gateway-api/src/lib.rs @@ -343,7 +343,7 @@ pub trait GatewayApi { #[endpoint { method = GET, path = "/sp/{type}/{slot}/component/{component}/vpd", - versions = COMPONENT_VPD.., + versions = VERSION_COMPONENT_VPD.., }] async fn sp_component_vpd_get( rqctx: RequestContext, diff --git a/gateway-types/src/component_vpd.rs b/gateway-types/src/component_vpd.rs new file mode 100644 index 00000000000..1a9748b36b1 --- /dev/null +++ b/gateway-types/src/component_vpd.rs @@ -0,0 +1,5 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +pub use gateway_types_versions::latest::component_vpd::*; diff --git a/gateway-types/src/lib.rs b/gateway-types/src/lib.rs index 2ea2c61f92c..f45e064b34d 100644 --- a/gateway-types/src/lib.rs +++ b/gateway-types/src/lib.rs @@ -14,6 +14,7 @@ pub mod caboose; pub mod component; pub mod component_details; +pub mod component_vpd; pub mod host; pub mod ignition; pub mod rot; diff --git a/gateway-types/versions/src/component_vpd/component_vpd.rs b/gateway-types/versions/src/component_vpd/component_vpd.rs index 795c56cb9ec..ee5c90d5e76 100644 --- a/gateway-types/versions/src/component_vpd/component_vpd.rs +++ b/gateway-types/versions/src/component_vpd/component_vpd.rs @@ -114,6 +114,12 @@ pub struct Tmp11x { pub eeprom3: u16, } +/// PMBus vital product data (VPD) read from a PMBus device. +/// +/// If the device does not support a particular VPD command, the field in this +/// struct corresponding to that command will be `None`. Otherwise, the value +/// contains the exact bytes returned by the device, including an empty value or +/// any NUL bytes returned by the device. #[derive( Debug, Clone, @@ -125,4 +131,21 @@ pub struct Tmp11x { Serialize, JsonSchema, )] -pub struct PmbusDevice {} +pub struct PmbusDevice { + /// `MFR_ID` (PMBus command 0x99). + pub mfr_id: Option>, + /// `MFR_MODEL` (PMBus command 0x9A). + pub mfr_model: Option>, + /// `MFR_REVISION` (PMBus command 0x9B). + pub mfr_revision: Option>, + /// `MFR_LOCATION` (PMBus command 0x9C). + pub mfr_location: Option>, + /// `MFR_DATE` (PMBus command 0x9D). + pub mfr_date: Option>, + /// `MFR_SERIAL` (PMBus command 0x9E). + pub mfr_serial: Option>, + /// `IC_DEVICE_ID` (PMBus command 0xAD). + pub ic_device_id: Option>, + /// `IC_DEVICE_REV` (PMBus command 0xAE). + pub ic_device_rev: Option>, +} diff --git a/gateway-types/versions/src/impls/component_vpd.rs b/gateway-types/versions/src/impls/component_vpd.rs index 6362e39650f..21cf382a668 100644 --- a/gateway-types/versions/src/impls/component_vpd.rs +++ b/gateway-types/versions/src/impls/component_vpd.rs @@ -3,7 +3,8 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use crate::latest::component_vpd::{ - Barcode, Mpn1Barcode, OxideBarcode, SledFanTray, + Barcode, ComponentVpd, Mpn1Barcode, OxideBarcode, PmbusDevice, SledFanTray, + Tmp11x, }; use gateway_messages::vpd as gw; use std::fmt; @@ -39,7 +40,15 @@ pub enum ParseBarcodeError { } #[derive(thiserror::Error, Debug)] -#[error("invalid {which_barcode} barcode")] +pub enum InvalidComponentVpd { + #[error(transparent)] + Barcode(#[from] ParseBarcodeError), + #[error(transparent)] + SledFanTray(#[from] InvalidAssemblyBarcode), +} + +#[derive(thiserror::Error, Debug)] +#[error("invalid fan assembly {which_barcode} barcode")] pub struct InvalidAssemblyBarcode { which_barcode: &'static str, #[source] @@ -273,6 +282,54 @@ impl fmt::Display for Mpn1Barcode { } } +impl TryFrom for ComponentVpd { + type Error = InvalidComponentVpd; + + fn try_from(value: gw::Vpd) -> Result { + match value { + gw::Vpd::Pmbus(vpd) => Ok(Self::Pmbus(vpd.into())), + gw::Vpd::Barcode(barcode) => Ok(match barcode.try_into()? { + Barcode::Oxide(barcode) => Self::OxideBarcode(barcode), + Barcode::Mpn1(barcode) => Self::Mpn1Barcode(barcode), + }), + gw::Vpd::SledFanTray(vpd) => Ok(Self::SledFanTray(vpd.try_into()?)), + gw::Vpd::Tmp11x(vpd) => Ok(Self::Tmp11x(vpd.into())), + } + } +} + +impl From for PmbusDevice { + fn from(value: gw::PmbusVpd) -> Self { + let gw::PmbusVpd { + mfr_id, + mfr_model, + mfr_revision, + mfr_location, + mfr_date, + mfr_serial, + ic_device_id, + ic_device_rev, + } = value; + Self { + mfr_id: mfr_id.as_bytes().map(<[u8]>::to_vec), + mfr_model: mfr_model.as_bytes().map(<[u8]>::to_vec), + mfr_revision: mfr_revision.as_bytes().map(<[u8]>::to_vec), + mfr_location: mfr_location.as_bytes().map(<[u8]>::to_vec), + mfr_date: mfr_date.as_bytes().map(<[u8]>::to_vec), + mfr_serial: mfr_serial.as_bytes().map(<[u8]>::to_vec), + ic_device_id: ic_device_id.as_bytes().map(<[u8]>::to_vec), + ic_device_rev: ic_device_rev.as_bytes().map(<[u8]>::to_vec), + } + } +} + +impl From for Tmp11x { + fn from(value: gw::Tmp11xVpd) -> Self { + let gw::Tmp11xVpd { id, eeprom1, eeprom2, eeprom3 } = value; + Self { device_id: id, eeprom1, eeprom2, eeprom3 } + } +} + impl TryFrom for SledFanTray { type Error = InvalidAssemblyBarcode; fn try_from(value: gw::SledFanTrayVpd) -> Result { diff --git a/gateway-types/versions/src/latest.rs b/gateway-types/versions/src/latest.rs index 1d92fa46f28..8aa6e1f2428 100644 --- a/gateway-types/versions/src/latest.rs +++ b/gateway-types/versions/src/latest.rs @@ -48,13 +48,17 @@ pub mod component_details { pub mod component_vpd { pub use crate::v4::component_vpd::Barcode; + pub use crate::v4::component_vpd::ComponentVpd; pub use crate::v4::component_vpd::Mpn1Barcode; pub use crate::v4::component_vpd::OxideBarcode; + pub use crate::v4::component_vpd::PmbusDevice; pub use crate::v4::component_vpd::SledFanTray; + pub use crate::v4::component_vpd::Tmp11x; // These error types are not part of the actual API, and are therefore not // versioned. They are returned by `TryFrom` and similar. pub use crate::impls::component_vpd::InvalidAssemblyBarcode; + pub use crate::impls::component_vpd::InvalidComponentVpd; pub use crate::impls::component_vpd::ParseBarcodeError; } diff --git a/gateway/src/error.rs b/gateway/src/error.rs index a78f3599129..dbf45b0a1df 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -5,8 +5,10 @@ //! Error handling facilities for the management gateway. use crate::management_switch::SpIdentifier; +use dropshot::ErrorStatusCode; use dropshot::HttpError; use gateway_messages::SpError; +use gateway_messages::VpdError; use gateway_sp_comms::BindError; pub use gateway_sp_comms::error::CommunicationError; use gateway_sp_comms::error::UpdateError; @@ -186,6 +188,9 @@ fn comms_error_to_http( InlineErrorChain::new(&error).to_string(), ) } + CommunicationError::SpError(SpError::Vpd(vpd_error)) => { + vpd_error_to_http(error, vpd_error) + } _ => http_err_with_message( dropshot::ErrorStatusCode::SERVICE_UNAVAILABLE, "SpCommunicationFailed", @@ -194,6 +199,63 @@ fn comms_error_to_http( } } +fn vpd_error_to_http(error: &dyn Error, kind: &VpdError) -> HttpError { + let (status_code, error_code) = match kind { + VpdError::InvalidDevice => { + (ErrorStatusCode::BAD_REQUEST, "InvalidVpdDevice") + } + VpdError::NotPresent => { + (ErrorStatusCode::SERVICE_UNAVAILABLE, "VpdDeviceNotPresent") + } + VpdError::DeviceError => { + (ErrorStatusCode::INTERNAL_SERVER_ERROR, "VpdDeviceError") + } + VpdError::Unavailable => { + (ErrorStatusCode::SERVICE_UNAVAILABLE, "VpdDeviceUnavailable") + } + VpdError::DeviceTimeout => { + (ErrorStatusCode::SERVICE_UNAVAILABLE, "VpdDeviceTimeout") + } + VpdError::DeviceOff => { + (ErrorStatusCode::SERVICE_UNAVAILABLE, "VpdDeviceOff") + } + VpdError::BadAddress => { + (ErrorStatusCode::INTERNAL_SERVER_ERROR, "InvalidVpdAddress") + } + VpdError::BadBuffer => { + (ErrorStatusCode::INTERNAL_SERVER_ERROR, "InvalidVpdBuffer") + } + VpdError::BadRead => { + (ErrorStatusCode::INTERNAL_SERVER_ERROR, "VpdReadFailed") + } + VpdError::BadWrite => { + (ErrorStatusCode::INTERNAL_SERVER_ERROR, "VpdWriteFailed") + } + VpdError::BadLock => { + (ErrorStatusCode::INTERNAL_SERVER_ERROR, "VpdLockFailed") + } + VpdError::NotImplemented => { + (ErrorStatusCode::NOT_IMPLEMENTED, "VpdNotImplemented") + } + VpdError::IsLocked => (ErrorStatusCode::CONFLICT, "VpdLocked"), + VpdError::PartiallyLocked => { + (ErrorStatusCode::CONFLICT, "VpdPartiallyLocked") + } + VpdError::AlreadyLocked => { + (ErrorStatusCode::CONFLICT, "VpdAlreadyLocked") + } + VpdError::TaskRestarted => { + (ErrorStatusCode::SERVICE_UNAVAILABLE, "VpdTaskRestarted") + } + }; + + http_err_with_message( + status_code, + error_code, + InlineErrorChain::new(&error).to_string(), + ) +} + impl From for HttpError { fn from(error: SpLookupError) -> Self { match error { diff --git a/gateway/src/http_entrypoints.rs b/gateway/src/http_entrypoints.rs index da748f721be..a29e8a6625f 100644 --- a/gateway/src/http_entrypoints.rs +++ b/gateway/src/http_entrypoints.rs @@ -41,6 +41,7 @@ use gateway_types::component::SpComponentList; use gateway_types::component::SpIdentifier; use gateway_types::component::SpState; use gateway_types::component_details::SpComponentDetails; +use gateway_types::component_vpd::ComponentVpd; use gateway_types::host::ComponentFirmwareHashStatus; use gateway_types::host::HostStartupOptions; use gateway_types::ignition::PathSpIgnitionCommand; @@ -707,6 +708,33 @@ impl GatewayApi for GatewayImpl { apictx.latencies.instrument_dropshot_handler(&rqctx, handler).await } + async fn sp_component_vpd_get( + rqctx: RequestContext, + path: Path, + ) -> Result, HttpError> { + let apictx = rqctx.context(); + + let PathSpComponent { sp, component } = path.into_inner(); + let sp_id = sp.into(); + let handler = async { + let sp = apictx.mgmt_switch.sp(sp_id)?; + let component = component_from_str(&component)?; + let vpd = sp.component_vpd(component).await.map_err(|err| { + SpCommsError::SpCommunicationFailed { sp: sp_id, err } + })?; + let vpd = vpd.try_into().map_err(|err| { + http_err_with_message( + dropshot::ErrorStatusCode::INTERNAL_SERVER_ERROR, + "InvalidComponentVpd", + format!("invalid VPD returned by SP: {err}"), + ) + })?; + + Ok(HttpResponseOk(vpd)) + }; + apictx.latencies.instrument_dropshot_handler(&rqctx, handler).await + } + async fn sp_rot_cmpa_get( rqctx: RequestContext, path: Path, diff --git a/gateway/src/metrics.rs b/gateway/src/metrics.rs index 9671b4c5d9e..b9ee4cac314 100644 --- a/gateway/src/metrics.rs +++ b/gateway/src/metrics.rs @@ -636,7 +636,7 @@ impl SpPoller { // These are supposed to always be strings. But, if we // see one that's not a string, fall back to the hex // representation rather than panicking. - let hex = hex::encode(dev.component.id); + let hex = hex::encode(dev.component.id()); slog::warn!( &self.log, "a SP component ID was not a string! this isn't \ @@ -1278,5 +1278,11 @@ fn comms_error_str(error: CommunicationError) -> &'static str { CommunicationError::BadDecompressionSize { .. } => { "bad_decompression_size" } + CommunicationError::HostPanicDataChanged { .. } => { + "host_panic_data_changed" + } + CommunicationError::HostBootfailDataChanged { .. } => { + "host_bootfail_data_changed" + } } } diff --git a/gateway/tests/integration_tests/serial_console.rs b/gateway/tests/integration_tests/serial_console.rs index bea06137ca6..e7bee29359c 100644 --- a/gateway/tests/integration_tests/serial_console.rs +++ b/gateway/tests/integration_tests/serial_console.rs @@ -2,7 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use dropshot::HttpErrorResponseBody; use futures::prelude::*; use gateway_messages::SpPort; use gateway_test_utils::current_simulator_state; @@ -90,12 +89,11 @@ async fn serial_console_detach() { .sp_component_serial_console_attach(&SpType::Sled, 0, "sp3-host-cpu") .await .unwrap_err(); - let gateway_client::Error::UnexpectedResponse(response) = err else { + let gateway_client::Error::ErrorResponse(response) = err else { panic!("unexpected error"); }; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - let err: HttpErrorResponseBody = response.json().await.unwrap(); - assert!(err.message.contains("serial console already attached")); + assert!(response.message.contains("serial console already attached")); // the original websocket should still work ws.send(Message::Binary(b"hello".to_vec())).await.unwrap(); diff --git a/openapi/gateway/gateway-3.0.0-dacda2.json.gitstub b/openapi/gateway/gateway-3.0.0-dacda2.json.gitstub new file mode 100644 index 00000000000..330390555d8 --- /dev/null +++ b/openapi/gateway/gateway-3.0.0-dacda2.json.gitstub @@ -0,0 +1 @@ +4d5bdc6d348b27761348d763c4085f060bcefc18:openapi/gateway/gateway-3.0.0-dacda2.json diff --git a/openapi/gateway/gateway-3.0.0-dacda2.json b/openapi/gateway/gateway-4.0.0-428501.json similarity index 91% rename from openapi/gateway/gateway-3.0.0-dacda2.json rename to openapi/gateway/gateway-4.0.0-428501.json index 7ac0310a3cc..bdc049fc70d 100644 --- a/openapi/gateway/gateway-3.0.0-dacda2.json +++ b/openapi/gateway/gateway-4.0.0-428501.json @@ -7,7 +7,7 @@ "url": "https://oxide.computer", "email": "api@oxide.computer" }, - "version": "3.0.0" + "version": "4.0.0" }, "paths": { "/ignition": { @@ -982,13 +982,14 @@ } ], "responses": { - "default": { - "description": "", - "content": { - "*/*": { - "schema": {} - } - } + "101": { + "description": "Negotiating protocol upgrade from HTTP/1.1 to WebSocket" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" } }, "x-dropshot-websocket": {} @@ -1231,6 +1232,60 @@ } } }, + "/sp/{type}/{slot}/component/{component}/vpd": { + "get": { + "summary": "Get the vital product data (VPD) identity of a component.", + "description": "Not all components have VPD. This endpoint will return an error if the requested component does not advertise the `HAS_VPD` DeviceCapability bit.", + "operationId": "sp_component_vpd_get", + "parameters": [ + { + "in": "path", + "name": "component", + "description": "ID for the component of the SP; this is the internal identifier used by the SP itself to identify its components.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "slot", + "required": true, + "schema": { + "type": "integer", + "format": "uint16", + "minimum": 0 + } + }, + { + "in": "path", + "name": "type", + "required": true, + "schema": { + "$ref": "#/components/schemas/SpType" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ComponentVpd" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, "/sp/{type}/{slot}/ereports": { "post": { "summary": "Request ereports from the target service processor.", @@ -1818,6 +1873,68 @@ }, "components": { "schemas": { + "Barcode": { + "oneOf": [ + { + "type": "object", + "properties": { + "part_number": { + "type": "string" + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "serial_number": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "oxide" + ] + } + }, + "required": [ + "part_number", + "revision", + "serial_number", + "type" + ] + }, + { + "type": "object", + "properties": { + "manufacturer": { + "type": "string" + }, + "part_number": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "serial_number": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "mpn1" + ] + } + }, + "required": [ + "manufacturer", + "part_number", + "revision", + "serial_number", + "type" + ] + } + ] + }, "ComponentFirmwareHashStatus": { "oneOf": [ { @@ -1878,6 +1995,235 @@ } ] }, + "ComponentVpd": { + "oneOf": [ + { + "type": "object", + "properties": { + "part_number": { + "type": "string" + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "serial_number": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "oxide_barcode" + ] + } + }, + "required": [ + "part_number", + "revision", + "serial_number", + "type" + ] + }, + { + "type": "object", + "properties": { + "manufacturer": { + "type": "string" + }, + "part_number": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "serial_number": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "mpn1_barcode" + ] + } + }, + "required": [ + "manufacturer", + "part_number", + "revision", + "serial_number", + "type" + ] + }, + { + "type": "object", + "properties": { + "fan0": { + "$ref": "#/components/schemas/Barcode" + }, + "fan1": { + "$ref": "#/components/schemas/Barcode" + }, + "fan2": { + "$ref": "#/components/schemas/Barcode" + }, + "identity": { + "$ref": "#/components/schemas/OxideBarcode" + }, + "type": { + "type": "string", + "enum": [ + "sled_fan_tray" + ] + }, + "vpd_board_identity": { + "$ref": "#/components/schemas/OxideBarcode" + } + }, + "required": [ + "fan0", + "fan1", + "fan2", + "identity", + "type", + "vpd_board_identity" + ] + }, + { + "type": "object", + "properties": { + "device_id": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "eeprom1": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "eeprom2": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "eeprom3": { + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "type": { + "type": "string", + "enum": [ + "tmp11x" + ] + } + }, + "required": [ + "device_id", + "eeprom1", + "eeprom2", + "eeprom3", + "type" + ] + }, + { + "description": "PMBus vital product data (VPD) read from a PMBus device.\n\nIf the device does not support a particular VPD command, the field in this struct corresponding to that command will be `None`. Otherwise, the value contains the exact bytes returned by the device, including an empty value or any NUL bytes returned by the device.", + "type": "object", + "properties": { + "ic_device_id": { + "nullable": true, + "description": "`IC_DEVICE_ID` (PMBus command 0xAD).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "ic_device_rev": { + "nullable": true, + "description": "`IC_DEVICE_REV` (PMBus command 0xAE).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "mfr_date": { + "nullable": true, + "description": "`MFR_DATE` (PMBus command 0x9D).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "mfr_id": { + "nullable": true, + "description": "`MFR_ID` (PMBus command 0x99).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "mfr_location": { + "nullable": true, + "description": "`MFR_LOCATION` (PMBus command 0x9C).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "mfr_model": { + "nullable": true, + "description": "`MFR_MODEL` (PMBus command 0x9A).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "mfr_revision": { + "nullable": true, + "description": "`MFR_REVISION` (PMBus command 0x9B).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "mfr_serial": { + "nullable": true, + "description": "`MFR_SERIAL` (PMBus command 0x9E).", + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0 + } + }, + "type": { + "type": "string", + "enum": [ + "pmbus" + ] + } + }, + "required": [ + "type" + ] + } + ] + }, "Duration": { "type": "object", "properties": { @@ -2405,6 +2751,27 @@ "type": "string", "format": "uuid" }, + "OxideBarcode": { + "type": "object", + "properties": { + "part_number": { + "type": "string" + }, + "revision": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "serial_number": { + "type": "string" + } + }, + "required": [ + "part_number", + "revision", + "serial_number" + ] + }, "PacketCount": { "type": "object", "properties": { diff --git a/openapi/gateway/gateway-latest.json b/openapi/gateway/gateway-latest.json index 7b2c936f827..a3deb05c24c 120000 --- a/openapi/gateway/gateway-latest.json +++ b/openapi/gateway/gateway-latest.json @@ -1 +1 @@ -gateway-3.0.0-dacda2.json \ No newline at end of file +gateway-4.0.0-428501.json \ No newline at end of file diff --git a/sp-sim/src/gimlet.rs b/sp-sim/src/gimlet.rs index 481cd38e963..1eeb0f1c36d 100644 --- a/sp-sim/src/gimlet.rs +++ b/sp-sim/src/gimlet.rs @@ -1287,6 +1287,12 @@ impl SpHandler for Handler { Ok(power_state.into()) } + fn power_state_with_reason( + &mut self, + ) -> Result { + Err(SpError::RequestUnsupportedForSp) + } + fn set_power_state( &mut self, sender: Sender, @@ -1547,6 +1553,22 @@ impl SpHandler for Handler { self.update_state.get_component_caboose_value(component, slot, key, buf) } + fn component_get_vpd( + &mut self, + component: SpComponent, + _buf: &mut [u8], + ) -> Result { + // TODO(eliza): we should allow configuring a VPD response in the sim + // config file... + warn!( + &self.log, + "asked to read VPD for component, which the simulator doesn't + implement yet"; + "component" => ?component, + ); + Err(SpError::RequestUnsupportedForComponent) + } + fn read_sensor( &mut self, request: gateway_messages::SensorRequest, @@ -1727,6 +1749,39 @@ impl SpHandler for Handler { fn get_host_flash_hash(&mut self, slot: u16) -> Result<[u8; 32], SpError> { self.update_state.get_host_flash_hash(slot) } + + fn get_pmbus_status( + &mut self, + rail: &gateway_messages::PowerRailName, + ) -> Result { + // TODO(eliza): we're gonna want a way to configure fake PMBus statuses + // in the config file... + warn!( + &self.log, + "asked to read PMBus status, which the simulator doesn't + implement yet"; + "rail" => ?rail, + ); + Err(SpError::RequestUnsupportedForSp) + } + + fn get_host_panic_payload( + &mut self, + _request: Option, + _len: u32, + _trailing_tx_buf: &mut [u8], + ) -> Result { + Err(SpError::RequestUnsupportedForSp) + } + + fn get_host_bootfail_payload( + &mut self, + _request: Option, + _len: u32, + _trailing_tx_buf: &mut [u8], + ) -> Result { + Err(SpError::RequestUnsupportedForSp) + } } impl SimSpHandler for Handler { diff --git a/sp-sim/src/sidecar.rs b/sp-sim/src/sidecar.rs index e8442211127..4306e9eba27 100644 --- a/sp-sim/src/sidecar.rs +++ b/sp-sim/src/sidecar.rs @@ -885,6 +885,12 @@ impl SpHandler for Handler { Ok(self.power_state) } + fn power_state_with_reason( + &mut self, + ) -> Result { + Err(SpError::RequestUnsupportedForSp) + } + fn set_power_state( &mut self, sender: Sender, @@ -1149,6 +1155,22 @@ impl SpHandler for Handler { self.update_state.get_component_caboose_value(component, slot, key, buf) } + fn component_get_vpd( + &mut self, + component: SpComponent, + _buf: &mut [u8], + ) -> Result { + // TODO(eliza): we should allow configuring a VPD response in the sim + // config file... + warn!( + &self.log, + "asked to read VPD for component, which the simulator doesn't + implement yet"; + "component" => ?component, + ); + Err(SpError::RequestUnsupportedForComponent) + } + fn read_sensor( &mut self, request: gateway_messages::SensorRequest, @@ -1325,6 +1347,39 @@ impl SpHandler for Handler { fn get_host_flash_hash(&mut self, _slot: u16) -> Result<[u8; 32], SpError> { Err(SpError::RequestUnsupportedForSp) } + + fn get_pmbus_status( + &mut self, + rail: &gateway_messages::PowerRailName, + ) -> Result { + // TODO(eliza): we're gonna want a way to configure fake PMBus statuses + // in the config file... + warn!( + &self.log, + "asked to read PMBus status, which the simulator doesn't + implement yet"; + "rail" => ?rail, + ); + Err(SpError::RequestUnsupportedForSp) + } + + fn get_host_panic_payload( + &mut self, + _request: Option, + _len: u32, + _trailing_tx_buf: &mut [u8], + ) -> Result { + Err(SpError::RequestUnsupportedForSp) + } + + fn get_host_bootfail_payload( + &mut self, + _request: Option, + _len: u32, + _trailing_tx_buf: &mut [u8], + ) -> Result { + Err(SpError::RequestUnsupportedForSp) + } } impl SimSpHandler for Handler { From 0c3abe203e97a0feabbe2b1e5fae6b4d61a35cea Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 9 Sep 2026 12:37:07 -0700 Subject: [PATCH 5/8] fixy --- gateway-types/versions/src/component_vpd/component_vpd.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/gateway-types/versions/src/component_vpd/component_vpd.rs b/gateway-types/versions/src/component_vpd/component_vpd.rs index ee5c90d5e76..5d153fce87a 100644 --- a/gateway-types/versions/src/component_vpd/component_vpd.rs +++ b/gateway-types/versions/src/component_vpd/component_vpd.rs @@ -17,6 +17,7 @@ use serde::{Deserialize, Serialize}; JsonSchema, )] #[serde(tag = "type", rename_all = "snake_case")] +#[allow(clippy::large_enum_variant)] pub enum ComponentVpd { OxideBarcode(OxideBarcode), Mpn1Barcode(Mpn1Barcode), From 9cef4d0e64563e7022e5b4ef30b686c3344e17d0 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 9 Sep 2026 14:12:26 -0700 Subject: [PATCH 6/8] hakari --- Cargo.lock | 70 ++++++++++++--------------------------- workspace-hack/Cargo.toml | 22 +++++++----- 2 files changed, 35 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9162963ba18..49bc19e756e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4250,7 +4250,7 @@ dependencies = [ "clap", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-types", "omicron-uuid-kinds", "omicron-workspace-hack", @@ -4277,7 +4277,7 @@ dependencies = [ "chrono", "daft", "ereport-types", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-types", "omicron-uuid-kinds", "omicron-workspace-hack", @@ -4303,40 +4303,13 @@ dependencies = [ "zerocopy 0.8.55", ] -[[package]] -name = "gateway-ereport-messages" -version = "0.1.0" -source = "git+https://github.com/oxidecomputer/management-gateway-service?rev=6c0aca2545a73fd75536e149d29faa7108be5862#6c0aca2545a73fd75536e149d29faa7108be5862" -dependencies = [ - "serde", - "zerocopy 0.8.55", -] - [[package]] name = "gateway-messages" version = "0.1.0" source = "git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1#438cd185666d5f164548885873f0f5df9a38eed1" dependencies = [ "bitflags 2.11.0", - "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", - "hubpack", - "serde", - "serde-big-array", - "serde_repr", - "smoltcp 0.9.1", - "static_assertions", - "strum 0.27.2", - "strum_macros 0.27.2", - "uuid", - "zerocopy 0.8.55", -] - -[[package]] -name = "gateway-messages" -version = "0.1.0" -source = "git+https://github.com/oxidecomputer/management-gateway-service?rev=6c0aca2545a73fd75536e149d29faa7108be5862#6c0aca2545a73fd75536e149d29faa7108be5862" -dependencies = [ - "bitflags 2.11.0", + "gateway-ereport-messages", "hubpack", "serde", "serde-big-array", @@ -4359,8 +4332,8 @@ dependencies = [ "base64 0.22.1", "futures", "fxhash", - "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-ereport-messages", + "gateway-messages", "hex", "hubpack", "hubtools 0.4.9", @@ -4395,7 +4368,7 @@ dependencies = [ "camino", "dropshot", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-types", "omicron-gateway", "omicron-test-utils", @@ -4422,7 +4395,7 @@ version = "0.1.0" dependencies = [ "daft", "dropshot", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "hex", "omicron-uuid-kinds", "omicron-workspace-hack", @@ -6997,7 +6970,7 @@ dependencies = [ "clap", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "libc", "omicron-gateway", @@ -7707,7 +7680,7 @@ dependencies = [ "fmd-adm-sys", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "gateway-types", "httpmock", @@ -7839,7 +7812,7 @@ dependencies = [ "dropshot", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "gateway-types", "http", @@ -8257,7 +8230,7 @@ dependencies = [ "dropshot", "fmd-adm-sys", "futures", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "headers", "hickory-resolver 0.25.2", @@ -9114,7 +9087,7 @@ dependencies = [ "futures", "gateway-api", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-sp-comms", "gateway-test-utils", "gateway-types", @@ -9290,7 +9263,7 @@ dependencies = [ "fmd-adm-sys", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "gateway-types", "headers", @@ -9513,7 +9486,7 @@ dependencies = [ "fmd-adm-sys", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "gateway-types", "http", @@ -10024,14 +9997,15 @@ dependencies = [ "futures-sink", "futures-task", "futures-util", - "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=6c0aca2545a73fd75536e149d29faa7108be5862)", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=6c0aca2545a73fd75536e149d29faa7108be5862)", + "gateway-messages", "generic-array 0.14.7", "getrandom 0.2.17", + "getrandom 0.3.4", "getrandom 0.4.3", "group 0.13.0", "hashbrown 0.15.5", "hashbrown 0.16.1", + "hashbrown 0.17.0", "heck 0.4.1", "hex", "hickory-proto 0.25.2", @@ -10142,7 +10116,6 @@ dependencies = [ "x509-cert", "zerocopy 0.8.55", "zeroize", - "zip 0.6.6", "zip 4.6.1", ] @@ -14575,7 +14548,7 @@ dependencies = [ "either", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "gateway-types", "http", @@ -15065,8 +15038,8 @@ dependencies = [ "clap", "dropshot", "futures", - "gateway-ereport-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-ereport-messages", + "gateway-messages", "gateway-types", "hex", "hubtools 0.4.7 (git+https://github.com/oxidecomputer/hubtools.git?rev=2b1ef9b38d75563ea800baa3b17327eec17b1b7a)", @@ -17890,7 +17863,7 @@ dependencies = [ "fs-err 3.3.0", "futures", "gateway-client", - "gateway-messages 0.1.0 (git+https://github.com/oxidecomputer/management-gateway-service?rev=438cd185666d5f164548885873f0f5df9a38eed1)", + "gateway-messages", "gateway-test-utils", "gateway-types", "hex", @@ -18885,7 +18858,6 @@ dependencies = [ "bzip2 0.4.4", "crc32fast", "crossbeam-utils", - "flate2", ] [[package]] diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index d9d151cc286..11688409813 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -64,13 +64,13 @@ futures-core = { version = "0.3.32" } futures-sink = { version = "0.3.32" } futures-task = { version = "0.3.32", default-features = false, features = ["std"] } futures-util = { version = "0.3.32", features = ["channel", "io", "sink"] } -gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6c0aca2545a73fd75536e149d29faa7108be5862", default-features = false, features = ["debug-impls", "serde"] } -gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6c0aca2545a73fd75536e149d29faa7108be5862", features = ["std"] } +gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "438cd185666d5f164548885873f0f5df9a38eed1", features = ["std"] } generic-array = { version = "0.14.7", default-features = false, features = ["more_lengths", "zeroize"] } getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2.17", default-features = false, features = ["js", "rdrand", "std"] } getrandom-9fbad63c4bcf4a8f = { package = "getrandom", version = "0.4.3", default-features = false, features = ["std", "sys_rng", "wasm_js"] } group = { version = "0.13.0", default-features = false, features = ["alloc"] } hashbrown-3575ec1268b04181 = { package = "hashbrown", version = "0.15.5" } +hashbrown-9067fe90e8c1f593 = { package = "hashbrown", version = "0.17.0", default-features = false, features = ["default-hasher"] } hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16.1" } hex = { version = "0.4.3", features = ["serde"] } hickory-proto = { version = "0.25.2", features = ["serde", "text-parsing"] } @@ -166,8 +166,7 @@ uuid = { version = "1.23.4", features = ["serde", "v4"] } x509-cert = { version = "0.2.5" } zerocopy = { version = "0.8.55", default-features = false, features = ["derive", "simd"] } zeroize = { version = "1.9.0", features = ["aarch64", "serde", "std", "zeroize_derive"] } -zip-164d15cefe24d7eb = { package = "zip", version = "4.6.1", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } -zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } +zip = { version = "4.6.1", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } [build-dependencies] ahash = { version = "0.8.12" } @@ -218,13 +217,13 @@ futures-core = { version = "0.3.32" } futures-sink = { version = "0.3.32" } futures-task = { version = "0.3.32", default-features = false, features = ["std"] } futures-util = { version = "0.3.32", features = ["channel", "io", "sink"] } -gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6c0aca2545a73fd75536e149d29faa7108be5862", default-features = false, features = ["debug-impls", "serde"] } -gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6c0aca2545a73fd75536e149d29faa7108be5862", features = ["std"] } +gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "438cd185666d5f164548885873f0f5df9a38eed1", features = ["std"] } generic-array = { version = "0.14.7", default-features = false, features = ["more_lengths", "zeroize"] } getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2.17", default-features = false, features = ["js", "rdrand", "std"] } getrandom-9fbad63c4bcf4a8f = { package = "getrandom", version = "0.4.3", default-features = false, features = ["std", "sys_rng", "wasm_js"] } group = { version = "0.13.0", default-features = false, features = ["alloc"] } hashbrown-3575ec1268b04181 = { package = "hashbrown", version = "0.15.5" } +hashbrown-9067fe90e8c1f593 = { package = "hashbrown", version = "0.17.0", default-features = false, features = ["default-hasher"] } hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16.1" } heck = { version = "0.4.1", features = ["unicode"] } hex = { version = "0.4.3", features = ["serde"] } @@ -326,13 +325,13 @@ vergen-lib = { version = "9.1.0", features = ["cargo", "git", "rustc"] } x509-cert = { version = "0.2.5" } zerocopy = { version = "0.8.55", default-features = false, features = ["derive", "simd"] } zeroize = { version = "1.9.0", features = ["aarch64", "serde", "std", "zeroize_derive"] } -zip-164d15cefe24d7eb = { package = "zip", version = "4.6.1", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } -zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } +zip = { version = "4.6.1", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } [target.x86_64-unknown-linux-gnu.dependencies] cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } linux-raw-sys = { version = "0.4.15", default-features = false, features = ["elf", "errno", "general", "ioctl", "no_std", "system"] } @@ -348,6 +347,7 @@ tokio-rustls = { version = "0.26.4", default-features = false, features = ["aws- cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } linux-raw-sys = { version = "0.4.15", default-features = false, features = ["elf", "errno", "general", "ioctl", "no_std", "system"] } @@ -362,6 +362,7 @@ tokio-rustls = { version = "0.26.4", default-features = false, features = ["aws- [target.x86_64-apple-darwin.dependencies] cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } errno = { version = "0.3.14" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } miniz_oxide = { version = "0.8.9", default-features = false, features = ["simd", "with-alloc"] } @@ -375,6 +376,7 @@ tokio-rustls = { version = "0.26.4", default-features = false, features = ["aws- [target.x86_64-apple-darwin.build-dependencies] cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } errno = { version = "0.3.14" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } miniz_oxide = { version = "0.8.9", default-features = false, features = ["simd", "with-alloc"] } @@ -388,6 +390,7 @@ tokio-rustls = { version = "0.26.4", default-features = false, features = ["aws- [target.aarch64-apple-darwin.dependencies] cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } errno = { version = "0.3.14" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } miniz_oxide = { version = "0.8.9", default-features = false, features = ["simd", "with-alloc"] } @@ -401,6 +404,7 @@ tokio-rustls = { version = "0.26.4", default-features = false, features = ["aws- [target.aarch64-apple-darwin.build-dependencies] cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } errno = { version = "0.3.14" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } miniz_oxide = { version = "0.8.9", default-features = false, features = ["simd", "with-alloc"] } @@ -418,6 +422,7 @@ cookie = { version = "0.18.1", default-features = false, features = ["percent-en dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } errno = { version = "0.3.14" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } inout = { version = "0.2.2", default-features = false, features = ["block-padding"] } @@ -438,6 +443,7 @@ cookie = { version = "0.18.1", default-features = false, features = ["percent-en dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } errno = { version = "0.3.14" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2"] } hyper-util = { version = "0.1.20", features = ["full"] } inout = { version = "0.2.2", default-features = false, features = ["block-padding"] } From 89f8e6a4743cfbb0fd63522a73ea576f09c648a6 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Thu, 10 Sep 2026 10:13:52 -0700 Subject: [PATCH 7/8] you have to also update faux-mgs --- package-manifest.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-manifest.toml b/package-manifest.toml index edb753576ce..e7105c67db0 100644 --- a/package-manifest.toml +++ b/package-manifest.toml @@ -605,8 +605,8 @@ source.type = "prebuilt" source.repo = "management-gateway-service" # In general, this commit should match the pinned revision of `gateway-sp-comms` # in `Cargo.toml`. -source.commit = "6c0aca2545a73fd75536e149d29faa7108be5862" -source.sha256 = "48748a5090ed9c7b4d61cc127d9c6959b228864b75a4ab111468dc22ae20d656" +source.commit = "438cd185666d5f164548885873f0f5df9a38eed1" +source.sha256 = "176fab5f1fdd892832d42f11fdef97734184d22400d7d76835c0d83981c25c4b" output.type = "zone" output.intermediate_only = true From d4dc8e72af2e2dde2c44b0899cd6c8dd5e706125 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 11 Sep 2026 13:05:45 -0700 Subject: [PATCH 8/8] post rebase unbreaking of things --- Cargo.lock | 19 ++++--------------- sp-sim/src/gimlet.rs | 2 +- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04936bcbc3c..3da5011b7f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5213,7 +5213,7 @@ dependencies = [ "path-slash 0.1.5", "rsa 0.9.10", "thiserror 1.0.69", - "tlvc 0.3.1 (git+https://github.com/oxidecomputer/tlvc)", + "tlvc 0.3.1", "tlvc-text 0.3.0", "toml 0.7.8", "x509-cert", @@ -5234,7 +5234,7 @@ dependencies = [ "path-slash 0.1.5", "rsa 0.9.10", "thiserror 1.0.69", - "tlvc 0.3.1 (git+https://github.com/oxidecomputer/tlvc)", + "tlvc 0.3.1", "tlvc-text 0.3.0", "toml 0.7.8", "x509-cert", @@ -5255,7 +5255,7 @@ dependencies = [ "path-slash 0.2.1", "rsa 0.9.10", "thiserror 2.0.18", - "tlvc 0.4.1", + "tlvc 0.4.1 (git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d8601ffd68853957da3)", "tlvc-text 0.4.0", "toml 1.1.2+spec-1.1.0", "x509-cert", @@ -16069,17 +16069,6 @@ dependencies = [ "zerocopy-derive 0.8.55", ] -[[package]] -name = "tlvc" -version = "0.4.1" -source = "git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d8601ffd68853957da3#7a96eab94c8aec9120412d8601ffd68853957da3" -dependencies = [ - "crc", - "thiserror 2.0.18", - "zerocopy 0.8.55", - "zerocopy-derive 0.8.55", -] - [[package]] name = "tlvc-text" version = "0.3.0" @@ -16098,7 +16087,7 @@ source = "git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d86 dependencies = [ "ron", "serde", - "tlvc 0.4.1", + "tlvc 0.4.1 (git+https://github.com/oxidecomputer/tlvc?rev=7a96eab94c8aec9120412d8601ffd68853957da3)", "zerocopy 0.8.55", ] diff --git a/sp-sim/src/gimlet.rs b/sp-sim/src/gimlet.rs index 12c47809587..c1634d8f168 100644 --- a/sp-sim/src/gimlet.rs +++ b/sp-sim/src/gimlet.rs @@ -1770,7 +1770,7 @@ impl SpHandler for Handler { fn get_pmbus_status( &mut self, - rail: &PowerRailName, + _rail: &PowerRailName, ) -> Result { Err(SpError::RequestUnsupportedForSp) }