host.binary_loader

Pluggable binary load strategy for embedded hosts.

Loading a binary into a device’s executable runtime — Zephyr’s LLEXT llext load_hex is the first example — is not a file transfer: there is no destination file or filesystem, the binary goes straight into the kernel’s loader. A BinaryLoader is a small stateless value object (mirroring CommandFrame) that formats the device’s load/unload commands and reads their output. The host executes; the loader never touches the session.

A project can register additional loaders via register_binary_loader() from a .otto init module — the same extension hook otto.host.command_frame.register_command_frame() follows.

class otto.host.binary_loader.BinaryLoader

Bases: ABC

How to load/unload a binary into an embedded target’s runtime.

type_name : ClassVar[str]

Lab-data string for this loader (e.g. 'llext-hex'); unique across loaders.

max_unload_rounds : ClassVar[int] = 16

Cap on the unload-to-eviction loop the host drives (see otto.host.embedded_host.EmbeddedHost.unload()). Some loaders (LLEXT) refcount a resident binary, so one unload may decrement without evicting.

abstract load_command(name: str, payload: bytes) str

Return the device command that loads payload under name.

abstract check_loaded(output: str) tuple[bool, str]

Return (ok, reason) from a load command’s output — reason is the failure text when ok is False, "" otherwise.

abstract unload_command(name: str) str

Return the device command that unloads (one round of) name.

abstract is_fully_unloaded(output: str) bool

Return True when an unload round’s output shows name no longer resident.

class otto.host.binary_loader.LlextHexLoader

Bases: BinaryLoader

Zephyr LLEXT shell loader: llext load_hex / llext unload.

load_hex takes the hex-encoded ELF inline as one shell-command argument. LLEXT refcounts a resident extension, so a full eviction may need several unload rounds — is_fully_unloaded() is True only once the shell reports No such extension.

type_name : ClassVar[str] = 'llext-hex'

Lab-data string for this loader (e.g. 'llext-hex'); unique across loaders.

load_command(name: str, payload: bytes) str

Return the device command that loads payload under name.

check_loaded(output: str) tuple[bool, str]

Return (ok, reason) from a load command’s output — reason is the failure text when ok is False, "" otherwise.

unload_command(name: str) str

Return the device command that unloads (one round of) name.

is_fully_unloaded(output: str) bool

Return True when an unload round’s output shows name no longer resident.

otto.host.binary_loader.register_binary_loader(type_name: str, cls: type[BinaryLoader]) None

Make a custom BinaryLoader subclass available to lab data.

Call from an init module listed in .otto/settings.toml — the same pattern otto.host.command_frame.register_command_frame() follows.

otto.host.binary_loader.build_binary_loader(type_name: str) BinaryLoader

Construct the BinaryLoader registered under type_name.