]> git.sur5r.net Git - openocd/commitdiff
- reworked image handling to support multiple sections (tested with ihex file contain...
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 30 May 2007 15:47:18 +0000 (15:47 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 30 May 2007 15:47:18 +0000 (15:47 +0000)
This checkin is still experimental, not recommended for general use

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

src/flash/flash.c
src/flash/nand.c
src/openocd.c
src/target/etm.h
src/target/image.c
src/target/image.h
src/target/target.c

index 6af29825ca293b17b85e9c1a465551e54df720b1..58a467d2b30b66e53186d2dc658e7abb8473f67d 100644 (file)
@@ -490,9 +490,10 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c
 int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        u32 offset;
-       u32 binary_size;
        u8 *buffer;
        u32 buf_cnt;
+       u32 image_size;
+       int i;
 
        image_t image;
        
@@ -531,51 +532,62 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha
                return ERROR_OK;
        }
        
-       binary_size = image.size;
-       buffer = malloc(binary_size);
-
-       image_read(&image, binary_size, buffer, &buf_cnt);
-       
-       if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK)
+       image_size = 0x0;
+       for (i = 0; i < image.num_sections; i++)
        {
-               command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x",
-                       args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0));
-               switch (retval)
+               buffer = malloc(image.sections[i].size);
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
                {
-                       case ERROR_TARGET_NOT_HALTED:
-                               command_print(cmd_ctx, "can't work with this flash while target is running");
-                               break;
-                       case ERROR_INVALID_ARGUMENTS:
-                               command_print(cmd_ctx, "usage: flash write <bank> <file> <offset>");
-                               break;
-                       case ERROR_FLASH_BANK_INVALID:
-                               command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base);
-                               break;
-                       case ERROR_FLASH_OPERATION_FAILED:
-                               command_print(cmd_ctx, "flash program error");
-                               break;
-                       case ERROR_FLASH_DST_BREAKS_ALIGNMENT:
-                               command_print(cmd_ctx, "offset breaks required alignment");
-                               break;
-                       case ERROR_FLASH_DST_OUT_OF_BANK:
-                               command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)");
-                               break;
-                       case ERROR_FLASH_SECTOR_NOT_ERASED:
-                               command_print(cmd_ctx, "destination sector(s) not erased");
-                               break;
-                       default:
-                               command_print(cmd_ctx, "unknown error");
+                       ERROR("image_read_section failed with error code: %i", retval);
+                       command_print(cmd_ctx, "image reading failed, flash write aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
                }
+               
+               if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK)
+               {
+                       command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x",
+                               args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0));
+                       switch (retval)
+                       {
+                               case ERROR_TARGET_NOT_HALTED:
+                                       command_print(cmd_ctx, "can't work with this flash while target is running");
+                                       break;
+                               case ERROR_INVALID_ARGUMENTS:
+                                       command_print(cmd_ctx, "usage: flash write <bank> <file> <offset>");
+                                       break;
+                               case ERROR_FLASH_BANK_INVALID:
+                                       command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base);
+                                       break;
+                               case ERROR_FLASH_OPERATION_FAILED:
+                                       command_print(cmd_ctx, "flash program error");
+                                       break;
+                               case ERROR_FLASH_DST_BREAKS_ALIGNMENT:
+                                       command_print(cmd_ctx, "offset breaks required alignment");
+                                       break;
+                               case ERROR_FLASH_DST_OUT_OF_BANK:
+                                       command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)");
+                                       break;
+                               case ERROR_FLASH_SECTOR_NOT_ERASED:
+                                       command_print(cmd_ctx, "destination sector(s) not erased");
+                                       break;
+                               default:
+                                       command_print(cmd_ctx, "unknown error");
+                       }
+               }
+               image_size += buf_cnt;
+
+               free(buffer);
        }
-       else
-       {
-               duration_stop_measure(&duration, &duration_text);
-               command_print(cmd_ctx, "wrote file %s to flash bank %i at offset 0x%8.8x in %s",
-                       args[1], strtoul(args[0], NULL, 0), offset, duration_text);
-               free(duration_text);
-       }
+
        
-       free(buffer);
+       duration_stop_measure(&duration, &duration_text);
+       command_print(cmd_ctx, "wrote %u byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)",
+               image_size, args[1], strtoul(args[0], NULL, 0), offset, duration_text,
+               (float)image_size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
+       free(duration_text);
+
        image_close(&image);
        
        return ERROR_OK;
index 38a70749a4f2553662df8a352cdcc53b30e04026..7ff73512d922a529c266997bd131309f92ca2739 100644 (file)
@@ -1164,8 +1164,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
        u32 buf_cnt;
        enum oob_formats oob_format = NAND_OOB_NONE;
        
-       image_t image;
-       int image_type_identified = 0;
+       fileio_t fileio;
        
        duration_t duration;
        char *duration_text;
@@ -1187,7 +1186,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
                u32 oob_size = 0;
                        
                duration_start_measure(&duration);
-               strtoul(args[2], NULL, 0);
+               offset = strtoul(args[2], NULL, 0);
                
                if (argc > 3)
                {
@@ -1200,40 +1199,18 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
                                        oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY;
                                else
                                {
-                                       if (identify_image_type(&image.type, args[i]) == ERROR_OK)
-                                       {
-                                               image_type_identified = 1;
-                                       }
-                                       else
-                                       {
-                                               command_print(cmd_ctx, "unknown option: %s", args[i]);
-                                       }
+                                       command_print(cmd_ctx, "unknown option: %s", args[i]);
                                }
                        }
                }
                
-               /* if no image type option was encountered, set the default */
-               if (!image_type_identified)
-               {
-                       
-                       identify_image_type(&image.type, NULL);
-                       image_type_identified = 1;
-               }
-
-               image.base_address_set = 1;
-               image.base_address = strtoul(args[2], NULL, 0);
-               image.start_address_set = 0;
-       
-               if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK)
+               if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
                {
-                       command_print(cmd_ctx, "flash write error: %s", image.error_str);
+                       command_print(cmd_ctx, "file open error: %s", fileio.error_str);
                        return ERROR_OK;
                }
        
-               /* the offset might have been overwritten by the image base address */
-               offset = image.base_address;
-               
-               buf_cnt = binary_size = image.size;
+               buf_cnt = binary_size = fileio.size;
                
                if (!(oob_format & NAND_OOB_ONLY))
                {
@@ -1262,7 +1239,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
                        
                        if (page)
                        {
-                               image_read(&image, page_size, page, &size_read);
+                               fileio_read(&fileio, page_size, page, &size_read);
                                buf_cnt -= size_read;
                                if (size_read < page_size)
                                {
@@ -1272,7 +1249,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
                                
                        if (oob)
                        {
-                               image_read(&image, oob_size, oob, &size_read);
+                               fileio_read(&fileio, oob_size, oob, &size_read);
                                buf_cnt -= size_read;
                                if (size_read < oob_size)
                                {
@@ -1289,9 +1266,11 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char
                        offset += page_size;
                }
 
+               fileio_close(&fileio);
+               
                duration_stop_measure(&duration, &duration_text);
                command_print(cmd_ctx, "wrote file %s to NAND flash %s at offset 0x%8.8x in %s",
-                       args[1], args[0], image.base_address, duration_text);
+                       args[1], args[0], offset, duration_text);
                free(duration_text);
        }
        else
index 10a4cfd28e4eb889c4422266cd93c21209f1c29f..9601b9ef1baf96969f39310d34e61a3b6709a3e1 100644 (file)
@@ -18,7 +18,7 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-29 13:15 CEST)"
+#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-30 17:45 CEST)"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
index 595917885a56dcd93518a42dc81def870c62a410..65fd757c8d3971b117f11150d7250162d5cfefcd 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef ETM_H\r
 #define ETM_H\r
 \r
+#include "image.h"\r
 #include "trace.h"\r
 #include "target.h"\r
 #include "register.h"\r
@@ -142,7 +143,7 @@ typedef struct etm_context_s
        etm_portmode_t portmode;                /* normal, multiplexed or demultiplexed */\r
        etmv1_tracemode_t tracemode;    /* type of information the trace contains (data, addres, contextID, ...) */ \r
        armv4_5_state_t core_state;             /* current core state (ARM, Thumb, Jazelle) */\r
-//     trace_image_provider_t image_provider;  /* source for target opcodes */\r
+       image_t image;                                  /* source for target opcodes */\r
        u32 pipe_index;                                 /* current trace cycle */\r
        u32 data_index;                                 /* cycle holding next data packet */\r
        u32 current_pc;                                 /* current program counter */\r
index 3cc9cc5b1d928e4449b6ba7621e7ff43786f3f56..7381440ed604942f75a7c22167ad70156425b4ff 100644 (file)
@@ -39,29 +39,38 @@ int image_ihex_buffer_complete(image_t *image)
        fileio_t *fileio = &ihex->fileio;
        u32 raw_bytes_read, raw_bytes;
        int retval;
-       u32 full_address = image->base_address;
-       char *buffer = malloc(ihex->raw_size);
-       u32 cooked_bytes = 0x0;
+       u32 full_address = 0x0;
+       char *buffer = malloc(fileio->size);
+       u32 cooked_bytes;
+       int i;
        
-       ihex->raw_size = fileio->size;
-       ihex->buffer = malloc(ihex->raw_size >> 1);
+       /* 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];
+       u8 *section_pointer[IMAGE_MAX_SECTIONS];
        
-       if ((retval = fileio_read(fileio, ihex->raw_size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK)
+       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 != ihex->raw_size)
+       if (raw_bytes_read != fileio->size)
        {
                free(buffer);
                ERROR("failed buffering complete IHEX file, only partially read");
                return ERROR_FILEIO_OPERATION_FAILED;
        }
-       
-       image->size = 0x0;
+
+       ihex->buffer = malloc(fileio->size >> 1);
        raw_bytes = 0x0;
+       cooked_bytes = 0x0;
+       image->num_sections = 0;
+       section_pointer[image->num_sections] = &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)
        {
                u32 count;
@@ -75,13 +84,24 @@ int image_ihex_buffer_complete(image_t *image)
                }
                raw_bytes += 9;
                
-               if (record_type == 0)
+               if (record_type == 0) /* Data Record */
                {
                        if ((full_address & 0xffff) != address)
                        {
-                               free(buffer);
-                               ERROR("can't handle non-linear IHEX file");
-                               return ERROR_IMAGE_FORMAT_ERROR;
+                               /* 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_pointer[image->num_sections] = &ihex->buffer[cooked_bytes];
+                               }
+                               section[image->num_sections].base_address =
+                                       (full_address & 0xffff0000) | address;
+                               full_address = (full_address & 0xffff0000) | address;
                        }
                        
                        while (count-- > 0)
@@ -89,16 +109,31 @@ int image_ihex_buffer_complete(image_t *image)
                                sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]);
                                raw_bytes += 2;
                                cooked_bytes += 1;
+                               section[image->num_sections].size += 1;
                                full_address++;
                        }
                }
-               else if (record_type == 1)
+               else if (record_type == 1) /* End of File Record */
                {
+                       /* finish the current section */
+                       image->num_sections++;
+                       
+                       /* copy section information */
+                       ihex->section_pointer = malloc(sizeof(u8*) * image->num_sections);
+                       image->sections = malloc(sizeof(image_section_t) * image->num_sections);
+                       for (i = 0; i < image->num_sections; i++)
+                       {
+                               ihex->section_pointer[i] = section_pointer[i];
+                               image->sections[i].base_address = section[i].base_address +
+                                       ((image->base_address_set) ? image->base_address : 0);
+                               image->sections[i].size = section[i].size;
+                               image->sections[i].flags = section[i].flags;
+                       }
+                       
                        free(buffer);
-                       image->size = cooked_bytes;
                        return ERROR_OK;
                }
-               else if (record_type == 4)
+               else if (record_type == 4) /* Extended Linear Address Record */
                {
                        u16 upper_address;
                        
@@ -107,12 +142,23 @@ int image_ihex_buffer_complete(image_t *image)
                        
                        if ((full_address >> 16) != upper_address)
                        {
-                               free(buffer);
-                               ERROR("can't handle non-linear IHEX file");
-                               return ERROR_IMAGE_FORMAT_ERROR;
+                               /* 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_pointer[image->num_sections] = &ihex->buffer[cooked_bytes];
+                               }
+                               section[image->num_sections].base_address = 
+                                       (full_address & 0xffff) | (upper_address << 16);
+                               full_address = (full_address & 0xffff) | (upper_address << 16);
                        }
                }
-               else if (record_type == 5)
+               else if (record_type == 5) /* Start Linear Address Record */
                {
                        u32 start_address;
                        
@@ -163,10 +209,14 @@ int image_open(image_t *image, void *source, enum fileio_access access)
                        return retval;
                }
                
-               if (access == FILEIO_WRITE)
-                       image->size = 0;
-               else
-                       image->size = image_binary->fileio.size;
+               image->num_sections = 1;
+               image->sections = malloc(sizeof(image_section_t));
+               image->sections[0].base_address = 0x0;
+               image->sections[0].size = image_binary->fileio.size;
+               image->sections[0].flags = 0;
+               
+               if (image->base_address_set == 1)
+                       image->sections[0].base_address = image->base_address;
                
                return ERROR_OK;
        }
@@ -192,9 +242,6 @@ int image_open(image_t *image, void *source, enum fileio_access access)
                        return retval;
                }
                
-               image_ihex->position = 0;
-               image_ihex->raw_size = image_ihex->fileio.size;
-               
                if ((retval = image_ihex_buffer_complete(image)) != ERROR_OK)
                {
                        snprintf(image->error_str, IMAGE_MAX_ERROR_STRING,
@@ -217,7 +264,7 @@ int image_open(image_t *image, void *source, enum fileio_access access)
        return retval;
 };
 
-int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read)
+int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read)
 {
        int retval;
        
@@ -225,6 +272,21 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read)
        {
                image_binary_t *image_binary = image->type_private;
                
+               /* only one section in a plain binary */
+               if (section != 0)
+                       return ERROR_INVALID_ARGUMENTS;
+                       
+               if ((offset > image->sections[0].size) || (offset + size > image->sections[0].size))
+                       return ERROR_INVALID_ARGUMENTS;
+               
+               /* seek to offset */
+               if ((retval = fileio_seek(&image_binary->fileio, offset)) != ERROR_OK)
+               {
+                       strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING);
+                       return retval;
+               }
+               
+               /* return requested bytes */
                if ((retval = fileio_read(&image_binary->fileio, size, buffer, size_read)) != ERROR_OK)
                {
                        strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING);
@@ -234,15 +296,8 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read)
        else if (image->type == IMAGE_IHEX)
        {
                image_ihex_t *image_ihex = image->type_private;
-       
-               if ((image_ihex->position + size) > image->size)
-               {
-                       /* don't read past the end of the file */
-                       size = (image->size - image_ihex->position);
-               }
-       
-               memcpy(buffer, image_ihex->buffer + image_ihex->position, size);
-               image_ihex->position += size;
+
+               memcpy(buffer, image_ihex->section_pointer[section] + offset, size);
                *size_read = size;
                image->error_str[0] = '\0';
                
@@ -256,37 +311,6 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read)
        return ERROR_OK;
 }
 
-int image_write(image_t *image, u32 size, u8 *buffer, u32 *size_written)
-{
-       int retval = ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
-       
-       if (image->type == IMAGE_BINARY)
-       {
-               image_binary_t *image_binary = image->type_private;
-               
-               if ((retval = fileio_write(&image_binary->fileio, size, buffer, size_written)) != ERROR_OK)
-               {
-                       strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING);
-                       return retval;
-               }
-       }
-       else if (image->type == IMAGE_IHEX)
-       {
-               return ERROR_FILEIO_OPERATION_NOT_SUPPORTED;
-       }
-       else if (image->type == IMAGE_MEMORY)
-       {
-               /* TODO: handle target memory pseudo image */
-       }
-       
-       if (retval != ERROR_OK)
-               return retval;
-               
-       image->size += size;
-       
-       return ERROR_OK;
-}
-
 int image_close(image_t *image)
 {
        if (image->type == IMAGE_BINARY)
@@ -301,6 +325,9 @@ int image_close(image_t *image)
                
                fileio_close(&image_ihex->fileio);
                
+               if (image_ihex->section_pointer)
+                       free(image_ihex->section_pointer);
+               
                if (image_ihex->buffer)
                        free(image_ihex->buffer);
        }
@@ -309,7 +336,11 @@ int image_close(image_t *image)
                /* do nothing for now */
        }
 
-       free(image->type_private);
+       if (image->type_private)
+               free(image->type_private);
+       
+       if (image->sections)
+               free(image->sections);
        
        return ERROR_OK;
 }
index 3df175a8d6c3ccd07737bee065b15a5fb08ce0ec..75288791a6394a6a2b8f5820c776a669cf86c824 100644 (file)
 #include "target.h"
 
 #define IMAGE_MAX_ERROR_STRING         (128)
+#define IMAGE_MAX_SECTIONS                     (128)
 
 typedef enum image_type
 {
     IMAGE_BINARY,      /* plain binary */
-    IMAGE_IHEX,        /* intel hex-record format */
+    IMAGE_IHEX,                /* intel hex-record format */
     IMAGE_MEMORY,      /* target-memory pseudo-image */
 /*
  * Possible future enhancements:
@@ -37,15 +38,23 @@ typedef enum image_type
  */
 } image_type_t;
 
+typedef struct image_section_s
+{
+       u32 base_address;
+       u32 size;
+       int flags;
+} image_section_t;
+
 typedef struct image_s
 {
        image_type_t type;              /* image type (plain, ihex, ...) */
        void *type_private;             /* type private data */
-       int base_address_set;   /* whether the image start address has been set */
-       u32 base_address;               /* base address of image in target memory */
+       int num_sections;               /* number of sections contained in the image */
+       image_section_t *sections;      /* array of sections */
+       int base_address_set;   /* whether the image has a base address set (for relocation purposes) */
+       int base_address;               /* base address, if one is set */
        int start_address_set;  /* whether the image has a start address (entry point) associated */
        u32 start_address;              /* start address, if one is set */
-       u32 size;                               /* image size in byte */
        char error_str[IMAGE_MAX_ERROR_STRING];
 } image_t;
 
@@ -57,9 +66,8 @@ typedef struct image_binary_s
 typedef struct image_ihex_s
 {
        fileio_t fileio;
-       u32 position;
-       u32 raw_size;
        u8 *buffer;
+       u8 **section_pointer;
 } image_ihex_t;
 
 typedef struct image_memory_s
@@ -68,8 +76,7 @@ typedef struct image_memory_s
 } image_memory_t;
 
 extern int image_open(image_t *image, void *source, enum fileio_access access);
-extern int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_written);
-extern int image_write(image_t *image, u32 size, u8 *buffer, u32 *size_written);
+extern int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read);
 extern int image_close(image_t *image);
 extern int identify_image_type(image_type_t *type, char *type_string);
 
index e980ae4a147239143ccd80b1473ab4c0fb6127ca..b7f842e7b8f85e8641a00bc79a9e063774e64395 100644 (file)
@@ -1658,6 +1658,8 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char
        u8 *buffer;
        u32 buf_cnt;
        u32 image_size;
+       int i;
+       int retval;
 
        image_t image;  
        
@@ -1678,8 +1680,6 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char
        image.base_address = strtoul(args[1], NULL, 0);
        
        image.start_address_set = 0;
-       
-       buffer = malloc(128 * 1024);
 
        duration_start_measure(&duration);
        
@@ -1689,21 +1689,27 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                return ERROR_OK;
        }
        
-       image_size = image.size;
-       address = image.base_address;
-       
-       while ((image_size > 0) &&
-               (image_read(&image, 128 * 1024, buffer, &buf_cnt) == ERROR_OK))
+       image_size = 0x0;
+       for (i = 0; i < image.num_sections; i++)
        {
-               target_write_buffer(target, address, buf_cnt, buffer);
-               address += buf_cnt;
-               image_size -= buf_cnt;
+               buffer = malloc(image.sections[i].size);
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+               {
+                       ERROR("image_read_section failed with error code: %i", retval);
+                       command_print(cmd_ctx, "image reading failed, download aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
+               image_size += buf_cnt;
+               command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
+               
+               free(buffer);
        }
 
-       free(buffer);
-       
        duration_stop_measure(&duration, &duration_text);
-       command_print(cmd_ctx, "downloaded %u byte in %s", image.size, duration_text);
+       command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
        free(duration_text);
        
        image_close(&image);