U-Boot NAND Reads: Budget Physical Span When Bad Blocks Are Skipped
A NAND image fits by byte count but a read still reports that it
exceeds its partition limit. The missing quantity may be the physical
span consumed while skipping bad eraseblocks. U-Boot v2025.01’s ordinary
NAND read path distinguishes useful bytes returned to RAM from flash
space traversed to obtain them.
For a Buildroot product using this bootloader, document that mapping
alongside the image format. This analysis covers the legacy
nand command and its raw-NAND helper. It does not cover
UBI’s mapping layer, preservation of factory bad-block markers or a
ROM’s board-specific boot-image rules.
Identify which
read format the command selects
An ordinary NAND read dispatches to
nand_read_skip_bad(). The command also has distinct raw and
OOB branches. These are not interchangeable ways of requesting the same
buffer. Tagged
NAND command.
The raw branch takes a page count and reserves a RAM representation
containing each page’s main data followed by its OOB bytes. Its
raw_access() helper uses MTD_OPS_RAW, advances
the flash offset by the page’s main-data size and advances the buffer by
main data plus OOB. The ordinary branch instead asks the skip-bad helper
for a logical byte count of main data.
A host artifact containing page-plus-OOB records therefore needs an
explicit format contract. Calling it a “raw image” in a filename does
not establish that it matches a command’s .raw layout. The
consumer must agree on page size, OOB inclusion and treatment of bad
blocks; the same total file length is insufficient evidence.

The helper preflights the
flash span
check_skip_len() walks eraseblocks from the starting
offset. A good block contributes useful bytes; a bad block contributes
to physical span but not useful capacity. The helper reports whether
skipping is needed and accumulates the span required for the requested
logical length. It also stops when the request cannot fit within the
device. NAND
utility implementation.
nand_read_skip_bad() requires a page-aligned start. It
then checks the calculated span against the caller’s limit. Exceeding
that limit returns -EFBIG and sets the returned logical
length to zero before data transfer. In this API, the optional
actual output represents required flash span, not simply
the number of useful bytes copied into RAM. The command itself passes
null for that output.
Consider a hypothetical read of two eraseblocks of useful data from
an eraseblock-aligned start. If one intervening eraseblock is bad, the
request can require three eraseblocks of physical span. A region with
room for only two cannot satisfy it even though the RAM buffer and image
are each two blocks long. This is a mapping illustration, not a measured
bad-block pattern.
Keep writer
and later reader conventions aligned
The ordinary write helper also preflights skip-bad span and skips
marked blocks. That shared convention explains how a compact main-data
image can be written and later reconstructed without including
placeholders for skipped physical blocks. It does not establish
compatibility with every factory programmer, ROM loader or raw-page
dump. Write
and read helpers.
Record the logical image length, allowed physical region and exact
writer/reader mapping convention. If a later stage uses fixed physical
offsets while provisioning skipped bad blocks, increasing the read
length alone does not reconcile the formats. The placement contract must
be corrected at the producer-consumer boundary.
For qualification, use a NAND simulator or disposable, recoverable
media with known bad-block layouts. Compare no skipped blocks, a skipped
block within the requested span and insufficient remaining physical
capacity. Separately verify the expected RAM layout for raw
page-plus-OOB input. Do not create bad blocks or rewrite markers on
production media to obtain a fixture.
No NAND reads, writes or simulated tests were run for this article.
The engineering result is a two-length budget: useful image bytes and
physical flash span must both fit their respective contracts.