CHG: enables proxmark3 client to reconnect to serial port without exiting / restarting.

This commit is contained in:
iceman1001 2017-09-26 17:04:25 +02:00
commit b18920b9f9
3 changed files with 89 additions and 41 deletions

View file

@ -27,15 +27,15 @@ static char* serial_port_name;
void cmd_debug(UsbCommand* UC) { void cmd_debug(UsbCommand* UC) {
// Debug // Debug
printf("UsbCommand length[len=%zd]\n",sizeof(UsbCommand)); printf("UsbCommand length[len=%zd]\n", sizeof(UsbCommand));
printf(" cmd[len=%zd]: %016" PRIx64"\n",sizeof(UC->cmd),UC->cmd); printf(" cmd[len=%zd]: %016" PRIx64"\n", sizeof(UC->cmd), UC->cmd);
printf(" arg0[len=%zd]: %016" PRIx64"\n",sizeof(UC->arg[0]),UC->arg[0]); printf(" arg0[len=%zd]: %016" PRIx64"\n", sizeof(UC->arg[0]), UC->arg[0]);
printf(" arg1[len=%zd]: %016" PRIx64"\n",sizeof(UC->arg[1]),UC->arg[1]); printf(" arg1[len=%zd]: %016" PRIx64"\n", sizeof(UC->arg[1]), UC->arg[1]);
printf(" arg2[len=%zd]: %016" PRIx64"\n",sizeof(UC->arg[2]),UC->arg[2]); printf(" arg2[len=%zd]: %016" PRIx64"\n", sizeof(UC->arg[2]), UC->arg[2]);
printf(" data[len=%zd]: ",sizeof(UC->d.asBytes)); printf(" data[len=%zd]: ", sizeof(UC->d.asBytes));
for (size_t i=0; i<16; i++) for (size_t i=0; i<16; i++)
printf("%02x",UC->d.asBytes[i]); printf("%02x", UC->d.asBytes[i]);
printf("...\n"); printf("...\n");
} }
@ -43,7 +43,7 @@ void cmd_debug(UsbCommand* UC) {
void SendCommand(UsbCommand* txcmd) { void SendCommand(UsbCommand* txcmd) {
// printf("send: "); // printf("send: ");
// cmd_debug(txcmd); // cmd_debug(txcmd);
if (!uart_send(sp,(byte_t*)txcmd,sizeof(UsbCommand))) { if (!uart_send(sp,(byte_t*)txcmd, sizeof(UsbCommand))) {
printf("Sending bytes to proxmark failed\n"); printf("Sending bytes to proxmark failed\n");
exit(1); exit(1);
} }
@ -80,8 +80,7 @@ int OpenProxmark(size_t i) {
return 1; return 1;
} }
static void usage(char *argv0) static void usage(char *argv0) {
{
fprintf(stderr, "Usage: %s <port> [-b] image.elf [image.elf...]\n\n", argv0); fprintf(stderr, "Usage: %s <port> [-b] image.elf [image.elf...]\n\n", argv0);
fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n"); fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n");
fprintf(stderr, "\nExample (Linux):\n\n\t %s /dev/ttyACM0 armsrc/obj/fullimage.elf\n", argv0); fprintf(stderr, "\nExample (Linux):\n\n\t %s /dev/ttyACM0 armsrc/obj/fullimage.elf\n", argv0);

View file

@ -28,9 +28,10 @@
// a global mutex to prevent interlaced printing from different threads // a global mutex to prevent interlaced printing from different threads
extern pthread_mutex_t print_lock; extern pthread_mutex_t print_lock;
static serial_port sp; static serial_port sp;
static UsbCommand txcmd; static UsbCommand txcmd;
static char comport[255];
volatile static bool txcmd_pending = false; volatile static bool txcmd_pending = false;
void SendCommand(UsbCommand *c) { void SendCommand(UsbCommand *c) {
@ -77,9 +78,30 @@ static void showBanner(void){
} }
#endif #endif
static bool hookUpPM3() {
bool ret = false;
sp = uart_open( comport );
if (sp == INVALID_SERIAL_PORT) {
printf("ERROR: invalid serial port\n");
ret = false;
offline = 1;
} else if (sp == CLAIMED_SERIAL_PORT) {
printf("ERROR: serial port is claimed by another process\n");
ret = false;
offline = 1;
} else {
//printf("OK: connected to serial port %s\n", comport);
ret = true;
offline = 0;
}
return ret;
}
// (iceman) if uart_receiver fails a command three times, we conside the device to be offline.
static void *uart_receiver(void *targ) { static void *uart_receiver(void *targ) {
struct receiver_arg *arg = (struct receiver_arg*)targ; struct receiver_arg *arg = (struct receiver_arg*)targ;
size_t rxlen; size_t rxlen;
int counter_to_offline = 0;
while (arg->run) { while (arg->run) {
rxlen = 0; rxlen = 0;
@ -98,24 +120,36 @@ static void *uart_receiver(void *targ) {
if ( tmpsignal ) { if ( tmpsignal ) {
bool res = uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand)); bool res = uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand));
if (!res) { if (!res) {
counter_to_offline++;
PrintAndLog("Sending bytes to proxmark failed"); PrintAndLog("Sending bytes to proxmark failed");
} }
__atomic_clear(&txcmd_pending, __ATOMIC_SEQ_CST); __atomic_clear(&txcmd_pending, __ATOMIC_SEQ_CST);
//txcmd_pending = false; //txcmd_pending = false;
// set offline flag
if ( counter_to_offline == 3 ) {
__atomic_test_and_set(&offline, __ATOMIC_SEQ_CST);
break;
} }
} }
}
// when this reader thread dies, we close the serial port.
uart_close(sp);
pthread_exit(NULL); pthread_exit(NULL);
return NULL; return NULL;
} }
void main_loop(char *script_cmds_file, bool usb_present) { void main_loop(char *script_cmds_file, bool usb_present) {
struct receiver_arg rarg; struct receiver_arg rarg;
char *cmd = NULL;
pthread_t reader_thread; pthread_t reader_thread;
char *cmd = NULL;
if (usb_present) { if (usb_present) {
rarg.run = 1; rarg.run = 1;
//
pthread_create(&reader_thread, NULL, &uart_receiver, &rarg); pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
// cache Version information now: // cache Version information now:
CmdVersion(NULL); CmdVersion(NULL);
@ -133,8 +167,24 @@ void main_loop(char *script_cmds_file, bool usb_present) {
read_history(".history"); read_history(".history");
// loops everytime enter is pressed...
while(1) { while(1) {
// this should hook up the PM3 again.
if (offline) {
// sets the global variable, SP and offline)
usb_present = hookUpPM3();
// usb and the reader_thread is NULL, create a new reader thread.
if (usb_present && !offline) {
rarg.run = 1;
pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
// cache Version information now:
CmdVersion(NULL);
}
}
// If there is a script file // If there is a script file
if (script_file) { if (script_file) {
@ -245,7 +295,8 @@ int main(int argc, char* argv[]) {
if (argc < 2) { if (argc < 2) {
printf("syntax: %s <port>\n\n",argv[0]); printf("syntax: %s <port>\n\n",argv[0]);
printf("\tLinux example:'%s /dev/ttyACM0'\n\n", argv[0]); printf("\tLinux example:'%s /dev/ttyACM0'\n", argv[0]);
printf("\tWindows example:'%s com3'\n\n", argv[0]);
printf("help: %s -h\n\n", argv[0]); printf("help: %s -h\n\n", argv[0]);
printf("\tDump all interactive help at once\n"); printf("\tDump all interactive help at once\n");
printf("markdown: %s -m\n\n", argv[0]); printf("markdown: %s -m\n\n", argv[0]);
@ -254,7 +305,8 @@ int main(int argc, char* argv[]) {
} }
if (strcmp(argv[1], "-h") == 0) { if (strcmp(argv[1], "-h") == 0) {
printf("syntax: %s <port>\n\n",argv[0]); printf("syntax: %s <port>\n\n",argv[0]);
printf("\tLinux example:'%s /dev/ttyACM0'\n\n", argv[0]); printf("\tLinux example:'%s /dev/ttyACM0'\n", argv[0]);
printf("\tWindows example:'%s com3'\n\n", argv[0]);
dumpAllHelp(0); dumpAllHelp(0);
return 0; return 0;
} }
@ -270,25 +322,20 @@ int main(int argc, char* argv[]) {
set_my_executable_path(); set_my_executable_path();
bool usb_present = false;
char *script_cmds_file = NULL; char *script_cmds_file = NULL;
sp = uart_open(argv[1]); // lets copy the comport string.
if (sp == INVALID_SERIAL_PORT) { memset(comport, 0, sizeof(comport));
printf("ERROR: invalid serial port\n"); memcpy(comport, argv[1], strlen(argv[1]));
usb_present = false;
offline = 1; // sets the global variable, SP and offline)
} else if (sp == CLAIMED_SERIAL_PORT) { bool usb_present = hookUpPM3();
printf("ERROR: serial port is claimed by another process\n");
usb_present = false;
offline = 1;
} else {
usb_present = true;
offline = 0;
}
// If the user passed the filename of the 'script' to execute, get it // If the user passed the filename of the 'script' to execute, get it
if (argc > 2 && argv[2]) { if (argc > 2 && argv[2]) {
printf("Num of args: %d -- %s\n", argc, argv[2]);
if (argv[2][0] == 'f' && //buzzy, if a word 'flush' passed, flush the output after every log entry. if (argv[2][0] == 'f' && //buzzy, if a word 'flush' passed, flush the output after every log entry.
argv[2][1] == 'l' && argv[2][1] == 'l' &&
argv[2][2] == 'u' && argv[2][2] == 'u' &&

View file

@ -62,11 +62,11 @@ serial_port uart_open(const char* pcPortName) {
serial_port_windows* sp = malloc(sizeof(serial_port_windows)); serial_port_windows* sp = malloc(sizeof(serial_port_windows));
// Copy the input "com?" to "\\.\COM?" format // Copy the input "com?" to "\\.\COM?" format
sprintf(acPortName,"\\\\.\\%s",pcPortName); sprintf(acPortName,"\\\\.\\%s", pcPortName);
upcase(acPortName); upcase(acPortName);
// Try to open the serial port // Try to open the serial port
sp->hPort = CreateFileA(acPortName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); sp->hPort = CreateFileA(acPortName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (sp->hPort == INVALID_HANDLE_VALUE) { if (sp->hPort == INVALID_HANDLE_VALUE) {
uart_close(sp); uart_close(sp);
return INVALID_SERIAL_PORT; return INVALID_SERIAL_PORT;
@ -75,13 +75,13 @@ serial_port uart_open(const char* pcPortName) {
// Prepare the device control // Prepare the device control
memset(&sp->dcb, 0, sizeof(DCB)); memset(&sp->dcb, 0, sizeof(DCB));
sp->dcb.DCBlength = sizeof(DCB); sp->dcb.DCBlength = sizeof(DCB);
if(!BuildCommDCBA("baud=115200 parity=N data=8 stop=1",&sp->dcb)) { if (!BuildCommDCBA("baud=115200 parity=N data=8 stop=1",&sp->dcb)) {
uart_close(sp); uart_close(sp);
return INVALID_SERIAL_PORT; return INVALID_SERIAL_PORT;
} }
// Update the active serial port // Update the active serial port
if(!SetCommState(sp->hPort,&sp->dcb)) { if (!SetCommState(sp->hPort, &sp->dcb)) {
uart_close(sp); uart_close(sp);
return INVALID_SERIAL_PORT; return INVALID_SERIAL_PORT;
} }
@ -92,7 +92,7 @@ serial_port uart_open(const char* pcPortName) {
sp->ct.WriteTotalTimeoutMultiplier = 0;//1; sp->ct.WriteTotalTimeoutMultiplier = 0;//1;
sp->ct.WriteTotalTimeoutConstant = 30; sp->ct.WriteTotalTimeoutConstant = 30;
if(!SetCommTimeouts(sp->hPort,&sp->ct)) { if (!SetCommTimeouts(sp->hPort, &sp->ct)) {
uart_close(sp); uart_close(sp);
return INVALID_SERIAL_PORT; return INVALID_SERIAL_PORT;
} }
@ -107,18 +107,20 @@ serial_port uart_open(const char* pcPortName) {
} }
void uart_close(const serial_port sp) { void uart_close(const serial_port sp) {
if (!sp) return;
if (((serial_port_windows*)sp)->hPort != NULL )
CloseHandle(((serial_port_windows*)sp)->hPort); CloseHandle(((serial_port_windows*)sp)->hPort);
free(sp); free(sp);
} }
bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) {
ReadFile(((serial_port_windows*)sp)->hPort,pbtRx,pszMaxRxLen,(LPDWORD)pszRxLen,NULL); ReadFile(((serial_port_windows*)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL);
return (*pszRxLen != 0); return (*pszRxLen != 0);
} }
bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) {
DWORD dwTxLen = 0; DWORD dwTxLen = 0;
return WriteFile(((serial_port_windows*)sp)->hPort,pbtTx,szTxLen,&dwTxLen,NULL); return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL);
return (dwTxLen != 0); return (dwTxLen != 0);
} }