diff options
| author | Keith Packard <keithp@keithp.com> | 2013-11-27 13:59:06 -0800 |
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2013-11-27 13:59:06 -0800 |
| commit | 95a8180f3d7929dbad65c80421f99c925f245af0 (patch) | |
| tree | 7934a5cc48edf7e774d5be5f366203a79a2db497 /ao-tools/ao-stmload | |
| parent | 73b1a7e644e255558378ab66de6426a7dfd8a7dc (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.am | 2 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-elf.c | 303 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-elf.h | 24 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-selfload.c | 8 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-stmload.c | 14 | ||||
| -rw-r--r-- | ao-tools/ao-stmload/ao-stmload.h | 13 |
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; |
