diff options
Diffstat (limited to 'ao-tools')
| -rw-r--r-- | ao-tools/ao-stmload/Makefile.am | 9 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-elf.c | 303 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-elf.h | 24 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-selfload.c | 127 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-stmload.c | 665 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-stmload.h | 49 | ||||
| -rw-r--r-- | ao-tools/lib/cc-usb.c | 8 | ||||
| -rw-r--r-- | ao-tools/lib/ccdbg-hex.c | 95 | ||||
| -rw-r--r-- | ao-tools/lib/ccdbg.h | 7 | 
9 files changed, 858 insertions, 429 deletions
| diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am index 5aea7db4..4eaf699c 100644 --- a/ao-tools/ao-stmload/Makefile.am +++ b/ao-tools/ao-stmload/Makefile.am @@ -4,11 +4,14 @@ bin_PROGRAMS=ao-stmload  LIBSTLINKDIR=/local/src/stlink -AM_CFLAGS=$(LIBSTLINK_CFLAGS) $(LIBUSB_CFLAGS) -I../lib +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBSTLINK_CFLAGS) $(LIBUSB_CFLAGS) +AO_STMLOAD_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a -ao_stmload_LDADD=$(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf +ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS) -ao_stmload_SOURCES=ao-stmload.c +ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf + +ao_stmload_SOURCES=ao-stmload.c ao-elf.c ao-stmload.h ao-selfload.c  man_MANS = ao-stmload.1 diff --git a/ao-tools/ao-stmload/ao-elf.c b/ao-tools/ao-stmload/ao-elf.c new file mode 100644 index 00000000..dad8fb80 --- /dev/null +++ b/ao-tools/ao-stmload/ao-elf.c @@ -0,0 +1,303 @@ +/* + * 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; 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 "ao-elf.h" +#include <err.h> +#include <gelf.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include "ccdbg.h" +#include "ao-stmload.h" + +/* + * Look through the Elf file for the AltOS symbols + * that can be adjusted before the image is written + * to the device + */ +static int +find_symbols (Elf *e) +{ +	Elf_Scn 	*scn; +	Elf_Data	*symbol_data = NULL; +	GElf_Shdr	shdr; +	GElf_Sym       	sym; +	int		i, symbol_count, s; +	int		required = 0; +	char		*symbol_name; +	char		*section_name; +	size_t		shstrndx; + +	if (elf_getshdrstrndx(e, &shstrndx) < 0) +		return 0; + +	/* +	 * Find the symbols +	 */ + +	scn = NULL; +	while ((scn = elf_nextscn(e, scn)) != NULL) { + +		if (gelf_getshdr(scn, &shdr) != &shdr) +			return 0; + +		if (shdr.sh_type == SHT_SYMTAB) { +			symbol_data = elf_getdata(scn, NULL); +			symbol_count = shdr.sh_size / shdr.sh_entsize; +			break; +		} +	} + +	if (!symbol_data) +		return 0; + +	for (i = 0; i < symbol_count; i++) { +		gelf_getsym(symbol_data, i, &sym); + +		symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name); + +		for (s = 0; s < ao_num_symbols; s++) +			if (!strcmp (ao_symbols[s].name, symbol_name)) { +				int	t; +				ao_symbols[s].addr = sym.st_value; +				if (ao_symbols[s].required) +					++required; +			} +	} + +	return required >= ao_num_required_symbols; +} + +uint32_t round4(uint32_t a) { +	return (a + 3) & ~3; +} + +struct hex_image * +new_load (uint32_t addr, uint32_t len) +{ +	struct hex_image *new; + +	len = round4(len); +	new = calloc (1, sizeof (struct hex_image) + len); +	if (!new) +		abort(); + +	new->address = addr; +	new->length = len; +	return new; +} + +void +load_paste(struct hex_image *into, struct hex_image *from) +{ +	if (from->address < into->address || into->address + into->length < from->address + from->length) +		abort(); + +	memcpy(into->data + from->address - into->address, from->data, from->length); +} + +/* + * Make a new load structure large enough to hold the old one and + * the new data + */ +struct hex_image * +expand_load(struct hex_image *from, uint32_t address, uint32_t length) +{ +	struct hex_image	*new; + +	if (from) { +		uint32_t	from_last = from->address + from->length; +		uint32_t	last = address + length; + +		if (address > from->address) +			address = from->address; +		if (last < from_last) +			last = from_last; + +		length = last - address; + +		if (address == from->address && length == from->length) +			return from; +	} +	new = new_load(address, length); +	if (from) { +		load_paste(new, from); +		free (from); +	} +	return new; +} + +/* + * Create a new load structure with data from the existing one + * and the new data + */ +struct hex_image * +load_write(struct hex_image *from, uint32_t address, uint32_t length, void *data) +{ +	struct hex_image	*new; + +	new = expand_load(from, address, length); +	memcpy(new->data + address - new->address, data, length); +	return new; +} + +/* + * Construct a large in-memory block for all + * of the loaded sections of the program + */ +static struct hex_image * +get_load(Elf *e) +{ +	Elf_Scn 	*scn; +	size_t		shstrndx; +	GElf_Shdr	shdr; +	Elf_Data	*data; +	char		*got_name; +	size_t		nphdr; +	size_t		p; +	GElf_Phdr	phdr; +	GElf_Addr	p_paddr; +	GElf_Off	p_offset; +	GElf_Addr	sh_paddr; +	struct hex_image	*load = NULL; +	char		*section_name; +	size_t		nshdr; +	size_t		s; +	 +	if (elf_getshdrstrndx(e, &shstrndx) < 0) +		return 0; + +	if (elf_getphdrnum(e, &nphdr) < 0) +		return 0; + +	if (elf_getshdrnum(e, &nshdr) < 0) +		return 0; + +	/* +	 * As far as I can tell, all of the phdr sections should +	 * be flashed to memory +	 */ +	for (p = 0; p < nphdr; p++) { + +		/* Find this phdr */ +		gelf_getphdr(e, p, &phdr); + +		if (phdr.p_type != PT_LOAD) +			continue; + +		p_offset = phdr.p_offset; +		/* Get the associated file section */ + +#if 0 +		printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", +			(uint32_t) phdr.p_offset, +			(uint32_t) phdr.p_vaddr, +			(uint32_t) phdr.p_paddr, +			(uint32_t) phdr.p_filesz, +			(uint32_t) phdr.p_memsz); +#endif +		 +		for (s = 0; s < nshdr; s++) { +			scn = elf_getscn(e, s); + +			if (!scn) { +				printf ("getscn failed\n"); +				abort(); +			} +			if (gelf_getshdr(scn, &shdr) != &shdr) { +				printf ("gelf_getshdr failed\n"); +				abort(); +			} + +			section_name = elf_strptr(e, shstrndx, shdr.sh_name); + +			if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) { +					 +				if (shdr.sh_size == 0) +					continue; + +				sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset; + +				printf ("\tsize %08x rom %08x exec %08x %s\n", +					(uint32_t) shdr.sh_size, +					(uint32_t) sh_paddr, +					(uint32_t) shdr.sh_addr, +					section_name); + +				data = elf_getdata(scn, NULL); + +				/* Write the section data into the memory block */ +				load = load_write(load, sh_paddr, shdr.sh_size, data->d_buf); +			} +		} +	} +	return load; +} + +/* + * Open the specified ELF file and + * check for the symbols we need + */ + +struct hex_image * +ao_load_elf(char *name) +{ +	int		fd; +	Elf		*e; +	Elf_Scn 	*scn; +	Elf_Data	*symbol_data = NULL; +	GElf_Shdr	shdr; +	GElf_Sym       	sym; +	size_t		n, shstrndx, sz; +	int		i, symbol_count, s; +	int		required = 0; +	struct hex_image	*image; + +	if (elf_version(EV_CURRENT) == EV_NONE) +		return NULL; + +	fd = open(name, O_RDONLY, 0); + +	if (fd < 0) +		return NULL; + +	e = elf_begin(fd, ELF_C_READ, NULL); + +	if (!e) +		return NULL; + +	if (elf_kind(e) != ELF_K_ELF) +		return NULL; + +	if (elf_getshdrstrndx(e, &shstrndx) != 0) +		return NULL; + +	if (!find_symbols(e)) { +		fprintf (stderr, "Cannot find required symbols\n"); +		return NULL; +	} + +	image = get_load(e); +	if (!image) { +		fprintf (stderr, "Cannot create memory image from file\n"); +		return NULL; +	} + +	return image; +} diff --git a/ao-tools/ao-stmload/ao-elf.h b/ao-tools/ao-stmload/ao-elf.h new file mode 100644 index 00000000..4303d5ca --- /dev/null +++ b/ao-tools/ao-stmload/ao-elf.h @@ -0,0 +1,24 @@ +/* + * 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; 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_ELF_H_ +#define _AO_ELF_H_ + +struct hex_image * +ao_load_elf(char *name); + +#endif diff --git a/ao-tools/ao-stmload/ao-selfload.c b/ao-tools/ao-stmload/ao-selfload.c new file mode 100644 index 00000000..95667dca --- /dev/null +++ b/ao-tools/ao-stmload/ao-selfload.c @@ -0,0 +1,127 @@ +/* + * 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; 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 <stdint.h> +#include <stdlib.h> +#include <sysexits.h> +#include <unistd.h> +#include <string.h> +#include "cc.h" +#include "cc-usb.h" +#include "ccdbg.h" +#include "ao-stmload.h" + +int	ao_self_verbose; + +#define TRACE(...) if (ao_self_verbose) printf (__VA_ARGS__) + +void +ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]) +{ +	int			byte; +	cc_usb_sync(cc); +	cc_usb_printf(cc, "R %x\n", address); +	for (byte = 0; byte < 0x100; byte++) { +		block[byte] = cc_usb_getchar(cc); +	} +	TRACE ("\nread %08x\n", address); +	for (byte = 0; byte < 0x100; byte++) { +		TRACE (" %02x", block[byte]); +		if ((byte & 0xf) == 0xf) +			TRACE ("\n"); +	} +} + +void +ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]) +{ +	int			byte; +	cc_usb_sync(cc); +	cc_usb_printf(cc, "W %x\n", address); +	TRACE ("write %08x\n", address); +	for (byte = 0; byte < 0x100; byte++) { +		TRACE (" %02x", block[byte]); +		if ((byte & 0xf) == 0xf) +			TRACE ("\n"); +	} +	for (byte = 0; byte < 0x100; byte++) { +		cc_usb_printf(cc, "%c", block[byte]); +	} +} + +struct hex_image * +ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length) +{ +	struct hex_image	*image; +	int			pages; +	int			page; +	uint32_t		base = address & ~0xff; +	uint32_t		bound = (address + length + 0xff) & ~0xff; + +	image = calloc(sizeof (struct hex_image) + (bound - base), 1); +	image->address = base; +	image->length = bound - base; +	pages = image->length / 0x100; +	for (page = 0; page < pages; page++) +		ao_self_block_read(cc, image->address + page * 0x100, image->data + page * 0x100); +	return image; +} + +int +ao_self_write(struct cc_usb *cc, struct hex_image *image) +{ +	uint8_t		block[256]; +	uint8_t		check[256]; +	uint32_t	base, bound, length, address; +	uint32_t	pages; +	uint32_t	page; + +	base = image->address & ~0xff; +	bound = (image->address + image->length + 0xff) & ~0xff; + +	address = base; +	length = bound - base; + +	pages = length / 0x100; +	printf ("Write %08x %d pages: ", address, length/0x100); fflush(stdout); +	for (page = 0; page < pages; page++) { +		uint32_t	start, stop; +		address = base + page * 0x100; + +		if (address < image->address || address + 0x100 > image->address + image->length) { +			ao_self_block_read(cc, address, block); +		} +		start = address; +		stop = address + 0x100; +		if (start < image->address) +			start = image->address; +		if (stop > image->address + image->length) +			stop = image->address + image->length; +		memcpy(block + start - address, image->data + start - image->address, stop - start); +		ao_self_block_write(cc, address, block); +		ao_self_block_read(cc, address, check); +		if (memcmp(block, check, 0x100) != 0) { +			fprintf(stderr, "Block at 0x%08x doesn't match\n", address); +			return 0; +		} +		putchar('.'); fflush(stdout); +	} +	printf("done\n"); +	cc_usb_printf(cc,"a\n"); +	return 1; +} diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c index 89b818da..dd25f07f 100644 --- a/ao-tools/ao-stmload/ao-stmload.c +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -26,365 +26,107 @@  #include <getopt.h>  #include <string.h>  #include "stlink-common.h" +#include "ao-elf.h" +#include "ccdbg.h" +#include "cc-usb.h" +#include "cc.h" +#include "ao-stmload.h"  #define AO_USB_DESC_STRING		3 -struct sym { -	unsigned	addr; -	char		*name; -	int		required; -} ao_symbols[] = { +struct sym ao_symbols[] = { -	{ 0,	"ao_romconfig_version",	1 }, +	{ 0, AO_BOOT_APPLICATION_BASE + 0x100,	"ao_romconfig_version",	1 },  #define AO_ROMCONFIG_VERSION	(ao_symbols[0].addr) -	{ 0,	"ao_romconfig_check",	1 }, +	{ 0, AO_BOOT_APPLICATION_BASE + 0x102,	"ao_romconfig_check",	1 },  #define AO_ROMCONFIG_CHECK	(ao_symbols[1].addr) -	{ 0,	"ao_serial_number", 1 }, +	{ 0, AO_BOOT_APPLICATION_BASE + 0x104,	"ao_serial_number", 1 },  #define AO_SERIAL_NUMBER	(ao_symbols[2].addr) -	{ 0,	"ao_usb_descriptors", 0 }, -#define AO_USB_DESCRIPTORS	(ao_symbols[3].addr) +	{ 0, AO_BOOT_APPLICATION_BASE + 0x108,	"ao_radio_cal", 0 }, +#define AO_RADIO_CAL		(ao_symbols[3].addr) -	{ 0,	"ao_radio_cal", 0 }, -#define AO_RADIO_CAL		(ao_symbols[4].addr) +	{ 0, AO_BOOT_APPLICATION_BASE + 0x10c,	"ao_usb_descriptors", 0 }, +#define AO_USB_DESCRIPTORS	(ao_symbols[4].addr)  };  #define NUM_SYMBOLS		5  #define NUM_REQUIRED_SYMBOLS	3 -/* - * Look through the Elf file for the AltOS symbols - * that can be adjusted before the image is written - * to the device - */ -static int -find_symbols (Elf *e) -{ -	Elf_Scn 	*scn; -	Elf_Data	*symbol_data = NULL; -	GElf_Shdr	shdr; -	GElf_Sym       	sym; -	int		i, symbol_count, s; -	int		required = 0; -	char		*symbol_name; -	char		*section_name; -	size_t		shstrndx; - -	if (elf_getshdrstrndx(e, &shstrndx) < 0) -		return 0; - -	/* -	 * Find the symbols -	 */ - -	scn = NULL; -	while ((scn = elf_nextscn(e, scn)) != NULL) { - -		if (gelf_getshdr(scn, &shdr) != &shdr) -			return 0; - -#if 0 -		section_name = elf_strptr(e, shstrndx, shdr.sh_name); - -		printf ("name %s\n", section_name); - -		if (shdr.sh_type == SHT_PROGBITS) -		{ -			printf ("\ttype %lx\n", shdr.sh_type); -			printf ("\tflags %lx\n", shdr.sh_flags); -			printf ("\taddr %lx\n", shdr.sh_addr); -			printf ("\toffset %lx\n", shdr.sh_offset); -			printf ("\tsize %lx\n", shdr.sh_size); -			printf ("\tlink %lx\n", shdr.sh_link); -			printf ("\tinfo %lx\n", shdr.sh_info); -			printf ("\taddralign %lx\n", shdr.sh_addralign); -			printf ("\tentsize %lx\n", shdr.sh_entsize); -		} -#endif - -		if (shdr.sh_type == SHT_SYMTAB) { -			symbol_data = elf_getdata(scn, NULL); -			symbol_count = shdr.sh_size / shdr.sh_entsize; -			break; -		} -	} - -	if (!symbol_data) -		return 0; - -	for (i = 0; i < symbol_count; i++) { -		gelf_getsym(symbol_data, i, &sym); - -		symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name); - -		for (s = 0; s < NUM_SYMBOLS; s++) -			if (!strcmp (ao_symbols[s].name, symbol_name)) { -				int	t; -				ao_symbols[s].addr = sym.st_value; -				if (ao_symbols[s].required) -					++required; -			} -	} - -	return required >= NUM_REQUIRED_SYMBOLS; -} - -struct load { -	uint32_t	addr; -	uint32_t	len; -	uint8_t		buf[0]; -}; - -uint32_t round4(uint32_t a) { -	return (a + 3) & ~3; -} - -struct load * -new_load (uint32_t addr, uint32_t len) -{ -	struct load *new; - -	len = round4(len); -	new = calloc (1, sizeof (struct load) + len); -	if (!new) -		abort(); - -	new->addr = addr; -	new->len = len; -	return new; -} - -void -load_paste(struct load *into, struct load *from) -{ -	if (from->addr < into->addr || into->addr + into->len < from->addr + from->len) -		abort(); - -	memcpy(into->buf + from->addr - into->addr, from->buf, from->len); -} - -/* - * Make a new load structure large enough to hold the old one and - * the new data - */ -struct load * -expand_load(struct load *from, uint32_t addr, uint32_t len) -{ -	struct load	*new; - -	if (from) { -		uint32_t	from_last = from->addr + from->len; -		uint32_t	last = addr + len; - -		if (addr > from->addr) -			addr = from->addr; -		if (last < from_last) -			last = from_last; - -		len = last - addr; - -		if (addr == from->addr && len == from->len) -			return from; -	} -	new = new_load(addr, len); -	if (from) { -		load_paste(new, from); -		free (from); -	} -	return new; -} - -/* - * Create a new load structure with data from the existing one - * and the new data - */ -struct load * -load_write(struct load *from, uint32_t addr, uint32_t len, void *data) -{ -	struct load	*new; - -	new = expand_load(from, addr, len); -	memcpy(new->buf + addr - new->addr, data, len); -	return new; -} - -/* - * Construct a large in-memory block for all - * of the loaded sections of the program - */ -static struct load * -get_load(Elf *e) -{ -	Elf_Scn 	*scn; -	size_t		shstrndx; -	GElf_Shdr	shdr; -	Elf_Data	*data; -	uint8_t		*buf; -	char		*got_name; -	size_t		nphdr; -	size_t		p; -	GElf_Phdr	phdr; -	GElf_Addr	p_paddr; -	GElf_Off	p_offset; -	GElf_Addr	sh_paddr; -	struct load	*load = NULL; -	char		*section_name; -	size_t		nshdr; -	size_t		s; -	 -	if (elf_getshdrstrndx(e, &shstrndx) < 0) -		return 0; - -	if (elf_getphdrnum(e, &nphdr) < 0) -		return 0; - -	if (elf_getshdrnum(e, &nshdr) < 0) -		return 0; - -	/* -	 * As far as I can tell, all of the phdr sections should -	 * be flashed to memory -	 */ -	for (p = 0; p < nphdr; p++) { - -		/* Find this phdr */ -		gelf_getphdr(e, p, &phdr); - -		if (phdr.p_type != PT_LOAD) -			continue; - -		p_offset = phdr.p_offset; -		/* Get the associated file section */ - -#if 0 -		printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n", -			(uint32_t) phdr.p_offset, -			(uint32_t) phdr.p_vaddr, -			(uint32_t) phdr.p_paddr, -			(uint32_t) phdr.p_filesz, -			(uint32_t) phdr.p_memsz); -#endif -		 -		for (s = 0; s < nshdr; s++) { -			scn = elf_getscn(e, s); - -			if (!scn) { -				printf ("getscn failed\n"); -				abort(); -			} -			if (gelf_getshdr(scn, &shdr) != &shdr) { -				printf ("gelf_getshdr failed\n"); -				abort(); -			} - -			section_name = elf_strptr(e, shstrndx, shdr.sh_name); - -			if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) { -					 -				if (shdr.sh_size == 0) -					continue; - -				sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset; - -				printf ("\tsize %08x rom %08x exec %08x %s\n", -					(uint32_t) shdr.sh_size, -					(uint32_t) sh_paddr, -					(uint32_t) shdr.sh_addr, -					section_name); - -				data = elf_getdata(scn, NULL); - -				/* Write the section data into the memory block */ -				load = load_write(load, sh_paddr, shdr.sh_size, data->d_buf); -			} -		} -	} -	return load; -} +int ao_num_symbols = NUM_SYMBOLS; +int ao_num_required_symbols = NUM_REQUIRED_SYMBOLS;  /*   * Edit the to-be-written memory block   */  static int -rewrite(struct load *load, unsigned addr, uint8_t *data, int len) +rewrite(struct hex_image *load, unsigned address, uint8_t *data, int length)  {  	int 		i; -	if (addr < load->addr || load->addr + load->len < addr + len) +	if (address < load->address || load->address + load->length < address + length)  		return 0; -	printf("rewrite %04x:", addr); -	for (i = 0; i < len; i++) -		printf (" %02x", load->buf[addr - load->addr + i]); +	printf("rewrite %04x:", address); +	for (i = 0; i < length; i++) +		printf (" %02x", load->data[address - load->address + i]);  	printf(" ->"); -	for (i = 0; i < len; i++) +	for (i = 0; i < length; i++)  		printf (" %02x", data[i]);  	printf("\n"); -	memcpy(load->buf + addr - load->addr, data, len); +	memcpy(load->data + address - load->address, data, length);  }  /* - * Open the specified ELF file and - * check for the symbols we need + * Read a 16-bit value from the USB target   */ -Elf * -ao_open_elf(char *name) +static uint16_t +get_uint16_cc(struct cc_usb *cc, uint32_t addr)  { -	int		fd; -	Elf		*e; -	Elf_Scn 	*scn; -	Elf_Data	*symbol_data = NULL; -	GElf_Shdr	shdr; -	GElf_Sym       	sym; -	size_t		n, shstrndx, sz; -	int		i, symbol_count, s; -	int		required = 0; - -	if (elf_version(EV_CURRENT) == EV_NONE) -		return NULL; +	struct hex_image	*hex = ao_self_read(cc, addr, 2); +	uint16_t		v; +	uint8_t			*data; -	fd = open(name, O_RDONLY, 0); - -	if (fd < 0) -		return NULL; - -	e = elf_begin(fd, ELF_C_READ, NULL); - -	if (!e) -		return NULL; - -	if (elf_kind(e) != ELF_K_ELF) -		return NULL; - -	if (elf_getshdrstrndx(e, &shstrndx) != 0) -		return NULL; +	if (!hex) +		return 0; +	data = hex->data + addr - hex->address; +	v = data[0] | (data[1] << 8); +	free(hex); +	return v; +} -	if (!find_symbols(e)) { -		fprintf (stderr, "Cannot find required symbols\n"); -		return NULL; -	} +static uint32_t +get_uint32_cc(struct cc_usb *cc, uint32_t addr) +{ +	struct hex_image	*hex = ao_self_read(cc, addr, 4); +	uint32_t		v; +	uint8_t			*data; -	return e; +	if (!hex) +		return 0; +	data = hex->data + addr - hex->address; +	v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); +	free(hex); +	return v;  }  /* - * Read a 32-bit value from the target device with arbitrary + * Read a 16-bit value from the target device with arbitrary   * alignment   */ -static uint32_t -get_uint32(stlink_t *sl, uint32_t addr) +static uint16_t +get_uint16_sl(stlink_t *sl, uint32_t addr)  {  	const 		uint8_t *data = sl->q_buf;  	uint32_t	actual_addr;  	int		off; -	uint32_t	result; +	uint16_t	result;  	sl->q_len = 0; -	printf ("read 0x%x\n", addr);  	actual_addr = addr & ~3; @@ -394,25 +136,37 @@ get_uint32(stlink_t *sl, uint32_t addr)  		abort();  	off = addr & 3; -	result = data[off] | (data[off + 1] << 8) | (data[off+2] << 16) | (data[off+3] << 24); -	printf ("read 0x%08x = 0x%08x\n", addr, result); +	result = data[off] | (data[off + 1] << 8); +	return result; +} + +static uint16_t +get_uint16(stlink_t *sl, struct cc_usb *cc, uint32_t addr) +{ +	uint16_t	result; +	if (cc) +		result = get_uint16_cc(cc, addr); +	else +		result = get_uint16_sl(sl, addr); +	printf ("read 0x%08x = 0x%04x\n", addr, result);  	return result;  }  /* - * Read a 16-bit value from the target device with arbitrary + * Read a 32-bit value from the target device with arbitrary   * alignment   */ -static uint16_t -get_uint16(stlink_t *sl, uint32_t addr) +static uint32_t +get_uint32_sl(stlink_t *sl, uint32_t addr)  {  	const 		uint8_t *data = sl->q_buf;  	uint32_t	actual_addr;  	int		off; -	uint16_t	result; +	uint32_t	result;  	sl->q_len = 0; +	printf ("read 0x%x\n", addr);  	actual_addr = addr & ~3; @@ -422,8 +176,24 @@ get_uint16(stlink_t *sl, uint32_t addr)  		abort();  	off = addr & 3; -	result = data[off] | (data[off + 1] << 8); -	printf ("read 0x%08x = 0x%04x\n", addr, result); +	result = data[off] | (data[off + 1] << 8) | (data[off+2] << 16) | (data[off+3] << 24); +	return result; +} + +/* + * Read a 32-bit value from the target device with arbitrary + * alignment + */ +static uint32_t +get_uint32(stlink_t *sl, struct cc_usb *cc, uint32_t addr) +{ +	uint32_t	result; + +	if (cc) +		result = get_uint32_cc(cc, addr); +	else +		result = get_uint32_sl(sl, addr); +	printf ("read 0x%08x = 0x%08x\n", addr, result);  	return result;  } @@ -436,10 +206,10 @@ get_uint16(stlink_t *sl, uint32_t addr)   * places this at 0x100 from the start of the rom section   */  static int -check_flashed(stlink_t *sl) +check_flashed(stlink_t *sl, struct cc_usb *cc)  { -	uint16_t	romconfig_version = get_uint16(sl, AO_ROMCONFIG_VERSION); -	uint16_t	romconfig_check = get_uint16(sl, AO_ROMCONFIG_CHECK); +	uint16_t	romconfig_version = get_uint16(sl, cc, AO_ROMCONFIG_VERSION); +	uint16_t	romconfig_check = get_uint16(sl, cc, AO_ROMCONFIG_CHECK);  	if (romconfig_version != (uint16_t) ~romconfig_check) {  		fprintf (stderr, "Device has not been flashed before\n"); @@ -449,21 +219,28 @@ check_flashed(stlink_t *sl)  }  static const struct option options[] = { +	{ .name = "stlink", .has_arg = 0, .val = 'S' }, +	{ .name = "tty", .has_arg = 1, .val = 'T' },  	{ .name = "device", .has_arg = 1, .val = 'D' },  	{ .name = "cal", .has_arg = 1, .val = 'c' },  	{ .name = "serial", .has_arg = 1, .val = 's' }, +	{ .name = "verbose", .has_arg = 0, .val = 'v' },  	{ 0, 0, 0, 0},  };  static void usage(char *program)  { -	fprintf(stderr, "usage: %s [--cal=<radio-cal>] [--serial=<serial>] file.elf\n", program); +	fprintf(stderr, "usage: %s [--stlink] [--verbose] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] file.{elf,ihx}\n", program);  	exit(1);  }  void -done(stlink_t *sl, int code) +done(stlink_t *sl, struct cc_usb *cc, int code)  { +	if (cc) { +/*		cc_usb_printf(cc, "a\n"); */ +		cc_usb_close(cc); +	}  	if (sl) {  		stlink_reset(sl);  		stlink_run(sl); @@ -473,6 +250,17 @@ done(stlink_t *sl, int code)  	exit (code);  } +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; +} +  int  main (int argc, char **argv)  { @@ -491,13 +279,21 @@ main (int argc, char **argv)  	char			cal_int[4];  	char			*cal_end;  	int			c; -	stlink_t		*sl; +	stlink_t		*sl = NULL;  	int			was_flashed = 0; -	struct load		*load; +	struct hex_image	*load;  	int			tries; +	struct cc_usb		*cc = NULL; +	int			use_stlink = 0; +	char			*tty = NULL; +	int			success; +	int			verbose = 0; -	while ((c = getopt_long(argc, argv, "D:c:s:", options, NULL)) != -1) { +	while ((c = getopt_long(argc, argv, "T:D:c:s:Sv", options, NULL)) != -1) {  		switch (c) { +		case 'T': +			tty = optarg; +			break;  		case 'D':  			device = optarg;  			break; @@ -511,101 +307,168 @@ main (int argc, char **argv)  			if (serial_end == optarg || *serial_end != '\0')  				usage(argv[0]);  			break; +		case 'S': +			use_stlink = 1; +			break; +		case 'v': +			verbose++; +			break;  		default:  			usage(argv[0]);  			break;  		}  	} +	ao_self_verbose = verbose; + +	if (verbose > 1) +		ccdbg_add_debug(CC_DEBUG_BITBANG); +  	filename = argv[optind];  	if (filename == NULL)  		usage(argv[0]); -	/* -	 * Open the source file and load the symbols and -	 * flash data -	 */ -	 -	e = ao_open_elf(filename); -	if (!e) { -		fprintf(stderr, "Cannot open file \"%s\"\n", filename); -		exit(1); -	} - -	if (!find_symbols(e)) { -		fprintf(stderr, "Cannot find symbols in \"%s\"\n", filename); -		exit(1); -	} +	if (ends_with (filename, ".elf")) { +		load = ao_load_elf(filename); +	} else if (ends_with (filename, ".ihx")) { +		int	i; +		load = ccdbg_hex_load(filename); +		for (i = 0; i < ao_num_symbols; i++) +			ao_symbols[i].addr = ao_symbols[i].default_addr; +	} else +		usage(argv[0]); -	if (!(load = get_load(e))) { -		fprintf(stderr, "Cannot find program data in \"%s\"\n", filename); -		exit(1); -	} -		 -	/* Connect to the programming dongle -	 */ +	if (use_stlink) { +		/* Connect to the programming dongle +		 */ -	for (tries = 0; tries < 3; tries++) { -		if (device) { -			sl = stlink_v1_open(50); -		} else { -			sl = stlink_open_usb(50); +		for (tries = 0; tries < 3; tries++) { +			if (device) { +				sl = stlink_v1_open(50); +			} else { +				sl = stlink_open_usb(50); +			} +			if (!sl) { +				fprintf (stderr, "No STLink devices present\n"); +				done (sl, NULL, 1); +			} + +			if (sl->chip_id != 0) +				break; +			stlink_reset(sl); +			stlink_close(sl); +			sl = NULL;  		}  		if (!sl) { -			fprintf (stderr, "No STLink devices present\n"); -			done (sl, 1); +			fprintf (stderr, "Debugger connection failed\n"); +			exit(1);  		} -		if (sl->chip_id != 0) -			break; -		stlink_reset(sl); -		stlink_close(sl); -	} -	if (sl->chip_id == 0) { -		fprintf (stderr, "Debugger connection failed\n"); -		done(sl, 1); -	} +		/* Verify that the loaded image fits entirely within device flash +		 */ +		if (load->address < sl->flash_base || +		    sl->flash_base + sl->flash_size < load->address + load->length) { +			fprintf (stderr, "\%s\": Invalid memory range 0x%08x - 0x%08x\n", filename, +				 load->address, load->address + load->length); +			done(sl, NULL, 1); +		} -	/* Verify that the loaded image fits entirely within device flash -	 */ -	if (load->addr < sl->flash_base || -	    sl->flash_base + sl->flash_size < load->addr + load->len) { -		fprintf (stderr, "\%s\": Invalid memory range 0x%08x - 0x%08x\n", filename, -			 load->addr, load->addr + load->len); -		done(sl, 1); +		/* Enter debugging mode +		 */ +		if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) +			stlink_exit_dfu_mode(sl); + +		if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) +			stlink_enter_swd_mode(sl); +	} else { +		int	is_loader; +		int	tries; + +		for (tries = 0; tries < 3; tries++) { +			char	*this_tty = tty; +			if (!this_tty) +				this_tty = cc_usbdevs_find_by_arg(device, "AltosFlash"); +			if (!this_tty) +				this_tty = cc_usbdevs_find_by_arg(device, "MegaMetrum"); +			if (!this_tty) +				this_tty = getenv("ALTOS_TTY"); +			if (!this_tty) +				this_tty="/dev/ttyACM0"; + +			cc = cc_usb_open(this_tty); + +			if (!cc) +				exit(1); +			cc_usb_printf(cc, "v\n"); +			is_loader = 0; +			for (;;) { +				char	line[256]; +				cc_usb_getline(cc, line, sizeof(line)); +				if (!strncmp(line, "altos-loader", 12)) +					is_loader = 1; +				if (!strncmp(line, "software-version", 16)) +					break; +			} +			if (is_loader) +				break; +			printf ("rebooting to loader\n"); +			cc_usb_printf(cc, "X\n"); +			cc_usb_close(cc); +			sleep(1); +			cc = NULL; +		} +		if (!is_loader) { +			fprintf(stderr, "Cannot switch to boot loader\n"); +			exit(1); +		} +#if 0 +		{ +			uint8_t	check[256]; +			int	i = 0; + +			ao_self_block_read(cc, AO_BOOT_APPLICATION_BASE, check); +			for (;;) { +				uint8_t block[256]; +				putchar ('.'); +				if (++i == 40) { +					putchar('\n'); +					i = 0; +				} +				fflush(stdout); +				ao_self_block_write(cc, AO_BOOT_APPLICATION_BASE, block); +				ao_self_block_read(cc, AO_BOOT_APPLICATION_BASE, block); +				if (memcmp(block, check, 256) != 0) { +					fprintf (stderr, "read differed\n"); +					exit(1); +				} +			} +		} +#endif  	} -	/* Enter debugging mode -	 */ -	if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) -		stlink_exit_dfu_mode(sl); - -	if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) -		stlink_enter_swd_mode(sl); -  	/* Go fetch existing config values  	 * if available  	 */ -	was_flashed = check_flashed(sl); +	was_flashed = check_flashed(sl, cc);  	if (!serial) {  		if (!was_flashed) {  			fprintf (stderr, "Must provide serial number\n"); -			done(sl, 1); +			done(sl, cc, 1);  		} -		serial = get_uint16(sl, AO_SERIAL_NUMBER); +		serial = get_uint16(sl, cc, AO_SERIAL_NUMBER);  		if (!serial || serial == 0xffff) {  			fprintf (stderr, "Invalid existing serial %d\n", serial); -			done(sl, 1); +			done(sl, cc, 1);  		}  	}  	if (!cal && AO_RADIO_CAL && was_flashed) { -		cal = get_uint32(sl, AO_RADIO_CAL); +		cal = get_uint32(sl, cc, AO_RADIO_CAL);  		if (!cal || cal == 0xffffffff) {  			fprintf (stderr, "Invalid existing rf cal %d\n", cal); -			done(sl, 1); +			done(sl, cc, 1);  		}  	} @@ -618,32 +481,31 @@ main (int argc, char **argv)  	if (!rewrite(load, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) {  		fprintf(stderr, "Cannot rewrite serial integer at %08x\n",  			AO_SERIAL_NUMBER); -		done(sl, 1); +		done(sl, cc, 1);  	}  	if (AO_USB_DESCRIPTORS) { -		unsigned	usb_descriptors; -		usb_descriptors = AO_USB_DESCRIPTORS - load->addr; +		uint32_t	usb_descriptors = AO_USB_DESCRIPTORS - load->address;  		string_num = 0; -		while (load->buf[usb_descriptors] != 0 && usb_descriptors < load->len) { -			if (load->buf[usb_descriptors+1] == AO_USB_DESC_STRING) { +		while (load->data[usb_descriptors] != 0 && usb_descriptors < load->length) { +			if (load->data[usb_descriptors+1] == AO_USB_DESC_STRING) {  				++string_num;  				if (string_num == 4)  					break;  			} -			usb_descriptors += load->buf[usb_descriptors]; +			usb_descriptors += load->data[usb_descriptors];  		} -		if (usb_descriptors >= load->len || load->buf[usb_descriptors] == 0 ) { +		if (usb_descriptors >= load->length || load->data[usb_descriptors] == 0 ) {  			fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS); -			done(sl, 1); +			done(sl, cc, 1);  		} -		serial_ucs2_len = load->buf[usb_descriptors] - 2; +		serial_ucs2_len = load->data[usb_descriptors] - 2;  		serial_ucs2 = malloc(serial_ucs2_len);  		if (!serial_ucs2) {  			fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); -			done(sl, 1); +			done(sl, cc, 1);  		}  		s = serial;  		for (i = serial_ucs2_len / 2; i; i--) { @@ -651,9 +513,9 @@ main (int argc, char **argv)  			serial_ucs2[i * 2 - 2] = (s % 10) + '0';  			s /= 10;  		} -		if (!rewrite(load, usb_descriptors + 2 + load->addr, serial_ucs2, serial_ucs2_len)) { +		if (!rewrite(load, usb_descriptors + 2 + load->address, serial_ucs2, serial_ucs2_len)) {  			fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS); -			done(sl, 1); +			done(sl, cc, 1);  		}  	} @@ -671,10 +533,15 @@ main (int argc, char **argv)  	/* And flash the resulting image to the device  	 */ -	if (stlink_write_flash(sl, load->addr, load->buf, load->len) < 0) { +	if (cc) +		success = ao_self_write(cc, load); +	else +		success = (stlink_write_flash(sl, load->address, load->data, load->length) >= 0); +		 +	if (!success) {  		fprintf (stderr, "\"%s\": Write failed\n", filename); -		done(sl, 1); +		done(sl, cc, 1);  	} -	done(sl, 0); +	done(sl, cc, 0);  } diff --git a/ao-tools/ao-stmload/ao-stmload.h b/ao-tools/ao-stmload/ao-stmload.h new file mode 100644 index 00000000..98884535 --- /dev/null +++ b/ao-tools/ao-stmload/ao-stmload.h @@ -0,0 +1,49 @@ +/* + * 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; 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_STMLOAD_H_ +#define _AO_STMLOAD_H_ + +struct sym { +	unsigned	addr; +	unsigned	default_addr; +	char		*name; +	int		required; +}; + +#define AO_BOOT_APPLICATION_BASE	0x08001000 + +extern struct sym ao_symbols[]; + +extern int ao_num_symbols; +extern int ao_num_required_symbols; + +void +ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]); + +void +ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]); + +struct hex_image * +ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length); + +int +ao_self_write(struct cc_usb *cc, struct hex_image *image); + +extern int ao_self_verbose; + +#endif /* _AO_STMLOAD_H_ */ diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c index 485583f9..d7ac138c 100644 --- a/ao-tools/lib/cc-usb.c +++ b/ao-tools/lib/cc-usb.c @@ -123,9 +123,10 @@ cc_handle_hex_read(struct cc_usb *cc)  static void  cc_usb_dbg(int indent, uint8_t *bytes, int len)  { -	int	eol = 1; +	static int	eol = 1;  	int	i;  	uint8_t	c; +	ccdbg_debug(CC_DEBUG_BITBANG, "<<<%d bytes>>>", len);  	while (len--) {  		c = *bytes++;  		if (eol) { @@ -135,10 +136,12 @@ cc_usb_dbg(int indent, uint8_t *bytes, int len)  		}  		switch (c) {  		case '\r': -			ccdbg_debug(CC_DEBUG_BITBANG, "^M"); +			ccdbg_debug(CC_DEBUG_BITBANG, "\\r");  			break;  		case '\n':  			eol = 1; +			ccdbg_debug(CC_DEBUG_BITBANG, "\\n\n"); +			break;  		default:  			if (c < ' ' || c > '~')  				ccdbg_debug(CC_DEBUG_BITBANG, "\\%02x", c); @@ -193,7 +196,6 @@ _cc_usb_sync(struct cc_usb *cc, int wait_for_input)  			ret = read(cc->fd, cc->in_buf + cc->in_count,  				   CC_IN_BUF - cc->in_count);  			if (ret > 0) { -				int i;  				cc_usb_dbg(24, cc->in_buf + cc->in_count, ret);  				cc->in_count += ret;  				if (cc->hex_count) diff --git a/ao-tools/lib/ccdbg-hex.c b/ao-tools/lib/ccdbg-hex.c index dfea9156..184b4e3b 100644 --- a/ao-tools/lib/ccdbg-hex.c +++ b/ao-tools/lib/ccdbg-hex.c @@ -233,15 +233,6 @@ ccdbg_hex_file_free(struct hex_file *hex)  	free(hex);  } -static int -ccdbg_hex_record_compar(const void *av, const void *bv) -{ -	const struct hex_record *a = *(struct hex_record **) av; -	const struct hex_record *b = *(struct hex_record **) bv; - -	return (int) a->address - (int) b->address; -} -  struct hex_file *  ccdbg_hex_file_read(FILE *file, char *name)  { @@ -272,11 +263,6 @@ ccdbg_hex_file_read(FILE *file, char *name)  		if (record->type == HEX_RECORD_EOF)  			done = 1;  	} -	/* -	 * Sort them into increasing addresses, except for EOF -	 */ -	qsort(hex->records, hex->nrecord - 1, sizeof (struct hex_record *), -	      ccdbg_hex_record_compar);  	return hex;  bail: @@ -288,16 +274,45 @@ struct hex_image *  ccdbg_hex_image_create(struct hex_file *hex)  {  	struct hex_image *image; -	struct hex_record *first, *last, *record; +	struct hex_record *record;  	int i; +	uint32_t addr;  	uint32_t base, bound;  	uint32_t offset; +	uint32_t extended_addr; +  	int length; -	first = hex->records[0]; -	last = hex->records[hex->nrecord - 2];	/* skip EOF */ -	base = (uint32_t) first->address; -	bound = (uint32_t) last->address + (uint32_t) last->length; +	base = 0xffffffff; +	bound = 0x0; +	extended_addr = 0; +	for (i = 0; i < hex->nrecord; i++) { +		uint32_t r_bound; +		record = hex->records[i]; +		switch (record->type) { +		case 0: +			addr = extended_addr + record->address; +			r_bound = addr + record->length; +			if (addr < base) +				base = addr; +			if (r_bound > bound) +				bound = r_bound; +			break; +		case 1: +			break; +		case 2: +			if (record->length != 2) +				return NULL; +			extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; +			break; +		case 4: +			if (record->length != 2) +				return NULL; +			extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; +			break; +		} + +	}  	length = bound - base;  	image = calloc(sizeof(struct hex_image) + length, 1);  	if (!image) @@ -305,10 +320,24 @@ ccdbg_hex_image_create(struct hex_file *hex)  	image->address = base;  	image->length = length;  	memset(image->data, 0xff, length); -	for (i = 0; i < hex->nrecord - 1; i++) { +	extended_addr = 0; +	for (i = 0; i < hex->nrecord; i++) {  		record = hex->records[i]; -		offset = record->address - base; -		memcpy(image->data + offset, record->data, record->length); +		switch (record->type) { +		case 0: +			addr = extended_addr + record->address; +			offset = addr - base; +			memcpy(image->data + offset, record->data, record->length); +			break; +		case 1: +			break; +		case 2: +			extended_addr = ((record->data[0] << 8) | record->data[1]) << 4; +			break; +		case 4: +			extended_addr = ((record->data[0] << 8) | record->data[1]) << 16; +			break; +		}  	}  	return image;  } @@ -328,3 +357,25 @@ ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b)  		return 0;  	return 1;  } + +struct hex_image * +ccdbg_hex_load(char *filename) +{ +	FILE *file; +	struct hex_file	*hex_file; +	struct hex_image *hex_image; + +	file = fopen (filename, "r"); +	if (!file) +		return 0; +	 +	hex_file = ccdbg_hex_file_read(file, filename); +	fclose(file); +	if (!hex_file) +		return 0; +	hex_image = ccdbg_hex_image_create(hex_file); +	if (!hex_image) +		return 0; +	ccdbg_hex_file_free(hex_file); +	return hex_image; +} diff --git a/ao-tools/lib/ccdbg.h b/ao-tools/lib/ccdbg.h index ca596143..a27ff5d1 100644 --- a/ao-tools/lib/ccdbg.h +++ b/ao-tools/lib/ccdbg.h @@ -122,8 +122,8 @@ struct hex_file {  };  struct hex_image { -	uint16_t	address; -	uint16_t	length; +	uint32_t	address; +	uint32_t	length;  	uint8_t		data[0];  }; @@ -253,6 +253,9 @@ ccdbg_hex_image_create(struct hex_file *hex);  void  ccdbg_hex_image_free(struct hex_image *image); +struct hex_image * +ccdbg_hex_load(char *filename); +  int  ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b); | 
