1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved.
3 * Description: LiteOS USB Driver Device Mass Protocol About Memory Media.
4 * Author: huangjieliang
5 * Create: 2019-11-26
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * --------------------------------------------------------------------------- */
28 /* ----------------------------------------------------------------------------
29 * Notice of Export Control Law
30 * ===============================================
31 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34 * applicable export control laws and regulations.
35 * --------------------------------------------------------------------------- */
36
37 #include <disk.h>
38 #include <driver.h>
39 #include "gadget/f_mass_storage_ram.h"
40 #include "user_copy.h"
41
42 #ifdef __cplusplus
43 #if __cplusplus
44 extern "C" {
45 #endif /* __cplusplus */
46 #endif /* __cplusplus */
47
48 #define SECTOR_SIZE 512
49 #define RAM_DEV_NAME "/dev/uram"
50
51 struct ram_storage_sc
52 {
53 uint8_t *start_addr;
54 uint32_t len;
55 uint32_t sector_size;
56 };
57
ram_open(struct inode * filep)58 static int ram_open(struct inode *filep)
59 {
60 (void)filep;
61 return 0;
62 }
63
ram_close(struct inode * filep)64 static int ram_close(struct inode *filep)
65 {
66 (void)filep;
67 return 0;
68 }
69
ram_read(struct inode * ram_inode,uint8_t * buffer,uint64_t start_sector,uint32_t nsectors)70 static ssize_t ram_read(struct inode *ram_inode, uint8_t *buffer,
71 uint64_t start_sector, uint32_t nsectors)
72 {
73 errno_t status;
74 struct ram_storage_sc *sc = ram_inode->i_private;
75 uint32_t sector_size = sc->sector_size;
76 uint8_t *start_addr = sc->start_addr;
77
78 if (start_sector + nsectors > sc->len / sector_size)
79 {
80 usb_err("start_sector = %llu, nsectors = %u\n", start_sector, nsectors);
81 return -1;
82 }
83
84 status = usbd_copy_to_user(buffer, nsectors * sector_size, start_addr +
85 start_sector * sector_size, nsectors * sector_size);
86 if(status != EOK)
87 {
88 return -1;
89 }
90
91 return (ssize_t)nsectors;
92 }
93
ram_write(struct inode * ram_inode,const uint8_t * buffer,uint64_t start_sector,uint32_t nsectors)94 static ssize_t ram_write(struct inode *ram_inode, const uint8_t *buffer,
95 uint64_t start_sector, uint32_t nsectors)
96 {
97 errno_t status;
98 struct ram_storage_sc *sc = ram_inode->i_private;
99 uint32_t sector_size = sc->sector_size;
100 uint8_t *start_addr = sc->start_addr;
101
102 if (start_sector + nsectors > sc->len / sector_size)
103 {
104 usb_err("start_sector = %llu, nsectors = %u\n", start_sector, nsectors);
105 return -1;
106 }
107
108 status = usbd_copy_from_user(start_addr + start_sector * sector_size,
109 nsectors * sector_size, buffer, nsectors * sector_size);
110 if(status != EOK)
111 {
112 return -1;
113 }
114
115 return (ssize_t)nsectors;
116 }
117
ram_geometry(struct inode * ram_inode,struct geometry * ram_geometry)118 static int ram_geometry(struct inode *ram_inode, struct geometry *ram_geometry)
119 {
120 struct ram_storage_sc *sc;
121
122 if (ram_geometry == NULL)
123 {
124 return -1;
125 }
126
127 sc = ram_inode->i_private;
128 ram_geometry->geo_nsectors = sc->len / sc->sector_size;
129 ram_geometry->geo_sectorsize = sc->sector_size;
130
131 return 0;
132 }
133
ram_ioctl(struct inode * ram_inode,int cmd,unsigned long arg)134 static int ram_ioctl(struct inode *ram_inode, int cmd, unsigned long arg)
135 {
136 (void)ram_inode;
137 (void)cmd;
138 (void)arg;
139 return 0;
140 }
141
142 const static struct block_operations g_ram_dev_ops =
143 {
144 .open = ram_open,
145 .close = ram_close,
146 .read = ram_read,
147 .write = ram_write,
148 .geometry = ram_geometry,
149 .ioctl = ram_ioctl,
150 .unlink = NULL
151 };
152
ram_mass_storage_init(void)153 int ram_mass_storage_init(void)
154 {
155 void *fat32_part_buf;
156 struct ram_storage_sc *sc;
157 int32_t disk_id;
158 int fd = -1;
159 ssize_t ret;
160
161 sc = malloc(sizeof(struct ram_storage_sc));
162 if (sc == NULL)
163 {
164 return -1;
165 }
166 (void)memset_s(sc, sizeof(struct ram_storage_sc), 0, sizeof(struct ram_storage_sc));
167
168 /* Request a memory block to store the fat32 partition, the length is 2M. */
169
170 fat32_part_buf = memalign(SECTOR_SIZE, FAT_PART_SIZE);
171 if (fat32_part_buf == NULL)
172 {
173 free(sc);
174 return -1;
175 }
176
177 fd = open(FAT_PART_IMAGE_PATH, O_RDONLY, 0);
178 if (fd < 0)
179 {
180 usb_err("open file failed!\n");
181 goto error;
182 }
183
184 /* Copy Fat32 partition from flash to memory */
185
186 ret = read(fd, fat32_part_buf, FAT_PART_SIZE);
187 if (ret != FAT_PART_SIZE)
188 {
189 usb_err("read bytes is too small, ret = %d\n", ret);
190 (void)close(fd);
191 goto error;
192 }
193 (void)close(fd);
194
195 sc->start_addr = (uint8_t *)fat32_part_buf;
196 sc->sector_size = SECTOR_SIZE;
197 sc->len = FAT_PART_SIZE;
198
199 /* Register the fat32 partition device node (/dev/uramp0). */
200
201 disk_id = los_alloc_diskid_byname(RAM_DEV_NAME);
202 OsSetUsbStatus((uint32_t)disk_id);
203 ret = los_disk_init(RAM_DEV_NAME, &g_ram_dev_ops, (void *)sc, disk_id, NULL);
204 if (ret)
205 {
206 usb_err("los_disk_init fail!\n");
207 goto error;
208 }
209
210 return 0;
211 error:
212 free(sc);
213 free(fat32_part_buf);
214 return -1;
215 }
216
ram_mass_storage_deinit(void)217 int ram_mass_storage_deinit(void)
218 {
219 struct ram_storage_sc *sc;
220 struct inode *inode;
221 char *fullpath = NULL;
222 int32_t disk_id;
223 int ret;
224
225 ret = vfs_normalize_path(NULL, RAM_DEV_NAME, &fullpath);
226 if (ret < 0)
227 {
228 return -1;
229 }
230
231 inode = inode_find(fullpath, NULL);
232 if (inode == NULL)
233 {
234 free(fullpath);
235 return -1;
236 }
237 sc = inode->i_private;
238 inode_release(inode);
239 free(fullpath);
240
241 disk_id = los_get_diskid_byname(RAM_DEV_NAME);
242 (void)los_disk_deinit(disk_id);
243 OsClearUsbStatus((uint32_t)disk_id);
244
245 if (sc != NULL)
246 {
247 free(sc->start_addr);
248 sc->start_addr = NULL;
249 free(sc);
250 }
251
252 return 0;
253 }
254
255 #ifdef __cplusplus
256 #if __cplusplus
257 }
258 #endif /* __cplusplus */
259 #endif /* __cplusplus */
260