Display section names when programming.

The binfile extraction and programming code is now aware of section
names when dealing with ELF32 files. The names are displayed when
programming, and chunks in different sections aren't combined, even if
they're contiguous.
This commit is contained in:
Daniel Beer 2011-10-12 13:52:56 +13:00
parent 27f56783ef
commit 18e3fbac74
10 changed files with 141 additions and 80 deletions

View File

@ -395,24 +395,23 @@ static FILE *find_firmware(void)
return NULL;
}
static int do_extract(void *user_data, address_t addr,
const uint8_t *data, int len)
static int do_extract(void *user_data, const struct binfile_chunk *ch)
{
struct firmware *f = (struct firmware *)user_data;
if (f->size != addr) {
if (f->size != ch->addr) {
printc_err("ti3410: firmware gap at 0x%x (ends at 0x%0x)\n",
f->size, addr);
f->size, ch->addr);
return -1;
}
if (f->size + len > sizeof(f->buf)) {
if (f->size + ch->len > sizeof(f->buf)) {
printc_err("ti3410: maximum firmware size exceeded\n");
return -1;
}
memcpy(f->buf + f->size, data, len);
f->size += len;
memcpy(f->buf + f->size, ch->data, ch->len);
f->size += ch->len;
return 0;
}

View File

@ -23,9 +23,16 @@
#include <stdint.h>
#include "stab.h"
struct binfile_chunk {
const char *name;
address_t addr;
const uint8_t *data;
int len;
};
/* Callback for binary image data */
typedef int (*binfile_imgcb_t)(void *user_data,
address_t addr, const uint8_t *data, int len);
const struct binfile_chunk *ch);
#define BINFILE_HAS_SYMS 0x01
#define BINFILE_HAS_TEXT 0x02

View File

@ -198,6 +198,7 @@ static int load_section(FILE *in, uint32_t addr, uint32_t offset,
uint32_t size,
binfile_imgcb_t cb, void *user_data)
{
struct binfile_chunk ch = {0};
uint8_t *section;
if (!size)
@ -217,7 +218,11 @@ static int load_section(FILE *in, uint32_t addr, uint32_t offset,
return -1;
}
if (cb(user_data, addr, section, size) < 0) {
ch.addr = addr;
ch.len = size;
ch.data = section;
if (cb(user_data, &ch) < 0) {
free(section);
return -1;
}

View File

@ -134,27 +134,40 @@ static uint32_t file_to_phys(struct elf32_info *info, uint32_t v)
}
static int feed_section(struct elf32_info *info,
FILE *in, uint32_t offset, uint32_t size,
FILE *in, const Elf32_Shdr *sh,
binfile_imgcb_t cb, void *user_data)
{
uint32_t offset = sh->sh_offset;
uint32_t size = sh->sh_size;
uint8_t buf[1024];
uint32_t addr = file_to_phys(info, offset);
const char *name = NULL;
if (fseek(in, offset, SEEK_SET) < 0) {
pr_error("elf32: can't seek to section");
return -1;
}
if (info->string_tab &&
sh->sh_name < info->string_len)
name = info->string_tab + sh->sh_name;
while (size) {
int ask = size > sizeof(buf) ? sizeof(buf) : size;
int len = fread(buf, 1, ask, in);
struct binfile_chunk ch = {0};
if (len < 0) {
pr_error("elf32: can't read section");
return -1;
}
if (cb(user_data, addr, buf, len) < 0)
ch.name = name;
ch.addr = addr;
ch.data = buf;
ch.len = len;
if (cb(user_data, &ch) < 0)
return -1;
size -= len;
@ -184,53 +197,7 @@ static int read_all(struct elf32_info *info, FILE *in)
return 0;
}
int elf32_extract(FILE *in, binfile_imgcb_t cb, void *user_data)
{
struct elf32_info info;
int i;
if (read_all(&info, in) < 0)
return -1;
for (i = 0; i < info.file_ehdr.e_shnum; i++) {
Elf32_Shdr *s = &info.file_shdrs[i];
if (s->sh_type == SHT_PROGBITS && s->sh_flags & SHF_ALLOC &&
feed_section(&info, in, s->sh_offset, s->sh_size,
cb, user_data) < 0)
return -1;
}
return 0;
}
int elf32_check(FILE *in)
{
int i;
rewind(in);
for (i = 0; i < sizeof(elf32_id); i++)
if (fgetc(in) != elf32_id[i])
return 0;
return 1;
}
static Elf32_Shdr *find_shdr(struct elf32_info *info, Elf32_Word type)
{
int i;
for (i = 0; i < info->file_ehdr.e_shnum; i++) {
Elf32_Shdr *s = &info->file_shdrs[i];
if (s->sh_type == type)
return s;
}
return NULL;
}
static int syms_load_strings(struct elf32_info *info, FILE *in, Elf32_Shdr *s)
static int load_strings(struct elf32_info *info, FILE *in, Elf32_Shdr *s)
{
int len = s->sh_size;
@ -264,6 +231,62 @@ static int syms_load_strings(struct elf32_info *info, FILE *in, Elf32_Shdr *s)
return 0;
}
int elf32_extract(FILE *in, binfile_imgcb_t cb, void *user_data)
{
struct elf32_info info;
int i;
int ret = 0;
if (read_all(&info, in) < 0)
return -1;
if (load_strings(&info, in,
&info.file_shdrs[info.file_ehdr.e_shstrndx]) < 0) {
printc_err("elf32: warning: can't load section string "
"table\n");
info.string_tab = NULL;
}
for (i = 0; i < info.file_ehdr.e_shnum; i++) {
Elf32_Shdr *s = &info.file_shdrs[i];
if (s->sh_type == SHT_PROGBITS && s->sh_flags & SHF_ALLOC &&
feed_section(&info, in, s, cb, user_data) < 0)
ret = -1;
}
if (info.string_tab)
free(info.string_tab);
return ret;
}
int elf32_check(FILE *in)
{
int i;
rewind(in);
for (i = 0; i < sizeof(elf32_id); i++)
if (fgetc(in) != elf32_id[i])
return 0;
return 1;
}
static Elf32_Shdr *find_shdr(struct elf32_info *info, Elf32_Word type)
{
int i;
for (i = 0; i < info->file_ehdr.e_shnum; i++) {
Elf32_Shdr *s = &info->file_shdrs[i];
if (s->sh_type == type)
return s;
}
return NULL;
}
#define N_SYMS 128
#ifndef STT_COMMON
@ -342,7 +365,7 @@ int elf32_syms(FILE *in)
return -1;
}
if (syms_load_strings(&info, in, &info.file_shdrs[s->sh_link]) < 0 ||
if (load_strings(&info, in, &info.file_shdrs[s->sh_link]) < 0 ||
syms_load_syms(&info, in, s) < 0)
ret = -1;

View File

@ -37,6 +37,7 @@ static int feed_line(FILE *in, uint8_t *data, int nbytes, binfile_imgcb_t cb,
uint8_t *payload;
int data_len;
int i;
struct binfile_chunk ch = {0};
if (nbytes < 5)
return 0;
@ -60,8 +61,10 @@ static int feed_line(FILE *in, uint8_t *data, int nbytes, binfile_imgcb_t cb,
switch (type) {
case 0:
return cb(user_data, address + *segment_offset,
payload, data_len);
ch.addr = address + *segment_offset;
ch.data = payload;
ch.len = data_len;
return cb(user_data, &ch);
case 1:
case 3:

View File

@ -110,6 +110,7 @@ int srec_extract(FILE *in, binfile_imgcb_t cb, void *user_data)
if (buf[1] >= '1' && buf[1] <= '3') {
int addrbytes = buf[1] - '1' + 2;
address_t addr = 0;
struct binfile_chunk ch = {0};
for (i = 0; i < addrbytes; i++)
addr = (addr << 8) | bytes[i + 1];
@ -120,10 +121,12 @@ int srec_extract(FILE *in, binfile_imgcb_t cb, void *user_data)
return -1;
}
if (cb(user_data, addr, bytes + addrbytes + 1,
count - 2 - addrbytes) < 0) {
printc_err("srec: error on line %d\n",
lno);
ch.addr = addr;
ch.data = bytes + addrbytes + 1;
ch.len = count - 2 - addrbytes;
if (cb(user_data, &ch) < 0) {
printc_err("srec: error on line %d\n", lno);
return -1;
}
}

View File

@ -75,6 +75,7 @@ static int process_data_line(address_t address, const char *buf,
int data_len = 0;
int value = 0;
int vc = 0;
struct binfile_chunk ch = {0};
while (*buf) {
int c = *(buf++);
@ -118,7 +119,10 @@ static int process_data_line(address_t address, const char *buf,
data[data_len++] = value;
}
if (cb(user_data, address, data, data_len) < 0)
ch.addr = address;
ch.data = data;
ch.len = data_len;
if (cb(user_data, &ch) < 0)
return -1;
return data_len;

View File

@ -490,10 +490,9 @@ fail:
return -1;
}
static int cmd_prog_feed(void *user_data, address_t addr,
const uint8_t *data, int len)
static int cmd_prog_feed(void *user_data, const struct binfile_chunk *ch)
{
return prog_feed((struct prog_data *)user_data, addr, data, len);
return prog_feed((struct prog_data *)user_data, ch);
}
static int do_cmd_prog(char **arg, int prog_flags)

View File

@ -41,7 +41,11 @@ int prog_flush(struct prog_data *prog)
prog->have_erased = 1;
}
printc_dbg("Writing %4d bytes to %04x...\n", prog->len, prog->addr);
printc_dbg("Writing %4d bytes to %04x", prog->len, prog->addr);
if (prog->section[0])
printc_dbg(" [section: %s]", prog->section);
printc_dbg("...\n");
if (device_writemem(prog->addr, prog->buf, prog->len) < 0)
return -1;
@ -50,16 +54,28 @@ int prog_flush(struct prog_data *prog)
return 0;
}
int prog_feed(struct prog_data *prog, address_t addr,
const uint8_t *data, int len)
int prog_feed(struct prog_data *prog, const struct binfile_chunk *ch)
{
/* Flush if this section is discontiguous */
if (prog->len && prog->addr + prog->len != addr &&
prog_flush(prog) < 0)
return -1;
const char *section = ch->name ? ch->name : "";
const uint8_t *data = ch->data;
int len = ch->len;
if (!prog->len)
prog->addr = addr;
/* Flush if this chunk is discontiguous, or in a different
* section.
*/
if (prog->len &&
((prog->addr + prog->len != ch->addr) ||
strcmp(prog->section, section))) {
if (prog_flush(prog) < 0)
return -1;
}
if (!prog->len) {
prog->addr = ch->addr;
strncpy(prog->section, section, sizeof(prog->section));
prog->section[sizeof(prog->section) - 1] = 0;
}
/* Add the buffer in piece by piece, flushing when it gets
* full.

View File

@ -19,9 +19,12 @@
#ifndef PROG_H_
#define PROG_H_
#include "binfile.h"
#define PROG_BUFSIZE 4096
struct prog_data {
char section[64];
uint8_t buf[PROG_BUFSIZE];
address_t addr;
int len;
@ -32,8 +35,7 @@ struct prog_data {
#define PROG_WANT_ERASE 0x01
void prog_init(struct prog_data *data, int flags);
int prog_feed(struct prog_data *data, address_t addr,
const uint8_t *buffer, int count);
int prog_feed(struct prog_data *data, const struct binfile_chunk *ch);
int prog_flush(struct prog_data *data);
#endif