Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
   216         kx /* grub-mkimage.c - make a bootable image */
   216         kx /*
   216         kx  *  GRUB  --  GRand Unified Bootloader
   216         kx  *  Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010  Free Software Foundation, Inc.
   216         kx  *
   216         kx  *  GRUB is free software: you can redistribute it and/or modify
   216         kx  *  it under the terms of the GNU General Public License as published by
   216         kx  *  the Free Software Foundation, either version 3 of the License, or
   216         kx  *  (at your option) any later version.
   216         kx  *
   216         kx  *  GRUB is distributed in the hope that it will be useful,
   216         kx  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   216         kx  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   216         kx  *  GNU General Public License for more details.
   216         kx  *
   216         kx  *  You should have received a copy of the GNU General Public License
   216         kx  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
   216         kx  */
   216         kx 
   216         kx #include <config.h>
   216         kx #include <grub/types.h>
   216         kx #include <grub/elf.h>
   216         kx #include <grub/aout.h>
   216         kx #include <grub/i18n.h>
   216         kx #include <grub/kernel.h>
   216         kx #include <grub/disk.h>
   216         kx #include <grub/emu/misc.h>
   216         kx #include <grub/util/misc.h>
   216         kx #include <grub/util/resolve.h>
   216         kx #include <grub/misc.h>
   216         kx #include <grub/offsets.h>
   216         kx #include <grub/crypto.h>
   216         kx #include <grub/dl.h>
   216         kx #include <time.h>
   216         kx #include <multiboot.h>
   216         kx 
   216         kx #include <stdio.h>
   216         kx #include <unistd.h>
   216         kx #include <string.h>
   216         kx #include <stdlib.h>
   216         kx #include <assert.h>
   216         kx #include <grub/efi/pe32.h>
   216         kx #include <grub/uboot/image.h>
   216         kx #include <grub/arm/reloc.h>
   216         kx #include <grub/arm64/reloc.h>
   216         kx #include <grub/ia64/reloc.h>
   216         kx #include <grub/osdep/hostfile.h>
   216         kx #include <grub/util/install.h>
   216         kx #include <grub/util/mkimage.h>
   216         kx 
   216         kx #include <xen/elfnote.h>
   216         kx 
   216         kx #pragma GCC diagnostic ignored "-Wcast-align"
   216         kx 
   216         kx #define GRUB_MKIMAGEXX
   216         kx #if !defined(MKIMAGE_ELF32) && !defined(MKIMAGE_ELF64)
   216         kx #if __SIZEOF_POINTER__ == 8
   216         kx #include "grub-mkimage64.c"
   216         kx #else
   216         kx #include "grub-mkimage32.c"
   216         kx #endif
   216         kx #endif
   216         kx 
   216         kx /* These structures are defined according to the CHRP binding to IEEE1275,
   216         kx    "Client Program Format" section.  */
   216         kx 
   216         kx struct grub_ieee1275_note_desc
   216         kx {
   216         kx   grub_uint32_t real_mode;
   216         kx   grub_uint32_t real_base;
   216         kx   grub_uint32_t real_size;
   216         kx   grub_uint32_t virt_base;
   216         kx   grub_uint32_t virt_size;
   216         kx   grub_uint32_t load_base;
   216         kx };
   216         kx 
   216         kx #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
   216         kx #define GRUB_IEEE1275_NOTE_TYPE 0x1275
   216         kx 
   216         kx struct grub_ieee1275_note
   216         kx {
   216         kx   Elf32_Nhdr header;
   216         kx   char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
   216         kx   struct grub_ieee1275_note_desc descriptor;
   216         kx };
   216         kx 
   216         kx #define GRUB_XEN_NOTE_NAME "Xen"
   216         kx 
   216         kx struct fixup_block_list
   216         kx {
   216         kx   struct fixup_block_list *next;
   216         kx   int state;
   216         kx   struct grub_pe32_fixup_block b;
   216         kx };
   216         kx 
   216         kx #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
   216         kx 
   216         kx struct section_metadata
   216         kx {
   216         kx   Elf_Half num_sections;
   216         kx   Elf_Shdr *sections;
   216         kx   Elf_Addr *addrs;
   216         kx   Elf_Addr *vaddrs;
   216         kx   Elf_Half section_entsize;
   216         kx   Elf_Shdr *symtab;
   216         kx   const char *strtab;
   216         kx };
   216         kx 
   216         kx static int
   216         kx is_relocatable (const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
   216         kx     || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
   216         kx }
   216         kx 
   216         kx #ifdef MKIMAGE_ELF32
   216         kx 
   216         kx /*
   216         kx  * R_ARM_THM_CALL/THM_JUMP24
   216         kx  *
   216         kx  * Relocate Thumb (T32) instruction set relative branches:
   216         kx  *   B.W, BL and BLX
   216         kx  */
   216         kx static grub_err_t
   216         kx grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
   216         kx {
   216         kx   grub_int32_t offset;
   216         kx 
   216         kx   offset = grub_arm_thm_call_get_offset (target);
   216         kx 
   216         kx   grub_dprintf ("dl", "    sym_addr = 0x%08x", sym_addr);
   216         kx 
   216         kx   offset += sym_addr;
   216         kx 
   216         kx   grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
   216         kx 	       target, sym_addr, offset);
   216         kx 
   216         kx   /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
   216         kx      is bigger than 2M  (currently under 150K) then we probably have a problem
   216         kx      somewhere else.  */
   216         kx   if (offset < -0x200000 || offset >= 0x200000)
   216         kx     return grub_error (GRUB_ERR_BAD_MODULE,
   216         kx 		       "THM_CALL Relocation out of range.");
   216         kx 
   216         kx   grub_dprintf ("dl", "    relative destination = %p",
   216         kx 		(char *) target + offset);
   216         kx 
   216         kx   return grub_arm_thm_call_set_offset (target, offset);
   216         kx }
   216         kx 
   216         kx /*
   216         kx  * R_ARM_THM_JUMP19
   216         kx  *
   216         kx  * Relocate conditional Thumb (T32) B<c>.W
   216         kx  */
   216         kx static grub_err_t
   216         kx grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
   216         kx {
   216         kx   grub_int32_t offset;
   216         kx 
   216         kx   if (!(sym_addr & 1))
   216         kx     return grub_error (GRUB_ERR_BAD_MODULE,
   216         kx 		       "Relocation targeting wrong execution state");
   216         kx 
   216         kx   offset = grub_arm_thm_jump19_get_offset (target);
   216         kx 
   216         kx   /* Adjust and re-truncate offset */
   216         kx   offset += sym_addr;
   216         kx 
   216         kx   if (!grub_arm_thm_jump19_check_offset (offset))
   216         kx     return grub_error (GRUB_ERR_BAD_MODULE,
   216         kx 		       "THM_JUMP19 Relocation out of range.");
   216         kx 
   216         kx   grub_arm_thm_jump19_set_offset (target, offset);
   216         kx 
   216         kx   return GRUB_ERR_NONE;
   216         kx }
   216         kx 
   216         kx /*
   216         kx  * R_ARM_JUMP24
   216         kx  *
   216         kx  * Relocate ARM (A32) B
   216         kx  */
   216         kx static grub_err_t
   216         kx grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
   216         kx {
   216         kx   grub_int32_t offset;
   216         kx 
   216         kx   if (sym_addr & 1)
   216         kx     return grub_error (GRUB_ERR_BAD_MODULE,
   216         kx 		       "Relocation targeting wrong execution state");
   216         kx 
   216         kx   offset = grub_arm_jump24_get_offset (target);
   216         kx   offset += sym_addr;
   216         kx 
   216         kx   if (!grub_arm_jump24_check_offset (offset))
   216         kx     return grub_error (GRUB_ERR_BAD_MODULE,
   216         kx 		       "JUMP24 Relocation out of range.");
   216         kx 
   216         kx 
   216         kx   grub_arm_jump24_set_offset (target, offset);
   216         kx 
   216         kx   return GRUB_ERR_NONE;
   216         kx }
   216         kx 
   216         kx #endif
   216         kx 
   216         kx void
   216         kx SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
   216         kx 				    int note, char **core_img, size_t *core_size,
   216         kx 				    Elf_Addr target_addr,
   216         kx 				    struct grub_mkimage_layout *layout)
   216         kx {
   216         kx   char *elf_img;
   216         kx   size_t program_size;
   216         kx   Elf_Ehdr *ehdr;
   216         kx   Elf_Phdr *phdr;
   216         kx   Elf_Shdr *shdr;
   216         kx   int header_size, footer_size = 0;
   216         kx   int phnum = 1;
   216         kx   int shnum = 4;
   216         kx   int string_size = sizeof (".text") + sizeof ("mods") + 1;
   216         kx 
   216         kx   if (image_target->id != IMAGE_LOONGSON_ELF)
   216         kx     phnum += 2;
   216         kx 
   216         kx   if (note)
   216         kx     {
   216         kx       phnum++;
   216         kx       footer_size += sizeof (struct grub_ieee1275_note);
   216         kx     }
   216         kx   if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
   216         kx     {
   216         kx       phnum++;
   216         kx       shnum++;
   216         kx       string_size += sizeof (".xen");
   216         kx       footer_size += (image_target->id == IMAGE_XEN) ? XEN_NOTE_SIZE : XEN_PVH_NOTE_SIZE;
   216         kx     }
   216         kx   header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
   216         kx 			  + shnum * sizeof (*shdr) + string_size, layout->align);
   216         kx 
   216         kx   program_size = ALIGN_ADDR (*core_size);
   216         kx 
   216         kx   elf_img = xmalloc (program_size + header_size + footer_size);
   216         kx   memset (elf_img, 0, program_size + header_size + footer_size);
   216         kx   memcpy (elf_img  + header_size, *core_img, *core_size);
   216         kx   ehdr = (void *) elf_img;
   216         kx   phdr = (void *) (elf_img + sizeof (*ehdr));
   216         kx   shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
   216         kx   memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
   216         kx   ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
   216         kx   if (!image_target->bigendian)
   216         kx     ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
   216         kx   else
   216         kx     ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
   216         kx   ehdr->e_ident[EI_VERSION] = EV_CURRENT;
   216         kx   ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
   216         kx   ehdr->e_type = grub_host_to_target16 (ET_EXEC);
   216         kx   ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
   216         kx   ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
   216         kx 
   216         kx   ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
   216         kx   ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
   216         kx   ehdr->e_phnum = grub_host_to_target16 (phnum);
   216         kx 
   216         kx   ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
   216         kx 					 - (grub_uint8_t *) ehdr);
   216         kx   if (image_target->id == IMAGE_LOONGSON_ELF)
   216         kx     ehdr->e_shentsize = grub_host_to_target16 (0);
   216         kx   else
   216         kx     ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
   216         kx   ehdr->e_shnum = grub_host_to_target16 (shnum);
   216         kx   ehdr->e_shstrndx = grub_host_to_target16 (1);
   216         kx 
   216         kx   ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
   216         kx 
   216         kx   phdr->p_type = grub_host_to_target32 (PT_LOAD);
   216         kx   phdr->p_offset = grub_host_to_target32 (header_size);
   216         kx   phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
   216         kx 
   216         kx   ehdr->e_entry = grub_host_to_target32 (target_addr);
   216         kx   phdr->p_vaddr = grub_host_to_target32 (target_addr);
   216         kx   phdr->p_paddr = grub_host_to_target32 (target_addr);
   216         kx   phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
   216         kx 					 layout->align : image_target->link_align);
   216         kx   if (image_target->id == IMAGE_LOONGSON_ELF)
   216         kx     ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER 
   216         kx 					   | EF_MIPS_PIC | EF_MIPS_CPIC);
   216         kx   else
   216         kx     ehdr->e_flags = 0;
   216         kx   if (image_target->id == IMAGE_LOONGSON_ELF)
   216         kx     {
   216         kx       phdr->p_filesz = grub_host_to_target32 (*core_size);
   216         kx       phdr->p_memsz = grub_host_to_target32 (*core_size);
   216         kx     }
   216         kx   else
   216         kx     {
   216         kx       grub_uint32_t target_addr_mods;
   216         kx       phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
   216         kx       if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
   216         kx 	phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
   216         kx       else
   216         kx 	phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
   216         kx 
   216         kx       phdr++;
   216         kx       phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
   216         kx       phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
   216         kx       phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
   216         kx       phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
   216         kx       phdr->p_align = grub_host_to_target32 (image_target->link_align);
   216         kx 
   216         kx       phdr++;
   216         kx       phdr->p_type = grub_host_to_target32 (PT_LOAD);
   216         kx       phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
   216         kx       phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
   216         kx       phdr->p_filesz = phdr->p_memsz
   216         kx 	= grub_host_to_target32 (*core_size - layout->kernel_size);
   216         kx 
   216         kx       if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
   216         kx 	target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
   216         kx       else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
   216         kx 	target_addr_mods = ALIGN_UP (target_addr + layout->end
   216         kx 				     + image_target->mod_gap,
   216         kx 				     image_target->mod_align);
   216         kx       else
   216         kx 	target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
   216         kx 				     + image_target->mod_gap,
   216         kx 				     image_target->mod_align);
   216         kx       phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
   216         kx       phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
   216         kx       phdr->p_align = grub_host_to_target32 (image_target->link_align);
   216         kx     }
   216         kx 
   216         kx   if (image_target->id == IMAGE_XEN)
   216         kx     {
   216         kx       char *note_start = (elf_img + program_size + header_size);
   216         kx       Elf_Nhdr *note_ptr;
   216         kx       char *ptr = (char *) note_start;
   216         kx 
   216         kx       grub_util_info ("adding XEN NOTE segment");
   216         kx 
   216         kx       /* Guest OS.  */
   216         kx       note_ptr = (Elf_Nhdr *) ptr;
   216         kx       note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       note_ptr->n_descsz = grub_host_to_target32 (sizeof (PACKAGE_NAME));
   216         kx       note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_GUEST_OS);
   216         kx       ptr += sizeof (Elf_Nhdr);
   216         kx       memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
   216         kx       memcpy (ptr, PACKAGE_NAME, sizeof (PACKAGE_NAME));
   216         kx       ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 4);
   216         kx 
   216         kx       /* Loader.  */
   216         kx       note_ptr = (Elf_Nhdr *) ptr;
   216         kx       note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       note_ptr->n_descsz = grub_host_to_target32 (sizeof ("generic"));
   216         kx       note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_LOADER);
   216         kx       ptr += sizeof (Elf_Nhdr);
   216         kx       memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
   216         kx       memcpy (ptr, "generic", sizeof ("generic"));
   216         kx       ptr += ALIGN_UP (sizeof ("generic"), 4);
   216         kx 
   216         kx       /* Version.  */
   216         kx       note_ptr = (Elf_Nhdr *) ptr;
   216         kx       note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       note_ptr->n_descsz = grub_host_to_target32 (sizeof ("xen-3.0"));
   216         kx       note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_XEN_VERSION);
   216         kx       ptr += sizeof (Elf_Nhdr);
   216         kx       memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
   216         kx       memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
   216         kx       ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
   216         kx 
   216         kx       /* Entry.  */
   216         kx       note_ptr = (Elf_Nhdr *) ptr;
   216         kx       note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx       note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_ENTRY);
   216         kx       ptr += sizeof (Elf_Nhdr);
   216         kx       memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
   216         kx       memset (ptr, 0, image_target->voidp_sizeof);
   216         kx       ptr += image_target->voidp_sizeof;
   216         kx 
   216         kx       /* Virt base.  */
   216         kx       note_ptr = (Elf_Nhdr *) ptr;
   216         kx       note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx       note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_VIRT_BASE);
   216         kx       ptr += sizeof (Elf_Nhdr);
   216         kx       memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
   216         kx       memset (ptr, 0, image_target->voidp_sizeof);
   216         kx       ptr += image_target->voidp_sizeof;
   216         kx 
   216         kx       /* PAE.  */
   216         kx       if (image_target->elf_target == EM_386)
   216         kx 	{
   216         kx 	  note_ptr = (Elf_Nhdr *) ptr;
   216         kx 	  note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
   216         kx 	  note_ptr->n_descsz = grub_host_to_target32 (sizeof ("yes,bimodal"));
   216         kx 	  note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PAE_MODE);
   216         kx 	  ptr += sizeof (Elf_Nhdr);
   216         kx 	  memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
   216         kx 	  ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
   216         kx 	  memcpy (ptr, "yes", sizeof ("yes"));
   216         kx 	  ptr += ALIGN_UP (sizeof ("yes"), 4);
   216         kx 	}
   216         kx 
   216         kx       assert (XEN_NOTE_SIZE == (ptr - note_start));
   216         kx 
   216         kx       phdr++;
   216         kx       phdr->p_type = grub_host_to_target32 (PT_NOTE);
   216         kx       phdr->p_flags = grub_host_to_target32 (PF_R);
   216         kx       phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx       phdr->p_vaddr = 0;
   216         kx       phdr->p_paddr = 0;
   216         kx       phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
   216         kx       phdr->p_memsz = 0;
   216         kx       phdr->p_offset = grub_host_to_target32 (header_size + program_size);
   216         kx     }
   216         kx 
   216         kx   if (image_target->id == IMAGE_XEN_PVH)
   216         kx     {
   216         kx       char *note_start = (elf_img + program_size + header_size);
   216         kx       Elf_Nhdr *note_ptr;
   216         kx       char *ptr = (char *) note_start;
   216         kx 
   216         kx       grub_util_info ("adding XEN NOTE segment");
   216         kx 
   216         kx       /* Phys32 Entry.  */
   216         kx       note_ptr = (Elf_Nhdr *) ptr;
   216         kx       note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx       note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PHYS32_ENTRY);
   216         kx       ptr += sizeof (Elf_Nhdr);
   216         kx       memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
   216         kx       ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
   216         kx       memset (ptr, 0, image_target->voidp_sizeof);
   216         kx       *(grub_uint32_t *) ptr = GRUB_KERNEL_I386_XEN_PVH_LINK_ADDR;
   216         kx       ptr += image_target->voidp_sizeof;
   216         kx 
   216         kx       assert (XEN_PVH_NOTE_SIZE == (ptr - note_start));
   216         kx 
   216         kx       phdr++;
   216         kx       phdr->p_type = grub_host_to_target32 (PT_NOTE);
   216         kx       phdr->p_flags = grub_host_to_target32 (PF_R);
   216         kx       phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx       phdr->p_vaddr = 0;
   216         kx       phdr->p_paddr = 0;
   216         kx       phdr->p_filesz = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
   216         kx       phdr->p_memsz = 0;
   216         kx       phdr->p_offset = grub_host_to_target32 (header_size + program_size);
   216         kx     }
   216         kx 
   216         kx   if (note)
   216         kx     {
   216         kx       int note_size = sizeof (struct grub_ieee1275_note);
   216         kx       struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *) 
   216         kx 	(elf_img + program_size + header_size);
   216         kx 
   216         kx       grub_util_info ("adding CHRP NOTE segment");
   216         kx 
   216         kx       note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
   216         kx       note_ptr->header.n_descsz = grub_host_to_target32 (sizeof (struct grub_ieee1275_note_desc));
   216         kx       note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
   216         kx       strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
   216         kx       note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
   216         kx       note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
   216         kx       note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
   216         kx       note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
   216         kx       note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
   216         kx       note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
   216         kx 
   216         kx       phdr++;
   216         kx       phdr->p_type = grub_host_to_target32 (PT_NOTE);
   216         kx       phdr->p_flags = grub_host_to_target32 (PF_R);
   216         kx       phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx       phdr->p_vaddr = 0;
   216         kx       phdr->p_paddr = 0;
   216         kx       phdr->p_filesz = grub_host_to_target32 (note_size);
   216         kx       phdr->p_memsz = 0;
   216         kx       phdr->p_offset = grub_host_to_target32 (header_size + program_size);
   216         kx     }
   216         kx 
   216         kx   {
   216         kx     char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
   216         kx 		       + shnum * sizeof (*shdr));
   216         kx     char *ptr = str_start + 1;
   216         kx 
   216         kx     shdr++;
   216         kx 
   216         kx     shdr->sh_name = grub_host_to_target32 (0);
   216         kx     shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
   216         kx     shdr->sh_addr = grub_host_to_target_addr (0);
   216         kx     shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
   216         kx     shdr->sh_size = grub_host_to_target32 (string_size);
   216         kx     shdr->sh_link = grub_host_to_target32 (0);
   216         kx     shdr->sh_info = grub_host_to_target32 (0);
   216         kx     shdr->sh_addralign = grub_host_to_target32 (layout->align);
   216         kx     shdr->sh_entsize = grub_host_to_target32 (0);
   216         kx     shdr++;
   216         kx 
   216         kx     memcpy (ptr, ".text", sizeof (".text"));
   216         kx 
   216         kx     shdr->sh_name = grub_host_to_target32 (ptr - str_start);
   216         kx     ptr += sizeof (".text");
   216         kx     shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
   216         kx     shdr->sh_addr = grub_host_to_target_addr (target_addr);
   216         kx     shdr->sh_offset = grub_host_to_target_addr (header_size);
   216         kx     shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
   216         kx     shdr->sh_link = grub_host_to_target32 (0);
   216         kx     shdr->sh_info = grub_host_to_target32 (0);
   216         kx     shdr->sh_addralign = grub_host_to_target32 (layout->align);
   216         kx     shdr->sh_entsize = grub_host_to_target32 (0);
   216         kx     shdr++;
   216         kx 
   216         kx     memcpy (ptr, "mods", sizeof ("mods"));
   216         kx     shdr->sh_name = grub_host_to_target32 (ptr - str_start);
   216         kx     ptr += sizeof ("mods");
   216         kx     shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
   216         kx     shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
   216         kx     shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
   216         kx     shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
   216         kx     shdr->sh_link = grub_host_to_target32 (0);
   216         kx     shdr->sh_info = grub_host_to_target32 (0);
   216         kx     shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx     shdr->sh_entsize = grub_host_to_target32 (0);
   216         kx     shdr++;
   216         kx 
   216         kx     if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
   216         kx       {
   216         kx 	memcpy (ptr, ".xen", sizeof (".xen"));
   216         kx 	shdr->sh_name = grub_host_to_target32 (ptr - str_start);
   216         kx 	ptr += sizeof (".xen");
   216         kx 	shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
   216         kx 	shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
   216         kx 	shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
   216         kx 	if (image_target->id == IMAGE_XEN)
   216         kx 	  shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
   216         kx 	else
   216         kx 	  shdr->sh_size = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
   216         kx 	shdr->sh_link = grub_host_to_target32 (0);
   216         kx 	shdr->sh_info = grub_host_to_target32 (0);
   216         kx 	shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
   216         kx 	shdr->sh_entsize = grub_host_to_target32 (0);
   216         kx 	shdr++;
   216         kx       }
   216         kx   }
   216         kx 
   216         kx   free (*core_img);
   216         kx   *core_img = elf_img;
   216         kx   *core_size = program_size + header_size + footer_size;
   216         kx }
   216         kx 
   216         kx /* Relocate symbols; note that this function overwrites the symbol table.
   216         kx    Return the address of a start symbol.  */
   216         kx static Elf_Addr
   216         kx SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd,
   216         kx 			   void *jumpers, Elf_Addr jumpers_addr,
   216         kx 			   Elf_Addr bss_start, Elf_Addr end,
   216         kx 			   const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   Elf_Word symtab_size, sym_size, num_syms;
   216         kx   Elf_Off symtab_offset;
   216         kx   Elf_Addr start_address = (Elf_Addr) -1;
   216         kx   Elf_Sym *sym;
   216         kx   Elf_Word i;
   216         kx   Elf_Shdr *symtab_section;
   216         kx   const char *symtab;
   216         kx   grub_uint64_t *jptr = jumpers;
   216         kx 
   216         kx   symtab_section = (Elf_Shdr *) ((char *) smd->sections
   216         kx 				 + grub_target_to_host32 (smd->symtab->sh_link)
   216         kx 				   * smd->section_entsize);
   216         kx   symtab = (char *) e + grub_target_to_host (symtab_section->sh_offset);
   216         kx 
   216         kx   symtab_size = grub_target_to_host (smd->symtab->sh_size);
   216         kx   sym_size = grub_target_to_host (smd->symtab->sh_entsize);
   216         kx   symtab_offset = grub_target_to_host (smd->symtab->sh_offset);
   216         kx   num_syms = symtab_size / sym_size;
   216         kx 
   216         kx   for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
   216         kx        i < num_syms;
   216         kx        i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
   216         kx     {
   216         kx       Elf_Section cur_index;
   216         kx       const char *name;
   216         kx 
   216         kx       name = symtab + grub_target_to_host32 (sym->st_name);
   216         kx 
   216         kx       cur_index = grub_target_to_host16 (sym->st_shndx);
   216         kx       if (cur_index == STN_ABS)
   216         kx         {
   216         kx           continue;
   216         kx         }
   216         kx       else if (cur_index == STN_UNDEF)
   216         kx 	{
   216         kx 	  if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
   216         kx 	    sym->st_value = bss_start;
   216         kx 	  else if (sym->st_name && grub_strcmp (name, "_end") == 0)
   216         kx 	    sym->st_value = end;
   216         kx 	  else if (sym->st_name)
   216         kx 	    grub_util_error ("undefined symbol %s", name);
   216         kx 	  else
   216         kx 	    continue;
   216         kx 	}
   216         kx       else if (cur_index >= smd->num_sections)
   216         kx 	grub_util_error ("section %d does not exist", cur_index);
   216         kx       else
   216         kx 	{
   216         kx 	  sym->st_value = (grub_target_to_host (sym->st_value)
   216         kx 			   + smd->vaddrs[cur_index]);
   216         kx 	}
   216         kx 
   216         kx       if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
   216         kx 	  == STT_FUNC)
   216         kx 	{
   216         kx 	  *jptr = grub_host_to_target64 (sym->st_value);
   216         kx 	  sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
   216         kx 	  jptr++;
   216         kx 	  *jptr = 0;
   216         kx 	  jptr++;
   216         kx 	}
   216         kx       grub_util_info ("locating %s at 0x%"  GRUB_HOST_PRIxLONG_LONG
   216         kx 		      " (0x%"  GRUB_HOST_PRIxLONG_LONG ")", name,
   216         kx 		      (unsigned long long) sym->st_value,
   216         kx 		      (unsigned long long) smd->vaddrs[cur_index]);
   216         kx 
   216         kx       if (start_address == (Elf_Addr)-1)
   216         kx 	if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
   216         kx 	  start_address = sym->st_value;
   216         kx     }
   216         kx 
   216         kx   return start_address;
   216         kx }
   216         kx 
   216         kx /* Return the address of a symbol at the index I in the section S.  */
   216         kx static Elf_Addr
   216         kx SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
   216         kx 			     const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   Elf_Sym *sym;
   216         kx 
   216         kx   sym = (Elf_Sym *) ((char *) e
   216         kx 		       + grub_target_to_host (s->sh_offset)
   216         kx 		       + i * grub_target_to_host (s->sh_entsize));
   216         kx   return sym->st_value;
   216         kx }
   216         kx 
   216         kx /* Return the address of a modified value.  */
   216         kx static Elf_Addr *
   216         kx SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
   216         kx 		    const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
   216         kx }
   216         kx 
   216         kx #ifdef MKIMAGE_ELF64
   216         kx static Elf_Addr
   216         kx SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
   216         kx 		      const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   Elf_Word symtab_size, sym_size, num_syms;
   216         kx   Elf_Off symtab_offset;
   216         kx   Elf_Sym *sym;
   216         kx   Elf_Word i;
   216         kx   int ret = 0;
   216         kx 
   216         kx   symtab_size = grub_target_to_host (symtab_section->sh_size);
   216         kx   sym_size = grub_target_to_host (symtab_section->sh_entsize);
   216         kx   symtab_offset = grub_target_to_host (symtab_section->sh_offset);
   216         kx   num_syms = symtab_size / sym_size;
   216         kx 
   216         kx   for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
   216         kx        i < num_syms;
   216         kx        i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
   216         kx     if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
   216         kx       ret++;
   216         kx 
   216         kx   return ret;
   216         kx }
   216         kx #endif
   216         kx 
   216         kx #ifdef MKIMAGE_ELF32
   216         kx /* Deal with relocation information. This function relocates addresses
   216         kx    within the virtual address space starting from 0. So only relative
   216         kx    addresses can be fully resolved. Absolute addresses must be relocated
   216         kx    again by a PE32 relocator when loaded.  */
   216         kx static grub_size_t
   216         kx arm_get_trampoline_size (Elf_Ehdr *e,
   216         kx 			 Elf_Shdr *sections,
   216         kx 			 Elf_Half section_entsize,
   216         kx 			 Elf_Half num_sections,
   216         kx 			 const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   Elf_Half i;
   216         kx   Elf_Shdr *s;
   216         kx   grub_size_t ret = 0;
   216         kx 
   216         kx   for (i = 0, s = sections;
   216         kx        i < num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
   216         kx     if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
   216         kx         (s->sh_type == grub_host_to_target32 (SHT_RELA)))
   216         kx       {
   216         kx 	Elf_Rela *r;
   216         kx 	Elf_Word rtab_size, r_size, num_rs;
   216         kx 	Elf_Off rtab_offset;
   216         kx 	Elf_Shdr *symtab_section;
   216         kx 	Elf_Word j;
   216         kx 
   216         kx 	symtab_section = (Elf_Shdr *) ((char *) sections
   216         kx 					 + (grub_target_to_host32 (s->sh_link)
   216         kx 					    * section_entsize));
   216         kx 
   216         kx 	rtab_size = grub_target_to_host (s->sh_size);
   216         kx 	r_size = grub_target_to_host (s->sh_entsize);
   216         kx 	rtab_offset = grub_target_to_host (s->sh_offset);
   216         kx 	num_rs = rtab_size / r_size;
   216         kx 
   216         kx 	for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
   216         kx 	     j < num_rs;
   216         kx 	     j++, r = (Elf_Rela *) ((char *) r + r_size))
   216         kx 	  {
   216         kx             Elf_Addr info;
   216         kx 	    Elf_Addr sym_addr;
   216         kx 
   216         kx 	    info = grub_target_to_host (r->r_info);
   216         kx 	    sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
   216         kx 						    ELF_R_SYM (info), image_target);
   216         kx 
   216         kx             sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
   216         kx 	      grub_target_to_host (r->r_addend) : 0;
   216         kx 
   216         kx 	    switch (ELF_R_TYPE (info))
   216         kx 	      {
   216         kx 	      case R_ARM_ABS32:
   216         kx 	      case R_ARM_V4BX:
   216         kx 		break;
   216         kx 	      case R_ARM_THM_CALL:
   216         kx 	      case R_ARM_THM_JUMP24:
   216         kx 	      case R_ARM_THM_JUMP19:
   216         kx 		if (!(sym_addr & 1))
   216         kx 		  ret += 8;
   216         kx 		break;
   216         kx 
   216         kx 	      case R_ARM_CALL:
   216         kx 	      case R_ARM_JUMP24:
   216         kx 		if (sym_addr & 1)
   216         kx 		  ret += 16;
   216         kx 		break;
   216         kx 
   216         kx 	      default:
   216         kx 		grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 				 (unsigned int) ELF_R_TYPE (info));
   216         kx 		break;
   216         kx 	      }
   216         kx 	  }
   216         kx       }
   216         kx   return ret;
   216         kx }
   216         kx #endif
   216         kx 
   216         kx static int
   216         kx SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target);
   216         kx static int
   216         kx SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
   216         kx 				struct section_metadata *smd);
   216         kx 
   216         kx /* Deal with relocation information. This function relocates addresses
   216         kx    within the virtual address space starting from 0. So only relative
   216         kx    addresses can be fully resolved. Absolute addresses must be relocated
   216         kx    again by a PE32 relocator when loaded.  */
   216         kx static void
   216         kx SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
   216         kx 			     char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off,
   216         kx 			     const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   Elf_Half i;
   216         kx   Elf_Shdr *s;
   216         kx #ifdef MKIMAGE_ELF64
   216         kx   struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
   216         kx   grub_uint64_t *gpptr = (void *) (pe_target + got_off);
   216         kx   unsigned unmatched_adr_got_page = 0;
   216         kx #define MASK19 ((1 << 19) - 1)
   216         kx #else
   216         kx   grub_uint32_t *tr = (void *) (pe_target + tramp_off);
   216         kx #endif
   216         kx 
   216         kx   for (i = 0, s = smd->sections;
   216         kx        i < smd->num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
   216         kx     if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
   216         kx         (s->sh_type == grub_host_to_target32 (SHT_RELA)))
   216         kx       {
   216         kx 	Elf_Rela *r;
   216         kx 	Elf_Word rtab_size, r_size, num_rs;
   216         kx 	Elf_Off rtab_offset;
   216         kx 	Elf_Word target_section_index;
   216         kx 	Elf_Addr target_section_addr;
   216         kx 	Elf_Shdr *target_section;
   216         kx 	Elf_Word j;
   216         kx 
   216         kx 	if (!SUFFIX (is_kept_section) (s, image_target) &&
   216         kx 	    !SUFFIX (is_kept_reloc_section) (s, image_target, smd))
   216         kx 	  {
   216         kx 	    grub_util_info ("not translating relocations for omitted section %s",
   216         kx 			smd->strtab + grub_le_to_cpu32 (s->sh_name));
   216         kx 	    continue;
   216         kx 	  }
   216         kx 
   216         kx 	target_section_index = grub_target_to_host32 (s->sh_info);
   216         kx 	target_section_addr = smd->addrs[target_section_index];
   216         kx 	target_section = (Elf_Shdr *) ((char *) smd->sections
   216         kx 					 + (target_section_index
   216         kx 					    * smd->section_entsize));
   216         kx 
   216         kx 	grub_util_info ("dealing with the relocation section %s for %s",
   216         kx 			smd->strtab + grub_target_to_host32 (s->sh_name),
   216         kx 			smd->strtab + grub_target_to_host32 (target_section->sh_name));
   216         kx 
   216         kx 	rtab_size = grub_target_to_host (s->sh_size);
   216         kx 	r_size = grub_target_to_host (s->sh_entsize);
   216         kx 	rtab_offset = grub_target_to_host (s->sh_offset);
   216         kx 	num_rs = rtab_size / r_size;
   216         kx 
   216         kx 	for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
   216         kx 	     j < num_rs;
   216         kx 	     j++, r = (Elf_Rela *) ((char *) r + r_size))
   216         kx 	  {
   216         kx             Elf_Addr info;
   216         kx 	    Elf_Addr offset;
   216         kx 	    Elf_Addr sym_addr;
   216         kx 	    Elf_Addr *target;
   216         kx 	    Elf_Addr addend;
   216         kx 
   216         kx 	    offset = grub_target_to_host (r->r_offset);
   216         kx 	    target = SUFFIX (get_target_address) (e, target_section,
   216         kx 						  offset, image_target);
   216         kx 	    info = grub_target_to_host (r->r_info);
   216         kx 	    sym_addr = SUFFIX (get_symbol_address) (e, smd->symtab,
   216         kx 						    ELF_R_SYM (info), image_target);
   216         kx 
   216         kx             addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
   216         kx 	      grub_target_to_host (r->r_addend) : 0;
   216         kx 
   216         kx 	   switch (image_target->elf_target)
   216         kx 	     {
   216         kx 	     case EM_386:
   216         kx 	      switch (ELF_R_TYPE (info))
   216         kx 		{
   216         kx 		case R_386_NONE:
   216         kx 		  break;
   216         kx 
   216         kx 		case R_386_32:
   216         kx 		  /* This is absolute.  */
   216         kx 		  *target = grub_host_to_target32 (grub_target_to_host32 (*target)
   216         kx 						   + addend + sym_addr);
   216         kx 		  grub_util_info ("relocating an R_386_32 entry to 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG,
   216         kx 				  (unsigned long long) *target,
   216         kx 				  (unsigned long long) offset);
   216         kx 		  break;
   216         kx 
   216         kx 		case R_386_PC32:
   216         kx 		  /* This is relative.  */
   216         kx 		  *target = grub_host_to_target32 (grub_target_to_host32 (*target)
   216         kx 						   + addend + sym_addr
   216         kx 						   - target_section_addr - offset
   216         kx 						   - image_target->vaddr_offset);
   216         kx 		  grub_util_info ("relocating an R_386_PC32 entry to 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG,
   216         kx 				  (unsigned long long) *target,
   216         kx 				  (unsigned long long) offset);
   216         kx 		  break;
   216         kx 		default:
   216         kx 		  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 				   (unsigned int) ELF_R_TYPE (info));
   216         kx 		  break;
   216         kx 		}
   216         kx 	      break;
   216         kx #ifdef MKIMAGE_ELF64
   216         kx 	     case EM_X86_64:
   216         kx 	      switch (ELF_R_TYPE (info))
   216         kx 		{
   216         kx 
   216         kx 		case R_X86_64_NONE:
   216         kx 		  break;
   216         kx 
   216         kx 		case R_X86_64_64:
   216         kx 		  *target = grub_host_to_target64 (grub_target_to_host64 (*target)
   216         kx 						   + addend + sym_addr);
   216         kx 		  grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG,
   216         kx 				  (unsigned long long) *target,
   216         kx 				  (unsigned long long) offset);
   216         kx 		  break;
   216         kx 
   216         kx 		case R_X86_64_PC32:
   216         kx 		case R_X86_64_PLT32:
   216         kx 		  {
   216         kx 		    grub_uint32_t *t32 = (grub_uint32_t *) target;
   216         kx 		    *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
   216         kx 						  + addend + sym_addr
   216         kx 						  - target_section_addr - offset
   216         kx 						  - image_target->vaddr_offset);
   216         kx 		    grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
   216         kx 				    GRUB_HOST_PRIxLONG_LONG,
   216         kx 				    *t32, (unsigned long long) offset);
   216         kx 		    break;
   216         kx 		  }
   216         kx 
   216         kx 		case R_X86_64_PC64:
   216         kx 		  {
   216         kx 		    *target = grub_host_to_target64 (grub_target_to_host64 (*target)
   216         kx 						     + addend + sym_addr
   216         kx 						     - target_section_addr - offset
   216         kx 						     - image_target->vaddr_offset);
   216         kx 		    grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
   216         kx 				    GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
   216         kx 				    GRUB_HOST_PRIxLONG_LONG,
   216         kx 				    (unsigned long long) *target,
   216         kx 				    (unsigned long long) offset);
   216         kx 		    break;
   216         kx 		  }
   216         kx 
   216         kx 		case R_X86_64_32:
   216         kx 		case R_X86_64_32S:
   216         kx 		  {
   216         kx 		    grub_uint32_t *t32 = (grub_uint32_t *) target;
   216         kx 		    *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
   216         kx 						  + addend + sym_addr);
   216         kx 		    grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
   216         kx 				    GRUB_HOST_PRIxLONG_LONG,
   216         kx 				    *t32, (unsigned long long) offset);
   216         kx 		    break;
   216         kx 		  }
   216         kx 
   216         kx 		default:
   216         kx 		  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 				   (unsigned int) ELF_R_TYPE (info));
   216         kx 		  break;
   216         kx 		}
   216         kx 	      break;
   216         kx 	     case EM_IA_64:
   216         kx 	      switch (ELF_R_TYPE (info))
   216         kx 		{
   216         kx 		case R_IA64_PCREL21B:
   216         kx 		  {
   216         kx 		    grub_uint64_t noff;
   216         kx 		    grub_ia64_make_trampoline (tr, addend + sym_addr);
   216         kx 		    noff = ((char *) tr - (char *) pe_target
   216         kx 			    - target_section_addr - (offset & ~3)) >> 4;
   216         kx 		    tr++;
   216         kx 		    if (noff & ~MASK19)
   216         kx 		      grub_util_error ("trampoline offset too big (%"
   216         kx 				       GRUB_HOST_PRIxLONG_LONG ")",
   216         kx 				       (unsigned long long) noff);
   216         kx 		    grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
   216         kx 		  }
   216         kx 		  break;
   216         kx 
   216         kx 		case R_IA64_LTOFF22X:
   216         kx 		case R_IA64_LTOFF22:
   216         kx 		  {
   216         kx 		    Elf_Sym *sym;
   216         kx 
   216         kx 		    sym = (Elf_Sym *) ((char *) e
   216         kx 				       + grub_target_to_host (smd->symtab->sh_offset)
   216         kx 				       + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
   216         kx 		    if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
   216         kx 		      sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
   216         kx 									    + sym->st_value
   216         kx 									    - image_target->vaddr_offset));
   216         kx 		  }
   216         kx 		/* FALLTHROUGH */
   216         kx 		case R_IA64_LTOFF_FPTR22:
   216         kx 		  *gpptr = grub_host_to_target64 (addend + sym_addr);
   216         kx 		  grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
   216         kx 						  (char *) gpptr - (char *) pe_target
   216         kx 						  + image_target->vaddr_offset);
   216         kx 		  gpptr++;
   216         kx 		  break;
   216         kx 
   216         kx 		case R_IA64_GPREL22:
   216         kx 		  grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
   216         kx 						  addend + sym_addr);
   216         kx 		  break;
   216         kx 		case R_IA64_GPREL64I:
   216         kx 		  grub_ia64_set_immu64 ((grub_addr_t) target,
   216         kx 					addend + sym_addr);
   216         kx 		  break;
   216         kx 		case R_IA64_PCREL64LSB:
   216         kx 		  *target = grub_host_to_target64 (grub_target_to_host64 (*target)
   216         kx 						   + addend + sym_addr
   216         kx 						   - target_section_addr - offset
   216         kx 						   - image_target->vaddr_offset);
   216         kx 		  break;
   216         kx 
   216         kx 		case R_IA64_SEGREL64LSB:
   216         kx 		  *target = grub_host_to_target64 (grub_target_to_host64 (*target)
   216         kx 						   + addend + sym_addr - target_section_addr);
   216         kx 		  break;
   216         kx 		case R_IA64_DIR64LSB:
   216         kx 		case R_IA64_FPTR64LSB:
   216         kx 		  *target = grub_host_to_target64 (grub_target_to_host64 (*target)
   216         kx 						   + addend + sym_addr);
   216         kx 		  grub_util_info ("relocating a direct entry to 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
   216         kx 				  GRUB_HOST_PRIxLONG_LONG,
   216         kx 				  (unsigned long long)
   216         kx 				  grub_target_to_host64 (*target),
   216         kx 				  (unsigned long long) offset);
   216         kx 		  break;
   216         kx 
   216         kx 		  /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV.  */
   216         kx 		case R_IA64_LDXMOV:
   216         kx 		  break;
   216         kx 
   216         kx 		default:
   216         kx 		  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 				   (unsigned int) ELF_R_TYPE (info));
   216         kx 		  break;
   216         kx 		}
   216         kx 	       break;
   216         kx 	     case EM_AARCH64:
   216         kx 	       {
   216         kx 		 sym_addr += addend;
   216         kx 		 switch (ELF_R_TYPE (info))
   216         kx 		   {
   216         kx 		   case R_AARCH64_ABS64:
   216         kx 		     {
   216         kx 		       *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_AARCH64_PREL32:
   216         kx 		     {
   216         kx 		       grub_uint32_t *t32 = (grub_uint32_t *) target;
   216         kx 		       *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
   216         kx 						     + sym_addr
   216         kx 						     - target_section_addr - offset
   216         kx 						     - image_target->vaddr_offset);
   216         kx 		       grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
   216         kx 				       GRUB_HOST_PRIxLONG_LONG,
   216         kx 				       *t32, (unsigned long long) offset);
   216         kx 		       break;
   216         kx 		     }
   216         kx 		   case R_AARCH64_ADD_ABS_LO12_NC:
   216         kx 		     grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
   216         kx 					      sym_addr);
   216         kx 		     break;
   216         kx 		   case R_AARCH64_LDST64_ABS_LO12_NC:
   216         kx 		     grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
   216         kx 						     sym_addr);
   216         kx 		     break;
   216         kx 		   case R_AARCH64_JUMP26:
   216         kx 		   case R_AARCH64_CALL26:
   216         kx 		     {
   216         kx 		       sym_addr -= offset;
   216         kx 		       sym_addr -= target_section_addr + image_target->vaddr_offset;
   216         kx 		       if (!grub_arm_64_check_xxxx26_offset (sym_addr))
   216         kx 			 grub_util_error ("%s", "CALL26 Relocation out of range");
   216         kx 
   216         kx 		       grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
   216         kx 						     sym_addr);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_AARCH64_ADR_GOT_PAGE:
   216         kx 		     {
   216         kx 		       Elf64_Rela *rel2;
   216         kx 		       grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
   216         kx 			 - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
   216         kx 		       unsigned k;
   216         kx 		       *gpptr = grub_host_to_target64 (sym_addr);
   216         kx 		       unmatched_adr_got_page++;
   216         kx 		       if (!grub_arm64_check_hi21_signed (gpoffset))
   216         kx 			 grub_util_error ("HI21 out of range");
   216         kx 		       grub_arm64_set_hi21((grub_uint32_t *)target,
   216         kx 					   gpoffset);
   216         kx 		       for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
   216         kx 			    k < num_rs;
   216         kx 			    k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
   216         kx 			 if (ELF_R_SYM (rel2->r_info)
   216         kx 			     == ELF_R_SYM (r->r_info)
   216         kx 			     && r->r_addend == rel2->r_addend
   216         kx 			     && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
   216         kx 			   {
   216         kx 			     grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
   216         kx 													    grub_target_to_host (rel2->r_offset), image_target),
   216         kx 							     ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
   216         kx 			     break;
   216         kx 			   }
   216         kx 		       if (k >= num_rs)
   216         kx 			 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
   216         kx 		       gpptr++;
   216         kx 	             }
   216         kx 		     break;
   216         kx 		   case R_AARCH64_LD64_GOT_LO12_NC:
   216         kx 		     if (unmatched_adr_got_page == 0)
   216         kx 		       grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
   216         kx 		     unmatched_adr_got_page--;
   216         kx 		     break;
   216         kx 		   case R_AARCH64_ADR_PREL_PG_HI21:
   216         kx 		     {
   216         kx 		       sym_addr &= ~0xfffULL;
   216         kx 		       sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
   216         kx 		       if (!grub_arm64_check_hi21_signed (sym_addr))
   216         kx 			 grub_util_error ("%s", "CALL26 Relocation out of range");
   216         kx 
   216         kx 		       grub_arm64_set_hi21((grub_uint32_t *)target,
   216         kx 					   sym_addr);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   default:
   216         kx 		     grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 				      (unsigned int) ELF_R_TYPE (info));
   216         kx 		     break;
   216         kx 		   }
   216         kx 	       break;
   216         kx 	       }
   216         kx #endif
   216         kx #if defined(MKIMAGE_ELF32)
   216         kx 	     case EM_ARM:
   216         kx 	       {
   216         kx 		 sym_addr += addend;
   216         kx 		 sym_addr -= image_target->vaddr_offset;
   216         kx 		 switch (ELF_R_TYPE (info))
   216         kx 		   {
   216         kx 		   case R_ARM_ABS32:
   216         kx 		     {
   216         kx 		       grub_util_info ("  ABS32:\toffset=%d\t(0x%08x)",
   216         kx 				       (int) sym_addr, (int) sym_addr);
   216         kx 		       /* Data will be naturally aligned */
   216         kx 		       if (image_target->id == IMAGE_EFI)
   216         kx 			 sym_addr += GRUB_PE32_SECTION_ALIGNMENT;
   216         kx 		       *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		     /* Happens when compiled with -march=armv4.
   216         kx 			Since currently we need at least armv5, keep bx as-is.
   216         kx 		     */
   216         kx 		   case R_ARM_V4BX:
   216         kx 		     break;
   216         kx 		   case R_ARM_THM_CALL:
   216         kx 		   case R_ARM_THM_JUMP24:
   216         kx 		   case R_ARM_THM_JUMP19:
   216         kx 		     {
   216         kx 		       grub_err_t err;
   216         kx 		       Elf_Sym *sym;
   216         kx 		       grub_util_info ("  THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
   216         kx 				       (unsigned long) ((char *) target
   216         kx 							- (char *) e),
   216         kx 				       sym_addr);
   216         kx 		       sym = (Elf_Sym *) ((char *) e
   216         kx 					  + grub_target_to_host (smd->symtab->sh_offset)
   216         kx 					  + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
   216         kx 		       if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
   216         kx 			 sym_addr |= 1;
   216         kx 		       if (!(sym_addr & 1))
   216         kx 			 {
   216         kx 			   grub_uint32_t tr_addr;
   216         kx 			   grub_int32_t new_offset;
   216         kx 			   tr_addr = (char *) tr - (char *) pe_target
   216         kx 			     - target_section_addr;
   216         kx 			   new_offset = sym_addr - tr_addr - 12;
   216         kx 
   216         kx 			   if (!grub_arm_jump24_check_offset (new_offset))
   216         kx 			     return grub_util_error ("jump24 relocation out of range");
   216         kx 
   216         kx 			   tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop  */
   216         kx 			   tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
   216         kx 			   tr += 2;
   216         kx 			   sym_addr = tr_addr | 1;
   216         kx 			 }
   216         kx 		       sym_addr -= offset;
   216         kx 		       /* Thumb instructions can be 16-bit aligned */
   216         kx 		       if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
   216         kx 			 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
   216         kx 		       else
   216         kx 			 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
   216         kx 							sym_addr);
   216         kx 		       if (err)
   216         kx 			 grub_util_error ("%s", grub_errmsg);
   216         kx 		     }
   216         kx 		     break;
   216         kx 
   216         kx 		   case R_ARM_CALL:
   216         kx 		   case R_ARM_JUMP24:
   216         kx 		     {
   216         kx 		       grub_err_t err;
   216         kx 		       grub_util_info ("  JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",  (unsigned long) ((char *) target - (char *) e), sym_addr);
   216         kx 		       if (sym_addr & 1)
   216         kx 			 {
   216         kx 			   grub_uint32_t tr_addr;
   216         kx 			   grub_int32_t new_offset;
   216         kx 			   tr_addr = (char *) tr - (char *) pe_target
   216         kx 			     - target_section_addr;
   216         kx 			   new_offset = sym_addr - tr_addr - 12;
   216         kx 
   216         kx 			   /* There is no immediate version of bx, only register one...  */
   216         kx 			   tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr	ip, [pc, #4] */
   216         kx 			   tr[1] = grub_host_to_target32 (0xe08cc00f); /* add	ip, ip, pc */
   216         kx 			   tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx	ip */
   216         kx 			   tr[3] = grub_host_to_target32 (new_offset | 1);
   216         kx 			   tr += 4;
   216         kx 			   sym_addr = tr_addr;
   216         kx 			 }
   216         kx 		       sym_addr -= offset;
   216         kx 		       err = grub_arm_reloc_jump24 (target,
   216         kx 						    sym_addr);
   216         kx 		       if (err)
   216         kx 			 grub_util_error ("%s", grub_errmsg);
   216         kx 		     }
   216         kx 		     break;
   216         kx 
   216         kx 		   default:
   216         kx 		     grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 				      (unsigned int) ELF_R_TYPE (info));
   216         kx 		     break;
   216         kx 		   }
   216         kx 		 break;
   216         kx 	       }
   216         kx #endif /* MKIMAGE_ELF32 */
   216         kx 	     case EM_RISCV:
   216         kx 	       {
   216         kx 		 grub_uint64_t *t64 = (grub_uint64_t *) target;
   216         kx 		 grub_uint32_t *t32 = (grub_uint32_t *) target;
   216         kx 		 grub_uint16_t *t16 = (grub_uint16_t *) target;
   216         kx 		 grub_uint8_t *t8 = (grub_uint8_t *) target;
   216         kx 		 grub_int64_t off;
   216         kx 
   216         kx 		 /*
   216         kx 		  * Instructions and instruction encoding are documented in the RISC-V
   216         kx 		  * specification. This file is based on version 2.2:
   216         kx 		  *
   216         kx 		  * https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf
   216         kx 		  */
   216         kx 
   216         kx 		 sym_addr += addend;
   216         kx 		 off = sym_addr - target_section_addr - offset - image_target->vaddr_offset;
   216         kx 
   216         kx 		 switch (ELF_R_TYPE (info))
   216         kx 		   {
   216         kx 		   case R_RISCV_ADD8:
   216         kx 		     *t8 = *t8 + sym_addr;
   216         kx 		     break;
   216         kx 		   case R_RISCV_ADD16:
   216         kx 		     *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) + sym_addr);
   216         kx 		     break;
   216         kx 		   case R_RISCV_32:
   216         kx 		   case R_RISCV_ADD32:
   216         kx 		     *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) + sym_addr);
   216         kx 		     break;
   216         kx 		   case R_RISCV_64:
   216         kx 		   case R_RISCV_ADD64:
   216         kx 		     *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
   216         kx 		     break;
   216         kx 
   216         kx 		   case R_RISCV_SUB8:
   216         kx 		     *t8 = sym_addr - *t8;
   216         kx 		     break;
   216         kx 		   case R_RISCV_SUB16:
   216         kx 		     *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) - sym_addr);
   216         kx 		     break;
   216         kx 		   case R_RISCV_SUB32:
   216         kx 		     *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) - sym_addr);
   216         kx 		     break;
   216         kx 		   case R_RISCV_SUB64:
   216         kx 		     *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) - sym_addr);
   216         kx 		     break;
   216         kx 		   case R_RISCV_BRANCH:
   216         kx 		     {
   216         kx 		       grub_uint32_t imm12 = (off & 0x1000) << (31 - 12);
   216         kx 		       grub_uint32_t imm11 = (off & 0x800) >> (11 - 7);
   216         kx 		       grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10);
   216         kx 		       grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4);
   216         kx 		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f)
   216         kx 						     | imm12 | imm11 | imm10_5 | imm4_1);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_JAL:
   216         kx 		     {
   216         kx 		       grub_uint32_t imm20 = (off & 0x100000) << (31 - 20);
   216         kx 		       grub_uint32_t imm19_12 = (off & 0xff000);
   216         kx 		       grub_uint32_t imm11 = (off & 0x800) << (20 - 11);
   216         kx 		       grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10);
   216         kx 		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff)
   216         kx 						     | imm20 | imm19_12 | imm11 | imm10_1);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_CALL:
   216         kx 		   case R_RISCV_CALL_PLT:
   216         kx 		     {
   216         kx 		       grub_uint32_t hi20, lo12;
   216         kx 
   216         kx 		       if (off != (grub_int32_t)off)
   216         kx 			 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
   216         kx 
   216         kx 		       hi20 = (off + 0x800) & 0xfffff000;
   216         kx 		       lo12 = (off - hi20) & 0xfff;
   216         kx 		       t32[0] = grub_host_to_target32 ((grub_target_to_host32 (t32[0]) & 0xfff) | hi20);
   216         kx 		       t32[1] = grub_host_to_target32 ((grub_target_to_host32 (t32[1]) & 0xfffff) | (lo12 << 20));
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_RVC_BRANCH:
   216         kx 		     {
   216         kx 		       grub_uint16_t imm8 = (off & 0x100) << (12 - 8);
   216         kx 		       grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5);
   216         kx 		       grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
   216         kx 		       grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5);
   216         kx 		       grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10);
   216         kx 		       *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe383)
   216         kx 						     | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_RVC_JUMP:
   216         kx 		     {
   216         kx 		       grub_uint16_t imm11 = (off & 0x800) << (12 - 11);
   216         kx 		       grub_uint16_t imm10 = (off & 0x400) >> (10 - 8);
   216         kx 		       grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11);
   216         kx 		       grub_uint16_t imm7 = (off & 0x80) >> (7 - 6);
   216         kx 		       grub_uint16_t imm6 = (off & 0x40) << (12 - 11);
   216         kx 		       grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
   216         kx 		       grub_uint16_t imm4 = (off & 0x10) << (12 - 5);
   216         kx 		       grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10);
   216         kx 		       *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe003)
   216         kx 						     | imm11 | imm10 | imm9_8 | imm7 | imm6
   216         kx 						     | imm5 | imm4 | imm3_1);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_PCREL_HI20:
   216         kx 		     {
   216         kx 		       grub_int32_t hi20;
   216         kx 
   216         kx 		       if (off != (grub_int32_t)off)
   216         kx 			 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
   216         kx 
   216         kx 		       hi20 = (off + 0x800) & 0xfffff000;
   216         kx 		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | hi20);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_PCREL_LO12_I:
   216         kx 		   case R_RISCV_PCREL_LO12_S:
   216         kx 		     {
   216         kx 		       Elf_Rela *rel2;
   216         kx 		       Elf_Word k;
   216         kx 		       /* Search backwards for matching HI20 reloc.  */
   216         kx 		       for (k = j, rel2 = (Elf_Rela *) ((char *) r - r_size);
   216         kx 			    k > 0;
   216         kx 			    k--, rel2 = (Elf_Rela *) ((char *) rel2 - r_size))
   216         kx 			 {
   216         kx 			   Elf_Addr rel2_info;
   216         kx 			   Elf_Addr rel2_offset;
   216         kx 			   Elf_Addr rel2_sym_addr;
   216         kx 			   Elf_Addr rel2_addend;
   216         kx 			   Elf_Addr rel2_loc;
   216         kx 			   grub_int64_t rel2_off;
   216         kx 
   216         kx 			   rel2_offset = grub_target_to_host (rel2->r_offset);
   216         kx 			   rel2_info = grub_target_to_host (rel2->r_info);
   216         kx 			   rel2_loc = target_section_addr + rel2_offset + image_target->vaddr_offset;
   216         kx 
   216         kx 			   if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20
   216         kx 			       && rel2_loc == sym_addr)
   216         kx 			     {
   216         kx 			       rel2_sym_addr = SUFFIX (get_symbol_address)
   216         kx 				 (e, smd->symtab, ELF_R_SYM (rel2_info),
   216         kx 				  image_target);
   216         kx 			       rel2_addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
   216         kx 				 grub_target_to_host (rel2->r_addend) : 0;
   216         kx 			       rel2_off = rel2_sym_addr + rel2_addend - rel2_loc;
   216         kx 			       off = rel2_off - ((rel2_off + 0x800) & 0xfffff000);
   216         kx 
   216         kx 			       if (ELF_R_TYPE (info) == R_RISCV_PCREL_LO12_I)
   216         kx 				 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | (off & 0xfff) << 20);
   216         kx 			       else
   216         kx 				 {
   216         kx 				   grub_uint32_t imm11_5 = (off & 0xfe0) << (31 - 11);
   216         kx 				   grub_uint32_t imm4_0 = (off & 0x1f) << (11 - 4);
   216         kx 				   *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
   216         kx 				 }
   216         kx 			       break;
   216         kx 			     }
   216         kx 			 }
   216         kx 		       if (k == 0)
   216         kx 			 grub_util_error ("cannot find matching HI20 relocation");
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_HI20:
   216         kx 		     *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | (((grub_int32_t) sym_addr + 0x800) & 0xfffff000));
   216         kx 		     break;
   216         kx 		   case R_RISCV_LO12_I:
   216         kx 		     {
   216         kx 		       grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
   216         kx 		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | ((lo12 & 0xfff) << 20));
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_LO12_S:
   216         kx 		     {
   216         kx 		       grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
   216         kx 		       grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11);
   216         kx 		       grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4);
   216         kx 		       *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
   216         kx 		     }
   216         kx 		     break;
   216         kx 		   case R_RISCV_RELAX:
   216         kx 		     break;
   216         kx 		   default:
   216         kx 		     grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 				      (unsigned int) ELF_R_TYPE (info));
   216         kx 		     break;
   216         kx 		   }
   216         kx 	       break;
   216         kx 	       }
   216         kx 	     default:
   216         kx 	       grub_util_error ("unknown architecture type %d",
   216         kx 				image_target->elf_target);
   216         kx 	     }
   216         kx 	  }
   216         kx       }
   216         kx }
   216         kx 
   216         kx /* Add a PE32's fixup entry for a relocation. Return the resulting address
   216         kx    after having written to the file OUT.  */
   216         kx static Elf_Addr
   216         kx add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
   216         kx 		 Elf_Addr addr, int flush, Elf_Addr current_address,
   216         kx 		 const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   struct grub_pe32_fixup_block *b;
   216         kx 
   216         kx   b = &((*cblock)->b);
   216         kx 
   216         kx   /* First, check if it is necessary to write out the current block.  */
   216         kx   if ((*cblock)->state)
   216         kx     {
   216         kx       if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
   216         kx 	{
   216         kx 	  grub_uint32_t size;
   216         kx 
   216         kx 	  if (flush)
   216         kx 	    {
   216         kx 	      /* Add as much padding as necessary to align the address
   216         kx 		 with a section boundary.  */
   216         kx 	      Elf_Addr next_address;
   216         kx 	      unsigned padding_size;
   216         kx               size_t cur_index;
   216         kx 
   216         kx 	      next_address = current_address + b->block_size;
   216         kx 	      padding_size = ((ALIGN_UP (next_address, image_target->section_align)
   216         kx 			       - next_address)
   216         kx 			      >> 1);
   216         kx               cur_index = ((b->block_size - sizeof (*b)) >> 1);
   216         kx               grub_util_info ("adding %d padding fixup entries", padding_size);
   216         kx 	      while (padding_size--)
   216         kx 		{
   216         kx 		  b->entries[cur_index++] = 0;
   216         kx 		  b->block_size += 2;
   216         kx 		}
   216         kx 	    }
   216         kx           else while (b->block_size & (8 - 1))
   216         kx             {
   216         kx 	      /* If not aligned with a 32-bit boundary, add
   216         kx 		 a padding entry.  */
   216         kx               size_t cur_index;
   216         kx 
   216         kx               grub_util_info ("adding a padding fixup entry");
   216         kx               cur_index = ((b->block_size - sizeof (*b)) >> 1);
   216         kx               b->entries[cur_index] = 0;
   216         kx               b->block_size += 2;
   216         kx             }
   216         kx 
   216         kx           /* Flush it.  */
   216         kx           grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
   216         kx                           b->block_size, b->page_rva);
   216         kx           size = b->block_size;
   216         kx 	  current_address += size;
   216         kx 	  b->page_rva = grub_host_to_target32 (b->page_rva);
   216         kx 	  b->block_size = grub_host_to_target32 (b->block_size);
   216         kx 	  (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
   216         kx 	  memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
   216         kx 	  *cblock = (*cblock)->next;
   216         kx 	}
   216         kx     }
   216         kx 
   216         kx   b = &((*cblock)->b);
   216         kx 
   216         kx   if (! flush)
   216         kx     {
   216         kx       grub_uint16_t entry;
   216         kx       size_t cur_index;
   216         kx 
   216         kx       /* If not allocated yet, allocate a block with enough entries.  */
   216         kx       if (! (*cblock)->state)
   216         kx 	{
   216         kx 	  (*cblock)->state = 1;
   216         kx 
   216         kx 	  /* The spec does not mention the requirement of a Page RVA.
   216         kx 	     Here, align the address with a 4K boundary for safety.  */
   216         kx 	  b->page_rva = (addr & ~(0x1000 - 1));
   216         kx 	  b->block_size = sizeof (*b);
   216         kx 	}
   216         kx 
   216         kx       /* Sanity check.  */
   216         kx       if (b->block_size >= sizeof (*b) + 2 * 0x1000)
   216         kx 	grub_util_error ("too many fixup entries");
   216         kx 
   216         kx       /* Add a new entry.  */
   216         kx       cur_index = ((b->block_size - sizeof (*b)) >> 1);
   216         kx       entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
   216         kx       b->entries[cur_index] = grub_host_to_target16 (entry);
   216         kx       b->block_size += 2;
   216         kx     }
   216         kx 
   216         kx   return current_address;
   216         kx }
   216         kx 
   216         kx struct raw_reloc
   216         kx {
   216         kx   struct raw_reloc *next;
   216         kx   grub_uint32_t offset;
   216         kx   enum raw_reloc_type {
   216         kx     RAW_RELOC_NONE = -1,
   216         kx     RAW_RELOC_32 = 0,
   216         kx     RAW_RELOC_MAX = 1,
   216         kx   } type;
   216         kx };
   216         kx 
   216         kx struct translate_context
   216         kx {
   216         kx   /* PE */
   216         kx   struct fixup_block_list *lst, *lst0;
   216         kx   Elf_Addr current_address;
   216         kx 
   216         kx   /* Raw */
   216         kx   struct raw_reloc *raw_relocs;
   216         kx };
   216         kx 
   216         kx static void
   216         kx translate_reloc_start (struct translate_context *ctx,
   216         kx 		       const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   grub_memset (ctx, 0, sizeof (*ctx));
   216         kx   if (image_target->id == IMAGE_EFI)
   216         kx     {
   216         kx       ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
   216         kx       memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
   216         kx       ctx->current_address = 0;
   216         kx     }
   216         kx }
   216         kx 
   216         kx static void
   216         kx translate_relocation_pe (struct translate_context *ctx,
   216         kx 			 Elf_Addr addr,
   216         kx 			 Elf_Addr info,
   216         kx 			 const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   /* Necessary to relocate only absolute addresses.  */
   216         kx   switch (image_target->elf_target)
   216         kx     {
   216         kx     case EM_386:
   216         kx       if (ELF_R_TYPE (info) == R_386_32)
   216         kx 	{
   216         kx 	  grub_util_info ("adding a relocation entry for 0x%"
   216         kx 			  GRUB_HOST_PRIxLONG_LONG,
   216         kx 			  (unsigned long long) addr);
   216         kx 	  ctx->current_address
   216         kx 	    = add_fixup_entry (&ctx->lst,
   216         kx 			       GRUB_PE32_REL_BASED_HIGHLOW,
   216         kx 			       addr, 0, ctx->current_address,
   216         kx 			       image_target);
   216         kx 	}
   216         kx       break;
   216         kx     case EM_X86_64:
   216         kx       if ((ELF_R_TYPE (info) == R_X86_64_32) ||
   216         kx 	  (ELF_R_TYPE (info) == R_X86_64_32S))
   216         kx 	{
   216         kx 	  grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
   216         kx 	}
   216         kx       else if (ELF_R_TYPE (info) == R_X86_64_64)
   216         kx 	{
   216         kx 	  grub_util_info ("adding a relocation entry for 0x%"
   216         kx 			  GRUB_HOST_PRIxLONG_LONG,
   216         kx 			  (unsigned long long) addr);
   216         kx 	  ctx->current_address
   216         kx 	    = add_fixup_entry (&ctx->lst,
   216         kx 			       GRUB_PE32_REL_BASED_DIR64,
   216         kx 			       addr,
   216         kx 			       0, ctx->current_address,
   216         kx 			       image_target);
   216         kx 	}
   216         kx       break;
   216         kx     case EM_IA_64:
   216         kx       switch (ELF_R_TYPE (info))
   216         kx 	{
   216         kx 	case R_IA64_PCREL64LSB:
   216         kx 	case R_IA64_LDXMOV:
   216         kx 	case R_IA64_PCREL21B:
   216         kx 	case R_IA64_LTOFF_FPTR22:
   216         kx 	case R_IA64_LTOFF22X:
   216         kx 	case R_IA64_LTOFF22:
   216         kx 	case R_IA64_GPREL22:
   216         kx 	case R_IA64_GPREL64I:
   216         kx 	case R_IA64_SEGREL64LSB:
   216         kx 	  break;
   216         kx 
   216         kx 	case R_IA64_FPTR64LSB:
   216         kx 	case R_IA64_DIR64LSB:
   216         kx #if 1
   216         kx 	  {
   216         kx 	    grub_util_info ("adding a relocation entry for 0x%"
   216         kx 			    GRUB_HOST_PRIxLONG_LONG,
   216         kx 			    (unsigned long long) addr);
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_DIR64,
   216         kx 				 addr,
   216         kx 				 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx #endif
   216         kx 	  break;
   216         kx 	default:
   216         kx 	  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 			   (unsigned int) ELF_R_TYPE (info));
   216         kx 	  break;
   216         kx 	}
   216         kx       break;
   216         kx     case EM_AARCH64:
   216         kx       switch (ELF_R_TYPE (info))
   216         kx 	{
   216         kx 	case R_AARCH64_ABS64:
   216         kx 	  {
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_DIR64,
   216         kx 				 addr, 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	  /* Relative relocations do not require fixup entries. */
   216         kx 	case R_AARCH64_CALL26:
   216         kx 	case R_AARCH64_JUMP26:
   216         kx 	case R_AARCH64_PREL32:
   216         kx 	  break;
   216         kx 	  /* Page-relative relocations do not require fixup entries. */
   216         kx 	case R_AARCH64_ADR_PREL_PG_HI21:
   216         kx 	  /* We page-align the whole kernel, so no need
   216         kx 	     for fixup entries.
   216         kx 	  */
   216         kx 	case R_AARCH64_ADD_ABS_LO12_NC:
   216         kx 	case R_AARCH64_LDST64_ABS_LO12_NC:
   216         kx 	  break;
   216         kx 
   216         kx 	  /* GOT is relocated separately.  */
   216         kx 	case R_AARCH64_ADR_GOT_PAGE:
   216         kx 	case R_AARCH64_LD64_GOT_LO12_NC:
   216         kx 	  break;
   216         kx 
   216         kx 	default:
   216         kx 	  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 			   (unsigned int) ELF_R_TYPE (info));
   216         kx 	  break;
   216         kx 	}
   216         kx       break;
   216         kx       break;
   216         kx #if defined(MKIMAGE_ELF32)
   216         kx     case EM_ARM:
   216         kx       switch (ELF_R_TYPE (info))
   216         kx 	{
   216         kx 	case R_ARM_V4BX:
   216         kx 	  /* Relative relocations do not require fixup entries. */
   216         kx 	case R_ARM_JUMP24:
   216         kx 	case R_ARM_THM_CALL:
   216         kx 	case R_ARM_THM_JUMP19:
   216         kx 	case R_ARM_THM_JUMP24:
   216         kx 	case R_ARM_CALL:
   216         kx 	  {
   216         kx 	    grub_util_info ("  %s:  not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	  /* Create fixup entry for PE/COFF loader */
   216         kx 	case R_ARM_ABS32:
   216         kx 	  {
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_HIGHLOW,
   216         kx 				 addr, 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	default:
   216         kx 	  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 			   (unsigned int) ELF_R_TYPE (info));
   216         kx 	  break;
   216         kx 	}
   216         kx       break;
   216         kx #endif /* defined(MKIMAGE_ELF32) */
   216         kx     case EM_RISCV:
   216         kx       switch (ELF_R_TYPE (info))
   216         kx 	{
   216         kx 	case R_RISCV_32:
   216         kx 	  {
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_HIGHLOW,
   216         kx 				 addr, 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	case R_RISCV_64:
   216         kx 	  {
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_DIR64,
   216         kx 				 addr, 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	  /* Relative relocations do not require fixup entries. */
   216         kx 	case R_RISCV_BRANCH:
   216         kx 	case R_RISCV_JAL:
   216         kx 	case R_RISCV_CALL:
   216         kx 	case R_RISCV_CALL_PLT:
   216         kx 	case R_RISCV_PCREL_HI20:
   216         kx 	case R_RISCV_PCREL_LO12_I:
   216         kx 	case R_RISCV_PCREL_LO12_S:
   216         kx 	case R_RISCV_RVC_BRANCH:
   216         kx 	case R_RISCV_RVC_JUMP:
   216         kx 	case R_RISCV_ADD32:
   216         kx 	case R_RISCV_SUB32:
   216         kx 	  grub_util_info ("  %s:  not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
   216         kx 	  break;
   216         kx 	case R_RISCV_HI20:
   216         kx 	  {
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_RISCV_HI20,
   216         kx 				 addr, 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	case R_RISCV_LO12_I:
   216         kx 	  {
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_RISCV_LOW12I,
   216         kx 				 addr, 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	case R_RISCV_LO12_S:
   216         kx 	  {
   216         kx 	    ctx->current_address
   216         kx 	      = add_fixup_entry (&ctx->lst,
   216         kx 				 GRUB_PE32_REL_BASED_RISCV_LOW12S,
   216         kx 				 addr, 0, ctx->current_address,
   216         kx 				 image_target);
   216         kx 	  }
   216         kx 	  break;
   216         kx 	case R_RISCV_RELAX:
   216         kx 	  break;
   216         kx 	default:
   216         kx 	  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 			   (unsigned int) ELF_R_TYPE (info));
   216         kx 	  break;
   216         kx 	}
   216         kx       break;
   216         kx     default:
   216         kx       grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
   216         kx     }
   216         kx }
   216         kx 
   216         kx static enum raw_reloc_type
   216         kx classify_raw_reloc (Elf_Addr info,
   216         kx 		    const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx     /* Necessary to relocate only absolute addresses.  */
   216         kx   switch (image_target->elf_target)
   216         kx     {
   216         kx     case EM_ARM:
   216         kx       switch (ELF_R_TYPE (info))
   216         kx 	{
   216         kx 	case R_ARM_V4BX:
   216         kx 	case R_ARM_JUMP24:
   216         kx 	case R_ARM_THM_CALL:
   216         kx 	case R_ARM_THM_JUMP19:
   216         kx 	case R_ARM_THM_JUMP24:
   216         kx 	case R_ARM_CALL:
   216         kx 	  return RAW_RELOC_NONE;
   216         kx 	case R_ARM_ABS32:
   216         kx 	  return RAW_RELOC_32;
   216         kx 	default:
   216         kx 	  grub_util_error (_("relocation 0x%x is not implemented yet"),
   216         kx 			   (unsigned int) ELF_R_TYPE (info));
   216         kx 	  break;
   216         kx 	}
   216         kx       break;
   216         kx     default:
   216         kx       grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
   216         kx     }
   216         kx }
   216         kx 
   216         kx static void
   216         kx translate_relocation_raw (struct translate_context *ctx,
   216         kx 			  Elf_Addr addr,
   216         kx 			  Elf_Addr info,
   216         kx 			  const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   enum raw_reloc_type class = classify_raw_reloc (info, image_target);
   216         kx   struct raw_reloc *rel;
   216         kx   if (class == RAW_RELOC_NONE)
   216         kx     return;
   216         kx   rel = xmalloc (sizeof (*rel));
   216         kx   rel->next = ctx->raw_relocs;
   216         kx   rel->type = class;
   216         kx   rel->offset = addr;
   216         kx   ctx->raw_relocs = rel;
   216         kx }
   216         kx 
   216         kx static void
   216         kx translate_relocation (struct translate_context *ctx,
   216         kx 		      Elf_Addr addr,
   216         kx 		      Elf_Addr info,
   216         kx 		      const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   if (image_target->id == IMAGE_EFI)
   216         kx     translate_relocation_pe (ctx, addr, info, image_target);
   216         kx   else
   216         kx     translate_relocation_raw (ctx, addr, info, image_target);
   216         kx }
   216         kx 
   216         kx static void
   216         kx finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
   216         kx 			     const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
   216         kx 
   216         kx   {
   216         kx     grub_uint8_t *ptr;
   216         kx     layout->reloc_section = ptr = xmalloc (ctx->current_address);
   216         kx     for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
   216         kx       if (ctx->lst->state)
   216         kx 	{
   216         kx 	  memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
   216         kx 	  ptr += grub_target_to_host32 (ctx->lst->b.block_size);
   216         kx 	}
   216         kx     assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
   216         kx   }
   216         kx 
   216         kx   for (ctx->lst = ctx->lst0; ctx->lst; )
   216         kx     {
   216         kx       struct fixup_block_list *next;
   216         kx       next = ctx->lst->next;
   216         kx       free (ctx->lst);
   216         kx       ctx->lst = next;
   216         kx     }
   216         kx 
   216         kx   layout->reloc_size = ctx->current_address;
   216         kx   if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
   216         kx     grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
   216         kx 		     "This breaks assembly assumptions. Please increase stack size",
   216         kx 		     (int) layout->reloc_size,
   216         kx 		     (int) GRUB_KERNEL_ARM_STACK_SIZE);
   216         kx }
   216         kx 
   216         kx /*
   216         kx   Layout:
   216         kx   <type 0 relocations>
   216         kx   <fffffffe>
   216         kx   <type 1 relocations>
   216         kx   <fffffffe>
   216         kx   ...
   216         kx   <type n relocations>
   216         kx   <ffffffff>
   216         kx   each relocation starts with 32-bit offset. Rest depends on relocation.
   216         kx   mkimage stops when it sees first unknown type or end marker.
   216         kx   This allows images to be created with mismatched mkimage and
   216         kx   kernel as long as no relocations are present in kernel that mkimage
   216         kx   isn't aware of (in which case mkimage aborts).
   216         kx   This also allows simple assembly to do the relocs.
   216         kx */
   216         kx 
   216         kx #define RAW_SEPARATOR 0xfffffffe
   216         kx #define RAW_END_MARKER 0xffffffff
   216         kx 
   216         kx static void
   216         kx finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
   216         kx 			      const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   size_t count = 0, sz;
   216         kx   enum raw_reloc_type highest = RAW_RELOC_NONE;
   216         kx   enum raw_reloc_type curtype;
   216         kx   struct raw_reloc *cur;
   216         kx   grub_uint32_t *p;
   216         kx   if (!ctx->raw_relocs)
   216         kx     {
   216         kx       layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
   216         kx       p[0] = RAW_END_MARKER;
   216         kx       layout->reloc_size = sizeof (grub_uint32_t);
   216         kx       return;
   216         kx     }
   216         kx   for (cur = ctx->raw_relocs; cur; cur = cur->next)
   216         kx     {
   216         kx       count++;
   216         kx       if (cur->type > highest)
   216         kx 	highest = cur->type;
   216         kx     }
   216         kx   /* highest separators, count relocations and one end marker.  */
   216         kx   sz = (highest + count + 1) * sizeof (grub_uint32_t);
   216         kx   layout->reloc_section = p = xmalloc (sz);
   216         kx   for (curtype = 0; curtype <= highest; curtype++)
   216         kx     {
   216         kx       /* Support for special cases would go here.  */
   216         kx       for (cur = ctx->raw_relocs; cur; cur = cur->next)
   216         kx 	if (cur->type == curtype)
   216         kx 	  {
   216         kx 	    *p++ = cur->offset;
   216         kx 	  }
   216         kx       *p++ = RAW_SEPARATOR;
   216         kx     }
   216         kx   *--p = RAW_END_MARKER;
   216         kx   layout->reloc_size = sz;
   216         kx }
   216         kx 
   216         kx static void
   216         kx finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
   216         kx 			  const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   if (image_target->id == IMAGE_EFI)
   216         kx     finish_reloc_translation_pe (ctx, layout, image_target);
   216         kx   else
   216         kx     finish_reloc_translation_raw (ctx, layout, image_target);
   216         kx }
   216         kx 
   216         kx 
   216         kx static void
   216         kx create_u64_fixups (struct translate_context *ctx,
   216         kx 		   Elf_Addr jumpers, grub_size_t njumpers,
   216         kx 		   const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   unsigned i;
   216         kx   assert (image_target->id == IMAGE_EFI);
   216         kx   for (i = 0; i < njumpers; i++)
   216         kx     ctx->current_address = add_fixup_entry (&ctx->lst,
   216         kx 					    GRUB_PE32_REL_BASED_DIR64,
   216         kx 					    jumpers + 8 * i,
   216         kx 					    0, ctx->current_address,
   216         kx 					    image_target);
   216         kx }
   216         kx 
   216         kx /* Make a .reloc section.  */
   216         kx static void
   216         kx make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
   216         kx 		    struct section_metadata *smd,
   216         kx 		    const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   unsigned i;
   216         kx   Elf_Shdr *s;
   216         kx   struct translate_context ctx;
   216         kx 
   216         kx   translate_reloc_start (&ctx, image_target);
   216         kx 
   216         kx   for (i = 0, s = smd->sections; i < smd->num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
   216         kx     if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
   216         kx         (grub_target_to_host32 (s->sh_type) == SHT_RELA))
   216         kx       {
   216         kx 	Elf_Rel *r;
   216         kx 	Elf_Word rtab_size, r_size, num_rs;
   216         kx 	Elf_Off rtab_offset;
   216         kx 	Elf_Addr section_address;
   216         kx 	Elf_Word j;
   216         kx 
   216         kx 	if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd))
   216         kx 	  {
   216         kx 	    grub_util_info ("not translating the skipped relocation section %s",
   216         kx 			    smd->strtab + grub_le_to_cpu32 (s->sh_name));
   216         kx 	    continue;
   216         kx 	  }
   216         kx 
   216         kx 	grub_util_info ("translating the relocation section %s",
   216         kx 			smd->strtab + grub_le_to_cpu32 (s->sh_name));
   216         kx 
   216         kx 	rtab_size = grub_target_to_host (s->sh_size);
   216         kx 	r_size = grub_target_to_host (s->sh_entsize);
   216         kx 	rtab_offset = grub_target_to_host (s->sh_offset);
   216         kx 	num_rs = rtab_size / r_size;
   216         kx 
   216         kx 	section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
   216         kx 
   216         kx 	for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
   216         kx 	     j < num_rs;
   216         kx 	     j++, r = (Elf_Rel *) ((char *) r + r_size))
   216         kx 	  {
   216         kx 	    Elf_Addr info;
   216         kx 	    Elf_Addr offset;
   216         kx 	    Elf_Addr addr;
   216         kx 
   216         kx 	    offset = grub_target_to_host (r->r_offset);
   216         kx 	    info = grub_target_to_host (r->r_info);
   216         kx 
   216         kx 	    addr = section_address + offset;
   216         kx 
   216         kx 	    translate_relocation (&ctx, addr, info, image_target);
   216         kx 	  }
   216         kx       }
   216         kx 
   216         kx   if (image_target->elf_target == EM_IA_64)
   216         kx     create_u64_fixups (&ctx,
   216         kx 		       layout->ia64jmp_off
   216         kx 		       + image_target->vaddr_offset,
   216         kx 		       2 * layout->ia64jmpnum,
   216         kx 		       image_target);
   216         kx   if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
   216         kx     create_u64_fixups (&ctx,
   216         kx 		       layout->got_off
   216         kx 		       + image_target->vaddr_offset,
   216         kx 		       (layout->got_size / 8),
   216         kx 		       image_target);
   216         kx 
   216         kx   finish_reloc_translation (&ctx, layout, image_target);
   216         kx }
   216         kx 
   216         kx /* Determine if this section is a text section. Return false if this
   216         kx    section is not allocated.  */
   216         kx static int
   216         kx SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   if (!is_relocatable (image_target)
   216         kx       && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
   216         kx     return 0;
   216         kx   return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
   216         kx 	  == (SHF_EXECINSTR | SHF_ALLOC));
   216         kx }
   216         kx 
   216         kx /* Determine if this section is a data section.  */
   216         kx static int
   216         kx SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   if (!is_relocatable (image_target) 
   216         kx       && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
   216         kx     return 0;
   216         kx   return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
   216         kx 	  == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
   216         kx }
   216         kx 
   216         kx static int
   216         kx SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   if (!is_relocatable (image_target))
   216         kx     return 0;
   216         kx   return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
   216         kx 	  == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
   216         kx }
   216         kx 
   216         kx /* Determine if a section is going to be in the final output */
   216         kx static int
   216         kx SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   /* We keep .text and .data */
   216         kx   if (SUFFIX (is_text_section) (s, image_target)
   216         kx       || SUFFIX (is_data_section) (s, image_target))
   216         kx     return 1;
   216         kx 
   216         kx   /*
   216         kx    * And we keep .bss if we're producing PE binaries or the target doesn't
   216         kx    * have a relocating loader.  Platforms other than EFI and U-boot shouldn't
   216         kx    * have .bss in their binaries as we build with -Wl,-Ttext.
   216         kx    */
   216         kx   if (SUFFIX (is_bss_section) (s, image_target)
   216         kx       && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
   216         kx     return 1;
   216         kx 
   216         kx   /* Otherwise this is not a section we're keeping in the final output. */
   216         kx   return 0;
   216         kx }
   216         kx 
   216         kx static int
   216         kx SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
   216         kx 				struct section_metadata *smd)
   216         kx {
   216         kx   int i;
   216         kx   int r = 0;
   216         kx   const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
   216         kx 
   216         kx   if (!strncmp (name, ".rela.", 6))
   216         kx     name += 5;
   216         kx   else if (!strncmp (name, ".rel.", 5))
   216         kx     name += 4;
   216         kx   else
   216         kx     return 1;
   216         kx 
   216         kx   for (i = 0, s = smd->sections; i < smd->num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
   216         kx     {
   216         kx       const char *sname = smd->strtab + grub_host_to_target32 (s->sh_name);
   216         kx       if (strcmp (sname, name))
   216         kx 	continue;
   216         kx 
   216         kx       return SUFFIX (is_kept_section) (s, image_target);
   216         kx     }
   216         kx 
   216         kx   return r;
   216         kx }
   216         kx 
   216         kx /* Return if the ELF header is valid.  */
   216         kx static int
   216         kx SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   if (size < sizeof (*e)
   216         kx       || e->e_ident[EI_MAG0] != ELFMAG0
   216         kx       || e->e_ident[EI_MAG1] != ELFMAG1
   216         kx       || e->e_ident[EI_MAG2] != ELFMAG2
   216         kx       || e->e_ident[EI_MAG3] != ELFMAG3
   216         kx       || e->e_ident[EI_VERSION] != EV_CURRENT
   216         kx       || e->e_ident[EI_CLASS] != ELFCLASSXX
   216         kx       || e->e_version != grub_host_to_target32 (EV_CURRENT))
   216         kx     return 0;
   216         kx 
   216         kx   return 1;
   216         kx }
   216         kx 
   216         kx static Elf_Addr
   216         kx SUFFIX (put_section) (Elf_Shdr *s, int i,
   216         kx 		      Elf_Addr current_address,
   216         kx 		      struct section_metadata *smd,
   216         kx 		      const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx 	Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
   216         kx 	const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
   216         kx 
   216         kx 	if (align)
   216         kx 	  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
   216         kx 				      align)
   216         kx 	    - image_target->vaddr_offset;
   216         kx 
   216         kx 	grub_util_info ("locating the section %s at 0x%"
   216         kx 			GRUB_HOST_PRIxLONG_LONG,
   216         kx 			name, (unsigned long long) current_address);
   216         kx 	if (!is_relocatable (image_target))
   216         kx 	  current_address = grub_host_to_target_addr (s->sh_addr)
   216         kx 			    - image_target->link_addr;
   216         kx 	smd->addrs[i] = current_address;
   216         kx 	current_address += grub_host_to_target_addr (s->sh_size);
   216         kx 	return current_address;
   216         kx }
   216         kx 
   216         kx /*
   216         kx  * Locate section addresses by merging code sections and data sections
   216         kx  * into .text and .data, respectively.
   216         kx  */
   216         kx static void
   216         kx SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
   216         kx 			  struct section_metadata *smd,
   216         kx 			  struct grub_mkimage_layout *layout,
   216         kx 			  const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   int i;
   216         kx   Elf_Shdr *s;
   216         kx 
   216         kx   layout->align = 1;
   216         kx   /* Page-aligning simplifies relocation handling.  */
   216         kx   if (image_target->elf_target == EM_AARCH64)
   216         kx     layout->align = 4096;
   216         kx 
   216         kx   layout->kernel_size = 0;
   216         kx 
   216         kx   for (i = 0, s = smd->sections;
   216         kx        i < smd->num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
   216         kx     if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
   216         kx 	&& grub_host_to_target32 (s->sh_addralign) > layout->align)
   216         kx       layout->align = grub_host_to_target32 (s->sh_addralign);
   216         kx 
   216         kx   /* .text */
   216         kx   for (i = 0, s = smd->sections;
   216         kx        i < smd->num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
   216         kx     if (SUFFIX (is_text_section) (s, image_target))
   216         kx       {
   216         kx 	layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size,
   216         kx 						smd, image_target);
   216         kx 	if (!is_relocatable (image_target) &&
   216         kx 	    grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
   216         kx 	  {
   216         kx 	    char *msg
   216         kx 	      = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
   216         kx 				  " instead of 0x%llx: ld.gold bug?"),
   216         kx 				kernel_path,
   216         kx 				(unsigned long long) grub_host_to_target_addr (s->sh_addr),
   216         kx 				(unsigned long long) image_target->link_addr);
   216         kx 	    grub_util_error ("%s", msg);
   216         kx 	  }
   216         kx       }
   216         kx 
   216         kx #ifdef MKIMAGE_ELF32
   216         kx   if (image_target->elf_target == EM_ARM)
   216         kx     {
   216         kx       grub_size_t tramp;
   216         kx 
   216         kx       layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
   216         kx 
   216         kx       tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize,
   216         kx 				       smd->num_sections, image_target);
   216         kx 
   216         kx       layout->tramp_off = layout->kernel_size;
   216         kx       layout->kernel_size += ALIGN_UP (tramp, 16);
   216         kx     }
   216         kx #endif
   216         kx 
   216         kx   layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
   216         kx 			      image_target->section_align)
   216         kx     - image_target->vaddr_offset;
   216         kx   layout->exec_size = layout->kernel_size;
   216         kx 
   216         kx   /* .data */
   216         kx   for (i = 0, s = smd->sections;
   216         kx        i < smd->num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
   216         kx     if (SUFFIX (is_data_section) (s, image_target))
   216         kx       layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd,
   216         kx 						  image_target);
   216         kx 
   216         kx   layout->bss_start = layout->kernel_size;
   216         kx   layout->end = layout->kernel_size;
   216         kx   
   216         kx   /* .bss */
   216         kx   for (i = 0, s = smd->sections;
   216         kx        i < smd->num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
   216         kx     {
   216         kx       if (SUFFIX (is_bss_section) (s, image_target))
   216         kx 	layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target);
   216         kx 
   216         kx       /*
   216         kx        * This must to be in the last time this function passes through the loop.
   216         kx        */
   216         kx       smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset;
   216         kx     }
   216         kx 
   216         kx   layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
   216         kx 			      image_target->section_align) - image_target->vaddr_offset;
   216         kx   /* Explicitly initialize BSS
   216         kx      when producing PE32 to avoid a bug in EFI implementations.
   216         kx      Platforms other than EFI and U-boot shouldn't have .bss in
   216         kx      their binaries as we build with -Wl,-Ttext.
   216         kx   */
   216         kx   if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
   216         kx     layout->kernel_size = layout->end;
   216         kx }
   216         kx 
   216         kx char *
   216         kx SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
   216         kx 				  size_t total_module_size,
   216         kx 				  struct grub_mkimage_layout *layout,
   216         kx 				  const struct grub_install_image_target_desc *image_target)
   216         kx {
   216         kx   char *kernel_img, *out_img;
   216         kx   struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0 };
   216         kx   Elf_Ehdr *e;
   216         kx   int i;
   216         kx   Elf_Shdr *s;
   216         kx   Elf_Off section_offset;
   216         kx   grub_size_t kernel_size;
   216         kx 
   216         kx   grub_memset (layout, 0, sizeof (*layout));
   216         kx 
   216         kx   layout->start_address = 0;
   216         kx 
   216         kx   kernel_size = grub_util_get_image_size (kernel_path);
   216         kx   kernel_img = xmalloc (kernel_size);
   216         kx   grub_util_load_image (kernel_path, kernel_img);
   216         kx 
   216         kx   e = (Elf_Ehdr *) kernel_img;
   216         kx   if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
   216         kx     grub_util_error ("invalid ELF header");
   216         kx 
   216         kx   section_offset = grub_target_to_host (e->e_shoff);
   216         kx   smd.section_entsize = grub_target_to_host16 (e->e_shentsize);
   216         kx   smd.num_sections = grub_target_to_host16 (e->e_shnum);
   216         kx 
   216         kx   if (kernel_size < section_offset
   216         kx 		    + (grub_uint32_t) smd.section_entsize * smd.num_sections)
   216         kx     grub_util_error (_("premature end of file %s"), kernel_path);
   216         kx 
   216         kx   smd.sections = (Elf_Shdr *) (kernel_img + section_offset);
   216         kx 
   216         kx   /* Relocate sections then symbols in the virtual address space.  */
   216         kx   s = (Elf_Shdr *) ((char *) smd.sections
   216         kx 		      + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
   216         kx   smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
   216         kx 
   216         kx   smd.addrs = xcalloc (smd.num_sections, sizeof (*smd.addrs));
   216         kx   smd.vaddrs = xcalloc (smd.num_sections, sizeof (*smd.vaddrs));
   216         kx 
   216         kx   SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
   216         kx 
   216         kx   if (!is_relocatable (image_target))
   216         kx     {
   216         kx       Elf_Addr current_address = layout->kernel_size;
   216         kx 
   216         kx       for (i = 0, s = smd.sections;
   216         kx 	   i < smd.num_sections;
   216         kx 	   i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
   216         kx 	if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
   216         kx 	  {
   216         kx 	    Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
   216         kx 	    const char *name = smd.strtab + grub_host_to_target32 (s->sh_name);
   216         kx 
   216         kx 	    if (sec_align)
   216         kx 	      current_address = ALIGN_UP (current_address
   216         kx 					  + image_target->vaddr_offset,
   216         kx 					  sec_align)
   216         kx 		- image_target->vaddr_offset;
   216         kx 
   216         kx 	    grub_util_info ("locating the section %s at 0x%"
   216         kx 			    GRUB_HOST_PRIxLONG_LONG,
   216         kx 			    name, (unsigned long long) current_address);
   216         kx 	    if (!is_relocatable (image_target))
   216         kx 	      current_address = grub_host_to_target_addr (s->sh_addr)
   216         kx 		- image_target->link_addr;
   216         kx 
   216         kx 	    smd.vaddrs[i] = current_address
   216         kx 	      + image_target->vaddr_offset;
   216         kx 	    current_address += grub_host_to_target_addr (s->sh_size);
   216         kx 	  }
   216         kx       current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
   216         kx 				  image_target->section_align)
   216         kx 	- image_target->vaddr_offset;
   216         kx       layout->bss_size = current_address - layout->kernel_size;
   216         kx     }
   216         kx   else
   216         kx     layout->bss_size = 0;
   216         kx 
   216         kx   if (image_target->id == IMAGE_SPARC64_AOUT
   216         kx       || image_target->id == IMAGE_SPARC64_RAW
   216         kx       || image_target->id == IMAGE_UBOOT
   216         kx       || image_target->id == IMAGE_COREBOOT
   216         kx       || image_target->id == IMAGE_SPARC64_CDCORE)
   216         kx     layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
   216         kx 
   216         kx   if (is_relocatable (image_target))
   216         kx     {
   216         kx       smd.symtab = NULL;
   216         kx       for (i = 0, s = smd.sections;
   216         kx 	   i < smd.num_sections;
   216         kx 	   i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
   216         kx 	if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
   216         kx 	  {
   216         kx 	    smd.symtab = s;
   216         kx 	    break;
   216         kx 	  }
   216         kx       if (! smd.symtab)
   216         kx 	grub_util_error ("%s", _("no symbol table"));
   216         kx #ifdef MKIMAGE_ELF64
   216         kx       if (image_target->elf_target == EM_IA_64)
   216         kx 	{
   216         kx 	  grub_size_t tramp;
   216         kx 
   216         kx 	  layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
   216         kx 
   216         kx 	  grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
   216         kx 
   216         kx 	  layout->tramp_off = layout->kernel_size;
   216         kx 	  layout->kernel_size += ALIGN_UP (tramp, 16);
   216         kx 
   216         kx 	  layout->ia64jmp_off = layout->kernel_size;
   216         kx 	  layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab,
   216         kx 						     image_target);
   216         kx 	  layout->kernel_size += 16 * layout->ia64jmpnum;
   216         kx 
   216         kx 	  layout->got_off = layout->kernel_size;
   216         kx 	  layout->kernel_size += ALIGN_UP (layout->got_size, 16);
   216         kx 	}
   216         kx       if (image_target->elf_target == EM_AARCH64)
   216         kx 	{
   216         kx 	  grub_size_t tramp;
   216         kx 
   216         kx 	  layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
   216         kx 
   216         kx 	  grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
   216         kx 
   216         kx 	  layout->got_off = layout->kernel_size;
   216         kx 	  layout->kernel_size += ALIGN_UP (layout->got_size, 16);
   216         kx 	}
   216         kx #endif
   216         kx 
   216         kx       if (image_target->id == IMAGE_EFI)
   216         kx         layout->kernel_size = ALIGN_UP (layout->kernel_size,
   216         kx                                         GRUB_PE32_FILE_ALIGNMENT);
   216         kx     }
   216         kx   else
   216         kx     {
   216         kx       layout->reloc_size = 0;
   216         kx       layout->reloc_section = NULL;
   216         kx     }
   216         kx 
   216         kx   out_img = xmalloc (layout->kernel_size + total_module_size);
   216         kx   memset (out_img, 0, layout->kernel_size + total_module_size);
   216         kx 
   216         kx   if (is_relocatable (image_target))
   216         kx     {
   216         kx       layout->start_address = SUFFIX (relocate_symbols) (e, &smd,
   216         kx 				  (char *) out_img + layout->ia64jmp_off,
   216         kx 				  layout->ia64jmp_off + image_target->vaddr_offset,
   216         kx 				  layout->bss_start, layout->end, image_target);
   216         kx 
   216         kx       if (layout->start_address == (Elf_Addr) -1)
   216         kx 	grub_util_error ("start symbol is not defined");
   216         kx 
   216         kx       /* Resolve addrs in the virtual address space.  */
   216         kx       SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off,
   216         kx 				   layout->got_off, image_target);
   216         kx 
   216         kx       make_reloc_section (e, layout, &smd, image_target);
   216         kx       if (image_target->id != IMAGE_EFI)
   216         kx 	{
   216         kx 	  out_img = xrealloc (out_img, layout->kernel_size + total_module_size
   216         kx 			      + ALIGN_UP (layout->reloc_size, image_target->mod_align));
   216         kx 	  memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
   216         kx 	  memset (out_img + layout->kernel_size + layout->reloc_size, 0,
   216         kx 		  total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
   216         kx 	  layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
   216         kx 	}
   216         kx     }
   216         kx 
   216         kx   for (i = 0, s = smd.sections;
   216         kx        i < smd.num_sections;
   216         kx        i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
   216         kx     if (SUFFIX (is_kept_section) (s, image_target))
   216         kx       {
   216         kx 	if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
   216         kx 	  memset (out_img + smd.addrs[i], 0,
   216         kx 		  grub_host_to_target_addr (s->sh_size));
   216         kx 	else
   216         kx 	  memcpy (out_img + smd.addrs[i],
   216         kx 		  kernel_img + grub_host_to_target_addr (s->sh_offset),
   216         kx 		  grub_host_to_target_addr (s->sh_size));
   216         kx       }
   216         kx   free (kernel_img);
   216         kx 
   216         kx   free (smd.vaddrs);
   216         kx   smd.vaddrs = NULL;
   216         kx   free (smd.addrs);
   216         kx   smd.addrs = NULL;
   216         kx 
   216         kx   return out_img;
   216         kx }