summaryrefslogtreecommitdiff
path: root/ao-tools/ao-stmload
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-11-27 13:59:06 -0800
committerKeith Packard <keithp@keithp.com>2013-11-27 13:59:06 -0800
commit95a8180f3d7929dbad65c80421f99c925f245af0 (patch)
tree7934a5cc48edf7e774d5be5f366203a79a2db497 /ao-tools/ao-stmload
parent73b1a7e644e255558378ab66de6426a7dfd8a7dc (diff)
ao-tools: Create general elf and hex library routines
Pulls the elf stuff out of ao-stmload, change the hex stuff into ao_ routines. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'ao-tools/ao-stmload')
-rw-r--r--ao-tools/ao-stmload/Makefile.am2
-rw-r--r--ao-tools/ao-stmload/ao-elf.c303
-rw-r--r--ao-tools/ao-stmload/ao-elf.h24
-rw-r--r--ao-tools/ao-stmload/ao-selfload.c8
-rw-r--r--ao-tools/ao-stmload/ao-stmload.c14
-rw-r--r--ao-tools/ao-stmload/ao-stmload.h13
6 files changed, 16 insertions, 348 deletions
diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am
index 4eaf699c..68b518f1 100644
--- a/ao-tools/ao-stmload/Makefile.am
+++ b/ao-tools/ao-stmload/Makefile.am
@@ -11,7 +11,7 @@ ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS)
ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf
-ao_stmload_SOURCES=ao-stmload.c ao-elf.c ao-stmload.h ao-selfload.c
+ao_stmload_SOURCES=ao-stmload.c ao-stmload.h ao-selfload.c
man_MANS = ao-stmload.1
diff --git a/ao-tools/ao-stmload/ao-elf.c b/ao-tools/ao-stmload/ao-elf.c
deleted file mode 100644
index dad8fb80..00000000
--- a/ao-tools/ao-stmload/ao-elf.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "ao-elf.h"
-#include <err.h>
-#include <gelf.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include "ccdbg.h"
-#include "ao-stmload.h"
-
-/*
- * Look through the Elf file for the AltOS symbols
- * that can be adjusted before the image is written
- * to the device
- */
-static int
-find_symbols (Elf *e)
-{
- Elf_Scn *scn;
- Elf_Data *symbol_data = NULL;
- GElf_Shdr shdr;
- GElf_Sym sym;
- int i, symbol_count, s;
- int required = 0;
- char *symbol_name;
- char *section_name;
- size_t shstrndx;
-
- if (elf_getshdrstrndx(e, &shstrndx) < 0)
- return 0;
-
- /*
- * Find the symbols
- */
-
- scn = NULL;
- while ((scn = elf_nextscn(e, scn)) != NULL) {
-
- if (gelf_getshdr(scn, &shdr) != &shdr)
- return 0;
-
- if (shdr.sh_type == SHT_SYMTAB) {
- symbol_data = elf_getdata(scn, NULL);
- symbol_count = shdr.sh_size / shdr.sh_entsize;
- break;
- }
- }
-
- if (!symbol_data)
- return 0;
-
- for (i = 0; i < symbol_count; i++) {
- gelf_getsym(symbol_data, i, &sym);
-
- symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name);
-
- for (s = 0; s < ao_num_symbols; s++)
- if (!strcmp (ao_symbols[s].name, symbol_name)) {
- int t;
- ao_symbols[s].addr = sym.st_value;
- if (ao_symbols[s].required)
- ++required;
- }
- }
-
- return required >= ao_num_required_symbols;
-}
-
-uint32_t round4(uint32_t a) {
- return (a + 3) & ~3;
-}
-
-struct hex_image *
-new_load (uint32_t addr, uint32_t len)
-{
- struct hex_image *new;
-
- len = round4(len);
- new = calloc (1, sizeof (struct hex_image) + len);
- if (!new)
- abort();
-
- new->address = addr;
- new->length = len;
- return new;
-}
-
-void
-load_paste(struct hex_image *into, struct hex_image *from)
-{
- if (from->address < into->address || into->address + into->length < from->address + from->length)
- abort();
-
- memcpy(into->data + from->address - into->address, from->data, from->length);
-}
-
-/*
- * Make a new load structure large enough to hold the old one and
- * the new data
- */
-struct hex_image *
-expand_load(struct hex_image *from, uint32_t address, uint32_t length)
-{
- struct hex_image *new;
-
- if (from) {
- uint32_t from_last = from->address + from->length;
- uint32_t last = address + length;
-
- if (address > from->address)
- address = from->address;
- if (last < from_last)
- last = from_last;
-
- length = last - address;
-
- if (address == from->address && length == from->length)
- return from;
- }
- new = new_load(address, length);
- if (from) {
- load_paste(new, from);
- free (from);
- }
- return new;
-}
-
-/*
- * Create a new load structure with data from the existing one
- * and the new data
- */
-struct hex_image *
-load_write(struct hex_image *from, uint32_t address, uint32_t length, void *data)
-{
- struct hex_image *new;
-
- new = expand_load(from, address, length);
- memcpy(new->data + address - new->address, data, length);
- return new;
-}
-
-/*
- * Construct a large in-memory block for all
- * of the loaded sections of the program
- */
-static struct hex_image *
-get_load(Elf *e)
-{
- Elf_Scn *scn;
- size_t shstrndx;
- GElf_Shdr shdr;
- Elf_Data *data;
- char *got_name;
- size_t nphdr;
- size_t p;
- GElf_Phdr phdr;
- GElf_Addr p_paddr;
- GElf_Off p_offset;
- GElf_Addr sh_paddr;
- struct hex_image *load = NULL;
- char *section_name;
- size_t nshdr;
- size_t s;
-
- if (elf_getshdrstrndx(e, &shstrndx) < 0)
- return 0;
-
- if (elf_getphdrnum(e, &nphdr) < 0)
- return 0;
-
- if (elf_getshdrnum(e, &nshdr) < 0)
- return 0;
-
- /*
- * As far as I can tell, all of the phdr sections should
- * be flashed to memory
- */
- for (p = 0; p < nphdr; p++) {
-
- /* Find this phdr */
- gelf_getphdr(e, p, &phdr);
-
- if (phdr.p_type != PT_LOAD)
- continue;
-
- p_offset = phdr.p_offset;
- /* Get the associated file section */
-
-#if 0
- printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n",
- (uint32_t) phdr.p_offset,
- (uint32_t) phdr.p_vaddr,
- (uint32_t) phdr.p_paddr,
- (uint32_t) phdr.p_filesz,
- (uint32_t) phdr.p_memsz);
-#endif
-
- for (s = 0; s < nshdr; s++) {
- scn = elf_getscn(e, s);
-
- if (!scn) {
- printf ("getscn failed\n");
- abort();
- }
- if (gelf_getshdr(scn, &shdr) != &shdr) {
- printf ("gelf_getshdr failed\n");
- abort();
- }
-
- section_name = elf_strptr(e, shstrndx, shdr.sh_name);
-
- if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) {
-
- if (shdr.sh_size == 0)
- continue;
-
- sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset;
-
- printf ("\tsize %08x rom %08x exec %08x %s\n",
- (uint32_t) shdr.sh_size,
- (uint32_t) sh_paddr,
- (uint32_t) shdr.sh_addr,
- section_name);
-
- data = elf_getdata(scn, NULL);
-
- /* Write the section data into the memory block */
- load = load_write(load, sh_paddr, shdr.sh_size, data->d_buf);
- }
- }
- }
- return load;
-}
-
-/*
- * Open the specified ELF file and
- * check for the symbols we need
- */
-
-struct hex_image *
-ao_load_elf(char *name)
-{
- int fd;
- Elf *e;
- Elf_Scn *scn;
- Elf_Data *symbol_data = NULL;
- GElf_Shdr shdr;
- GElf_Sym sym;
- size_t n, shstrndx, sz;
- int i, symbol_count, s;
- int required = 0;
- struct hex_image *image;
-
- if (elf_version(EV_CURRENT) == EV_NONE)
- return NULL;
-
- fd = open(name, O_RDONLY, 0);
-
- if (fd < 0)
- return NULL;
-
- e = elf_begin(fd, ELF_C_READ, NULL);
-
- if (!e)
- return NULL;
-
- if (elf_kind(e) != ELF_K_ELF)
- return NULL;
-
- if (elf_getshdrstrndx(e, &shstrndx) != 0)
- return NULL;
-
- if (!find_symbols(e)) {
- fprintf (stderr, "Cannot find required symbols\n");
- return NULL;
- }
-
- image = get_load(e);
- if (!image) {
- fprintf (stderr, "Cannot create memory image from file\n");
- return NULL;
- }
-
- return image;
-}
diff --git a/ao-tools/ao-stmload/ao-elf.h b/ao-tools/ao-stmload/ao-elf.h
deleted file mode 100644
index 4303d5ca..00000000
--- a/ao-tools/ao-stmload/ao-elf.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_ELF_H_
-#define _AO_ELF_H_
-
-struct hex_image *
-ao_load_elf(char *name);
-
-#endif
diff --git a/ao-tools/ao-stmload/ao-selfload.c b/ao-tools/ao-stmload/ao-selfload.c
index 95667dca..dee1c3cb 100644
--- a/ao-tools/ao-stmload/ao-selfload.c
+++ b/ao-tools/ao-stmload/ao-selfload.c
@@ -64,16 +64,16 @@ ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256])
}
}
-struct hex_image *
+struct ao_hex_image *
ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length)
{
- struct hex_image *image;
+ struct ao_hex_image *image;
int pages;
int page;
uint32_t base = address & ~0xff;
uint32_t bound = (address + length + 0xff) & ~0xff;
- image = calloc(sizeof (struct hex_image) + (bound - base), 1);
+ image = calloc(sizeof (struct ao_hex_image) + (bound - base), 1);
image->address = base;
image->length = bound - base;
pages = image->length / 0x100;
@@ -83,7 +83,7 @@ ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length)
}
int
-ao_self_write(struct cc_usb *cc, struct hex_image *image)
+ao_self_write(struct cc_usb *cc, struct ao_hex_image *image)
{
uint8_t block[256];
uint8_t check[256];
diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c
index dd25f07f..6e3906fd 100644
--- a/ao-tools/ao-stmload/ao-stmload.c
+++ b/ao-tools/ao-stmload/ao-stmload.c
@@ -34,7 +34,7 @@
#define AO_USB_DESC_STRING 3
-struct sym ao_symbols[] = {
+struct ao_elf_sym ao_symbols[] = {
{ 0, AO_BOOT_APPLICATION_BASE + 0x100, "ao_romconfig_version", 1 },
#define AO_ROMCONFIG_VERSION (ao_symbols[0].addr)
@@ -62,7 +62,7 @@ int ao_num_required_symbols = NUM_REQUIRED_SYMBOLS;
* Edit the to-be-written memory block
*/
static int
-rewrite(struct hex_image *load, unsigned address, uint8_t *data, int length)
+rewrite(struct ao_hex_image *load, unsigned address, uint8_t *data, int length)
{
int i;
@@ -86,7 +86,7 @@ rewrite(struct hex_image *load, unsigned address, uint8_t *data, int length)
static uint16_t
get_uint16_cc(struct cc_usb *cc, uint32_t addr)
{
- struct hex_image *hex = ao_self_read(cc, addr, 2);
+ struct ao_hex_image *hex = ao_self_read(cc, addr, 2);
uint16_t v;
uint8_t *data;
@@ -101,7 +101,7 @@ get_uint16_cc(struct cc_usb *cc, uint32_t addr)
static uint32_t
get_uint32_cc(struct cc_usb *cc, uint32_t addr)
{
- struct hex_image *hex = ao_self_read(cc, addr, 4);
+ struct ao_hex_image *hex = ao_self_read(cc, addr, 4);
uint32_t v;
uint8_t *data;
@@ -281,7 +281,7 @@ main (int argc, char **argv)
int c;
stlink_t *sl = NULL;
int was_flashed = 0;
- struct hex_image *load;
+ struct ao_hex_image *load;
int tries;
struct cc_usb *cc = NULL;
int use_stlink = 0;
@@ -329,10 +329,10 @@ main (int argc, char **argv)
usage(argv[0]);
if (ends_with (filename, ".elf")) {
- load = ao_load_elf(filename);
+ load = ao_load_elf(filename, ao_symbols, ao_num_symbols);
} else if (ends_with (filename, ".ihx")) {
int i;
- load = ccdbg_hex_load(filename);
+ load = ao_hex_load(filename);
for (i = 0; i < ao_num_symbols; i++)
ao_symbols[i].addr = ao_symbols[i].default_addr;
} else
diff --git a/ao-tools/ao-stmload/ao-stmload.h b/ao-tools/ao-stmload/ao-stmload.h
index 98884535..28c2dda4 100644
--- a/ao-tools/ao-stmload/ao-stmload.h
+++ b/ao-tools/ao-stmload/ao-stmload.h
@@ -18,16 +18,11 @@
#ifndef _AO_STMLOAD_H_
#define _AO_STMLOAD_H_
-struct sym {
- unsigned addr;
- unsigned default_addr;
- char *name;
- int required;
-};
+#include "ao-elf.h"
#define AO_BOOT_APPLICATION_BASE 0x08001000
-extern struct sym ao_symbols[];
+extern struct ao_elf_sym ao_symbols[];
extern int ao_num_symbols;
extern int ao_num_required_symbols;
@@ -38,11 +33,11 @@ ao_self_block_read(struct cc_usb *cc, uint32_t address, uint8_t block[256]);
void
ao_self_block_write(struct cc_usb *cc, uint32_t address, uint8_t block[256]);
-struct hex_image *
+struct ao_hex_image *
ao_self_read(struct cc_usb *cc, uint32_t address, uint32_t length);
int
-ao_self_write(struct cc_usb *cc, struct hex_image *image);
+ao_self_write(struct cc_usb *cc, struct ao_hex_image *image);
extern int ao_self_verbose;