mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-14 02:26:59 -07:00
Implement version information storage and retrieval for the bootrom and the osimage.
Use perl to create the version information (thereby re-creating the perl dependency and adding an svn dependency) but fall back in case of missing perl or svn
This commit is contained in:
parent
42bc3be31c
commit
8a6aec16d8
13 changed files with 171 additions and 13 deletions
|
@ -13,6 +13,7 @@ THUMBSRC = start.c \
|
|||
lfops.c \
|
||||
iso15693.c \
|
||||
util.c \
|
||||
version.c \
|
||||
usb.c
|
||||
|
||||
# These are to be compiled in ARM mode
|
||||
|
@ -43,6 +44,7 @@ clean:
|
|||
$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
|
||||
$(DELETE) $(OBJDIR)$(PATHSEP)*.map
|
||||
$(DELETE) $(OBJDIR)$(PATHSEP)*.d
|
||||
$(DELETE) version.c
|
||||
|
||||
.PHONY: all clean help
|
||||
help:
|
||||
|
|
|
@ -236,10 +236,28 @@ void ReadMem(int addr)
|
|||
DbpIntegers(0, data[i], data[i+1]);
|
||||
}
|
||||
|
||||
/* osimage version information is linked in */
|
||||
extern struct version_information version_information;
|
||||
void SendVersion(void)
|
||||
{
|
||||
char temp[48]; /* Limited data payload in USB packets */
|
||||
DbpString("Prox/RFID mark3 RFID instrument");
|
||||
|
||||
/* Try to find the bootrom version information. For the time being, expect
|
||||
* to find a pointer at address 0x1001fc, perform slight sanity checks on
|
||||
* the pointer, then use it.
|
||||
*/
|
||||
void *bootrom_version = *(void**)0x1001fc;
|
||||
if( bootrom_version < (void*)0x100000 || bootrom_version > (void*)0x101000 ) {
|
||||
DbpString("bootrom version information appears invalid");
|
||||
} else {
|
||||
FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version);
|
||||
DbpString(temp);
|
||||
}
|
||||
|
||||
FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
|
||||
DbpString(temp);
|
||||
|
||||
FpgaGatherVersion(temp, sizeof(temp));
|
||||
DbpString(temp);
|
||||
}
|
||||
|
|
|
@ -112,5 +112,6 @@ void LED(int led, int ms);
|
|||
void LEDsoff();
|
||||
int BUTTON_CLICKED(int ms);
|
||||
int BUTTON_HELD(int ms);
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@ SECTIONS
|
|||
*(.text.*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.version_information)
|
||||
} >osimage
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
|
|
|
@ -235,3 +235,37 @@ void SpinDelay(int ms)
|
|||
// convert to uS and call microsecond delay function
|
||||
SpinDelayUs(ms*1000);
|
||||
}
|
||||
|
||||
/* Similar to FpgaGatherVersion this formats stored version information
|
||||
* into a string representation. It takes a pointer to the struct version_information,
|
||||
* verifies the magic properties, then stores a formatted string, prefixed by
|
||||
* prefix in dst.
|
||||
*/
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information)
|
||||
{
|
||||
struct version_information *v = (struct version_information*)version_information;
|
||||
dst[0] = 0;
|
||||
strncat(dst, prefix, len);
|
||||
if(v->magic != VERSION_INFORMATION_MAGIC) {
|
||||
strncat(dst, "Missing/Invalid version information", len);
|
||||
return;
|
||||
}
|
||||
if(v->versionversion != 1) {
|
||||
strncat(dst, "Version information not understood", len);
|
||||
return;
|
||||
}
|
||||
if(!v->present) {
|
||||
strncat(dst, "Version information not available", len);
|
||||
return;
|
||||
}
|
||||
|
||||
strncat(dst, v->svnversion, len);
|
||||
if(v->clean == 0) {
|
||||
strncat(dst, "-unclean", len);
|
||||
} else if(v->clean == 2) {
|
||||
strncat(dst, "-suspect", len);
|
||||
}
|
||||
|
||||
strncat(dst, " ", len);
|
||||
strncat(dst, v->buildtime, len);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code
|
||||
ARMSRC = fromflash.c
|
||||
THUMBSRC = usb.c bootrom.c
|
||||
THUMBSRC = usb.c version.c bootrom.c
|
||||
ASMSRC = ram-reset.s flash-reset.s
|
||||
|
||||
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
|
||||
|
@ -19,8 +19,9 @@ clean:
|
|||
$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
|
||||
$(DELETE) $(OBJDIR)$(PATHSEP)*.map
|
||||
$(DELETE) $(OBJDIR)$(PATHSEP)*.d
|
||||
$(DELETE) version.c
|
||||
|
||||
.PHONY: all clean help
|
||||
.PHONY: all clean help
|
||||
help:
|
||||
@echo Multi-OS Makefile, you are running on $(DETECTED_OS)
|
||||
@echo Possible targets:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <proxmark3.h>
|
||||
|
||||
void __attribute__((section("bootphase1"))) CopyBootToRAM(void)
|
||||
void __attribute__((section(".bootphase1"))) CopyBootToRAM(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
|
@ -8,6 +8,18 @@ SECTIONS
|
|||
bootphase1 : {
|
||||
*(.startup)
|
||||
*(.bootphase1)
|
||||
|
||||
/* It seems to be impossible to flush align a section at the
|
||||
end of a memory segment. Instead, we'll put the version_information
|
||||
wherever the linker wants it, and then put a pointer to the start
|
||||
of the version information at the end of the section.
|
||||
-- Henryk Plötz <henryk@ploetzli.ch> 2009-08-28 */
|
||||
|
||||
_version_information_start = .;
|
||||
*(.version_information);
|
||||
|
||||
. = LENGTH(bootphase1) - 0x4; /* Skip ahead to the end */
|
||||
LONG(_version_information_start)
|
||||
} >bootphase1
|
||||
|
||||
bootphase2 : {
|
||||
|
|
|
@ -20,6 +20,7 @@ ifeq ($(UNAME), Linux)
|
|||
# Linux. (Todo: Add MacOS X if appropriate)
|
||||
DELETE=rm -rf
|
||||
MOVE=mv
|
||||
COPY=cp
|
||||
PATHSEP=/
|
||||
DETECTED_OS=Linux
|
||||
# You may/should set this in your environment
|
||||
|
@ -31,6 +32,7 @@ else
|
|||
# Assume that we are running on Windows.
|
||||
DELETE=del /q
|
||||
MOVE=ren
|
||||
COPY=copy
|
||||
PATHSEP=\\#
|
||||
ARMLIB ?= ../../devkitARM/lib/gcc/arm-elf/4.1.0/interwork
|
||||
DETECTED_OS=Windows
|
||||
|
@ -77,6 +79,11 @@ $(OBJDIR)/%.s19: $(OBJDIR)/%.elf
|
|||
--change-section-address .text-0x100000 \
|
||||
--change-section-address .rodata-0x100000 $^ $@
|
||||
|
||||
# version.c should be remade on every compilation
|
||||
.PHONY: version.c
|
||||
version.c: default_version.c
|
||||
perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
|
||||
|
||||
# Automatic dependency generation
|
||||
DEPENDENCY_FILES = $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(THUMBSRC))) \
|
||||
$(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(ARMSRC))) \
|
||||
|
|
9
common/default_version.c
Normal file
9
common/default_version.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <proxmark3.h>
|
||||
/* This is the default version.c file that Makefile.common falls back to if perl is not available */
|
||||
struct version_information __attribute__((section(".version_information"))) version_information = {
|
||||
VERSION_INFORMATION_MAGIC,
|
||||
1, /* version version 1 */
|
||||
0, /* version information not present */
|
||||
2, /* cleanliness couldn't be determined */
|
||||
/* Remaining fields: zero */
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
#define VERSION "$Id $"
|
||||
static const struct __attribute__((packed)) {
|
||||
const char string[48];
|
||||
unsigned int length;
|
||||
unsigned int magic;
|
||||
} version __attribute__((unused,section("versioninformation"))) = {
|
||||
VERSION,
|
||||
sizeof(VERSION),
|
||||
0x48151623,
|
||||
};
|
|
@ -60,4 +60,14 @@ void UsbStart(void);
|
|||
// if data are available.
|
||||
void UsbPacketReceived(BYTE *packet, int len);
|
||||
|
||||
#define VERSION_INFORMATION_MAGIC 0x56334d50
|
||||
struct version_information {
|
||||
int magic; /* Magic sequence to identify this as a correct version information structure. Must be VERSION_INFORMATION_MAGIC */
|
||||
char versionversion; /* Must be 1 */
|
||||
char present; /* 1 if the version information could be created at compile time, otherwise 0 and the remaining fields (except for magic) are empty */
|
||||
char clean; /* 1: Tree was clean, no local changes. 0: Tree was unclean. 2: Couldn't be determined */
|
||||
char svnversion[9]; /* String with the SVN revision */
|
||||
char buildtime[30]; /* string with the build time */
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif
|
||||
|
|
73
tools/mkversion.pl
Normal file
73
tools/mkversion.pl
Normal file
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/perl
|
||||
# Output a version.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
|
||||
|
||||
use strict;
|
||||
|
||||
my $main_dir = shift;
|
||||
|
||||
# Clear environment locale so that svn will not use localized strings
|
||||
$ENV{'LC_ALL'} = "C";
|
||||
$ENV{'LANG'} = "C";
|
||||
|
||||
my $svnversion = 0;
|
||||
my $present = 0;
|
||||
my $clean = 2;
|
||||
my @compiletime = gmtime();
|
||||
|
||||
# Strategy one: call svn info and extract last changed revision, call svn status and look for ^M
|
||||
if(open(SVNINFO, "svn info $main_dir|")) {
|
||||
while(<SVNINFO>) {
|
||||
if (/^Last Changed Rev: (.*)/) {
|
||||
$present = 1;
|
||||
$svnversion = $1;
|
||||
## last; # Do not abort here, since SVN tends to complain about a Broken pipe
|
||||
}
|
||||
}
|
||||
close(SVNINFO);
|
||||
|
||||
if(open(SVNSTATUS, "svn status $main_dir|")) {
|
||||
$clean = 1;
|
||||
while(<SVNSTATUS>) {
|
||||
if(/^M/) {
|
||||
$clean = 0;
|
||||
## last;
|
||||
}
|
||||
}
|
||||
close(SVNINFO);
|
||||
}
|
||||
|
||||
} else {
|
||||
# Strategy two: look for .svn/entries. The third line should be "dir", the fourth line should contain the current
|
||||
# revision.
|
||||
if(open(ENTRIES, "$main_dir/.svn/entries")) {
|
||||
my $i = 1;
|
||||
while(<ENTRIES>) {
|
||||
last if($i == 3 and !/^dir/);
|
||||
if($i == 4 and /^([0-9]*)/) {
|
||||
$present = 1;
|
||||
$svnversion = $1;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$compiletime[4] += 1;
|
||||
$compiletime[5] += 1900;
|
||||
my $ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @compiletime);
|
||||
|
||||
print <<EOF
|
||||
#include <proxmark3.h>
|
||||
/* Generated file, do not edit */
|
||||
struct version_information __attribute__((section(".version_information"))) version_information = {
|
||||
VERSION_INFORMATION_MAGIC,
|
||||
1,
|
||||
$present,
|
||||
$clean,
|
||||
"svn $svnversion",
|
||||
"$ctime",
|
||||
};
|
||||
EOF
|
Loading…
Add table
Add a link
Reference in a new issue