From ec16e02639930c32ea6d97f9529a805130c72701 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 15 Oct 2013 19:14:55 +0200 Subject: [PATCH] * util/grub-mkimage.c: Move backend part to ... * util/mkimage.c: ... here. --- ChangeLog | 5 + Makefile.util.def | 1 + include/grub/util/install.h | 29 + util/grub-mkimage.c | 1832 +--------------------------------- util/grub-mkimagexx.c | 24 +- util/mkimage.c | 1865 +++++++++++++++++++++++++++++++++++ 6 files changed, 1931 insertions(+), 1825 deletions(-) create mode 100644 util/mkimage.c diff --git a/ChangeLog b/ChangeLog index 803942412..25a0c3848 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-10-15 Vladimir Serbinenko + + * util/grub-mkimage.c: Move backend part to ... + * util/mkimage.c: ... here. + 2013-10-15 Vladimir Serbinenko Allow compilation with mingw64 albeit with warnings due to lack of diff --git a/Makefile.util.def b/Makefile.util.def index 0e7974ffe..ea1d05800 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -160,6 +160,7 @@ program = { mansection = 1; common = util/grub-mkimage.c; + common = util/mkimage.c; common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/osdep/init.c; diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 36f84be5a..bcce6b278 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -25,6 +25,30 @@ #include #include #include + +typedef enum { + GRUB_COMPRESSION_AUTO, + GRUB_COMPRESSION_NONE, + GRUB_COMPRESSION_XZ, + GRUB_COMPRESSION_LZMA +} grub_compression_t; + +struct grub_install_image_target_desc; + +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); + +const struct grub_install_image_target_desc * +grub_install_get_image_target (const char *arg); + void grub_util_bios_setup (const char *dir, const char *boot_file, const char *core_file, @@ -36,6 +60,11 @@ grub_util_sparc_setup (const char *dir, const char *dest, int force, int fs_probe, int allow_floppy); +char * +grub_install_get_image_targets_string (void); + +const char * +grub_util_get_target_dirname (const struct grub_install_image_target_desc *t); void grub_install_get_blocklist (grub_device_t root_dev, diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 8819323a2..6e1e424db 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -44,1786 +44,13 @@ #include #include #include +#include #define _GNU_SOURCE 1 #include #include "progname.h" -#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) - -#ifdef HAVE_LIBLZMA -#include -#endif - -#define TARGET_NO_FIELD 0xffffffff - -typedef enum { - COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ, COMPRESSION_LZMA -} grub_compression_t; - -struct 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 - } 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) - -struct 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 = 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 = 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 = "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 = 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 = 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 = 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 - }, - { - .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 - }, - { - .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 - }, - { - .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 = 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 = 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 = 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 = 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 = 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 = 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, - }, - }; - -#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 (struct 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 (struct 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 (struct 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 (struct 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 (struct 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 (struct 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 (struct 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 (struct 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_hdr -{ - grub_uint32_t namesz; - grub_uint32_t descsz; - grub_uint32_t type; - char name[sizeof (GRUB_IEEE1275_NOTE_NAME)]; -}; - -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 -{ - struct grub_ieee1275_note_hdr header; - struct grub_ieee1275_note_desc descriptor; -}; - -#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val)) - -#include - -static void *SzAlloc(void *p, size_t size) { p = p; return xmalloc(size); } -static void SzFree(void *p, void *address) { p = p; 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 HAVE_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 (struct 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 == COMPRESSION_LZMA)) - { - compress_kernel_lzma (kernel_img, kernel_size, core_img, - core_size); - return; - } - -#ifdef HAVE_LIBLZMA - if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS - && (comp == COMPRESSION_XZ)) - { - compress_kernel_xz (kernel_img, kernel_size, core_img, - core_size); - return; - } -#endif - - if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS - && (comp != COMPRESSION_NONE)) - grub_util_error (_("unknown compression %d\n"), 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; -}; - -#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 - -static void -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, struct 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, config_size_pure = 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 == COMPRESSION_AUTO) - comp = image_target->default_compression; - - if (image_target->id == IMAGE_I386_PC - || image_target->id == IMAGE_I386_PC_PXE) - comp = 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 %zd is 0x%llx", - 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%llx", - (unsigned long long) memdisk_size); - total_module_size += memdisk_size + sizeof (struct grub_module_header); - } - - if (config_path) - { - config_size_pure = grub_util_get_image_size (config_path) + 1; - config_size = ALIGN_ADDR (config_size_pure); - grub_util_info ("the size of config file is 0x%llx", - (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%llx", - (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->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); - - 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); - memset (modinfo, 0, sizeof (struct grub_module_info64)); - 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); - memset (modinfo, 0, sizeof (struct grub_module_info32)); - 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, orig_size; - - orig_size = grub_util_get_image_size (p->name); - mod_size = ALIGN_ADDR (orig_size); - - header = (struct grub_module_header *) (kernel_img + offset); - memset (header, 0, sizeof (struct grub_module_header)); - header->type = grub_host_to_target32 (OBJ_TYPE_ELF); - header->size = grub_host_to_target32 (mod_size + sizeof (*header)); - offset += sizeof (*header); - memset (kernel_img + offset + orig_size, 0, mod_size - orig_size); - - 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); - memset (header, 0, sizeof (struct grub_module_header)); - 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); - memset (header, 0, sizeof (struct grub_module_header)); - 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); - memset (header, 0, sizeof (struct grub_module_header)); - 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); - *(kernel_img + offset + config_size_pure - 1) = 0; - offset += config_size; - } - - if (prefix) - { - struct grub_module_header *header; - - header = (struct grub_module_header *) (kernel_img + offset); - memset (header, 0, sizeof (struct grub_module_header)); - header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX); - header->size = grub_host_to_target32 (prefix_size + sizeof (*header)); - offset += sizeof (*header); - - grub_memset (kernel_img + offset, 0, prefix_size); - grub_strcpy (kernel_img + offset, prefix); - offset += prefix_size; - } - - grub_util_info ("kernel_img=%p, kernel_size=0x%llx", 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%llx", (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 COMPRESSION_XZ: - name = "xz_decompress.img"; - break; - case COMPRESSION_LZMA: - name = "lzma_decompress.img"; - break; - case COMPRESSION_NONE: - name = "none_decompress.img"; - break; - default: - grub_util_error (_("unknown compression %d\n"), 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) - && 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); - memset (full_img, 0, full_size); - - memcpy (full_img, decompress_img, decompress_size); - - memcpy (full_img + decompress_size, core_img, core_size); - - memset (full_img + decompress_size + core_size, 0, - full_size - (decompress_size + core_size)); - - free (core_img); - core_img = full_img; - core_size = full_size; - } - - switch (image_target->id) - { - case IMAGE_I386_PC: - case IMAGE_I386_PC_PXE: - 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: - 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: - { - 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; - } - } - - 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); - 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 (time (0)); - 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 (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 (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 (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 (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 (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; - grub_uint8_t context[GRUB_MD_SHA512->contextsize]; - /* 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; - - 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_memset (context, 0, sizeof (context)); - GRUB_MD_SHA512->init (context); - GRUB_MD_SHA512->write (context, boot_img, boot_size); - GRUB_MD_SHA512->final (context); - if (grub_memcmp (GRUB_MD_SHA512->read (context), 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; - } - 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; - GRUB_PROPERLY_ALIGNED_ARRAY (crc32_context, GRUB_MD_CRC32->contextsize); - - 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 (time (0)); - 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_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, hdr + 1, core_size); - GRUB_MD_CRC32->final(crc32_context); - hdr->ih_dcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context)); - - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, hdr, sizeof (*hdr)); - GRUB_MD_CRC32->final(crc32_context); - hdr->ih_hcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context)); - - 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 == 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_COREBOOT: - case IMAGE_I386_IEEE1275: - { - char *elf_img; - size_t program_size; - Elf32_Ehdr *ehdr; - Elf32_Phdr *phdr; - grub_uint32_t target_addr; - int header_size, footer_size = 0; - int phnum = 1; - - if (image_target->id != IMAGE_LOONGSON_ELF) - phnum += 2; - - if (note) - { - phnum++; - footer_size += sizeof (struct grub_ieee1275_note); - } - header_size = ALIGN_ADDR (sizeof (*ehdr) + phnum * sizeof (*phdr)); - - program_size = ALIGN_ADDR (core_size); - - elf_img = xmalloc (program_size + header_size + footer_size); - memset (elf_img, 0, program_size + header_size); - memcpy (elf_img + header_size, core_img, core_size); - ehdr = (void *) elf_img; - phdr = (void *) (elf_img + sizeof (*ehdr)); - memcpy (ehdr->e_ident, ELFMAG, SELFMAG); - ehdr->e_ident[EI_CLASS] = ELFCLASS32; - if (!image_target->bigendian) - ehdr->e_ident[EI_DATA] = ELFDATA2LSB; - else - ehdr->e_ident[EI_DATA] = ELFDATA2MSB; - ehdr->e_ident[EI_VERSION] = EV_CURRENT; - ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE; - ehdr->e_type = grub_host_to_target16 (ET_EXEC); - ehdr->e_machine = grub_host_to_target16 (image_target->elf_target); - ehdr->e_version = grub_host_to_target32 (EV_CURRENT); - - ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr); - ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr)); - ehdr->e_phnum = grub_host_to_target16 (phnum); - - /* No section headers. */ - ehdr->e_shoff = grub_host_to_target32 (0); - if (image_target->id == IMAGE_LOONGSON_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_ehsize = grub_host_to_target16 (sizeof (*ehdr)); - - phdr->p_type = grub_host_to_target32 (PT_LOAD); - phdr->p_offset = grub_host_to_target32 (header_size); - phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X); - - if (image_target->id == IMAGE_LOONGSON_ELF) - { - if (comp == 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; - 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 (align > image_target->link_align ? align : image_target->link_align); - if (image_target->id == IMAGE_LOONGSON_ELF) - ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER - | EF_MIPS_PIC | EF_MIPS_CPIC); - else - ehdr->e_flags = 0; - if (image_target->id == IMAGE_LOONGSON_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); - - if (image_target->id == IMAGE_COREBOOT) - target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR; - else - 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) - { - int note_size = sizeof (struct grub_ieee1275_note); - struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *) - (elf_img + program_size + header_size); - - grub_util_info ("adding CHRP NOTE segment"); - - note_ptr->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME)); - note_ptr->header.descsz = grub_host_to_target32 (note_size); - note_ptr->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE); - strcpy (note_ptr->header.name, GRUB_IEEE1275_NOTE_NAME); - note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff); - note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000); - note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff); - note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff); - note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff); - note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000); - - 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); - core_img = elf_img; - core_size = program_size + header_size + footer_size; - } - break; - } - - grub_util_write_image (core_img, core_size, out, outname); - free (core_img); - free (kernel_path); - - while (path_list) - { - next = path_list->next; - free ((void *) path_list->name); - free (path_list); - path_list = next; - } -} - static struct argp_option options[] = { @@ -1861,22 +88,7 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused))) return xasprintf (text, DEFAULT_DIRECTORY); case 'O': { - int format_len = 0; - char *formats; - char *ptr; - char *ret; - 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; + char *formats = grub_install_get_image_targets_string (), *ret; ret = xasprintf ("%s\n%s %s", _("generate an image in FORMAT"), _("available formats:"), formats); free (formats); @@ -1901,7 +113,7 @@ struct arguments char *font; char *config; int note; - struct image_target_desc *image_target; + const struct grub_install_image_target_desc *image_target; grub_compression_t comp; }; @@ -1923,12 +135,7 @@ argp_parser (int key, char *arg, struct argp_state *state) case 'O': { - unsigned i, j; - for (i = 0; i < ARRAY_SIZE (image_targets); i++) - for (j = 0; image_targets[i].names[j] - && j < ARRAY_SIZE (image_targets[i].names); j++) - if (strcmp (arg, image_targets[i].names[j]) == 0) - arguments->image_target = &image_targets[i]; + arguments->image_target = grub_install_get_image_target (arg); if (!arguments->image_target) { printf (_("unknown target format %s\n"), arg); @@ -1978,16 +185,16 @@ argp_parser (int key, char *arg, struct argp_state *state) if (grub_strcmp (arg, "xz") == 0) { #ifdef HAVE_LIBLZMA - arguments->comp = COMPRESSION_XZ; + arguments->comp = GRUB_COMPRESSION_XZ; #else grub_util_error ("%s", _("grub-mkimage is compiled without XZ support")); #endif } else if (grub_strcmp (arg, "none") == 0) - arguments->comp = COMPRESSION_NONE; + arguments->comp = GRUB_COMPRESSION_NONE; else if (grub_strcmp (arg, "auto") == 0) - arguments->comp = COMPRESSION_AUTO; + arguments->comp = GRUB_COMPRESSION_AUTO; else grub_util_error (_("Unknown compression format %s"), arg); break; @@ -2028,7 +235,7 @@ main (int argc, char *argv[]) grub_util_host_init (&argc, &argv); memset (&arguments, 0, sizeof (struct arguments)); - arguments.comp = COMPRESSION_AUTO; + arguments.comp = GRUB_COMPRESSION_AUTO; arguments.modules_max = argc + 1; arguments.modules = xmalloc ((arguments.modules_max + 1) * sizeof (arguments.modules[0])); @@ -2060,21 +267,20 @@ main (int argc, char *argv[]) if (!arguments.dir) { - arguments.dir = xmalloc (sizeof (GRUB_PKGLIBDIR) - + grub_strlen (arguments.image_target->dirname) - + 1); - memcpy (arguments.dir, GRUB_PKGLIBDIR, - sizeof (GRUB_PKGLIBDIR) - 1); + const char *dn = grub_util_get_target_dirname (arguments.image_target); + arguments.dir = xmalloc (sizeof (GRUB_PKGLIBDIR) + grub_strlen (dn) + 1); + memcpy (arguments.dir, GRUB_PKGLIBDIR, sizeof (GRUB_PKGLIBDIR) - 1); *(arguments.dir + sizeof (GRUB_PKGLIBDIR) - 1) = '/'; - strcpy (arguments.dir + sizeof (GRUB_PKGLIBDIR), - arguments.image_target->dirname); + strcpy (arguments.dir + sizeof (GRUB_PKGLIBDIR), dn); } - generate_image (arguments.dir, arguments.prefix ? : DEFAULT_DIRECTORY, fp, - arguments.output, - arguments.modules, arguments.memdisk, arguments.pubkeys, - arguments.npubkeys, arguments.config, - arguments.image_target, arguments.note, arguments.comp); + grub_install_generate_image (arguments.dir, + arguments.prefix ? : DEFAULT_DIRECTORY, fp, + arguments.output, arguments.modules, + arguments.memdisk, arguments.pubkeys, + arguments.npubkeys, arguments.config, + arguments.image_target, arguments.note, + arguments.comp); fflush (fp); fsync (fileno (fp)); diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index aa31fc9fd..edccb7368 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -67,7 +67,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Shdr *symtab_section, Elf_Addr *section_addresses, Elf_Half section_entsize, Elf_Half num_sections, void *jumpers, Elf_Addr jumpers_addr, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { Elf_Word symtab_size, sym_size, num_syms; Elf_Off symtab_offset; @@ -140,7 +140,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, /* Return the address of a symbol at the index I in the section S. */ static Elf_Addr SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { Elf_Sym *sym; @@ -153,7 +153,7 @@ SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i, /* Return the address of a modified value. */ static Elf_Addr * SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset); } @@ -161,7 +161,7 @@ SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset, #ifdef MKIMAGE_ELF64 static Elf_Addr SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { Elf_Word symtab_size, sym_size, num_syms; Elf_Off symtab_offset; @@ -195,7 +195,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, const char *strtab, char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { Elf_Half i; Elf_Shdr *s; @@ -472,7 +472,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, static Elf_Addr SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type, Elf_Addr addr, int flush, Elf_Addr current_address, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { struct grub_pe32_fixup_block *b; @@ -569,7 +569,7 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, Elf_Half section_entsize, Elf_Half num_sections, const char *strtab, Elf_Addr jumpers, grub_size_t njumpers, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { unsigned i; Elf_Shdr *s; @@ -755,7 +755,7 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, /* Determine if this section is a text section. Return false if this section is not allocated. */ static int -SUFFIX (is_text_section) (Elf_Shdr *s, struct image_target_desc *image_target) +SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target) { if (image_target->id != IMAGE_EFI && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS) @@ -768,7 +768,7 @@ SUFFIX (is_text_section) (Elf_Shdr *s, struct image_target_desc *image_target) BSS is also a data section, since the converter initializes BSS when producing PE32 to avoid a bug in EFI implementations. */ static int -SUFFIX (is_data_section) (Elf_Shdr *s, struct image_target_desc *image_target) +SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target) { if (image_target->id != IMAGE_EFI && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS) @@ -779,7 +779,7 @@ SUFFIX (is_data_section) (Elf_Shdr *s, struct image_target_desc *image_target) /* Return if the ELF header is valid. */ static int -SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, struct image_target_desc *image_target) +SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target) { if (size < sizeof (*e) || e->e_ident[EI_MAG0] != ELFMAG0 @@ -802,7 +802,7 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, Elf_Half num_sections, const char *strtab, size_t *exec_size, size_t *kernel_sz, size_t *all_align, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { int i; Elf_Addr current_address; @@ -884,7 +884,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, size_t total_module_size, grub_uint64_t *start, void **reloc_section, size_t *reloc_size, size_t *align, - struct image_target_desc *image_target) + const struct grub_install_image_target_desc *image_target) { char *kernel_img, *out_img; const char *strtab; diff --git a/util/mkimage.c b/util/mkimage.c new file mode 100644 index 000000000..3135ba82b --- /dev/null +++ b/util/mkimage.c @@ -0,0 +1,1865 @@ +/* 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) + +#ifdef HAVE_LIBLZMA +#include +#endif + +#define TARGET_NO_FIELD 0xffffffff + +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 + } 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-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 = "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 + }, + { + .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 + }, + { + .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 + }, + { + .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, + }, + }; + +#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_hdr +{ + grub_uint32_t namesz; + grub_uint32_t descsz; + grub_uint32_t type; + char name[sizeof (GRUB_IEEE1275_NOTE_NAME)]; +}; + +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 +{ + struct grub_ieee1275_note_hdr header; + struct grub_ieee1275_note_desc descriptor; +}; + +#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val)) + +#include + +static void *SzAlloc(void *p, size_t size) { p = p; return xmalloc(size); } +static void SzFree(void *p, void *address) { p = p; 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 HAVE_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 HAVE_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\n"), 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; +}; + +#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; image_targets[i].names[j] + && j < ARRAY_SIZE (image_targets[i].names); 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; +} + +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, config_size_pure = 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) + 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 %zd is 0x%llx", + 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%llx", + (unsigned long long) memdisk_size); + total_module_size += memdisk_size + sizeof (struct grub_module_header); + } + + if (config_path) + { + config_size_pure = grub_util_get_image_size (config_path) + 1; + config_size = ALIGN_ADDR (config_size_pure); + grub_util_info ("the size of config file is 0x%llx", + (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%llx", + (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->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); + + 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); + memset (modinfo, 0, sizeof (struct grub_module_info64)); + 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); + memset (modinfo, 0, sizeof (struct grub_module_info32)); + 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, orig_size; + + orig_size = grub_util_get_image_size (p->name); + mod_size = ALIGN_ADDR (orig_size); + + header = (struct grub_module_header *) (kernel_img + offset); + memset (header, 0, sizeof (struct grub_module_header)); + header->type = grub_host_to_target32 (OBJ_TYPE_ELF); + header->size = grub_host_to_target32 (mod_size + sizeof (*header)); + offset += sizeof (*header); + memset (kernel_img + offset + orig_size, 0, mod_size - orig_size); + + 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); + memset (header, 0, sizeof (struct grub_module_header)); + 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); + memset (header, 0, sizeof (struct grub_module_header)); + 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); + memset (header, 0, sizeof (struct grub_module_header)); + 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); + *(kernel_img + offset + config_size_pure - 1) = 0; + offset += config_size; + } + + if (prefix) + { + struct grub_module_header *header; + + header = (struct grub_module_header *) (kernel_img + offset); + memset (header, 0, sizeof (struct grub_module_header)); + header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX); + header->size = grub_host_to_target32 (prefix_size + sizeof (*header)); + offset += sizeof (*header); + + grub_memset (kernel_img + offset, 0, prefix_size); + grub_strcpy (kernel_img + offset, prefix); + offset += prefix_size; + } + + grub_util_info ("kernel_img=%p, kernel_size=0x%llx", 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%llx", (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\n"), 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) + && 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); + memset (full_img, 0, full_size); + + memcpy (full_img, decompress_img, decompress_size); + + memcpy (full_img + decompress_size, core_img, core_size); + + memset (full_img + decompress_size + core_size, 0, + full_size - (decompress_size + core_size)); + + free (core_img); + core_img = full_img; + core_size = full_size; + } + + switch (image_target->id) + { + case IMAGE_I386_PC: + case IMAGE_I386_PC_PXE: + 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: + 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: + { + 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; + } + } + + 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); + 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 (time (0)); + 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 (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 (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 (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 (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 (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; + grub_uint8_t context[GRUB_MD_SHA512->contextsize]; + /* 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; + + 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_memset (context, 0, sizeof (context)); + GRUB_MD_SHA512->init (context); + GRUB_MD_SHA512->write (context, boot_img, boot_size); + GRUB_MD_SHA512->final (context); + if (grub_memcmp (GRUB_MD_SHA512->read (context), 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; + } + 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; + GRUB_PROPERLY_ALIGNED_ARRAY (crc32_context, GRUB_MD_CRC32->contextsize); + + 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 (time (0)); + 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_MD_CRC32->init(crc32_context); + GRUB_MD_CRC32->write(crc32_context, hdr + 1, core_size); + GRUB_MD_CRC32->final(crc32_context); + hdr->ih_dcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context)); + + GRUB_MD_CRC32->init(crc32_context); + GRUB_MD_CRC32->write(crc32_context, hdr, sizeof (*hdr)); + GRUB_MD_CRC32->final(crc32_context); + hdr->ih_hcrc = grub_get_unaligned32 (GRUB_MD_CRC32->read (crc32_context)); + + 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_COREBOOT: + case IMAGE_I386_IEEE1275: + { + char *elf_img; + size_t program_size; + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + grub_uint32_t target_addr; + int header_size, footer_size = 0; + int phnum = 1; + + if (image_target->id != IMAGE_LOONGSON_ELF) + phnum += 2; + + if (note) + { + phnum++; + footer_size += sizeof (struct grub_ieee1275_note); + } + header_size = ALIGN_ADDR (sizeof (*ehdr) + phnum * sizeof (*phdr)); + + program_size = ALIGN_ADDR (core_size); + + elf_img = xmalloc (program_size + header_size + footer_size); + memset (elf_img, 0, program_size + header_size); + memcpy (elf_img + header_size, core_img, core_size); + ehdr = (void *) elf_img; + phdr = (void *) (elf_img + sizeof (*ehdr)); + memcpy (ehdr->e_ident, ELFMAG, SELFMAG); + ehdr->e_ident[EI_CLASS] = ELFCLASS32; + if (!image_target->bigendian) + ehdr->e_ident[EI_DATA] = ELFDATA2LSB; + else + ehdr->e_ident[EI_DATA] = ELFDATA2MSB; + ehdr->e_ident[EI_VERSION] = EV_CURRENT; + ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE; + ehdr->e_type = grub_host_to_target16 (ET_EXEC); + ehdr->e_machine = grub_host_to_target16 (image_target->elf_target); + ehdr->e_version = grub_host_to_target32 (EV_CURRENT); + + ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr); + ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr)); + ehdr->e_phnum = grub_host_to_target16 (phnum); + + /* No section headers. */ + ehdr->e_shoff = grub_host_to_target32 (0); + if (image_target->id == IMAGE_LOONGSON_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_ehsize = grub_host_to_target16 (sizeof (*ehdr)); + + phdr->p_type = grub_host_to_target32 (PT_LOAD); + phdr->p_offset = grub_host_to_target32 (header_size); + phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X); + + 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; + 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 (align > image_target->link_align ? align : image_target->link_align); + if (image_target->id == IMAGE_LOONGSON_ELF) + ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER + | EF_MIPS_PIC | EF_MIPS_CPIC); + else + ehdr->e_flags = 0; + if (image_target->id == IMAGE_LOONGSON_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); + + if (image_target->id == IMAGE_COREBOOT) + target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR; + else + 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) + { + int note_size = sizeof (struct grub_ieee1275_note); + struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *) + (elf_img + program_size + header_size); + + grub_util_info ("adding CHRP NOTE segment"); + + note_ptr->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME)); + note_ptr->header.descsz = grub_host_to_target32 (note_size); + note_ptr->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE); + strcpy (note_ptr->header.name, GRUB_IEEE1275_NOTE_NAME); + note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000); + note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000); + + 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); + core_img = elf_img; + core_size = program_size + header_size + footer_size; + } + break; + } + + grub_util_write_image (core_img, core_size, out, outname); + free (core_img); + free (kernel_path); + + while (path_list) + { + next = path_list->next; + free ((void *) path_list->name); + free (path_list); + path_list = next; + } +}