+ 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]);
+ }
+
+ public void add_symbol(AltosHexsym symbol) {
+ symlist.add(symbol);
+ }
+
+ /* Take symbols from another hexfile and duplicate them here */
+ public void add_symbols(AltosHexfile other) {
+ for (AltosHexsym symbol : other.symlist)
+ symlist.add(symbol);
+ }
+
+ public AltosHexsym lookup_symbol(String name) {
+ if (symlist.isEmpty())
+ add_cc_symbols();
+
+ for (AltosHexsym symbol : symlist)
+ if (name.equals(symbol.name))
+ return symbol;
+ return null;
+ }
+
+ private long find_usb_descriptors() {
+ AltosHexsym usb_descriptors = lookup_symbol("ao_usb_descriptors");
+ long a;
+
+ if (usb_descriptors == null)
+ return -1;
+
+ try {
+ /* The address of this has moved depending on
+ * padding in the linker script. Look forward
+ * and backwards two bytes to see if we can find it
+ */
+ a = usb_descriptors.address;
+
+ if (get_u8(a) == 0x12 && get_u8(a+1) == AO_USB_DESC_DEVICE)
+ return a;
+ else if (get_u8(a+1) == 0x12 && get_u8(a+3) == AO_USB_DESC_DEVICE)
+ return a + 2;
+ else if (get_u8(a-2) == 0x12 && get_u8(a-1) == AO_USB_DESC_DEVICE)
+ return a - 2;
+
+ return -1;
+ } catch (ArrayIndexOutOfBoundsException ae) {
+ return -1;
+ }
+ }
+
+ 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);
+
+ 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);
+
+ product += Character.toString((char) c);
+ }
+
+ if (AltosLink.debug)
+ 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++)
+ s += (char) data[start + i];
+ return s;
+ }
+
+ public AltosHexfile(byte[] bytes, long offset) {
+ data = bytes;
+ address = offset;
+ max_address = address + bytes.length;