#define PT_NUM 8 /* Number of defined types */
#define PT_LOOS 0x60000000 /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK 0x6474e551 /* GCC stack segment */
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
#ifndef GRUB_KERNEL_CPU_HEADER
#define GRUB_KERNEL_CPU_HEADER 1
-
-#ifdef GRUB_MACHINE_IEEE1275
-#define GRUB_MOD_ALIGN 0x1000
-#else
-#define GRUB_MOD_ALIGN 0x1
-#endif
-
-/* Non-zero value is only needed for PowerMacs. */
-#define GRUB_MOD_GAP 0x0
-
#endif
#define GRUB_KERNEL_I386_IEEE1275_DATA_END 0x42
#define GRUB_KERNEL_I386_IEEE1275_LINK_ADDR 0x10000
+#define GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN 0x1000
+#define GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN 0x1
+
+/* Non-zero value is only needed for PowerMacs. */
+#define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0
+#define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0
+
+#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000
+
+/* Minimal gap between _end and the start of the modules. It's a hack
+ for PowerMac to prevent "CLAIM failed" error. The real fix is to
+ rewrite grub-mkimage to generate valid ELF files. */
+#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x8000
+
#ifdef MACHINE
#define GRUB_OFFSETS_CONCAT_(a,b,c) a ## b ## c
#define GRUB_OFFSETS_CONCAT(a,b,c) GRUB_OFFSETS_CONCAT_(a,b,c)
+#define GRUB_KERNEL_MACHINE_MOD_ALIGN GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _MOD_ALIGN)
+#define GRUB_KERNEL_MACHINE_MOD_GAP GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _MOD_GAP)
#define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _TOTAL_MODULE_SIZE)
#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _KERNEL_IMAGE_SIZE)
#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _COMPRESSED_SIZE)
#ifndef GRUB_KERNEL_CPU_HEADER
#define GRUB_KERNEL_CPU_HEADER 1
-#define GRUB_MOD_ALIGN 0x1000
-
-/* Minimal gap between _end and the start of the modules. It's a hack
- for PowerMac to prevent "CLAIM failed" error. The real fix is to
- rewrite grub-mkimage to generate valid ELF files. */
-#define GRUB_MOD_GAP 0x8000
-
#endif
#ifdef GRUB_MACHINE_QEMU
return grub_core_entry_addr + grub_kernel_image_size;
#else
- return ALIGN_UP((grub_addr_t) _end, GRUB_MOD_ALIGN);
+ return ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN);
#endif
}
grub_addr_t
grub_arch_modules_addr (void)
{
- return ALIGN_UP((grub_addr_t) _end + GRUB_MOD_GAP, GRUB_MOD_ALIGN);
+ return ALIGN_UP((grub_addr_t) _end + GRUB_KERNEL_MACHINE_MOD_GAP, GRUB_KERNEL_MACHINE_MOD_ALIGN);
}
signed vaddr_offset;
unsigned install_dos_part, install_bsd_part;
grub_uint64_t link_addr;
+ unsigned mod_gap, mod_align;
};
struct image_target_desc image_targets[] =
.vaddr_offset = 0,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
- .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR
+ .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
+ .elf_target = EM_386,
+ .link_align = 4,
+ .mod_gap = GRUB_KERNEL_I386_COREBOOT_MOD_GAP,
+ .mod_align = GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
},
{
.name = "i386-pc",
.vaddr_offset = 0,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
- .link_addr = GRUB_KERNEL_I386_IEEE1275_LINK_ADDR
+ .link_addr = GRUB_KERNEL_I386_IEEE1275_LINK_ADDR,
+ .elf_target = EM_386,
+ .mod_gap = GRUB_KERNEL_I386_IEEE1275_MOD_GAP,
+ .mod_align = GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN,
+ .link_align = 4,
},
{
.name = "i386-qemu",
.vaddr_offset = 0,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
- .link_addr = GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR
+ .link_addr = GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR,
+ .elf_target = EM_PPC,
+ .mod_gap = GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP,
+ .mod_align = GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN,
+ .link_align = 4
},
{
.name = "sparc64-ieee1275-raw",
grub_size_t bss_size;
grub_uint64_t start_address;
void *rel_section;
- grub_size_t reloc_size;
+ grub_size_t reloc_size, align;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
kernel_path = grub_util_get_path (dir, "kernel.img");
if (image_target->voidp_sizeof == 4)
kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size,
total_module_size, &start_address, &rel_section,
- &reloc_size, image_target);
+ &reloc_size, &align, image_target);
else
kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size,
total_module_size, &start_address, &rel_section,
- &reloc_size, image_target);
+ &reloc_size, &align, image_target);
if (image_target->prefix + strlen (prefix) + 1 > image_target->data_end)
grub_util_error (_("prefix is too long"));
grub_uint32_t target_addr;
int header_size, footer_size = 0;
int phnum = 1;
+
+ if (image_target->id != IMAGE_YEELOONG_ELF)
+ phnum += 2;
if (note)
{
/* No section headers. */
ehdr->e_shoff = grub_host_to_target32 (0);
- ehdr->e_shentsize = grub_host_to_target16 (0);
+ if (image_target->id == IMAGE_YEELOONG_ELF)
+ ehdr->e_shentsize = grub_host_to_target16 (0);
+ else
+ ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf32_Shdr));
ehdr->e_shnum = grub_host_to_target16 (0);
ehdr->e_shstrndx = grub_host_to_target16 (0);
ehdr->e_entry = grub_host_to_target32 (target_addr);
phdr->p_vaddr = grub_host_to_target32 (target_addr);
phdr->p_paddr = grub_host_to_target32 (target_addr);
- phdr->p_align = grub_host_to_target32 (image_target->link_align);
+ phdr->p_align = grub_host_to_target32 (align > image_target->link_align ? align : image_target->link_align);
if (image_target->id == IMAGE_YEELOONG_ELF)
ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
| EF_MIPS_PIC | EF_MIPS_CPIC);
else
ehdr->e_flags = 0;
- phdr->p_filesz = grub_host_to_target32 (core_size);
- phdr->p_memsz = grub_host_to_target32 (core_size);
+ if (image_target->id == IMAGE_YEELOONG_ELF)
+ {
+ phdr->p_filesz = grub_host_to_target32 (core_size);
+ phdr->p_memsz = grub_host_to_target32 (core_size);
+ }
+ else
+ {
+ grub_uint32_t target_addr_mods;
+ phdr->p_filesz = grub_host_to_target32 (kernel_size);
+ phdr->p_memsz = grub_host_to_target32 (kernel_size + bss_size);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
+ phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
+ phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
+ phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
+ phdr->p_align = grub_host_to_target32 (image_target->link_align);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_LOAD);
+ phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
+ phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
+ phdr->p_filesz = phdr->p_memsz
+ = grub_host_to_target32 (core_size - kernel_size);
+
+ target_addr_mods = ALIGN_UP (target_addr + kernel_size + bss_size
+ + image_target->mod_gap,
+ image_target->mod_align);
+ phdr->p_vaddr = grub_host_to_target32 (target_addr_mods);
+ phdr->p_paddr = grub_host_to_target32 (target_addr_mods);
+ phdr->p_align = grub_host_to_target32 (image_target->link_align);
+ }
if (note)
{
note->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
note->descriptor.load_base = grub_host_to_target32 (0x00004000);
- phdr[1].p_type = grub_host_to_target32 (PT_NOTE);
- phdr[1].p_flags = grub_host_to_target32 (PF_R);
- phdr[1].p_align = grub_host_to_target32 (image_target->voidp_sizeof);
- phdr[1].p_vaddr = 0;
- phdr[1].p_paddr = 0;
- phdr[1].p_filesz = grub_host_to_target32 (note_size);
- phdr[1].p_memsz = 0;
- phdr[1].p_offset = grub_host_to_target32 (header_size + program_size);
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size);
}
free (core_img);
SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize,
Elf_Half num_sections, const char *strtab,
grub_size_t *exec_size, grub_size_t *kernel_sz,
+ grub_size_t *all_align,
struct image_target_desc *image_target)
{
int i;
Elf_Addr *section_addresses;
Elf_Shdr *s;
+ *all_align = 1;
+
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
current_address = 0;
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
+ && grub_host_to_target32 (s->sh_addralign) > *all_align)
+ *all_align = grub_host_to_target32 (s->sh_addralign);
+
+
/* .text */
for (i = 0, s = sections;
i < num_sections;
if (align)
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
align) - image_target->vaddr_offset;
-
grub_util_info ("locating the section %s at 0x%x",
name, current_address);
section_addresses[i] = current_address;
grub_size_t *kernel_sz, grub_size_t *bss_size,
grub_size_t total_module_size, grub_uint64_t *start,
void **reloc_section, grub_size_t *reloc_size,
+ grub_size_t *align,
struct image_target_desc *image_target)
{
char *kernel_img, *out_img;
section_addresses = SUFFIX (locate_sections) (sections, section_entsize,
num_sections, strtab,
- exec_size, kernel_sz, image_target);
+ exec_size, kernel_sz, align,
+ image_target);
- if (image_target->id == IMAGE_EFI)
- {
- section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
+ section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
- for (i = 0; i < num_sections; i++)
- section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
+ for (i = 0; i < num_sections; i++)
+ section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
-#if 0
- {
- Elf_Addr current_address = *kernel_sz;
+ if (image_target->id != IMAGE_EFI)
+ {
+ Elf_Addr current_address = *kernel_sz;
- for (i = 0, s = sections;
- i < num_sections;
- i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
- if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
- {
- Elf_Word align = grub_host_to_target32 (s->sh_addralign);
- const char *name = strtab + grub_host_to_target32 (s->sh_name);
+ for (i = 0, s = sections;
+ i < num_sections;
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
+ {
+ Elf_Word align = grub_host_to_target32 (s->sh_addralign);
+ const char *name = strtab + grub_host_to_target32 (s->sh_name);
- if (align)
- current_address = ALIGN_UP (current_address + VADDR_OFFSET, align)
- - VADDR_OFFSET;
+ if (align)
+ current_address = ALIGN_UP (current_address
+ + image_target->vaddr_offset, align)
+ - image_target->vaddr_offset;
- grub_util_info ("locating the section %s at 0x%x",
- name, current_address);
- section_vaddresses[i] = current_address + VADDR_OFFSET;
- current_address += grub_host_to_target_addr (s->sh_size);
- }
- current_address = ALIGN_UP (current_address + VADDR_OFFSET, SECTION_ALIGN)
- - VADDR_OFFSET;
- *bss_size = current_address - *kernel_sz;
- }
-#else
- *bss_size = 0;
-#endif
+ grub_util_info ("locating the section %s at 0x%x",
+ name, current_address);
+ section_vaddresses[i] = current_address
+ + image_target->vaddr_offset;
+ current_address += grub_host_to_target_addr (s->sh_size);
+ }
+ current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+ image_target->section_align)
+ - image_target->vaddr_offset;
+ *bss_size = current_address - *kernel_sz;
+ }
+ else
+ *bss_size = 0;
+ if (image_target->id == IMAGE_EFI)
+ {
symtab_section = NULL;
for (i = 0, s = sections;
i < num_sections;
}
else
{
- *bss_size = 0;
*reloc_size = 0;
*reloc_section = NULL;
}