summaryrefslogtreecommitdiff
path: root/documentation/6.components/device-driver/block/partitions.md
blob: b26de94aef21c7ce75bc887b748198d9d9214be9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
@page page_device_partitions Disk partition probing

# Partition tables on `rt_blk_disk`

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: @ref page_device_blk. Disk registration: @ref page_device_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.

---

## `rt_blk_disk_probe_partition`

```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`**).

---

## `blk_put_partition`

```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 (`partitions/efi.c`)

### Boot-time `force_gpt`

**`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 (`partitions/dfs.c`)

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 **`a`–`z`** | **`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

- @ref page_device_blk
- @ref page_device_disk
- `components/drivers/block/blk_partition.c`
- `components/drivers/block/partitions/efi.c`
- `components/drivers/block/partitions/dfs.c`