1 /* 2 * Copyright (c) 2019, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <cdefs.h> 8 #include <common/debug.h> 9 #include <lib/debugfs.h> 10 #include <string.h> 11 12 #include "dev.h" 13 14 #define NR_MOUNT_POINTS 4 15 16 struct mount_point { 17 chan_t *new; 18 chan_t *old; 19 }; 20 21 /* This array contains all the available channels of the filesystem. 22 * A file descriptor is the index of a specific channel in this array. 23 */ 24 static chan_t fdset[NR_CHANS]; 25 26 /* This array contains all the available mount points of the filesystem. */ 27 static struct mount_point mount_points[NR_MOUNT_POINTS]; 28 29 /* This variable stores the channel associated to the root directory. */ 30 static chan_t slash_channel; 31 32 /* This function creates a channel from a device index and registers 33 * it to fdset. 34 */ 35 static chan_t *create_new_channel(unsigned char index) 36 { 37 chan_t *channel = NULL; 38 int i; 39 40 for (i = 0; i < NR_CHANS; i++) { 41 if (fdset[i].index == NODEV) { 42 channel = &fdset[i]; 43 channel->index = index; 44 break; 45 } 46 } 47 48 return channel; 49 } 50 51 /******************************************************************************* 52 * This function returns a pointer to an existing channel in fdset from a file 53 * descriptor. 54 ******************************************************************************/ 55 static chan_t *fd_to_channel(int fd) 56 { 57 if ((fd < 0) || (fd >= NR_CHANS) || (fdset[fd].index == NODEV)) { 58 return NULL; 59 } 60 61 return &fdset[fd]; 62 } 63 64 /******************************************************************************* 65 * This function returns a file descriptor from a channel. 66 * The caller must be sure that the channel is registered in fdset. 67 ******************************************************************************/ 68 static int channel_to_fd(chan_t *channel) 69 { 70 return (channel == NULL) ? -1 : (channel - fdset); 71 } 72 73 /******************************************************************************* 74 * This function checks the validity of a mode. 75 ******************************************************************************/ 76 static bool is_valid_mode(int mode) 77 { 78 if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR))) { 79 return false; 80 } 81 if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR))) { 82 return false; 83 } 84 if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE))) { 85 return false; 86 } 87 88 return true; 89 } 90 91 /******************************************************************************* 92 * This function extracts the next part of the given path contained and puts it 93 * in token. It returns a pointer to the remainder of the path. 94 ******************************************************************************/ 95 static const char *next(const char *path, char *token) 96 { 97 int index; 98 const char *cursor; 99 100 while (*path == '/') { 101 ++path; 102 } 103 104 index = 0; 105 cursor = path; 106 if (*path != '\0') { 107 while (*cursor != '/' && *cursor != '\0') { 108 if (index == NAMELEN) { 109 return NULL; 110 } 111 token[index++] = *cursor++; 112 } 113 } 114 token[index] = '\0'; 115 116 return cursor; 117 } 118 119 /******************************************************************************* 120 * This function returns the driver index in devtab of the driver 121 * identified by id. 122 ******************************************************************************/ 123 static int get_device_index(int id) 124 { 125 int index; 126 dev_t * const *dp; 127 128 for (index = 0, dp = devtab; *dp && (*dp)->id != id; ++dp) { 129 index++; 130 } 131 132 if (*dp == NULL) { 133 return -1; 134 } 135 136 return index; 137 } 138 139 /******************************************************************************* 140 * This function clears a given channel fields 141 ******************************************************************************/ 142 static void channel_clear(chan_t *channel) 143 { 144 channel->offset = 0; 145 channel->qid = 0; 146 channel->index = NODEV; 147 channel->dev = 0; 148 channel->mode = 0; 149 } 150 151 /******************************************************************************* 152 * This function closes the channel pointed to by c. 153 ******************************************************************************/ 154 void channel_close(chan_t *channel) 155 { 156 if (channel != NULL) { 157 channel_clear(channel); 158 } 159 } 160 161 /******************************************************************************* 162 * This function copies data from src to dst after applying the offset of the 163 * channel c. nbytes bytes are expected to be copied unless the data goes over 164 * dst + len. 165 * It returns the actual number of bytes that were copied. 166 ******************************************************************************/ 167 int buf_to_channel(chan_t *channel, void *dst, void *src, int nbytes, long len) 168 { 169 const char *addr = src; 170 171 if ((channel == NULL) || (dst == NULL) || (src == NULL)) { 172 return 0; 173 } 174 175 if (channel->offset >= len) { 176 return 0; 177 } 178 179 if ((channel->offset + nbytes) > len) { 180 nbytes = len - channel->offset; 181 } 182 183 memcpy(dst, addr + channel->offset, nbytes); 184 185 channel->offset += nbytes; 186 187 return nbytes; 188 } 189 190 /******************************************************************************* 191 * This function checks whether a channel (identified by its device index and 192 * qid) is registered as a mount point. 193 * Returns a pointer to the channel it is mounted to when found, NULL otherwise. 194 ******************************************************************************/ 195 static chan_t *mount_point_to_channel(int index, qid_t qid) 196 { 197 chan_t *channel; 198 struct mount_point *mp; 199 200 for (mp = mount_points; mp < &mount_points[NR_MOUNT_POINTS]; mp++) { 201 channel = mp->new; 202 if (channel == NULL) { 203 continue; 204 } 205 206 if ((channel->index == index) && (channel->qid == qid)) { 207 return mp->old; 208 } 209 } 210 211 return NULL; 212 } 213 214 /******************************************************************************* 215 * This function calls the attach function of the driver identified by id. 216 ******************************************************************************/ 217 chan_t *attach(int id, int dev) 218 { 219 /* Get the devtab index for the driver identified by id */ 220 int index = get_device_index(id); 221 222 if (index < 0) { 223 return NULL; 224 } 225 226 return devtab[index]->attach(id, dev); 227 } 228 229 /******************************************************************************* 230 * This function is the default implementation of the driver attach function. 231 * It creates a new channel and returns a pointer to it. 232 ******************************************************************************/ 233 chan_t *devattach(int id, int dev) 234 { 235 chan_t *channel; 236 int index; 237 238 index = get_device_index(id); 239 if (index < 0) { 240 return NULL; 241 } 242 243 channel = create_new_channel(index); 244 if (channel == NULL) { 245 return NULL; 246 } 247 248 channel->dev = dev; 249 channel->qid = CHDIR; 250 251 return channel; 252 } 253 254 /******************************************************************************* 255 * This function returns a channel given a path. 256 * It goes through the filesystem, from the root namespace ('/') or from a 257 * device namespace ('#'), switching channel on mount points. 258 ******************************************************************************/ 259 chan_t *path_to_channel(const char *path, int mode) 260 { 261 int i, n; 262 const char *path_next; 263 chan_t *mnt, *channel; 264 char elem[NAMELEN]; 265 266 if (path == NULL) { 267 return NULL; 268 } 269 270 switch (path[0]) { 271 case '/': 272 channel = clone(&slash_channel, NULL); 273 path_next = path; 274 break; 275 case '#': 276 path_next = next(path + 1, elem); 277 if (path_next == NULL) { 278 goto noent; 279 } 280 281 n = 0; 282 for (i = 1; (elem[i] >= '0') && (elem[i] <= '9'); i++) { 283 n += elem[i] - '0'; 284 } 285 286 if (elem[i] != '\0') { 287 goto noent; 288 } 289 290 channel = attach(elem[0], n); 291 break; 292 default: 293 return NULL; 294 } 295 296 if (channel == NULL) { 297 return NULL; 298 } 299 300 for (path_next = next(path_next, elem); *elem; 301 path_next = next(path_next, elem)) { 302 if ((channel->qid & CHDIR) == 0) { 303 goto notfound; 304 } 305 306 if (devtab[channel->index]->walk(channel, elem) < 0) { 307 channel_close(channel); 308 goto notfound; 309 } 310 311 mnt = mount_point_to_channel(channel->index, channel->qid); 312 if (mnt != NULL) { 313 clone(mnt, channel); 314 } 315 } 316 317 if (path_next == NULL) { 318 goto notfound; 319 } 320 321 /* TODO: check mode */ 322 return channel; 323 324 notfound: 325 channel_close(channel); 326 noent: 327 return NULL; 328 } 329 330 /******************************************************************************* 331 * This function calls the clone function of the driver associated to the 332 * channel c. 333 ******************************************************************************/ 334 chan_t *clone(chan_t *c, chan_t *nc) 335 { 336 return devtab[c->index]->clone(c, nc); 337 } 338 339 /******************************************************************************* 340 * This function is the default implementation of the driver clone function. 341 * It creates a new channel and returns a pointer to it. 342 * It clones channel into new_channel. 343 ******************************************************************************/ 344 chan_t *devclone(chan_t *channel, chan_t *new_channel) 345 { 346 if (channel == NULL) { 347 return NULL; 348 } 349 350 if (new_channel == NULL) { 351 new_channel = create_new_channel(channel->index); 352 if (new_channel == NULL) { 353 return NULL; 354 } 355 } 356 357 new_channel->qid = channel->qid; 358 new_channel->dev = channel->dev; 359 new_channel->mode = channel->mode; 360 new_channel->offset = channel->offset; 361 new_channel->index = channel->index; 362 363 return new_channel; 364 } 365 366 /******************************************************************************* 367 * This function is the default implementation of the driver walk function. 368 * It goes through all the elements of tab using the gen function until a match 369 * is found with name. 370 * If a match is found, it copies the qid of the new directory. 371 ******************************************************************************/ 372 int devwalk(chan_t *channel, const char *name, const dirtab_t *tab, 373 int ntab, devgen_t *gen) 374 { 375 int i; 376 dir_t dir; 377 378 if ((channel == NULL) || (name == NULL) || (gen == NULL)) { 379 return -1; 380 } 381 382 if ((name[0] == '.') && (name[1] == '\0')) { 383 return 1; 384 } 385 386 for (i = 0; ; i++) { 387 switch ((*gen)(channel, tab, ntab, i, &dir)) { 388 case 0: 389 /* Intentional fall-through */ 390 case -1: 391 return -1; 392 case 1: 393 if (strncmp(name, dir.name, NAMELEN) != 0) { 394 continue; 395 } 396 channel->qid = dir.qid; 397 return 1; 398 } 399 } 400 } 401 402 /******************************************************************************* 403 * This is a helper function which exposes the content of a directory, element 404 * by element. It is meant to be called until the end of the directory is 405 * reached or an error occurs. 406 * It returns -1 on error, 0 on end of directory and 1 when a new file is found. 407 ******************************************************************************/ 408 int dirread(chan_t *channel, dir_t *dir, const dirtab_t *tab, 409 int ntab, devgen_t *gen) 410 { 411 int i, ret; 412 413 if ((channel == NULL) || (dir == NULL) || (gen == NULL)) { 414 return -1; 415 } 416 417 i = channel->offset/sizeof(dir_t); 418 ret = (*gen)(channel, tab, ntab, i, dir); 419 if (ret == 1) { 420 channel->offset += sizeof(dir_t); 421 } 422 423 return ret; 424 } 425 426 /******************************************************************************* 427 * This function sets the elements of dir. 428 ******************************************************************************/ 429 void make_dir_entry(chan_t *channel, dir_t *dir, 430 const char *name, long length, qid_t qid, unsigned int mode) 431 { 432 if ((channel == NULL) || (dir == NULL) || (name == NULL)) { 433 return; 434 } 435 436 strlcpy(dir->name, name, sizeof(dir->name)); 437 dir->length = length; 438 dir->qid = qid; 439 dir->mode = mode; 440 441 if ((qid & CHDIR) != 0) { 442 dir->mode |= O_DIR; 443 } 444 445 dir->index = channel->index; 446 dir->dev = channel->dev; 447 } 448 449 /******************************************************************************* 450 * This function is the default implementation of the internal driver gen 451 * function. 452 * It copies and formats the information of the nth element of tab into dir. 453 ******************************************************************************/ 454 int devgen(chan_t *channel, const dirtab_t *tab, int ntab, int n, dir_t *dir) 455 { 456 const dirtab_t *dp; 457 458 if ((channel == NULL) || (dir == NULL) || (tab == NULL) || 459 (n >= ntab)) { 460 return 0; 461 } 462 463 dp = &tab[n]; 464 make_dir_entry(channel, dir, dp->name, dp->length, dp->qid, dp->perm); 465 return 1; 466 } 467 468 /******************************************************************************* 469 * This function returns a file descriptor identifying the channel associated to 470 * the given path. 471 ******************************************************************************/ 472 int open(const char *path, int mode) 473 { 474 chan_t *channel; 475 476 if (path == NULL) { 477 return -1; 478 } 479 480 if (is_valid_mode(mode) == false) { 481 return -1; 482 } 483 484 channel = path_to_channel(path, mode); 485 486 return channel_to_fd(channel); 487 } 488 489 /******************************************************************************* 490 * This function closes the channel identified by the file descriptor fd. 491 ******************************************************************************/ 492 int close(int fd) 493 { 494 chan_t *channel; 495 496 channel = fd_to_channel(fd); 497 if (channel == NULL) { 498 return -1; 499 } 500 501 channel_close(channel); 502 return 0; 503 } 504 505 /******************************************************************************* 506 * This function is the default implementation of the driver stat function. 507 * It goes through all the elements of tab using the gen function until a match 508 * is found with file. 509 * If a match is found, dir contains the information file. 510 ******************************************************************************/ 511 int devstat(chan_t *dirc, const char *file, dir_t *dir, 512 const dirtab_t *tab, int ntab, devgen_t *gen) 513 { 514 int i, r = 0; 515 chan_t *c, *mnt; 516 517 if ((dirc == NULL) || (dir == NULL) || (gen == NULL)) { 518 return -1; 519 } 520 521 c = path_to_channel(file, O_STAT); 522 if (c == NULL) { 523 return -1; 524 } 525 526 for (i = 0; ; i++) { 527 switch ((*gen)(dirc, tab, ntab, i, dir)) { 528 case 0: 529 /* Intentional fall-through */ 530 case -1: 531 r = -1; 532 goto leave; 533 case 1: 534 mnt = mount_point_to_channel(dir->index, dir->qid); 535 if (mnt != NULL) { 536 dir->qid = mnt->qid; 537 dir->index = mnt->index; 538 } 539 540 if ((dir->qid != c->qid) || (dir->index != c->index)) { 541 continue; 542 } 543 544 goto leave; 545 } 546 } 547 548 leave: 549 channel_close(c); 550 return r; 551 } 552 553 /******************************************************************************* 554 * This function calls the stat function of the driver associated to the parent 555 * directory of the file in path. 556 * The result is stored in dir. 557 ******************************************************************************/ 558 int stat(const char *path, dir_t *dir) 559 { 560 int r; 561 size_t len; 562 chan_t *channel; 563 char *p, dirname[PATHLEN]; 564 565 if ((path == NULL) || (dir == NULL)) { 566 return -1; 567 } 568 569 len = strlen(path); 570 if ((len + 1) > sizeof(dirname)) { 571 return -1; 572 } 573 574 memcpy(dirname, path, len); 575 for (p = dirname + len; p > dirname; --p) { 576 if (*p != '/') { 577 break; 578 } 579 } 580 581 p = memrchr(dirname, '/', p - dirname); 582 if (p == NULL) { 583 return -1; 584 } 585 586 dirname[p - dirname + 1] = '\0'; 587 588 channel = path_to_channel(dirname, O_STAT); 589 if (channel == NULL) { 590 return -1; 591 } 592 593 r = devtab[channel->index]->stat(channel, path, dir); 594 channel_close(channel); 595 596 return r; 597 } 598 599 /******************************************************************************* 600 * This function calls the read function of the driver associated to fd. 601 * It fills buf with at most n bytes. 602 * It returns the number of bytes that were actually read. 603 ******************************************************************************/ 604 int read(int fd, void *buf, int n) 605 { 606 chan_t *channel; 607 608 if (buf == NULL) { 609 return -1; 610 } 611 612 channel = fd_to_channel(fd); 613 if (channel == NULL) { 614 return -1; 615 } 616 617 if (((channel->qid & CHDIR) != 0) && (n < sizeof(dir_t))) { 618 return -1; 619 } 620 621 return devtab[channel->index]->read(channel, buf, n); 622 } 623 624 /******************************************************************************* 625 * This function calls the write function of the driver associated to fd. 626 * It writes at most n bytes of buf. 627 * It returns the number of bytes that were actually written. 628 ******************************************************************************/ 629 int write(int fd, void *buf, int n) 630 { 631 chan_t *channel; 632 633 if (buf == NULL) { 634 return -1; 635 } 636 637 channel = fd_to_channel(fd); 638 if (channel == NULL) { 639 return -1; 640 } 641 642 if ((channel->qid & CHDIR) != 0) { 643 return -1; 644 } 645 646 return devtab[channel->index]->write(channel, buf, n); 647 } 648 649 /******************************************************************************* 650 * This function calls the seek function of the driver associated to fd. 651 * It applies the offset off according to the strategy whence. 652 ******************************************************************************/ 653 int seek(int fd, long off, int whence) 654 { 655 chan_t *channel; 656 657 channel = fd_to_channel(fd); 658 if (channel == NULL) { 659 return -1; 660 } 661 662 if ((channel->qid & CHDIR) != 0) { 663 return -1; 664 } 665 666 return devtab[channel->index]->seek(channel, off, whence); 667 } 668 669 /******************************************************************************* 670 * This function is the default error implementation of the driver mount 671 * function. 672 ******************************************************************************/ 673 chan_t *deverrmount(chan_t *channel, const char *spec) 674 { 675 return NULL; 676 } 677 678 /******************************************************************************* 679 * This function is the default error implementation of the driver write 680 * function. 681 ******************************************************************************/ 682 int deverrwrite(chan_t *channel, void *buf, int n) 683 { 684 return -1; 685 } 686 687 /******************************************************************************* 688 * This function is the default error implementation of the driver seek 689 * function. 690 ******************************************************************************/ 691 int deverrseek(chan_t *channel, long off, int whence) 692 { 693 return -1; 694 } 695 696 /******************************************************************************* 697 * This function is the default implementation of the driver seek function. 698 * It applies the offset off according to the strategy whence to the channel c. 699 ******************************************************************************/ 700 int devseek(chan_t *channel, long off, int whence) 701 { 702 switch (whence) { 703 case KSEEK_SET: 704 channel->offset = off; 705 break; 706 case KSEEK_CUR: 707 channel->offset += off; 708 break; 709 case KSEEK_END: 710 /* Not implemented */ 711 return -1; 712 } 713 714 return 0; 715 } 716 717 /******************************************************************************* 718 * This function registers the channel associated to the path new as a mount 719 * point for the channel c. 720 ******************************************************************************/ 721 static int add_mount_point(chan_t *channel, const char *new) 722 { 723 int i; 724 chan_t *cn; 725 struct mount_point *mp; 726 727 if (new == NULL) { 728 goto err0; 729 } 730 731 cn = path_to_channel(new, O_READ); 732 if (cn == NULL) { 733 goto err0; 734 } 735 736 if ((cn->qid & CHDIR) == 0) { 737 goto err1; 738 } 739 740 for (i = NR_MOUNT_POINTS - 1; i >= 0; i--) { 741 mp = &mount_points[i]; 742 if (mp->new == NULL) { 743 break; 744 } 745 } 746 747 if (i < 0) { 748 goto err1; 749 } 750 751 mp->new = cn; 752 mp->old = channel; 753 754 return 0; 755 756 err1: 757 channel_close(cn); 758 err0: 759 return -1; 760 } 761 762 /******************************************************************************* 763 * This function registers the path new as a mount point for the path old. 764 ******************************************************************************/ 765 int bind(const char *old, const char *new) 766 { 767 chan_t *channel; 768 769 channel = path_to_channel(old, O_BIND); 770 if (channel == NULL) { 771 return -1; 772 } 773 774 if (add_mount_point(channel, new) < 0) { 775 channel_close(channel); 776 return -1; 777 } 778 779 return 0; 780 } 781 782 /******************************************************************************* 783 * This function calls the mount function of the driver associated to the path 784 * srv. 785 * It mounts the path srv on the path where. 786 ******************************************************************************/ 787 int mount(const char *srv, const char *where, const char *spec) 788 { 789 chan_t *channel, *mount_point_chan; 790 int ret; 791 792 channel = path_to_channel(srv, O_RDWR); 793 if (channel == NULL) { 794 goto err0; 795 } 796 797 mount_point_chan = devtab[channel->index]->mount(channel, spec); 798 if (mount_point_chan == NULL) { 799 goto err1; 800 } 801 802 ret = add_mount_point(mount_point_chan, where); 803 if (ret < 0) { 804 goto err2; 805 } 806 807 channel_close(channel); 808 809 return 0; 810 811 err2: 812 channel_close(mount_point_chan); 813 err1: 814 channel_close(channel); 815 err0: 816 return -1; 817 } 818 819 /******************************************************************************* 820 * This function initializes the device environment. 821 * It creates the '/' channel. 822 * It links the device drivers to the physical drivers. 823 ******************************************************************************/ 824 void debugfs_init(void) 825 { 826 chan_t *channel, *cloned_channel; 827 828 for (channel = fdset; channel < &fdset[NR_CHANS]; channel++) { 829 channel_clear(channel); 830 } 831 832 channel = devattach('/', 0); 833 if (channel == NULL) { 834 panic(); 835 } 836 837 cloned_channel = clone(channel, &slash_channel); 838 if (cloned_channel == NULL) { 839 panic(); 840 } 841 842 channel_close(channel); 843 devlink(); 844 } 845 846 __dead2 void devpanic(const char *cause) 847 { 848 panic(); 849 } 850