- int i;
- Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
- Elf64_Phdr *p, *ph;
- int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
- unsigned long addr, loadaddr;
-
- /* Read the rest of the Elf header... */
- if ((*(file->fs->read))(file, size, &e->e_version) < size) {
- prom_printf("\nCan't read Elf64 image header\n");
- return 0;
- }
-
- DEBUG_F("Elf64 header:\n");
- DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
- DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
- DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
- DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
- DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
- DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
- DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
- DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
- DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
- DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
-
- loadinfo->entry = e->e_entry;
-
- if (e->e_phnum > MAX_HEADERS) {
- prom_printf ("Can only load kernels with one program header\n");
- return 0;
- }
-
- ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
- if (!ph) {
- prom_printf ("Malloc error\n");
- return 0;
- }
-
- /* Now, we read the section header */
- if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
- prom_printf ("Seek error\n");
- return 0;
- }
- if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
- sizeof(Elf64_Phdr) * e->e_phnum) {
- prom_printf ("Read error\n");
- return 0;
- }
-
- /* Scan through the program header
- * HACK: We must return the _memory size of the kernel image, not the
- * file size (because we have to leave room before other boot
- * infos. This code works as a side effect of the fact that
- * we have one section and vaddr == p_paddr
- */
- loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
- p = ph;
- for (i = 0; i < e->e_phnum; ++i, ++p) {
- if (p->p_type != PT_LOAD || p->p_offset == 0)
- continue;
- if (loadinfo->memsize == 0) {
- loadinfo->offset = p->p_offset;
- loadinfo->memsize = p->p_memsz;
- loadinfo->filesize = p->p_filesz;
- loadinfo->load_loc = p->p_vaddr;
- } else {
- loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
- loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
- }
- }
-
- if (loadinfo->memsize == 0) {
- prom_printf("Can't find a loadable segment !\n");
- return 0;
- }
-
- /* leave some room (1Mb) for boot infos */
- loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
- /* Claim OF memory */
- DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
-
- /* On some systems, loadaddr may already be claimed, so try some
- * other nearby addresses before giving up.
- */
- loadaddr = (e->e_entry == KERNEL_LINK_ADDR_PPC64) ? KERNELADDR : e->e_entry;
- for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
- loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
- if (loadinfo->base != (void *)-1) break;
- }
- if (loadinfo->base == (void *)-1) {
- prom_printf("Claim error, can't allocate kernel memory\n");
- return 0;
- }
-
- DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
- loadinfo->base, loadinfo->memsize);
- DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
- loadaddr, loadinfo->memsize);
-
- /* Load the program segments... */
- p = ph;
- for (i = 0; i < e->e_phnum; ++i, ++p) {
- unsigned long offset;
- if (p->p_type != PT_LOAD || p->p_offset == 0)
- continue;
-
- /* Now, we skip to the image itself */
- if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
- prom_printf ("Seek error\n");
- prom_release(loadinfo->base, loadinfo->memsize);
- return 0;
- }
- offset = p->p_vaddr - loadinfo->load_loc;
- if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
- prom_printf ("Read failed\n");
- prom_release(loadinfo->base, loadinfo->memsize);
- return 0;
- }
- }
-
- free(ph);
+ int i;
+ Elf64_Ehdr *e = &(loadinfo->elf.elf64hdr);
+ Elf64_Phdr *p, *ph;
+ int size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
+ unsigned long addr, loadaddr;
+
+ /* Read the rest of the Elf header... */
+ if ((*(file->fs->read))(file, size, &e->e_version) < size) {
+ prom_printf("\nCan't read Elf64 image header\n");
+ return 0;
+ }
+
+ DEBUG_F("Elf64 header:\n");
+ DEBUG_F(" e.e_type = %d\n", (int)e->e_type);
+ DEBUG_F(" e.e_machine = %d\n", (int)e->e_machine);
+ DEBUG_F(" e.e_version = %d\n", (int)e->e_version);
+ DEBUG_F(" e.e_entry = 0x%016lx\n", (long)e->e_entry);
+ DEBUG_F(" e.e_phoff = 0x%016lx\n", (long)e->e_phoff);
+ DEBUG_F(" e.e_shoff = 0x%016lx\n", (long)e->e_shoff);
+ DEBUG_F(" e.e_flags = %d\n", (int)e->e_flags);
+ DEBUG_F(" e.e_ehsize = 0x%08x\n", (int)e->e_ehsize);
+ DEBUG_F(" e.e_phentsize = 0x%08x\n", (int)e->e_phentsize);
+ DEBUG_F(" e.e_phnum = %d\n", (int)e->e_phnum);
+
+ loadinfo->entry = e->e_entry;
+
+ if (e->e_phnum > MAX_HEADERS) {
+ prom_printf ("Can only load kernels with one program header\n");
+ return 0;
+ }
+
+ ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
+ if (!ph) {
+ prom_printf ("Malloc error\n");
+ return 0;
+ }
+
+ /* Now, we read the section header */
+ if ((*(file->fs->seek))(file, e->e_phoff) != FILE_ERR_OK) {
+ prom_printf ("Seek error\n");
+ return 0;
+ }
+ if ((*(file->fs->read))(file, sizeof(Elf64_Phdr) * e->e_phnum, ph) !=
+ sizeof(Elf64_Phdr) * e->e_phnum) {
+ prom_printf ("Read error\n");
+ return 0;
+ }
+
+ /* Scan through the program header
+ * HACK: We must return the _memory size of the kernel image, not the
+ * file size (because we have to leave room before other boot
+ * infos. This code works as a side effect of the fact that
+ * we have one section and vaddr == p_paddr
+ */
+ loadinfo->memsize = loadinfo->filesize = loadinfo->offset = 0;
+ p = ph;
+ for (i = 0; i < e->e_phnum; ++i, ++p) {
+ if (p->p_type != PT_LOAD || p->p_offset == 0)
+ continue;
+ if (loadinfo->memsize == 0) {
+ loadinfo->offset = p->p_offset;
+ loadinfo->memsize = p->p_memsz;
+ loadinfo->filesize = p->p_filesz;
+ loadinfo->load_loc = p->p_vaddr;
+ } else {
+ loadinfo->memsize = p->p_offset + p->p_memsz - loadinfo->offset; /* XXX Bogus */
+ loadinfo->filesize = p->p_offset + p->p_filesz - loadinfo->offset;
+ }
+ }
+
+ if (loadinfo->memsize == 0) {
+ prom_printf("Can't find a loadable segment !\n");
+ return 0;
+ }
+
+ /* leave some room (1Mb) for boot infos */
+ loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
+ /* Claim OF memory */
+ DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
+
+ /* Determine whether we are trying to boot a vmlinux or some
+ * other binary image (eg, zImage). We load vmlinux's at
+ * KERNELADDR and all other binaries at their e_entry value.
+ */
+ if (e->e_entry == KERNEL_LINK_ADDR_PPC64) {
+ flat_vmlinux = 1;
+ loadaddr = KERNELADDR;
+ } else {
+ flat_vmlinux = 0;
+ loadaddr = e->e_entry;
+ }
+
+ /* On some systems, loadaddr may already be claimed, so try some
+ * other nearby addresses before giving up.
+ */
+ for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
+ loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
+ if (loadinfo->base != (void *)-1) break;
+ }
+ if (loadinfo->base == (void *)-1) {
+ prom_printf("Claim error, can't allocate kernel memory\n");
+ return 0;
+ }
+
+ DEBUG_F("After ELF parsing, load base: %p, mem_sz: 0x%08lx\n",
+ loadinfo->base, loadinfo->memsize);
+ DEBUG_F(" wanted load base: 0x%08lx, mem_sz: 0x%08lx\n",
+ loadaddr, loadinfo->memsize);
+
+ /* Load the program segments... */
+ p = ph;
+ for (i = 0; i < e->e_phnum; ++i, ++p) {
+ unsigned long offset;
+ if (p->p_type != PT_LOAD || p->p_offset == 0)
+ continue;
+
+ /* Now, we skip to the image itself */
+ if ((*(file->fs->seek))(file, p->p_offset) != FILE_ERR_OK) {
+ prom_printf ("Seek error\n");
+ prom_release(loadinfo->base, loadinfo->memsize);
+ return 0;
+ }
+ offset = p->p_vaddr - loadinfo->load_loc;
+ if ((*(file->fs->read))(file, p->p_filesz, loadinfo->base+offset) != p->p_filesz) {
+ prom_printf ("Read failed\n");
+ prom_release(loadinfo->base, loadinfo->memsize);
+ return 0;
+ }
+ }
+
+ free(ph);