On 07/04/2012 11:09 PM, Tormod Volden wrote:
Address argument is not required when dfu-suffix is used to delete or check
prefix. Deleting prefix needs to happen at the same time when DFU suffix is
removed.
I don't think that options can have optional argument when using
getopt(). I think the -s option will swallow whatever word comes next
whether it starts with a hyphen or not.

Yes you are correct. There is optional_argument option for getopt_long but that does not seem to work as I want it. And there seems to be a reason why it is implemented as it is. Anyhow I do not want to use it. So I added another option -t that requires no argument and is meant to use with deleting prefix (with -D). And option -s is for adding (-a).

Suggestions are very welcome how to handle this better.

To add DFU suffix and prefix use:
dfu-suffix -s 0x2000 -v 0x1cbe -p 0x00ff -d 0x0000 -a image.bin

To remove DFU suffix and prefix use:
dfu-suffix -s -D image.bin
Did you test this? So I would think -D will be interpreted as a
Stellaris address.

I guess I did not test this since it was not working.

diff --git a/src/lmdfu.c b/src/lmdfu.c
new file mode 100644
index 0000000..d7a5bb7
--- /dev/null
+++ b/src/lmdfu.c
@@ -0,0 +1,181 @@
+/* This implements the TI Stellaris DFU
+ * as per the Application Update Using the USB Device Firmware Upgrade Class
+ * (Document AN012373)
Maybe add the document link since it is difficult to find.
Added.
+ *
+ * (C) 2007-2008 by Harald Welte<lafo...@gnumonks.org>
Bad paste? I am not sure what Harald has to do with this code?
Not a bad paste. First patch had a lot copy-paste code from Harald. Not anymore so this is remove.

+
+/* dfu_prefix payload length excludes prefix and suffix */
+unsigned char dfu_prefix[] = {
Maybe call this lmdfu_dfu_prefix[] or lmdfu_prefix[] for consistency?
Done.

+ }
+
+ ret = ftruncate(fileno(file->filep), 0);
We guard this with #ifdef HAVE_FTRUNCATE in src/suffix.c, just in case
someone manage to compile it in some exotic environment.

Whole function implementation is now guarded.


+
+int lmdfu_check_prefix(struct dfu_file *file)
+{
+ unsigned char *data;
+ int ret;
+
+ data = malloc(sizeof(dfu_prefix));
+
+ ret = fread(data, 1, sizeof(dfu_prefix), file->filep);
+ if (ret<  sizeof(dfu_prefix)) {
+ fprintf(stderr, "Could not read prefix\n");
+ perror(file->name);
+ }
+
+ if ((data[0] != 0x01)&&  (data[1] != 0x00)) {
+ printf("Not valid TI Stellaris DFU prefix\n");
This will be printed out for all "normal" files, since this function
is unconditionally called from check_suffix, right? Would it be
possible to reserve this to the case -s is used? Or are there
advantages enough to always report on a missing TI prefix?
Good point. Don't see any reason to do this without -t or -s. Implementation changed.

diff --git a/src/suffix.c b/src/suffix.c
index fe19194..7b3f843 100644
--- a/src/suffix.c
+++ b/src/suffix.c
@@ -22,6 +22,7 @@
  #include<getopt.h>

  #include "dfu_file.h"
+#include "lmdfu.h"
  #ifdef HAVE_CONFIG_H
  #include "config.h"
  #endif
@@ -47,6 +48,7 @@ static void help(void)
   "  -d --did\tAdd device ID into DFU suffix in<file>\n"
   "  -c --check\tCheck DFU suffix of<file>\n"
   "  -a --add\tAdd DFU suffix to<file>\n"
+ "  -s --stellaris Add TI Stellaris prefic to<file>\n"
s/prefic/prefix

You do not mention the address argument here?
Fixed.

@@ -134,6 +132,8 @@ int main(int argc, char **argv)
   struct dfu_file file;
   int pid, vid, did;
   enum mode mode = MODE_NONE;
+ unsigned int prefix_address=0;
Maybe you should call this lmdfu_prefix_address? Or even lmdfu_start_address?
Changed to lmdfu_flash_address to implicate it is address in target flash memory.
[sorry, gmail ate all the tabs when I quoted the patch] After taking a look at the TI application note, I see TI offer a dfu-wrap command line utility. Is your dfu-suffix version pretty much equivalent to this? Then you might want to mention it somewhere to help people googling for alternatives. Oh, I just did ;) We can also add that to the dfu-util web page. Cheers, Tormod

Yes you can do pretty much the same with dfuwrap tool from StellarisWare.

Thank you for the comments. And here's new patch.

-Tommi

>From 8b49b3441de91c580d7c0326d1d4973fd280aa54 Mon Sep 17 00:00:00 2001
From: Tommi Keisala <tommi.keis...@ray.fi>
Date: Thu, 5 Jul 2012 08:34:29 +0300
Subject: [PATCH] add, remove and check TI Stellaris DFU prefix

Patch adds functionality to add, remove and check TI Stellaris DFU prefix with
dfu-suffix tool. TI Stellaris bootloader expects to have 8 byte prefix in the
beginning of binary image. Patch adds option -s --stellaris to dfu-suffix to
add that prefix (with -a).

When adding (-a) prefix (and suffix) option -s requires address as an argument.
To delete prefix use -D and -t option.
Deleting prefix needs to happen at the same time when DFU suffix is removed.

To add DFU suffix and prefix use:
dfu-suffix -s 0x2000 -v 0x1cbe -p 0x00ff -d 0x0000 -a image.bin

To remove DFU suffix and prefix use:
dfu-suffix -t -D image.bin

To check DFU suffix use:
dfu-suffix -t -c image.bin
---
 src/Makefile.am |    4 +-
 src/lmdfu.c     |  185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lmdfu.h     |   30 +++++++++
 src/suffix.c    |   42 ++++++++++---
 4 files changed, 253 insertions(+), 8 deletions(-)
 create mode 100644 src/lmdfu.c
 create mode 100644 src/lmdfu.h

diff --git a/src/Makefile.am b/src/Makefile.am
index df2ef36..99df307 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,4 +19,6 @@ dfu_util_SOURCES = main.c \
 
 dfu_suffix_SOURCES = suffix.c \
 		dfu_file.h \
-		dfu_file.c
+		dfu_file.c \
+		lmdfu.c \
+		lmdfu.h
diff --git a/src/lmdfu.c b/src/lmdfu.c
new file mode 100644
index 0000000..0989056
--- /dev/null
+++ b/src/lmdfu.c
@@ -0,0 +1,185 @@
+/* This implements the TI Stellaris DFU
+ * as per the Application Update Using the USB Device Firmware Upgrade Class
+ * (Document AN012373)
+ * http://www.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=spma003&fileType=pdf
+ *
+ * Copyright 2012 Tommi Keisala <tommi.keis...@ray.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "portable.h"
+#include "dfu.h"
+#include "dfu_file.h"
+#include "quirks.h"
+
+/* lmdfu_dfu_prefix payload length excludes prefix and suffix */
+unsigned char lmdfu_dfu_prefix[] = {
+	0x01,			/* STELLARIS_DFU_PROG */
+	0x00,			/* Reserved */
+	0x00,			/* LSB start address / 1024 */
+	0x20,			/* MSB start address / 1024 */
+	0x00,			/* LSB file payload length */
+	0x00,			/* Byte 2 file payload length */
+	0x00,			/* Byte 3 file payload length */
+	0x00,			/* MSB file payload length */
+};
+
+int lmdfu_add_prefix(struct dfu_file file, unsigned int address)
+{
+	int ret;
+	uint16_t addr;
+	uint32_t len;
+
+	unsigned char *data = NULL;
+
+	fseek(file.filep, 0, SEEK_END);
+	len = ftell(file.filep);
+	rewind(file.filep);
+
+	data = (unsigned char *)malloc(len);
+	if (!data) {
+		fprintf(stderr, "Unable to allocate buffer.\n");
+		exit(1);
+	}
+
+	ret = fread(data, 1, len, file.filep);
+	if (ret < 0) {
+		fprintf(stderr, "Could not read file\n");
+		perror(file.name);
+		free(data);
+		return ret;
+	} else if (ret < len) {
+		fprintf(stderr, "Could not read whole file\n");
+		free(data);
+		return -EIO;
+	}
+
+	/* fill Stellaris lmdfu_dfu_prefix with correct data */
+	addr = address / 1024;
+	lmdfu_dfu_prefix[2] = (unsigned char)addr & 0xff;
+	lmdfu_dfu_prefix[3] = (unsigned char)addr >> 8;
+	lmdfu_dfu_prefix[4] = (unsigned char)len & 0xff;
+	lmdfu_dfu_prefix[5] = (unsigned char)(len >> 8) & 0xff;
+	lmdfu_dfu_prefix[6] = (unsigned char)(len >> 16) & 0xff;
+	lmdfu_dfu_prefix[7] = (unsigned char)(len) >> 24;
+
+	rewind(file.filep);
+	ret = fwrite(lmdfu_dfu_prefix, 1, sizeof(lmdfu_dfu_prefix), file.filep);
+	if (ret < 0) {
+		fprintf(stderr, "Could not write TI Stellaris DFU prefix\n");
+		perror(file.name);
+	} else if (ret < sizeof(lmdfu_dfu_prefix)) {
+		fprintf(stderr, "Could not write while file\n");
+		ret = -EIO;
+	}
+
+	ret = fwrite(data, 1, len, file.filep);
+	if (ret < 0) {
+		fprintf(stderr, "Could not write data after TI Stellaris DFU "
+			"prefix\n");
+		perror(file.name);
+	} else if (ret < sizeof(lmdfu_dfu_prefix)) {
+		fprintf(stderr, "Could not write whole file\n");
+		ret = -EIO;
+	}
+
+	rewind(file.filep);
+	printf("TI Stellaris DFU prefix added.\n");
+	return 0;
+}
+
+int lmdfu_remove_prefix(struct dfu_file *file)
+{
+	long len;
+	unsigned char *data;
+	int ret;
+
+#ifdef HAVE_FTRUNCATE
+	printf("Remove TI Stellaris prefix\n");
+
+	fseek(file->filep, 0, SEEK_END);
+	len = ftell(file->filep);
+	rewind(file->filep);
+
+	data = (unsigned char *)malloc(len);
+	if (!data) {
+		fprintf(stderr, "Unable to allocate buffer.\n");
+		exit(1);
+	}
+
+	ret = fread(data, 1, len, file->filep);
+	if (ret < 0) {
+		fprintf(stderr, "Could not read file\n");
+		perror(file->name);
+		free(data);
+		return ret;
+	} else if (ret < len) {
+		fprintf(stderr, "Could not read whole file\n");
+		free(data);
+		return -EIO;
+	}
+
+	ret = ftruncate(fileno(file->filep), 0);
+	if (ret < 0) {
+		fprintf(stderr, "Error truncating\n");
+	}
+	rewind(file->filep);
+
+	fwrite(data + sizeof(lmdfu_dfu_prefix), 1, len - sizeof(lmdfu_dfu_prefix),
+	       file->filep);
+
+	printf("TI Stellaris prefix removed\n");
+#else
+	printf("Prefix removal not implemented on this platform\n");
+#endif /* HAVE_FTRUNCATE */
+
+	return ret;
+}
+
+int lmdfu_check_prefix(struct dfu_file *file)
+{
+	unsigned char *data;
+	int ret;
+
+	data = malloc(sizeof(lmdfu_dfu_prefix));
+
+	ret = fread(data, 1, sizeof(lmdfu_dfu_prefix), file->filep);
+	if (ret < sizeof(lmdfu_dfu_prefix)) {
+		fprintf(stderr, "Could not read prefix\n");
+		perror(file->name);
+	}
+
+	if ((data[0] != 0x01) && (data[1] != 0x00)) {
+		printf("Not valid TI Stellaris DFU prefix\n");
+		ret = 0;
+		goto out_rewind;
+	} else {
+		printf
+		    ("Possible TI Stellaris DFU prefix with the following properties\n");
+		printf("Address:        0x%08x\n",
+		       1024 * (data[3] << 8 | data[2]));
+		printf("Payload length: %d\n",
+		       data[4] | data[5] << 8 | data[6] << 16 | data[7] << 14);
+	}
+
+out_rewind:
+	rewind(file->filep);
+	return ret;
+}
diff --git a/src/lmdfu.h b/src/lmdfu.h
new file mode 100644
index 0000000..8af689f
--- /dev/null
+++ b/src/lmdfu.h
@@ -0,0 +1,30 @@
+
+/* This implements the TI Stellaris DFU
+ * as per the Application Update Using the USB Device Firmware Upgrade Class
+ * (Document AN012373)
+ *
+ * Copyright 2012 Tommi Keisala <tommi.keis...@ray.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LMDFU_H
+#define LMDFU_H
+
+int lmdfu_add_prefix(struct dfu_file file, unsigned int address);
+int lmdfu_remove_prefix(struct dfu_file *file);
+int lmdfu_check_prefix(struct dfu_file *file);
+
+#endif /* LMDFU_H */
diff --git a/src/suffix.c b/src/suffix.c
index fe19194..30ca3f5 100644
--- a/src/suffix.c
+++ b/src/suffix.c
@@ -20,8 +20,10 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <getopt.h>
+#include <string.h>
 
 #include "dfu_file.h"
+#include "lmdfu.h"
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -47,6 +49,8 @@ static void help(void)
 		"  -d --did\tAdd device ID into DFU suffix in <file>\n"
 		"  -c --check\tCheck DFU suffix of <file>\n"
 		"  -a --add\tAdd DFU suffix to <file>\n"
+		"  -s address\tAdd TI Stellaris prefix address to <file>\n"
+		"  -t\t\tDelete TI Stellaris prefix from <file>\n"
 		);
 }
 
@@ -67,6 +71,8 @@ static struct option opts[] = {
 	{ "did", 1, 0, 'd' },
 	{ "check", 1, 0, 'c' },
 	{ "add", 1, 0, 'a' },
+	{ "stellaris-add", 1, 0, 's' },
+	{ "stellaris-del", 0, 0, 't' },
 };
 
 static int check_suffix(struct dfu_file *file) {
@@ -111,12 +117,6 @@ static void remove_suffix(struct dfu_file *file)
 static void add_suffix(struct dfu_file *file, int pid, int vid, int did) {
 	int ret;
 
-	ret = check_suffix(file);
-	if (ret > 0) {
-		printf("Please remove existing DFU suffix before adding a new one.\n");
-		exit(1);
-	}
-
 	file->idProduct = pid;
 	file->idVendor = vid;
 	file->bcdDevice = did;
@@ -134,6 +134,8 @@ int main(int argc, char **argv)
 	struct dfu_file file;
 	int pid, vid, did;
 	enum mode mode = MODE_NONE;
+	unsigned int lmdfu_flash_address=0;
+	int lmdfu_prefix=0;
 
 	print_version();
 
@@ -142,7 +144,7 @@ int main(int argc, char **argv)
 
 	while (1) {
 		int c, option_index = 0;
-		c = getopt_long(argc, argv, "hVD:p:v:d:c:a:", opts,
+		c = getopt_long(argc, argv, "hVD:p:v:d:c:a:s:t", opts,
 				&option_index);
 		if (c == -1)
 			break;
@@ -176,6 +178,13 @@ int main(int argc, char **argv)
 			file.name = optarg;
 			mode = MODE_ADD;
 			break;
+		case 's':
+			lmdfu_flash_address = strtoul(optarg, NULL, 16);
+			lmdfu_prefix = 1;
+			break;
+		case 't':
+			lmdfu_prefix = 1;
+			break;
 		default:
 			help();
 			exit(2);
@@ -198,14 +207,33 @@ int main(int argc, char **argv)
 
 	switch(mode) {
 	case MODE_ADD:
+		if (check_suffix(&file)) {
+			if(lmdfu_prefix) lmdfu_check_prefix(&file);
+			printf("Please remove existing DFU suffix before adding a new one.\n");
+			exit(1);
+		}
+		if(lmdfu_prefix) {
+			if(lmdfu_check_prefix(&file)) {
+				fprintf(stderr, "Adding new anyway\n");
+			}
+			if(lmdfu_flash_address)
+				lmdfu_add_prefix(file, lmdfu_flash_address);
+			else {
+				fprintf(stderr, "Not valid address for TI Stellaris prefix\n");
+				exit(2);
+			}
+		}
 		add_suffix(&file, pid, vid, did);
 		break;
 	case MODE_CHECK:
 		/* FIXME: could open read-only here */
 		check_suffix(&file);
+		if(lmdfu_prefix) lmdfu_check_prefix(&file);
 		break;
 	case MODE_DEL:
 		remove_suffix(&file);
+		if(lmdfu_prefix)
+			lmdfu_remove_prefix(&file);
 		break;
 	default:
 		help();
-- 
1.7.10

_______________________________________________
devel mailing list
devel@lists.openmoko.org
https://lists.openmoko.org/mailman/listinfo/devel

Reply via email to