fxBoot/src/builtin/hyp.c

256 lines
6.3 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/std/stdio.h>
#include <gint/gint.h>
#include <gintrace/tracer.h>
#include "./src/hypervisor/internal/elf.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;
//---
// Internal information
//---
/* hyp_get_image(): return the image using its ID */
static struct himage *hyp_get_image(int id)
{
struct himage *img;
int counter;
counter = 0;
img = hypinfo.images;
while (img != NULL) {
if (counter == id)
break;
counter = counter + 1;
img = img->next;
}
return (img);
}
//---
// Module management
//---
/* hyp_img_module(): Handle argument for the image module part */
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 (strcmp(argv[2], "load") == 0) {
if (argc < 3) {
terminal_write("image ID missing\n");
return (84);
}
struct himage *img = hyp_get_image(atoi(argv[3]));
if (img == NULL) {
terminal_write("image ID invalid\n");
return (84);
}
if (hypervisor_loader(img) != 0)
return (84);
terminal_write("image successfully loaded\n");
return (0);
}
if (strcmp(argv[2], "dyn") == 0) {
if (argc < 3) {
terminal_write("image ID missing\n");
return (84);
}
struct himage *img = hyp_get_image(atoi(argv[3]));
if (img == NULL) {
terminal_write("image ID invalid\n");
return (84);
}
return (hypervisor_elf_loader_dynamic_check(img->private));
}
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);
}
/* hyp_os_module(): Handle argument for the os module part */
static int hyp_os_module(int argc, char **argv)
{
if (argc < 2)
goto error;
if (strcmp(argv[2], "ls") == 0) {
int counter = 0;
char line[32];
struct hworld *world = hypervisor_wswitch_queue_get();
int sp = (terminal.winsize.ws_col - 4) / 3;
snprintf(line, 32, "%%-3s%%-%ds%%-%ds%%s\n", sp, sp);
terminal_write(line, "ID", "NAME", "ENV", "SIZE");
snprintf(line, 32, "%%-3d%%-%ds%%-%ds%%do\n", sp, sp);
const char *env = NULL;
while (world != NULL) {
env = "Casio";
if (world->private.env == HYPERVISOR_ENV_GINT)
env = "Gint";
terminal_write(line,
counter,
world->private.inode->name,
env,
world->memory.program.size);
world = world->private.next;
counter = counter + 1;
}
return (0);
}
if (argc < 3) {
terminal_write("OS ID missing\n");
return (84);
}
int counter = 0;
int id = atoi(argv[3]);
struct hworld *world = hypervisor_wswitch_queue_get();
while (world != NULL) {
if (counter == id)
break;
counter = counter + 1;
world = world->private.next;
}
if (world == NULL) {
terminal_write("image ID invalid\n");
return (84);
}
if (strcmp(argv[2], "run") == 0) {
//FIXME: indicate that the world is running !
//FIXME: check if the world is already running !
if (hypervisor_wswitch(world) != 0)
return (84);
return (0);
}
if (strcmp(argv[2], "trace") == 0) {
//FIXME: indicate that the world is running !
//FIXME: check if the world is already running !
world->private.debug.tracer =
tracer_create_session((void*)world->context.cpu.spc,
TRACER_DISASM
| TRACER_CONTEXT
| TRACER_HEXDUMP);
if (world->private.debug.tracer == NULL) {
terminal_write("tracer session error\n");
return (84);
}
if (hypervisor_wswitch(world) != 0)
return (84);
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);
}
/* hyp_install(): Installer interface */
static int hyp_install(int argc, char **argv)
{
extern void *hypervisor_vbr_exch;
extern void *hypervisor_vbr_tlbh;
extern void *hypervisor_vbr_inth;
extern void *hypervisor_vbr;
if (argc < 2)
goto error;
if (strcmp(argv[2], "debug") == 0) {
terminal_write("VBR: %p\n", hypervisor_vbr_exch - 0x100);
terminal_write("exch: %p\n", hypervisor_vbr_exch);
terminal_write("tlbh: %p\n", hypervisor_vbr_tlbh);
terminal_write("inth: %p\n", hypervisor_vbr_inth);
return (0);
}
if (strcmp(argv[2], "now") == 0) {
hypervisor_install();
terminal_write("installed at <%p>\n", hypervisor_vbr);
return (0);
}
error:
terminal_write("\"hyp install\" requiere at least 1 argument\n");
terminal_write("\n");
terminal_write("Hypervisor installer\n");
terminal_write("\n");
terminal_write("commands:\n");
terminal_write(" debug Display hypervisor low level information\n");
return (0);
}
//---
// 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(argc, argv));
if (strcmp(argv[1], "trap") == 0) {
int allo;
__asm__ volatile ("trapa #0; mov r0, %0":"=r"(allo));
return (allo);
}
}
/* 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);
}