add SMEM primitive (using Casio's BFile* syscall) + add "mnt" and "ls" builtin
This commit is contained in:
parent
b50a84e47b
commit
95333b656d
|
@ -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__*/
|
|
@ -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__*/
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue