[3298] Add command-line options to rebuild the flash or reboot

This commit is contained in:
claudiol 2018-08-29 17:42:33 -04:00
parent df33a5ac5b
commit 0a148f61e3
3 changed files with 118 additions and 23 deletions

34
flash.c
View file

@ -512,7 +512,11 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
if (flash->size > st.st_size) { if (flash->size > st.st_size) {
fprintf(stderr, "Flash too small, rebuilding\n"); fprintf(stderr, "Flash too small, rebuilding\n");
x49gp->startup_reinit = X49GP_REINIT_FLASH_FULL;
}
if (x49gp->startup_reinit >= X49GP_REINIT_FLASH) {
if (x49gp->startup_reinit == X49GP_REINIT_FLASH_FULL)
memset(phys_ram_base + flash->offset, 0xff, memset(phys_ram_base + flash->offset, 0xff,
flash->size - st.st_size); flash->size - st.st_size);
@ -547,22 +551,29 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
close(bootfd); close(bootfd);
g_free(bootfile); g_free(bootfile);
/* The stock firmware expects special markers in certain spots if (x49gp->startup_reinit == X49GP_REINIT_FLASH_FULL) {
across the flash. Without these, the user banks act up and /* The stock firmware expects special markers in certain
are not usable, and PINIT apparently won't fix it. spots across the flash. Without these, the user banks
Let's help it out; custom firmware will have to deal with act up and are not usable, and PINIT apparently won't
remnants of the user banks on real calculators anyway, fix it. Let's help it out; custom firmware will have
so if they break here, they will too on actual hardware to deal with remnants of the user banks on real
because that always comes with the stock firmware and calculators anyway, so if they break here, they will
its user banks marked properly. */ too on actual hardware because that always comes with
the stock firmware and its user banks marked
properly. */
for (i=2;i<14;i++) { for (i=2;i<14;i++) {
bank_marker[1] = i; bank_marker[1] = i;
memcpy(phys_ram_base + flash->offset + 0x40100 + memcpy(phys_ram_base + flash->offset + 0x40100 +
0x20000 * i, bank_marker, 5); 0x20000 * i, bank_marker, 5);
} }
}
filename = NULL; filename = NULL;
if (x49gp->firmware != NULL) {
filename = g_strdup(x49gp->firmware);
} else {
x49gp_ui_open_firmware(x49gp, &filename); x49gp_ui_open_firmware(x49gp, &filename);
}
if (filename != NULL) { if (filename != NULL) {
fwfd = open(filename, O_RDONLY); fwfd = open(filename, O_RDONLY);
if (fwfd < 0) { if (fwfd < 0) {
@ -572,6 +583,9 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
fprintf(stderr, "Warning: Could not open " fprintf(stderr, "Warning: Could not open "
"selected firmware, falling back to " "selected firmware, falling back to "
"bootloader recovery tools\n"); "bootloader recovery tools\n");
/* Mark firmware as invalid if there is one */
memset(phys_ram_base + flash->offset +
BOOT_SIZE, 0, 16);
} else { } else {
/* The firmware may be shorter than /* The firmware may be shorter than
SST29VF160_SIZE - BOOT_SIZE, but if so, SST29VF160_SIZE - BOOT_SIZE, but if so,
@ -588,6 +602,10 @@ flash_load(x49gp_module_t *module, GKeyFile *key)
"read selected firmware, " "read selected firmware, "
"falling back to bootloader " "falling back to bootloader "
"recovery tools\n"); "recovery tools\n");
/* Mark firmware as invalid
if there is one */
memset(phys_ram_base + flash->offset +
BOOT_SIZE, 0, 16);
} else { } else {
/* Mark the firmware as valid in the /* Mark the firmware as valid in the
same way the bootloader does */ same way the bootloader does */

View file

@ -54,6 +54,12 @@ struct __x49gp_module_s__ {
struct list_head list; 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__ { struct __x49gp_s__ {
CPUARMState *env; CPUARMState *env;
@ -97,6 +103,8 @@ struct __x49gp_s__ {
const char *progpath; const char *progpath;
const char *basename; 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); extern void x49gp_set_idle(x49gp_t *, x49gp_arm_idle_t idle);

73
main.c
View file

@ -254,6 +254,8 @@ struct options {
char *config; char *config;
int debug_port; int debug_port;
int start_debugger; int start_debugger;
char *firmware;
x49gp_reinit_t reinit;
int more_options; int more_options;
}; };
@ -275,6 +277,13 @@ 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, static int action_debug(struct options *opt, struct option_def *match,
char *this_opt, char *param, char *progname); 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, static int action_unknown_with_param(struct options *opt,
struct option_def *match, char *this_opt, struct option_def *match, char *this_opt,
@ -288,6 +297,9 @@ struct option_def option_defs[] = {
{ action_help, "help", 'h' }, { action_help, "help", 'h' },
{ action_debuglater, "enable-debug", 'D' }, { action_debuglater, "enable-debug", 'D' },
{ action_debug, "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_longopt, NULL, '-' },
{ action_unknown_with_param, NULL, '=' }, { action_unknown_with_param, NULL, '=' },
@ -319,6 +331,20 @@ action_help(struct options *opt, struct option_def *match, char *this_opt,
" (default port: %u)\n" " (default port: %u)\n"
" -d, --debug[=<port>] like -D, but also start the" " -d, --debug[=<port>] like -D, but also start the"
" debugger immediately\n" " debugger immediately\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" " -h, --help print this message and exit\n"
"The config file is formatted as INI file and contains the" "The config file is formatted as INI file and contains the"
" settings for which\n" " settings for which\n"
@ -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); 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 static int
action_longopt(struct options *opt, struct option_def *match, char *this_opt, action_longopt(struct options *opt, struct option_def *match, char *this_opt,
char *param, char *progname) char *param, char *progname)
@ -530,6 +595,8 @@ main(int argc, char **argv)
opt.config = NULL; opt.config = NULL;
opt.debug_port = 0; opt.debug_port = 0;
opt.start_debugger = FALSE; opt.start_debugger = FALSE;
opt.reinit = X49GP_REINIT_NONE;
opt.firmware = NULL;
parse_options(&opt, argc, argv, progname); parse_options(&opt, argc, argv, progname);
x49gp = malloc(sizeof(x49gp_t)); x49gp = malloc(sizeof(x49gp_t));
@ -595,10 +662,12 @@ main(int argc, char **argv)
x49gp->basename = g_path_get_dirname(opt.config); x49gp->basename = g_path_get_dirname(opt.config);
x49gp->debug_port = opt.debug_port; x49gp->debug_port = opt.debug_port;
x49gp->startup_reinit = opt.reinit;
x49gp->firmware = opt.firmware;
error = x49gp_modules_load(x49gp, opt.config); error = x49gp_modules_load(x49gp, opt.config);
if (error) { if (error || opt.reinit >= X49GP_REINIT_REBOOT_ONLY) {
if (error != -EAGAIN) { if (error && error != -EAGAIN) {
exit(1); exit(1);
} }
x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON); x49gp_modules_reset(x49gp, X49GP_RESET_POWER_ON);