AxlSys – System Utilities

System operations, environment variables, time, NVRAM storage, driver lifecycle, and hex dump.

Headers:

  • <axl/axl-sys.h> – System operations (reset, GUID, device map refresh)

  • <axl/axl-env.h> – Environment variables and working directory

  • <axl/axl-time.h> – Wall-clock time and monotonic timestamps

  • <axl/axl-nvstore.h> – UEFI NVRAM variable access

  • <axl/axl-driver.h> – Driver binding and lifecycle

  • <axl/axl-hexdump.h> – Hex/ASCII dump formatting

Overview

GUIDs

UEFI identifies protocols, variables, and services by 128-bit GUIDs. AXL provides AxlGuid (standard C types, no UEFI headers needed) and the AXL_GUID macro for initialization:

AxlGuid my_guid = AXL_GUID(0x12345678, 0xabcd, 0xef01,
    0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01);

if (axl_guid_cmp(&a, &b) == 0) {
    // GUIDs are equal
}

Firmware Globals

After AXL_APP or axl_driver_init, these globals are available (typed when <uefi/axl-uefi.h> is included):

NVRAM Variables

Read and write persistent UEFI variables (survive reboot):

// Read
uint8_t secure_boot;
size_t sz = sizeof(secure_boot);
if (axl_nvstore_get("global", "SecureBoot", &secure_boot, &sz) == 0) {
    axl_printf("SecureBoot: %s\n", secure_boot ? "on" : "off");
}

// Write
axl_nvstore_set("app", "last-run", timestamp, timestamp_len,
                AXL_NVSTORE_BOOT | AXL_NVSTORE_NV);

Driver Lifecycle

Build DXE drivers with axl-cc --type driver. The driver entry point is DriverEntry (not main). Call axl_driver_init to set up the AXL runtime:

EFI_STATUS EFIAPI DriverEntry(EFI_HANDLE ImageHandle,
                               EFI_SYSTEM_TABLE *SystemTable) {
    axl_driver_init(ImageHandle, SystemTable);
    axl_printf("Driver loaded\n");
    // ...
}

See sdk/examples/driver.c for a complete example.

AxlSys

Defines

AXL_GUID(d1, d2, d3, d4_0, d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7)

Initialize an AxlGuid from literal values.

Usage: AxlGuid

g = AXL_GUID(0x12345678, 0xABCD, 0xEF01,

0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01);

AXL_RESET_COLD

cold reset (full power cycle)

AXL_RESET_WARM

warm reset (CPU reset, memory preserved)

AXL_RESET_SHUTDOWN

power off

Functions

static inline bool axl_guid_cmp(const AxlGuid *a, const AxlGuid *b)

Compare two GUIDs for equality.

Returns:

true if equal.

bool axl_device_path_has_vendor(void *device_path, const AxlGuid *guid)

Check if a device path contains a vendor node with the given GUID.

Walks the device path node chain looking for a hardware vendor node (type 0x01, subtype 0x04) whose GUID matches guid.

Parameters:
  • device_path – device path (from “device-path” service)

  • guid – vendor GUID to match

Returns:

true if a matching vendor node is found.

void axl_reset(int type)

Reset or shut down the system.

Does not return on success.

Parameters:
  • type – AXL_RESET_COLD, AXL_RESET_WARM, or AXL_RESET_SHUTDOWN

int axl_map_refresh(void)

Rescan device-to-filesystem mappings.

Equivalent to the Shell “map -r” command. Call after hot-plugging a USB drive or after a driver installs a new filesystem.

Returns:

0 on success, -1 on error.

int axl_sys_get_firmware_info(AxlFirmwareInfo *info)

Get firmware information (vendor, revision, spec version).

Parameters:
  • info – [out] receives firmware info

Returns:

0 on success, -1 on error.

int axl_sys_get_memory_size(uint64_t *total_bytes)

Get total usable memory size in bytes.

Queries the firmware memory map and sums all usable regions.

Parameters:
  • total_bytes – [out] receives total usable RAM

Returns:

0 on success, -1 on error.

int axl_handle_get_service(void *handle, const char *name, void **interface)

Get a service interface from a specific handle.

Parameters:
  • handle – handle from axl_service_enumerate

  • name – service name (e.g., “device-path”, “simple-fs”)

  • interface – [out] service interface pointer

Returns:

0 on success, -1 if not found.

void axl_stall(uint64_t microseconds)

Busy-wait for a duration.

Parameters:
  • microseconds – duration in microseconds

int axl_service_find(const char *name, void **interface)

Find a system service by name.

Looks up a named service in the platform service registry. Well-known names: “smbios”, “shell”, “simple-network”, “simple-fs”.

Parameters:
  • name – service name

  • interface – [out] service interface pointer

Returns:

0 on success, -1 if not found.

int axl_service_enumerate(const char *name, void ***handles, size_t *count)

Enumerate all handles providing a named service.

Caller frees the returned handles array with axl_free().

Parameters:
  • name – service name

  • handles – [out] array of handles

  • count – [out] number of handles

Returns:

0 on success (count may be 0), -1 on error.

int axl_service_register(const char *name, void *interface, void **handle)

Register a service on a handle.

Creates a new handle if *handle is NULL.

Parameters:
  • name – service name

  • interface – service interface to install

  • handle – [in/out] handle (NULL to create new)

Returns:

0 on success, -1 on error.

int axl_service_unregister(void *handle, const char *name, void *interface)

Unregister a service from a handle.

Parameters:
  • handle – handle from axl_service_register

  • name – service name

  • interface – interface to remove

Returns:

0 on success, -1 on error.

int axl_service_register_multiple(void **handle, ...)

Register multiple services on a handle atomically.

Installs one or more services on the same handle in one operation. If any fails, none are installed. Creates a new handle if *handle is NULL. Pass name/interface pairs followed by NULL:

void *h = NULL;
axl_service_register_multiple(&h,
    "simple-fs", &my_fs,
    "device-path", &my_dp,
    NULL);
Parameters:
  • handle – [in/out] handle (NULL to create new)

Param :

name, interface pairs, terminated by NULL

Returns:

0 on success, -1 on error.

struct AxlGuid
#include <axl-sys.h>

UEFI-compatible GUID in standard C types.

Binary-compatible with EFI_GUID. Use in public API so consumer apps don’t need <uefi/axl-uefi.h> for GUID operations.

Public Members

uint32_t data1
uint16_t data2
uint16_t data3
uint8_t data4[8]
struct AxlFirmwareInfo
#include <axl-sys.h>

Firmware information.

Public Members

char vendor[64]

firmware vendor name (UTF-8)

uint32_t firmware_revision

vendor firmware revision

uint16_t spec_major

UEFI spec major version.

uint16_t spec_minor

UEFI spec minor version.

AxlEnv

Functions

char *axl_getenv(const char *name)

Get a shell environment variable.

Returns a UTF-8 copy of the variable’s value. Caller frees with axl_free().

Parameters:
  • name – variable name (UTF-8)

Returns:

value string, or NULL if not found.

int axl_setenv(const char *name, const char *value, bool overwrite)

Set a shell environment variable.

Parameters:
  • name – variable name (UTF-8)

  • value – value (UTF-8)

  • overwrite – if false, don’t replace existing value

Returns:

0 on success, -1 on error.

int axl_unsetenv(const char *name)

Remove a shell environment variable.

Parameters:
  • name – variable name (UTF-8)

Returns:

0 on success, -1 on error.

AxlTime

Functions

size_t axl_time_format(char *buf, size_t buf_size)

Format current time as ISO 8601 with microseconds.

Example: “2026-03-27T14:05:32.123456”

Parameters:
  • buf – destination buffer (at least 28 bytes)

  • buf_size – size of buffer

Returns:

characters written (excluding NUL), 0 on error.

void axl_sleep(uint64_t seconds)

Sleep for the specified number of seconds. CPU-idle, not spinning.

void axl_msleep(uint64_t milliseconds)

Sleep for the specified number of milliseconds. CPU-idle.

void axl_usleep(uint64_t microseconds)

Sleep for the specified number of microseconds. CPU-idle.

void axl_spin_sleep(uint64_t seconds)

Busy-wait for the specified number of seconds.

void axl_spin_msleep(uint64_t milliseconds)

Busy-wait for the specified number of milliseconds.

void axl_spin_usleep(uint64_t microseconds)

Busy-wait for the specified number of microseconds.

uint64_t axl_time_get_ms(void)

Get a monotonic millisecond counter.

Based on firmware time — not wall-clock accurate but monotonically increasing within a boot session. Useful for measuring elapsed time.

Returns:

milliseconds since an arbitrary epoch (typically boot).

AxlNvStore

Defines

AXL_NV_VOLATILE

lost on reboot

AXL_NV_PERSISTENT

survives reboot (non-volatile)

AXL_NV_BOOT

accessible during boot services

AXL_NV_RUNTIME

accessible at runtime

Functions

int axl_nvstore_get(const char *ns, const char *key, void *buf, size_t *size)

Read a value from non-volatile storage.

Parameters:
  • ns – namespace (e.g., “global”, “app”)

  • key – variable name (UTF-8)

  • buf – output buffer

  • size – [in/out] buffer size / bytes read

Returns:

0 on success, -1 on error (variable not found, buffer too small, etc.). On buffer-too-small, size is updated to the required size.

int axl_nvstore_set(const char *ns, const char *key, const void *buf, size_t size, uint32_t flags)

Write a value to non-volatile storage.

Parameters:
  • ns – namespace (e.g., “global”, “app”)

  • key – variable name (UTF-8)

  • buf – data to write

  • size – data size in bytes

  • flags – AXL_NV_* flags

Returns:

0 on success, -1 on error.

AxlDriver

Typedefs

typedef void *AxlDriverHandle

Opaque handle to a loaded driver image.

Functions

int axl_driver_load(const char *path, AxlDriverHandle *handle)

Load a driver image from a file path.

Loads the .efi file into memory but does not start it.

Parameters:
  • path – path to .efi driver (UTF-8)

  • handle – [out] receives driver handle

Returns:

0 on success, -1 on error.

int axl_driver_start(AxlDriverHandle handle)

Start a loaded driver image.

Calls the driver’s entry point. The driver registers its binding protocol(s) but does not yet bind to devices.

Parameters:
  • handle – driver handle from axl_driver_load

Returns:

0 on success, -1 on error.

int axl_driver_connect(AxlDriverHandle handle)

Connect a driver to all matching device handles.

Triggers the driver’s Supported/Start sequence for each compatible device. Call after axl_driver_start.

Parameters:
  • handle – driver handle

Returns:

0 on success, -1 on error.

int axl_driver_disconnect(AxlDriverHandle handle)

Disconnect a driver from all devices.

Triggers the driver’s Stop sequence for each bound device.

Parameters:
  • handle – driver handle

Returns:

0 on success, -1 on error.

int axl_driver_unload(AxlDriverHandle handle)

Unload a driver image from memory.

The driver must be disconnected first.

Parameters:
  • handle – driver handle

Returns:

0 on success, -1 on error.

int axl_driver_set_load_options(AxlDriverHandle handle, const void *data, size_t size)

Set load options on a loaded driver image.

Provides configuration data (e.g., a URL) that the driver reads from EFI_LOADED_IMAGE_PROTOCOL.LoadOptions during startup. The data is copied internally — caller’s buffer can be freed after. Pass NULL data to clear load options. Call between axl_driver_load and axl_driver_start.

Parameters:
  • handle – driver handle from axl_driver_load

  • data – option data (copied; NULL to clear)

  • size – option data size in bytes

Returns:

0 on success, -1 on error.

void axl_driver_init(void *image_handle, void *system_table)

Initialize the AXL runtime for a DXE driver.

Drivers don’t use AXL_APP / int main(). Call this from DriverEntry to set up firmware table pointers (gST/gBS/gRT) and I/O streams so axl_printf, axl_malloc, etc. work.

EFI_STATUS EFIAPI DriverEntry(EFI_HANDLE ImageHandle,
                               EFI_SYSTEM_TABLE *SystemTable) {
    axl_driver_init(ImageHandle, SystemTable);
    axl_printf("Driver loaded\n");
    ...
}
Parameters:
  • image_handle – EFI_HANDLE from DriverEntry

  • system_table – EFI_SYSTEM_TABLE* from DriverEntry

int axl_driver_set_unload(void *unload_fn)

Set the unload callback for the current driver image.

Call from DriverEntry to register a cleanup function that runs when the driver is unloaded. The callback has EFIAPI calling convention — declare it as: EFI_STATUS EFIAPI MyUnload(EFI_HANDLE ImageHandle)

Parameters:
  • unload_fn – EFIAPI unload function pointer

Returns:

0 on success, -1 on error.

char *axl_driver_get_load_options(void)

Get the load options that were passed to the current image.

Returns a UTF-8 copy of the load options string. Caller frees with axl_free(). Useful for drivers that receive configuration (e.g., a URL) via LoadOptions.

Returns:

options string, or NULL if no options or on error.

char *axl_driver_get_image_path(void)

Get the filesystem path the current image was loaded from.

Returns a UTF-8 path like “fs0:\drivers\MyDriver.efi”. Useful for finding companion files next to the driver. Caller frees with axl_free().

Returns:

path string, or NULL if unavailable.

int axl_driver_connect_handle(void *handle)

Connect controllers on a specific handle.

Triggers driver binding for one handle (e.g., after installing a filesystem protocol on a new handle). More targeted than axl_driver_connect which reconnects all handles.

Parameters:
  • handle – handle to connect (from axl_service_register, etc.)

Returns:

0 on success, -1 on error.

int axl_driver_load_dir(const char *dir_path, const char *pattern, size_t *loaded_count)

Load, start, and connect all .efi drivers in a directory.

Scans dir_path for files matching pattern (glob, e.g. “*.efi”). Each matching file is loaded, started, and connected. On return, loaded_count receives the number of drivers successfully started. Pass NULL for pattern to match all .efi files.

Parameters:
  • dir_path – directory to scan (UTF-8)

  • pattern – glob pattern (NULL = “*.efi”)

  • loaded_count – [out] number of drivers loaded (may be NULL)

Returns:

0 on success (even if no drivers found), -1 on error.

AxlHexdump

Defines

AXL_HEX_GROUP_BYTE
AXL_HEX_GROUP_WORD
AXL_HEX_GROUP_DWORD
AXL_HEX_GROUP_QWORD
AXL_HEXDUMP_MAX_SIZE
AxlHexDumpLog(Level, Name, Data, Size, BytesPerLine, GroupSize)

Convenience macro that injects _AxlLogDomain, func, LINE.

Requires AXL_LOG_DOMAIN() in the source file.

Functions

void axl_hexdump(const char *name, const void *data, size_t size, size_t bytes_per_line, size_t group_size)

Print a hex+ASCII dump to stdout via axl_print().

Parameters:
  • name – label printed above the dump (may be NULL)

  • data – buffer to dump

  • size – number of bytes

  • bytes_per_line – columns (0 = default 16, max 64)

  • group_size – grouping width (AXL_HEX_GROUP_*)

void axl_hexdump_to_log(int level, const char *domain, const char *func, int line, const char *name, const void *data, size_t size, size_t bytes_per_line, size_t group_size)

Emit a hex+ASCII dump through axl_log_full().

Parameters:
  • level – log level (AXL_LOG_ERROR..AXL_LOG_TRACE)

  • domain – log domain

  • funcfunc

  • lineLINE

  • name – label printed above the dump (may be NULL)

  • data – buffer to dump

  • size – number of bytes

  • bytes_per_line – columns (0 = default 16, max 64)

  • group_size – grouping width (AXL_HEX_GROUP_*)