From ff04d4235f3f9efd0349f313fdc60bf618b8691d Mon Sep 17 00:00:00 2001 From: Matt Keeter Date: Fri, 11 Oct 2024 15:18:43 -0400 Subject: [PATCH] Add `control-plane-agent` and `host-sp-comms` to Grapefruit (#1898) - Rename `gimlet_seq` to `cpu_seq` in Idol and API crates, and use it for both Gimlet and Grapefruit - Remove fan power control APIs, which are seemingly unused - Update `grapefruit-seq-server` to do mock power control, like `mock-gimlet-seq-server` - Rename the `gimlet` BSP in `control-plane-agent` to `cpu-sled`, and use it for both Gimlet and Cosmo - Add `usart6` support to `host-sp-comms`, since that's what Grapefruit uses - Add `host-sp-comms`, `control-plane-agent`, and `stm32h7-update-server` to `grapefruit/app.toml` - Initial Grapefruit / Cosmo inventory support in `control-plane-agent` and `host-sp-comms` --- Cargo.lock | 176 +++++++++++------- Cargo.toml | 2 +- app/gimlet/base.toml | 4 +- app/gimletlet/app.toml | 4 +- app/grapefruit/app.toml | 69 ++++++- build/xtask/src/dist.rs | 2 +- drv/cosmo-hf/Cargo.toml | 2 +- drv/cosmo-hf/src/main.rs | 7 +- .../Cargo.toml | 2 +- .../src/lib.rs | 0 .../Cargo.toml | 4 +- drv/{gimlet-seq-api => cpu-seq-api}/build.rs | 2 +- .../src/lib.rs | 2 +- drv/gimlet-seq-server/Cargo.toml | 4 +- drv/gimlet-seq-server/build.rs | 2 +- drv/gimlet-seq-server/src/main.rs | 26 +-- drv/grapefruit-seq-api/Cargo.toml | 23 --- drv/grapefruit-seq-api/build.rs | 10 - drv/grapefruit-seq-api/src/lib.rs | 11 -- drv/grapefruit-seq-server/Cargo.toml | 3 + drv/grapefruit-seq-server/build.rs | 2 +- drv/grapefruit-seq-server/src/main.rs | 66 ++++++- drv/mock-gimlet-seq-server/Cargo.toml | 4 +- drv/mock-gimlet-seq-server/build.rs | 2 +- drv/mock-gimlet-seq-server/src/main.rs | 16 +- idl/{gimlet-seq.idol => cpu-seq.idol} | 20 +- idl/grapefruit-seq.idol | 11 -- task/control-plane-agent/Cargo.toml | 6 +- task/control-plane-agent/src/inventory.rs | 21 ++- task/control-plane-agent/src/main.rs | 32 ++-- .../{mgs_gimlet.rs => mgs_compute_sled.rs} | 12 +- .../host_phase2.rs | 0 task/control-plane-agent/src/update/mod.rs | 2 +- task/gimlet-inspector/Cargo.toml | 2 +- task/gimlet-inspector/src/main.rs | 2 +- task/host-sp-comms/Cargo.toml | 4 +- task/host-sp-comms/src/bsp/grapefruit.rs | 90 +++++++++ task/host-sp-comms/src/main.rs | 42 ++++- task/net/Cargo.toml | 4 +- task/net/src/bsp/gimlet_bcdef.rs | 2 +- task/packrat/Cargo.toml | 4 +- task/packrat/src/gimlet.rs | 2 +- task/power/Cargo.toml | 4 +- task/power/src/bsp/gimlet_bcdef.rs | 2 +- task/spd/Cargo.toml | 3 +- task/spd/src/main.rs | 3 +- task/thermal/Cargo.toml | 4 +- task/thermal/src/bsp/gimlet_bcdef.rs | 4 +- 48 files changed, 460 insertions(+), 261 deletions(-) rename drv/{gimlet-state => cpu-power-state}/Cargo.toml (91%) rename drv/{gimlet-state => cpu-power-state}/src/lib.rs (100%) rename drv/{gimlet-seq-api => cpu-seq-api}/Cargo.toml (84%) rename drv/{gimlet-seq-api => cpu-seq-api}/build.rs (82%) rename drv/{gimlet-seq-api => cpu-seq-api}/src/lib.rs (96%) delete mode 100644 drv/grapefruit-seq-api/Cargo.toml delete mode 100644 drv/grapefruit-seq-api/build.rs delete mode 100644 drv/grapefruit-seq-api/src/lib.rs rename idl/{gimlet-seq.idol => cpu-seq.idol} (68%) delete mode 100644 idl/grapefruit-seq.idol rename task/control-plane-agent/src/{mgs_gimlet.rs => mgs_compute_sled.rs} (99%) rename task/control-plane-agent/src/{mgs_gimlet => mgs_compute_sled}/host_phase2.rs (100%) create mode 100644 task/host-sp-comms/src/bsp/grapefruit.rs diff --git a/Cargo.lock b/Cargo.lock index b74e3a1eaf..3bf1cf0cfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,12 @@ dependencies = [ "zerocopy 0.6.6", ] +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.3" @@ -485,6 +491,9 @@ name = "cc" version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -715,9 +724,9 @@ checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -730,12 +739,9 @@ checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-bigint" @@ -1019,7 +1025,7 @@ dependencies = [ "build-util", "cortex-m", "counters", - "drv-grapefruit-seq-api", + "drv-cpu-seq-api", "drv-hash-api", "drv-hf-api", "hubpack", @@ -1033,6 +1039,30 @@ dependencies = [ "zerocopy 0.6.6", ] +[[package]] +name = "drv-cpu-power-state" +version = "0.1.0" +dependencies = [ + "counters", + "num-traits", + "userlib", + "zerocopy 0.6.6", +] + +[[package]] +name = "drv-cpu-seq-api" +version = "0.1.0" +dependencies = [ + "counters", + "derive-idol-err", + "drv-cpu-power-state", + "idol", + "idol-runtime", + "num-traits", + "userlib", + "zerocopy 0.6.6", +] + [[package]] name = "drv-eeprom" version = "0.1.0" @@ -1133,20 +1163,6 @@ dependencies = [ "zerocopy 0.6.6", ] -[[package]] -name = "drv-gimlet-seq-api" -version = "0.1.0" -dependencies = [ - "counters", - "derive-idol-err", - "drv-gimlet-state", - "idol", - "idol-runtime", - "num-traits", - "userlib", - "zerocopy 0.6.6", -] - [[package]] name = "drv-gimlet-seq-server" version = "0.1.0" @@ -1159,8 +1175,8 @@ dependencies = [ "cfg-if", "cortex-m", "counters", - "drv-gimlet-seq-api", - "drv-gimlet-state", + "drv-cpu-power-state", + "drv-cpu-seq-api", "drv-hf-api", "drv-i2c-api", "drv-i2c-devices", @@ -1185,28 +1201,6 @@ dependencies = [ "zerocopy 0.6.6", ] -[[package]] -name = "drv-gimlet-state" -version = "0.1.0" -dependencies = [ - "counters", - "num-traits", - "userlib", - "zerocopy 0.6.6", -] - -[[package]] -name = "drv-grapefruit-seq-api" -version = "0.1.0" -dependencies = [ - "counters", - "idol", - "idol-runtime", - "num-traits", - "userlib", - "zerocopy 0.6.6", -] - [[package]] name = "drv-grapefruit-seq-server" version = "0.1.0" @@ -1215,6 +1209,8 @@ dependencies = [ "cfg-if", "counters", "drv-auxflash-api", + "drv-cpu-power-state", + "drv-cpu-seq-api", "drv-spi-api", "drv-stm32xx-sys-api", "gnarle", @@ -1223,6 +1219,7 @@ dependencies = [ "num-traits", "ringbuf", "sha3", + "task-jefe-api", "userlib", "zerocopy 0.6.6", ] @@ -1687,8 +1684,8 @@ dependencies = [ name = "drv-mock-gimlet-seq-server" version = "0.1.0" dependencies = [ - "drv-gimlet-seq-api", - "drv-gimlet-state", + "drv-cpu-power-state", + "drv-cpu-seq-api", "idol", "idol-runtime", "num-traits", @@ -2651,6 +2648,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499" +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fletcher" version = "0.3.0" @@ -2672,7 +2679,7 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "gateway-messages" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/management-gateway-service#1885b52b0601f4215c020cb17516c6a7fa1e2c9d" +source = "git+https://github.com/oxidecomputer/management-gateway-service#c8abf88bc0aeb3aa411eea276c73abdea405f7ba" dependencies = [ "bitflags 2.6.0", "hubpack", @@ -3458,9 +3465,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -3471,6 +3478,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "multimap" version = "0.8.3" @@ -4816,7 +4832,7 @@ dependencies = [ "drv-auxflash-api", "drv-caboose", "drv-caboose-pos", - "drv-gimlet-seq-api", + "drv-cpu-seq-api", "drv-hf-api", "drv-ignition-api", "drv-lpc55-update-api", @@ -4937,7 +4953,7 @@ version = "0.1.0" dependencies = [ "build-util", "counters", - "drv-gimlet-seq-api", + "drv-cpu-seq-api", "gimlet-inspector-protocol", "hubpack", "idol", @@ -4990,7 +5006,7 @@ dependencies = [ "corncobs", "cortex-m", "counters", - "drv-gimlet-seq-api", + "drv-cpu-seq-api", "drv-hf-api", "drv-i2c-api", "drv-i2c-devices", @@ -5129,7 +5145,7 @@ dependencies = [ "cfg-if", "cortex-m", "counters", - "drv-gimlet-seq-api", + "drv-cpu-seq-api", "drv-medusa-seq-api", "drv-psc-seq-api", "drv-sidecar-seq-api", @@ -5209,7 +5225,7 @@ dependencies = [ "anyhow", "build-util", "cfg-if", - "drv-gimlet-seq-api", + "drv-cpu-seq-api", "idol", "idol-runtime", "mutable-statics", @@ -5269,7 +5285,7 @@ dependencies = [ "build-util", "cfg-if", "cortex-m", - "drv-gimlet-seq-api", + "drv-cpu-seq-api", "drv-i2c-api", "drv-i2c-devices", "drv-sidecar-seq-api", @@ -5392,8 +5408,7 @@ dependencies = [ "build-util", "cfg-if", "cortex-m", - "drv-gimlet-seq-api", - "drv-gimlet-state", + "drv-cpu-seq-api", "drv-i2c-api", "drv-stm32xx-i2c", "drv-stm32xx-sys-api", @@ -5424,7 +5439,7 @@ dependencies = [ "build-util", "cortex-m", "counters", - "drv-gimlet-seq-api", + "drv-cpu-seq-api", "drv-i2c-api", "drv-i2c-devices", "drv-onewire", @@ -5792,22 +5807,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 1.0.94", + "syn 2.0.52", ] [[package]] @@ -6536,4 +6551,35 @@ dependencies = [ "bzip2", "crc32fast", "crossbeam-utils", + "flate2", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.12+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" +dependencies = [ + "cc", + "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index b6a7a3294b..1c376057b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -118,7 +118,7 @@ vcell = { version = "0.1.2", default-features = false } walkdir = { version = "2.0.0", default-features = false } zerocopy = { version = "0.6.1", default-features = false } zeroize = { version = "1.5.7", default-features = false, features = ["zeroize_derive"] } -zip = { version = "0.6", default-features = false, features = ["bzip2"] } +zip = { version = "0.6", default-features = false, features = ["bzip2", "deflate", "zstd"] } # Oxide forks and repos attest-data = { git = "https://github.com/oxidecomputer/dice-util", default-features = false, version = "0.4.0" } diff --git a/app/gimlet/base.toml b/app/gimlet/base.toml index 4368fcf0a1..3b66000a72 100644 --- a/app/gimlet/base.toml +++ b/app/gimlet/base.toml @@ -234,7 +234,7 @@ priority = 7 max-sizes = {flash = 65536, ram = 65536} stacksize = 5080 start = true -task-slots = ["sys", "gimlet_seq", "hf", "control_plane_agent", "net", "packrat", "i2c_driver", { spi_driver = "spi2_driver" }, "sprot"] +task-slots = ["sys", { cpu_seq = "gimlet_seq" }, "hf", "control_plane_agent", "net", "packrat", "i2c_driver", { spi_driver = "spi2_driver" }, "sprot"] notifications = ["jefe-state-change", "usart-irq", "multitimer", "control-plane-agent"] [tasks.udpecho] @@ -271,7 +271,7 @@ task-slots = [ "update_server", "sys", "hf", - "gimlet_seq", + { cpu_seq = "gimlet_seq" }, "validate", "sensor", "sprot", diff --git a/app/gimletlet/app.toml b/app/gimletlet/app.toml index 9a7baef248..b1ac7c6fe5 100644 --- a/app/gimletlet/app.toml +++ b/app/gimletlet/app.toml @@ -64,7 +64,7 @@ task-slots = [ "update_server", "sys", "hf", - "gimlet_seq", + { cpu_seq = "gimlet_seq" }, "validate", "sensor", "sprot", @@ -109,7 +109,7 @@ priority = 8 max-sizes = {flash = 65536, ram = 65536} stacksize = 4096 start = true -task-slots = ["sys", "gimlet_seq", "hf", "control_plane_agent", "net", "packrat", "sprot"] +task-slots = ["sys", { cpu_seq = "gimlet_seq" }, "hf", "control_plane_agent", "net", "packrat", "sprot"] notifications = [ "jefe-state-change", "usart-irq", diff --git a/app/grapefruit/app.toml b/app/grapefruit/app.toml index 09ba4d2bcb..0bf0e79a9d 100644 --- a/app/grapefruit/app.toml +++ b/app/grapefruit/app.toml @@ -14,6 +14,7 @@ requires = {flash = 32768, ram = 8192} features = ["dump"] [caboose] +tasks = ["control_plane_agent"] region = "flash" size = 256 default = true @@ -30,7 +31,8 @@ extern-regions = ["sram1", "sram2", "sram3", "sram4"] [tasks.jefe.config.allowed-callers] set_reset_reason = ["sys"] -request_reset = ["hiffy", "udprpc"] +set_state = ["grapefruit_seq"] +request_reset = ["hiffy", "udprpc", "control_plane_agent"] [tasks.sys] name = "drv-stm32xx-sys" @@ -174,7 +176,7 @@ priority = 4 max-sizes = {flash = 131072, ram = 16384 } stacksize = 2600 start = true -task-slots = ["sys", {spi = "spi2_driver"}, "auxflash"] +task-slots = ["sys", {spi = "spi2_driver"}, "auxflash", "jefe"] [tasks.thermal] name = "task-thermal" @@ -186,6 +188,17 @@ start = true task-slots = ["i2c_driver", "sensor", "jefe"] notifications = ["timer"] +[tasks.update_server] +name = "stm32h7-update-server" +priority = 3 +max-sizes = {flash = 16384, ram = 4096} +stacksize = 2048 +start = true +uses = ["flash_controller"] +extern-regions = ["bank2"] +interrupts = {"flash_controller.irq" = "flash-irq"} +notifications = ["flash-irq"] + [tasks.sensor] name = "task-sensor" priority = 4 @@ -193,6 +206,51 @@ max-sizes = {flash = 16384, ram = 8192 } stacksize = 1024 start = true +[tasks.host_sp_comms] +name = "task-host-sp-comms" +features = ["stm32h753", "usart6", "baud_rate_3M", "hardware_flow_control", "vlan", "grapefruit"] +uses = ["usart6", "dbgmcu"] +interrupts = {"usart6.irq" = "usart-irq"} +priority = 7 +max-sizes = {flash = 65536, ram = 65536} +stacksize = 5080 +start = true +task-slots = ["sys", "hf", "packrat", "control_plane_agent", "net", { cpu_seq = "grapefruit_seq" }, { spi_driver = "spi2_driver" }, "sprot"] +notifications = ["jefe-state-change", "usart-irq", "multitimer", "control-plane-agent"] + +[tasks.control_plane_agent] +name = "task-control-plane-agent" +priority = 6 +max-sizes = {flash = 131072, ram = 32768} +# This can probably overkill and can be tuned later +stacksize = 6000 +start = true +uses = ["usart1"] +task-slots = [ + "auxflash", + "jefe", + "net", + "update_server", + "sys", + "hf", + { cpu_seq = "grapefruit_seq" }, + "validate", + "sensor", + "sprot", + "packrat", + "user_leds", +] +features = [ + "auxflash", + "cosmo", # close enough! + "usart1", + "vlan", + "baud_rate_3M", +] +notifications = ["usart-irq", "socket", "timer"] +interrupts = {"usart1.irq" = "usart-irq"} + + [tasks.auxflash] name = "drv-auxflash-server" priority = 3 @@ -302,6 +360,13 @@ port = 998 tx = { packets = 3, bytes = 1024 } rx = { packets = 3, bytes = 1024 } +[config.net.sockets.control_plane_agent] +kind = "udp" +owner = {name = "control_plane_agent", notification = "socket"} +port = 11111 +tx = { packets = 3, bytes = 2048 } +rx = { packets = 3, bytes = 2048 } + [config.net.sockets.dump_agent] kind = "udp" owner = {name = "dump_agent", notification = "socket"} diff --git a/build/xtask/src/dist.rs b/build/xtask/src/dist.rs index 1eb7117904..a0604d421b 100644 --- a/build/xtask/src/dist.rs +++ b/build/xtask/src/dist.rs @@ -2971,7 +2971,7 @@ impl Archive { tmp_path, inner, opts: zip::write::FileOptions::default() - .compression_method(zip::CompressionMethod::Bzip2), + .compression_method(zip::CompressionMethod::Deflated), }) } diff --git a/drv/cosmo-hf/Cargo.toml b/drv/cosmo-hf/Cargo.toml index 6ab4a55627..5eaea78aa2 100644 --- a/drv/cosmo-hf/Cargo.toml +++ b/drv/cosmo-hf/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] counters = { path = "../../lib/counters" } -drv-grapefruit-seq-api = { path = "../grapefruit-seq-api" } +drv-cpu-seq-api = { path = "../cpu-seq-api" } drv-hash-api = { path = "../hash-api" } drv-hf-api = { path = "../hf-api" } ringbuf = { path = "../../lib/ringbuf" } diff --git a/drv/cosmo-hf/src/main.rs b/drv/cosmo-hf/src/main.rs index d8a7944758..7f8ebc2316 100644 --- a/drv/cosmo-hf/src/main.rs +++ b/drv/cosmo-hf/src/main.rs @@ -60,9 +60,10 @@ pub const SECTOR_SIZE_BYTES: u32 = 65_536; #[export_name = "main"] fn main() -> ! { - // Wait for the FPGA to be configured - let seq = drv_grapefruit_seq_api::Sequencer::from(SEQ.get_task_id()); - seq.ping(); // waits until the sequencer has completed configuration + // Wait for the FPGA to be configured; the sequencer task only starts its + // Idol loop after the FPGA has been brought up. + let seq = drv_cpu_seq_api::Sequencer::from(SEQ.get_task_id()); + let _ = seq.get_state(); let id = unsafe { reg::BASE.read_volatile() }; if id != 0x1de { diff --git a/drv/gimlet-state/Cargo.toml b/drv/cpu-power-state/Cargo.toml similarity index 91% rename from drv/gimlet-state/Cargo.toml rename to drv/cpu-power-state/Cargo.toml index 6bd617f13a..35f1a77016 100644 --- a/drv/gimlet-state/Cargo.toml +++ b/drv/cpu-power-state/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "drv-gimlet-state" +name = "drv-cpu-power-state" version = "0.1.0" edition = "2021" diff --git a/drv/gimlet-state/src/lib.rs b/drv/cpu-power-state/src/lib.rs similarity index 100% rename from drv/gimlet-state/src/lib.rs rename to drv/cpu-power-state/src/lib.rs diff --git a/drv/gimlet-seq-api/Cargo.toml b/drv/cpu-seq-api/Cargo.toml similarity index 84% rename from drv/gimlet-seq-api/Cargo.toml rename to drv/cpu-seq-api/Cargo.toml index caf0382b3b..6037890b6a 100644 --- a/drv/gimlet-seq-api/Cargo.toml +++ b/drv/cpu-seq-api/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "drv-gimlet-seq-api" +name = "drv-cpu-seq-api" version = "0.1.0" edition = "2021" @@ -10,7 +10,7 @@ zerocopy.workspace = true counters = { path = "../../lib/counters", features = ["derive"] } derive-idol-err = { path = "../../lib/derive-idol-err" } -drv-gimlet-state = { path = "../gimlet-state" } +drv-cpu-power-state = { path = "../cpu-power-state" } userlib = { path = "../../sys/userlib" } [build-dependencies] diff --git a/drv/gimlet-seq-api/build.rs b/drv/cpu-seq-api/build.rs similarity index 82% rename from drv/gimlet-seq-api/build.rs rename to drv/cpu-seq-api/build.rs index 78fc06e28b..eed2f5e4b0 100644 --- a/drv/gimlet-seq-api/build.rs +++ b/drv/cpu-seq-api/build.rs @@ -5,6 +5,6 @@ fn main() -> Result<(), Box> { idol::Generator::new() .with_counters(idol::CounterSettings::default()) - .build_client_stub("../../idl/gimlet-seq.idol", "client_stub.rs")?; + .build_client_stub("../../idl/cpu-seq.idol", "client_stub.rs")?; Ok(()) } diff --git a/drv/gimlet-seq-api/src/lib.rs b/drv/cpu-seq-api/src/lib.rs similarity index 96% rename from drv/gimlet-seq-api/src/lib.rs rename to drv/cpu-seq-api/src/lib.rs index a7a46edc49..8ab006e097 100644 --- a/drv/gimlet-seq-api/src/lib.rs +++ b/drv/cpu-seq-api/src/lib.rs @@ -11,7 +11,7 @@ use derive_idol_err::IdolError; use userlib::{sys_send, FromPrimitive}; // Re-export PowerState for client convenience. -pub use drv_gimlet_state::PowerState; +pub use drv_cpu_power_state::PowerState; #[derive( Copy, Clone, Debug, FromPrimitive, Eq, PartialEq, IdolError, Count, diff --git a/drv/gimlet-seq-server/Cargo.toml b/drv/gimlet-seq-server/Cargo.toml index 3541998e35..7f25db3845 100644 --- a/drv/gimlet-seq-server/Cargo.toml +++ b/drv/gimlet-seq-server/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] drv-hf-api = { path = "../hf-api" } -drv-gimlet-seq-api = { path = "../gimlet-seq-api" } -drv-gimlet-state = { path = "../gimlet-state" } +drv-cpu-seq-api = { path = "../cpu-seq-api" } +drv-cpu-power-state = { path = "../cpu-power-state" } drv-i2c-api = { path = "../i2c-api" } drv-i2c-devices = { path = "../i2c-devices" } drv-ice40-spi-program = { path = "../ice40-spi-program" } diff --git a/drv/gimlet-seq-server/build.rs b/drv/gimlet-seq-server/build.rs index d39b68730f..12e070e62d 100644 --- a/drv/gimlet-seq-server/build.rs +++ b/drv/gimlet-seq-server/build.rs @@ -69,7 +69,7 @@ fn main() -> Result<(), Box> { )?; idol::Generator::new().build_server_support( - "../../idl/gimlet-seq.idol", + "../../idl/cpu-seq.idol", "server_stub.rs", idol::server::ServerStyle::InOrder, )?; diff --git a/drv/gimlet-seq-server/src/main.rs b/drv/gimlet-seq-server/src/main.rs index 585fb048eb..20f2b57711 100644 --- a/drv/gimlet-seq-server/src/main.rs +++ b/drv/gimlet-seq-server/src/main.rs @@ -17,7 +17,7 @@ use userlib::{ sys_set_timer, task_slot, units, RecvMessage, TaskId, UnwrapLite, }; -use drv_gimlet_seq_api::{PowerState, SeqError}; +use drv_cpu_seq_api::{PowerState, SeqError}; use drv_hf_api as hf_api; use drv_i2c_api as i2c; use drv_ice40_spi_program as ice40; @@ -1036,28 +1036,6 @@ impl idl::InOrderSequencerImpl for ServerImpl { self.set_state_internal(state).map_err(RequestError::from) } - fn fans_on( - &mut self, - _: &RecvMessage, - ) -> Result<(), RequestError> { - let on = Reg::EARLY_POWER_CTRL::FANPWREN; - self.seq - .set_bytes(Addr::EARLY_POWER_CTRL, &[on]) - .unwrap_lite(); - Ok(()) - } - - fn fans_off( - &mut self, - _: &RecvMessage, - ) -> Result<(), RequestError> { - let off = Reg::EARLY_POWER_CTRL::FANPWREN; - self.seq - .clear_bytes(Addr::EARLY_POWER_CTRL, &[off]) - .unwrap_lite(); - Ok(()) - } - fn send_hardware_nmi( &mut self, _: &RecvMessage, @@ -1098,7 +1076,7 @@ fn read_spd_data_and_load_packrat( packrat: &Packrat, i2c_task: TaskId, ) -> Result<(), i2c::ResponseCode> { - use drv_gimlet_seq_api::NUM_SPD_BANKS; + use drv_cpu_seq_api::NUM_SPD_BANKS; use drv_i2c_api::{Controller, I2cDevice, Mux, PortIndex, Segment}; type SpdBank = (Controller, PortIndex, Option<(Mux, Segment)>); diff --git a/drv/grapefruit-seq-api/Cargo.toml b/drv/grapefruit-seq-api/Cargo.toml deleted file mode 100644 index 47edfab89e..0000000000 --- a/drv/grapefruit-seq-api/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "drv-grapefruit-seq-api" -version = "0.1.0" -edition = "2021" - -[dependencies] -idol-runtime = { workspace = true } -num-traits.workspace = true -zerocopy.workspace = true - -counters = { path = "../../lib/counters", features = ["derive"] } -userlib = { path = "../../sys/userlib" } - -[build-dependencies] -idol.workspace = true - -[lib] -test = false -doctest = false -bench = false - -[lints] -workspace = true diff --git a/drv/grapefruit-seq-api/build.rs b/drv/grapefruit-seq-api/build.rs deleted file mode 100644 index b7f4f6a93a..0000000000 --- a/drv/grapefruit-seq-api/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -// 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/. - -fn main() -> Result<(), Box> { - idol::Generator::new() - .with_counters(idol::CounterSettings::default()) - .build_client_stub("../../idl/grapefruit-seq.idol", "client_stub.rs")?; - Ok(()) -} diff --git a/drv/grapefruit-seq-api/src/lib.rs b/drv/grapefruit-seq-api/src/lib.rs deleted file mode 100644 index 629e602bbd..0000000000 --- a/drv/grapefruit-seq-api/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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/. - -//! API crate for the Grapefruit Sequencer server. - -#![no_std] - -use userlib::sys_send; - -include!(concat!(env!("OUT_DIR"), "/client_stub.rs")); diff --git a/drv/grapefruit-seq-server/Cargo.toml b/drv/grapefruit-seq-server/Cargo.toml index 4c9b79f70a..dea4f786bd 100644 --- a/drv/grapefruit-seq-server/Cargo.toml +++ b/drv/grapefruit-seq-server/Cargo.toml @@ -5,12 +5,15 @@ edition = "2021" [dependencies] drv-spi-api = { path = "../spi-api" } +drv-cpu-seq-api = { path = "../cpu-seq-api" } +drv-cpu-power-state = { path = "../cpu-power-state" } drv-stm32xx-sys-api = { path = "../stm32xx-sys-api" } drv-auxflash-api = { path = "../auxflash-api" } counters = { path = "../../lib/counters" } gnarle = { path = "../../lib/gnarle" } ringbuf = { path = "../../lib/ringbuf" } userlib = { path = "../../sys/userlib", features = ["panic-messages"] } +task-jefe-api = { path = "../../task/jefe-api" } cfg-if = { workspace = true } idol-runtime.workspace = true diff --git a/drv/grapefruit-seq-server/build.rs b/drv/grapefruit-seq-server/build.rs index 00b1ac20c2..414e2c1bdd 100644 --- a/drv/grapefruit-seq-server/build.rs +++ b/drv/grapefruit-seq-server/build.rs @@ -28,7 +28,7 @@ fn main() -> Result<(), Box> { )?; idol::Generator::new().build_server_support( - "../../idl/grapefruit-seq.idol", + "../../idl/cpu-seq.idol", "server_stub.rs", idol::server::ServerStyle::InOrder, )?; diff --git a/drv/grapefruit-seq-server/src/main.rs b/drv/grapefruit-seq-server/src/main.rs index bff6f4efe7..176ac15706 100644 --- a/drv/grapefruit-seq-server/src/main.rs +++ b/drv/grapefruit-seq-server/src/main.rs @@ -7,14 +7,21 @@ #![no_std] #![no_main] +use drv_cpu_seq_api::PowerState; use drv_spi_api::{SpiDevice, SpiServer}; use drv_stm32xx_sys_api as sys_api; use idol_runtime::{NotificationHandler, RequestError}; use sha3::{Digest, Sha3_256}; -use userlib::{hl, sys_recv_notification, task_slot, RecvMessage}; +use task_jefe_api::Jefe; +use userlib::{ + hl, sys_recv_notification, task_slot, FromPrimitive, RecvMessage, + UnwrapLite, +}; use ringbuf::{counted_ringbuf, ringbuf_entry, Count}; +task_slot!(JEFE, jefe); + #[derive(Copy, Clone, PartialEq, Count)] enum Trace { FpgaInit(#[count(children)] bool), @@ -79,6 +86,7 @@ fn main() -> ! { #[allow(unused)] struct ServerImpl { + jefe: Jefe, sys: sys_api::Sys, seq: SpiDevice, } @@ -236,8 +244,10 @@ impl ServerImpl { let server = Self { sys: sys.clone(), + jefe: Jefe::from(JEFE.get_task_id()), seq, }; + server.set_state_impl(PowerState::A2); // Clear the external fault now that we're about to start serving // messages and fewer things can go wrong. @@ -248,15 +258,62 @@ impl ServerImpl { Ok(server) } + + fn get_state_impl(&self) -> PowerState { + // Only we should be setting the state, and we set it to A2 on startup; + // this conversion should never fail. + PowerState::from_u32(self.jefe.get_state()).unwrap_lite() + } + + fn set_state_impl(&self, state: PowerState) { + self.jefe.set_state(state as u32); + } } -impl idl::InOrderSequencerImpl for ServerImpl { - fn ping( +// The `Sequencer` implementation for Grapefruit is copied from +// `mock-gimlet-seq-server`. State is set to Jefe, but isn't actually +// controlled here. +impl idl::InOrderSequencerImpl for ServerImpl { + fn get_state( + &mut self, + _: &RecvMessage, + ) -> Result> { + Ok(self.get_state_impl()) + } + + fn set_state( + &mut self, + _: &RecvMessage, + state: PowerState, + ) -> Result<(), RequestError> { + match (self.get_state_impl(), state) { + (PowerState::A2, PowerState::A0) + | (PowerState::A0, PowerState::A2) + | (PowerState::A0PlusHP, PowerState::A2) + | (PowerState::A0Thermtrip, PowerState::A2) => { + self.set_state_impl(state); + Ok(()) + } + + _ => Err(RequestError::Runtime( + drv_cpu_seq_api::SeqError::IllegalTransition, + )), + } + } + + fn send_hardware_nmi( &mut self, _: &RecvMessage, ) -> Result<(), RequestError> { Ok(()) } + + fn read_fpga_regs( + &mut self, + _: &RecvMessage, + ) -> Result<[u8; 64], RequestError> { + Ok([0; 64]) + } } impl NotificationHandler for ServerImpl { @@ -265,11 +322,12 @@ impl NotificationHandler for ServerImpl { } fn handle_notification(&mut self, _bits: u32) { - panic!() + unreachable!() } } mod idl { + use drv_cpu_seq_api::SeqError; include!(concat!(env!("OUT_DIR"), "/server_stub.rs")); } diff --git a/drv/mock-gimlet-seq-server/Cargo.toml b/drv/mock-gimlet-seq-server/Cargo.toml index bf52ac6879..73c31abb61 100644 --- a/drv/mock-gimlet-seq-server/Cargo.toml +++ b/drv/mock-gimlet-seq-server/Cargo.toml @@ -8,8 +8,8 @@ idol-runtime = { workspace = true } num-traits = { workspace = true } zerocopy = { workspace = true } -drv-gimlet-seq-api = { path = "../gimlet-seq-api" } -drv-gimlet-state = { path = "../gimlet-state" } +drv-cpu-seq-api = { path = "../cpu-seq-api" } +drv-cpu-power-state = { path = "../cpu-power-state" } task-jefe-api = { path = "../../task/jefe-api" } userlib = { path = "../../sys/userlib" } diff --git a/drv/mock-gimlet-seq-server/build.rs b/drv/mock-gimlet-seq-server/build.rs index ba73486876..bec83d13d0 100644 --- a/drv/mock-gimlet-seq-server/build.rs +++ b/drv/mock-gimlet-seq-server/build.rs @@ -8,7 +8,7 @@ fn main() -> Result<(), Box> { idol::CounterSettings::default().with_server_counters(false), ) .build_server_support( - "../../idl/gimlet-seq.idol", + "../../idl/cpu-seq.idol", "server_stub.rs", idol::server::ServerStyle::InOrder, )?; diff --git a/drv/mock-gimlet-seq-server/src/main.rs b/drv/mock-gimlet-seq-server/src/main.rs index cd1b8862bf..64b0733bdd 100644 --- a/drv/mock-gimlet-seq-server/src/main.rs +++ b/drv/mock-gimlet-seq-server/src/main.rs @@ -7,7 +7,7 @@ #![no_std] #![no_main] -use drv_gimlet_seq_api::{PowerState, SeqError}; +use drv_cpu_seq_api::{PowerState, SeqError}; use idol_runtime::{NotificationHandler, RequestError}; use task_jefe_api::Jefe; use userlib::{FromPrimitive, RecvMessage, UnwrapLite}; @@ -72,20 +72,6 @@ impl idl::InOrderSequencerImpl for ServerImpl { } } - fn fans_on( - &mut self, - _: &RecvMessage, - ) -> Result<(), RequestError> { - Ok(()) - } - - fn fans_off( - &mut self, - _: &RecvMessage, - ) -> Result<(), RequestError> { - Ok(()) - } - fn send_hardware_nmi( &mut self, _: &RecvMessage, diff --git a/idl/gimlet-seq.idol b/idl/cpu-seq.idol similarity index 68% rename from idl/gimlet-seq.idol rename to idl/cpu-seq.idol index 96201f2b79..f345f36ed4 100644 --- a/idl/gimlet-seq.idol +++ b/idl/cpu-seq.idol @@ -1,4 +1,4 @@ -// Gimlet Sequencer API +// CPU Sequencer API Interface( name: "Sequencer", @@ -7,7 +7,7 @@ Interface( doc: "Return the power state", args: {}, reply: Simple(( - type: "drv_gimlet_state::PowerState", + type: "drv_cpu_power_state::PowerState", recv: FromPrimitive("u8"), )), idempotent: true, @@ -16,7 +16,7 @@ Interface( doc: "Set the power state", args: { "state": ( - type: "drv_gimlet_state::PowerState", + type: "drv_cpu_power_state::PowerState", recv: FromPrimitive("u8"), ) }, @@ -25,20 +25,6 @@ Interface( err: CLike("SeqError"), ), ), - "fans_on": ( - args: {}, - reply: Result( - ok: "()", - err: ServerDeath, - ), - ), - "fans_off": ( - args: {}, - reply: Result( - ok: "()", - err: ServerDeath, - ), - ), "send_hardware_nmi": ( doc: "Triggers a hardware NMI by toggling LPC_SMI_L", args: {}, diff --git a/idl/grapefruit-seq.idol b/idl/grapefruit-seq.idol deleted file mode 100644 index 1606caa823..0000000000 --- a/idl/grapefruit-seq.idol +++ /dev/null @@ -1,11 +0,0 @@ -// Grapefruit Sequencer API -Interface( - name: "Sequencer", - ops: { - "ping": ( - args: {}, - reply: Simple("()"), - idempotent: true, - ), - } -) diff --git a/task/control-plane-agent/Cargo.toml b/task/control-plane-agent/Cargo.toml index 5591819576..43c1252fab 100644 --- a/task/control-plane-agent/Cargo.toml +++ b/task/control-plane-agent/Cargo.toml @@ -22,7 +22,7 @@ drv-auxflash-api = { path = "../../drv/auxflash-api", optional = true } drv-caboose = { path = "../../drv/caboose" } drv-caboose-pos = { path = "../../drv/caboose-pos" } drv-hf-api = { path = "../../drv/hf-api", optional = true } -drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api", optional = true } +drv-cpu-seq-api = { path = "../../drv/cpu-seq-api", optional = true } drv-ignition-api = { path = "../../drv/ignition-api", optional = true } drv-lpc55-update-api = { path = "../../drv/lpc55-update-api" } drv-monorail-api = { path = "../../drv/monorail-api", optional = true } @@ -58,7 +58,9 @@ ssh-key = { workspace = true } [features] no-ipc-counters = ["idol/no-counters"] -gimlet = ["drv-hf-api", "drv-gimlet-seq-api", "drv-stm32h7-usart", "drv-user-leds-api"] +compute-sled = ["drv-hf-api", "drv-cpu-seq-api", "drv-stm32h7-usart", "drv-user-leds-api"] +gimlet = ["compute-sled"] +cosmo = ["compute-sled"] sidecar = ["drv-sidecar-seq-api", "drv-monorail-api", "drv-ignition-api", "drv-transceivers-api", "p256", "sha2", "drv-rng-api"] psc = ["drv-user-leds-api"] vpd = ["task-vpd-api"] diff --git a/task/control-plane-agent/src/inventory.rs b/task/control-plane-agent/src/inventory.rs index dfd3cda037..f5f2ad48e4 100644 --- a/task/control-plane-agent/src/inventory.rs +++ b/task/control-plane-agent/src/inventory.rs @@ -279,17 +279,29 @@ mod devices_with_static_validation { capabilities: DeviceCapabilities::HAS_SERIAL_CONSOLE, presence: DevicePresence::Present, // TODO: ok to assume always present? }, + // Same for cosmo / grapefruit + #[cfg(feature = "cosmo")] + DeviceDescription { + component: SpComponent::SP5_HOST_CPU, + device: SpComponent::SP5_HOST_CPU.const_as_str(), + description: "Cosmo SP5 host cpu", + capabilities: DeviceCapabilities::HAS_SERIAL_CONSOLE, + presence: DevicePresence::Present, // TODO: ok to assume always present? + }, // If we're building for gimlet, we always claim to have host boot flash. // // This is a lie on gimletlet (where we still build with the "gimlet" // feature), and a less useful one than the host CPU (since trying to // access the "host flash" will fail unless we have an adapter providing // QSPI flash). - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] DeviceDescription { component: SpComponent::HOST_CPU_BOOT_FLASH, device: SpComponent::HOST_CPU_BOOT_FLASH.const_as_str(), + #[cfg(feature = "gimlet")] description: "Gimlet host boot flash", + #[cfg(feature = "cosmo")] + description: "Cosmo host boot flash", capabilities: DeviceCapabilities::UPDATEABLE, presence: DevicePresence::Present, // TODO: ok to assume always present? }, @@ -304,7 +316,12 @@ mod devices_with_static_validation { // to MGS messages anyway! presence: DevicePresence::Present, }, - #[cfg(any(feature = "gimlet", feature = "psc", feature = "sidecar"))] + #[cfg(any( + feature = "gimlet", + feature = "cosmo", + feature = "psc", + feature = "sidecar" + ))] DeviceDescription { component: SpComponent::SYSTEM_LED, device: SpComponent::SYSTEM_LED.const_as_str(), diff --git a/task/control-plane-agent/src/main.rs b/task/control-plane-agent/src/main.rs index 8040365cd9..5728ff6595 100644 --- a/task/control-plane-agent/src/main.rs +++ b/task/control-plane-agent/src/main.rs @@ -34,7 +34,7 @@ mod update; // sequence of `cfg_attr`s will trigger an unused_attributes warning. We build // everything with -Dunused_attributes, which will catch any such build system // misconfiguration. -#[cfg_attr(feature = "gimlet", path = "mgs_gimlet.rs")] +#[cfg_attr(feature = "compute-sled", path = "mgs_compute_sled.rs")] #[cfg_attr(feature = "sidecar", path = "mgs_sidecar.rs")] #[cfg_attr(feature = "psc", path = "mgs_psc.rs")] mod mgs_handler; @@ -179,15 +179,15 @@ enum IpcRequest { GetStartupOptions, SetStartupOptions(HostStartupOptions), Identity, - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] GetInstallinatorImageId, - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] GetUartClient, - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] SetHumilityUartClient(#[count(children)] UartClient), - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] UartRead(usize), - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] UartWrite(usize), } @@ -326,7 +326,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { Ok(self.mgs_handler.identity()) } - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] fn get_installinator_image_id( &mut self, _msg: &userlib::RecvMessage, @@ -348,7 +348,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { } } - #[cfg(not(feature = "gimlet"))] + #[cfg(not(feature = "compute-sled"))] fn get_installinator_image_id( &mut self, _msg: &userlib::RecvMessage, @@ -364,7 +364,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { Err(RequestError::Fail(ClientError::BadMessageContents)) } - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] fn get_uart_client( &mut self, _msg: &userlib::RecvMessage, @@ -373,7 +373,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { Ok(self.mgs_handler.uart_client()) } - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] fn set_humility_uart_client( &mut self, _msg: &userlib::RecvMessage, @@ -390,7 +390,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { Ok(self.mgs_handler.set_uart_client(client)?) } - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] fn uart_read( &mut self, _msg: &userlib::RecvMessage, @@ -400,7 +400,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { self.mgs_handler.uart_read(data) } - #[cfg(feature = "gimlet")] + #[cfg(feature = "compute-sled")] fn uart_write( &mut self, _msg: &userlib::RecvMessage, @@ -410,7 +410,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { self.mgs_handler.uart_write(data) } - #[cfg(not(feature = "gimlet"))] + #[cfg(not(feature = "compute-sled"))] fn get_uart_client( &mut self, _msg: &userlib::RecvMessage, @@ -420,7 +420,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { Ok(UartClient::Mgs) } - #[cfg(not(feature = "gimlet"))] + #[cfg(not(feature = "compute-sled"))] fn set_humility_uart_client( &mut self, _msg: &userlib::RecvMessage, @@ -431,7 +431,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { )) } - #[cfg(not(feature = "gimlet"))] + #[cfg(not(feature = "compute-sled"))] fn uart_read( &mut self, _msg: &userlib::RecvMessage, @@ -442,7 +442,7 @@ impl idl::InOrderControlPlaneAgentImpl for ServerImpl { )) } - #[cfg(not(feature = "gimlet"))] + #[cfg(not(feature = "compute-sled"))] fn uart_write( &mut self, _msg: &userlib::RecvMessage, diff --git a/task/control-plane-agent/src/mgs_gimlet.rs b/task/control-plane-agent/src/mgs_compute_sled.rs similarity index 99% rename from task/control-plane-agent/src/mgs_gimlet.rs rename to task/control-plane-agent/src/mgs_compute_sled.rs index 60b048249e..e013d136e1 100644 --- a/task/control-plane-agent/src/mgs_gimlet.rs +++ b/task/control-plane-agent/src/mgs_compute_sled.rs @@ -8,7 +8,7 @@ use crate::{ usize_max, CriticalEvent, Log, MgsMessage, SYS, }; use core::time::Duration; -use drv_gimlet_seq_api::Sequencer; +use drv_cpu_seq_api::Sequencer; use drv_stm32h7_usart::Usart; use drv_user_leds_api::UserLeds; use gateway_messages::sp_impl::{ @@ -37,7 +37,7 @@ use userlib::{sys_get_timer, sys_irq_control, FromPrimitive, UnwrapLite}; // We're included under a special `path` cfg from main.rs, which confuses rustc // about where our submodules live. Pass explicit paths to correct it. -#[path = "mgs_gimlet/host_phase2.rs"] +#[path = "mgs_compute_sled/host_phase2.rs"] mod host_phase2; use host_phase2::HostPhase2Requester; @@ -87,7 +87,7 @@ static_assertions::const_assert!( const SERIAL_CONSOLE_FLUSH_TIMEOUT_MILLIS: u64 = 500; userlib::task_slot!(HOST_FLASH, hf); -userlib::task_slot!(GIMLET_SEQ, gimlet_seq); +userlib::task_slot!(CPU_SEQ, cpu_seq); userlib::task_slot!(USER_LEDS, user_leds); type InstallinatorImageIdBuf = Vec; @@ -160,7 +160,7 @@ impl MgsHandler { common: MgsCommon::claim_static_resources(base_mac_address), host_flash_update: HostFlashUpdate::new(), host_phase2: HostPhase2Requester::new(host_phase2_buf), - sequencer: Sequencer::from(GIMLET_SEQ.get_task_id()), + sequencer: Sequencer::from(CPU_SEQ.get_task_id()), user_leds: UserLeds::from(USER_LEDS.get_task_id()), usart, attached_serial_console_mgs: None, @@ -437,7 +437,7 @@ impl MgsHandler { } fn power_state_impl(&self) -> Result { - use drv_gimlet_seq_api::PowerState as DrvPowerState; + use drv_cpu_seq_api::PowerState as DrvPowerState; // TODO Do we want to expose the sub-states to the control plane? For // now, squish them down. @@ -708,7 +708,7 @@ impl SpHandler for MgsHandler { sender: Sender, power_state: PowerState, ) -> Result<(), SpError> { - use drv_gimlet_seq_api::PowerState as DrvPowerState; + use drv_cpu_seq_api::PowerState as DrvPowerState; ringbuf_entry_root!( CRITICAL, CriticalEvent::SetPowerState { diff --git a/task/control-plane-agent/src/mgs_gimlet/host_phase2.rs b/task/control-plane-agent/src/mgs_compute_sled/host_phase2.rs similarity index 100% rename from task/control-plane-agent/src/mgs_gimlet/host_phase2.rs rename to task/control-plane-agent/src/mgs_compute_sled/host_phase2.rs diff --git a/task/control-plane-agent/src/update/mod.rs b/task/control-plane-agent/src/update/mod.rs index 650db2551e..a72bcb3c4f 100644 --- a/task/control-plane-agent/src/update/mod.rs +++ b/task/control-plane-agent/src/update/mod.rs @@ -5,7 +5,7 @@ use crate::mgs_handler::UpdateBuffer; use gateway_messages::{SpError, UpdateId, UpdateStatus}; -#[cfg(feature = "gimlet")] +#[cfg(feature = "compute-sled")] pub(crate) mod host_flash; mod common; diff --git a/task/gimlet-inspector/Cargo.toml b/task/gimlet-inspector/Cargo.toml index 372338dd0d..060ab73dcf 100644 --- a/task/gimlet-inspector/Cargo.toml +++ b/task/gimlet-inspector/Cargo.toml @@ -9,7 +9,7 @@ hubpack = { workspace = true } gimlet-inspector-protocol = { workspace = true } task-net-api = { path = "../net-api" } -drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api" } +drv-cpu-seq-api = { path = "../../drv/cpu-seq-api" } userlib = { path = "../../sys/userlib", features = ["panic-messages"] } counters = { path = "../../lib/counters" } diff --git a/task/gimlet-inspector/src/main.rs b/task/gimlet-inspector/src/main.rs index 228a9132d3..9c6a40636d 100644 --- a/task/gimlet-inspector/src/main.rs +++ b/task/gimlet-inspector/src/main.rs @@ -10,7 +10,7 @@ #![no_main] use counters::*; -use drv_gimlet_seq_api::Sequencer; +use drv_cpu_seq_api::Sequencer; use gimlet_inspector_protocol::{ QueryV0, Request, SequencerRegistersResponseV0, ANY_RESPONSE_V0_MAX_SIZE, REQUEST_TRAILER, diff --git a/task/host-sp-comms/Cargo.toml b/task/host-sp-comms/Cargo.toml index 28eee63096..49a633ca4a 100644 --- a/task/host-sp-comms/Cargo.toml +++ b/task/host-sp-comms/Cargo.toml @@ -23,7 +23,7 @@ pmbus = { workspace = true, optional = true } counters.path = "../../lib/counters" drv-hf-api.path= "../../drv/hf-api" -drv-gimlet-seq-api.path= "../../drv/gimlet-seq-api" +drv-cpu-seq-api.path= "../../drv/cpu-seq-api" drv-oxide-vpd.path= "../../drv/oxide-vpd" drv-stm32h7-dbgmcu.path = "../../drv/stm32h7-dbgmcu" drv-stm32xx-sys-api.path= "../../drv/stm32xx-sys-api" @@ -55,11 +55,13 @@ idol.workspace = true no-ipc-counters = ["idol/no-counters"] stm32h743 = ["drv-stm32h7-usart/h743", "drv-stm32xx-sys-api/h743", "drv-stm32h7-dbgmcu/h743"] stm32h753 = ["drv-stm32h7-usart/h753", "drv-stm32xx-sys-api/h753", "drv-stm32h7-dbgmcu/h753"] +usart6 = [] uart7 = [] baud_rate_3M = [] hardware_flow_control = [] vlan = ["task-net-api/vlan"] gimlet = ["pmbus", "tlvc", "drv-i2c-api", "drv-i2c-devices", "drv-spi-api", "ksz8463", "build-i2c", "task-sensor-api"] +grapefruit = ["drv-spi-api", "ksz8463"] [[bin]] name = "task-host-sp-comms" diff --git a/task/host-sp-comms/src/bsp/grapefruit.rs b/task/host-sp-comms/src/bsp/grapefruit.rs new file mode 100644 index 0000000000..ff73ac14d6 --- /dev/null +++ b/task/host-sp-comms/src/bsp/grapefruit.rs @@ -0,0 +1,90 @@ +// 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/. + +//! SP inventory types and implementation +//! +//! This reduces clutter in the main `ServerImpl` implementation +use super::ServerImpl; + +use drv_spi_api::SpiServer; + +use host_sp_messages::{InventoryData, InventoryDataResult}; + +userlib::task_slot!(SPI, spi_driver); + +impl ServerImpl { + /// Number of devices in our inventory + pub(crate) const INVENTORY_COUNT: u32 = 2; + + /// Look up a device in our inventory, by index + /// + /// Indexes are assigned arbitrarily and may change freely with SP + /// revisions. + /// + /// On success, we will have already filled `self.tx_buf` with our response; + /// this _may_ be an error if the index was valid but we can't communicate + /// with the target device. + /// + /// This function should only return an error if the index is invalid; + /// in that case, our caller is responsible for encoding the error as + /// ``` + /// SpToHost::InventoryData{ + /// result: err + /// name: [0; u32], + /// } + /// ``` + pub(crate) fn perform_inventory_lookup( + &mut self, + sequence: u64, + index: u32, + ) -> Result<(), InventoryDataResult> { + #[forbid(unreachable_patterns)] + match index { + // Grapefruit has a FRU ID EEPROM, but it's connected to the FPGA, + // so it's obnoxious to read here + 0 => { + // U12: the service processor itself + // The UID is readable by stm32xx_sys + let sys = + drv_stm32xx_sys_api::Sys::from(crate::SYS.get_task_id()); + let uid = sys.read_uid(); + + let idc = drv_stm32h7_dbgmcu::read_idc(); + let dbgmcu_rev_id = (idc >> 16) as u16; + let dbgmcu_dev_id = (idc & 4095) as u16; + let data = InventoryData::Stm32H7 { + uid, + dbgmcu_rev_id, + dbgmcu_dev_id, + }; + self.tx_buf + .try_encode_inventory(sequence, b"U12", || Ok(&data)); + } + + 1 => { + let spi = drv_spi_api::Spi::from(SPI.get_task_id()); + let ksz8463_dev = spi.device(drv_spi_api::devices::KSZ8463); + let ksz8463 = ksz8463::Ksz8463::new(ksz8463_dev); + let mut data = InventoryData::Ksz8463 { cider: 0 }; + self.tx_buf.try_encode_inventory(sequence, b"U401", || { + let InventoryData::Ksz8463 { cider } = &mut data else { + unreachable!(); + }; + *cider = ksz8463 + .read(ksz8463::Register::CIDER) + .map_err(|_| InventoryDataResult::DeviceFailed)?; + Ok(&data) + }); + } + + // We need to specify INVENTORY_COUNT individually here to trigger + // an error if we've overlapped it with a previous range + Self::INVENTORY_COUNT | Self::INVENTORY_COUNT..=u32::MAX => { + return Err(InventoryDataResult::InvalidIndex) + } + } + + Ok(()) + } +} diff --git a/task/host-sp-comms/src/main.rs b/task/host-sp-comms/src/main.rs index b5ddf15b07..f0d39438c7 100644 --- a/task/host-sp-comms/src/main.rs +++ b/task/host-sp-comms/src/main.rs @@ -12,7 +12,7 @@ use attest_data::messages::{ HostToRotCommand, RecvSprotError as AttestDataSprotError, RotToHost, MAX_DATA_LEN, }; -use drv_gimlet_seq_api::{PowerState, SeqError, Sequencer}; +use drv_cpu_seq_api::{PowerState, SeqError, Sequencer}; use drv_hf_api::{HfDevSelect, HfMuxState, HostFlash}; use drv_sprot_api::SpRot; use drv_stm32xx_sys_api as sys_api; @@ -54,13 +54,14 @@ use inventory::INVENTORY_API_VERSION; path = "bsp/gimlet_bcde.rs" )] #[cfg_attr(target_board = "gimletlet-2", path = "bsp/gimletlet.rs")] +#[cfg_attr(target_board = "grapefruit", path = "bsp/grapefruit.rs")] mod bsp; mod tx_buf; use tx_buf::TxBuf; task_slot!(CONTROL_PLANE_AGENT, control_plane_agent); -task_slot!(GIMLET_SEQ, gimlet_seq); +task_slot!(CPU_SEQ, cpu_seq); task_slot!(HOST_FLASH, hf); task_slot!(PACKRAT, packrat); task_slot!(NET, net); @@ -297,7 +298,7 @@ impl ServerImpl { tx_buf: tx_buf::TxBuf::new(tx_buf), rx_buf, status: Status::empty(), - sequencer: Sequencer::from(GIMLET_SEQ.get_task_id()), + sequencer: Sequencer::from(CPU_SEQ.get_task_id()), hf: HostFlash::from(HOST_FLASH.get_task_id()), net: Net::from(NET.get_task_id()), cp_agent: ControlPlaneAgent::from( @@ -322,12 +323,12 @@ impl ServerImpl { fn set_status_impl(&mut self, status: Status) { if status != self.status { self.status = status; - // SP_TO_SP3_INT_L: `INT_L` is "interrupt low", so we assert the pin + // SP_TO_HOST_CPU_INT_L: `INT_L` is "interrupt low", so we assert the pin // when we do not have status and deassert it when we do. if self.status.is_empty() { - self.sys.gpio_set(SP_TO_SP3_INT_L); + self.sys.gpio_set(SP_TO_HOST_CPU_INT_L); } else { - self.sys.gpio_reset(SP_TO_SP3_INT_L); + self.sys.gpio_reset(SP_TO_HOST_CPU_INT_L); } } } @@ -1529,6 +1530,22 @@ fn configure_uart_device(sys: &sys_api::Sys) -> Usart { let usart = unsafe { &*device::UART7::ptr() }; let peripheral = Peripheral::Uart7; let pins = PINS; + } else if #[cfg(feature = "usart6")] { + const PINS: &[(PinSet, Alternate)] = { + cfg_if::cfg_if! { + if #[cfg(feature = "hardware_flow_control")] { + &[( + Port::G.pin(8).and_pin(9).and_pin(14).and_pin(15), + Alternate::AF7 + )] + } else { + compile_error!("hardware_flow_control should be enabled"); + } + } + }; + let usart = unsafe { &*device::USART6::ptr() }; + let peripheral = Peripheral::Usart6; + let pins = PINS; } else { compile_error!("no usartX/uartX feature specified"); } @@ -1553,21 +1570,26 @@ cfg_if::cfg_if! { target_board = "gimlet-e", target_board = "gimlet-f", ))] { - const SP_TO_SP3_INT_L: sys_api::PinSet = sys_api::Port::I.pin(7); + // This net is named SP_TO_SP3_INT_L in the schematic + const SP_TO_HOST_CPU_INT_L: sys_api::PinSet = sys_api::Port::I.pin(7); } else if #[cfg(target_board = "gimletlet-2")] { // gimletlet doesn't have an SP3 to interrupt, but we can wire up an LED // to one of the exposed E2-E6 pins to see it visually. - const SP_TO_SP3_INT_L: sys_api::PinSet = sys_api::Port::E.pin(2); + const SP_TO_HOST_CPU_INT_L: sys_api::PinSet = sys_api::Port::E.pin(2); + } else if #[cfg(target_board = "grapefruit")] { + // the CPU interrupt is not connected on grapefruit, so pick an + // unconnected GPIO + const SP_TO_HOST_CPU_INT_L: sys_api::PinSet = sys_api::Port::B.pin(1); } else { compile_error!("unsupported target board"); } } fn sp_to_sp3_interrupt_enable(sys: &sys_api::Sys) { - sys.gpio_set(SP_TO_SP3_INT_L); + sys.gpio_set(SP_TO_HOST_CPU_INT_L); sys.gpio_configure_output( - SP_TO_SP3_INT_L, + SP_TO_HOST_CPU_INT_L, sys_api::OutputType::OpenDrain, sys_api::Speed::Low, sys_api::Pull::None, diff --git a/task/net/Cargo.toml b/task/net/Cargo.toml index a0b6c870db..81ca1ea008 100644 --- a/task/net/Cargo.toml +++ b/task/net/Cargo.toml @@ -20,7 +20,7 @@ vsc7448-pac = { workspace = true } zerocopy = { workspace = true } counters = { path = "../../lib/counters" } -drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api", optional = true } +drv-cpu-seq-api = { path = "../../drv/cpu-seq-api", optional = true } drv-medusa-seq-api = { path = "../../drv/medusa-seq-api", optional = true } drv-psc-seq-api = { path = "../../drv/psc-seq-api", optional = true } drv-sidecar-seq-api = { path = "../../drv/sidecar-seq-api", optional = true } @@ -45,7 +45,7 @@ no-ipc-counters = ["idol/no-counters"] use-spi-core = ["drv-stm32h7-spi-server-core"] mgmt = ["drv-spi-api", "ksz8463", "drv-user-leds-api", "task-net-api/mgmt"] vpd-mac = ["task-packrat-api"] -gimlet = ["drv-gimlet-seq-api"] +gimlet = ["drv-cpu-seq-api"] sidecar = ["drv-sidecar-seq-api"] medusa = ["drv-medusa-seq-api"] psc = ["drv-psc-seq-api"] diff --git a/task/net/src/bsp/gimlet_bcdef.rs b/task/net/src/bsp/gimlet_bcdef.rs index 68327850b6..842c1c0232 100644 --- a/task/net/src/bsp/gimlet_bcdef.rs +++ b/task/net/src/bsp/gimlet_bcdef.rs @@ -9,7 +9,7 @@ use crate::{ bsp_support::{self, Ksz8463}, mgmt, notifications, pins, }; -use drv_gimlet_seq_api::PowerState; +use drv_cpu_seq_api::PowerState; use drv_spi_api::SpiServer; use drv_stm32h7_eth as eth; use drv_stm32xx_sys_api::{Alternate, Port, Sys}; diff --git a/task/packrat/Cargo.toml b/task/packrat/Cargo.toml index f10c663b12..9221c4fb8e 100644 --- a/task/packrat/Cargo.toml +++ b/task/packrat/Cargo.toml @@ -10,7 +10,7 @@ spd.workspace = true static_assertions.workspace = true zerocopy.workspace = true -drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api", optional = true } +drv-cpu-seq-api = { path = "../../drv/cpu-seq-api", optional = true } mutable-statics = { path = "../../lib/mutable-statics" } ringbuf = { path = "../../lib/ringbuf" } static-cell = { path = "../../lib/static-cell" } @@ -25,7 +25,7 @@ idol.workspace = true build-util = { path = "../../build/util" } [features] -gimlet = ["drv-gimlet-seq-api"] +gimlet = ["drv-cpu-seq-api"] boot-kmdb = [] no-ipc-counters = ["idol/no-counters"] diff --git a/task/packrat/src/gimlet.rs b/task/packrat/src/gimlet.rs index 468e5b7bc7..5de473ab03 100644 --- a/task/packrat/src/gimlet.rs +++ b/task/packrat/src/gimlet.rs @@ -6,7 +6,7 @@ use crate::Trace; use core::convert::Infallible; -use drv_gimlet_seq_api::NUM_SPD_BANKS; +use drv_cpu_seq_api::NUM_SPD_BANKS; use idol_runtime::{ClientError, Leased, LenLimit, RequestError}; use ringbuf::ringbuf_entry_root as ringbuf_entry; use task_packrat_api::HostStartupOptions; diff --git a/task/power/Cargo.toml b/task/power/Cargo.toml index 4a71fbcf6d..2582db2a21 100644 --- a/task/power/Cargo.toml +++ b/task/power/Cargo.toml @@ -15,7 +15,7 @@ serde.workspace = true static_assertions.workspace = true zerocopy.workspace = true -drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api", optional = true } +drv-cpu-seq-api = { path = "../../drv/cpu-seq-api", optional = true } drv-i2c-api = { path = "../../drv/i2c-api" } drv-i2c-devices = { path = "../../drv/i2c-devices" } drv-sidecar-seq-api = { path = "../../drv/sidecar-seq-api", optional = true } @@ -35,7 +35,7 @@ build-i2c = { path = "../../build/i2c" } build-util = { path = "../../build/util" } [features] -gimlet = ["drv-gimlet-seq-api", "h753"] +gimlet = ["drv-cpu-seq-api", "h753"] sidecar = ["drv-sidecar-seq-api", "h753"] psc = ["drv-stm32xx-sys-api", "h753"] dc2024 = ["drv-stm32xx-sys-api", "h753"] diff --git a/task/power/src/bsp/gimlet_bcdef.rs b/task/power/src/bsp/gimlet_bcdef.rs index c737eb0d9f..01523360c8 100644 --- a/task/power/src/bsp/gimlet_bcdef.rs +++ b/task/power/src/bsp/gimlet_bcdef.rs @@ -58,7 +58,7 @@ pub(crate) static CONTROLLER_CONFIG: [PowerControllerConfig; pub(crate) fn get_state() -> PowerState { userlib::task_slot!(SEQUENCER, gimlet_seq); - use drv_gimlet_seq_api as seq_api; + use drv_cpu_seq_api as seq_api; let sequencer = seq_api::Sequencer::from(SEQUENCER.get_task_id()); diff --git a/task/spd/Cargo.toml b/task/spd/Cargo.toml index ac1952a317..42c70ed146 100644 --- a/task/spd/Cargo.toml +++ b/task/spd/Cargo.toml @@ -10,8 +10,7 @@ num-traits = { workspace = true } spd = { workspace = true } stm32h7 = { workspace = true } -drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api" } -drv-gimlet-state = { path = "../../drv/gimlet-state" } +drv-cpu-seq-api = { path = "../../drv/cpu-seq-api" } drv-i2c-api = { path = "../../drv/i2c-api" } drv-stm32xx-i2c = { path = "../../drv/stm32xx-i2c", features = ["amd_erratum_1394"] } drv-stm32xx-sys-api = { path = "../../drv/stm32xx-sys-api" } diff --git a/task/spd/src/main.rs b/task/spd/src/main.rs index bbefb6689d..6f3453e5d3 100644 --- a/task/spd/src/main.rs +++ b/task/spd/src/main.rs @@ -23,8 +23,7 @@ use core::cell::Cell; use core::cell::RefCell; -use drv_gimlet_seq_api::NUM_SPD_BANKS; -use drv_gimlet_state::PowerState; +use drv_cpu_seq_api::{PowerState, NUM_SPD_BANKS}; use drv_stm32xx_i2c::{I2cPins, I2cTargetControl}; use drv_stm32xx_sys_api::{OutputType, Pull, Speed, Sys}; use ringbuf::{ringbuf, ringbuf_entry}; diff --git a/task/thermal/Cargo.toml b/task/thermal/Cargo.toml index ef49a3867d..29f399dfd1 100644 --- a/task/thermal/Cargo.toml +++ b/task/thermal/Cargo.toml @@ -12,7 +12,7 @@ serde.workspace = true hubpack.workspace = true zerocopy.workspace = true -drv-gimlet-seq-api = { path = "../../drv/gimlet-seq-api", optional = true } +drv-cpu-seq-api = { path = "../../drv/cpu-seq-api", optional = true } drv-sidecar-seq-api = { path = "../../drv/sidecar-seq-api", optional = true } drv-transceivers-api = { path = "../../drv/transceivers-api", optional = true } userlib = { path = "../../sys/userlib", features = ["panic-messages"] } @@ -35,7 +35,7 @@ build-i2c = { path = "../../build/i2c" } build-util = { path = "../../build/util" } [features] -gimlet = ["drv-gimlet-seq-api", "h753"] +gimlet = ["drv-cpu-seq-api", "h753"] sidecar = ["drv-sidecar-seq-api", "drv-transceivers-api", "h753"] medusa = ["h753", "drv-transceivers-api"] grapefruit = ["h753"] diff --git a/task/thermal/src/bsp/gimlet_bcdef.rs b/task/thermal/src/bsp/gimlet_bcdef.rs index 993418c326..220a2fe2d7 100644 --- a/task/thermal/src/bsp/gimlet_bcdef.rs +++ b/task/thermal/src/bsp/gimlet_bcdef.rs @@ -11,8 +11,8 @@ use crate::{ }, i2c_config::{devices, sensors}, }; -pub use drv_gimlet_seq_api::SeqError; -use drv_gimlet_seq_api::{PowerState, Sequencer}; +pub use drv_cpu_seq_api::SeqError; +use drv_cpu_seq_api::{PowerState, Sequencer}; use task_sensor_api::SensorId; use task_thermal_api::ThermalProperties; use userlib::{task_slot, units::Celsius, TaskId, UnwrapLite};