From f14f84ca1e5d4fbab00c52100859af5ec8226753 Mon Sep 17 00:00:00 2001 From: oharboe Date: Wed, 5 Mar 2008 13:27:50 +0000 Subject: [PATCH] Pavel Chromy: memory leak in at91sam7 flash driver, possible incorrect pointer conversion in gpnvm command handling, uninitialized buffer issue in handle_flash_info_command in flash.c, some formatting. git-svn-id: svn://svn.berlios.de/openocd/trunk@446 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/flash/at91sam7.c | 165 ++++++++++++++++-------------------------- src/flash/at91sam7.h | 4 +- src/flash/flash.c | 13 ++-- src/flash/flash.h | 1 + src/flash/stellaris.c | 90 +++++++++++------------ 5 files changed, 117 insertions(+), 156 deletions(-) diff --git a/src/flash/at91sam7.c b/src/flash/at91sam7.c index 99a8a9af..0c7a7c0a 100644 --- a/src/flash/at91sam7.c +++ b/src/flash/at91sam7.c @@ -77,7 +77,7 @@ flash_driver_t at91sam7_flash = .protect = at91sam7_protect, .write = at91sam7_write, .probe = at91sam7_probe, - .auto_probe = at91sam7_auto_probe, + .auto_probe = at91sam7_probe, .erase_check = at91sam7_erase_check, .protect_check = at91sam7_protect_check, .info = at91sam7_info @@ -145,7 +145,7 @@ u32 at91sam7_get_flash_status(flash_bank_t *bank, u8 flashplane) return fsr; } -/** Read clock configuration and set at91sam7_info->usec_clocks*/ +/* Read clock configuration and set at91sam7_info->usec_clocks*/ void at91sam7_read_clock_info(flash_bank_t *bank) { at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; @@ -180,7 +180,7 @@ void at91sam7_read_clock_info(flash_bank_t *bank) case 2: /* Reserved */ break; - case 3: /* PLL Clock */ + case 3: /* PLL Clock */ if (mcfr & CKGR_MCFR_MAINRDY) { target_read_u32(target, CKGR_PLLR, &pllr); @@ -313,6 +313,9 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) target_t *target = bank->target; u32 cidr, status; int sectornum; + + if (at91sam7_info->cidr != 0) + return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */ /* Read and parse chip identification register */ target_read_u32(target, DBGU_CIDR, &cidr); @@ -553,9 +556,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) return ERROR_OK; } - WARNING("at91sam7 flash only tested for AT91SAM7Sxx series"); - - return ERROR_OK; + WARNING("at91sam7 flash only tested for AT91SAM7Sxx series"); + return ERROR_OK; } int at91sam7_erase_check(struct flash_bank_s *bank) @@ -579,20 +581,14 @@ int at91sam7_protect_check(struct flash_bank_s *bank) at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - if (bank->target->state != TARGET_HALTED) - { - return ERROR_TARGET_NOT_HALTED; - } - if (at91sam7_info->cidr == 0) { - at91sam7_read_part_info(bank); + return ERROR_FLASH_BANK_NOT_PROBED; } - if (at91sam7_info->cidr == 0) + if (bank->target->state != TARGET_HALTED) { - WARNING("Cannot identify target as an AT91SAM"); - return ERROR_FLASH_OPERATION_FAILED; + return ERROR_TARGET_NOT_HALTED; } for (flashplane=0;flashplanenum_planes;flashplane++) @@ -619,7 +615,6 @@ int at91sam7_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, ch at91sam7_info = malloc(sizeof(at91sam7_flash_bank_t)); bank->driver_priv = at91sam7_info; - at91sam7_info->probed = 0; /* part wasn't probed for info yet */ at91sam7_info->cidr = 0; @@ -634,21 +629,15 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last) at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; u8 flashplane; - if (bank->target->state != TARGET_HALTED) - { - return ERROR_TARGET_NOT_HALTED; - } - if (at91sam7_info->cidr == 0) { - at91sam7_read_part_info(bank); + return ERROR_FLASH_BANK_NOT_PROBED; } - if (at91sam7_info->cidr == 0) + if (bank->target->state != TARGET_HALTED) { - WARNING("Cannot identify target as an AT91SAM"); - return ERROR_FLASH_OPERATION_FAILED; - } + return ERROR_TARGET_NOT_HALTED; + } if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { @@ -683,6 +672,11 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last) at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; + if (at91sam7_info->cidr == 0) + { + return ERROR_FLASH_BANK_NOT_PROBED; + } + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; @@ -693,17 +687,6 @@ int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last) return ERROR_FLASH_SECTOR_INVALID; } - if (at91sam7_info->cidr == 0) - { - at91sam7_read_part_info(bank); - } - - if (at91sam7_info->cidr == 0) - { - WARNING("Cannot identify target as an AT91SAM"); - return ERROR_FLASH_OPERATION_FAILED; - } - at91sam7_read_clock_info(bank); for (lockregion=first;lockregion<=last;lockregion++) @@ -738,22 +721,16 @@ int at91sam7_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) u32 first_page, last_page, pagen, buffer_pos; u8 flashplane; - if (bank->target->state != TARGET_HALTED) - { - return ERROR_TARGET_NOT_HALTED; - } - if (at91sam7_info->cidr == 0) { - at91sam7_read_part_info(bank); + return ERROR_FLASH_BANK_NOT_PROBED; } - if (at91sam7_info->cidr == 0) + if (bank->target->state != TARGET_HALTED) { - WARNING("Cannot identify target as an AT91SAM"); - return ERROR_FLASH_OPERATION_FAILED; + return ERROR_TARGET_NOT_HALTED; } - + if (offset + count > bank->size) return ERROR_FLASH_DST_OUT_OF_BANK; @@ -809,56 +786,34 @@ int at91sam7_probe(struct flash_bank_s *bank) * if this is an at91sam7, it has the configured flash */ at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - at91sam7_info->probed = 0; + int retval; - if (bank->target->state != TARGET_HALTED) + if (at91sam7_info->cidr != 0) { - return ERROR_TARGET_NOT_HALTED; + return ERROR_OK; /* already probed */ } - if (at91sam7_info->cidr == 0) + if (bank->target->state != TARGET_HALTED) { - at91sam7_read_part_info(bank); + return ERROR_TARGET_NOT_HALTED; } - if (at91sam7_info->cidr == 0) - { - WARNING("Cannot identify target as an AT91SAM"); - return ERROR_FLASH_OPERATION_FAILED; - } - - at91sam7_info->probed = 1; + retval = at91sam7_read_part_info(bank); + if (retval != ERROR_OK) + return retval; return ERROR_OK; } -int at91sam7_auto_probe(struct flash_bank_s *bank) -{ - at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - if (at91sam7_info->probed) - return ERROR_OK; - return at91sam7_probe(bank); -} - int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size) { int printed, flashplane; at91sam7_flash_bank_t *at91sam7_info = bank->driver_priv; - if (bank->target->state != TARGET_HALTED) - { - return ERROR_TARGET_NOT_HALTED; - } - - at91sam7_read_part_info(bank); - if (at91sam7_info->cidr == 0) { - printed = snprintf(buf, buf_size, "Cannot identify target as an AT91SAM\n"); - buf += printed; - buf_size -= printed; - return ERROR_FLASH_OPERATION_FAILED; + return ERROR_FLASH_BANK_NOT_PROBED; } printed = snprintf(buf, buf_size, "\nat91sam7 information: Chip is %s\n",at91sam7_info->target_name); @@ -894,7 +849,7 @@ int at91sam7_info(struct flash_bank_s *bank, char *buf, int buf_size) buf_size -= printed; } - printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits: 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->nvmbits); + printed = snprintf(buf, buf_size, "securitybit: %i, nvmbits(%i): 0x%1.1x\n", at91sam7_info->securitybit, at91sam7_info->num_nvmbits, at91sam7_info->nvmbits); buf += printed; buf_size -= printed; @@ -919,6 +874,7 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, u32 status; char *value; at91sam7_flash_bank_t *at91sam7_info; + int retval; if (argc < 3) { @@ -926,32 +882,48 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, return ERROR_OK; } - bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + bank = get_flash_bank_by_num_noprobe(strtoul(args[0], NULL, 0)); bit = atoi(args[1]); value = args[2]; - if (!bank) + if (bank == NULL) { - command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); - return ERROR_OK; + return ERROR_FLASH_BANK_INVALID; + } + + if (bank->driver != &at91sam7_flash) + { + command_print(cmd_ctx, "not an at91sam7 flash bank '%s'", args[0]); + return ERROR_FLASH_BANK_INVALID; + } + + if (strcmp(value, "set") == 0) + { + flashcmd = SGPB; + } + else if (strcmp(value, "clear") == 0) + { + flashcmd = CGPB; + } + else + { + return ERROR_COMMAND_SYNTAX_ERROR; } at91sam7_info = bank->driver_priv; if (bank->target->state != TARGET_HALTED) { + ERROR("target has to be halted to perform flash operation"); return ERROR_TARGET_NOT_HALTED; } if (at91sam7_info->cidr == 0) { - at91sam7_read_part_info(bank); - } - - if (at91sam7_info->cidr == 0) - { - WARNING("Cannot identify target as an AT91SAM"); - return ERROR_FLASH_OPERATION_FAILED; + retval = at91sam7_read_part_info(bank); + if (retval != ERROR_OK) { + return retval; + } } if ((bit<0) || (at91sam7_info->num_nvmbits <= bit)) @@ -960,19 +932,6 @@ int at91sam7_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, return ERROR_OK; } - if (strcmp(value, "set") == 0) - { - flashcmd = SGPB; - } - else if (strcmp(value, "clear") == 0) - { - flashcmd = CGPB; - } - else - { - return ERROR_COMMAND_SYNTAX_ERROR; - } - /* Configure the flash controller timing */ at91sam7_read_clock_info(bank); at91sam7_set_flash_mode(bank, 0, FMR_TIMING_NVBITS); diff --git a/src/flash/at91sam7.h b/src/flash/at91sam7.h index eb0213c0..ecb56701 100644 --- a/src/flash/at91sam7.h +++ b/src/flash/at91sam7.h @@ -59,9 +59,7 @@ typedef struct at91sam7_flash_bank_s /* main clock status */ u8 mck_valid; u32 mck_freq; - - int probed; - + } at91sam7_flash_bank_t; /* AT91SAM7 control registers */ diff --git a/src/flash/flash.c b/src/flash/flash.c index 92ac6fd6..1c6773db 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -93,7 +93,7 @@ static int flash_driver_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, retval=bank->driver->write(bank, buffer, offset, count); if (retval!=ERROR_OK) { - ERROR("error writing to flash at address 0x%08x at offset 0x%8.8x", bank->base, offset); + ERROR("error writing to flash at address 0x%08x at offset 0x%8.8x (%d)", bank->base, offset, retval); } return retval; @@ -106,7 +106,7 @@ static int flash_driver_erase(struct flash_bank_s *bank, int first, int last) retval=bank->driver->erase(bank, first, last); if (retval!=ERROR_OK) { - ERROR("failed erasing sectors %d to %d", first, last); + ERROR("failed erasing sectors %d to %d (%d)", first, last, retval); } return retval; @@ -119,7 +119,7 @@ int flash_driver_protect(struct flash_bank_s *bank, int set, int first, int last retval=bank->driver->protect(bank, set, first, last); if (retval!=ERROR_OK) { - ERROR("failed setting protection for areas %d to %d", first, last); + ERROR("failed setting protection for areas %d to %d (%d)", first, last, retval); } return retval; @@ -311,6 +311,7 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char flash_bank_t *p; int i = 0; int j = 0; + int retval; if (argc != 1) { @@ -351,8 +352,11 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char erase_state, protect_state); } - p->driver->info(p, buf, 1024); + *buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */ + retval = p->driver->info(p, buf, sizeof(buf)); command_print(cmd_ctx, "%s", buf); + if (retval != ERROR_OK) + ERROR("error retrieving flash info (%d)", retval); } } @@ -918,7 +922,6 @@ int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd if (argc != 1) { return ERROR_COMMAND_SYNTAX_ERROR; - } if (strcmp(args[0], "on") == 0) diff --git a/src/flash/flash.h b/src/flash/flash.h index 2e6c1ec0..846ddc4b 100644 --- a/src/flash/flash.h +++ b/src/flash/flash.h @@ -80,6 +80,7 @@ extern void flash_set_dirty(void); extern int flash_get_bank_count(); extern flash_bank_t *get_flash_bank_by_num(int num); +extern flash_bank_t *get_flash_bank_by_num_noprobe(int num); extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr); #define ERROR_FLASH_BANK_INVALID (-900) diff --git a/src/flash/stellaris.c b/src/flash/stellaris.c index 2eca290c..2f91e564 100644 --- a/src/flash/stellaris.c +++ b/src/flash/stellaris.c @@ -77,7 +77,7 @@ flash_driver_t stellaris_flash = struct { u32 partno; - char *partname; + char *partname; } StellarisParts[] = { {0x01,"LM3S101"}, @@ -269,9 +269,9 @@ int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size) { device_class = 0; } - printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n", - device_class, StellarisClassname[device_class], stellaris_info->target_name, - 'A' + (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF); + printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n", + device_class, StellarisClassname[device_class], stellaris_info->target_name, + 'A' + (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF); buf += printed; buf_size -= printed; @@ -352,7 +352,7 @@ void stellaris_read_clock_info(flash_bank_t *bank) stellaris_info->mck_freq = mainfreq; /* Forget old flash timing */ - stellaris_set_flash_mode(bank,0); + stellaris_set_flash_mode(bank,0); } /* Setup the timimg registers */ @@ -407,7 +407,7 @@ int stellaris_read_part_info(struct flash_bank_s *bank) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; target_t *target = bank->target; - u32 did0,did1, ver, fam, status; + u32 did0,did1, ver, fam, status; int i; /* Read and parse chip identification register */ @@ -417,10 +417,10 @@ int stellaris_read_part_info(struct flash_bank_s *bank) target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1); DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x",did0, did1, stellaris_info->dc0,stellaris_info->dc1); - ver = did0 >> 28; - if((ver != 0) && (ver != 1)) + ver = did0 >> 28; + if((ver != 0) && (ver != 1)) { - WARNING("Unknown did0 version, cannot identify target"); + WARNING("Unknown did0 version, cannot identify target"); return ERROR_FLASH_OPERATION_FAILED; } @@ -430,11 +430,11 @@ int stellaris_read_part_info(struct flash_bank_s *bank) return ERROR_FLASH_OPERATION_FAILED; } - ver = did1 >> 28; - fam = (did1 >> 24) & 0xF; - if(((ver != 0) && (ver != 1)) || (fam != 0)) + ver = did1 >> 28; + fam = (did1 >> 24) & 0xF; + if(((ver != 0) && (ver != 1)) || (fam != 0)) { - WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris"); + WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris"); } for (i=0;StellarisParts[i].partno;i++) @@ -464,7 +464,7 @@ int stellaris_read_part_info(struct flash_bank_s *bank) } /*************************************************************************** -* flash operations * +* flash operations * ***************************************************************************/ int stellaris_erase_check(struct flash_bank_s *bank) @@ -527,7 +527,7 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) if (stellaris_info->did1 == 0) { - WARNING("Cannot identify target as Stellaris"); + WARNING("Cannot identify target as Stellaris"); return ERROR_FLASH_OPERATION_FAILED; } @@ -546,7 +546,7 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) if ((first == 0) && (last == (stellaris_info->num_pages-1))) { - target_write_u32(target, FLASH_FMA, 0); + target_write_u32(target, FLASH_FMA, 0); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); /* Wait until erase complete */ do @@ -555,18 +555,18 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) } while(flash_fmc & FMC_MERASE); - /* if device has > 128k, then second erase cycle is needed */ - if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) - { - target_write_u32(target, FLASH_FMA, 0x20000); - target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); - /* Wait until erase complete */ - do - { - target_read_u32(target, FLASH_FMC, &flash_fmc); - } - while(flash_fmc & FMC_MERASE); - } + /* if device has > 128k, then second erase cycle is needed */ + if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) + { + target_write_u32(target, FLASH_FMA, 0x20000); + target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); + /* Wait until erase complete */ + do + { + target_read_u32(target, FLASH_FMC, &flash_fmc); + } + while(flash_fmc & FMC_MERASE); + } return ERROR_OK; } @@ -687,26 +687,26 @@ u8 stellaris_write_code[] = r6 = bytes written r7 = temp reg */ - 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */ - 0x08,0x4C, /* ldr r4,FLASHWRITECMD */ - 0x01,0x25, /* movs r5, 1 */ - 0x00,0x26, /* movs r6, #0 */ + 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */ + 0x08,0x4C, /* ldr r4,FLASHWRITECMD */ + 0x01,0x25, /* movs r5, 1 */ + 0x00,0x26, /* movs r6, #0 */ /* mainloop: */ - 0x19,0x60, /* str r1, [r3, #0] */ - 0x87,0x59, /* ldr r7, [r0, r6] */ - 0x5F,0x60, /* str r7, [r3, #4] */ - 0x9C,0x60, /* str r4, [r3, #8] */ + 0x19,0x60, /* str r1, [r3, #0] */ + 0x87,0x59, /* ldr r7, [r0, r6] */ + 0x5F,0x60, /* str r7, [r3, #4] */ + 0x9C,0x60, /* str r4, [r3, #8] */ /* waitloop: */ - 0x9F,0x68, /* ldr r7, [r3, #8] */ - 0x2F,0x42, /* tst r7, r5 */ - 0xFC,0xD1, /* bne waitloop */ - 0x04,0x31, /* adds r1, r1, #4 */ - 0x04,0x36, /* adds r6, r6, #4 */ - 0x96,0x42, /* cmp r6, r2 */ - 0xF4,0xD1, /* bne mainloop */ - 0x00,0xBE, /* bkpt #0 */ + 0x9F,0x68, /* ldr r7, [r3, #8] */ + 0x2F,0x42, /* tst r7, r5 */ + 0xFC,0xD1, /* bne waitloop */ + 0x04,0x31, /* adds r1, r1, #4 */ + 0x04,0x36, /* adds r6, r6, #4 */ + 0x96,0x42, /* cmp r6, r2 */ + 0xF4,0xD1, /* bne mainloop */ + 0x00,0xBE, /* bkpt #0 */ /* pFLASH_CTRL_BASE: */ - 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */ + 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */ /* FLASHWRITECMD: */ 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */ }; -- 2.39.5