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 <sys/__assert.h>
10 #include <sys/util.h>
11 #include <init.h>
12 #include <storage/disk_access.h>
13 #include <errno.h>
14 #include <device.h>
15 
16 #define LOG_LEVEL CONFIG_DISK_LOG_LEVEL
17 #include <logging/log.h>
18 LOG_MODULE_REGISTER(disk);
19 
20 /* list of mounted file systems */
21 static sys_dlist_t disk_access_list;
22 
23 /* lock to protect storage layer registration */
24 static struct k_mutex 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) registred", 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) unregistred", disk->name);
167 unreg_err:
168 	k_mutex_unlock(&mutex);
169 	return rc;
170 }
171 
disk_init(const struct device * dev)172 static int disk_init(const struct device *dev)
173 {
174 	ARG_UNUSED(dev);
175 
176 	k_mutex_init(&mutex);
177 	sys_dlist_init(&disk_access_list);
178 	return 0;
179 }
180 
181 SYS_INIT(disk_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
182