Skip to content
LinuxDeep Dive Published Updated 7 min readViews unavailable

Linux NVMEM Cells and Layouts: Read Calibration Data Without Guessing

Trace Linux NVMEM providers, named cells, layouts, and consumer APIs while preserving offsets, units, permissions, and irreversible-write safety.

Embedded Linux systems often store board identity, calibration constants, MAC addresses, hardware revisions, and manufacturing data in EEPROM, one-time-programmable fuses, or another non-volatile memory. The kernel NVMEM framework gives providers a common way to expose such storage and gives consumers a way to request named fields without duplicating every bus-specific read path. The framework does not define the vendor’s binary format, validate that a calibration value is physically correct, or make irreversible storage writes safe.

The key distinction is between a provider and a consumer. The provider knows how to read or write a physical storage device. A cell describes a named byte range or transformed field within it. A consumer asks for that field by its binding-defined name. Diagnosing a bad board value therefore requires identifying all three: storage provider, cell/layout mapping, and consuming driver.

Trace the source before interpreting bytes

Begin with the running kernel and the actual NVMEM device:

find /sys/bus/nvmem/devices -maxdepth 2 -type f -print 2>/dev/null
find /sys/bus/nvmem/devices -maxdepth 2 -name nvmem -print 2>/dev/null
journalctl -k -b --no-pager | grep -i -E 'nvmem|eeprom|efuse|otp'

The sysfs paths are conditional on the provider and kernel configuration. A provider can exist without exposing an unrestricted raw userspace file, and some devices are intentionally read-only. Do not infer missing hardware from a missing sysfs entry alone; check the underlying I2C/SPI/firmware device and driver binding.

Record the provider name, parent device, bus address, size, driver, and any firmware description that defines cells. Device-tree bindings can place cell definitions in a consumer node or describe a provider’s fixed cells. Some storage uses a layout driver to parse records whose offsets are not fixed. A cell’s name is an ABI contract between firmware description and consumer driver; it is not necessarily the file name or human description shown in a board schematic.

Before interpreting a raw dump, obtain the exact format specification for the board revision. Determine byte order, field width, signedness, scaling, checksum or CRC, blank-value encoding, and whether a field is binary or printable. Calibration fields can use a fixed-point representation, and a MAC address or serial number may have a vendor-specific envelope. A hex dump is evidence of bytes, not evidence of a valid value.

Provider, cell, and layout responsibilities

A provider registers the storage operations and geometry with the NVMEM core. It can expose read-only operations, read/write operations, or additional constraints determined by the device and kernel configuration. A provider’s success only establishes that it can service a byte-range request; it does not establish that callers used the correct offset or length.

Static cells describe a name, offset, and length. Consumer drivers can acquire a named cell through APIs such as nvmem_cell_get() or the device-managed variant, then read it into a buffer with the matching NVMEM API. The consumer must handle errors, validate the returned length, parse the field, and release non-managed references. A device-managed reference follows the device resource lifecycle, but the returned data buffer still has its own ownership rules.

Layouts address storage whose logical fields are not simply fixed ranges. A layout can parse the backing contents and register cells dynamically, such as when a table contains tagged records. Layouts can also post-process cell data. That flexibility adds another layer to troubleshooting: the raw bytes may be valid while the layout parser rejects an unsupported version, malformed record, or missing terminator. Compare provider errors, layout errors, and consumer parsing separately.

The framework also offers direct device-level read and write APIs. These are appropriate only when a consumer truly needs arbitrary offsets or a structured region rather than one declared cell. Broad raw access increases the chance that a bug overwrites unrelated data. Prefer a named cell with a narrow, reviewed definition when the hardware format supports it.

Read-only inspection and decoding

Where the raw nvmem sysfs file is present and readable, capture a bounded dump without modifying storage:

stat -c '%n %s bytes %a' /sys/bus/nvmem/devices/DEVICE/nvmem
od -Ax -tx1 -N 256 /sys/bus/nvmem/devices/DEVICE/nvmem

Replace DEVICE with the discovered provider name and limit the read to the region needed for diagnosis. The size and mode are observations of the current ABI, not proof that writes are supported. Avoid publishing dumps from real hardware: NVMEM may contain serial numbers, network addresses, cryptographic material, or customer provisioning data.

To decode a cell, use the authoritative board or binding definition. Confirm its offset and length against the provider’s exposed size. If an offset is calculated from a table, verify integer overflow and bounds in the parser. Check whether the layout adjusts the data before the consumer sees it. Compare a known-good unit of the same hardware revision, but do not copy calibration data from another device unless the vendor explicitly defines it as shared.

Use read-only consumers, driver debug output, or a purpose-built decoder to compare raw and interpreted values. If a consumer reports a value in microvolts, microamps, or another scaled unit, confirm the driver’s conversion and the NVMEM cell’s raw encoding. A plausible value is not proof that the correct cell was read.

Writes and one-time-programmable storage

Treat NVMEM writes as destructive operations. EEPROMs may be rewritable but have endurance limits, page boundaries, write-cycle delays, or power-failure behavior. Fuses and OTP regions may only transition bits in one direction or may not be rewritable at all. A successful system call does not guarantee that the value is physically durable unless the provider and device contract say so.

Never use dd, echo, or an ad hoc script to test an NVMEM write on a production board. A write to the wrong offset can damage identity, calibration, boot configuration, or manufacturing state. For an authorized update, use the vendor’s provisioning tool and documented format, perform range and checksum validation before writing, retain a verified original dump where policy permits, and validate the written value through an independent read path. Power-failure behavior should be tested on sacrificial hardware with the exact storage part.

If userspace cannot write a raw node, do not try to bypass the mode or provider restrictions. The storage may be intentionally read-only, protected by kernel policy, or inaccessible because the relevant write method is not implemented. Resolve the hardware owner’s access model before changing driver configuration.

Diagnose consumer probe failures

When a consumer cannot retrieve a cell, check the exact cell name expected by the driver, the consumer’s firmware-node reference, provider registration order, and deferred-probe status. A typo in a device-tree property can look like a missing NVMEM device. A provider that has not registered yet may cause the consumer to defer rather than fail permanently. Kernel logs and the driver model’s probe status can distinguish these cases.

Once the provider and cell resolve, investigate data errors at the next layer: short reads, byte order, endianness, cell length, checksum, conversion, and consumer-specific range validation. Avoid changing the provider offset to accommodate one consumer’s parsing bug; first verify the board format and all consumers of that cell. Shared NVMEM cells can influence several drivers, including network, clock, display, and sensor calibration paths.

Acceptance record

For each NVMEM issue or change, keep a record of:

  • board model and revision, provider driver, storage part, bus, and kernel release;
  • provider size and read/write capabilities as documented for that exact implementation;
  • cell name, source binding or layout, offset/length, and raw format definition;
  • original and interpreted value, validation/checksum result, and consumer driver;
  • whether the access was read-only or a formally authorized write;
  • recovery procedure and device-specific verification after a write.

The framework is valuable because it separates storage transport from logical fields. Use that separation deliberately: confirm the provider’s bytes, the cell’s mapping, and the consumer’s interpretation independently. This prevents a valid EEPROM read from being mistaken for valid calibration and prevents a parsing defect from turning into a dangerous storage rewrite.

Related:

Sources:

Comments