diff options
| author | Keith Packard <keithp@keithp.com> | 2009-05-27 21:53:15 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2009-05-27 21:53:15 -0700 | 
| commit | 8a9a3f02b951382573ff74dd6ce5a1c0f335fa86 (patch) | |
| tree | ba5a54a3e61a026a7a585091562225e7153436b6 | |
| parent | 837c620f07b63efc171be3ac14c78bc99adf7592 (diff) | |
Add aoload to load serial-numbered altos binaries.
aoload is a custom version of ccload which edits the data before sending it
to the target machine, writing the target serial number into the data.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | aoload/Makefile.am | 10 | ||||
| -rw-r--r-- | aoload/aoload.c | 231 | ||||
| -rw-r--r-- | configure.ac | 1 | 
4 files changed, 243 insertions, 1 deletions
| diff --git a/Makefile.am b/Makefile.am index ee3d2924..86f2fad5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ccload s51 ccmanual ccdump +SUBDIRS=lib ccload s51 ccmanual ccdump aoload diff --git a/aoload/Makefile.am b/aoload/Makefile.am new file mode 100644 index 00000000..2e32c0b9 --- /dev/null +++ b/aoload/Makefile.am @@ -0,0 +1,10 @@ +bin_PROGRAMS=aoload + +AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS) +AOLOAD_LIBS=../lib/libcc.a + +aoload_DEPENDENCIES = $(AOLOAD_LIBS) + +aoload_LDADD=$(AOLOAD_LIBS) $(LIBUSB_LIBS) + +aoload_SOURCES = aoload.c diff --git a/aoload/aoload.c b/aoload/aoload.c new file mode 100644 index 00000000..a36ad375 --- /dev/null +++ b/aoload/aoload.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2008 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. + */ + +#include <stdlib.h> +#include <limits.h> +#include <stdint.h> +#include "ccdbg.h" + +#define AO_USB_DESC_STRING		3 + +void +usage(char *program) +{ +	fprintf(stderr, "usage: %s <filename.ihx> <serial>\n", program); +	exit(1); +} + +struct sym { +	unsigned	addr; +	char		*name; +} serial_symbols[] = { +	{ 0,	"_ao_serial_number" }, +#define AO_SERIAL_NUMBER	(serial_symbols[0].addr) +	{ 0,	"_ao_usb_descriptors" }, +#define AO_USB_DESCRIPTORS	(serial_symbols[1].addr) +}; + +#define NUM_SERIAL_SYMBOLS	(sizeof(serial_symbols)/sizeof(serial_symbols[0])) + +static int +find_symbols(FILE *map) +{ +	char	line[2048]; +	char	*addr, *addr_end; +	char	*name; +	char	*save; +	char	*colon; +	unsigned long	a; +	int	s; +	int	found = 0; + +	while (fgets(line, sizeof(line), map) != NULL) { +		line[sizeof(line)-1] = '\0'; +		addr = strtok_r(line, " \t\n", &save); +		if (!addr) +			continue; +		name = strtok_r(NULL, " \t\n", &save); +		if (!name) +			continue; +		colon = strchr (addr, ':'); +		if (!colon) +			continue; +		a = strtoul(colon+1, &addr_end, 16); +		if (a == ULONG_MAX || addr_end == addr) +			continue; +		for (s = 0; s < NUM_SERIAL_SYMBOLS; s++) +			if (!strcmp(serial_symbols[s].name, name)) { +				serial_symbols[s].addr = (unsigned) a; +				++found; +				break; +			} +	} +	return found == NUM_SERIAL_SYMBOLS; +} + +static int +rewrite(struct hex_image *image, unsigned addr, char *data, int len) +{ +	int i; +	if (addr < image->address || image->address + image->length < addr + len) +		return 0; +	printf("rewrite %04x:", addr); +	for (i = 0; i < len; i++) +		printf (" %02x", image->data[addr - image->address + i]); +	printf(" ->"); +	for (i = 0; i < len; i++) +		printf (" %02x", data[i]); +	printf("\n"); +	memcpy(image->data + addr - image->address, data, len); +} + +int +main (int argc, char **argv) +{ +	struct ccdbg	*dbg; +	uint8_t		status; +	uint16_t	pc; +	struct hex_file	*hex; +	struct hex_image *image; +	char *filename; +	FILE *file; +	FILE *map; +	char *serial_string; +	unsigned int serial; +	char *mapname, *dot; +	char		*serial_ucs2; +	int		serial_ucs2_len; +	char		serial_int[2]; +	unsigned int	s; +	int		i; +	unsigned	usb_descriptors; +	int		string_num; + +	filename = argv[1]; +	if (filename == NULL) +		usage(argv[0]); +	mapname = strdup(filename); +	dot = strrchr(mapname, '.'); +	if (!dot || strcmp(dot, ".ihx") != 0) +		usage(argv[0]); +	strcpy(dot, ".map"); + +	serial_string = argv[2]; +	if (serial_string == NULL) +		usage(argv[0]); +	 +	file = fopen(filename, "r"); +	if (!file) { +		perror(filename); +		exit(1); +	} +	map = fopen(mapname, "r"); +	if (!map) { +		perror(mapname); +		exit(1); +	} +	if (!find_symbols(map)) { +		fprintf(stderr, "Cannot find symbols in \"%s\"\n", mapname); +		exit(1); +	} +	fclose(map); + +	hex = ccdbg_hex_file_read(file, filename); +	fclose(file); +	if (!hex) { +		perror(filename); +		exit (1); +	} +	image = ccdbg_hex_image_create(hex); +	if (!image) { +		fprintf(stderr, "image create failed\n"); +		exit (1); +	} +	ccdbg_hex_file_free(hex); + +	serial = strtoul(serial_string, NULL, 0); +	if (!serial) +		usage(argv[0]); + +	serial_int[0] = serial & 0xff; +	serial_int[1] = (serial >> 8) & 0xff; + +	if (!rewrite(image, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) { +		fprintf(stderr, "Cannot rewrite serial integer at %04x\n", +			AO_SERIAL_NUMBER); +		exit(1); +	} +	 +	usb_descriptors = AO_USB_DESCRIPTORS - image->address; +	string_num = 0; +	while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) { +		if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) { +			++string_num; +			if (string_num == 4) +				break; +		} +		usb_descriptors += image->data[usb_descriptors]; +	} +	if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) { +		fprintf(stderr, "Cannot rewrite serial string at %04x\n", AO_USB_DESCRIPTORS); +		exit(1); +	} +		 +	serial_ucs2_len = image->data[usb_descriptors] - 2; +	serial_ucs2 = malloc(serial_ucs2_len); +	if (!serial_ucs2) { +		fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); +		exit(1); +	} +	s = serial; +	for (i = serial_ucs2_len / 2; i; i--) { +		serial_ucs2[i * 2 - 1] = 0; +		serial_ucs2[i * 2 - 2] = (s % 10) + '0'; +		s /= 10; +	} +	if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) +		usage(argv[0]); +	 +	dbg = ccdbg_open(); +	if (!dbg) +		exit (1); +	 +	ccdbg_add_debug(CC_DEBUG_FLASH); + +	ccdbg_debug_mode(dbg); +	ccdbg_halt(dbg); +	if (image->address == 0xf000) { +		printf("Loading %d bytes to execute from RAM\n", +		       image->length); +		ccdbg_write_hex_image(dbg, image, 0); +	} else if (image->address == 0x0000) { +		printf("Loading %d bytes to execute from FLASH\n", +		       image->length); +		ccdbg_flash_hex_image(dbg, image); +	} else { +		printf("Cannot load code to 0x%04x\n", +		       image->address); +		ccdbg_hex_image_free(image); +		ccdbg_close(dbg); +		exit(1); +	} +	ccdbg_set_pc(dbg, image->address); +	ccdbg_resume(dbg); +	ccdbg_close(dbg); +	exit (0); +} diff --git a/configure.ac b/configure.ac index 1d4720a6..6c8963c4 100644 --- a/configure.ac +++ b/configure.ac @@ -99,4 +99,5 @@ ccload/Makefile  s51/Makefile  ccmanual/Makefile  ccdump/Makefile +aoload/Makefile  ]) | 
