RT-Thread RTOS
An open source embedded real-time operating system
Disk partition probing

Partition tables on <tt>rt_blk_disk</tt>

After **rt_hw_blk_disk_register**, the core calls **rt_blk_disk_probe_partition** to read the on-disk partition layout and register one **rt_blk_device** per slice via **blk_put_partition**. Implementation: **components/drivers/block/blk_partition.c**; parsers in **components/drivers/block/partitions/**.

Volume naming and application access: Block layer (blk). Disk registration: Physical disk (rt_blk_disk).


Kconfig

Option File Role
**RT_BLK_PARTITION_EFI** partitions/efi.c Protective MBR + GPT (UEFI-style)
**RT_BLK_PARTITION_DFS** partitions/dfs.c DFS legacy partition table in sector 0

Both can be enabled; **partition_list[]** order is EFI first, then DFS. The first parser returning 0 wins.


<tt>rt_blk_disk_probe_partition</tt>

{103:154:components/drivers/block/blk_partition.c}
rt_err_t rt_blk_disk_probe_partition(struct rt_blk_disk *disk)
Step Behavior
1 **disk == NULL** → **-RT_EINVAL**
2 **disk->partitions != 0** → return success (already probed)
3 **max_partitions == RT_BLK_PARTITION_NONE** → **-RT_EEMPTY**
4 Loop **partition_list[i](disk)**
5 Parser **-RT_ENOMEM** → abort, return **-RT_ENOMEM**
6 Parser 0 → success, stop
7 No parser matched → full-disk volume: **blk_put_partition(disk, NULL, 0, total_sectors, 0)**

So a blank or unknown layout still yields one mountable device covering the entire disk (**partno == 0**).


<tt>blk_put_partition</tt>

{27:100:components/drivers/block/blk_partition.c}
rt_err_t blk_put_partition(struct rt_blk_disk *disk, const char *type,
rt_size_t start, rt_size_t count, int partno)
Phase Action
Allocate **struct rt_blk_device**
Init **blk_dev_initialize(blk)**
Range **sector_start = start**, **sector_count = count**, **partno**
DFS meta **partition.offset**, **partition.size**, **partition.lock = &disk->usr_lock**
Register **disk_add_blk_dev(disk, blk)** → **rt_device_register**, link **part_nodes**
Count **disk->partitions++**

Console log

For non-**"dfs"** types, printk partition index, byte offset, and human-readable size (KB/MB/GB).

Failure

**-RT_ENOMEM** frees the partial **rt_blk_device** and logs via **LOG_E**.


EFI / GPT (<tt>partitions/efi.c</tt>)

Boot-time <tt>force_gpt</tt>

**INIT_CORE_EXPORT(force_gpt_setup)** reads bootarg **gpt** via **rt_ofw_bootargs_select("gpt", 0)** when **RT_USING_OFW**. When set, GPT probing is forced even if protective MBR checks are ambiguous.

Validation flow (summary)

  1. Read LBA 0 — check protective MBR (EFI GPT type, starting LBA 1).
  2. Read primary GPT header at LBA 1 (or from **force_gpt** path).
  3. Verify signature **"EFI PART"**, header CRC (**efi_crc32**), **my_lba**, **first_usable_lba / last_usable_lba** vs disk capacity (**last_lba()** = **rt_blk_disk_get_capacity - 1**).
  4. Load partition entry array; validate entry CRC.
  5. For each valid entry: **blk_put_partition(disk, type, start, count, partno)** with type string / GUID mapping where implemented.

Sector size

All LBA math uses **rt_blk_disk_get_logical_block_size(disk)** — must stay consistent with **getgeome**.

Enable

Menu: **RT_BLK_PARTITION_EFI** (default y when blk partitions menu is on).


DFS partition (<tt>partitions/dfs.c</tt>)

Legacy path for RT-Thread DFS on-disk superblock layout:

  1. Allocate one sector buffer.
  2. **disk->ops->read(disk, 0, sector, 1)**.
  3. Loop **dfs_filesystem_get_partition(&part, sector, i)** for **i < max_partitions**.
  4. **blk_put_partition(disk, "dfs", part.offset, part.size, i)**.

Requires **RT_USING_DFS** and **RT_BLK_PARTITION_DFS**.


Volume naming after probe

Handled in **disk_add_blk_dev** (blk_dev.c):

Disk name ends with Example disk Volume examples
Letter **az** **sda** **sdap1**, **sdap2**
Digit / other **mmcsd0**, **nvme0n1** **mmcsd0p1**, **nvme0n1p2**

When to call probe

Scenario Action
Normal driver Rely on **rt_hw_blk_disk_register** (automatic)
Media just formatted Unregister disk, register again, or call **rt_blk_disk_probe_partition** if **partitions == 0**
Disable tables Set **max_partitions = RT_BLK_PARTITION_NONE**
RAM disk / single volume Still get one full-disk **partno 0** unless you manage volumes manually

Call sites in tree

Location Notes
**blk.c** End of **rt_hw_blk_disk_register**
Driver after hotplug Rare; prefer re-register

Interaction with disk IOCTLs

IOCTL Multi-partition disk
ERASE / AUTOREFRESH on volume **-RT_EIO** if **disk->partitions > 1**
ERASE on disk Removes all volumes first, then **ops->erase**
GETGEOME on volume **sector_count** = partition only

Driver / BSP quick notes

Topic Guidance
Order EFI before DFS — do not rely on DFS if GPT is present
**max_partitions** SDIO passes **RT_MMCSD_MAX_PARTITION**; NVMe uses **RT_BLK_PARTITION_MAX**
Empty card Probe still creates full-disk volume — mount may need valid FS
Re-probe Not supported with existing volumes; unregister disk first
Custom layouts Add a parser to **partition_list[]** or call **blk_put_partition** from driver code

See also