summaryrefslogtreecommitdiff
path: root/Source/Kernel/FileSystems/FAT/FATFS.class.h
blob: 114622addbb80377cb7543f94af3ad76b9f512ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef DEF_FATFS_CLASS_H
#define DEF_FATFS_CLASS_H

#include <VFS/FileSystem.proto.h>
#include <VFS/Part.ns.h>
#include <VFS/BlockCache.class.h>

struct fat_extBS_32_t {			//Extended boot sector for FAT32
	unsigned int		table_size_32;
	unsigned short		extended_flags;
	unsigned short		fat_version;
	unsigned int		root_cluster;
	unsigned short		fat_info;
	unsigned short		backup_BS_sector;
	unsigned char 		reserved_0[12];
	unsigned char		drive_number;
	unsigned char 		reserved_1;
	unsigned char		boot_signature;
	unsigned int 		volume_id;
	unsigned char		volume_label[11];
	unsigned char		fat_type_label[8];
}__attribute__((packed));

struct fat_extBS_16_t {	//Extended boot sector for FAT12 and FAT16
	unsigned char		bios_drive_num;
	unsigned char		reserved1;
	unsigned char		boot_signature;
	unsigned int		volume_id;
	unsigned char		volume_label[11];
	unsigned char		fat_type_label[8];
}__attribute__((packed));

struct fat_BS_t {		//Boot sector
	unsigned char 		bootjmp[3];
	unsigned char 		oem_name[8];
	unsigned short 	        bytes_per_sector;
	unsigned char		sectors_per_cluster;
	unsigned short		reserved_sector_count;
	unsigned char		table_count;
	unsigned short		root_entry_count;
	unsigned short		total_sectors_16;
	unsigned char		media_type;
	unsigned short		table_size_16;
	unsigned short		sectors_per_track;
	unsigned short		head_side_count;
	unsigned int 		hidden_sector_count;
	unsigned int 		total_sectors_32;
	union {
		fat_extBS_32_t	extBS_32;
		fat_extBS_16_t	extBS_16;
	};
}__attribute__((packed));

struct fat_date_t {
	u16int year		: 7;
	u16int month	: 4;
	u16int day		: 5;
}__attribute__((packed));

struct fat_time_t {
	u16int hour		: 5;
	u16int minutes	: 6;
	u16int seconds	: 5;
}__attribute__((packed));

struct fat_dir_entry_t {
	char name[8];
	char extension[3];
	u8int attributes;
	u8int reserved;
	u8int createtenthsofseconds;
	fat_time_t created_time;
	fat_date_t created_date;
	fat_date_t accessed_date;
	u16int first_clust_high;	//always 0 on FAT12/16
	fat_time_t modified_time;
	fat_date_t modified_date;
	u16int first_clust_low;
	u32int size;
}__attribute__((packed));

#define FA_READONLY 0x01
#define FA_HIDDEN 0x02
#define FA_SYSTEM 0x04
#define FA_VOLUMEID 0x08
#define FA_DIRECTORY 0x10
#define FA_ARCHIVE 0x20
#define FA_LFN 0x0F

class FATFS : public FileSystem {
	private:
	fat_BS_t m_bs;
	bool m_readOnly;
	u32int m_fatSize;	//Size of one FAT, in sectors
	u32int m_totalSectors;	//Total sectors used by the FAT
	u32int m_rootDirSectors;	//Sectors used by the root directory
	u32int m_firstDataSector;	//First data sector, start of cluster 2
	u32int m_countOfClusters;	//Count of usable clusters, EXCLUDING the ones used by the root directory
	u32int m_clusterSize;	//size of a cluster in bytes
	u32int m_fatType;	//12, 16 or 32
	Partition* m_part;
	BlockCache<Partition> m_fatCache;

	u32int nextCluster(u32int cluster);		//Get the next cluster number in the chain (0 = EOF)
	bool readCluster(u32int cluster, u8int* data);	//Read the content of a cluster to a buffer
	
	~FATFS() {}
	FATFS(Partition* p) : m_part(p), m_fatCache(p) {}

	public:
	static FileSystem* mount(Partition* p, DirectoryNode* mountpoint, bool readwrite = false);

	bool unmount();

	bool setName(FSNode* node, String name);
	bool setPermissions(FSNode* node, u32int permissions);
	bool setUid(FSNode* node, u32int uid);
	bool setGid(FSNode* node, u32int gid);
	bool setParent(FSNode* node, FSNode* parent);

	u32int read(FileNode* file, u64int position, u32int max_length, u8int *data);
	bool write(FileNode* file, u64int position, u32int length, u8int *data);
	bool truncate(FileNode* file);

	bool loadContents(DirectoryNode* dir);
	FileNode* createFile(DirectoryNode* parent, String name);
	DirectoryNode* createDirectory(DirectoryNode* parent, String name);
	bool remove(DirectoryNode* parent, FSNode* node);

	Partition* getPart() { return m_part; }
};

#endif