From: Aurelien Jacobs Date: Tue, 8 May 2012 18:53:18 +0000 (+0200) Subject: cfi: fix write_bank segfault with spansion flash on armv7m X-Git-Tag: v0.6.0-rc1~99 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=9d31589d19b1c9c4cbde5c361c046d735c43c215 cfi: fix write_bank segfault with spansion flash on armv7m cfi_spansion_write_block() passes an arm_algorithm struct to target_run_algorithm() which in turn calls armv7m_start_algorithm() which expect an armv7m_algorithm struct. As armv7m_algorithm is bigger than arm_algorithm, when armv7m_start_algorithm() writes in the struct, it overrun the buffer, writting junk on the stack, which latter on generates a segfault. This patch ensure we use a properly sized armv7m_algorithm struct when the target is an armv7m. Change-Id: I4ab67c15ae4bb72454414a81b92a4231dcdb2239 Signed-off-by: Aurelien Jacobs Reviewed-on: http://openocd.zylin.com/623 Tested-by: jenkins Reviewed-by: Spencer Oliver --- diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index bb6afa322a..ec90d7a2ef 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -1634,7 +1634,9 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; struct target *target = bank->target; struct reg_param reg_params[10]; - struct arm_algorithm arm_algo; + struct arm_algorithm *arm_algo; + struct arm_algorithm armv4_5_algo; + struct armv7m_algorithm armv7m_algo; struct working_area *source; uint32_t buffer_size = 32768; uint32_t status; @@ -1814,14 +1816,15 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, return cfi_spansion_write_block_mips(bank, buffer, address, count); if (is_armv7m(target_to_armv7m(target))) { /* Cortex-M3 target */ - arm_algo.common_magic = ARMV7M_COMMON_MAGIC; - arm_algo.core_mode = ARMV7M_MODE_HANDLER; - arm_algo.core_state = ARM_STATE_ARM; + armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_algo.core_mode = ARMV7M_MODE_HANDLER; + arm_algo = (struct arm_algorithm *)&armv7m_algo; } else if (is_arm(target_to_arm(target))) { /* All other ARM CPUs have 32 bit instructions */ - arm_algo.common_magic = ARM_COMMON_MAGIC; - arm_algo.core_mode = ARM_MODE_SVC; - arm_algo.core_state = ARM_STATE_ARM; + armv4_5_algo.common_magic = ARM_COMMON_MAGIC; + armv4_5_algo.core_mode = ARM_MODE_SVC; + armv4_5_algo.core_state = ARM_STATE_ARM; + arm_algo = &armv4_5_algo; } else { LOG_ERROR("Unknown architecture"); return ERROR_FAIL; @@ -1832,7 +1835,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, switch (bank->bus_width) { case 1: - if (arm_algo.common_magic != ARM_COMMON_MAGIC) { + if (arm_algo->common_magic != ARM_COMMON_MAGIC) { LOG_ERROR("Unknown ARM architecture"); return ERROR_FAIL; } @@ -1842,10 +1845,10 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, case 2: /* Check for DQ5 support */ if (cfi_info->status_poll_mask & (1 << 5)) { - if (arm_algo.common_magic == ARM_COMMON_MAGIC) {/* armv4_5 target */ + if (arm_algo->common_magic == ARM_COMMON_MAGIC) {/* armv4_5 target */ target_code_src = armv4_5_word_16_code; target_code_size = sizeof(armv4_5_word_16_code); - } else if (arm_algo.common_magic == ARMV7M_COMMON_MAGIC) { /* + } else if (arm_algo->common_magic == ARMV7M_COMMON_MAGIC) { /* *cortex-m3 *target **/ @@ -1854,7 +1857,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, } } else { /* No DQ5 support. Use DQ7 DATA# polling only. */ - if (arm_algo.common_magic != ARM_COMMON_MAGIC) { + if (arm_algo->common_magic != ARM_COMMON_MAGIC) { LOG_ERROR("Unknown ARM architecture"); return ERROR_FAIL; } @@ -1863,7 +1866,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, } break; case 4: - if (arm_algo.common_magic != ARM_COMMON_MAGIC) { + if (arm_algo->common_magic != ARM_COMMON_MAGIC) { LOG_ERROR("Unknown ARM architecture"); return ERROR_FAIL; } @@ -1954,7 +1957,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, retval = target_run_algorithm(target, 0, NULL, 10, reg_params, cfi_info->write_algorithm->address, cfi_info->write_algorithm->address + ((target_code_size) - 4), - 10000, &arm_algo); + 10000, arm_algo); if (retval != ERROR_OK) break;