mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 14:23:50 -07:00
Merge pull request #1610 from RfidResearchGroup/sha
version checking of firmware files and client executable
This commit is contained in:
commit
680121b178
19 changed files with 253 additions and 183 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
||||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||||
|
|
||||||
## [unreleased][unreleased]
|
## [unreleased][unreleased]
|
||||||
|
- Added detection of a possible mismatch between client and Proxmark3 image (@doegox)
|
||||||
- Changed `hf 14a info` - added a ATR historical compact TLV decoder (@iceman1001)
|
- Changed `hf 14a info` - added a ATR historical compact TLV decoder (@iceman1001)
|
||||||
- Added `hf mf value` - decode a value block (@iceman1001)
|
- Added `hf mf value` - decode a value block (@iceman1001)
|
||||||
- Changed `hf mf nested` - removed option `--single` redundant with usage of `--tblk` (@doegox)
|
- Changed `hf mf nested` - removed option `--single` redundant with usage of `--tblk` (@doegox)
|
||||||
|
@ -22,7 +23,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Changed `hf_mf_uidbruteforce` - added support for S70, enhance UID length management (@cactuschibre)
|
- Changed `hf_mf_uidbruteforce` - added support for S70, enhance UID length management (@cactuschibre)
|
||||||
- Fixed build issues that may happen from building `mfd_aes_brute` (@linuxgemini)
|
- Fixed build issues that may happen from building `mfd_aes_brute` (@linuxgemini)
|
||||||
- Added silicon data parsing logic for NXP chips in `hf mfu info` (@linuxgemini)
|
- Added silicon data parsing logic for NXP chips in `hf mfu info` (@linuxgemini)
|
||||||
- Addes luascript `hf_mf_em_util.lua` - Script for emulator configuration (@nisgola)
|
- Added luascript `hf_mf_em_util.lua` - Script for emulator configuration (@nisgola)
|
||||||
- Fixes `hf mf restore` - now takes bin/eml/json as dump files (@iceman1001)
|
- Fixes `hf mf restore` - now takes bin/eml/json as dump files (@iceman1001)
|
||||||
- Fixes `script run some_python_script` segfault on armhf architecture (@doegox)
|
- Fixes `script run some_python_script` segfault on armhf architecture (@doegox)
|
||||||
- Added `trace extract` - extract authentication parts from trace (@iceman1001)
|
- Added `trace extract` - extract authentication parts from trace (@iceman1001)
|
||||||
|
@ -37,7 +38,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
||||||
- Added new standalone mode `lf_em4100rsww` (@zabszk)
|
- Added new standalone mode `lf_em4100rsww` (@zabszk)
|
||||||
- Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz)
|
- Fixed `hf 15 slixdisable` wrong pass id (@r1ddl3rz)
|
||||||
|
|
||||||
## [Frostbit.4.14831] [2022-01-11]
|
## [Frostbit.4.14831][2022-01-11]
|
||||||
- Changed Wiegand format lookup - now case-insensitive (@iceman1001)
|
- Changed Wiegand format lookup - now case-insensitive (@iceman1001)
|
||||||
- Added new standalone mode `hf_15SNIFF` - Same as `hf_14ASNIFF` standalone mode for RDV4 - flashmem (@startrk1995)
|
- Added new standalone mode `hf_15SNIFF` - Same as `hf_14ASNIFF` standalone mode for RDV4 - flashmem (@startrk1995)
|
||||||
- Added `hf gallagher` commands for read/writing DESFire cards (@DarkMatterMatt)
|
- Added `hf gallagher` commands for read/writing DESFire cards (@DarkMatterMatt)
|
||||||
|
|
|
@ -184,7 +184,7 @@ showinfo:
|
||||||
# version_pm3.c should be remade on every time fullimage.stage1.elf should be remade
|
# version_pm3.c should be remade on every time fullimage.stage1.elf should be remade
|
||||||
version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
version_pm3.c: default_version_pm3.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@
|
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@
|
||||||
|
|
||||||
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
|
@ -210,14 +210,6 @@ $(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $
|
||||||
$(info [=] LD $@)
|
$(info [=] LD $@)
|
||||||
$(Q)$(CROSS_LD) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
|
$(Q)$(CROSS_LD) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf
|
|
||||||
$(info [-] GEN $@)
|
|
||||||
$(Q)$(CROSS_OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@
|
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin
|
|
||||||
$(info [-] GEN $@)
|
|
||||||
$(Q)$(CROSS_OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@
|
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
|
$(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
|
||||||
$(info [-] GEN $@)
|
$(info [-] GEN $@)
|
||||||
$(Q)$(CROSS_OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
|
$(Q)$(CROSS_OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
|
||||||
|
@ -230,14 +222,10 @@ else
|
||||||
$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@
|
$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z
|
$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.stage1.elf $(OBJDIR)/fullimage.data.bin.z
|
||||||
$(info [-] GEN $@)
|
|
||||||
$(Q)$(CROSS_OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@
|
|
||||||
|
|
||||||
$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o
|
|
||||||
ifeq (,$(findstring WITH_NO_COMPRESSION,$(APP_CFLAGS)))
|
ifeq (,$(findstring WITH_NO_COMPRESSION,$(APP_CFLAGS)))
|
||||||
$(info [=] LD $@)
|
$(info [=] LD $@)
|
||||||
$(Q)$(CROSS_LD) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^
|
$(Q)$(CROSS_OBJCOPY) -O elf32-littlearm -I elf32-littlearm --strip-all --update-section .data=$(OBJDIR)/fullimage.data.bin.z $(OBJDIR)/fullimage.stage1.elf $@
|
||||||
else
|
else
|
||||||
$(Q)$(CP) $(OBJDIR)/fullimage.stage1.elf $@
|
$(Q)$(CP) $(OBJDIR)/fullimage.stage1.elf $@
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -287,6 +287,7 @@ static void SendVersion(void) {
|
||||||
strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
|
strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FormatVersionInformation(temp, sizeof(temp), " os: ", &g_version_information);
|
FormatVersionInformation(temp, sizeof(temp), " os: ", &g_version_information);
|
||||||
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
|
strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1);
|
||||||
strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
|
strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
|
||||||
|
|
|
@ -24,7 +24,6 @@ SECTIONS
|
||||||
} >osimage :text
|
} >osimage :text
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
KEEP(*(stage1_image))
|
|
||||||
*(.text)
|
*(.text)
|
||||||
*(.text.*)
|
*(.text.*)
|
||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
|
@ -36,12 +35,10 @@ SECTIONS
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
*(.rodata.*)
|
*(.rodata.*)
|
||||||
*(fpga_all_bit.data)
|
*(fpga_all_bit.data)
|
||||||
KEEP(*(.version_information))
|
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
} >osimage :text
|
} >osimage :text
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
KEEP(*(compressed_data))
|
|
||||||
*(.data)
|
*(.data)
|
||||||
*(.data.*)
|
*(.data.*)
|
||||||
*(.ramfunc)
|
*(.ramfunc)
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "BigBuf.h"
|
#include "BigBuf.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "ticks.h"
|
||||||
|
|
||||||
extern common_area_t g_common_area;
|
extern common_area_t g_common_area;
|
||||||
extern uint32_t __data_src_start__[], __data_start__[], __data_end__[], __bss_start__[], __bss_end__[];
|
extern uint32_t __data_src_start__[], __data_start__[], __data_end__[], __bss_start__[], __bss_end__[];
|
||||||
|
@ -40,9 +41,15 @@ static void uncompress_data_section(void) {
|
||||||
// uncompress data segment to RAM
|
// uncompress data segment to RAM
|
||||||
char *p = (char *)__data_src_start__;
|
char *p = (char *)__data_src_start__;
|
||||||
int res = LZ4_decompress_safe(p + 4, (char *)__data_start__, avail_in, avail_out);
|
int res = LZ4_decompress_safe(p + 4, (char *)__data_start__, avail_in, avail_out);
|
||||||
|
if (res < 0) {
|
||||||
if (res < 0)
|
while (true) {
|
||||||
return;
|
LED_A_INV();
|
||||||
|
LED_B_INV();
|
||||||
|
LED_C_INV();
|
||||||
|
LED_D_INV();
|
||||||
|
SpinDelay(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
// save the size of the compressed data section
|
// save the size of the compressed data section
|
||||||
g_common_area.arg1 = avail_in;
|
g_common_area.arg1 = avail_in;
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,7 +358,7 @@ set (TARGET_SOURCES
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || perl ${PM3_ROOT}/tools/mkversion.pl > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -881,9 +881,9 @@ src/pm3_pywrap.c: pm3.i
|
||||||
.PHONY: all clean install uninstall tarbin .FORCE
|
.PHONY: all clean install uninstall tarbin .FORCE
|
||||||
|
|
||||||
# version_pm3.c should be remade on every compilation
|
# version_pm3.c should be remade on every compilation
|
||||||
src/version_pm3.c: default_version_pm3.c
|
src/version_pm3.c: .FORCE default_version_pm3.c
|
||||||
$(info [=] GEN $@)
|
$(info [=] GEN $@)
|
||||||
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(PERL) ../tools/mkversion.pl > $@ || $(CP) $< $@
|
$(Q)$(SH) ../tools/mkversion.sh > $@ || $(CP) $< $@
|
||||||
|
|
||||||
# easy printing of MAKE VARIABLES
|
# easy printing of MAKE VARIABLES
|
||||||
print-%: ; @echo $* = $($*)
|
print-%: ; @echo $* = $($*)
|
||||||
|
|
|
@ -359,7 +359,7 @@ set (TARGET_SOURCES
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
OUTPUT ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || perl ${PM3_ROOT}/tools/mkversion.pl > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version_pm3.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version_pm3.c ${CMAKE_BINARY_DIR}/version_pm3.c
|
||||||
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
DEPENDS ${PM3_ROOT}/common/default_version_pm3.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1072,12 +1072,27 @@ void pm3_version(bool verbose, bool oneliner) {
|
||||||
|
|
||||||
struct p *payload = (struct p *)&resp.data.asBytes;
|
struct p *payload = (struct p *)&resp.data.asBytes;
|
||||||
|
|
||||||
|
bool armsrc_mismatch = false;
|
||||||
|
char *ptr = strstr(payload->versionstr, " os: ");
|
||||||
|
if (ptr != NULL) {
|
||||||
|
ptr = strstr(ptr, "\n");
|
||||||
|
if ((ptr != NULL) && (strlen(g_version_information.armsrc) == 9)) {
|
||||||
|
if (strncmp(ptr - 9, g_version_information.armsrc, 9) != 0) {
|
||||||
|
armsrc_mismatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
PrintAndLogEx(NORMAL, payload->versionstr);
|
PrintAndLogEx(NORMAL, payload->versionstr);
|
||||||
if (strstr(payload->versionstr, "2s30vq100") == NULL) {
|
if (strstr(payload->versionstr, "2s30vq100") == NULL) {
|
||||||
PrintAndLogEx(NORMAL, " FPGA firmware... %s", _RED_("chip mismatch"));
|
PrintAndLogEx(NORMAL, " FPGA firmware... %s", _RED_("chip mismatch"));
|
||||||
}
|
}
|
||||||
|
|
||||||
lookupChipID(payload->id, payload->section_size);
|
lookupChipID(payload->id, payload->section_size);
|
||||||
|
if (armsrc_mismatch) {
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled"));
|
||||||
|
PrintAndLogEx(WARNING, "Make sure to flash a correct and up-to-date version");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
|
@ -48,9 +48,22 @@ typedef struct {
|
||||||
uint16_t e_phnum;
|
uint16_t e_phnum;
|
||||||
uint16_t e_shentsize;
|
uint16_t e_shentsize;
|
||||||
uint16_t e_shnum;
|
uint16_t e_shnum;
|
||||||
uint16_t e_shtrndx;
|
uint16_t e_shstrndx;
|
||||||
} PACKED Elf32_Ehdr_t;
|
} PACKED Elf32_Ehdr_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t sh_name; // Section name, index in string tbl
|
||||||
|
uint32_t sh_type; // Type of section
|
||||||
|
uint32_t sh_flags; // Miscellaneous section attributes
|
||||||
|
uint32_t sh_addr; // Section virtual addr at execution
|
||||||
|
uint32_t sh_offset; // Section file offset
|
||||||
|
uint32_t sh_size; // Size of section in bytes
|
||||||
|
uint32_t sh_link; // Index of another section
|
||||||
|
uint32_t sh_info; // Additional section information
|
||||||
|
uint32_t sh_addralign; // Section alignment
|
||||||
|
uint32_t sh_entsize; // Entry size if section holds table
|
||||||
|
} PACKED Elf32_Shdr_t;
|
||||||
|
|
||||||
#define PT_NULL 0
|
#define PT_NULL 0
|
||||||
#define PT_LOAD 1
|
#define PT_LOAD 1
|
||||||
#define PT_DYNAMIC 2
|
#define PT_DYNAMIC 2
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "at91sam7s512.h"
|
#include "at91sam7s512.h"
|
||||||
#include "util_posix.h"
|
#include "util_posix.h"
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
|
#include "commonutil.h"
|
||||||
|
|
||||||
#define FLASH_START 0x100000
|
#define FLASH_START 0x100000
|
||||||
|
|
||||||
|
@ -84,12 +85,13 @@ static int chipid_to_mem_avail(uint32_t iChipID) {
|
||||||
|
|
||||||
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
||||||
// unaligned segments if needed
|
// unaligned segments if needed
|
||||||
static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdrs, uint16_t num_phdrs, uint32_t flash_end) {
|
static int build_segs_from_phdrs(flash_file_t *ctx, uint32_t flash_size) {
|
||||||
Elf32_Phdr_t *phdr = phdrs;
|
uint32_t flash_end = FLASH_START + flash_size;
|
||||||
|
Elf32_Phdr_t *phdr = ctx->phdrs;
|
||||||
flash_seg_t *seg;
|
flash_seg_t *seg;
|
||||||
uint32_t last_end = 0;
|
uint32_t last_end = 0;
|
||||||
|
|
||||||
ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t));
|
ctx->segments = calloc(sizeof(flash_seg_t) * ctx->num_phdrs, sizeof(uint8_t));
|
||||||
if (!ctx->segments) {
|
if (!ctx->segments) {
|
||||||
PrintAndLogEx(ERR, "Out of memory");
|
PrintAndLogEx(ERR, "Out of memory");
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
|
@ -98,7 +100,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdr
|
||||||
seg = ctx->segments;
|
seg = ctx->segments;
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Loading usable ELF segments:");
|
PrintAndLogEx(SUCCESS, "Loading usable ELF segments:");
|
||||||
for (int i = 0; i < num_phdrs; i++) {
|
for (int i = 0; i < ctx->num_phdrs; i++) {
|
||||||
if (le32(phdr->p_type) != PT_LOAD) {
|
if (le32(phdr->p_type) != PT_LOAD) {
|
||||||
phdr++;
|
phdr++;
|
||||||
continue;
|
continue;
|
||||||
|
@ -148,11 +150,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdr
|
||||||
PrintAndLogEx(ERR, "Error: Out of memory");
|
PrintAndLogEx(ERR, "Error: Out of memory");
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) {
|
memcpy(data, ctx->elf + offset, filesz);
|
||||||
PrintAndLogEx(ERR, "Error while reading PHDR payload");
|
|
||||||
free(data);
|
|
||||||
return PM3_EFILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t block_offset = paddr & (BLOCK_SIZE - 1);
|
uint32_t block_offset = paddr & (BLOCK_SIZE - 1);
|
||||||
if (block_offset) {
|
if (block_offset) {
|
||||||
|
@ -208,7 +206,8 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr_t *phdr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check segments and check for bootloader writes
|
// Sanity check segments and check for bootloader writes
|
||||||
static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) {
|
static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_size) {
|
||||||
|
uint32_t flash_end = FLASH_START + flash_size;
|
||||||
for (int i = 0; i < ctx->num_segs; i++) {
|
for (int i = 0; i < ctx->num_segs; i++) {
|
||||||
flash_seg_t *seg = &ctx->segments[i];
|
flash_seg_t *seg = &ctx->segments[i];
|
||||||
|
|
||||||
|
@ -236,92 +235,150 @@ static int check_segs(flash_file_t *ctx, int can_write_bl, uint32_t flash_end) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load an ELF file and prepare it for flashing
|
static int print_and_validate_version(struct version_information_t *vi) {
|
||||||
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_size) {
|
if (vi->magic != VERSION_INFORMATION_MAGIC)
|
||||||
|
return PM3_EFILE;
|
||||||
|
char temp[PM3_CMD_DATA_SIZE - 12]; // same limit as for ARM image
|
||||||
|
FormatVersionInformation(temp, sizeof(temp), "", vi);
|
||||||
|
PrintAndLogEx(SUCCESS, _CYAN_("ELF file version") _YELLOW_(" %s"), temp);
|
||||||
|
if (strlen(g_version_information.armsrc) == 9) {
|
||||||
|
if (strncmp(vi->armsrc, g_version_information.armsrc, 9) != 0) {
|
||||||
|
PrintAndLogEx(WARNING, _RED_("ARM firmware does not match the source at the time the client was compiled"));
|
||||||
|
return PM3_EINVARG;
|
||||||
|
} else {
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_EUNDEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load an ELF file for flashing
|
||||||
|
int flash_load(flash_file_t *ctx, bool force) {
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
Elf32_Ehdr_t ehdr;
|
Elf32_Ehdr_t *ehdr;
|
||||||
Elf32_Phdr_t *phdrs = NULL;
|
Elf32_Shdr_t *shdrs = NULL;
|
||||||
uint16_t num_phdrs;
|
uint8_t *shstr = NULL;
|
||||||
uint32_t flash_end = FLASH_START + flash_size;
|
struct version_information_t *vi = NULL;
|
||||||
int res = PM3_EUNDEF;
|
int res = PM3_EUNDEF;
|
||||||
|
|
||||||
fd = fopen(name, "rb");
|
fd = fopen(ctx->filename, "rb");
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", name);
|
PrintAndLogEx(ERR, _RED_("Could not open file") " %s >>> ", ctx->filename);
|
||||||
res = PM3_EFILE;
|
res = PM3_EFILE;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), name);
|
PrintAndLogEx(SUCCESS, _CYAN_("Loading ELF file") _YELLOW_(" %s"), ctx->filename);
|
||||||
|
|
||||||
if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) {
|
// get filesize in order to malloc memory
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF file header");
|
fseek(fd, 0, SEEK_END);
|
||||||
|
long fsize = ftell(fd);
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (fsize <= 0) {
|
||||||
|
PrintAndLogEx(ERR, "Error, when getting filesize");
|
||||||
|
res = PM3_EFILE;
|
||||||
|
fclose(fd);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->elf = calloc(fsize, sizeof(uint8_t));
|
||||||
|
if (!ctx->elf) {
|
||||||
|
PrintAndLogEx(ERR, "Error, cannot allocate memory");
|
||||||
|
res = PM3_EMALLOC;
|
||||||
|
fclose(fd);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytes_read = fread(ctx->elf, 1, fsize, fd);
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
if (bytes_read != fsize) {
|
||||||
|
PrintAndLogEx(ERR, "Error, bytes read mismatch file size");
|
||||||
res = PM3_EFILE;
|
res = PM3_EFILE;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident))
|
|
||||||
|| le32(ehdr.e_version) != 1) {
|
ehdr = (Elf32_Ehdr_t *)ctx->elf;
|
||||||
|
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");
|
PrintAndLogEx(ERR, "Not an ELF file or wrong ELF type");
|
||||||
res = PM3_EFILE;
|
res = PM3_EFILE;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (le16(ehdr.e_type) != ET_EXEC) {
|
if (le16(ehdr->e_type) != ET_EXEC) {
|
||||||
PrintAndLogEx(ERR, "ELF is not executable");
|
PrintAndLogEx(ERR, "ELF is not executable");
|
||||||
res = PM3_EFILE;
|
res = PM3_EFILE;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (le16(ehdr.e_machine) != EM_ARM) {
|
if (le16(ehdr->e_machine) != EM_ARM) {
|
||||||
PrintAndLogEx(ERR, "Wrong ELF architecture");
|
PrintAndLogEx(ERR, "Wrong ELF architecture");
|
||||||
res = PM3_EFILE;
|
res = PM3_EFILE;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (!ehdr.e_phnum || !ehdr.e_phoff) {
|
if (!ehdr->e_phnum || !ehdr->e_phoff) {
|
||||||
PrintAndLogEx(ERR, "ELF has no PHDRs");
|
PrintAndLogEx(ERR, "ELF has no PHDRs");
|
||||||
res = PM3_EFILE;
|
res = PM3_EFILE;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr_t)) {
|
if (le16(ehdr->e_phentsize) != sizeof(Elf32_Phdr_t)) {
|
||||||
// could be a structure padding issue...
|
// could be a structure padding issue...
|
||||||
PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail");
|
PrintAndLogEx(ERR, "Either the ELF file or this code is made of fail");
|
||||||
res = PM3_EFILE;
|
res = PM3_EFILE;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
num_phdrs = le16(ehdr.e_phnum);
|
ctx->num_phdrs = le16(ehdr->e_phnum);
|
||||||
|
ctx->phdrs = (Elf32_Phdr_t *)(ctx->elf + le32(ehdr->e_phoff));
|
||||||
|
shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff));
|
||||||
|
shdrs = (Elf32_Shdr_t *)(ctx->elf + le32(ehdr->e_shoff));
|
||||||
|
shstr = ctx->elf + le32(shdrs[ehdr->e_shstrndx].sh_offset);
|
||||||
|
|
||||||
phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr_t), sizeof(uint8_t));
|
for (uint16_t i = 0; i < le16(ehdr->e_shnum); i++) {
|
||||||
if (!phdrs) {
|
if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".version_information") == 0) {
|
||||||
PrintAndLogEx(ERR, "Out of memory");
|
vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset));
|
||||||
res = PM3_EMALLOC;
|
res = print_and_validate_version(vi);
|
||||||
goto fail;
|
break;
|
||||||
}
|
}
|
||||||
if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) {
|
if (strcmp(((char *)shstr) + shdrs[i].sh_name, ".bootphase1") == 0) {
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF PHDRs");
|
uint32_t offset = *(uint32_t*)(ctx->elf + le32(shdrs[i].sh_offset) + le32(shdrs[i].sh_size) - 4);
|
||||||
res = PM3_EFILE;
|
if (offset >= le32(shdrs[i].sh_addr)) {
|
||||||
goto fail;
|
offset -= le32(shdrs[i].sh_addr);
|
||||||
|
if (offset < le32(shdrs[i].sh_size)) {
|
||||||
|
vi = (struct version_information_t *)(ctx->elf + le32(shdrs[i].sh_offset) + offset);
|
||||||
|
res = print_and_validate_version(vi);
|
||||||
}
|
}
|
||||||
if (fread(phdrs, sizeof(Elf32_Phdr_t), num_phdrs, fd) != num_phdrs) {
|
|
||||||
res = PM3_EFILE;
|
|
||||||
PrintAndLogEx(ERR, "Error while reading ELF PHDRs");
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res == PM3_SUCCESS)
|
||||||
|
return res;
|
||||||
|
// We could not find proper version_information
|
||||||
|
if (res == PM3_EUNDEF)
|
||||||
|
PrintAndLogEx(WARNING, "Unable to check version_information");
|
||||||
|
if (force)
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
PrintAndLogEx(INFO, "Make sure to flash a correct and up-to-date version");
|
||||||
|
PrintAndLogEx(INFO, "You can force flashing this firmware by using the option '--force'");
|
||||||
|
fail:
|
||||||
|
flash_free(ctx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs, flash_end);
|
// Prepare an ELF file for flashing
|
||||||
|
int flash_prepare(flash_file_t *ctx, int can_write_bl, int flash_size) {
|
||||||
|
int res = PM3_EUNDEF;
|
||||||
|
|
||||||
|
res = build_segs_from_phdrs(ctx, flash_size);
|
||||||
if (res != PM3_SUCCESS)
|
if (res != PM3_SUCCESS)
|
||||||
goto fail;
|
goto fail;
|
||||||
res = check_segs(ctx, can_write_bl, flash_end);
|
res = check_segs(ctx, can_write_bl, flash_size);
|
||||||
if (res != PM3_SUCCESS)
|
if (res != PM3_SUCCESS)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
free(phdrs);
|
|
||||||
fclose(fd);
|
|
||||||
ctx->filename = name;
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (phdrs)
|
|
||||||
free(phdrs);
|
|
||||||
if (fd)
|
|
||||||
fclose(fd);
|
|
||||||
flash_free(ctx);
|
flash_free(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -618,6 +675,16 @@ int flash_write(flash_file_t *ctx) {
|
||||||
void flash_free(flash_file_t *ctx) {
|
void flash_free(flash_file_t *ctx) {
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return;
|
return;
|
||||||
|
if (ctx->filename != NULL) {
|
||||||
|
free(ctx->filename);
|
||||||
|
ctx->filename = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->elf) {
|
||||||
|
free(ctx->elf);
|
||||||
|
ctx->elf = NULL;
|
||||||
|
ctx->phdrs = NULL;
|
||||||
|
ctx->num_phdrs = 0;
|
||||||
|
}
|
||||||
if (ctx->segments) {
|
if (ctx->segments) {
|
||||||
for (int i = 0; i < ctx->num_segs; i++)
|
for (int i = 0; i < ctx->num_segs; i++)
|
||||||
free(ctx->segments[i].data);
|
free(ctx->segments[i].data);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define __FLASH_H__
|
#define __FLASH_H__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "elf.h"
|
||||||
|
|
||||||
#define FLASH_MAX_FILES 4
|
#define FLASH_MAX_FILES 4
|
||||||
#define ONE_KB 1024
|
#define ONE_KB 1024
|
||||||
|
@ -31,13 +32,17 @@ typedef struct {
|
||||||
} flash_seg_t;
|
} flash_seg_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *filename;
|
char *filename;
|
||||||
|
uint8_t *elf;
|
||||||
|
Elf32_Phdr_t *phdrs;
|
||||||
|
uint16_t num_phdrs;
|
||||||
int can_write_bl;
|
int can_write_bl;
|
||||||
int num_segs;
|
int num_segs;
|
||||||
flash_seg_t *segments;
|
flash_seg_t *segments;
|
||||||
} flash_file_t;
|
} flash_file_t;
|
||||||
|
|
||||||
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl, int flash_size);
|
int flash_load(flash_file_t *ctx, bool force);
|
||||||
|
int flash_prepare(flash_file_t *ctx, int can_write_bl, int flash_size);
|
||||||
int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed);
|
int flash_start_flashing(int enable_bl_writes, char *serial_port_name, uint32_t *max_allowed);
|
||||||
int flash_write(flash_file_t *ctx);
|
int flash_write(flash_file_t *ctx);
|
||||||
void flash_free(flash_file_t *ctx);
|
void flash_free(flash_file_t *ctx);
|
||||||
|
|
|
@ -576,7 +576,8 @@ static void show_help(bool showFullHelp, char *exec_name) {
|
||||||
PrintAndLogEx(NORMAL, " --incognito do not use history, prefs file nor log files");
|
PrintAndLogEx(NORMAL, " --incognito do not use history, prefs file nor log files");
|
||||||
PrintAndLogEx(NORMAL, "\nOptions in flasher mode:");
|
PrintAndLogEx(NORMAL, "\nOptions in flasher mode:");
|
||||||
PrintAndLogEx(NORMAL, " --flash flash Proxmark3, requires at least one --image");
|
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, " --unlock-bootloader Enable flashing of bootloader area *DANGEROUS* (need --flash)");
|
||||||
|
PrintAndLogEx(NORMAL, " --force Enable flashing even if firmware seems to not match client version");
|
||||||
PrintAndLogEx(NORMAL, " --image <imagefile> image to flash. Can be specified several times.");
|
PrintAndLogEx(NORMAL, " --image <imagefile> image to flash. Can be specified several times.");
|
||||||
PrintAndLogEx(NORMAL, "\nExamples:");
|
PrintAndLogEx(NORMAL, "\nExamples:");
|
||||||
PrintAndLogEx(NORMAL, "\n to run Proxmark3 client:\n");
|
PrintAndLogEx(NORMAL, "\n to run Proxmark3 client:\n");
|
||||||
|
@ -602,12 +603,11 @@ static void show_help(bool showFullHelp, char *exec_name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[FLASH_MAX_FILES], bool can_write_bl) {
|
static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[FLASH_MAX_FILES], bool can_write_bl, bool force) {
|
||||||
|
|
||||||
int ret = PM3_EUNDEF;
|
int ret = PM3_EUNDEF;
|
||||||
flash_file_t files[FLASH_MAX_FILES];
|
flash_file_t files[FLASH_MAX_FILES];
|
||||||
memset(files, 0, sizeof(files));
|
memset(files, 0, sizeof(files));
|
||||||
char *filepaths[FLASH_MAX_FILES] = {0};
|
|
||||||
|
|
||||||
if (serial_port_name == NULL) {
|
if (serial_port_name == NULL) {
|
||||||
PrintAndLogEx(ERR, "You must specify a port.\n");
|
PrintAndLogEx(ERR, "You must specify a port.\n");
|
||||||
|
@ -627,12 +627,20 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[
|
||||||
if (ret != PM3_SUCCESS) {
|
if (ret != PM3_SUCCESS) {
|
||||||
goto finish2;
|
goto finish2;
|
||||||
}
|
}
|
||||||
filepaths[i] = path;
|
files[i].filename = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "About to use the following file%s:", num_files > 1 ? "s" : "");
|
PrintAndLogEx(SUCCESS, "About to use the following file%s:", num_files > 1 ? "s" : "");
|
||||||
for (int i = 0 ; i < num_files; ++i) {
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), filepaths[i]);
|
PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), files[i].filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
|
ret = flash_load(&files[i], force);
|
||||||
|
if (ret != PM3_SUCCESS) {
|
||||||
|
goto finish2;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpenProxmark(&g_session.current_device, serial_port_name, true, 60, true, FLASHMODE_SPEED)) {
|
if (OpenProxmark(&g_session.current_device, serial_port_name, true, 60, true, FLASHMODE_SPEED)) {
|
||||||
|
@ -653,7 +661,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
for (int i = 0 ; i < num_files; ++i) {
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
ret = flash_load(&files[i], filepaths[i], can_write_bl, max_allowed * ONE_KB);
|
ret = flash_prepare(&files[i], can_write_bl, max_allowed * ONE_KB);
|
||||||
if (ret != PM3_SUCCESS) {
|
if (ret != PM3_SUCCESS) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -667,22 +675,22 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[
|
||||||
if (ret != PM3_SUCCESS) {
|
if (ret != PM3_SUCCESS) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
flash_free(&files[i]);
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (ret != PM3_SUCCESS)
|
if (ret != PM3_SUCCESS)
|
||||||
PrintAndLogEx(INFO, "The flashing procedure failed, follow the suggested steps!");
|
PrintAndLogEx(WARNING, "The flashing procedure failed, follow the suggested steps!");
|
||||||
ret = flash_stop_flashing();
|
ret = flash_stop_flashing();
|
||||||
CloseProxmark(g_session.current_device);
|
CloseProxmark(g_session.current_device);
|
||||||
finish2:
|
finish2:
|
||||||
for (int i = 0 ; i < num_files; ++i) {
|
for (int i = 0 ; i < num_files; ++i) {
|
||||||
if (filepaths[i] != NULL)
|
flash_free(&files[i]);
|
||||||
free(filepaths[i]);
|
|
||||||
}
|
}
|
||||||
if (ret == PM3_SUCCESS)
|
if (ret == PM3_SUCCESS)
|
||||||
PrintAndLogEx(SUCCESS, _CYAN_("All done"));
|
PrintAndLogEx(SUCCESS, _CYAN_("All done"));
|
||||||
|
else if (ret == PM3_EOPABORTED)
|
||||||
|
PrintAndLogEx(FAILED, "Aborted by user");
|
||||||
else
|
else
|
||||||
PrintAndLogEx(ERR, "Aborted on error");
|
PrintAndLogEx(ERR, "Aborted on error");
|
||||||
PrintAndLogEx(INFO, "\nHave a nice day!");
|
PrintAndLogEx(INFO, "\nHave a nice day!");
|
||||||
|
@ -725,6 +733,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
bool flash_mode = false;
|
bool flash_mode = false;
|
||||||
bool flash_can_write_bl = false;
|
bool flash_can_write_bl = false;
|
||||||
|
bool flash_force = false;
|
||||||
bool debug_mode_forced = false;
|
bool debug_mode_forced = false;
|
||||||
int flash_num_files = 0;
|
int flash_num_files = 0;
|
||||||
char *flash_filenames[FLASH_MAX_FILES];
|
char *flash_filenames[FLASH_MAX_FILES];
|
||||||
|
@ -941,6 +950,12 @@ int main(int argc, char *argv[]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// force flash even if firmware seems to not match client version
|
||||||
|
if (strcmp(argv[i], "--force") == 0) {
|
||||||
|
flash_force = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// flash file
|
// flash file
|
||||||
if (strcmp(argv[i], "--image") == 0) {
|
if (strcmp(argv[i], "--image") == 0) {
|
||||||
if (flash_num_files == FLASH_MAX_FILES) {
|
if (flash_num_files == FLASH_MAX_FILES) {
|
||||||
|
@ -982,7 +997,7 @@ int main(int argc, char *argv[]) {
|
||||||
speed = USART_BAUD_RATE;
|
speed = USART_BAUD_RATE;
|
||||||
|
|
||||||
if (flash_mode) {
|
if (flash_mode) {
|
||||||
flash_pm3(port, flash_num_files, flash_filenames, flash_can_write_bl);
|
flash_pm3(port, flash_num_files, flash_filenames, flash_can_write_bl, flash_force);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
|
||||||
|
|
||||||
strncat(dst, " ", len - strlen(dst) - 1);
|
strncat(dst, " ", len - strlen(dst) - 1);
|
||||||
strncat(dst, v->buildtime, len - strlen(dst) - 1);
|
strncat(dst, v->buildtime, len - strlen(dst) - 1);
|
||||||
|
strncat(dst, " ", len - strlen(dst) - 1);
|
||||||
|
strncat(dst, v->armsrc, len - strlen(dst) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
// See LICENSE.txt for the text of the license.
|
// See LICENSE.txt for the text of the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
/* This is the default version_pm3.c file that Makefile.common falls back to if neither sh nor perl are available */
|
/* This is the default version_pm3.c file that Makefile.common falls back to if sh is not available */
|
||||||
#ifndef ON_DEVICE
|
#ifndef ON_DEVICE
|
||||||
#define SECTVERSINFO
|
#define SECTVERSINFO
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct version_information_t {
|
||||||
char clean; /* 1: Tree was clean, no local changes. 0: Tree was unclean. 2: Couldn't be determined */
|
char clean; /* 1: Tree was clean, no local changes. 0: Tree was unclean. 2: Couldn't be determined */
|
||||||
char gitversion[50]; /* String with the git revision */
|
char gitversion[50]; /* String with the git revision */
|
||||||
char buildtime[30]; /* string with the build time */
|
char buildtime[30]; /* string with the build time */
|
||||||
|
char armsrc[10]; /* sha256sum of sha256sum of armsrc files */
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
|
|
40
pm3
40
pm3
|
@ -288,6 +288,8 @@ elif [ "$SCRIPT" = "pm3-flash" ]; then
|
||||||
while [ "$1" != "" ]; do
|
while [ "$1" != "" ]; do
|
||||||
if [ "$1" == "-b" ]; then
|
if [ "$1" == "-b" ]; then
|
||||||
ARGS+=("--unlock-bootloader")
|
ARGS+=("--unlock-bootloader")
|
||||||
|
elif [ "$1" == "--force" ]; then
|
||||||
|
ARGS+=("--force")
|
||||||
else
|
else
|
||||||
ARGS+=("--image" "$1")
|
ARGS+=("--image" "$1")
|
||||||
fi
|
fi
|
||||||
|
@ -320,7 +322,19 @@ elif [ "$SCRIPT" = "pm3-flash-all" ]; then
|
||||||
FINDBTDONGLE=false
|
FINDBTDONGLE=false
|
||||||
FINDBTRFCOMM=false
|
FINDBTRFCOMM=false
|
||||||
FINDBTDIRECT=false
|
FINDBTDIRECT=false
|
||||||
CMD() { $CLIENT "--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE"; }
|
|
||||||
|
|
||||||
|
CMD() {
|
||||||
|
ARGS=("--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE")
|
||||||
|
shift;
|
||||||
|
while [ "$1" != "" ]; do
|
||||||
|
if [ "$1" == "--force" ]; then
|
||||||
|
ARGS+=("--force")
|
||||||
|
fi
|
||||||
|
shift;
|
||||||
|
done
|
||||||
|
$CLIENT "${ARGS[@]}";
|
||||||
|
}
|
||||||
HELP() {
|
HELP() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Quick helper script for flashing a Proxmark device via USB
|
Quick helper script for flashing a Proxmark device via USB
|
||||||
|
@ -340,7 +354,17 @@ elif [ "$SCRIPT" = "pm3-flash-fullimage" ]; then
|
||||||
FINDBTDONGLE=false
|
FINDBTDONGLE=false
|
||||||
FINDBTRFCOMM=false
|
FINDBTRFCOMM=false
|
||||||
FINDBTDIRECT=false
|
FINDBTDIRECT=false
|
||||||
CMD() { $CLIENT "--port" "$1" "--flash" "--image" "$FULLIMAGE"; }
|
CMD() {
|
||||||
|
ARGS=("--port" "$1" "--flash" "--image" "$FULLIMAGE")
|
||||||
|
shift;
|
||||||
|
while [ "$1" != "" ]; do
|
||||||
|
if [ "$1" == "--force" ]; then
|
||||||
|
ARGS+=("--force")
|
||||||
|
fi
|
||||||
|
shift;
|
||||||
|
done
|
||||||
|
$CLIENT "${ARGS[@]}";
|
||||||
|
}
|
||||||
HELP() {
|
HELP() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Quick helper script for flashing a Proxmark device via USB
|
Quick helper script for flashing a Proxmark device via USB
|
||||||
|
@ -360,7 +384,17 @@ elif [ "$SCRIPT" = "pm3-flash-bootrom" ]; then
|
||||||
FINDBTDONGLE=false
|
FINDBTDONGLE=false
|
||||||
FINDBTRFCOMM=false
|
FINDBTRFCOMM=false
|
||||||
FINDBTDIRECT=false
|
FINDBTDIRECT=false
|
||||||
CMD() { $CLIENT "--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE"; }
|
CMD() {
|
||||||
|
ARGS=("--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE")
|
||||||
|
shift;
|
||||||
|
while [ "$1" != "" ]; do
|
||||||
|
if [ "$1" == "--force" ]; then
|
||||||
|
ARGS+=("--force")
|
||||||
|
fi
|
||||||
|
shift;
|
||||||
|
done
|
||||||
|
$CLIENT "${ARGS[@]}";
|
||||||
|
}
|
||||||
HELP() {
|
HELP() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Quick helper script for flashing a Proxmark device via USB
|
Quick helper script for flashing a Proxmark device via USB
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
# Output a version_pm3.c file that includes information about the current build
|
|
||||||
# Normally a couple of lines of bash would be enough (see openpcd project, original firmware by Harald Welte and Milosch Meriac)
|
|
||||||
# but this will, at least in theory, also work on Windows with our current compile environment.
|
|
||||||
# -- Henryk Plötz <henryk@ploetzli.ch> 2009-09-28
|
|
||||||
# Modified april 2014 because of the move to github.
|
|
||||||
# --- Martin Holst Swende <martin@swende.se>
|
|
||||||
# Modified january 2016 to work with Travis-CI
|
|
||||||
# --- iceman <iceman@iuse.se>
|
|
||||||
|
|
||||||
# Clear environment locale so that git will not use localized strings
|
|
||||||
$ENV{'LC_ALL'} = "C";
|
|
||||||
$ENV{'LANG'} = "C";
|
|
||||||
|
|
||||||
# if you are making your own fork, change this line to reflect your fork-name
|
|
||||||
my $fullgitinfo = 'RRG/Iceman';
|
|
||||||
my $ctime;
|
|
||||||
# GIT status 0 = dirty, 1 = clean , 2 = undecided
|
|
||||||
my $clean = 2;
|
|
||||||
my $undecided = (defined $ARGV[0]) && ($ARGV[0] =~ '--undecided');
|
|
||||||
# Do we have access to git command?
|
|
||||||
#######
|
|
||||||
# solves some bug on macos i.e:
|
|
||||||
##
|
|
||||||
# perl ../tools/mkversion.pl .. > version_pm3.c || cp ../common/default_version_pm3.c version_pm3.c
|
|
||||||
# /usr/bin/which: /usr/bin/which: cannot execute binary file
|
|
||||||
# fatal: No names found, cannot describe anything.
|
|
||||||
##
|
|
||||||
# anyway forcing any kind of shell is at least useless, at worst fatal.
|
|
||||||
my $commandGIT = "env which git";
|
|
||||||
|
|
||||||
if ( defined($commandGIT) ) {
|
|
||||||
|
|
||||||
# this goes on Internet and cause major slowdowns on poor connections or intranets, let's comment it
|
|
||||||
#my $githistory = `git fetch --all`;
|
|
||||||
# now avoiding the "fatal: No names found, cannot describe anything." error by fallbacking to abbrev hash in such case
|
|
||||||
my $gitversion = `git describe --dirty --always`;
|
|
||||||
my $gitbranch = `git rev-parse --abbrev-ref HEAD`;
|
|
||||||
if (not $undecided) {
|
|
||||||
$clean = $gitversion =~ '-dirty' ? 0 : 1;
|
|
||||||
}
|
|
||||||
if ( defined($gitbranch) and defined($gitversion) ) {
|
|
||||||
$fullgitinfo = $fullgitinfo.'/'. $gitbranch . '/' . $gitversion;
|
|
||||||
|
|
||||||
my @compiletime = localtime();
|
|
||||||
$compiletime[4] += 1;
|
|
||||||
$compiletime[5] += 1900;
|
|
||||||
$ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @compiletime);
|
|
||||||
} else {
|
|
||||||
$fullgitinfo = $fullgitinfo.'/master/release (git)';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$fullgitinfo = $fullgitinfo.'/master/release (no_git)';
|
|
||||||
my @dl_time = localtime( (stat('../README.md'))[10] );
|
|
||||||
$dl_time[4] += 1;
|
|
||||||
$dl_time[5] += 1900;
|
|
||||||
$ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @dl_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
$fullgitinfo =~ s/(\s)//g;
|
|
||||||
|
|
||||||
# Crop so it fits within 50 characters
|
|
||||||
#$fullgitinfo =~ s/.{50}\K.*//s;
|
|
||||||
$fullgitinfo = substr $fullgitinfo, 0, 49;
|
|
||||||
|
|
||||||
print <<EOF
|
|
||||||
#include "common.h"
|
|
||||||
/* Generated file, do not edit */
|
|
||||||
#ifndef ON_DEVICE
|
|
||||||
#define SECTVERSINFO
|
|
||||||
#else
|
|
||||||
#define SECTVERSINFO __attribute__((section(".version_information")))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const struct version_information_t SECTVERSINFO g_version_information = {
|
|
||||||
VERSION_INFORMATION_MAGIC,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
$clean,
|
|
||||||
"$fullgitinfo",
|
|
||||||
"$ctime",
|
|
||||||
};
|
|
||||||
EOF
|
|
|
@ -58,6 +58,13 @@ if [ "$fullgitinfoextra" != "$fullgitinfo" ]; then
|
||||||
fullgitinfo46="${fullgitinfo%"${fullgitinfoextra}"}"
|
fullgitinfo46="${fullgitinfo%"${fullgitinfoextra}"}"
|
||||||
fullgitinfo="${fullgitinfo46}..."
|
fullgitinfo="${fullgitinfo46}..."
|
||||||
fi
|
fi
|
||||||
|
sha=$(
|
||||||
|
pm3path=$(dirname -- "$0")/..
|
||||||
|
cd "$pm3path" || return
|
||||||
|
# did we find the src?
|
||||||
|
[ -f armsrc/appmain.c ] || return
|
||||||
|
ls armsrc/*.[ch] common_arm/*.[ch]|grep -E -v "(disabled|version_pm3|fpga_version_info)"|xargs sha256sum|sha256sum|grep -o '^.........'
|
||||||
|
)
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
/* Generated file, do not edit */
|
/* Generated file, do not edit */
|
||||||
|
@ -74,5 +81,6 @@ const struct version_information_t SECTVERSINFO g_version_information = {
|
||||||
$clean,
|
$clean,
|
||||||
"$fullgitinfo",
|
"$fullgitinfo",
|
||||||
"$ctime",
|
"$ctime",
|
||||||
|
"$sha"
|
||||||
};
|
};
|
||||||
EOF
|
EOF
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue