CVSROOT: /home/cvs
Module name: malta
Changes by: beth@ftp.linux-mips.org 05/08/11 14:27:51
Modified files:
linux/arch/mips/kernel: Tag: MaltaRef_2_6 vpe.c
Log message:
Support fully linked SP programs.
diff -urN malta/linux/arch/mips/kernel/vpe.c malta/linux/arch/mips/kernel/vpe.c
--- malta/linux/arch/mips/kernel/vpe.c 2005/08/08 13:24:14 1.1.1000.2
+++ malta/linux/arch/mips/kernel/vpe.c 2005/08/11 13:27:51 1.1.1000.3
@@ -852,8 +852,7 @@
Elf_Shdr *sechdrs;
long err = 0;
char *secstrings, *strtab = NULL;
- unsigned int len, i, symindex = 0, strindex = 0;
-
+ unsigned int len, i, symindex = 0, strindex = 0, relocate = 0;
struct module mod; // so we can re-use the relocations code
memset(&mod, 0, sizeof(struct module));
@@ -865,13 +864,17 @@
/* Sanity checks against insmoding binaries or wrong arch,
weird elf version */
if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
- || hdr->e_type != ET_REL || !elf_check_arch(hdr)
+ || (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC)
+ || !elf_check_arch(hdr)
|| hdr->e_shentsize != sizeof(*sechdrs)) {
printk(KERN_WARNING
"VPE program, wrong arch or weird elf version\n");
return -ENOEXEC;
}
+
+ if (hdr->e_type == ET_REL)
+ relocate = 1;
if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
printk(KERN_ERR "VPE program length %u truncated\n", len);
@@ -886,87 +889,116 @@
/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = 0;
- for (i = 1; i < hdr->e_shnum; i++) {
+ if (relocate) {
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (sechdrs[i].sh_type != SHT_NOBITS
+ && len < sechdrs[i].sh_offset + sechdrs[i].sh_size)
{
+ printk(KERN_ERR "VPE program length %u
truncated\n",
+ len);
+ return -ENOEXEC;
+ }
- if (sechdrs[i].sh_type != SHT_NOBITS
- && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
- printk(KERN_ERR "VPE program length %u truncated\n",
- len);
- return -ENOEXEC;
+ /* Mark all sections sh_addr with their address in the
+ temporary image. */
+ sechdrs[i].sh_addr = (size_t) hdr +
sechdrs[i].sh_offset;
+
+ /* Internal symbols and strings. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ symindex = i;
+ strindex = sechdrs[i].sh_link;
+ strtab = (char *)hdr +
sechdrs[strindex].sh_offset;
+ }
}
- /* Mark all sections sh_addr with their address in the
- temporary image. */
- sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
-
- /* Internal symbols and strings. */
- if (sechdrs[i].sh_type == SHT_SYMTAB) {
- symindex = i;
- strindex = sechdrs[i].sh_link;
- strtab = (char *)hdr + sechdrs[strindex].sh_offset;
- }
+ layout_sections(&mod, hdr, sechdrs, secstrings);
}
- layout_sections(&mod, hdr, sechdrs, secstrings);
v->load_addr = alloc_progmem(mod.core_size);
memset(v->load_addr, 0, mod.core_size);
printk("VPE elf_loader: loading to %p\n", v->load_addr);
- for (i = 0; i < hdr->e_shnum; i++) {
- void *dest;
+ if (relocate) {
+ for (i = 0; i < hdr->e_shnum; i++) {
+ void *dest;
+
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+ continue;
+
+ dest = v->load_addr + sechdrs[i].sh_entsize;
+
+ if (sechdrs[i].sh_type != SHT_NOBITS)
+ memcpy(dest, (void *)sechdrs[i].sh_addr,
+ sechdrs[i].sh_size);
+ /* Update sh_addr to point to copy in image. */
+ sechdrs[i].sh_addr = (unsigned long)dest;
+
+ printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",
+ secstrings + sechdrs[i].sh_name,
sechdrs[i].sh_addr);
+ }
- if (!(sechdrs[i].sh_flags & SHF_ALLOC))
- continue;
- dest = v->load_addr + sechdrs[i].sh_entsize;
+ /* Fix up syms, so that st_value is a pointer to location. */
+ err = simplify_symbols(sechdrs, symindex, strtab, secstrings,
+ hdr->e_shnum, &mod);
+ if (err < 0) {
+ printk(KERN_WARNING "VPE: unable to simplify
symbols\n");
+ goto cleanup;
+ }
- if (sechdrs[i].sh_type != SHT_NOBITS)
- memcpy(dest, (void *)sechdrs[i].sh_addr,
- sechdrs[i].sh_size);
- /* Update sh_addr to point to copy in image. */
- sechdrs[i].sh_addr = (unsigned long)dest;
+ /* Now do relocations. */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ const char *strtab = (char *)sechdrs[strindex].sh_addr;
+ unsigned int info = sechdrs[i].sh_info;
+
+ /* Not a valid relocation section? */
+ if (info >= hdr->e_shnum)
+ continue;
+
+ /* Don't bother with non-allocated sections */
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+ continue;
+
+ if (sechdrs[i].sh_type == SHT_REL)
+ err = apply_relocations(sechdrs, strtab,
symindex, i, &mod);
+ else if (sechdrs[i].sh_type == SHT_RELA)
+ err = apply_relocate_add(sechdrs, strtab,
symindex, i,
+ &mod);
+ if (err < 0) {
+ printk(KERN_WARNING
+ "vpe_elfload: error in relocations err
%ld\n",
+ err);
+ goto cleanup;
+ }
+ }
+ } else {
+ for (i = 0; i < hdr->e_shnum; i++) {
- printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",
- secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr);
- }
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC) ||
sechdrs[i].sh_type == PT_MIPS_REGINFO)
+ continue;
- /* Fix up syms, so that st_value is a pointer to location. */
- err =
- simplify_symbols(sechdrs, symindex, strtab, secstrings,
- hdr->e_shnum, &mod);
- if (err < 0) {
- printk(KERN_WARNING "VPE: unable to simplify symbols\n");
- goto cleanup;
- }
-
- /* Now do relocations. */
- for (i = 1; i < hdr->e_shnum; i++) {
- const char *strtab = (char *)sechdrs[strindex].sh_addr;
- unsigned int info = sechdrs[i].sh_info;
-
- /* Not a valid relocation section? */
- if (info >= hdr->e_shnum)
- continue;
-
- /* Don't bother with non-allocated sections */
- if (!(sechdrs[info].sh_flags & SHF_ALLOC))
- continue;
-
- if (sechdrs[i].sh_type == SHT_REL)
- err = apply_relocations(sechdrs, strtab, symindex, i,
&mod);
- else if (sechdrs[i].sh_type == SHT_RELA)
- err = apply_relocate_add(sechdrs, strtab, symindex, i,
- &mod);
- if (err < 0) {
- printk(KERN_WARNING
- "vpe_elfload: error in relocations err %ld\n",
- err);
- goto cleanup;
+ if (sechdrs[i].sh_addr < (unsigned int)v->load_addr) {
+ printk( KERN_WARNING "vpe_elfload: fully linked
image has invalid "
+ "section, name %s address 0x%x, before
load "
+ "address of 0x%x\n", secstrings +
sechdrs[i].sh_name,
+ sechdrs[i].sh_addr, (unsigned
int)v->load_addr);
+ return -ENOEXEC;
+ }
+
+ printk(KERN_DEBUG " copying section sh_name %s, sh_addr
0x%x size 0x%x\n",
+ secstrings + sechdrs[i].sh_name,
sechdrs[i].sh_addr,
+ sechdrs[i].sh_size);
+
+ if (sechdrs[i].sh_type != SHT_NOBITS)
+ memcpy((void *)sechdrs[i].sh_addr, v->pbuffer +
sechdrs[i].sh_offset,
+ sechdrs[i].sh_size);
+ else
+ memset((void *)sechdrs[i].sh_addr, 0,
sechdrs[i].sh_size);
}
}
+
/* make sure it's physically written out */
flush_icache_range((unsigned long)v->load_addr,
(unsigned long)v->load_addr + v->len);
@@ -1119,6 +1151,14 @@
ret = -ENOEXEC;
}
+ /* It's good to be able to run the SP and if it chokes have a look at
+ the /dev/rt?. But if we reset the pointer to the shared struct we
+ loose what has happened. So perhaps if garbage is sent to the vpe
+ device, use it as a trigger for the reset. Hopefully a nice
+ executable will be along shortly. */
+ if (ret < 0)
+ v->shared_ptr = NULL;
+
// cleanup any temp buffers
if (v->pbuffer)
vfree(v->pbuffer);
|