1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * storage_common.c -- Common definitions for mass storage functionality
4 *
5 * Copyright (C) 2003-2008 Alan Stern
6 * Copyeight (C) 2009 Samsung Electronics
7 * Author: Michal Nazarewicz (mina86@mina86.com)
8 */
9
10/*
11 * This file requires the following identifiers used in USB strings to
12 * be defined (each of type pointer to char):
13 *  - fsg_string_interface    -- name of the interface
14 */
15
16/*
17 * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers
18 * sets the number of pipeline buffers (length of the fsg_buffhd array).
19 * The valid range of num_buffers is: num >= 2 && num <= 4.
20 */
21
22#include <linux/module.h>
23#include <linux/blkdev.h>
24#include <linux/file.h>
25#include <linux/fs.h>
26#include <linux/kstrtox.h>
27#include <linux/usb/composite.h>
28
29#include "storage_common.h"
30
31/* There is only one interface. */
32
33struct usb_interface_descriptor fsg_intf_desc = {
34	.bLength =		sizeof fsg_intf_desc,
35	.bDescriptorType =	USB_DT_INTERFACE,
36
37	.bNumEndpoints =	2,		/* Adjusted during fsg_bind() */
38	.bInterfaceClass =	USB_CLASS_MASS_STORAGE,
39	.bInterfaceSubClass =	USB_SC_SCSI,	/* Adjusted during fsg_bind() */
40	.bInterfaceProtocol =	USB_PR_BULK,	/* Adjusted during fsg_bind() */
41	.iInterface =		FSG_STRING_INTERFACE,
42};
43EXPORT_SYMBOL_GPL(fsg_intf_desc);
44
45/*
46 * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
47 * interrupt-in.
48 */
49
50struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = {
51	.bLength =		USB_DT_ENDPOINT_SIZE,
52	.bDescriptorType =	USB_DT_ENDPOINT,
53
54	.bEndpointAddress =	USB_DIR_IN,
55	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
56	/* wMaxPacketSize set by autoconfiguration */
57};
58EXPORT_SYMBOL_GPL(fsg_fs_bulk_in_desc);
59
60struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
61	.bLength =		USB_DT_ENDPOINT_SIZE,
62	.bDescriptorType =	USB_DT_ENDPOINT,
63
64	.bEndpointAddress =	USB_DIR_OUT,
65	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
66	/* wMaxPacketSize set by autoconfiguration */
67};
68EXPORT_SYMBOL_GPL(fsg_fs_bulk_out_desc);
69
70struct usb_descriptor_header *fsg_fs_function[] = {
71	(struct usb_descriptor_header *) &fsg_intf_desc,
72	(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
73	(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
74	NULL,
75};
76EXPORT_SYMBOL_GPL(fsg_fs_function);
77
78
79/*
80 * USB 2.0 devices need to expose both high speed and full speed
81 * descriptors, unless they only run at full speed.
82 *
83 * That means alternate endpoint descriptors (bigger packets).
84 */
85struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
86	.bLength =		USB_DT_ENDPOINT_SIZE,
87	.bDescriptorType =	USB_DT_ENDPOINT,
88
89	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
90	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
91	.wMaxPacketSize =	cpu_to_le16(512),
92};
93EXPORT_SYMBOL_GPL(fsg_hs_bulk_in_desc);
94
95struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
96	.bLength =		USB_DT_ENDPOINT_SIZE,
97	.bDescriptorType =	USB_DT_ENDPOINT,
98
99	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
100	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
101	.wMaxPacketSize =	cpu_to_le16(512),
102	.bInterval =		1,	/* NAK every 1 uframe */
103};
104EXPORT_SYMBOL_GPL(fsg_hs_bulk_out_desc);
105
106
107struct usb_descriptor_header *fsg_hs_function[] = {
108	(struct usb_descriptor_header *) &fsg_intf_desc,
109	(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
110	(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
111	NULL,
112};
113EXPORT_SYMBOL_GPL(fsg_hs_function);
114
115struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
116	.bLength =		USB_DT_ENDPOINT_SIZE,
117	.bDescriptorType =	USB_DT_ENDPOINT,
118
119	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
120	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
121	.wMaxPacketSize =	cpu_to_le16(1024),
122};
123EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_desc);
124
125struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
126	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
127	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
128
129	/*.bMaxBurst =		DYNAMIC, */
130};
131EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_comp_desc);
132
133struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
134	.bLength =		USB_DT_ENDPOINT_SIZE,
135	.bDescriptorType =	USB_DT_ENDPOINT,
136
137	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
138	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
139	.wMaxPacketSize =	cpu_to_le16(1024),
140};
141EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_desc);
142
143struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
144	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
145	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
146
147	/*.bMaxBurst =		DYNAMIC, */
148};
149EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_comp_desc);
150
151struct usb_descriptor_header *fsg_ss_function[] = {
152	(struct usb_descriptor_header *) &fsg_intf_desc,
153	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
154	(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
155	(struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,
156	(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
157	NULL,
158};
159EXPORT_SYMBOL_GPL(fsg_ss_function);
160
161
162 /*-------------------------------------------------------------------------*/
163
164/*
165 * If the next two routines are called while the gadget is registered,
166 * the caller must own fsg->filesem for writing.
167 */
168
169void fsg_lun_close(struct fsg_lun *curlun)
170{
171	if (curlun->filp) {
172		LDBG(curlun, "close backing file\n");
173		fput(curlun->filp);
174		curlun->filp = NULL;
175	}
176}
177EXPORT_SYMBOL_GPL(fsg_lun_close);
178
179int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
180{
181	int				ro;
182	struct file			*filp = NULL;
183	int				rc = -EINVAL;
184	struct inode			*inode = NULL;
185	loff_t				size;
186	loff_t				num_sectors;
187	loff_t				min_sectors;
188	unsigned int			blkbits;
189	unsigned int			blksize;
190
191	/* R/W if we can, R/O if we must */
192	ro = curlun->initially_ro;
193	if (!ro) {
194		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
195		if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES)
196			ro = 1;
197	}
198	if (ro)
199		filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
200	if (IS_ERR(filp)) {
201		LINFO(curlun, "unable to open backing file: %s\n", filename);
202		return PTR_ERR(filp);
203	}
204
205	if (!(filp->f_mode & FMODE_WRITE))
206		ro = 1;
207
208	inode = filp->f_mapping->host;
209	if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {
210		LINFO(curlun, "invalid file type: %s\n", filename);
211		goto out;
212	}
213
214	/*
215	 * If we can't read the file, it's no good.
216	 * If we can't write the file, use it read-only.
217	 */
218	if (!(filp->f_mode & FMODE_CAN_READ)) {
219		LINFO(curlun, "file not readable: %s\n", filename);
220		goto out;
221	}
222	if (!(filp->f_mode & FMODE_CAN_WRITE))
223		ro = 1;
224
225	size = i_size_read(inode);
226	if (size < 0) {
227		LINFO(curlun, "unable to find file size: %s\n", filename);
228		rc = (int) size;
229		goto out;
230	}
231
232	if (curlun->cdrom) {
233		blksize = 2048;
234		blkbits = 11;
235	} else if (S_ISBLK(inode->i_mode)) {
236		blksize = bdev_logical_block_size(I_BDEV(inode));
237		blkbits = blksize_bits(blksize);
238	} else {
239		blksize = 512;
240		blkbits = 9;
241	}
242
243	num_sectors = size >> blkbits; /* File size in logic-block-size blocks */
244	min_sectors = 1;
245	if (curlun->cdrom) {
246		min_sectors = 300;	/* Smallest track is 300 frames */
247		if (num_sectors >= 256*60*75) {
248			num_sectors = 256*60*75 - 1;
249			LINFO(curlun, "file too big: %s\n", filename);
250			LINFO(curlun, "using only first %d blocks\n",
251					(int) num_sectors);
252		}
253	}
254	if (num_sectors < min_sectors) {
255		LINFO(curlun, "file too small: %s\n", filename);
256		rc = -ETOOSMALL;
257		goto out;
258	}
259
260	if (fsg_lun_is_open(curlun))
261		fsg_lun_close(curlun);
262
263	curlun->blksize = blksize;
264	curlun->blkbits = blkbits;
265	curlun->ro = ro;
266	curlun->filp = filp;
267	curlun->file_length = size;
268	curlun->num_sectors = num_sectors;
269	LDBG(curlun, "open backing file: %s\n", filename);
270	return 0;
271
272out:
273	fput(filp);
274	return rc;
275}
276EXPORT_SYMBOL_GPL(fsg_lun_open);
277
278
279/*-------------------------------------------------------------------------*/
280
281/*
282 * Sync the file data, don't bother with the metadata.
283 * This code was copied from fs/buffer.c:sys_fdatasync().
284 */
285int fsg_lun_fsync_sub(struct fsg_lun *curlun)
286{
287	struct file	*filp = curlun->filp;
288
289	if (curlun->ro || !filp)
290		return 0;
291	return vfs_fsync(filp, 1);
292}
293EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub);
294
295void store_cdrom_address(u8 *dest, int msf, u32 addr)
296{
297	if (msf) {
298		/*
299		 * Convert to Minutes-Seconds-Frames.
300		 * Sector size is already set to 2048 bytes.
301		 */
302		addr += 2*75;		/* Lead-in occupies 2 seconds */
303		dest[3] = addr % 75;	/* Frames */
304		addr /= 75;
305		dest[2] = addr % 60;	/* Seconds */
306		addr /= 60;
307		dest[1] = addr;		/* Minutes */
308		dest[0] = 0;		/* Reserved */
309	} else {
310		/* Absolute sector */
311		put_unaligned_be32(addr, dest);
312	}
313}
314EXPORT_SYMBOL_GPL(store_cdrom_address);
315
316/*-------------------------------------------------------------------------*/
317
318
319ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf)
320{
321	return sprintf(buf, "%d\n", fsg_lun_is_open(curlun)
322				  ? curlun->ro
323				  : curlun->initially_ro);
324}
325EXPORT_SYMBOL_GPL(fsg_show_ro);
326
327ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf)
328{
329	return sprintf(buf, "%u\n", curlun->nofua);
330}
331EXPORT_SYMBOL_GPL(fsg_show_nofua);
332
333ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
334		      char *buf)
335{
336	char		*p;
337	ssize_t		rc;
338
339	down_read(filesem);
340	if (fsg_lun_is_open(curlun)) {	/* Get the complete pathname */
341		p = file_path(curlun->filp, buf, PAGE_SIZE - 1);
342		if (IS_ERR(p))
343			rc = PTR_ERR(p);
344		else {
345			rc = strlen(p);
346			memmove(buf, p, rc);
347			buf[rc] = '\n';		/* Add a newline */
348			buf[++rc] = 0;
349		}
350	} else {				/* No file, return 0 bytes */
351		*buf = 0;
352		rc = 0;
353	}
354	up_read(filesem);
355	return rc;
356}
357EXPORT_SYMBOL_GPL(fsg_show_file);
358
359ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf)
360{
361	return sprintf(buf, "%u\n", curlun->cdrom);
362}
363EXPORT_SYMBOL_GPL(fsg_show_cdrom);
364
365ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf)
366{
367	return sprintf(buf, "%u\n", curlun->removable);
368}
369EXPORT_SYMBOL_GPL(fsg_show_removable);
370
371ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf)
372{
373	return sprintf(buf, "%s\n", curlun->inquiry_string);
374}
375EXPORT_SYMBOL_GPL(fsg_show_inquiry_string);
376
377/*
378 * The caller must hold fsg->filesem for reading when calling this function.
379 */
380static ssize_t _fsg_store_ro(struct fsg_lun *curlun, bool ro)
381{
382	if (fsg_lun_is_open(curlun)) {
383		LDBG(curlun, "read-only status change prevented\n");
384		return -EBUSY;
385	}
386
387	curlun->ro = ro;
388	curlun->initially_ro = ro;
389	LDBG(curlun, "read-only status set to %d\n", curlun->ro);
390
391	return 0;
392}
393
394ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
395		     const char *buf, size_t count)
396{
397	ssize_t		rc;
398	bool		ro;
399
400	rc = kstrtobool(buf, &ro);
401	if (rc)
402		return rc;
403
404	/*
405	 * Allow the write-enable status to change only while the
406	 * backing file is closed.
407	 */
408	down_read(filesem);
409	rc = _fsg_store_ro(curlun, ro);
410	if (!rc)
411		rc = count;
412	up_read(filesem);
413
414	return rc;
415}
416EXPORT_SYMBOL_GPL(fsg_store_ro);
417
418ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
419{
420	bool		nofua;
421	int		ret;
422
423	ret = kstrtobool(buf, &nofua);
424	if (ret)
425		return ret;
426
427	/* Sync data when switching from async mode to sync */
428	if (!nofua && curlun->nofua)
429		fsg_lun_fsync_sub(curlun);
430
431	curlun->nofua = nofua;
432
433	return count;
434}
435EXPORT_SYMBOL_GPL(fsg_store_nofua);
436
437ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
438		       const char *buf, size_t count)
439{
440	int		rc = 0;
441
442	if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
443		LDBG(curlun, "eject attempt prevented\n");
444		return -EBUSY;				/* "Door is locked" */
445	}
446
447	/* Remove a trailing newline */
448	if (count > 0 && buf[count-1] == '\n')
449		((char *) buf)[count-1] = 0;		/* Ugh! */
450
451	/* Load new medium */
452	down_write(filesem);
453	if (count > 0 && buf[0]) {
454		/* fsg_lun_open() will close existing file if any. */
455		rc = fsg_lun_open(curlun, buf);
456		if (rc == 0)
457			curlun->unit_attention_data =
458					SS_NOT_READY_TO_READY_TRANSITION;
459	} else if (fsg_lun_is_open(curlun)) {
460		fsg_lun_close(curlun);
461		curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
462	}
463	up_write(filesem);
464	return (rc < 0 ? rc : count);
465}
466EXPORT_SYMBOL_GPL(fsg_store_file);
467
468ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
469			const char *buf, size_t count)
470{
471	bool		cdrom;
472	int		ret;
473
474	ret = kstrtobool(buf, &cdrom);
475	if (ret)
476		return ret;
477
478	down_read(filesem);
479	ret = cdrom ? _fsg_store_ro(curlun, true) : 0;
480
481	if (!ret) {
482		curlun->cdrom = cdrom;
483		ret = count;
484	}
485	up_read(filesem);
486
487	return ret;
488}
489EXPORT_SYMBOL_GPL(fsg_store_cdrom);
490
491ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
492			    size_t count)
493{
494	bool		removable;
495	int		ret;
496
497	ret = kstrtobool(buf, &removable);
498	if (ret)
499		return ret;
500
501	curlun->removable = removable;
502
503	return count;
504}
505EXPORT_SYMBOL_GPL(fsg_store_removable);
506
507ssize_t fsg_store_inquiry_string(struct fsg_lun *curlun, const char *buf,
508				 size_t count)
509{
510	const size_t len = min(count, sizeof(curlun->inquiry_string));
511
512	if (len == 0 || buf[0] == '\n') {
513		curlun->inquiry_string[0] = 0;
514	} else {
515		snprintf(curlun->inquiry_string,
516			 sizeof(curlun->inquiry_string), "%-28s", buf);
517		if (curlun->inquiry_string[len-1] == '\n')
518			curlun->inquiry_string[len-1] = ' ';
519	}
520
521	return count;
522}
523EXPORT_SYMBOL_GPL(fsg_store_inquiry_string);
524
525ssize_t fsg_store_forced_eject(struct fsg_lun *curlun, struct rw_semaphore *filesem,
526			       const char *buf, size_t count)
527{
528	int ret;
529
530	/*
531	 * Forcibly detach the backing file from the LUN
532	 * regardless of whether the host has allowed it.
533	 */
534	curlun->prevent_medium_removal = 0;
535	ret = fsg_store_file(curlun, filesem, "", 0);
536	return ret < 0 ? ret : count;
537}
538EXPORT_SYMBOL_GPL(fsg_store_forced_eject);
539
540MODULE_LICENSE("GPL");
541