diff -ru grub2.orig/include/grub/i386/pc/loader.h grub2.multiboot/include/grub/i386/pc/loader.h --- grub2.orig/include/grub/i386/pc/loader.h 2004-09-12 19:20:52.000000000 +0700 +++ grub2.multiboot/include/grub/i386/pc/loader.h 2007-06-17 18:31:53.000000000 +0700 @@ -28,11 +28,17 @@ extern char *EXPORT_VAR(grub_linux_tmp_addr); extern char *EXPORT_VAR(grub_linux_real_addr); +/* Multiboot loader needs to know boot device. */ +extern grub_uint32_t EXPORT_VAR(grub_boot_drive); +extern grub_int32_t EXPORT_VAR(grub_install_dos_part); +extern grub_int32_t EXPORT_VAR(grub_install_bsd_part); + void EXPORT_FUNC(grub_linux_boot_zimage) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_linux_boot_bzimage) (void) __attribute__ ((noreturn)); /* This is an asm part of the chainloader. */ -void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn)); +void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) + __attribute__ ((noreturn)); /* The asm part of the multiboot loader. */ void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry, diff -ru grub2.orig/loader/i386/pc/multiboot.c grub2.multiboot/loader/i386/pc/multiboot.c --- grub2.orig/loader/i386/pc/multiboot.c 2006-06-04 22:56:54.000000000 +0700 +++ grub2.multiboot/loader/i386/pc/multiboot.c 2007-06-17 19:02:10.000000000 +0700 @@ -22,8 +22,6 @@ * FIXME: The following features from the Multiboot specification still * need to be implemented: * - VBE support - * - a.out support - * - boot device * - symbol table * - memory map * - drives table @@ -236,6 +234,75 @@ return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class"); } +/* Load with a.out kludge. */ +static grub_err_t +grub_multiboot_load_raw (grub_file_t file, grub_off_t header_offset, + const struct grub_multiboot_header *header) +{ + grub_off_t file_size = grub_file_size (file); + grub_off_t load_offset = header_offset + - (header->header_addr - header->load_addr); + grub_uint32_t load_end_addr = header->load_end_addr; + grub_uint32_t bss_end_addr = header->bss_end_addr; + grub_uint32_t load_size, total_size; + + if (header->header_addr < header->load_addr) + return grub_error (GRUB_ERR_BAD_OS, "Header precedes code"); + + if (header_offset < (header->header_addr - header->load_addr) + || load_offset > file_size) + return grub_error (GRUB_ERR_BAD_OS, "Code and data go out of file"); + + if (load_end_addr == 0) + { + if (file_size - load_offset > 0xFFFFFFFF) + return grub_error (GRUB_ERR_BAD_OS, "Code and data size is too big"); + load_size = file_size - load_offset; + load_end_addr = header->load_addr + load_size; + } + else + load_size = load_end_addr - header->load_addr; + + if (load_end_addr < header->load_addr) + return grub_error (GRUB_ERR_BAD_OS, "Code and data size is negative"); + + if (-(grub_uint64_t) load_size <= load_offset + || load_offset + load_size > file_size) + return grub_error (GRUB_ERR_BAD_OS, "Code and data go out of file"); + + if (header->entry_addr < header->load_addr + || header->entry_addr >= load_end_addr) + return grub_error (GRUB_ERR_BAD_OS, + "Entry point is outside of code and data area"); + + if (bss_end_addr == 0) + bss_end_addr = load_end_addr; + + if (bss_end_addr < load_end_addr) + return grub_error (GRUB_ERR_BAD_OS, "BSS size is negative"); + + total_size = load_size + (bss_end_addr - load_end_addr); + + if (-load_size <= (bss_end_addr - load_end_addr) + || header->load_addr < grub_os_area_addr + || -total_size <= header->load_addr + || (header->load_addr + total_size) + > (grub_os_area_addr + grub_os_area_size)) + return grub_error (GRUB_ERR_BAD_OS, + "Kernel doesn't fit in memory reserved for the OS"); + + if (grub_file_seek (file, load_offset) == (grub_off_t) -1 + || grub_file_read (file, (char *) header->load_addr, load_size) + != (grub_ssize_t) load_size) + return grub_error (GRUB_ERR_READ_ERROR, "Cannot read code and data"); + + grub_memset ((void *) load_end_addr, 0, total_size - load_size); + + entry = header->entry_addr; + + return GRUB_ERR_NONE; +} + void grub_rescue_cmd_multiboot (int argc, char *argv[]) { @@ -293,7 +360,13 @@ goto fail; } - if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE) + if (header->flags & GRUB_MB_AOUT_KLUDGE) + { + if (grub_multiboot_load_raw (file, (char *) header - buffer, header) + != GRUB_ERR_NONE) + goto fail; + } + else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE) goto fail; mbi = grub_malloc (sizeof (struct grub_multiboot_info)); @@ -325,6 +398,15 @@ mbi->flags |= GRUB_MB_INFO_CMDLINE; mbi->cmdline = (grub_uint32_t) cmdline; + mbi->flags |= GRUB_MB_INFO_BOOTDEV; + mbi->boot_device = (grub_boot_drive << 24); + if (grub_install_dos_part >= 0) + mbi->boot_device |= 0x00FFFF | (grub_install_dos_part << 16); + else if (grub_install_bsd_part >= 0) + mbi->boot_device |= 0xFF00FF | (grub_install_bsd_part << 8); + else + mbi->boot_device |= 0xFFFFFF; + mbi->flags |= GRUB_MB_INFO_BOOT_LOADER_NAME; mbi->boot_loader_name = (grub_uint32_t) grub_strdup (PACKAGE_STRING);