[ext2] Massive EXT2 compatibility commit.
This commit is contained in:
parent
73e15ede2f
commit
f6fdaf49aa
@ -119,14 +119,8 @@
|
|||||||
* Defines for often-used integral values
|
* Defines for often-used integral values
|
||||||
* related to our binning and paging strategy.
|
* related to our binning and paging strategy.
|
||||||
*/
|
*/
|
||||||
#if SIZE_MAX == UINT32_MAX
|
|
||||||
#define NUM_BINS 11U /* Number of bins, total, under 32-bit. */
|
#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)). */
|
#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 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. */
|
#define SMALLEST_BIN (1UL << SMALLEST_BIN_LOG) /* Size of the smallest bin. */
|
||||||
|
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
ext2_superblock_t * initrd_superblock;
|
ext2_superblock_t * initrd_superblock;
|
||||||
ext2_inodetable_t * initrd_root_node;
|
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_root;
|
||||||
fs_node_t * initrd_dev;
|
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);
|
void close_initrd(fs_node_t *node);
|
||||||
struct dirent *readdir_initrd(fs_node_t *node, uint32_t index);
|
struct dirent *readdir_initrd(fs_node_t *node, uint32_t index);
|
||||||
fs_node_t *finddir_initrd(fs_node_t *node, char *name);
|
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
|
uint32_t
|
||||||
read_initrd(
|
read_initrd(
|
||||||
@ -61,16 +68,71 @@ readdir_initrd(
|
|||||||
fs_node_t *node,
|
fs_node_t *node,
|
||||||
uint32_t index
|
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;
|
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 *
|
fs_node_t *
|
||||||
finddir_initrd(
|
finddir_initrd(
|
||||||
fs_node_t *node,
|
fs_node_t *node,
|
||||||
char *name
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
fs_node_t * outnode = malloc(sizeof(fs_node_t));
|
||||||
|
initrd_node_from_file(direntry->inode, direntry, outnode);
|
||||||
|
return outnode;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
initrd_node_from_file(
|
initrd_node_from_file(
|
||||||
@ -93,6 +155,54 @@ initrd_node_from_file(
|
|||||||
fnode->mask = inode->mode & 0xFFF;
|
fnode->mask = inode->mode & 0xFFF;
|
||||||
/* File Flags */
|
/* File Flags */
|
||||||
fnode->flags = 0;
|
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) {
|
if (inode->mode & EXT2_S_IFREG) {
|
||||||
fnode->flags &= FS_FILE;
|
fnode->flags &= FS_FILE;
|
||||||
}
|
}
|
||||||
@ -117,4 +227,60 @@ initrd_node_from_file(
|
|||||||
fnode->close = close_initrd;
|
fnode->close = close_initrd;
|
||||||
fnode->readdir = readdir_initrd;
|
fnode->readdir = readdir_initrd;
|
||||||
fnode->finddir = finddir_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;
|
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
|
* memset
|
||||||
* Set `count` bytes to `val`.
|
* 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) {
|
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);
|
return node->finddir(node, name);
|
||||||
} else {
|
} else {
|
||||||
return (fs_node_t *)NULL;
|
return (fs_node_t *)NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retreive the node for the requested path
|
||||||
|
*/
|
||||||
fs_node_t *
|
fs_node_t *
|
||||||
kopen(
|
kopen(
|
||||||
const char *filename,
|
const char *filename,
|
||||||
uint32_t flags
|
uint32_t flags
|
||||||
) {
|
) {
|
||||||
/* let's do this shit */
|
/* 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;
|
typedef struct ext2_dir ext2_dir_t;
|
||||||
|
|
||||||
|
void initrd_mount(uint32_t mem_head, uint32_t mem_top);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,7 @@ extern unsigned short *memsetw(unsigned short *dest, unsigned short val, int cou
|
|||||||
extern int strlen(const char *str);
|
extern int strlen(const char *str);
|
||||||
extern unsigned char inportb (unsigned short _port);
|
extern unsigned char inportb (unsigned short _port);
|
||||||
extern void outportb (unsigned short _port, unsigned char _data);
|
extern void outportb (unsigned short _port, unsigned char _data);
|
||||||
|
int strcmp(const char * a, const char * b);
|
||||||
|
|
||||||
/* Panic */
|
/* Panic */
|
||||||
#define HALT_AND_CATCH_FIRE(mesg) halt_and_catch_fire(mesg, __FILE__, __LINE__)
|
#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)) malloc(size_t size);
|
||||||
void * __attribute__ ((malloc)) realloc(void * ptr, size_t size);
|
void * __attribute__ ((malloc)) realloc(void * ptr, size_t size);
|
||||||
void * __attribute__ ((malloc)) calloc(size_t nmemb, size_t size);
|
void * __attribute__ ((malloc)) calloc(size_t nmemb, size_t size);
|
||||||
|
void free(void * ptr);
|
||||||
|
|
||||||
#endif
|
#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_start = *((uint32_t*)mboot_ptr->mods_addr);
|
||||||
uint32_t module_end = *(uint32_t*)(mboot_ptr->mods_addr+4);
|
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);
|
ext2_superblock_t * superblock = (ext2_superblock_t *)(module_start + 1024);
|
||||||
kprintf("Magic is 0x%x\n", (int)superblock->magic);
|
kprintf("Magic is 0x%x\n", (int)superblock->magic);
|
||||||
assert(superblock->magic == EXT2_SUPER_MAGIC);
|
assert(superblock->magic == EXT2_SUPER_MAGIC);
|
||||||
@ -160,6 +168,7 @@ main(struct multiboot *mboot_ptr) {
|
|||||||
}
|
}
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user