Capability firewall¶
The capability firewall in src/hal/capability_firewall.cpp controls which host functions and peripherals a pod may use.
At admission, the firewall converts the pod manifest into a grant, claims requested pins, channels, and buses, and installs ESP-IDF bus drivers. If a pin or bus is reserved or owned by another pod, admission fails with CapabilityAdmissionFailed. When you remove the pod, the firewall removes its bus drivers and releases its claims.
On every call, guarded host functions check the calling pod's grant. An ungranted call returns K32_ERR_PERM, which is -1, and logs [FIREWALL] denied <pod>: ....
Resource grants¶
The firewall reads resources.requests, or resources.limits if requests is absent. Every esp32.io/ key also accepts the esp.io/ prefix.
| Resource | securityContext.capabilities.add |
Grants |
|---|---|---|
hardware.kube32.io/ipc: "1" |
CHANNEL_IPC, IPC |
k32_event_emit, kube32_channel_open |
| None | SERVICE_CALL |
k32_http_call |
hardware.kube32.io/tft-display: "1" |
DISPLAY, TFT_DISPLAY |
k32_display_text, k32_display_rect, k32_display_bar |
hardware.kube32.io/keyboard: "1" |
KEYBOARD |
k32_key_read |
hardware.kube32.io/speaker: "1" |
SPEAKER, AUDIO |
k32_tone |
hardware.kube32.io/sd: "1" plus volume claim |
SD, SD_CARD |
k32_fs_* in the pod directory, see storage |
esp32.io/gpio-<N> |
None | Pin N read and write, value ignored |
esp32.io/gpio: "<count>" |
None | Free pins, lowest numbers first |
esp32.io/adc1-channel-<0..9> or esp32.io/adc: "<count>" |
None | ADC1 channels |
esp32.io/i2c-bus-<0\|1> or esp32.io/i2c: "<count>" |
None | I2C buses, esp32_i2c_read and esp32_i2c_write |
esp32.io/uart-<1\|2> or esp32.io/uart: "<count>" |
None | UART ports, esp32_uart_read and esp32_uart_write |
esp32.io/rmt-tx: "1", esp32.io/rmt-rx: "1" |
None | One RMT (infrared) channel per direction, esp32_rmt_send and esp32_rmt_receive |
A volume declared with persistentVolumeClaim grants k32_fs_* on the node storage root without hardware.kube32.io/sd. Adding hardware.kube32.io/sd: "1", SD, or a kube32.io/sd volume requires a mounted microSD card. Unrecognized capability names in securityContext.capabilities.add are ignored.
Buses and pin annotations¶
Claiming an I2C bus or UART port claims its two GPIO pins and installs the ESP-IDF i2c_master or uart_driver_install driver while the pod runs. Calling esp32_i2c_write with length 0 probes an address, returning 0 on ACK or -19 when no device answers.
Set pins and speeds in metadata.annotations, or omit the annotation to use the board profile defaults:
kube32.io/i2c-bus-<0|1>: "sda=<pin>,scl=<pin>[,hz=<1000..1000000>]"with a default of100000Hzkube32.io/uart-<1|2>: "tx=<pin>,rx=<pin>[,baud=<300..5000000>]"with a default of115200baud
Buses without board defaults require an annotation. See examples/i2cscan.yaml and apps/i2cscan.
RMT channels take their pin the same way, from kube32.io/rmt-tx: "pin=<n>[,carrier=<Hz>][,duty=<percent>]" and kube32.io/rmt-rx: "pin=<n>[,active=low|high][,idle_us=<n>]" or the board default (GPIO 44, the IR LED, for TX on the cardputer profile; no other defaults). The firewall admits at most four channels of each direction, and the driver is created while the pod runs. See peripherals, examples/irremote.yaml, and apps/irremote.
Board profiles and reserved pins¶
The ESP32-S3 provides GPIO 0 to 21 and 26 to 48. KUBE32_RESERVED_GPIO_MASK in include/hal/capability_firewall.hpp reserves pins 0, 19, 20, 26 to 32, 43, and 44 on every board for boot strapping, native USB, SPI flash, quad PSRAM, and UART0.
The board profile, set at boot from NVS key board via K32_CMD:BOARD:cardputer|generic, reserves on-board peripheral pins and sets node capacity:
| Profile | GPIO | ADC1 | I2C | UART | RMT TX / RX | Default pins |
|---|---|---|---|---|---|---|
generic |
33 | 10 | 2 | 2 | 4 / 4 | I2C0 on GPIO 8/9, UART1 on GPIO 17/18 |
cardputer |
11 | 3 | 1 | 1 | 4 / 4 | Grove port GPIO 2/1 shared by I2C0 and UART1; RMT TX on GPIO 44 (IR LED) |
The cardputer profile reserves pins 33 to 38 for the LCD, 41 and 42 for I2S, 3 to 9, 11, 13, and 15 for the key matrix, and 12, 14, 39, and 40 for the microSD bus. It offers GPIO 44, a UART0 pin the board wires only to its IR LED, to RMT TX channels. An ADC1 channel is claimable only when its pin, GPIO channel + 1, is claimable.
Limitations¶
KUBE32_RESERVED_GPIO_MASKdoes not block strapping pins 3, 45, and 46 or octal PSRAM pins 33 to 37.- Claiming an ADC1 channel does not claim its GPIO pin.