Skip to content

feat(spi_nand_flash): Add block device support#606

Merged
pacucha42 merged 2 commits into
espressif:masterfrom
RathiSonika:feat/nand_flash_bdl_support
Apr 1, 2026
Merged

feat(spi_nand_flash): Add block device support#606
pacucha42 merged 2 commits into
espressif:masterfrom
RathiSonika:feat/nand_flash_bdl_support

Conversation

@RathiSonika
Copy link
Copy Markdown
Collaborator

@RathiSonika RathiSonika commented Nov 10, 2025

Change description

  • Add block device support (nand_flash_bdl and nand_wl_bdl)

  • Please refer spi_nand_flash/layered_architecture.md for the details and migration guide

  • Refactor the component for improved structure, maintainability and readability
    - Added page-based API terminology (read_page, write_page, get_page_count, get_page_size) with backward-compatible sector aliases.

  • Removed the fatfs/vfs component dependency; it will be relocated (along with examples) to another component in a different PR.

  • Add Kconfig option NAND_FLASH_ENABLE_BDL to enable/disable BDL support

  • Updated test_apps and host_tests to verify the same

  • OTP and OOB area handling are still missing. I’ll address them in a separate PR, as the scope of this one is already growing.

Comment thread spi_nand_flash/src/nand_flash_blockdev.c Fixed
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch 2 times, most recently from 5e70c2f to afd1301 Compare November 11, 2025 08:38
Comment thread spi_nand_flash/include/esp_nand_blockdev.h
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch 2 times, most recently from 69e8bbd to 422413c Compare November 12, 2025 09:38
Comment thread spi_nand_flash/src/dhara_glue.c Outdated
Comment thread spi_nand_flash/src/dhara_glue.c Outdated
@RathiSonika RathiSonika self-assigned this Nov 13, 2025
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch 3 times, most recently from b05a6d5 to 2d1b2a3 Compare November 13, 2025 19:11
Comment thread spi_nand_flash/diskio/diskio_nand_blockdev.c Fixed
Comment thread spi_nand_flash/vfs/vfs_fat_spinandflash.c Fixed
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch from 2d1b2a3 to 19bd12c Compare November 14, 2025 07:45
Comment thread spi_nand_flash/diskio/diskio_nand_blockdev.c Fixed
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch 15 times, most recently from c335750 to cc21a22 Compare November 19, 2025 12:31
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch 3 times, most recently from 0f79e0e to d773d82 Compare March 16, 2026 10:31
@RathiSonika RathiSonika marked this pull request as ready for review March 17, 2026 07:42
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch 3 times, most recently from cdb519e to 2f78ca0 Compare March 30, 2026 13:05
@pacucha42
Copy link
Copy Markdown
Collaborator

Outcome of the final review:

1. Flash BDL erase: missing out-of-bounds check

Severity: High

nand_flash_blockdev_erase() validates alignment and non-zero length but never checks whether the erase range exceeds device bounds. An erase request past the end of flash passes all validation and proceeds to erase non-existent blocks.

Both nand_flash_blockdev_read() and nand_flash_blockdev_write() in the same file have this check. The WL BDL erase (spi_nand_flash_wl_blockdev_erase()) also has it.

Location: spi_nand_flash/src/nand_flash_blockdev.c, nand_flash_blockdev_erase()

Fix — add after the erase_len alignment check:

if (start_addr + erase_len > handle->geometry.disk_size) {
    ESP_LOGE(TAG, "Erase range exceeds device bounds");
    return ESP_ERR_INVALID_SIZE;
}

2. dhara_nand_read BDL path: dst_buf_size doesn't match actual buffer

Severity: Medium

In the BDL path of dhara_nand_read():

ret = bdl_handle->ops->read(bdl_handle, data, bdl_handle->geometry.read_size,
                            (p * bdl_handle->geometry.read_size) + offset, length);

bdl_handle->geometry.read_size (full page size, e.g. 2048) is passed as dst_buf_size, but Dhara's data buffer is only length bytes. The current read implementation only writes data_read_len bytes so there is no buffer overflow today; however, the safety check (dst_buf_size < data_read_len) is semantically defeated — it can never trip even when the actual buffer is smaller than claimed.

Location: spi_nand_flash/src/dhara_glue.c, dhara_nand_read()

Fix:

ret = bdl_handle->ops->read(bdl_handle, data, length,
                            (p * bdl_handle->geometry.read_size) + offset, length);

3. spi_nand_flash_init_device() doxygen not updated for BDL incompatibility

Severity: Medium

When CONFIG_NAND_FLASH_ENABLE_BDL=y, spi_nand_flash_init_device() unconditionally returns ESP_ERR_NOT_SUPPORTED. The CHANGELOG and migration guide document this, but:

  • The doxygen on spi_nand_flash_init_device() in spi_nand_flash.h is unchanged — a user reading only the header won't know until runtime.
  • The Kconfig help text for NAND_FLASH_ENABLE_BDL says "When disabled, only the legacy API is available" but does not state the inverse: when enabled, spi_nand_flash_init_device() is not available.

Location: spi_nand_flash/include/spi_nand_flash.h (doxygen of spi_nand_flash_init_device), spi_nand_flash/Kconfig

Fix:

Add to spi_nand_flash_init_device() doxygen:

 * @note When CONFIG_NAND_FLASH_ENABLE_BDL is enabled, this function returns
 *       ESP_ERR_NOT_SUPPORTED. Use spi_nand_flash_init_with_layers() instead.

Add to Kconfig help:

When enabled, the legacy spi_nand_flash_init_device() is not available
(returns ESP_ERR_NOT_SUPPORTED). Use spi_nand_flash_init_with_layers().

4. Triplicated ECC threshold check logic

Severity: Low

The same ECC-threshold comparison exists in three places:

File Function
src/nand_flash_blockdev.c is_ecc_exceed_threshold()
src/nand_diag_api.c is_ecc_exceed_threshold()
src/nand.c s_need_data_refresh()

All three are identical: compare ecc_corrected_bits_status against ecc_data_refresh_threshold using the same 1/4/7 mapping.

Fix: Extract a single shared helper (e.g. static inline in a private header) and call it from all three sites.


5. chip_name stores only manufacturer name

Severity: Low

Device init files (nand_gigadevice.c, nand_micron.c, nand_winbond.c, etc.) set chip_name to just the manufacturer string:

char *name = "gigadevice";
strncpy(dev->device_info.chip_name, name, strlen(name) + 1);

The GET_NAND_FLASH_INFO ioctl exposes this to users. For diagnostics, a model-specific name (e.g. "GD5F1GQ5UExxG" or at least "gigadevice-0x51") would be more useful. The 32-byte chip_name field is underutilized.


6. size_tuint32_t truncation in erase log

Severity: Low

In nand_flash_blockdev_erase():

ESP_LOGV(TAG, "erase - ... size=0x%08" PRIx32 " ...", ..., (uint32_t)erase_len, ret);

erase_len is size_t (64-bit on Linux host). The (uint32_t) cast silently truncates. The WL erase log has the same pattern. Use %zx or cast to uint64_t with PRIx64.


Summary

# Severity Issue
1 High Flash BDL erase: missing out-of-bounds check
2 Medium dhara_nand_read BDL path: dst_buf_size doesn't match actual buffer
3 Medium spi_nand_flash_init_device() doxygen/Kconfig not updated for BDL incompatibility
4 Low Triplicated ECC threshold check logic
5 Low chip_name only stores manufacturer, not model
6 Low size_tuint32_t truncation in erase log

After fixing those points (1,2,3 and 6 at least), the PR can be merged.

Thank you

@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch from 2f78ca0 to 14991e0 Compare March 31, 2026 07:20
@RathiSonika RathiSonika requested a review from hfudev March 31, 2026 07:52
Copy link
Copy Markdown
Member

@hfudev hfudev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI changes LGTM.

@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch from 554f473 to 14991e0 Compare March 31, 2026 11:19
Copy link
Copy Markdown
Collaborator

@pacucha42 pacucha42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Thank you for addressing all the comments. Approving

@hfudev hfudev self-requested a review March 31, 2026 11:39
@hfudev
Copy link
Copy Markdown
Member

hfudev commented Mar 31, 2026

need to revert the deletion of the workaround: https://github.com/espressif/idf-extra-components/compare/554f4734e8927e1308bfca81d213f39e512efdba..14991e0849cb7d6e2a7c41067d460657a54135d9

the latest docker images still requires hours to be created.

@hfudev
Copy link
Copy Markdown
Member

hfudev commented Mar 31, 2026

need to revert the deletion of the workaround: https://github.com/espressif/idf-extra-components/compare/554f4734e8927e1308bfca81d213f39e512efdba..14991e0849cb7d6e2a7c41067d460657a54135d9

the latest docker images still requires hours to be created.

the latest docker image has been updated!

Comment thread spi_nand_flash/src/nand_flash_blockdev.c Outdated
Copy link
Copy Markdown

@haberturdeur haberturdeur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides a small nitpick LGTM!

@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch from 14991e0 to 8e079e9 Compare March 31, 2026 13:52
Comment thread spi_nand_flash/include/esp_nand_blockdev.h Outdated
Comment thread spi_nand_flash/include/esp_nand_blockdev.h Outdated
@RathiSonika RathiSonika force-pushed the feat/nand_flash_bdl_support branch 4 times, most recently from 154e464 to 6178b51 Compare April 1, 2026 14:06
- add block device support
- refactor the component for improved structure and maintainability
- remove the fatfs/vfs component dependency from the driver
Copy link
Copy Markdown
Collaborator

@pacucha42 pacucha42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks good, approviing. Thank you @RathiSonika

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants