From: Tomas Vanek Date: Thu, 25 Nov 2021 05:24:52 +0000 (+0100) Subject: flash/nor/stm32xx: fix segfault accessing Cortex-M part number X-Git-Tag: v0.12.0-rc1~324 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=13cd75b6ecfd flash/nor/stm32xx: fix segfault accessing Cortex-M part number Some of STM32 flash drivers read Cortex-M part number from cortex_m->core_info. In corner cases the core_info pointer was observed uninitialised even if target_was_examined() returned true. See also [1] Use the new and safe helper to get Cortex-M part number. While on it switch also target_to_cm()/target_to_armv7m() to the safe versions. This prevents a crash when the flash bank is misconfigured with non-Cortex-M target. Add missing checks for target_was_examined() to flash probes. [1] 6545: fix crash in case cortex_m->core_info is not set https://review.openocd.org/c/openocd/+/6545 Change-Id: If2471af74ebfe22f14442f48ae109b2e1bb5fa3b Signed-off-by: Tomas Vanek Fixes: f5898bd93ff8 (flash/stm32fxx.c: do not read CPUID as this info is stored in cortex_m_common) Reviewed-on: https://review.openocd.org/c/openocd/+/6752 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tarek BOCHKATI --- diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index 90cee64120..29a3b7e06f 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -622,15 +622,14 @@ cleanup: static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id) { struct target *target = bank->target; - struct cortex_m_common *cortex_m = target_to_cm(target); uint32_t device_id_register = 0; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; + return ERROR_TARGET_NOT_EXAMINED; } - switch (cortex_m->core_info->partno) { + switch (cortex_m_get_partno_safe(target)) { case CORTEX_M0_PARTNO: /* STM32F0x devices */ device_id_register = 0x40015800; break; @@ -659,15 +658,14 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id) static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_size_in_kb) { struct target *target = bank->target; - struct cortex_m_common *cortex_m = target_to_cm(target); uint32_t flash_size_reg; if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; + return ERROR_TARGET_NOT_EXAMINED; } - switch (cortex_m->core_info->partno) { + switch (cortex_m_get_partno_safe(target)) { case CORTEX_M0_PARTNO: /* STM32F0x devices */ flash_size_reg = 0x1FFFF7CC; break; diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index aa0363232e..58edca7e1b 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -966,14 +966,14 @@ static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id) * Only effects Rev A silicon */ struct target *target = bank->target; - struct cortex_m_common *cortex_m = target_to_cm(target); /* read stm32 device id register */ int retval = target_read_u32(target, 0xE0042000, device_id); if (retval != ERROR_OK) return retval; - if ((*device_id & 0xfff) == 0x411 && cortex_m->core_info->partno == CORTEX_M4_PARTNO) { + if ((*device_id & 0xfff) == 0x411 + && cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO) { *device_id &= ~((0xFFFF << 16) | 0xfff); *device_id |= (0x1000 << 16) | 0x413; LOG_INFO("stm32f4x errata detected - fixing incorrect MCU_IDCODE"); @@ -1011,6 +1011,11 @@ static int stm32x_probe(struct flash_bank *bank) bank->num_prot_blocks = 0; bank->prot_blocks = NULL; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } + /* if explicitly called out as OTP bank, short circuit probe */ if (stm32x_is_otp(bank)) { if (stm32x_otp_is_f7(bank)) { diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index d3f17b2b19..6d3149f946 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -759,7 +759,6 @@ static int stm32x_read_id_code(struct flash_bank *bank, uint32_t *id) static int stm32x_probe(struct flash_bank *bank) { struct target *target = bank->target; - struct cortex_m_common *cortex_m = target_to_cm(target); struct stm32h7x_flash_bank *stm32x_info = bank->driver_priv; uint16_t flash_size_in_kb; uint32_t device_id; @@ -767,6 +766,11 @@ static int stm32x_probe(struct flash_bank *bank) stm32x_info->probed = false; stm32x_info->part_info = NULL; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } + int retval = stm32x_read_id_code(bank, &stm32x_info->idcode); if (retval != ERROR_OK) return retval; @@ -800,7 +804,8 @@ static int stm32x_probe(struct flash_bank *bank) /* get flash size from target */ /* STM32H74x/H75x, the second core (Cortex-M4) cannot read the flash size */ retval = ERROR_FAIL; - if (device_id == DEVID_STM32H74_H75XX && cortex_m->core_info->partno == CORTEX_M4_PARTNO) + if (device_id == DEVID_STM32H74_H75XX + && cortex_m_get_partno_safe(target) == CORTEX_M4_PARTNO) LOG_WARNING("%s cannot read the flash size register", target_name(target)); else retval = target_read_u16(target, stm32x_info->part_info->fsize_addr, &flash_size_in_kb); diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index e5100a0159..fa8924ed38 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1633,12 +1633,13 @@ err_lock: static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) { int retval; + struct target *target = bank->target; /* try reading possible IDCODE registers, in the following order */ uint32_t dbgmcu_idcode[] = {DBGMCU_IDCODE_L4_G4, DBGMCU_IDCODE_G0, DBGMCU_IDCODE_L5}; for (unsigned int i = 0; i < ARRAY_SIZE(dbgmcu_idcode); i++) { - retval = target_read_u32(bank->target, dbgmcu_idcode[i], id); + retval = target_read_u32(target, dbgmcu_idcode[i], id); if ((retval == ERROR_OK) && ((*id & 0xfff) != 0) && ((*id & 0xfff) != 0xfff)) return ERROR_OK; } @@ -1647,12 +1648,16 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) * DBGMCU_IDCODE cannot be read using CPU1 (Cortex-M0+) at AP1, * to solve this read the UID64 (IEEE 64-bit unique device ID register) */ - struct cortex_m_common *cortex_m = target_to_cm(bank->target); + struct armv7m_common *armv7m = target_to_armv7m_safe(target); + if (!armv7m) { + LOG_ERROR("Flash requires Cortex-M target"); + return ERROR_TARGET_INVALID; + } /* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1. * Using HLA adapters armv7m.debug_ap is null, and checking ap_num triggers a segfault */ - if (cortex_m->core_info->partno == CORTEX_M0P_PARTNO && - cortex_m->armv7m.debug_ap && cortex_m->armv7m.debug_ap->ap_num == 1) { + if (cortex_m_get_partno_safe(target) == CORTEX_M0P_PARTNO && + armv7m->debug_ap && armv7m->debug_ap->ap_num == 1) { uint32_t uid64_ids; /* UID64 is contains @@ -1662,7 +1667,7 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) * * read only the fixed values {STID,DEVID} from UID64_IDS to identify the device as STM32WLx */ - retval = target_read_u32(bank->target, UID64_IDS, &uid64_ids); + retval = target_read_u32(target, UID64_IDS, &uid64_ids); if (retval == ERROR_OK && uid64_ids == UID64_IDS_STM32WL) { /* force the DEV_ID to DEVID_STM32WLE_WL5XX and the REV_ID to unknown */ *id = DEVID_STM32WLE_WL5XX; @@ -1700,11 +1705,21 @@ static const char *get_stm32l4_bank_type_str(struct flash_bank *bank) static int stm32l4_probe(struct flash_bank *bank) { struct target *target = bank->target; - struct armv7m_common *armv7m = target_to_armv7m(target); struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; const struct stm32l4_part_info *part_info; uint16_t flash_size_kb = 0xffff; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_TARGET_NOT_EXAMINED; + } + + struct armv7m_common *armv7m = target_to_armv7m_safe(target); + if (!armv7m) { + LOG_ERROR("Flash requires Cortex-M target"); + return ERROR_TARGET_INVALID; + } + stm32l4_info->probed = false; /* read stm32 device id registers */