1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include "defs.h"
13 #include <errno.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <pthread.h>
17 #include <stdio.h>
18 #include <chcore-internal/fs_defs.h>
19 #include <chcore/ipc.h>
20 #include <chcore/services.h>
21
22 #include "device.h"
23
24 #define UNUSED(x) (void)(x)
25
26 /*
27 * partition informations
28 */
29 static device_partition_t dparts[5];
30
31 /* lock to protect 'dparts' */
32 static pthread_mutex_t dparts_lock = PTHREAD_MUTEX_INITIALIZER;
33
34 /* whether fill the 'dparts' */
35 static bool dparts_inited = false;
36
initialize_dparts(void)37 static void initialize_dparts(void)
38 {
39 memcpy(dparts[0].device_name, "sda1", 5);
40 memcpy(dparts[1].device_name, "sda2", 5);
41 memcpy(dparts[2].device_name, "sda3", 5);
42 memcpy(dparts[3].device_name, "sda4", 5);
43 memcpy(dparts[4].device_name, "sda5", 5);
44 }
45
chcore_parse_devices(void)46 static int chcore_parse_devices(void)
47 {
48 return -1;
49 }
50
51 /*
52 * @arg: 'device_name' is like 'sda1'...etc
53 * @return: device_partition_t* dparts, 0 for any error
54 */
chcore_get_server(const char * device_name)55 device_partition_t *chcore_get_server(const char *device_name)
56 {
57 int i;
58
59 for (i = 0; i < MAX_PARTS_CNT; i++)
60 if (strcmp(dparts[i].device_name, device_name) == 0)
61 return &(dparts[i]);
62
63 printf("[debug %d] can't find server id\n", __LINE__);
64 return 0;
65 }
66
67 /*
68 * @arg: 'fs_cap' is fatfs server_cap, 'partition' is partition_index in device
69 * @return: error code returned by fatfs server
70 */
chcore_initial_fat_partition(cap_t fs_cap,int partition)71 int chcore_initial_fat_partition(cap_t fs_cap, int partition)
72 {
73 int ret;
74 ipc_msg_t *ipc_msg;
75 struct fs_request *fr_ptr;
76 ipc_struct_t *ipc_struct = ipc_register_client(fs_cap);
77 ipc_msg = ipc_create_msg(ipc_struct, sizeof(struct fs_request));
78 fr_ptr = (struct fs_request *)ipc_get_msg_data(ipc_msg);
79
80 fr_ptr->req = FS_REQ_MOUNT;
81 fr_ptr->mount.paritition = partition;
82
83 ipc_set_msg_data(ipc_msg, (char *)fr_ptr, 0, sizeof(struct fs_request));
84 ret = ipc_call(ipc_struct, ipc_msg);
85 ipc_destroy_msg(ipc_msg);
86
87 return ret;
88 }
89
90 /*
91 * Once start a ext4fs server, transform parititon offset to server using
92 * FS_REQ_MOUNT
93 * @arg: 'fs_cap' is ext4fs server_cap, 'partition_lba' is partition offset
94 * @return: error code returned by ext4fs server
95 */
chcore_initial_ext4_partition(int fs_cap,uint64_t partition_lba)96 int chcore_initial_ext4_partition(int fs_cap, uint64_t partition_lba)
97 {
98 int ret;
99 ipc_msg_t *ipc_msg;
100 struct fs_request *fr_ptr;
101 ipc_struct_t *ipc_struct = ipc_register_client(fs_cap);
102 ipc_msg = ipc_create_msg(ipc_struct, sizeof(struct fs_request));
103 fr_ptr = (struct fs_request *)ipc_get_msg_data(ipc_msg);
104
105 fr_ptr->req = FS_REQ_MOUNT;
106 fr_ptr->mount.offset = partition_lba; // Store partition_lba in offset
107
108 ipc_set_msg_data(ipc_msg, (char *)fr_ptr, 0, sizeof(struct fs_request));
109 ret = ipc_call(ipc_struct, ipc_msg);
110 ipc_destroy_msg(ipc_msg);
111
112 return ret;
113 }
114
chcore_initial_littlefs_partition(int fs_cap,uint64_t partition_lba)115 int chcore_initial_littlefs_partition(int fs_cap, uint64_t partition_lba)
116 {
117 return chcore_initial_ext4_partition(fs_cap, partition_lba);
118 }
119
120 /*
121 * @arg: 'device_name' is like 'sda1'.. etc
122 * @return: corresponding fs server cap
123 */
mount_storage_device(const char * device_name)124 int mount_storage_device(const char *device_name)
125 {
126 struct proc_request *proc_req;
127 cap_t fs_server_cap = 0;
128 device_partition_t *fs_server;
129 ipc_msg_t *proc_ipc_msg;
130
131 /*
132 * Refill 'dparts' to refresh partition_information
133 * Write 'dparts' only first call 'chcore_parse_devices'
134 */
135 pthread_mutex_lock(&dparts_lock);
136 if (chcore_parse_devices() < 0) {
137 return -1;
138 }
139 print_devices();
140 pthread_mutex_unlock(&dparts_lock);
141
142 /* get corresponding fs server id */
143 fs_server = chcore_get_server(device_name);
144 if (fs_server == NULL || !fs_server->valid) {
145 errno = EINVAL;
146 return -1;
147 }
148
149 /* prepare structs to IPC call FSM */
150 proc_ipc_msg =
151 ipc_create_msg(procmgr_ipc_struct, sizeof(struct proc_request));
152 proc_req = (struct proc_request *)ipc_get_msg_data(proc_ipc_msg);
153 proc_req->req = PROC_REQ_GET_SERVER_CAP;
154 proc_req->get_server_cap.server_id = fs_server->server_id;
155
156 ipc_call(procmgr_ipc_struct, proc_ipc_msg);
157 fs_server_cap = ipc_get_msg_cap(proc_ipc_msg, 0);
158 ipc_destroy_msg(proc_ipc_msg);
159
160 /* deal with different fs type */
161 if (fs_server->server_id == SERVER_FAT32_FS) {
162 /* FAT type */
163 if (!fs_server->mounted) {
164 chcore_initial_fat_partition(fs_server_cap,
165 fs_server->partition_index);
166 fs_server->mounted = true;
167 }
168 } else if (fs_server->server_id == SERVER_EXT4_FS) {
169 /* EXT4 type */
170 if (!fs_server->mounted) {
171 chcore_initial_ext4_partition(fs_server_cap,
172 fs_server->partition_lba);
173 }
174 } else if (fs_server->server_id == SERVER_LITTLEFS) {
175 /* LITTLEFS type */
176 if (!fs_server->mounted) {
177 chcore_initial_littlefs_partition(fs_server_cap,
178 fs_server->partition_lba);
179 }
180 } else {
181 /* others */
182 printf("[WARNING] Not supported fs type \n");
183 }
184
185 return fs_server_cap;
186 }
187
print_partition(partition_struct_t * p)188 void print_partition(partition_struct_t *p)
189 {
190 printf("partition infomation:\n");
191
192 /* parse boot */
193 if (p->boot == 0x0)
194 printf(" boot: no\n");
195 else if (p->boot == 0x80)
196 printf(" boot: yes\n");
197 else
198 printf(" boot: (unknown)\n");
199
200 /* print fs id */
201 printf(" file system id: 0x%x\n", p->fs_id);
202
203 /* parse fs type */
204 if (p->fs_id == EXT4_PARTITION)
205 printf(" file system: Linux File System\n");
206 else if (p->fs_id == FAT32_PARTITION)
207 printf(" file system: W95 FAT32 (LBA)\n");
208 else if (p->fs_id == 0)
209 printf(" file system: Unused\n");
210 else
211 printf(" file system: (unknown)\n");
212
213 /* parse partition lba */
214 printf(" partition lba: 0x%x = %d\n", p->lba, p->lba);
215
216 /* parse partition size */
217 printf(" partition size: 0x%x = %d\n", p->total_sector, p->total_sector);
218 }
219
print_devices(void)220 void print_devices(void)
221 {
222 /* Now, only support sd device */
223 int i;
224 printf("[SDCARD]\n");
225 printf("Device\tServer\tPartition\tType\n");
226 for (i = 0; i < 5; i++)
227 if (dparts[i].valid)
228 printf("%s\t%d\t%d\t%x\n",
229 dparts[i].device_name,
230 dparts[i].server_id,
231 dparts[i].partition_index,
232 dparts[i].partition_type);
233 }
234