vxBoot - 1.0.0 : GUI

@add
<> src/gui : add GUI menu
<> src/loader/kernel : move kernel image list interaction
<> assets-cg/fonts : add font for fxcg50 device
<> include/vxBoot/config : add VXBOOT_VERSION macro

@update
<> src/cli/entry : move CLI main loop here
<> src/main : link GUI en move CLI

@fix
<> src/loader/scan : fix file type check for emulator
This commit is contained in:
Yann MAGNIN 2022-01-04 15:18:58 +01:00
parent f90c07132a
commit ce1f594a53
14 changed files with 433 additions and 72 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(vxBoot VERSION 0.0.3 LANGUAGES C)
project(vxBoot VERSION 1.0.0 LANGUAGES C)
include(GenerateG1A)
include(GenerateG3A)
@ -8,7 +8,11 @@ find_package(Gint 2.1 REQUIRED)
set(SOURCES
src/main.c
src/gui/entry.c
src/gui/fx9860g.c
src/gui/fxcg50.c
src/cli/parser.c
src/cli/entry.c
src/fs/smemfs/mount.c
src/fs/smemfs/pread.c
src/terminal/close.c
@ -25,6 +29,7 @@ set(SOURCES
src/loader/elf/image.c
src/loader/error.c
src/loader/entry.c
src/loader/kernel.c
src/hardware/get_info.c
)
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
@ -35,13 +40,13 @@ set(ASSETS_fx
assets-fx/fonts/hexa.png
)
set(ASSETS_cg
# ...
assets-cg/fonts/font8x9.png
)
fxconv_declare_assets(${ASSETS} ${ASSETS_fx} ${ASSETS_cg} WITH_METADATA)
add_executable(vxBoot ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}})
target_compile_options(vxBoot PRIVATE -Wall -Wextra -Os)
target_compile_options(vxBoot PRIVATE -Wall -Wextra -Os -DVXBOOT_VERSION="${PROJECT_VERSION}")
target_include_directories(vxBoot PRIVATE include/)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)

BIN
assets-cg/fonts/font8x9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,8 @@
font8x9.png:
type: font
name: font_fxcg50
charset: print
grid.size: 8x11
grid.padding: 1
grid.border: 0
height: 9

View File

@ -4,6 +4,10 @@
#include <stddef.h>
#include <stdint.h>
/* cli_main() : main entry for the CLI */
extern void cli_main(void);
extern int cli_parser_strtotab(int *argc, char ***argv, char const *str);
extern void cli_parser_strtotab_quit(int *argc, char ***argv);

9
include/vxBoot/config.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef VXBOOT_CONFIG
# define VXBOOT_CONFIG 1
/* vxBoot version */
#ifndef VXBOOT_VERSION
# define VXBOOT_VERSION "0.0.0"
#endif
#endif /* VXBOOT_CONFIG */

32
include/vxBoot/gui.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef __VXBOOT_GUI_H__
# define __VXBOOT_GUI_H__
#include <stddef.h>
#include <stdint.h>
/* internal GUI information */
struct gui_meta {
struct {
int anchor;
int select;
int count;
int line;
} list;
struct {
int x;
int y;
int width;
int offset;
} scroll;
};
/* gui_main() : main entry for the GUI */
extern void gui_main(void);
/* gui_fx9860g_display() : fx9860-specific display */
extern void gui_fx9860g_display(struct gui_meta *gui);
/* gui_fxcg50_display() : fxcg50-specific display */
extern void gui_fxcg50_display(struct gui_meta *gui);
#endif /*__VXBOOT_GUI_H__*/

View File

@ -114,6 +114,14 @@ struct ldimg {
/* loader_scan() : scan the storage memory and try to find ELF PIE file */
extern int loader_scan(void);
/* loader_kernel_img_get() : get the image ID information */
extern struct ldimg *loader_kernel_img_get(int id);
/* loader_kernel_img_count() : count the number of kernel image found */
extern int loader_kernel_img_count(void);
/* loader() : try to load a ELF PIE file */
#define LOADER_DEFAULT 0
#define LOADER_DUMP 1

70
src/cli/entry.c Normal file
View File

@ -0,0 +1,70 @@
#include "vxBoot/cli.h"
#include "vxBoot/builtin.h"
#include "vxBoot/terminal.h"
#include <string.h>
//TODO: better API for the command-line parser
/* internal builtin list */
struct {
const char *name;
int (*f)(int argc, char **argv);
} cmd_list[] = {
{.name = "ls", &ls_main},
{.name = "ld", &ld_main},
{.name = "hw", &hw_main},
{.name = "help", &help_main},
{.name = NULL, NULL}
};
/* try to find the appropriate command */
static int (*check_cmd(char *cmd))(int, char**)
{
for (int i = 0; cmd_list[i].name != NULL; ++i) {
if (strcmp(cmd, cmd_list[i].name) != 0)
continue;
if (cmd_list[i].f == NULL)
terminal_write("command exist but not implemented\n");
return (cmd_list[i].f);
}
return (NULL);
}
void cli_main(void)
{
int (*builtin)(int, char**);
const char *usrline;
char buff[128];
char **argv;
int argc;
int ret;
/* CLI loop */
ret = 0;
while (1) {
/* get user command */
usrline = (ret != 0) ? "/[%d]>" : "/>";
terminal_write(usrline, ret);
ret = 0;
if (terminal_read(buff, 128) <= 1)
continue;
/* parse and try to find the command */
if (cli_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;
}
/* execute the command and free'd allocated memories */
ret = builtin(argc, argv);
cli_parser_strtotab_quit(&argc, &argv);
}
}

137
src/gui/entry.c Normal file
View File

@ -0,0 +1,137 @@
#include "vxBoot/gui.h"
#include "vxBoot/loader.h"
#include <gint/display.h>
#include <gint/keyboard.h>
//---
// Private
//---
//--
// Public
//---
/* gui_main() : main loop for the GUI display */
void gui_main(void)
{
struct gui_meta disp;
void (*display)(struct gui_meta*);
int key;
disp.list.anchor = 0;
disp.list.select = 0;
disp.list.count = loader_kernel_img_count();
#ifdef FX9860G
disp.list.line = 5;
disp.scroll.y = 10;
disp.scroll.offset = 0;
if (disp.list.count - 6 > 0) {
disp.scroll.width = (6 * 48) / disp.list.count;
disp.scroll.offset = (38 - disp.scroll.width);
disp.scroll.offset /= (disp.list.count - 6);
}
display = &gui_fx9860g_display;
#endif
#ifdef FXCG50
disp.list.line = 11;
disp.scroll.y = 21;
disp.scroll.offset = 0;
if (disp.list.count - 11 > 0) {
disp.scroll.width = 167 / (disp.list.count - 11);
disp.scroll.offset = (167 - disp.scroll.width);
disp.scroll.offset /= (disp.list.count - 11);
}
display = &gui_fxcg50_display;
#endif
while (1) {
dclear(C_BLACK);
(*display)(&disp);
dupdate();
key = getkey().key;
if (key == KEY_F6)
break;
if (key == KEY_EXE || key == KEY_SHIFT) {
loader(
loader_kernel_img_get(disp.list.select)->inode,
LOADER_DEFAULT
);
}
if (key == KEY_UP) {
disp.list.select -= 1;
if (disp.list.select < 0)
disp.list.select = 0;
if (disp.list.select < disp.list.anchor)
disp.list.anchor -= 1;
}
if (key != KEY_DOWN)
continue;
disp.list.select += 1;
if (disp.list.select >= disp.list.count)
disp.list.select = disp.list.count - 1;
if (disp.list.select - disp.list.anchor >= disp.list.line)
disp.list.anchor += 1;
}
}
#if 0
/* gui_main() : main loop for the GUI display */
void gui_main(void)
{
int select_height;
int disp_start;
int max_line;
int offsetW;
int offsetH;
int selected;
int lheight;
int loffset;
int lrest;
int count;
int key;
int pos;
int i;
selected = 0;
disp_start = 0;
offsetW = (DWIDTH * 5) / 100;
offsetH = (DHEIGHT * 5) / 100;
select_height = DHEIGHT - (offsetH * 3) - 6;
select_height = select_height - (offsetH * 2) - 6;
max_line = (select_height / (FHEIGHT + 6)) + 1;
count = loader_kernel_img_count();
lheight = (max_line * select_height) / count;
lrest = select_height - lheight;
while (1) {
dclear(C_BLACK);
dupdate();
key = getkey().key;
if (key == KEY_F6)
break;
if (key == KEY_EXE || key == KEY_SHIFT) {
loader(
loader_kernel_img_get(selected)->inode,
LOADER_DEFAULT
);
}
if (key == KEY_UP) {
selected -= 1;
if (selected < 0) selected = 0;
if (selected < disp_start) disp_start -= 1;
}
if (key == KEY_DOWN) {
selected += 1;
if (selected >= count) selected = count - 1;
if (selected - disp_start >= max_line) disp_start += 1;
}
}
}
#endif

51
src/gui/fx9860g.c Normal file
View File

@ -0,0 +1,51 @@
#include "vxBoot/gui.h"
#include "vxBoot/loader.h"
#include <gint/display.h>
#if FX9860G
/* fx9860g_display() : Hardcoded display for the fx9860g */
void gui_fx9860g_display(struct gui_meta *disp)
{
char const * name;
int posy;
int tmp;
int sy;
int i;
dprint_opt(
DWIDTH / 2, 1,
C_WHITE, C_BLACK,
DTEXT_CENTER, DTEXT_TOP,
"VxBoot version %s",
VXBOOT_VERSION
);
drect_border(8, 8, 120, 50, C_NONE, 1, C_WHITE);
if (disp->scroll.offset > 0) {
sy = disp->scroll.y + (disp->list.anchor * disp->scroll.offset);
dline(118, sy, 118, sy + disp->scroll.width, C_WHITE);
}
i = disp->list.anchor - 1;
while (++i < disp->list.count && i - disp->list.anchor < 6) {
posy = 10 + ((i - disp->list.anchor) * 7);
name = loader_kernel_img_get(i)->inode->name;
dtext(11, posy + 1, C_WHITE, name);
if (i != disp->list.select)
continue;
tmp = (disp->scroll.offset > 0) ? 116 : 118;
drect(10, posy, tmp, posy + 6, C_INVERT);
}
dprint_opt(
DWIDTH / 2, 54,
C_WHITE, C_BLACK,
DTEXT_CENTER, DTEXT_MIDDLE,
"Use arrows to select"
);
dprint_opt(
DWIDTH / 2, 60,
C_WHITE, C_BLACK,
DTEXT_CENTER, DTEXT_MIDDLE,
"Press [EXE] to boot"
);
}
#endif

52
src/gui/fxcg50.c Normal file
View File

@ -0,0 +1,52 @@
#include "vxBoot/gui.h"
#include "vxBoot/loader.h"
#include "vxBoot/config.h"
#include <gint/display.h>
/* fxcg50_display() : Hardcoded display for the fxcg50 */
void gui_fxcg50_display(struct gui_meta *disp)
{
char const * name;
int posy;
int tmp;
int sy;
int i;
dprint_opt(
DWIDTH / 2, 5,
C_WHITE, C_BLACK,
DTEXT_CENTER, DTEXT_TOP,
"VxBoot version %s",
VXBOOT_VERSION
);
drect_border(17, 18, 378, 189, C_NONE, 1, C_WHITE);
if (disp->scroll.offset > 0) {
sy = disp->scroll.y + (disp->list.anchor * disp->scroll.offset);
dline(375, sy, 375, sy + disp->scroll.width, C_WHITE);
}
i = disp->list.anchor - 1;
while (++i < disp->list.count && i - disp->list.anchor < 11) {
posy = 22 + ((i - disp->list.anchor) * 15);
name = loader_kernel_img_get(i)->inode->name;
dtext(22, posy + 2, C_WHITE, name);
if (i != disp->list.select)
continue;
tmp = (disp->scroll.offset > 0) ? 373 : 375;
drect(20, posy, tmp, posy + 13, C_INVERT);
}
dprint_opt(
DWIDTH / 2, 200,
C_WHITE, C_BLACK,
DTEXT_CENTER, DTEXT_MIDDLE,
"Use arrows keys to select entry"
);
dprint_opt(
DWIDTH / 2, 212,
C_WHITE, C_BLACK,
DTEXT_CENTER, DTEXT_MIDDLE,
"Press [EXE] to boot the selected OS"
);
}

35
src/loader/kernel.c Normal file
View File

@ -0,0 +1,35 @@
#include "vxBoot/loader.h"
/* kernel image list */
struct ldimg *kernel_img_list = NULL;
/* loader_kernel_img_get() : get the image ID information */
struct ldimg *loader_kernel_img_get(int id)
{
struct ldimg *img;
img = kernel_img_list;
while (--id >= 0) {
if (img == NULL)
return NULL;
img = img->next;
}
return img;
}
/* loader_kernel_img_count() : count the number of kernel image found */
int loader_kernel_img_count(void)
{
struct ldimg *img;
int counter;
counter = 0;
img = kernel_img_list;
while (img != NULL) {
counter = counter + 1;
img = img->next;
}
return counter;
}

View File

@ -6,18 +6,23 @@
#include <stdlib.h>
/* internal kernel image list */
struct ldimg *kernel_img_list = NULL;
extern struct ldimg *kernel_img_list;
/* hypervisor_get_image_list(): Dump all ELF file stored into the SMEM */
/* hypervisor_get_image_list(): Dump all ELF file stored into the SMEM
*
* @note:
* on real calculator, all file transfered using USB are concidered to be
* 'archived', but on emulator they are concidered like file. */
static int loader_list_img(struct ldimg **image, struct smemfs_inode *inode)
{
if (inode == NULL)
return (0);
int counter = 0;
if (inode->type != BFile_Type_Archived) {
if (inode->type != BFile_Type_Archived
&& inode->type != BFile_Type_File) {
counter += loader_list_img(image, inode->child);
goto anchor;
}

View File

@ -1,56 +1,24 @@
#include "vxBoot/terminal.h"
#include "vxBoot/cli.h"
#include "vxBoot/builtin.h"
#include "vxBoot/fs/smemfs.h"
#include "vxBoot/loader.h"
#include "vxBoot/gui.h"
#include "vxBoot/cli.h"
#include <gint/keyboard.h>
#include <gint/display.h>
#include <string.h>
//TODO: better API for the command-line parser
/* internal builtin list */
struct {
const char *name;
int (*f)(int argc, char **argv);
} cmd_list[] = {
{.name = "ls", &ls_main},
{.name = "ld", &ld_main},
{.name = "hw", &hw_main},
{.name = "help", &help_main},
{.name = NULL, NULL}
};
/* try to find the appropriate command */
static int (*check_cmd(char *cmd))(int, char**)
{
for (int i = 0; cmd_list[i].name != NULL; ++i) {
if (strcmp(cmd, cmd_list[i].name) != 0)
continue;
if (cmd_list[i].f == NULL)
terminal_write("command exist but not implemented\n");
return (cmd_list[i].f);
}
return (NULL);
}
/* entry of the bootloader */
int main(void)
{
int (*builtin)(int, char**);
const char *usrline;
char buff[128];
char **argv;
int argc;
int ret;
/* change default font on fx9860 */
#ifdef FX9860G
extern font_t font_hexa;
dfont(&font_hexa);
#endif
#ifdef FXCG50
extern font_t font_fxcg50;
dfont(&font_fxcg50);
#endif
/* early log */
terminal_open();
@ -64,32 +32,9 @@ int main(void)
smemfs_mount();
loader_scan();
/* CLI loop */
ret = 0;
while (1) {
/* get user command */
usrline = (ret != 0) ? "/[%d]>" : "/>";
terminal_write(usrline, ret);
ret = 0;
if (terminal_read(buff, 128) <= 1)
continue;
/* parse and try to find the command */
if (cli_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;
}
/* execute the command and free'd allocated memories */
ret = builtin(argc, argv);
cli_parser_strtotab_quit(&argc, &argv);
}
/* GUI Loop */
if (loader_kernel_img_count() >= 1)
gui_main();
cli_main();
return (1);
}