From 0a148f61e3fc1b59c11563e9f3c827513dac1e3b Mon Sep 17 00:00:00 2001 From: claudiol Date: Wed, 29 Aug 2018 17:42:33 -0400 Subject: [PATCH] [3298] Add command-line options to rebuild the flash or reboot --- flash.c | 48 +++++++++++++++++++--------- include/x49gp.h | 10 +++++- main.c | 83 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 118 insertions(+), 23 deletions(-) diff --git a/flash.c b/flash.c index bc0cb9b..7291634 100644 --- a/flash.c +++ b/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 */ diff --git a/include/x49gp.h b/include/x49gp.h index 2c6ea15..23d36a9 100644 --- a/include/x49gp.h +++ b/include/x49gp.h @@ -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); diff --git a/main.c b/main.c index 29ec79b..bd184ab 100644 --- a/main.c +++ b/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 [] []\n" "Valid options:\n" - " -D, --enable-debug[=] like -D, but also start the" + " -D, --enable-debug[=] 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);