Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/geom/geom_flashmap.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2012 Semihalf
5
* Copyright (c) 2009 Jakub Klama <[email protected]>
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <sys/param.h>
31
#include <sys/systm.h>
32
#include <sys/kernel.h>
33
#include <sys/malloc.h>
34
#include <sys/lock.h>
35
#include <sys/mutex.h>
36
#include <sys/slicer.h>
37
38
#include <geom/geom.h>
39
#include <geom/geom_disk.h>
40
#include <geom/geom_flashmap.h>
41
#include <geom/geom_slice.h>
42
43
struct g_flashmap_slice {
44
off_t sl_start;
45
off_t sl_end;
46
const char *sl_name;
47
48
STAILQ_ENTRY(g_flashmap_slice) sl_link;
49
};
50
51
STAILQ_HEAD(g_flashmap_head, g_flashmap_slice);
52
53
static struct {
54
const char *type;
55
flash_slicer_t slicer;
56
} g_flashmap_slicers[] = {
57
{ "NAND::device", NULL },
58
{ "CFI::device", NULL },
59
{ "SPI::device", NULL },
60
{ "MMC::device", NULL }
61
};
62
63
static g_taste_t g_flashmap_taste;
64
65
static int g_flashmap_load(device_t dev, struct g_provider *pp,
66
flash_slicer_t slicer, struct g_flashmap_head *head);
67
static int g_flashmap_modify(struct g_flashmap *gfp, struct g_geom *gp,
68
const char *devname, int secsize, struct g_flashmap_head *slices);
69
static void g_flashmap_print(struct g_flashmap_slice *slice);
70
71
MALLOC_DECLARE(M_FLASHMAP);
72
MALLOC_DEFINE(M_FLASHMAP, "geom_flashmap", "GEOM flash memory slicer class");
73
74
static void
75
g_flashmap_print(struct g_flashmap_slice *slice)
76
{
77
78
printf("%08jx-%08jx: %s (%juKB)\n", (uintmax_t)slice->sl_start,
79
(uintmax_t)slice->sl_end, slice->sl_name,
80
(uintmax_t)(slice->sl_end - slice->sl_start) / 1024);
81
}
82
83
static int
84
g_flashmap_modify(struct g_flashmap *gfp, struct g_geom *gp,
85
const char *devname, int secsize, struct g_flashmap_head *slices)
86
{
87
struct g_flashmap_slice *slice;
88
int i, error;
89
90
g_topology_assert();
91
92
i = 0;
93
STAILQ_FOREACH(slice, slices, sl_link) {
94
if (bootverbose) {
95
printf("%s: slice ", devname);
96
g_flashmap_print(slice);
97
}
98
99
error = g_slice_config(gp, i++, G_SLICE_CONFIG_CHECK,
100
slice->sl_start,
101
slice->sl_end - slice->sl_start + 1,
102
secsize, FLASH_SLICES_FMT, gp->name, slice->sl_name);
103
104
if (error)
105
return (error);
106
}
107
108
i = 0;
109
STAILQ_FOREACH(slice, slices, sl_link) {
110
free(__DECONST(void *, gfp->labels[i]), M_FLASHMAP);
111
gfp->labels[i] = strdup(slice->sl_name, M_FLASHMAP);
112
error = g_slice_config(gp, i++, G_SLICE_CONFIG_SET,
113
slice->sl_start,
114
slice->sl_end - slice->sl_start + 1,
115
secsize, "%ss.%s", gp->name, slice->sl_name);
116
117
if (error)
118
return (error);
119
}
120
121
return (0);
122
}
123
124
static struct g_geom *
125
g_flashmap_taste(struct g_class *mp, struct g_provider *pp, int flags)
126
{
127
struct g_geom *gp;
128
struct g_consumer *cp;
129
struct g_flashmap_head head;
130
struct g_flashmap_slice *slice, *slice_temp;
131
struct g_flashmap *gfp;
132
flash_slicer_t slicer;
133
device_t dev;
134
int i, size;
135
136
g_trace(G_T_TOPOLOGY, "flashmap_taste(%s,%s)", mp->name, pp->name);
137
g_topology_assert();
138
139
if (flags == G_TF_NORMAL &&
140
strcmp(pp->geom->class->name, G_DISK_CLASS_NAME) != 0)
141
return (NULL);
142
143
gp = g_slice_new(mp, FLASH_SLICES_MAX_NUM, pp, &cp, (void**)&gfp,
144
sizeof(struct g_flashmap), NULL);
145
if (gp == NULL)
146
return (NULL);
147
148
STAILQ_INIT(&head);
149
150
do {
151
slicer = NULL;
152
for (i = 0; i < nitems(g_flashmap_slicers); i++) {
153
size = sizeof(device_t);
154
if (g_io_getattr(g_flashmap_slicers[i].type, cp,
155
&size, &dev) == 0) {
156
slicer = g_flashmap_slicers[i].slicer;
157
break;
158
}
159
}
160
if (slicer == NULL)
161
break;
162
163
if (g_flashmap_load(dev, pp, slicer, &head) == 0)
164
break;
165
166
g_flashmap_modify(gfp, gp, cp->provider->name,
167
cp->provider->sectorsize, &head);
168
} while (0);
169
170
g_access(cp, -1, 0, 0);
171
172
STAILQ_FOREACH_SAFE(slice, &head, sl_link, slice_temp)
173
free(slice, M_FLASHMAP);
174
175
if (LIST_EMPTY(&gp->provider)) {
176
g_slice_spoiled(cp);
177
return (NULL);
178
}
179
return (gp);
180
}
181
182
static int
183
g_flashmap_load(device_t dev, struct g_provider *pp, flash_slicer_t slicer,
184
struct g_flashmap_head *head)
185
{
186
struct flash_slice *slices;
187
struct g_flashmap_slice *slice;
188
int i, nslices = 0;
189
190
slices = malloc(sizeof(struct flash_slice) * FLASH_SLICES_MAX_NUM,
191
M_FLASHMAP, M_WAITOK | M_ZERO);
192
if (slicer(dev, pp->name, slices, &nslices) == 0) {
193
for (i = 0; i < nslices; i++) {
194
slice = malloc(sizeof(struct g_flashmap_slice),
195
M_FLASHMAP, M_WAITOK);
196
197
slice->sl_name = slices[i].label;
198
slice->sl_start = slices[i].base;
199
slice->sl_end = slices[i].base + slices[i].size - 1;
200
201
STAILQ_INSERT_TAIL(head, slice, sl_link);
202
}
203
}
204
205
free(slices, M_FLASHMAP);
206
return (nslices);
207
}
208
209
void flash_register_slicer(flash_slicer_t slicer, u_int type, bool force)
210
{
211
212
g_topology_lock();
213
if (g_flashmap_slicers[type].slicer == NULL || force == TRUE)
214
g_flashmap_slicers[type].slicer = slicer;
215
g_topology_unlock();
216
}
217
218
static struct g_class g_flashmap_class = {
219
.name = FLASHMAP_CLASS_NAME,
220
.version = G_VERSION,
221
.taste = g_flashmap_taste,
222
};
223
224
DECLARE_GEOM_CLASS(g_flashmap_class, g_flashmap);
225
MODULE_VERSION(geom_flashmap, 0);
226
227