flash/nor/stm32xx: fix segfault accessing Cortex-M part number
authorTomas Vanek <vanekt@fbl.cz>
Thu, 25 Nov 2021 05:24:52 +0000 (06:24 +0100)
committerTomas Vanek <vanekt@fbl.cz>
Fri, 25 Feb 2022 20:28:02 +0000 (20:28 +0000)
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 <vanekt@fbl.cz>
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 <borneo.antonio@gmail.com>
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
src/flash/nor/stm32f1x.c
src/flash/nor/stm32f2x.c
src/flash/nor/stm32h7x.c
src/flash/nor/stm32l4x.c

index 90cee641206a3c792601096e5bdb8e985dfbe98b..29a3b7e06fd914b4b3a789d52074e54c699f22fc 100644 (file)
@@ -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;
index aa0363232e55082799198eb66ecedba41c79a42a..58edca7e1be9a5f6723b345c1cb6a9805d58ed77 100644 (file)
@@ -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)) {
index d3f17b2b199aab0bbde460b0450c060c89836fd2..6d3149f9464dd1c9a813db3c19dc27d61d208e6b 100644 (file)
@@ -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);
index e5100a0159bcba06b3e9053db54231c32ccc08db..fa8924ed385e12dc144930e7ae37d49eb256f911 100644 (file)
@@ -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 */