Implement --bsl-entry-password option.

This commit is contained in:
Daniel Beer 2019-03-08 08:46:16 +13:00
parent 3bc5cb2686
commit 989038d3b3
5 changed files with 76 additions and 11 deletions

View File

@ -86,6 +86,7 @@ struct device_args {
int bsl_gpio_used;
int bsl_gpio_rts;
int bsl_gpio_dtr;
uint8_t bsl_entry_password[32];
};
struct device_class {

View File

@ -384,7 +384,8 @@ static int flash_bsl_erase(device_t dev_base, device_erase_type_t type,
return 0;
}
static int flash_bsl_unlock(struct flash_bsl_device *dev)
static int flash_bsl_unlock(struct flash_bsl_device *dev,
const uint8_t *password)
{
/*
* after erase, the password will be 0xff * (16 or 32)
@ -401,6 +402,8 @@ static int flash_bsl_unlock(struct flash_bsl_device *dev)
uint8_t response_buffer[16];
int ret;
memcpy(rx_password_cmd + 1, password, 32);
/* mass erase - this might wipe Information Memory on some devices */
/* (according to the documentation it should not) */
if (flash_bsl_erase((device_t)dev, DEVICE_ERASE_MAIN, 0) < 0) {
@ -625,7 +628,7 @@ static device_t flash_bsl_open(const struct device_args *args)
delay_ms(500);
/* unlock device (erase then send password) */
if (flash_bsl_unlock(dev) < 0) {
if (flash_bsl_unlock(dev, args->bsl_entry_password) < 0) {
goto fail;
}

View File

@ -404,15 +404,9 @@ static int rom_bsl_erase(device_t dev_base, device_erase_type_t type,
return 0;
}
static int unlock_device(struct rom_bsl_device *dev)
static int unlock_device(struct rom_bsl_device *dev,
const uint8_t *password)
{
const static uint8_t password[32] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
printc_dbg("Performing mass erase...\n");
if (rom_bsl_xfer(dev, CMD_MASS_ERASE, 0xfffe, NULL, 0xa506) < 0) {
@ -488,7 +482,7 @@ static device_t rom_bsl_open(const struct device_args *args)
dev->reply_buf[15],
dev->reply_buf[16]);
if (unlock_device(dev) < 0) {
if (unlock_device(dev, args->bsl_entry_password) < 0) {
printc_err("rom_bsl: failed to unlock\n");
goto fail;
}

View File

@ -100,6 +100,11 @@ line transition (R: RTS on, r: RTS off, D: DTR on, d: DTR off). A comma
indicates a delay. The entry and exit sequences are separated by a
colon. The default value is \fBdR,r,R,r,R,D:dR,DR\fR, for the
\fBflash-bsl\fR driver.
.IP "\-\-bsl\-entry\-password \fIhex\-string\fR"
Specify a BSL unlock password as a hexadecimal byte string. This
option affects both the flash and ROM BSL drivers. The password will
be padded with 0xff bytes, and the default password is a sequence
consisting of only 0xff bytes.
.SH DRIVERS
For drivers supporting both USB and tty access, USB is the default,
unless specified otherwise (see \fB-d\fR above).

View File

@ -154,6 +154,8 @@ static void usage(const char *progname)
" On some host (say RaspberryPi) defines a GPIO pin# to be used as RTS\n"
" --bsl-gpio-dtr\n"
" On some host (say RaspberryPi) defines a GPIO pin# to be used as DTR\n"
" --bsl-entry-password <hex string>\n"
" Use the given hex byte string as a BSL entry password.\n"
"\n"
"Most drivers connect by default via USB, unless told otherwise via the\n"
"-d option. By default, the first USB device found is opened.\n"
@ -170,6 +172,51 @@ static void usage(const char *progname)
}
}
static int parse_hex_string(uint8_t *buf, size_t len, const char *text)
{
unsigned int ptr = 0;
uint8_t b = 0;
while (*text) {
char d = *(text++);
int digit = 0;
if (d >= '0' && d <= '9')
digit = d - '0';
else if (d >= 'A' && d <= 'F')
digit = d - 'A' + 10;
else if (d >= 'a' && d <= 'f')
digit = d - 'a' + 10;
else {
fprintf(stderr, "invalid hex digit: %c\n", d);
return -1;
}
b = (b << 4) | digit;
ptr++;
if (!(ptr & 1)) {
unsigned int pos = (ptr >> 1) - 1;
if (pos >= len) {
fprintf(stderr,
"maximum length exceeded (%d)\n",
(int)len);
return -1;
}
buf[pos] = b;
}
}
if (ptr & 1) {
fprintf(stderr, "odd number of hex digits encountered\n");
return -1;
}
return 0;
}
static void process_rc_file(const char *config)
{
char text[256];
@ -255,6 +302,7 @@ static int parse_cmdline_args(int argc, char **argv,
LOPT_BSL_ENTRY_SEQUENCE,
LOPT_BSL_GPIO_RTS,
LOPT_BSL_GPIO_DTR,
LOPT_BSL_ENTRY_PASSWORD,
};
static const struct option longopts[] = {
@ -272,6 +320,7 @@ static int parse_cmdline_args(int argc, char **argv,
{"bsl-entry-sequence", 1, 0, LOPT_BSL_ENTRY_SEQUENCE},
{"bsl-gpio-rts", 1, 0, LOPT_BSL_GPIO_RTS},
{"bsl-gpio-dtr", 1, 0, LOPT_BSL_GPIO_DTR},
{"bsl-entry-password", 1, 0, LOPT_BSL_ENTRY_PASSWORD},
{NULL, 0, 0, 0}
};
@ -295,6 +344,16 @@ static int parse_cmdline_args(int argc, char **argv,
}
break;
case LOPT_BSL_ENTRY_PASSWORD:
if (parse_hex_string
(args->devarg.bsl_entry_password,
sizeof(args->devarg.bsl_entry_password),
optarg) < 0) {
fprintf(stderr, "invalid BSL password\n");
return -1;
}
break;
case LOPT_BSL_ENTRY_SEQUENCE:
args->devarg.bsl_entry_seq = optarg;
break;
@ -465,6 +524,9 @@ int main(int argc, char **argv)
args.devarg.vcc_mv = 3000;
args.devarg.requested_serial = NULL;
memset(args.devarg.bsl_entry_password, 0xff,
sizeof(args.devarg.bsl_entry_password));
if (parse_cmdline_args(argc, argv, &args) < 0)
goto fail_parse;