fix one too small
[RRG-proxmark3.git] / client / src / cmdhw.c
blobc1007a86aca41109ef577502e90576af4ae9179c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Hardware commands
17 // low-level hardware control
18 //-----------------------------------------------------------------------------
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
25 #include "cmdparser.h" // command_t
26 #include "cliparser.h"
27 #include "comms.h"
28 #include "usart_defs.h"
29 #include "ui.h"
30 #include "fpga.h"
31 #include "cmdhw.h"
32 #include "cmddata.h"
33 #include "commonutil.h"
34 #include "preferences.h"
35 #include "pm3_cmd.h"
36 #include "pmflash.h" // rdv40validation_t
37 #include "cmdflashmem.h" // get_signature..
38 #include "uart/uart.h" // configure timeout
39 #include "util_posix.h"
40 #include "flash.h" // reboot to bootloader mode
41 #include "proxgui.h"
42 #include "graph.h" // for graph data
44 static int CmdHelp(const char *Cmd);
46 static void lookup_chipid_short(uint32_t iChipID, uint32_t mem_used) {
47 const char *asBuff;
48 switch (iChipID) {
49 case 0x270B0A40:
50 asBuff = "AT91SAM7S512 Rev A";
51 break;
52 case 0x270B0A4E:
53 case 0x270B0A4F:
54 asBuff = "AT91SAM7S512 Rev B";
55 break;
56 case 0x270D0940:
57 asBuff = "AT91SAM7S256 Rev A";
58 break;
59 case 0x270B0941:
60 asBuff = "AT91SAM7S256 Rev B";
61 break;
62 case 0x270B0942:
63 asBuff = "AT91SAM7S256 Rev C";
64 break;
65 case 0x270B0943:
66 asBuff = "AT91SAM7S256 Rev D";
67 break;
68 case 0x270C0740:
69 asBuff = "AT91SAM7S128 Rev A";
70 break;
71 case 0x270A0741:
72 asBuff = "AT91SAM7S128 Rev B";
73 break;
74 case 0x270A0742:
75 asBuff = "AT91SAM7S128 Rev C";
76 break;
77 case 0x270A0743:
78 asBuff = "AT91SAM7S128 Rev D";
79 break;
80 case 0x27090540:
81 asBuff = "AT91SAM7S64 Rev A";
82 break;
83 case 0x27090543:
84 asBuff = "AT91SAM7S64 Rev B";
85 break;
86 case 0x27090544:
87 asBuff = "AT91SAM7S64 Rev C";
88 break;
89 case 0x27080342:
90 asBuff = "AT91SAM7S321 Rev A";
91 break;
92 case 0x27080340:
93 asBuff = "AT91SAM7S32 Rev A";
94 break;
95 case 0x27080341:
96 asBuff = "AT91SAM7S32 Rev B";
97 break;
98 case 0x27050241:
99 asBuff = "AT9SAM7S161 Rev A";
100 break;
101 case 0x27050240:
102 asBuff = "AT91SAM7S16 Rev A";
103 break;
104 default:
105 asBuff = "Unknown";
106 break;
108 PrintAndLogEx(NORMAL, " MCU....... " _YELLOW_("%s"), asBuff);
110 uint32_t mem_avail = 0;
111 switch ((iChipID & 0xF00) >> 8) {
112 case 0:
113 mem_avail = 0;
114 break;
115 case 1:
116 mem_avail = 8;
117 break;
118 case 2:
119 mem_avail = 16;
120 break;
121 case 3:
122 mem_avail = 32;
123 break;
124 case 5:
125 mem_avail = 64;
126 break;
127 case 7:
128 mem_avail = 128;
129 break;
130 case 9:
131 mem_avail = 256;
132 break;
133 case 10:
134 mem_avail = 512;
135 break;
136 case 12:
137 mem_avail = 1024;
138 break;
139 case 14:
140 mem_avail = 2048;
141 break;
144 PrintAndLogEx(NORMAL, " Memory.... " _YELLOW_("%u") " KB ( " _YELLOW_("%2.0f%%") " used )"
145 , mem_avail
146 , mem_avail == 0 ? 0.0f : (float)mem_used / (mem_avail * 1024) * 100
149 PrintAndLogEx(NORMAL, "");
152 static void lookupChipID(uint32_t iChipID, uint32_t mem_used) {
153 const char *asBuff;
154 uint32_t mem_avail = 0;
155 PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Hardware") " ]");
157 switch (iChipID) {
158 case 0x270B0A40:
159 asBuff = "AT91SAM7S512 Rev A";
160 break;
161 case 0x270B0A4E:
162 case 0x270B0A4F:
163 asBuff = "AT91SAM7S512 Rev B";
164 break;
165 case 0x270D0940:
166 asBuff = "AT91SAM7S256 Rev A";
167 break;
168 case 0x270B0941:
169 asBuff = "AT91SAM7S256 Rev B";
170 break;
171 case 0x270B0942:
172 asBuff = "AT91SAM7S256 Rev C";
173 break;
174 case 0x270B0943:
175 asBuff = "AT91SAM7S256 Rev D";
176 break;
177 case 0x270C0740:
178 asBuff = "AT91SAM7S128 Rev A";
179 break;
180 case 0x270A0741:
181 asBuff = "AT91SAM7S128 Rev B";
182 break;
183 case 0x270A0742:
184 asBuff = "AT91SAM7S128 Rev C";
185 break;
186 case 0x270A0743:
187 asBuff = "AT91SAM7S128 Rev D";
188 break;
189 case 0x27090540:
190 asBuff = "AT91SAM7S64 Rev A";
191 break;
192 case 0x27090543:
193 asBuff = "AT91SAM7S64 Rev B";
194 break;
195 case 0x27090544:
196 asBuff = "AT91SAM7S64 Rev C";
197 break;
198 case 0x27080342:
199 asBuff = "AT91SAM7S321 Rev A";
200 break;
201 case 0x27080340:
202 asBuff = "AT91SAM7S32 Rev A";
203 break;
204 case 0x27080341:
205 asBuff = "AT91SAM7S32 Rev B";
206 break;
207 case 0x27050241:
208 asBuff = "AT9SAM7S161 Rev A";
209 break;
210 case 0x27050240:
211 asBuff = "AT91SAM7S16 Rev A";
212 break;
213 default:
214 asBuff = "Unknown";
215 break;
217 PrintAndLogEx(NORMAL, " --= uC: " _YELLOW_("%s"), asBuff);
219 switch ((iChipID & 0xE0) >> 5) {
220 case 1:
221 asBuff = "ARM946ES";
222 break;
223 case 2:
224 asBuff = "ARM7TDMI";
225 break;
226 case 4:
227 asBuff = "ARM920T";
228 break;
229 case 5:
230 asBuff = "ARM926EJS";
231 break;
232 default:
233 asBuff = "Unknown";
234 break;
236 PrintAndLogEx(NORMAL, " --= Embedded Processor: %s", asBuff);
238 switch ((iChipID & 0xF0000) >> 16) {
239 case 1:
240 asBuff = "1K bytes";
241 break;
242 case 2:
243 asBuff = "2K bytes";
244 break;
245 case 3:
246 asBuff = "6K bytes";
247 break;
248 case 4:
249 asBuff = "112K bytes";
250 break;
251 case 5:
252 asBuff = "4K bytes";
253 break;
254 case 6:
255 asBuff = "80K bytes";
256 break;
257 case 7:
258 asBuff = "160K bytes";
259 break;
260 case 8:
261 asBuff = "8K bytes";
262 break;
263 case 9:
264 asBuff = "16K bytes";
265 break;
266 case 10:
267 asBuff = "32K bytes";
268 break;
269 case 11:
270 asBuff = "64K bytes";
271 break;
272 case 12:
273 asBuff = "128K bytes";
274 break;
275 case 13:
276 asBuff = "256K bytes";
277 break;
278 case 14:
279 asBuff = "96K bytes";
280 break;
281 case 15:
282 asBuff = "512K bytes";
283 break;
284 default:
285 asBuff = "Unknown";
286 break;
288 PrintAndLogEx(NORMAL, " --= Internal SRAM size: %s", asBuff);
290 switch ((iChipID & 0xFF00000) >> 20) {
291 case 0x19:
292 asBuff = "AT91SAM9xx Series";
293 break;
294 case 0x29:
295 asBuff = "AT91SAM9XExx Series";
296 break;
297 case 0x34:
298 asBuff = "AT91x34 Series";
299 break;
300 case 0x37:
301 asBuff = "CAP7 Series";
302 break;
303 case 0x39:
304 asBuff = "CAP9 Series";
305 break;
306 case 0x3B:
307 asBuff = "CAP11 Series";
308 break;
309 case 0x40:
310 asBuff = "AT91x40 Series";
311 break;
312 case 0x42:
313 asBuff = "AT91x42 Series";
314 break;
315 case 0x55:
316 asBuff = "AT91x55 Series";
317 break;
318 case 0x60:
319 asBuff = "AT91SAM7Axx Series";
320 break;
321 case 0x61:
322 asBuff = "AT91SAM7AQxx Series";
323 break;
324 case 0x63:
325 asBuff = "AT91x63 Series";
326 break;
327 case 0x70:
328 asBuff = "AT91SAM7Sxx Series";
329 break;
330 case 0x71:
331 asBuff = "AT91SAM7XCxx Series";
332 break;
333 case 0x72:
334 asBuff = "AT91SAM7SExx Series";
335 break;
336 case 0x73:
337 asBuff = "AT91SAM7Lxx Series";
338 break;
339 case 0x75:
340 asBuff = "AT91SAM7Xxx Series";
341 break;
342 case 0x92:
343 asBuff = "AT91x92 Series";
344 break;
345 case 0xF0:
346 asBuff = "AT75Cxx Series";
347 break;
348 default:
349 asBuff = "Unknown";
350 break;
352 PrintAndLogEx(NORMAL, " --= Architecture identifier: %s", asBuff);
354 switch ((iChipID & 0x70000000) >> 28) {
355 case 0:
356 asBuff = "ROM";
357 break;
358 case 1:
359 asBuff = "ROMless or on-chip Flash";
360 break;
361 case 2:
362 asBuff = "Embedded flash memory";
363 break;
364 case 3:
365 asBuff = "ROM and Embedded flash memory\nNVPSIZ is ROM size\nNVPSIZ2 is Flash size";
366 break;
367 case 4:
368 asBuff = "SRAM emulating ROM";
369 break;
370 default:
371 asBuff = "Unknown";
372 break;
374 switch ((iChipID & 0xF00) >> 8) {
375 case 0:
376 mem_avail = 0;
377 break;
378 case 1:
379 mem_avail = 8;
380 break;
381 case 2:
382 mem_avail = 16;
383 break;
384 case 3:
385 mem_avail = 32;
386 break;
387 case 5:
388 mem_avail = 64;
389 break;
390 case 7:
391 mem_avail = 128;
392 break;
393 case 9:
394 mem_avail = 256;
395 break;
396 case 10:
397 mem_avail = 512;
398 break;
399 case 12:
400 mem_avail = 1024;
401 break;
402 case 14:
403 mem_avail = 2048;
404 break;
407 PrintAndLogEx(NORMAL, " --= %s " _YELLOW_("%uK") " bytes ( " _YELLOW_("%2.0f%%") " used )"
408 , asBuff
409 , mem_avail
410 , mem_avail == 0 ? 0.0f : (float)mem_used / (mem_avail * 1024) * 100
414 switch ((iChipID & 0xF000) >> 12) {
415 case 0:
416 asBuff = "None");
417 break;
418 case 1:
419 asBuff = "8K bytes");
420 break;
421 case 2:
422 asBuff = "16K bytes");
423 break;
424 case 3:
425 asBuff = "32K bytes");
426 break;
427 case 5:
428 asBuff = "64K bytes");
429 break;
430 case 7:
431 asBuff = "128K bytes");
432 break;
433 case 9:
434 asBuff = "256K bytes");
435 break;
436 case 10:
437 asBuff = "512K bytes");
438 break;
439 case 12:
440 asBuff = "1024K bytes");
441 break;
442 case 14:
443 asBuff = "2048K bytes");
444 break;
446 PrintAndLogEx(NORMAL, " --= Second nonvolatile program memory size: %s", asBuff);
450 static int CmdDbg(const char *Cmd) {
452 CLIParserContext *ctx;
453 CLIParserInit(&ctx, "hw dbg",
454 "Set device side debug level output.\n"
455 "Note: option `-4`, this option may cause malfunction itself by\n"
456 "introducing delays in time critical functions like simulation or sniffing",
457 "hw dbg --> get current log level\n"
458 "hw dbg -1 --> set log level to _error_\n"
461 void *argtable[] = {
462 arg_param_begin,
463 arg_lit0("0", NULL, "no debug messages"),
464 arg_lit0("1", NULL, "error messages"),
465 arg_lit0("2", NULL, "plus information messages"),
466 arg_lit0("3", NULL, "plus debug messages"),
467 arg_lit0("4", NULL, "print even debug messages in timing critical functions"),
468 arg_param_end
470 CLIExecWithReturn(ctx, Cmd, argtable, true);
471 bool lv0 = arg_get_lit(ctx, 1);
472 bool lv1 = arg_get_lit(ctx, 2);
473 bool lv2 = arg_get_lit(ctx, 3);
474 bool lv3 = arg_get_lit(ctx, 4);
475 bool lv4 = arg_get_lit(ctx, 5);
476 CLIParserFree(ctx);
478 if ((lv0 + lv1 + lv2 + lv3 + lv4) > 1) {
479 PrintAndLogEx(INFO, "Can only set one debug level");
480 return PM3_EINVARG;
483 uint8_t curr = DBG_NONE;
484 if (getDeviceDebugLevel(&curr) != PM3_SUCCESS)
485 return PM3_EFAILED;
487 const char *dbglvlstr;
488 switch (curr) {
489 case DBG_NONE:
490 dbglvlstr = "none";
491 break;
492 case DBG_ERROR:
493 dbglvlstr = "error";
494 break;
495 case DBG_INFO:
496 dbglvlstr = "info";
497 break;
498 case DBG_DEBUG:
499 dbglvlstr = "debug";
500 break;
501 case DBG_EXTENDED:
502 dbglvlstr = "extended";
503 break;
504 default:
505 dbglvlstr = "unknown";
506 break;
508 PrintAndLogEx(INFO, " Current debug log level..... %d ( " _YELLOW_("%s")" )", curr, dbglvlstr);
511 if ((lv0 + lv1 + lv2 + lv3 + lv4) == 1) {
512 uint8_t dbg = 0;
513 if (lv0)
514 dbg = 0;
515 else if (lv1)
516 dbg = 1;
517 else if (lv2)
518 dbg = 2;
519 else if (lv3)
520 dbg = 3;
521 else if (lv4)
522 dbg = 4;
524 if (setDeviceDebugLevel(dbg, true) != PM3_SUCCESS)
525 return PM3_EFAILED;
527 return PM3_SUCCESS;
530 static int CmdDetectReader(const char *Cmd) {
531 CLIParserContext *ctx;
532 CLIParserInit(&ctx, "hw detectreader",
533 "Start to detect presences of reader field",
534 "hw detectreader\n"
535 "hw detectreader -L\n"
538 void *argtable[] = {
539 arg_param_begin,
540 arg_lit0("L", "LF", "only detect low frequency 125/134 kHz"),
541 arg_lit0("H", "HF", "only detect high frequency 13.56 MHZ"),
542 arg_param_end
544 CLIExecWithReturn(ctx, Cmd, argtable, true);
545 bool lf = arg_get_lit(ctx, 1);
546 bool hf = arg_get_lit(ctx, 2);
547 CLIParserFree(ctx);
549 // 0: Detect both frequency in mode 1
550 // 1: LF_ONLY
551 // 2: HF_ONLY
552 uint8_t arg = 0;
553 if (lf == true && hf == false) {
554 arg = 1;
555 } else if (hf == true && lf == false) {
556 arg = 2;
559 clearCommandBuffer();
560 SendCommandNG(CMD_LISTEN_READER_FIELD, (uint8_t *)&arg, sizeof(arg));
561 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or " _GREEN_("<Enter>") " to change modes and exit");
563 for (;;) {
564 if (kbd_enter_pressed()) {
565 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
566 PrintAndLogEx(DEBUG, _GREEN_("<Enter>") " pressed");
569 PacketResponseNG resp;
570 if (WaitForResponseTimeout(CMD_LISTEN_READER_FIELD, &resp, 1000)) {
571 if (resp.status != PM3_EOPABORTED) {
572 PrintAndLogEx(ERR, "Unexpected response: %d", resp.status);
574 break;
577 PrintAndLogEx(INFO, "Done!");
578 return PM3_SUCCESS;
581 // ## FPGA Control
582 static int CmdFPGAOff(const char *Cmd) {
583 CLIParserContext *ctx;
584 CLIParserInit(&ctx, "hw fpgaoff",
585 "Turn of fpga and antenna field",
586 "hw fpgaoff\n"
589 void *argtable[] = {
590 arg_param_begin,
591 arg_param_end
593 CLIExecWithReturn(ctx, Cmd, argtable, true);
594 CLIParserFree(ctx);
596 clearCommandBuffer();
597 SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF, NULL, 0);
598 return PM3_SUCCESS;
601 static int CmdLCD(const char *Cmd) {
602 CLIParserContext *ctx;
603 CLIParserInit(&ctx, "hw lcd",
604 "Send command/data to LCD",
605 "hw lcd -r AA -c 03 -> sends 0xAA three times"
608 void *argtable[] = {
609 arg_param_begin,
610 arg_int1("r", "raw", "<hex>", "data "),
611 arg_int1("c", "cnt", "<dec>", "number of times to send"),
612 arg_param_end
614 CLIExecWithReturn(ctx, Cmd, argtable, true);
616 int r_len = 0;
617 uint8_t raw[1] = {0};
618 CLIGetHexWithReturn(ctx, 1, raw, &r_len);
619 int j = arg_get_int_def(ctx, 2, 1);
620 CLIParserFree(ctx);
621 if (j < 1) {
622 PrintAndLogEx(WARNING, "Count must be larger than zero");
623 return PM3_EINVARG;
626 while (j--) {
627 clearCommandBuffer();
628 SendCommandMIX(CMD_LCD, raw[0], 0, 0, NULL, 0);
630 return PM3_SUCCESS;
633 static int CmdLCDReset(const char *Cmd) {
634 CLIParserContext *ctx;
635 CLIParserInit(&ctx, "hw lcdreset",
636 "Hardware reset LCD",
637 "hw lcdreset\n"
640 void *argtable[] = {
641 arg_param_begin,
642 arg_param_end
644 CLIExecWithReturn(ctx, Cmd, argtable, true);
645 CLIParserFree(ctx);
646 clearCommandBuffer();
647 SendCommandNG(CMD_LCD_RESET, NULL, 0);
648 return PM3_SUCCESS;
651 static int CmdReadmem(const char *Cmd) {
652 CLIParserContext *ctx;
653 CLIParserInit(&ctx, "hw readmem",
654 "Reads processor flash memory into a file or views on console",
655 "hw readmem -f myfile -> save 512KB processor flash memory to file\n"
656 "hw readmem -a 8192 -l 512 -> display 512 bytes from offset 8192\n"
659 void *argtable[] = {
660 arg_param_begin,
661 arg_u64_0("a", "adr", "<dec>", "flash address to start reading from"),
662 arg_u64_0("l", "len", "<dec>", "length (default 32 or 512KB)"),
663 arg_str0("f", "file", "<fn>", "save to file"),
664 arg_u64_0("c", "cols", "<dec>", "column breaks"),
665 arg_lit0("r", "raw", "use raw address mode: read from anywhere, not just flash"),
666 arg_param_end
668 CLIExecWithReturn(ctx, Cmd, argtable, false);
670 // check for -file option first to determine the output mode
671 int fnlen = 0;
672 char filename[FILE_PATH_SIZE] = {0};
673 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
674 bool save_to_file = fnlen > 0;
676 // default len to 512KB when saving to file, to 32 bytes when viewing on the console.
677 uint32_t default_len = save_to_file ? 512 * 1024 : 32;
679 uint32_t address = arg_get_u32_def(ctx, 1, 0);
680 uint32_t len = arg_get_u32_def(ctx, 2, default_len);
681 int breaks = arg_get_int_def(ctx, 4, 32);
682 bool raw = arg_get_lit(ctx, 5);
683 CLIParserFree(ctx);
685 uint8_t *buffer = calloc(len, sizeof(uint8_t));
686 if (!buffer) {
687 PrintAndLogEx(ERR, "error, cannot allocate memory ");
688 return PM3_EMALLOC;
691 const char *flash_str = raw ? "" : " flash";
692 PrintAndLogEx(INFO, "reading "_YELLOW_("%u")" bytes from processor%s memory",
693 len, flash_str);
695 DeviceMemType_t type = raw ? MCU_MEM : MCU_FLASH;
696 if (!GetFromDevice(type, buffer, len, address, NULL, 0, NULL, -1, true)) {
697 PrintAndLogEx(FAILED, "ERROR; reading from MCU flash memory");
698 free(buffer);
699 return PM3_EFLASH;
702 if (save_to_file) {
703 saveFile(filename, ".bin", buffer, len);
704 } else {
705 PrintAndLogEx(INFO, "---- " _CYAN_("processor%s memory") " ----", flash_str);
706 print_hex_break(buffer, len, breaks);
709 free(buffer);
710 return PM3_SUCCESS;
713 static int CmdReset(const char *Cmd) {
714 CLIParserContext *ctx;
715 CLIParserInit(&ctx, "hw reset",
716 "Reset the Proxmark3 device.",
717 "hw reset"
720 void *argtable[] = {
721 arg_param_begin,
722 arg_param_end
724 CLIExecWithReturn(ctx, Cmd, argtable, true);
725 CLIParserFree(ctx);
726 clearCommandBuffer();
727 SendCommandNG(CMD_HARDWARE_RESET, NULL, 0);
728 PrintAndLogEx(INFO, "Proxmark3 has been reset.");
729 return PM3_SUCCESS;
733 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
734 * 600kHz.
736 static int CmdSetDivisor(const char *Cmd) {
738 CLIParserContext *ctx;
739 CLIParserInit(&ctx, "hw setlfdivisor",
740 "Drive LF antenna at 12 MHz / (divisor + 1).",
741 "hw setlfdivisor -d 88"
744 void *argtable[] = {
745 arg_param_begin,
746 arg_u64_1("d", "div", "<dec>", "19 - 255 divisor value (def 95)"),
747 arg_param_end
749 CLIExecWithReturn(ctx, Cmd, argtable, true);
750 uint8_t arg = arg_get_u32_def(ctx, 1, 95);
751 CLIParserFree(ctx);
753 if (arg < 19) {
754 PrintAndLogEx(ERR, "Divisor must be between " _YELLOW_("19") " and " _YELLOW_("255"));
755 return PM3_EINVARG;
757 // 12 000 000 (12MHz)
758 clearCommandBuffer();
759 SendCommandNG(CMD_LF_SET_DIVISOR, (uint8_t *)&arg, sizeof(arg));
760 PrintAndLogEx(SUCCESS, "Divisor set, expected " _YELLOW_("%.1f")" kHz", ((double)12000 / (arg + 1)));
761 return PM3_SUCCESS;
764 static int CmdSetHFThreshold(const char *Cmd) {
766 CLIParserContext *ctx;
767 CLIParserInit(&ctx, "hw sethfthresh",
768 "Set thresholds in HF/14a and Legic mode.",
769 "hw sethfthresh -t 7 -i 20 -l 8"
772 void *argtable[] = {
773 arg_param_begin,
774 arg_int0("t", "thresh", "<dec>", "threshold, used in 14a reader mode (def 7)"),
775 arg_int0("i", "high", "<dec>", "high threshold, used in 14a sniff mode (def 20)"),
776 arg_int0("l", "legic", "<dec>", "threshold used in Legic mode (def 8)"),
777 arg_param_end
779 CLIExecWithReturn(ctx, Cmd, argtable, true);
781 struct {
782 uint8_t threshold;
783 uint8_t threshold_high;
784 uint8_t legic_threshold;
785 } PACKED params;
787 params.threshold = arg_get_int_def(ctx, 1, 7);
788 params.threshold_high = arg_get_int_def(ctx, 2, 20);
789 params.legic_threshold = arg_get_int_def(ctx, 3, 8);
790 CLIParserFree(ctx);
792 if ((params.threshold < 1) || (params.threshold > 63) || (params.threshold_high < 1) || (params.threshold_high > 63)) {
793 PrintAndLogEx(ERR, "Thresholds must be between " _YELLOW_("1") " and " _YELLOW_("63"));
794 return PM3_EINVARG;
797 clearCommandBuffer();
798 SendCommandNG(CMD_HF_ISO14443A_SET_THRESHOLDS, (uint8_t *)&params, sizeof(params));
799 PrintAndLogEx(SUCCESS, "Thresholds set.");
800 return PM3_SUCCESS;
803 static int CmdSetMux(const char *Cmd) {
805 CLIParserContext *ctx;
806 CLIParserInit(&ctx, "hw setmux",
807 "Set the ADC mux to a specific value",
808 "hw setmux --hipkd -> set HIGH PEAK\n"
811 void *argtable[] = {
812 arg_param_begin,
813 arg_lit0(NULL, "lopkd", "low peak"),
814 arg_lit0(NULL, "loraw", "low raw"),
815 arg_lit0(NULL, "hipkd", "high peak"),
816 arg_lit0(NULL, "hiraw", "high raw"),
817 arg_param_end
819 CLIExecWithReturn(ctx, Cmd, argtable, true);
820 bool lopkd = arg_get_lit(ctx, 1);
821 bool loraw = arg_get_lit(ctx, 2);
822 bool hipkd = arg_get_lit(ctx, 3);
823 bool hiraw = arg_get_lit(ctx, 4);
824 CLIParserFree(ctx);
826 if ((lopkd + loraw + hipkd + hiraw) > 1) {
827 PrintAndLogEx(INFO, "Can only set one mux");
828 return PM3_EINVARG;
831 #ifdef WITH_FPC_USART
832 if (loraw || hiraw) {
833 PrintAndLogEx(INFO, "this ADC mux option is unavailable on RDV4 compiled with FPC USART");
834 return PM3_EINVARG;
836 #endif
838 uint8_t arg = 0;
839 if (lopkd)
840 arg = 0;
841 else if (loraw)
842 arg = 1;
843 else if (hipkd)
844 arg = 2;
845 else if (hiraw)
846 arg = 3;
848 clearCommandBuffer();
849 SendCommandNG(CMD_SET_ADC_MUX, (uint8_t *)&arg, sizeof(arg));
850 return PM3_SUCCESS;
853 static int CmdStandalone(const char *Cmd) {
854 CLIParserContext *ctx;
855 CLIParserInit(&ctx, "hw standalone",
856 "Start standalone mode",
857 "hw standalone -> start \n"
858 "hw standalone -a 1 -> start and send arg 1"
861 void *argtable[] = {
862 arg_param_begin,
863 arg_u64_0("a", "arg", "<dec>", "argument byte"),
864 arg_str0("b", NULL, "<str>", "UniSniff arg: 14a, 14b, 15, iclass"),
865 arg_param_end
867 CLIExecWithReturn(ctx, Cmd, argtable, true);
869 struct p {
870 uint8_t arg;
871 uint8_t mlen;
872 uint8_t mode[10];
873 } PACKED packet;
875 packet.arg = arg_get_u32_def(ctx, 1, 1);
876 int mlen = 0;
877 CLIParamStrToBuf(arg_get_str(ctx, 2), packet.mode, sizeof(packet.mode), &mlen);
878 if (mlen) {
879 packet.mlen = mlen;
881 CLIParserFree(ctx);
882 clearCommandBuffer();
883 SendCommandNG(CMD_STANDALONE, (uint8_t *)&packet, sizeof(struct p));
884 return PM3_SUCCESS;
887 static int CmdTune(const char *Cmd) {
889 CLIParserContext *ctx;
890 CLIParserInit(&ctx, "hw tune",
891 "Measure tuning of device antenna. Results shown in graph window.\n"
892 "This command doesn't actively tune your antennas, \n"
893 "it's only informative by measuring voltage that the antennas will generate",
894 "hw tune"
896 void *argtable[] = {
897 arg_param_begin,
898 arg_param_end
900 CLIExecWithReturn(ctx, Cmd, argtable, true);
901 CLIParserFree(ctx);
903 #define NON_VOLTAGE 1000
904 #define LF_UNUSABLE_V 2000
905 #define LF_MARGINAL_V 10000
906 #define HF_UNUSABLE_V 3000
907 #define HF_MARGINAL_V 5000
908 #define ANTENNA_ERROR 1.00 // current algo has 3% error margin.
910 PrintAndLogEx(NORMAL, "");
911 PrintAndLogEx(INFO, "-------- " _CYAN_("Reminder") " ----------------------------");
912 PrintAndLogEx(INFO, "`" _YELLOW_("hw tune") "` doesn't actively tune your antennas.");
913 PrintAndLogEx(INFO, "It's only informative.");
914 PrintAndLogEx(INFO, "Measuring antenna characteristics...");
916 // hide demod plot line
917 g_DemodBufferLen = 0;
918 setClockGrid(0, 0);
919 RepaintGraphWindow();
920 int timeout = 0;
921 int timeout_max = 20;
923 clearCommandBuffer();
924 SendCommandNG(CMD_MEASURE_ANTENNA_TUNING, NULL, 0);
925 PacketResponseNG resp;
926 PrintAndLogEx(INPLACE, "% 3i", timeout_max - timeout);
927 while (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING, &resp, 500)) {
928 fflush(stdout);
929 if (timeout >= timeout_max) {
930 PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
931 return PM3_ETIMEOUT;
933 timeout++;
934 PrintAndLogEx(INPLACE, "% 3i", timeout_max - timeout);
936 PrintAndLogEx(NORMAL, "");
938 if (resp.status != PM3_SUCCESS) {
939 PrintAndLogEx(WARNING, "Antenna tuning failed");
940 return PM3_ESOFT;
943 PrintAndLogEx(NORMAL, "");
944 PrintAndLogEx(INFO, "-------- " _CYAN_("LF Antenna") " ----------");
945 // in mVolt
946 struct p {
947 uint32_t v_lf134;
948 uint32_t v_lf125;
949 uint32_t v_lfconf;
950 uint32_t v_hf;
951 uint32_t peak_v;
952 uint32_t peak_f;
953 int divisor;
954 uint8_t results[256];
955 } PACKED;
957 struct p *package = (struct p *)resp.data.asBytes;
959 if (package->v_lf125 > NON_VOLTAGE)
960 PrintAndLogEx(SUCCESS, "%.2f kHz ........... " _YELLOW_("%5.2f") " V", LF_DIV2FREQ(LF_DIVISOR_125), (package->v_lf125 * ANTENNA_ERROR) / 1000.0);
962 if (package->v_lf134 > NON_VOLTAGE)
963 PrintAndLogEx(SUCCESS, "%.2f kHz ........... " _YELLOW_("%5.2f") " V", LF_DIV2FREQ(LF_DIVISOR_134), (package->v_lf134 * ANTENNA_ERROR) / 1000.0);
965 if (package->v_lfconf > NON_VOLTAGE && package->divisor > 0 && package->divisor != LF_DIVISOR_125 && package->divisor != LF_DIVISOR_134)
966 PrintAndLogEx(SUCCESS, "%.2f kHz ........... " _YELLOW_("%5.2f") " V", LF_DIV2FREQ(package->divisor), (package->v_lfconf * ANTENNA_ERROR) / 1000.0);
968 if (package->peak_v > NON_VOLTAGE && package->peak_f > 0)
969 PrintAndLogEx(SUCCESS, "%.2f kHz optimal.... " _BACK_GREEN_("%5.2f") " V", LF_DIV2FREQ(package->peak_f), (package->peak_v * ANTENNA_ERROR) / 1000.0);
971 // Empirical measures in mV
972 const double vdd_rdv4 = 9000;
973 const double vdd_other = 5400;
974 double vdd = IfPm3Rdv4Fw() ? vdd_rdv4 : vdd_other;
976 if (package->peak_v > NON_VOLTAGE && package->peak_f > 0) {
978 // Q measure with Q=f/delta_f
979 double v_3db_scaled = (double)(package->peak_v * 0.707) / 512; // /512 == >>9
980 uint32_t s2 = 0, s4 = 0;
981 for (int i = 1; i < 256; i++) {
982 if ((s2 == 0) && (package->results[i] > v_3db_scaled)) {
983 s2 = i;
985 if ((s2 != 0) && (package->results[i] < v_3db_scaled)) {
986 s4 = i;
987 break;
991 PrintAndLogEx(SUCCESS, "");
992 PrintAndLogEx(SUCCESS, "Approx. Q factor measurement");
993 double lfq1 = 0;
994 if (s4 != 0) { // we got all our points of interest
995 double a = package->results[s2 - 1];
996 double b = package->results[s2];
997 double f1 = LF_DIV2FREQ(s2 - 1 + (v_3db_scaled - a) / (b - a));
998 double c = package->results[s4 - 1];
999 double d = package->results[s4];
1000 double f2 = LF_DIV2FREQ(s4 - 1 + (c - v_3db_scaled) / (c - d));
1001 lfq1 = LF_DIV2FREQ(package->peak_f) / (f1 - f2);
1002 PrintAndLogEx(SUCCESS, "Frequency bandwidth... " _YELLOW_("%.1lf"), lfq1);
1005 // Q measure with Vlr=Q*(2*Vdd/pi)
1006 double lfq2 = (double)package->peak_v * 3.14 / 2 / vdd;
1007 PrintAndLogEx(SUCCESS, "Peak voltage.......... " _YELLOW_("%.1lf"), lfq2);
1008 // cross-check results
1009 if (lfq1 > 3) {
1010 double approx_vdd = (double)package->peak_v * 3.14 / 2 / lfq1;
1011 // Got 8858 on a RDV4 with large antenna 134/14
1012 // Got 8761 on a non-RDV4
1013 const double approx_vdd_other_max = 8840;
1015 // 1% over threshold and supposedly non-RDV4
1016 if ((approx_vdd > approx_vdd_other_max * 1.01) && (!IfPm3Rdv4Fw())) {
1017 PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3GENERIC firmware on a RDV4"));
1018 PrintAndLogEx(WARNING, "False positives is possible but please check your setup");
1020 // 1% below threshold and supposedly RDV4
1021 if ((approx_vdd < approx_vdd_other_max * 0.99) && (IfPm3Rdv4Fw())) {
1022 PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_RDV4 firmware on a generic device"));
1023 PrintAndLogEx(WARNING, "False positives is possible but please check your setup");
1028 char judgement[20];
1029 memset(judgement, 0, sizeof(judgement));
1030 // LF evaluation
1031 if (package->peak_v < LF_UNUSABLE_V)
1032 snprintf(judgement, sizeof(judgement), _RED_("unusable"));
1033 else if (package->peak_v < LF_MARGINAL_V)
1034 snprintf(judgement, sizeof(judgement), _YELLOW_("marginal"));
1035 else
1036 snprintf(judgement, sizeof(judgement), _GREEN_("ok"));
1038 //PrintAndLogEx((package->peak_v < LF_UNUSABLE_V) ? WARNING : SUCCESS, "LF antenna ( %s )", judgement);
1039 PrintAndLogEx((package->peak_v < LF_UNUSABLE_V) ? WARNING : SUCCESS, "LF antenna............ %s", judgement);
1041 PrintAndLogEx(NORMAL, "");
1042 PrintAndLogEx(INFO, "-------- " _CYAN_("HF Antenna") " ----------");
1043 // HF evaluation
1044 if (package->v_hf > NON_VOLTAGE) {
1045 PrintAndLogEx(SUCCESS, "13.56 MHz............. " _BACK_GREEN_("%5.2f") " V", (package->v_hf * ANTENNA_ERROR) / 1000.0);
1048 memset(judgement, 0, sizeof(judgement));
1050 PrintAndLogEx(SUCCESS, "");
1051 PrintAndLogEx(SUCCESS, "Approx. Q factor measurement");
1053 if (package->v_hf >= HF_UNUSABLE_V) {
1054 // Q measure with Vlr=Q*(2*Vdd/pi)
1055 double hfq = (double)package->v_hf * 3.14 / 2 / vdd;
1056 PrintAndLogEx(SUCCESS, "Peak voltage.......... " _YELLOW_("%.1lf"), hfq);
1059 if (package->v_hf < HF_UNUSABLE_V)
1060 snprintf(judgement, sizeof(judgement), _RED_("unusable"));
1061 else if (package->v_hf < HF_MARGINAL_V)
1062 snprintf(judgement, sizeof(judgement), _YELLOW_("marginal"));
1063 else
1064 snprintf(judgement, sizeof(judgement), _GREEN_("ok"));
1066 PrintAndLogEx((package->v_hf < HF_UNUSABLE_V) ? WARNING : SUCCESS, "HF antenna ( %s )", judgement);
1068 // graph LF measurements
1069 // even here, these values has 3% error.
1070 uint16_t test1 = 0;
1071 for (int i = 0; i < 256; i++) {
1072 g_GraphBuffer[i] = package->results[i] - 128;
1073 test1 += package->results[i];
1076 if (test1 > 0) {
1077 PrintAndLogEx(NORMAL, "");
1078 PrintAndLogEx(INFO, "-------- " _CYAN_("LF tuning graph") " ------------");
1079 PrintAndLogEx(SUCCESS, "Orange line - divisor %d / %.2f kHz"
1080 , LF_DIVISOR_125
1081 , LF_DIV2FREQ(LF_DIVISOR_125)
1083 PrintAndLogEx(SUCCESS, "Blue line - divisor %d / %.2f kHz\n\n"
1084 , LF_DIVISOR_134
1085 , LF_DIV2FREQ(LF_DIVISOR_134)
1087 g_GraphTraceLen = 256;
1088 g_MarkerC.pos = LF_DIVISOR_125;
1089 g_MarkerD.pos = LF_DIVISOR_134;
1090 ShowGraphWindow();
1091 RepaintGraphWindow();
1092 } else {
1093 PrintAndLogEx(FAILED, "\nAll values are zero. Not showing LF tuning graph\n\n");
1096 PrintAndLogEx(NORMAL, "");
1097 PrintAndLogEx(INFO, "Q factor must be measured without tag on the antenna");
1098 PrintAndLogEx(NORMAL, "");
1099 return PM3_SUCCESS;
1102 static int CmdVersion(const char *Cmd) {
1103 CLIParserContext *ctx;
1104 CLIParserInit(&ctx, "hw version",
1105 "Show version information about the client and the connected Proxmark3",
1106 "hw version"
1109 void *argtable[] = {
1110 arg_param_begin,
1111 arg_param_end
1113 CLIExecWithReturn(ctx, Cmd, argtable, true);
1114 CLIParserFree(ctx);
1115 pm3_version(true, false);
1116 return PM3_SUCCESS;
1119 static int CmdStatus(const char *Cmd) {
1120 CLIParserContext *ctx;
1121 CLIParserInit(&ctx, "hw status",
1122 "Show runtime status information about the connected Proxmark3",
1123 "hw status\n"
1124 "hw status --ms 1000 -> Test connection speed with 1000ms timeout\n"
1127 void *argtable[] = {
1128 arg_param_begin,
1129 arg_int0("m", "ms", "<ms>", "speed test timeout in micro seconds"),
1130 arg_param_end
1132 CLIExecWithReturn(ctx, Cmd, argtable, true);
1133 int32_t speedTestTimeout = arg_get_int_def(ctx, 1, -1);
1134 CLIParserFree(ctx);
1136 clearCommandBuffer();
1137 PacketResponseNG resp;
1138 if (speedTestTimeout < 0) {
1139 speedTestTimeout = 0;
1140 SendCommandNG(CMD_STATUS, NULL, 0);
1141 } else {
1142 SendCommandNG(CMD_STATUS, (uint8_t *)&speedTestTimeout, sizeof(speedTestTimeout));
1145 if (WaitForResponseTimeout(CMD_STATUS, &resp, 2000 + speedTestTimeout) == false) {
1146 PrintAndLogEx(WARNING, "Status command timeout. Communication speed test timed out");
1147 return PM3_ETIMEOUT;
1149 return PM3_SUCCESS;
1152 int handle_tearoff(tearoff_params_t *params, bool verbose) {
1154 if (params == NULL)
1155 return PM3_EINVARG;
1157 clearCommandBuffer();
1158 SendCommandNG(CMD_SET_TEAROFF, (uint8_t *)params, sizeof(tearoff_params_t));
1159 PacketResponseNG resp;
1160 if (WaitForResponseTimeout(CMD_SET_TEAROFF, &resp, 500) == false) {
1161 PrintAndLogEx(WARNING, "Tear-off command timeout.");
1162 return PM3_ETIMEOUT;
1165 if (resp.status == PM3_SUCCESS) {
1166 if (params->delay_us > 0 && verbose)
1167 PrintAndLogEx(INFO, "Tear-off hook configured with delay of " _GREEN_("%i us"), params->delay_us);
1169 if (params->on && verbose)
1170 PrintAndLogEx(INFO, "Tear-off hook " _GREEN_("enabled"));
1172 if (params->off && verbose)
1173 PrintAndLogEx(INFO, "Tear-off hook " _RED_("disabled"));
1174 } else if (verbose)
1175 PrintAndLogEx(WARNING, "Tear-off command failed.");
1176 return resp.status;
1179 static int CmdTearoff(const char *Cmd) {
1180 CLIParserContext *ctx;
1181 CLIParserInit(&ctx, "hw tearoff",
1182 "Configure a tear-off hook for the next write command supporting tear-off\n"
1183 "After having been triggered by a write command, the tear-off hook is deactivated\n"
1184 "Delay (in us) must be between 1 and 43000 (43ms). Precision is about 1/3us.",
1185 "hw tearoff --delay 1200 --> define delay of 1200us\n"
1186 "hw tearoff --on --> (re)activate a previously defined delay\n"
1187 "hw tearoff --off --> deactivate a previously activated but not yet triggered hook\n");
1189 void *argtable[] = {
1190 arg_param_begin,
1191 arg_int0(NULL, "delay", "<dec>", "Delay in us before triggering tear-off, must be between 1 and 43000"),
1192 arg_lit0(NULL, "on", "Activate tear-off hook"),
1193 arg_lit0(NULL, "off", "Deactivate tear-off hook"),
1194 arg_lit0("s", "silent", "less verbose output"),
1195 arg_param_end
1198 CLIExecWithReturn(ctx, Cmd, argtable, false);
1199 tearoff_params_t params;
1200 int delay = arg_get_int_def(ctx, 1, -1);
1201 params.on = arg_get_lit(ctx, 2);
1202 params.off = arg_get_lit(ctx, 3);
1203 bool silent = arg_get_lit(ctx, 4);
1204 CLIParserFree(ctx);
1206 if (delay != -1) {
1207 if ((delay < 1) || (delay > 43000)) {
1208 PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
1209 return PM3_EINVARG;
1211 } else {
1212 delay = 0; // will be ignored by ARM
1215 params.delay_us = delay;
1216 if (params.on && params.off) {
1217 PrintAndLogEx(WARNING, "You can't set both --on and --off!");
1218 return PM3_EINVARG;
1221 return handle_tearoff(&params, !silent);
1224 static int CmdTia(const char *Cmd) {
1225 CLIParserContext *ctx;
1226 CLIParserInit(&ctx, "hw tia",
1227 "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider",
1228 "hw tia"
1231 void *argtable[] = {
1232 arg_param_begin,
1233 arg_param_end
1235 CLIExecWithReturn(ctx, Cmd, argtable, true);
1236 CLIParserFree(ctx);
1238 PrintAndLogEx(INFO, "Triggering new Timing Interval Acquisition (TIA)...");
1239 clearCommandBuffer();
1240 SendCommandNG(CMD_TIA, NULL, 0);
1241 PacketResponseNG resp;
1242 if (WaitForResponseTimeout(CMD_TIA, &resp, 2000) == false) {
1243 PrintAndLogEx(WARNING, "TIA command timeout. You probably need to unplug the Proxmark3.");
1244 return PM3_ETIMEOUT;
1246 PrintAndLogEx(INFO, "TIA done.");
1247 return PM3_SUCCESS;
1250 static int CmdTimeout(const char *Cmd) {
1252 CLIParserContext *ctx;
1253 CLIParserInit(&ctx, "hw timeout",
1254 "Set the communication timeout on the client side",
1255 "hw timeout --> Show current timeout\n"
1256 "hw timeout -m 20 --> Set the timeout to 20ms\n"
1257 "hw timeout --ms 500 --> Set the timeout to 500ms\n"
1260 void *argtable[] = {
1261 arg_param_begin,
1262 arg_int0("m", "ms", "<ms>", "timeout in micro seconds"),
1263 arg_param_end
1265 CLIExecWithReturn(ctx, Cmd, argtable, true);
1266 int32_t arg = arg_get_int_def(ctx, 1, -1);
1267 CLIParserFree(ctx);
1269 uint32_t oldTimeout = uart_get_timeouts();
1271 // timeout is not given/invalid, just show the current timeout then return
1272 if (arg < 0) {
1273 PrintAndLogEx(INFO, "Current communication timeout... " _GREEN_("%u") " ms", oldTimeout);
1274 return PM3_SUCCESS;
1277 uint32_t newTimeout = arg;
1278 // UART_USB_CLIENT_RX_TIMEOUT_MS is considered as the minimum required timeout.
1279 if (newTimeout < UART_USB_CLIENT_RX_TIMEOUT_MS) {
1280 PrintAndLogEx(WARNING, "Timeout less than %u ms might cause errors.", UART_USB_CLIENT_RX_TIMEOUT_MS);
1281 } else if (newTimeout > 5000) {
1282 PrintAndLogEx(WARNING, "Timeout greater than 5000 ms makes the client unresponsive.");
1284 uart_reconfigure_timeouts(newTimeout);
1285 PrintAndLogEx(INFO, "Old communication timeout... %u ms", oldTimeout);
1286 PrintAndLogEx(INFO, "New communication timeout... " _GREEN_("%u") " ms", newTimeout);
1287 return PM3_SUCCESS;
1290 static int CmdPing(const char *Cmd) {
1291 CLIParserContext *ctx;
1292 CLIParserInit(&ctx, "hw ping",
1293 "Test if the Proxmark3 is responsive",
1294 "hw ping\n"
1295 "hw ping --len 32"
1298 void *argtable[] = {
1299 arg_param_begin,
1300 arg_u64_0("l", "len", "<dec>", "length of payload to send"),
1301 arg_param_end
1304 CLIExecWithReturn(ctx, Cmd, argtable, true);
1305 uint32_t len = arg_get_u32_def(ctx, 1, 32);
1306 CLIParserFree(ctx);
1308 if (len > PM3_CMD_DATA_SIZE)
1309 len = PM3_CMD_DATA_SIZE;
1311 if (len) {
1312 PrintAndLogEx(INFO, "Ping sent with payload len... " _YELLOW_("%d"), len);
1313 } else {
1314 PrintAndLogEx(INFO, "Ping sent");
1317 clearCommandBuffer();
1318 PacketResponseNG resp;
1319 uint8_t data[PM3_CMD_DATA_SIZE] = {0};
1321 for (uint16_t i = 0; i < len; i++) {
1322 data[i] = i & 0xFF;
1325 uint64_t tms = msclock();
1326 SendCommandNG(CMD_PING, data, len);
1327 if (WaitForResponseTimeout(CMD_PING, &resp, 1000)) {
1328 tms = msclock() - tms;
1329 if (len) {
1330 bool error = (memcmp(data, resp.data.asBytes, len) != 0);
1331 PrintAndLogEx((error) ? ERR : SUCCESS, "Ping response " _GREEN_("received")
1332 " in " _YELLOW_("%" PRIu64) " ms and content ( %s )",
1333 tms, error ? _RED_("fail") : _GREEN_("ok"));
1334 } else {
1335 PrintAndLogEx(SUCCESS, "Ping response " _GREEN_("received")
1336 " in " _YELLOW_("%" PRIu64) " ms", tms);
1338 } else
1339 PrintAndLogEx(WARNING, "Ping response " _RED_("timeout"));
1340 return PM3_SUCCESS;
1343 static int CmdConnect(const char *Cmd) {
1345 CLIParserContext *ctx;
1346 CLIParserInit(&ctx, "hw connect",
1347 "Connects to a Proxmark3 device via specified serial port.\n"
1348 "Baudrate here is only for physical UART or UART-BT, NOT for USB-CDC or blue shark add-on",
1349 "hw connect -p "SERIAL_PORT_EXAMPLE_H"\n"
1350 "hw connect -p "SERIAL_PORT_EXAMPLE_H" -b 115200"
1353 void *argtable[] = {
1354 arg_param_begin,
1355 arg_str0("p", "port", NULL, "Serial port to connect to, else retry the last used one"),
1356 arg_u64_0("b", "baud", "<dec>", "Baudrate"),
1357 arg_param_end
1359 CLIExecWithReturn(ctx, Cmd, argtable, true);
1361 char port[FILE_PATH_SIZE] = {0};
1362 int p_len = sizeof(port) - 1; // CLIGetStrWithReturn does not guarantee string to be null-terminated;
1363 CLIGetStrWithReturn(ctx, 1, (uint8_t *)port, &p_len);
1364 uint32_t baudrate = arg_get_u32_def(ctx, 2, USART_BAUD_RATE);
1365 CLIParserFree(ctx);
1367 if (baudrate == 0) {
1368 PrintAndLogEx(WARNING, "Baudrate can't be zero");
1369 return PM3_EINVARG;
1372 // default back to previous used serial port
1373 if (strlen(port) == 0) {
1374 if (strlen(g_conn.serial_port_name) == 0) {
1375 PrintAndLogEx(WARNING, "Must specify a serial port");
1376 return PM3_EINVARG;
1378 memcpy(port, g_conn.serial_port_name, sizeof(port));
1381 if (g_session.pm3_present) {
1382 CloseProxmark(g_session.current_device);
1385 // 10 second timeout
1386 OpenProxmark(&g_session.current_device, port, false, 10, false, baudrate);
1388 if (g_session.pm3_present && (TestProxmark(g_session.current_device) != PM3_SUCCESS)) {
1389 PrintAndLogEx(ERR, _RED_("ERROR:") " cannot communicate with the Proxmark3\n");
1390 CloseProxmark(g_session.current_device);
1391 return PM3_ENOTTY;
1393 return PM3_SUCCESS;
1396 static int CmdBreak(const char *Cmd) {
1398 CLIParserContext *ctx;
1399 CLIParserInit(&ctx, "hw break",
1400 "send break loop package",
1401 "hw break\n"
1404 void *argtable[] = {
1405 arg_param_begin,
1406 arg_param_end
1408 CLIExecWithReturn(ctx, Cmd, argtable, true);
1409 CLIParserFree(ctx);
1410 clearCommandBuffer();
1411 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
1412 return PM3_SUCCESS;
1415 static int CmdBootloader(const char *Cmd) {
1417 CLIParserContext *ctx;
1418 CLIParserInit(&ctx, "hw bootloader",
1419 "Reboot Proxmark3 into bootloader mode",
1420 "hw bootloader\n"
1423 void *argtable[] = {
1424 arg_param_begin,
1425 arg_param_end
1427 CLIExecWithReturn(ctx, Cmd, argtable, true);
1428 CLIParserFree(ctx);
1429 clearCommandBuffer();
1430 flash_reboot_bootloader(g_conn.serial_port_name, false);
1431 return PM3_SUCCESS;
1434 int set_fpga_mode(uint8_t mode) {
1435 if (mode < FPGA_BITSTREAM_MIN || mode > FPGA_BITSTREAM_MAX) {
1436 return PM3_EINVARG;
1438 uint8_t d[] = {mode};
1439 clearCommandBuffer();
1440 SendCommandNG(CMD_SET_FPGAMODE, d, sizeof(d));
1441 PacketResponseNG resp;
1442 if (WaitForResponseTimeout(CMD_SET_FPGAMODE, &resp, 1000) == false) {
1443 PrintAndLogEx(WARNING, "command execution timeout");
1444 return PM3_ETIMEOUT;
1446 if (resp.status != PM3_SUCCESS) {
1447 PrintAndLogEx(ERR, "failed to set FPGA mode");
1449 return resp.status;
1452 static command_t CommandTable[] = {
1453 {"help", CmdHelp, AlwaysAvailable, "This help"},
1454 {"-------------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Operation") " -----------------------"},
1455 {"detectreader", CmdDetectReader, IfPm3Present, "Detect external reader field"},
1456 {"status", CmdStatus, IfPm3Present, "Show runtime status information about the connected Proxmark3"},
1457 {"tearoff", CmdTearoff, IfPm3Present, "Program a tearoff hook for the next command supporting tearoff"},
1458 {"timeout", CmdTimeout, AlwaysAvailable, "Set the communication timeout on the client side"},
1459 {"version", CmdVersion, AlwaysAvailable, "Show version information about the client and Proxmark3"},
1460 {"-------------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Hardware") " -----------------------"},
1461 {"break", CmdBreak, IfPm3Present, "Send break loop usb command"},
1462 {"bootloader", CmdBootloader, IfPm3Present, "Reboot into bootloader mode"},
1463 {"connect", CmdConnect, AlwaysAvailable, "Connect to the device via serial port"},
1464 {"dbg", CmdDbg, IfPm3Present, "Set device side debug level"},
1465 {"fpgaoff", CmdFPGAOff, IfPm3Present, "Turn off FPGA on device"},
1466 {"lcd", CmdLCD, IfPm3Lcd, "Send command/data to LCD"},
1467 {"lcdreset", CmdLCDReset, IfPm3Lcd, "Hardware reset LCD"},
1468 {"ping", CmdPing, IfPm3Present, "Test if the Proxmark3 is responsive"},
1469 {"readmem", CmdReadmem, IfPm3Present, "Read from MCU flash"},
1470 {"reset", CmdReset, IfPm3Present, "Reset the device"},
1471 {"setlfdivisor", CmdSetDivisor, IfPm3Lf, "Drive LF antenna at 12MHz / (divisor + 1)"},
1472 {"sethfthresh", CmdSetHFThreshold, IfPm3Iso14443a, "Set thresholds in HF/14a mode"},
1473 {"setmux", CmdSetMux, IfPm3Present, "Set the ADC mux to a specific value"},
1474 {"standalone", CmdStandalone, IfPm3Present, "Start installed standalone mode on device"},
1475 {"tia", CmdTia, IfPm3Present, "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider"},
1476 {"tune", CmdTune, IfPm3Lf, "Measure tuning of device antenna"},
1477 {NULL, NULL, NULL, NULL}
1480 static int CmdHelp(const char *Cmd) {
1481 (void)Cmd; // Cmd is not used so far
1482 CmdsHelp(CommandTable);
1483 return PM3_SUCCESS;
1486 int CmdHW(const char *Cmd) {
1487 clearCommandBuffer();
1488 return CmdsParse(CommandTable, Cmd);
1492 #if defined(__MINGW64__)
1493 # define PM3CLIENTCOMPILER "MinGW-w64 "
1494 #elif defined(__MINGW32__)
1495 # define PM3CLIENTCOMPILER "MinGW "
1496 #elif defined(__clang__)
1497 # define PM3CLIENTCOMPILER "Clang/LLVM "
1498 #elif defined(__GNUC__) || defined(__GNUG__)
1499 # define PM3CLIENTCOMPILER "GCC "
1500 #else
1501 # define PM3CLIENTCOMPILER "unknown compiler "
1502 #endif
1504 #if defined(__APPLE__) || defined(__MACH__)
1505 # define PM3HOSTOS "OSX"
1506 #elif defined(__ANDROID__) || defined(ANDROID)
1507 // must be tested before __linux__
1508 # define PM3HOSTOS "Android"
1509 #elif defined(__linux__)
1510 # define PM3HOSTOS "Linux"
1511 #elif defined(__FreeBSD__)
1512 # define PM3HOSTOS "FreeBSD"
1513 #elif defined(__NetBSD__)
1514 # define PM3HOSTOS "NetBSD"
1515 #elif defined(__OpenBSD__)
1516 # define PM3HOSTOS "OpenBSD"
1517 #elif defined(__CYGWIN__)
1518 # define PM3HOSTOS "Cygwin"
1519 #elif defined(_WIN64) || defined(__WIN64__)
1520 // must be tested before _WIN32
1521 # define PM3HOSTOS "Windows (64b)"
1522 #elif defined(_WIN32) || defined(__WIN32__)
1523 # define PM3HOSTOS "Windows (32b)"
1524 #else
1525 # define PM3HOSTOS "unknown"
1526 #endif
1528 #if defined(__x86_64__)
1529 # define PM3HOSTARCH "x86_64"
1530 #elif defined(__i386__)
1531 # define PM3HOSTARCH "x86"
1532 #elif defined(__aarch64__)
1533 # define PM3HOSTARCH "aarch64"
1534 #elif defined(__arm__)
1535 # define PM3HOSTARCH "arm"
1536 #elif defined(__powerpc64__)
1537 # define PM3HOSTARCH "powerpc64"
1538 #elif defined(__mips__)
1539 # define PM3HOSTARCH "mips"
1540 #else
1541 # define PM3HOSTARCH "unknown"
1542 #endif
1544 void pm3_version_short(void) {
1545 PrintAndLogEx(NORMAL, " [ " _CYAN_("Proxmark3 RFID instrument") " ]");
1546 PrintAndLogEx(NORMAL, "");
1548 if (g_session.pm3_present) {
1550 PacketResponseNG resp;
1551 clearCommandBuffer();
1552 SendCommandNG(CMD_VERSION, NULL, 0);
1554 if (WaitForResponseTimeout(CMD_VERSION, &resp, 1000)) {
1556 struct p {
1557 uint32_t id;
1558 uint32_t section_size;
1559 uint32_t versionstr_len;
1560 char versionstr[PM3_CMD_DATA_SIZE - 12];
1561 } PACKED;
1563 struct p *payload = (struct p *)&resp.data.asBytes;
1565 lookup_chipid_short(payload->id, payload->section_size);
1567 // client
1568 char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image
1569 format_version_information_short(temp, sizeof(temp), &g_version_information);
1570 PrintAndLogEx(NORMAL, " Client.... %s", temp);
1572 bool armsrc_mismatch = false;
1573 char *ptr = strstr(payload->versionstr, " os: ");
1574 if (ptr != NULL) {
1575 ptr = strstr(ptr, "\n");
1576 if ((ptr != NULL) && (strlen(g_version_information.armsrc) == 9)) {
1577 if (strncmp(ptr - 9, g_version_information.armsrc, 9) != 0) {
1578 armsrc_mismatch = true;
1583 // bootrom
1584 ptr = strstr(payload->versionstr, " bootrom: ");
1585 if (ptr != NULL) {
1586 char *ptr_end = strstr(ptr, "\n");
1587 if (ptr_end != NULL) {
1588 uint8_t len = ptr_end - 19 - ptr;
1589 PrintAndLogEx(NORMAL, " Bootrom... %.*s", len, ptr + 10);
1593 // os:
1594 ptr = strstr(payload->versionstr, " os: ");
1595 if (ptr != NULL) {
1596 char *ptr_end = strstr(ptr, "\n");
1597 if (ptr_end != NULL) {
1598 uint8_t len = ptr_end - 14 - ptr;
1599 PrintAndLogEx(NORMAL, " OS........ %.*s", len, ptr + 5);
1604 if (IfPm3Rdv4Fw()) {
1606 bool is_genuine_rdv4 = false;
1607 // validate signature data
1608 rdv40_validation_t mem;
1609 if (rdv4_get_signature(&mem) == PM3_SUCCESS) {
1610 if (rdv4_validate(&mem) == PM3_SUCCESS) {
1611 is_genuine_rdv4 = true;
1615 PrintAndLogEx(NORMAL, " Target.... %s", (is_genuine_rdv4) ? _YELLOW_("RDV4") : _RED_("device / fw mismatch"));
1616 } else {
1617 PrintAndLogEx(NORMAL, " Target.... %s", _YELLOW_("PM3 GENERIC"));
1620 PrintAndLogEx(NORMAL, "");
1622 if (armsrc_mismatch) {
1623 PrintAndLogEx(NORMAL, "");
1624 PrintAndLogEx(WARNING, " --> " _RED_("ARM firmware does not match the source at the time the client was compiled"));
1625 PrintAndLogEx(WARNING, " --> Make sure to flash a correct and up-to-date version");
1629 PrintAndLogEx(NORMAL, "");
1632 void pm3_version(bool verbose, bool oneliner) {
1634 char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image
1636 if (oneliner) {
1637 // For "proxmark3 -v", simple printf, avoid logging
1638 FormatVersionInformation(temp, sizeof(temp), "Client: ", &g_version_information);
1639 PrintAndLogEx(NORMAL, "%s compiled with " PM3CLIENTCOMPILER __VERSION__ " OS:" PM3HOSTOS " ARCH:" PM3HOSTARCH "\n", temp);
1640 return;
1643 if (!verbose)
1644 return;
1646 PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Proxmark3 RFID instrument") " ]");
1647 PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Client") " ]");
1648 FormatVersionInformation(temp, sizeof(temp), " ", &g_version_information);
1649 PrintAndLogEx(NORMAL, "%s", temp);
1650 PrintAndLogEx(NORMAL, " compiled with............. " PM3CLIENTCOMPILER __VERSION__);
1651 PrintAndLogEx(NORMAL, " platform.................. " PM3HOSTOS " / " PM3HOSTARCH);
1652 #if defined(HAVE_READLINE)
1653 PrintAndLogEx(NORMAL, " Readline support.......... " _GREEN_("present"));
1654 #elif defined(HAVE_LINENOISE)
1655 PrintAndLogEx(NORMAL, " Linenoise support......... " _GREEN_("present"));
1656 #else
1657 PrintAndLogEx(NORMAL, " Readline/Linenoise support." _YELLOW_("absent"));
1658 #endif
1659 #ifdef HAVE_GUI
1660 PrintAndLogEx(NORMAL, " QT GUI support............ " _GREEN_("present"));
1661 #else
1662 PrintAndLogEx(NORMAL, " QT GUI support............ " _YELLOW_("absent"));
1663 #endif
1664 #ifdef HAVE_BLUEZ
1665 PrintAndLogEx(NORMAL, " native BT support......... " _GREEN_("present"));
1666 #else
1667 PrintAndLogEx(NORMAL, " native BT support......... " _YELLOW_("absent"));
1668 #endif
1669 #ifdef HAVE_PYTHON
1670 PrintAndLogEx(NORMAL, " Python script support..... " _GREEN_("present"));
1671 #else
1672 PrintAndLogEx(NORMAL, " Python script support..... " _YELLOW_("absent"));
1673 #endif
1674 #ifdef HAVE_LUA_SWIG
1675 PrintAndLogEx(NORMAL, " Lua SWIG support.......... " _GREEN_("present"));
1676 #else
1677 PrintAndLogEx(NORMAL, " Lua SWIG support.......... " _YELLOW_("absent"));
1678 #endif
1679 #ifdef HAVE_PYTHON_SWIG
1680 PrintAndLogEx(NORMAL, " Python SWIG support....... " _GREEN_("present"));
1681 #else
1682 PrintAndLogEx(NORMAL, " Python SWIG support....... " _YELLOW_("absent"));
1683 #endif
1685 if (g_session.pm3_present) {
1686 PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("Proxmark3") " ]");
1688 PacketResponseNG resp;
1689 clearCommandBuffer();
1690 SendCommandNG(CMD_VERSION, NULL, 0);
1692 if (WaitForResponseTimeout(CMD_VERSION, &resp, 1000)) {
1693 if (IfPm3Rdv4Fw()) {
1695 bool is_genuine_rdv4 = false;
1696 // validate signature data
1697 rdv40_validation_t mem;
1698 if (rdv4_get_signature(&mem) == PM3_SUCCESS) {
1699 if (rdv4_validate(&mem) == PM3_SUCCESS) {
1700 is_genuine_rdv4 = true;
1704 PrintAndLogEx(NORMAL, " device.................... %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _RED_("device / fw mismatch"));
1705 PrintAndLogEx(NORMAL, " firmware.................. %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _YELLOW_("RDV4"));
1706 PrintAndLogEx(NORMAL, " external flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
1707 PrintAndLogEx(NORMAL, " smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));
1708 PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
1709 } else {
1710 PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3 GENERIC"));
1711 if (IfPm3Flash()) {
1712 PrintAndLogEx(NORMAL, " external flash............ %s", _GREEN_("present"));
1715 if (IfPm3FpcUsartHost()) {
1716 PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", _GREEN_("present"));
1720 if (IfPm3FpcUsartDevFromUsb()) {
1721 PrintAndLogEx(NORMAL, " FPC USART for developer... %s", _GREEN_("present"));
1724 PrintAndLogEx(NORMAL, "");
1726 struct p {
1727 uint32_t id;
1728 uint32_t section_size;
1729 uint32_t versionstr_len;
1730 char versionstr[PM3_CMD_DATA_SIZE - 12];
1731 } PACKED;
1733 struct p *payload = (struct p *)&resp.data.asBytes;
1735 bool armsrc_mismatch = false;
1736 char *ptr = strstr(payload->versionstr, " os: ");
1737 if (ptr != NULL) {
1738 ptr = strstr(ptr, "\n");
1739 if ((ptr != NULL) && (strlen(g_version_information.armsrc) == 9)) {
1740 if (strncmp(ptr - 9, g_version_information.armsrc, 9) != 0) {
1741 armsrc_mismatch = true;
1745 PrintAndLogEx(NORMAL, payload->versionstr);
1746 if (strstr(payload->versionstr, FPGA_TYPE) == NULL) {
1747 PrintAndLogEx(NORMAL, " FPGA firmware... %s", _RED_("chip mismatch"));
1750 lookupChipID(payload->id, payload->section_size);
1751 if (armsrc_mismatch) {
1752 PrintAndLogEx(NORMAL, "");
1753 PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled"));
1754 PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version");
1758 PrintAndLogEx(NORMAL, "");