Commit 36212460 authored by Vladimir Serbinenko's avatar Vladimir Serbinenko
Browse files

mkimage.c: Split into separate files.

util/grub-mkimagexx.c is included in a special way into mkimage.c.
Interoperation between defines makes this very tricky. Instead
just have a clean interface and compile util/grub-mkimage*.c separately
from mkimage.c
parent 2ebef43c
......@@ -172,6 +172,8 @@ program = {
common = util/grub-mkimage.c;
common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/resolve.c;
common = grub-core/kern/emu/argp_common.c;
common = grub-core/osdep/init.c;
......@@ -510,6 +512,8 @@ program = {
common = util/render-label.c;
common = util/glue-efi.c;
common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c;
common = util/setup_bios.c;
common = util/setup_sparc.c;
......@@ -552,6 +556,8 @@ program = {
common = util/render-label.c;
common = util/glue-efi.c;
common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c;
common = util/setup_bios.c;
common = util/setup_sparc.c;
......@@ -595,6 +601,8 @@ program = {
common = util/grub-install.c;
common = util/probe.c;
common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c;
common = util/setup_bios.c;
common = util/setup_sparc.c;
......@@ -632,6 +640,8 @@ program = {
common = util/grub-mknetdir.c;
common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c;
common = util/setup_bios.c;
common = util/setup_sparc.c;
......
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_UTIL_MKIMAGE_HEADER
#define GRUB_UTIL_MKIMAGE_HEADER 1
/* Private header. Use only in mkimage-related sources. */
char *
grub_mkimage_load_image32 (const char *kernel_path, size_t *exec_size,
size_t *kernel_sz, size_t *bss_size,
size_t total_module_size, grub_uint64_t *start,
void **reloc_section, size_t *reloc_size,
size_t *align,
const struct grub_install_image_target_desc *image_target);
char *
grub_mkimage_load_image64 (const char *kernel_path, size_t *exec_size,
size_t *kernel_sz, size_t *bss_size,
size_t total_module_size, grub_uint64_t *start,
void **reloc_section, size_t *reloc_size,
size_t *align,
const struct grub_install_image_target_desc *image_target);
void
grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
int note, char **core_img, size_t *core_size,
Elf32_Addr target_addr, grub_size_t align,
size_t kernel_size, size_t bss_size);
void
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
int note, char **core_img, size_t *core_size,
Elf64_Addr target_addr, grub_size_t align,
size_t kernel_size, size_t bss_size);
struct grub_install_image_target_desc
{
const char *dirname;
const char *names[6];
grub_size_t voidp_sizeof;
int bigendian;
enum {
IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
IMAGE_I386_IEEE1275,
IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN, IMAGE_I386_PC_ELTORITO
} id;
enum
{
PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_DECOMPRESSORS = 2,
PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
} flags;
unsigned total_module_size;
unsigned decompressor_compressed_size;
unsigned decompressor_uncompressed_size;
unsigned decompressor_uncompressed_addr;
unsigned link_align;
grub_uint16_t elf_target;
unsigned section_align;
signed vaddr_offset;
grub_uint64_t link_addr;
unsigned mod_gap, mod_align;
grub_compression_t default_compression;
grub_uint16_t pe_target;
};
#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
#define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
#define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
#define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
#define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
#define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
static inline grub_uint32_t
grub_target_to_host32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu32 (in);
else
return grub_le_to_cpu32 (in);
}
static inline grub_uint64_t
grub_target_to_host64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu64 (in);
else
return grub_le_to_cpu64 (in);
}
static inline grub_uint64_t
grub_host_to_target64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be64 (in);
else
return grub_cpu_to_le64 (in);
}
static inline grub_uint32_t
grub_host_to_target32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be32 (in);
else
return grub_cpu_to_le32 (in);
}
static inline grub_uint16_t
grub_target_to_host16_real (const struct grub_install_image_target_desc *image_target,
grub_uint16_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu16 (in);
else
return grub_le_to_cpu16 (in);
}
static inline grub_uint16_t
grub_host_to_target16_real (const struct grub_install_image_target_desc *image_target,
grub_uint16_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be16 (in);
else
return grub_cpu_to_le16 (in);
}
static inline grub_uint64_t
grub_host_to_target_addr_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
{
if (image_target->voidp_sizeof == 8)
return grub_host_to_target64_real (image_target, in);
else
return grub_host_to_target32_real (image_target, in);
}
static inline grub_uint64_t
grub_target_to_host_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
{
if (image_target->voidp_sizeof == 8)
return grub_target_to_host64_real (image_target, in);
else
return grub_target_to_host32_real (image_target, in);
}
#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
#endif
#define MKIMAGE_ELF32 1
# define SUFFIX(x) x ## 32
# define ELFCLASSXX ELFCLASS32
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Phdr Elf32_Phdr
# define Elf_Nhdr Elf32_Nhdr
# define Elf_Addr Elf32_Addr
# define Elf_Sym Elf32_Sym
# define Elf_Off Elf32_Off
# define Elf_Shdr Elf32_Shdr
# define Elf_Rela Elf32_Rela
# define Elf_Rel Elf32_Rel
# define Elf_Word Elf32_Word
# define Elf_Half Elf32_Half
# define Elf_Section Elf32_Section
# define ELF_R_SYM(val) ELF32_R_SYM(val)
# define ELF_R_TYPE(val) ELF32_R_TYPE(val)
# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
#define XEN_NOTE_SIZE 132
#include "grub-mkimagexx.c"
#define MKIMAGE_ELF64 1
# define SUFFIX(x) x ## 64
# define ELFCLASSXX ELFCLASS64
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Phdr Elf64_Phdr
# define Elf_Nhdr Elf64_Nhdr
# define Elf_Addr Elf64_Addr
# define Elf_Sym Elf64_Sym
# define Elf_Off Elf64_Off
# define Elf_Shdr Elf64_Shdr
# define Elf_Rela Elf64_Rela
# define Elf_Rel Elf64_Rel
# define Elf_Word Elf64_Word
# define Elf_Half Elf64_Half
# define Elf_Section Elf64_Section
# define ELF_R_SYM(val) ELF64_R_SYM(val)
# define ELF_R_TYPE(val) ELF64_R_TYPE(val)
# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
#define XEN_NOTE_SIZE 120
#include "grub-mkimagexx.c"
......@@ -17,58 +17,172 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#undef ELF_R_SYM
#undef ELF_R_TYPE
#if defined(MKIMAGE_ELF32)
# define SUFFIX(x) x ## 32
# define ELFCLASSXX ELFCLASS32
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Phdr Elf32_Phdr
# define Elf_Nhdr Elf32_Nhdr
# define Elf_Addr Elf32_Addr
# define Elf_Sym Elf32_Sym
# define Elf_Off Elf32_Off
# define Elf_Shdr Elf32_Shdr
# define Elf_Rela Elf32_Rela
# define Elf_Rel Elf32_Rel
# define Elf_Word Elf32_Word
# define Elf_Half Elf32_Half
# define Elf_Section Elf32_Section
# define ELF_R_SYM(val) ELF32_R_SYM(val)
# define ELF_R_TYPE(val) ELF32_R_TYPE(val)
# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
#define XEN_NOTE_SIZE 132
#elif defined(MKIMAGE_ELF64)
# define SUFFIX(x) x ## 64
# define ELFCLASSXX ELFCLASS64
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Phdr Elf64_Phdr
# define Elf_Nhdr Elf64_Nhdr
# define Elf_Addr Elf64_Addr
# define Elf_Sym Elf64_Sym
# define Elf_Off Elf64_Off
# define Elf_Shdr Elf64_Shdr
# define Elf_Rela Elf64_Rela
# define Elf_Rel Elf64_Rel
# define Elf_Word Elf64_Word
# define Elf_Half Elf64_Half
# define Elf_Section Elf64_Section
# define ELF_R_SYM(val) ELF64_R_SYM(val)
# define ELF_R_TYPE(val) ELF64_R_TYPE(val)
# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
#define XEN_NOTE_SIZE 120
#else
#error "I'm confused"
#endif
#include <config.h>
#include <grub/types.h>
#include <grub/elf.h>
#include <grub/aout.h>
#include <grub/i18n.h>
#include <grub/kernel.h>
#include <grub/disk.h>
#include <grub/emu/misc.h>
#include <grub/util/misc.h>
#include <grub/util/resolve.h>
#include <grub/misc.h>
#include <grub/offsets.h>
#include <grub/crypto.h>
#include <grub/dl.h>
#include <time.h>
#include <multiboot.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <grub/efi/pe32.h>
#include <grub/uboot/image.h>
#include <grub/arm/reloc.h>
#include <grub/arm64/reloc.h>
#include <grub/ia64/reloc.h>
#include <grub/osdep/hostfile.h>
#include <grub/util/install.h>
#include <grub/util/mkimage.h>
#pragma GCC diagnostic ignored "-Wcast-align"
static Elf_Addr SUFFIX (entry_point);
static void
SUFFIX (generate_elf) (const struct grub_install_image_target_desc *image_target,
int note, char **core_img, size_t *core_size,
Elf_Addr target_addr, grub_size_t align,
size_t kernel_size, size_t bss_size)
/* These structures are defined according to the CHRP binding to IEEE1275,
"Client Program Format" section. */
struct grub_ieee1275_note_desc
{
grub_uint32_t real_mode;
grub_uint32_t real_base;
grub_uint32_t real_size;
grub_uint32_t virt_base;
grub_uint32_t virt_size;
grub_uint32_t load_base;
};
#define GRUB_IEEE1275_NOTE_NAME "PowerPC"
#define GRUB_IEEE1275_NOTE_TYPE 0x1275
struct grub_ieee1275_note
{
Elf32_Nhdr header;
char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
struct grub_ieee1275_note_desc descriptor;
};
#define GRUB_XEN_NOTE_NAME "Xen"
struct fixup_block_list
{
struct fixup_block_list *next;
int state;
struct grub_pe32_fixup_block b;
};
#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
#ifdef MKIMAGE_ELF32
/*
* R_ARM_THM_CALL/THM_JUMP24
*
* Relocate Thumb (T32) instruction set relative branches:
* B.W, BL and BLX
*/
static grub_err_t
grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
{
grub_int32_t offset;
offset = grub_arm_thm_call_get_offset (target);
grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
offset += sym_addr;
grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
target, sym_addr, offset);
/* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
is bigger than 2M (currently under 150K) then we probably have a problem
somewhere else. */
if (offset < -0x200000 || offset >= 0x200000)
return grub_error (GRUB_ERR_BAD_MODULE,
"THM_CALL Relocation out of range.");
grub_dprintf ("dl", " relative destination = %p",
(char *) target + offset);
return grub_arm_thm_call_set_offset (target, offset);
}
/*
* R_ARM_THM_JUMP19
*
* Relocate conditional Thumb (T32) B<c>.W
*/
static grub_err_t
grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
{
grub_int32_t offset;
if (!(sym_addr & 1))
return grub_error (GRUB_ERR_BAD_MODULE,
"Relocation targeting wrong execution state");
offset = grub_arm_thm_jump19_get_offset (target);
/* Adjust and re-truncate offset */
offset += sym_addr;
if (!grub_arm_thm_jump19_check_offset (offset))
return grub_error (GRUB_ERR_BAD_MODULE,
"THM_JUMP19 Relocation out of range.");
grub_arm_thm_jump19_set_offset (target, offset);
return GRUB_ERR_NONE;
}
/*
* R_ARM_JUMP24
*
* Relocate ARM (A32) B
*/
static grub_err_t
grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
{
grub_int32_t offset;
if (sym_addr & 1)
return grub_error (GRUB_ERR_BAD_MODULE,
"Relocation targeting wrong execution state");
offset = grub_arm_jump24_get_offset (target);
offset += sym_addr;
if (!grub_arm_jump24_check_offset (offset))
return grub_error (GRUB_ERR_BAD_MODULE,
"JUMP24 Relocation out of range.");
grub_arm_jump24_set_offset (target, offset);
return GRUB_ERR_NONE;
}
#endif
void
SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
int note, char **core_img, size_t *core_size,
Elf_Addr target_addr, grub_size_t align,
size_t kernel_size, size_t bss_size)
{
char *elf_img;
size_t program_size;
......@@ -1457,13 +1571,13 @@ SUFFIX (locate_sections) (const char *kernel_path,
return section_addresses;
}
static char *
SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
size_t *kernel_sz, size_t *bss_size,
size_t total_module_size, grub_uint64_t *start,
void **reloc_section, size_t *reloc_size,
size_t *align,
const struct grub_install_image_target_desc *image_target)
char *
SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size,
size_t *kernel_sz, size_t *bss_size,
size_t total_module_size, grub_uint64_t *start,
void **reloc_section, size_t *reloc_size,
size_t *align,
const struct grub_install_image_target_desc *image_target)
{
char *kernel_img, *out_img;
const char *strtab;
......@@ -1671,23 +1785,3 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
return out_img;
}
#undef SUFFIX
#undef ELFCLASSXX
#undef Elf_Ehdr
#undef Elf_Phdr
#undef Elf_Nhdr
#undef Elf_Shdr
#undef Elf_Addr
#undef Elf_Sym
#undef Elf_Off
#undef Elf_Rela
#undef Elf_Rel
#undef ELF_R_TYPE
#undef ELF_R_SYM
#undef Elf_Word
#undef Elf_Half
#undef Elf_Section
#undef ELF_ST_TYPE
#undef XEN_NOTE_SIZE
......@@ -46,6 +46,7 @@
#include <grub/ia64/reloc.h>
#include <grub/osdep/hostfile.h>
#include <grub/util/install.h>
#include <grub/util/mkimage.h>
#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
......@@ -53,45 +54,13 @@
#include <lzma.h>
#endif
#pragma GCC diagnostic ignored "-Wcast-align"
#define TARGET_NO_FIELD 0xffffffff
/* use 2015-01-01T00:00:00+0000 as a stock timestamp */
#define STABLE_EMBEDDING_TIMESTAMP 1420070400
struct grub_install_image_target_desc
{
const char *dirname;
const char *names[6];
grub_size_t voidp_sizeof;
int bigendian;
enum {
IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
IMAGE_I386_IEEE1275,
IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN, IMAGE_I386_PC_ELTORITO
} id;
enum
{
PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_DECOMPRESSORS = 2,
PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
} flags;
unsigned total_module_size;
unsigned decompressor_compressed_size;
unsigned decompressor_uncompressed_size;
unsigned decompressor_uncompressed_addr;
unsigned link_align;
grub_uint16_t elf_target;
unsigned section_align;
signed vaddr_offset;
grub_uint64_t link_addr;
unsigned mod_gap, mod_align;
grub_compression_t default_compression;
grub_uint16_t pe_target;
};
#define EFI32_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
+ GRUB_PE32_SIGNATURE_SIZE \
+ sizeof (struct grub_pe32_coff_header) \
......@@ -603,119 +572,6 @@ static const struct grub_install_image_target_desc image_targets[] =
},
};
#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
#define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
#define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
#define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
#define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
#define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
static inline grub_uint32_t
grub_target_to_host32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu32 (in);
else
return grub_le_to_cpu32 (in);
}
static inline grub_uint64_t
grub_target_to_host64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu64 (in);
else
return grub_le_to_cpu64 (in);
}
static inline grub_uint64_t
grub_host_to_target64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be64 (in);
else
return grub_cpu_to_le64 (in);
}
static inline grub_uint32_t
grub_host_to_target32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be32 (in);
else
return grub_cpu_to_le32 (in);
}
static inline grub_uint16_t
grub_target_to_host16_real (const struct grub_install_image_target_desc *image_target,