256 lines
6.3 KiB
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);
|
|
}
|