A build system for compiling your own C applications to run as BareMetal apps: a musl libc port (syscalls dispatched into libBareMetal calls instead of trapped), a BMFS file I/O layer, a lwIP-based TCP/IP networking, Mbed TLS for TLS/SSL, curl/libcurl (HTTP/HTTPS only) on top of all of it, and SQLite on top of BMFS via its own small VFS. See OPENISSUES.md for what's supported and what isn't.
gcc, ld, make, curl, tar, unzip (a standard Linux toolchain works).
Run once, from this directory:
./setup.sh
This downloads musl 1.2.6 and applies the BareMetal port patch, then downloads lwIP 2.2.0, Mbed TLS 3.6.6, curl 8.21.0, and the SQLite 3.46.1 amalgamation (all four used as-is, unmodified), creating build/musl-1.2.6/, build/lwip-2.2.0/, build/mbedtls-3.6.6/, build/curl-8.21.0/, and build/sqlite-3.46.1/. All are pinned versions -- the patch and the port/lwip_port//port/mbedtls_port//port/curl_port//port/sqlite_port/ glue are written against these exact releases. (setup.sh just runs scripts/get-musl.sh, scripts/get-lwip.sh, scripts/get-mbedtls.sh, scripts/get-curl.sh, and scripts/get-sqlite.sh in turn, if you want to re-run one on its own.)
./build-app.sh myapp.c # builds your own app -> myapp.app
Downloaded sources and intermediate .o files live under build/; the final .app is placed here in the top-level directory. It's a flat binary linked at 0xFFFF800000000000 (see port/c.ld), ready to load as a BareMetal app (e.g. copy it onto a BMFS disk image and load it from the BareMetal monitor or run it as a unikernel).
./clean.sh removes library code and build artifacts (.o/.a/.app) from this directory and build/ without touching the fetched musl-1.2.6//lwip-2.2.0//mbedtls-3.6.6//curl-8.21.0//sqlite-3.46.1/ zip/tarball.
setup.sh-- fetches musl, lwIP, Mbed TLS, and curl (see Setup above).build-app.sh-- builds an app (see Building an app above).clean.sh-- removes build artifacts.hello.c-- minimal demo app (muslprintf, argc/argv/envp).clock.c-- prints the current wall-clock time (viatime()and a directb_system(WALLCLOCK, ...)call) and time elapsed since boot (clock_gettime(CLOCK_MONOTONIC, ...)).crawler.c/https_crawler.c-- a small HTTP(S) web crawler, speaking raw HTTP by hand overport/net_shim.c's sockets and TLS by hand overport/tls_shim.c's mbedTLS wrapper.curltest.c-- a minimal demo of libcurl's easy interface (an HTTP/ HTTPS GET) -- the same sockets and the same vendored mbedTLS as above, but reached through curl's own APIs instead.sqltest.c-- a minimal demo of SQLite: creates a table on a real BMFS-backed database file, inserts rows across two transactions, and queries them back -- exercisingport/sqlite_port/sqlite_vfs.c's read/write/journal handling end to end.port/-- the port glue every app links against:crt0.c,c.ld-- startup and linker script for the flat-binary, ring-0, fixed-address BareMetal environment (no ELF loader, no syscall trap).posix_shim.c/.h-- the syscall dispatcher musl's patchedsyscall_arch.hcalls into, plus the heap (brk/mmap) backing it.bmfs.c/.h-- POSIX file I/O (open/read/write/stat/...) on top of BMFS, the on-disk format BareMetal uses.net_glue.c/.h,net_shim.c/.h,lwip_port/-- a blocking BSD-socket-shaped layer over lwIP's raw callback API, plus the Ethernet netif driver and port config.dns_shim.c--gethostbyname(), backed by lwIP's resolver.tls_shim.c/.h,mbedtls_port/-- a small blocking HTTPS-shaped TLS client wrapper over Mbed TLS, plus its port config (baremetal_mbedtls_config.h) and RNG hook (entropy_hardware_poll.c, viardrand).curl_port/curl_config.h-- libcurl's build config for this port (HTTP/HTTPS only, mbedTLS backend,gethostbyname()-based resolver, no threads -- see its own file header andOPENISSUES.md's "libcurl" section for the reasoning behind each).sqlite_port/sqlite_baremetal_config.h,sqlite_port/sqlite_vfs.c-- SQLite's build config for this port (SQLITE_OS_OTHER=1, single-threaded, no WAL/mmap/load-extension -- see its own file header) and the smallsqlite3_vfsimplementation it requires in place of SQLite's ownos_unix.c, built directly overposix_shim.c/bmfs.cthe same waytls_shim.c/net_shim.care (seesqlite_vfs.c's own header andOPENISSUES.md's "SQLite" section for the reasoning behind each choice).libBareMetal.c/.h/.asm-- the low-level calls into the BareMetal kernel (b_output,b_net_tx, ...) everything above is built on.
scripts/-- the fetch scriptssetup.shcalls:get-musl.sh-- downloads musl 1.2.6 and appliesport/musl_port/musl-1.2.6-baremetal.patch, the 3-file patch (syscall transport, TLS bootstrap, cancellation-point syscalls), then installsport/musl_port/musl-1.2.6-config.makas musl'sconfig.mak(equivalent to running musl's./configurewith the flags this port needs, without you having to runconfigureyourself).get-lwip.sh-- downloads lwIP 2.2.0. lwIP is vendored unmodified; all lwIP-side port work lives inport/lwip_port/andport/net_glue.c/net_shim.cinstead of patches to lwIP itself.get-mbedtls.sh-- downloads Mbed-TLS 3.6.6. Mbed-TLS is vendored unmodified; all Mbed-TLS-side port work lives inport/tls_shim.cinstead of patches to Mbed-TLS itself.get-curl.sh-- downloads curl 8.21.0. curl is vendored unmodified too; all curl-side port work lives inport/curl_port/curl_config.hinstead of patches to curl itself.get-sqlite.sh-- downloads the SQLite 3.46.1 amalgamation (sqlite3.c/sqlite3.h). Vendored unmodified as well; all SQLite-side port work lives inport/sqlite_port/instead of patches tosqlite3.citself.
This is not a general-purpose POSIX environment: no fork/exec, no threads (yet), no signals (yet?), flat BMFS namespace (no subdirectories), TCP/UDP only (no raw sockets exposed), 30s timeout on blocking socket calls. See OPENISSUES.md for the full list and the reasoning behind each cut.