Example #1
0
char*
elf_rawfile(Elf *elf, size_t *ptr) {
    size_t tmp;

    if (!ptr) {
	ptr = &tmp;
    }
    *ptr = 0;
    if (!elf) {
	return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (!elf->e_readable) {
	return NULL;
    }
    else if (elf->e_size && !elf->e_rawdata) {
	elf_assert(elf->e_data);
	if (!elf->e_cooked) {
	    elf->e_rawdata = elf->e_data;
	}
	else if (!(elf->e_rawdata = _elf_read(elf, NULL, 0, elf->e_size))) {
	    return NULL;
	}
	*ptr = elf->e_size;
    }
    return elf->e_rawdata;
}
Example #2
0
char *
elf_rawfile(Elf * elf, size_t * ptr)
{
	register size_t	sz;
	char		*p = 0;

	if (elf == 0) {
		if (ptr != 0)
			*ptr = 0;
		return (0);
	}

	ELFWLOCK(elf)
	if ((sz = elf->ed_fsz) == 0) {
		if (ptr != 0)
			*ptr = 0;
		ELFUNLOCK(elf)
		return (0);
	}

	if (elf->ed_raw != 0)
		p = elf->ed_raw;
	else if (elf->ed_status == ES_COOKED) {
		if ((p = _elf_read(elf->ed_fd, elf->ed_baseoff, sz)) != 0) {
			elf->ed_raw = p;
			elf->ed_myflags |= EDF_RAWALLOC;
		} else
			sz = 0;
	} else {
		p = elf->ed_raw = elf->ed_ident;
		elf->ed_status = ES_FROZEN;
		if (_elf_vm(elf, (size_t)0, elf->ed_fsz) != OK_YES) {
			p = 0;
			sz = 0;
		}
	}
	if (ptr != 0)
		*ptr = sz;
	ELFUNLOCK(elf)
	return (p);
}
Example #3
0
Elf_Data*
elf_rawdata(Elf_Scn *scn, Elf_Data *data) {
    Scn_Data *sd;
    Elf *elf;

    if (!scn) {
        return NULL;
    }
    elf_assert(scn->s_magic == SCN_MAGIC);
    elf = scn->s_elf;
    elf_assert(elf);
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (!elf->e_readable) {
        return NULL;
    }
    else if (scn->s_index == SHN_UNDEF || scn->s_type == SHT_NULL) {
        seterr(ERROR_NULLSCN);
    }
    else if (data) {
        return NULL;
    }
    else if ((sd = scn->s_rawdata)) {
        return &sd->sd_data;
    }
    else if (scn->s_offset < 0 || scn->s_offset > elf->e_size) {
        seterr(ERROR_OUTSIDE);
    }
    else if (scn->s_type != SHT_NOBITS
             && scn->s_offset + scn->s_size > elf->e_size) {
        seterr(ERROR_TRUNC_SCN);
    }
    else if (!(sd = (Scn_Data*)malloc(sizeof(*sd)))) {
        seterr(ERROR_MEM_SCNDATA);
    }
    else {
        *sd = _elf_data_init;
        sd->sd_freeme = 1;
        sd->sd_data.d_size = scn->s_size;
        sd->sd_data.d_version = _elf_version;
        if (scn->s_type != SHT_NOBITS && scn->s_size) {
            if (!(sd->sd_memdata = (char*)malloc(scn->s_size))) {
                seterr(ERROR_IO_2BIG);
                free(sd);
                return NULL;
            }
            else if (elf->e_rawdata) {
                memcpy(sd->sd_memdata, elf->e_rawdata + scn->s_offset, scn->s_size);
            }
            else if (!_elf_read(elf, sd->sd_memdata, scn->s_offset, scn->s_size)) {
                free(sd->sd_memdata);
                free(sd);
                return NULL;
            }
            sd->sd_data.d_buf = sd->sd_memdata;
            sd->sd_free_data = 1;
        }
        scn->s_rawdata = sd;
        return &sd->sd_data;
    }
    return NULL;
}
Example #4
0
Elf*
elf_begin(int fd, Elf_Cmd cmd, Elf *ref) {
    Elf_Arhdr *arhdr = NULL;
    size_t size = 0;
    off_t off;
    Elf *elf;

    elf_assert(_elf_init.e_magic == ELF_MAGIC);
    if (_elf_version == EV_NONE) {
	seterr(ERROR_VERSION_UNSET);
	return NULL;
    }
    else if (cmd == ELF_C_NULL) {
	return NULL;
    }
    else if (cmd == ELF_C_WRITE) {
	ref = NULL;
    }
    else if (cmd != ELF_C_READ && cmd != ELF_C_RDWR) {
	seterr(ERROR_INVALID_CMD);
	return NULL;
    }
    else if (ref) {
	elf_assert(ref->e_magic == ELF_MAGIC);
	if (!ref->e_readable || (cmd == ELF_C_RDWR && !ref->e_writable)) {
	    seterr(ERROR_CMDMISMATCH);
	    return NULL;
	}
	if (ref->e_kind != ELF_K_AR) {
	    ref->e_count++;
	    return ref;
	}
	if (cmd == ELF_C_RDWR) {
	    seterr(ERROR_MEMBERWRITE);
	    return NULL;
	}
	if (ref->e_memory) {
	    fd = ref->e_fd;
	}
	else if (fd != ref->e_fd) {
	    seterr(ERROR_FDMISMATCH);
	    return NULL;
	}
	if (!(arhdr = _elf_arhdr(ref))) {
	    return NULL;
	}
	size = arhdr->ar_size;
    }
    else if ((off = lseek(fd, (off_t)0, SEEK_END)) == (off_t)-1         // Cause assert!
	  || (off_t)(size = off) != off) {
	seterr(ERROR_IO_GETSIZE);
	return NULL;
    }

    if (!(elf = (Elf*)malloc(sizeof(Elf)))) {
	seterr(ERROR_MEM_ELF);
	return NULL;
    }
    *elf = _elf_init;
    elf->e_fd = fd;
    elf->e_parent = ref;
    elf->e_size = elf->e_dsize = size;

    if (cmd != ELF_C_READ) {
	elf->e_writable = 1;
    }
    if (cmd != ELF_C_WRITE) {
	elf->e_readable = 1;
    }
    else {
	return elf;
    }

    if (ref) {
	size_t offset = ref->e_off + sizeof(struct ar_hdr);
	Elf *xelf;

	elf_assert(arhdr);
	elf->e_arhdr = arhdr;
	elf->e_base = ref->e_base + offset;
	/*
	 * Share the archive's memory image. To avoid
	 * multiple independent elf descriptors if the
	 * same member is requested twice, scan the list
	 * of open members for duplicates.
	 *
	 * I don't know how SVR4 handles this case. Don't rely on it.
	 */
	for (xelf = ref->e_members; xelf; xelf = xelf->e_link) {
	    elf_assert(xelf->e_parent == ref);
	    if (xelf->e_base == elf->e_base) {
		free(arhdr);
		free(elf);
		xelf->e_count++;
		return xelf;
	    }
	}
	if (size == 0) {
	    elf->e_data = NULL;
	}
#if 1
	else {
	    /*
	     * Archive members may be misaligned.  Freezing them will
	     * cause libelf to allocate buffers for translated data,
	     * which should be properly aligned in all cases.
	     */
	    elf_assert(!ref->e_cooked);
	    elf->e_data = elf->e_rawdata = ref->e_data + offset;
	}
#else
	else if (ref->e_data == ref->e_rawdata) {
	    elf_assert(!ref->e_cooked);
	    /*
	     * archive is frozen - freeze member, too
	     */
	    elf->e_data = elf->e_rawdata = ref->e_data + offset;
	}
	else {
	    elf_assert(!ref->e_memory);
	    elf->e_data = ref->e_data + offset;
	    /*
	     * The member's memory image may have been modified if
	     * the member has been processed before. Since we need the
	     * original image, we have to re-read the archive file.
	     * Will fail if the archive's file descriptor is disabled.
	     */
	    if (!ref->e_cooked) {
		ref->e_cooked = 1;
	    }
	    else if (!_elf_read(ref, elf->e_data, offset, size)) {
		free(arhdr);
		free(elf);
		return NULL;
	    }
	}
#endif
	elf->e_next = offset + size + (size & 1);
	elf->e_disabled = ref->e_disabled;
	elf->e_memory = ref->e_memory;
	/* parent/child linking */
	elf->e_link = ref->e_members;
	ref->e_members = elf;
	ref->e_count++;
	/* Slowaris compatibility - do not rely on this! */
	ref->e_off = elf->e_next;
    }
/*--------------------------------------------
| Name:        _tiny_elfloader
| Description:
| Parameters:  none
| Return Type: none
| Comments:
| See:
----------------------------------------------*/
unsigned long _tiny_elfloader(unsigned long flash_base, unsigned long base)
{
   Elf32_Ehdr ehdr;

   Elf32_Phdr phdr[MAX_PHDR];
   unsigned long offset = 0;
   int phx=0;
   int len=0;
   unsigned char ch;
   unsigned char *addr;
   unsigned long addr_offset = 0;
   unsigned long highest_address = 0;
   unsigned long lowest_address = 0xFFFFFFFF;
   unsigned char *SHORT_DATA = "error: short data reading elf file\r\n";

   //
   int cb=0;
   boot_handler_t boot_handler = (boot_handler_t)0x00000000;

#ifdef DEBUG
   _elf_printf("read elf file at 0x%x\r\n", (unsigned int)flash_base);
#endif
   //ALREADY DONE
   //_at91sam9261_remap_internal_ram();

   // Read the header
   _elf_printf("read elf header informations:\r\n" );
   if (_elf_read(flash_base, (unsigned char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
#ifdef DEBUG
      _elf_printf("error: can't read elf header\r\n");
#endif
      return 0;
   }
   offset += sizeof(ehdr);
   //
#ifdef DEBUG
   _elf_printf(
      "type: %d, machine: %d, version: %d\r\nentry: 0x%x, PHoff: 0x%x/%d/%d, SHoff: 0x%x/%d/%d\r\n\r\n",
      ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_entry,
      ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum,
      ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);
#endif
   //
   if (ehdr.e_type != ET_EXEC) {
#ifdef DEBUG
      _elf_printf("error: only absolute elf images supported\r\n");
#endif
      return 0;
   }
   //
   if (ehdr.e_phnum > MAX_PHDR) {
#ifdef DEBUG
      _elf_printf("error: too many firmware headers\r\n");
#endif
      return 0;
   }
#ifdef DEBUG
   _elf_printf("jump to offset 0x%x wait some seconds... ",ehdr.e_phoff);
#endif
   //jump to offset
#ifdef USE_OPTIMIZED_READELF
   //optimized code
   #if !defined(__GNUC__)
   _elf_lseek(flash_base,ehdr.e_phoff,0);
   offset+=ehdr.e_phoff;
   #endif
#else
   //not optimized original code from reboot
   while (offset < ehdr.e_phoff) {
      if (_elf_getc(flash_base) < 0) {
   #ifdef DEBUG
         printf(SHORT_DATA);
   #endif
         return 0;
      }
      offset++;
   }
#endif

   //
#ifdef DEBUG
   _elf_printf("done\r\n");
#endif

#ifdef DEBUG
   _elf_printf("read elf section header\r\n");
#endif
   //
   for (phx = 0; phx < ehdr.e_phnum; phx++) {
      if (_elf_read(flash_base, (unsigned char *)&phdr[phx], sizeof(phdr[0])) != sizeof(phdr[0])) {
#ifdef DEBUG
         _elf_printf("error: can't read ELF program header\r\n");
#endif
         return 0;
      }
#ifdef DEBUG
      _elf_printf(
         "section header: type: %d, off: 0x%x\r\nva: 0x%x, pa: 0x%x, len: %d/%d, flags: %d\r\n",
         phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,
         phdr[phx].p_filesz, phdr[phx].p_memsz, phdr[phx].p_flags);
#endif
      offset += sizeof(phdr[0]);
   }

   if (base) {
      // Set address offset based on lowest address in file.
      addr_offset = 0xFFFFFFFF;
      for (phx = 0; phx < ehdr.e_phnum; phx++) {
#ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS
         if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_vaddr < addr_offset)) {
            addr_offset = phdr[phx].p_vaddr;
#else
         if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_paddr < addr_offset)) {
            addr_offset = phdr[phx].p_paddr;
#endif
         }
      }
      addr_offset = (unsigned long)base - addr_offset;
   }else{
      addr_offset = 0;
   }
   //phlb modif
#if !defined(__GNUC__)
   _elf_lseek(flash_base,sizeof(ehdr),0);
#endif

#ifdef DEBUG
   _elf_printf("copy firmware in ram started:\r\n");
#endif

   for (phx = 0; phx < ehdr.e_phnum; phx++) {

      //
      if (phdr[phx].p_type == PT_LOAD) {
         // Loadable segment
#ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS
         addr = (unsigned char *)phdr[phx].p_vaddr;
#else
         addr = (unsigned char *)phdr[phx].p_paddr;
#endif

         //
         len = phdr[phx].p_filesz;
         if ((unsigned long)addr < lowest_address) {
            lowest_address = (unsigned long)addr;
         }
         //
         addr += addr_offset;
         if (offset > phdr[phx].p_offset) {
            /*
             if ((phdr[phx].p_offset + len) < offset) {
                 printf("Can't load ELF file - program headers out of order\r\n");
                 return 0;
             }
             */
            /*addr += offset - phdr[phx].p_offset;*/
         } else {
            while (offset < phdr[phx].p_offset) {
               if (_elf_getc(flash_base) < 0) {
#ifdef DEBUG
                  printf(SHORT_DATA);
#endif
                  return 0;
               }
               offset++;
            }
         }

#ifdef DEBUG
         _elf_printf(
            "program header: type: %d, off: 0x%x, va: 0x%x, pa:0x%x, len: %d/%d, flags: %d\r\n",
            phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,
            phdr[phx].p_filesz, phdr[phx].p_memsz, phdr[phx].p_flags);

#endif

         // Copy data into memory
#ifndef USE_OPTIMIZED_READELF
         while (len-- > 0) {

            if ((ch = _elf_getc(flash_base)) < 0) {
   #ifdef DEBUG
               printf(SHORT_DATA);
   #endif
               return 0;
            }
   #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
            if (valid_address(addr))
   #endif
            *addr = ch;      //original code
   #ifdef DEBUG
            if(!(((unsigned long)offset)%(80*1*1024)))
               _elf_printf(".");
   #endif

            addr++;
            offset++;
            if ((unsigned long)(addr-addr_offset) > highest_address) {
               highest_address = (unsigned long)(addr - addr_offset);
            }
         }
#endif

#ifdef USE_OPTIMIZED_READELF
         //
   #if defined(__GNUC__)
         _elf_lseek(flash_base,phdr[phx].p_offset,0);
         _elf_printf("offset:%d addr:0x%x fl_offset:%d\r\n", offset, addr, elf_flash_offset);
   #endif

         cb=0;
         while((len-cb)) {
            unsigned char elf_buffer[4096]={0};
            int sz=0;

            if((len-cb)>=sizeof(elf_buffer))
               sz=sizeof(elf_buffer);
            else
               sz=(len-cb);

            //cb += read(fd,elf_buffer,sz);
            cb+=_elf_read(flash_base, addr, sz);
            /*
            #ifdef DEBUG
            lseek(fd_bin,(unsigned long)addr,SEEK_SET);
            write(fd_bin,elf_buffer,sz);
            #endif
            */
   #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
            if (valid_address(addr))
   #endif
            //memcpy(addr,elf_buffer,sz);

            //
            addr+=sz;
            offset+=sz;
            if ((unsigned long)(addr-addr_offset) > highest_address) {
               highest_address = (unsigned long)(addr - addr_offset);
            }
         }
#endif
      }
   }

   // Save load base/top and entry
   if (base) {
      load_address = base;
      load_address_end = base + (highest_address - lowest_address);
      entry_address = base + (ehdr.e_entry - lowest_address);
   } else {
      load_address = lowest_address;
      load_address_end = highest_address;
      entry_address = ehdr.e_entry;
   }

   // nak everything to stop the transfer, since redboot
   // usually doesn't read all the way to the end of the
   // elf files.
#ifdef DEBUG
   _elf_printf("\r\ncopy firmware in ram done\r\n");
   if (addr_offset)
      _elf_printf("address offset = 0x%x\n", addr_offset);
   _elf_printf("firmware entry point: 0x%x, address range: 0x%x-0x%x\r\n",entry_address,
               load_address,
               load_address_end);
   _elf_printf("ready to rumble? ;)\r\nboot on firmware\r\n");
#endif

   boot_handler = (boot_handler_t)entry_address;

   //boot!!!!
   boot_handler();
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   __asm__("nop");
   for(;; ) ;

   return 1;
}