diff options
Diffstat (limited to 'ao-tools')
| -rw-r--r-- | ao-tools/Makefile.am | 2 | ||||
| -rw-r--r-- | ao-tools/ao-chaosread/.gitignore | 1 | ||||
| -rw-r--r-- | ao-tools/ao-chaosread/Makefile.am | 9 | ||||
| -rw-r--r-- | ao-tools/ao-chaosread/ao-chaosread.1 | 36 | ||||
| -rw-r--r-- | ao-tools/ao-chaosread/ao-chaosread.c | 272 | ||||
| -rw-r--r-- | ao-tools/ao-dump-up/ao-dump-up.c | 14 | ||||
| -rw-r--r-- | ao-tools/ao-makebin/Makefile.am | 12 | ||||
| -rw-r--r-- | ao-tools/ao-makebin/ao-makebin.1 | 47 | ||||
| -rw-r--r-- | ao-tools/ao-makebin/ao-makebin.c | 172 | ||||
| -rw-r--r-- | ao-tools/lib/Makefile.am | 2 | ||||
| -rw-r--r-- | ao-tools/lib/ao-dfu.c | 202 | ||||
| -rw-r--r-- | ao-tools/lib/ao-dfu.h | 35 | ||||
| -rw-r--r-- | ao-tools/lib/ao-elf.c | 6 | ||||
| -rw-r--r-- | ao-tools/lib/ao-hex.c | 33 | ||||
| -rw-r--r-- | ao-tools/lib/ao-hex.h | 3 | 
15 files changed, 824 insertions, 22 deletions
diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 66d2560e..fb554857 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -3,7 +3,7 @@ SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \  	ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \  	ao-flash ao-usbload ao-test-igniter ao-test-baro \  	ao-test-flash ao-cal-accel ao-test-gps ao-usbtrng \ -	ao-cal-freq +	ao-cal-freq ao-chaosread ao-makebin  if LIBSTLINK  SUBDIRS += ao-stmload  endif diff --git a/ao-tools/ao-chaosread/.gitignore b/ao-tools/ao-chaosread/.gitignore new file mode 100644 index 00000000..b9443879 --- /dev/null +++ b/ao-tools/ao-chaosread/.gitignore @@ -0,0 +1 @@ +ao-chaosread diff --git a/ao-tools/ao-chaosread/Makefile.am b/ao-tools/ao-chaosread/Makefile.am new file mode 100644 index 00000000..581eb2d2 --- /dev/null +++ b/ao-tools/ao-chaosread/Makefile.am @@ -0,0 +1,9 @@ +bin_PROGRAMS=ao-chaosread + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) + +ao_chaosread_LDADD=$(LIBUSB_LIBS) + +ao_chaosread_SOURCES = ao-chaosread.c + +man_MANS = ao-chaosread.1 diff --git a/ao-tools/ao-chaosread/ao-chaosread.1 b/ao-tools/ao-chaosread/ao-chaosread.1 new file mode 100644 index 00000000..d8ed6cb3 --- /dev/null +++ b/ao-tools/ao-chaosread/ao-chaosread.1 @@ -0,0 +1,36 @@ +.\" +.\" Copyright © 2016 Keith Packard <keithp@keithp.com> +.\" +.\" 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. +.\" +.\" +.TH AO-LOAD 1 "ao-chaosread" "" +.SH NAME +ao-chaosread \- read raw noise source from chaoskey +.SH SYNOPSIS +.B "ao-chaosread" +.SH DESCRIPTION +.I ao-chaosread +reads ADC values from the noise source on the attached ChaosKey device. +.SH OPTIONS +.TP +\-s serial | --serial serial +This selects a ChaosKey by serial number instead of using the first +one found. +.SH USAGE +.I ao-chaosread +reads noise data. +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-chaosread/ao-chaosread.c b/ao-tools/ao-chaosread/ao-chaosread.c new file mode 100644 index 00000000..806c2ef9 --- /dev/null +++ b/ao-tools/ao-chaosread/ao-chaosread.c @@ -0,0 +1,272 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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; version 2 of the License. + * + * 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 <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <libusb.h> +#include <getopt.h> +#include <string.h> +#include <strings.h> + +#define CHAOS_SIZE	64 + +#define CHAOS_VENDOR	0x1d50 +#define CHAOS_PRODUCT	0x60c6 + +struct chaoskey { +	libusb_context		*ctx; +	libusb_device_handle	*handle; +	int			kernel_active; +}; + +libusb_device_handle * +chaoskey_match(libusb_device *dev, char *match_serial) +{ +	struct libusb_device_descriptor desc; +	int ret; +	int match_len; +	char *device_serial = NULL; +	libusb_device_handle *handle = NULL; + +	ret = libusb_get_device_descriptor(dev, &desc); +	if (ret < 0) { +		fprintf(stderr, "failed to get device descriptor: %s\n", libusb_strerror(ret)); +		return 0; +	} + +	if (desc.idVendor != CHAOS_VENDOR) +		return NULL; +	if (desc.idProduct != CHAOS_PRODUCT) +		return NULL; + +	ret = libusb_open(dev, &handle); + +	if (match_serial == NULL) +		return handle; + +	if (ret < 0) { +		fprintf(stderr, "failed to open device: %s\n", libusb_strerror(ret)); +		return NULL; +	} + +	match_len = strlen(match_serial); +	device_serial = malloc(match_len + 2); + +	if (!device_serial) { +		fprintf(stderr, "malloc failed\n"); +		goto out; +	} + +	ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, device_serial, match_len + 1); + +	if (ret < 0) { +		fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret)); +		goto out; +	} + +	device_serial[ret] = '\0'; + +	ret = strcmp(device_serial, match_serial); +	free(device_serial); +	if (ret) +		goto out; + +	return handle; + +out: +	free(device_serial); +	if (handle) +		libusb_close(handle); +	return 0; +} + +struct chaoskey * +chaoskey_open(char *serial) +{ +	struct chaoskey	*ck; +	int		ret; +	ssize_t		num; +	libusb_device	**list; +	libusb_device	*device = NULL; +	int		d; + +	ck = calloc(sizeof (struct chaoskey), 1); +	if (!ck) +		goto out; +	ret = libusb_init(&ck->ctx); +	if (ret ) { +		fprintf(stderr, "libusb_init failed: %s\n", libusb_strerror(ret)); +		goto out; +	} + +	num = libusb_get_device_list(ck->ctx, &list); +	if (num < 0) { +		fprintf(stderr, "libusb_get_device_list failed: %s\n", libusb_strerror(num)); +		goto out; +	} + +	for (d = 0; d < num; d++) { +		libusb_device_handle *handle; + +		handle = chaoskey_match(list[d], serial); +		if (handle) { +			ck->handle = handle; +			break; +		} +	} + +	libusb_free_device_list(list, 1); + +	if (!ck->handle) { +		if (serial) +			fprintf (stderr, "No chaoskey matching %s\n", serial); +		else +			fprintf (stderr, "No chaoskey\n"); +		goto out; +	} + +	ck->kernel_active = libusb_kernel_driver_active(ck->handle, 0); +	if (ck->kernel_active) { +		ret = libusb_detach_kernel_driver(ck->handle, 0); +		if (ret) +			goto out; +	} + +	ret = libusb_claim_interface(ck->handle, 0); +	if (ret) +		goto out; + +	return ck; +out: +	if (ck->kernel_active) +		libusb_attach_kernel_driver(ck->handle, 0); +	if (ck->ctx) +		libusb_exit(ck->ctx); +	free(ck); +	return NULL; +} + +void +chaoskey_close(struct chaoskey *ck) +{ +	libusb_release_interface(ck->handle, 0); +	if (ck->kernel_active) +		libusb_attach_kernel_driver(ck->handle, 0); +	libusb_close(ck->handle); +	libusb_exit(ck->ctx); +	free(ck); +} + +void +chaoskey_transfer_callback(struct libusb_transfer *transfer) +{ +	struct chaoskey *ck = transfer->user_data; +} + +#define ENDPOINT	0x86 + +int +chaoskey_read(struct chaoskey *ck, uint8_t *buffer, int len) +{ +	int	total = 0; + +	while (len) { +		int	ret; +		int	transferred; + +		ret = libusb_bulk_transfer(ck->handle, ENDPOINT, buffer, len, &transferred, 10000); +		if (ret) { +			if (total) +				return total; +			else { +				errno = EIO; +				return -1; +			} +		} +		len -= transferred; +		buffer += transferred; +	} +} + +static const struct option options[] = { +	{ .name = "serial", .has_arg = 1, .val = 's' }, +	{ .name = "length", .has_arg = 1, .val = 'l' }, +	{ 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ +	fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]]\n", program); +	exit(1); +} + +int +main (int argc, char **argv) +{ +	struct chaoskey	*ck; +	char	buf[1024]; +	int	got; +	int	c; +	char	*serial = NULL; +	char	*length_string; +	char	*length_end; +	unsigned long	length = sizeof(buf); +	int		this_time; + +	while ((c = getopt_long(argc, argv, "s:l:", options, NULL)) != -1) { +		switch (c) { +		case 's': +			serial = optarg; +			break; +		case 'l': +			length_string = optarg; +			length = strtoul(length_string, &length_end, 10); +			if (!strcasecmp(length_end, "k")) +				length *= 1024; +			else if (!strcasecmp(length_end, "m")) +				length *= 1024 * 1024; +			else if (!strcasecmp(length_end, "g")) +				length *= 1024 * 1024 * 1024; +			else if (strlen(length_end)) +				 usage(argv[0]); +			break; +		default: +			usage(argv[0]); +			break; +		} +	} + +	ck = chaoskey_open(serial); +	if (!ck) +		exit(1); + +	while (length) { +		this_time = sizeof(buf); +		if (length < sizeof(buf)) +			this_time = (int) length; +		got = chaoskey_read(ck, buf, this_time); +		if (got < 0) { +			perror("read"); +			exit(1); +		} +		write(1, buf, got); +		length -= got; +	} +	exit(0); +} diff --git a/ao-tools/ao-dump-up/ao-dump-up.c b/ao-tools/ao-dump-up/ao-dump-up.c index b1f85af6..df05088c 100644 --- a/ao-tools/ao-dump-up/ao-dump-up.c +++ b/ao-tools/ao-dump-up/ao-dump-up.c @@ -140,20 +140,6 @@ static int find_header(struct cc_usb *cc)  	}  } -static const char *state_names[] = { -	"startup", -	"idle", -	"pad", -	"boost", -	"fast", -	"coast", -	"drogue", -	"main", -	"landed", -	"invalid" -}; - -  int  main (int argc, char **argv)  { diff --git a/ao-tools/ao-makebin/Makefile.am b/ao-tools/ao-makebin/Makefile.am new file mode 100644 index 00000000..758097a4 --- /dev/null +++ b/ao-tools/ao-makebin/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-makebin + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) +AO_ELFTOHEX_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_makebin_DEPENDENCIES = $(AO_ELFTOHEX_LIBS) + +ao_makebin_LDADD=$(AO_ELFTOHEX_LIBS) -lelf + +ao_makebin_SOURCES=ao-makebin.c + +man_MANS = ao-makebin.1 diff --git a/ao-tools/ao-makebin/ao-makebin.1 b/ao-tools/ao-makebin/ao-makebin.1 new file mode 100644 index 00000000..e19ec2cc --- /dev/null +++ b/ao-tools/ao-makebin/ao-makebin.1 @@ -0,0 +1,47 @@ +.\" +.\" Copyright © 2013 Keith Packard <keithp@keithp.com> +.\" +.\" 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. +.\" +.\" +.TH AO-LOAD 1 "ao-makebin" "" +.SH NAME +ao-makebin \- construct raw binary file or DFU image from collection of ELF files +.SH SYNOPSIS +.B "ao-makebin" +[\--base=\fIbase-address\fP] +[\--output=\fIoutput.bin\fP] +[\--dfu] +[\--verbose] +\fIinput.elf ...\fP +.SH DESCRIPTION +.I ao-makebin +reads the specified .elf files and writes out a raw binary flash image +.SH OPTIONS +.TP +\--base=\fIbase-address\fP +This specifies the target address for the first byte of the file (default is 0) +.TP +\--output=\fIoutput.bin\fP +This specifies the output file (default is stdout) +.TP +\--dfu +Creates a DFU file (as documented by ST's UM0391 user manual) instead +of a raw binary file. +.TP +\--verbose +Dumps some debug information. +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-makebin/ao-makebin.c b/ao-tools/ao-makebin/ao-makebin.c new file mode 100644 index 00000000..31ce1889 --- /dev/null +++ b/ao-tools/ao-makebin/ao-makebin.c @@ -0,0 +1,172 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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; version 2 of the License. + * + * 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 <getopt.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include "ao-hex.h" +#include "ao-elf.h" +#include "ao-dfu.h" + +static const struct option options[] = { +	{ .name = "verbose", .has_arg = 0, .val = 'v' }, +	{ .name = "output", .has_arg = 1, .val = 'o' }, +	{ .name = "base", .has_arg = 1, .val = 'b' }, +	{ .name = "align", .has_arg = 1, .val = 'a' }, +	{ .name = "dfu", .has_arg = 0, .val = 'd' }, +	{ 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ +	fprintf(stderr, "usage: %s [--verbose=<level>] [--output=<output.bin>] [--base=<base-address>] [--align=<align>] [--dfu] <input.elf> ...\n", program); +	exit(1); +} + +static int +ends_with(char *whole, char *suffix) +{ +	int whole_len = strlen(whole); +	int suffix_len = strlen(suffix); + +	if (suffix_len > whole_len) +		return 0; +	return strcmp(whole + whole_len - suffix_len, suffix) == 0; +} + +static struct ao_dfu_info dfu_info = { +	.bcdDevice = 0x0000, +	.idProduct = 0xdf11, +	.idVendor = 0x0483, +}; + +int +main (int argc, char **argv) +{ +	char			*output = NULL; +	struct ao_hex_image	*image = NULL; +	struct ao_sym		*file_symbols; +	int			num_file_symbols; +	FILE			*file; +	int			c; +	uint32_t		base = 0xffffffff; +	uint32_t		align = 0; +	uint32_t		length; +	int			verbose = 0; +	int			dfu = 0; + +	while ((c = getopt_long(argc, argv, "dvo:b:a:", options, NULL)) != -1) { +		switch (c) { +		case 'o': +			output = optarg; +			break; +		case 'v': +			verbose++; +			break; +		case 'b': +			base = strtoul(optarg, NULL, 0); +			break; +		case 'a': +			align = strtoul(optarg, NULL, 0); +			break; +		case 'd': +			dfu = 1; +			break; +		default: +			usage(argv[0]); +			break; +		} +	} + +	while (argv[optind]) { +		char			*input = argv[optind]; +		struct ao_hex_image	*tmp; + +		if (ends_with (input, ".ihx")) +			tmp = ao_hex_load(input, &file_symbols, &num_file_symbols); +		else +			tmp = ao_load_elf(input, &file_symbols, &num_file_symbols); + +		if (!tmp) +			usage(argv[0]); + +		if (verbose) +			fprintf(stderr, "%s: 0x%x %d\n", input, tmp->address, tmp->length); + +		if (image) { +			image = ao_hex_image_cat(image, tmp); +			if (!image) +				usage(argv[0]); +		} else +			image = tmp; +		optind++; +	} + +	if (base != 0xffffffff && base > image->address) { +		fprintf(stderr, "requested base 0x%x is after image address 0x%x\n", +			base, image->address); +		usage(argv[0]); +	} + +	if (verbose) +		fprintf(stderr, "%s: base 0x%x length %d\n", output ? output : "<stdout>", image->address, image->length); + +	if (!output) +		file = stdout; +	else { +		file = fopen(output, "w"); +		if (!file) { +			perror(output); +			exit(1); +		} +	} + +	if (dfu) { +		if (!ao_dfu_write(file, &dfu_info, 1, image)) { +			fprintf(stderr, "%s: dfu_write failed: %s\n", output, strerror(errno)); +			if (output) +				unlink(output); +			exit(1); +		} +	} else { +		while (base < image->address) { +			fputc(0xff, file); +			base++; +		} + +		if (fwrite(image->data, 1, image->length, file) != image->length) { +			fprintf(stderr, "%s: failed to write bin file\n", output ? output : "<stdout>"); +			if (output) +				unlink(output); +			exit(1); +		} + +		if (align) { +			length = image->length; + +			while (length % align) { +				fputc(0xff, file); +				length++; +			} +		} +		fflush(file); +	} + +	exit(0); +} diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index a03a976c..a33d682d 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -46,6 +46,8 @@ libao_tools_a_SOURCES = \  	ao-editaltos.h \  	ao-elf.c \  	ao-elf.h \ +	ao-dfu.c \ +	ao-dfu.h \  	ao-selfload.c \  	ao-selfload.h \  	ao-verbose.c \ diff --git a/ao-tools/lib/ao-dfu.c b/ao-tools/lib/ao-dfu.c new file mode 100644 index 00000000..b6778495 --- /dev/null +++ b/ao-tools/lib/ao-dfu.c @@ -0,0 +1,202 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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; version 2 of the License. + * + * 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 <stdarg.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> +#include <errno.h> +#include "ao-hex.h" +#include "ao-dfu.h" + +static uint32_t	dfu_crc; +static FILE	*dfu_file; +static int	dfu_failed; +static int	dfu_error; + +static uint32_t update_crc(uint32_t crc, uint8_t byte) +{ +	int j; +	uint32_t mask; + +	crc = crc ^ byte; +	for (j = 0; j < 8; j++) { +		mask = -(crc & 1); +		crc = (crc >> 1) ^ (0xEDB88320 & mask); +	} +	return crc; +} + +static void dfu_init(FILE *file) +{ +	dfu_crc = 0xffffffff; +	dfu_file = file; +	dfu_failed = 0; +	dfu_error = 0; +} + +static int dfu_fini(void) +{ +	if (fflush(dfu_file) == EOF) { +		if (!dfu_failed) { +			dfu_failed = 1; +			dfu_error = errno; +		} +	} +	if (dfu_failed) +		errno = dfu_error; +	return !dfu_failed; +} + +static void dfu_8(uint8_t byte) { +	if (putc(byte, dfu_file) == EOF) { +		if (!dfu_failed) { +			dfu_failed = 1; +			dfu_error = errno; +		} +	} +	dfu_crc = update_crc(dfu_crc, byte); +} + +static void dfu_pad(int len) { +	while (len--) +		dfu_8(0); +} + +static void dfu_string(char *string) { +	char	c; + +	while ((c = *string++)) +		dfu_8((uint8_t) c); +} + +static void dfu_string_pad(char *string, int len) { +	char	c; + +	while ((c = *string++)) { +		dfu_8((uint8_t) c); +		len--; +	} +	dfu_pad(len); +} + +static void dfu_block(uint8_t *bytes, int len) { +	while (len--) +		dfu_8(*bytes++); +} + +static void dfu_lsb16(uint16_t value) { +	dfu_8(value); +	dfu_8(value>>8); +} + +static void dfu_lsb32(uint32_t value) { +	dfu_8(value); +	dfu_8(value >> 8); +	dfu_8(value >> 16); +	dfu_8(value >> 24); +} + +static uint32_t dfu_image_size(struct ao_hex_image *image) { +	return 8 + image->length; +} + +static uint32_t dfu_images_size(int num_image, struct ao_hex_image images[]) +{ +	uint32_t	size = 0; +	int		i; + +	for (i = 0; i < num_image; i++) +		size += dfu_image_size(&images[i]); +	return size; +} + +static void dfu_image(struct ao_hex_image *image) +{ +	dfu_lsb32(image->address); +	dfu_lsb32(image->length); +	dfu_block(image->data, image->length); +} + +static void dfu_target(char *name, int num_image, struct ao_hex_image images[]) +{ +	uint32_t	images_size = dfu_images_size(num_image, images); +	int		i; + +	dfu_string("Target"); +	dfu_8(0); +	if (name) { +		dfu_8(1); +		dfu_pad(3); +		dfu_string_pad(name, 255); +	} else { +		dfu_8(0); +		dfu_pad(3); +		dfu_pad(255); +	} +	dfu_lsb32(images_size); +	dfu_lsb32(num_image); +	for (i = 0; i < num_image; i++) +		dfu_image(&images[i]); +} + +static uint32_t dfu_target_size(int num_image, struct ao_hex_image images[]) +{ +	return 274 + dfu_images_size(num_image, images); +} + +static uint32_t +dfu_size(int num_image, struct ao_hex_image images[]) +{ +	uint32_t	size = 0; +	size += 11;	/* DFU Prefix */ + +	size += dfu_target_size(num_image, images); + +	return size; +} + +int +ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[]) +{ +	uint32_t	total_size; + +	total_size = dfu_size(num_image, images); + +	dfu_init(file); +	/* DFU Prefix */ +	dfu_string(DFU_SIGNATURE); +	dfu_8(0x01); +	dfu_lsb32(total_size); +	dfu_8(0x01); + +	dfu_target("ST...", num_image, images); + +	/* DFU Suffix */ +	dfu_lsb16(info->bcdDevice); +	dfu_lsb16(info->idProduct); +	dfu_lsb16(info->idVendor); +	dfu_lsb16(DFU_SPEC_VERSION); +	dfu_string("UFD"); +	dfu_8(16); +	dfu_lsb32(dfu_crc); +	return dfu_fini(); +} + diff --git a/ao-tools/lib/ao-dfu.h b/ao-tools/lib/ao-dfu.h new file mode 100644 index 00000000..c3dfc496 --- /dev/null +++ b/ao-tools/lib/ao-dfu.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2016 Keith Packard <keithp@keithp.com> + * + * 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; version 2 of the License. + * + * 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 _AO_DFU_H_ +#define _AO_DFU_H_ + +struct ao_dfu_info { +	uint16_t	bcdDevice; +	uint16_t	idProduct; +	uint16_t	idVendor; +}; + +#define DFU_SIGNATURE		"DfuSe" +#define DFU_SPEC_VERSION	0x011a + +#define DFU_TARGET_SIGNATURE	"Target" + +int +ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[]); + +#endif /* _AO_DFU_H_ */ diff --git a/ao-tools/lib/ao-elf.c b/ao-tools/lib/ao-elf.c index 99b37210..680a80f0 100644 --- a/ao-tools/lib/ao-elf.c +++ b/ao-tools/lib/ao-elf.c @@ -206,7 +206,7 @@ get_load(Elf *e)  #endif  	size_t		nshdr;  	size_t		s; -	 +  	if (elf_getshdrstrndx(e, &shstrndx) < 0)  		return 0; @@ -238,7 +238,7 @@ get_load(Elf *e)  			 (uint32_t) phdr.p_filesz,  			 (uint32_t) phdr.p_memsz);  #endif -		 +  		for (s = 0; s < nshdr; s++) {  			scn = elf_getscn(e, s); @@ -256,7 +256,7 @@ get_load(Elf *e)  #endif  			if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) { -					 +  				if (shdr.sh_size == 0)  					continue; diff --git a/ao-tools/lib/ao-hex.c b/ao-tools/lib/ao-hex.c index 5cfc63c1..2ceed7ab 100644 --- a/ao-tools/lib/ao-hex.c +++ b/ao-tools/lib/ao-hex.c @@ -294,7 +294,7 @@ load_symbols(struct ao_hex_file *hex,  	struct ao_sym		*symbol;  	int			num_symbols = 0;  	int			size_symbols = 0; -	 +  	extended_addr = 0;  	for (i = 0; i < hex->nrecord; i++) {  		record = hex->records[i]; @@ -451,6 +451,31 @@ ao_hex_image_free(struct ao_hex_image *image)  	free(image);  } +uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; } +uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; } + +struct ao_hex_image * +ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b) +{ +	struct ao_hex_image	*n; +	uint32_t		base, bound; +	uint32_t		length; + +	base = min(a->address, b->address); +	bound = max(a->address + a->length, b->address + b->length); +	length = bound - base; + +	n = calloc (sizeof (struct ao_hex_image) + length, 1); +	if (!n) +		return NULL; +	n->address = base; +	n->length = length; +	memset(n->data, 0xff, length); +	memcpy(n->data + a->address - n->address, a->data, a->length); +	memcpy(n->data + b->address - n->address, b->data, b->length); +	return n; +} +  int  ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b)  { @@ -471,7 +496,7 @@ ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbolsp)  	file = fopen (filename, "r");  	if (!file)  		return NULL; -	 +  	hex_file = ao_hex_file_read(file, filename);  	fclose(file);  	if (!hex_file) @@ -549,7 +574,7 @@ ao_hex_file_create(struct ao_hex_image *image, struct ao_sym *symbols, int num_s  	ao_hex_record_set_checksum(record);  	hex_file->records[nrecord++] = record; -	 +  	/* Add the symbols  	 */ @@ -616,7 +641,7 @@ ao_hex_save(FILE *file, struct ao_hex_image *image,  			goto write_failed;  	}  	ret = true; -	 +  	if (fflush(file) != 0)  		ret = false;  write_failed: diff --git a/ao-tools/lib/ao-hex.h b/ao-tools/lib/ao-hex.h index eb510ba2..a1ab490c 100644 --- a/ao-tools/lib/ao-hex.h +++ b/ao-tools/lib/ao-hex.h @@ -71,6 +71,9 @@ ao_hex_image_free(struct ao_hex_image *image);  struct ao_hex_image *  ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols); +struct ao_hex_image * +ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b); +  int  ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b);  | 
