AxlMemPhys — physical-memory access

Held _map/_unmap mappings plus one-shot _read{8,16,32,64} / _write{8,16,32,64} helpers and a byte-pattern _search. UEFI is identity-mapped so map is effectively a no-op; the abstraction is preserved for portability to backends where physical access requires explicit mapping (Linux mmap("/dev/mem"), AXL kernel POC explicit page-table mapping).

API Reference

Physical-memory access — map / unmap and one-shot read / write.

UEFI runs with the physical memory map identity-mapped, so the map step is effectively a no-op there: the returned VA equals the physical address. The map / unmap shape exists for portability — a future Linux backend would mmap("/dev/mem") on the way in and munmap on the way out, and consumer code that holds a mapping over multiple accesses keeps working.

For the common case where a tool reads (or writes) a single address one time, the one-shot helpers do the map / access / unmap trio in one call. They keep the typical *(volatile uint32_t *)0xFEE00000 style readable without forcing every call site to manage a mapping.

// Held mapping over multiple accesses.
void *va;
if (axl_mem_phys_map(0xFED00000, 4096, &va) == 0) {
    for (size_t i = 0; i < 4096; i += 4) {
        uint32_t w = *(volatile uint32_t *)((uint8_t *)va + i);
        // ...
    }
    axl_mem_phys_unmap(va, 4096);
}

// One-shot.
uint32_t signature;
axl_mem_phys_read32(0xE0000, &signature);

Functions

int axl_mem_phys_map(uintptr_t phys, size_t len, void **out_va)

Map len bytes of physical memory starting at phys.

Returns a virtual address through out_va. On UEFI this is the same as phys (identity-mapped); on a future Linux backend it is a mmap return value. Either way the caller dereferences the VA directly with volatile uint{N}_t * casts to read or write, and pairs every successful map with an axl_mem_phys_unmap using the same len.

Parameters:
  • phys – physical address (alignment is consumer’s responsibility)

  • len – number of bytes to map

  • out_va – [out] receives the mapped VA

Returns:

0 on success, -1 if the mapping cannot be established.

void axl_mem_phys_unmap(void *va, size_t len)

Release a mapping established by axl_mem_phys_map.

On UEFI this is a no-op; on a future Linux backend it is munmap. NULL va is tolerated (no-op).

Parameters:
  • va – VA returned by axl_mem_phys_map

  • len – same length passed to map

int axl_mem_phys_read8(uintptr_t phys, uint8_t *out)

Read a byte from physical memory.

Maps the smallest aligned region covering phys, dereferences, and unmaps. On UEFI all three steps are direct; on backends that actually need to map, this is one mmap + read + munmap per call, so the held-mapping API above is the better choice for hot loops.

Returns:

0 on success, -1 if the mapping cannot be established.

int axl_mem_phys_read16(uintptr_t phys, uint16_t *out)

16-bit variant. phys must be 16-bit aligned on AArch64 (a misaligned access raises a synchronous Data Abort and terminates the image); x86 tolerates misaligned reads at a performance penalty.

int axl_mem_phys_read32(uintptr_t phys, uint32_t *out)

32-bit variant. Same alignment caveat as axl_mem_phys_read16 — required on AArch64, advisory on x86.

int axl_mem_phys_read64(uintptr_t phys, uint64_t *out)

64-bit variant. Same alignment caveat as axl_mem_phys_read16 — required on AArch64, advisory on x86.

int axl_mem_phys_write8(uintptr_t phys, uint8_t value)

One-shot byte write.

int axl_mem_phys_write16(uintptr_t phys, uint16_t value)

One-shot 16-bit write.

int axl_mem_phys_write32(uintptr_t phys, uint32_t value)

One-shot 32-bit write.

int axl_mem_phys_write64(uintptr_t phys, uint64_t value)

One-shot 64-bit write.

Find the first occurrence of needle in a mapped region.

Operates on a VA (typically returned by axl_mem_phys_map). Useful for scanning ROMs, firmware tables, or signature blocks. Linear byte-by-byte scan; use sparingly on multi-megabyte regions.

Parameters:
  • va – mapped region base

  • len – region length in bytes

  • needle – pattern to find

  • needle_len – pattern length in bytes

  • out_match – [out] pointer inside va

Returns:

0 on hit (and *out_match is set to a pointer inside va), -1 if needle is not present.