mirror of
https://github.com/ruvnet/RuView
synced 2026-07-28 18:21:42 +00:00
feat(firmware): QEMU ESP32-S3 testing platform (ADR-061)
Implement full QEMU emulation framework for firmware testing without physical hardware: Mock CSI Generator (mock_csi.c): - 10 test scenarios: empty room, static/walking person, fall, multi-person, channel sweep, MAC filter, ring overflow, boundary RSSI, zero-length - Physics-based signal model with breathing modulation and Doppler - LFSR pseudo-random noise, CONFIG_CSI_MOCK_ENABLED Kconfig guard - Scenario 255 runs all sequentially QEMU Runner & CI: - qemu-esp32s3-test.sh: build, merge flash image, run QEMU, validate - validate_qemu_output.py: 14 automated checks (boot, NVS, edge, vitals, crash detection) with colored output and severity-based exit codes - generate_nvs_matrix.py: 14 NVS provisioning configs for matrix testing - firmware-qemu.yml: GitHub Actions CI with 4-scenario matrix Fuzz Testing: - 3 libFuzzer targets: CSI serialize, NVS config validation, ring buffer - Host-compilable ESP-IDF stubs (no ESP-IDF dependency for fuzzing) - 6 seed corpus files for guided fuzzing - Makefile with ASAN + UBSAN sanitizers Documentation: - firmware/esp32-csi-node/README.md: comprehensive QEMU testing guide - Root README.md: collapsed QEMU testing section Build verified: normal firmware build (RC=0) with mock_csi excluded. Closes #259 Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef ESP_ERR_H_STUB
|
||||
#define ESP_ERR_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef ESP_LOG_H_STUB
|
||||
#define ESP_LOG_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file esp_stubs.c
|
||||
* @brief Implementation of ESP-IDF stubs for host-based fuzz testing.
|
||||
*
|
||||
* Must be compiled with: -Istubs -I../main
|
||||
* so that ESP-IDF headers resolve to stubs/ and firmware headers
|
||||
* resolve to ../main/.
|
||||
*/
|
||||
|
||||
#include "esp_stubs.h"
|
||||
#include "edge_processing.h"
|
||||
#include "wasm_runtime.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/** Monotonically increasing microsecond counter for esp_timer_get_time(). */
|
||||
static int64_t s_fake_time_us = 0;
|
||||
|
||||
int64_t esp_timer_get_time(void)
|
||||
{
|
||||
/* Advance by 50ms each call (~20 Hz CSI rate simulation). */
|
||||
s_fake_time_us += 50000;
|
||||
return s_fake_time_us;
|
||||
}
|
||||
|
||||
/* ---- stream_sender stubs ---- */
|
||||
|
||||
int stream_sender_send(const uint8_t *data, size_t len)
|
||||
{
|
||||
(void)data;
|
||||
return (int)len;
|
||||
}
|
||||
|
||||
int stream_sender_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stream_sender_init_with(const char *ip, uint16_t port)
|
||||
{
|
||||
(void)ip; (void)port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stream_sender_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* ---- wasm_runtime stubs ---- */
|
||||
|
||||
void wasm_runtime_on_frame(const float *phases, const float *amplitudes,
|
||||
const float *variances, uint16_t n_sc,
|
||||
const edge_vitals_pkt_t *vitals)
|
||||
{
|
||||
(void)phases; (void)amplitudes; (void)variances;
|
||||
(void)n_sc; (void)vitals;
|
||||
}
|
||||
|
||||
esp_err_t wasm_runtime_init(void) { return ESP_OK; }
|
||||
esp_err_t wasm_runtime_load(const uint8_t *d, uint32_t l, uint8_t *id) { (void)d; (void)l; (void)id; return ESP_OK; }
|
||||
esp_err_t wasm_runtime_start(uint8_t id) { (void)id; return ESP_OK; }
|
||||
esp_err_t wasm_runtime_stop(uint8_t id) { (void)id; return ESP_OK; }
|
||||
esp_err_t wasm_runtime_unload(uint8_t id) { (void)id; return ESP_OK; }
|
||||
void wasm_runtime_on_timer(void) {}
|
||||
void wasm_runtime_get_info(wasm_module_info_t *info, uint8_t *count) { (void)info; if(count) *count = 0; }
|
||||
esp_err_t wasm_runtime_set_manifest(uint8_t id, const char *n, uint32_t c, uint32_t m) { (void)id; (void)n; (void)c; (void)m; return ESP_OK; }
|
||||
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* @file esp_stubs.h
|
||||
* @brief Minimal ESP-IDF type stubs for host-based fuzz testing.
|
||||
*
|
||||
* Provides just enough type definitions and macros to compile
|
||||
* csi_collector.c and edge_processing.c on a Linux/macOS host
|
||||
* without the full ESP-IDF SDK.
|
||||
*/
|
||||
|
||||
#ifndef ESP_STUBS_H
|
||||
#define ESP_STUBS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ---- esp_err.h ---- */
|
||||
typedef int esp_err_t;
|
||||
#define ESP_OK 0
|
||||
#define ESP_FAIL (-1)
|
||||
#define ESP_ERR_NO_MEM 0x101
|
||||
#define ESP_ERR_INVALID_ARG 0x102
|
||||
|
||||
/* ---- esp_log.h ---- */
|
||||
#define ESP_LOGI(tag, fmt, ...) ((void)0)
|
||||
#define ESP_LOGW(tag, fmt, ...) ((void)0)
|
||||
#define ESP_LOGE(tag, fmt, ...) ((void)0)
|
||||
#define ESP_LOGD(tag, fmt, ...) ((void)0)
|
||||
#define ESP_ERROR_CHECK(x) ((void)(x))
|
||||
|
||||
/* ---- esp_timer.h ---- */
|
||||
typedef void *esp_timer_handle_t;
|
||||
|
||||
/**
|
||||
* Stub: returns a monotonically increasing microsecond counter.
|
||||
* Declared here, defined in esp_stubs.c.
|
||||
*/
|
||||
int64_t esp_timer_get_time(void);
|
||||
|
||||
/* ---- esp_wifi_types.h ---- */
|
||||
|
||||
/** Minimal rx_ctrl fields needed by csi_serialize_frame. */
|
||||
typedef struct {
|
||||
signed rssi : 8;
|
||||
unsigned channel : 4;
|
||||
unsigned noise_floor : 8;
|
||||
unsigned rx_ant : 2;
|
||||
/* Padding to fill out the struct so it compiles. */
|
||||
unsigned _pad : 10;
|
||||
} wifi_pkt_rx_ctrl_t;
|
||||
|
||||
/** Minimal wifi_csi_info_t needed by csi_serialize_frame. */
|
||||
typedef struct {
|
||||
wifi_pkt_rx_ctrl_t rx_ctrl;
|
||||
uint8_t mac[6];
|
||||
int16_t len; /**< Length of the I/Q buffer in bytes. */
|
||||
int8_t *buf; /**< Pointer to I/Q data. */
|
||||
} wifi_csi_info_t;
|
||||
|
||||
/* ---- Kconfig defaults ---- */
|
||||
#ifndef CONFIG_CSI_NODE_ID
|
||||
#define CONFIG_CSI_NODE_ID 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CSI_WIFI_CHANNEL
|
||||
#define CONFIG_CSI_WIFI_CHANNEL 6
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CSI_WIFI_SSID
|
||||
#define CONFIG_CSI_WIFI_SSID "test_ssid"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CSI_TARGET_IP
|
||||
#define CONFIG_CSI_TARGET_IP "192.168.1.1"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CSI_TARGET_PORT
|
||||
#define CONFIG_CSI_TARGET_PORT 5500
|
||||
#endif
|
||||
|
||||
/* Suppress the build-time guard in csi_collector.c */
|
||||
#ifndef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
#define CONFIG_ESP_WIFI_CSI_ENABLED 1
|
||||
#endif
|
||||
|
||||
/* ---- sdkconfig.h stub ---- */
|
||||
/* (empty — all needed CONFIG_ macros are above) */
|
||||
|
||||
/* ---- FreeRTOS stubs ---- */
|
||||
#define pdMS_TO_TICKS(x) ((x))
|
||||
#define pdPASS 1
|
||||
typedef int BaseType_t;
|
||||
|
||||
static inline int xPortGetCoreID(void) { return 0; }
|
||||
static inline void vTaskDelay(uint32_t ticks) { (void)ticks; }
|
||||
static inline BaseType_t xTaskCreatePinnedToCore(
|
||||
void (*fn)(void *), const char *name, uint32_t stack,
|
||||
void *arg, int prio, void *handle, int core)
|
||||
{
|
||||
(void)fn; (void)name; (void)stack; (void)arg;
|
||||
(void)prio; (void)handle; (void)core;
|
||||
return pdPASS;
|
||||
}
|
||||
|
||||
/* ---- WiFi API stubs (no-ops) ---- */
|
||||
typedef int wifi_interface_t;
|
||||
typedef int wifi_second_chan_t;
|
||||
#define WIFI_IF_STA 0
|
||||
#define WIFI_SECOND_CHAN_NONE 0
|
||||
|
||||
typedef struct {
|
||||
unsigned filter_mask;
|
||||
} wifi_promiscuous_filter_t;
|
||||
|
||||
typedef int wifi_promiscuous_pkt_type_t;
|
||||
#define WIFI_PROMIS_FILTER_MASK_MGMT 1
|
||||
#define WIFI_PROMIS_FILTER_MASK_DATA 2
|
||||
|
||||
typedef struct {
|
||||
int lltf_en;
|
||||
int htltf_en;
|
||||
int stbc_htltf2_en;
|
||||
int ltf_merge_en;
|
||||
int channel_filter_en;
|
||||
int manu_scale;
|
||||
int shift;
|
||||
} wifi_csi_config_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t primary;
|
||||
} wifi_ap_record_t;
|
||||
|
||||
static inline esp_err_t esp_wifi_set_promiscuous(bool en) { (void)en; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_set_promiscuous_rx_cb(void *cb) { (void)cb; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_set_promiscuous_filter(wifi_promiscuous_filter_t *f) { (void)f; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_set_csi_config(wifi_csi_config_t *c) { (void)c; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_set_csi_rx_cb(void *cb, void *ctx) { (void)cb; (void)ctx; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_set_csi(bool en) { (void)en; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_set_channel(uint8_t ch, wifi_second_chan_t sc) { (void)ch; (void)sc; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *b, int len, bool en) { (void)ifx; (void)b; (void)len; (void)en; return ESP_OK; }
|
||||
static inline esp_err_t esp_wifi_sta_get_ap_info(wifi_ap_record_t *ap) { (void)ap; return ESP_FAIL; }
|
||||
static inline const char *esp_err_to_name(esp_err_t code) { (void)code; return "STUB"; }
|
||||
|
||||
/* ---- NVS stubs ---- */
|
||||
typedef uint32_t nvs_handle_t;
|
||||
#define NVS_READONLY 0
|
||||
static inline esp_err_t nvs_open(const char *ns, int mode, nvs_handle_t *h) { (void)ns; (void)mode; (void)h; return ESP_FAIL; }
|
||||
static inline void nvs_close(nvs_handle_t h) { (void)h; }
|
||||
static inline esp_err_t nvs_get_str(nvs_handle_t h, const char *k, char *v, size_t *l) { (void)h; (void)k; (void)v; (void)l; return ESP_FAIL; }
|
||||
static inline esp_err_t nvs_get_u8(nvs_handle_t h, const char *k, uint8_t *v) { (void)h; (void)k; (void)v; return ESP_FAIL; }
|
||||
static inline esp_err_t nvs_get_u16(nvs_handle_t h, const char *k, uint16_t *v) { (void)h; (void)k; (void)v; return ESP_FAIL; }
|
||||
static inline esp_err_t nvs_get_u32(nvs_handle_t h, const char *k, uint32_t *v) { (void)h; (void)k; (void)v; return ESP_FAIL; }
|
||||
static inline esp_err_t nvs_get_blob(nvs_handle_t h, const char *k, void *v, size_t *l) { (void)h; (void)k; (void)v; (void)l; return ESP_FAIL; }
|
||||
|
||||
/* ---- stream_sender stubs (defined in esp_stubs.c) ---- */
|
||||
int stream_sender_send(const uint8_t *data, size_t len);
|
||||
int stream_sender_init(void);
|
||||
int stream_sender_init_with(const char *ip, uint16_t port);
|
||||
void stream_sender_deinit(void);
|
||||
|
||||
/*
|
||||
* wasm_runtime stubs: defined in esp_stubs.c.
|
||||
* The actual prototype comes from ../main/wasm_runtime.h (via csi_collector.c).
|
||||
* We just need the definition in esp_stubs.c to link.
|
||||
*/
|
||||
|
||||
#endif /* ESP_STUBS_H */
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef ESP_TIMER_H_STUB
|
||||
#define ESP_TIMER_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef ESP_WIFI_H_STUB
|
||||
#define ESP_WIFI_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef ESP_WIFI_TYPES_H_STUB
|
||||
#define ESP_WIFI_TYPES_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef FREERTOS_H_STUB
|
||||
#define FREERTOS_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef FREERTOS_TASK_H_STUB
|
||||
#define FREERTOS_TASK_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef NVS_H_STUB
|
||||
#define NVS_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: redirect to unified stubs header. */
|
||||
#ifndef NVS_FLASH_H_STUB
|
||||
#define NVS_FLASH_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Stub: sdkconfig.h — all CONFIG_ macros provided by esp_stubs.h. */
|
||||
#ifndef SDKCONFIG_H_STUB
|
||||
#define SDKCONFIG_H_STUB
|
||||
#include "esp_stubs.h"
|
||||
#endif
|
||||
Reference in New Issue
Block a user