On Sun, Dec 29, 2013 at 06:47:35PM +0000, Ian Campbell wrote: > To do so support the specification of a "target_address" (which must be 0 for > image types which do not have this flag) and a new image flag to signal the > need for absolute relocation. If this flag is present then image->link_addr is > the default target. > > Account for the target address when relocating. > > Fabricate correct addresses for absolute symbols relating to the bss > ("__bss_start" and "_end"). > > This functionality is not yet used by any image type and is connected only to > grub-mkimage ("-T option) and not yet to grub-install. > > Signed-off-by: Ian Campbell <i...@hellion.org.uk> > --- > include/grub/util/install.h | 2 +- > util/grub-install-common.c | 4 +-- > util/grub-mkimage.c | 7 +++++ > util/grub-mkimagexx.c | 74 > +++++++++++++++++++++++++++++++-------------- > util/mkimage.c | 24 ++++++++++++--- > 5 files changed, 81 insertions(+), 30 deletions(-) > > diff --git a/include/grub/util/install.h b/include/grub/util/install.h > index bc987aa..b7ecf27 100644 > --- a/include/grub/util/install.h > +++ b/include/grub/util/install.h > @@ -167,7 +167,7 @@ struct grub_install_image_target_desc; > > void > grub_install_generate_image (const char *dir, const char *prefix, > - FILE *out, > + FILE *out, grub_uint64_t target_address, > const char *outname, char *mods[], > char *memdisk_path, char **pubkey_paths, > size_t npubkeys, > diff --git a/util/grub-install-common.c b/util/grub-install-common.c > index ae26875..82a44f2 100644 > --- a/util/grub-install-common.c > +++ b/util/grub-install-common.c > @@ -495,8 +495,8 @@ grub_install_make_image_wrap_file (const char *dir, const > char *prefix, > if (!tgt) > grub_util_error (_("unknown target format %s\n"), mkimage_target); > > - grub_install_generate_image (dir, prefix, fp, outname, > - modules.entries, memdisk_path, > + grub_install_generate_image (dir, prefix, fp, 0, > + outname, modules.entries, memdisk_path, > pubkeys, npubkeys, config_path, tgt, > note, compression); > while (dc--) > diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c > index a2bd4c1..267beaa 100644 > --- a/util/grub-mkimage.c > +++ b/util/grub-mkimage.c > @@ -65,6 +65,7 @@ static struct argp_option options[] = { > /* TRANSLATORS: platform here isn't identifier. It can be translated. */ > N_("use images and modules under DIR [default=%s/<platform>]"), 0}, > {"prefix", 'p', N_("DIR"), 0, N_("set prefix directory [default=%s]"), 0}, > + {"target-address", 'T', N_("ADDR"), 0, N_("set kernel target address > [default=%d]"), 0},
For this to actually print a default value, you need to also update the help_filter function. Also, you probably want a %p here. --- --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -65,7 +65,7 @@ static struct argp_option options[] = { /* TRANSLATORS: platform here isn't identifier. It can be translated. */ N_("use images and modules under DIR [default=%s/<platform>]"), 0}, {"prefix", 'p', N_("DIR"), 0, N_("set prefix directory [default=%s]"), 0}, - {"target-address", 'T', N_("ADDR"), 0, N_("set kernel target address [default=%d]"), 0}, + {"target-address", 'T', N_("ADDR"), 0, N_("set kernel target address [default=%p]"), 0}, {"memdisk", 'm', N_("FILE"), 0, /* TRANSLATORS: "memdisk" here isn't an identifier, it can be translated. "embed" is a verb (command description). "*/ @@ -104,6 +104,8 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused))) free (formats); return ret; } + case 'T': + return xasprintf (text, GRUB_KERNEL_ARM_UBOOT_DEFAULT_LINK_ADDR); default: return (char *) text; } --- (Of course, you probably want to abstract away the ARM_UBOOT bit...) > {"memdisk", 'm', N_("FILE"), 0, > /* TRANSLATORS: "memdisk" here isn't an identifier, it can be translated. > "embed" is a verb (command description). "*/ > @@ -126,6 +127,7 @@ struct arguments > int note; > const struct grub_install_image_target_desc *image_target; > grub_compression_t comp; > + grub_uint64_t target_address; > }; > > static error_t > @@ -217,6 +219,10 @@ argp_parser (int key, char *arg, struct argp_state > *state) > arguments->prefix = xstrdup (arg); > break; > > + case 'T': > + arguments->target_address = strtoull (arg, NULL, 0); > + break; > + > case 'v': > verbosity++; > break; > @@ -289,6 +295,7 @@ main (int argc, char *argv[]) > > grub_install_generate_image (arguments.dir, > arguments.prefix ? : DEFAULT_DIRECTORY, fp, > + arguments.target_address, > arguments.output, arguments.modules, > arguments.memdisk, arguments.pubkeys, > arguments.npubkeys, arguments.config, > diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c > index b4216ff..186d259 100644 > --- a/util/grub-mkimagexx.c > +++ b/util/grub-mkimagexx.c > @@ -378,6 +378,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr > *sections, > Elf_Shdr *symtab_section, Elf_Addr > *section_addresses, > Elf_Half section_entsize, Elf_Half num_sections, > void *jumpers, Elf_Addr jumpers_addr, > + Elf_Addr bss_addr, size_t bss_size, > const struct grub_install_image_target_desc > *image_target) > { > Elf_Word symtab_size, sym_size, num_syms; > @@ -416,10 +417,14 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr > *sections, > } > else if (cur_index == STN_UNDEF) > { > - if (sym->st_name) > + if (strcmp (name, "__bss_start") == 0 && bss_addr) > + sym->st_value = bss_addr; > + else if (strcmp (name, "_end") == 0 && bss_addr) > + sym->st_value = bss_addr + bss_size; > + else if (sym->st_name) > grub_util_error ("undefined symbol %s", name); > - else > - continue; > + > + continue; > } > else if (cur_index >= num_sections) > grub_util_error ("section %d does not exist", cur_index); > @@ -584,7 +589,7 @@ static void > SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, > Elf_Addr *section_addresses, > Elf_Half section_entsize, Elf_Half num_sections, > - const char *strtab, > + const char *strtab, grub_uint64_t target_address, > char *pe_target, Elf_Addr tramp_off, > Elf_Addr got_off, > const struct grub_install_image_target_desc > *image_target) > @@ -867,6 +872,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr > *sections, > { > case R_ARM_ABS32: > { > + sym_addr += target_address; > grub_util_info (" > ABS32:\ttarget=0x%08lx\toffset=(0x%08x)", > (unsigned long) ((char *) target > - (char *) e), > @@ -928,7 +934,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr > *sections, > grub_uint32_t tr_addr; > grub_int32_t new_offset; > tr_addr = (char *) tr - (char *) pe_target > - - target_section_addr; > + - (target_address - target_section_addr); > new_offset = sym_addr - tr_addr - 12; > > /* There is no immediate version of bx, only > register one... */ > @@ -1337,6 +1343,7 @@ static Elf_Addr * > SUFFIX (locate_sections) (const char *kernel_path, > Elf_Shdr *sections, Elf_Half section_entsize, > Elf_Half num_sections, const char *strtab, > + grub_uint64_t target_address, > size_t *exec_size, size_t *kernel_sz, > size_t *all_align, > const struct grub_install_image_target_desc > *image_target) > @@ -1351,7 +1358,7 @@ SUFFIX (locate_sections) (const char *kernel_path, > section_addresses = xmalloc (sizeof (*section_addresses) * num_sections); > memset (section_addresses, 0, sizeof (*section_addresses) * num_sections); > > - current_address = 0; > + current_address = target_address; > > for (i = 0, s = sections; > i < num_sections; > @@ -1391,6 +1398,15 @@ SUFFIX (locate_sections) (const char *kernel_path, > grub_util_error ("%s", msg); > } > } > + else if (!grub_image_needs_abs_reloc(image_target)) > + { > + if (grub_host_to_target_addr (s->sh_addr)) > + grub_util_error (_("`%s' is miscompiled: its start address is > 0x%llx" > + " but this platform uses late relocation"), > + kernel_path, > + (unsigned long long) grub_host_to_target_addr > (s->sh_addr)); > + } > + > section_addresses[i] = current_address; > current_address += grub_host_to_target_addr (s->sh_size); > } > @@ -1398,7 +1414,7 @@ SUFFIX (locate_sections) (const char *kernel_path, > current_address = ALIGN_UP (current_address + image_target->vaddr_offset, > image_target->section_align) > - image_target->vaddr_offset; > - *exec_size = current_address; > + *exec_size = current_address - target_address; > > /* .data */ > for (i = 0, s = sections; > @@ -1426,14 +1442,15 @@ SUFFIX (locate_sections) (const char *kernel_path, > > current_address = ALIGN_UP (current_address + image_target->vaddr_offset, > image_target->section_align) - > image_target->vaddr_offset; > - *kernel_sz = current_address; > + *kernel_sz = current_address - target_address; > return section_addresses; > } > > static char * > SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, > size_t *kernel_sz, size_t *bss_size, > - size_t total_module_size, grub_uint64_t *start, > + size_t total_module_size, grub_uint64_t target_address, > + grub_uint64_t *start, > void **reloc_section, size_t *reloc_size, > size_t *align, > const struct grub_install_image_target_desc *image_target) > @@ -1444,6 +1461,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > Elf_Shdr *sections; > Elf_Addr *section_addresses; > Elf_Addr *section_vaddresses; > + Elf_Addr bss_addr = 0; > int i; > Elf_Shdr *s; > Elf_Half num_sections; > @@ -1455,6 +1473,9 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > Elf_Shdr *symtab_section = 0; > grub_size_t got = 0; > > + if (target_address && !grub_image_needs_abs_reloc(image_target)) > + grub_util_error("cannot perform absolute relocation for this image > type"); > + > *start = 0; > > kernel_size = grub_util_get_image_size (kernel_path); > @@ -1481,7 +1502,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > > section_addresses = SUFFIX (locate_sections) (kernel_path, > sections, section_entsize, > - num_sections, strtab, > + num_sections, strtab, > target_address, > exec_size, kernel_sz, align, > image_target); > > @@ -1530,9 +1551,9 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > for (i = 0; i < num_sections; i++) > section_vaddresses[i] = section_addresses[i] + > image_target->vaddr_offset; > > - if (!grub_image_needs_reloc(image_target)) > + if (!grub_image_needs_reloc(image_target) || > grub_image_needs_abs_reloc(image_target)) > { > - Elf_Addr current_address = *kernel_sz; > + Elf_Addr current_address = target_address + *kernel_sz; > > for (i = 0, s = sections; > i < num_sections; > @@ -1558,11 +1579,16 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > section_vaddresses[i] = current_address > + image_target->vaddr_offset; > current_address += grub_host_to_target_addr (s->sh_size); > + > + if (!bss_addr) > + bss_addr = section_vaddresses[i]; > } > current_address = ALIGN_UP (current_address + > image_target->vaddr_offset, > image_target->section_align) > - image_target->vaddr_offset; > - *bss_size = current_address - *kernel_sz; > + *bss_size = current_address - *kernel_sz - target_address; > + grub_util_info ("locating bss at 0x%x-0x%x (0x%x bytes)", > + (int)bss_addr, (int)(bss_addr + *bss_size), > (int)*bss_size); > } > else > *bss_size = 0; > @@ -1603,6 +1629,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > (char *) out_img + ia64jmp_off, > ia64jmp_off > + image_target->vaddr_offset, > + bss_addr, *bss_size, > image_target); > if (*start == INVALID_START_ADDR) > grub_util_error ("start symbol is not defined"); > @@ -1612,17 +1639,18 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > /* Resolve addresses in the virtual address space. */ > SUFFIX (relocate_addresses) (e, sections, section_addresses, > section_entsize, > - num_sections, strtab, > + num_sections, strtab, target_address, > out_img, tramp_off, ia64_got_off, > image_target); > > - *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section, > - section_vaddresses, sections, > - section_entsize, num_sections, > - strtab, ia64jmp_off > - + image_target->vaddr_offset, > - 2 * ia64jmpnum + (got / 8), > - image_target); > + if (!grub_image_needs_abs_reloc(image_target)) > + *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section, > + section_vaddresses, > sections, > + section_entsize, > num_sections, > + strtab, ia64jmp_off > + + > image_target->vaddr_offset, > + 2 * ia64jmpnum + (got / 8), > + image_target); The above is only indentation changes? > } > > for (i = 0, s = sections; > @@ -1632,10 +1660,10 @@ SUFFIX (load_image) (const char *kernel_path, size_t > *exec_size, > || SUFFIX (is_text_section) (s, image_target)) > { > if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS) > - memset (out_img + section_addresses[i], 0, > + memset (out_img + section_addresses[i] - target_address, 0, > grub_host_to_target_addr (s->sh_size)); > else > - memcpy (out_img + section_addresses[i], > + memcpy (out_img + section_addresses[i] - target_address, > kernel_img + grub_host_to_target_addr (s->sh_offset), > grub_host_to_target_addr (s->sh_size)); > } > diff --git a/util/mkimage.c b/util/mkimage.c > index 645e296..7b29acf 100644 > --- a/util/mkimage.c > +++ b/util/mkimage.c > @@ -74,6 +74,7 @@ struct grub_install_image_target_desc > PLATFORM_FLAGS_NONE = 0, > PLATFORM_FLAGS_DECOMPRESSORS = 2, > PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4, > + PLATFORM_FLAGS_ABS_RELOC = 8, > } flags; > unsigned total_module_size; > unsigned decompressor_compressed_size; > @@ -922,11 +923,16 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, > Elf32_Addr sym_addr) > return GRUB_ERR_NONE; > } > > +static int grub_image_needs_abs_reloc(const struct > grub_install_image_target_desc *target) > +{ > + return target->flags & PLATFORM_FLAGS_ABS_RELOC; > +} > + > static int grub_image_needs_reloc(const struct > grub_install_image_target_desc *target) > { > if (target->id == IMAGE_EFI) > return 1; > - return 0; > + return grub_image_needs_abs_reloc(target); > } > > #pragma GCC diagnostic ignored "-Wcast-align" > @@ -987,7 +993,8 @@ grub_install_get_image_targets_string (void) > > void > grub_install_generate_image (const char *dir, const char *prefix, > - FILE *out, const char *outname, char *mods[], > + FILE *out, grub_uint64_t target_address, > + const char *outname, char *mods[], > char *memdisk_path, char **pubkey_paths, > size_t npubkeys, char *config_path, > const struct grub_install_image_target_desc > *image_target, > @@ -1024,6 +1031,13 @@ grub_install_generate_image (const char *dir, const > char *prefix, > else > total_module_size = sizeof (struct grub_module_info32); > > + if (!target_address && grub_image_needs_abs_reloc(image_target)) > + { > + grub_util_info ("Using default target address 0x%llx", > + (unsigned long long)image_target->link_addr); > + target_address = image_target->link_addr; > + } > + > { > size_t i; > for (i = 0; i < npubkeys; i++) > @@ -1069,11 +1083,13 @@ grub_install_generate_image (const char *dir, const > char *prefix, > > if (image_target->voidp_sizeof == 4) > kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, > &bss_size, > - total_module_size, &start_address, &rel_section, > + total_module_size, target_address, > + &start_address, &rel_section, > &reloc_size, &align, image_target); > else > kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size, > &bss_size, > - total_module_size, &start_address, &rel_section, > + total_module_size, target_address, > + &start_address, &rel_section, > &reloc_size, &align, image_target); > if (image_target->id == IMAGE_XEN && align < 4096) > align = 4096; > -- > 1.8.4.rc3 > _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel