fxBoot/src/fs/smemfs/mount.c

129 lines
3.4 KiB
C

//---
// fxBoot:fs:smemfs:mount - Casio SMEM mount primtive
//---
#include "fxBoot/fs/smemfs.h"
#include "fxBoot/terminal.h"
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
#include <gint/bfile.h>
/* world information */
extern void *kernel_env_casio;
extern void *kernel_env_gint;
extern void *gint_switch_to_world(void *buffctx);
/* Define the super block information */
struct smemfs_superblock smemfs_superblock = {
.root_inode = NULL,
.fake_root_inode = NULL
};
/* wide_char_convert(): convert wide character to ASCII format */
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);
}
/* dump_smem_level(): Dump one level of the SMEM FileSystem */
static void dump_smem_level(struct smemfs_inode *parent,
struct smemfs_inode **sibling,
uint16_t *path, off_t cursor)
{
struct BFile_FileInfo file_info;
struct smemfs_inode *inode;
uint16_t buffer[32];
int handle;
/* Generate searching path:
This format is used by the `Bfile_Find*()` syscall */
if (parent != NULL) {
for (int j = 0; parent->name[j] != '\0'; ++j)
path[cursor++] = (uint16_t)(parent->name[j]);
path[cursor++] = '\\';
}
path[cursor + 0] = '*';
path[cursor + 1] = 0x0000;
/* Find the first file:
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 space. */
if (BFile_FindFirst(path, &handle, buffer, &file_info) != 0)
return;
inode = NULL;
do {
/* Try to alloc new inode */
*sibling = calloc(sizeof(struct smemfs_inode), 1);
if (*sibling == NULL)
break;
/* Save the first inode (used after for directories checking) */
if (inode == NULL)
inode = *sibling;
/* Convert wide char to ASCII */
wide_char_convert((*sibling)->name, buffer);
/* Dump file informations */
(*sibling)->type = file_info.type;
(*sibling)->fsize = file_info.file_size;
(*sibling)->dsize = file_info.data_size;
/* Link node and get next sibling */
(*sibling)->parent = parent;
sibling = &(*sibling)->sibling;
/* try to find the next file information */
} while (BFile_FindNext(handle, buffer, &file_info) == 0);
BFile_FindClose(handle);
/* Now let's check all files to find directories */
while (inode != NULL) {
if (inode->type == BFile_Type_Directory)
dump_smem_level(inode, &inode->child, path, cursor);
inode = inode->sibling;
}
}
/* smemfs_mount(): Mount the file system
We only use internal Casio's syscall, so this dummy primitive can
be ported easly. */
struct smemfs_inode *smemfs_mount(void)
{
uint16_t buffer[512];
void *root_inode;
/* switch to the Casio's OS */
gint_switch_to_world(kernel_env_casio);
/* Check useless mount */
root_inode = smemfs_superblock.root_inode;
if (root_inode == NULL) {
/* Generate fake root inode */
smemfs_superblock.fake_root_inode = SMEMFS_FAKE_ROOT_INODE;
/* Dump SMEM files organisation */
smemfs_superblock.root_inode = NULL;
memcpy(buffer, u"\\\\fls0\\", 14);
dump_smem_level(smemfs_superblock.root_inode,
&smemfs_superblock.root_inode,
buffer, 7);
/* Get the "fake" root inode */
root_inode = smemfs_superblock.fake_root_inode;
}
/* switch to the Gint kernel */
gint_switch_to_world(kernel_env_gint);
/* Return the sector table to simulate the root inode. */
return (root_inode);
}