fxBoot/src/builtin/hyp.c

243 lines
6.0 KiB
C

//---
// fxBoot:builtin:hyp - Hypervisor utility
//---
#include "fxBoot/builtin.h"
#include "fxBoot/terminal.h"
#include "fxBoot/fs/smemfs.h"
#include "fxBoot/hypervisor.h"
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
#include <gint/gint.h>
/* internal structiure used to handle the hypervisor module */
#define HYP_INFO_WATERMARK (0xdeadbeef)
struct {
struct himage *images;
uint32_t watermark;
uint32_t installed;
} hypinfo;
#if 0
//---
// SMEM abstraction
//---
static void smemfs_find(struct smemfs_inode *inode, char *buffer, int *counter)
{
const char *ext;
if (inode == NULL)
return;
smemfs_find(inode->child, buffer, counter);
ext = strrchr(inode->name, '.');
if (ext != NULL) {
if (strcmp(ext, ".elf") == 0) {
terminal_write("[%d] %s\n", *counter, inode->name);
*counter += 1;
}
}
smemfs_find(inode->sibling, buffer, counter);
}
static struct smemfs_inode *smemfs_get(struct smemfs_inode *inode,
int *counter, int id)
{
struct smemfs_inode *file;
const char *ext;
if (inode == NULL)
return (NULL);
file = smemfs_get(inode->child, counter, id);
if (file != NULL)
return (file);
ext = strrchr(inode->name, '.');
if (ext != NULL) {
if (strcmp(ext, ".elf") == 0) {
if (*counter == id)
return (inode);
*counter += 1;
}
}
return (smemfs_get(inode->sibling, counter, id));
}
#endif
//---
// Module management
//---
static int hyp_img_module(int argc, char **argv)
{
if (argc < 2)
goto error;
if (strcmp(argv[2], "ls") == 0) {
int counter = 0;
struct himage *img = hypinfo.images;
while (img != NULL) {
terminal_write("[%d] %s\n", counter, img->name);
counter = counter + 1;
img = img->next;
}
return (0);
}
#if 0
if (strcmp(argv[2], "load") == 0) {
if (argc < 3) {
terminal_write("image ID missing\n");
return (84);
}
int id = 0;
struct smemfs_inode *file;
int counter = 0;
id = atoi(argv[3]);
file = smemfs_get(smemfs_superblock.root_inode,
&counter, id);
if (file == NULL) {
terminal_write("image ID invalid\n");
return (84);
}
struct worldctx *worldctx = calloc(sizeof(struct worldctx), 1);
if (hypervisor_loader(worldctx, file) != 0)
return (84);
worldctx->private.next = hyp_info.os_list;
hyp_info.os_list = worldctx;
terminal_write("image successfully loaded\n");
return (0);
}
#endif
error:
terminal_write("\"hyp img\" requires at least 1 argument\n");
terminal_write("\n");
terminal_write("Manage image\n");
terminal_write("\n");
terminal_write("commands:\n");
terminal_write(" ls List images available on the device\n");
terminal_write(" load Load image on memory\n");
return (1);
}
#if 0
static int hyp_os_module(int argc, char **argv)
{
if (argc < 2)
goto error;
if (strcmp(argv[2], "ls") == 0) {
int counter = 0;
struct worldctx *worldctx = hyp_info.os_list;
while (worldctx != NULL) {
terminal_write("[%d] - %s\n", counter, worldctx->private.file->name);
terminal_write("|-- cpu context:\n");
for (int i = 0; i < 16; ++i)
terminal_write("| |-- r%d: %p\n", i, worldctx->context.cpu.reg[i]);
terminal_write("| |-- gbr: %p\n", worldctx->context.cpu.gbr);
terminal_write("| |-- macl: %p\n", worldctx->context.cpu.macl);
terminal_write("| |-- mach: %p\n", worldctx->context.cpu.mach);
terminal_write("| |-- ssr: %p\n", worldctx->context.cpu.ssr);
terminal_write("| |-- spc: %p\n", worldctx->context.cpu.spc);
terminal_write("| `-- pr: %p\n", worldctx->context.cpu.pr);
terminal_write("`-- memory:\n");
terminal_write(" |-- entry: %p\n", worldctx->memory.program.start);
terminal_write(" `-- size : %do\n", worldctx->memory.program.size);
worldctx = worldctx->private.next;
counter = counter + 1;
}
return (0);
}
if (strcmp(argv[2], "run") == 0) {
if (argc < 3) {
terminal_write("OS ID missing\n");
return (84);
}
int id = atoi(argv[3]);
int counter = 0;
struct worldctx *worldctx = hyp_info.os_list;
while (worldctx != NULL) {
if (counter == id)
break;
worldctx = worldctx->private.next;
counter = counter + 1;
}
if (worldctx == NULL) {
terminal_write("OS ID invalid\n");
return (84);
}
/* Switch from gint to the OS after a short wait */
gint_switch_to_casio();
/* call Casio's specific code */
((void(*)(void))(uintptr_t)worldctx->context.cpu.spc)();
/* Then switch back to gint once the OS finishes working */
gint_switch_to_gint();
return (0);
}
error:
terminal_write("\"hyp os\" requiere at least 1 argument\n");
terminal_write("\n");
terminal_write("Manage image\n");
terminal_write("\n");
terminal_write("commands:\n");
terminal_write(" ls List images available on the device\n");
terminal_write(" run Run image (you cannot return to fxBoot)\n");
return (1);
}
/* install the hypervisor */
static int hyp_install(void)
{
/* extern void *bhyp_rom;
extern void *bhyp_ram;
extern void *zhyp;
// check if the hypervisor is already installed.
if (hyp_info.installed == 0xdeb0cad0) {
terminal_write("hypervisor already installed\n");
return (1);
}
// install the hypervisor
if (hyperisor_install() != 0) {
terminal_write("hypervisor installation fail :(\n");
return (84);
}*/
return (0);
}
#endif
//---
// Entry
//---
/* hyp_main(): hypervisor helper */
int hyp_main(int argc, char **argv)
{
/* initialize the buildtin (TODO: better way) */
if (hypinfo.watermark != HYP_INFO_WATERMARK) {
hypinfo.watermark = HYP_INFO_WATERMARK;
hypervisor_loader_list(&hypinfo.images);
}
/* handle arguments */
if (argc > 1) {
if (strcmp(argv[1], "img") == 0)
return (hyp_img_module(argc, argv));
//if (strcmp(argv[1], "os") == 0)
// return (hyp_os_module(argc, argv));
//if (strcmp(argv[1], "install") == 0)
// return (hyp_install());
}
/* error or helper */
terminal_write("Usage: hyp [OPTION] commands\n");
terminal_write("\n");
terminal_write("Manage image loading\n");
terminal_write("\n");
terminal_write("commands:\n");
terminal_write(" img Image management\n");
terminal_write(" os OS loading management\n");
terminal_write(" install Hypervisor installation\n");
return (0);
}