mirror of
https://github.com/gwenhael-le-moine/x49gp.git
synced 2024-12-25 21:58:49 +01:00
[3298] Add command-line options to rebuild the flash or reboot
This commit is contained in:
parent
df33a5ac5b
commit
0a148f61e3
3 changed files with 118 additions and 23 deletions
48
flash.c
48
flash.c
|
@ -512,9 +512,13 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
|
|||
|
||||
if (flash->size > st.st_size) {
|
||||
fprintf(stderr, "Flash too small, rebuilding\n");
|
||||
x49gp->startup_reinit = X49GP_REINIT_FLASH_FULL;
|
||||
}
|
||||
if (x49gp->startup_reinit >= X49GP_REINIT_FLASH) {
|
||||
|
||||
memset(phys_ram_base + flash->offset, 0xff,
|
||||
flash->size - st.st_size);
|
||||
if (x49gp->startup_reinit == X49GP_REINIT_FLASH_FULL)
|
||||
memset(phys_ram_base + flash->offset, 0xff,
|
||||
flash->size - st.st_size);
|
||||
|
||||
bootfd = x49gp_module_open_rodata(module,
|
||||
calc == UI_CALCULATOR_HP49GP ?
|
||||
|
@ -547,22 +551,29 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
|
|||
close(bootfd);
|
||||
g_free(bootfile);
|
||||
|
||||
/* The stock firmware expects special markers in certain spots
|
||||
across the flash. Without these, the user banks act up and
|
||||
are not usable, and PINIT apparently won't fix it.
|
||||
Let's help it out; custom firmware will have to deal with
|
||||
remnants of the user banks on real calculators anyway,
|
||||
so if they break here, they will too on actual hardware
|
||||
because that always comes with the stock firmware and
|
||||
its user banks marked properly. */
|
||||
for (i=2;i<14;i++) {
|
||||
bank_marker[1] = i;
|
||||
memcpy(phys_ram_base + flash->offset + 0x40100 +
|
||||
0x20000 * i, bank_marker, 5);
|
||||
if (x49gp->startup_reinit == X49GP_REINIT_FLASH_FULL) {
|
||||
/* The stock firmware expects special markers in certain
|
||||
spots across the flash. Without these, the user banks
|
||||
act up and are not usable, and PINIT apparently won't
|
||||
fix it. Let's help it out; custom firmware will have
|
||||
to deal with remnants of the user banks on real
|
||||
calculators anyway, so if they break here, they will
|
||||
too on actual hardware because that always comes with
|
||||
the stock firmware and its user banks marked
|
||||
properly. */
|
||||
for (i=2;i<14;i++) {
|
||||
bank_marker[1] = i;
|
||||
memcpy(phys_ram_base + flash->offset + 0x40100 +
|
||||
0x20000 * i, bank_marker, 5);
|
||||
}
|
||||
}
|
||||
|
||||
filename = NULL;
|
||||
x49gp_ui_open_firmware(x49gp, &filename);
|
||||
if (x49gp->firmware != NULL) {
|
||||
filename = g_strdup(x49gp->firmware);
|
||||
} else {
|
||||
x49gp_ui_open_firmware(x49gp, &filename);
|
||||
}
|
||||
if (filename != NULL) {
|
||||
fwfd = open(filename, O_RDONLY);
|
||||
if (fwfd < 0) {
|
||||
|
@ -572,6 +583,9 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
|
|||
fprintf(stderr, "Warning: Could not open "
|
||||
"selected firmware, falling back to "
|
||||
"bootloader recovery tools\n");
|
||||
/* Mark firmware as invalid if there is one */
|
||||
memset(phys_ram_base + flash->offset +
|
||||
BOOT_SIZE, 0, 16);
|
||||
} else {
|
||||
/* The firmware may be shorter than
|
||||
SST29VF160_SIZE - BOOT_SIZE, but if so,
|
||||
|
@ -588,6 +602,10 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
|
|||
"read selected firmware, "
|
||||
"falling back to bootloader "
|
||||
"recovery tools\n");
|
||||
/* Mark firmware as invalid
|
||||
if there is one */
|
||||
memset(phys_ram_base + flash->offset +
|
||||
BOOT_SIZE, 0, 16);
|
||||
} else {
|
||||
/* Mark the firmware as valid in the
|
||||
same way the bootloader does */
|
||||
|
|
|
@ -54,6 +54,12 @@ struct __x49gp_module_s__ {
|
|||
struct list_head list;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
X49GP_REINIT_NONE = 0,
|
||||
X49GP_REINIT_REBOOT_ONLY,
|
||||
X49GP_REINIT_FLASH,
|
||||
X49GP_REINIT_FLASH_FULL
|
||||
} x49gp_reinit_t;
|
||||
|
||||
struct __x49gp_s__ {
|
||||
CPUARMState *env;
|
||||
|
@ -96,7 +102,9 @@ struct __x49gp_s__ {
|
|||
const char *progname;
|
||||
const char *progpath;
|
||||
const char *basename;
|
||||
int debug_port;
|
||||
int debug_port;
|
||||
x49gp_reinit_t startup_reinit;
|
||||
char *firmware;
|
||||
};
|
||||
|
||||
extern void x49gp_set_idle(x49gp_t *, x49gp_arm_idle_t idle);
|
||||
|
|
83
main.c
83
main.c
|
@ -254,6 +254,8 @@ struct options {
|
|||
char *config;
|
||||
int debug_port;
|
||||
int start_debugger;
|
||||
char *firmware;
|
||||
x49gp_reinit_t reinit;
|
||||
|
||||
int more_options;
|
||||
};
|
||||
|
@ -272,9 +274,16 @@ struct option_def {
|
|||
static int action_help(struct options *opt, struct option_def *match,
|
||||
char *this_opt, char *param, char *progname);
|
||||
static int action_debuglater(struct options *opt, struct option_def *match,
|
||||
char *this_opt, char *param, char *progname);
|
||||
char *this_opt, char *param, char *progname);
|
||||
static int action_debug(struct options *opt, struct option_def *match,
|
||||
char *this_opt, char *param, char *progname);
|
||||
static int action_reinit_flash(struct options *opt, struct option_def *match,
|
||||
char *this_opt, char *param, char *progname);
|
||||
static int action_reinit_flash_full(struct options *opt,
|
||||
struct option_def *match, char *this_opt,
|
||||
char *param, char *progname);
|
||||
static int action_reboot(struct options *opt, struct option_def *match,
|
||||
char *this_opt, char *param, char *progname);
|
||||
|
||||
static int action_unknown_with_param(struct options *opt,
|
||||
struct option_def *match, char *this_opt,
|
||||
|
@ -288,6 +297,9 @@ struct option_def option_defs[] = {
|
|||
{ action_help, "help", 'h' },
|
||||
{ action_debuglater, "enable-debug", 'D' },
|
||||
{ action_debug, "debug", 'd' },
|
||||
{ action_reinit_flash, "reflash", 'f' },
|
||||
{ action_reinit_flash_full, "reflash-full", 'F' },
|
||||
{ action_reboot, "reboot", 'r' },
|
||||
|
||||
{ action_longopt, NULL, '-' },
|
||||
{ action_unknown_with_param, NULL, '=' },
|
||||
|
@ -315,11 +327,25 @@ action_help(struct options *opt, struct option_def *match, char *this_opt,
|
|||
fprintf(stderr, "Emulator for HP 49G+ / 50G calculators\n"
|
||||
"Usage: %s [<options>] [<config-file>]\n"
|
||||
"Valid options:\n"
|
||||
" -D, --enable-debug[=<port] enable the debugger interface\n"
|
||||
" (default port: %u)\n"
|
||||
" -d, --debug[=<port>] like -D, but also start the"
|
||||
" -D, --enable-debug[=<port] enable the debugger interface\n"
|
||||
" (default port: %u)\n"
|
||||
" -d, --debug[=<port>] like -D, but also start the"
|
||||
" debugger immediately\n"
|
||||
" -h, --help print this message and exit\n"
|
||||
" -f, --reflash[=firmware] rebuild the flash using the"
|
||||
" supplied firmware\n"
|
||||
" (default: select one"
|
||||
" interactively)\n"
|
||||
" (implies -r for safety"
|
||||
" reasons)\n"
|
||||
" -F, --reflash-full[=firmware] like -f, but don't preserve the"
|
||||
" flash contents\n"
|
||||
" in the area beyond the"
|
||||
" firmware\n"
|
||||
" -r, --reboot reboot on startup instead of"
|
||||
" continuing from the\n"
|
||||
" saved state in the config"
|
||||
" file\n"
|
||||
" -h, --help print this message and exit\n"
|
||||
"The config file is formatted as INI file and contains the"
|
||||
" settings for which\n"
|
||||
"persistence makes sense, like calculator model, CPU"
|
||||
|
@ -366,6 +392,45 @@ action_debug(struct options *opt, struct option_def *match, char *this_opt,
|
|||
return action_debuglater(opt, match, this_opt, param, progname);
|
||||
}
|
||||
|
||||
static int
|
||||
action_reinit_flash(struct options *opt, struct option_def *match,
|
||||
char *this_opt, char *param, char *progname)
|
||||
{
|
||||
if (opt->reinit < X49GP_REINIT_FLASH)
|
||||
opt->reinit = X49GP_REINIT_FLASH;
|
||||
|
||||
if (param == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (opt->firmware != NULL)
|
||||
fprintf(stderr, "Additional firmware file \"%s\" specified,"
|
||||
" overriding\n", param);
|
||||
opt->firmware = param;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
action_reinit_flash_full(struct options *opt,
|
||||
struct option_def *match, char *this_opt,
|
||||
char *param, char *progname)
|
||||
{
|
||||
int result = action_reinit_flash(opt, match, this_opt, param, progname);
|
||||
opt->reinit = X49GP_REINIT_FLASH_FULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
action_reboot(struct options *opt, struct option_def *match, char *this_opt,
|
||||
char *param, char *progname)
|
||||
{
|
||||
if (param != NULL)
|
||||
warn_unneeded_param(match, this_opt);
|
||||
|
||||
if (opt->reinit < X49GP_REINIT_REBOOT_ONLY)
|
||||
opt->reinit = X49GP_REINIT_REBOOT_ONLY;
|
||||
return param != NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
action_longopt(struct options *opt, struct option_def *match, char *this_opt,
|
||||
char *param, char *progname)
|
||||
|
@ -530,6 +595,8 @@ main(int argc, char **argv)
|
|||
opt.config = NULL;
|
||||
opt.debug_port = 0;
|
||||
opt.start_debugger = FALSE;
|
||||
opt.reinit = X49GP_REINIT_NONE;
|
||||
opt.firmware = NULL;
|
||||
parse_options(&opt, argc, argv, progname);
|
||||
|
||||
x49gp = malloc(sizeof(x49gp_t));
|
||||
|
@ -595,10 +662,12 @@ main(int argc, char **argv)
|
|||
|
||||
x49gp->basename = g_path_get_dirname(opt.config);
|
||||
x49gp->debug_port = opt.debug_port;
|
||||
x49gp->startup_reinit = opt.reinit;
|
||||
x49gp->firmware = opt.firmware;
|
||||
|
||||
error = x49gp_modules_load(x49gp, opt.config);
|
||||
if (error) {
|
||||
if (error != -EAGAIN) {
|
||||
if (error || opt.reinit >= X49GP_REINIT_REBOOT_ONLY) {
|
||||
if (error && error != -EAGAIN) {
|
||||
exit(1);
|
||||
}
|
||||
x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);
|
||||
|
|
Loading…
Reference in a new issue