1 /*
2 * Copyright (c) 2015 Steve White
3 * Copyright (c) 2022 Travis Geiselbrecht
4 *
5 * Use of this source code is governed by a MIT-style
6 * license that can be found in the LICENSE file or at
7 * https://opensource.org/licenses/MIT
8 */
9 #pragma once
10
11 #include <lib/bio.h>
12 #include <lib/bcache.h>
13 #include <lib/fs.h>
14 #include <kernel/mutex.h>
15
16 // computed constants about a particular mount
17 struct fat_info {
18 uint32_t bytes_per_sector = 0;
19 uint32_t sectors_per_cluster = 0;
20 uint32_t bytes_per_cluster = 0;
21 uint32_t reserved_sectors = 0;
22 uint32_t fat_bits = 0;
23 uint32_t fat_count = 0;
24 uint32_t sectors_per_fat = 0;
25 uint32_t total_sectors = 0;
26 uint32_t active_fat = 0;
27 uint32_t data_start_sector = 0;
28 uint32_t total_clusters = 0;
29 uint32_t root_cluster = 0;
30 uint32_t root_entries = 0;
31 uint32_t root_start_sector = 0;
32 uint32_t root_dir_sectors = 0;
33 };
34
35 class fat_file;
36 struct dir_entry_location;
37
38 // main fs object representing a mount
39 class fat_fs {
40 public:
41 // mount hook, creates a new fs instance and passes it back in fscookie
42 static status_t mount(bdev_t *dev, fscookie **cookie);
43 static status_t unmount(fscookie *cookie);
44
dev()45 bdev_t *dev() { return dev_; }
bcache()46 bcache_t bcache() { return bcache_; }
info()47 const fat_info &info() const { return info_; }
48
49 // file list apis
50 // must be called with lock held
51 void add_to_file_list(fat_file *file);
52 fat_file *lookup_file(const dir_entry_location &loc);
53
54 // for now keep the lock public
55 Mutex lock;
56
57 private:
58 fat_fs();
59 ~fat_fs();
60
61 bdev_t *dev_ = nullptr;
62 bcache_t bcache_ = nullptr;
63
64 // list of all the open files and directories
65 list_node file_list_ = LIST_INITIAL_VALUE(file_list_);
66
67 // data computed from BPB
68 fat_info info_ {};
69 };
70
71 enum class fat_attribute : uint8_t {
72 read_only = 0x01,
73 hidden = 0x02,
74 system = 0x04,
75 volume_id = 0x08,
76 directory = 0x10,
77 archive = 0x20,
78 lfn = read_only | hidden | system | volume_id,
79 };
80
fat_read32(const void * _buffer,size_t offset)81 inline uint32_t fat_read32(const void *_buffer, size_t offset) {
82 auto *buffer = (const uint8_t *)_buffer;
83
84 return buffer[offset] +
85 (buffer[offset + 1] << 8) +
86 (buffer[offset + 2] << 16) +
87 (buffer[offset + 3] << 24);
88 }
89
fat_read16(const void * _buffer,size_t offset)90 inline uint16_t fat_read16(const void *_buffer, size_t offset) {
91 auto *buffer = (const uint8_t *)_buffer;
92
93 return buffer[offset] +
94 (buffer[offset + 1] << 8);
95 }
96
97 // In fat32, clusters between 0x0fff.fff8 and 0x0fff.ffff are interpreted as
98 // end of file.
99 const uint32_t EOF_CLUSTER_BASE = 0x0ffffff8;
100 const uint32_t EOF_CLUSTER = 0x0fffffff;
101
is_eof_cluster(uint32_t cluster)102 inline bool is_eof_cluster(uint32_t cluster) {
103 return cluster >= EOF_CLUSTER_BASE && cluster <= EOF_CLUSTER;
104 }
105
106 const int DIR_ENTRY_LENGTH = 32;
107 const size_t MAX_FILE_NAME_LEN = 256;
108
109