diff --git a/Makefile b/Makefile index 90ee442ca..ebb4dacb8 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ all clean install uninstall: %: client/% bootrom/% armsrc/% recovery/% mfkey/% n INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py findbits.py rfidtest.pl xorcheck.py INSTALLSIMFW=sim011.bin sim011.sha512.txt -INSTALLSCRIPTS=pm3 pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage +INSTALLSCRIPTS=pm3 pm3-flash pm3-flash-all pm3-flash-bootrom pm3-flash-fullimage INSTALLSHARES=tools/jtag_openocd traces INSTALLDOCS=doc/*.md doc/md diff --git a/client/Makefile b/client/Makefile index 96b5d1bf4..6fee6eae8 100644 --- a/client/Makefile +++ b/client/Makefile @@ -14,7 +14,7 @@ ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) include ../Makefile.defs -INSTALLBIN = proxmark3 proxmark3-flasher +INSTALLBIN = proxmark3 INSTALLSHARE = cmdscripts lualibs luascripts resources dictionaries VPATH = ../common uart @@ -237,7 +237,8 @@ CMDSRCS = crapto1/crapto1.c \ cmdscript.c \ pm3_bitlib.c \ cmdcrc.c \ - bucketsort.c + bucketsort.c \ + flash.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) @@ -278,7 +279,7 @@ ifeq "$(SUPPORTS_AVX512)" "True" MULTIARCHOBJS += $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX512.o) endif -BINS = proxmark3 proxmark3-flasher +BINS = proxmark3 CLEAN = $(BINS) *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua # transition: make sure old flasher is gone too CLEAN += flasher @@ -294,10 +295,6 @@ proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(info [=] LD $@) $(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(LDLIBS) -o $@ -proxmark3-flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) $(OBJCOBJS) - $(info [=] LD $@) - $(Q)$(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ - proxgui.cpp: ui/ui_overlays.h proxguiqt.moc.cpp: proxguiqt.h @@ -447,7 +444,7 @@ DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(REVEN $(patsubst %.o, %.d, $(MULTIARCHOBJS)) \ $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \ $(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) \ - $(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/proxmark3-flasher.d $(OBJDIR)/flasher.d + $(OBJDIR)/proxmark3.d $(DEPENDENCY_FILES): ; .PRECIOUS: $(DEPENDENCY_FILES) diff --git a/client/flash.c b/client/flash.c index 84e1d687b..5bbb669c0 100644 --- a/client/flash.c +++ b/client/flash.c @@ -83,7 +83,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t)); if (!ctx->segments) { PrintAndLogEx(ERR, "Out of memory"); - return -1; + return PM3_EMALLOC; } ctx->num_segs = 0; seg = ctx->segments; @@ -113,19 +113,19 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, if (filesz != memsz) { PrintAndLogEx(ERR, "Error: PHDR file size does not equal memory size\n" "(DATA+BSS PHDRs do not make sense on ROM platforms!)"); - return -1; + return PM3_EFILE; } if (paddr < last_end) { PrintAndLogEx(ERR, "Error: PHDRs not sorted or overlap"); - return -1; + return PM3_EFILE; } if (paddr < FLASH_START || (paddr + filesz) > flash_end) { PrintAndLogEx(ERR, "Error: PHDR is not contained in Flash"); - return -1; + return PM3_EFILE; } if (vaddr >= FLASH_START && vaddr < flash_end && (flags & PF_W)) { PrintAndLogEx(ERR, "Error: Flash VMA segment is writable"); - return -1; + return PM3_EFILE; } uint8_t *data; @@ -133,12 +133,12 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, data = calloc(filesz + BLOCK_SIZE, sizeof(uint8_t)); if (!data) { PrintAndLogEx(ERR, "Error: Out of memory"); - return -1; + return PM3_EMALLOC; } if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) { PrintAndLogEx(ERR, "Error while reading PHDR payload"); free(data); - return -1; + return PM3_EFILE; } uint32_t block_offset = paddr & (BLOCK_SIZE - 1); @@ -157,7 +157,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, if (!new_data) { PrintAndLogEx(ERR, "Error: Out of memory"); free(data); - return -1; + return PM3_EMALLOC; } memset(new_data, 0xff, new_length); memcpy(new_data, prev_seg->data, prev_seg->length); @@ -191,7 +191,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, last_end = paddr + filesz; phdr++; } - return 0; + return PM3_SUCCESS; } // Sanity check segments and check for bootloader writes @@ -201,26 +201,26 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) { if (seg->start & (BLOCK_SIZE - 1)) { PrintAndLogEx(ERR, "Error: Segment is not aligned"); - return -1; + return PM3_EFILE; } if (seg->start < FLASH_START) { PrintAndLogEx(ERR, "Error: Segment is outside of flash bounds"); - return -1; + return PM3_EFILE; } if (seg->start + seg->length > flash_end) { PrintAndLogEx(ERR, "Error: Segment is outside of flash bounds"); - return -1; + return PM3_EFILE; } if (!can_write_bl && seg->start < BOOTLOADER_END) { PrintAndLogEx(ERR, "Attempted to write bootloader but bootloader writes are not enabled"); - return -1; + return PM3_EINVARG; } if (can_write_bl && seg->start < BOOTLOADER_END && (seg->start + seg->length > BOOTLOADER_END)) { PrintAndLogEx(ERR, "Error: Segment is outside of bootloader bounds"); - return -1; + return PM3_EFILE; } } - return 0; + return PM3_SUCCESS; } // Load an ELF file and prepare it for flashing @@ -230,11 +230,12 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_ Elf32_Phdr *phdrs = NULL; uint16_t num_phdrs; uint32_t flash_end = FLASH_START + flash_size; - int res; + int res = PM3_EUNDEF; fd = fopen(name, "rb"); if (!fd) { PrintAndLogEx(ERR, _RED_("Could not open file") "%s >>> ", name); + res = PM3_EFILE; goto fail; } @@ -242,28 +243,34 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_ if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) { PrintAndLogEx(ERR, "Error while reading ELF file header"); + res = PM3_EFILE; goto fail; } if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident)) || le32(ehdr.e_version) != 1) { PrintAndLogEx(ERR, "Not an ELF file or wrong ELF type"); + res = PM3_EFILE; goto fail; } if (le16(ehdr.e_type) != ET_EXEC) { PrintAndLogEx(ERR, "ELF is not executable"); + res = PM3_EFILE; goto fail; } if (le16(ehdr.e_machine) != EM_ARM) { PrintAndLogEx(ERR, "Wrong ELF architecture"); + res = PM3_EFILE; goto fail; } if (!ehdr.e_phnum || !ehdr.e_phoff) { PrintAndLogEx(ERR, "ELF has no PHDRs"); + res = PM3_EFILE; goto fail; } if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) { // could be a structure padding issue... PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail"); + res = PM3_EFILE; goto fail; } num_phdrs = le16(ehdr.e_phnum); @@ -271,28 +278,31 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_ phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr), sizeof(uint8_t)); if (!phdrs) { PrintAndLogEx(ERR, "Out of memory"); + res = PM3_EMALLOC; goto fail; } if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) { PrintAndLogEx(ERR, "Error while reading ELF PHDRs"); + res = PM3_EFILE; goto fail; } if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) { + res = PM3_EFILE; PrintAndLogEx(ERR, "Error while reading ELF PHDRs"); goto fail; } res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs, flash_end); - if (res < 0) + if (res != PM3_SUCCESS) goto fail; res = check_segs(ctx, can_write_bl, flash_end); - if (res < 0) + if (res != PM3_SUCCESS) goto fail; free(phdrs); fclose(fd); ctx->filename = name; - return 0; + return PM3_SUCCESS; fail: if (phdrs) @@ -300,7 +310,7 @@ fail: if (fd) fclose(fd); flash_free(ctx); - return -1; + return res; } // Get the state of the proxmark, backwards compatible @@ -326,22 +336,23 @@ static int get_proxmark_state(uint32_t *state) { break; default: PrintAndLogEx(ERR, _RED_("Error:") "Couldn't get Proxmark3 state, bad response type: 0x%04x", resp.cmd); - return -1; + return PM3_EFATAL; break; } - return 0; + return PM3_SUCCESS; } // Enter the bootloader to be able to start flashing static int enter_bootloader(char *serial_port_name) { uint32_t state; + int ret; - if (get_proxmark_state(&state) < 0) - return -1; + if ((ret = get_proxmark_state(&state)) != PM3_SUCCESS) + return ret; /* Already in flash state, we're done. */ if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) - return 0; + return PM3_SUCCESS; if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) { PrintAndLogEx(SUCCESS, _BLUE_("Entering bootloader...")); @@ -364,15 +375,15 @@ static int enter_bootloader(char *serial_port_name) { if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { PrintAndLogEx(NORMAL, " " _GREEN_("Found")); - return 0; + return PM3_SUCCESS; } else { PrintAndLogEx(ERR, _RED_("Error:") "Proxmark3 not found."); - return -1; + return PM3_ETIMEOUT; } } PrintAndLogEx(ERR, _RED_("Error:") "Unknown Proxmark3 mode"); - return -1; + return PM3_EFATAL; } static int wait_for_ack(PacketResponseNG *ack) { @@ -383,9 +394,9 @@ static int wait_for_ack(PacketResponseNG *ack) { ack->cmd, (ack->cmd == CMD_NACK) ? "NACK" : "" ); - return -1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } static void flash_suggest_update_bootloader(void) { @@ -401,12 +412,15 @@ static void flash_suggest_update_flasher(void) { int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed) { uint32_t state; uint32_t chipinfo = 0; + int ret; - if (enter_bootloader(serial_port_name) < 0) - return -1; + ret = enter_bootloader(serial_port_name); + if (ret != PM3_SUCCESS) + return ret; - if (get_proxmark_state(&state) < 0) - return -1; + ret = get_proxmark_state(&state); + if (ret != PM3_SUCCESS) + return ret; if (state & DEVICE_INFO_FLAG_UNDERSTANDS_CHIP_INFO) { SendCommandBL(CMD_CHIP_INFO, 0, 0, 0, NULL, 0); @@ -485,7 +499,7 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t PrintAndLogEx(ERR, _RED_("Note: Your bootloader does not understand the new " _YELLOW_("START_FLASH") _RED_("command"))); flash_suggest_update_bootloader(); } - return 0; + return PM3_SUCCESS; } static int write_block(uint32_t address, uint8_t *data, uint32_t length) { @@ -531,7 +545,7 @@ int flash_write(flash_file_t *ctx) { if (write_block(baddr, data, block_size) < 0) { PrintAndLogEx(ERR, "Error writing block %d of %u", block, blocks); - return -1; + return PM3_EFATAL; } data += block_size; @@ -544,7 +558,7 @@ int flash_write(flash_file_t *ctx) { PrintAndLogEx(NORMAL, " " _GREEN_("OK")); fflush(stdout); } - return 0; + return PM3_SUCCESS; } // free a file context @@ -564,5 +578,5 @@ void flash_free(flash_file_t *ctx) { int flash_stop_flashing(void) { SendCommandBL(CMD_HARDWARE_RESET, 0, 0, 0, NULL, 0); msleep(100); - return 0; + return PM3_SUCCESS; } diff --git a/client/flash.h b/client/flash.h index eca4d9ccc..23dd28079 100644 --- a/client/flash.h +++ b/client/flash.h @@ -11,6 +11,9 @@ #include "common.h" +#define FLASH_MAX_FILES 4 +#define ONE_KB 1024 + typedef struct { void *data; uint32_t start; diff --git a/client/flasher.c b/client/flasher.c deleted file mode 100644 index 931976997..000000000 --- a/client/flasher.c +++ /dev/null @@ -1,130 +0,0 @@ -//----------------------------------------------------------------------------- -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Flasher frontend tool -//----------------------------------------------------------------------------- - -#include -#include -#include "usart_defs.h" -#include "flash.h" -#include "comms.h" -#include "ui.h" - -#define MAX_FILES 4 -#define ONE_KB 1024 - -static void usage(char *argv0) { - PrintAndLogEx(NORMAL, "Usage: %s [-b] image.elf [image.elf...]", argv0); - PrintAndLogEx(NORMAL, " %s -i\n", argv0); - PrintAndLogEx(NORMAL, "\t-b\tEnable flashing of bootloader area (DANGEROUS)"); - PrintAndLogEx(NORMAL, "\t-i\tProbe the connected Proxmark3 to retrieve its memory size"); - PrintAndLogEx(NORMAL, "\nExamples:\n\t %s "SERIAL_PORT_EXAMPLE_H" -i", argv0); - PrintAndLogEx(NORMAL, "\t %s "SERIAL_PORT_EXAMPLE_H" armsrc/obj/fullimage.elf", argv0); -#ifdef __linux__ - PrintAndLogEx(NORMAL, "\nNote (Linux):\nif the flasher gets stuck in 'Waiting for Proxmark3 to reappear on ',"); - PrintAndLogEx(NORMAL, "you need to blacklist Proxmark3 for modem-manager - see documentation for more details:"); - PrintAndLogEx(NORMAL, "* https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md"); - PrintAndLogEx(NORMAL, "\nMore info on flashing procedure from the official Proxmark3 wiki:"); - PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Gentoo%%20Linux"); - PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Ubuntu%%20Linux"); - PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/OSX\n"); -#endif -} - -int main(int argc, char **argv) { - int can_write_bl = 0; - int num_files = 0; - int res; - int ret = 0; - flash_file_t files[MAX_FILES]; - char *filenames[MAX_FILES]; - bool info = false; - memset(files, 0, sizeof(files)); - - session.supports_colors = false; - session.stdinOnTTY = isatty(STDIN_FILENO); - session.stdoutOnTTY = isatty(STDOUT_FILENO); -#if defined(__linux__) || (__APPLE__) - if (session.stdinOnTTY && session.stdoutOnTTY) - session.supports_colors = true; -#endif - session.help_dump_mode = false; - - if (argc < 3) { - usage(argv[0]); - return -1; - } - - for (int i = 2; i < argc; i++) { - if (argv[i][0] == '-') { - if (!strcmp(argv[i], "-b")) { - can_write_bl = 1; - } else if (!strcmp(argv[i], "-i")) { - info = true; - } else { - usage(argv[0]); - return -1; - } - } else { - filenames[num_files] = argv[i]; - num_files++; - } - } - - char *serial_port_name = argv[1]; - - if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { - PrintAndLogEx(NORMAL, _GREEN_("Found")); - } else { - PrintAndLogEx(ERR, "Could not find Proxmark3 on " _RED_("%s") ".\n", serial_port_name); - return -1; - } - - uint32_t max_allowed = 0; - res = flash_start_flashing(can_write_bl, serial_port_name, &max_allowed); - if (res < 0) { - ret = -1; - goto finish; - } - - if (info) - goto finish; - - for (int i = 0 ; i < num_files; ++i) { - res = flash_load(&files[i], filenames[i], can_write_bl, max_allowed * ONE_KB); - if (res < 0) { - ret = -1; - goto finish; - } - PrintAndLogEx(NORMAL, ""); - } - - PrintAndLogEx(SUCCESS, "\n" _BLUE_("Flashing...")); - - for (int i = 0; i < num_files; i++) { - res = flash_write(&files[i]); - if (res < 0) { - ret = -1; - goto finish; - } - flash_free(&files[i]); - PrintAndLogEx(NORMAL, "\n"); - } - -finish: - res = flash_stop_flashing(); - if (res < 0) - ret = -1; - - CloseProxmark(); - - if (ret == 0) - PrintAndLogEx(SUCCESS, _BLUE_("All done.")); - else - PrintAndLogEx(ERR, "Aborted on error."); - PrintAndLogEx(NORMAL, "\nHave a nice day!"); - return ret; -} diff --git a/client/proxmark3.c b/client/proxmark3.c index 26256dd12..05afcc1fd 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -25,6 +25,7 @@ #include "whereami.h" #include "comms.h" #include "fileutils.h" +#include "flash.h" static void showBanner(void) { @@ -278,12 +279,12 @@ static void set_my_executable_path(void) { static void show_help(bool showFullHelp, char *exec_name) { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "syntax: %s [-h|-t|-m]\n", exec_name); - PrintAndLogEx(NORMAL, " %s [[-p] ] [-b] [-w] [-f] [-c ]|[-l ]|[-s ] [-i]\n", exec_name); + PrintAndLogEx(NORMAL, "\nsyntax: %s [-h|-t|-m]", exec_name); + PrintAndLogEx(NORMAL, " %s [[-p] ] [-b] [-w] [-f] [-c ]|[-l ]|[-s ] [-i]", exec_name); + PrintAndLogEx(NORMAL, " %s [-p] --flash [--unlock-bootloader] [--image ]+", exec_name); if (showFullHelp) { - PrintAndLogEx(NORMAL, "options:"); + PrintAndLogEx(NORMAL, "\nOptions in client mode:"); PrintAndLogEx(NORMAL, " -h/--help this help"); PrintAndLogEx(NORMAL, " -t/--text dump all interactive command's help at once"); PrintAndLogEx(NORMAL, " -m/--markdown dump all interactive help at once in markdown syntax"); @@ -296,21 +297,93 @@ static void show_help(bool showFullHelp, char *exec_name) { PrintAndLogEx(NORMAL, " -s/--script-file script file with one Proxmark3 command per line"); PrintAndLogEx(NORMAL, " -i/--interactive enter interactive mode after executing the script or the command"); PrintAndLogEx(NORMAL, " -v/--version print client version"); - PrintAndLogEx(NORMAL, "\nsamples:"); - PrintAndLogEx(NORMAL, " %s -h\n", exec_name); - PrintAndLogEx(NORMAL, " %s -m\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -f -- flush output everytime\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -w -- wait for serial port\n", exec_name); - PrintAndLogEx(NORMAL, "\n how to run Proxmark3 client\n"); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -- runs the pm3 client\n", exec_name); - PrintAndLogEx(NORMAL, " %s -- runs the pm3 client in OFFLINE mode\n", exec_name); - PrintAndLogEx(NORMAL, "\n how to execute different commands from terminal\n"); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -c \"hf mf chk 1* ?\" -- execute cmd and quit client\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -l hf_read -- execute lua script " _YELLOW_("`hf_read`")"and quit client\n", exec_name); - PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -s mycmds.txt -- execute each pm3 cmd in file and quit client\n", exec_name); + PrintAndLogEx(NORMAL, "\nOptions in flasher mode:"); + PrintAndLogEx(NORMAL, " --flash flash Proxmark3, requires at least one --image"); + PrintAndLogEx(NORMAL, " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash or --flash-info)"); + PrintAndLogEx(NORMAL, " --image image to flash. Can be specified several times."); + PrintAndLogEx(NORMAL, "\nExamples:"); + PrintAndLogEx(NORMAL, "\n to run Proxmark3 client:\n"); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -- runs the pm3 client", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -f -- flush output everytime", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -w -- wait for serial port", exec_name); + PrintAndLogEx(NORMAL, " %s -- runs the pm3 client in OFFLINE mode", exec_name); + PrintAndLogEx(NORMAL, "\n to execute different commands from terminal:\n"); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -c \"hf mf chk 1* ?\" -- execute cmd and quit client", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -l hf_read -- execute lua script " _YELLOW_("`hf_read`")"and quit client", exec_name); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" -s mycmds.txt -- execute each pm3 cmd in file and quit client", exec_name); + PrintAndLogEx(NORMAL, "\n to flash fullimage and bootloader:\n"); + PrintAndLogEx(NORMAL, " %s "SERIAL_PORT_EXAMPLE_H" --flash --unlock-bootloader --image bootrom.elf --image fullimage.elf", exec_name); +#ifdef __linux__ + PrintAndLogEx(NORMAL, "\nNote (Linux):\nif the flasher gets stuck in 'Waiting for Proxmark3 to reappear on ',"); + PrintAndLogEx(NORMAL, "you need to blacklist Proxmark3 for modem-manager - see documentation for more details:"); + PrintAndLogEx(NORMAL, "* https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md"); + PrintAndLogEx(NORMAL, "\nMore info on flashing procedure from the official Proxmark3 wiki:"); + PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Gentoo%%20Linux"); + PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/Ubuntu%%20Linux"); + PrintAndLogEx(NORMAL, "* https://github.com/Proxmark/proxmark3/wiki/OSX\n"); +#endif } } +static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[FLASH_MAX_FILES], bool can_write_bl) { + + int ret = PM3_EUNDEF; + flash_file_t files[FLASH_MAX_FILES]; + memset(files, 0, sizeof(files)); + + if (serial_port_name == NULL) { + PrintAndLogEx(ERR, "You must specify a port.\n"); + return PM3_EINVARG; + } + + if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { + PrintAndLogEx(NORMAL, _GREEN_("Found")); + } else { + PrintAndLogEx(ERR, "Could not find Proxmark3 on " _RED_("%s") ".\n", serial_port_name); + return PM3_ETIMEOUT; + } + + uint32_t max_allowed = 0; + ret = flash_start_flashing(can_write_bl, serial_port_name, &max_allowed); + if (ret != PM3_SUCCESS) { + goto finish; + } + + if (num_files == 0) + goto finish; + + for (int i = 0 ; i < num_files; ++i) { + ret = flash_load(&files[i], filenames[i], can_write_bl, max_allowed * ONE_KB); + if (ret != PM3_SUCCESS) { + goto finish; + } + PrintAndLogEx(NORMAL, ""); + } + + PrintAndLogEx(SUCCESS, "\n" _BLUE_("Flashing...")); + + for (int i = 0; i < num_files; i++) { + ret = flash_write(&files[i]); + if (ret != PM3_SUCCESS) { + goto finish; + } + flash_free(&files[i]); + PrintAndLogEx(NORMAL, "\n"); + } + +finish: + ret = flash_stop_flashing(); + + CloseProxmark(); + + if (ret == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, _BLUE_("All done.")); + else + PrintAndLogEx(ERR, "Aborted on error."); + PrintAndLogEx(NORMAL, "\nHave a nice day!"); + return ret; +} + int main(int argc, char *argv[]) { srand(time(0)); @@ -341,6 +414,11 @@ int main(int argc, char *argv[]) { } #endif + bool flash_mode = false; + bool flash_can_write_bl = false; + int flash_num_files = 0; + char *flash_filenames[FLASH_MAX_FILES]; + for (int i = 1; i < argc; i++) { if (argv[i][0] != '-') { @@ -467,6 +545,33 @@ int main(int argc, char *argv[]) { continue; } + // go to flash mode + if (strcmp(argv[i], "--flash") == 0) { + flash_mode = true; + continue; + } + + // unlock bootloader area + if (strcmp(argv[i], "--unlock-bootloader") == 0) { + flash_can_write_bl = true; + continue; + } + + // flash file + if (strcmp(argv[i], "--image") == 0) { + if (flash_num_files == FLASH_MAX_FILES) { + PrintAndLogEx(ERR, _RED_("ERROR:") "too many --image, please use it max %i times\n", FLASH_MAX_FILES); + return 1; + } + if (i + 1 == argc) { + PrintAndLogEx(ERR, _RED_("ERROR:") "missing image specification after --image\n"); + show_help(false, exec_name); + return 1; + } + flash_filenames[flash_num_files++] = argv[++i]; + continue; + } + // We got an unknown parameter PrintAndLogEx(ERR, _RED_("ERROR:") "invalid parameter: " _YELLOW_("%s") "\n", argv[i]); show_help(false, exec_name); @@ -487,13 +592,18 @@ int main(int argc, char *argv[]) { session.supports_colors = true; #endif // ascii art only in interactive client - if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY) + if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY && !flash_mode) showBanner(); // Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway if (speed == 0) speed = USART_BAUD_RATE; + if (flash_mode) { + flash_pm3(port, flash_num_files, flash_filenames, flash_can_write_bl); + exit(EXIT_SUCCESS); + } + if (script_cmd) { while (script_cmd[strlen(script_cmd) - 1] == ' ') script_cmd[strlen(script_cmd) - 1] = 0x00; diff --git a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md index ba6547cb2..6d6a1c48a 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -40,7 +40,7 @@ pm3-flash-all If port detection failed, you'll have to call the flasher manually and specify the correct port: ```sh -proxmark3-flasher /dev/tty.usbmodemiceman1 -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf +pm3-flash /dev/tty.usbmodemiceman1 -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf ``` > Depending on the firmware version your Proxmark3 can also appear as `/dev/tty.usbmodem881`. @@ -99,13 +99,13 @@ pm3-flash-all If port detection failed, you'll have to call the flasher manually and specify the correct port: ```sh -proxmark3-flasher /dev/tty.usbmodemiceman1 -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf +pm3-flash /dev/tty.usbmodemiceman1 -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf ``` or from the local repo ```sh -client/proxmark3-flasher /dev/tty.usbmodemiceman1 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +client/pm3-flash /dev/tty.usbmodemiceman1 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf ``` Similarly, to run the client, you may try: diff --git a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md index c2c01f44f..7303bdb4b 100644 --- a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md +++ b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md @@ -121,7 +121,7 @@ In short: * unplug device * press button and keep it pressed (IMPORTANT) * plug in device -* run flash command `proxmark3-flasher /dev/ttyACM0 /usr/local/share/proxmark3/firmware/fullimage.elf` +* run flash command `pm3-flash /dev/ttyACM0 /usr/local/share/proxmark3/firmware/fullimage.elf` * wait until flash is finished * release button * un/plug device diff --git a/doc/md/Installation_Instructions/Troubleshooting.md b/doc/md/Installation_Instructions/Troubleshooting.md index e9ae8bce9..b7898fb97 100644 --- a/doc/md/Installation_Instructions/Troubleshooting.md +++ b/doc/md/Installation_Instructions/Troubleshooting.md @@ -23,7 +23,7 @@ Always use the latest repository commits from *master* branch. There are always Try using directly the client or flasher: ``` -client/proxmark3-flasher ... +client/pm3-flash ... client/proxmark3 ... ``` @@ -49,8 +49,8 @@ pm3-flash-fullimage ``` or ``` -proxmark3-flasher -b bootrom/obj/bootrom.elf -proxmark3-flasher armsrc/obj/fullimage.elf +pm3-flash -b bootrom/obj/bootrom.elf +pm3-flash armsrc/obj/fullimage.elf ``` ### Find out why it would be bricked @@ -71,7 +71,7 @@ pm3-flash-fullimage ``` or ``` -proxmark3-flasher armsrc/obj/fullimage.elf +pm3-flash armsrc/obj/fullimage.elf ``` You should be back on tracks now. In case the flasher complains about bootloader version, you can follow the button procedure and flash first your bootloader. @@ -81,7 +81,7 @@ pm3-flash-bootrom ``` or ``` -proxmark3-flasher -b bootrom/obj/bootrom.elf +pm3-flash -b bootrom/obj/bootrom.elf ``` ### Ok, my bootloader is definitively dead, now what? @@ -119,9 +119,9 @@ proxmark3 and you must adapt accordingly the file path of some commands, e.g. ``` -proxmark3-flasher /usr/local/share/proxmark3/firmware/fullimage.elf +pm3-flash /usr/local/share/proxmark3/firmware/fullimage.elf <> -proxmark3-flasher /usr/share/proxmark3/firmware/fullimage.elf +pm3-flash /usr/share/proxmark3/firmware/fullimage.elf pm3 --> sc upgrade f /usr/local/share/proxmark3/firmware/sim011.bin <> @@ -144,9 +144,9 @@ cd client; ./proxmark3 ... Therefore client commands referring to files of the repo must be adapted, e.g. ``` -client/proxmark3-flasher armsrc/obj/fullimage.elf +client/pm3-flash armsrc/obj/fullimage.elf <> -./proxmark3-flasher ../armsrc/obj/fullimage.elf +./pm3-flash ../armsrc/obj/fullimage.elf pm3 --> sc upgrade f tools/simmodule/sim011.bin <> diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 6a821a992..4f6bf99e8 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -54,7 +54,7 @@ pacman -S mingw-w64-x86_64-astyle Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). -To use the compiled client and flasher, the only differences are that executables end with `.exe` (e.g. `proxmark3-flasher.exe`) and that the Proxmark3 port is one of your `comX` ports where "X" is the com port number assigned to proxmark3 under Windows. +To use the compiled client and flasher, the only differences are that executables end with `.exe` (e.g. `proxmark3.exe`) and that the Proxmark3 port is one of your `comX` ports where "X" is the com port number assigned to proxmark3 under Windows. To flash: In principle, the helper script `pm3-flash-all` should auto-detect your COM port, so you can just try: @@ -65,13 +65,13 @@ pm3-flash-all If COM port detection failed, you'll have to call the flasher manually and specify the correct port: ```sh -proxmark3-flasher.exe comX -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf +pm3-flash comX -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf ``` or from the local repo ```sh -client/proxmark3-flasher.exe comX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +client/pm3-flash comX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf ``` Similarly, to run the client, you may try: @@ -156,13 +156,13 @@ pm3-flash-all If port detection failed, you'll have to call the flasher manually and specify the correct port: ```sh -proxmark3-flasher.exe /dev/ttySX -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf +pm3-flash /dev/ttySX -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf ``` or from the local repo ```sh -client/proxmark3-flasher.exe /dev/ttySX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +client/pm3-flash /dev/ttySX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf ``` Similarly, to run the client, you may try: diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index 7faa6a658..7ec483d0c 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -45,13 +45,13 @@ In most cases, you can run the script `pm3-flash-all` which try to auto-detect t For the other cases, specify the port by yourself. For example, for a Proxmark3 connected via USB under Linux: ```sh -proxmark3-flasher /dev/ttyACM0 -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf +pm3-flash /dev/ttyACM0 -b /usr/local/share/proxmark3/firmware/bootrom.elf /usr/local/share/proxmark3/firmware/fullimage.elf ``` or from the local repo ```sh -client/proxmark3-flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +client/pm3-flash /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf ``` ## Run the client diff --git a/doc/path_notes.md b/doc/path_notes.md index bcdc19e33..556780f54 100644 --- a/doc/path_notes.md +++ b/doc/path_notes.md @@ -15,8 +15,8 @@ The main Proxmark3 executables / shellscripts will be copied to /usr/local/bin/ ``` -* executables: `proxmark3`, `proxmark3-flasher` -* scripts: `pm3`, `pm3-flash-all`, `pm3-flash-bootloader`, `pm3-flash-fullimage` +* executables: `proxmark3` +* scripts: `pm3`, `pm3-flash`, `pm3-flash-all`, `pm3-flash-bootloader`, `pm3-flash-fullimage` Some more executable / scripts will be copied to diff --git a/pm3 b/pm3 index 11eb59d31..705cd288e 100755 --- a/pm3 +++ b/pm3 @@ -4,19 +4,16 @@ PM3PATH=$(dirname "$0") # try pm3 dirs in current repo workdir if [ -d "$PM3PATH/client/" ]; then CLIENT="$PM3PATH/client/proxmark3" - FLASHER="$PM3PATH/client/proxmark3-flasher" FULLIMAGE="$PM3PATH/armsrc/obj/fullimage.elf" BOOTIMAGE="$PM3PATH/bootrom/obj/bootrom.elf" # try install dir elif [ -x "$PM3PATH/proxmark3" ]; then CLIENT="$PM3PATH/proxmark3" - FLASHER="$PM3PATH/proxmark3-flasher" FULLIMAGE="$PM3PATH/../share/proxmark3/firmware/fullimage.elf" BOOTIMAGE="$PM3PATH/../share/proxmark3/firmware/bootrom.elf" else # hope it's installed somehow, still not sure where fw images are... CLIENT="proxmark3" - FLASHER="proxmark3-flasher" FULLIMAGE="$PM3PATH/../share/proxmark3/firmware/fullimage.elf" BOOTIMAGE="$PM3PATH/../share/proxmark3/firmware/bootrom.elf" fi @@ -80,12 +77,26 @@ SCRIPT=$(basename -- "$0") if [ "$SCRIPT" = "pm3" ]; then CMD() { $CLIENT "$@"; } +elif [ "$SCRIPT" = "pm3-flash" ]; then + CMD() { + ARGS=("$1" "--flash") + shift; + while [ "$1" != "" ]; do + if [ "$1" == "-b" ]; then + ARGS+=("--unlock-bootloader") + else + ARGS+=("--image" "$1") + fi + shift; + done + $CLIENT ${ARGS[@]}; + } elif [ "$SCRIPT" = "pm3-flash-all" ]; then - CMD() { $FLASHER "$1" -b "$BOOTIMAGE" "$FULLIMAGE"; } + CMD() { $CLIENT "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE"; } elif [ "$SCRIPT" = "pm3-flash-fullimage" ]; then - CMD() { $FLASHER "$1" "$FULLIMAGE"; } + CMD() { $CLIENT "$1" "--flash" "--image" "$FULLIMAGE"; } elif [ "$SCRIPT" = "pm3-flash-bootrom" ]; then - CMD() { $FLASHER "$1" -b "$BOOTIMAGE"; } + CMD() { $CLIENT "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE"; } else echo "[!!] Script ran under unknown name, abort: $SCRIPT" exit 1 diff --git a/pm3-flash b/pm3-flash new file mode 100755 index 000000000..e5cd5479d --- /dev/null +++ b/pm3-flash @@ -0,0 +1,4 @@ +#!/bin/bash + +PM3PATH=$(dirname "$0") +. "$PM3PATH/pm3"