add SMEM primitive (using Casio's BFile* syscall) + add "mnt" and "ls" builtin

This commit is contained in:
Yatis 2021-01-11 12:41:31 +01:00
parent b50a84e47b
commit 95333b656d
7 changed files with 337 additions and 1 deletions

10
include/fxBoot/builtin.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __FXBOOT_BUILTIN_H__
# define __FXBOOT_BUILTIN_H__
#include <stddef.h>
#include <stdint.h>
extern int mnt_main(int argc, char **argv);
extern int ls_main(int argc, char **argv);
#endif /*__FXBOOT_BUILTIN_H__*/

View File

@ -0,0 +1,49 @@
#ifndef __FS_SMEMFS_H__
# define __FS_SMEMFS_H__
#include <stddef.h>
#include <stdint.h>
#include <gint/defs/types.h>
//----
// Internal structure used to provide Casio's syscall abstraction
//---
/* Internal superblock use for the Casio's syscall abstraction */
struct smemfs_superblock {
struct smemfs_inode *root_inode;
struct smemfs_inode *fake_root_inode;
};
/* Internal struct used to store SMEM dump */
struct smemfs_inode {
/* File name */
char name[32];
/* Internal file's information */
int type;
size_t fsize;
size_t dsize;
/* Internal abstraction information */
struct smemfs_inode *child;
struct smemfs_inode *sibling;
struct smemfs_inode *parent;
};
//---
// Dev symbols
//---
#define SMEMFS_FAKE_ROOT_INODE ((void*)0xdeadbeef)
extern struct smemfs_superblock smemfs_superblock;
//---
// primitive
//---
extern struct smemfs_inode *smemfs_mount(void);
extern ssize_t smemfs_read(struct smemfs_inode *inode,
void *buf, size_t count, off_t pos);
extern struct smemfs_inode *smemfs_alloc_inode(void);
#endif /*__FS_SMEMFS_H__*/

55
src/builtin/ls.c Normal file
View File

@ -0,0 +1,55 @@
//---
// builtin:ls - list directory contents
//---
#include "fxBoot/builtin.h"
#include "fxBoot/terminal.h"
#include "fxBoot/fs/smemfs.h"
#include <gint/bfile.h>
static void smemfs_walk(struct smemfs_inode *inode, int level, uint32_t bitmap)
{
const char *records;
if (inode == NULL)
return;
/* handle indentation */
for (int i = 0; i < level; ++i) {
records = "\t";
if ((bitmap & (1 << i)) != 0)
records = "|\t";
terminal_write(records);
}
/* handle file name and sibling dependencies */
records = "|-- %s";
bitmap |= 1 << level;
if (inode->sibling == NULL) {
records = "`-- %s";
bitmap &= ~(1 << level);
}
terminal_write(records, inode->name);
/* handle file type */
if (inode->type == BFile_Type_Directory) {
terminal_write(":\n");
smemfs_walk(inode->child, level + 1, bitmap);
smemfs_walk(inode->sibling, level, bitmap);
return;
}
terminal_write("\n");
smemfs_walk(inode->sibling, level, bitmap);
}
int ls_main(int argc, char **argv)
{
(void)argc;
(void)argv;
if (smemfs_superblock.fake_root_inode != SMEMFS_FAKE_ROOT_INODE) {
terminal_write("smemfs not mounted !\n");
return (84);
}
terminal_write("/\n");
smemfs_walk(smemfs_superblock.root_inode, 0, 0x00000000);
return (0);
}

18
src/builtin/mnt.c Normal file
View File

@ -0,0 +1,18 @@
//---
// builtin:mnt - Mount the SMEM file system
//---
#include "fxBoot/builtin.h"
#include "fxBoot/fs/smemfs.h"
#include "fxBoot/terminal.h"
int mnt_main(int argc, char **argv)
{
(void)argc;
(void)argv;
if (smemfs_mount() != NULL) {
terminal_write("smemfs mounted !\n");
return (0);
}
terminal_write("error when mounted smemfs :(\n");
return (84);
}

127
src/fs/smemfs/mount.c Normal file
View File

@ -0,0 +1,127 @@
//---
// 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;
int i;
/* 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;
i = 0;
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 (i == 0)
inode = *sibling;
i = 1;
/* 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);
}

71
src/fs/smemfs/read.c Normal file
View File

@ -0,0 +1,71 @@
//---
// fxBoot:fs:smemfs:read - Casio SMEM read primtive
//---
#include "fxBoot/fs/smemfs.h"
#include <gint/std/string.h>
#include <gint/bfile.h>
#include <gint/gint.h>
/* external symbols */
extern uint32_t (*cpu_setVBR)(uint32_t vbr, void (*conf_intc)(int), int arg);
/* generate_abolute_path(): Generate abolute path
This function will generate the absolute path of a file because Casio's open
primitive doesn't handle cannonical path */
static void generate_absolute_path(uint16_t *pathname,
struct smemfs_inode *inode, int *pos)
{
/* Check root inode */
if (inode == NULL) {
memcpy(pathname, u"\\\\fls0", 12);
*pos = 6;
return;
}
/* Get the parent inode name */
generate_absolute_path(pathname, inode->parent, pos);
/* Insert the file name */
pathname[(*pos)++] = '\\';
for (int i = 0; inode->name[i] != '\0'; ) {
pathname[*pos] = inode->name[i];
*pos = *pos + 1;
i = i + 1;
}
pathname[*pos] = '\0';
}
/* bfile_abstract(): */
/* smemfs_read(): Read primitive */
ssize_t smemfs_read(struct smemfs_inode *inode,
void *buf, size_t count, off_t pos)
{
uint16_t pathname[64];
ssize_t read;
int handle;
if (inode == NULL)
return (-1);
/* Generate the absolute pathname with FONTCHARACTER format */
generate_absolute_path(pathname, inode, &handle);
/* Switch from gint to the OS after a short wait */
gint_switch_to_casio();
/* Open, read and close the file using Casio's OS syscall */
read = -1;
handle = BFile_Open(pathname, BFile_ReadOnly);
if (handle >= 0) {
read = BFile_Read(handle, buf, count, pos);
BFile_Close(handle);
}
/* Then switch back to gint once the OS finishes working */
gint_switch_to_gint();
/* return the number of byte readed */
return (read);
}

View File

@ -1,5 +1,6 @@
#include "fxBoot/terminal.h"
#include "fxBoot/parser.h"
#include "fxBoot/builtin.h"
#include <gint/std/string.h>
#include <gint/keyboard.h>
#include <gint/display.h>
@ -9,7 +10,8 @@ struct {
const char *name;
int (*f)(int argc, char **argv);
} cmd_list[] = {
{.name = "ls", NULL},
{.name = "mnt", &mnt_main},
{.name = "ls", &ls_main},
{.name = NULL, NULL}
};
@ -45,16 +47,20 @@ int main(void)
usrline = "/[%d]>";
}
terminal_write(usrline, ret);
ret = 0;
if (terminal_read(buff, 128) <= 1)
continue;
/* parse and try to find the command */
if (parser_strtotab(&argc, &argv, buff) != 0) {
terminal_write("error when processing \"%s\"", buff);
ret = 255;
continue;
}
builtin = check_cmd(argv[0]);
if (builtin == NULL) {
terminal_write("command \"%s\" not found...\n", argv[0]);
ret = 127;
continue;
}