+ return ERROR_OK;
+ }
+ else if (strstr(packet, "qCRC:"))
+ {
+ if (packet_size > 5)
+ {
+ int retval;
+ char gdb_reply[10];
+ char *separator;
+ uint32_t checksum;
+ uint32_t addr = 0;
+ uint32_t len = 0;
+
+ /* skip command character */
+ packet += 5;
+
+ addr = strtoul(packet, &separator, 16);
+
+ if (*separator != ',')
+ {
+ LOG_ERROR("incomplete read memory packet received, dropping connection");
+ return ERROR_SERVER_REMOTE_CLOSED;
+ }
+
+ len = strtoul(separator + 1, NULL, 16);
+
+ retval = target_checksum_memory(target, addr, len, &checksum);
+
+ if (retval == ERROR_OK)
+ {
+ snprintf(gdb_reply, 10, "C%8.8" PRIx32 "", checksum);
+ gdb_put_packet(connection, gdb_reply, 9);
+ }
+ else
+ {
+ if ((retval = gdb_error(connection, retval)) != ERROR_OK)
+ return retval;
+ }
+
+ return ERROR_OK;
+ }
+ }
+ else if (strstr(packet, "qSupported"))
+ {
+ /* we currently support packet size and qXfer:memory-map:read (if enabled)
+ * disable qXfer:features:read for the moment */
+ int retval = ERROR_OK;
+ char *buffer = NULL;
+ int pos = 0;
+ int size = 0;
+
+ xml_printf(&retval, &buffer, &pos, &size,
+ "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-;QStartNoAckMode+",
+ (GDB_BUFFER_SIZE - 1), ((gdb_use_memory_map == 1)&&(flash_get_bank_count()>0)) ? '+' : '-');
+
+ if (retval != ERROR_OK)
+ {
+ gdb_send_error(connection, 01);
+ return ERROR_OK;
+ }
+
+ gdb_put_packet(connection, buffer, strlen(buffer));
+ free(buffer);
+
+ return ERROR_OK;
+ }
+ else if (strstr(packet, "qXfer:memory-map:read::")&&(flash_get_bank_count()>0))
+ {
+ /* We get away with only specifying flash here. Regions that are not
+ * specified are treated as if we provided no memory map(if not we
+ * could detect the holes and mark them as RAM).
+ * Normally we only execute this code once, but no big deal if we
+ * have to regenerate it a couple of times. */
+
+ flash_bank_t *p;
+ char *xml = NULL;
+ int size = 0;
+ int pos = 0;
+ int retval = ERROR_OK;
+
+ int offset;
+ int length;
+ char *separator;
+ int blocksize;
+
+ /* 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 make non-flash memory be ram(or rather
+ read/write) by default for GDB.
+ GDB does not have a concept of non-cacheable read/write memory.
+ */
+ flash_bank_t **banks=malloc(sizeof(flash_bank_t *)*flash_get_bank_count());
+ int i;
+
+ for (i=0; i<flash_get_bank_count(); i++)
+ {
+ p = get_flash_bank_by_num(i);
+ if (p == NULL)
+ {
+ free(banks);
+ retval = ERROR_FAIL;
+ gdb_send_error(connection, retval);
+ return retval;
+ }
+ banks[i]=p;
+ }
+
+ qsort(banks, flash_get_bank_count(), sizeof(flash_bank_t *), compare_bank);
+
+ uint32_t ram_start=0;
+ for (i=0; i<flash_get_bank_count(); i++)
+ {
+ p = banks[i];
+
+ 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);
+ }
+
+ /* if device has uneven sector sizes, eg. str7, lpc
+ * we pass the smallest sector size to gdb memory map */
+ blocksize = gdb_calc_blocksize(p);
+
+ xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
+ "<property name=\"blocksize\">0x%x</property>\n" \
+ "</memory>\n", \
+ p->base, p->size, blocksize);
+ 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_send_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;
+ }
+ else if (strstr(packet, "qXfer:features:read:"))
+ {
+ char *xml = NULL;
+ int size = 0;
+ int pos = 0;
+ int retval = ERROR_OK;
+
+ int offset;
+ unsigned int length;
+ char *annex;
+
+ /* skip command character */
+ packet += 20;
+
+ if (decode_xfer_read(packet, &annex, &offset, &length) < 0)
+ {
+ gdb_send_error(connection, 01);
+ return ERROR_OK;
+ }
+
+ if (strcmp(annex, "target.xml") != 0)
+ {
+ gdb_send_error(connection, 01);
+ return ERROR_OK;
+ }
+
+ xml_printf(&retval, &xml, &pos, &size, \
+ "l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");
+
+ if (retval != ERROR_OK)
+ {
+ gdb_send_error(connection, retval);
+ return retval;
+ }
+
+ gdb_put_packet(connection, xml, strlen(xml));
+
+ free(xml);
+ return ERROR_OK;
+ }
+ else if (strstr(packet, "QStartNoAckMode"))
+ {
+ gdb_connection->noack_mode = 1;
+ gdb_put_packet(connection, "OK", 2);
+ return ERROR_OK;