1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
9 // low-level hardware control
10 //-----------------------------------------------------------------------------
17 #include "cmdparser.h" // command_t
18 #include "cliparser.h"
20 #include "usart_defs.h"
24 #include "commonutil.h"
26 #include "pmflash.h" // rdv40validation_t
27 #include "cmdflashmem.h" // get_signature..
29 static int CmdHelp(const char *Cmd
);
31 static void lookupChipID(uint32_t iChipID
, uint32_t mem_used
) {
33 memset(asBuff
, 0, sizeof(asBuff
));
34 uint32_t mem_avail
= 0;
35 PrintAndLogEx(NORMAL
, "\n [ " _YELLOW_("Hardware") " ]");
39 sprintf(asBuff
, "AT91SAM7S512 Rev A");
42 sprintf(asBuff
, "AT91SAM7S512 Rev B");
45 sprintf(asBuff
, "AT91SAM7S256 Rev A");
48 sprintf(asBuff
, "AT91SAM7S256 Rev B");
51 sprintf(asBuff
, "AT91SAM7S256 Rev C");
54 sprintf(asBuff
, "AT91SAM7S256 Rev D");
57 sprintf(asBuff
, "AT91SAM7S128 Rev A");
60 sprintf(asBuff
, "AT91SAM7S128 Rev B");
63 sprintf(asBuff
, "AT91SAM7S128 Rev C");
66 sprintf(asBuff
, "AT91SAM7S128 Rev D");
69 sprintf(asBuff
, "AT91SAM7S64 Rev A");
72 sprintf(asBuff
, "AT91SAM7S64 Rev B");
75 sprintf(asBuff
, "AT91SAM7S64 Rev C");
78 sprintf(asBuff
, "AT91SAM7S321 Rev A");
81 sprintf(asBuff
, "AT91SAM7S32 Rev A");
84 sprintf(asBuff
, "AT91SAM7S32 Rev B");
87 sprintf(asBuff
, "AT9SAM7S161 Rev A");
90 sprintf(asBuff
, "AT91SAM7S16 Rev A");
93 PrintAndLogEx(NORMAL
, " --= uC: " _YELLOW_("%s"), asBuff
);
95 switch ((iChipID
& 0xE0) >> 5) {
97 sprintf(asBuff
, "ARM946ES");
100 sprintf(asBuff
, "ARM7TDMI");
103 sprintf(asBuff
, "ARM920T");
106 sprintf(asBuff
, "ARM926EJS");
109 PrintAndLogEx(NORMAL
, " --= Embedded Processor: %s", asBuff
);
111 switch ((iChipID
& 0xF0000) >> 16) {
113 sprintf(asBuff
, "1K bytes");
116 sprintf(asBuff
, "2K bytes");
119 sprintf(asBuff
, "6K bytes");
122 sprintf(asBuff
, "112K bytes");
125 sprintf(asBuff
, "4K bytes");
128 sprintf(asBuff
, "80K bytes");
131 sprintf(asBuff
, "160K bytes");
134 sprintf(asBuff
, "8K bytes");
137 sprintf(asBuff
, "16K bytes");
140 sprintf(asBuff
, "32K bytes");
143 sprintf(asBuff
, "64K bytes");
146 sprintf(asBuff
, "128K bytes");
149 sprintf(asBuff
, "256K bytes");
152 sprintf(asBuff
, "96K bytes");
155 sprintf(asBuff
, "512K bytes");
158 PrintAndLogEx(NORMAL
, " --= Internal SRAM size: %s", asBuff
);
160 switch ((iChipID
& 0xFF00000) >> 20) {
162 sprintf(asBuff
, "AT91SAM9xx Series");
165 sprintf(asBuff
, "AT91SAM9XExx Series");
168 sprintf(asBuff
, "AT91x34 Series");
171 sprintf(asBuff
, "CAP7 Series");
174 sprintf(asBuff
, "CAP9 Series");
177 sprintf(asBuff
, "CAP11 Series");
180 sprintf(asBuff
, "AT91x40 Series");
183 sprintf(asBuff
, "AT91x42 Series");
186 sprintf(asBuff
, "AT91x55 Series");
189 sprintf(asBuff
, "AT91SAM7Axx Series");
192 sprintf(asBuff
, "AT91SAM7AQxx Series");
195 sprintf(asBuff
, "AT91x63 Series");
198 sprintf(asBuff
, "AT91SAM7Sxx Series");
201 sprintf(asBuff
, "AT91SAM7XCxx Series");
204 sprintf(asBuff
, "AT91SAM7SExx Series");
207 sprintf(asBuff
, "AT91SAM7Lxx Series");
210 sprintf(asBuff
, "AT91SAM7Xxx Series");
213 sprintf(asBuff
, "AT91x92 Series");
216 sprintf(asBuff
, "AT75Cxx Series");
219 PrintAndLogEx(NORMAL
, " --= Architecture identifier: %s", asBuff
);
221 switch ((iChipID
& 0x70000000) >> 28) {
223 sprintf(asBuff
, "ROM");
226 sprintf(asBuff
, "ROMless or on-chip Flash");
229 sprintf(asBuff
, "Embedded flash memory");
232 sprintf(asBuff
, "ROM and Embedded flash memory\nNVPSIZ is ROM size\nNVPSIZ2 is Flash size");
235 sprintf(asBuff
, "SRAM emulating ROM");
238 switch ((iChipID
& 0xF00) >> 8) {
271 PrintAndLogEx(NORMAL
, " --= %s " _YELLOW_("%uK") " bytes ( " _YELLOW_("%2.0f%%") " used )"
274 , mem_avail
== 0 ? 0.0f
: (float)mem_used
/ (mem_avail
* 1024) * 100
278 switch ((iChipID & 0xF000) >> 12) {
280 sprintf(asBuff, "None");
283 sprintf(asBuff, "8K bytes");
286 sprintf(asBuff, "16K bytes");
289 sprintf(asBuff, "32K bytes");
292 sprintf(asBuff, "64K bytes");
295 sprintf(asBuff, "128K bytes");
298 sprintf(asBuff, "256K bytes");
301 sprintf(asBuff, "512K bytes");
304 sprintf(asBuff, "1024K bytes");
307 sprintf(asBuff, "2048K bytes");
310 PrintAndLogEx(NORMAL, " --= Second nonvolatile program memory size: %s", asBuff);
314 static int CmdDbg(const char *Cmd
) {
316 CLIParserContext
*ctx
;
317 CLIParserInit(&ctx
, "hw dbg",
318 "Set device side debug level output.\n"
319 "Note: option -4, this option may cause malfunction itself",
325 arg_lit0("0", NULL
, "no debug messages"),
326 arg_lit0("1", NULL
, "error messages"),
327 arg_lit0("2", NULL
, "plus information messages"),
328 arg_lit0("3", NULL
, "plus debug messages"),
329 arg_lit0("4", NULL
, "print even debug messages in timing critical functions"),
332 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
333 bool lv0
= arg_get_lit(ctx
, 1);
334 bool lv1
= arg_get_lit(ctx
, 2);
335 bool lv2
= arg_get_lit(ctx
, 3);
336 bool lv3
= arg_get_lit(ctx
, 4);
337 bool lv4
= arg_get_lit(ctx
, 5);
340 if ((lv0
+ lv1
+ lv2
+ lv3
+ lv4
) > 1) {
341 PrintAndLogEx(INFO
, "Can only set one debug level");
357 SendCommandNG(CMD_SET_DBGMODE
, &dbg
, sizeof(dbg
));
361 static int CmdDetectReader(const char *Cmd
) {
362 CLIParserContext
*ctx
;
363 CLIParserInit(&ctx
, "hw detectreader",
364 "Start to detect presences of reader field",
365 "hw detectreader -L\n"
370 arg_lit0("L", "LF", "detect low frequence 125/134 kHz"),
371 arg_lit0("H", "HF", "detect high frequence 13.56 MHZ"),
374 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
375 bool lf
= arg_get_lit(ctx
, 1);
376 bool hf
= arg_get_lit(ctx
, 2);
380 PrintAndLogEx(INFO
, "Can only set one frequence");
390 PrintAndLogEx(INFO
, "press pm3 button to change modes and finally exit");
391 clearCommandBuffer();
392 SendCommandNG(CMD_LISTEN_READER_FIELD
, (uint8_t *)&arg
, sizeof(arg
));
397 static int CmdFPGAOff(const char *Cmd
) {
398 CLIParserContext
*ctx
;
399 CLIParserInit(&ctx
, "hw fpgaoff",
400 "Turn of fpga and antenna field",
408 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
411 clearCommandBuffer();
412 SendCommandNG(CMD_FPGA_MAJOR_MODE_OFF
, NULL
, 0);
416 static int CmdLCD(const char *Cmd
) {
417 CLIParserContext
*ctx
;
418 CLIParserInit(&ctx
, "hw lcd",
419 "Send command/data to LCD",
420 "hw lcd -r AA -c 03 -> sends 0xAA three times"
425 arg_int1("r", "raw", "<hex>", "data "),
426 arg_int1("c", "cnt", "<dec>", "number of times to send"),
429 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
433 uint8_t raw
[1] = {0};
434 CLIGetHexWithReturn(ctx
, 1, raw
, &r_len
);
435 int j
= arg_get_int(ctx
, 2);
437 PrintAndLogEx(WARNING
, "Count must be larger than zero");
442 clearCommandBuffer();
443 SendCommandMIX(CMD_LCD
, raw
[0], 0, 0, NULL
, 0);
448 static int CmdLCDReset(const char *Cmd
) {
449 CLIParserContext
*ctx
;
450 CLIParserInit(&ctx
, "hw lcdreset",
451 "Hardware reset LCD",
459 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
461 clearCommandBuffer();
462 SendCommandNG(CMD_LCD_RESET
, NULL
, 0);
466 static int CmdReadmem(const char *Cmd
) {
467 CLIParserContext
*ctx
;
468 CLIParserInit(&ctx
, "hw readmem",
469 "Read memory at decimal address from ARM chip flash.",
470 "hw readmem -a 10000"
475 arg_u64_1("a", "adr", "<dec>", "address to read"),
478 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
479 uint32_t address
= arg_get_u32(ctx
, 1);
481 clearCommandBuffer();
482 SendCommandNG(CMD_READ_MEM
, (uint8_t *)&address
, sizeof(address
));
486 static int CmdReset(const char *Cmd
) {
487 CLIParserContext
*ctx
;
488 CLIParserInit(&ctx
, "hw reset",
489 "Reset the Proxmark3 device.",
497 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
499 clearCommandBuffer();
500 SendCommandNG(CMD_HARDWARE_RESET
, NULL
, 0);
501 PrintAndLogEx(INFO
, "Proxmark3 has been reset.");
506 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
509 static int CmdSetDivisor(const char *Cmd
) {
511 CLIParserContext
*ctx
;
512 CLIParserInit(&ctx
, "hw setlfdivisor",
513 "Drive LF antenna at 12 MHz / (divisor + 1).",
514 "hw setlfdivisor -d 88"
519 arg_u64_1("d", "div", "<dec>", "19 - 255 divisor value (def 95)"),
522 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
523 uint8_t arg
= arg_get_u32_def(ctx
, 1, 95);
527 PrintAndLogEx(ERR
, "Divisor must be between" _YELLOW_("19") " and " _YELLOW_("255"));
530 // 12 000 000 (12MHz)
531 clearCommandBuffer();
532 SendCommandNG(CMD_LF_SET_DIVISOR
, (uint8_t *)&arg
, sizeof(arg
));
533 PrintAndLogEx(SUCCESS
, "Divisor set, expected " _YELLOW_("%.1f")" kHz", ((double)12000 / (arg
+ 1)));
537 static int CmdSetMux(const char *Cmd
) {
539 CLIParserContext
*ctx
;
540 CLIParserInit(&ctx
, "hw setmux",
541 "Set the ADC mux to a specific value",
542 "hw setmux --hiraw -> set HIGH RAW"
547 arg_lit0(NULL
, "lopkd", "low peak"),
548 arg_lit0(NULL
, "loraw", "low raw"),
549 arg_lit0(NULL
, "hipkd", "high peak"),
550 arg_lit0(NULL
, "hiraw", "high raw"),
553 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
554 bool lopkd
= arg_get_lit(ctx
, 1);
555 bool loraw
= arg_get_lit(ctx
, 2);
556 bool hipkd
= arg_get_lit(ctx
, 3);
557 bool hiraw
= arg_get_lit(ctx
, 4);
560 if ((lopkd
+ loraw
+ hipkd
+ hiraw
) > 1) {
561 PrintAndLogEx(INFO
, "Can only set one mux");
575 clearCommandBuffer();
576 SendCommandNG(CMD_SET_ADC_MUX
, (uint8_t *)&arg
, sizeof(arg
));
580 static int CmdStandalone(const char *Cmd
) {
581 CLIParserContext
*ctx
;
582 CLIParserInit(&ctx
, "hw standalone",
583 "Start standalone mode",
584 "hw standalone -> start \n"
585 "hw standalone -a 1 -> start and send arg 1"
590 arg_u64_0("a", "arg", "<dec>", "argument byte"),
593 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
594 uint8_t arg
= arg_get_u32(ctx
, 1);
596 clearCommandBuffer();
597 SendCommandNG(CMD_STANDALONE
, (uint8_t *)&arg
, sizeof(arg
));
601 static int CmdTune(const char *Cmd
) {
602 CLIParserContext
*ctx
;
603 CLIParserInit(&ctx
, "hw tune",
604 "Measure antenna tuning",
612 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
614 return CmdTuneSamples(Cmd
);
617 static int CmdVersion(const char *Cmd
) {
618 CLIParserContext
*ctx
;
619 CLIParserInit(&ctx
, "hw version",
620 "Show version information about the connected Proxmark3",
628 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
630 pm3_version(true, false);
634 static int CmdStatus(const char *Cmd
) {
635 CLIParserContext
*ctx
;
636 CLIParserInit(&ctx
, "hw status",
637 "Show runtime status information about the connected Proxmark3",
645 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
647 clearCommandBuffer();
648 PacketResponseNG resp
;
649 SendCommandNG(CMD_STATUS
, NULL
, 0);
650 if (WaitForResponseTimeout(CMD_STATUS
, &resp
, 2000) == false) {
651 PrintAndLogEx(WARNING
, "Status command timeout. Communication speed test timed out");
657 int handle_tearoff(tearoff_params_t
*params
, bool verbose
) {
662 clearCommandBuffer();
663 SendCommandNG(CMD_SET_TEAROFF
, (uint8_t *)params
, sizeof(tearoff_params_t
));
664 PacketResponseNG resp
;
665 if (WaitForResponseTimeout(CMD_SET_TEAROFF
, &resp
, 500) == false) {
666 PrintAndLogEx(WARNING
, "Tear-off command timeout.");
670 if (resp
.status
== PM3_SUCCESS
) {
671 if (params
->delay_us
> 0 && verbose
)
672 PrintAndLogEx(INFO
, "Tear-off hook configured with delay of " _GREEN_("%i us"), params
->delay_us
);
674 if (params
->on
&& verbose
)
675 PrintAndLogEx(INFO
, "Tear-off hook " _GREEN_("enabled"));
677 if (params
->off
&& verbose
)
678 PrintAndLogEx(INFO
, "Tear-off hook " _RED_("disabled"));
680 PrintAndLogEx(WARNING
, "Tear-off command failed.");
684 static int CmdTearoff(const char *Cmd
) {
685 CLIParserContext
*ctx
;
686 CLIParserInit(&ctx
, "hw tearoff",
687 "Configure a tear-off hook for the next write command supporting tear-off\n"
688 "After having been triggered by a write command, the tear-off hook is deactivated\n"
689 "Delay (in us) must be between 1 and 43000 (43ms). Precision is about 1/3us.",
690 "hw tearoff --delay 1200 --> define delay of 1200us\n"
691 "hw tearoff --on --> (re)activate a previously defined delay\n"
692 "hw tearoff --off --> deactivate a previously activated but not yet triggered hook\n");
696 arg_int0(NULL
, "delay", "<dec>", "Delay in us before triggering tear-off, must be between 1 and 43000"),
697 arg_lit0(NULL
, "on", "Activate tear-off hook"),
698 arg_lit0(NULL
, "off", "Deactivate tear-off hook"),
699 arg_lit0("s", "silent", "less verbose output"),
703 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
704 tearoff_params_t params
;
705 int delay
= arg_get_int_def(ctx
, 1, -1);
706 params
.on
= arg_get_lit(ctx
, 2);
707 params
.off
= arg_get_lit(ctx
, 3);
708 bool silent
= arg_get_lit(ctx
, 4);
712 if ((delay
< 1) || (delay
> 43000)) {
713 PrintAndLogEx(WARNING
, "You can't set delay out of 1..43000 range!");
717 delay
= 0; // will be ignored by ARM
720 params
.delay_us
= delay
;
721 if (params
.on
&& params
.off
) {
722 PrintAndLogEx(WARNING
, "You can't set both --on and --off!");
726 return handle_tearoff(¶ms
, !silent
);
729 static int CmdTia(const char *Cmd
) {
730 CLIParserContext
*ctx
;
731 CLIParserInit(&ctx
, "hw tia",
732 "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider",
740 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
743 PrintAndLogEx(INFO
, "Triggering new Timing Interval Acquisition (TIA)...");
744 clearCommandBuffer();
745 SendCommandNG(CMD_TIA
, NULL
, 0);
746 PacketResponseNG resp
;
747 if (WaitForResponseTimeout(CMD_TIA
, &resp
, 2000) == false) {
748 PrintAndLogEx(WARNING
, "TIA command timeout. You probably need to unplug the Proxmark3.");
751 PrintAndLogEx(INFO
, "TIA done.");
755 static int CmdPing(const char *Cmd
) {
756 CLIParserContext
*ctx
;
757 CLIParserInit(&ctx
, "hw ping",
758 "Test if the Proxmark3 is responsive",
765 arg_u64_0("l", "len", "<dec>", "length of payload to send"),
768 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
769 uint32_t len
= arg_get_u32(ctx
, 1);
772 if (len
> PM3_CMD_DATA_SIZE
)
773 len
= PM3_CMD_DATA_SIZE
;
776 PrintAndLogEx(INFO
, "Ping sent with payload len " _YELLOW_("%d"), len
);
778 PrintAndLogEx(INFO
, "Ping sent");
781 clearCommandBuffer();
782 PacketResponseNG resp
;
783 uint8_t data
[PM3_CMD_DATA_SIZE
] = {0};
785 for (uint16_t i
= 0; i
< len
; i
++)
788 SendCommandNG(CMD_PING
, data
, len
);
789 if (WaitForResponseTimeout(CMD_PING
, &resp
, 1000)) {
791 bool error
= (memcmp(data
, resp
.data
.asBytes
, len
) != 0);
792 PrintAndLogEx((error
) ? ERR
: SUCCESS
, "Ping response " _GREEN_("received") " and content is %s", error
? _RED_("NOT ok") : _GREEN_("OK"));
794 PrintAndLogEx(SUCCESS
, "Ping response " _GREEN_("received"));
797 PrintAndLogEx(WARNING
, "Ping response " _RED_("timeout"));
801 static int CmdConnect(const char *Cmd
) {
803 CLIParserContext
*ctx
;
804 CLIParserInit(&ctx
, "hw connect",
805 "Connects to a Proxmark3 device via specified serial port.\n"
806 "Baudrate here is only for physical UART or UART-BT, NOT for USB-CDC or blue shark add-on",
807 "hw connect -p "SERIAL_PORT_EXAMPLE_H
"\n"
808 "hw connect -p "SERIAL_PORT_EXAMPLE_H
" -b 115200"
813 arg_str0("p", "port", NULL
, "Serial port to connect to, else retry the last used one"),
814 arg_u64_0("b", "baud", "<dec>", "Baudrate"),
817 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
819 int p_len
= FILE_PATH_SIZE
;
820 char port
[FILE_PATH_SIZE
] = {0};
821 CLIGetStrWithReturn(ctx
, 1, (uint8_t *)port
, &p_len
);
822 uint32_t baudrate
= arg_get_u32_def(ctx
, 2, USART_BAUD_RATE
);
826 PrintAndLogEx(WARNING
, "Baudrate can't be zero");
830 // default back to previous used serial port
831 if (strlen(port
) == 0) {
832 if (strlen(conn
.serial_port_name
) == 0) {
833 PrintAndLogEx(WARNING
, "Must specify a serial port");
836 memcpy(port
, conn
.serial_port_name
, sizeof(port
));
839 if (session
.pm3_present
) {
840 CloseProxmark(session
.current_device
);
844 OpenProxmark(&session
.current_device
, port
, false, 10, false, baudrate
);
846 if (session
.pm3_present
&& (TestProxmark(session
.current_device
) != PM3_SUCCESS
)) {
847 PrintAndLogEx(ERR
, _RED_("ERROR:") " cannot communicate with the Proxmark3\n");
848 CloseProxmark(session
.current_device
);
854 static int CmdBreak(const char *Cmd
) {
856 CLIParserContext
*ctx
;
857 CLIParserInit(&ctx
, "hw break",
858 "send break loop package",
866 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
868 clearCommandBuffer();
869 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
874 static command_t CommandTable
[] = {
875 {"-------------", CmdHelp
, AlwaysAvailable
, "----------------------- " _CYAN_("Hardware") " -----------------------"},
876 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
877 {"break", CmdBreak
, IfPm3Present
, "Send break loop usb command"},
878 {"connect", CmdConnect
, AlwaysAvailable
, "Connect Proxmark3 to serial port"},
879 {"dbg", CmdDbg
, IfPm3Present
, "Set Proxmark3 debug level"},
880 {"detectreader", CmdDetectReader
, IfPm3Present
, "Detect external reader field"},
881 {"fpgaoff", CmdFPGAOff
, IfPm3Present
, "Set FPGA off"},
882 {"lcd", CmdLCD
, IfPm3Lcd
, "Send command/data to LCD"},
883 {"lcdreset", CmdLCDReset
, IfPm3Lcd
, "Hardware reset LCD"},
884 {"ping", CmdPing
, IfPm3Present
, "Test if the Proxmark3 is responsive"},
885 {"readmem", CmdReadmem
, IfPm3Present
, "Read memory at decimal address from flash"},
886 {"reset", CmdReset
, IfPm3Present
, "Reset the Proxmark3"},
887 {"setlfdivisor", CmdSetDivisor
, IfPm3Present
, "Drive LF antenna at 12MHz / (divisor + 1)"},
888 {"setmux", CmdSetMux
, IfPm3Present
, "Set the ADC mux to a specific value"},
889 {"standalone", CmdStandalone
, IfPm3Present
, "Jump to the standalone mode"},
890 {"status", CmdStatus
, IfPm3Present
, "Show runtime status information about the connected Proxmark3"},
891 {"tearoff", CmdTearoff
, IfPm3Present
, "Program a tearoff hook for the next command supporting tearoff"},
892 {"tia", CmdTia
, IfPm3Present
, "Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider"},
893 {"tune", CmdTune
, IfPm3Present
, "Measure antenna tuning"},
894 {"version", CmdVersion
, IfPm3Present
, "Show version information about the connected Proxmark3"},
895 {NULL
, NULL
, NULL
, NULL
}
898 static int CmdHelp(const char *Cmd
) {
899 (void)Cmd
; // Cmd is not used so far
900 CmdsHelp(CommandTable
);
904 int CmdHW(const char *Cmd
) {
905 clearCommandBuffer();
906 return CmdsParse(CommandTable
, Cmd
);
909 void pm3_version(bool verbose
, bool oneliner
) {
911 #if defined(__MINGW64__)
912 # define PM3CLIENTCOMPILER "MinGW-w64 "
913 #elif defined(__MINGW32__)
914 # define PM3CLIENTCOMPILER "MinGW "
915 #elif defined(__clang__)
916 # define PM3CLIENTCOMPILER "Clang/LLVM "
917 #elif defined(__GNUC__) || defined(__GNUG__)
918 # define PM3CLIENTCOMPILER "GCC "
920 # define PM3CLIENTCOMPILER "unknown compiler "
923 #if defined(__APPLE__) || defined(__MACH__)
924 # define PM3HOSTOS " OS:OSX"
925 #elif defined(__ANDROID__) || defined(ANDROID)
926 // must be tested before __linux__
927 # define PM3HOSTOS " OS:Android"
928 #elif defined(__linux__)
929 # define PM3HOSTOS " OS:Linux"
930 #elif defined(__FreeBSD__)
931 # define PM3HOSTOS " OS:FreeBSD"
932 #elif defined(__NetBSD__)
933 # define PM3HOSTOS " OS:NetBSD"
934 #elif defined(__OpenBSD__)
935 # define PM3HOSTOS " OS:OpenBSD"
936 #elif defined(__CYGWIN__)
937 # define PM3HOSTOS " OS:Cygwin"
938 #elif defined(_WIN64) || defined(__WIN64__)
939 // must be tested before _WIN32
940 # define PM3HOSTOS " OS:Windows (64b)"
941 #elif defined(_WIN32) || defined(__WIN32__)
942 # define PM3HOSTOS " OS:Windows (32b)"
944 # define PM3HOSTOS " OS:unknown"
947 #if defined(__x86_64__)
948 # define PM3HOSTARCH " ARCH:x86_64"
949 #elif defined(__i386__)
950 # define PM3HOSTARCH " ARCH:x86"
951 #elif defined(__aarch64__)
952 # define PM3HOSTARCH " ARCH:aarch64"
953 #elif defined(__arm__)
954 # define PM3HOSTARCH " ARCH:arm"
955 #elif defined(__powerpc64__)
956 # define PM3HOSTARCH " ARCH:powerpc64"
957 #elif defined(__mips__)
958 # define PM3HOSTARCH " ARCH:mips"
960 # define PM3HOSTARCH " ARCH:unknown"
964 // For "proxmark3 -v", simple printf, avoid logging
965 char temp
[PM3_CMD_DATA_SIZE
- 12]; // same limit as for ARM image
966 FormatVersionInformation(temp
, sizeof(temp
), "Client: ", &version_information
);
967 PrintAndLogEx(NORMAL
, "%s compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH
"\n", temp
);
974 PacketResponseNG resp
;
975 clearCommandBuffer();
976 SendCommandNG(CMD_VERSION
, NULL
, 0);
978 if (WaitForResponseTimeout(CMD_VERSION
, &resp
, 1000)) {
979 char temp
[PM3_CMD_DATA_SIZE
- 12]; // same limit as for ARM image
980 PrintAndLogEx(NORMAL
, "\n [ " _CYAN_("Proxmark3 RFID instrument") " ]");
981 PrintAndLogEx(NORMAL
, "\n [ " _YELLOW_("CLIENT") " ]");
982 FormatVersionInformation(temp
, sizeof(temp
), " client: ", &version_information
);
983 PrintAndLogEx(NORMAL
, "%s", temp
);
984 PrintAndLogEx(NORMAL
, " compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH
);
986 PrintAndLogEx(NORMAL
, "\n [ " _YELLOW_("PROXMARK3") " ]");
989 bool is_genuine_rdv4
= false;
990 // validate signature data
991 rdv40_validation_t mem
;
992 if (rdv4_get_signature(&mem
) == PM3_SUCCESS
) {
993 if (rdv4_validate(&mem
) == PM3_SUCCESS
) {
994 is_genuine_rdv4
= true;
998 PrintAndLogEx(NORMAL
, " device.................... %s", (is_genuine_rdv4
) ? _GREEN_("RDV4") : _RED_("device / fw mismatch"));
999 PrintAndLogEx(NORMAL
, " firmware.................. %s", (is_genuine_rdv4
) ? _GREEN_("RDV4") : _YELLOW_("RDV4"));
1000 PrintAndLogEx(NORMAL
, " external flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
1001 PrintAndLogEx(NORMAL
, " smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));
1002 PrintAndLogEx(NORMAL
, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
1004 PrintAndLogEx(NORMAL
, " firmware.................. %s", _YELLOW_("PM3 GENERIC"));
1005 if (IfPm3FpcUsartHost()) {
1006 PrintAndLogEx(NORMAL
, " FPC USART for BT add-on... %s", _GREEN_("present"));
1010 if (IfPm3FpcUsartDevFromUsb()) {
1011 PrintAndLogEx(NORMAL
, " FPC USART for developer... %s", _GREEN_("present"));
1014 PrintAndLogEx(NORMAL
, "");
1018 uint32_t section_size
;
1019 uint32_t versionstr_len
;
1020 char versionstr
[PM3_CMD_DATA_SIZE
- 12];
1023 struct p
*payload
= (struct p
*)&resp
.data
.asBytes
;
1025 PrintAndLogEx(NORMAL
, payload
->versionstr
);
1026 if (strstr(payload
->versionstr
, "2s30vq100") == NULL
) {
1027 PrintAndLogEx(NORMAL
, " FPGA firmware... %s", _RED_("chip mismatch"));
1030 lookupChipID(payload
->id
, payload
->section_size
);
1032 PrintAndLogEx(NORMAL
, "");