seed.c — Self-Growing Firmware
Source: https://github.com/Awis13/seed
You have access to a seed node — a minimal C firmware with an HTTP API
that you can grow by writing and compiling new firmware on the device.
First steps
If the user hasn't given you a node address and token, ask them:
- - Do they already have a seed node running? If so, get the IP and token.
- If not, offer to deploy one. All they need is a Linux machine with gcc:
CODEBLOCK0
The seed binary is ~70KB, zero dependencies beyond libc.
Connecting
The node prints its address and token on startup. If you don't know them:
CODEBLOCK1
All requests except /health need: INLINECODE1
What you can do
1. Discover the hardware
curl -H "Authorization: Bearer $TOKEN" http://$HOST/capabilities
Returns: arch, CPU, RAM, disk, temperature, GPIO, I2C, serial ports,
USB devices, WiFi, Bluetooth, WireGuard — everything the node has.
2. Read the running firmware
curl -H "Authorization: Bearer $TOKEN" http://$HOST/firmware/source
Returns the C source code currently running on the node.
3. Write new firmware
curl -H "Authorization: Bearer $TOKEN" \
-X POST --data-binary @new_firmware.c \
http://$HOST/firmware/source
Upload C source code. The node saves it for compilation.
4. Compile on the device
curl -H "Authorization: Bearer $TOKEN" -X POST http://$HOST/firmware/build
The node runs
gcc -O2 on itself. Check errors with
GET /firmware/build/logs.
5. Apply (hot-swap)
curl -H "Authorization: Bearer $TOKEN" -X POST http://$HOST/firmware/apply
Atomic binary swap. 10-second watchdog — if the new firmware fails
the health check, the old version is restored automatically.
API reference
| Method | Path | Description |
|---|
| GET | /health | Alive check (no auth) |
| GET |
/capabilities | Hardware fingerprint |
| GET | /config.md | Node config (markdown) |
| POST | /config.md | Update config |
| GET | /events | Event log (?since=unix_ts) |
| GET | /firmware/version | Version, build date, uptime |
| GET | /firmware/source | Read source code |
| POST | /firmware/source | Upload new source |
| POST | /firmware/build | Compile (gcc -O2) |
| GET | /firmware/build/logs | Compiler output |
| POST | /firmware/apply | Apply + watchdog rollback |
| GET | /skill | Generate this file with live connection details |
Writing firmware
Constraints:
- - C only, libc only — no external libraries
- INLINECODE4 must compile with no extra flags
- Single-threaded, one request at a time
- Max request body: 64KB
- 3 failed applies -> /firmware/apply locks (POST /firmware/apply/reset to unlock)
Handler pattern:
CODEBLOCK7
Available functions:
- -
json_resp(fd, code, status, json) — send JSON response - INLINECODE6 — send plain text
- INLINECODE7 — send anything
- INLINECODE8 — read file, returns malloc'd buffer
- INLINECODE9 — write file
- INLINECODE10 — run command, capture output
- INLINECODE11 — log event
Request struct: req.method, req.path, req.body (malloc'd, may be NULL),
req.body_len, req.content_length. Path includes query string.
Auth is already checked before your handler. /health is always public.
Capabilities example
CODEBLOCK8
Use this to decide what the node can do and what firmware to write.
Typical workflow
- 1.
GET /health — is it alive? - INLINECODE19 — what hardware does it have?
- INLINECODE20 — read the current code
- Write new firmware that adds the endpoints you need
- INLINECODE21 — upload it
- INLINECODE22 — compile
- INLINECODE23 — check for errors
- INLINECODE24 — deploy (auto-rollback on failure)
- Test the new endpoints
- Repeat — the grown firmware still has
/firmware/*, so you can grow it again
seed.c — 自生长固件
来源: https://github.com/Awis13/seed
你拥有一个种子节点——一个极简的C语言固件,带有HTTP API,你可以通过在设备上编写和编译新固件来使其生长。
第一步
如果用户没有提供节点地址和令牌,请询问他们:
- - 他们是否已经运行了种子节点?如果是,获取IP和令牌。
- 如果没有,主动提出部署一个。他们只需要一台装有gcc的Linux机器:
bash
在目标机器上(树莓派、VPS、任何Linux设备):
curl -fsSL https://raw.githubusercontent.com/Awis13/seed/main/seeds/linux/seed.c -o seed.c
gcc -O2 -o seed seed.c
./seed 8080
令牌将被打印出来——将其提供给代理
种子二进制文件约70KB,除libc外零依赖。
连接
节点在启动时会打印其地址和令牌。如果你不知道它们:
bash
用户将提供地址,或者:
curl http://
:8080/health # 无需认证
curl http://:8080/skill # 完整连接详情 + 令牌
除/health外的所有请求都需要:Authorization: Bearer
你能做什么
1. 发现硬件
bash
curl -H Authorization: Bearer $TOKEN http://$HOST/capabilities
返回:架构、CPU、内存、磁盘、温度、GPIO、I2C、串口、
USB设备、WiFi、蓝牙、WireGuard——节点拥有的所有信息。
2. 读取运行中的固件
bash
curl -H Authorization: Bearer $TOKEN http://$HOST/firmware/source
返回当前在节点上运行的C语言源代码。
3. 编写新固件
bash
curl -H Authorization: Bearer $TOKEN \
-X POST --data-binary @new_firmware.c \
http://$HOST/firmware/source
上传C语言源代码。节点会保存它以供编译。
4. 在设备上编译
bash
curl -H Authorization: Bearer $TOKEN -X POST http://$HOST/firmware/build
节点在自身运行gcc -O2。使用GET /firmware/build/logs检查错误。
5. 应用(热切换)
bash
curl -H Authorization: Bearer $TOKEN -X POST http://$HOST/firmware/apply
原子级二进制切换。10秒看门狗——如果新固件未能通过健康检查,旧版本将自动恢复。
API参考
| 方法 | 路径 | 描述 |
|---|
| GET | /health | 存活检查(无需认证) |
| GET |
/capabilities | 硬件指纹 |
| GET | /config.md | 节点配置(markdown格式) |
| POST | /config.md | 更新配置 |
| GET | /events | 事件日志(?since=unix_ts) |
| GET | /firmware/version | 版本、构建日期、运行时间 |
| GET | /firmware/source | 读取源代码 |
| POST | /firmware/source | 上传新源代码 |
| POST | /firmware/build | 编译(gcc -O2) |
| GET | /firmware/build/logs | 编译器输出 |
| POST | /firmware/apply | 应用 + 看门狗回滚 |
| GET | /skill | 生成此文件并附带实时连接详情 |
编写固件
约束条件:
- - 仅限C语言,仅限libc——无外部库
- gcc -O2 -o seed seed.c 必须无需额外标志即可编译
- 单线程,一次处理一个请求
- 最大请求体:64KB
- 3次应用失败 -> /firmware/apply 锁定(POST /firmware/apply/reset 解锁)
处理程序模式:
c
if (strcmp(req.path, /myendpoint) == 0
&& strcmp(req.method, GET) == 0) {
char resp[4096];
snprintf(resp, sizeof(resp), {\key\:\value\});
json_resp(fd, 200, OK, resp);
goto done;
}
可用函数:
- - jsonresp(fd, code, status, json) — 发送JSON响应
- textresp(fd, code, status, text) — 发送纯文本
- respond(fd, code, status, contenttype, body, len) — 发送任意内容
- fileread(path, &len) — 读取文件,返回malloc分配的缓冲区
- filewrite(path, data, len) — 写入文件
- cmdout(shellcmd, buf, bufsize) — 运行命令,捕获输出
- eventadd(fmt, ...) — 记录事件
请求结构体: req.method、req.path、req.body(malloc分配,可能为NULL)、
req.bodylen、req.contentlength。路径包含查询字符串。
在你的处理程序之前,认证已经完成。/health始终公开。
能力示例
json
{
type: seed, version: 0.1.0, seed: true,
hostname: raspberrypi, arch: armv6l,
cpus: 1, memmb: 512, diskmb: 14000,
tempc: 42.3, boardmodel: Raspberry Pi Zero W Rev 1.1,
has_gcc: true,
net_interfaces: [eth0, wlan0, usb0],
serial_ports: [/dev/ttyAMA0],
i2c_buses: [/dev/i2c-1],
gpio_chips: [/dev/gpiochip0],
haswifi: true, hasbluetooth: true,
endpoints: [/health, /capabilities, /config.md, ...]
}
使用此信息来决定节点能做什么以及要编写什么固件。
典型工作流程
- 1. GET /health — 是否存活?
- GET /capabilities — 它有什么硬件?
- GET /firmware/source — 读取当前代码
- 编写添加所需端点的新固件
- POST /firmware/source — 上传
- POST /firmware/build — 编译
- GET /firmware/build/logs — 检查错误
- POST /firmware/apply — 部署(失败时自动回滚)
- 测试新端点
- 重复——生长后的固件仍然包含/firmware/*,因此你可以再次使其生长