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