Files
lk/lib/fs/fat/fat_fs.h
Travis Geiselbrecht afa659732e [fs][fat] Implement first implementation of file create
Limitations:
Only supports simple 8.3 file names
Cannot create with size > 0
Timestamp is bogus
2022-09-05 21:54:36 -07:00

126 lines
3.2 KiB
C++

/*
* Copyright (c) 2015 Steve White
* Copyright (c) 2022 Travis Geiselbrecht
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#pragma once
#include <lib/bio.h>
#include <lib/bcache.h>
#include <lib/fs.h>
#include <kernel/mutex.h>
// computed constants about a particular mount
struct fat_info {
uint32_t bytes_per_sector = 0;
uint32_t sectors_per_cluster = 0;
uint32_t bytes_per_cluster = 0;
uint32_t reserved_sectors = 0;
uint32_t fat_bits = 0;
uint32_t fat_count = 0;
uint32_t sectors_per_fat = 0;
uint32_t total_sectors = 0;
uint32_t active_fat = 0;
uint32_t data_start_sector = 0;
uint32_t total_clusters = 0;
uint32_t root_cluster = 0;
uint32_t root_entries = 0;
uint32_t root_start_sector = 0;
uint32_t root_dir_sectors = 0;
};
class fat_file;
struct dir_entry_location;
// main fs object representing a mount
class fat_fs {
public:
// mount hook, creates a new fs instance and passes it back in fscookie
static status_t mount(bdev_t *dev, fscookie **cookie);
static status_t unmount(fscookie *cookie);
bdev_t *dev() { return dev_; }
bcache_t bcache() { return bcache_; }
const fat_info &info() const { return info_; }
// file list apis
// must be called with lock held
void add_to_file_list(fat_file *file);
fat_file *lookup_file(const dir_entry_location &loc);
// for now keep the lock public
Mutex lock;
private:
fat_fs();
~fat_fs();
bdev_t *dev_ = nullptr;
bcache_t bcache_ = nullptr;
// list of all the open files and directories
list_node file_list_ = LIST_INITIAL_VALUE(file_list_);
// data computed from BPB
fat_info info_ {};
};
enum class fat_attribute : uint8_t {
file = 0x0, // lack of attribute is a file
read_only = 0x01,
hidden = 0x02,
system = 0x04,
volume_id = 0x08,
directory = 0x10,
archive = 0x20,
lfn = read_only | hidden | system | volume_id,
};
inline uint32_t fat_read32(const void *_buffer, size_t offset) {
auto *buffer = (const uint8_t *)_buffer;
return buffer[offset] +
(buffer[offset + 1] << 8) +
(buffer[offset + 2] << 16) +
(buffer[offset + 3] << 24);
}
inline void fat_write32(void *_buffer, size_t offset, uint32_t val) {
auto *buffer = (uint8_t *)_buffer;
buffer[offset] = val;
buffer[offset + 1] = val >> 8;
buffer[offset + 2] = val >> 16;
buffer[offset + 3] = val >> 24;
}
inline uint16_t fat_read16(const void *_buffer, size_t offset) {
auto *buffer = (const uint8_t *)_buffer;
return buffer[offset] +
(buffer[offset + 1] << 8);
}
inline void fat_write16(void *_buffer, size_t offset, uint16_t val) {
auto *buffer = (uint8_t *)_buffer;
buffer[offset] = val;
buffer[offset + 1] = val >> 8;
}
// In fat32, clusters between 0x0fff.fff8 and 0x0fff.ffff are interpreted as
// end of file.
const uint32_t EOF_CLUSTER_BASE = 0x0ffffff8;
const uint32_t EOF_CLUSTER = 0x0fffffff;
inline bool is_eof_cluster(uint32_t cluster) {
return cluster >= EOF_CLUSTER_BASE && cluster <= EOF_CLUSTER;
}
const int DIR_ENTRY_LENGTH = 32;
const size_t MAX_FILE_NAME_LEN = 256;