if (phdr->p_filesz != phdr->p_memsz)
memset(dst + phdr->p_filesz, 0x00,
phdr->p_memsz - phdr->p_filesz);
- flush_cache((unsigned long)dst, phdr->p_filesz);
+ flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
+ roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
++phdr;
}
+ if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
+ EF_PPC64_ELFV1_ABI)) {
+ /*
+ * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
+ * descriptor pointer with the first double word being the
+ * address of the entry point of the function.
+ */
+ uintptr_t addr = ehdr->e_entry;
+
+ return *(Elf64_Addr *)addr;
+ }
+
+ return ehdr->e_entry;
+}
+
+static unsigned long load_elf64_image_shdr(unsigned long addr)
+{
+ Elf64_Ehdr *ehdr; /* Elf header structure pointer */
+ Elf64_Shdr *shdr; /* Section header structure pointer */
+ unsigned char *strtab = 0; /* String table pointer */
+ unsigned char *image; /* Binary image pointer */
+ int i; /* Loop counter */
+
+ ehdr = (Elf64_Ehdr *)addr;
+
+ /* Find the section header string table for output info */
+ shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
+ (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
+
+ if (shdr->sh_type == SHT_STRTAB)
+ strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
+
+ /* Load each appropriate section */
+ for (i = 0; i < ehdr->e_shnum; ++i) {
+ shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
+ (i * sizeof(Elf64_Shdr)));
+
+ if (!(shdr->sh_flags & SHF_ALLOC) ||
+ shdr->sh_addr == 0 || shdr->sh_size == 0) {
+ continue;
+ }
+
+ if (strtab) {
+ debug("%sing %s @ 0x%08lx (%ld bytes)\n",
+ (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
+ &strtab[shdr->sh_name],
+ (unsigned long)shdr->sh_addr,
+ (long)shdr->sh_size);
+ }
+
+ if (shdr->sh_type == SHT_NOBITS) {
+ memset((void *)(uintptr_t)shdr->sh_addr, 0,
+ shdr->sh_size);
+ } else {
+ image = (unsigned char *)addr + (ulong)shdr->sh_offset;
+ memcpy((void *)(uintptr_t)shdr->sh_addr,
+ (const void *)image, shdr->sh_size);
+ }
+ flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
+ roundup((shdr->sh_addr + shdr->sh_size),
+ ARCH_DMA_MINALIGN) -
+ rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
+ }
+
+ if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
+ EF_PPC64_ELFV1_ABI)) {
+ /*
+ * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
+ * descriptor pointer with the first double word being the
+ * address of the entry point of the function.
+ */
+ uintptr_t addr = ehdr->e_entry;
+
+ return *(Elf64_Addr *)addr;
+ }
+
return ehdr->e_entry;
}
if (phdr->p_filesz != phdr->p_memsz)
memset(dst + phdr->p_filesz, 0x00,
phdr->p_memsz - phdr->p_filesz);
- flush_cache((unsigned long)dst, phdr->p_filesz);
+ flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
+ roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
++phdr;
}
int i; /* Loop counter */
ehdr = (Elf32_Ehdr *)addr;
+ if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+ return load_elf64_image_shdr(addr);
/* Find the section header string table for output info */
shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
memcpy((void *)(uintptr_t)shdr->sh_addr,
(const void *)image, shdr->sh_size);
}
- flush_cache(shdr->sh_addr, shdr->sh_size);
+ flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
+ roundup((shdr->sh_addr + shdr->sh_size),
+ ARCH_DMA_MINALIGN) -
+ rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
}
return ehdr->e_entry;
int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned long addr; /* Address of image */
- unsigned long bootaddr; /* Address to put the bootline */
+ unsigned long bootaddr = 0; /* Address to put the bootline */
char *bootline; /* Text of the bootline */
char *tmp; /* Temporary char pointer */
char build_buf[128]; /* Buffer for building the bootline */
puts("## Ethernet MAC address not copied to NV RAM\n");
#endif
- /*
- * Use bootaddr to find the location in memory that VxWorks
- * will look for the bootline string. The default value is
- * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
- * VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
- */
- tmp = env_get("bootaddr");
- if (!tmp) {
- printf("## VxWorks bootline address not specified\n");
- } else {
- bootaddr = simple_strtoul(tmp, NULL, 16);
-
- /*
- * Check to see if the bootline is defined in the 'bootargs'
- * parameter. If it is not defined, we may be able to
- * construct the info.
- */
- bootline = env_get("bootargs");
- if (!bootline) {
- tmp = env_get("bootdev");
- if (tmp) {
- strcpy(build_buf, tmp);
- ptr = strlen(tmp);
- } else
- printf("## VxWorks boot device not specified\n");
-
- tmp = env_get("bootfile");
- if (tmp)
- ptr += sprintf(build_buf + ptr,
- "host:%s ", tmp);
- else
- ptr += sprintf(build_buf + ptr,
- "host:vxWorks ");
-
- /*
- * The following parameters are only needed if 'bootdev'
- * is an ethernet device, otherwise they are optional.
- */
- tmp = env_get("ipaddr");
- if (tmp) {
- ptr += sprintf(build_buf + ptr, "e=%s", tmp);
- tmp = env_get("netmask");
- if (tmp) {
- u32 mask = env_get_ip("netmask").s_addr;
- ptr += sprintf(build_buf + ptr,
- ":%08x ", ntohl(mask));
- } else {
- ptr += sprintf(build_buf + ptr, " ");
- }
- }
-
- tmp = env_get("serverip");
- if (tmp)
- ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
-
- tmp = env_get("gatewayip");
- if (tmp)
- ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
-
- tmp = env_get("hostname");
- if (tmp)
- ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
-
- tmp = env_get("othbootargs");
- if (tmp) {
- strcpy(build_buf + ptr, tmp);
- ptr += strlen(tmp);
- }
-
- bootline = build_buf;
- }
-
- memcpy((void *)bootaddr, bootline,
- max(strlen(bootline), (size_t)255));
- flush_cache(bootaddr, max(strlen(bootline), (size_t)255));
- printf("## Using bootline (@ 0x%lx): %s\n", bootaddr,
- (char *)bootaddr);
- }
-
#ifdef CONFIG_X86
/*
* Get VxWorks's physical memory base address from environment,
#endif
/*
+ * Use bootaddr to find the location in memory that VxWorks
+ * will look for the bootline string. The default value is
+ * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
+ * VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
+ */
+ tmp = env_get("bootaddr");
+ if (!tmp) {
+#ifdef CONFIG_X86
+ bootaddr = base + X86_BOOT_LINE_OFFSET;
+#else
+ printf("## VxWorks bootline address not specified\n");
+ return 1;
+#endif
+ }
+
+ if (!bootaddr)
+ bootaddr = simple_strtoul(tmp, NULL, 16);
+
+ /*
+ * Check to see if the bootline is defined in the 'bootargs' parameter.
+ * If it is not defined, we may be able to construct the info.
+ */
+ bootline = env_get("bootargs");
+ if (!bootline) {
+ tmp = env_get("bootdev");
+ if (tmp) {
+ strcpy(build_buf, tmp);
+ ptr = strlen(tmp);
+ } else {
+ printf("## VxWorks boot device not specified\n");
+ }
+
+ tmp = env_get("bootfile");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "host:%s ", tmp);
+ else
+ ptr += sprintf(build_buf + ptr, "host:vxWorks ");
+
+ /*
+ * The following parameters are only needed if 'bootdev'
+ * is an ethernet device, otherwise they are optional.
+ */
+ tmp = env_get("ipaddr");
+ if (tmp) {
+ ptr += sprintf(build_buf + ptr, "e=%s", tmp);
+ tmp = env_get("netmask");
+ if (tmp) {
+ u32 mask = env_get_ip("netmask").s_addr;
+ ptr += sprintf(build_buf + ptr,
+ ":%08x ", ntohl(mask));
+ } else {
+ ptr += sprintf(build_buf + ptr, " ");
+ }
+ }
+
+ tmp = env_get("serverip");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
+
+ tmp = env_get("gatewayip");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
+
+ tmp = env_get("hostname");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
+
+ tmp = env_get("othbootargs");
+ if (tmp) {
+ strcpy(build_buf + ptr, tmp);
+ ptr += strlen(tmp);
+ }
+
+ bootline = build_buf;
+ }
+
+ memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255));
+ flush_cache(bootaddr, max(strlen(bootline), (size_t)255));
+ printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr);
+
+ /*
* If the data at the load address is an elf image, then
* treat it like an elf image. Otherwise, assume that it is a
* binary image.