1 #include <sys/mman.h>
2 #include <sys/socket.h>
3 #include <sys/types.h>
4 #include <ctype.h>
5 #include <dirent.h>
6 #include <err.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <libqrtr.h>
10 #include <limits.h>
11 #include <signal.h>
12 #include <stdarg.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 
20 #include "qmi_rmtfs.h"
21 #include "util.h"
22 #include "rmtfs.h"
23 
24 #define RMTFS_QMI_SERVICE	14
25 #define RMTFS_QMI_VERSION	1
26 #define RMTFS_QMI_INSTANCE	0
27 
28 static struct rmtfs_mem *rmem;
29 static sig_atomic_t sig_int_count;
30 
31 static bool dbgprintf_enabled;
dbgprintf(const char * fmt,...)32 static void dbgprintf(const char *fmt, ...)
33 {
34 	va_list ap;
35 
36 	if (!dbgprintf_enabled)
37 		return;
38 
39 	va_start(ap, fmt);
40 	vprintf(fmt, ap);
41 	va_end(ap);
42 }
43 
qmi_result_error(struct rmtfs_qmi_result * result,unsigned error)44 static void qmi_result_error(struct rmtfs_qmi_result *result, unsigned error)
45 {
46 	/* Only propagate initial error */
47 	if (result->result == QMI_RMTFS_RESULT_FAILURE)
48 		return;
49 
50 	result->result = QMI_RMTFS_RESULT_FAILURE;
51 	result->error = error;
52 }
53 
rmtfs_open(int sock,const struct qrtr_packet * pkt)54 static void rmtfs_open(int sock, const struct qrtr_packet *pkt)
55 {
56 	struct rmtfs_open_resp resp = {};
57 	struct rmtfs_open_req req = {};
58 	DEFINE_QRTR_PACKET(resp_buf, 256);
59 	struct rmtfd *rmtfd;
60 	unsigned int txn;
61 	ssize_t len;
62 	int caller_id = -1;
63 	int ret;
64 
65 	ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
66 				 QMI_RMTFS_OPEN, rmtfs_open_req_ei);
67 	if (ret < 0) {
68 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
69 		goto respond;
70 	}
71 
72 	rmtfd = storage_open(pkt->node, req.path);
73 	if (!rmtfd) {
74 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
75 		goto respond;
76 	}
77 
78 	caller_id = storage_get_caller_id(rmtfd);
79 	resp.caller_id = caller_id;
80 	resp.caller_id_valid = true;
81 
82 respond:
83 	dbgprintf("[RMTFS] open %s => %d (%d:%d)\n",
84 		  req.path, caller_id, resp.result.result, resp.result.error);
85 
86 	len = qmi_encode_message(&resp_buf,
87 				 QMI_RESPONSE, QMI_RMTFS_OPEN, txn, &resp,
88 				 rmtfs_open_resp_ei);
89 	if (len < 0) {
90 		fprintf(stderr, "[RMTFS] failed to encode open-response: %s\n",
91 			strerror(-len));
92 		return;
93 	}
94 
95 	ret = qrtr_sendto(sock, pkt->node, pkt->port,
96 			  resp_buf.data, resp_buf.data_len);
97 	if (ret < 0)
98 		fprintf(stderr, "[RMTFS] failed to send open-response: %s\n",
99 			strerror(-ret));
100 }
101 
rmtfs_close(int sock,const struct qrtr_packet * pkt)102 static void rmtfs_close(int sock, const struct qrtr_packet *pkt)
103 {
104 	struct rmtfs_close_resp resp = {};
105 	struct rmtfs_close_req req = {};
106 	DEFINE_QRTR_PACKET(resp_buf, 256);
107 	struct rmtfd *rmtfd;
108 	unsigned int txn;
109 	ssize_t len;
110 	int ret;
111 
112 	ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
113 				 QMI_RMTFS_CLOSE, rmtfs_close_req_ei);
114 	if (ret < 0) {
115 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
116 		goto respond;
117 	}
118 
119 	rmtfd = storage_get(pkt->node, req.caller_id);
120 	if (!rmtfd) {
121 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
122 		goto respond;
123 	}
124 
125 	storage_close(rmtfd);
126 	rmtfs_mem_free(rmem);
127 
128 respond:
129 	dbgprintf("[RMTFS] close %s => %d (%d:%d)\n",
130 		  req.caller_id, resp.result.result, resp.result.error);
131 
132 	len = qmi_encode_message(&resp_buf,
133 				 QMI_RESPONSE, QMI_RMTFS_CLOSE, txn, &resp,
134 				 rmtfs_close_resp_ei);
135 	if (len < 0) {
136 		fprintf(stderr, "[RMTFS] failed to encode close-response: %s\n",
137 			strerror(-len));
138 		return;
139 	}
140 
141 	ret = qrtr_sendto(sock, pkt->node, pkt->port,
142 			  resp_buf.data, resp_buf.data_len);
143 	if (ret < 0)
144 		fprintf(stderr, "[RMTFS] failed to send close-response: %s\n",
145 			strerror(-ret));
146 }
147 
rmtfs_iovec(int sock,struct qrtr_packet * pkt)148 static void rmtfs_iovec(int sock, struct qrtr_packet *pkt)
149 {
150 	struct rmtfs_iovec_entry *entries;
151 	struct rmtfs_iovec_resp resp = {};
152 	struct rmtfs_iovec_req req = {};
153 	DEFINE_QRTR_PACKET(resp_buf, 256);
154 	struct rmtfd *rmtfd;
155 	uint32_t caller_id = 0;
156 	size_t num_entries = 0;
157 	off_t sector_base;
158 	uint8_t is_write;
159 	off_t phys_base;
160 	uint8_t force = 0;
161 	unsigned txn;
162 	off_t offset;
163 	ssize_t len;
164 	ssize_t n;
165 	char buf[SECTOR_SIZE];
166 	int ret;
167 	int i;
168 	int j;
169 
170 	ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
171 				 QMI_RMTFS_RW_IOVEC, rmtfs_iovec_req_ei);
172 	if (ret < 0) {
173 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
174 		goto respond;
175 	}
176 
177 	caller_id = req.caller_id;
178 	is_write = req.direction;
179 	entries = req.iovec;
180 	num_entries = req.iovec_len;
181 	force = req.is_force_sync;
182 
183 	rmtfd = storage_get(pkt->node, caller_id);
184 	if (!rmtfd) {
185 		fprintf(stderr, "[RMTFS] iovec request for non-existing caller\n");
186 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
187 		goto respond;
188 	}
189 
190 	for (i = 0; i < num_entries; i++) {
191 		phys_base = entries[i].phys_offset;
192 		sector_base = entries[i].sector_addr * SECTOR_SIZE;
193 		offset = 0;
194 
195 		for (j = 0; j < entries[i].num_sector; j++) {
196 			if (is_write) {
197 				n = rmtfs_mem_read(rmem, phys_base + offset, buf, SECTOR_SIZE);
198 				if (n == SECTOR_SIZE)
199 					n = storage_pwrite(rmtfd, buf, n, sector_base + offset);
200 			} else {
201 				n = storage_pread(rmtfd, buf, SECTOR_SIZE, sector_base + offset);
202 				if (n >= 0) {
203 					if (n < SECTOR_SIZE)
204 						memset(buf + n, 0, SECTOR_SIZE - n);
205 					n = rmtfs_mem_write(rmem, phys_base + offset, buf, SECTOR_SIZE);
206 				}
207 			}
208 
209 			if (n != SECTOR_SIZE) {
210 				fprintf(stderr, "[RMTFS] failed to %s sector %d\n",
211 					is_write ? "write" : "read", entries[i].sector_addr + j);
212 				qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
213 				goto respond;
214 			}
215 
216 			offset += SECTOR_SIZE;
217 		}
218 	}
219 
220 respond:
221 	dbgprintf("[RMTFS] iovec %d, %sforced => (%d:%d)\n", caller_id, force ? "" : "not ",
222 							     resp.result.result, resp.result.error);
223 
224 	if (is_write)
225 		storage_sync(rmtfd);
226 
227 	for (i = 0; i < num_entries; i++) {
228 		dbgprintf("[RMTFS]       %s %d:%d 0x%x\n", is_write ? "write" : "read",
229 							   entries[i].sector_addr,
230 							   entries[i].num_sector,
231 							   entries[i].phys_offset);
232 	}
233 
234 	len = qmi_encode_message(&resp_buf,
235 				 QMI_RESPONSE, QMI_RMTFS_RW_IOVEC, txn, &resp,
236 				 rmtfs_iovec_resp_ei);
237 	if (len < 0) {
238 		fprintf(stderr, "[RMTFS] failed to encode iovec-response: %s\n",
239 			strerror(-len));
240 		return;
241 	}
242 
243 	ret = qrtr_sendto(sock, pkt->node, pkt->port,
244 			  resp_buf.data, resp_buf.data_len);
245 	if (ret < 0)
246 		fprintf(stderr, "[RMTFS] failed to send iovec-response: %s\n",
247 			strerror(-ret));
248 }
249 
rmtfs_alloc_buf(int sock,struct qrtr_packet * pkt)250 static void rmtfs_alloc_buf(int sock, struct qrtr_packet *pkt)
251 {
252 	struct rmtfs_alloc_buf_resp resp = {};
253 	struct rmtfs_alloc_buf_req req = {};
254 	DEFINE_QRTR_PACKET(resp_buf, 256);
255 	uint32_t alloc_size = 0;
256 	uint32_t caller_id = 0;
257 	int64_t address = 0;
258 	unsigned txn;
259 	ssize_t len;
260 	int ret;
261 
262 	ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
263 				 QMI_RMTFS_ALLOC_BUFF, rmtfs_alloc_buf_req_ei);
264 	if (ret < 0) {
265 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
266 		goto respond;
267 	}
268 
269 	caller_id = req.caller_id;
270 	alloc_size = req.buff_size;
271 
272 	address = rmtfs_mem_alloc(rmem, alloc_size);
273 	if (address < 0) {
274 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
275 		goto respond;
276 	}
277 
278 	resp.buff_address = address;
279 	resp.buff_address_valid = true;
280 respond:
281 	dbgprintf("[RMTFS] alloc %d, %d => 0x%lx (%d:%d)\n", caller_id, alloc_size, address, resp.result.result, resp.result.error);
282 
283 	len = qmi_encode_message(&resp_buf,
284 				 QMI_RESPONSE, QMI_RMTFS_ALLOC_BUFF, txn, &resp,
285 				 rmtfs_alloc_buf_resp_ei);
286 	if (len < 0) {
287 		fprintf(stderr, "[RMTFS] failed to encode alloc-buf-response: %s\n",
288 			strerror(-len));
289 		return;
290 	}
291 
292 	ret = qrtr_sendto(sock, pkt->node, pkt->port,
293 			  resp_buf.data, resp_buf.data_len);
294 	if (ret < 0)
295 		fprintf(stderr, "[RMTFS] failed to send alloc-buf-response: %s\n",
296 			strerror(-ret));
297 }
298 
rmtfs_get_dev_error(int sock,struct qrtr_packet * pkt)299 static void rmtfs_get_dev_error(int sock, struct qrtr_packet *pkt)
300 {
301 	struct rmtfs_dev_error_resp resp = {};
302 	struct rmtfs_dev_error_req req = {};
303 	DEFINE_QRTR_PACKET(resp_buf, 256);
304 	struct rmtfd *rmtfd;
305 	unsigned txn;
306 	ssize_t len;
307 	int ret;
308 
309 	ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
310 				 QMI_RMTFS_GET_DEV_ERROR,
311 				 rmtfs_dev_error_req_ei);
312 	if (ret < 0) {
313 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
314 		goto respond;
315 	}
316 
317 	rmtfd = storage_get(pkt->node, req.caller_id);
318 	if (rmtfd) {
319 		qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
320 		goto respond;
321 	}
322 
323 	resp.status = storage_get_error(rmtfd);
324 	resp.status_valid = true;
325 
326 respond:
327 	dbgprintf("[RMTFS] dev_error %d => %d (%d:%d)\n", req.caller_id, resp.status, resp.result.result, resp.result.error);
328 
329 	len = qmi_encode_message(&resp_buf,
330 				 QMI_RESPONSE, QMI_RMTFS_GET_DEV_ERROR, txn,
331 				 &resp, rmtfs_dev_error_resp_ei);
332 	if (len < 0) {
333 		fprintf(stderr, "[RMTFS] failed to encode dev-error-response: %s\n",
334 			strerror(-len));
335 		return;
336 	}
337 
338 	ret = qrtr_sendto(sock, pkt->node, pkt->port,
339 			  resp_buf.data, resp_buf.data_len);
340 	if (ret < 0)
341 		fprintf(stderr, "[RMTFS] failed to send dev-error-response: %s\n",
342 			strerror(-ret));
343 }
344 
rmtfs_bye(uint32_t node)345 static int rmtfs_bye(uint32_t node)
346 {
347 	dbgprintf("[RMTFS] bye from %d\n", node);
348 
349 	return 0;
350 }
351 
rmtfs_del_client(uint32_t node,uint32_t port)352 static int rmtfs_del_client(uint32_t node, uint32_t port)
353 {
354 	dbgprintf("[RMTFS] del_client %d:%d\n", node, port);
355 
356 	return 0;
357 }
358 
handle_rmtfs(int sock)359 static int handle_rmtfs(int sock)
360 {
361 	struct sockaddr_qrtr sq;
362 	struct qrtr_packet pkt;
363 	unsigned int msg_id;
364 	socklen_t sl;
365 	char buf[4096];
366 	int ret;
367 
368 	sl = sizeof(sq);
369 	ret = recvfrom(sock, buf, sizeof(buf), 0, (void *)&sq, &sl);
370 	if (ret < 0) {
371 		ret = -errno;
372 		if (ret != -ENETRESET)
373 			fprintf(stderr, "[RMTFS] recvfrom failed: %d\n", ret);
374 		return ret;
375 	}
376 
377 	dbgprintf("[RMTFS] packet; from: %d:%d\n", sq.sq_node, sq.sq_port);
378 
379 	ret = qrtr_decode(&pkt, buf, ret, &sq);
380 	if (ret < 0) {
381 		fprintf(stderr, "[RMTFS] unable to decode qrtr packet\n");
382 		return ret;
383 	}
384 
385 	switch (pkt.type) {
386 	case QRTR_TYPE_BYE:
387 		return rmtfs_bye(pkt.node);
388 	case QRTR_TYPE_DEL_CLIENT:
389 		return rmtfs_del_client(pkt.node, pkt.port);
390 	case QRTR_TYPE_DATA:
391 		ret = qmi_decode_header(&pkt, &msg_id);
392 		if (ret < 0)
393 			return ret;
394 
395 		switch (msg_id) {
396 		case QMI_RMTFS_OPEN:
397 			rmtfs_open(sock, &pkt);
398 			break;
399 		case QMI_RMTFS_CLOSE:
400 			rmtfs_close(sock, &pkt);
401 			break;
402 		case QMI_RMTFS_RW_IOVEC:
403 			rmtfs_iovec(sock, &pkt);
404 			break;
405 		case QMI_RMTFS_ALLOC_BUFF:
406 			rmtfs_alloc_buf(sock, &pkt);
407 			break;
408 		case QMI_RMTFS_GET_DEV_ERROR:
409 			rmtfs_get_dev_error(sock, &pkt);
410 			break;
411 		default:
412 			fprintf(stderr, "[RMTFS] Unknown request: %d\n", msg_id);
413 			break;
414 		}
415 
416 		return 0;
417 	}
418 
419 	return ret;
420 }
421 
422 static int sig_int_count;
423 
run_rmtfs(int rprocfd)424 static int run_rmtfs(int rprocfd)
425 {
426 	bool sig_int_handled = false;
427 	int rmtfs_fd;
428 	fd_set rfds;
429 	char done;
430 	int nfds;
431 	int ret;
432 
433 	rmtfs_fd = qrtr_open(RMTFS_QMI_SERVICE);
434 	if (rmtfs_fd < 0) {
435 		fprintf(stderr, "failed to create qrtr socket\n");
436 		return rmtfs_fd;
437 	}
438 
439 	dbgprintf("registering services\n");
440 
441 	ret = qrtr_publish(rmtfs_fd, RMTFS_QMI_SERVICE,
442 			   RMTFS_QMI_VERSION, RMTFS_QMI_INSTANCE);
443 	if (ret < 0) {
444 		fprintf(stderr, "failed to publish rmtfs service");
445 		return ret;
446 	}
447 
448 	if (rprocfd >= 0)
449 		rproc_start();
450 
451 	for (;;) {
452 		if (sig_int_count == 1 && !sig_int_handled) {
453 			if (rprocfd < 0)
454 				break;
455 
456 			rproc_stop();
457 			sig_int_handled = true;
458 		} else if (sig_int_count > 1) {
459 			break;
460 		}
461 
462 		FD_ZERO(&rfds);
463 		FD_SET(rmtfs_fd, &rfds);
464 		if (rprocfd >= 0)
465 			FD_SET(rprocfd, &rfds);
466 		nfds = MAX(rmtfs_fd, rprocfd) + 1;
467 
468 		ret = select(nfds, &rfds, NULL, NULL, NULL);
469 		if (ret < 0 && errno != EINTR)
470 			break;
471 		else if (ret < 0 && errno == EINTR)
472 			continue;
473 
474 		if (rprocfd >= 0 && FD_ISSET(rprocfd, &rfds)) {
475 			ret = read(rprocfd, &done, 1);
476 			if (!ret || done == 'Y')
477 				break;
478 		}
479 
480 		if (FD_ISSET(rmtfs_fd, &rfds)) {
481 			ret = handle_rmtfs(rmtfs_fd);
482 			if (ret == -ENETRESET)
483 				break;
484 		}
485 	}
486 
487 	close(rmtfs_fd);
488 
489 	return ret;
490 }
491 
sig_int_handler(int signo __unused)492 static void sig_int_handler(int signo __unused)
493 {
494 	sig_int_count++;
495 }
496 
main(int argc,char ** argv)497 int main(int argc, char **argv)
498 {
499 	struct sigaction action;
500 	bool use_partitions = false;
501 	bool read_only = false;
502 	int rprocfd = -1;
503 	int ret;
504 	int option;
505 	const char *storage_root = NULL;
506 
507 	while ((option = getopt(argc, argv, "o:Prsv")) != -1) {
508 		switch (option) {
509 		/*
510 		 * -o sets the directory where EFS images are stored,
511 		 * or sets the directory from where raw EFS partitions
512 		 * can be picked by-name when used with -P option.
513 		 */
514 		case 'o':
515 			storage_root = optarg;
516 			break;
517 
518 		/* -P to find and use raw EFS partitions */
519 		case 'P':
520 			use_partitions = true;
521 			break;
522 
523 		/* -r to avoid writing to storage */
524 		case 'r':
525 			read_only = true;
526 			break;
527 
528 		/* enable sync for the mss rproc instance */
529 		case 's':
530 			rprocfd = rproc_init();
531 			if (rprocfd < 0) {
532 				fprintf(stderr, "Failed to get rprocfd\n");
533 				return 1;
534 			}
535 
536 			break;
537 
538 		/* -v is for verbose */
539 		case 'v':
540 			dbgprintf_enabled = 1;
541 			break;
542 
543 		case '?':
544 			fprintf(stderr, "Unknown option: -%c\n", option);
545 			return 1;
546 		}
547 	}
548 
549 	sigemptyset(&action.sa_mask);
550 	action.sa_handler = sig_int_handler;
551 	action.sa_flags = 0;
552 
553 	sigaction(SIGINT, &action, NULL);
554 	sigaction(SIGTERM, &action, NULL);
555 
556 	rmem = rmtfs_mem_open();
557 	if (!rmem)
558 		return 1;
559 
560 	ret = storage_init(storage_root, read_only, use_partitions);
561 	if (ret) {
562 		fprintf(stderr, "failed to initialize storage system\n");
563 		goto close_rmtfs_mem;
564 	}
565 
566 	do {
567 		ret = run_rmtfs(rprocfd);
568 	} while (ret == -ENETRESET);
569 
570 	storage_exit();
571 close_rmtfs_mem:
572 	rmtfs_mem_close(rmem);
573 
574 	return 0;
575 }
576