grub/util/mkimage.c
Andrei Borzenkov 1018e91dce mkimage: zero fill alignment space
This did not cause real problem but is good for reproducible builds. I hit
it with recent bootinfoscript that displays embedded config; I was puzzled
by random garbage at the end.

Prezero memory buffer used to assemble core.img. This makes individual
memset redundant. Also ensure buffer is filled with zeroes in several other
places.

Also remove redundant zeroing code where we fill in the whole memory block
anyway.
2015-11-06 21:33:28 +03:00

1914 lines
63 KiB
C

/* grub-mkimage.c - make a bootable image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 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/>.
*/
#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>
#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
#ifdef USE_LIBLZMA
#include <lzma.h>
#endif
#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) \
+ sizeof (struct grub_pe32_optional_header) \
+ 4 * sizeof (struct grub_pe32_section_table), \
GRUB_PE32_SECTION_ALIGNMENT)
#define EFI64_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
+ GRUB_PE32_SIGNATURE_SIZE \
+ sizeof (struct grub_pe32_coff_header) \
+ sizeof (struct grub_pe64_optional_header) \
+ 4 * sizeof (struct grub_pe32_section_table), \
GRUB_PE32_SECTION_ALIGNMENT)
static const struct grub_install_image_target_desc image_targets[] =
{
{
.dirname = "i386-coreboot",
.names = { "i386-coreboot", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_COREBOOT,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.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
},
{
.dirname = "i386-multiboot",
.names = { "i386-multiboot", NULL},
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_COREBOOT,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.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
},
{
.dirname = "i386-pc",
.names = { "i386-pc", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_I386_PC,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
.default_compression = GRUB_COMPRESSION_LZMA
},
{
.dirname = "i386-pc",
.names = { "i386-pc-pxe", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_I386_PC_PXE,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
.default_compression = GRUB_COMPRESSION_LZMA
},
{
.dirname = "i386-pc",
.names = { "i386-pc-eltorito", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_I386_PC_ELTORITO,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR,
.default_compression = GRUB_COMPRESSION_LZMA
},
{
.dirname = "i386-efi",
.names = { "i386-efi", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_EFI,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_PE32_SECTION_ALIGNMENT,
.vaddr_offset = EFI32_HEADER_SIZE,
.pe_target = GRUB_PE32_MACHINE_I386,
.elf_target = EM_386,
},
{
.dirname = "i386-ieee1275",
.names = { "i386-ieee1275", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_I386_IEEE1275,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.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,
},
{
.dirname = "i386-qemu",
.names = { "i386-qemu", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_QEMU,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR
},
{
.dirname = "x86_64-efi",
.names = { "x86_64-efi", NULL },
.voidp_sizeof = 8,
.bigendian = 0,
.id = IMAGE_EFI,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_PE32_SECTION_ALIGNMENT,
.vaddr_offset = EFI64_HEADER_SIZE,
.pe_target = GRUB_PE32_MACHINE_X86_64,
.elf_target = EM_X86_64,
},
{
.dirname = "i386-xen",
.names = { "i386-xen", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_XEN,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = 0,
.elf_target = EM_386,
.mod_gap = GRUB_KERNEL_I386_XEN_MOD_GAP,
.mod_align = GRUB_KERNEL_I386_XEN_MOD_ALIGN,
.link_align = 4
},
{
.dirname = "x86_64-xen",
.names = { "x86_64-xen", NULL },
.voidp_sizeof = 8,
.bigendian = 0,
.id = IMAGE_XEN,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = 0,
.elf_target = EM_X86_64,
.mod_gap = GRUB_KERNEL_X86_64_XEN_MOD_GAP,
.mod_align = GRUB_KERNEL_X86_64_XEN_MOD_ALIGN,
.link_align = 8
},
{
.dirname = "mipsel-loongson",
.names = { "mipsel-yeeloong-flash", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_YEELOONG_FLASH,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "mipsel-loongson",
.names = { "mipsel-fuloong2f-flash", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_FULOONG2F_FLASH,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "mipsel-loongson",
.names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf",
"mipsel-fuloong2f-elf", "mipsel-fuloong2e-elf",
"mipsel-fuloong-elf", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_LOONGSON_ELF,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "powerpc-ieee1275",
.names = { "powerpc-ieee1275", NULL },
.voidp_sizeof = 4,
.bigendian = 1,
.id = IMAGE_PPC,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.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
},
{
.dirname = "sparc64-ieee1275",
.names = { "sparc64-ieee1275-raw", NULL },
.voidp_sizeof = 8,
.bigendian = 1,
.id = IMAGE_SPARC64_RAW,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR,
.mod_align = GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN,
},
{
.dirname = "sparc64-ieee1275",
.names = { "sparc64-ieee1275-cdcore", NULL },
.voidp_sizeof = 8,
.bigendian = 1,
.id = IMAGE_SPARC64_CDCORE,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR,
.mod_align = GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN,
},
{
.dirname = "sparc64-ieee1275",
.names = { "sparc64-ieee1275-aout", NULL },
.voidp_sizeof = 8,
.bigendian = 1,
.id = IMAGE_SPARC64_AOUT,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR,
.mod_align = GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN,
},
{
.dirname = "ia64-efi",
.names = {"ia64-efi", NULL},
.voidp_sizeof = 8,
.bigendian = 0,
.id = IMAGE_EFI,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_PE32_SECTION_ALIGNMENT,
.vaddr_offset = EFI64_HEADER_SIZE,
.pe_target = GRUB_PE32_MACHINE_IA64,
.elf_target = EM_IA_64,
},
{
.dirname = "mips-arc",
.names = {"mips-arc", NULL},
.voidp_sizeof = 4,
.bigendian = 1,
.id = IMAGE_MIPS_ARC,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "mipsel-arc",
.names = {"mipsel-arc", NULL},
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_MIPS_ARC,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPSEL_ARC_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "mipsel-qemu_mips",
.names = { "mipsel-qemu_mips-elf", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_LOONGSON_ELF,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "mips-qemu_mips",
.names = { "mips-qemu_mips-flash", NULL },
.voidp_sizeof = 4,
.bigendian = 1,
.id = IMAGE_QEMU_MIPS_FLASH,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "mipsel-qemu_mips",
.names = { "mipsel-qemu_mips-flash", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_QEMU_MIPS_FLASH,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "mips-qemu_mips",
.names = { "mips-qemu_mips-elf", NULL },
.voidp_sizeof = 4,
.bigendian = 1,
.id = IMAGE_LOONGSON_ELF,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE,
.decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE,
.decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR,
.section_align = 1,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN,
.default_compression = GRUB_COMPRESSION_NONE
},
{
.dirname = "arm-uboot",
.names = { "arm-uboot", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_UBOOT,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
.vaddr_offset = 0,
.link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR,
.elf_target = EM_ARM,
.mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP,
.mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
.link_align = 4
},
{
.dirname = "arm-efi",
.names = { "arm-efi", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_EFI,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_PE32_SECTION_ALIGNMENT,
.vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE
+ GRUB_PE32_SIGNATURE_SIZE
+ sizeof (struct grub_pe32_coff_header)
+ sizeof (struct grub_pe32_optional_header)
+ 4 * sizeof (struct grub_pe32_section_table),
GRUB_PE32_SECTION_ALIGNMENT),
.pe_target = GRUB_PE32_MACHINE_ARMTHUMB_MIXED,
.elf_target = EM_ARM,
},
{
.dirname = "arm64-efi",
.names = { "arm64-efi", NULL },
.voidp_sizeof = 8,
.bigendian = 0,
.id = IMAGE_EFI,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = TARGET_NO_FIELD,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_PE32_SECTION_ALIGNMENT,
.vaddr_offset = EFI64_HEADER_SIZE,
.pe_target = GRUB_PE32_MACHINE_ARM64,
.elf_target = EM_AARCH64,
},
};
#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_IEEE1275_NOTE_NAME "PowerPC"
#define GRUB_IEEE1275_NOTE_TYPE 0x1275
/* 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;
};
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"
#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
#include <grub/lib/LzmaEnc.h>
static void *SzAlloc(void *p __attribute__ ((unused)), size_t size) { return xmalloc(size); }
static void SzFree(void *p __attribute__ ((unused)), void *address) { free(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
static void
compress_kernel_lzma (char *kernel_img, size_t kernel_size,
char **core_img, size_t *core_size)
{
CLzmaEncProps props;
unsigned char out_props[5];
size_t out_props_size = 5;
LzmaEncProps_Init(&props);
props.dictSize = 1 << 16;
props.lc = 3;
props.lp = 0;
props.pb = 2;
props.numThreads = 1;
*core_img = xmalloc (kernel_size);
*core_size = kernel_size;
if (LzmaEncode ((unsigned char *) *core_img, core_size,
(unsigned char *) kernel_img,
kernel_size,
&props, out_props, &out_props_size,
0, NULL, &g_Alloc, &g_Alloc) != SZ_OK)
grub_util_error ("%s", _("cannot compress the kernel image"));
}
#ifdef USE_LIBLZMA
static void
compress_kernel_xz (char *kernel_img, size_t kernel_size,
char **core_img, size_t *core_size)
{
lzma_stream strm = LZMA_STREAM_INIT;
lzma_ret xzret;
lzma_options_lzma lzopts = {
.dict_size = 1 << 16,
.preset_dict = NULL,
.preset_dict_size = 0,
.lc = 3,
.lp = 0,
.pb = 2,
.mode = LZMA_MODE_NORMAL,
.nice_len = 64,
.mf = LZMA_MF_BT4,
.depth = 0,
};
lzma_filter fltrs[] = {
{ .id = LZMA_FILTER_LZMA2, .options = &lzopts},
{ .id = LZMA_VLI_UNKNOWN, .options = NULL}
};
xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE);
if (xzret != LZMA_OK)
grub_util_error ("%s", _("cannot compress the kernel image"));
*core_img = xmalloc (kernel_size);
*core_size = kernel_size;
strm.next_in = (unsigned char *) kernel_img;
strm.avail_in = kernel_size;
strm.next_out = (unsigned char *) *core_img;
strm.avail_out = *core_size;
while (1)
{
xzret = lzma_code (&strm, LZMA_FINISH);
if (xzret == LZMA_OK)
continue;
if (xzret == LZMA_STREAM_END)
break;
grub_util_error ("%s", _("cannot compress the kernel image"));
}
*core_size -= strm.avail_out;
}
#endif
static void
compress_kernel (const struct grub_install_image_target_desc *image_target, char *kernel_img,
size_t kernel_size, char **core_img, size_t *core_size,
grub_compression_t comp)
{
if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
&& (comp == GRUB_COMPRESSION_LZMA))
{
compress_kernel_lzma (kernel_img, kernel_size, core_img,
core_size);
return;
}
#ifdef USE_LIBLZMA
if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
&& (comp == GRUB_COMPRESSION_XZ))
{
compress_kernel_xz (kernel_img, kernel_size, core_img,
core_size);
return;
}
#endif
if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
&& (comp != GRUB_COMPRESSION_NONE))
grub_util_error (_("unknown compression %d"), comp);
*core_img = xmalloc (kernel_size);
memcpy (*core_img, kernel_img, kernel_size);
*core_size = kernel_size;
}
struct fixup_block_list
{
struct fixup_block_list *next;
int state;
struct grub_pe32_fixup_block b;
};
/*
* 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;
}
#pragma GCC diagnostic ignored "-Wcast-align"
#define MKIMAGE_ELF32 1
#include "grub-mkimagexx.c"
#undef MKIMAGE_ELF32
#define MKIMAGE_ELF64 1
#include "grub-mkimagexx.c"
#undef MKIMAGE_ELF64
const struct grub_install_image_target_desc *
grub_install_get_image_target (const char *arg)
{
unsigned i, j;
for (i = 0; i < ARRAY_SIZE (image_targets); i++)
for (j = 0; j < ARRAY_SIZE (image_targets[i].names) &&
image_targets[i].names[j]; j++)
if (strcmp (arg, image_targets[i].names[j]) == 0)
return &image_targets[i];
return NULL;
}
const char *
grub_util_get_target_dirname (const struct grub_install_image_target_desc *t)
{
return t->dirname;
}
const char *
grub_util_get_target_name (const struct grub_install_image_target_desc *t)
{
return t->names[0];
}
char *
grub_install_get_image_targets_string (void)
{
int format_len = 0;
char *formats;
char *ptr;
unsigned i;
for (i = 0; i < ARRAY_SIZE (image_targets); i++)
format_len += strlen (image_targets[i].names[0]) + 2;
ptr = formats = xmalloc (format_len);
for (i = 0; i < ARRAY_SIZE (image_targets); i++)
{
strcpy (ptr, image_targets[i].names[0]);
ptr += strlen (image_targets[i].names[0]);
*ptr++ = ',';
*ptr++ = ' ';
}
ptr[-2] = 0;
return formats;
}
void
grub_install_generate_image (const char *dir, const char *prefix,
FILE *out, const char *outname, char *mods[],
char *memdisk_path, char **pubkey_paths,
size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc *image_target,
int note,
grub_compression_t comp)
{
char *kernel_img, *core_img;
size_t kernel_size, total_module_size, core_size, exec_size;
size_t memdisk_size = 0, config_size = 0;
size_t prefix_size = 0;
char *kernel_path;
size_t offset;
struct grub_util_path_list *path_list, *p, *next;
size_t bss_size;
grub_uint64_t start_address;
void *rel_section = 0;
size_t reloc_size = 0, align;
size_t decompress_size = 0;
if (comp == GRUB_COMPRESSION_AUTO)
comp = image_target->default_compression;
if (image_target->id == IMAGE_I386_PC
|| image_target->id == IMAGE_I386_PC_PXE
|| image_target->id == IMAGE_I386_PC_ELTORITO)
comp = GRUB_COMPRESSION_LZMA;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
kernel_path = grub_util_get_path (dir, "kernel.img");
if (image_target->voidp_sizeof == 8)
total_module_size = sizeof (struct grub_module_info64);
else
total_module_size = sizeof (struct grub_module_info32);
{
size_t i;
for (i = 0; i < npubkeys; i++)
{
size_t curs;
curs = ALIGN_ADDR (grub_util_get_image_size (pubkey_paths[i]));
grub_util_info ("the size of public key %u is 0x%"
GRUB_HOST_PRIxLONG_LONG,
(unsigned) i, (unsigned long long) curs);
total_module_size += curs + sizeof (struct grub_module_header);
}
}
if (memdisk_path)
{
memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
grub_util_info ("the size of memory disk is 0x%" GRUB_HOST_PRIxLONG_LONG,
(unsigned long long) memdisk_size);
total_module_size += memdisk_size + sizeof (struct grub_module_header);
}
if (config_path)
{
config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
grub_util_info ("the size of config file is 0x%" GRUB_HOST_PRIxLONG_LONG,
(unsigned long long) config_size);
total_module_size += config_size + sizeof (struct grub_module_header);
}
if (prefix)
{
prefix_size = ALIGN_ADDR (strlen (prefix) + 1);
total_module_size += prefix_size + sizeof (struct grub_module_header);
}
for (p = path_list; p; p = p->next)
total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name))
+ sizeof (struct grub_module_header));
grub_util_info ("the total module size is 0x%" GRUB_HOST_PRIxLONG_LONG,
(unsigned long long) total_module_size);
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, &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, &align, image_target);
if (image_target->id == IMAGE_XEN && align < 4096)
align = 4096;
if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
&& (image_target->total_module_size != TARGET_NO_FIELD))
*((grub_uint32_t *) (kernel_img + image_target->total_module_size))
= grub_host_to_target32 (total_module_size);
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
{
memmove (kernel_img + total_module_size, kernel_img, kernel_size);
memset (kernel_img, 0, total_module_size);
}
if (image_target->voidp_sizeof == 8)
{
/* Fill in the grub_module_info structure. */
struct grub_module_info64 *modinfo;
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
modinfo = (struct grub_module_info64 *) kernel_img;
else
modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
modinfo->size = grub_host_to_target_addr (total_module_size);
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
offset = sizeof (struct grub_module_info64);
else
offset = kernel_size + sizeof (struct grub_module_info64);
}
else
{
/* Fill in the grub_module_info structure. */
struct grub_module_info32 *modinfo;
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
modinfo = (struct grub_module_info32 *) kernel_img;
else
modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
modinfo->size = grub_host_to_target_addr (total_module_size);
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
offset = sizeof (struct grub_module_info32);
else
offset = kernel_size + sizeof (struct grub_module_info32);
}
for (p = path_list; p; p = p->next)
{
struct grub_module_header *header;
size_t mod_size;
mod_size = ALIGN_ADDR (grub_util_get_image_size (p->name));
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_host_to_target32 (OBJ_TYPE_ELF);
header->size = grub_host_to_target32 (mod_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (p->name, kernel_img + offset);
offset += mod_size;
}
{
size_t i;
for (i = 0; i < npubkeys; i++)
{
size_t curs;
struct grub_module_header *header;
curs = grub_util_get_image_size (pubkey_paths[i]);
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
header->size = grub_host_to_target32 (curs + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (pubkey_paths[i], kernel_img + offset);
offset += ALIGN_ADDR (curs);
}
}
if (memdisk_path)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_host_to_target32 (OBJ_TYPE_MEMDISK);
header->size = grub_host_to_target32 (memdisk_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (memdisk_path, kernel_img + offset);
offset += memdisk_size;
}
if (config_path)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_host_to_target32 (OBJ_TYPE_CONFIG);
header->size = grub_host_to_target32 (config_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (config_path, kernel_img + offset);
offset += config_size;
}
if (prefix)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX);
header->size = grub_host_to_target32 (prefix_size + sizeof (*header));
offset += sizeof (*header);
grub_strcpy (kernel_img + offset, prefix);
offset += prefix_size;
}
grub_util_info ("kernel_img=%p, kernel_size=0x%" GRUB_HOST_PRIxLONG_LONG,
kernel_img,
(unsigned long long) kernel_size);
compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
&core_img, &core_size, comp);
free (kernel_img);
grub_util_info ("the core size is 0x%" GRUB_HOST_PRIxLONG_LONG,
(unsigned long long) core_size);
if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
&& image_target->total_module_size != TARGET_NO_FIELD)
*((grub_uint32_t *) (core_img + image_target->total_module_size))
= grub_host_to_target32 (total_module_size);
if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
{
char *full_img;
size_t full_size;
char *decompress_path, *decompress_img;
const char *name;
switch (comp)
{
case GRUB_COMPRESSION_XZ:
name = "xz_decompress.img";
break;
case GRUB_COMPRESSION_LZMA:
name = "lzma_decompress.img";
break;
case GRUB_COMPRESSION_NONE:
name = "none_decompress.img";
break;
default:
grub_util_error (_("unknown compression %d"), comp);
}
decompress_path = grub_util_get_path (dir, name);
decompress_size = grub_util_get_image_size (decompress_path);
decompress_img = grub_util_read_image (decompress_path);
if ((image_target->id == IMAGE_I386_PC
|| image_target->id == IMAGE_I386_PC_PXE
|| image_target->id == IMAGE_I386_PC_ELTORITO)
&& decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200)
grub_util_error ("%s", _("Decompressor is too big"));
if (image_target->decompressor_compressed_size != TARGET_NO_FIELD)
*((grub_uint32_t *) (decompress_img
+ image_target->decompressor_compressed_size))
= grub_host_to_target32 (core_size);
if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD)
*((grub_uint32_t *) (decompress_img
+ image_target->decompressor_uncompressed_size))
= grub_host_to_target32 (kernel_size + total_module_size);
if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD)
{
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
*((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
= grub_host_to_target_addr (image_target->link_addr - total_module_size);
else
*((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr))
= grub_host_to_target_addr (image_target->link_addr);
}
full_size = core_size + decompress_size;
full_img = xmalloc (full_size);
memcpy (full_img, decompress_img, decompress_size);
memcpy (full_img + decompress_size, core_img, core_size);
free (core_img);
core_img = full_img;
core_size = full_size;
free (decompress_img);
free (decompress_path);
}
switch (image_target->id)
{
case IMAGE_I386_PC:
case IMAGE_I386_PC_PXE:
case IMAGE_I386_PC_ELTORITO:
if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000
|| (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))
|| (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
grub_util_error (_("core image is too big (0x%x > 0x%x)"),
GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size,
0x78000);
/* fallthrough */
case IMAGE_COREBOOT:
case IMAGE_QEMU:
if (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
(unsigned) kernel_size + (unsigned) bss_size
+ GRUB_KERNEL_I386_PC_LINK_ADDR,
0x68000);
break;
case IMAGE_LOONGSON_ELF:
case IMAGE_YEELOONG_FLASH:
case IMAGE_FULOONG2F_FLASH:
case IMAGE_EFI:
case IMAGE_MIPS_ARC:
case IMAGE_QEMU_MIPS_FLASH:
case IMAGE_XEN:
break;
case IMAGE_SPARC64_AOUT:
case IMAGE_SPARC64_RAW:
case IMAGE_SPARC64_CDCORE:
case IMAGE_I386_IEEE1275:
case IMAGE_PPC:
case IMAGE_UBOOT:
break;
}
switch (image_target->id)
{
case IMAGE_I386_PC:
case IMAGE_I386_PC_PXE:
case IMAGE_I386_PC_ELTORITO:
{
unsigned num;
char *boot_path, *boot_img;
size_t boot_size;
num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
if (image_target->id == IMAGE_I386_PC_PXE)
{
char *pxeboot_path, *pxeboot_img;
size_t pxeboot_size;
grub_uint32_t *ptr;
pxeboot_path = grub_util_get_path (dir, "pxeboot.img");
pxeboot_size = grub_util_get_image_size (pxeboot_path);
pxeboot_img = grub_util_read_image (pxeboot_path);
grub_util_write_image (pxeboot_img, pxeboot_size, out,
outname);
free (pxeboot_img);
free (pxeboot_path);
/* Remove Multiboot header to avoid confusing ipxe. */
for (ptr = (grub_uint32_t *) core_img;
ptr < (grub_uint32_t *) (core_img + MULTIBOOT_SEARCH); ptr++)
if (*ptr == grub_host_to_target32 (MULTIBOOT_HEADER_MAGIC)
&& grub_target_to_host32 (ptr[0])
+ grub_target_to_host32 (ptr[1])
+ grub_target_to_host32 (ptr[2]) == 0)
{
*ptr = 0;
break;
}
}
if (image_target->id == IMAGE_I386_PC_ELTORITO)
{
char *eltorito_path, *eltorito_img;
size_t eltorito_size;
eltorito_path = grub_util_get_path (dir, "cdboot.img");
eltorito_size = grub_util_get_image_size (eltorito_path);
eltorito_img = grub_util_read_image (eltorito_path);
grub_util_write_image (eltorito_img, eltorito_size, out,
outname);
free (eltorito_img);
free (eltorito_path);
}
boot_path = grub_util_get_path (dir, "diskboot.img");
boot_size = grub_util_get_image_size (boot_path);
if (boot_size != GRUB_DISK_SECTOR_SIZE)
grub_util_error (_("diskboot.img size must be %u bytes"),
GRUB_DISK_SECTOR_SIZE);
boot_img = grub_util_read_image (boot_path);
{
struct grub_pc_bios_boot_blocklist *block;
block = (struct grub_pc_bios_boot_blocklist *) (boot_img
+ GRUB_DISK_SECTOR_SIZE
- sizeof (*block));
block->len = grub_host_to_target16 (num);
/* This is filled elsewhere. Verify it just in case. */
assert (block->segment
== grub_host_to_target16 (GRUB_BOOT_I386_PC_KERNEL_SEG
+ (GRUB_DISK_SECTOR_SIZE >> 4)));
}
grub_util_write_image (boot_img, boot_size, out, outname);
free (boot_img);
free (boot_path);
}
break;
case IMAGE_EFI:
{
void *pe_img;
grub_uint8_t *header;
void *sections;
size_t pe_size;
struct grub_pe32_coff_header *c;
struct grub_pe32_section_table *text_section, *data_section;
struct grub_pe32_section_table *mods_section, *reloc_section;
static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
int header_size;
int reloc_addr;
if (image_target->voidp_sizeof == 4)
header_size = EFI32_HEADER_SIZE;
else
header_size = EFI64_HEADER_SIZE;
reloc_addr = ALIGN_UP (header_size + core_size,
image_target->section_align);
pe_size = ALIGN_UP (reloc_addr + reloc_size,
image_target->section_align);
pe_img = xmalloc (reloc_addr + reloc_size);
memset (pe_img, 0, header_size);
memcpy ((char *) pe_img + header_size, core_img, core_size);
memset ((char *) pe_img + header_size + core_size, 0, reloc_addr - (header_size + core_size));
memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size);
header = pe_img;
/* The magic. */
memcpy (header, stub, GRUB_PE32_MSDOS_STUB_SIZE);
memcpy (header + GRUB_PE32_MSDOS_STUB_SIZE, "PE\0\0",
GRUB_PE32_SIGNATURE_SIZE);
/* The COFF file header. */
c = (struct grub_pe32_coff_header *) (header + GRUB_PE32_MSDOS_STUB_SIZE
+ GRUB_PE32_SIGNATURE_SIZE);
c->machine = grub_host_to_target16 (image_target->pe_target);
c->num_sections = grub_host_to_target16 (4);
c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP);
c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
| GRUB_PE32_LINE_NUMS_STRIPPED
| ((image_target->voidp_sizeof == 4)
? GRUB_PE32_32BIT_MACHINE
: 0)
| GRUB_PE32_LOCAL_SYMS_STRIPPED
| GRUB_PE32_DEBUG_STRIPPED);
/* The PE Optional header. */
if (image_target->voidp_sizeof == 4)
{
struct grub_pe32_optional_header *o;
c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe32_optional_header));
o = (struct grub_pe32_optional_header *)
(header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
+ sizeof (struct grub_pe32_coff_header));
o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
o->code_size = grub_host_to_target32 (exec_size);
o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
- header_size);
o->bss_size = grub_cpu_to_le32 (bss_size);
o->entry_addr = grub_cpu_to_le32 (start_address);
o->code_base = grub_cpu_to_le32 (header_size);
o->data_base = grub_host_to_target32 (header_size + exec_size);
o->image_base = 0;
o->section_alignment = grub_host_to_target32 (image_target->section_align);
o->file_alignment = grub_host_to_target32 (image_target->section_align);
o->image_size = grub_host_to_target32 (pe_size);
o->header_size = grub_host_to_target32 (header_size);
o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
/* Do these really matter? */
o->stack_reserve_size = grub_host_to_target32 (0x10000);
o->stack_commit_size = grub_host_to_target32 (0x10000);
o->heap_reserve_size = grub_host_to_target32 (0x10000);
o->heap_commit_size = grub_host_to_target32 (0x10000);
o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
sections = o + 1;
}
else
{
struct grub_pe64_optional_header *o;
c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
o = (struct grub_pe64_optional_header *)
(header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
+ sizeof (struct grub_pe32_coff_header));
o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
o->code_size = grub_host_to_target32 (exec_size);
o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
- header_size);
o->bss_size = grub_cpu_to_le32 (bss_size);
o->entry_addr = grub_cpu_to_le32 (start_address);
o->code_base = grub_cpu_to_le32 (header_size);
o->image_base = 0;
o->section_alignment = grub_host_to_target32 (image_target->section_align);
o->file_alignment = grub_host_to_target32 (image_target->section_align);
o->image_size = grub_host_to_target32 (pe_size);
o->header_size = grub_host_to_target32 (header_size);
o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
/* Do these really matter? */
o->stack_reserve_size = grub_host_to_target64 (0x10000);
o->stack_commit_size = grub_host_to_target64 (0x10000);
o->heap_reserve_size = grub_host_to_target64 (0x10000);
o->heap_commit_size = grub_host_to_target64 (0x10000);
o->num_data_directories
= grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
sections = o + 1;
}
/* The sections. */
text_section = sections;
strcpy (text_section->name, ".text");
text_section->virtual_size = grub_cpu_to_le32 (exec_size);
text_section->virtual_address = grub_cpu_to_le32 (header_size);
text_section->raw_data_size = grub_cpu_to_le32 (exec_size);
text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
text_section->characteristics = grub_cpu_to_le32_compile_time (
GRUB_PE32_SCN_CNT_CODE
| GRUB_PE32_SCN_MEM_EXECUTE
| GRUB_PE32_SCN_MEM_READ);
data_section = text_section + 1;
strcpy (data_section->name, ".data");
data_section->virtual_size = grub_cpu_to_le32 (kernel_size - exec_size);
data_section->virtual_address = grub_cpu_to_le32 (header_size + exec_size);
data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size);
data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size);
data_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_READ
| GRUB_PE32_SCN_MEM_WRITE);
#if 0
bss_section = data_section + 1;
strcpy (bss_section->name, ".bss");
bss_section->virtual_size = grub_cpu_to_le32 (bss_size);
bss_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size);
bss_section->raw_data_size = 0;
bss_section->raw_data_offset = 0;
bss_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_MEM_READ
| GRUB_PE32_SCN_MEM_WRITE
| GRUB_PE32_SCN_ALIGN_64BYTES
| GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| 0x80);
#endif
mods_section = data_section + 1;
strcpy (mods_section->name, "mods");
mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
mods_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size + bss_size);
mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size);
mods_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_READ
| GRUB_PE32_SCN_MEM_WRITE);
reloc_section = mods_section + 1;
strcpy (reloc_section->name, ".reloc");
reloc_section->virtual_size = grub_cpu_to_le32 (reloc_size);
reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + bss_size);
reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size);
reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
reloc_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_DISCARDABLE
| GRUB_PE32_SCN_MEM_READ);
free (core_img);
core_img = pe_img;
core_size = pe_size;
}
break;
case IMAGE_QEMU:
{
char *rom_img;
size_t rom_size;
char *boot_path, *boot_img;
size_t boot_size;
boot_path = grub_util_get_path (dir, "boot.img");
boot_size = grub_util_get_image_size (boot_path);
boot_img = grub_util_read_image (boot_path);
/* Rom sizes must be 64k-aligned. */
rom_size = ALIGN_UP (core_size + boot_size, 64 * 1024);
rom_img = xmalloc (rom_size);
memset (rom_img, 0, rom_size);
*((grub_int32_t *) (core_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR))
= grub_host_to_target32 ((grub_uint32_t) -rom_size);
memcpy (rom_img, core_img, core_size);
*((grub_int32_t *) (boot_img + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR))
= grub_host_to_target32 ((grub_uint32_t) -rom_size);
memcpy (rom_img + rom_size - boot_size, boot_img, boot_size);
free (core_img);
core_img = rom_img;
core_size = rom_size;
free (boot_img);
free (boot_path);
}
break;
case IMAGE_SPARC64_AOUT:
{
void *aout_img;
size_t aout_size;
struct grub_aout32_header *aout_head;
aout_size = core_size + sizeof (*aout_head);
aout_img = xmalloc (aout_size);
aout_head = aout_img;
grub_memset (aout_head, 0, sizeof (*aout_head));
aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16)
| AOUT32_OMAGIC);
aout_head->a_text = grub_host_to_target32 (core_size);
aout_head->a_entry
= grub_host_to_target32 (GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS);
memcpy ((char *) aout_img + sizeof (*aout_head), core_img, core_size);
free (core_img);
core_img = aout_img;
core_size = aout_size;
}
break;
case IMAGE_SPARC64_RAW:
{
unsigned int num;
char *boot_path, *boot_img;
size_t boot_size;
num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
num <<= GRUB_DISK_SECTOR_BITS;
boot_path = grub_util_get_path (dir, "diskboot.img");
boot_size = grub_util_get_image_size (boot_path);
if (boot_size != GRUB_DISK_SECTOR_SIZE)
grub_util_error (_("diskboot.img size must be %u bytes"),
GRUB_DISK_SECTOR_SIZE);
boot_img = grub_util_read_image (boot_path);
*((grub_uint32_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
- GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE + 8))
= grub_host_to_target32 (num);
grub_util_write_image (boot_img, boot_size, out, outname);
free (boot_img);
free (boot_path);
}
break;
case IMAGE_SPARC64_CDCORE:
break;
case IMAGE_YEELOONG_FLASH:
case IMAGE_FULOONG2F_FLASH:
{
char *rom_img;
size_t rom_size;
char *boot_path, *boot_img;
size_t boot_size;
/* fwstart.img is the only part which can't be tested by using *-elf
target. Check it against the checksum. */
const grub_uint8_t yeeloong_fwstart_good_hash[512 / 8] =
{
0x5f, 0x67, 0x46, 0x57, 0x31, 0x30, 0xc5, 0x0a,
0xe9, 0x98, 0x18, 0xc9, 0xf3, 0xca, 0x45, 0xa5,
0x75, 0x64, 0x6b, 0xbb, 0x24, 0xcd, 0xb4, 0xbc,
0xf2, 0x3e, 0x23, 0xf9, 0xc2, 0x6a, 0x8c, 0xde,
0x3b, 0x94, 0x9c, 0xcc, 0xa5, 0xa7, 0x58, 0xb1,
0xbe, 0x8b, 0x3d, 0x73, 0x98, 0x18, 0x7e, 0x68,
0x5e, 0x5f, 0x23, 0x7d, 0x7a, 0xe8, 0x51, 0xf7,
0x1a, 0xaf, 0x2f, 0x54, 0x11, 0x2e, 0x5c, 0x25
};
const grub_uint8_t fuloong2f_fwstart_good_hash[512 / 8] =
{
0x76, 0x9b, 0xad, 0x6e, 0xa2, 0x39, 0x47, 0x62,
0x1f, 0xc9, 0x3a, 0x6d, 0x05, 0x5c, 0x43, 0x5c,
0x29, 0x4a, 0x7e, 0x08, 0x2a, 0x31, 0x8f, 0x5d,
0x02, 0x84, 0xa0, 0x85, 0xf2, 0xd1, 0xb9, 0x53,
0xa2, 0xbc, 0xf2, 0xe1, 0x39, 0x1e, 0x51, 0xb5,
0xaf, 0xec, 0x9e, 0xf2, 0xf1, 0xf3, 0x0a, 0x2f,
0xe6, 0xf1, 0x08, 0x89, 0xbe, 0xbc, 0x73, 0xab,
0x46, 0x50, 0xd6, 0x21, 0xce, 0x8e, 0x24, 0xa7
};
const grub_uint8_t *fwstart_good_hash;
grub_uint8_t fwstart_hash[512 / 8];
if (image_target->id == IMAGE_FULOONG2F_FLASH)
{
fwstart_good_hash = fuloong2f_fwstart_good_hash;
boot_path = grub_util_get_path (dir, "fwstart_fuloong2f.img");
}
else
{
fwstart_good_hash = yeeloong_fwstart_good_hash;
boot_path = grub_util_get_path (dir, "fwstart.img");
}
boot_size = grub_util_get_image_size (boot_path);
boot_img = grub_util_read_image (boot_path);
grub_crypto_hash (GRUB_MD_SHA512, fwstart_hash, boot_img, boot_size);
if (grub_memcmp (fwstart_hash, fwstart_good_hash,
GRUB_MD_SHA512->mdlen) != 0)
/* TRANSLATORS: fwstart.img may still be good, just it wasn't checked. */
grub_util_warn ("%s",
_("fwstart.img doesn't match the known good version. "
"proceed at your own risk"));
if (core_size + boot_size > 512 * 1024)
grub_util_error ("%s", _("firmware image is too big"));
rom_size = 512 * 1024;
rom_img = xmalloc (rom_size);
memset (rom_img, 0, rom_size);
memcpy (rom_img, boot_img, boot_size);
memcpy (rom_img + boot_size, core_img, core_size);
memset (rom_img + boot_size + core_size, 0,
rom_size - (boot_size + core_size));
free (core_img);
core_img = rom_img;
core_size = rom_size;
free (boot_img);
free (boot_path);
}
break;
case IMAGE_QEMU_MIPS_FLASH:
{
char *rom_img;
size_t rom_size;
if (core_size > 512 * 1024)
grub_util_error ("%s", _("firmware image is too big"));
rom_size = 512 * 1024;
rom_img = xmalloc (rom_size);
memset (rom_img, 0, rom_size);
memcpy (rom_img, core_img, core_size);
memset (rom_img + core_size, 0,
rom_size - core_size);
free (core_img);
core_img = rom_img;
core_size = rom_size;
}
break;
case IMAGE_UBOOT:
{
struct grub_uboot_image_header *hdr;
hdr = xmalloc (core_size + sizeof (struct grub_uboot_image_header));
memcpy (hdr + 1, core_img, core_size);
memset (hdr, 0, sizeof (*hdr));
hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
hdr->ih_time = grub_cpu_to_be32 (STABLE_EMBEDDING_TIMESTAMP);
hdr->ih_size = grub_cpu_to_be32 (core_size);
hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr);
hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr);
hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL;
hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX;
hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM;
hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE;
grub_crypto_hash (GRUB_MD_CRC32, &hdr->ih_dcrc, hdr + 1, core_size);
grub_crypto_hash (GRUB_MD_CRC32, &hdr->ih_hcrc, hdr, sizeof (*hdr));
free (core_img);
core_img = (char *) hdr;
core_size += sizeof (struct grub_uboot_image_header);
}
break;
case IMAGE_MIPS_ARC:
{
char *ecoff_img;
struct ecoff_header {
grub_uint16_t magic;
grub_uint16_t nsec;
grub_uint32_t time;
grub_uint32_t syms;
grub_uint32_t nsyms;
grub_uint16_t opt;
grub_uint16_t flags;
grub_uint16_t magic2;
grub_uint16_t version;
grub_uint32_t textsize;
grub_uint32_t datasize;
grub_uint32_t bsssize;
grub_uint32_t entry;
grub_uint32_t text_start;
grub_uint32_t data_start;
grub_uint32_t bss_start;
grub_uint32_t gprmask;
grub_uint32_t cprmask[4];
grub_uint32_t gp_value;
};
struct ecoff_section
{
char name[8];
grub_uint32_t paddr;
grub_uint32_t vaddr;
grub_uint32_t size;
grub_uint32_t file_offset;
grub_uint32_t reloc;
grub_uint32_t gp;
grub_uint16_t nreloc;
grub_uint16_t ngp;
grub_uint32_t flags;
};
struct ecoff_header *head;
struct ecoff_section *section;
grub_uint32_t target_addr;
size_t program_size;
program_size = ALIGN_ADDR (core_size);
if (comp == GRUB_COMPRESSION_NONE)
target_addr = (image_target->link_addr - decompress_size);
else
target_addr = ALIGN_UP (image_target->link_addr
+ kernel_size + total_module_size, 32);
ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
head = (void *) ecoff_img;
section = (void *) (head + 1);
head->magic = image_target->bigendian ? grub_host_to_target16 (0x160)
: grub_host_to_target16 (0x166);
head->nsec = grub_host_to_target16 (1);
head->time = grub_host_to_target32 (0);
head->opt = grub_host_to_target16 (0x38);
head->flags = image_target->bigendian
? grub_host_to_target16 (0x207)
: grub_host_to_target16 (0x103);
head->magic2 = grub_host_to_target16 (0x107);
head->textsize = grub_host_to_target32 (program_size);
head->entry = grub_host_to_target32 (target_addr);
head->text_start = grub_host_to_target32 (target_addr);
head->data_start = grub_host_to_target32 (target_addr + program_size);
grub_memcpy (section->name, ".text", sizeof (".text") - 1);
section->vaddr = grub_host_to_target32 (target_addr);
section->size = grub_host_to_target32 (program_size);
section->file_offset = grub_host_to_target32 (sizeof (*head) + sizeof (*section));
if (!image_target->bigendian)
{
section->paddr = grub_host_to_target32 (0xaa60);
section->flags = grub_host_to_target32 (0x20);
}
memcpy (section + 1, core_img, core_size);
free (core_img);
core_img = ecoff_img;
core_size = program_size + sizeof (*head) + sizeof (*section);
}
break;
case IMAGE_LOONGSON_ELF:
case IMAGE_PPC:
case IMAGE_XEN:
case IMAGE_COREBOOT:
case IMAGE_I386_IEEE1275:
{
grub_uint64_t target_addr;
if (image_target->id == IMAGE_LOONGSON_ELF)
{
if (comp == GRUB_COMPRESSION_NONE)
target_addr = (image_target->link_addr - decompress_size);
else
target_addr = ALIGN_UP (image_target->link_addr
+ kernel_size + total_module_size, 32);
}
else
target_addr = image_target->link_addr;
if (image_target->voidp_sizeof == 4)
generate_elf32 (image_target, note, &core_img, &core_size,
target_addr, align, kernel_size, bss_size);
else
generate_elf64 (image_target, note, &core_img, &core_size,
target_addr, align, kernel_size, bss_size);
}
break;
}
grub_util_write_image (core_img, core_size, out, outname);
free (core_img);
free (kernel_path);
free (rel_section);
while (path_list)
{
next = path_list->next;
free ((void *) path_list->name);
free (path_list);
path_list = next;
}
}