diff options
| -rw-r--r-- | altoslib/AltosFlash.java | 10 | ||||
| -rw-r--r-- | altoslib/AltosHexfile.java | 137 | ||||
| -rw-r--r-- | altoslib/AltosProgrammer.java | 6 | ||||
| -rw-r--r-- | altoslib/AltosRomconfig.java | 71 | ||||
| -rw-r--r-- | altoslib/AltosSelfFlash.java | 41 | ||||
| -rw-r--r-- | altoslib/AltosUsbId.java | 26 | ||||
| -rw-r--r-- | altoslib/Makefile.am | 1 | ||||
| -rw-r--r-- | altosuilib/AltosFlashUI.java | 37 | 
8 files changed, 281 insertions, 48 deletions
| diff --git a/altoslib/AltosFlash.java b/altoslib/AltosFlash.java index c8db1f77..9bf0da25 100644 --- a/altoslib/AltosFlash.java +++ b/altoslib/AltosFlash.java @@ -254,7 +254,7 @@ public class AltosFlash extends AltosProgrammer {  			clock_init();  			int remain = image.data.length; -			int flash_addr = image.address; +			int flash_addr = (int) image.address;  			int image_start = 0;  			action("start", 0); @@ -295,7 +295,7 @@ public class AltosFlash extends AltosProgrammer {  			if (!aborted) {  				action("done", 100);  				if (debug != null) { -					debug.set_pc(image.address); +					debug.set_pc((int) image.address);  					debug.resume();  				}  			} @@ -331,12 +331,16 @@ public class AltosFlash extends AltosProgrammer {  		rom_config = romconfig;  	} -	public AltosRomconfig romconfig() throws InterruptedException { +	public AltosRomconfig target_romconfig() throws InterruptedException {  		if (!check_rom_config())  			return null;  		return rom_config;  	} +	public AltosRomconfig image_romconfig() { +		return new AltosRomconfig(image); +	} +  	public AltosFlash(File file, AltosLink link, AltosFlashListener listener)  		throws IOException, FileNotFoundException, InterruptedException {  		this.file = file; diff --git a/altoslib/AltosHexfile.java b/altoslib/AltosHexfile.java index 7ab121ad..6aa98383 100644 --- a/altoslib/AltosHexfile.java +++ b/altoslib/AltosHexfile.java @@ -46,7 +46,7 @@ class HexFileInputStream extends PushbackInputStream {  }  class HexRecord implements Comparable<Object> { -	public int	address; +	public long	address;  	public int	type;  	public byte	checksum;  	public byte[]	data; @@ -110,7 +110,14 @@ class HexRecord implements Comparable<Object> {  	public int compareTo(Object other) {  		HexRecord	o = (HexRecord) other; -		return address - o.address; + +		long diff = address - o.address; + +		if (diff > 0) +			return 1; +		if (diff < 0) +			return -1; +		return 0;  	}  	public String toString() { @@ -119,8 +126,8 @@ class HexRecord implements Comparable<Object> {  	public HexRecord(HexFileInputStream input) throws IOException, EOFException {  		read_state	state = read_state.marker; -		int		nhexbytes = 0; -		int		hex = 0; +		long		nhexbytes = 0; +		long		hex = 0;  		int		ndata = 0;  		byte		got_checksum; @@ -154,7 +161,7 @@ class HexRecord implements Comparable<Object> {  				switch (state) {  				case length: -					data = new byte[hex]; +					data = new byte[(int) hex];  					state = read_state.address;  					nhexbytes = 4;  					break; @@ -164,7 +171,7 @@ class HexRecord implements Comparable<Object> {  					nhexbytes = 2;  					break;  				case type: -					type = hex; +					type = (int) hex;  					if (data.length > 0)  						state = read_state.data;  					else @@ -211,12 +218,21 @@ class HexRecord implements Comparable<Object> {  }  public class AltosHexfile { -	public int		address; +	public long		address; +	public long		max_address;  	public byte[]		data;  	LinkedList<AltosHexsym>	symlist = new LinkedList<AltosHexsym>(); -	public byte get_byte(int a) { -		return data[a - address]; +	public byte get_byte(long a) { +		return data[(int) (a - address)]; +	} + +	public int get_u8(long a) { +		return ((int) get_byte(a)) & 0xff; +	} + +	public int get_u16(long a) { +		return get_u8(a) | (get_u8(a+1) << 8);  	}  	/* CC1111-based products have the romconfig stuff located @@ -237,6 +253,15 @@ public class AltosHexfile {  		new AltosHexsym("ao_usb_descriptors", ao_usb_descriptors_addr)  	}; +	static final int AO_USB_DESC_DEVICE		= 1; +	static final int AO_USB_DESC_STRING		= 3; + +	static final int AO_ROMCONFIG_VERSION_INDEX	= 0; +	static final int AO_ROMCONFIG_CHECK_INDEX	= 1; +	static final int AO_SERIAL_NUMBER_INDEX		= 2; +	static final int AO_RADIO_CAL_INDEX		= 3; +	static final int AO_USB_DESCRIPTORS_INDEX	= 4; +  	private void add_cc_symbols() {  		for (int i = 0; i < cc_symbols.length; i++)  			symlist.add(cc_symbols[i]); @@ -262,6 +287,92 @@ public class AltosHexfile {  		return null;  	} +	private long find_usb_descriptors() { +		AltosHexsym	usb_descriptors = lookup_symbol("ao_usb_descriptors"); +		long		a; + +		if (usb_descriptors == null) +			return -1; + +		/* Walk the descriptors looking for the device */ +		a = usb_descriptors.address; +		while (get_u8(a+1) != AO_USB_DESC_DEVICE) { +			int delta = get_u8(a); +			a += delta; +			if (delta == 0 || a >= max_address) +				return -1; +		} +		return a; +	} + +	public AltosUsbId find_usb_id() { +		long a = find_usb_descriptors(); + +		if (a == -1) +			return null; + +		/* Walk the descriptors looking for the device */ +		while (get_u8(a+1) != AO_USB_DESC_DEVICE) { +			int delta = get_u8(a); +			a += delta; +			if (delta == 0 || a >= max_address) +				return null; +		} + +		return new AltosUsbId(get_u16(a + 8), +				      get_u16(a + 10)); +	} + +	public String find_usb_product() { +		long		a = find_usb_descriptors(); +		int		num_strings; +		int		product_string; + +		if (a == -1) +			return null; + +		product_string = get_u8(a+15); + +		/* Walk the descriptors looking for the device */ +		num_strings = 0; +		for (;;) { +			if (get_u8(a+1) == AO_USB_DESC_STRING) { +				++num_strings; +				if (num_strings == product_string + 1) +					break; +			} + +			int delta = get_u8(a); +			a += delta; +			if (delta == 0 || a >= max_address) +				return null; +		} + +		int product_len = get_u8(a); + +		System.out.printf("Product is at %x length %d\n", a, product_len); + +		for (int i = 0; i < product_len; i++) +			System.out.printf(" %2d: %02x\n", i, get_u8(a+i)); + +		if (product_len <= 0) +			return null; + +		String product = ""; + +		for (int i = 0; i < product_len - 2; i += 2) { +			int	c = get_u16(a + 2 + i); + +			System.out.printf("character %x\n", c); + +			product += Character.toString((char) c); +		} + +		System.out.printf("product %s\n", product); + +		return product; +	} +  	private String make_string(byte[] data, int start, int length) {  		String s = "";  		for (int i = 0; i < length; i++) @@ -269,9 +380,10 @@ public class AltosHexfile {  		return s;  	} -	public AltosHexfile(byte[] bytes, int offset) { +	public AltosHexfile(byte[] bytes, long offset) {  		data = bytes;  		address = offset; +		max_address = address + bytes.length;  	}  	public AltosHexfile(FileInputStream file) throws IOException { @@ -335,7 +447,8 @@ public class AltosHexfile {  			throw new IOException("hex file too large");  		data = new byte[(int) (bound - base)]; -		address = (int) base; +		address = base; +		max_address = bound;  		Arrays.fill(data, (byte) 0xff);  		/* Paint the records into the new array */ @@ -366,4 +479,4 @@ public class AltosHexfile {  			}  		}  	} -}
\ No newline at end of file +} diff --git a/altoslib/AltosProgrammer.java b/altoslib/AltosProgrammer.java index 0a828a32..e4f57578 100644 --- a/altoslib/AltosProgrammer.java +++ b/altoslib/AltosProgrammer.java @@ -28,7 +28,9 @@ public abstract class AltosProgrammer {  	abstract public void abort(); -	abstract public AltosRomconfig romconfig() throws InterruptedException; +	abstract public AltosRomconfig target_romconfig() throws InterruptedException; + +	abstract public AltosRomconfig image_romconfig();  	abstract public void set_romconfig(AltosRomconfig config); -}
\ No newline at end of file +} diff --git a/altoslib/AltosRomconfig.java b/altoslib/AltosRomconfig.java index 46ee2b6e..1fbb4115 100644 --- a/altoslib/AltosRomconfig.java +++ b/altoslib/AltosRomconfig.java @@ -26,20 +26,31 @@ public class AltosRomconfig {  	public int	check;  	public int	serial_number;  	public int	radio_calibration; +	public AltosUsbId	usb_id; +	public String		usb_product; -	static private int find_offset(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol { +	static private long find_address(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol {  		AltosHexsym symbol = hexfile.lookup_symbol(name); -		if (symbol == null) -			throw new AltosNoSymbol(name); -		int offset = (int) symbol.address - hexfile.address; -		if (offset < 0 || hexfile.data.length < offset + len) +		if (symbol == null) { +			System.out.printf("no symbol %s\n", name);  			throw new AltosNoSymbol(name); -		return offset; +		} +		if (hexfile.address <= symbol.address && symbol.address + len < hexfile.max_address) { +			System.out.printf("%s: %x\n", name, symbol.address); +			return symbol.address; +		} +		System.out.printf("invalid symbol addr %x range is %x - %x\n", +				  symbol.address, hexfile.address, hexfile.max_address); +		throw new AltosNoSymbol(name); +	} + +	static private int find_offset(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol { +		return (int) (find_address(hexfile, name, len) - hexfile.address);  	}  	static int get_int(AltosHexfile hexfile, String name, int len) throws AltosNoSymbol {  		byte[] bytes = hexfile.data; -		int start = find_offset(hexfile, name, len); +		int start = (int) find_offset(hexfile, name, len);  		int	v = 0;  		int	o = 0; @@ -112,13 +123,17 @@ public class AltosRomconfig {  	public AltosRomconfig(AltosHexfile hexfile) {  		try { +			System.out.printf("Attempting symbols\n");  			version = get_int(hexfile, ao_romconfig_version, 2); +			System.out.printf("version %d\n", version);  			check = get_int(hexfile, ao_romconfig_check, 2); +			System.out.printf("check %d\n", check);  			if (check == (~version & 0xffff)) {  				switch (version) {  				case 2:  				case 1:  					serial_number = get_int(hexfile, ao_serial_number, 2); +					System.out.printf("serial %d\n", serial_number);  					try {  						radio_calibration = get_int(hexfile, ao_radio_cal, 4);  					} catch (AltosNoSymbol missing) { @@ -128,6 +143,19 @@ public class AltosRomconfig {  					break;  				}  			} +			System.out.printf("attempting usbid\n"); +			usb_id = hexfile.find_usb_id(); +			if (usb_id == null) +				System.out.printf("No usb id\n"); +			else +				System.out.printf("usb id: %04x:%04x\n", +						  usb_id.vid, usb_id.pid); +			usb_product = hexfile.find_usb_product(); +			if (usb_product == null) +				System.out.printf("No usb product\n"); +			else +				System.out.printf("usb product: %s\n", usb_product); +  		} catch (AltosNoSymbol missing) {  			valid = false;  		} @@ -137,9 +165,16 @@ public class AltosRomconfig {  		ao_romconfig_version,  		ao_romconfig_check,  		ao_serial_number, -		ao_radio_cal +		ao_radio_cal, +		ao_usb_descriptors,  	}; +	private static int fetch_len(String name) { +		if (name.equals(ao_usb_descriptors)) +			return 256; +		return 2; +	} +  	private final static String[] required_names = {  		ao_romconfig_version,  		ao_romconfig_check, @@ -153,13 +188,16 @@ public class AltosRomconfig {  		return false;  	} -	public static int fetch_base(AltosHexfile hexfile) throws AltosNoSymbol { -		int	base = 0x7fffffff; +	public static long fetch_base(AltosHexfile hexfile) throws AltosNoSymbol { +		long	base = 0xffffffffL;  		for (String name : fetch_names) {  			try { -				int	addr = find_offset(hexfile, name, 2) + hexfile.address; +				int	len = fetch_len(name); +				long	addr = find_address(hexfile, name, len); +  				if (addr < base)  					base = addr; +				System.out.printf("symbol %s at %x base %x\n", name, addr, base);  			} catch (AltosNoSymbol ns) {  				if (name_required(name))  					throw (ns); @@ -168,19 +206,22 @@ public class AltosRomconfig {  		return base;  	} -	public static int fetch_bounds(AltosHexfile hexfile) throws AltosNoSymbol { -		int	bounds = 0; +	public static long fetch_bounds(AltosHexfile hexfile) throws AltosNoSymbol { +		long	bounds = 0;  		for (String name : fetch_names) {  			try { -				int	addr = find_offset(hexfile, name, 2) + hexfile.address; +				int	len = fetch_len(name); +				long	addr = find_address(hexfile, name, len) + len;  				if (addr > bounds)  					bounds = addr; +				System.out.printf("symbol %s at %x bounds %x\n", name, addr, bounds);  			} catch (AltosNoSymbol ns) {  				if (name_required(name))  					throw (ns);  			}  		} -		return bounds + 2; + +		return bounds;  	}  	public void write (AltosHexfile hexfile) throws IOException { diff --git a/altoslib/AltosSelfFlash.java b/altoslib/AltosSelfFlash.java index 53782172..c7ea147f 100644 --- a/altoslib/AltosSelfFlash.java +++ b/altoslib/AltosSelfFlash.java @@ -45,18 +45,33 @@ public class AltosSelfFlash extends AltosProgrammer {  		int b;  		byte[]	data = new byte[len]; +		System.out.printf("read_memory %x %d\n", addr, len);  		for (int offset = 0; offset < len; offset += 0x100) {  			link.printf("R %x\n", addr + offset);  			byte[]	reply = link.get_binary_reply(5000, 0x100);  			if (reply == null)  				throw new IOException("Read device memory timeout"); -			for (b = 0; b < len; b++) +			for (b = 0; b < 0x100 && b + offset < len; b++)  				data[b+offset] = reply[b];  		}  		return data;  	} +	AltosHexfile read_hexfile(long addr, int len) throws InterruptedException { +		try { +			byte[] mem = read_memory(addr, len); + +			AltosHexfile	hexfile = new AltosHexfile(mem, addr); + +			if (image != null) +				hexfile.add_symbols(image); +			return hexfile; +		} catch (IOException ie) { +			return null; +		} +	} +  	void write_memory(long addr, byte[] data, int start, int len) {  		int b;  		link.printf("W %x\n", addr); @@ -143,18 +158,14 @@ public class AltosSelfFlash extends AltosProgrammer {  	private AltosHexfile get_rom() throws InterruptedException {  		try { -			int base = AltosRomconfig.fetch_base(image); -			int bounds = AltosRomconfig.fetch_bounds(image); -			byte[] data = read_memory(base, bounds - base); -			AltosHexfile hexfile = new AltosHexfile(data, base); -			hexfile.add_symbols(image); -			return hexfile; -		} catch (AltosNoSymbol none) { -			return null; -		} catch (IOException ie) { +			long base = AltosRomconfig.fetch_base(image); +			long bounds = AltosRomconfig.fetch_bounds(image); + +			System.out.printf("rom base %x bounds %x\n", base, bounds); +			return read_hexfile(base, (int) (bounds - base)); +		} catch (AltosNoSymbol ns) {  			return null;  		} -  	}  	public boolean check_rom_config() throws InterruptedException { @@ -173,12 +184,16 @@ public class AltosSelfFlash extends AltosProgrammer {  		rom_config = romconfig;  	} -	public AltosRomconfig romconfig() throws InterruptedException { +	public AltosRomconfig target_romconfig() throws InterruptedException {  		if (!check_rom_config())  			return null;  		return rom_config;  	} +	public AltosRomconfig image_romconfig() { +		return new AltosRomconfig(image); +	} +  	public AltosSelfFlash(File file, AltosLink link, AltosFlashListener listener)  		throws IOException, FileNotFoundException, InterruptedException {  		this.file = file; @@ -187,4 +202,4 @@ public class AltosSelfFlash extends AltosProgrammer {  		input = new FileInputStream(file);  		image = new AltosHexfile(input);  	} -}
\ No newline at end of file +} diff --git a/altoslib/AltosUsbId.java b/altoslib/AltosUsbId.java new file mode 100644 index 00000000..e3794304 --- /dev/null +++ b/altoslib/AltosUsbId.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2018 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. + */ + +package org.altusmetrum.altoslib_12; + +public class AltosUsbId { +	public int	vid; +	public int	pid; + + +	public AltosUsbId(int vid, int pid) { +		this.vid = vid; +		this.pid = pid; +	} +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 2a1cb8e4..7c5d767d 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -99,6 +99,7 @@ altoslib_JAVA = \  	AltosRomconfig.java \  	AltosSavedState.java \  	AltosSelfFlash.java \ +	AltosUsbId.java \  	AltosSensorMM.java \  	AltosSensorEMini.java \  	AltosSensorTM.java \ diff --git a/altosuilib/AltosFlashUI.java b/altosuilib/AltosFlashUI.java index ca089ca8..c717e47c 100644 --- a/altosuilib/AltosFlashUI.java +++ b/altosuilib/AltosFlashUI.java @@ -276,8 +276,37 @@ public class AltosFlashUI  		return true;  	} -	boolean update_rom_config_info(AltosRomconfig existing_config) { +	boolean rom_config_matches (AltosRomconfig a, AltosRomconfig b) { +		if (a.usb_id != null && b.usb_id != null && +		    (a.usb_id.vid != b.usb_id.vid || +		     a.usb_id.pid != b.usb_id.pid)) +			return false; + +		if (a.usb_product != null && b.usb_product != null && +		    !a.usb_product.equals(b.usb_product)) +			return false; + +		return true; +	} + +	boolean update_rom_config_info(AltosRomconfig existing_config, AltosRomconfig image_config) {  		AltosRomconfig	new_config; + +		if (!rom_config_matches(existing_config, image_config)) { +			int ret = JOptionPane.showConfirmDialog(this, +								String.format("Device is %04x:%04x %s\nImage is %04x:%04x %s\nFlash anyways?", +									      existing_config.usb_id.vid, +									      existing_config.usb_id.pid, +									      existing_config.usb_product, +									      image_config.usb_id.vid, +									      image_config.usb_id.pid, +									      image_config.usb_product), +								"Image doesn't match Device", +								JOptionPane.YES_NO_OPTION); +			if (ret != JOptionPane.YES_OPTION) +				return false; +		} +  		new_config = AltosRomconfigUI.show(frame, existing_config);  		if (new_config == null)  			return false; @@ -335,13 +364,15 @@ public class AltosFlashUI  				else  					programmer = new AltosSelfFlash(ui.file, link, this); -				final AltosRomconfig	current_config = programmer.romconfig(); +				final AltosRomconfig	current_config = programmer.target_romconfig(); + +				final AltosRomconfig	image_config = programmer.image_romconfig();  				final Semaphore await_rom_config = new Semaphore(0);  				SwingUtilities.invokeLater(new Runnable() {  						public void run() {  							ui.programmer = programmer; -							ui.update_rom_config_info(current_config); +							ui.update_rom_config_info(current_config, image_config);  							await_rom_config.release();  						}  					}); | 
