#include "image.h"
#include "target.h"
-#include "log.h"
+#include <helper/log.h>
/* convert ELF header field to host endianness */
{
int retval;
struct fileio fileio;
- uint32_t read_bytes;
+ size_t read_bytes;
uint8_t buffer[9];
/* read the first 4 bytes of image */
return ERROR_OK;
}
-static int image_ihex_buffer_complete(struct image *image)
+static int image_ihex_buffer_complete_inner(struct image *image, char *lpszLine, struct imagesection *section)
{
struct image_ihex *ihex = image->type_private;
struct fileio *fileio = &ihex->fileio;
uint32_t full_address = 0x0;
uint32_t 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 */
- struct imageection section[IMAGE_MAX_SECTIONS];
- ihex->buffer = malloc(fileio->size >> 1);
+ int filesize;
+ int retval;
+ retval = fileio_size(fileio, &filesize);
+ if (retval != ERROR_OK)
+ return retval;
+
+ ihex->buffer = malloc(filesize >> 1);
cooked_bytes = 0x0;
image->num_sections = 0;
section[image->num_sections].private = &ihex->buffer[cooked_bytes];
uint32_t record_type;
uint32_t checksum;
uint8_t cal_checksum = 0;
- uint32_t bytes_read = 0;
+ size_t bytes_read = 0;
if (sscanf(&lpszLine[bytes_read], ":%2" SCNx32 "%4" SCNx32 "%2" SCNx32 , &count, &address, &record_type) != 3)
{
image->num_sections++;
/* copy section information */
- image->sections = malloc(sizeof(struct imageection) * image->num_sections);
+ image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
for (i = 0; i < image->num_sections; i++)
{
image->sections[i].private = section[i].private;
return ERROR_IMAGE_FORMAT_ERROR;
}
+/**
+ * Allocate memory dynamically instead of on the stack. This
+ * is important w/embedded hosts.
+ */
+static int image_ihex_buffer_complete(struct image *image)
+{
+ char *lpszLine = malloc(1023);
+ if (lpszLine == NULL)
+ {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS);
+ if (section == NULL)
+ {
+ free(lpszLine);
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ int retval;
+
+ retval = image_ihex_buffer_complete_inner(image, lpszLine, section);
+
+ free(section);
+ free(lpszLine);
+
+ return retval;
+}
+
static int image_elf_read_headers(struct image *image)
{
struct image_elf *elf = image->type_private;
- uint32_t read_bytes;
+ size_t read_bytes;
uint32_t i,j;
int retval;
+ uint32_t nload,load_to_vaddr=0;
elf->header = malloc(sizeof(Elf32_Ehdr));
if ((elf->endianness != ELFDATA2LSB)
&&(elf->endianness != ELFDATA2MSB))
{
- LOG_ERROR("invalid ELF file, unknown endianess setting");
+ LOG_ERROR("invalid ELF file, unknown endianness setting");
return ERROR_IMAGE_FORMAT_ERROR;
}
for (i = 0;i < elf->segment_count;i++)
if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0))
image->num_sections++;
+
+ /**
+ * some ELF linkers produce binaries with *all* the program header
+ * p_paddr fields zero (there can be however one loadable segment
+ * that has valid physical address 0x0).
+ * If we have such a binary with more than
+ * one PT_LOAD header, then use p_vaddr instead of p_paddr
+ * (ARM ELF standard demands p_paddr = 0 anyway, and BFD
+ * library uses this approach to workaround zero-initialized p_paddrs
+ * when obtaining lma - look at elf.c of BDF)
+ */
+ for (nload = 0, i = 0; i < elf->segment_count; i++)
+ if (elf->segments[i].p_paddr != 0)
+ break;
+ else if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_memsz) != 0))
+ ++nload;
+
+ if (i >= elf->segment_count && nload > 1)
+ load_to_vaddr = 1;
+
/* alloc and fill sections array with loadable segments */
- image->sections = malloc(image->num_sections * sizeof(struct imageection));
+ image->sections = malloc(image->num_sections * sizeof(struct imagesection));
for (i = 0,j = 0;i < elf->segment_count;i++)
{
if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0))
{
image->sections[j].size = field32(elf,elf->segments[i].p_filesz);
- image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr);
+ if (load_to_vaddr)
+ image->sections[j].base_address = field32(elf,elf->segments[i].p_vaddr);
+ else
+ image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr);
image->sections[j].private = &elf->segments[i];
image->sections[j].flags = field32(elf,elf->segments[i].p_flags);
j++;
return ERROR_OK;
}
-static int image_elf_read_section(struct image *image, int section, uint32_t offset, uint32_t size, uint8_t *buffer, uint32_t *size_read)
+static int image_elf_read_section(struct image *image, int section, uint32_t offset, uint32_t size, uint8_t *buffer, size_t *size_read)
{
struct image_elf *elf = image->type_private;
Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private;
- uint32_t read_size,really_read;
+ size_t read_size,really_read;
int retval;
*size_read = 0;
{
/* maximal size present in file for the current segment */
read_size = MIN(size, field32(elf,segment->p_filesz)-offset);
- LOG_DEBUG("read elf: size = 0x%" PRIx32 " at 0x%" PRIx32 "",read_size,
+ LOG_DEBUG("read elf: size = 0x%zu at 0x%" PRIx32 "", read_size,
field32(elf,segment->p_offset) + offset);
/* read initialized area of the segment */
if ((retval = fileio_seek(&elf->fileio, field32(elf,segment->p_offset) + offset)) != ERROR_OK)
return ERROR_OK;
}
-static int image_mot_buffer_complete(struct image *image)
+static int image_mot_buffer_complete_inner(struct image *image, char *lpszLine, struct imagesection *section)
{
struct image_mot *mot = image->type_private;
struct fileio *fileio = &mot->fileio;
uint32_t full_address = 0x0;
uint32_t 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 */
- struct imageection section[IMAGE_MAX_SECTIONS];
- mot->buffer = malloc(fileio->size >> 1);
+ int retval;
+ int filesize;
+ retval = fileio_size(fileio, &filesize);
+ if (retval != ERROR_OK)
+ return retval;
+
+ mot->buffer = malloc(filesize >> 1);
cooked_bytes = 0x0;
image->num_sections = 0;
section[image->num_sections].private = &mot->buffer[cooked_bytes];
image->num_sections++;
/* copy section information */
- image->sections = malloc(sizeof(struct imageection) * image->num_sections);
+ image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
for (i = 0; i < image->num_sections; i++)
{
image->sections[i].private = section[i].private;
return ERROR_IMAGE_FORMAT_ERROR;
}
+/**
+ * Allocate memory dynamically instead of on the stack. This
+ * is important w/embedded hosts.
+ */
+static int image_mot_buffer_complete(struct image *image)
+{
+ char *lpszLine = malloc(1023);
+ if (lpszLine == NULL)
+ {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ struct imagesection *section = malloc(sizeof(struct imagesection) * IMAGE_MAX_SECTIONS);
+ if (section == NULL)
+ {
+ free(lpszLine);
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+ int retval;
+
+ retval = image_mot_buffer_complete_inner(image, lpszLine, section);
+
+ free(section);
+ free(lpszLine);
+
+ return retval;
+}
+
+
int image_open(struct image *image, const char *url, const char *type_string)
{
int retval = ERROR_OK;
{
return retval;
}
+ int filesize;
+ retval = fileio_size(&image_binary->fileio, &filesize);
+ if (retval != ERROR_OK)
+ {
+ fileio_close(&image_binary->fileio);
+ return retval;
+ }
image->num_sections = 1;
- image->sections = malloc(sizeof(struct imageection));
+ image->sections = malloc(sizeof(struct imagesection));
image->sections[0].base_address = 0x0;
- image->sections[0].size = image_binary->fileio.size;
+ image->sections[0].size = filesize;
image->sections[0].flags = 0;
}
else if (image->type == IMAGE_IHEX)
struct image_memory *image_memory;
image->num_sections = 1;
- image->sections = malloc(sizeof(struct imageection));
+ image->sections = malloc(sizeof(struct imagesection));
image->sections[0].base_address = 0x0;
image->sections[0].size = 0xffffffff;
image->sections[0].flags = 0;
return retval;
};
-int image_read_section(struct image *image, int section, uint32_t offset, uint32_t size, uint8_t *buffer, uint32_t *size_read)
+int image_read_section(struct image *image, int section, uint32_t offset, uint32_t size, uint8_t *buffer, size_t *size_read)
{
int retval;
int image_add_section(struct image *image, uint32_t base, uint32_t size, int flags, uint8_t *data)
{
- struct imageection *section;
+ struct imagesection *section;
/* only image builder supports adding sections */
if (image->type != IMAGE_BUILDER)
/* allocate new section */
image->num_sections++;
- image->sections = realloc(image->sections, sizeof(struct imageection) * image->num_sections);
+ image->sections = realloc(image->sections, sizeof(struct imagesection) * image->num_sections);
section = &image->sections[image->num_sections - 1];
section->base_address = base;
section->size = size;
uint32_t crc = 0xffffffff;
LOG_DEBUG("Calculating checksum");
- uint32_t crc32_table[256];
+ static uint32_t crc32_table[256];
- /* Initialize the CRC table and the decoding table. */
- int i, j;
- unsigned int c;
- for (i = 0; i < 256; i++)
+ static bool first_init = false;
+ if (!first_init)
{
- /* as per gdb */
- for (c = i << 24, j = 8; j > 0; --j)
- c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
- crc32_table[i] = c;
+ /* Initialize the CRC table and the decoding table. */
+ int i, j;
+ unsigned int c;
+ for (i = 0; i < 256; i++)
+ {
+ /* as per gdb */
+ for (c = i << 24, j = 8; j > 0; --j)
+ c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
+ crc32_table[i] = c;
+ }
+
+ first_init = true;
}
while (nbytes > 0)