- flash autoerase <on|off> cmd added, default is off - flash banks are calculated...
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 1 Oct 2007 08:31:30 +0000 (08:31 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 1 Oct 2007 08:31:30 +0000 (08:31 +0000)
- corrected array overrun in armv7m.c
- corrected breakpoint memory allocation bug
- image read now uses fgets, vastly improves reading of large files
- improved hex file reading, support for Linear Address Record added

git-svn-id: svn://svn.berlios.de/openocd/trunk@208 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/flash/flash.c
src/flash/flash.h
src/helper/fileio.c
src/helper/fileio.h
src/jtag/ft2232.c
src/server/gdb_server.c
src/target/armv7m.c
src/target/breakpoints.c
src/target/image.c

index 83b6fc3703a956bc5ee5ca99f927efeab58045e0..9ab34e7b67fc933f5dead9882a7eeabebe593427 100644 (file)
@@ -49,6 +49,7 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
 int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 /* flash drivers
  */
@@ -76,6 +77,7 @@ flash_driver_t *flash_drivers[] =
 
 flash_bank_t *flash_banks;
 static         command_t *flash_cmd;
+static int auto_erase = 0;
 
 int flash_register_commands(struct command_context_s *cmd_ctx)
 {
@@ -110,6 +112,8 @@ int flash_init(struct command_context_s *cmd_ctx)
                                                 "write image <file> [offset] [type]");
                register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC,
                                                 "set protection of sectors at <bank> <first> <last> <on|off>");
+               register_command(cmd_ctx, flash_cmd, "auto_erase", handle_flash_auto_erase_command, COMMAND_EXEC,
+                                                "auto erase flash sectors <on|off>");
        }
        
        return ERROR_OK;
@@ -566,7 +570,7 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
        
        failed = malloc(sizeof(int) * image.num_sections);
 
-       if ((retval = flash_write(target, &image, &written, &error_str, failed)) != ERROR_OK)
+       if ((retval = flash_write(target, &image, &written, &error_str, failed, auto_erase)) != ERROR_OK)
        {
                command_print(cmd_ctx, "failed writing image %s: %s", args[0], error_str);
                free(error_str);
@@ -700,17 +704,16 @@ flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr)
 int flash_erase(target_t *target, u32 addr, u32 length)
 {
        flash_bank_t *c;
-       unsigned long sector_size;
-       int first;
-       int last;
-
+       int first = -1;
+       int last = -1;
+       int i;
+       
        if ((c = get_flash_bank_by_addr(target, addr)) == NULL)
                return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */
-       /* sanity checks */
-       if (c->size == 0 || c->num_sectors == 0 || c->size % c->num_sectors)
-               return ERROR_FLASH_BANK_INVALID;
 
+       if (c->size == 0 || c->num_sectors == 0)
+               return ERROR_FLASH_BANK_INVALID;
+       
        if (length == 0)
        {
                /* special case, erase whole bank when length is zero */
@@ -722,22 +725,29 @@ int flash_erase(target_t *target, u32 addr, u32 length)
 
        /* check whether it fits */
        if (addr + length > c->base + c->size)
-         return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
-
-       /* calculate sector size */
-       sector_size = c->size / c->num_sectors;
-
-       /* check alignment */
-       if ((addr - c->base) % sector_size || length % sector_size)
                return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
-
-       first = (addr - c->base) / sector_size;
-       last = first + length / sector_size - 1;
+       
+       addr -= c->base;
+       
+       for (i = 0; i < c->num_sectors; i++)
+       {               
+               /* check whether sector overlaps with the given range and is not yet erased */
+               if (addr < c->sectors[i].offset + c->sectors[i].size && addr + length > c->sectors[i].offset && c->sectors[i].is_erased != 1) {
+                       /* if first is not set yet then this is the first sector */
+                       if (first == -1)
+                               first = i;
+                       last = i; /* and it is the last one so far in any case */
+               }
+       }
+       
+       if( first == -1 || last == -1 )
+               return ERROR_OK;
+       
        return c->driver->erase(c, first, last);
 }
 
 /* write an image to flash memory of the given target */
-int flash_write(target_t *target, image_t *image, u32 *written, char **error_str, int *failed)
+int flash_write(target_t *target, image_t *image, u32 *written, char **error_str, int *failed, int erase)
 {
        int retval;
        int i;
@@ -854,7 +864,20 @@ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str
                        }
                }
 
-               retval = c->driver->write(c, buffer, run_address - c->base, run_size);
+               retval = ERROR_OK;
+               \r
+               if (erase)
+               {
+                       /* calculate and erase sectors */
+                       retval = flash_erase( target, run_address, run_size );
+               }
+               
+               if (retval == ERROR_OK)
+               {
+                       /* write flash sectors */
+                       retval = c->driver->write(c, buffer, run_address - c->base, run_size);
+               }
+               
                free(buffer);
 
                if (retval != ERROR_OK)
@@ -896,3 +919,20 @@ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str
 
        return ERROR_OK;
 }
+
+int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc != 1)
+       {
+               command_print(cmd_ctx, "usage: flash auto_erase <on|off>");
+               return ERROR_OK;
+       }
+       
+       if (strcmp(args[0], "on") == 0)
+               auto_erase = 1;
+       else if (strcmp(args[0], "off") == 0)
+               auto_erase = 0;
+       
+       return ERROR_OK;
+}
+
index 7ba6ff54e688125e456893456779cb03b61efc89..e8f915009ff0ac0513ebca43e32d87b744a16d8c 100644 (file)
@@ -67,7 +67,7 @@ extern int flash_register_commands(struct command_context_s *cmd_ctx);
 extern int flash_init(struct command_context_s *cmd_ctx);
 
 extern int flash_erase(target_t *target, u32 addr, u32 length);
-extern int flash_write(target_t *target, image_t *image, u32 *written, char **error, int *failed);
+extern int flash_write(target_t *target, image_t *image, u32 *written, char **error, int *failed, int erase);
 
 extern flash_bank_t *get_flash_bank_by_num(int num);
 extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr);
index b0ad446e179171c1768431d662494cc4a66620bb..3ee0b18bc6651f6d58abc7e3b479ca2c0319dd83 100644 (file)
@@ -284,6 +284,29 @@ int fileio_read_u32(fileio_t *fileio, u32 *data)
        return ERROR_OK;
 }
 
+int fileio_local_fgets(fileio_t *fileio, u32 size, u8 *buffer)
+{
+       fileio_local_t *fileio_local = fileio->location_private;
+       
+       if( fgets(buffer, size, fileio_local->file) == NULL)
+               return ERROR_FILEIO_OPERATION_FAILED;
+       
+       return ERROR_OK;
+}
+
+int fileio_fgets(fileio_t *fileio, u32 size, u8 *buffer)
+{
+       switch (fileio->location)
+       {
+               case FILEIO_LOCAL:
+                       return fileio_local_fgets(fileio, size, buffer);
+                       break;
+               default:
+                       ERROR("BUG: should never get here");
+                       exit(-1);
+       }
+}
+
 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
 {
        fileio_local_t *fileio_local = fileio->location_private;
index 5c0a88dae4146a502b0862e0f445bedf06c745fb..20e5c62962eb51a8e1b93187a8a86b26d16f9da6 100644 (file)
@@ -79,6 +79,7 @@ typedef struct fileio_local_s
 
 extern int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written);
 extern int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read);
+extern int fileio_fgets(fileio_t *fileio, u32 size, u8 *buffer);
 extern int fileio_seek(fileio_t *fileio, u32 position);
 extern int fileio_close(fileio_t *fileio);
 extern int fileio_open(fileio_t *fileio, char *url, enum fileio_access access, enum fileio_type type);
index 629bab08495e4b3311629efa5cdb822029ec1849..137ea64b16ad80a2f1edff56543f719cfbab1091 100644 (file)
@@ -249,7 +249,7 @@ int ft2232_speed(int speed)
        u32 bytes_written;
 
        buf[0] = 0x86; /* command "set divisor" */
-       buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=1.5MHz, ...*/
+       buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=2.0MHz, ...*/
        buf[2] = (speed >> 8) & 0xff; /* valueH */
        
        DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
index 5dd6f3c207f9529a653cc99cadecf608a43bf398..f579de1c4c92a1af999efe7223521f6d09010e01 100644 (file)
@@ -1274,7 +1274,7 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
                char *error_str;
 
                /* process the flashing buffer */
-               if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL)) != ERROR_OK)
+               if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL, 0)) != ERROR_OK)
                {
                        if (result == ERROR_FLASH_DST_OUT_OF_BANK)
                                gdb_put_packet(connection, "E.memtype", 9);
index 96864fd1299d76fd184a0d642a3347c55efa3005..7010b5c0f4d09f6b4bd10eb3a13e8adc75120b2c 100644 (file)
@@ -186,7 +186,7 @@ int armv7m_restore_context(target_t *target)
        if (armv7m->pre_restore_context)
                armv7m->pre_restore_context(target);
                
-       for (i = ARMV7NUMCOREREGS; i >= 0; i--)
+       for (i = ARMV7NUMCOREREGS-1; i >= 0; i--)
        {
                if (armv7m->core_cache->reg_list[i].dirty)
                {
index cc38d029b9f13cbb0deed9686379a7bb8855a2db..f52ff3067a11a9c83c4ad46e789c120326907141 100644 (file)
@@ -62,7 +62,7 @@ int breakpoint_add(target_t *target, u32 address, u32 length, enum breakpoint_ty
        (*breakpoint_p)->length = length;
        (*breakpoint_p)->type = type;
        (*breakpoint_p)->set = 0;
-       (*breakpoint_p)->orig_instr = malloc(CEIL(length, 8));
+       (*breakpoint_p)->orig_instr = malloc(length);
        (*breakpoint_p)->next = NULL;
        
        if ((retval = target->type->add_breakpoint(target, *breakpoint_p)) != ERROR_OK)
index 0c203f6b57b3df37c00c0c3eebe2982b49766858..dbb1c2ab3a41791de683a42bdf760bb209888b05 100644 (file)
@@ -154,52 +154,37 @@ int image_ihex_buffer_complete(image_t *image)
 {
        image_ihex_t *ihex = image->type_private;
        fileio_t *fileio = &ihex->fileio;
-       u32 raw_bytes_read, raw_bytes;
-       int retval;
        u32 full_address = 0x0;
-       char *buffer = malloc(fileio->size);
        u32 cooked_bytes;
        int i;
+       char lpszLine[1023];
        
        /* we can't determine the number of sections that we'll have to create ahead of time,
         * so we locally hold them until parsing is finished */
        image_section_t section[IMAGE_MAX_SECTIONS];
-       
-       if ((retval = fileio_read(fileio, fileio->size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK)
-       {
-               free(buffer);
-               ERROR("failed buffering IHEX file, read failed");
-               return ERROR_FILEIO_OPERATION_FAILED;
-       }
-       
-       if (raw_bytes_read != fileio->size)
-       {
-               free(buffer);
-               ERROR("failed buffering complete IHEX file, only partially read");
-               return ERROR_FILEIO_OPERATION_FAILED;
-       }
 
        ihex->buffer = malloc(fileio->size >> 1);
-       raw_bytes = 0x0;
        cooked_bytes = 0x0;
        image->num_sections = 0;
        section[image->num_sections].private = &ihex->buffer[cooked_bytes];
        section[image->num_sections].base_address = 0x0;
        section[image->num_sections].size = 0x0;
        section[image->num_sections].flags = 0;
-       while (raw_bytes < raw_bytes_read)
+       
+       while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK)
        {
                u32 count;
                u32 address;
                u32 record_type;
                u32 checksum;
                u8 cal_checksum = 0;
+               u32 bytes_read = 0;
                
-               if (sscanf(&buffer[raw_bytes], ":%2x%4x%2x", &count, &address, &record_type) != 3)
+               if (sscanf(&lpszLine[bytes_read], ":%2x%4x%2x", &count, &address, &record_type) != 3)
                {
                        return ERROR_IMAGE_FORMAT_ERROR;
                }
-               raw_bytes += 9;
+               bytes_read += 9;
                
                cal_checksum += (u8)count;
                cal_checksum += (u8)(address >> 8);
@@ -228,9 +213,9 @@ int image_ihex_buffer_complete(image_t *image)
                        
                        while (count-- > 0)
                        {
-                               sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]);
+                               sscanf(&lpszLine[bytes_read], "%2x", (u32*)&ihex->buffer[cooked_bytes]);
                                cal_checksum += (u8)ihex->buffer[cooked_bytes];
-                               raw_bytes += 2;
+                               bytes_read += 2;
                                cooked_bytes += 1;
                                section[image->num_sections].size += 1;
                                full_address++;
@@ -252,17 +237,43 @@ int image_ihex_buffer_complete(image_t *image)
                                image->sections[i].flags = section[i].flags;
                        }
                        
-                       free(buffer);
                        return ERROR_OK;
                }
+               else if (record_type == 2) /* Linear Address Record */
+               {
+                       u16 upper_address;
+                       
+                       sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
+                       cal_checksum += (u8)(upper_address >> 8);
+                       cal_checksum += (u8)upper_address;
+                       bytes_read += 4;
+                       
+                       if ((full_address >> 4) != upper_address)
+                       {
+                               /* we encountered a nonconsecutive location, create a new section,
+                                * unless the current section has zero size, in which case this specifies
+                                * the current section's base address
+                                */
+                               if (section[image->num_sections].size != 0)
+                               {
+                                       image->num_sections++;
+                                       section[image->num_sections].size = 0x0;
+                                       section[image->num_sections].flags = 0;
+                                       section[image->num_sections].private = &ihex->buffer[cooked_bytes];
+                               }
+                               section[image->num_sections].base_address = 
+                                       (full_address & 0xffff) | (upper_address << 4);
+                               full_address = (full_address & 0xffff) | (upper_address << 4);
+                       }
+               }
                else if (record_type == 4) /* Extended Linear Address Record */
                {
                        u16 upper_address;
                        
-                       sscanf(&buffer[raw_bytes], "%4hx", &upper_address);
+                       sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
                        cal_checksum += (u8)(upper_address >> 8);
                        cal_checksum += (u8)upper_address;
-                       raw_bytes += 4;
+                       bytes_read += 4;
                        
                        if ((full_address >> 16) != upper_address)
                        {
@@ -286,43 +297,33 @@ int image_ihex_buffer_complete(image_t *image)
                {
                        u32 start_address;
                        
-                       sscanf(&buffer[raw_bytes], "%8x", &start_address);
+                       sscanf(&lpszLine[bytes_read], "%8x", &start_address);
                        cal_checksum += (u8)(start_address >> 24);
                        cal_checksum += (u8)(start_address >> 16);
                        cal_checksum += (u8)(start_address >> 8);
                        cal_checksum += (u8)start_address;
-                       raw_bytes += 8;
+                       bytes_read += 8;
                        
                        image->start_address_set = 1;
                        image->start_address = be_to_h_u32((u8*)&start_address);
                }
                else
                {
-                       free(buffer);
                        ERROR("unhandled IHEX record type: %i", record_type);
                        return ERROR_IMAGE_FORMAT_ERROR;
                }
                
-               sscanf(&buffer[raw_bytes], "%2x", &checksum);
-               raw_bytes += 2;
+               sscanf(&lpszLine[bytes_read], "%2x", &checksum);
+               bytes_read += 2;
                
                if ((u8)checksum != (u8)(~cal_checksum + 1))
                {
                        /* checksum failed */
-                       free(buffer);
                        ERROR("incorrect record checksum found in IHEX file");
                        return ERROR_IMAGE_CHECKSUM;
                }
-               
-               /* consume new-line character(s) */
-               if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
-                       raw_bytes++;
-
-               if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
-                       raw_bytes++;
        }
-
-       free(buffer);
+       
        ERROR("premature end of IHEX file, no end-of-file record found");
        return ERROR_IMAGE_FORMAT_ERROR;
 }
@@ -466,33 +467,16 @@ int image_mot_buffer_complete(image_t *image)
 {
        image_mot_t *mot = image->type_private;
        fileio_t *fileio = &mot->fileio;
-       u32 raw_bytes_read, raw_bytes;
-       int retval;
        u32 full_address = 0x0;
-       char *buffer = malloc(fileio->size);
        u32 cooked_bytes;
        int i;
+       char lpszLine[1023];
        
        /* we can't determine the number of sections that we'll have to create ahead of time,
         * so we locally hold them until parsing is finished */
        image_section_t section[IMAGE_MAX_SECTIONS];
        
-       if ((retval = fileio_read(fileio, fileio->size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK)
-       {
-               free(buffer);
-               ERROR("failed buffering S19 file, read failed");
-               return ERROR_FILEIO_OPERATION_FAILED;
-       }
-       
-       if (raw_bytes_read != fileio->size)
-       {
-               free(buffer);
-               ERROR("failed buffering complete IHEX file, only partially read");
-               return ERROR_FILEIO_OPERATION_FAILED;
-       }
-
        mot->buffer = malloc(fileio->size >> 1);
-       raw_bytes = 0x0;
        cooked_bytes = 0x0;
        image->num_sections = 0;
        section[image->num_sections].private = &mot->buffer[cooked_bytes];
@@ -500,21 +484,22 @@ int image_mot_buffer_complete(image_t *image)
        section[image->num_sections].size = 0x0;
        section[image->num_sections].flags = 0;
        
-       while (raw_bytes < raw_bytes_read)
+       while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK)
        {
                u32 count;
                u32 address;
                u32 record_type;
                u32 checksum;
                u8 cal_checksum = 0;
-               
+               u32 bytes_read = 0;
+                       
                /* get record type and record length */
-               if (sscanf(&buffer[raw_bytes], "S%1x%2x", &record_type, &count) != 2)
+               if (sscanf(&lpszLine[bytes_read], "S%1x%2x", &record_type, &count) != 2)
                {
                        return ERROR_IMAGE_FORMAT_ERROR;
                }
                
-               raw_bytes += 4;
+               bytes_read += 4;
                cal_checksum += (u8)count;
                
                /* skip checksum byte */
@@ -526,9 +511,9 @@ int image_mot_buffer_complete(image_t *image)
                        int iValue;
                        
                        while (count-- > 0) {
-                               sscanf(&buffer[raw_bytes], "%2x", &iValue);
+                               sscanf(&lpszLine[bytes_read], "%2x", &iValue);
                                cal_checksum += (u8)iValue;
-                               raw_bytes += 2;
+                               bytes_read += 2;
                        }
                }
                else if (record_type >= 1 && record_type <= 3)
@@ -537,31 +522,31 @@ int image_mot_buffer_complete(image_t *image)
                        {
                                case 1:
                                        /* S1 - 16 bit address data record */
-                                       sscanf(&buffer[raw_bytes], "%4x", &address);
+                                       sscanf(&lpszLine[bytes_read], "%4x", &address);
                                        cal_checksum += (u8)(address >> 8);
                                        cal_checksum += (u8)address;
-                                       raw_bytes += 4;
+                                       bytes_read += 4;
                                        count -=2;
                                        break;
                        
                                case 2:
                                        /* S2 - 24 bit address data record */
-                                       sscanf(&buffer[raw_bytes], "%6x", &address);
+                                       sscanf(&lpszLine[bytes_read], "%6x", &address);
                                        cal_checksum += (u8)(address >> 16);
                                        cal_checksum += (u8)(address >> 8);
                                        cal_checksum += (u8)address;
-                                       raw_bytes += 6;
+                                       bytes_read += 6;
                                        count -=3;
                                        break;
                                        
                                case 3:
                                        /* S3 - 32 bit address data record */
-                                       sscanf(&buffer[raw_bytes], "%8x", &address);
+                                       sscanf(&lpszLine[bytes_read], "%8x", &address);
                                        cal_checksum += (u8)(address >> 24);
                                        cal_checksum += (u8)(address >> 16);
                                        cal_checksum += (u8)(address >> 8);
                                        cal_checksum += (u8)address;
-                                       raw_bytes += 8;
+                                       bytes_read += 8;
                                        count -=4;
                                        break;
                        
@@ -580,16 +565,15 @@ int image_mot_buffer_complete(image_t *image)
                                        section[image->num_sections].flags = 0;
                                        section[image->num_sections].private = &mot->buffer[cooked_bytes];
                                }
-                               section[image->num_sections].base_address =
-                                       full_address | address;
-                               full_address = full_address | address;
+                               section[image->num_sections].base_address = address;
+                               full_address = address;
                        }
                        
                        while (count-- > 0)
                        {
-                               sscanf(&buffer[raw_bytes], "%2hhx", &mot->buffer[cooked_bytes]);
+                               sscanf(&lpszLine[bytes_read], "%2x", (u32*)&mot->buffer[cooked_bytes]);
                                cal_checksum += (u8)mot->buffer[cooked_bytes];
-                               raw_bytes += 2;
+                               bytes_read += 2;
                                cooked_bytes += 1;
                                section[image->num_sections].size += 1;
                                full_address++;
@@ -611,38 +595,27 @@ int image_mot_buffer_complete(image_t *image)
                                image->sections[i].flags = section[i].flags;
                        }
                        
-                       free(buffer);
                        return ERROR_OK;
                }
                else
                {
-                       free(buffer);
                        ERROR("unhandled S19 record type: %i", record_type);
                        return ERROR_IMAGE_FORMAT_ERROR;
                }
                
                /* account for checksum, will always be 0xFF */
-               sscanf(&buffer[raw_bytes], "%2x", &checksum);
+               sscanf(&lpszLine[bytes_read], "%2x", &checksum);
                cal_checksum += (u8)checksum;
-               raw_bytes += 2;
+               bytes_read += 2;
                
                if( cal_checksum != 0xFF )
                {
                        /* checksum failed */
-                       free(buffer);
                        ERROR("incorrect record checksum found in S19 file");
                        return ERROR_IMAGE_CHECKSUM;
                }
-               
-               /* consume new-line character(s) */
-               if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
-                       raw_bytes++;
-
-               if ((buffer[raw_bytes] == '\n') || (buffer[raw_bytes] == '\r'))
-                       raw_bytes++;
        }
-
-       free(buffer);
+       
        ERROR("premature end of S19 file, no end-of-file record found");
        return ERROR_IMAGE_FORMAT_ERROR;
 }

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)