ARG DEBIAN_FRONTEND=noninteractive ARG QEMU_TAG=esp-develop-9.2.2-20260417 ARG QEMU_ARCHIVE=qemu-xtensa-softmmu-esp_develop_9.2.2_20260417-x86_64-linux-gnu.tar.xz # ============================================================================= # Stage 1 — extract ESP32 ROM blobs from the official pre-built package # (these binary blobs are not built from source; we reuse them as-is) # ============================================================================= FROM ubuntu:22.04 AS rom-extractor ARG QEMU_TAG QEMU_ARCHIVE DEBIAN_FRONTEND RUN apt-get update && apt-get install -y --no-install-recommends \ wget ca-certificates xz-utils \ && rm -rf /var/lib/apt/lists/* RUN wget -qO /tmp/qemu.tar.xz \ "https://github.com/espressif/qemu/releases/download/${QEMU_TAG}/${QEMU_ARCHIVE}" \ && mkdir -p /tmp/rom \ && tar -xJf /tmp/qemu.tar.xz -C /tmp/rom --strip-components=1 \ && ls /tmp/rom/share/qemu/esp32*.bin # ============================================================================= # Stage 2 — build patched QEMU from Espressif source # Adds a silent stub for WiFi modem registers (0x60033C00) so the firmware # does not crash with LoadStorePIFAddrError on first WiFi register access. # ============================================================================= FROM ubuntu:22.04 AS qemu-builder ARG QEMU_TAG DEBIAN_FRONTEND RUN apt-get update && apt-get install -y --no-install-recommends \ git python3 python3-pip python3-tomli ninja-build pkg-config \ libglib2.0-dev libpixman-1-dev libslirp-dev libfdt-dev \ zlib1g-dev libpng-dev libgcrypt20-dev build-essential flex bison \ && rm -rf /var/lib/apt/lists/* # QEMU 9.x requires meson >= 1.1.0 — Ubuntu 22.04 ships an older version RUN pip3 install --quiet 'meson>=1.5' # Shallow clone of the exact release tag RUN git clone --depth=1 --branch "${QEMU_TAG}" \ https://github.com/espressif/qemu.git /qemu WORKDIR /qemu # Inject WiFi modem stub into hw/xtensa/esp32.c COPY wifi_stub_patch.py /tmp/ RUN python3 /tmp/wifi_stub_patch.py # Configure and build — xtensa only, no UI, no docs RUN ./configure \ --target-list=xtensa-softmmu \ --disable-docs \ --disable-gtk \ --disable-sdl \ --disable-vnc \ --disable-curses \ --disable-opengl \ --disable-virglrenderer \ --disable-spice \ --disable-dbus-display \ --disable-guest-agent \ --disable-capstone \ --disable-libudev \ --disable-libusb \ --disable-usb-redir \ --audio-drv-list= \ --enable-slirp \ --enable-fdt \ && ninja -C build qemu-system-xtensa # ============================================================================= # Stage 3 — final runtime image # ============================================================================= FROM ubuntu:22.04 ARG DEBIAN_FRONTEND RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-pip \ libglib2.0-0 libpixman-1-0 libslirp0 libfdt1 libpng16-16 \ && rm -rf /var/lib/apt/lists/* # ROM blobs from the official pre-built package RUN mkdir -p /usr/local/share/qemu COPY --from=rom-extractor /tmp/rom/share/qemu/esp32*.bin /usr/local/share/qemu/ # Patched QEMU binary (built from source with WiFi stub) COPY --from=qemu-builder /qemu/build/qemu-system-xtensa /usr/local/bin/qemu-system-xtensa RUN chmod +x /usr/local/bin/qemu-system-xtensa RUN pip3 install --quiet esptool WORKDIR /emulator COPY modbus_stub.py server.py entrypoint.sh ./ COPY ui/ ui/ RUN chmod +x entrypoint.sh # 8888 = UI debug 3 volets 10080 = webserver ESP32 EXPOSE 8888 10080 ENTRYPOINT ["/emulator/entrypoint.sh"]