132 lines
4.7 KiB
C
132 lines
4.7 KiB
C
/*
|
|
Turbo BDM Light ColdFire
|
|
Copyright (C) 2006 Daniel Malik
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "version.h"
|
|
#include "log_cmdline.h"
|
|
#include "tblcf.h"
|
|
|
|
char device_name[128];
|
|
int device_no=0;
|
|
|
|
unsigned char unsec_instr[4];
|
|
unsigned int unsec_instruction_len;
|
|
unsigned char flash_clock_divisor;
|
|
|
|
/* returns number of parameters or a negative number in case of error */
|
|
char handleoptions(int argc,char *argv[]) {
|
|
int i,notoption=0;
|
|
for (i=1; i< argc;i++) {
|
|
if (argv[i][0] == '/' || argv[i][0] == '-') {
|
|
switch (argv[i][1]) {
|
|
case 'd':
|
|
case 'D':
|
|
/* USB device number */
|
|
{
|
|
strcpy (device_name, argv[i]+2);
|
|
print_screen("Device #: %s\n",device_name);
|
|
break;
|
|
}
|
|
case 'l':
|
|
case 'L':
|
|
/* -l<log file> */
|
|
open_log(argv[i]+2);
|
|
break;
|
|
default:
|
|
print_screen("Unknown option %s\n",argv[i]);
|
|
return(-1);
|
|
}
|
|
} else {
|
|
if (notoption==0) {
|
|
unsigned long int unsec_instruction;
|
|
sscanf(argv[i],"%lX",&unsec_instruction);
|
|
print_screen("Unsecure instruction: 0x%lX\n",unsec_instruction);
|
|
unsec_instr[0]=unsec_instruction&0xff;
|
|
unsec_instr[1]=(unsec_instruction>>8)&0xff;
|
|
unsec_instr[2]=(unsec_instruction>>16)&0xff;
|
|
unsec_instr[3]=(unsec_instruction>>24)&0xff;
|
|
} else if (notoption==1) {
|
|
sscanf(argv[i],"%d",&unsec_instruction_len);
|
|
print_screen("Instruction length: %d\n",unsec_instruction_len);
|
|
} else if (notoption==2) {
|
|
unsigned int flash_clock_div;
|
|
sscanf(argv[i],"%X",&flash_clock_div);
|
|
flash_clock_divisor = flash_clock_div&0xff;
|
|
print_screen("Flash clock divisor: 0x%X\n",flash_clock_divisor);
|
|
} else {
|
|
print_screen("Too many parameters!\n");
|
|
}
|
|
notoption++;
|
|
}
|
|
}
|
|
return(notoption);
|
|
}
|
|
|
|
void usage(void) {
|
|
print_screen("\nUsage:\n\nTBLCF_UNSEC [<options>] <LR_INSTR> <LEN> <CLKDIV>\n\n");
|
|
print_screen("<LR_INSTR>\tLOCKOUT_RECOVERY JTAG instruction in hexadecimal\n");
|
|
print_screen("<LEN>\t\tLength of the unsecure instruction in decimal\n");
|
|
print_screen("<CLKDIV>\tFlash clock divisor in hexadecimal\n\n");
|
|
print_screen("Options:\n\n");
|
|
print_screen("-D<n>\t\tSpecify which USB device to work with\n");
|
|
print_screen("-L<log file>\tWrite messages into a log file\n\n");
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int i;
|
|
unsigned char idcode[4]={0,0,0,1}; /* IDCODE instruction */
|
|
unsigned char part_id[4];
|
|
print_screen("Turbo BDM Light ColdFire Unsecure Utility ver %01X.%01X.\nCompiled on %s, %s.\n",TBLCF_UNSEC_VERSION>>4,TBLCF_UNSEC_VERSION&0x0f,__DATE__,__TIME__);
|
|
print_screen("TBLCF DLL version: %02X\n",tblcf_version());
|
|
/* handle user supplied options */
|
|
i=handleoptions(argc,argv);
|
|
if (i != 3) { /* number of parameters is incorrect */
|
|
print_screen("Number of parameters incorrect\n");
|
|
usage();
|
|
return(1);
|
|
}
|
|
print_screen("found %d Turbo BDM Light ColdFire device(s)\n",i=tblcf_init());
|
|
if (device_no>=i) {
|
|
print_screen("Not enough devices connected to work with device #%d\n",device_no);
|
|
return(1);
|
|
}
|
|
device_no = tblcf_open(device_name);
|
|
tblcf_set_target_type(device_no, JTAG); /* select JTAG target */
|
|
tblcf_jtag_sel_shift(device_no, 1); /* select instruction path */
|
|
tblcf_jtag_write(device_no,
|
|
unsec_instruction_len,1,idcode+4-((unsec_instruction_len-1)>>3)); /* shift the IDCODE instruction in */
|
|
tblcf_jtag_sel_shift(device_no, 0); /* select data path */
|
|
tblcf_jtag_read(device_no, 32,1,part_id); /* get the ID */
|
|
printf("Part ID: %02X%02X%02X%02X\n",part_id[0],part_id[1],part_id[2],part_id[3]);
|
|
tblcf_jtag_sel_shift(device_no, 1); /* select instruction path */
|
|
tblcf_jtag_write(device_no, unsec_instruction_len,1,unsec_instr); /* shift the LOCKOUT_RECOVERY instruction in */
|
|
tblcf_jtag_sel_shift(device_no, 0); /* select data path */
|
|
tblcf_jtag_write(device_no, 7,1,&flash_clock_divisor); /* shift the flash clk div in */
|
|
tblcf_jtag_sel_reset(device_no); /* go to TEST-LOGIC-RESET */
|
|
usleep(300 * 1000); /* wait to make sure the flash is mass erased before exiting */
|
|
tblcf_close(device_no);
|
|
printf("Done.\n");
|
|
return(0);
|
|
}
|
|
|
|
|