1 /* 2 * fat.c 3 * 4 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg 5 * 6 * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6 7 * 2003-03-10 - kharris@nexus-tech.net - ported to uboot 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include <common.h> 13 #include <blk.h> 14 #include <config.h> 15 #include <exports.h> 16 #include <fat.h> 17 #include <fs.h> 18 #include <asm/byteorder.h> 19 #include <part.h> 20 #include <malloc.h> 21 #include <memalign.h> 22 #include <linux/compiler.h> 23 #include <linux/ctype.h> 24 25 #ifdef CONFIG_SUPPORT_VFAT 26 static const int vfat_enabled = 1; 27 #else 28 static const int vfat_enabled = 0; 29 #endif 30 31 /* 32 * Convert a string to lowercase. Converts at most 'len' characters, 33 * 'len' may be larger than the length of 'str' if 'str' is NULL 34 * terminated. 35 */ 36 static void downcase(char *str, size_t len) 37 { 38 while (*str != '\0' && len--) { 39 *str = tolower(*str); 40 str++; 41 } 42 } 43 44 static struct blk_desc *cur_dev; 45 static disk_partition_t cur_part_info; 46 47 #define DOS_BOOT_MAGIC_OFFSET 0x1fe 48 #define DOS_FS_TYPE_OFFSET 0x36 49 #define DOS_FS32_TYPE_OFFSET 0x52 50 51 static int disk_read(__u32 block, __u32 nr_blocks, void *buf) 52 { 53 ulong ret; 54 55 if (!cur_dev) 56 return -1; 57 58 ret = blk_dread(cur_dev, cur_part_info.start + block, nr_blocks, buf); 59 60 if (ret != nr_blocks) 61 return -1; 62 63 return ret; 64 } 65 66 int fat_set_blk_dev(struct blk_desc *dev_desc, disk_partition_t *info) 67 { 68 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz); 69 70 cur_dev = dev_desc; 71 cur_part_info = *info; 72 73 /* Make sure it has a valid FAT header */ 74 if (disk_read(0, 1, buffer) != 1) { 75 cur_dev = NULL; 76 return -1; 77 } 78 79 /* Check if it's actually a DOS volume */ 80 if (memcmp(buffer + DOS_BOOT_MAGIC_OFFSET, "\x55\xAA", 2)) { 81 cur_dev = NULL; 82 return -1; 83 } 84 85 /* Check for FAT12/FAT16/FAT32 filesystem */ 86 if (!memcmp(buffer + DOS_FS_TYPE_OFFSET, "FAT", 3)) 87 return 0; 88 if (!memcmp(buffer + DOS_FS32_TYPE_OFFSET, "FAT32", 5)) 89 return 0; 90 91 cur_dev = NULL; 92 return -1; 93 } 94 95 int fat_register_device(struct blk_desc *dev_desc, int part_no) 96 { 97 disk_partition_t info; 98 99 /* First close any currently found FAT filesystem */ 100 cur_dev = NULL; 101 102 /* Read the partition table, if present */ 103 if (part_get_info(dev_desc, part_no, &info)) { 104 if (part_no != 0) { 105 printf("** Partition %d not valid on device %d **\n", 106 part_no, dev_desc->devnum); 107 return -1; 108 } 109 110 info.start = 0; 111 info.size = dev_desc->lba; 112 info.blksz = dev_desc->blksz; 113 info.name[0] = 0; 114 info.type[0] = 0; 115 info.bootable = 0; 116 #if CONFIG_IS_ENABLED(PARTITION_UUIDS) 117 info.uuid[0] = 0; 118 #endif 119 } 120 121 return fat_set_blk_dev(dev_desc, &info); 122 } 123 124 /* 125 * Extract zero terminated short name from a directory entry. 126 */ 127 static void get_name(dir_entry *dirent, char *s_name) 128 { 129 char *ptr; 130 131 memcpy(s_name, dirent->name, 8); 132 s_name[8] = '\0'; 133 ptr = s_name; 134 while (*ptr && *ptr != ' ') 135 ptr++; 136 if (dirent->lcase & CASE_LOWER_BASE) 137 downcase(s_name, (unsigned)(ptr - s_name)); 138 if (dirent->ext[0] && dirent->ext[0] != ' ') { 139 *ptr++ = '.'; 140 memcpy(ptr, dirent->ext, 3); 141 if (dirent->lcase & CASE_LOWER_EXT) 142 downcase(ptr, 3); 143 ptr[3] = '\0'; 144 while (*ptr && *ptr != ' ') 145 ptr++; 146 } 147 *ptr = '\0'; 148 if (*s_name == DELETED_FLAG) 149 *s_name = '\0'; 150 else if (*s_name == aRING) 151 *s_name = DELETED_FLAG; 152 } 153 154 static int flush_dirty_fat_buffer(fsdata *mydata); 155 #if !defined(CONFIG_FAT_WRITE) 156 /* Stub for read only operation */ 157 int flush_dirty_fat_buffer(fsdata *mydata) 158 { 159 (void)(mydata); 160 return 0; 161 } 162 #endif 163 164 /* 165 * Get the entry at index 'entry' in a FAT (12/16/32) table. 166 * On failure 0x00 is returned. 167 */ 168 static __u32 get_fatent(fsdata *mydata, __u32 entry) 169 { 170 __u32 bufnum; 171 __u32 offset, off8; 172 __u32 ret = 0x00; 173 174 if (CHECK_CLUST(entry, mydata->fatsize)) { 175 printf("Error: Invalid FAT entry: 0x%08x\n", entry); 176 return ret; 177 } 178 179 switch (mydata->fatsize) { 180 case 32: 181 bufnum = entry / FAT32BUFSIZE; 182 offset = entry - bufnum * FAT32BUFSIZE; 183 break; 184 case 16: 185 bufnum = entry / FAT16BUFSIZE; 186 offset = entry - bufnum * FAT16BUFSIZE; 187 break; 188 case 12: 189 bufnum = entry / FAT12BUFSIZE; 190 offset = entry - bufnum * FAT12BUFSIZE; 191 break; 192 193 default: 194 /* Unsupported FAT size */ 195 return ret; 196 } 197 198 debug("FAT%d: entry: 0x%08x = %d, offset: 0x%04x = %d\n", 199 mydata->fatsize, entry, entry, offset, offset); 200 201 /* Read a new block of FAT entries into the cache. */ 202 if (bufnum != mydata->fatbufnum) { 203 __u32 getsize = FATBUFBLOCKS; 204 __u8 *bufptr = mydata->fatbuf; 205 __u32 fatlength = mydata->fatlength; 206 __u32 startblock = bufnum * FATBUFBLOCKS; 207 208 /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */ 209 if (startblock + getsize > fatlength) 210 getsize = fatlength - startblock; 211 212 startblock += mydata->fat_sect; /* Offset from start of disk */ 213 214 /* Write back the fatbuf to the disk */ 215 if (flush_dirty_fat_buffer(mydata) < 0) 216 return -1; 217 218 if (disk_read(startblock, getsize, bufptr) < 0) { 219 debug("Error reading FAT blocks\n"); 220 return ret; 221 } 222 mydata->fatbufnum = bufnum; 223 } 224 225 /* Get the actual entry from the table */ 226 switch (mydata->fatsize) { 227 case 32: 228 ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]); 229 break; 230 case 16: 231 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]); 232 break; 233 case 12: 234 off8 = (offset * 3) / 2; 235 /* fatbut + off8 may be unaligned, read in byte granularity */ 236 ret = mydata->fatbuf[off8] + (mydata->fatbuf[off8 + 1] << 8); 237 238 if (offset & 0x1) 239 ret >>= 4; 240 ret &= 0xfff; 241 } 242 debug("FAT%d: ret: 0x%08x, entry: 0x%08x, offset: 0x%04x\n", 243 mydata->fatsize, ret, entry, offset); 244 245 return ret; 246 } 247 248 /* 249 * Read at most 'size' bytes from the specified cluster into 'buffer'. 250 * Return 0 on success, -1 otherwise. 251 */ 252 static int 253 get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) 254 { 255 __u32 idx = 0; 256 __u32 startsect; 257 int ret; 258 259 if (clustnum > 0) { 260 startsect = clust_to_sect(mydata, clustnum); 261 } else { 262 startsect = mydata->rootdir_sect; 263 } 264 265 debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect); 266 267 if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) { 268 ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); 269 270 printf("FAT: Misaligned buffer address (%p)\n", buffer); 271 272 while (size >= mydata->sect_size) { 273 ret = disk_read(startsect++, 1, tmpbuf); 274 if (ret != 1) { 275 debug("Error reading data (got %d)\n", ret); 276 return -1; 277 } 278 279 memcpy(buffer, tmpbuf, mydata->sect_size); 280 buffer += mydata->sect_size; 281 size -= mydata->sect_size; 282 } 283 } else { 284 idx = size / mydata->sect_size; 285 ret = disk_read(startsect, idx, buffer); 286 if (ret != idx) { 287 debug("Error reading data (got %d)\n", ret); 288 return -1; 289 } 290 startsect += idx; 291 idx *= mydata->sect_size; 292 buffer += idx; 293 size -= idx; 294 } 295 if (size) { 296 ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); 297 298 ret = disk_read(startsect, 1, tmpbuf); 299 if (ret != 1) { 300 debug("Error reading data (got %d)\n", ret); 301 return -1; 302 } 303 304 memcpy(buffer, tmpbuf, size); 305 } 306 307 return 0; 308 } 309 310 /* 311 * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr' 312 * into 'buffer'. 313 * Update the number of bytes read in *gotsize or return -1 on fatal errors. 314 */ 315 __u8 get_contents_vfatname_block[MAX_CLUSTSIZE] 316 __aligned(ARCH_DMA_MINALIGN); 317 318 static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, 319 __u8 *buffer, loff_t maxsize, loff_t *gotsize) 320 { 321 loff_t filesize = FAT2CPU32(dentptr->size); 322 unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; 323 __u32 curclust = START(dentptr); 324 __u32 endclust, newclust; 325 loff_t actsize; 326 327 *gotsize = 0; 328 debug("Filesize: %llu bytes\n", filesize); 329 330 if (pos >= filesize) { 331 debug("Read position past EOF: %llu\n", pos); 332 return 0; 333 } 334 335 if (maxsize > 0 && filesize > pos + maxsize) 336 filesize = pos + maxsize; 337 338 debug("%llu bytes\n", filesize); 339 340 actsize = bytesperclust; 341 342 /* go to cluster at pos */ 343 while (actsize <= pos) { 344 curclust = get_fatent(mydata, curclust); 345 if (CHECK_CLUST(curclust, mydata->fatsize)) { 346 debug("curclust: 0x%x\n", curclust); 347 debug("Invalid FAT entry\n"); 348 return 0; 349 } 350 actsize += bytesperclust; 351 } 352 353 /* actsize > pos */ 354 actsize -= bytesperclust; 355 filesize -= actsize; 356 pos -= actsize; 357 358 /* align to beginning of next cluster if any */ 359 if (pos) { 360 actsize = min(filesize, (loff_t)bytesperclust); 361 if (get_cluster(mydata, curclust, get_contents_vfatname_block, 362 (int)actsize) != 0) { 363 printf("Error reading cluster\n"); 364 return -1; 365 } 366 filesize -= actsize; 367 actsize -= pos; 368 memcpy(buffer, get_contents_vfatname_block + pos, actsize); 369 *gotsize += actsize; 370 if (!filesize) 371 return 0; 372 buffer += actsize; 373 374 curclust = get_fatent(mydata, curclust); 375 if (CHECK_CLUST(curclust, mydata->fatsize)) { 376 debug("curclust: 0x%x\n", curclust); 377 debug("Invalid FAT entry\n"); 378 return 0; 379 } 380 } 381 382 actsize = bytesperclust; 383 endclust = curclust; 384 385 do { 386 /* search for consecutive clusters */ 387 while (actsize < filesize) { 388 newclust = get_fatent(mydata, endclust); 389 if ((newclust - 1) != endclust) 390 goto getit; 391 if (CHECK_CLUST(newclust, mydata->fatsize)) { 392 debug("curclust: 0x%x\n", newclust); 393 debug("Invalid FAT entry\n"); 394 return 0; 395 } 396 endclust = newclust; 397 actsize += bytesperclust; 398 } 399 400 /* get remaining bytes */ 401 actsize = filesize; 402 if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { 403 printf("Error reading cluster\n"); 404 return -1; 405 } 406 *gotsize += actsize; 407 return 0; 408 getit: 409 if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { 410 printf("Error reading cluster\n"); 411 return -1; 412 } 413 *gotsize += (int)actsize; 414 filesize -= actsize; 415 buffer += actsize; 416 417 curclust = get_fatent(mydata, endclust); 418 if (CHECK_CLUST(curclust, mydata->fatsize)) { 419 debug("curclust: 0x%x\n", curclust); 420 printf("Invalid FAT entry\n"); 421 return 0; 422 } 423 actsize = bytesperclust; 424 endclust = curclust; 425 } while (1); 426 } 427 428 /* 429 * Extract the file name information from 'slotptr' into 'l_name', 430 * starting at l_name[*idx]. 431 * Return 1 if terminator (zero byte) is found, 0 otherwise. 432 */ 433 static int slot2str(dir_slot *slotptr, char *l_name, int *idx) 434 { 435 int j; 436 437 for (j = 0; j <= 8; j += 2) { 438 l_name[*idx] = slotptr->name0_4[j]; 439 if (l_name[*idx] == 0x00) 440 return 1; 441 (*idx)++; 442 } 443 for (j = 0; j <= 10; j += 2) { 444 l_name[*idx] = slotptr->name5_10[j]; 445 if (l_name[*idx] == 0x00) 446 return 1; 447 (*idx)++; 448 } 449 for (j = 0; j <= 2; j += 2) { 450 l_name[*idx] = slotptr->name11_12[j]; 451 if (l_name[*idx] == 0x00) 452 return 1; 453 (*idx)++; 454 } 455 456 return 0; 457 } 458 459 /* Calculate short name checksum */ 460 static __u8 mkcksum(const char name[8], const char ext[3]) 461 { 462 int i; 463 464 __u8 ret = 0; 465 466 for (i = 0; i < 8; i++) 467 ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i]; 468 for (i = 0; i < 3; i++) 469 ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i]; 470 471 return ret; 472 } 473 474 /* 475 * TODO these should go away once fat_write is reworked to use the 476 * directory iterator 477 */ 478 __u8 get_dentfromdir_block[MAX_CLUSTSIZE] 479 __aligned(ARCH_DMA_MINALIGN); 480 __u8 do_fat_read_at_block[MAX_CLUSTSIZE] 481 __aligned(ARCH_DMA_MINALIGN); 482 483 /* 484 * Read boot sector and volume info from a FAT filesystem 485 */ 486 static int 487 read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize) 488 { 489 __u8 *block; 490 volume_info *vistart; 491 int ret = 0; 492 493 if (cur_dev == NULL) { 494 debug("Error: no device selected\n"); 495 return -1; 496 } 497 498 block = malloc_cache_aligned(cur_dev->blksz); 499 if (block == NULL) { 500 debug("Error: allocating block\n"); 501 return -1; 502 } 503 504 if (disk_read(0, 1, block) < 0) { 505 debug("Error: reading block\n"); 506 goto fail; 507 } 508 509 memcpy(bs, block, sizeof(boot_sector)); 510 bs->reserved = FAT2CPU16(bs->reserved); 511 bs->fat_length = FAT2CPU16(bs->fat_length); 512 bs->secs_track = FAT2CPU16(bs->secs_track); 513 bs->heads = FAT2CPU16(bs->heads); 514 bs->total_sect = FAT2CPU32(bs->total_sect); 515 516 /* FAT32 entries */ 517 if (bs->fat_length == 0) { 518 /* Assume FAT32 */ 519 bs->fat32_length = FAT2CPU32(bs->fat32_length); 520 bs->flags = FAT2CPU16(bs->flags); 521 bs->root_cluster = FAT2CPU32(bs->root_cluster); 522 bs->info_sector = FAT2CPU16(bs->info_sector); 523 bs->backup_boot = FAT2CPU16(bs->backup_boot); 524 vistart = (volume_info *)(block + sizeof(boot_sector)); 525 *fatsize = 32; 526 } else { 527 vistart = (volume_info *)&(bs->fat32_length); 528 *fatsize = 0; 529 } 530 memcpy(volinfo, vistart, sizeof(volume_info)); 531 532 if (*fatsize == 32) { 533 if (strncmp(FAT32_SIGN, vistart->fs_type, SIGNLEN) == 0) 534 goto exit; 535 } else { 536 if (strncmp(FAT12_SIGN, vistart->fs_type, SIGNLEN) == 0) { 537 *fatsize = 12; 538 goto exit; 539 } 540 if (strncmp(FAT16_SIGN, vistart->fs_type, SIGNLEN) == 0) { 541 *fatsize = 16; 542 goto exit; 543 } 544 } 545 546 debug("Error: broken fs_type sign\n"); 547 fail: 548 ret = -1; 549 exit: 550 free(block); 551 return ret; 552 } 553 554 static int get_fs_info(fsdata *mydata) 555 { 556 boot_sector bs; 557 volume_info volinfo; 558 int ret; 559 560 ret = read_bootsectandvi(&bs, &volinfo, &mydata->fatsize); 561 if (ret) { 562 debug("Error: reading boot sector\n"); 563 return ret; 564 } 565 566 if (mydata->fatsize == 32) { 567 mydata->fatlength = bs.fat32_length; 568 } else { 569 mydata->fatlength = bs.fat_length; 570 } 571 572 mydata->fat_sect = bs.reserved; 573 574 mydata->rootdir_sect = mydata->fat_sect + mydata->fatlength * bs.fats; 575 576 mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0]; 577 mydata->clust_size = bs.cluster_size; 578 if (mydata->sect_size != cur_part_info.blksz) { 579 printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n", 580 mydata->sect_size, cur_part_info.blksz); 581 return -1; 582 } 583 584 if (mydata->fatsize == 32) { 585 mydata->data_begin = mydata->rootdir_sect - 586 (mydata->clust_size * 2); 587 mydata->root_cluster = bs.root_cluster; 588 } else { 589 mydata->rootdir_size = ((bs.dir_entries[1] * (int)256 + 590 bs.dir_entries[0]) * 591 sizeof(dir_entry)) / 592 mydata->sect_size; 593 mydata->data_begin = mydata->rootdir_sect + 594 mydata->rootdir_size - 595 (mydata->clust_size * 2); 596 mydata->root_cluster = 597 sect_to_clust(mydata, mydata->rootdir_sect); 598 } 599 600 mydata->fatbufnum = -1; 601 mydata->fat_dirty = 0; 602 mydata->fatbuf = malloc_cache_aligned(FATBUFSIZE); 603 if (mydata->fatbuf == NULL) { 604 debug("Error: allocating memory\n"); 605 return -1; 606 } 607 608 if (vfat_enabled) 609 debug("VFAT Support enabled\n"); 610 611 debug("FAT%d, fat_sect: %d, fatlength: %d\n", 612 mydata->fatsize, mydata->fat_sect, mydata->fatlength); 613 debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n" 614 "Data begins at: %d\n", 615 mydata->root_cluster, 616 mydata->rootdir_sect, 617 mydata->rootdir_sect * mydata->sect_size, mydata->data_begin); 618 debug("Sector size: %d, cluster size: %d\n", mydata->sect_size, 619 mydata->clust_size); 620 621 return 0; 622 } 623 624 625 /* 626 * Directory iterator, to simplify filesystem traversal 627 * 628 * Implements an iterator pattern to traverse directory tables, 629 * transparently handling directory tables split across multiple 630 * clusters, and the difference between FAT12/FAT16 root directory 631 * (contiguous) and subdirectories + FAT32 root (chained). 632 * 633 * Rough usage: 634 * 635 * for (fat_itr_root(&itr, fsdata); fat_itr_next(&itr); ) { 636 * // to traverse down to a subdirectory pointed to by 637 * // current iterator position: 638 * fat_itr_child(&itr, &itr); 639 * } 640 * 641 * For more complete example, see fat_itr_resolve() 642 */ 643 644 typedef struct { 645 fsdata *fsdata; /* filesystem parameters */ 646 unsigned clust; /* current cluster */ 647 int last_cluster; /* set once we've read last cluster */ 648 int is_root; /* is iterator at root directory */ 649 int remaining; /* remaining dent's in current cluster */ 650 651 /* current iterator position values: */ 652 dir_entry *dent; /* current directory entry */ 653 char l_name[VFAT_MAXLEN_BYTES]; /* long (vfat) name */ 654 char s_name[14]; /* short 8.3 name */ 655 char *name; /* l_name if there is one, else s_name */ 656 657 /* storage for current cluster in memory: */ 658 u8 block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); 659 } fat_itr; 660 661 static int fat_itr_isdir(fat_itr *itr); 662 663 /** 664 * fat_itr_root() - initialize an iterator to start at the root 665 * directory 666 * 667 * @itr: iterator to initialize 668 * @fsdata: filesystem data for the partition 669 * @return 0 on success, else -errno 670 */ 671 static int fat_itr_root(fat_itr *itr, fsdata *fsdata) 672 { 673 if (get_fs_info(fsdata)) 674 return -ENXIO; 675 676 itr->fsdata = fsdata; 677 itr->clust = fsdata->root_cluster; 678 itr->dent = NULL; 679 itr->remaining = 0; 680 itr->last_cluster = 0; 681 itr->is_root = 1; 682 683 return 0; 684 } 685 686 /** 687 * fat_itr_child() - initialize an iterator to descend into a sub- 688 * directory 689 * 690 * Initializes 'itr' to iterate the contents of the directory at 691 * the current cursor position of 'parent'. It is an error to 692 * call this if the current cursor of 'parent' is pointing at a 693 * regular file. 694 * 695 * Note that 'itr' and 'parent' can be the same pointer if you do 696 * not need to preserve 'parent' after this call, which is useful 697 * for traversing directory structure to resolve a file/directory. 698 * 699 * @itr: iterator to initialize 700 * @parent: the iterator pointing at a directory entry in the 701 * parent directory of the directory to iterate 702 */ 703 static void fat_itr_child(fat_itr *itr, fat_itr *parent) 704 { 705 fsdata *mydata = parent->fsdata; /* for silly macros */ 706 unsigned clustnum = START(parent->dent); 707 708 assert(fat_itr_isdir(parent)); 709 710 itr->fsdata = parent->fsdata; 711 if (clustnum > 0) { 712 itr->clust = clustnum; 713 itr->is_root = 0; 714 } else { 715 itr->clust = parent->fsdata->root_cluster; 716 itr->is_root = 1; 717 } 718 itr->dent = NULL; 719 itr->remaining = 0; 720 itr->last_cluster = 0; 721 } 722 723 static void *next_cluster(fat_itr *itr) 724 { 725 fsdata *mydata = itr->fsdata; /* for silly macros */ 726 int ret; 727 u32 sect; 728 729 /* have we reached the end? */ 730 if (itr->last_cluster) 731 return NULL; 732 733 sect = clust_to_sect(itr->fsdata, itr->clust); 734 735 debug("FAT read(sect=%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n", 736 sect, itr->fsdata->clust_size, DIRENTSPERBLOCK); 737 738 /* 739 * NOTE: do_fat_read_at() had complicated logic to deal w/ 740 * vfat names that span multiple clusters in the fat16 case, 741 * which get_dentfromdir() probably also needed (and was 742 * missing). And not entirely sure what fat32 didn't have 743 * the same issue.. We solve that by only caring about one 744 * dent at a time and iteratively constructing the vfat long 745 * name. 746 */ 747 ret = disk_read(sect, itr->fsdata->clust_size, 748 itr->block); 749 if (ret < 0) { 750 debug("Error: reading block\n"); 751 return NULL; 752 } 753 754 if (itr->is_root && itr->fsdata->fatsize != 32) { 755 itr->clust++; 756 sect = clust_to_sect(itr->fsdata, itr->clust); 757 if (sect - itr->fsdata->rootdir_sect >= 758 itr->fsdata->rootdir_size) { 759 debug("cursect: 0x%x\n", itr->clust); 760 itr->last_cluster = 1; 761 } 762 } else { 763 itr->clust = get_fatent(itr->fsdata, itr->clust); 764 if (CHECK_CLUST(itr->clust, itr->fsdata->fatsize)) { 765 debug("cursect: 0x%x\n", itr->clust); 766 itr->last_cluster = 1; 767 } 768 } 769 770 return itr->block; 771 } 772 773 static dir_entry *next_dent(fat_itr *itr) 774 { 775 if (itr->remaining == 0) { 776 struct dir_entry *dent = next_cluster(itr); 777 unsigned nbytes = itr->fsdata->sect_size * 778 itr->fsdata->clust_size; 779 780 /* have we reached the last cluster? */ 781 if (!dent) 782 return NULL; 783 784 itr->remaining = nbytes / sizeof(dir_entry) - 1; 785 itr->dent = dent; 786 } else { 787 itr->remaining--; 788 itr->dent++; 789 } 790 791 /* have we reached the last valid entry? */ 792 if (itr->dent->name[0] == 0) 793 return NULL; 794 795 return itr->dent; 796 } 797 798 static dir_entry *extract_vfat_name(fat_itr *itr) 799 { 800 struct dir_entry *dent = itr->dent; 801 int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK; 802 u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum; 803 int n = 0; 804 805 while (seqn--) { 806 char buf[13]; 807 int idx = 0; 808 809 slot2str((dir_slot *)dent, buf, &idx); 810 811 /* shift accumulated long-name up and copy new part in: */ 812 memmove(itr->l_name + idx, itr->l_name, n); 813 memcpy(itr->l_name, buf, idx); 814 n += idx; 815 816 dent = next_dent(itr); 817 if (!dent) 818 return NULL; 819 } 820 821 itr->l_name[n] = '\0'; 822 823 chksum = mkcksum(dent->name, dent->ext); 824 825 /* checksum mismatch could mean deleted file, etc.. skip it: */ 826 if (chksum != alias_checksum) { 827 debug("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n", 828 chksum, alias_checksum, itr->l_name, dent->name, dent->ext); 829 return NULL; 830 } 831 832 return dent; 833 } 834 835 /** 836 * fat_itr_next() - step to the next entry in a directory 837 * 838 * Must be called once on a new iterator before the cursor is valid. 839 * 840 * @itr: the iterator to iterate 841 * @return boolean, 1 if success or 0 if no more entries in the 842 * current directory 843 */ 844 static int fat_itr_next(fat_itr *itr) 845 { 846 dir_entry *dent; 847 848 itr->name = NULL; 849 850 while (1) { 851 dent = next_dent(itr); 852 if (!dent) 853 return 0; 854 855 if (dent->name[0] == DELETED_FLAG || 856 dent->name[0] == aRING) 857 continue; 858 859 if (dent->attr & ATTR_VOLUME) { 860 if (vfat_enabled && 861 (dent->attr & ATTR_VFAT) == ATTR_VFAT && 862 (dent->name[0] & LAST_LONG_ENTRY_MASK)) { 863 dent = extract_vfat_name(itr); 864 if (!dent) 865 continue; 866 itr->name = itr->l_name; 867 break; 868 } else { 869 /* Volume label or VFAT entry, skip */ 870 continue; 871 } 872 } 873 874 break; 875 } 876 877 get_name(dent, itr->s_name); 878 if (!itr->name) 879 itr->name = itr->s_name; 880 881 return 1; 882 } 883 884 /** 885 * fat_itr_isdir() - is current cursor position pointing to a directory 886 * 887 * @itr: the iterator 888 * @return true if cursor is at a directory 889 */ 890 static int fat_itr_isdir(fat_itr *itr) 891 { 892 return !!(itr->dent->attr & ATTR_DIR); 893 } 894 895 /* 896 * Helpers: 897 */ 898 899 #define TYPE_FILE 0x1 900 #define TYPE_DIR 0x2 901 #define TYPE_ANY (TYPE_FILE | TYPE_DIR) 902 903 /** 904 * fat_itr_resolve() - traverse directory structure to resolve the 905 * requested path. 906 * 907 * Traverse directory structure to the requested path. If the specified 908 * path is to a directory, this will descend into the directory and 909 * leave it iterator at the start of the directory. If the path is to a 910 * file, it will leave the iterator in the parent directory with current 911 * cursor at file's entry in the directory. 912 * 913 * @itr: iterator initialized to root 914 * @path: the requested path 915 * @type: bitmask of allowable file types 916 * @return 0 on success or -errno 917 */ 918 static int fat_itr_resolve(fat_itr *itr, const char *path, unsigned type) 919 { 920 const char *next; 921 922 /* chomp any extra leading slashes: */ 923 while (path[0] && ISDIRDELIM(path[0])) 924 path++; 925 926 /* are we at the end? */ 927 if (strlen(path) == 0) { 928 if (!(type & TYPE_DIR)) 929 return -ENOENT; 930 return 0; 931 } 932 933 /* find length of next path entry: */ 934 next = path; 935 while (next[0] && !ISDIRDELIM(next[0])) 936 next++; 937 938 while (fat_itr_next(itr)) { 939 int match = 0; 940 unsigned n = max(strlen(itr->name), (size_t)(next - path)); 941 942 /* check both long and short name: */ 943 if (!strncasecmp(path, itr->name, n)) 944 match = 1; 945 else if (itr->name != itr->s_name && 946 !strncasecmp(path, itr->s_name, n)) 947 match = 1; 948 949 if (!match) 950 continue; 951 952 if (fat_itr_isdir(itr)) { 953 /* recurse into directory: */ 954 fat_itr_child(itr, itr); 955 return fat_itr_resolve(itr, next, type); 956 } else if (next[0]) { 957 /* 958 * If next is not empty then we have a case 959 * like: /path/to/realfile/nonsense 960 */ 961 debug("bad trailing path: %s\n", next); 962 return -ENOENT; 963 } else if (!(type & TYPE_FILE)) { 964 return -ENOTDIR; 965 } else { 966 return 0; 967 } 968 } 969 970 return -ENOENT; 971 } 972 973 int file_fat_detectfs(void) 974 { 975 boot_sector bs; 976 volume_info volinfo; 977 int fatsize; 978 char vol_label[12]; 979 980 if (cur_dev == NULL) { 981 printf("No current device\n"); 982 return 1; 983 } 984 985 #if defined(CONFIG_IDE) || \ 986 defined(CONFIG_SATA) || \ 987 defined(CONFIG_SCSI) || \ 988 defined(CONFIG_CMD_USB) || \ 989 defined(CONFIG_MMC) 990 printf("Interface: "); 991 switch (cur_dev->if_type) { 992 case IF_TYPE_IDE: 993 printf("IDE"); 994 break; 995 case IF_TYPE_SATA: 996 printf("SATA"); 997 break; 998 case IF_TYPE_SCSI: 999 printf("SCSI"); 1000 break; 1001 case IF_TYPE_ATAPI: 1002 printf("ATAPI"); 1003 break; 1004 case IF_TYPE_USB: 1005 printf("USB"); 1006 break; 1007 case IF_TYPE_DOC: 1008 printf("DOC"); 1009 break; 1010 case IF_TYPE_MMC: 1011 printf("MMC"); 1012 break; 1013 default: 1014 printf("Unknown"); 1015 } 1016 1017 printf("\n Device %d: ", cur_dev->devnum); 1018 dev_print(cur_dev); 1019 #endif 1020 1021 if (read_bootsectandvi(&bs, &volinfo, &fatsize)) { 1022 printf("\nNo valid FAT fs found\n"); 1023 return 1; 1024 } 1025 1026 memcpy(vol_label, volinfo.volume_label, 11); 1027 vol_label[11] = '\0'; 1028 volinfo.fs_type[5] = '\0'; 1029 1030 printf("Filesystem: %s \"%s\"\n", volinfo.fs_type, vol_label); 1031 1032 return 0; 1033 } 1034 1035 int fat_exists(const char *filename) 1036 { 1037 fsdata fsdata; 1038 fat_itr *itr; 1039 int ret; 1040 1041 itr = malloc_cache_aligned(sizeof(fat_itr)); 1042 if (!itr) 1043 return 0; 1044 ret = fat_itr_root(itr, &fsdata); 1045 if (ret) 1046 goto out; 1047 1048 ret = fat_itr_resolve(itr, filename, TYPE_ANY); 1049 free(fsdata.fatbuf); 1050 out: 1051 free(itr); 1052 return ret == 0; 1053 } 1054 1055 int fat_size(const char *filename, loff_t *size) 1056 { 1057 fsdata fsdata; 1058 fat_itr *itr; 1059 int ret; 1060 1061 itr = malloc_cache_aligned(sizeof(fat_itr)); 1062 if (!itr) 1063 return -ENOMEM; 1064 ret = fat_itr_root(itr, &fsdata); 1065 if (ret) 1066 goto out_free_itr; 1067 1068 ret = fat_itr_resolve(itr, filename, TYPE_FILE); 1069 if (ret) { 1070 /* 1071 * Directories don't have size, but fs_size() is not 1072 * expected to fail if passed a directory path: 1073 */ 1074 free(fsdata.fatbuf); 1075 fat_itr_root(itr, &fsdata); 1076 if (!fat_itr_resolve(itr, filename, TYPE_DIR)) { 1077 *size = 0; 1078 ret = 0; 1079 } 1080 goto out_free_both; 1081 } 1082 1083 *size = FAT2CPU32(itr->dent->size); 1084 out_free_both: 1085 free(fsdata.fatbuf); 1086 out_free_itr: 1087 free(itr); 1088 return ret; 1089 } 1090 1091 int file_fat_read_at(const char *filename, loff_t pos, void *buffer, 1092 loff_t maxsize, loff_t *actread) 1093 { 1094 fsdata fsdata; 1095 fat_itr *itr; 1096 int ret; 1097 1098 itr = malloc_cache_aligned(sizeof(fat_itr)); 1099 if (!itr) 1100 return -ENOMEM; 1101 ret = fat_itr_root(itr, &fsdata); 1102 if (ret) 1103 goto out_free_itr; 1104 1105 ret = fat_itr_resolve(itr, filename, TYPE_FILE); 1106 if (ret) 1107 goto out_free_both; 1108 1109 printf("reading %s\n", filename); 1110 ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread); 1111 1112 out_free_both: 1113 free(fsdata.fatbuf); 1114 out_free_itr: 1115 free(itr); 1116 return ret; 1117 } 1118 1119 int file_fat_read(const char *filename, void *buffer, int maxsize) 1120 { 1121 loff_t actread; 1122 int ret; 1123 1124 ret = file_fat_read_at(filename, 0, buffer, maxsize, &actread); 1125 if (ret) 1126 return ret; 1127 else 1128 return actread; 1129 } 1130 1131 int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, 1132 loff_t *actread) 1133 { 1134 int ret; 1135 1136 ret = file_fat_read_at(filename, offset, buf, len, actread); 1137 if (ret) 1138 printf("** Unable to read file %s **\n", filename); 1139 1140 return ret; 1141 } 1142 1143 typedef struct { 1144 struct fs_dir_stream parent; 1145 struct fs_dirent dirent; 1146 fsdata fsdata; 1147 fat_itr itr; 1148 } fat_dir; 1149 1150 int fat_opendir(const char *filename, struct fs_dir_stream **dirsp) 1151 { 1152 fat_dir *dir; 1153 int ret; 1154 1155 dir = malloc_cache_aligned(sizeof(*dir)); 1156 if (!dir) 1157 return -ENOMEM; 1158 memset(dir, 0, sizeof(*dir)); 1159 1160 ret = fat_itr_root(&dir->itr, &dir->fsdata); 1161 if (ret) 1162 goto fail_free_dir; 1163 1164 ret = fat_itr_resolve(&dir->itr, filename, TYPE_DIR); 1165 if (ret) 1166 goto fail_free_both; 1167 1168 *dirsp = (struct fs_dir_stream *)dir; 1169 return 0; 1170 1171 fail_free_both: 1172 free(dir->fsdata.fatbuf); 1173 fail_free_dir: 1174 free(dir); 1175 return ret; 1176 } 1177 1178 int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp) 1179 { 1180 fat_dir *dir = (fat_dir *)dirs; 1181 struct fs_dirent *dent = &dir->dirent; 1182 1183 if (!fat_itr_next(&dir->itr)) 1184 return -ENOENT; 1185 1186 memset(dent, 0, sizeof(*dent)); 1187 strcpy(dent->name, dir->itr.name); 1188 1189 if (fat_itr_isdir(&dir->itr)) { 1190 dent->type = FS_DT_DIR; 1191 } else { 1192 dent->type = FS_DT_REG; 1193 dent->size = FAT2CPU32(dir->itr.dent->size); 1194 } 1195 1196 *dentp = dent; 1197 1198 return 0; 1199 } 1200 1201 void fat_closedir(struct fs_dir_stream *dirs) 1202 { 1203 fat_dir *dir = (fat_dir *)dirs; 1204 free(dir->fsdata.fatbuf); 1205 free(dir); 1206 } 1207 1208 void fat_close(void) 1209 { 1210 } 1211