ELF Apps
ELF Apps
Third-party apps are compiled outside the OS into a .app.elf, packed into a .tar with an overlay sidecar and an icon, and installed at runtime through the app loader. No firmware reflash is involved. This page covers the app from the OS side: how the loader runs it, where installed apps live, and what an app can rely on. The binary contract itself, the build tooling, and the full symbol surface are owned by the SDK documentation and are not duplicated here.
For building and shipping an app, start with the SDK docs:
- App ABI - the binary contract
- Overlay format - the
.elfosidecar - Building apps - the toolchain and
maketargets - Symbols - the host export surface
What an ELF app is
An ELF app is a standalone 32-bit ET_DYN program linked against the PocketMage SDK with PM_TARGET_APP. It links -nostdlib, so it ships no runtime of its own; everything it references, from malloc to the pm_* API, resolves from the host at load time.
The runner (src/elf_runner.cpp) loads an installed app in two stages. It reads the .app.elf from the SD card and relocates the base image with esp_elf, then loads the matching .elfo overlay sidecar, which pages the app’s code into executable RAM on demand and patches ISA-specific relocations. The entry (app_main) then runs in its own 16 KB task on core 1. While the app runs, the OS loop and the E-Ink task stand down and the app owns the UI through the host singletons.
Exiting is a return from app_main. No reboot is needed: the runner unloads the overlay, deinitializes the base image, and reopens HOME.
Packaging and installing
- Build the app into
<name>.app.elfand its<name>.elfooverlay sidecar. - Pack them with a 40x40
<name>_ICON.binand an optionalapp.propertiesmanifest into a plain.tar(make packdoes this). - Copy the
.taronto the SD card, typically over USB. - Open the app loader on the device and use the swap action to install it into one of the four slots.
Installed apps live in /apps/slot1 through /apps/slot4 on the SD card and are tracked in NVS under ELFINFO1 through ELFINFO4. Launch an installed app from the home screen by typing A, B, C, or D, or from the loader.
The manifest (app.properties)
The loader reads an optional app.properties from the app’s slot directory (up to 1024 bytes). Recognized fields are name, version, author, and scope. The first three become the app’s display metadata and are passed to app_main as argv. scope (default all) restricts which pm_* symbols the app may resolve: anything outside its scope fails to resolve, so a mis-scoped app is rejected at load rather than reaching an API it did not declare. The runtime baseline (libc, libstdc++, ESP-IDF) stays available at any scope.
What an ELF app should assume
- It runs without the native PocketMageOS app set. Do not call functions from
src/OS_APPS/. - Keep the app self-contained and link against the SDK only.
- Use the PocketMage library for hardware access, exactly like native apps.
- The host exports a curated symbol set (generated into
src/ELF_SYMS/esp_all_symbol.cpp), includingpocketmage_sdk_versionfor version checks. A symbol outside that set must be added to the SDK surface before an app can resolve it.