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
lfops.c \\r
iso15693.c \\r
util.c \\r
+ version.c \\r
usb.c\r
\r
# These are to be compiled in ARM mode\r
$(DELETE) $(OBJDIR)$(PATHSEP)*.s19\r
$(DELETE) $(OBJDIR)$(PATHSEP)*.map\r
$(DELETE) $(OBJDIR)$(PATHSEP)*.d\r
+ $(DELETE) version.c\r
\r
.PHONY: all clean help\r
help:\r
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);
}
void LEDsoff();\r
int BUTTON_CLICKED(int ms);\r
int BUTTON_HELD(int ms);\r
+void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);\r
\r
#endif\r
*(.text.*)\r
*(.glue_7)\r
*(.glue_7t)\r
+ *(.version_information)\r
} >osimage\r
.rodata : { \r
*(.rodata) \r
// convert to uS and call microsecond delay function\r
SpinDelayUs(ms*1000);\r
}\r
+\r
+/* Similar to FpgaGatherVersion this formats stored version information\r
+ * into a string representation. It takes a pointer to the struct version_information,\r
+ * verifies the magic properties, then stores a formatted string, prefixed by\r
+ * prefix in dst.
+ */\r
+void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information)\r
+{\r
+ struct version_information *v = (struct version_information*)version_information;\r
+ dst[0] = 0;\r
+ strncat(dst, prefix, len);\r
+ if(v->magic != VERSION_INFORMATION_MAGIC) {\r
+ strncat(dst, "Missing/Invalid version information", len);\r
+ return;\r
+ }\r
+ if(v->versionversion != 1) {\r
+ strncat(dst, "Version information not understood", len);\r
+ return;\r
+ }\r
+ if(!v->present) {\r
+ strncat(dst, "Version information not available", len);\r
+ return;\r
+ }\r
+ \r
+ strncat(dst, v->svnversion, len);\r
+ if(v->clean == 0) {\r
+ strncat(dst, "-unclean", len);\r
+ } else if(v->clean == 2) {\r
+ strncat(dst, "-suspect", len);\r
+ }\r
+ \r
+ strncat(dst, " ", len);\r
+ strncat(dst, v->buildtime, len);\r
+}\r
\r
# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code\r
ARMSRC = fromflash.c \r
-THUMBSRC = usb.c bootrom.c\r
+THUMBSRC = usb.c version.c bootrom.c\r
ASMSRC = ram-reset.s flash-reset.s\r
\r
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC\r
$(DELETE) $(OBJDIR)$(PATHSEP)*.s19\r
$(DELETE) $(OBJDIR)$(PATHSEP)*.map\r
$(DELETE) $(OBJDIR)$(PATHSEP)*.d\r
+ $(DELETE) version.c\r
\r
-.PHONY: all clean help\r
+.PHONY: all clean help \r
help:\r
@echo Multi-OS Makefile, you are running on $(DETECTED_OS)\r
@echo Possible targets:\r
#include <proxmark3.h>\r
\r
-void __attribute__((section("bootphase1"))) CopyBootToRAM(void)\r
+void __attribute__((section(".bootphase1"))) CopyBootToRAM(void)\r
{\r
int i;\r
\r
bootphase1 : {\r
*(.startup) \r
*(.bootphase1)\r
+ \r
+ /* It seems to be impossible to flush align a section at the\r
+ end of a memory segment. Instead, we'll put the version_information\r
+ wherever the linker wants it, and then put a pointer to the start\r
+ of the version information at the end of the section.\r
+ -- Henryk Plötz <henryk@ploetzli.ch> 2009-08-28 */\r
+ \r
+ _version_information_start = .;\r
+ *(.version_information);\r
+ \r
+ . = LENGTH(bootphase1) - 0x4; /* Skip ahead to the end */\r
+ LONG(_version_information_start)\r
} >bootphase1\r
\r
bootphase2 : {\r
# 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
# 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
--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))) \
--- /dev/null
+#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 */
+};
+++ /dev/null
-#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,
-};
// if data are available.\r
void UsbPacketReceived(BYTE *packet, int len);\r
\r
+#define VERSION_INFORMATION_MAGIC 0x56334d50\r
+struct version_information {\r
+ int magic; /* Magic sequence to identify this as a correct version information structure. Must be VERSION_INFORMATION_MAGIC */ \r
+ char versionversion; /* Must be 1 */\r
+ char present; /* 1 if the version information could be created at compile time, otherwise 0 and the remaining fields (except for magic) are empty */\r
+ char clean; /* 1: Tree was clean, no local changes. 0: Tree was unclean. 2: Couldn't be determined */\r
+ char svnversion[9]; /* String with the SVN revision */\r
+ char buildtime[30]; /* string with the build time */\r
+} __attribute__((packed));\r
+\r
#endif\r
--- /dev/null
+#!/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