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
//! The storage a driver talks to — the bottom of the allocator-free stack.
//!
//! This is the layer beneath the filesystems: two traits describing the two
//! shapes storage comes in. Nothing here allocates, touches `std`, or knows
//! which filesystem is above it, so a program implements one of these traits
//! over its peripheral and then mounts whatever the medium turns out to
//! hold.
//!
//! * [`SectorDriver`] — media addressed in fixed-size sectors that can be
//! rewritten in place: SD, eMMC, USB mass storage, a file. This is what
//! [`fs::fat`](crate::fs::fat)'s and [`fs::exfat`](crate::fs::exfat)'s
//! drivers are written against, so one implementation serves both — which
//! is what a card reader needs, since an SDXC card arrives formatted exFAT
//! and an SDHC one FAT32.
//! * [`FlashDriver`] — media that must be erased before it is programmed,
//! and only a whole block at a time: raw NOR and NAND. This is what
//! [`fs::littlefs`](crate::fs::littlefs)'s driver is written against, and
//! it mirrors littlefs's own `lfs_config`.
//!
//! Those two traits are the whole contract: what a consumer *implements*.
//! Everything a driver hands back about the medium is data, and lives beside
//! them rather than among them — the partition tables that say where on a
//! medium a volume begins:
//!
//! * [`mbr`] — the master boot record's four primary slots.
//! * [`gpt`] — the EFI GUID Partition Table, header CRC checked, with the
//! backup at the end of the medium used when the primary does not.
//!
//! They are here rather than in [`part`](crate::part) because the hosted
//! partition layer builds owned tables and needs a heap, while a driver
//! mounting a volume needs a handful of numbers and no allocator.
//!
//! With `alloc` on, [`block`](crate::block) re-exports the two traits beside
//! its own [`SectorIo`](crate::block::SectorIo) — which is the trait to
//! implement when you want a *byte-addressed* device for the hosted
//! filesystems, rather than a driver for the allocator-free ones.
/// A driver for sector-addressed storage: the one trait an embedded consumer
/// implements for a card.
///
/// The volume checks every request before making it, so an implementation
/// need not: `buf` is always a non-zero multiple of
/// [`sector_size`](Self::sector_size) bytes long, and `lba + buf.len() /
/// sector_size` never exceeds [`sector_count`](Self::sector_count).
/// A driver for erase-block storage: raw flash, which must be erased before
/// it can be programmed.
///
/// It mirrors littlefs's own `lfs_config`. The volume checks every request
/// before making it, so an implementation need not: `block` is always below
/// [`block_count`](Self::block_count), and `off + buf.len()` never exceeds
/// [`block_size`](Self::block_size).
///
/// The usual flash contract applies and a filesystem relies on it: a block
/// reads as `0xff` after [`erase`](Self::erase), and [`prog`](Self::prog) is
/// only ever called on erased storage, at offsets and lengths that are
/// multiples of [`prog_size`](Self::prog_size).