-/*
- * 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 0
- section_name = elf_strptr(e, shstrndx, shdr.sh_name);
-
- printf ("name %s\n", section_name);
-
- if (shdr.sh_type == SHT_PROGBITS)
- {
- printf ("\ttype %lx\n", shdr.sh_type);
- printf ("\tflags %lx\n", shdr.sh_flags);
- printf ("\taddr %lx\n", shdr.sh_addr);
- printf ("\toffset %lx\n", shdr.sh_offset);
- printf ("\tsize %lx\n", shdr.sh_size);
- printf ("\tlink %lx\n", shdr.sh_link);
- printf ("\tinfo %lx\n", shdr.sh_info);
- printf ("\taddralign %lx\n", shdr.sh_addralign);
- printf ("\tentsize %lx\n", shdr.sh_entsize);
- }
-#endif
-
- 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 < 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 >= NUM_REQUIRED_SYMBOLS;
-}
-
-struct load {
- uint32_t addr;
- uint32_t len;
- uint8_t buf[0];
-};
-
-uint32_t round4(uint32_t a) {
- return (a + 3) & ~3;
-}
-
-struct load *
-new_load (uint32_t addr, uint32_t len)
-{
- struct load *new;
-
- len = round4(len);
- new = calloc (1, sizeof (struct load) + len);
- if (!new)
- abort();
-
- new->addr = addr;
- new->len = len;
- return new;
-}
-
-void
-load_paste(struct load *into, struct load *from)
-{
- if (from->addr < into->addr || into->addr + into->len < from->addr + from->len)
- abort();
-
- memcpy(into->buf + from->addr - into->addr, from->buf, from->len);
-}
-
-/*
- * Make a new load structure large enough to hold the old one and
- * the new data
- */
-struct load *
-expand_load(struct load *from, uint32_t addr, uint32_t len)
-{
- struct load *new;
-
- if (from) {
- uint32_t from_last = from->addr + from->len;
- uint32_t last = addr + len;
-
- if (addr > from->addr)
- addr = from->addr;
- if (last < from_last)
- last = from_last;
-
- len = last - addr;
-
- if (addr == from->addr && len == from->len)
- return from;
- }
- new = new_load(addr, len);
- 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 load *
-load_write(struct load *from, uint32_t addr, uint32_t len, void *data)
-{
- struct load *new;
-
- new = expand_load(from, addr, len);
- memcpy(new->buf + addr - new->addr, data, len);
- return new;
-}
-
-/*
- * Construct a large in-memory block for all
- * of the loaded sections of the program
- */
-static struct load *
-get_load(Elf *e)
-{
- Elf_Scn *scn;
- size_t shstrndx;
- GElf_Shdr shdr;
- Elf_Data *data;
- uint8_t *buf;
- 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 load *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;
-}