Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/uboot/uboot_disk.c
34677 views
1
/*-
2
* Copyright (c) 2008 Semihalf, Rafal Jaworowski
3
* Copyright (c) 2009 Semihalf, Piotr Ziecik
4
* Copyright (c) 2012 Andrey V. Elsukov <[email protected]>
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*
28
*/
29
30
/*
31
* Block storage I/O routines for U-Boot
32
*/
33
34
#include <sys/param.h>
35
#include <sys/disk.h>
36
#include <sys/stdarg.h>
37
38
#include <stand.h>
39
40
#include "api_public.h"
41
#include "bootstrap.h"
42
#include "disk.h"
43
#include "glue.h"
44
#include "libuboot.h"
45
46
#define stor_printf(fmt, args...) do { \
47
printf("%s%d: ", dev->dd.d_dev->dv_name, dev->dd.d_unit); \
48
printf(fmt, ##args); \
49
} while (0)
50
51
#ifdef DEBUG
52
#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
53
printf(fmt,##args); } while (0)
54
#else
55
#define debugf(fmt, args...)
56
#endif
57
58
static struct {
59
int opened; /* device is opened */
60
int handle; /* storage device handle */
61
int type; /* storage type */
62
off_t blocks; /* block count */
63
u_int bsize; /* block size */
64
} stor_info[UB_MAX_DEV];
65
66
#define SI(dev) (stor_info[(dev)->dd.d_unit])
67
68
static int stor_info_no = 0;
69
static int stor_opendev(struct disk_devdesc *);
70
static int stor_readdev(struct disk_devdesc *, daddr_t, size_t, char *);
71
72
/* devsw I/F */
73
static int stor_init(void);
74
static int stor_strategy(void *, int, daddr_t, size_t, char *, size_t *);
75
static int stor_open(struct open_file *, ...);
76
static int stor_close(struct open_file *);
77
static int stor_ioctl(struct open_file *f, u_long cmd, void *data);
78
static int stor_print(int);
79
static void stor_cleanup(void);
80
81
struct devsw uboot_storage = {
82
.dv_name = "disk",
83
.dv_type = DEVT_DISK,
84
.dv_init = stor_init,
85
.dv_strategy = stor_strategy,
86
.dv_open = stor_open,
87
.dv_close = stor_close,
88
.dv_ioctl = stor_ioctl,
89
.dv_print = stor_print,
90
.dv_cleanup = stor_cleanup,
91
.dv_fmtdev = disk_fmtdev,
92
.dv_parsedev = disk_parsedev,
93
};
94
95
static int
96
stor_init(void)
97
{
98
struct device_info *di;
99
int i;
100
101
if (devs_no == 0) {
102
printf("No U-Boot devices! Really enumerated?\n");
103
return (-1);
104
}
105
106
for (i = 0; i < devs_no; i++) {
107
di = ub_dev_get(i);
108
if ((di != NULL) && (di->type & DEV_TYP_STOR)) {
109
if (stor_info_no >= UB_MAX_DEV) {
110
printf("Too many storage devices: %d\n",
111
stor_info_no);
112
return (-1);
113
}
114
stor_info[stor_info_no].handle = i;
115
stor_info[stor_info_no].opened = 0;
116
stor_info[stor_info_no].type = di->type;
117
stor_info[stor_info_no].blocks =
118
di->di_stor.block_count;
119
stor_info[stor_info_no].bsize =
120
di->di_stor.block_size;
121
stor_info_no++;
122
}
123
}
124
125
if (!stor_info_no) {
126
debugf("No storage devices\n");
127
return (-1);
128
}
129
130
debugf("storage devices found: %d\n", stor_info_no);
131
return (0);
132
}
133
134
static void
135
stor_cleanup(void)
136
{
137
int i;
138
139
for (i = 0; i < stor_info_no; i++)
140
if (stor_info[i].opened > 0)
141
ub_dev_close(stor_info[i].handle);
142
}
143
144
static int
145
stor_strategy(void *devdata, int rw, daddr_t blk, size_t size,
146
char *buf, size_t *rsize)
147
{
148
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
149
daddr_t bcount;
150
int err;
151
152
rw &= F_MASK;
153
if (rw != F_READ) {
154
stor_printf("write attempt, operation not supported!\n");
155
return (EROFS);
156
}
157
158
if (size % SI(dev).bsize) {
159
stor_printf("size=%zu not multiple of device "
160
"block size=%d\n",
161
size, SI(dev).bsize);
162
return (EIO);
163
}
164
bcount = size / SI(dev).bsize;
165
if (rsize)
166
*rsize = 0;
167
168
err = stor_readdev(dev, blk + dev->d_offset, bcount, buf);
169
if (!err && rsize)
170
*rsize = size;
171
172
return (err);
173
}
174
175
static int
176
stor_open(struct open_file *f, ...)
177
{
178
va_list ap;
179
struct disk_devdesc *dev;
180
181
va_start(ap, f);
182
dev = va_arg(ap, struct disk_devdesc *);
183
va_end(ap);
184
185
return (stor_opendev(dev));
186
}
187
188
static int
189
stor_opendev(struct disk_devdesc *dev)
190
{
191
int err;
192
193
if (dev->dd.d_unit < 0 || dev->dd.d_unit >= stor_info_no)
194
return (EIO);
195
196
if (SI(dev).opened == 0) {
197
err = ub_dev_open(SI(dev).handle);
198
if (err != 0) {
199
stor_printf("device open failed with error=%d, "
200
"handle=%d\n", err, SI(dev).handle);
201
return (ENXIO);
202
}
203
SI(dev).opened++;
204
}
205
return (disk_open(dev, SI(dev).blocks * SI(dev).bsize,
206
SI(dev).bsize));
207
}
208
209
static int
210
stor_close(struct open_file *f)
211
{
212
struct disk_devdesc *dev;
213
214
dev = (struct disk_devdesc *)(f->f_devdata);
215
return (disk_close(dev));
216
}
217
218
static int
219
stor_readdev(struct disk_devdesc *dev, daddr_t blk, size_t size, char *buf)
220
{
221
lbasize_t real_size;
222
int err;
223
224
debugf("reading blk=%d size=%d @ 0x%08x\n", (int)blk, size, (uint32_t)buf);
225
226
err = ub_dev_read(SI(dev).handle, buf, size, blk, &real_size);
227
if (err != 0) {
228
stor_printf("read failed, error=%d\n", err);
229
return (EIO);
230
}
231
232
if (real_size != size) {
233
stor_printf("real size != size\n");
234
err = EIO;
235
}
236
237
return (err);
238
}
239
240
static int
241
stor_print(int verbose)
242
{
243
struct disk_devdesc dev;
244
static char line[80];
245
int i, ret = 0;
246
247
if (stor_info_no == 0)
248
return (ret);
249
250
printf("%s devices:", uboot_storage.dv_name);
251
if ((ret = pager_output("\n")) != 0)
252
return (ret);
253
254
for (i = 0; i < stor_info_no; i++) {
255
dev.dd.d_dev = &uboot_storage;
256
dev.dd.d_unit = i;
257
dev.d_slice = D_SLICENONE;
258
dev.d_partition = D_PARTNONE;
259
snprintf(line, sizeof(line), "\tdisk%d (%s)\n", i,
260
ub_stor_type(SI(&dev).type));
261
if ((ret = pager_output(line)) != 0)
262
break;
263
if (stor_opendev(&dev) == 0) {
264
sprintf(line, "\tdisk%d", i);
265
ret = disk_print(&dev, line, verbose);
266
disk_close(&dev);
267
if (ret != 0)
268
break;
269
}
270
}
271
return (ret);
272
}
273
274
static int
275
stor_ioctl(struct open_file *f, u_long cmd, void *data)
276
{
277
struct disk_devdesc *dev;
278
int rc;
279
280
dev = (struct disk_devdesc *)f->f_devdata;
281
rc = disk_ioctl(dev, cmd, data);
282
if (rc != ENOTTY)
283
return (rc);
284
285
switch (cmd) {
286
case DIOCGSECTORSIZE:
287
*(u_int *)data = SI(dev).bsize;
288
break;
289
case DIOCGMEDIASIZE:
290
*(uint64_t *)data = SI(dev).bsize * SI(dev).blocks;
291
break;
292
default:
293
return (ENOTTY);
294
}
295
return (0);
296
}
297
298
299
/*
300
* Return the device unit number for the given type and type-relative unit
301
* number.
302
*/
303
int
304
uboot_diskgetunit(int type, int type_unit)
305
{
306
int local_type_unit;
307
int i;
308
309
local_type_unit = 0;
310
for (i = 0; i < stor_info_no; i++) {
311
if ((stor_info[i].type & type) == type) {
312
if (local_type_unit == type_unit) {
313
return (i);
314
}
315
local_type_unit++;
316
}
317
}
318
319
return (-1);
320
}
321
322