echfs: Add open and read functions
This commit is contained in:
parent
1ce2a8d3ab
commit
225a7c238d
102
src/fs/echfs.c
102
src/fs/echfs.c
|
@ -12,70 +12,86 @@ struct echfs_identity_table {
|
|||
uint64_t block_size;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct echfs_dir_entry {
|
||||
uint64_t parent_id;
|
||||
uint8_t type;
|
||||
char name[201];
|
||||
uint64_t atime;
|
||||
uint64_t mtime;
|
||||
uint16_t perms;
|
||||
uint16_t owner;
|
||||
uint16_t group;
|
||||
uint64_t ctime;
|
||||
uint64_t payload;
|
||||
uint64_t size;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define ROOT_DIR_ID (~((uint64_t)0))
|
||||
#define END_OF_CHAIN (~((uint64_t)0))
|
||||
#define FILE_TYPE 0
|
||||
|
||||
int load_echfs_file(int disk, int partition, void *buffer, const char *filename) {
|
||||
struct mbr_part mbr_part;
|
||||
mbr_get_part(&mbr_part, disk, partition);
|
||||
#define CACHE_ADDR ((uint8_t *)(0x1000000))
|
||||
|
||||
static int cache_block(struct echfs_file_handle *file, uint64_t block) {
|
||||
// Load the file.
|
||||
uint64_t block_val = file->dir_entry.payload;
|
||||
for (uint64_t i = 0; i < block; i++) {
|
||||
if (block_val == END_OF_CHAIN)
|
||||
return -1;
|
||||
|
||||
// Read the next block.
|
||||
read_partition(file->disk, &file->mbr_part, &block_val, file->alloc_table_offset + block_val * sizeof(uint64_t),
|
||||
sizeof(uint64_t));
|
||||
}
|
||||
|
||||
if (block_val == END_OF_CHAIN)
|
||||
return -1;
|
||||
|
||||
return read_partition(file->disk, &file->mbr_part, CACHE_ADDR, block_val * file->block_size, file->block_size);
|
||||
}
|
||||
|
||||
int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count) {
|
||||
for (uint64_t progress = 0; progress < count;) {
|
||||
/* cache the block */
|
||||
uint64_t block = (loc + progress) / file->block_size;
|
||||
|
||||
int ret = cache_block(file, block);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
uint64_t chunk = count - progress;
|
||||
uint64_t offset = (loc + progress) % file->block_size;
|
||||
if (chunk > file->block_size - offset)
|
||||
chunk = file->block_size - offset;
|
||||
|
||||
memcpy(buf + progress, &CACHE_ADDR[offset], chunk);
|
||||
progress += chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int echfs_open(struct echfs_file_handle *ret, int disk, int partition, const char *filename) {
|
||||
ret->disk = disk;
|
||||
|
||||
mbr_get_part(&ret->mbr_part, disk, partition);
|
||||
|
||||
struct echfs_identity_table id_table;
|
||||
read_partition(disk, &mbr_part, &id_table, 0, sizeof(struct echfs_identity_table));
|
||||
read_partition(disk, &ret->mbr_part, &id_table, 0, sizeof(struct echfs_identity_table));
|
||||
|
||||
if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
|
||||
print("echfs: signature invalid\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const uint64_t block_size = id_table.block_size;
|
||||
const uint64_t block_count = id_table.block_count;
|
||||
const uint64_t dir_length = id_table.dir_length * block_size;
|
||||
const uint64_t alloc_table_size = DIV_ROUNDUP(block_count * sizeof(uint64_t), block_size) * block_size;
|
||||
const uint64_t alloc_table_offset = 16 * block_size;
|
||||
const uint64_t dir_offset = alloc_table_offset + alloc_table_size;
|
||||
ret->block_size = id_table.block_size;
|
||||
ret->block_count = id_table.block_count;
|
||||
ret->dir_length = id_table.dir_length * ret->block_size;
|
||||
ret->alloc_table_size = DIV_ROUNDUP(ret->block_count * sizeof(uint64_t), ret->block_size) * ret->block_size;
|
||||
ret->alloc_table_offset = 16 * ret->block_size;
|
||||
ret->dir_offset = ret->alloc_table_offset + ret->alloc_table_size;
|
||||
|
||||
// Find the file in the root dir.
|
||||
struct echfs_dir_entry entry;
|
||||
for (uint64_t i = 0; i < dir_length; i += sizeof(struct echfs_dir_entry)) {
|
||||
read_partition(disk, &mbr_part, &entry, i + dir_offset, sizeof(struct echfs_dir_entry));
|
||||
for (uint64_t i = 0; i < ret->dir_length; i += sizeof(struct echfs_dir_entry)) {
|
||||
read_partition(disk, &ret->mbr_part, &ret->dir_entry, i + ret->dir_offset, sizeof(struct echfs_dir_entry));
|
||||
|
||||
if (!entry.parent_id) {
|
||||
if (!ret->dir_entry.parent_id) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(filename, entry.name) && entry.parent_id == ROOT_DIR_ID && entry.type == FILE_TYPE) {
|
||||
goto found;
|
||||
if (!strcmp(filename, ret->dir_entry.name) &&
|
||||
ret->dir_entry.parent_id == ROOT_DIR_ID &&
|
||||
ret->dir_entry.type == FILE_TYPE) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
print("echfs: file %s not found\n", filename);
|
||||
return -1;
|
||||
|
||||
found:;
|
||||
// Load the file.
|
||||
for (uint64_t i = entry.payload; i != END_OF_CHAIN;) {
|
||||
// Read block.
|
||||
read_partition(disk, &mbr_part, buffer, i * block_size, block_size);
|
||||
buffer += block_size;
|
||||
|
||||
// Read the next block.
|
||||
read_partition(disk, &mbr_part, &i, alloc_table_offset + i * sizeof(uint64_t), sizeof(uint64_t));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,36 @@
|
|||
#ifndef __FS__ECHFS_H__
|
||||
#define __FS__ECHFS_H__
|
||||
|
||||
int load_echfs_file(int disk, int partition, void *buffer, const char *filename);
|
||||
#include <stdint.h>
|
||||
#include <lib/mbr.h>
|
||||
|
||||
struct echfs_dir_entry {
|
||||
uint64_t parent_id;
|
||||
uint8_t type;
|
||||
char name[201];
|
||||
uint64_t atime;
|
||||
uint64_t mtime;
|
||||
uint16_t perms;
|
||||
uint16_t owner;
|
||||
uint16_t group;
|
||||
uint64_t ctime;
|
||||
uint64_t payload;
|
||||
uint64_t size;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct echfs_file_handle {
|
||||
int disk;
|
||||
struct mbr_part mbr_part;
|
||||
uint64_t block_size;
|
||||
uint64_t block_count;
|
||||
uint64_t dir_length;
|
||||
uint64_t alloc_table_size;
|
||||
uint64_t alloc_table_offset;
|
||||
uint64_t dir_offset;
|
||||
struct echfs_dir_entry dir_entry;
|
||||
};
|
||||
|
||||
int echfs_open(struct echfs_file_handle *ret, int disk, int partition, const char *filename);
|
||||
int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,8 @@ extern symbol bss_end;
|
|||
static int config_loaded = 0;
|
||||
|
||||
void main(int boot_drive) {
|
||||
struct echfs_file_handle f;
|
||||
|
||||
// Zero out .bss section
|
||||
for (uint8_t *p = bss_begin; p < bss_end; p++)
|
||||
*p = 0;
|
||||
|
@ -43,7 +45,8 @@ void main(int boot_drive) {
|
|||
} else {
|
||||
print(" Found!\n");
|
||||
if (!config_loaded) {
|
||||
if (!load_echfs_file(boot_drive, i, (void *)0x100000, CONFIG_NAME)) {
|
||||
if (!echfs_open(&f, boot_drive, i, CONFIG_NAME)) {
|
||||
echfs_read(&f, (void *)0x100000, 0, f.dir_entry.size);
|
||||
config_loaded = 1;
|
||||
print(" Config file found and loaded!\n");
|
||||
}
|
||||
|
@ -77,7 +80,8 @@ void main(int boot_drive) {
|
|||
}
|
||||
}
|
||||
|
||||
load_echfs_file(drive, part, (void *)0x100000, path);
|
||||
echfs_open(&f, drive, part, path);
|
||||
echfs_read(&f, (void *)0x100000, 0, f.dir_entry.size);
|
||||
|
||||
// Boot the kernel.
|
||||
asm volatile (
|
||||
|
|
Loading…
Reference in New Issue