Vhex-kernel/src/kernel/fs/smemfs/power_graphic_3/filesystem/mount.c

162 lines
3.9 KiB
C

#include <kernel/fs/smemfs.h>
#include <kernel/util/atomic.h>
#include <kernel/util/casio.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/driver.h>
#include <string.h>
static size_t wide_char_convert(char *pathname, uint16_t *pathname_wc)
{
size_t i;
i = -1;
while (pathname_wc[++i] != 0x0000 && pathname_wc[i] != 0xffff)
pathname[i] = pathname_wc[i] & 0x00ff;
pathname[i] = '\0';
return (i);
}
/*static void display_test(uint16_t *buffer)
{
for (int i = 0 ; buffer[i] != 0x0000 ; ++i)
earlyterm_write("%c", buffer[i] & 0x00ff);
earlyterm_write("\n");
}*/
// @note: send buffer to avoid recursif buffer definition
static void dump_smem_level(struct smemfs_USB3_inode *parent,
struct smemfs_USB3_inode **sibling, uint16_t *buffer)
{
struct casio_file_info file_info;
struct smemfs_USB3_inode *inode;
int handle;
int i;
// Generate search path
i = 7;
memcpy(buffer, u"\\\\fls0\\", 14);
if (parent != NULL) {
for (int j = 0 ; parent->name[j] != '\0' ; ) {
buffer[i] = (uint16_t)(parent->name[j]);
i = i + 1;
j = j + 1;
}
buffer[i++] = '\\';
}
buffer[i + 0] = '*';
buffer[i + 1] = 0x0000;
//DEBUG
//display_test(buffer);
// Find the first file
// @note: the search buffer and the buffer which will content
// the file name is the same. But it's not used at the same time
// so we can use this tricky way to save some stack
if (casio_Bfile_FindFirst(buffer, &handle, buffer, &file_info) != 0)
return;
// Get all inode stored in this level
i = 0;
do {
// Try to alloc new inode
// TODO: return error code !
*sibling = smemfs_USB3_alloc_inode();
if (*sibling == NULL)
break;
// Get first inide
if (i == 0)
inode = *sibling;
i = 1;
// Convert wide char into char
wide_char_convert((*sibling)->name, buffer);
// Dump file informations
(*sibling)->type = file_info.type;
(*sibling)->fsize = file_info.size.file;
(*sibling)->dsize = file_info.size.data;
// Link node and get next sibling
(*sibling)->parent = parent;
sibling = &(*sibling)->sibling;
} while (casio_Bfile_FindNext(handle, buffer, &file_info) == 0);
// Close casio BfileFind* handle
casio_Bfile_FindClose(handle);
// Now let's check all file to find directories
while (inode != NULL)
{
// Check directory type
if (inode->type == DT_DIRECTORY)
dump_smem_level(inode, &inode->child, buffer);
// Get next inode
inode = inode->sibling;
}
}
static void proto_ls(struct smemfs_USB3_inode *inode, int level)
{
if (inode == NULL)
return;
for (int i = 0 ; i < level ; ++i)
earlyterm_write(" ");
earlyterm_write("%s\n", inode->name);
if (inode->child != NULL)
proto_ls(inode->child, level + 1);
proto_ls(inode->sibling, level);
}
/*
** smemfs_USB3_mount() - Mount the file system (sync)
** @note:
** We don't known how the file system work, so we should use
** Casio's "Bfile_*" sycalls to dump all internal informations
** to avoid OS switch (Vhex -> Casio -> Vhex)
*/
void *smemfs_USB3_mount(void)
{
extern struct smemfs_USB3_superblock smemfs_USB3_superblock;
uint16_t buffer[64];
void *root_inode;
// Get current root inode
atomic_start();
root_inode = smemfs_USB3_superblock.root_inode;
atomic_stop();
// Check useless mount
if (root_inode != NULL)
return (root_inode);
// We should use internal Casio's `Bfile_*` syscall
// to dump SMEM content
drivers_uninstall(0);
// Generate fake root inode
smemfs_USB3_superblock.fake_root_inode = (void*)0xdeadbeff;
// Dump SMEM files organisation
smemfs_USB3_superblock.root_inode = NULL;
dump_smem_level(smemfs_USB3_superblock.root_inode,
&smemfs_USB3_superblock.root_inode, buffer);
// Get the "fake" root inode
root_inode = smemfs_USB3_superblock.fake_root_inode;
//DEBUG
//proto_ls(smemfs_USB3_superblock.root_inode, 0);
//earlyterm_write("TAMER !\n");
//while (1);
// Restore all drivers
drivers_install(0);
// Return the sector table to simulate the root inode.
return (root_inode);
}