diff --git a/drivers/device.h b/drivers/device.h index 0e6e03e..55b4133 100644 --- a/drivers/device.h +++ b/drivers/device.h @@ -30,7 +30,8 @@ typedef enum { DEVICE_CTL_RESET, DEVICE_CTL_RUN, DEVICE_CTL_HALT, - DEVICE_CTL_STEP + DEVICE_CTL_STEP, + DEVICE_CTL_SECURE } device_ctl_t; typedef enum { diff --git a/drivers/fet3.c b/drivers/fet3.c index 04a4ba4..2cb3e16 100644 --- a/drivers/fet3.c +++ b/drivers/fet3.c @@ -170,6 +170,10 @@ static int fet3_ctl(device_t dev_base, device_ctl_t type) if (v3hil_single_step(&fet->hil) < 0) return -1; return v3hil_update_regs(&fet->hil); + + default: + printc_err("fet3: unsupported operation\n"); + return -1; } return 0; diff --git a/drivers/fet_core.c b/drivers/fet_core.c index cc956d6..6d4e590 100644 --- a/drivers/fet_core.c +++ b/drivers/fet_core.c @@ -708,6 +708,13 @@ int fet_ctl(device_t dev_base, device_ctl_t action) break; } break; + + case DEVICE_CTL_SECURE: + if (fet_proto_xfer(&dev->proto, C_SECURE, NULL, 0, 0) < 0) { + printc_err("fet: failed to secure device\n"); + return -1; + } + break; } return 0; diff --git a/drivers/gdbc.c b/drivers/gdbc.c index 577135f..e297ac4 100644 --- a/drivers/gdbc.c +++ b/drivers/gdbc.c @@ -308,6 +308,10 @@ static int gdbc_ctl(device_t dev_base, device_ctl_t op) case DEVICE_CTL_RESET: return do_reset(dev); + + default: + printc_err("gdbc: unsupported operation\n"); + return -1; } return 0; diff --git a/drivers/goodfet.c b/drivers/goodfet.c index cb8aefd..ddddeb0 100644 --- a/drivers/goodfet.c +++ b/drivers/goodfet.c @@ -566,8 +566,8 @@ static int goodfet_ctl(device_t dev_base, device_ctl_t type) case DEVICE_CTL_HALT: return goodfet_halt(gc); - case DEVICE_CTL_STEP: - printc_err("goodfet: single-stepping not implemented\n"); + default: + printc_err("goodfet: unsupported operation\n"); return -1; } diff --git a/drivers/loadbsl.c b/drivers/loadbsl.c index d486ad1..22965d8 100644 --- a/drivers/loadbsl.c +++ b/drivers/loadbsl.c @@ -403,6 +403,7 @@ static int loadbsl_ctl(device_t base, device_ctl_t type) default: printc_err("loadbsl: CPU control is not possible\n"); + return -1; } return 0; diff --git a/drivers/pif.c b/drivers/pif.c index f91327e..760242a 100644 --- a/drivers/pif.c +++ b/drivers/pif.c @@ -290,8 +290,8 @@ static int pif_ctl(device_t dev_base, device_ctl_t type) jtag_get_device(&dev->jtag); break; - case DEVICE_CTL_STEP: - printc_err("pif: single-stepping not implemented\n"); + default: + printc_err("pif: unsupported operation\n"); return -1; } diff --git a/drivers/sim.c b/drivers/sim.c index d20b67a..6b10da5 100644 --- a/drivers/sim.c +++ b/drivers/sim.c @@ -696,6 +696,10 @@ static int sim_ctl(device_t dev_base, device_ctl_t op) case DEVICE_CTL_RUN: dev->running = 1; return 0; + + default: + printc_err("sim: unsupported operation\n"); + return -1; } return 0; diff --git a/drivers/tilib.c b/drivers/tilib.c index 6037b4c..9453799 100644 --- a/drivers/tilib.c +++ b/drivers/tilib.c @@ -64,6 +64,7 @@ struct tilib_device { STATUS_T TIDLL (*MSP430_Reset)(long method, long execute, long releaseJTAG); STATUS_T TIDLL (*MSP430_Erase)(long type, long address, long length); + STATUS_T TIDLL (*MSP430_Secure)(void); STATUS_T TIDLL (*MSP430_Error_Number)(void); const char *TIDLL (*MSP430_Error_String)(long errNumber); @@ -187,6 +188,10 @@ static int get_all_funcs(struct tilib_device *dev) if (!dev->MSP430_Erase) return -1; + dev->MSP430_Secure = get_func(dev->hnd, "MSP430_Secure"); + if (!dev->MSP430_Secure) + return -1; + dev->MSP430_Error_Number = get_func(dev->hnd, "MSP430_Error_Number"); if (!dev->MSP430_Error_Number) return -1; @@ -510,6 +515,13 @@ static int tilib_ctl(device_t dev_base, device_ctl_t op) case DEVICE_CTL_STEP: return do_step(dev); + + case DEVICE_CTL_SECURE: + if (dev->MSP430_Secure() < 0) { + report_error(dev, "MSP430_Secure"); + return -1; + } + return 0; } return 0; diff --git a/mspdebug.man b/mspdebug.man index b00d77b..b6721cf 100644 --- a/mspdebug.man +++ b/mspdebug.man @@ -230,6 +230,10 @@ Define a command alias. The text \fIcommand\fR will be substituted for a command plus arguments, if the entire text is wrapped in quotes when defining the alias. To avoid alias substitution when interpreting commands, prefix the command with \\ (a backslash character). +.IP "\fBblow_jtag_fuse\fR" +Blow the device's JTAG fuse. + +.B WARNING: this is an irreversible operation! .IP "\fBbreak\fR" Show a list of active breakpoints. Breakpoints can be added and removed with the \fBsetbreak\fR and \fBdelbreak\fR commands. Each breakpoint is @@ -735,6 +739,12 @@ BSL memory. If in doubt, do not enable this. If set, some drivers will allow erase/program access to the info A segment. If in doubt, do not enable this. Currently, the tilib and uif drivers are affected by this option. +.IP "\fBenable_fuse_blow\fR" +If set, some drivers will allow the JTAG security fuse to be blown. + +.B WARNING: this is an irreversible operation! + +If in doubt, do not enable this option. .IP "\fBgdb_default_port\fR (numeric)" This option controls the default TCP port for the GDB server, if no argument is given to the "\fBgdb\fR" command. diff --git a/ui/cmddb.c b/ui/cmddb.c index 645e1a6..57e27f4 100644 --- a/ui/cmddb.c +++ b/ui/cmddb.c @@ -175,6 +175,15 @@ const struct cmddb_record commands[] = { .help = "reset\n" " Reset (and halt) the CPU.\n" + }, + { + .name = "blow_jtag_fuse", + .func = cmd_blow_jtag_fuse, + .help = +"blow-jtag-fuse\n" +" Blow the device's JTAG fuse.\n" +"\n" +" \x1b[1mWARNING: this is an irreversible operation!\x1b[0m\n" }, { .name = "erase", diff --git a/ui/devcmd.c b/ui/devcmd.c index bc1b592..960c377 100644 --- a/ui/devcmd.c +++ b/ui/devcmd.c @@ -31,6 +31,7 @@ #include "util.h" #include "prog.h" #include "dis.h" +#include "opdb.h" int cmd_regs(char **arg) { @@ -832,3 +833,21 @@ int cmd_fill(char **arg) return 0; } + +int cmd_blow_jtag_fuse(char **arg) +{ + (void)arg; + + if (!opdb_get_boolean("enable_fuse_blow")) { + printc_err( +"blow_jtag_fuse: fuse blow has not been enabled.\n" +"\n" +"If you really want to blow the JTAG fuse, you need to set the option\n" +"\"enable_fuse_blow\" first. If in doubt, do not do this.\n" +"\n" +"\x1b[1mWARNING: this is in irreversible operation!\x1b[0m\n"); + return -1; + } + + return device_ctl(DEVICE_CTL_SECURE); +} diff --git a/ui/devcmd.h b/ui/devcmd.h index 957c8d7..a1f6205 100644 --- a/ui/devcmd.h +++ b/ui/devcmd.h @@ -39,5 +39,6 @@ int cmd_setwatch_w(char **arg); int cmd_delbreak(char **arg); int cmd_break(char **arg); int cmd_fill(char **arg); +int cmd_blow_jtag_fuse(char **arg); #endif diff --git a/util/opdb.c b/util/opdb.c index b535b34..bf1ef06 100644 --- a/util/opdb.c +++ b/util/opdb.c @@ -103,6 +103,16 @@ static const struct opdb_key keys[] = { .defval = { .numeric = 2000 } + }, + { + .name = "enable_fuse_blow", + .type = OPDB_TYPE_BOOLEAN, + .help = +"If set, some drivers will allow the JTAG security fuse to be blown.\n" +"\n" +"\x1b[1mWARNING: this is an irreversible operation!\x1b[0m\n" +"\n" +"If in doubt, do not enable this option.\n" } };