diff --git a/ChangeLog b/ChangeLog index 0c97dd314..d0c959ae3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2012-01-24 Vladimir Serbinenko + + Eliminate fixed limit on reed solomon decoder length. + + * grub-core/boot/i386/pc/lnxboot.S: Scan for multiboot signature + rather than hardcoding the address. + * grub-core/boot/i386/pc/startup_raw.S: Add new data field + no_reed_solomon_length. + Move gate_a20 to no-reed-solomon part. + Don't force a particular size of no reed-solomon part. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): + Removed. + (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH): New define. + * util/grub-setup.c (setup): Read no_rs_length from the image itself. + 2012-01-24 Vladimir Serbinenko * grub-core/commands/wildcard.c (match_files): Handle filenames diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index 4fe0df139..9a516c694 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -177,20 +177,21 @@ real_code_2: pushw %es popw %ds -#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200 - movl $0x200, %ecx - addl %ecx, %esi -#else - movl $(GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4), %ecx + movl $0x1000, %ecx addl $0x200, %esi -#endif movl $DATA_ADDR, %edi call LOCAL(move_memory) /* Check for multiboot signature. */ - cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART) + movl $DATA_ADDR, %edi +3: + movl %ss:(%edi), %eax + cmpl $MULTIBOOT_HEADER_MAGIC, %eax jz 1f + addl $4, %edi + cmpl $(DATA_ADDR + 0x1000), %edi + jne 3b movl (ramdisk_image - start), %esi movl (ramdisk_size - start), %ecx @@ -199,8 +200,9 @@ real_code_2: 1: + movl $(DATA_ADDR + 0x1000), %edi movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx - addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx + addl $(0x9000 - 0x8200), %ecx 2: call LOCAL(move_memory) diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 0e6794f56..56f1ba957 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -60,6 +60,8 @@ LOCAL(uncompressed_size): . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY reed_solomon_redundancy: .long 0 + . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH + .short (LOCAL(reed_solomon_part) - _start) /* * This is the area for all of the special variables. @@ -103,9 +105,9 @@ LOCAL (codestart): call grub_gate_a20 movl LOCAL(compressed_size), %edx - addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - _start), %edx + addl $(LOCAL(decompressor_end) - LOCAL(reed_solomon_part)), %edx movl reed_solomon_redundancy, %ecx - leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax + leal LOCAL(reed_solomon_part), %eax cld call EXT_C (grub_reed_solomon_recover) jmp post_reed_solomon @@ -116,82 +118,6 @@ LOCAL (codestart): .text - . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART -/* - * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). - * This uses the a.out kludge to load raw binary to the area starting at 1MB, - * and relocates itself after loaded. - */ - .p2align 2 /* force 4-byte alignment */ -multiboot_header: - /* magic */ - .long 0x1BADB002 - /* flags */ - .long (1 << 16) - /* checksum */ - .long -0x1BADB002 - (1 << 16) - /* header addr */ - .long multiboot_header - _start + 0x100000 + 0x200 - /* load addr */ - .long 0x100000 - /* load end addr */ - .long 0 - /* bss end addr */ - .long 0 - /* entry addr */ - .long multiboot_entry - _start + 0x100000 + 0x200 - -multiboot_entry: - .code32 - /* obtain the boot device */ - movl 12(%ebx), %edx - - movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp - movl %ebp, %esp - - /* relocate the code */ - movl $(LOCAL(decompressor_end) + 0x200), %ecx - addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx - movl $0x100000, %esi - movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi - cld - rep - movsb - /* jump to the real address */ - movl $multiboot_trampoline, %eax - jmp *%eax - -multiboot_trampoline: - /* fill the boot information */ - movl %edx, LOCAL(boot_dev) - shrl $24, %edx - /* enter the usual booting */ - call prot_to_real - .code16 - jmp LOCAL (codestart) - .code32 - -post_reed_solomon: - -#ifdef ENABLE_LZMA - movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi - movl $LOCAL(decompressor_end), %esi - pushl %edi - movl LOCAL (uncompressed_size), %ecx - leal (%edi, %ecx), %ebx - /* Don't remove this push: it's an argument. */ - push %ecx - call _LzmaDecodeA - pop %ecx - /* _LzmaDecodeA clears DF, so no need to run cld */ - popl %esi -#endif - - movl LOCAL(boot_dev), %edx - movl $prot_to_real, %edi - movl $real_to_prot, %ecx - jmp *%esi - /* * grub_gate_a20(int on) * @@ -342,6 +268,83 @@ gate_a20_check_state: popl %ebx ret +LOCAL(reed_solomon_part): + +/* + * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). + * This uses the a.out kludge to load raw binary to the area starting at 1MB, + * and relocates itself after loaded. + */ + .p2align 2 /* force 4-byte alignment */ +multiboot_header: + /* magic */ + .long 0x1BADB002 + /* flags */ + .long (1 << 16) + /* checksum */ + .long -0x1BADB002 - (1 << 16) + /* header addr */ + .long multiboot_header - _start + 0x100000 + 0x200 + /* load addr */ + .long 0x100000 + /* load end addr */ + .long 0 + /* bss end addr */ + .long 0 + /* entry addr */ + .long multiboot_entry - _start + 0x100000 + 0x200 + +multiboot_entry: + .code32 + /* obtain the boot device */ + movl 12(%ebx), %edx + + movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp + movl %ebp, %esp + + /* relocate the code */ + movl $(LOCAL(decompressor_end) + 0x200), %ecx + addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx + movl $0x100000, %esi + movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi + cld + rep + movsb + /* jump to the real address */ + movl $multiboot_trampoline, %eax + jmp *%eax + +multiboot_trampoline: + /* fill the boot information */ + movl %edx, LOCAL(boot_dev) + shrl $24, %edx + /* enter the usual booting */ + call prot_to_real + .code16 + jmp LOCAL (codestart) + .code32 + +post_reed_solomon: + +#ifdef ENABLE_LZMA + movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi + movl $LOCAL(decompressor_end), %esi + pushl %edi + movl LOCAL (uncompressed_size), %ecx + leal (%edi, %ecx), %ebx + /* Don't remove this push: it's an argument. */ + push %ecx + call _LzmaDecodeA + pop %ecx + /* _LzmaDecodeA clears DF, so no need to run cld */ + popl %esi +#endif + + movl LOCAL(boot_dev), %edx + movl $prot_to_real, %edi + movl $real_to_prot, %ecx + jmp *%esi + #ifdef ENABLE_LZMA #include "lzma_decode.S" #endif diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 75a46e128..21aea5cd6 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -28,7 +28,8 @@ /* Offset of reed_solomon_redundancy. */ #define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x10 -#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x7e0 +/* Offset of field holding no reed solomon length. */ +#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH 0x14 /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 diff --git a/util/grub-setup.c b/util/grub-setup.c index 8965143c5..9618d1a5d 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -444,14 +444,22 @@ setup (const char *dir, + GRUB_DISK_SECTOR_SIZE - sizeof (*block)); + grub_size_t no_rs_length; *(grub_uint32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY) = grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size); + no_rs_length = grub_target_to_host16 + (*(grub_uint16_t *) (core_img + + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH)); + + if (no_rs_length == 0xffff) + grub_util_error ("core.img version mismatch"); void *tmp = xmalloc (core_size); grub_memcpy (tmp, core_img, core_size); - grub_reed_solomon_add_redundancy (core_img + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + GRUB_DISK_SECTOR_SIZE, - core_size - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - GRUB_DISK_SECTOR_SIZE, + grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE, + core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE, nsec * GRUB_DISK_SECTOR_SIZE - core_size); assert (grub_memcmp (tmp, core_img, core_size) == 0);