diff options
| -rw-r--r-- | ao-tools/ao-usbload/ao-usbload.c | 94 | ||||
| -rw-r--r-- | ao-tools/lib/ao-editaltos.c | 95 | ||||
| -rw-r--r-- | ao-tools/lib/ao-editaltos.h | 28 | ||||
| -rw-r--r-- | ao-tools/lib/ao-selfload.c | 37 | ||||
| -rw-r--r-- | ao-tools/lib/ao-selfload.h | 10 | 
5 files changed, 244 insertions, 20 deletions
diff --git a/ao-tools/ao-usbload/ao-usbload.c b/ao-tools/ao-usbload/ao-usbload.c index 2f121cfe..d0579de1 100644 --- a/ao-tools/ao-usbload/ao-usbload.c +++ b/ao-tools/ao-usbload/ao-usbload.c @@ -41,7 +41,6 @@ get_uint16(struct cc_usb *cc, uint32_t addr)  {  	uint16_t	result;  	result = ao_self_get_uint16(cc, addr); -	printf ("read 0x%08x = 0x%04x\n", addr, result);  	return result;  } @@ -55,7 +54,6 @@ get_uint32(struct cc_usb *cc, uint32_t addr)  	uint32_t	result;  	result = ao_self_get_uint32(cc, addr); -	printf ("read 0x%08x = 0x%08x\n", addr, result);  	return result;  } @@ -88,12 +86,13 @@ static const struct option options[] = {  	{ .name = "serial", .has_arg = 1, .val = 's' },  	{ .name = "verbose", .has_arg = 1, .val = 'v' },  	{ .name = "wait", .has_arg = 0, .val = 'w' }, +	{ .name = "force", .has_arg = 0, .val = 'f' },  	{ 0, 0, 0, 0},  };  static void usage(char *program)  { -	fprintf(stderr, "usage: %s [--raw] [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] [--wait] file.{elf,ihx}\n", program); +	fprintf(stderr, "usage: %s [--raw] [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] [--wait] [--force] file.{elf,ihx}\n", program);  	exit(1);  } @@ -116,6 +115,48 @@ ends_with(char *whole, char *suffix)  	return strcmp(whole + whole_len - suffix_len, suffix) == 0;  } +static int +ucs2len(uint16_t *ucs2) +{ +	int	len = 0; +	while (*ucs2++) +		len++; +	return len; +} + +int +putucs4(uint32_t c, FILE *file) +{ +	char d; +	int	bits; + +	     if (c <       0x80) { d = c;                         bits= -6; } +	else if (c <      0x800) { d= ((c >>  6) & 0x1F) | 0xC0;  bits=  0; } +	else if (c <    0x10000) { d= ((c >> 12) & 0x0F) | 0xE0;  bits=  6; } +	else if (c <   0x200000) { d= ((c >> 18) & 0x07) | 0xF0;  bits= 12; } +	else if (c <  0x4000000) { d= ((c >> 24) & 0x03) | 0xF8;  bits= 18; } +	else if (c < 0x80000000) { d= ((c >> 30) & 0x01) | 0xFC;  bits= 24; } +	else return EOF; + +	if (putc (d, file) < 0) +		return EOF; + +	for ( ; bits >= 0; bits-= 6) +		if (putc (((c >> bits) & 0x3F) | 0x80, file) < 0) +			return EOF; + +	return 0; +} + +static void +putucs2str(uint16_t *ucs2str, FILE *file) +{ +	uint16_t	ucs2; + +	while ((ucs2 = *ucs2str++) != 0) +		putucs4(ucs2, file); +} +  int  main (int argc, char **argv)  { @@ -146,6 +187,7 @@ main (int argc, char **argv)  	int			num_file_symbols;  	uint32_t		flash_base, flash_bound;  	int			has_flash_size = 0; +	int			force = 0;  	while ((c = getopt_long(argc, argv, "wrT:D:c:s:v:", options, NULL)) != -1) {  		switch (c) { @@ -174,6 +216,9 @@ main (int argc, char **argv)  		case 'v':  			verbose++;  			break; +		case 'f': +			force = 1; +			break;  		default:  			usage(argv[0]);  			break; @@ -323,9 +368,52 @@ main (int argc, char **argv)  			}  		} +		if (!force && was_flashed) { +			struct ao_usb_id	new_id, old_id; +			uint16_t		*new_product, *old_product; +			int			new_len, old_len; + +			if (!ao_heximage_usb_id(load, &new_id)) { +				fprintf(stderr, "Can't get new USB id\n"); +				done(cc, 1); +			} + +			if (!ao_self_get_usb_id(cc, &old_id)) { +				fprintf(stderr, "Can't get old USB id\n"); +				done(cc, 1); +			} +			if (new_id.vid != old_id.vid || new_id.pid != old_id.pid) { +				fprintf(stderr, "USB ID mismatch (device is %04x/%04x image is %04x/%04x)\n", +					old_id.vid, old_id.pid, new_id.vid, new_id.pid); +				done(cc, 1); +			} + +			new_product = ao_heximage_usb_product(load); +			if (!new_product) { +				fprintf(stderr, "Can't get new USB product name\n"); +				done(cc, 1); +			} +			old_product = ao_self_get_usb_product(cc); +			if (!old_product) { +				fprintf(stderr, "Can't get existing USB product name\n"); +				done(cc, 1); +			} +			new_len = ucs2len(new_product); +			old_len = ucs2len(old_product); +			if (1 || new_len != old_len || memcmp(new_product, old_product, new_len * 2) != 0) { +				fprintf(stderr, "USB product mismatch (device is "); +				putucs2str(new_product, stderr); +				fprintf(stderr, ", image is "); +				putucs2str(old_product, stderr); +				fprintf(stderr, ")\n"); +				done(cc, 1); +			} +		} +  		if (!ao_editaltos(load, serial, cal))  			done(cc, 1);  	} +	done(cc, 0);  	/* And flash the resulting image to the device  	 */ diff --git a/ao-tools/lib/ao-editaltos.c b/ao-tools/lib/ao-editaltos.c index 2a52c156..06009653 100644 --- a/ao-tools/lib/ao-editaltos.c +++ b/ao-tools/lib/ao-editaltos.c @@ -21,23 +21,23 @@  #include "ao-editaltos.h"  struct ao_sym ao_symbols[] = { -	{ +	[AO_ROMCONFIG_VERSION_INDEX] = {  		.name = "ao_romconfig_version",  		.required = 1  	}, -	{ +	[AO_ROMCONFIG_CHECK_INDEX] = {  		.name = "ao_romconfig_check",  		.required = 1  	}, -	{ +	[AO_SERIAL_NUMBER_INDEX] = {  		.name = "ao_serial_number",  		.required = 1  	}, -	{ +	[AO_RADIO_CAL_INDEX] = {  		.name = "ao_radio_cal",  		.required = 0  	}, -	{ +	[AO_USB_DESCRIPTORS_INDEX] = {  		.name = "ao_usb_descriptors",  		.required = 0  	}, @@ -58,13 +58,6 @@ rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length)  	if (address < load->address || load->address + load->length < address + length)  		return false; -	printf("rewrite %04x:", address); -	for (i = 0; i < length; i++) -		printf (" %02x", load->data[address - load->address + i]); -	printf(" ->"); -	for (i = 0; i < length; i++) -		printf (" %02x", data[i]); -	printf("\n");  	memcpy(load->data + address - load->address, data, length);  	return true;  } @@ -166,3 +159,81 @@ ao_editaltos(struct ao_hex_image *image,  	}  	return true;  } + +static uint16_t +read_le16(uint8_t *src) +{ +	return (uint16_t) src[0] | ((uint16_t) src[1] << 8); +} + +bool +ao_heximage_usb_id(struct ao_hex_image *image, struct ao_usb_id *id) +{ +	uint32_t	usb_descriptors; + +	if (!AO_USB_DESCRIPTORS) +		return false; +	usb_descriptors = AO_USB_DESCRIPTORS - image->address; + +	while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) { +		if (image->data[usb_descriptors+1] == AO_USB_DESC_DEVICE) { +			break; +		} +		usb_descriptors += image->data[usb_descriptors]; +	} + +	/* +	 * check to make sure there's at least 0x12 (size of a USB +	 * device descriptor) available +	 */ +	if (usb_descriptors >= image->length || image->data[usb_descriptors] != 0x12) +		return false; + +	id->vid = read_le16(image->data + usb_descriptors + 8); +	id->pid = read_le16(image->data + usb_descriptors + 10); + +	return true; +} + +uint16_t * +ao_heximage_usb_product(struct ao_hex_image *image) +{ +	uint32_t	usb_descriptors; +	int		string_num; +	uint16_t	*product; +	uint8_t		product_len; + +	if (!AO_USB_DESCRIPTORS) +		return NULL; +	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 == 3) +				break; +		} +		usb_descriptors += image->data[usb_descriptors]; +	} + +	/* +	 * check to make sure there's at least 0x12 (size of a USB +	 * device descriptor) available +	 */ +	if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0) +		return NULL; + +	product_len = image->data[usb_descriptors] - 2; + +	if (usb_descriptors < product_len + 2) +		return NULL; + +	product = malloc (product_len + 2); +	if (!product) +		return NULL; + +	memcpy(product, image->data + usb_descriptors + 2, product_len); +	product[product_len/2] = 0; +	return product; +} diff --git a/ao-tools/lib/ao-editaltos.h b/ao-tools/lib/ao-editaltos.h index a480954b..6f2829b0 100644 --- a/ao-tools/lib/ao-editaltos.h +++ b/ao-tools/lib/ao-editaltos.h @@ -26,19 +26,31 @@  extern struct ao_sym ao_symbols[];  extern int ao_num_symbols; +#define AO_USB_DESC_DEVICE		1  #define AO_USB_DESC_STRING		3 -#define AO_ROMCONFIG_VERSION	(ao_symbols[0].addr) -#define AO_ROMCONFIG_CHECK	(ao_symbols[1].addr) -#define AO_SERIAL_NUMBER	(ao_symbols[2].addr) -#define AO_RADIO_CAL		(ao_symbols[3].addr) -#define AO_USB_DESCRIPTORS	(ao_symbols[4].addr) +#define AO_ROMCONFIG_VERSION_INDEX	0 +#define AO_ROMCONFIG_CHECK_INDEX	1 +#define AO_SERIAL_NUMBER_INDEX		2 +#define AO_RADIO_CAL_INDEX		3 +#define AO_USB_DESCRIPTORS_INDEX	4 + +#define AO_ROMCONFIG_VERSION	(ao_symbols[AO_ROMCONFIG_VERSION_INDEX].addr) +#define AO_ROMCONFIG_CHECK	(ao_symbols[AO_ROMCONFIG_CHECK_INDEX].addr) +#define AO_SERIAL_NUMBER	(ao_symbols[AO_SERIAL_NUMBER_INDEX].addr) +#define AO_RADIO_CAL		(ao_symbols[AO_RADIO_CAL_INDEX].addr) +#define AO_USB_DESCRIPTORS	(ao_symbols[AO_USB_DESCRIPTORS_INDEX].addr)  struct ao_editaltos_funcs {  	uint16_t	(*get_uint16)(void *closure, uint32_t addr);  	uint32_t	(*get_uint32)(void *closure, uint32_t addr);  }; +struct ao_usb_id { +	uint16_t	vid; +	uint16_t	pid; +}; +  bool  ao_editaltos_find_symbols(struct ao_sym *file_symbols, int num_file_symbols,  			  struct ao_sym *symbols, int num_symbols); @@ -48,4 +60,10 @@ ao_editaltos(struct ao_hex_image *image,  	     uint16_t serial,  	     uint32_t radio_cal); +bool +ao_heximage_usb_id(struct ao_hex_image *image, struct ao_usb_id *id); + +uint16_t * +ao_heximage_usb_product(struct ao_hex_image *image); +  #endif /* _AO_EDITALTOS_H_ */ diff --git a/ao-tools/lib/ao-selfload.c b/ao-tools/lib/ao-selfload.c index b4b878d1..0a23dfda 100644 --- a/ao-tools/lib/ao-selfload.c +++ b/ao-tools/lib/ao-selfload.c @@ -157,3 +157,40 @@ ao_self_get_uint32(struct cc_usb *cc, uint32_t addr)  	free(hex);  	return v;  } + +bool +ao_self_get_usb_id(struct cc_usb *cc, struct ao_usb_id *id) +{ +	struct ao_hex_image	*hex; +	bool			ret; + +	if (!AO_USB_DESCRIPTORS) +		return false; + +	hex = ao_self_read(cc, AO_USB_DESCRIPTORS, 512); +	if (!hex) +		return false; + +	ret = ao_heximage_usb_id(hex, id); +	free(hex); +	return ret; +} + +uint16_t * +ao_self_get_usb_product(struct cc_usb *cc) +{ +	struct ao_hex_image	*hex; +	uint16_t 		*ret; + +	if (!AO_USB_DESCRIPTORS) +		return NULL; + +	hex = ao_self_read(cc, AO_USB_DESCRIPTORS, 512); +	if (!hex) +		return NULL; + +	ret = ao_heximage_usb_product(hex); +	free(hex); +	return ret; +} + diff --git a/ao-tools/lib/ao-selfload.h b/ao-tools/lib/ao-selfload.h index 71529d1e..4aac5848 100644 --- a/ao-tools/lib/ao-selfload.h +++ b/ao-tools/lib/ao-selfload.h @@ -22,6 +22,7 @@  #include <stdbool.h>  #include "ao-hex.h"  #include "cc-usb.h" +#include "ao-editaltos.h"  struct ao_hex_image *  ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length); @@ -35,4 +36,13 @@ ao_self_get_uint16(struct cc_usb *cc, uint32_t addr);  uint32_t  ao_self_get_uint32(struct cc_usb *cc, uint32_t addr); +bool +ao_self_get_usb_id(struct cc_usb *cc, struct ao_usb_id *id); + +uint16_t * +ao_self_get_usb_product(struct cc_usb *cc); + +uint16_t * +ao_self_get_usb_product(struct cc_usb *cc); +  #endif /* _AO_SELFLOAD_H_ */  | 
