ipdbg: fix double free of virtual-ir data
[openocd.git] / src / flash / nor / xmc4xxx.c
index 2a52269dc5b7f7288c80d333e517ff9f4a3d6244..54fd5a58678e8d5114381441a8c4a125a53549ac 100644 (file)
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /**************************************************************************
 *   Copyright (C) 2015 Jeff Ciesielski <jeffciesielski@gmail.com>         *
-*                                                                         *
-*   This program is free software; you can redistribute it and/or modify  *
-*   it under the terms of the GNU General Public License as published by  *
-*   the Free Software Foundation; either version 2 of the License, or     *
-*   (at your option) any later version.                                   *
-*                                                                         *
-*   This program is distributed in the hope that it will be useful,       *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
-*   GNU General Public License for more details.                          *
-*                                                                         *
-*   You should have received a copy of the GNU General Public License     *
-*   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 
 /* Flash controller configuration values */
 #define FLASH_ID_XMC4500        0xA2
-#define FLASH_ID_XMC4700_4800   0x92
+#define FLASH_ID_XMC4300_XMC4700_4800   0x92
 #define FLASH_ID_XMC4100_4200   0x9C
 #define FLASH_ID_XMC4400        0x9F
 
@@ -280,7 +269,7 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
 
        /* At this point, we know which flash controller ID we're
         * talking to and simply need to fill out the bank structure accordingly */
-       LOG_DEBUG("%d sectors", bank->num_sectors);
+       LOG_DEBUG("%u sectors", bank->num_sectors);
 
        switch (bank->num_sectors) {
        case 8:
@@ -296,7 +285,7 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
                capacity = sector_capacity_16;
                break;
        default:
-               LOG_ERROR("Unexpected number of sectors, %d\n",
+               LOG_ERROR("Unexpected number of sectors, %u\n",
                          bank->num_sectors);
                return ERROR_FAIL;
        }
@@ -307,7 +296,7 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
        uint32_t total_offset = 0;
        bank->sectors = calloc(bank->num_sectors,
                               sizeof(struct flash_sector));
-       for (int i = 0; i < bank->num_sectors; i++) {
+       for (unsigned int i = 0; i < bank->num_sectors; i++) {
                bank->sectors[i].size = capacity[i] * 1024;
                bank->sectors[i].offset = total_offset;
                bank->sectors[i].is_erased = -1;
@@ -319,8 +308,8 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
        }
 
        /* This part doesn't follow the typical standard of 0xff
-        * being the default padding value.*/
-       bank->default_padded_value = 0x00;
+        * being the erased value.*/
+       bank->default_padded_value = bank->erased_value = 0x00;
 
        return ERROR_OK;
 }
@@ -383,7 +372,7 @@ static int xmc4xxx_probe(struct flash_bank *bank)
                bank->num_sectors = 12;
                LOG_DEBUG("XMC4xxx: XMC4500 detected.");
                break;
-       case FLASH_ID_XMC4700_4800:
+       case FLASH_ID_XMC4300_XMC4700_4800:
                bank->num_sectors = 16;
                LOG_DEBUG("XMC4xxx: XMC4700/4800 detected.");
                break;
@@ -408,7 +397,7 @@ static int xmc4xxx_probe(struct flash_bank *bank)
 }
 
 static int xmc4xxx_get_sector_start_addr(struct flash_bank *bank,
-                                        int sector, uint32_t *ret_addr)
+               unsigned int sector, uint32_t *ret_addr)
 {
        /* Make sure we understand this sector */
        if (sector > bank->num_sectors)
@@ -538,7 +527,8 @@ static int xmc4xxx_erase_sector(struct flash_bank *bank, uint32_t address,
        return res;
 }
 
-static int xmc4xxx_erase(struct flash_bank *bank, int first, int last)
+static int xmc4xxx_erase(struct flash_bank *bank, unsigned int first,
+               unsigned int last)
 {
        struct xmc4xxx_flash_bank *fb = bank->driver_priv;
        int res;
@@ -556,14 +546,14 @@ static int xmc4xxx_erase(struct flash_bank *bank, int first, int last)
 
        uint32_t tmp_addr;
        /* Loop through the sectors and erase each one */
-       for (int i = first; i <= last; i++) {
+       for (unsigned int i = first; i <= last; i++) {
                res = xmc4xxx_get_sector_start_addr(bank, i, &tmp_addr);
                if (res != ERROR_OK) {
-                       LOG_ERROR("Invalid sector %d", i);
+                       LOG_ERROR("Invalid sector %u", i);
                        return res;
                }
 
-               LOG_DEBUG("Erasing sector %d @ 0x%08"PRIx32, i, tmp_addr);
+               LOG_DEBUG("Erasing sector %u @ 0x%08"PRIx32, i, tmp_addr);
 
                res = xmc4xxx_erase_sector(bank, tmp_addr, false);
                if (res != ERROR_OK) {
@@ -576,8 +566,6 @@ static int xmc4xxx_erase(struct flash_bank *bank, int first, int last)
 
                if (res != ERROR_OK)
                        goto clear_status_and_exit;
-
-               bank->sectors[i].is_erased = 1;
        }
 
 clear_status_and_exit:
@@ -617,99 +605,6 @@ static int xmc4xxx_enter_page_mode(struct flash_bank *bank)
        return res;
 }
 
-/* The logical erase value of an xmc4xxx memory cell is 0x00,
- * therefore, we cannot use the built in flash blank check and must
- * implement our own */
-
-/** Checks whether a memory region is zeroed. */
-static int xmc4xxx_blank_check_memory(struct target *target,
-       uint32_t address, uint32_t count, uint32_t *blank)
-{
-       struct working_area *erase_check_algorithm;
-       struct reg_param reg_params[3];
-       struct armv7m_algorithm armv7m_info;
-       int retval;
-
-       static const uint8_t erase_check_code[] = {
-#include "../../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
-       };
-
-       /* make sure we have a working area */
-       if (target_alloc_working_area(target, sizeof(erase_check_code),
-               &erase_check_algorithm) != ERROR_OK)
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
-       retval = target_write_buffer(target, erase_check_algorithm->address,
-                       sizeof(erase_check_code), (uint8_t *)erase_check_code);
-       if (retval != ERROR_OK)
-               goto cleanup;
-
-       armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
-       armv7m_info.core_mode = ARM_MODE_THREAD;
-
-       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
-       buf_set_u32(reg_params[0].value, 0, 32, address);
-
-       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-       buf_set_u32(reg_params[1].value, 0, 32, count);
-
-       init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
-       buf_set_u32(reg_params[2].value, 0, 32, 0x00);
-
-       retval = target_run_algorithm(target,
-                                     0,
-                                     NULL,
-                                     3,
-                                     reg_params,
-                                     erase_check_algorithm->address,
-                                     erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
-                                     10000,
-                                     &armv7m_info);
-
-       if (retval == ERROR_OK)
-               *blank = buf_get_u32(reg_params[2].value, 0, 32);
-
-       destroy_reg_param(&reg_params[0]);
-       destroy_reg_param(&reg_params[1]);
-       destroy_reg_param(&reg_params[2]);
-
-cleanup:
-       target_free_working_area(target, erase_check_algorithm);
-
-       return retval;
-}
-
-static int xmc4xxx_flash_blank_check(struct flash_bank *bank)
-{
-       struct target *target = bank->target;
-       int i;
-       int retval = ERROR_OK;
-       uint32_t blank;
-
-       if (bank->target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       for (i = 0; i < bank->num_sectors; i++) {
-               uint32_t address = bank->base + bank->sectors[i].offset;
-               uint32_t size = bank->sectors[i].size;
-
-               LOG_DEBUG("Erase checking 0x%08"PRIx32, address);
-               retval = xmc4xxx_blank_check_memory(target, address, size, &blank);
-
-               if (retval != ERROR_OK)
-                       break;
-
-               if (blank == 0x00)
-                       bank->sectors[i].is_erased = 1;
-               else
-                       bank->sectors[i].is_erased = 0;
-       }
-
-       return retval;
-}
-
 static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf,
                              uint32_t offset, bool user_config)
 {
@@ -871,7 +766,7 @@ static int xmc4xxx_write(struct flash_bank *bank, const uint8_t *buffer,
                memcpy(&tmp_buf[start_pad], buffer, remaining);
 
                if (end_pad) {
-                       LOG_INFO("Padding end of page @%08"PRIx32" by %d bytes",
+                       LOG_INFO("Padding end of page @" TARGET_ADDR_FMT " by %d bytes",
                                 bank->base + offset, end_pad);
                        memset(&tmp_buf[256 - end_pad], 0xff, end_pad);
                }
@@ -897,7 +792,7 @@ abort_write_and_exit:
 
 }
 
-static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
+static int xmc4xxx_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
 {
        struct xmc4xxx_flash_bank *fb = bank->driver_priv;
        uint32_t scu_idcode;
@@ -944,6 +839,14 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_
                        break;
                }
                break;
+       case 0x300:
+               dev_str = "XMC4300";
+
+               switch (rev_id) {
+               case 0x1:
+                       rev_str = "AA";
+               }
+               break;
        case 0x400:
                dev_str = "XMC4400";
 
@@ -998,9 +901,7 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_
                break;
 
        default:
-               snprintf(buf, buf_size,
-                        "Cannot identify target as an XMC4xxx. SCU_ID: %"PRIx32"\n",
-                        scu_idcode);
+               command_print_sameline(cmd, "Cannot identify target as an XMC4xxx. SCU_ID: %"PRIx32 "\n", scu_idcode);
                return ERROR_OK;
        }
 
@@ -1010,29 +911,27 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_
                snprintf(prot_str, sizeof(prot_str), "\nFlash is read protected");
 
        bool otp_enabled = false;
-       for (int i = 0; i < bank->num_sectors; i++)
+       for (unsigned int i = 0; i < bank->num_sectors; i++)
                if (fb->write_prot_otp[i])
                        otp_enabled = true;
 
        /* If OTP Write protection is enabled (User 2), list each
         * sector that has it enabled */
-       char otp_str[8];
+       char otp_str[14];
        if (otp_enabled) {
                strcat(prot_str, "\nOTP Protection is enabled for sectors:\n");
-               for (int i = 0; i < bank->num_sectors; i++) {
+               for (unsigned int i = 0; i < bank->num_sectors; i++) {
                        if (fb->write_prot_otp[i]) {
                                snprintf(otp_str, sizeof(otp_str), "- %d\n", i);
-                               strncat(prot_str, otp_str, ARRAY_SIZE(otp_str));
+                               strncat(prot_str, otp_str, sizeof(prot_str) - strlen(prot_str) - 1);
                        }
                }
        }
 
-       if (rev_str != NULL)
-               snprintf(buf, buf_size, "%s - Rev: %s%s",
-                        dev_str, rev_str, prot_str);
+       if (rev_str)
+               command_print_sameline(cmd, "%s - Rev: %s%s", dev_str, rev_str, prot_str);
        else
-               snprintf(buf, buf_size, "%s - Rev: unknown (0x%01x)%s",
-                        dev_str, rev_id, prot_str);
+               command_print_sameline(cmd, "%s - Rev: unknown (0x%01x)%s", dev_str, rev_id, prot_str);
 
        return ERROR_OK;
 }
@@ -1091,11 +990,6 @@ static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level)
        uint32_t addr;
        int res;
 
-       if ((level < 0) || (level > 1)) {
-               LOG_ERROR("Invalid user level. Must be 0-1");
-               return ERROR_FAIL;
-       }
-
        switch (level) {
        case 0:
                addr = UCB0_BASE;
@@ -1103,6 +997,9 @@ static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level)
        case 1:
                addr = UCB1_BASE;
                break;
+       default:
+               LOG_ERROR("Invalid user level. Must be 0-1");
+               return ERROR_FAIL;
        }
 
        res = xmc4xxx_erase_sector(bank, addr, true);
@@ -1115,7 +1012,7 @@ static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level)
 
 /* Reference: "XMC4500 Flash Protection.pptx" app note */
 static int xmc4xxx_flash_protect(struct flash_bank *bank, int level, bool read_protect,
-                                int first, int last)
+               unsigned int first, unsigned int last)
 {
        /* User configuration block buffers */
        uint8_t ucp0_buf[8 * sizeof(uint32_t)] = {0};
@@ -1174,7 +1071,7 @@ static int xmc4xxx_flash_protect(struct flash_bank *bank, int level, bool read_p
 
        /*  We need to fill out the procon register representation
         *   that we will be writing to the device */
-       for (int i = first; i <= last; i++)
+       for (unsigned int i = first; i <= last; i++)
                procon |= 1 << i;
 
        /* If read protection is requested, set the appropriate bit
@@ -1231,7 +1128,8 @@ static int xmc4xxx_flash_protect(struct flash_bank *bank, int level, bool read_p
        return ERROR_OK;
 }
 
-static int xmc4xxx_protect(struct flash_bank *bank, int set, int first, int last)
+static int xmc4xxx_protect(struct flash_bank *bank, int set, unsigned int first,
+               unsigned int last)
 {
        int ret;
        struct xmc4xxx_flash_bank *fb = bank->driver_priv;
@@ -1280,15 +1178,15 @@ static int xmc4xxx_protect_check(struct flash_bank *bank)
                return ret;
        }
 
-       int sectors = bank->num_sectors;
+       unsigned int sectors = bank->num_sectors;
 
-       /* On devices with 12 sectors, sectors 10 & 11 are ptected
+       /* On devices with 12 sectors, sectors 10 & 11 are protected
         * together instead of individually */
        if (sectors == 12)
                sectors--;
 
        /* Clear the protection status */
-       for (int i = 0; i < bank->num_sectors; i++) {
+       for (unsigned int i = 0; i < bank->num_sectors; i++) {
                bank->sectors[i].is_protected = 0;
                fb->write_prot_otp[i] = false;
        }
@@ -1301,7 +1199,7 @@ static int xmc4xxx_protect_check(struct flash_bank *bank)
 
                /* Check for write protection on every available
                *  sector */
-               for (int j = 0; j < sectors; j++) {
+               for (unsigned int j = 0; j < sectors; j++) {
                        int set = (protection[i] & (1 << j)) ? 1 : 0;
                        bank->sectors[j].is_protected |= set;
 
@@ -1322,7 +1220,7 @@ static int xmc4xxx_protect_check(struct flash_bank *bank)
                }
        }
 
-       /* XMC4xxx also supports read proptection, make a note
+       /* XMC4xxx also supports read protection, make a note
         * in the private driver structure */
        if (protection[0] & PROCON_RPRO_MASK)
                fb->read_protected = true;
@@ -1359,21 +1257,21 @@ COMMAND_HANDLER(xmc4xxx_handle_flash_password_command)
        errno = 0;
 
        /* We skip over the flash bank */
-       fb->pw1 = strtol(CMD_ARGV[1], NULL, 16);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], fb->pw1);
 
        if (errno)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       fb->pw2 = strtol(CMD_ARGV[2], NULL, 16);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], fb->pw2);
 
        if (errno)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        fb->pw_set = true;
 
-       command_print(CMD_CTX, "XMC4xxx flash passwords set to:\n");
-       command_print(CMD_CTX, "-0x%08"PRIx32"\n", fb->pw1);
-       command_print(CMD_CTX, "-0x%08"PRIx32"\n", fb->pw2);
+       command_print(CMD, "XMC4xxx flash passwords set to:\n");
+       command_print(CMD, "-0x%08"PRIx32"\n", fb->pw1);
+       command_print(CMD, "-0x%08"PRIx32"\n", fb->pw2);
        return ERROR_OK;
 }
 
@@ -1416,7 +1314,8 @@ static const struct command_registration xmc4xxx_exec_command_handlers[] = {
                .usage = "bank_id user_level[0-1]",
                .help = "Permanently Removes flash protection (read and write) "
                "for the specified user level",
-       },      COMMAND_REGISTRATION_DONE
+       },
+       COMMAND_REGISTRATION_DONE
 };
 
 static const struct command_registration xmc4xxx_command_handlers[] = {
@@ -1430,7 +1329,7 @@ static const struct command_registration xmc4xxx_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
-struct flash_driver xmc4xxx_flash = {
+const struct flash_driver xmc4xxx_flash = {
        .name = "xmc4xxx",
        .commands = xmc4xxx_command_handlers,
        .flash_bank_command = xmc4xxx_flash_bank_command,
@@ -1439,8 +1338,9 @@ struct flash_driver xmc4xxx_flash = {
        .read = default_flash_read,
        .probe = xmc4xxx_probe,
        .auto_probe = xmc4xxx_probe,
-       .erase_check = xmc4xxx_flash_blank_check,
+       .erase_check = default_flash_blank_check,
        .info = xmc4xxx_get_info_command,
        .protect_check = xmc4xxx_protect_check,
        .protect = xmc4xxx_protect,
+       .free_driver_priv = default_flash_free_driver_priv,
 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)