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