1 /* 2 * Copyright (c) 2019-2025, 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, or -1 on error. 166 ******************************************************************************/ 167 int buf_to_channel(chan_t *channel, void *dst, void *src, size_t nbytes, long len) 168 { 169 const char *addr = src; 170 171 if ((channel == NULL) || (dst == NULL) || (src == NULL)) { 172 return -1; 173 } 174 175 if (channel->offset >= len) { 176 return -1; 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 if (c->index == NODEV) { 337 return NULL; 338 } 339 340 return devtab[c->index]->clone(c, nc); 341 } 342 343 /******************************************************************************* 344 * This function is the default implementation of the driver clone function. 345 * It creates a new channel and returns a pointer to it. 346 * It clones channel into new_channel. 347 ******************************************************************************/ 348 chan_t *devclone(chan_t *channel, chan_t *new_channel) 349 { 350 if (channel == NULL) { 351 return NULL; 352 } 353 354 if (new_channel == NULL) { 355 new_channel = create_new_channel(channel->index); 356 if (new_channel == NULL) { 357 return NULL; 358 } 359 } 360 361 new_channel->qid = channel->qid; 362 new_channel->dev = channel->dev; 363 new_channel->mode = channel->mode; 364 new_channel->offset = channel->offset; 365 new_channel->index = channel->index; 366 367 return new_channel; 368 } 369 370 /******************************************************************************* 371 * This function is the default implementation of the driver walk function. 372 * It goes through all the elements of tab using the gen function until a match 373 * is found with name. 374 * If a match is found, it copies the qid of the new directory. 375 ******************************************************************************/ 376 int devwalk(chan_t *channel, const char *name, const dirtab_t *tab, 377 int ntab, devgen_t *gen) 378 { 379 int i; 380 dir_t dir; 381 382 if ((channel == NULL) || (name == NULL) || (gen == NULL)) { 383 return -1; 384 } 385 386 if ((name[0] == '.') && (name[1] == '\0')) { 387 return 1; 388 } 389 390 for (i = 0; ; i++) { 391 switch ((*gen)(channel, tab, ntab, i, &dir)) { 392 case 0: 393 /* Intentional fall-through */ 394 case -1: 395 return -1; 396 case 1: 397 if (strncmp(name, dir.name, NAMELEN) != 0) { 398 continue; 399 } 400 channel->qid = dir.qid; 401 return 1; 402 } 403 } 404 } 405 406 /******************************************************************************* 407 * This is a helper function which exposes the content of a directory, element 408 * by element. It is meant to be called until the end of the directory is 409 * reached or an error occurs. 410 * It returns -1 on error, 0 on end of directory and 1 when a new file is found. 411 ******************************************************************************/ 412 int dirread(chan_t *channel, dir_t *dir, const dirtab_t *tab, 413 int ntab, devgen_t *gen) 414 { 415 int i, ret; 416 417 if ((channel == NULL) || (dir == NULL) || (gen == NULL)) { 418 return -1; 419 } 420 421 i = channel->offset/sizeof(dir_t); 422 ret = (*gen)(channel, tab, ntab, i, dir); 423 if (ret == 1) { 424 channel->offset += sizeof(dir_t); 425 } 426 427 return ret; 428 } 429 430 /******************************************************************************* 431 * This function sets the elements of dir. 432 ******************************************************************************/ 433 void make_dir_entry(chan_t *channel, dir_t *dir, 434 const char *name, long length, qid_t qid, unsigned int mode) 435 { 436 if ((channel == NULL) || (dir == NULL) || (name == NULL)) { 437 return; 438 } 439 440 strlcpy(dir->name, name, sizeof(dir->name)); 441 dir->length = length; 442 dir->qid = qid; 443 dir->mode = mode; 444 445 if ((qid & CHDIR) != 0) { 446 dir->mode |= O_DIR; 447 } 448 449 dir->index = channel->index; 450 dir->dev = channel->dev; 451 } 452 453 /******************************************************************************* 454 * This function is the default implementation of the internal driver gen 455 * function. 456 * It copies and formats the information of the nth element of tab into dir. 457 ******************************************************************************/ 458 int devgen(chan_t *channel, const dirtab_t *tab, int ntab, int n, dir_t *dir) 459 { 460 const dirtab_t *dp; 461 462 if ((channel == NULL) || (dir == NULL) || (tab == NULL) || 463 (n >= ntab)) { 464 return 0; 465 } 466 467 dp = &tab[n]; 468 make_dir_entry(channel, dir, dp->name, dp->length, dp->qid, dp->perm); 469 return 1; 470 } 471 472 /******************************************************************************* 473 * This function returns a file descriptor identifying the channel associated to 474 * the given path. 475 ******************************************************************************/ 476 int open(const char *path, int mode) 477 { 478 chan_t *channel; 479 480 if (path == NULL) { 481 return -1; 482 } 483 484 if (is_valid_mode(mode) == false) { 485 return -1; 486 } 487 488 channel = path_to_channel(path, mode); 489 490 return channel_to_fd(channel); 491 } 492 493 /******************************************************************************* 494 * This function closes the channel identified by the file descriptor fd. 495 ******************************************************************************/ 496 int close(int fd) 497 { 498 chan_t *channel; 499 500 channel = fd_to_channel(fd); 501 if (channel == NULL) { 502 return -1; 503 } 504 505 channel_close(channel); 506 return 0; 507 } 508 509 /******************************************************************************* 510 * This function is the default implementation of the driver stat function. 511 * It goes through all the elements of tab using the gen function until a match 512 * is found with file. 513 * If a match is found, dir contains the information file. 514 ******************************************************************************/ 515 int devstat(chan_t *dirc, const char *file, dir_t *dir, 516 const dirtab_t *tab, int ntab, devgen_t *gen) 517 { 518 int i, r = 0; 519 chan_t *c, *mnt; 520 521 if ((dirc == NULL) || (dir == NULL) || (gen == NULL)) { 522 return -1; 523 } 524 525 c = path_to_channel(file, O_STAT); 526 if (c == NULL) { 527 return -1; 528 } 529 530 for (i = 0; ; i++) { 531 switch ((*gen)(dirc, tab, ntab, i, dir)) { 532 case 0: 533 /* Intentional fall-through */ 534 case -1: 535 r = -1; 536 goto leave; 537 case 1: 538 mnt = mount_point_to_channel(dir->index, dir->qid); 539 if (mnt != NULL) { 540 dir->qid = mnt->qid; 541 dir->index = mnt->index; 542 } 543 544 if ((dir->qid != c->qid) || (dir->index != c->index)) { 545 continue; 546 } 547 548 goto leave; 549 } 550 } 551 552 leave: 553 channel_close(c); 554 return r; 555 } 556 557 /******************************************************************************* 558 * This function calls the stat function of the driver associated to the parent 559 * directory of the file in path. 560 * The result is stored in dir. 561 ******************************************************************************/ 562 int stat(const char *path, dir_t *dir) 563 { 564 int r; 565 size_t len; 566 chan_t *channel; 567 char *p, dirname[PATHLEN]; 568 569 if ((path == NULL) || (dir == NULL)) { 570 return -1; 571 } 572 573 len = strlen(path); 574 if ((len + 1) > sizeof(dirname)) { 575 return -1; 576 } 577 578 memcpy(dirname, path, len); 579 for (p = dirname + len; p > dirname; --p) { 580 if (*p != '/') { 581 break; 582 } 583 } 584 585 p = memrchr(dirname, '/', p - dirname); 586 if (p == NULL) { 587 return -1; 588 } 589 590 dirname[p - dirname + 1] = '\0'; 591 592 channel = path_to_channel(dirname, O_STAT); 593 if (channel == NULL) { 594 return -1; 595 } 596 597 r = devtab[channel->index]->stat(channel, path, dir); 598 channel_close(channel); 599 600 return r; 601 } 602 603 /******************************************************************************* 604 * This function calls the read function of the driver associated to fd. 605 * It fills buf with at most n bytes. 606 * It returns the number of bytes that were actually read. 607 ******************************************************************************/ 608 int read(int fd, void *buf, int n) 609 { 610 chan_t *channel; 611 612 if (buf == NULL) { 613 return -1; 614 } 615 616 channel = fd_to_channel(fd); 617 if (channel == NULL) { 618 return -1; 619 } 620 621 if (((channel->qid & CHDIR) != 0) && (n < sizeof(dir_t))) { 622 return -1; 623 } 624 625 return devtab[channel->index]->read(channel, buf, n); 626 } 627 628 /******************************************************************************* 629 * This function calls the write function of the driver associated to fd. 630 * It writes at most n bytes of buf. 631 * It returns the number of bytes that were actually written. 632 ******************************************************************************/ 633 int write(int fd, void *buf, int n) 634 { 635 chan_t *channel; 636 637 if (buf == NULL) { 638 return -1; 639 } 640 641 channel = fd_to_channel(fd); 642 if (channel == NULL) { 643 return -1; 644 } 645 646 if ((channel->qid & CHDIR) != 0) { 647 return -1; 648 } 649 650 return devtab[channel->index]->write(channel, buf, n); 651 } 652 653 /******************************************************************************* 654 * This function calls the seek function of the driver associated to fd. 655 * It applies the offset off according to the strategy whence. 656 ******************************************************************************/ 657 int seek(int fd, long off, int whence) 658 { 659 chan_t *channel; 660 661 channel = fd_to_channel(fd); 662 if (channel == NULL) { 663 return -1; 664 } 665 666 if ((channel->qid & CHDIR) != 0) { 667 return -1; 668 } 669 670 return devtab[channel->index]->seek(channel, off, whence); 671 } 672 673 /******************************************************************************* 674 * This function is the default error implementation of the driver mount 675 * function. 676 ******************************************************************************/ 677 chan_t *deverrmount(chan_t *channel, const char *spec) 678 { 679 return NULL; 680 } 681 682 /******************************************************************************* 683 * This function is the default error implementation of the driver write 684 * function. 685 ******************************************************************************/ 686 int deverrwrite(chan_t *channel, void *buf, int n) 687 { 688 return -1; 689 } 690 691 /******************************************************************************* 692 * This function is the default error implementation of the driver seek 693 * function. 694 ******************************************************************************/ 695 int deverrseek(chan_t *channel, long off, int whence) 696 { 697 return -1; 698 } 699 700 /******************************************************************************* 701 * This function is the default implementation of the driver seek function. 702 * It applies the offset off according to the strategy whence to the channel c. 703 ******************************************************************************/ 704 int devseek(chan_t *channel, long off, int whence) 705 { 706 switch (whence) { 707 case KSEEK_SET: 708 channel->offset = off; 709 break; 710 case KSEEK_CUR: 711 channel->offset += off; 712 break; 713 case KSEEK_END: 714 /* Not implemented */ 715 return -1; 716 } 717 718 return 0; 719 } 720 721 /******************************************************************************* 722 * This function registers the channel associated to the path new as a mount 723 * point for the channel c. 724 ******************************************************************************/ 725 static int add_mount_point(chan_t *channel, const char *new) 726 { 727 int i; 728 chan_t *cn; 729 struct mount_point *mp; 730 731 if (new == NULL) { 732 goto err0; 733 } 734 735 cn = path_to_channel(new, O_READ); 736 if (cn == NULL) { 737 goto err0; 738 } 739 740 if ((cn->qid & CHDIR) == 0) { 741 goto err1; 742 } 743 744 for (i = NR_MOUNT_POINTS - 1; i >= 0; i--) { 745 mp = &mount_points[i]; 746 if (mp->new == NULL) { 747 break; 748 } 749 } 750 751 if (i < 0) { 752 goto err1; 753 } 754 755 mp->new = cn; 756 mp->old = channel; 757 758 return 0; 759 760 err1: 761 channel_close(cn); 762 err0: 763 return -1; 764 } 765 766 /******************************************************************************* 767 * This function registers the path new as a mount point for the path old. 768 ******************************************************************************/ 769 int bind(const char *old, const char *new) 770 { 771 chan_t *channel; 772 773 channel = path_to_channel(old, O_BIND); 774 if (channel == NULL) { 775 return -1; 776 } 777 778 if (add_mount_point(channel, new) < 0) { 779 channel_close(channel); 780 return -1; 781 } 782 783 return 0; 784 } 785 786 /******************************************************************************* 787 * This function calls the mount function of the driver associated to the path 788 * srv. 789 * It mounts the path srv on the path where. 790 ******************************************************************************/ 791 int mount(const char *srv, const char *where, const char *spec) 792 { 793 chan_t *channel, *mount_point_chan; 794 int ret; 795 796 channel = path_to_channel(srv, O_RDWR); 797 if (channel == NULL) { 798 goto err0; 799 } 800 801 mount_point_chan = devtab[channel->index]->mount(channel, spec); 802 if (mount_point_chan == NULL) { 803 goto err1; 804 } 805 806 ret = add_mount_point(mount_point_chan, where); 807 if (ret < 0) { 808 goto err2; 809 } 810 811 channel_close(channel); 812 813 return 0; 814 815 err2: 816 channel_close(mount_point_chan); 817 err1: 818 channel_close(channel); 819 err0: 820 return -1; 821 } 822 823 /******************************************************************************* 824 * This function initializes the device environment. 825 * It creates the '/' channel. 826 * It links the device drivers to the physical drivers. 827 ******************************************************************************/ 828 void debugfs_init(void) 829 { 830 chan_t *channel, *cloned_channel; 831 832 for (channel = fdset; channel < &fdset[NR_CHANS]; channel++) { 833 channel_clear(channel); 834 } 835 836 channel = devattach('/', 0); 837 if (channel == NULL) { 838 panic(); 839 } 840 841 cloned_channel = clone(channel, &slash_channel); 842 if (cloned_channel == NULL) { 843 panic(); 844 } 845 846 channel_close(channel); 847 devlink(); 848 } 849 850 __dead2 void devpanic(const char *cause) 851 { 852 panic(); 853 } 854