1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
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 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "disk.h"
32 #include "fs/fs.h"
33 #include "hdf_base.h"
34 #include "hdf_log.h"
35 #include "mmc_block.h"
36 #include "mmc_sd.h"
37 #include "sys/ioctl.h"
38 #include "user_copy.h"
39
40 #define HDF_LOG_TAG mmc_block_lite_c
41
42 /* block ioctl */
43 #define MMC_IOC_MAGIC 'm'
44 #define RT_DEVICE_CTRL_BLK_GETGEOME _IOR(MMC_IOC_MAGIC, 1, struct RtDeviceBlkGeometry)
45 #define RT_DEVICE_CARD_STATUS _IOR(MMC_IOC_MAGIC, 2, int)
46 #define RT_DEVICE_CARD_AU_SIZE _IOR(MMC_IOC_MAGIC, 3, unsigned int)
47 #define RT_DEVICE_BLOCK_ERROR_COUNT _IOR(MMC_IOC_MAGIC, 4, int)
48
49 #define RT_BLOCK_SIZE 512
50
51 /**
52 * block device geometry structure
53 */
54 struct RtDeviceBlkGeometry {
55 unsigned long sectorCount; /**< count of sectors */
56 unsigned long bytesPerSector; /**< number of bytes per sector */
57 unsigned long blockSize; /**< number of bytes to erase one block */
58 };
59
60 struct disk_divide_info g_emmcInfo = {.sector_count = 0xffffffff};
61
62 #ifdef LOSCFG_STORAGE_EMMC
StorageBlockGetEmmc(void)63 struct disk_divide_info *StorageBlockGetEmmc(void)
64 {
65 return &g_emmcInfo;
66 }
67 #endif
68
StorageBlockGetEmmcNodeName(void * block)69 char *StorageBlockGetEmmcNodeName(void *block)
70 {
71 struct MmcBlock *mb = (struct MmcBlock *)block;
72
73 if (mb == NULL) {
74 return NULL;
75 }
76 return mb->name;
77 }
78
LiteosBlockOpen(FAR struct Vnode * vnode)79 static int LiteosBlockOpen(FAR struct Vnode *vnode)
80 {
81 (void)vnode;
82 return 0;
83 }
84
LiteosBlockClose(FAR struct Vnode * vnode)85 static int LiteosBlockClose(FAR struct Vnode *vnode)
86 {
87 (void)vnode;
88 return 0;
89 }
90
LiteosBlockRead(FAR struct Vnode * vnode,FAR unsigned char * buf,unsigned long long secStart,unsigned int nSecs)91 static ssize_t LiteosBlockRead(FAR struct Vnode *vnode, FAR unsigned char *buf,
92 unsigned long long secStart, unsigned int nSecs)
93 {
94 size_t max = (size_t)(-1);
95 struct MmcBlock *mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
96
97 if (secStart >= max || nSecs >= max) {
98 return HDF_ERR_INVALID_PARAM;
99 }
100 if (mb == NULL) {
101 HDF_LOGE("%s: mmc block is null", __func__);
102 return HDF_ERR_INVALID_OBJECT;
103 }
104
105 return MmcDeviceRead(mb->mmc, buf, (size_t)secStart, (size_t)nSecs);
106 }
107
LiteosBlockWrite(FAR struct Vnode * vnode,FAR const unsigned char * buf,unsigned long long secStart,unsigned int nSecs)108 static ssize_t LiteosBlockWrite(FAR struct Vnode *vnode, FAR const unsigned char *buf,
109 unsigned long long secStart, unsigned int nSecs)
110 {
111 size_t max = (size_t)(-1);
112 struct MmcBlock *mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
113
114 if (secStart >= max || nSecs >= max) {
115 return HDF_ERR_INVALID_PARAM;
116 }
117 if (mb == NULL) {
118 HDF_LOGE("%s: mmc block is null", __func__);
119 return HDF_ERR_INVALID_OBJECT;
120 }
121
122 return MmcDeviceWrite(mb->mmc, (uint8_t *)buf, (size_t)secStart, (size_t)nSecs);
123 }
124
LiteosBlockGeometry(FAR struct Vnode * vnode,FAR struct geometry * geometry)125 static int LiteosBlockGeometry(FAR struct Vnode *vnode, FAR struct geometry *geometry)
126 {
127 struct MmcBlock *mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
128
129 if (mb == NULL) {
130 return HDF_ERR_INVALID_OBJECT;
131 }
132 if (geometry == NULL) {
133 return HDF_ERR_INVALID_PARAM;
134 }
135 geometry->geo_available = true;
136 geometry->geo_mediachanged = false;
137 geometry->geo_writeenabled = true;
138 geometry->geo_nsectors = mb->capacity; /* MmcDevice sized by sectors */
139 geometry->geo_sectorsize = mb->secSize;
140 return HDF_SUCCESS;
141 }
142
LiteosBlockSaveGeometry(FAR struct Vnode * vnode,unsigned long arg)143 static int32_t LiteosBlockSaveGeometry(FAR struct Vnode *vnode, unsigned long arg)
144 {
145 int32_t ret;
146 struct geometry gm;
147 struct RtDeviceBlkGeometry rtGeo = {0};
148
149 ret = LiteosBlockGeometry(vnode, &gm);
150 if (ret != HDF_SUCCESS) {
151 return ret;
152 }
153 rtGeo.sectorCount = gm.geo_nsectors;
154 rtGeo.bytesPerSector = gm.geo_sectorsize;
155 rtGeo.blockSize = RT_BLOCK_SIZE;
156 ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(struct RtDeviceBlkGeometry),
157 &rtGeo, sizeof(struct RtDeviceBlkGeometry));
158 if (ret != 0) {
159 return HDF_ERR_IO;
160 }
161 return HDF_SUCCESS;
162 }
163
MmcBlockGetAuSize(struct MmcBlock * mb,uint32_t * auSize)164 static int32_t MmcBlockGetAuSize(struct MmcBlock *mb, uint32_t *auSize)
165 {
166 struct MmcDevice *mmc = NULL;
167 struct SdDevice *sd = NULL;
168
169 if (mb == NULL || mb->mmc == NULL) {
170 HDF_LOGE("%s: mmc block or device is null", __func__);
171 return HDF_ERR_INVALID_OBJECT;
172 }
173
174 mmc = (struct MmcDevice *)mb->mmc;
175 if (mmc->type != MMC_DEV_SD) {
176 HDF_LOGE("%s: media is not sd", __func__);
177 return HDF_ERR_NOT_SUPPORT;
178 }
179 sd = (struct SdDevice *)mmc;
180
181 *auSize = sd->reg.ssr.auSize;
182 return HDF_SUCCESS;
183 }
184
LiteosBlockIoctl(FAR struct Vnode * vnode,int cmd,unsigned long arg)185 static int32_t LiteosBlockIoctl(FAR struct Vnode *vnode, int cmd, unsigned long arg)
186 {
187 int32_t ret;
188 int flag, errCnt;
189 unsigned int au;
190 uint32_t auSize;
191 struct MmcBlock *mb = NULL;
192
193 mb = (struct MmcBlock *)((struct drv_data*)vnode->data)->priv;
194
195 switch (cmd) {
196 case RT_DEVICE_CTRL_BLK_GETGEOME:
197 ret = LiteosBlockSaveGeometry(vnode, arg);
198 break;
199 case RT_DEVICE_CARD_STATUS:
200 flag = (MmcDeviceIsPresent(mb->mmc)) ? 1 : 0;
201 ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(int), &flag, sizeof(int));
202 if (ret) {
203 ret = HDF_ERR_IO;
204 }
205 break;
206 case RT_DEVICE_CARD_AU_SIZE:
207 ret = MmcBlockGetAuSize(mb, &auSize);
208 if (ret == HDF_SUCCESS) {
209 au = (unsigned int)auSize;
210 ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(au), &au, sizeof(au));
211 if (ret) {
212 ret = HDF_ERR_IO;
213 }
214 }
215 break;
216 case RT_DEVICE_BLOCK_ERROR_COUNT:
217 errCnt = (int)mb->errCnt;
218 ret = LOS_CopyFromKernel((void *)(uintptr_t)arg, sizeof(int), &errCnt,
219 sizeof(int));
220 if (ret) {
221 ret = HDF_ERR_IO;
222 }
223 break;
224 default:
225 ret = HDF_ERR_NOT_SUPPORT;
226 break;
227 }
228
229 return ret;
230 }
231
232 static struct block_operations g_blockOps = {
233 .open = LiteosBlockOpen,
234 .close = LiteosBlockClose,
235 .read = LiteosBlockRead,
236 .write = LiteosBlockWrite,
237 .geometry = LiteosBlockGeometry,
238 .ioctl = LiteosBlockIoctl,
239 };
240
StorageBlockGetMmcOps(void)241 struct block_operations *StorageBlockGetMmcOps(void)
242 {
243 return &g_blockOps;
244 }
245
246 static struct MmcBlock *g_diskIdTable[SYS_MAX_DISK] = { };
247
MmcBlockOsInit(struct MmcDevice * mmcDevice)248 int32_t MmcBlockOsInit(struct MmcDevice *mmcDevice)
249 {
250 int32_t ret;
251 int32_t diskId;
252 struct disk_divide_info *info = NULL;
253 struct MmcBlock *mb = NULL;
254
255 if (mmcDevice == NULL || mmcDevice->mb == NULL) {
256 return HDF_ERR_INVALID_OBJECT;
257 }
258 mb = mmcDevice->mb;
259
260 if (mb->name[0] == '\0') {
261 HDF_LOGE("%s: mmc block name invalid", __func__);
262 return HDF_ERR_INVALID_OBJECT;
263 }
264
265 diskId = los_alloc_diskid_byname(mb->name);
266 if (!mb->removeable) {
267 info = &g_emmcInfo;
268 info->sector_count = mb->capacity;
269 }
270
271 ret = los_disk_init(mb->name, &g_blockOps, (void *)mb, diskId, info);
272 if (ret != ENOERR) {
273 HDF_LOGE("%s: los_disk_init fail:%d", __func__, ret);
274 return ret;
275 }
276
277 mb->osData = get_disk(diskId);
278 if (mb->osData == NULL) {
279 HDF_LOGE("%s: los_disk_init fail:%d", __func__, ret);
280 return HDF_PLT_ERR_OS_API;
281 }
282
283 if (diskId >= 0 && diskId < SYS_MAX_DISK) {
284 g_diskIdTable[diskId] = mb;
285 }
286
287 return HDF_SUCCESS;
288 }
289
MmcBlockOsUninit(struct MmcDevice * mmcDevice)290 void MmcBlockOsUninit(struct MmcDevice *mmcDevice)
291 {
292 int diskId;
293 struct MmcBlock *mb = NULL;
294
295 if (mmcDevice == NULL || mmcDevice->mb == NULL) {
296 return;
297 }
298 mb = mmcDevice->mb;
299
300 diskId = los_get_diskid_byname(mb->name);
301 (void)los_disk_deinit(diskId);
302
303 if (diskId >= 0 && diskId < SYS_MAX_DISK) {
304 g_diskIdTable[diskId] = NULL;
305 }
306 }
307
MmcBlockFromDiskId(int32_t diskId)308 struct MmcBlock *MmcBlockFromDiskId(int32_t diskId)
309 {
310 if (diskId >= 0 && diskId < SYS_MAX_DISK) {
311 return g_diskIdTable[diskId];
312 }
313 return NULL;
314 }
315
StorageBlockMmcErase(uint32_t diskId,size_t secStart,size_t secNr)316 ssize_t StorageBlockMmcErase(uint32_t diskId, size_t secStart, size_t secNr)
317 {
318 struct MmcBlock *mb = NULL;
319
320 mb = MmcBlockFromDiskId((int32_t)diskId);
321 if (mb == NULL || mb->mmc == NULL) {
322 return HDF_ERR_INVALID_PARAM;
323 }
324 return MmcDeviceErase(mb->mmc, secStart, secNr);
325 }
326