kernel/fat.c (view raw)
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 135 136 137 138 139 140 141 142 143 144
#include "file.h"
#include "fat.h"
#include "string.h"
#include "assert.h"
#include "core.h"
#include "memory.h"
#include "fat12.h"
#include <stdint.h>
file_operations_t FAT_fops = {
NULL, /* open */
FAT_openat, /* openat */
FAT_read, /* read */
NULL, /* write */
FAT_dir_next, /* dir_next */
FAT_lseek, /* lseek */
FAT_tell /* tell */
};
uint8_t *cluster_buffer;
FAT12_descriptor_t *fat_desc;
void *FAT12_read(uint32_t lba, uint32_t *offset, size_t size, void *buffer) {
void *FAT_addr = (void*)(0x10000);
if (offset != NULL) {
lba += (*offset) / fat_desc->bytes_per_sect;
*offset = (*offset) % fat_desc->bytes_per_sect;
void *ptr = (void*)((long)(FAT_addr) + (long)(lba * fat_desc->bytes_per_sect));
return memcpy(buffer, ptr + *offset, size);
} else {
void *ptr = (void*)((long)(FAT_addr) + (long)(lba * fat_desc->bytes_per_sect));
return memcpy(buffer, ptr, size);
}
}
void FAT_init() {
fat_desc = malloc(sizeof(FAT12_descriptor_t));
FAT12_init(fat_desc);
cluster_buffer = malloc(fat_desc->cluster_size);
}
int FAT_dir_next(file_t *file, int index, char *fname_buffer) {
uint16_t first_cluster;
uint32_t file_size;
(void)file;
// TODO: subdirectories
return FAT12_root_dir_next(fat_desc, index, fname_buffer, &first_cluster, &file_size);
}
int FAT_openat(file_t *root, file_t *handle, const char *fname, int flags) {
int i = 0;
(void)root;
(void)flags;
// TODO: take fd into consideration (open file in that subdirectory)
uint16_t first_cluster;
while (1) {
char buffer[832];
uint32_t file_size;
i = FAT12_root_dir_next(fat_desc, i, buffer, &first_cluster, &file_size);
if (i <= 0) { return -1; }
if (sstrcmp(buffer, fname) == 0) {
// file found
handle->pos = 0;
handle->size = file_size;
handle->fops = &FAT_fops;
handle->fat_cluster = first_cluster;
return 0;
}
}
}
ssize_t FAT_read(file_t *file, char *buffer, size_t count) {
uint16_t cluster = file->fat_cluster;
fpos_t offset = file->pos;
size_t file_size = file->size, size = 0;
if (offset + count > file_size) {
count = file_size - offset;
}
while (offset >= fat_desc->cluster_size) {
cluster = FAT12_next_cluster(fat_desc, cluster);
if (cluster == 0xFFF || cluster == 0x000) { return -1; }
offset -= fat_desc->cluster_size;
}
while (count > 0) {
if (cluster == 0xFFF || cluster == 0x000) { break; }
FAT12_read_cluster(fat_desc, cluster, cluster_buffer);
cluster = FAT12_next_cluster(fat_desc, cluster);
uint32_t memcpy_size;
if (offset + count > fat_desc->cluster_size) {
memcpy_size = (fat_desc->cluster_size - offset);
} else {
memcpy_size = count;
}
memcpy(buffer, (cluster_buffer + offset), memcpy_size);
offset = 0;
count -= memcpy_size;
buffer += memcpy_size;
size += memcpy_size;
}
file->pos += size;
return size;
}
off_t FAT_lseek(file_t *file, off_t offset, int whence) {
if (whence == SEEK_SET) {
file->pos = offset;
} else if (whence == SEEK_CUR) {
file->pos += offset;
} else if (whence == SEEK_END) {
// to be implemented
} else {
kpanic("Wrong whence!");
}
return file->pos;
}
off_t FAT_tell(file_t *file) {
return file->pos;
}