+ struct target *target = get_target_from_connection(connection);
+ struct flash_bank *p;
+ char *xml = NULL;
+ int size = 0;
+ int pos = 0;
+ int retval = ERROR_OK;
+ struct flash_bank **banks;
+ int offset;
+ int length;
+ char *separator;
+ uint32_t ram_start = 0;
+ int i;
+ int target_flash_banks = 0;
+
+ /* skip command character */
+ packet += 23;
+
+ offset = strtoul(packet, &separator, 16);
+ length = strtoul(separator + 1, &separator, 16);
+
+ xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
+
+ /* Sort banks in ascending order. We need to report non-flash
+ * memory as ram (or rather read/write) by default for GDB, since
+ * it has no concept of non-cacheable read/write memory (i/o etc).
+ *
+ * FIXME Most non-flash addresses are *NOT* RAM! Don't lie.
+ * Current versions of GDB assume unlisted addresses are RAM...
+ */
+ banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
+
+ for (i = 0; i < flash_get_bank_count(); i++) {
+ retval = get_flash_bank_by_num(i, &p);
+ if (retval != ERROR_OK) {
+ free(banks);
+ gdb_error(connection, retval);
+ return retval;
+ }
+ if (p->target == target)
+ banks[target_flash_banks++] = p;
+ }
+
+ qsort(banks, target_flash_banks, sizeof(struct flash_bank *),
+ compare_bank);
+
+ for (i = 0; i < target_flash_banks; i++) {
+ int j;
+ unsigned sector_size = 0;
+ uint32_t start;
+
+ p = banks[i];
+ start = p->base;
+
+ if (ram_start < p->base)
+ xml_printf(&retval, &xml, &pos, &size,
+ "<memory type=\"ram\" start=\"0x%x\" "
+ "length=\"0x%x\"/>\n",
+ ram_start, p->base - ram_start);
+
+ /* Report adjacent groups of same-size sectors. So for
+ * example top boot CFI flash will list an initial region
+ * with several large sectors (maybe 128KB) and several
+ * smaller ones at the end (maybe 32KB). STR7 will have
+ * regions with 8KB, 32KB, and 64KB sectors; etc.
+ */
+ for (j = 0; j < p->num_sectors; j++) {
+ unsigned group_len;
+
+ /* Maybe start a new group of sectors. */
+ if (sector_size == 0) {
+ start = p->base + p->sectors[j].offset;
+ xml_printf(&retval, &xml, &pos, &size,
+ "<memory type=\"flash\" "
+ "start=\"0x%x\" ",
+ start);
+ sector_size = p->sectors[j].size;
+ }
+
+ /* Does this finish a group of sectors?
+ * If not, continue an already-started group.
+ */
+ if (j == p->num_sectors - 1)
+ group_len = (p->base + p->size) - start;
+ else if (p->sectors[j + 1].size != sector_size)
+ group_len = p->base + p->sectors[j + 1].offset
+ - start;
+ else
+ continue;
+
+ xml_printf(&retval, &xml, &pos, &size,
+ "length=\"0x%x\">\n"
+ "<property name=\"blocksize\">"
+ "0x%x</property>\n"
+ "</memory>\n",
+ group_len,
+ sector_size);
+ sector_size = 0;
+ }
+
+ ram_start = p->base + p->size;
+ }
+
+ if (ram_start != 0)
+ xml_printf(&retval, &xml, &pos, &size,
+ "<memory type=\"ram\" start=\"0x%x\" "
+ "length=\"0x%x\"/>\n",
+ ram_start, 0-ram_start);
+ /* ELSE a flash chip could be at the very end of the 32 bit address
+ * space, in which case ram_start will be precisely 0
+ */
+
+ free(banks);
+ banks = NULL;
+
+ xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
+
+ if (retval != ERROR_OK) {
+ gdb_error(connection, retval);
+ return retval;
+ }
+
+ if (offset + length > pos)
+ length = pos - offset;
+
+ char *t = malloc(length + 1);
+ t[0] = 'l';
+ memcpy(t + 1, xml + offset, length);
+ gdb_put_packet(connection, t, length + 1);
+
+ free(t);
+ free(xml);
+ return ERROR_OK;
+}
+
+static const char *gdb_get_reg_type_name(enum reg_type type)
+{
+ switch (type) {
+ case REG_TYPE_INT:
+ return "int";
+ case REG_TYPE_INT8:
+ return "int8";
+ case REG_TYPE_INT16:
+ return "int16";
+ case REG_TYPE_INT32:
+ return "int32";
+ case REG_TYPE_INT64:
+ return "int64";
+ case REG_TYPE_INT128:
+ return "int128";
+ case REG_TYPE_UINT8:
+ return "uint8";
+ case REG_TYPE_UINT16:
+ return "uint16";
+ case REG_TYPE_UINT32:
+ return "uint32";
+ case REG_TYPE_UINT64:
+ return "uint64";
+ case REG_TYPE_UINT128:
+ return "uint128";
+ case REG_TYPE_CODE_PTR:
+ return "code_ptr";
+ case REG_TYPE_DATA_PTR:
+ return "data_ptr";
+ case REG_TYPE_FLOAT:
+ return "float";
+ case REG_TYPE_IEEE_SINGLE:
+ return "ieee_single";
+ case REG_TYPE_IEEE_DOUBLE:
+ return "ieee_double";
+ case REG_TYPE_ARCH_DEFINED:
+ return "int"; /* return arbitrary string to avoid compile warning. */
+ }
+
+ return "int"; /* "int" as default value */
+}
+
+static int gdb_generate_reg_type_description(struct target *target,
+ char **tdesc, int *pos, int *size, struct reg_data_type *type)
+{
+ int retval = ERROR_OK;
+
+ if (type->type_class == REG_TYPE_CLASS_VECTOR) {
+ /* <vector id="id" type="type" count="count"/> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>\n",
+ type->id, type->reg_type_vector->type->id,
+ type->reg_type_vector->count);
+
+ } else if (type->type_class == REG_TYPE_CLASS_UNION) {
+ /* <union id="id">
+ * <field name="name" type="type"/> ...
+ * </union> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<union id=\"%s\">\n",
+ type->id);
+
+ struct reg_data_type_union_field *field;
+ field = type->reg_type_union->fields;
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" type=\"%s\"/>\n",
+ field->name, field->type->id);
+
+ field = field->next;
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</union>\n");
+
+ } else if (type->type_class == REG_TYPE_CLASS_STRUCT) {
+ struct reg_data_type_struct_field *field;
+ field = type->reg_type_struct->fields;
+
+ if (field->use_bitfields) {
+ /* <struct id="id" size="size">
+ * <field name="name" start="start" end="end"/> ...
+ * </struct> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<struct id=\"%s\" size=\"%d\">\n",
+ type->id, type->reg_type_struct->size);
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n",
+ field->name, field->bitfield->start,
+ field->bitfield->end);
+
+ field = field->next;
+ }
+ } else {
+ /* <struct id="id">
+ * <field name="name" type="type"/> ...
+ * </struct> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<struct id=\"%s\">\n",
+ type->id);
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" type=\"%s\"/>\n",
+ field->name, field->type->id);
+
+ field = field->next;
+ }
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</struct>\n");
+
+ } else if (type->type_class == REG_TYPE_CLASS_FLAGS) {
+ /* <flags id="id" size="size">
+ * <field name="name" start="start" end="end"/> ...
+ * </flags> */
+ xml_printf(&retval, tdesc, pos, size,
+ "<flags id=\"%s\" size=\"%d\">\n",
+ type->id, type->reg_type_flags->size);
+
+ struct reg_data_type_flags_field *field;
+ field = type->reg_type_flags->fields;
+ while (field != NULL) {
+ xml_printf(&retval, tdesc, pos, size,
+ "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n",
+ field->name, field->bitfield->start, field->bitfield->end);
+
+ field = field->next;
+ }
+
+ xml_printf(&retval, tdesc, pos, size,
+ "</flags>\n");