Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/usb/storage/umass_loader.c
34691 views
1
/*-
2
* Copyright (c) 2014 Hans Petter Selasky <[email protected]>
3
* All rights reserved.
4
*
5
* This software was developed by SRI International and the University of
6
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7
* ("CTSRD"), as part of the DARPA CRASH research programme.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*/
30
31
#include <sys/param.h>
32
33
#include <bootstrap.h>
34
#include <stdarg.h>
35
36
#include <stand.h>
37
#include <disk.h>
38
39
#define HAVE_STANDARD_DEFS
40
41
#include USB_GLOBAL_INCLUDE_FILE
42
43
#include "umass_common.h"
44
45
static int umass_disk_init(void);
46
static int umass_disk_open(struct open_file *,...);
47
static int umass_disk_close(struct open_file *);
48
static void umass_disk_cleanup(void);
49
static int umass_disk_ioctl(struct open_file *, u_long, void *);
50
static int umass_disk_strategy(void *, int, daddr_t, size_t, char *, size_t *);
51
static int umass_disk_print(int);
52
53
struct devsw umass_disk = {
54
.dv_name = "umass",
55
.dv_type = DEVT_DISK,
56
.dv_init = umass_disk_init,
57
.dv_strategy = umass_disk_strategy,
58
.dv_open = umass_disk_open,
59
.dv_close = umass_disk_close,
60
.dv_ioctl = umass_disk_ioctl,
61
.dv_print = umass_disk_print,
62
.dv_cleanup = umass_disk_cleanup,
63
.dv_fmtdev = disk_fmtdev,
64
.dv_parsedev = disk_parsedev,
65
};
66
67
static int
68
umass_disk_init(void)
69
{
70
uint32_t time;
71
72
usb_init();
73
usb_needs_explore_all();
74
75
/* wait 8 seconds for a USB mass storage device to appear */
76
for (time = 0; time < (8 * hz); time++) {
77
usb_idle();
78
delay(1000000 / hz);
79
time++;
80
callout_process(1);
81
if (umass_uaa.device != NULL)
82
return (0);
83
}
84
return (0);
85
}
86
87
static int
88
umass_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
89
char *buf, size_t *rsizep)
90
{
91
if (umass_uaa.device == NULL)
92
return (ENXIO);
93
if (rsizep != NULL)
94
*rsizep = 0;
95
96
flag &= F_MASK;
97
if (flag == F_WRITE) {
98
if (usb_msc_write_10(umass_uaa.device, 0, dblk, size >> 9, buf) != 0)
99
return (EINVAL);
100
} else if (flag == F_READ) {
101
if (usb_msc_read_10(umass_uaa.device, 0, dblk, size >> 9, buf) != 0)
102
return (EINVAL);
103
} else {
104
return (EROFS);
105
}
106
107
if (rsizep != NULL)
108
*rsizep = size;
109
return (0);
110
}
111
112
static int
113
umass_disk_open_sub(struct disk_devdesc *dev)
114
{
115
uint32_t nblock;
116
uint32_t blocksize;
117
118
if (usb_msc_read_capacity(umass_uaa.device, 0, &nblock, &blocksize) != 0)
119
return (EINVAL);
120
121
return (disk_open(dev, ((uint64_t)nblock + 1) * (uint64_t)blocksize, blocksize));
122
}
123
124
static int
125
umass_disk_open(struct open_file *f,...)
126
{
127
va_list ap;
128
struct disk_devdesc *dev;
129
130
va_start(ap, f);
131
dev = va_arg(ap, struct disk_devdesc *);
132
va_end(ap);
133
134
if (umass_uaa.device == NULL)
135
return (ENXIO);
136
if (dev->d_unit != 0)
137
return (EIO);
138
return (umass_disk_open_sub(dev));
139
}
140
141
static int
142
umass_disk_ioctl(struct open_file *f, u_long cmd, void *buf)
143
{
144
struct disk_devdesc *dev;
145
uint32_t nblock;
146
uint32_t blocksize;
147
int rc;
148
149
dev = (struct disk_devdesc *)(f->f_devdata);
150
if (dev == NULL)
151
return (EINVAL);
152
153
rc = disk_ioctl(dev, cmd, buf);
154
if (rc != ENOTTY)
155
return (rc);
156
157
switch (cmd) {
158
case DIOCGSECTORSIZE:
159
case DIOCGMEDIASIZE:
160
if (usb_msc_read_capacity(umass_uaa.device, 0,
161
&nblock, &blocksize) != 0)
162
return (EINVAL);
163
164
if (cmd == DIOCGMEDIASIZE)
165
*(uint64_t*)buf = nblock;
166
else
167
*(uint32_t*)buf = blocksize;
168
169
return (0);
170
default:
171
return (ENXIO);
172
}
173
}
174
175
static int
176
umass_disk_close(struct open_file *f)
177
{
178
struct disk_devdesc *dev;
179
180
dev = (struct disk_devdesc *)f->f_devdata;
181
return (disk_close(dev));
182
}
183
184
static int
185
umass_disk_print(int verbose)
186
{
187
struct disk_devdesc dev;
188
189
printf("%s devices:", umass_disk.dv_name);
190
if (pager_output("\n") != 0)
191
return (1);
192
193
memset(&dev, 0, sizeof(dev));
194
195
ret = pager_output(" umass0 UMASS device\n");
196
if (ret != 0)
197
return (ret);
198
dev.d_dev = &umass_disk;
199
dev.d_unit = 0;
200
dev.d_slice = D_SLICENONE;
201
dev.d_partition = D_PARTNONE;
202
203
if (umass_disk_open_sub(&dev) == 0) {
204
ret = disk_print(&dev, " umass0", verbose);
205
disk_close(&dev);
206
}
207
return (ret);
208
}
209
210
static void
211
umass_disk_cleanup(void)
212
{
213
214
usb_uninit();
215
}
216
217
218
/* USB specific functions */
219
220
extern void callout_process(int);
221
extern void usb_idle(void);
222
extern void usb_init(void);
223
extern void usb_uninit(void);
224
225
void
226
DELAY(unsigned int usdelay)
227
{
228
delay(usdelay);
229
}
230
231
int
232
pause(const char *what, int timeout)
233
{
234
if (timeout == 0)
235
timeout = 1;
236
237
delay((1000000 / hz) * timeout);
238
239
return (0);
240
}
241
242