#include "image.h"
#include "target.h"
-#include "log.h"
+#include <helper/log.h>
/* convert ELF header field to host endianness */
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];
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;
}
sscanf(&lpszLine[bytes_read], "%2" SCNx32 , &checksum);
- bytes_read += 2;
if ((uint8_t)checksum != (uint8_t)(~cal_checksum + 1))
{
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;
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++;
+
+ assert(image->num_sections > 0);
+
+ /**
+ * 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++;
LOG_ERROR("cannot read ELF segment content, read failed");
return retval;
}
- buffer += read_size;
size -= read_size;
- offset += read_size;
*size_read += read_size;
/* need more data ? */
if (!size)
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;
/* account for checksum, will always be 0xFF */
sscanf(&lpszLine[bytes_read], "%2" SCNx32 , &checksum);
cal_checksum += (uint8_t)checksum;
- bytes_read += 2;
if (cal_checksum != 0xFF)
{
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;
{
LOG_DEBUG("read past end of section: 0x%8.8" PRIx32 " + 0x%8.8" PRIx32 " > 0x%8.8" PRIx32 "",
offset, size, image->sections[section].size);
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
}
if (image->type == IMAGE_BINARY)
/* only one section in a plain binary */
if (section != 0)
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
/* seek to offset */
if ((retval = fileio_seek(&image_binary->fileio, offset)) != ERROR_OK)
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)
- return ERROR_INVALID_ARGUMENTS;
+ return ERROR_COMMAND_SYNTAX_ERROR;
/* see if there's a previous section */
if (image->num_sections)
/* 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;