This should avoid mis-programming devices with incorrect firmware.
Signed-off-by: Keith Packard <keithp@keithp.com>
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);
if (!aborted) {
action("done", 100);
if (debug != null) {
- debug.set_pc(image.address);
+ debug.set_pc((int) image.address);
debug.resume();
}
}
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;
}
class HexRecord implements Comparable<Object> {
- public int address;
+ public long address;
public int type;
public byte checksum;
public byte[] data;
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() {
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;
switch (state) {
case length:
- data = new byte[hex];
+ data = new byte[(int) hex];
state = read_state.address;
nhexbytes = 4;
break;
nhexbytes = 2;
break;
case type:
- type = hex;
+ type = (int) hex;
if (data.length > 0)
state = read_state.data;
else
}
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
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]);
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++)
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 {
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 */
}
}
}
-}
\ No newline at end of file
+}
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
+}
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;
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) {
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;
}
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,
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);
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 {
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);
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 {
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;
input = new FileInputStream(file);
image = new AltosHexfile(input);
}
-}
\ No newline at end of file
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
AltosRomconfig.java \
AltosSavedState.java \
AltosSelfFlash.java \
+ AltosUsbId.java \
AltosSensorMM.java \
AltosSensorEMini.java \
AltosSensorTM.java \
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;
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();
}
});