Add check for correct firmware when flashing to a devices

It's using the product string for now, but there are other
things that we could check too. Use -i to ignore the check.
rad1o badge will always pass the check because it uses
"HackRF" as the product string, whichis a substring of both
other devices..
This commit is contained in:
Dominic Spill
2017-08-09 11:29:24 +01:00
parent ded4258105
commit 75d3a0a5b1

View File

@ -51,6 +51,7 @@ static struct option long_options[] = {
{ "length", required_argument, 0, 'l' }, { "length", required_argument, 0, 'l' },
{ "read", required_argument, 0, 'r' }, { "read", required_argument, 0, 'r' },
{ "write", required_argument, 0, 'w' }, { "write", required_argument, 0, 'w' },
{ "compatibility", no_argument, 0, 'c' },
{ "device", required_argument, 0, 'd' }, { "device", required_argument, 0, 'd' },
{ "reset", no_argument, 0, 'R' }, { "reset", no_argument, 0, 'R' },
{ "verbose", no_argument, 0, 'v' }, { "verbose", no_argument, 0, 'v' },
@ -58,6 +59,51 @@ static struct option long_options[] = {
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 },
}; };
int compatibility_check(uint8_t* data, int length, hackrf_device* device)
{
int str_len, i,j;
bool match = false;
uint8_t board_id;
char* dev_str;
hackrf_board_id_read(device, &board_id);
switch(board_id)
{
case BOARD_ID_JAWBREAKER:
dev_str = "HackRF Jawbreaker";
str_len = 17;
break;
case BOARD_ID_HACKRF_ONE:
dev_str = "HackRF One";
str_len = 10;
break;
case BOARD_ID_RAD1O:
//This is somewhat problematic,
// it's a substring of the others
dev_str = "HackRF";
str_len = 6;
break;
default:
printf("Unknown Board ID");
return 1;
}
for(i=0; i<length-str_len; i++){
if(data[i] == dev_str[0]) {
// Test rest of string
match = true;
for(j=1; j<str_len; j++) {
if((data[i+j*2] != dev_str[j]) ||
(data[1+i+j*2] != 0x00)) {
match = false;
break;
}
}
if(match)
return 0;
}
}
return 1;
}
int parse_u32(char* s, uint32_t* const value) int parse_u32(char* s, uint32_t* const value)
{ {
char* s_end; char* s_end;
@ -94,6 +140,7 @@ static void usage()
printf("\t-l, --length <n>: number of bytes to read (default: %d)\n", MAX_LENGTH); printf("\t-l, --length <n>: number of bytes to read (default: %d)\n", MAX_LENGTH);
printf("\t-r, --read <filename>: Read data into file.\n"); printf("\t-r, --read <filename>: Read data into file.\n");
printf("\t-w, --write <filename>: Write data from file.\n"); printf("\t-w, --write <filename>: Write data from file.\n");
printf("\t-i, --no-check: Skip check for firmware compatibility with target device.\n");
printf("\t-d, --device <serialnumber>: Serial number of device, if multiple devices\n"); printf("\t-d, --device <serialnumber>: Serial number of device, if multiple devices\n");
printf("\t-R, --reset: Reset HackRF after other operations.\n"); printf("\t-R, --reset: Reset HackRF after other operations.\n");
printf("\t-v, --verbose: Verbose output.\n"); printf("\t-v, --verbose: Verbose output.\n");
@ -116,11 +163,12 @@ int main(int argc, char** argv)
FILE* fd = NULL; FILE* fd = NULL;
bool read = false; bool read = false;
bool write = false; bool write = false;
bool ignore_compat_check = false;
bool verbose = false; bool verbose = false;
bool reset = false; bool reset = false;
uint16_t usb_api; uint16_t usb_api;
while ((opt = getopt_long(argc, argv, "a:l:r:w:d:vRh?", long_options, while ((opt = getopt_long(argc, argv, "a:l:r:w:id:vRh?", long_options,
&option_index)) != EOF) { &option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'a': case 'a':
@ -141,6 +189,10 @@ int main(int argc, char** argv)
path = optarg; path = optarg;
break; break;
case 'i':
ignore_compat_check = true;
break;
case 'd': case 'd':
serial_number = optarg; serial_number = optarg;
break; break;
@ -278,6 +330,16 @@ int main(int argc, char** argv)
fd = NULL; fd = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(!ignore_compat_check) {
printf("Checking target device compatibility\n");
result = compatibility_check(data, length, device);
if(result) {
printf("Compatibility test failed.\n");
fclose(fd);
fd = NULL;
return EXIT_FAILURE;
}
}
printf("Erasing SPI flash.\n"); printf("Erasing SPI flash.\n");
result = hackrf_spiflash_erase(device); result = hackrf_spiflash_erase(device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {