Skip to content

allwinner: V831/V833 machine -- YI camera boots from its NOR dump, with Ethernet, SD and a coded picture - #203

Merged
dimerr merged 4 commits into
OpenIPC:masterfrom
dimerr:allwinner-v83x
Oct 24, 2026
Merged

dimerr merged 4 commits into
OpenIPC:masterfrom
dimerr:allwinner-v83x

Conversation

@dimerr

@dimerr dimerr commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

New machine -M v831 / -M v833 (Allwinner sun8iw19). A Xiaoyi (YI, y291ga) SPI NOR dump boots unmodified through boot0, OP-TEE, U-Boot 2018.05 and Linux 4.9 to a root shell and the vendor application.

What works

  • Full boot from the flash image: BROM stub → eGON boot0 → OP-TEE → U-Boot → kernel → squashfs root. The kernel console needs /debug_tty on the SD card.
  • Ethernet: sun8i EMAC (the camera ships Wi-Fi only). DHCP, ping and HTTP all work.
  • SD card: an 8 GB SDHC card mounts and passes the firmware's fsck. Patch 0010 adds the CMD11 answer that SDHC init needs.
  • Video: sensor (GC2053), CSI DMA, IOMMU, cedar VE.
    • The H.264 encoder codes the actual input picture in CABAC: I_16x16 with DC coefficients and exact reconstruction tracking; P frames use skip + I_PCM.
    • In LBC mode the video input writes a private block-average stand-in (aw-qlbc.h), since the real LBC format isn't public.
    • Dumped main (1080p) and sub (360p) streams decode with libavcodec with zero errors and show the test pattern.
  • G2D: the RCQ register queue with scale + format conversion. The app's 640x360 NV21 → 320x240 Y8 task now succeeds, and its motion detection fires.
  • Audio: capture FIFOs feed silence at the programmed rate, so the AAC encoder runs.
  • qemu-boot/yi-v831-prepare.sh makes a copy of the dump that behaves as paired: a Wi-Fi config, plus eth0 renamed to wlan0 with a wpa_cli stand-in.

Not modelled

USB Wi-Fi, the real LBC/FBC formats, JPEG, ISP statistics, NNA (person detection), G2D blending/rotation, CE. Event recording by mp4record was not checked.

Testing

  • bash qemu-boot/test-v831-boot.sh --flash full.bin passes all milestones, including shell and Ethernet, in about 15 s.
  • An offline encoder harness against libavcodec is pixel-exact over QP 0–51.

Docs: docs/allwinner-v83x.md.

…, with Ethernet, SD and a coded picture

A new machine (-M v831 / v833) that runs a Xiaoyi (y291ga) SPI NOR dump
through boot0, OP-TEE, U-Boot and Linux to the vendor application:

- SoC devices: CCU, DRAMC, DMA, SPI + NOR, watchdog, PIO, TWI, IOMMU,
  audio capture FIFOs; upstream timers, sdhost, i2c, sun8i EMAC.
- Video: cedar VE (aw-ve) with the H.264 encoder coding the input picture
  in CABAC (I_16x16 DC, P_Skip/I_PCM, exact reconstruction tracking);
  CSI DMA (aw-vinc) painting a test pattern, and in LBC mode a private
  block-average stand-in (aw-qlbc.h) the encoder reads; G2D (aw-g2d)
  running the register queue's scale/convert task.
- Patches for upstream sdhost, i2c, EMAC MDIO and SD CMD11.
- qemu-boot/test-v831-boot.sh (boot + Ethernet milestones) and
  qemu-boot/yi-v831-prepare.sh (a copy that runs as if paired).
- docs/allwinner-v83x.md.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add Allwinner V831/V833 machines with NOR boot and camera media support

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add V831/V833 machines that boot camera NOR dumps through the vendor firmware stack.
• Model Ethernet, SD, audio, and video devices needed by the YI application.
• Add boot checks, image preparation tools, compatibility patches, and documentation.
Diagram

graph TD
  NOR[("SPI NOR")] --> Machine["V83x machine"] --> Firmware["Vendor firmware"]
  Machine --> Peripherals["Boot peripherals"]
  Machine --> IOMMU["Media IOMMU"]
  Firmware --> Input["CSI input"] --> IOMMU --> Encoder["H.264 encoder"]
  IOMMU --> G2D["G2D scaler"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Shortcut the firmware boot chain
  • ➕ Requires fewer boot-facing device models.
  • ➖ Would not exercise unmodified boot0, OP-TEE, U-Boot, or their peripheral interactions.
2. Use an external H.264 encoder
  • ➕ Could reduce bespoke codec logic to maintain.
  • ➖ Adds a dependency and complicates integration with CedarC's bitstream-writer commands and reference tracking.

Recommendation: Keep the peripheral-based boot path: running the unmodified dump is the central goal, which a shortcut would undermine. The in-model encoder fits CedarC's register-level workflow, although its codec correctness merits focused review.

Files changed (28) +6075 / -2

Enhancement (16) +5289 / -0
yi-v831-prepare.shPrepare a paired-mode copy of a YI dump +182/-0

Prepare a paired-mode copy of a YI dump

• Sets Wi-Fi configuration in a copied image and rebuilds its home filesystem with an Ethernet-to-wlan0 rename and wpa_cli stand-in. This lets the application proceed past pairing and start its encoders.

qemu-boot/yi-v831-prepare.sh

allwinner-v83x.cDefine V831/V833 machines and wire their SoC devices +603/-0

Define V831/V833 machines and wire their SoC devices

• Adds Cortex-A7 machines with different default RAM sizes, TrustZone-capable GIC wiring, memory maps, flash-backed boot0 loading, and peripheral connections. It reuses existing QEMU devices alongside the new models.

qemu/hw/arm/allwinner-v83x.c

aw-audio.cModel silent audio capture FIFOs +221/-0

Model silent audio capture FIFOs

• Adds codec ADC and DAUDIO capture registers, timed silent samples, and DMA requests so ALSA capture and the application’s AAC encoder can run.

qemu/hw/audio/aw-audio.c

aw-dma.cModel descriptor-driven Allwinner DMA +418/-0

Model descriptor-driven Allwinner DMA

• Adds 16 channels with descriptor chains, interrupts, and separate source and destination DRQ handshakes. This supports FIFO transfers such as U-Boot’s large SPI reads.

qemu/hw/dma/aw-dma.c

aw-pio.cModel GPIO input levels and pin configuration +121/-0

Model GPIO input levels and pin configuration

• Adds PIO register storage and idle-high input reads unless a pin is pulled down, avoiding a false reset-button press in the YI firmware.

qemu/hw/gpio/aw-pio.c

aw-twi.cAdd the Allwinner TWI packet engine +350/-0

Add the Allwinner TWI packet engine

• Models the packet-mode controller’s FIFOs, transfers, status, and interrupts alongside the reused legacy TWI device. The documented YI kernel uses the legacy registers rather than this new path.

qemu/hw/i2c/aw-twi.c

aw-ccu.cProvide boot-visible clock control status +121/-0

Provide boot-visible clock control status

• Stores clock registers and reports immediate PLL lock and clock-update completion where boot firmware polls for them.

qemu/hw/misc/aw-ccu.c

aw-dramc.cComplete firmware DRAM training polls +111/-0

Complete firmware DRAM training polls

• Adds DRAM controller registers that report training steps complete and the controller in normal operating mode.

qemu/hw/misc/aw-dramc.c

aw-g2d.cExecute G2D register-queue scale and convert tasks +457/-0

Execute G2D register-queue scale and convert tasks

• Loads IOMMU-backed register blocks from the RCQ, scales the video layer into a write-back buffer, converts supported formats, and signals completion. This covers the application’s NV21-to-Y8 motion-detection task.

qemu/hw/misc/aw-g2d.c

aw-iommu.cTranslate media-device DMA addresses +190/-0

Translate media-device DMA addresses

• Adds enable and bypass registers plus two-level page-table walks for media buffer access. Cache invalidation requests complete immediately because the model does not cache translations.

qemu/hw/misc/aw-iommu.c

aw-ve.cModel cedar VE bitstream writing and H.264 encoding +1378/-0

Model cedar VE bitstream writing and H.264 encoding

• Implements CedarC-visible identity, register handshakes, bitstream writing, interrupts, and CABAC slice coding from input-picture block averages. Tracks reconstruction per stream and optionally dumps encoded frames.

qemu/hw/misc/aw-ve.c

aw-vinc.cGenerate timed CSI test-pattern frames +454/-0

Generate timed CSI test-pattern frames

• Models four video-input DMA channels, buffer modes, and frame interrupts. Writes raw frames or the private LBC stand-in through the IOMMU for downstream media processing.

qemu/hw/misc/aw-vinc.c

aw-spi.cModel SPI exchanges with FIFO and DMA pacing +435/-0

Model SPI exchanges with FIFO and DMA pacing

• Adds SPI controllers with chip-select handling, transmit and receive FIFOs, interrupts, and DRQ outputs. Exchanges pause for FIFO service to support boot0 and U-Boot NOR transfers.

qemu/hw/ssi/aw-spi.c

aw-wdt.cModel the Allwinner watchdog timer +170/-0

Model the Allwinner watchdog timer

• Adds restart-key, interval, interrupt, and whole-system reset behavior used by the vendor firmware.

qemu/hw/watchdog/aw-wdt.c

aw-iommu.hExpose media-master DMA translation helpers +34/-0

Expose media-master DMA translation helpers

• Declares master IDs and read/write helpers shared by the CSI, G2D, and VE models.

qemu/include/hw/misc/aw-iommu.h

aw-qlbc.hDefine the private video-input buffer format +44/-0

Define the private video-input buffer format

• Defines a block-average stand-in shared by video input and the encoder because the hardware LBC format is not public.

qemu/include/hw/misc/aw-qlbc.h

Bug fix (7) +266 / -0
0004-allwinner-sdhost-dmac-soft-reset.patchMake SD host IDMAC reset self-clearing +33/-0

Make SD host IDMAC reset self-clearing

• Changes the upstream SD host model so vendor U-Boot can finish its DMA reset poll.

qemu/patches/0004-allwinner-sdhost-dmac-soft-reset.patch

0005-allwinner-i2c-soft-reset-pulse.patchMake legacy TWI soft reset a pulse +34/-0

Make legacy TWI soft reset a pulse

• Changes the upstream I2C model to clear reset after a reset write, allowing vendor drivers to continue with transfers.

qemu/patches/0005-allwinner-i2c-soft-reset-pulse.patch

0006-allwinner-i2c-nack-raises-interrupt.patchSignal TWI NACK state changes +30/-0

Signal TWI NACK state changes

• Raises the upstream I2C model’s interrupt flag on address and data NACKs so failed probes do not wait for a timeout.

qemu/patches/0006-allwinner-i2c-nack-raises-interrupt.patch

0007-allwinner-i2c-master-without-bus-en.patchAllow TWI master transfers without BUS_EN +40/-0

Allow TWI master transfers without BUS_EN

• Removes a BUS_EN requirement from upstream master-mode transfers and interrupt generation to match the vendor driver’s use of the controller.

qemu/patches/0007-allwinner-i2c-master-without-bus-en.patch

0008-allwinner-i2c-irq-follows-int-en.patchGate the TWI interrupt line with INT_EN +25/-0

Gate the TWI interrupt line with INT_EN

• Updates the upstream model’s IRQ level after control-register writes so disabling interrupts prevents repeated handler entry.

qemu/patches/0008-allwinner-i2c-irq-follows-int-en.patch

0009-allwinner-sun8i-emac-mdio-absent-phy.patchCorrect EMAC MDIO scans of absent PHYs +40/-0

Correct EMAC MDIO scans of absent PHYs

• Expands PHY and register address fields to five bits and returns 0xffff for absent PHYs. This prevents the vendor driver from attaching to a phantom PHY.

qemu/patches/0009-allwinner-sun8i-emac-mdio-absent-phy.patch

0010-sd-answer-cmd11-voltage-switch.patchLet SDHC initialization fall back from 1.8 V +64/-0

Let SDHC initialization fall back from 1.8 V

• Answers CMD11 with an error when voltage switching is unsupported and reports S18A only when requested, allowing the vendor host to continue at 3.3 V.

qemu/patches/0010-sd-answer-cmd11-voltage-switch.patch

Tests (1) +173 / -0
test-v831-boot.shCheck NOR boot milestones and Ethernet +173/-0

Check NOR boot milestones and Ethernet

• Copies a supplied dump, creates an SD image containing /debug_tty, and checks ordered boot milestones plus shell, DHCP, and ping probes. The vendor flash image is supplied externally.

qemu-boot/test-v831-boot.sh

Documentation (3) +296 / -2
CLAUDE.mdRecord V83x implementation and firmware constraints +24/-0

Record V83x implementation and firmware constraints

• Adds maintainer notes on the boot path, peripheral fixes, media models, and YI image preparation.

CLAUDE.md

README.mdList and introduce the V831/V833 machines +28/-2

List and introduce the V831/V833 machines

• Adds Allwinner to the machine inventory and summarizes boot, networking, media support, and the V833 testing limitation.

README.md

allwinner-v83x.mdDocument V83x boot and device behavior +244/-0

Document V83x boot and device behavior

• Provides the memory map, boot instructions, firmware-specific requirements, media pipeline, image preparation, and unsupported features.

docs/allwinner-v83x.md

Other (1) +51 / -0
setup.shInclude V83x sources in the QEMU build +51/-0

Include V83x sources in the QEMU build

• Copies the new machine and device files into the QEMU source tree and adds guarded Kconfig and Meson entries for their build dependencies.

qemu/setup.sh

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Camera peripherals become inaccessible 🐞 Bug ≡ Correctness
Description
aw_v83x_common_init() adds a catch-all unimplemented region after mapping the modeled peripherals
at the same overlap priority. Because its address range includes the UART, storage, network, and
media registers, guest accesses can resolve to the catch-all region instead of those devices.
Code

qemu/hw/arm/allwinner-v83x.c[525]

+    create_unimplemented_device("aw-periph", 0x01000000, 0x09000000);
Evidence
The new region spans 0x01000000–0x09ffffff and is installed after ordinary mappings for devices
within that range; the repository's Novatek machine instead uses explicit higher-priority overlaps
for modeled devices inside a broad unimplemented region.

qemu/hw/arm/allwinner-v83x.c[459-492]
qemu/hw/arm/allwinner-v83x.c[520-525]
qemu/hw/arm/novatek.c[1106-1139]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The catch-all unimplemented MMIO region overlaps modeled peripherals and is installed after them without lower priority.
## Fix Focus Areas
- qemu/hw/arm/allwinner-v83x.c[520-525]
## Recommended Fix
Map the catch-all with lower overlap priority, or explicitly give every modeled region higher priority, and verify accesses reach representative devices.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. A DMA descriptor can terminate QEMU ✓ Resolved
Description
aw_dma_step() allocates the entire guest-supplied memory-to-memory transfer length with
g_malloc(). A guest can enable a channel whose descriptor specifies an enormous length, causing an
unbounded host allocation before any transfer error is handled.
Code

qemu/hw/dma/aw-dma.c[140]

+    AwDmaChan *c = &s->ch[n];
Evidence
Descriptor word three directly sets c->left, enabling the channel calls the transfer path, and
that path allocates c->left bytes without a bound.

qemu/hw/dma/aw-dma.c[101-114]
qemu/hw/dma/aw-dma.c[126-150]
qemu/hw/dma/aw-dma.c[173-188]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Guest DMA descriptor length is passed directly to a potentially fatal host allocation.
## Fix Focus Areas
- qemu/hw/dma/aw-dma.c[126-151]
## Recommended Fix
Transfer memory-to-memory payloads in a fixed-size buffer, advancing addresses and checking transaction results for each chunk.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Odd-width video output overruns chroma ✓ Resolved
Description
aw_g2d_put() writes both chroma bytes at x and x + 1 for every even output pixel without
checking whether the second byte fits. With an odd-width semiplanar output and its default pitch,
the last pixel writes past the row and can write past the allocated plane.
Code

qemu/hw/misc/aw-g2d.c[R249-255]

+    case FMT_YUV422SP_VU: case FMT_YUV420SP_VU:
+        pl[1][cy * p->pitch[1] + x] = yuv[2];
+        pl[1][cy * p->pitch[1] + x + 1] = yuv[1];
+        break;
+    case FMT_YUV422SP_UV: case FMT_YUV420SP_UV:
+        pl[1][cy * p->pitch[1] + x] = yuv[1];
+        pl[1][cy * p->pitch[1] + x + 1] = yuv[2];
Evidence
Default pitch can equal an odd width, while the write path stores at x + 1 for the final even x;
the allocated chroma plane is derived from that pitch.

qemu/hw/misc/aw-g2d.c[243-276]
qemu/hw/misc/aw-g2d.c[292-300]
qemu/hw/misc/aw-g2d.c[339-349]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Semiplanar chroma writes unconditionally access the byte after the last pixel of an odd-width row.
## Fix Focus Areas
- qemu/hw/misc/aw-g2d.c[243-255]
- qemu/hw/misc/aw-g2d.c[292-300]
## Recommended Fix
Reject unsupported odd widths or size and index chroma rows so both bytes of each pair are always within the allocation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View action required (2)
4. Guest G2D pitch overruns QEMU heap buffers ✓ Resolved
Description
aw_g2d_plane_size() computes allocations as pitch * h using guest-programmed values, while
aw_g2d_get() and aw_g2d_put() index pixels by y * pitch + x * bpp without checking that the
pitch covers the configured width or that the allocation-size product fits in uint32_t. A short
pitch, such as 1 for an 8192-wide ARGB picture, or a wrapping product lets a register-queue task
read beyond the input plane and write beyond the output plane, corrupting QEMU's heap.
Code

qemu/hw/misc/aw-g2d.c[R269-276]

+    if (n == 0) {
+        return p->pitch[0] * p->h;
+    }
+    if (p->fmt == FMT_Y8 || aw_g2d_fmt_bpp(p->fmt) ||
+        (n == 2 && p->fmt != FMT_YUV422P && p->fmt != FMT_YUV420P)) {
+        return 0;
+    }
+    return p->pitch[n] * (c420 ? (p->h + 1) / 2 : p->h);
Evidence
Picture dimensions and pitches come from registers, and a pitch is replaced only when it is zero.
Plane allocation uses pitch * h, but packed-pixel access adds x * bpp for columns up to the
configured width without checking the minimum row pitch; aw_g2d_put() then writes px[0..3]
through op[0]. The allocation product is also computed in uint32_t, so it can wrap.

qemu/hw/misc/aw-g2d.c[265-302]
qemu/hw/misc/aw-g2d.c[326-355]
qemu/hw/misc/aw-g2d.c[147-239]
qemu/hw/misc/aw-g2d.c[155-157]
qemu/hw/misc/aw-g2d.c[265-301]
qemu/hw/misc/aw-g2d.c[330-349]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
G2D plane buffers are sized from guest-programmed pitches, but pixel access is governed by the configured width. A pitch smaller than its plane's row width, or a `pitch * height` product that overflows, can let a guest task access beyond the allocated buffers.
## Fix Focus Areas
- qemu/hw/misc/aw-g2d.c[265-302]
- qemu/hw/misc/aw-g2d.c[326-355]
## Recommended Fix
In `aw_g2d_pic`/`aw_g2d_task`, validate each format's minimum plane pitch before allocation or pixel access and reject invalid tasks with `LOG_GUEST_ERROR`. Require `pitch[0] >= w * max(bpp, 1)`; for chroma planes, require `pitch[1] >= round_up(w, 2)` for semi-planar formats and at least `(w + 1) / 2` for planar formats. Compute plane sizes in `uint64_t` and reject sizes above a sane cap, such as 64 MiB.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Guest-chosen frame size can crash the VE 🐞 Bug ⛨ Security
Description
aw_ve_encode() derives macroblock counts of up to 32768x32768 from register 0xA00.
aw_h264_pic_alloc() then computes mbw * mbh * 16 in unsigned, which wraps (2^34 becomes 0), or
else asks for gigabytes. aw_ve_input() likewise sizes its buffer as bw * bh + 2 * cw * ch from
16-bit header fields, and that sum can wrap. aw_ve_blocks() then reads and writes with the
unwrapped dimensions, so a guest can overflow QEMU's heap or make g_malloc abort.
Code

qemu/hw/misc/aw-ve.c[R679-681]

+    p->y = g_malloc0(mbw * mbh * 16);
+    p->u = g_malloc0(mbw * mbh * 4);
+    p->v = g_malloc0(mbw * mbh * 4);
Evidence
w and h come from 16-bit register fields scaled by 8/16, and nothing bounds them. The
allocations use unchecked 32-bit products. aw_ve_blocks writes dh*dw bytes based on mbw/mbh
and reads src from bw/bh/cw/ch.

qemu/hw/misc/aw-ve.c[675-682]
qemu/hw/misc/aw-ve.c[1094-1139]
qemu/hw/misc/aw-ve.c[1141-1180]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Guest-controlled picture dimensions in the VE encoder overflow the size calculations, which leads to undersized allocations and out-of-bounds accesses, or to huge allocations that abort QEMU.
## Fix Focus Areas
- qemu/hw/misc/aw-ve.c[675-682]
- qemu/hw/misc/aw-ve.c[1113-1139]
- qemu/hw/misc/aw-ve.c[1141-1172]
## Recommended Fix
In `aw_ve_encode`, reject (log LOG_GUEST_ERROR and return) when `w` or `h` is 0 or above the hardware maximum (e.g. 4096x4096 pixels, i.e. 256 MBs per side). In `aw_ve_input`, bound bw/bh/cw/ch (e.g. <= 4096) and compute the buffer size in size_t/uint64_t before allocating.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

6. Small video buffers corrupt encoded output ✓ Resolved
Description
aw_ve_vle_byte() wraps bitstream writes to the beginning of the programmed output range, but
aw_ve_encode() does not stop when a generated slice exceeds that range. A P slice containing a raw
macroblock can exceed a small guest-programmed buffer and overwrite its earlier bytes while
reporting the longer slice length.
Code

qemu/hw/misc/aw-ve.c[R107-114]

+static uint32_t aw_ve_vle_byte(AwVeState *s, uint32_t pos)
+{
+    uint32_t base = s->regs[AVC_VLE_ADDR >> 2] << 8;
+    uint32_t size = (s->regs[AVC_VLE_END >> 2] + 1 -
+                     s->regs[AVC_VLE_ADDR >> 2]) << 8;
+
+    return base + (size ? (pos >> 3) % size : pos >> 3);
+}
Evidence
Byte addresses are calculated modulo the configured size, while encoding continues to write and
advance the output length; the P-frame raw-macroblock path alone can emit 384 picture bytes.

qemu/hw/misc/aw-ve.c[107-114]
qemu/hw/misc/aw-ve.c[969-996]
qemu/hw/misc/aw-ve.c[1179-1195]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The encoder can wrap and overwrite an unfinished slice when generated output exceeds the programmed range.
## Fix Focus Areas
- qemu/hw/misc/aw-ve.c[107-114]
- qemu/hw/misc/aw-ve.c[1179-1195]
## Recommended Fix
Check available output capacity before writing the encoded slice; report an encoder failure instead of wrapping over bytes needed by the same slice.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. A video trigger produces undefined bits ✓ Resolved
Description
aw_ve_put_bits() shifts a 32-bit value by n - 1 - i, but the trigger handler accepts bit counts
up to 63. Writing a trigger with a count above 32 reaches an undefined C shift and makes the emitted
bits compiler-dependent.
Code

qemu/hw/misc/aw-ve.c[128]

+        b = (b & ~(1u << sh)) | (((v >> (n - 1 - i)) & 1) << sh);
Evidence
The MMIO trigger passes a six-bit count to the writer, which shifts a uint32_t by n - 1 - i; a
count of 63 makes the first shift 62.

qemu/hw/misc/aw-ve.c[117-132]
qemu/hw/misc/aw-ve.c[1238-1247]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A guest-provided count can make the bit writer shift a 32-bit value by more than 31.
## Fix Focus Areas
- qemu/hw/misc/aw-ve.c[117-132]
- qemu/hw/misc/aw-ve.c[1238-1247]
## Recommended Fix
Define and enforce the supported count for this 32-bit value, or implement larger counts without out-of-range shifts.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. A fifth video stream inherits old frames ✓ Resolved
Description
aw_ve_stream() reassigns a four-slot stream entry to a new output address without clearing its
reference and previous-frame pictures when dimensions match. After four distinct streams, a P frame
on a fifth address can be marked unchanged against the evicted stream and emitted as a skip despite
having no corresponding decoder reference.
Code

qemu/hw/misc/aw-ve.c[R1077-1083]

+    if (!st) {
+        i = s->next_stream++ % AW_VE_STREAMS;
+        if (!s->streams[i]) {
+            s->streams[i] = g_new0(AwVeStream, 1);
+        }
+        st = s->streams[i];
+        st->vle_addr = addr;
Evidence
Slot selection wraps after four addresses, but picture state is reset only on a dimension change;
the P-frame skip decision compares its input against prev.

qemu/hw/misc/aw-ve.c[1065-1089]
qemu/hw/misc/aw-ve.c[947-966]
qemu/hw/misc/aw-ve.c[1032-1041]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Reusing an encoder slot for a different output address preserves the previous stream's coding reference.
## Fix Focus Areas
- qemu/hw/misc/aw-ve.c[1065-1089]
## Recommended Fix
Reset the reference and previous-frame state whenever a slot is assigned to a different stream, including when dimensions are unchanged.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View review recommended (10)
9. Long camera control transfers stall ✓ Resolved
Description
aw_twi_run() returns when its transmit FIFO empties or receive FIFO fills without requesting
service through an interrupt. Interrupt-driven transfers longer than the 32-byte FIFO stop at that
point because completion and the existing receive-request signal are raised only after the packet
finishes.
Code

qemu/hw/i2c/aw-twi.c[R182-186]

+            if (fifo8_is_full(&s->rx)) {
+                return;
+            }
+            fifo8_push(&s->rx, i2c_recv(s->bus));
+        } else {
Evidence
The run loop returns on empty TX or full RX without setting pending status; normal receive-request
status is set in the completion routine rather than while a full FIFO blocks progress.

qemu/hw/i2c/aw-twi.c[90-116]
qemu/hw/i2c/aw-twi.c[151-190]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The packet engine does not interrupt the guest when an unfinished transfer needs its FIFO refilled or drained.
## Fix Focus Areas
- qemu/hw/i2c/aw-twi.c[65-95]
- qemu/hw/i2c/aw-twi.c[151-190]
## Recommended Fix
Implement transmit and receive FIFO service pending bits, assert them at starvation/full thresholds, and update them as the guest accesses the FIFOs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Reset can leave a camera bus busy ✓ Resolved
Description
aw_twi_reset_hold() marks an active packet idle without ending its I²C bus transfer. Reset after
aw_twi_start() succeeds leaves the bus transaction open rather than taking the
i2c_end_transfer() path used for normal completion.
Code

qemu/hw/i2c/aw-twi.c[R322-326]

+                          AW_TWI_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+    s->bus = i2c_init_bus(DEVICE(obj), "i2c");
+    fifo8_create(&s->tx, AW_TWI_FIFO);
Evidence
The packet path opens a bus transfer, normal completion closes it, and reset clears the phase
without calling the bus close operation.

qemu/hw/i2c/aw-twi.c[100-127]
qemu/hw/i2c/aw-twi.c[315-327]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Reset drops packet-engine state without closing an active I²C bus transaction.
## Fix Focus Areas
- qemu/hw/i2c/aw-twi.c[315-327]
## Recommended Fix
If a transfer is active, call `i2c_end_transfer()` before clearing the packet state and FIFOs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Disabled flash controller still exchanges data ✓ Resolved
Description
aw_spi_write() starts an exchange on TCR.XCH without checking the controller-enable bit in
GCR. A guest write can therefore call ssi_transfer() and clock the attached flash while the SPI
controller is disabled.
Code

qemu/hw/ssi/aw-spi.c[R222-237]

+    aw_spi_update(s);
+}
+
+static void aw_spi_soft_reset(AwSpiState *s)
+{
+    s->gcr = 0x80;              /* transmit pause enabled */
+    s->tcr = 0x87;              /* SS_LEVEL, SPOL, CPOL, CPHA */
+    s->ier = 0;
+    s->isr = 0;
+    s->fcr = 0x00400001;
+    s->wcr = 0;
+    s->ccr = 2;
+    s->mbc = s->mtc = s->bcc = 0;
+    fifo8_reset(&s->tx);
+    s->rx_head = s->rx_count = 0;
+    s->busy = false;
Evidence
The implementation identifies GCR bit zero as enable, but the exchange-start branch tests only
TCR.XCH and busy state before the run loop calls ssi_transfer().

qemu/hw/ssi/aw-spi.c[1-7]
qemu/hw/ssi/aw-spi.c[175-178]
qemu/hw/ssi/aw-spi.c[222-237]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The exchange-start path ignores the SPI controller's enable state.
## Fix Focus Areas
- qemu/hw/ssi/aw-spi.c[222-237]
## Recommended Fix
Prevent an exchange from starting when `GCR.EN` is clear and cover the disabled-controller case in a device test.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Resets leave peripheral signals high ✓ Resolved
Description
The new DMA, I²C, SPI, audio, and watchdog reset paths clear internal request or interrupt state
without driving their output lines low; the DMA reset also retains sampled request levels. Reset
while one of those signals is asserted can leave a stale interrupt or let a subsequently enabled DMA
channel act on a request from an empty audio FIFO.
Code

qemu/hw/dma/aw-dma.c[R369-377]

+};
+
+static void aw_dma_reset_hold(Object *obj, ResetType type)
+{
+    AwDmaState *s = AW_DMA(obj);
+
+    s->irq_en[0] = s->irq_en[1] = 0;
+    s->irq_pend[0] = s->irq_pend[1] = 0;
+    s->secu = s->gate = 0;
Evidence
Each reset clears the status that would normally control an output but omits its output-update
operation; DMA additionally stores DRQ levels independently of the audio FIFO state.

qemu/hw/dma/aw-dma.c[369-377]
qemu/hw/i2c/aw-twi.c[90-95]
qemu/hw/i2c/aw-twi.c[315-327]
qemu/hw/ssi/aw-spi.c[258-271]
qemu/hw/audio/aw-audio.c[167-173]
qemu/hw/watchdog/aw-wdt.c[119-126]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Several new devices reset stored state without clearing already-driven IRQ or DMA-request lines.
## Fix Focus Areas
- qemu/hw/dma/aw-dma.c[369-377]
- qemu/hw/i2c/aw-twi.c[315-327]
- qemu/hw/ssi/aw-spi.c[258-271]
- qemu/hw/audio/aw-audio.c[167-173]
- qemu/hw/watchdog/aw-wdt.c[119-126]
## Recommended Fix
Recompute or explicitly lower each output during reset; also clear DMA's sampled request levels so a later channel enable cannot use a pre-reset request.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. A Wi-Fi name can alter guest commands ✓ Resolved
Description
yi-v831-prepare.sh expands SSID directly into executable echo lines in the generated wpa_cli
shell script. An SSID containing shell quoting or command syntax changes what runs when the guest
invokes status or scan_results, rather than being treated solely as a network name.
Code

qemu-boot/yi-v831-prepare.sh[124]

+    echo "ssid=$SSID"
Evidence
The unquoted heredoc substitutes the SSID into command text at two locations, and the generated file
is installed as an executable guest-side stand-in.

qemu-boot/yi-v831-prepare.sh[105-106]
qemu-boot/yi-v831-prepare.sh[120-153]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An operator-supplied SSID is embedded unescaped in shell commands executed by the prepared guest.
## Fix Focus Areas
- qemu-boot/yi-v831-prepare.sh[105-153]
## Recommended Fix
Store the SSID as quoted data outside the generated executable script, or apply shell-safe quoting before emitting it; test names containing quotes and command substitution.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. The boot test accepts stages out of order ✓ Resolved
Description
test-v831-boot.sh checks each milestone against the entire accumulated serial buffer without
requiring its match to follow the preceding milestone. If a later stage's text appears first, it
remains in the buffer and can still satisfy the check after the earlier text arrives.
Code

qemu-boot/test-v831-boot.sh[R151-153]

+    while i < len(steps) and steps[i][0] in buf:
+        print('ok   %-45s %6.1fs' % (steps[i][1], time.time() - t0))
+        i += 1
Evidence
The script defines an ordered milestone list but searches the same whole buffer for each item,
allowing an already-seen later item to pass its turn.

qemu-boot/test-v831-boot.sh[2-10]
qemu-boot/test-v831-boot.sh[121-153]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The boot test claims to verify ordered milestones but only verifies their presence in accumulated output.
## Fix Focus Areas
- qemu-boot/test-v831-boot.sh[121-153]
## Recommended Fix
After each match, advance a search cursor past that match and search for the next milestone only in subsequent output.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. A large G2D queue length hangs the emulator ✓ Resolved
Description
aw_g2d_load_rcq() loops for (i = 0; i + 16 = 0xFFFFFFF0, i + 16 wraps to 0 and the loop never
ends. Even without wrapping, a length near 4 GiB makes the synchronous MMIO write perform hundreds
of millions of DMA header reads, which freezes the vCPU.
Code

qemu/hw/misc/aw-g2d.c[R101-104]

+    uint32_t len = s->regs[G2D_RCQ_HEADER_LEN >> 2];
+    uint32_t i;
+
+    for (i = 0; i + 16 <= len; i += 16) {
Evidence
len is an unbounded register value and i is uint32_t. The loop condition i + 16 <= len
overflows, and the parser runs synchronously from the RCQ start write.

qemu/hw/misc/aw-g2d.c[98-121]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The RCQ parser loop can overflow, or run billions of times, when the guest gives a huge queue length.
## Fix Focus Areas
- qemu/hw/misc/aw-g2d.c[98-121]
## Recommended Fix
Clamp `len` to a reasonable maximum (e.g. 64 KiB worth of headers). Write the loop as `for (i = 0; len - i >= 16 && i < len; i += 16)`, or count headers as `len / 16` in a separate counter.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. A looping DMA descriptor chain freezes QEMU ✓ Resolved
Description
aw_dma_run() follows c->desc = c->next for as long as aw_dma_step() succeeds, and only the
0xFFFFF800 sentinel ends the chain. There is no iteration bound and no yield. A guest chain that
points back on itself, using memory-to-memory descriptors or zero-length descriptors (which always
complete at once), keeps the MMIO write handler spinning forever.
Code

qemu/hw/dma/aw-dma.c[R195-216]

+            while (c->en && !c->pause) {
+                if (!c->active) {
+                    if (c->desc == AW_DMA_LINK_END ||
+                        !aw_dma_load(s, n, c->desc)) {
+                        c->en = 0;
+                        break;
+                    }
+                }
+                if (!aw_dma_step(s, n)) {
+                    break;
+                }
+                c->active = false;
+                c->pkg_num++;
+                aw_dma_raise(s, n, IRQ_HALF | IRQ_PKG);
+                if (c->next == AW_DMA_LINK_END) {
+                    aw_dma_raise(s, n, IRQ_QUEUE);
+                    c->desc = AW_DMA_LINK_END;
+                    c->en = 0;
+                } else {
+                    c->desc = c->next;
+                }
+            }
Evidence
SDRAM-to-SDRAM steps and steps with left == 0 return true without waiting for a DRQ. The inner
while loop therefore never breaks on a cyclic next pointer, and Linux's cyclic dmaengine mode
builds exactly such rings.

qemu/hw/dma/aw-dma.c[138-179]
qemu/hw/dma/aw-dma.c[181-222]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Circular DMA descriptor lists that never wait on a DRQ make aw_dma_run loop forever.
## Fix Focus Areas
- qemu/hw/dma/aw-dma.c[181-222]
## Recommended Fix
Limit how many descriptors one call processes per channel (e.g. 1024). When the limit is hit, break out and continue from a bottom half or timer so the guest makes progress without hanging the vCPU. Also cap `c->left` for the memory-to-memory g_malloc.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


17. Full-duplex SPI reads lose bytes past 64 ✓ Resolved
Description
In aw_spi_run() the RX-FIFO-full stall applies only outside the transmit phase. When TCR_DHB is
clear, bytes received during the TX phase go to aw_spi_rx_push(), which drops them with a log
message once 64 are queued. A full-duplex transfer that receives more than 64 bytes before the
driver drains RX loses data silently, although the file's header says the exchange waits for RX to
drain.
Code

qemu/hw/ssi/aw-spi.c[R199-212]

+        if (tx_phase) {
+            if (fifo8_is_empty(&s->tx)) {
+                break;
+            }
+            out = fifo8_pop(&s->tx);
+        } else if (s->rx_count == AW_SPI_FIFO) {
+            break;
+        }
+        in = ssi_transfer(s->bus, out);
+        if (!tx_phase && s->done >= mtc + dbc) {
+            aw_spi_rx_push(s, in);
+        } else if (tx_phase && !(s->tcr & TCR_DHB)) {
+            aw_spi_rx_push(s, in);
+        }
Evidence
The else if (s->rx_count == AW_SPI_FIFO) break; check is reached only when !tx_phase.
aw_spi_rx_push returns without storing the byte when the FIFO is full.

qemu/hw/ssi/aw-spi.c[18-24]
qemu/hw/ssi/aw-spi.c[177-212]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
RX bytes are dropped during the full-duplex TX phase once the RX FIFO is full.
## Fix Focus Areas
- qemu/hw/ssi/aw-spi.c[194-212]
## Recommended Fix
Before popping a TX byte, break out of the loop if the byte will be pushed to RX (tx_phase && !(tcr & TCR_DHB)) and `rx_count == AW_SPI_FIFO`. The exchange then resumes when the guest or DMA drains RXD.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


18. SD cards stop offering 1.8 V on every board ✓ Resolved
Description
Patch 0010’s sd_cmd_SEND_OP_COND() clears R_OCR_ACCEPT_SWITCH_1V8_MASK from the persistent
sd->ocr when an ACMD41 request omits S18R, rather than masking only that response, and the bit is
not restored until card reset. Linux’s initial argument-zero OCR query triggers this before a later
S18R request, so the card no longer advertises its configured 1.8 V capability on any machine
sharing sd.c, including the EV300 boards configured by setup.sh.
Code

qemu/patches/0010-sd-answer-cmd11-voltage-switch.patch[R49-52]

++        /* S18A answers S18R: a host that did not ask is not offered 1.8 V */
++        if (!(req.arg & R_OCR_ACCEPT_SWITCH_1V8_MASK)) {
++            sd->ocr &= ~R_OCR_ACCEPT_SWITCH_1V8_MASK;
++        }
Evidence
The ACMD41 handler mutates the card-state value sd->ocr rather than a response-local OCR value,
while setup.sh sets S18A only during OCR initialization. Because every qemu/patches/*.patch is
applied to the shared upstream tree, the change affects all machines using sd.c, including the EV300
boards.

qemu/patches/0010-sd-answer-cmd11-voltage-switch.patch[1-13]
qemu/patches/0010-sd-answer-cmd11-voltage-switch.patch[45-55]
qemu/setup.sh[842-851]
qemu/patches/0010-sd-answer-cmd11-voltage-switch.patch[45-53]
qemu/setup.sh[842-852]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An ACMD41 request without S18R permanently removes the card’s configured S18A capability until reset; Linux’s initial OCR query has argument zero, so a later request with S18R cannot receive the 1.8 V advertisement.
## Fix Focus Areas
- qemu/patches/0010-sd-answer-cmd11-voltage-switch.patch[45-55]
## Recommended Fix
Keep the S18A capability in `sd->ocr` and mask it only in the R3 OCR response to requests without S18R. Compute a response-local OCR value in the R3 response path, or store the request’s S18R bit in a state flag used by the R3 builder. If the intent is instead never to offer 1.8 V, remove the bit at its source and update the commit message.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

19. Video input leaks a stale chroma byte ✓ Resolved
Description
For an odd chroma line length clen, the pair loop in the aw-vinc chroma path fills only `x + 1 <
clen positions, yet the whole clen`-byte line is DMA'd to the guest. The last byte comes from an
uninitialised g_realloc buffer (host heap contents) or from an earlier line.
Code

qemu/hw/misc/aw-vinc.c[R207-213]

+            aw_vinc_pixel(p, MIN(x, p->w - 1), c422 ? y : y * 2, yuv);
+            s->line[x] = vu ? yuv[2] : yuv[1];
+            s->line[x + 1] = vu ? yuv[1] : yuv[2];
+        }
+        aw_iommu_dma_write(s->iommu, AW_IOMMU_MASTER_CSI, ca + y * clen,
+                           s->line, clen);
+    }
Evidence
Explorer verified that clen comes from the guest BUF_LEN register, the line buffer is realloc'd
without clearing, and the loop leaves the final byte unset when clen is odd.

qemu/hw/misc/aw-vinc.c[183-216]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An odd chroma length leaves the last byte of the line buffer uninitialised before it is DMA'd to guest memory.
## Fix Focus Areas
- qemu/hw/misc/aw-vinc.c[183-216]
## Recommended Fix
Use g_realloc followed by memset, or g_malloc0, for the line buffer, or write the tail byte explicitly when clen is odd.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can choose which labels appear on a finding, and whether they show icons or text

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo


sysbus_create_simple("aw-ccu", AW_CCU_BASE, NULL);
sysbus_create_simple("aw-dramc", AW_DRAM_CTL_BASE, NULL);
create_unimplemented_device("aw-periph", 0x01000000, 0x09000000);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Camera peripherals become inaccessible 🐞 Bug ≡ Correctness

aw_v83x_common_init() adds a catch-all unimplemented region after mapping the modeled peripherals
at the same overlap priority. Because its address range includes the UART, storage, network, and
media registers, guest accesses can resolve to the catch-all region instead of those devices.
Agent Prompt
## Issue description
The catch-all unimplemented MMIO region overlaps modeled peripherals and is installed after them without lower priority.
## Fix Focus Areas
- qemu/hw/arm/allwinner-v83x.c[520-525]
## Recommended Fix
Map the catch-all with lower overlap priority, or explicitly give every modeled region higher priority, and verify accesses reach representative devices.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread qemu/hw/dma/aw-dma.c
Comment thread qemu/hw/misc/aw-g2d.c
Comment thread qemu/hw/misc/aw-ve.c
Comment thread qemu/hw/misc/aw-ve.c Outdated
Comment thread qemu/hw/misc/aw-ve.c
Comment on lines +679 to +681
p->y = g_malloc0(mbw * mbh * 16);
p->u = g_malloc0(mbw * mbh * 4);
p->v = g_malloc0(mbw * mbh * 4);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. Guest-chosen frame size can crash the ve 🐞 Bug ⛨ Security

aw_ve_encode() derives macroblock counts of up to 32768x32768 from register 0xA00.
aw_h264_pic_alloc() then computes mbw * mbh * 16 in unsigned, which wraps (2^34 becomes 0), or
else asks for gigabytes. aw_ve_input() likewise sizes its buffer as bw * bh + 2 * cw * ch from
16-bit header fields, and that sum can wrap. aw_ve_blocks() then reads and writes with the
unwrapped dimensions, so a guest can overflow QEMU's heap or make g_malloc abort.
Agent Prompt
## Issue description
Guest-controlled picture dimensions in the VE encoder overflow the size calculations, which leads to undersized allocations and out-of-bounds accesses, or to huge allocations that abort QEMU.

## Fix Focus Areas
- qemu/hw/misc/aw-ve.c[675-682]
- qemu/hw/misc/aw-ve.c[1113-1139]
- qemu/hw/misc/aw-ve.c[1141-1172]

## Recommended Fix
In `aw_ve_encode`, reject (log LOG_GUEST_ERROR and return) when `w` or `h` is 0 or above the hardware maximum (e.g. 4096x4096 pixels, i.e. 256 MBs per side). In `aw_ve_input`, bound bw/bh/cw/ch (e.g. <= 4096) and compute the buffer size in size_t/uint64_t before allocating.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread qemu/hw/dma/aw-dma.c
Comment thread qemu/hw/ssi/aw-spi.c
Comment thread qemu/patches/0010-sd-answer-cmd11-voltage-switch.patch Outdated
Comment thread qemu/hw/misc/aw-vinc.c
…eset lines, SD S18A

- aw-dma: memory-to-memory moves in 4 KiB chunks; a run moves at most
  4 MiB (a descriptor counts 64 bytes) and leaves the rest to its bottom
  half, so a huge length or a looping chain cannot hold the vCPU.
- aw-g2d: pitches must hold the width (chroma pairs included), planes are
  bounded, the RCQ length is capped.
- aw-ve: pictures up to 256x256 MBs; a reused stream slot drops its
  reference; a P frame that would wrap over itself in the bitstream
  buffer is sent all-skipped; PutBits counts above 32 put zeros.
- aw-spi: an exchange needs GCR.EN; full-duplex exchanges wait for RX to
  drain instead of dropping bytes.
- aw-twi: TX/RX request interrupts when a packet waits on the FIFOs;
  reset ends an open bus transfer.
- DMA, SPI, TWI, audio, watchdog: reset exit lowers their lines.
- aw-vinc: no stale byte at the end of an odd chroma line.
- patch 0010: S18A is masked in the ACMD41 response only, not cleared
  from the card's OCR.
- yi-v831-prepare.sh quotes the SSID in the wpa_cli stand-in;
  test-v831-boot.sh requires the milestones in order.
… ready (bridged tap received nothing)

On a bridged tap the host sends traffic before the guest's interface is
up; that frame was queued while RX was off, the tap stopped being read,
and the model flushed only on BASIC_CTL1/RX_CTL1 writes, not on RX_CTL0,
which Linux enables reception with last.  The camera's ARP requests went
out and no reply ever came in.  Patch 0011 flushes after any register
write that leaves the receiver ready.  Reproduced with a UDP socket
netdev and a peer that chatters from power-on: 3 ARP requests, no ping
before; 3/3 pings after.
… motion

The colour bars give way to the OpenIPC logo (from OpenIPC/.github
assets/openipc-logo-white.svg), white on a navy gradient, centred and
still, with a round dot sliding to and fro beneath it so the YI
application's motion detection (and with it the recorder) still has
something to see.  The logo is kept as a 3x bitmap's run lengths
(base64 varints, 23 KiB of source), averaged into 4-bit-and-better
coverage once at start-up.  A moving logo would change ~400 macroblocks
a frame, all sent raw in P frames; the dot costs a few.  Both YI streams
decode with no errors.
@dimerr
dimerr merged commit 684ef4e into OpenIPC:master Oct 24, 2026
23 checks passed
@dimerr
dimerr deleted the allwinner-v83x branch October 24, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant