v0.1.0 - Hypervisor refactoring
@add * create hypervisor module * refacto hypervisor interface (hyp builtin) @update * ELF scanning: check ELF header validity instead of file extension * improve ELF scanning
This commit is contained in:
parent
95333b656d
commit
63db69e784
|
@ -6,5 +6,6 @@
|
|||
|
||||
extern int mnt_main(int argc, char **argv);
|
||||
extern int ls_main(int argc, char **argv);
|
||||
extern int hyp_main(int argc, char **argv);
|
||||
|
||||
#endif /*__FXBOOT_BUILTIN_H__*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,7 +42,7 @@ extern struct smemfs_superblock smemfs_superblock;
|
|||
//---
|
||||
extern struct smemfs_inode *smemfs_mount(void);
|
||||
|
||||
extern ssize_t smemfs_read(struct smemfs_inode *inode,
|
||||
extern ssize_t smemfs_pread(struct smemfs_inode *inode,
|
||||
void *buf, size_t count, off_t pos);
|
||||
|
||||
extern struct smemfs_inode *smemfs_alloc_inode(void);
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
#ifndef __FXBOOT_LOADER_H__
|
||||
# define __FXBOOT_LOADER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* define smemfs_*() pirmitive */
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
|
||||
|
||||
#define HYPERVISOR_BSS __attribute__((section(".hypervisor.bss")))
|
||||
|
||||
//---
|
||||
// World switch structure
|
||||
// TODO: move me !
|
||||
//--
|
||||
/* Define the SuperH CPU hardware context */
|
||||
struct cpuctx {
|
||||
uint32_t reg[16];
|
||||
uint32_t gbr;
|
||||
uint32_t macl;
|
||||
uint32_t mach;
|
||||
uint32_t ssr;
|
||||
uint32_t spc;
|
||||
uint32_t pr;
|
||||
};
|
||||
|
||||
struct hworld {
|
||||
/* hardware context */
|
||||
struct {
|
||||
struct cpuctx cpu;
|
||||
} context;
|
||||
|
||||
/* memory information */
|
||||
struct {
|
||||
struct {
|
||||
void *start;
|
||||
size_t size;
|
||||
} program;
|
||||
} memory;
|
||||
|
||||
/* private information (used by the hypeviseur) */
|
||||
struct {
|
||||
struct smemfs_inode *inode;
|
||||
struct worldctx *next;
|
||||
} private;
|
||||
};
|
||||
|
||||
|
||||
struct himage {
|
||||
const char *name;
|
||||
void *private;
|
||||
struct himage *next;
|
||||
};
|
||||
|
||||
//---
|
||||
// Loader interface
|
||||
//---
|
||||
|
||||
/* hypervisor_loader(): Load the IMAGE into memory.
|
||||
|
||||
The loader will relocalise the IMAGE that is an ELF program compiled in PIE.
|
||||
The fact that if the image use Gint as a shared librarie then the loader
|
||||
will automatically resolve missing symbols.
|
||||
|
||||
Note that the hypervisor does not support shared libraries "on-calc" because
|
||||
GCC cannot generate shared libraries for the SuperH archtiecture. Gint is
|
||||
only possible because the hypervisor known where is located the kernel and
|
||||
all of these symbols name is hardcoded to allow symbols resolving.
|
||||
|
||||
@params
|
||||
(in) image hypervisor image that can be get using the
|
||||
"hypervisor_loader_list()" function
|
||||
|
||||
@return
|
||||
0 if successfully loaded
|
||||
negative if error occur */
|
||||
extern int hypervisor_loader(struct himage *image);
|
||||
|
||||
|
||||
/* hypervisor_loader_list(): Generate the list all loadable image
|
||||
|
||||
The hypervisor will scan all files into the SMEM storage memory and will
|
||||
check if the file is an ELF format with PIE encoding.
|
||||
|
||||
Note that the generated list should be destroyed using the
|
||||
"hypervisor_loader_list_destroy()" function.
|
||||
|
||||
@param
|
||||
(out) list list that will be generated
|
||||
|
||||
@return
|
||||
possitive The number of valid file
|
||||
0 No file can be loadable
|
||||
negative if error occur */
|
||||
extern int hypervisor_loader_list(struct himage **list);
|
||||
|
||||
/* hypervisor_loader_list_destroy(): Destroy the image list
|
||||
|
||||
This function will destroy the list generates by the
|
||||
"hypervisor_loader_list()" function.
|
||||
|
||||
@params
|
||||
(out) list List that will be destroyed and set to NULL */
|
||||
extern void hypervisor_loader_list_destroy(struct himage **list);
|
||||
|
||||
#endif /*__FXBOOT_LOADER_H__*/
|
|
@ -57,8 +57,8 @@ CFLAGS += -Wall -Wextra -Wno-missing-field-initializers -Os
|
|||
# be able to include files with #include<>. The Makefile provides a variable
|
||||
# GCC_INCLUDE_FX/GCC_INCLUDE_CG that represents the default include folder,
|
||||
# which is useful for some libraries such as OpenLibm.
|
||||
INCLUDE_FX = -I include
|
||||
INCLUDE_CG = -I include
|
||||
INCLUDE_FX = -I include -I.
|
||||
INCLUDE_CG = -I include -I.
|
||||
|
||||
# Libraries. Add one -l option for each library you are using, and also
|
||||
# suitable -L options if you have library files in custom folders. To use
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
//---
|
||||
// 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);
|
||||
}
|
|
@ -4,8 +4,39 @@
|
|||
#include "fxBoot/builtin.h"
|
||||
#include "fxBoot/terminal.h"
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/bfile.h>
|
||||
|
||||
static void smemfs_generate_path(volatile char **path,
|
||||
struct smemfs_inode *inode)
|
||||
{
|
||||
if (inode == NULL)
|
||||
return;
|
||||
smemfs_generate_path(path, inode->parent);
|
||||
size_t length = strlen(inode->name);
|
||||
memcpy((void*)*path, inode->name, length);
|
||||
(*path)[length] = '\0';
|
||||
*path = &(*path)[length];
|
||||
}
|
||||
|
||||
static void smemfs_find(struct smemfs_inode *inode, char *buffer)
|
||||
{
|
||||
const char *ext;
|
||||
|
||||
if (inode == NULL)
|
||||
return;
|
||||
smemfs_find(inode->child, buffer);
|
||||
ext = strrchr(inode->name, '.');
|
||||
if (ext != NULL) {
|
||||
if (strcmp(ext, ".elf") == 0) {
|
||||
smemfs_generate_path((volatile char **)&buffer, inode);
|
||||
/* TODO: check ELF validity */
|
||||
terminal_write("(%x) %s\n", inode->type, inode->name);
|
||||
}
|
||||
}
|
||||
smemfs_find(inode->sibling, buffer);
|
||||
}
|
||||
|
||||
static void smemfs_walk(struct smemfs_inode *inode, int level, uint32_t bitmap)
|
||||
{
|
||||
const char *records;
|
||||
|
@ -22,13 +53,13 @@ static void smemfs_walk(struct smemfs_inode *inode, int level, uint32_t bitmap)
|
|||
}
|
||||
|
||||
/* handle file name and sibling dependencies */
|
||||
records = "|-- %s";
|
||||
records = "|-- (%x) %s";
|
||||
bitmap |= 1 << level;
|
||||
if (inode->sibling == NULL) {
|
||||
records = "`-- %s";
|
||||
records = "`-- (%x) %s";
|
||||
bitmap &= ~(1 << level);
|
||||
}
|
||||
terminal_write(records, inode->name);
|
||||
terminal_write(records, inode->type, inode->name);
|
||||
|
||||
/* handle file type */
|
||||
if (inode->type == BFile_Type_Directory) {
|
||||
|
@ -43,13 +74,16 @@ static void smemfs_walk(struct smemfs_inode *inode, int level, uint32_t 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");
|
||||
if (argc > 1 && strcmp(argv[1], "-elf") == 0) {
|
||||
char buffer[512];
|
||||
smemfs_find(smemfs_superblock.root_inode, buffer);
|
||||
return (0);
|
||||
}
|
||||
terminal_write("/:\n");
|
||||
smemfs_walk(smemfs_superblock.root_inode, 0, 0x00000000);
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ static void dump_smem_level(struct smemfs_inode *parent,
|
|||
struct smemfs_inode *inode;
|
||||
uint16_t buffer[32];
|
||||
int handle;
|
||||
int i;
|
||||
|
||||
/* Generate searching path:
|
||||
This format is used by the `Bfile_Find*()` syscall */
|
||||
|
@ -53,7 +52,6 @@ static void dump_smem_level(struct smemfs_inode *parent,
|
|||
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 */
|
||||
|
@ -62,9 +60,8 @@ static void dump_smem_level(struct smemfs_inode *parent,
|
|||
break;
|
||||
|
||||
/* Save the first inode (used after for directories checking) */
|
||||
if (i == 0)
|
||||
if (inode == NULL)
|
||||
inode = *sibling;
|
||||
i = 1;
|
||||
|
||||
/* Convert wide char to ASCII */
|
||||
wide_char_convert((*sibling)->name, buffer);
|
||||
|
|
|
@ -39,7 +39,7 @@ static void generate_absolute_path(uint16_t *pathname,
|
|||
/* bfile_abstract(): */
|
||||
|
||||
/* smemfs_read(): Read primitive */
|
||||
ssize_t smemfs_read(struct smemfs_inode *inode,
|
||||
ssize_t smemfs_pread(struct smemfs_inode *inode,
|
||||
void *buf, size_t count, off_t pos)
|
||||
{
|
||||
uint16_t pathname[64];
|
|
@ -0,0 +1,16 @@
|
|||
//---
|
||||
// fxBoot:hypervisor:config - Configuration interface
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
|
||||
//---
|
||||
// User API
|
||||
//---
|
||||
/* hypervisor_wswitch_config(): Try to configure the hypervisor wswitch part */
|
||||
int hypervisor_config(int config, ...)
|
||||
{
|
||||
//TODO: key remap.
|
||||
//TODO: return behvious to hypervisor interface.
|
||||
//TODO: remap hypervisor interface key combos
|
||||
(void)config;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#if 0
|
||||
.section .hypervisor.text, "ax"
|
||||
.global _hypervisor_install
|
||||
|
||||
.align 2
|
||||
_hypervisor_install:
|
||||
/* check if the hypervisor is installed */
|
||||
stc vbr, r0
|
||||
mov.l hypervisor_vbr, r1
|
||||
cmp/eq r1, r0
|
||||
bf install
|
||||
rts
|
||||
mov #-1, r0
|
||||
|
||||
install:
|
||||
/* Block all interrupts by setting IMASK=15 */
|
||||
mov #0xf, r0
|
||||
shll2 r0
|
||||
shll2 r0
|
||||
stc sr, r2
|
||||
or r2, r0
|
||||
ldc r0, sr
|
||||
|
||||
/* install the hypervisor */
|
||||
ldc r1, vbr
|
||||
|
||||
/* restore VBR then exit */
|
||||
ldc r2, sr
|
||||
rts
|
||||
xor r0, r0
|
||||
|
||||
.align 4
|
||||
hypervisor_vbr:
|
||||
.long _hypervisor_vbr
|
||||
#endif
|
|
@ -0,0 +1,14 @@
|
|||
//---
|
||||
// hypervisor:install - Hypervisor installation
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
|
||||
//---
|
||||
// User API
|
||||
//---
|
||||
/* hypervisor_install(): Install the hypervisor */
|
||||
int hypervisor_install(void)
|
||||
{
|
||||
//TODO:generate the world context for the interface
|
||||
//TODO: switch VBR
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef __HYPERVISOR_INTERNAL_H__
|
||||
# define __HYPERVISOR_INTERNAL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/elf.h"
|
||||
|
||||
//---
|
||||
// Error helpers
|
||||
//---
|
||||
struct hel_error_db {
|
||||
const int id;
|
||||
const char *strerror;
|
||||
};
|
||||
extern int hypervisor_elf_loader_error(const struct hel_error_db *db,
|
||||
const char *prefix, int errnum);
|
||||
|
||||
//---
|
||||
// ELF Header helpers
|
||||
//---
|
||||
enum {
|
||||
hel_header_valid = 0,
|
||||
hel_header_size_error = -1,
|
||||
hel_header_magic_error = -2,
|
||||
hel_header_class_error = -3,
|
||||
hel_header_indent_error = -4,
|
||||
hel_header_type_error = -5,
|
||||
hel_header_machine_error = -6,
|
||||
hel_header_version_error = -7,
|
||||
};
|
||||
extern int hypervisor_elf_loader_header_get(struct smemfs_inode*,Elf32_Ehdr*);
|
||||
extern int hypervisor_elf_loader_header_check(struct smemfs_inode *inode);
|
||||
extern int hypervisor_elf_loader_header_error(int errnum);
|
||||
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// ELF image helpers
|
||||
//---
|
||||
enum {
|
||||
hel_image_success = 0,
|
||||
hel_image_size_error = -1,
|
||||
hel_image_type_error = -2,
|
||||
hel_image_mem_error = -3,
|
||||
};
|
||||
extern int hypervisor_elf_loader_image_load(struct hworld *world,
|
||||
struct smemfs_inode *inode, Elf32_Ehdr *header);
|
||||
extern int hypervisor_elf_loader_image_error(int errnum);
|
||||
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// ELF symbols relocatlisation helpers
|
||||
//---
|
||||
enum {
|
||||
hel_reloc_success = 0,
|
||||
hel_reloc_size_error = -1,
|
||||
hel_reloc_error = -2,
|
||||
};
|
||||
extern int hypervisor_elf_loader_reloc_sym(struct hworld *world,
|
||||
struct smemfs_inode *inode, Elf32_Ehdr *header);
|
||||
extern int hypervisor_elf_loader_reloc_error(int errnum);
|
||||
#endif /*__HYPERVISOR_INTERNAL_H__*/
|
|
@ -0,0 +1,52 @@
|
|||
//---
|
||||
// fxBoot:hypervisor:loader:entry - ELF Loader entry
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
#include "fxBoot/terminal.h"
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/elf.h"
|
||||
|
||||
/* internal header */
|
||||
#include "../src/hypervisor/internal/elf.h"
|
||||
|
||||
/* loader_entry(): Load a ELF programm (PIE) */
|
||||
int hypervisor_elf_loader(struct hworld *world, struct smemfs_inode *inode)
|
||||
{
|
||||
Elf32_Ehdr header;
|
||||
int err;
|
||||
|
||||
if (world == NULL)
|
||||
return (-1);
|
||||
|
||||
/* save private information */
|
||||
terminal_write("hypervisor:\n");
|
||||
terminal_write("- load the inode \"%s\"\n", inode->name);
|
||||
world->private.inode = inode;
|
||||
|
||||
/* Try to get the ELF header information */
|
||||
terminal_write("- check header information\n");
|
||||
err = hypervisor_elf_loader_header_get(inode, &header);
|
||||
if (err != 0)
|
||||
return (-2);
|
||||
|
||||
/* Get / Check program validity */
|
||||
terminal_write("- load image\n");
|
||||
err = hypervisor_elf_loader_image_load(world, inode, &header);
|
||||
if (err != 0)
|
||||
return (-3);
|
||||
|
||||
/* Relocalise sections / symbols */
|
||||
terminal_write("- relocalise static symbols\n");
|
||||
err = hypervisor_elf_loader_reloc_sym(world, inode, &header);
|
||||
if (err != 0)
|
||||
return (-4);
|
||||
|
||||
#if 0
|
||||
/* Relocalise Gint symbols */
|
||||
terminal_write("- relocalise shared symbols\n");
|
||||
err = hypervisor_elf_loader_reloc_gint(world, inode, &header);
|
||||
if (err != 0)
|
||||
return (-5);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
//---
|
||||
// elf/error - error engine
|
||||
//---
|
||||
#include "fxBoot/terminal.h"
|
||||
#include "./src/hypervisor/internal/elf.h"
|
||||
|
||||
/* hypervisor_elf_loader_error(): Display error information */
|
||||
int hypervisor_elf_loader_error(const struct hel_error_db *db,
|
||||
const char *prefix, int errnum)
|
||||
{
|
||||
for (int i = 0; db[i].strerror != NULL; ++i) {
|
||||
if (db[i].id != errnum)
|
||||
continue;
|
||||
terminal_write("%s %s\n", prefix, db[i].strerror);
|
||||
return (0);
|
||||
}
|
||||
return (-1);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
//---
|
||||
// fxBoot:loader:header - Check ELF header
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
#include "fxBoot/terminal.h"
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/elf.h"
|
||||
|
||||
#include "./src/hypervisor/internal/elf.h"
|
||||
|
||||
/* error string list */
|
||||
const struct hel_error_db header_error_db[] = {
|
||||
{.id = hel_header_valid, .strerror = "valid"},
|
||||
{.id = hel_header_size_error, .strerror = "size error"},
|
||||
{.id = hel_header_magic_error, .strerror = "magic error"},
|
||||
{.id = hel_header_class_error, .strerror = "class error"},
|
||||
{.id = hel_header_indent_error, .strerror = "indent error"},
|
||||
{.id = hel_header_type_error, .strerror = "type error"},
|
||||
{.id = hel_header_machine_error, .strerror = "machine error"},
|
||||
{.id = hel_header_version_error, .strerror = "version error"},
|
||||
{.id = 0xdeb0cad0, .strerror = NULL},
|
||||
};
|
||||
|
||||
/* hypervisor_elf_loader_header_error(): Display header error information */
|
||||
int hypervisor_elf_loader_header_error(int errnum)
|
||||
{
|
||||
return (hypervisor_elf_loader_error(header_error_db,
|
||||
"ELF header", errnum));
|
||||
}
|
||||
|
||||
/* hypervisor_elf_loader_header_get(): Get ELF header and check validity */
|
||||
int hypervisor_elf_loader_header_get(struct smemfs_inode *inode,
|
||||
Elf32_Ehdr *header)
|
||||
{
|
||||
/* try to read the ELF header */
|
||||
if (smemfs_pread(inode, header, sizeof(*header), 0) != sizeof(*header))
|
||||
return (hel_header_size_error);
|
||||
|
||||
/* Check magic number */
|
||||
if (header->e_ident[EI_MAG0] != ELFMAG0
|
||||
|| header->e_ident[EI_MAG1] != ELFMAG1
|
||||
|| header->e_ident[EI_MAG2] != ELFMAG2
|
||||
|| header->e_ident[EI_MAG3] != ELFMAG3) {
|
||||
return (hel_header_magic_error);
|
||||
}
|
||||
|
||||
/* Check class */
|
||||
if (header->e_ident[EI_CLASS] != ELFCLASS32)
|
||||
return (hel_header_class_error);
|
||||
|
||||
/* Check data encoding */
|
||||
if (header->e_ident[EI_DATA] != ELFDATA2MSB)
|
||||
return (hel_header_indent_error);
|
||||
|
||||
/* Check ELF type */
|
||||
if (header->e_type != ET_DYN)
|
||||
return (hel_header_type_error);
|
||||
|
||||
/* Check ELF specifique instruction */
|
||||
if (header->e_machine != EM_SH)
|
||||
return (hel_header_machine_error);
|
||||
|
||||
/* Check ELF version */
|
||||
if (header->e_version != EV_CURRENT)
|
||||
return (hel_header_version_error);
|
||||
return (hel_header_valid);
|
||||
}
|
||||
|
||||
/* hypervisor_elf_loader_header_check(): Check ELF header validity */
|
||||
int hypervisor_elf_loader_header_check(struct smemfs_inode *inode)
|
||||
{
|
||||
Elf32_Ehdr header;
|
||||
return (hypervisor_elf_loader_header_get(inode, &header));
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
//---
|
||||
// fxBoot:loader:entry - ELF Loader entry
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/elf.h"
|
||||
|
||||
#include <gint/std/stdlib.h>
|
||||
#include <gint/std/string.h>
|
||||
|
||||
#include "./src/hypervisor/internal/elf.h"
|
||||
|
||||
/* error string list */
|
||||
const struct hel_error_db image_error_db[] = {
|
||||
{.id = hel_image_success, .strerror = "valid"},
|
||||
{.id = hel_image_size_error, .strerror = "size error"},
|
||||
{.id = hel_image_type_error, .strerror = "type error"},
|
||||
{.id = hel_image_mem_error, .strerror = "out of memory error"},
|
||||
{.id = 0xdeb0cad0, .strerror = NULL},
|
||||
};
|
||||
|
||||
/* hypervisor_elf_loader_image_error(): Display image error information */
|
||||
int hypervisor_elf_loader_image_error(int errnum)
|
||||
{
|
||||
return (hypervisor_elf_loader_error(image_error_db,
|
||||
"ELF image ", errnum));
|
||||
}
|
||||
|
||||
/* loader_load_image() - Load the program into Virtual Memory */
|
||||
int hypervisor_elf_loader_image_load(struct hworld *world,
|
||||
struct smemfs_inode *inode, Elf32_Ehdr *header)
|
||||
{
|
||||
Elf32_Phdr program;
|
||||
void *paddress;
|
||||
off_t offset;
|
||||
uint16_t i;
|
||||
|
||||
/* Walk one time to get the entier program size and check ELF
|
||||
validity. */
|
||||
i = -1;
|
||||
world->memory.program.size = 0;
|
||||
while (++i < header->e_phnum) {
|
||||
offset = header->e_phoff + (i * sizeof(Elf32_Phdr));
|
||||
if (smemfs_pread(inode, &program, sizeof(Elf32_Phdr), offset)
|
||||
!= sizeof(Elf32_Phdr)) {
|
||||
return (hel_image_size_error);
|
||||
}
|
||||
if (program.p_type != PT_LOAD)
|
||||
return (hel_image_type_error);
|
||||
world->memory.program.size += program.p_memsz;
|
||||
}
|
||||
|
||||
/* Allocate programe memory */
|
||||
world->memory.program.start = calloc(world->memory.program.size, 1);
|
||||
if (world->memory.program.start == NULL)
|
||||
return (hel_image_mem_error);
|
||||
|
||||
/* Now, load all program section into physical memory. To do this, we
|
||||
read each program header, generate the "real" physical address of
|
||||
the segment then dump data.
|
||||
|
||||
Nota that the p_inodesz can be smaller than p_memsz so, we need to
|
||||
wipe the segment area before the dump. */
|
||||
i = -1;
|
||||
while (++i < header->e_phnum) {
|
||||
offset = header->e_phoff + (i * sizeof(Elf32_Phdr));
|
||||
smemfs_pread(inode, &program, sizeof(Elf32_Phdr), offset);
|
||||
|
||||
paddress = program.p_vaddr + world->memory.program.start;
|
||||
|
||||
memset(paddress, 0, program.p_memsz);
|
||||
smemfs_pread(inode, paddress,
|
||||
program.p_filesz, program.p_offset);
|
||||
}
|
||||
|
||||
/* Generate program entry address */
|
||||
world->context.cpu.spc = (uint32_t)header->e_entry;
|
||||
world->context.cpu.spc += (uintptr_t)world->memory.program.start;
|
||||
return (hel_image_success);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
//---
|
||||
// fxBoot:loader:entry - ELF Loader entry
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/elf.h"
|
||||
|
||||
#include "./src/hypervisor/internal/elf.h"
|
||||
|
||||
//---
|
||||
// Internal helpers
|
||||
//---
|
||||
/* reloc_section(): Relocalise section's symbols */
|
||||
static int reloc_section(struct hworld *world,
|
||||
struct smemfs_inode *inode, Elf32_Shdr *shdr)
|
||||
{
|
||||
Elf32_Rela rela;
|
||||
uint32_t *prog;
|
||||
off_t offset;
|
||||
|
||||
/* List symbols */
|
||||
prog = (void*)world->memory.program.start;
|
||||
for (uint32_t i = 0 ; i < shdr->sh_size / shdr->sh_entsize ; ++i) {
|
||||
/* Get relocatable symbol information */
|
||||
offset = shdr->sh_offset + (i * shdr->sh_entsize);
|
||||
if (smemfs_pread(inode, &rela, shdr->sh_entsize, offset)
|
||||
!= (ssize_t)shdr->sh_entsize) {
|
||||
return (hel_reloc_size_error);
|
||||
}
|
||||
|
||||
/* Relocalise the symbol */
|
||||
prog[rela.r_offset >> 2] +=
|
||||
(uintptr_t)world->memory.program.start;
|
||||
}
|
||||
return (hel_reloc_success);
|
||||
}
|
||||
|
||||
//---
|
||||
// Public helpers
|
||||
//---
|
||||
/* loader_reloc_sym(): Relocalise all symbols */
|
||||
int hypervisor_elf_loader_reloc_sym(struct hworld *world,
|
||||
struct smemfs_inode *inode, Elf32_Ehdr *header)
|
||||
{
|
||||
Elf32_Shdr shdr;
|
||||
off_t offset;
|
||||
|
||||
for (int i = 1 ; i < header->e_shnum ; ++i) {
|
||||
offset = header->e_shoff + (i * header->e_shentsize);
|
||||
if (smemfs_pread(inode, &shdr, header->e_shentsize, offset)
|
||||
!= header->e_shentsize) {
|
||||
return (hel_reloc_size_error);
|
||||
}
|
||||
if (shdr.sh_type != SHT_RELA)
|
||||
continue;
|
||||
if (reloc_section(world, inode, &shdr) != hel_reloc_success)
|
||||
return (hel_reloc_error);
|
||||
}
|
||||
return (hel_reloc_success);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _SRC_HYPERVISOR_LOADER_LOADER_H__
|
||||
# define _SRC_HYPERVISOR_LOADER_LOADER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* internal definition */
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/elf.h"
|
||||
|
||||
//---
|
||||
// Internal primitive
|
||||
//---
|
||||
extern int loader_get_header(struct smemfs_inode *file, Elf32_Ehdr *header);
|
||||
extern int loader_load_image(struct worldctx *worldctx,
|
||||
struct smemfs_inode *file, Elf32_Ehdr *header);
|
||||
|
||||
extern int loader_reloc_sym(struct worldctx *worldctx,
|
||||
struct smemfs_inode *file, Elf32_Ehdr *header);
|
||||
|
||||
#endif /*_SRC_HYPERVISOR_LOADER_LOADER_H__*/
|
|
@ -0,0 +1,70 @@
|
|||
//---
|
||||
// fxBoot:hypervisor:loader - ELF loader interface
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
#include "fxBoot/terminal.h"
|
||||
|
||||
#include "./src/hypervisor/internal/elf.h"
|
||||
|
||||
#include <gint/std/stdlib.h>
|
||||
#include <gint/bfile.h>
|
||||
|
||||
//---
|
||||
// Internal helpers
|
||||
//---
|
||||
/* hypervisor_get_image_list(): Dump all ELF file stored into the SMEM */
|
||||
static int hypervisor_get_img_list(struct himage ***image,
|
||||
struct smemfs_inode *inode)
|
||||
{
|
||||
if (inode == NULL)
|
||||
return (0);
|
||||
|
||||
int counter = 0;
|
||||
if (inode->type != BFile_Type_Archived) {
|
||||
counter += hypervisor_get_img_list(image, inode->child);
|
||||
goto anchor;
|
||||
}
|
||||
if (hypervisor_elf_loader_header_check(inode) == hel_header_valid) {
|
||||
(**image) = calloc(sizeof(struct himage), 1);
|
||||
if ((**image) == NULL) {
|
||||
terminal_write("hypervisor: out of memory :(\n");
|
||||
goto anchor;
|
||||
}
|
||||
(**image)->name = inode->name;
|
||||
(**image)->private = inode;
|
||||
*image = &((**image)->next);
|
||||
}
|
||||
anchor:
|
||||
return (hypervisor_get_img_list(image, inode->sibling) + counter);
|
||||
}
|
||||
|
||||
//---
|
||||
// User API
|
||||
//---
|
||||
/* hypervisor_loader(): Load a ELF (must be PIE) and start it */
|
||||
int hypervisor_loader(struct himage *image)
|
||||
{
|
||||
(void)image;
|
||||
//TODO: create a new world context
|
||||
//TODO: try to load the image
|
||||
//TODO: link the new world context
|
||||
//TODO: perform a world switch.
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* hypervisor_loader_list(): Return a list of all supported file on SMEM */
|
||||
int hypervisor_loader_list(struct himage **list)
|
||||
{
|
||||
return (hypervisor_get_img_list(&list, smemfs_superblock.root_inode));
|
||||
}
|
||||
|
||||
/* hypervisor_loader_list_destroy(): Destroy the image image list */
|
||||
void hypervisor_loader_list_destroy(struct himage **list)
|
||||
{
|
||||
if (list == NULL || *list == NULL)
|
||||
return;
|
||||
hypervisor_loader_list_destroy(&(*list)->next);
|
||||
free(*list);
|
||||
*list = NULL;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#if 0
|
||||
.section .hypervisor.interrupt, "ax"
|
||||
.global _hypervisor_inth
|
||||
|
||||
.align 2
|
||||
_hypervisor_inth:
|
||||
/* save interrupt related information */
|
||||
sts.l mach, @-r15
|
||||
sts.l macl, @-r15
|
||||
stc.l gbr, @-r15
|
||||
stc.l spc, @-r15
|
||||
stc.l ssr, @-r15
|
||||
sts.l pr, @-r15
|
||||
|
||||
/* check manually the keyboard status to see if the we need to
|
||||
perform a world switch */
|
||||
mov.l hypervisor_wswitch_check, r0
|
||||
jsr @r0
|
||||
nop
|
||||
mov.l r0, @-r15
|
||||
|
||||
/* involve the "real" vbr handler */
|
||||
mov.l hypervisor_inth_second_part, r0
|
||||
ldc r0, vbr
|
||||
mov.l hypervisor_current_vbr, r0
|
||||
mov.l @r0, r0
|
||||
mov #0x06, r1
|
||||
shll8 r1
|
||||
add r1, r0
|
||||
jsr @r0
|
||||
nop
|
||||
|
||||
hypervisor_inth_prologue:
|
||||
/* check if world switch is requested */
|
||||
mov.l @r15+, r0
|
||||
tst r0, r0
|
||||
bf.s hypervisor_inth_exit
|
||||
mov.l hypervisor_wswitch, r0
|
||||
jsr @r0
|
||||
nop
|
||||
|
||||
|
||||
hypervisor_inth_exit:
|
||||
/* restore the saved information */
|
||||
lds.l @r15+, pr
|
||||
ldc.l @r15+, ssr
|
||||
ldc.l @r15+, spc
|
||||
ldc.l @r15+, gbr
|
||||
lds.l @r15+, macl
|
||||
rte
|
||||
lds.l @r15+, mach
|
||||
|
||||
.align 4
|
||||
hypervisor_wswitch_check: .long _hypervisor_worldswitch_check
|
||||
hypervisor_wswitch: .long _hypervisor_worldswitch
|
||||
hypervisor_current_vbr: .long _hypervisor_current_vbr
|
||||
hypervisor_vbr: .long _hypervisor_vbr
|
||||
hypervisor_inth_second_part: .long hypervisor_inth_prologue
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
//---
|
||||
// hypervisor:wsiwtch - hypervisor world switch
|
||||
//---
|
||||
#include "fxBoot/hypervisor.h"
|
||||
|
||||
/* internal globals information */
|
||||
HYPERVISOR_BSS void *hypervisor_current_vbr = NULL;
|
||||
HYPERVISOR_BSS struct hworld *hypervisor_world_queue = NULL;
|
||||
|
||||
//---
|
||||
// User API
|
||||
//---
|
||||
/* hypervisor_wswitch_check(): Check if a world switch is needed */
|
||||
int hypervisor_wswitch_check(void)
|
||||
{
|
||||
//TODO: scan the KEYSC registers
|
||||
}
|
||||
|
||||
/* hypervisor_wswitch(): Perform a world switch */
|
||||
int hypervisor_wswitch(void)
|
||||
{
|
||||
//TODO: display menu
|
||||
//TODO: perform a world switch woth the next world context
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#include "fxBoot/terminal.h"
|
||||
#include "fxBoot/parser.h"
|
||||
#include "fxBoot/builtin.h"
|
||||
#include "fxBoot/fs/smemfs.h"
|
||||
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/display.h>
|
||||
|
@ -12,6 +14,7 @@ struct {
|
|||
} cmd_list[] = {
|
||||
{.name = "mnt", &mnt_main},
|
||||
{.name = "ls", &ls_main},
|
||||
{.name = "hyp", &hyp_main},
|
||||
{.name = NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -37,6 +40,10 @@ int main(void)
|
|||
int argc;
|
||||
int ret;
|
||||
|
||||
/* automated hook */
|
||||
/* TODO: better way to execute early command */
|
||||
smemfs_mount();
|
||||
|
||||
ret = 0;
|
||||
terminal_open();
|
||||
terminal_write("Welcome to fxBoot!\n");
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/make -f
|
||||
## ---
|
||||
## Project: PIE executable
|
||||
## Author: yann.magnin@epitech.eu
|
||||
## ---
|
||||
|
||||
##---
|
||||
## Static variables
|
||||
##--
|
||||
HEADER := -I./include
|
||||
|
||||
NAME := test
|
||||
EXEC := $(NAME).elf
|
||||
LDFLAG := -T $(NAME).ld
|
||||
MEMORY_MAP := $(NAME).map
|
||||
BUILD := build
|
||||
|
||||
|
||||
# Tools
|
||||
COMPILER := sh-elf-
|
||||
CC := $(COMPILER)gcc
|
||||
LD := $(COMPILER)ld
|
||||
OBJCOPY := $(COMPILER)objcopy
|
||||
OBJDUMP := $(COMPILER)objdump
|
||||
WRAPPER := g1a-wrapper
|
||||
|
||||
# Flags
|
||||
CFLAGS := -Werror -Wall -W -Wextra -std=c18 -m3 -mb -mrenesas \
|
||||
-ffreestanding -nostdlib -fstrict-volatile-bitfields \
|
||||
-Wno-unused-const-variable -Wno-unused-function \
|
||||
-Wno-unused-variable -Wno-unused-but-set-variable \
|
||||
-Wno-unused-parameter -Wno-pointer-to-int-cast
|
||||
|
||||
# Colors
|
||||
red := \033[1;31m
|
||||
green := \033[1;32m
|
||||
blue := \033[1;34m
|
||||
white := \033[1;37m
|
||||
nocolor := \033[1;0m
|
||||
|
||||
|
||||
|
||||
##---
|
||||
## Automated variables
|
||||
##---
|
||||
SRC := $(wildcard src/*.[csS])
|
||||
OBJ := $(patsubst %,$(BUILD)/%.o,\
|
||||
$(subst /,_,$(subst src/,,$(basename $(SRC)))))
|
||||
|
||||
|
||||
|
||||
|
||||
##---
|
||||
## General rules
|
||||
##---
|
||||
all: $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJ) | $(DEBUG)
|
||||
$(CC) -pie -Wl,-M $(LDFLAG) $(CFLAGS) -o $@ $(OBJ) $(HEADER) > $(MEMORY_MAP)
|
||||
|
||||
check:
|
||||
@ echo 'src: $(SRC)'
|
||||
@ echo 'obj: $(OBJ)'
|
||||
|
||||
$(BUILD):
|
||||
mkdir -p $@
|
||||
|
||||
|
||||
|
||||
##---
|
||||
## Automated rules
|
||||
##---
|
||||
define rule-src
|
||||
$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1 | $(BUILD)
|
||||
@ printf "compiling $(white)$$<$(nocolor)..."
|
||||
@ $(CC) -pie -DFXCG50 $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
|
||||
@ printf "$(green)[ok]$(nocolor)\n"
|
||||
endef
|
||||
|
||||
$(foreach source,$(SRC),$(eval \
|
||||
$(call rule-src,$(source))) \
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
##---
|
||||
## Cleaning rules
|
||||
##---
|
||||
clean:
|
||||
rm -rf $(BUILD)
|
||||
|
||||
fclean: clean
|
||||
rm -f $(EXEC)
|
||||
|
||||
re: fclean all
|
||||
|
||||
|
||||
|
||||
|
||||
.PHONY: re fclean clean all install
|
|
@ -0,0 +1,75 @@
|
|||
#ifndef __CASIO_H__
|
||||
# define __CASIO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Internal Casio datat structure
|
||||
struct rect
|
||||
{
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
};
|
||||
|
||||
//
|
||||
// Casio prototypes.
|
||||
//
|
||||
/* Bdisp_putDisp_DD - display Casio's VRAM */
|
||||
void casio_Bdisp_PutDisp_DD(void);
|
||||
|
||||
/* GetKey() - display Casio's VRAM and wait keyboard input. */
|
||||
void casio_GetKey(unsigned int *key);
|
||||
|
||||
/* Bdisp_AllClr_VRAM() - clear entirely the Casio's VRAM */
|
||||
void casio_Bdisp_AllClr_VRAM(void);
|
||||
|
||||
/* Bdisp_AreaClr_VRAM() - clear only VRAM area. */
|
||||
void casio_Bdisp_AreaClr_VRAM(const struct rect *buf);
|
||||
|
||||
/* PrintMini() - print string in Casio's VRAM (and display on screen ?) */
|
||||
void casio_PrintMini(size_t x, size_t y, char const *str, int mode);
|
||||
|
||||
/* Bdisp_DrawLine_VRAM() - draw line in Casio's VRAM. */
|
||||
void casio_Bdisp_DrawLine_VRAM(int x1, int y1, int x2, int y2);
|
||||
|
||||
/* Bdisp_AreaReverseVRAM() - reverse area in Casio's VRAM */
|
||||
void casio_Bdisp_AreaReverseVRAM(int x0, int y0, int x1, int y1);
|
||||
|
||||
/* RestoreDisp() - restore saved screen. */
|
||||
void casio_RestoreDisp(unsigned char page);
|
||||
|
||||
/* SaveDisp() - save the content of the screen. */
|
||||
void casio_SaveDisp(unsigned char page);
|
||||
|
||||
/* Malloc() - malloc syscall */
|
||||
void *casio_Malloc(size_t size);
|
||||
|
||||
/* Free() - free syscall */
|
||||
void *casio_Free(void *ptr);
|
||||
|
||||
int casio_Bfile_CreateFile(const uint16_t *name, int type, size_t *size);
|
||||
int casio_Bfile_OpenFile(const uint16_t *name, int useless_flags);
|
||||
int casio_Bfile_WriteFile(int handle, const void *buf, size_t size);
|
||||
int casio_Bfile_ReadFile(int handle, void *buf, size_t size, int cursorpos);
|
||||
int casio_Bfile_CloseFile(int handle);
|
||||
|
||||
// Internal casio abstraction.
|
||||
static inline void dclear_area(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
struct rect area = {.left = x1, .top = y1, .right = x2, .bottom = y2};
|
||||
casio_Bdisp_AreaClr_VRAM(&area);
|
||||
}
|
||||
#define print(x, y, str) casio_PrintMini(x, y, str, 0)
|
||||
#define getkey casio_GetKey
|
||||
#define dline_horizontal(y, x1, x2) casio_Bdisp_DrawLine_VRAM(x1, y, x2, y)
|
||||
#define dreverse_area casio_Bdisp_AreaReverseVRAM
|
||||
#define dclear casio_Bdisp_AllClr_VRAM
|
||||
#define display casio_Bdisp_PutDisp_DD
|
||||
#define save_window casio_SaveDisp
|
||||
#define restore_window casio_RestoreDisp
|
||||
#define malloc casio_Malloc
|
||||
#define free casio_Free
|
||||
|
||||
#endif /*__CASIO_H__*/
|
|
@ -0,0 +1,14 @@
|
|||
#include "syscalls.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
casio_Bdisp_AllClr_VRAM();
|
||||
casio_PrintMini(0, 0, "PIE executable test", 0);
|
||||
casio_PrintMini(0, 10, "press [EXIT] key...", 0);
|
||||
casio_Bdisp_PutDisp_DD();
|
||||
|
||||
unsigned int key;
|
||||
while (1) {
|
||||
casio_GetKey(&key);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
.global _casio_GetKey
|
||||
.global _casio_PrintMini
|
||||
.global _casio_Bdisp_PutDisp_DD
|
||||
.global _casio_Bdisp_AllClr_VRAM
|
||||
.global _casio_Bdisp_DrawLine_VRAM
|
||||
.global _casio_Bdisp_AreaReverseVRAM
|
||||
.global _casio_Bdisp_AreaClr_VRAM
|
||||
.global _casio_RestoreDisp
|
||||
.global _casio_SaveDisp
|
||||
.global _casio_Malloc
|
||||
.global _casio_Free
|
||||
|
||||
.type _casio_GetKey, @function
|
||||
.type _casio_PrintMini, @function
|
||||
.type _casio_Bdisp_PutDisp_DD, @function
|
||||
.type _casio_Bdisp_AllClr_VRAM, @function
|
||||
.type _casio_Bdisp_DrawLine_VRAM, @function
|
||||
.type _casio_Bdisp_AreaReverseVRAM, @function
|
||||
.type _casio_Bdisp_AreaClr_VRAM, @function
|
||||
.type _casio_RestoreDisp, @function
|
||||
.type _casio_SaveDisp, @function
|
||||
.type _casio_Malloc, @function
|
||||
.type _casio_Free, @function
|
||||
|
||||
|
||||
.global _casio_Bfile_CreateFile
|
||||
.global _casio_Bfile_OpenFile
|
||||
.global _casio_Bfile_ReadFile
|
||||
.global _casio_Bfile_WriteFile
|
||||
.global _casio_Bfile_CloseFile
|
||||
|
||||
.type _casio_Bfile_CreateFile, @function
|
||||
.type _casio_Bfile_OpenFile, @function
|
||||
.type _casio_Bfile_ReadFile, @function
|
||||
.type _casio_Bfile_WriteFile, @function
|
||||
.type _casio_Bfile_CloseFile, @function
|
||||
|
||||
#define syscall_(id, syscall_table) \
|
||||
mov.l syscall_table, r2 ;\
|
||||
mov.l 1f, r0 ;\
|
||||
jmp @r2 ;\
|
||||
nop ;\
|
||||
.align 4 ;\
|
||||
1: .long id
|
||||
|
||||
#define syscall(id) syscall_(id, syscall_table)
|
||||
|
||||
|
||||
|
||||
#ifdef FX9860G
|
||||
|
||||
_casio_GetKey:
|
||||
syscall(0x90f)
|
||||
|
||||
_casio_PrintMini:
|
||||
syscall(0xc4f)
|
||||
|
||||
_casio_Bdisp_AllClr_VRAM:
|
||||
syscall(0x143)
|
||||
_casio_Bdisp_PutDisp_DD:
|
||||
syscall(0x028)
|
||||
_casio_Bdisp_DrawLine_VRAM:
|
||||
syscall(0x030)
|
||||
_casio_Bdisp_AreaClr_VRAM:
|
||||
syscall(0x14b)
|
||||
_casio_Bdisp_AreaReverseVRAM:
|
||||
syscall(0x14d)
|
||||
|
||||
_casio_Malloc:
|
||||
syscall(0xacd)
|
||||
_casio_Free:
|
||||
syscall(0xacc)
|
||||
|
||||
_casio_Bfile_CreateFile:
|
||||
syscall(0x434)
|
||||
_casio_Bfile_OpenFile:
|
||||
syscall(0x42c)
|
||||
_casio_Bfile_WriteFile:
|
||||
syscall(0x435)
|
||||
_casio_Bfile_ReadFile:
|
||||
syscall(0x432)
|
||||
_casio_Bfile_CloseFile:
|
||||
syscall(0x42d)
|
||||
|
||||
syscall_table:
|
||||
.long 0x80010070
|
||||
#endif /* FXCG9860G */
|
||||
|
||||
|
||||
#ifdef FXCG50
|
||||
|
||||
_casio_GetKey:
|
||||
syscall(0x0eab)
|
||||
|
||||
_casio_PrintMini:
|
||||
sts.l pr, @-r15
|
||||
|
||||
! fxcg50 prototype:
|
||||
! void PrintMinit(int *x, int *y, void *str, int mode, int color, int mode2)
|
||||
mov.l r4, @-r15
|
||||
mov r15, r4 ! x position
|
||||
mov.l r5, @-r15
|
||||
mov r15, r5 ! y posiition
|
||||
mov #0, r7 ! mode
|
||||
mov #0, r0 ! color
|
||||
mov #0, r1 ! mode2
|
||||
mov.l r0, @-r15
|
||||
mov.l r1, @-r15
|
||||
|
||||
! syscall
|
||||
mov.l syscall_table, r2
|
||||
mov.l 1f, r0
|
||||
jsr @r2
|
||||
nop
|
||||
|
||||
! restore stack
|
||||
add #16, r15
|
||||
lds.l @r15+, pr
|
||||
rts
|
||||
nop
|
||||
.align 4
|
||||
1: .long 0x021b
|
||||
|
||||
_casio_Bdisp_AllClr_VRAM:
|
||||
syscall(0x272)
|
||||
_casio_Bdisp_PutDisp_DD:
|
||||
syscall(0x025f)
|
||||
|
||||
_casio_Bfile_CreateFile:
|
||||
syscall(0x1dae)
|
||||
_casio_Bfile_OpenFile:
|
||||
mov #0, r6
|
||||
syscall(0x1da3)
|
||||
_casio_Bfile_CloseFile:
|
||||
syscall(0x1da4)
|
||||
_casio_Bfile_WriteFile:
|
||||
syscall(0x1daf)
|
||||
_casio_Bfile_ReadFile:
|
||||
syscall(0x1dac)
|
||||
|
||||
_casio_Malloc:
|
||||
syscall(0x1f44)
|
||||
_casio_Free:
|
||||
syscall(0x1f42)
|
||||
|
||||
syscall_table:
|
||||
.long 0x80020070
|
||||
|
||||
#endif /* FXCG50 */
|
||||
.end
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,84 @@
|
|||
OUTPUT_FORMAT("elf32-sh", "elf32-sh", "elf32-sh")
|
||||
OUTPUT_ARCH(sh3)
|
||||
ENTRY(_main)
|
||||
|
||||
/*
|
||||
** Linker script for user executables.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
/* virtual memory, read-write segment */
|
||||
userram (WX) : o = 0x00000000, l = 256k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections */
|
||||
.text : {
|
||||
/* Code */
|
||||
*(.text);
|
||||
*(.text.*);
|
||||
|
||||
/* Read-Only data */
|
||||
*(.rodata);
|
||||
*(.rodata.*);
|
||||
|
||||
/* Dynamic symbols */
|
||||
*(.hash)
|
||||
*(.dynsym)
|
||||
*(.dynstr)
|
||||
*(.dynbss)
|
||||
*(.dynamic)
|
||||
|
||||
/* Procedure Linkage Table */
|
||||
*(.plt)
|
||||
|
||||
/* GLobal Offset Table */
|
||||
*(.got.plt)
|
||||
*(.got.*)
|
||||
*(.got)
|
||||
|
||||
/* ???? */
|
||||
*(.rofixup)
|
||||
} > userram
|
||||
|
||||
/* Relocatable sections */
|
||||
.rela.dyn : {
|
||||
*(.rela.plt)
|
||||
*(.rela.got)
|
||||
*(.rela.got.*)
|
||||
*(.rela.*)
|
||||
*(.rela.text)
|
||||
*(.real.data)
|
||||
} > userram
|
||||
|
||||
/* readable / writable data */
|
||||
.data ALIGN(4) : {
|
||||
|
||||
/* Data sections */
|
||||
*(.data);
|
||||
*(.data.*);
|
||||
|
||||
/* bss section included to avoid missaligned segment */
|
||||
*(.bss);
|
||||
*(.bss.*);
|
||||
*(COMMON);
|
||||
} > userram
|
||||
|
||||
/* unwanted section */
|
||||
/DISCARD/ : {
|
||||
*(.gnu.*)
|
||||
*(.debug_info)
|
||||
*(.debug_abbrev)
|
||||
*(.debug_loc)
|
||||
*(.debug_aranges)
|
||||
*(.debug_ranges)
|
||||
*(.debug_line)
|
||||
*(.debug_str)
|
||||
*(.jcr)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
*(.comment)
|
||||
*(.interp)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
build/main.o: dynamic relocation in read-only section `.text'
|
||||
|
||||
Discarded input sections
|
||||
|
||||
.comment 0x0000000000000000 0x13 build/main.o
|
||||
|
||||
Memory Configuration
|
||||
|
||||
Name Origin Length Attributes
|
||||
userram 0x0000000000000000 0x0000000000040000 xw
|
||||
*default* 0x0000000000000000 0xffffffffffffffff
|
||||
|
||||
Linker script and memory map
|
||||
|
||||
LOAD build/main.o
|
||||
LOAD build/syscalls.o
|
||||
|
||||
.text 0x0000000000000000 0x230
|
||||
*(.text)
|
||||
.text 0x0000000000000000 0x68 build/main.o
|
||||
0x0000000000000000 _main
|
||||
*fill* 0x0000000000000068 0x8
|
||||
.text 0x0000000000000070 0xe0 build/syscalls.o
|
||||
0x0000000000000070 _casio_GetKey
|
||||
0x0000000000000084 _casio_PrintMini
|
||||
0x00000000000000b4 _casio_Bdisp_AllClr_VRAM
|
||||
0x00000000000000c4 _casio_Bdisp_PutDisp_DD
|
||||
0x00000000000000d4 _casio_Bfile_CreateFile
|
||||
0x00000000000000e4 _casio_Bfile_OpenFile
|
||||
0x00000000000000f4 _casio_Bfile_CloseFile
|
||||
0x0000000000000104 _casio_Bfile_WriteFile
|
||||
0x0000000000000114 _casio_Bfile_ReadFile
|
||||
0x0000000000000124 _casio_Malloc
|
||||
0x0000000000000134 _casio_Free
|
||||
*(.text.*)
|
||||
*(.rodata)
|
||||
.rodata 0x0000000000000150 0x25 build/main.o
|
||||
*(.rodata.*)
|
||||
*(.hash)
|
||||
*fill* 0x0000000000000175 0x3
|
||||
.hash 0x0000000000000178 0x10 build/main.o
|
||||
*(.dynsym)
|
||||
.dynsym 0x0000000000000188 0x10 build/main.o
|
||||
*(.dynstr)
|
||||
.dynstr 0x0000000000000198 0x1 build/main.o
|
||||
*(.dynbss)
|
||||
.dynbss 0x0000000000000199 0x0 build/main.o
|
||||
*(.dynamic)
|
||||
*fill* 0x0000000000000199 0x3
|
||||
.dynamic 0x000000000000019c 0x88 build/main.o
|
||||
0x000000000000019c _DYNAMIC
|
||||
*(.plt)
|
||||
.plt 0x0000000000000224 0x0 build/main.o
|
||||
*(.got.plt)
|
||||
.got.plt 0x0000000000000224 0xc build/main.o
|
||||
0x0000000000000224 _GLOBAL_OFFSET_TABLE_
|
||||
*(.got.*)
|
||||
.got.funcdesc 0x0000000000000230 0x0 build/main.o
|
||||
*(.got)
|
||||
.got 0x0000000000000230 0x0 build/main.o
|
||||
*(.rofixup)
|
||||
.rofixup 0x0000000000000230 0x0 build/main.o
|
||||
|
||||
.rela.dyn 0x0000000000000230 0x48
|
||||
*(.rela.plt)
|
||||
.rela.plt 0x0000000000000230 0x0 build/main.o
|
||||
*(.rela.got)
|
||||
.rela.got 0x0000000000000230 0x0 build/main.o
|
||||
*(.rela.got.*)
|
||||
.rela.got.funcdesc
|
||||
0x0000000000000230 0x0 build/main.o
|
||||
*(.rela.*)
|
||||
.rela.text 0x0000000000000230 0x48 build/main.o
|
||||
*(.rela.text)
|
||||
*(.real.data)
|
||||
|
||||
.data 0x0000000000000278 0x0
|
||||
*(.data)
|
||||
.data 0x0000000000000278 0x0 build/main.o
|
||||
.data 0x0000000000000278 0x0 build/syscalls.o
|
||||
*(.data.*)
|
||||
*(.bss)
|
||||
.bss 0x0000000000000278 0x0 build/main.o
|
||||
.bss 0x0000000000000278 0x0 build/syscalls.o
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
|
||||
/DISCARD/
|
||||
*(.gnu.*)
|
||||
*(.debug_info)
|
||||
*(.debug_abbrev)
|
||||
*(.debug_loc)
|
||||
*(.debug_aranges)
|
||||
*(.debug_ranges)
|
||||
*(.debug_line)
|
||||
*(.debug_str)
|
||||
*(.jcr)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
*(.comment)
|
||||
*(.interp)
|
||||
OUTPUT(test.elf elf32-sh)
|
Loading…
Reference in New Issue