1 /*
2 * Copyright (c) 2018 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <zephyr/types.h>
9 #include <zephyr/sys/__assert.h>
10 #include <zephyr/sys/util.h>
11 #include <zephyr/init.h>
12 #include <zephyr/storage/disk_access.h>
13 #include <errno.h>
14 #include <zephyr/device.h>
15
16 #define LOG_LEVEL CONFIG_DISK_LOG_LEVEL
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(disk);
19
20 /* list of mounted file systems */
21 static sys_dlist_t disk_access_list = SYS_DLIST_STATIC_INIT(&disk_access_list);
22
23 /* lock to protect storage layer registration */
24 static K_MUTEX_DEFINE(mutex);
25
disk_access_get_di(const char * name)26 struct disk_info *disk_access_get_di(const char *name)
27 {
28 struct disk_info *disk = NULL, *itr;
29 size_t name_len = strlen(name);
30 sys_dnode_t *node;
31
32 k_mutex_lock(&mutex, K_FOREVER);
33 SYS_DLIST_FOR_EACH_NODE(&disk_access_list, node) {
34 itr = CONTAINER_OF(node, struct disk_info, node);
35
36 /*
37 * Move to next node if mount point length is
38 * shorter than longest_match match or if path
39 * name is shorter than the mount point name.
40 */
41 if (strlen(itr->name) != name_len) {
42 continue;
43 }
44
45 /* Check for disk name match */
46 if (strncmp(name, itr->name, name_len) == 0) {
47 disk = itr;
48 break;
49 }
50 }
51 k_mutex_unlock(&mutex);
52
53 return disk;
54 }
55
disk_access_init(const char * pdrv)56 int disk_access_init(const char *pdrv)
57 {
58 struct disk_info *disk = disk_access_get_di(pdrv);
59 int rc = -EINVAL;
60
61 if ((disk != NULL) && (disk->ops != NULL) &&
62 (disk->ops->init != NULL)) {
63 rc = disk->ops->init(disk);
64 }
65
66 return rc;
67 }
68
disk_access_status(const char * pdrv)69 int disk_access_status(const char *pdrv)
70 {
71 struct disk_info *disk = disk_access_get_di(pdrv);
72 int rc = -EINVAL;
73
74 if ((disk != NULL) && (disk->ops != NULL) &&
75 (disk->ops->status != NULL)) {
76 rc = disk->ops->status(disk);
77 }
78
79 return rc;
80 }
81
disk_access_read(const char * pdrv,uint8_t * data_buf,uint32_t start_sector,uint32_t num_sector)82 int disk_access_read(const char *pdrv, uint8_t *data_buf,
83 uint32_t start_sector, uint32_t num_sector)
84 {
85 struct disk_info *disk = disk_access_get_di(pdrv);
86 int rc = -EINVAL;
87
88 if ((disk != NULL) && (disk->ops != NULL) &&
89 (disk->ops->read != NULL)) {
90 rc = disk->ops->read(disk, data_buf, start_sector, num_sector);
91 }
92
93 return rc;
94 }
95
disk_access_write(const char * pdrv,const uint8_t * data_buf,uint32_t start_sector,uint32_t num_sector)96 int disk_access_write(const char *pdrv, const uint8_t *data_buf,
97 uint32_t start_sector, uint32_t num_sector)
98 {
99 struct disk_info *disk = disk_access_get_di(pdrv);
100 int rc = -EINVAL;
101
102 if ((disk != NULL) && (disk->ops != NULL) &&
103 (disk->ops->write != NULL)) {
104 rc = disk->ops->write(disk, data_buf, start_sector, num_sector);
105 }
106
107 return rc;
108 }
109
disk_access_ioctl(const char * pdrv,uint8_t cmd,void * buf)110 int disk_access_ioctl(const char *pdrv, uint8_t cmd, void *buf)
111 {
112 struct disk_info *disk = disk_access_get_di(pdrv);
113 int rc = -EINVAL;
114
115 if ((disk != NULL) && (disk->ops != NULL) &&
116 (disk->ops->ioctl != NULL)) {
117 rc = disk->ops->ioctl(disk, cmd, buf);
118 }
119
120 return rc;
121 }
122
disk_access_register(struct disk_info * disk)123 int disk_access_register(struct disk_info *disk)
124 {
125 int rc = 0;
126
127 k_mutex_lock(&mutex, K_FOREVER);
128 if ((disk == NULL) || (disk->name == NULL)) {
129 LOG_ERR("invalid disk interface!!");
130 rc = -EINVAL;
131 goto reg_err;
132 }
133
134 if (disk_access_get_di(disk->name) != NULL) {
135 LOG_ERR("disk interface already registered!!");
136 rc = -EINVAL;
137 goto reg_err;
138 }
139
140 /* append to the disk list */
141 sys_dlist_append(&disk_access_list, &disk->node);
142 LOG_DBG("disk interface(%s) registered", disk->name);
143 reg_err:
144 k_mutex_unlock(&mutex);
145 return rc;
146 }
147
disk_access_unregister(struct disk_info * disk)148 int disk_access_unregister(struct disk_info *disk)
149 {
150 int rc = 0;
151
152 k_mutex_lock(&mutex, K_FOREVER);
153 if ((disk == NULL) || (disk->name == NULL)) {
154 LOG_ERR("invalid disk interface!!");
155 rc = -EINVAL;
156 goto unreg_err;
157 }
158
159 if (disk_access_get_di(disk->name) == NULL) {
160 LOG_ERR("disk interface not registered!!");
161 rc = -EINVAL;
162 goto unreg_err;
163 }
164 /* remove disk node from the list */
165 sys_dlist_remove(&disk->node);
166 LOG_DBG("disk interface(%s) unregistered", disk->name);
167 unreg_err:
168 k_mutex_unlock(&mutex);
169 return rc;
170 }
171