1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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 //-----------------------------------------------------------------------------
17 // low-level hardware control
18 //-----------------------------------------------------------------------------
25 #include "cmdparser.h" // command_t
26 #include "cliparser.h"
28 #include "usart_defs.h"
33 #include "commonutil.h"
34 #include "preferences.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
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
) {
50 asBuff
= "AT91SAM7S512 Rev A";
54 asBuff
= "AT91SAM7S512 Rev B";
57 asBuff
= "AT91SAM7S256 Rev A";
60 asBuff
= "AT91SAM7S256 Rev B";
63 asBuff
= "AT91SAM7S256 Rev C";
66 asBuff
= "AT91SAM7S256 Rev D";
69 asBuff
= "AT91SAM7S128 Rev A";
72 asBuff
= "AT91SAM7S128 Rev B";
75 asBuff
= "AT91SAM7S128 Rev C";
78 asBuff
= "AT91SAM7S128 Rev D";
81 asBuff
= "AT91SAM7S64 Rev A";
84 asBuff
= "AT91SAM7S64 Rev B";
87 asBuff
= "AT91SAM7S64 Rev C";
90 asBuff
= "AT91SAM7S321 Rev A";
93 asBuff
= "AT91SAM7S32 Rev A";
96 asBuff
= "AT91SAM7S32 Rev B";
99 asBuff
= "AT9SAM7S161 Rev A";
102 asBuff
= "AT91SAM7S16 Rev A";
108 PrintAndLogEx(NORMAL
, " MCU....... " _YELLOW_("%s"), asBuff
);
110 uint32_t mem_avail
= 0;
111 switch ((iChipID
& 0xF00) >> 8) {
144 PrintAndLogEx(NORMAL
, " Memory.... " _YELLOW_("%u") " KB ( " _YELLOW_("%2.0f%%") " used )"
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
) {
154 uint32_t mem_avail
= 0;
155 PrintAndLogEx(NORMAL
, "\n [ " _YELLOW_("Hardware") " ]");
159 asBuff
= "AT91SAM7S512 Rev A";
163 asBuff
= "AT91SAM7S512 Rev B";
166 asBuff
= "AT91SAM7S256 Rev A";
169 asBuff
= "AT91SAM7S256 Rev B";
172 asBuff
= "AT91SAM7S256 Rev C";
175 asBuff
= "AT91SAM7S256 Rev D";
178 asBuff
= "AT91SAM7S128 Rev A";
181 asBuff
= "AT91SAM7S128 Rev B";
184 asBuff
= "AT91SAM7S128 Rev C";
187 asBuff
= "AT91SAM7S128 Rev D";
190 asBuff
= "AT91SAM7S64 Rev A";
193 asBuff
= "AT91SAM7S64 Rev B";
196 asBuff
= "AT91SAM7S64 Rev C";
199 asBuff
= "AT91SAM7S321 Rev A";
202 asBuff
= "AT91SAM7S32 Rev A";
205 asBuff
= "AT91SAM7S32 Rev B";
208 asBuff
= "AT9SAM7S161 Rev A";
211 asBuff
= "AT91SAM7S16 Rev A";
217 PrintAndLogEx(NORMAL
, " --= uC: " _YELLOW_("%s"), asBuff
);
219 switch ((iChipID
& 0xE0) >> 5) {
230 asBuff
= "ARM926EJS";
236 PrintAndLogEx(NORMAL
, " --= Embedded Processor: %s", asBuff
);
238 switch ((iChipID
& 0xF0000) >> 16) {
249 asBuff
= "112K bytes";
255 asBuff
= "80K bytes";
258 asBuff
= "160K bytes";
264 asBuff
= "16K bytes";
267 asBuff
= "32K bytes";
270 asBuff
= "64K bytes";
273 asBuff
= "128K bytes";
276 asBuff
= "256K bytes";
279 asBuff
= "96K bytes";
282 asBuff
= "512K bytes";
288 PrintAndLogEx(NORMAL
, " --= Internal SRAM size: %s", asBuff
);
290 switch ((iChipID
& 0xFF00000) >> 20) {
292 asBuff
= "AT91SAM9xx Series";
295 asBuff
= "AT91SAM9XExx Series";
298 asBuff
= "AT91x34 Series";
301 asBuff
= "CAP7 Series";
304 asBuff
= "CAP9 Series";
307 asBuff
= "CAP11 Series";
310 asBuff
= "AT91x40 Series";
313 asBuff
= "AT91x42 Series";
316 asBuff
= "AT91x55 Series";
319 asBuff
= "AT91SAM7Axx Series";
322 asBuff
= "AT91SAM7AQxx Series";
325 asBuff
= "AT91x63 Series";
328 asBuff
= "AT91SAM7Sxx Series";
331 asBuff
= "AT91SAM7XCxx Series";
334 asBuff
= "AT91SAM7SExx Series";
337 asBuff
= "AT91SAM7Lxx Series";
340 asBuff
= "AT91SAM7Xxx Series";
343 asBuff
= "AT91x92 Series";
346 asBuff
= "AT75Cxx Series";
352 PrintAndLogEx(NORMAL
, " --= Architecture identifier: %s", asBuff
);
354 switch ((iChipID
& 0x70000000) >> 28) {
359 asBuff
= "ROMless or on-chip Flash";
362 asBuff
= "Embedded flash memory";
365 asBuff
= "ROM and Embedded flash memory\nNVPSIZ is ROM size\nNVPSIZ2 is Flash size";
368 asBuff
= "SRAM emulating ROM";
374 switch ((iChipID
& 0xF00) >> 8) {
407 PrintAndLogEx(NORMAL
, " --= %s " _YELLOW_("%uK") " bytes ( " _YELLOW_("%2.0f%%") " used )"
410 , mem_avail
== 0 ? 0.0f
: (float)mem_used
/ (mem_avail
* 1024) * 100
414 switch ((iChipID & 0xF000) >> 12) {
419 asBuff = "8K bytes");
422 asBuff = "16K bytes");
425 asBuff = "32K bytes");
428 asBuff = "64K bytes");
431 asBuff = "128K bytes");
434 asBuff = "256K bytes");
437 asBuff = "512K bytes");
440 asBuff = "1024K bytes");
443 asBuff = "2048K bytes");
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"
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"),
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);
478 if ((lv0
+ lv1
+ lv2
+ lv3
+ lv4
) > 1) {
479 PrintAndLogEx(INFO
, "Can only set one debug level");
483 uint8_t curr
= DBG_NONE
;
484 if (getDeviceDebugLevel(&curr
) != PM3_SUCCESS
)
487 const char *dbglvlstr
;
502 dbglvlstr
= "extended";
505 dbglvlstr
= "unknown";
508 PrintAndLogEx(INFO
, " Current debug log level..... %d ( " _YELLOW_("%s")" )", curr
, dbglvlstr
);
511 if ((lv0
+ lv1
+ lv2
+ lv3
+ lv4
) == 1) {
524 if (setDeviceDebugLevel(dbg
, true) != 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",
535 "hw detectreader -L\n"
540 arg_lit0("L", "LF", "only detect low frequency 125/134 kHz"),
541 arg_lit0("H", "HF", "only detect high frequency 13.56 MHZ"),
544 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
545 bool lf
= arg_get_lit(ctx
, 1);
546 bool hf
= arg_get_lit(ctx
, 2);
549 // 0: Detect both frequency in mode 1
553 if (lf
== true && hf
== false) {
555 } else if (hf
== true && lf
== false) {
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");
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
);
577 PrintAndLogEx(INFO
, "Done!");
582 static int CmdFPGAOff(const char *Cmd
) {
583 CLIParserContext
*ctx
;
584 CLIParserInit(&ctx
, "hw fpgaoff",
585 "Turn of fpga and antenna field",
593 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
596 clearCommandBuffer();
597 SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF
, NULL
, 0);
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"
610 arg_int1("r", "raw", "<hex>", "data "),
611 arg_int1("c", "cnt", "<dec>", "number of times to send"),
614 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
617 uint8_t raw
[1] = {0};
618 CLIGetHexWithReturn(ctx
, 1, raw
, &r_len
);
619 int j
= arg_get_int_def(ctx
, 2, 1);
622 PrintAndLogEx(WARNING
, "Count must be larger than zero");
627 clearCommandBuffer();
628 SendCommandMIX(CMD_LCD
, raw
[0], 0, 0, NULL
, 0);
633 static int CmdLCDReset(const char *Cmd
) {
634 CLIParserContext
*ctx
;
635 CLIParserInit(&ctx
, "hw lcdreset",
636 "Hardware reset LCD",
644 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
646 clearCommandBuffer();
647 SendCommandNG(CMD_LCD_RESET
, NULL
, 0);
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"
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"),
668 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
670 // check for -file option first to determine the output mode
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);
685 uint8_t *buffer
= calloc(len
, sizeof(uint8_t));
687 PrintAndLogEx(ERR
, "error, cannot allocate memory ");
691 const char *flash_str
= raw
? "" : " flash";
692 PrintAndLogEx(INFO
, "reading "_YELLOW_("%u")" bytes from processor%s memory",
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");
703 saveFile(filename
, ".bin", buffer
, len
);
705 PrintAndLogEx(INFO
, "---- " _CYAN_("processor%s memory") " ----", flash_str
);
706 print_hex_break(buffer
, len
, breaks
);
713 static int CmdReset(const char *Cmd
) {
714 CLIParserContext
*ctx
;
715 CLIParserInit(&ctx
, "hw reset",
716 "Reset the Proxmark3 device.",
724 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
726 clearCommandBuffer();
727 SendCommandNG(CMD_HARDWARE_RESET
, NULL
, 0);
728 PrintAndLogEx(INFO
, "Proxmark3 has been reset.");
733 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
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"
746 arg_u64_1("d", "div", "<dec>", "19 - 255 divisor value (def 95)"),
749 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
750 uint8_t arg
= arg_get_u32_def(ctx
, 1, 95);
754 PrintAndLogEx(ERR
, "Divisor must be between " _YELLOW_("19") " and " _YELLOW_("255"));
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)));
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"
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)"),
779 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
783 uint8_t threshold_high
;
784 uint8_t legic_threshold
;
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);
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"));
797 clearCommandBuffer();
798 SendCommandNG(CMD_HF_ISO14443A_SET_THRESHOLDS
, (uint8_t *)¶ms
, sizeof(params
));
799 PrintAndLogEx(SUCCESS
, "Thresholds set.");
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"
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"),
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);
826 if ((lopkd
+ loraw
+ hipkd
+ hiraw
) > 1) {
827 PrintAndLogEx(INFO
, "Can only set one mux");
831 #ifdef WITH_FPC_USART
832 if (loraw
|| hiraw
) {
833 PrintAndLogEx(INFO
, "this ADC mux option is unavailable on RDV4 compiled with FPC USART");
848 clearCommandBuffer();
849 SendCommandNG(CMD_SET_ADC_MUX
, (uint8_t *)&arg
, sizeof(arg
));
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"
863 arg_u64_0("a", "arg", "<dec>", "argument byte"),
864 arg_str0("b", NULL
, "<str>", "UniSniff arg: 14a, 14b, 15, iclass"),
867 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
875 packet
.arg
= arg_get_u32_def(ctx
, 1, 1);
877 CLIParamStrToBuf(arg_get_str(ctx
, 2), packet
.mode
, sizeof(packet
.mode
), &mlen
);
882 clearCommandBuffer();
883 SendCommandNG(CMD_STANDALONE
, (uint8_t *)&packet
, sizeof(struct p
));
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",
900 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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;
919 RepaintGraphWindow();
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)) {
929 if (timeout
>= timeout_max
) {
930 PrintAndLogEx(WARNING
, "\nNo response from Proxmark3. Aborting...");
934 PrintAndLogEx(INPLACE
, "% 3i", timeout_max
- timeout
);
936 PrintAndLogEx(NORMAL
, "");
938 if (resp
.status
!= PM3_SUCCESS
) {
939 PrintAndLogEx(WARNING
, "Antenna tuning failed");
943 PrintAndLogEx(NORMAL
, "");
944 PrintAndLogEx(INFO
, "-------- " _CYAN_("LF Antenna") " ----------");
954 uint8_t results
[256];
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
)) {
985 if ((s2
!= 0) && (package
->results
[i
] < v_3db_scaled
)) {
991 PrintAndLogEx(SUCCESS
, "");
992 PrintAndLogEx(SUCCESS
, "Approx. Q factor measurement");
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
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");
1029 memset(judgement
, 0, sizeof(judgement
));
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"));
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") " ----------");
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"));
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.
1071 for (int i
= 0; i
< 256; i
++) {
1072 g_GraphBuffer
[i
] = package
->results
[i
] - 128;
1073 test1
+= package
->results
[i
];
1077 PrintAndLogEx(NORMAL
, "");
1078 PrintAndLogEx(INFO
, "-------- " _CYAN_("LF tuning graph") " ------------");
1079 PrintAndLogEx(SUCCESS
, "Orange line - divisor %d / %.2f kHz"
1081 , LF_DIV2FREQ(LF_DIVISOR_125
)
1083 PrintAndLogEx(SUCCESS
, "Blue line - divisor %d / %.2f kHz\n\n"
1085 , LF_DIV2FREQ(LF_DIVISOR_134
)
1087 g_GraphTraceLen
= 256;
1088 g_MarkerC
.pos
= LF_DIVISOR_125
;
1089 g_MarkerD
.pos
= LF_DIVISOR_134
;
1091 RepaintGraphWindow();
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
, "");
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",
1109 void *argtable
[] = {
1113 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1115 pm3_version(true, false);
1119 static int CmdStatus(const char *Cmd
) {
1120 CLIParserContext
*ctx
;
1121 CLIParserInit(&ctx
, "hw status",
1122 "Show runtime status information about the connected Proxmark3",
1124 "hw status --ms 1000 -> Test connection speed with 1000ms timeout\n"
1127 void *argtable
[] = {
1129 arg_int0("m", "ms", "<ms>", "speed test timeout in micro seconds"),
1132 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1133 int32_t speedTestTimeout
= arg_get_int_def(ctx
, 1, -1);
1136 clearCommandBuffer();
1137 PacketResponseNG resp
;
1138 if (speedTestTimeout
< 0) {
1139 speedTestTimeout
= 0;
1140 SendCommandNG(CMD_STATUS
, NULL
, 0);
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
;
1152 int handle_tearoff(tearoff_params_t
*params
, bool verbose
) {
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"));
1175 PrintAndLogEx(WARNING
, "Tear-off command failed.");
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
[] = {
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"),
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);
1207 if ((delay
< 1) || (delay
> 43000)) {
1208 PrintAndLogEx(WARNING
, "You can't set delay out of 1..43000 range!");
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!");
1221 return handle_tearoff(¶ms
, !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",
1231 void *argtable
[] = {
1235 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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.");
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
[] = {
1262 arg_int0("m", "ms", "<ms>", "timeout in micro seconds"),
1265 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1266 int32_t arg
= arg_get_int_def(ctx
, 1, -1);
1269 uint32_t oldTimeout
= uart_get_timeouts();
1271 // timeout is not given/invalid, just show the current timeout then return
1273 PrintAndLogEx(INFO
, "Current communication timeout... " _GREEN_("%u") " ms", oldTimeout
);
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
);
1290 static int CmdPing(const char *Cmd
) {
1291 CLIParserContext
*ctx
;
1292 CLIParserInit(&ctx
, "hw ping",
1293 "Test if the Proxmark3 is responsive",
1298 void *argtable
[] = {
1300 arg_u64_0("l", "len", "<dec>", "length of payload to send"),
1304 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1305 uint32_t len
= arg_get_u32_def(ctx
, 1, 32);
1308 if (len
> PM3_CMD_DATA_SIZE
)
1309 len
= PM3_CMD_DATA_SIZE
;
1312 PrintAndLogEx(INFO
, "Ping sent with payload len... " _YELLOW_("%d"), len
);
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
++) {
1325 uint64_t tms
= msclock();
1326 SendCommandNG(CMD_PING
, data
, len
);
1327 if (WaitForResponseTimeout(CMD_PING
, &resp
, 1000)) {
1328 tms
= msclock() - tms
;
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"));
1335 PrintAndLogEx(SUCCESS
, "Ping response " _GREEN_("received")
1336 " in " _YELLOW_("%" PRIu64
) " ms", tms
);
1339 PrintAndLogEx(WARNING
, "Ping response " _RED_("timeout"));
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
[] = {
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"),
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
);
1367 if (baudrate
== 0) {
1368 PrintAndLogEx(WARNING
, "Baudrate can't be zero");
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");
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
);
1396 static int CmdBreak(const char *Cmd
) {
1398 CLIParserContext
*ctx
;
1399 CLIParserInit(&ctx
, "hw break",
1400 "send break loop package",
1404 void *argtable
[] = {
1408 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1410 clearCommandBuffer();
1411 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
1415 static int CmdBootloader(const char *Cmd
) {
1417 CLIParserContext
*ctx
;
1418 CLIParserInit(&ctx
, "hw bootloader",
1419 "Reboot Proxmark3 into bootloader mode",
1423 void *argtable
[] = {
1427 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1429 clearCommandBuffer();
1430 flash_reboot_bootloader(g_conn
.serial_port_name
, false);
1434 int set_fpga_mode(uint8_t mode
) {
1435 if (mode
< FPGA_BITSTREAM_MIN
|| mode
> FPGA_BITSTREAM_MAX
) {
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");
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
);
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 "
1501 # define PM3CLIENTCOMPILER "unknown compiler "
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)"
1525 # define PM3HOSTOS "unknown"
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"
1541 # define PM3HOSTARCH "unknown"
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)) {
1558 uint32_t section_size
;
1559 uint32_t versionstr_len
;
1560 char versionstr
[PM3_CMD_DATA_SIZE
- 12];
1563 struct p
*payload
= (struct p
*)&resp
.data
.asBytes
;
1565 lookup_chipid_short(payload
->id
, payload
->section_size
);
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: ");
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;
1584 ptr
= strstr(payload
->versionstr
, " bootrom: ");
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);
1594 ptr
= strstr(payload
->versionstr
, " os: ");
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"));
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
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
);
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"));
1657 PrintAndLogEx(NORMAL
, " Readline/Linenoise support." _YELLOW_("absent"));
1660 PrintAndLogEx(NORMAL
, " QT GUI support............ " _GREEN_("present"));
1662 PrintAndLogEx(NORMAL
, " QT GUI support............ " _YELLOW_("absent"));
1665 PrintAndLogEx(NORMAL
, " native BT support......... " _GREEN_("present"));
1667 PrintAndLogEx(NORMAL
, " native BT support......... " _YELLOW_("absent"));
1670 PrintAndLogEx(NORMAL
, " Python script support..... " _GREEN_("present"));
1672 PrintAndLogEx(NORMAL
, " Python script support..... " _YELLOW_("absent"));
1674 #ifdef HAVE_LUA_SWIG
1675 PrintAndLogEx(NORMAL
, " Lua SWIG support.......... " _GREEN_("present"));
1677 PrintAndLogEx(NORMAL
, " Lua SWIG support.......... " _YELLOW_("absent"));
1679 #ifdef HAVE_PYTHON_SWIG
1680 PrintAndLogEx(NORMAL
, " Python SWIG support....... " _GREEN_("present"));
1682 PrintAndLogEx(NORMAL
, " Python SWIG support....... " _YELLOW_("absent"));
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"));
1710 PrintAndLogEx(NORMAL
, " firmware.................. %s", _YELLOW_("PM3 GENERIC"));
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
, "");
1728 uint32_t section_size
;
1729 uint32_t versionstr_len
;
1730 char versionstr
[PM3_CMD_DATA_SIZE
- 12];
1733 struct p
*payload
= (struct p
*)&resp
.data
.asBytes
;
1735 bool armsrc_mismatch
= false;
1736 char *ptr
= strstr(payload
->versionstr
, " os: ");
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
, "");