[dfu-util] TI Stellaris prefix support for dfu-suffix
Tormod Volden
lists.tormod at gmail.com
Wed Jul 4 22:09:36 CEST 2012
On Tue, Jul 3, 2012 at 6:56 AM, Tommi Keisala wrote:
> Hi,
>
> After discussion over the weekend I brewed another patch that obsoletes the
> old one.
> So here's a new patch that adds TI Stellaris bootloader DFU prefix support
> for dfu-suffix tool.
> After binary image is prefixed (and suffixed) it can be flashed with stock
> dfu-util.
>
> So comments and suggestions are welcome.
Great! I like this approach better. Thanks a lot for the rework. The
patch looks very clean and nice, just a few comments, nitpicks and
bikeshedding from me:
>> From 99e1f89efe677897ade62d70a3f05e7c26c9f125 Mon Sep 17 00:00:00 2001
>> From: Tommi Keisala <tommi.keisala at ray.fi>
>> Date: Tue, 3 Jul 2012 07:47:09 +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
>> generate that prefix.
>>
>> When adding prefix (and suffix) option -s requires address as and argument.
s/and/an
>> 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.
>>
>> 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.
>>
>> To check DFU suffix use:
>> dfu-suffix -c image.bin
>> ---
>> src/Makefile.am | 4 +-
>> src/lmdfu.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> src/lmdfu.h | 30 +++++++++
>> src/suffix.c | 35 ++++++++---
>> 4 files changed, 242 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..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.
>> + *
>> + * (C) 2007-2008 by Harald Welte <laforge at gnumonks.org>
Bad paste? I am not sure what Harald has to do with this code?
>> + * Copyright 2012 Tommi Keisala <tommi.keisala at 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"
>> +
>> +/* dfu_prefix payload length excludes prefix and suffix */
>> +unsigned char dfu_prefix[] = {
Maybe call this lmdfu_dfu_prefix[] or lmdfu_prefix[] for consistency?
>> + 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 dfu_prefix with correct data */
>> + addr = address / 1024;
>> + dfu_prefix[2] = (unsigned char)addr & 0xff;
>> + dfu_prefix[3] = (unsigned char)addr >> 8;
>> + dfu_prefix[4] = (unsigned char)len & 0xff;
>> + dfu_prefix[5] = (unsigned char)(len >> 8) & 0xff;
>> + dfu_prefix[6] = (unsigned char)(len >> 16) & 0xff;
>> + dfu_prefix[7] = (unsigned char)(len) >> 24;
>> +
>> + rewind(file.filep);
>> + ret = fwrite(dfu_prefix, 1, sizeof(dfu_prefix), file.filep);
>> + if (ret < 0) {
>> + fprintf(stderr, "Could not write TI Stellaris DFU prefix\n");
>> + perror(file.name);
>> + } else if (ret < sizeof(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(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;
>> +
>> + 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);
We guard this with #ifdef HAVE_FTRUNCATE in src/suffix.c, just in case
someone manage to compile it in some exotic environment.
>> + if (ret < 0) {
>> + fprintf(stderr, "Error truncating\n");
>> + }
>> + rewind(file->filep);
>> +
>> + fwrite(data + sizeof(dfu_prefix), 1, len - sizeof(dfu_prefix),
>> + file->filep);
>> +
>> + printf("TI Stellaris prefix removed\n");
>> +
>> + return ret;
>> +}
>> +
>> +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?
>> + 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.keisala at 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..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?
>> );
>> }
>>
>> @@ -67,6 +69,7 @@ static struct option opts[] = {
>> { "did", 1, 0, 'd' },
>> { "check", 1, 0, 'c' },
>> { "add", 1, 0, 'a' },
>> + { "stellaris", 1, 0, 's' },
>> };
>>
>> static int check_suffix(struct dfu_file *file) {
>> @@ -81,6 +84,7 @@ static int check_suffix(struct dfu_file *file) {
>> printf("BCD DFU:\t0x%04X\n", file->bcdDFU);
>> printf("Length:\t\t%i\n", file->suffixlen);
>> printf("CRC:\t\t0x%08X\n", file->dwCRC);
>> + lmdfu_check_prefix(file);
>> }
>>
>> return ret;
>> @@ -111,12 +115,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 +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?
>> + int lmdfu_prefix=0;
>>
>> print_version();
>>
>> @@ -142,7 +142,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:", opts,
>> &option_index);
>> if (c == -1)
>> break;
>> @@ -176,6 +176,10 @@ int main(int argc, char **argv)
>> file.name = optarg;
>> mode = MODE_ADD;
>> break;
>> + case 's':
>> + prefix_address = strtoul(optarg, NULL, 16);
>> + lmdfu_prefix = 1;
>> + break;
>> default:
>> help();
>> exit(2);
>> @@ -198,6 +202,21 @@ int main(int argc, char **argv)
>>
>> switch(mode) {
>> case MODE_ADD:
>> + if (check_suffix(&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(prefix_address)
>> + lmdfu_add_prefix(file, prefix_address);
>> + else {
>> + fprintf(stderr, "Not valid address for TI Stellaris prefix\n");
>> + exit(2);
>> + }
>> + }
>> add_suffix(&file, pid, vid, did);
>> break;
>> case MODE_CHECK:
>> @@ -206,6 +225,8 @@ int main(int argc, char **argv)
>> break;
>> case MODE_DEL:
>> remove_suffix(&file);
>> + if(lmdfu_prefix)
>> + lmdfu_remove_prefix(&file);
>> break;
>> default:
>> help();
>> --
>> 1.7.10
[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
More information about the devel
mailing list