[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openocd-development
Subject:    [OpenOCD-devel] [PATCH]: 37c20e1 Add functions for memory map support
From:       gerrit () openocd ! org (gerrit)
Date:       2015-07-16 16:31:40
Message-ID: 20150716163140.6E7A21980724 () mail ! openocd ! org
[Download RAW message or body]

This is an automated email from Gerrit.

Evan Hunter (evanhunter920@gmail.com) just uploaded a new patch set to Gerrit, which \
you can find at http://openocd.zylin.com/2870

-- gerrit

commit 37c20e114ff8961124d0b8e4be76984eb5acb14f
Author: Evan Hunter <ehunter@broadcom.com>
Date:   Thu Jul 16 16:23:29 2015 +0100

    Add functions for memory map support
    
    Allows definition of a memory map of valid memory areas, so that OpenOCD will \
know to avoid attempting to read from invalid addresses.  
    Example usage:
    	$_TARGETNAME configure -memorymap RO 0x00400000 0x00090000 ROM        "ROM"
    	$_TARGETNAME configure -memorymap RW 0x004A0000 0x00202000 RAM        "RAM"
    
    Parameters are : <RO|WO|RW> <start_address> <size> <short_name> <long_name>
    
    This could be extended to tell GDB about the memory map via the \
"qXfer:memory-map:read" packet  
    Change-Id: I829ea85d677199737d39b36b369727c5fbd40387
    Signed-off-by: Evan Hunter <ehunter@broadcom.com>

diff --git a/src/target/target.c b/src/target/target.c
index 4ea445f..57e1dc1 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -69,6 +69,7 @@ static int target_array2mem(Jim_Interp *interp, struct target \
*target,  static int target_mem2array(Jim_Interp *interp, struct target *target,
 		int argc, Jim_Obj * const *argv);
 static int target_register_user_commands(struct command_context *cmd_ctx);
+static int add_memory_mapping(Jim_GetOptInfo *goi, struct target *target);
 static int target_get_gdb_fileio_info_default(struct target *target,
 		struct gdb_fileio_info *fileio_info);
 static int target_gdb_fileio_end_default(struct target *target, int retcode,
@@ -1017,6 +1018,37 @@ int target_run_flash_async_algorithm(struct target *target,
 int target_read_memory(struct target *target,
 		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
+	if (target->memory_map_list_head != NULL) {
+		/* There is a memory map defined for this target
+		 * Check that the requested read is for a location that is valid
+		 * according to the memory map
+		 */
+		uint64_t bytes_read = 0;
+		struct memory_map_elem *curr_elem = target->memory_map_list_head;
+		memset(buffer, 0, count*size);
+		do {
+			/* Calculate the intersection of the request and the current memory map block (if \
any) */ +			uint64_t start = MAX(curr_elem->start_address, address);
+			uint64_t end   = MIN(curr_elem->start_address + curr_elem->size, address + \
count*size); +
+			/* If there is data that can be read from this block, read it */
+			if ((end > start) &&
+			    (curr_elem->access != MEMORY_MAP_WRITE_ONLY)) {
+				int retval = target->type->read_memory(target, start, 1, (end - start), buffer);
+				if (retval != 0)
+					return retval;
+
+				bytes_read += (end - start);
+			}
+			curr_elem = curr_elem->next_elem;
+		} while (curr_elem != NULL);
+		if (count*size != bytes_read) {
+			LOG_WARNING("Ignoring read of non readable area - Request address: 0x%X, "
+						"Request size %d. Bytes successfully read: %d", address, count*size, \
(int)bytes_read); +		}
+		return ERROR_OK;
+	}
+
 	if (!target_was_examined(target)) {
 		LOG_ERROR("Target not examined yet");
 		return ERROR_FAIL;
@@ -1037,6 +1069,36 @@ int target_read_phys_memory(struct target *target,
 int target_write_memory(struct target *target,
 		uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
+	if (target->memory_map_list_head != NULL)	{
+		/* There is a memory map defined for this target
+		 * Check that the requested write is for a location that is valid
+		 * according to the memory map
+		 */
+		uint64_t bytes_written = 0;
+		struct memory_map_elem *curr_elem = target->memory_map_list_head;
+		do {
+			/* Calculate the intersection of the request and the current memory map block (if \
any) */ +			uint64_t start = MAX(curr_elem->start_address, address);
+			uint64_t end   = MIN(curr_elem->start_address + curr_elem->size, address + \
count*size); +
+			/* If there is data that can be written to this block, write it */
+			if ((end > start) &&
+			    (curr_elem->access != MEMORY_MAP_READ_ONLY)) {
+				int retval = target->type->write_memory(target, start, 1, (end - start), \
buffer); +				if (retval != 0)
+					return retval;
+
+				bytes_written += (end - start);
+			}
+			curr_elem = curr_elem->next_elem;
+		} while (curr_elem != NULL);
+		if (count*size != bytes_written) {
+			LOG_WARNING("Ignoring write to non writable area - Request address: 0x%X, "
+						"Request size %d. Bytes successfully written: %d", address, count*size, \
(int)bytes_written); +		}
+		return ERROR_OK;
+	}
+
 	if (!target_was_examined(target)) {
 		LOG_ERROR("Target not examined yet");
 		return ERROR_FAIL;
@@ -4241,6 +4303,7 @@ enum target_cfg_param {
 	TCFG_CHAIN_POSITION,
 	TCFG_DBGBASE,
 	TCFG_RTOS,
+	TCFG_MEMORYMAP,
 };
 
 static Jim_Nvp nvp_config_opts[] = {
@@ -4255,6 +4318,7 @@ static Jim_Nvp nvp_config_opts[] = {
 	{ .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
 	{ .name = "-dbgbase",          .value = TCFG_DBGBASE },
 	{ .name = "-rtos",             .value = TCFG_RTOS },
+	{ .name = "-memorymap",        .value = TCFG_MEMORYMAP },
 	{ .name = NULL, .value = -1 }
 };
 
@@ -4529,6 +4593,17 @@ no_params:
 			}
 			/* loop for more */
 			break;
+
+		case TCFG_MEMORYMAP:
+			/* RTOS */
+			{
+				int result = add_memory_mapping(goi, target);
+				if (result != JIM_OK)
+					return result;
+			}
+			/* loop for more */
+			break;
+
 		}
 	} /* while (goi->argc) */
 
@@ -4537,6 +4612,93 @@ no_params:
 	return JIM_OK;
 }
 
+static int add_memory_mapping(Jim_GetOptInfo *goi, struct target *target)
+{
+	char *type_str;
+	enum memory_map_access type;
+	char *short_name = NULL;
+	char *long_name = NULL;
+	int64_t start_addr;
+	int64_t size;
+	int retval;
+
+	if ((goi->argc < 3) || (goi->argc > 6)) {
+		Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv,
+							"<type> <start_addr> <size> [short_name] [long_name] [parent]");
+		return JIM_ERR;
+	}
+
+	/* Parse type - must be RW, RO or WO */
+	retval = Jim_GetOpt_String(goi, &type_str, NULL);
+	if (retval != JIM_OK)
+		return retval;
+	if (strcmp(type_str, "RW") == 0)
+		type = MEMORY_MAP_READ_WRITE;
+	else if (strcmp(type_str, "RO") == 0)
+		type = MEMORY_MAP_READ_ONLY;
+	else if (strcmp(type_str, "WO") == 0)
+		type = MEMORY_MAP_WRITE_ONLY;
+	else {
+		Jim_SetResultFormatted(goi->interp,
+				"memory map field type must be \"RW\", \"RO\" or \"WO\"");
+		return JIM_ERR;
+	}
+
+	/* Parse Block start address */
+	retval = Jim_GetOpt_Wide(goi, (long long *) &start_addr);
+	if (retval != JIM_OK)
+		return retval;
+
+	/* Parse Block size */
+	retval = Jim_GetOpt_Wide(goi, (long long *) &size);
+	if (retval != JIM_OK)
+		return retval;
+
+	/* Parse Short Name if available */
+	if (goi->argc > 0) {
+		retval = Jim_GetOpt_String(goi, &short_name, NULL);
+		if (retval != JIM_OK)
+			return retval;
+	}
+
+	/* Parse Long Name if available */
+	if (goi->argc > 0) {
+		retval = Jim_GetOpt_String(goi, &long_name, NULL);
+		if (retval != JIM_OK)
+			return retval;
+	}
+
+	/* Create a new memory map list element and populate it */
+	struct memory_map_elem *new_item = (struct memory_map_elem *) malloc(sizeof(struct \
memory_map_elem)); +	if (new_item == NULL) {
+		Jim_SetResultFormatted(goi->interp,
+				"Failed to allocate space for new memory map item");
+		return JIM_ERR;
+	}
+
+	new_item->access = type;
+	new_item->short_name = strdup(short_name);
+	new_item->long_name = strdup(long_name);
+	new_item->size = size;
+	new_item->start_address = start_addr;
+	new_item->next_elem = NULL;
+
+	/* Insert new element into linked list */
+	if (target->memory_map_list_head == NULL) {
+		target->memory_map_list_head = new_item;
+	} else {
+		struct memory_map_elem *curr_item = target->memory_map_list_head;
+		while (curr_item->next_elem != NULL)
+			curr_item = curr_item->next_elem;
+
+		curr_item->next_elem = new_item;
+	}
+
+	return JIM_OK;
+}
+
+
+
 static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
 {
 	Jim_GetOptInfo goi;
diff --git a/src/target/target.h b/src/target/target.h
index 7471c1b..aca6ea3 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -118,6 +118,23 @@ struct backoff_timer {
 	int count;
 };
 
+enum memory_map_access {
+	MEMORY_MAP_READ_WRITE,
+	MEMORY_MAP_READ_ONLY,
+	MEMORY_MAP_WRITE_ONLY,
+};
+
+struct memory_map_elem {
+	uint64_t                start_address;
+	uint64_t                size;
+	char                   *short_name;
+	char                   *long_name;
+	bool                    contiguous;
+	struct memory_map_elem *sub_elems;
+	struct memory_map_elem *next_elem;
+	enum memory_map_access  access;
+};
+
 /* split target registers into multiple class */
 enum target_register_class {
 	REG_CLASS_ALL,
@@ -197,6 +214,8 @@ struct target {
 
 	/* file-I/O information for host to do syscall */
 	struct gdb_fileio_info *fileio_info;
+
+	struct memory_map_elem *memory_map_list_head;
 };
 
 struct target_list {

-- 

------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic