Skip to content

chore: sync main into earlgrey-hwe - #337

Open
synchronizebot[bot] wants to merge 60 commits into
earlgrey-hwefrom
sync/main-to-earlgrey-hwe
Open

chore: sync main into earlgrey-hwe#337
synchronizebot[bot] wants to merge 60 commits into
earlgrey-hwefrom
sync/main-to-earlgrey-hwe

Conversation

@synchronizebot

Copy link
Copy Markdown

Automated daily sync from main to earlgrey-hwe.

⚠️ If conflicts exist, click the "Resolve conflicts" button below to fix them in your browser.

Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v5...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
dependabot Bot and others added 25 commits July 10, 2026 09:29
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Add RAM_NC memory region (0x000A0000, 128K) to target.ld.tmpl and
a .ram_nc (NOLOAD) section so statics tagged with
#[unsafe(link_section = ".ram_nc")] are placed in the AST1060's
non-cached SRAM window rather than cached RAM.

Shrink ram_size_bytes in all system.json5 files that used 384KB
(ending at 0x000A0500) so that the cached RAM region ends exactly
at the RAM_NC boundary (0x000A0000).
The no_panics_test scans the compiled ELF and fails if any panic path is
reachable. Two root causes remained in the SHA-2 / HMAC code linked into
the hace_sha256 binary:

- div_by_zero: chunks_exact(4).zip(..) in load_iv / digest_from_context.
  ChunksExact stores its chunk size as a runtime field, so Zip::new emits
  a len / chunk_size division the optimizer cannot prove non-zero.
  Replaced with index-stride loops over length-proven [u8; 4] arrays.

- copy_from_slice len_mismatch_fail: the staging copies in
  HaceDigest::update and HaceHmacCtx::update copy between two range-sliced
  &[u8] of equal-by-construction length the optimizer cannot prove equal.
  Replaced with zip element-wise copies (no length assert, no division).

Also hardened the AES IV copies (AesCipher::crypt, AesSkin CBC chaining)
to use <[u8; AES_BLOCK]>::try_from array assignment instead of
copy_from_slice, per the project no-panic patterns.

no_panics_test now PASSES; nm shows no panic_is_possible, len_mismatch_fail,
or div_by_zero symbols.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The HACE SHA-2/HMAC KAT test (hace_sha256_test) HardFaulted with an
unaligned UsageFault (wild pointer 0x191818f6) at the sha256 stream-9000
case. Root cause: run_hace_sha2_kats builds a large single stack frame
that overflowed the pigweed-default 2 KiB kernel bootstrap stack into
adjacent .bss (INPUT_BUF); the first case that writes that 4 KiB buffer
(stream-9000) clobbered the live frame and corrupted a saved pointer.
The one-shot cases passed only because they never write INPUT_BUF.

Two parts:
- hmac.rs: move the large HMAC working buffers (key, ipad, opad, and the
  1 KiB msg) off the stack into a single .ram_nc static (HmacNcBufs), so
  HaceHmacCtx is just a few scalars (~20 bytes). This removes the dominant
  per-op stack pressure from the back-to-back HMAC cases. Remaining
  copy_from_slice calls are also converted to zip-copies.
- config.rs: raise KernelConfigInterface::KERNEL_STACK_SIZE_BYTES from the
  2 KiB default to 16 KiB, giving the bootstrap/idle kernel stacks ample
  headroom for the crypto KAT workloads. The AST10x0 has 768 KiB SRAM so
  the extra RAM is negligible.

hace_sha256_test and no_panics_test both pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
It is ready for basic hardware testing, but not production-complete. Region filtering, permanent policy locking, and board-level external-mux GPIO switching/delay still need implementation.
Spimonitor is not monitoring the traffic from spi controller.
Spi monitor is only monitoring the traffic from either BMC or host.
…9 for pulse helper. and split it into explicit assert/release operations so monitor setup happens while the BMC is held in reset.
BMC master and Host.
Configure board-level GPIO:
  - BMC: mux select bit 0, active-low OE bit 1, reset bit 7
  - Host: mux select bit 2, active-low OE bit 3, reset bit 6
Switch the shared SPIM1/2 BMC mux from RoT value 1 to BMC value 0.
 Adding a PROT recovery timeout: if BMC CSIN stays low, assert BMC reset, route to RoT, reset flashes and monitors, then retry
chrysh and others added 30 commits July 21, 2026 11:04
Introduce the Boot Orchestrator's actuation capability: the BootControl
trait (hold_in_reset / release) and HalBootControl, which binds one HAL
ResetControl line to a managed device. Includes a host unit test verifying
that holding a device in reset asserts exactly its configured line.

Includes tests that release deasserts the device's configured line and that a
controller error surfaces through BootControl unchanged. Extend the fake
reset controller with opt-in failure injection to drive the error case.

Closes: 9elements#2

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Christina Quast <christina.quast@9elements.com>
Co-authored-by: Marvin Gudel <marvin@gudel.org>
Tighten BootControl::Error from Debug-only to
`core::error::Error + system_control::Error` so the orchestrator gets
Display and a source() cause chain instead of just the Debug dump, and
so generic `BootControl` consumers can categorize failures via kind()
without downcasting to a concrete error type.

HAL reset controllers keep the existing Error/kind() pattern unchanged;
the new BootError adapter supplies the core::error::Error machinery over
any HAL error, so no per-implementation work is required.

Cover the combined bound with a compile-time fence and tests for Display
output, source(), dyn downcast, and kind() reached through a generic
BootControl.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Christina Quast <christina.quast@9elements.com>
Split the HAL-backed adapter out of fwmanager-api so the api crate is a
dependency-free leaf holding only the BootControl capability contract,
matching the layout of 9elements#20. HalBootControl and the
BootError wrapper move to the new fwmanager-hal-adapters crate, which
depends on //hal/blocking and the api crate.

Drop the system_control::Error bound from BootControl::Error, keeping
core::error::Error only: requiring the HAL error trait in the api crate
would keep the HAL dependency the split is meant to remove. BootError
still exposes kind(), and the generic-consumer test now recovers the
error category by downcasting the dyn core::error::Error instead of
relying on the removed bound.

Add impl From<E> for BootError<E> so implementations forwarding HAL
calls can use ? instead of .map_err(BootError), and switch
HalBootControl over to it.

Add api-side tests proving the contract stays implementable with no HAL
in sight, and cover the release error path in the adapter.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Christina Quast <christina.quast@9elements.com>
Port the AST1060 I3C controller/target driver from aspeed-rust
(src/i3c @ ce3b567) into the ast10x0_peripherals crate, mirroring the
existing I2C port and following the pac-design-patterns conventions.

Driver (peripherals/i3c/): ccc, config, constants, controller, error,
hardware, ibi, mod, types. hal_impl is folded into controller as
inherent methods (proposed_traits is unavailable in openprot and
embedded-hal has no I3C trait).

Design-pattern conformance:
- Confined-`unsafe` MMIO facade: raw `*const` register pointers, a single
  `unsafe fn new`, private `&'static` derefs, `!Sync`; no unsafe or PAC
  types leak above the facade.
- Cooperative-yield bounded poll: an injected `Y: FnMut(u32)` yield
  closure replaces embedded-hal DelayNs, type-erased at the poll loops.
- Borrow-arbitrated exclusivity for per-call state; the global IBI/IRQ
  plane is kept (documented delta) since an ISR cannot borrow a
  stack-owned device.

Notable deltas: drop the Logger generic and the `#[no_mangle]` ISR
symbol exports (kernel owns the vector and calls dispatch_i3c_irq);
heapless 0.9 SPSC with edition-2024 `addr_of_mut!`; reachable
transfer/clock paths hardened to be panic-free (no_panics_test) without
changing success-path behavior.

Also: add scu pinctrl groups (PINCTRL_I3C0..3 / PINCTRL_HVI3C0..3, the
HV groups clearing the conflicting LV pad bits); wire critical-section
and cortex-m `critical-section-single-core` into the crate universe; add
i3c_init and i3c_irq tests, the latter a faithful controller/target IBI
pair mirroring aspeed-rust tests-hw on I3C2 HV.

See target/ast10x0/peripherals/i3c/plans/goal.md for the behavioral
parity plan, authority pin, and deltas ledger.

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One driver type now manages all four bus instances: the Instance
type-parameter and its per-bus impl macro are removed, and the bus is
selected at runtime in I3cRegisters::new(bus), mirroring the SmcRegisters
shape. All I3C MMIO unsafe (pointer derefs) is confined to the new
registers.rs; hardware.rs accesses the blocks through safe delegates.

IRQ ownership moves to the integration layer: enable_irq/disable_irq are
dropped from the hardware traits and the driver only exposes
dispatch_i3c_irq plus an i3c_bus_interrupt(bus) mapping for the NVIC line
the kernel owns. The per-bus handler registry becomes single-shot
(typed Busy on a second claim) and panic-free (UnsafeCell + critical
section, same rationale as the IBI rings, whose closure-based access is
also replaced by leaf push/pop helpers).

The controller is rebuilt around an ISR-shared I3cCore pinned at a
'static address, so the trampoline pointer's validity is type-guaranteed
rather than a convention, with a light two-state lifecycle
(Uninitialized -> start() -> Ready) matching the SMC precedent. Tests
construct the core via cortex_m::singleton!, which also moves the large
config off the 2 KiB bootstrap stack, and unmask the NVIC line
themselves after start().
Complete the SmcRegisters alignment: instead of only confining the
pointer derefs, every register operation now goes through an
intent-named method on I3cRegisters (enable_controller_primary,
assert_all_queue_resets, dat_program_addr, ...), so hardware.rs is pure
protocol logic with zero PAC register types and zero MMIO unsafe. Its
remaining unsafe is non-MMIO only: the IRQ-registry critical-section
leaves, the forwarded constructor gate, the curr_xfer handoff cast, and
the transfer buffer re-slicing.

The per-bus I3C-global reg0/reg1 dispatch and the eight-slot DAT
dispatch move into private macros inside the facade (the bus index
already lives there), deleting the macro layer from hardware.rs along
with its unreachable fallback arms. The FIFO word loops sink into the
facade as tx_fifo_write/rx_fifo_read/rx_fifo_drain/ibi_fifo_*, which
also retires the closure-taking rd_fifo/drain_fifo trait methods.
Restore console_backend.rs to main: the lock -> try_lock change rode
along in the I3C IRQ test stabilization commit but alters shared console
behavior for every target, which does not belong in the I3C series. If
ISR-context console writes need a deadlock-free path, that is its own
change with its own review.
The ISR no longer fabricates a &mut over any thread-owned object. The
per-bus registry now parks an IsrCtx (an ISR-side register handle plus
the role flag) instead of a raw context pointer, and the service routine
works exclusively through &self register methods, per-bus ISR_EVENTS
atomics, and the global IBI rings. Master transfer completion follows
the SMC flag-and-defer model: the ISR masks the completion sources and
latches the status; the polling thread drains the response queue into
its own transfer and re-enables the sources. Target-mode completions
and the master-assigned dynamic address move into the per-bus event
block; ISR-side halt/resume recovery (which needs the wait policy) is
deferred to the thread as a fault flag.

This dissolves the machinery the old design needed: the curr_xfer
AtomicPtr handoff and its unsafe reconstruction, I3cXfer's completion
flag, and the pinned 'static I3cCore (with its singleton! storage and
Pin plumbing) are all gone. The controller is a plain owned value with
zero unsafe; in-flight transfer overlap is structurally impossible
because the transfer never leaves the thread.

The controller borrows its I3cConfig (&'c mut) rather than owning it:
the config embeds ~0.5 KiB of device tables, and the typestate
transition moves the controller by value, so owning the config would
transiently stack multiple copies and overflow the 2 KiB kernel
bootstrap stack (observed as a silent hang during bring-up on the EVB).
Borrowing keeps exactly one config alive in the caller's frame, the
same footprint as the validated pre-rework layout, and matches the I2C
driver's caller-owned-resource convention.

Behavioral deltas from the reference ISR, all thread-visible only:
SIR address validation moves from the ISR to the consumer (which
already validates), and target error recovery runs at the next
operation instead of inside the interrupt.

Verified on a two-board AST1060 setup: the dual-device IBI exchange
test passes 10/10 exchanges.
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Make init, halt, and reset_ctrl return Result instead of swallowing poll
timeouts; start() releases the IRQ slot on init failure so a retry is not
wedged on Busy.

Harden priv_xfer_build_cmds: cap transfers at 16 (4-bit TID aliased larger
batches) and reject over-long lengths (16-bit field truncated silently),
both before consuming any buffer. Replace the unsafe raw-pointer reborrow
with Option::take.

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Set i2c_buses: &[] and handle init's new Result in the three i3c
targets; the i2c commit added both but only updated i2c tests.

Patch off pigweed's syscall_defs incompatibility gate. The roll makes
kernel hard-depend on syscall_defs, which stays incompatible unless
userspace_build is set, breaking every userspace=False system_image.
syscall_defs is pure type defs the kernel always pulls in, so dropping
the constraint changes no runtime behavior. Re-apply on next roll.

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
- Drain RX/IBI FIFO leftovers to prevent transfer misalignment
- SETNEWDA now updates DAT slot + address book
- Address bookkeeping: alloc marking, slot bounds, occupancy checks
- Master error recovery preserves IBI queue (don't reset it)
- validate_clock: fix overflow panic

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
attach_i2c_dev + i2c_write/read/write_read and an embedded-hal I2c impl
route legacy devices through DAT slots by static address. Add
SETMWL/SETMRL/GETMWL/GETMRL/GETMXDS, and latch target-side MWL/MRL
updates from SLV_MAX_LEN.

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Address review feedback from PR #278 and improve state safety during DAA
and transfer recovery:

- Replace boolean `da_assigned` and `ibi_en` with explicit `DaState` and `IbiState` enums.
- Fix `do_ccc` timeout handling to return `I3cDrvError::Timeout` immediately.
- Enforce sticky fault (`xfer_faulted`) when recovery fails to prevent hardware lockup.
- Log and set sticky fault on `init()` failures during SIR timeout recovery.
- Add 7-bit address bounds checks and spec-defined default reservations to `AddrBook`.
- Update peripheral tests (`i3c_init`, `i3c_irq`) to conform to updated state models.

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
…_halt

Confirmed with the original Zephyr I3C driver author: enter_halt isn't
expected to fail in practice, so reset_ctrl intentionally stays
unconditional to match the vendor driver's behavior. A halt failure is
still caught via halt_ok and latches xfer_faulted.

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
The i3c_init and i3c_irq test configs still used the pre-merge
ram_size_bytes (384KB), which now overlaps the RAM_NC alias region
introduced at 0x000A0000 by the upstream merge, causing a link-time
section overlap error. Shrink ram_size_bytes in each config so
ram_start_address + ram_size_bytes lands exactly on the RAM_NC
boundary, matching the fix already applied upstream to i2c_irq.

Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Add gpio peripheral driver to ast10x0_peripherals crate, ported from
aspeed-rust/src/gpio.rs. Follows the crate's established driver pattern:

- types.rs: type states (Input, Output, PushPull, OpenDrain, PullUp,
  PullDown, Floating, Tristate), mode traits, InterruptMode, GpioExt,
  GpioError
- registers.rs: GpioRegisters wrapping *const gpio::RegisterBlock with
  PhantomData<*const ()>, unsafe new(ptr) and new_global() constructors
- mod.rs: gpio_macro! adapted to use GpioRegisters; all 21 bank
  instantiations A-U

Update lib.rs and BUILD.bazel accordingly.
Signed-off-by: Chris Frantz <cfrantz@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants