grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[]);
void grub_multiboot_set_bootdev (void);
+void
+grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
+ unsigned shndx, void *data);
#endif /* ! GRUB_MULTIBOOT_HEADER */
if (i == ehdr->e_phnum)
return grub_error (GRUB_ERR_BAD_OS, "entry point isn't in a segment");
+ if (ehdr->e_shnum)
+ {
+ grub_uint8_t *shdr, *shdrptr;
+
+ shdr = grub_malloc (ehdr->e_shnum * ehdr->e_shentsize);
+ if (!shdr)
+ return grub_errno;
+
+ if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "invalid offset to section headers");
+
+ if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize)
+ != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "couldn't read sections headers from file");
+
+ for (shdrptr = shdr, i = 0; i < ehdr->e_shnum;
+ shdrptr += ehdr->e_shentsize, i++)
+ {
+ Elf_Shdr *sh = (Elf_Shdr *) shdrptr;
+ void *src;
+ grub_addr_t target;
+ grub_err_t err;
+
+ /* This section is a loaded section,
+ so we don't care. */
+ if (sh->sh_addr != 0)
+ continue;
+
+ /* This section is empty, so we don't care. */
+ if (sh->sh_size == 0)
+ continue;
+
+ err
+ = grub_relocator_alloc_chunk_align (grub_multiboot_relocator,
+ &src, &target, 0,
+ (0xffffffff - sh->sh_size) + 1,
+ sh->sh_size,
+ sh->sh_addralign,
+ GRUB_RELOCATOR_PREFERENCE_NONE);
+ if (err)
+ {
+ grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);
+ return err;
+ }
+
+ if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "invalid offset in section header");
+
+ if (grub_file_read (file, src, sh->sh_size)
+ != (grub_ssize_t) sh->sh_size)
+ return grub_error (GRUB_ERR_BAD_OS,
+ "couldn't read segment from file");
+ sh->sh_addr = target;
+ }
+ grub_multiboot_add_elfsyms (ehdr->e_shnum, ehdr->e_shentsize,
+ ehdr->e_shstrndx, shdr);
+ }
+
#undef phdr
return grub_errno;
static char *cmdline = NULL;
static grub_uint32_t bootdev;
static int bootdev_set;
+static grub_size_t elf_sec_num, elf_sec_entsize;
+static unsigned elf_sec_shstrndx;
+static void *elf_sections;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
{
return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
- + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ();
+ + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+ + elf_sec_entsize * elf_sec_num;
}
/* Fill previously allocated Multiboot mmap. */
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
}
+ if (elf_sec_num)
+ {
+ mbi->u.elf_sec.addr = ptrdest;
+ grub_memcpy (ptrorig, elf_sections, elf_sec_entsize * elf_sec_num);
+ mbi->u.elf_sec.num = elf_sec_num;
+ mbi->u.elf_sec.size = elf_sec_entsize;
+ mbi->u.elf_sec.shndx = elf_sec_shstrndx;
+
+ mbi->flags |= MULTIBOOT_INFO_ELF_SHDR;
+ }
+
return GRUB_ERR_NONE;
}
+void
+grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
+ unsigned shndx, void *data)
+{
+ elf_sec_num = num;
+ elf_sec_shstrndx = shndx;
+ elf_sec_entsize = entsize;
+ elf_sections = data;
+}
+
void
grub_multiboot_free_mbi (void)
{
}
modules = NULL;
modules_last = NULL;
+
+ grub_free (elf_sections);
+ elf_sections = NULL;
+ elf_sec_entsize = 0;
+ elf_sec_num = 0;
}
grub_err_t