125 lines
3.3 KiB
C
125 lines
3.3 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>
|
|
#include <gint/gint.h>
|
|
|
|
/* 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_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_gint();
|
|
|
|
/* Return the sector table to simulate the root inode. */
|
|
return (root_inode);
|
|
}
|