blob: b3ed289ff977ead6348dca50dd9f63179ea05601 [file] [log] [blame]
Amit Pundird477f822020-02-07 22:26:08 +05301#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
28static struct rmtfs_mem *rmem;
29static sig_atomic_t sig_int_count;
30
31static bool dbgprintf_enabled;
32static 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
44static 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
54static 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
82respond:
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
102static 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
128respond:
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
148static 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
220respond:
221 dbgprintf("[RMTFS] iovec %d, %sforced => (%d:%d)\n", caller_id, force ? "" : "not ",
222 resp.result.result, resp.result.error);
Amit Pundir53c12872022-10-27 21:55:51 +0530223
224 if (is_write)
225 storage_sync(rmtfd);
226
Amit Pundird477f822020-02-07 22:26:08 +0530227 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
250static 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;
280respond:
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
299static 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
326respond:
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
345static int rmtfs_bye(uint32_t node)
346{
347 dbgprintf("[RMTFS] bye from %d\n", node);
348
349 return 0;
350}
351
352static 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
359static 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
422static int sig_int_count;
423
424static 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 (;;) {
Amit Pundir53c12872022-10-27 21:55:51 +0530452 if (sig_int_count == 1 && !sig_int_handled) {
453 if (rprocfd < 0)
454 break;
455
Amit Pundird477f822020-02-07 22:26:08 +0530456 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
John Stultz26656692020-02-26 23:41:07 +0000492static void sig_int_handler(int signo __unused)
Amit Pundird477f822020-02-07 22:26:08 +0530493{
494 sig_int_count++;
495}
496
497int 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) {
Amit Pundir39f249c2020-02-24 13:23:55 +0530509 /*
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 */
Amit Pundird477f822020-02-07 22:26:08 +0530514 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();
571close_rmtfs_mem:
572 rmtfs_mem_close(rmem);
573
574 return 0;
575}