[ext2] Massive EXT2 compatibility commit.
This commit is contained in:
parent
73e15ede2f
commit
f6fdaf49aa
@ -119,14 +119,8 @@
|
||||
* Defines for often-used integral values
|
||||
* related to our binning and paging strategy.
|
||||
*/
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
#define NUM_BINS 11U /* Number of bins, total, under 32-bit. */
|
||||
#define SMALLEST_BIN_LOG 2U /* Logarithm base two of the smallest bin: log_2(sizeof(int32)). */
|
||||
#else
|
||||
#define NUM_BINS 10U /* Number of bins, total, under 64-bit. */
|
||||
#define SMALLEST_BIN_LOG 3U /* Logarithm base two of the smallest bin: log_2(sizeof(int64)). */
|
||||
#endif
|
||||
|
||||
#define BIG_BIN (NUM_BINS - 1) /* Index for the big bin, (NUM_BINS - 1) */
|
||||
#define SMALLEST_BIN (1UL << SMALLEST_BIN_LOG) /* Size of the smallest bin. */
|
||||
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
ext2_superblock_t * initrd_superblock;
|
||||
ext2_inodetable_t * initrd_root_node;
|
||||
ext2_bgdescriptor_t * initrd_root_block;
|
||||
ext2_inodetable_t * initrd_inode_table;
|
||||
void * initrd_start;
|
||||
|
||||
fs_node_t * initrd_root;
|
||||
fs_node_t * initrd_dev;
|
||||
|
||||
@ -14,6 +18,9 @@ void open_initrd(fs_node_t *node, uint8_t read, uint8_t write);
|
||||
void close_initrd(fs_node_t *node);
|
||||
struct dirent *readdir_initrd(fs_node_t *node, uint32_t index);
|
||||
fs_node_t *finddir_initrd(fs_node_t *node, char *name);
|
||||
ext2_dir_t * ext2_get_direntry(ext2_inodetable_t * inode, uint32_t index);
|
||||
ext2_inodetable_t * ext2_get_inode(uint32_t inode);
|
||||
void * ext2_get_block(uint32_t block);
|
||||
|
||||
uint32_t
|
||||
read_initrd(
|
||||
@ -61,15 +68,70 @@ readdir_initrd(
|
||||
fs_node_t *node,
|
||||
uint32_t index
|
||||
) {
|
||||
ext2_inodetable_t * inode = ext2_get_inode(node->inode);
|
||||
ext2_dir_t * direntry = ext2_get_direntry(inode, index);
|
||||
if (!direntry) {
|
||||
return NULL;
|
||||
}
|
||||
struct dirent * dirent = malloc(sizeof(struct dirent));
|
||||
memcpy(&dirent->name, &direntry->name, direntry->name_len);
|
||||
dirent->name[direntry->name_len] = '\0';
|
||||
dirent->ino = direntry->inode;
|
||||
return dirent;
|
||||
}
|
||||
|
||||
/*
|
||||
* find the child entry named `name` within the directory
|
||||
* node `node`. The VFS has already checked that `node` is
|
||||
* a valid directory, but we'll do that again just to be safe,
|
||||
* and just in case someone didn't use the VFS layer to call us.
|
||||
* Basically, run through the directory entries until we find
|
||||
* the one requested and build an fs_node_t for it. The requester
|
||||
* will have to free it when they are done with it.
|
||||
*/
|
||||
fs_node_t *
|
||||
finddir_initrd(
|
||||
fs_node_t *node,
|
||||
char *name
|
||||
) {
|
||||
/*
|
||||
* Find the actual inode in the ramdisk image for the requested file
|
||||
*/
|
||||
ext2_inodetable_t * inode = ext2_get_inode(node->inode);
|
||||
void * block;
|
||||
ext2_dir_t * direntry = NULL;
|
||||
block = (void *)ext2_get_block(inode->block[0]);
|
||||
uint32_t dir_offset;
|
||||
dir_offset = 0;
|
||||
/*
|
||||
* Look through the requested entries until we find what we're looking for
|
||||
*/
|
||||
while (dir_offset < inode->size) {
|
||||
ext2_dir_t * d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
|
||||
if (strlen(name) != d_ent->name_len) {
|
||||
dir_offset += d_ent->rec_len;
|
||||
continue;
|
||||
}
|
||||
char * dname = malloc(sizeof(char) * (d_ent->name_len + 1));
|
||||
memcpy(dname, &d_ent->name, d_ent->name_len);
|
||||
dname[d_ent->name_len] = '\0';
|
||||
if (!strcmp(dname, name)) {
|
||||
free(dname);
|
||||
direntry = d_ent;
|
||||
break;
|
||||
}
|
||||
free(dname);
|
||||
dir_offset += d_ent->rec_len;
|
||||
}
|
||||
if (!direntry) {
|
||||
/*
|
||||
* We could not find the requested entry in this directory.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
fs_node_t * outnode = malloc(sizeof(fs_node_t));
|
||||
initrd_node_from_file(direntry->inode, direntry, outnode);
|
||||
return outnode;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@ -93,6 +155,54 @@ initrd_node_from_file(
|
||||
fnode->mask = inode->mode & 0xFFF;
|
||||
/* File Flags */
|
||||
fnode->flags = 0;
|
||||
if (inode->mode & EXT2_S_IFREG) {
|
||||
fnode->flags |= FS_FILE;
|
||||
}
|
||||
if (inode->mode & EXT2_S_IFDIR) {
|
||||
fnode->flags |= FS_DIRECTORY;
|
||||
}
|
||||
if (inode->mode & EXT2_S_IFBLK) {
|
||||
fnode->flags |= FS_BLOCKDEVICE;
|
||||
}
|
||||
if (inode->mode & EXT2_S_IFCHR) {
|
||||
fnode->flags |= FS_CHARDEVICE;
|
||||
}
|
||||
if (inode->mode & EXT2_S_IFIFO) {
|
||||
fnode->flags |= FS_PIPE;
|
||||
}
|
||||
if (inode->mode & EXT2_S_IFLNK) {
|
||||
fnode->flags |= FS_SYMLINK;
|
||||
}
|
||||
fnode->read = read_initrd;
|
||||
fnode->write = write_initrd;
|
||||
fnode->open = open_initrd;
|
||||
fnode->close = close_initrd;
|
||||
fnode->readdir = readdir_initrd;
|
||||
fnode->finddir = finddir_initrd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
initrd_node_from_dirent(
|
||||
ext2_inodetable_t * inode,
|
||||
struct dirent * direntry,
|
||||
fs_node_t * fnode
|
||||
) {
|
||||
if (!fnode) {
|
||||
/* You didn't give me a node to write into, go *** yourself */
|
||||
return 0;
|
||||
}
|
||||
/* Information from the direntry */
|
||||
fnode->inode = direntry->ino;
|
||||
memcpy(&fnode->name, &direntry->name, strlen(direntry->name));
|
||||
fnode->name[strlen(direntry->name)] = '\0';
|
||||
/* Information from the inode */
|
||||
fnode->uid = inode->uid;
|
||||
fnode->gid = inode->gid;
|
||||
fnode->length = inode->size;
|
||||
fnode->mask = inode->mode & 0xFFF;
|
||||
/* File Flags */
|
||||
fnode->flags = 0;
|
||||
if (inode->mode & EXT2_S_IFREG) {
|
||||
fnode->flags &= FS_FILE;
|
||||
}
|
||||
@ -117,4 +227,60 @@ initrd_node_from_file(
|
||||
fnode->close = close_initrd;
|
||||
fnode->readdir = readdir_initrd;
|
||||
fnode->finddir = finddir_initrd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ext2_inodetable_t *
|
||||
ext2_get_inode(
|
||||
uint32_t inode
|
||||
) {
|
||||
return (ext2_inodetable_t *)((uintptr_t)initrd_inode_table + initrd_superblock->inode_size * (inode - 1));
|
||||
}
|
||||
|
||||
void *
|
||||
ext2_get_block(
|
||||
uint32_t block
|
||||
) {
|
||||
return (void *)((uintptr_t)initrd_start + (1024 << initrd_superblock->log_block_size) * block);
|
||||
}
|
||||
|
||||
ext2_dir_t *
|
||||
ext2_get_direntry(
|
||||
ext2_inodetable_t * inode,
|
||||
uint32_t index
|
||||
) {
|
||||
assert(inode->mode & EXT2_S_IFDIR);
|
||||
void * block;
|
||||
block = (void *)ext2_get_block(inode->block[0]);
|
||||
uint32_t dir_offset;
|
||||
dir_offset = 0;
|
||||
uint32_t dir_index;
|
||||
dir_index = 0;
|
||||
while (dir_offset < inode->size) {
|
||||
ext2_dir_t * d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
|
||||
if (dir_index == index) {
|
||||
return d_ent;
|
||||
}
|
||||
dir_offset += d_ent->rec_len;
|
||||
dir_index++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
initrd_mount(
|
||||
uint32_t mem_head,
|
||||
uint32_t mem_top
|
||||
) {
|
||||
initrd_start = (void *)mem_head;
|
||||
initrd_superblock = (ext2_superblock_t *)((uintptr_t)initrd_start + 1024);
|
||||
assert(initrd_superblock->magic == EXT2_SUPER_MAGIC);
|
||||
initrd_root_block = (ext2_bgdescriptor_t *)((uintptr_t)initrd_start + 1024 + 1024);
|
||||
initrd_inode_table = (ext2_inodetable_t *)((uintptr_t)initrd_start + (1024 << initrd_superblock->log_block_size) * initrd_root_block->inode_table);
|
||||
// Get the second inode
|
||||
ext2_inodetable_t * root_inode = ext2_get_inode(2);
|
||||
ext2_dir_t * root_direntry = ext2_get_direntry(root_inode, 0);
|
||||
initrd_root = (fs_node_t *)malloc(sizeof(fs_node_t));
|
||||
assert(initrd_node_from_file(root_inode, root_direntry, initrd_root));
|
||||
fs_root = initrd_root;
|
||||
}
|
||||
|
@ -20,6 +20,26 @@ memcpy(
|
||||
return dest;
|
||||
}
|
||||
|
||||
int
|
||||
strcmp(
|
||||
const char * a,
|
||||
const char * b
|
||||
) {
|
||||
uint32_t i = 0;
|
||||
while (1) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
} else if (a[i] > b[i]) {
|
||||
return 1;
|
||||
} else {
|
||||
if (a[i] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* memset
|
||||
* Set `count` bytes to `val`.
|
||||
|
38
core/vfs.c
38
core/vfs.c
@ -40,19 +40,55 @@ struct dirent * readdir_fs(fs_node_t *node, uint32_t index) {
|
||||
}
|
||||
|
||||
fs_node_t *finddir_fs(fs_node_t *node, char *name) {
|
||||
if ((node->flags & 0x07) == FS_DIRECTORY && node->readdir != 0) {
|
||||
if ((node->flags & FS_DIRECTORY) && node->readdir != 0) {
|
||||
return node->finddir(node, name);
|
||||
} else {
|
||||
return (fs_node_t *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Retreive the node for the requested path
|
||||
*/
|
||||
fs_node_t *
|
||||
kopen(
|
||||
const char *filename,
|
||||
uint32_t flags
|
||||
) {
|
||||
/* let's do this shit */
|
||||
if (!fs_root) {
|
||||
HALT_AND_CATCH_FIRE("Attempted to kopen() without a filesystem in place.");
|
||||
}
|
||||
if (!filename[0] == '/') {
|
||||
HALT_AND_CATCH_FIRE("Attempted to kopen() a non-absolute path.");
|
||||
}
|
||||
uint32_t path_len = strlen(filename);
|
||||
char * path = (char *)malloc(sizeof(char) * (path_len));
|
||||
memcpy(path, filename, path_len);
|
||||
char * path_offset = path;
|
||||
uint32_t path_depth = 0;
|
||||
while (path_offset < path + path_len) {
|
||||
if (*path_offset == '/') {
|
||||
*path_offset = '\0';
|
||||
path_depth++;
|
||||
}
|
||||
path_offset++;
|
||||
}
|
||||
path[path_len] = '\0';
|
||||
path_offset = path + 1;
|
||||
uint32_t depth;
|
||||
fs_node_t * node_ptr = fs_root;
|
||||
for (depth = 0; depth < path_depth; ++depth) {
|
||||
node_ptr = finddir_fs(node_ptr, path_offset);
|
||||
if (!node_ptr) {
|
||||
free((void *)path);
|
||||
return NULL;
|
||||
} else if (depth == path_depth - 1) {
|
||||
return node_ptr;
|
||||
}
|
||||
}
|
||||
free((void *)path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -149,4 +149,6 @@ struct ext2_dir {
|
||||
|
||||
typedef struct ext2_dir ext2_dir_t;
|
||||
|
||||
void initrd_mount(uint32_t mem_head, uint32_t mem_top);
|
||||
|
||||
#endif
|
||||
|
@ -30,6 +30,7 @@ extern unsigned short *memsetw(unsigned short *dest, unsigned short val, int cou
|
||||
extern int strlen(const char *str);
|
||||
extern unsigned char inportb (unsigned short _port);
|
||||
extern void outportb (unsigned short _port, unsigned char _data);
|
||||
int strcmp(const char * a, const char * b);
|
||||
|
||||
/* Panic */
|
||||
#define HALT_AND_CATCH_FIRE(mesg) halt_and_catch_fire(mesg, __FILE__, __LINE__)
|
||||
@ -129,5 +130,6 @@ void heap_install();
|
||||
void * __attribute__ ((malloc)) malloc(size_t size);
|
||||
void * __attribute__ ((malloc)) realloc(void * ptr, size_t size);
|
||||
void * __attribute__ ((malloc)) calloc(size_t nmemb, size_t size);
|
||||
void free(void * ptr);
|
||||
|
||||
#endif
|
||||
|
9
main.c
9
main.c
@ -92,6 +92,14 @@ main(struct multiboot *mboot_ptr) {
|
||||
uint32_t module_start = *((uint32_t*)mboot_ptr->mods_addr);
|
||||
uint32_t module_end = *(uint32_t*)(mboot_ptr->mods_addr+4);
|
||||
|
||||
initrd_mount(module_start, module_end);
|
||||
fs_node_t * test_file = kopen("/hello.txt", NULL);
|
||||
if (!test_file) {
|
||||
kprintf("Couldn't find /hello.txt\n");
|
||||
}
|
||||
kprintf("Found %s at inode %d\n", test_file->name, test_file->inode);
|
||||
|
||||
#if 0
|
||||
ext2_superblock_t * superblock = (ext2_superblock_t *)(module_start + 1024);
|
||||
kprintf("Magic is 0x%x\n", (int)superblock->magic);
|
||||
assert(superblock->magic == EXT2_SUPER_MAGIC);
|
||||
@ -160,6 +168,7 @@ main(struct multiboot *mboot_ptr) {
|
||||
}
|
||||
kprintf("\n");
|
||||
};
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user