From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 18:53:25 +0000 (+0100) Subject: Use decompressors framework on i386-pc. It increases core size X-Git-Tag: 2.00~952 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=60240b8bc1a501951944c9e07d094c9e5e5e7084;p=thirdparty%2Fgrub.git Use decompressors framework on i386-pc. It increases core size by 46 bytes but improves compatibility and maintainability. * grub-core/Makefile.core.def (lzma_decompress): New image. (kernel): Add i386_pc_ldflags. * grub-core/kern/i386/pc/startup.S: Move intial part to .. * grub-core/boot/i386/pc/startup_raw.S: ... here. Pass pointers to real_to_prot, prot_to_real and device info. * include/grub/offsets.h: Renamed decompressor offsets. * util/grub-mkimage.c (grub_compression_t): New cmpression lzma. (image_target_desc): Remove raw_size and rename decompressor fields. (compress_kernel): Handle lzma. (generate_image): Handle decompressors on i386-pc. --- diff --git a/ChangeLog b/ChangeLog index 409a41ca5..eeb9bda57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-11-12 Vladimir Serbinenko + + Use decompressors framework on i386-pc. It increases core size + by 46 bytes but improves compatibility and maintainability. + + * grub-core/Makefile.core.def (lzma_decompress): New image. + (kernel): Add i386_pc_ldflags. + * grub-core/kern/i386/pc/startup.S: Move intial part to .. + * grub-core/boot/i386/pc/startup_raw.S: ... here. Pass pointers + to real_to_prot, prot_to_real and device info. + * include/grub/offsets.h: Renamed decompressor offsets. + * util/grub-mkimage.c (grub_compression_t): New cmpression lzma. + (image_target_desc): Remove raw_size and rename decompressor fields. + (compress_kernel): Handle lzma. + (generate_image): Handle decompressors on i386-pc. + 2011-11-12 Vladimir Serbinenko * configure.ac: Add -fno-asynchronous-unwind-tables. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 9590188fb..18264f98f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -34,7 +34,7 @@ kernel = { ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; - i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; @@ -356,6 +356,15 @@ image = { enable = mips; }; +image = { + name = lzma_decompress; + i386_pc = boot/i386/pc/startup_raw.S; + + objcopyflags = '-O binary'; + ldflags = '-Wl,-Ttext,0x8200'; + enable = i386_pc; +}; + image = { name = fwstart; mips_loongson = boot/mips/loongson/fwstart.S; diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index bb43ed73c..e5227d174 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -199,12 +199,8 @@ real_code_2: 1: - movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx -#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200 - addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx -#else - addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx -#endif + movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx + addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx 2: call LOCAL(move_memory) diff --git a/grub-core/kern/i386/pc/lzma_decode.S b/grub-core/boot/i386/pc/lzma_decode.S similarity index 100% rename from grub-core/kern/i386/pc/lzma_decode.S rename to grub-core/boot/i386/pc/lzma_decode.S diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S new file mode 100644 index 000000000..4820e3442 --- /dev/null +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -0,0 +1,369 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 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 + +#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) + + .file "startup_raw.S" + + .text + + /* Tell GAS to generate 16-bit instructions so that this code works + in real mode. */ + .code16 + + .globl start, _start +start: +_start: +LOCAL (base): + /* + * Guarantee that "main" is loaded at 0x0:0x8200. + */ +#ifdef __APPLE__ + ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000) +#else + ljmp $0, $ABS(LOCAL (codestart)) +#endif + + /* + * This is a special data area. + */ + + . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE +LOCAL(compressed_size): + .long 0 + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE +LOCAL(uncompressed_size): + .long 0 + + . = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART +LOCAL(dos_part): + .long 0xFFFFFFFF + . = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART +LOCAL(bsd_part): + .long 0xFFFFFFFF + + . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY +reed_solomon_redundancy: + .long 0 + +/* + * This is the area for all of the special variables. + */ + +LOCAL(boot_drive): + .byte 0 + +/* the real mode code continues... */ +LOCAL (codestart): + cli /* we're not safe here! */ + + /* set up %ds, %ss, and %es */ + xorw %ax, %ax + movw %ax, %ds + movw %ax, %ss + movw %ax, %es + + /* set up the real mode/BIOS stack */ + movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp + movl %ebp, %esp + + sti /* we're safe again */ + + /* save the boot drive */ + ADDR32 movb %dl, LOCAL(boot_drive) + + /* reset disk system (%ah = 0) */ + int $0x13 + + /* transition to protected mode */ + DATA32 call real_to_prot + + /* The ".code32" directive takes GAS out of 16-bit mode. */ + .code32 + + incl %eax + call grub_gate_a20 + + movl LOCAL(compressed_size), %edx + addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx + movl reed_solomon_redundancy, %ecx + leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax + call EXT_C (grub_reed_solomon_recover) + jmp post_reed_solomon + +#include + + .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, %eax + shrl $8, %eax + xorl %ebx, %ebx + cmpb $0xFF, %ah + je 1f + movb %ah, %bl + movl %ebx, LOCAL(dos_part) +1: + cmpb $0xFF, %al + je 2f + movb %al, %bl + movl %ebx, LOCAL(bsd_part) +2: + shrl $24, %edx + movb %dl, LOCAL(boot_drive) + movb $0xFF, %dh + movl $GRUB_MEMORY_MACHINE_PROT_STACK, %esp + /* 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 + call _LzmaDecodeA + /* _LzmaDecodeA clears DF, so no need to run cld */ + popl %esi +#endif + + movb LOCAL(boot_drive), %dl + movl LOCAL(dos_part), %eax + movl LOCAL(bsd_part), %ebx + movl $prot_to_real, %edi + movl $real_to_prot, %ecx + jmp *%esi + +#include "../../../kern/i386/realmode.S" + +/* + * grub_gate_a20(int on) + * + * Gate address-line 20 for high memory. + * + * This routine is probably overconservative in what it does, but so what? + * + * It also eats any keystrokes in the keyboard buffer. :-( + */ + +grub_gate_a20: + movl %eax, %edx + +gate_a20_test_current_state: + /* first of all, test if already in a good state */ + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_bios + ret + +gate_a20_try_bios: + /* second, try a BIOS call */ + pushl %ebp + call prot_to_real + + .code16 + movw $0x2400, %ax + testb %dl, %dl + jz 1f + incw %ax +1: int $0x15 + + DATA32 call real_to_prot + .code32 + + popl %ebp + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_system_control_port_a + ret + +gate_a20_try_system_control_port_a: + /* + * In macbook, the keyboard test would hang the machine, so we move + * this forward. + */ + /* fourth, try the system control port A */ + inb $0x92 + andb $(~0x03), %al + testb %dl, %dl + jz 6f + orb $0x02, %al +6: outb $0x92 + + /* When turning off Gate A20, do not check the state strictly, + because a failure is not fatal usually, and Gate A20 is always + on some modern machines. */ + testb %dl, %dl + jz 7f + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_keyboard_controller +7: ret + +gate_a20_flush_keyboard_buffer: + inb $0x64 + andb $0x02, %al + jnz gate_a20_flush_keyboard_buffer +2: + inb $0x64 + andb $0x01, %al + jz 3f + inb $0x60 + jmp 2b +3: + ret + +gate_a20_try_keyboard_controller: + /* third, try the keyboard controller */ + call gate_a20_flush_keyboard_buffer + + movb $0xd1, %al + outb $0x64 +4: + inb $0x64 + andb $0x02, %al + jnz 4b + + movb $0xdd, %al + testb %dl, %dl + jz 5f + orb $0x02, %al +5: outb $0x60 + call gate_a20_flush_keyboard_buffer + + /* output a dummy command (USB keyboard hack) */ + movb $0xff, %al + outb $0x64 + call gate_a20_flush_keyboard_buffer + + call gate_a20_check_state + cmpb %al, %dl + /* everything failed, so restart from the beginning */ + jnz gate_a20_try_bios + ret + +gate_a20_check_state: + /* iterate the checking for a while */ + movl $100, %ecx +1: + call 3f + cmpb %al, %dl + jz 2f + loop 1b +2: + ret +3: + pushl %ebx + pushl %ecx + xorl %eax, %eax + /* compare the byte at 0x8000 with that at 0x108000 */ + movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx + pushl %ebx + /* save the original byte in CL */ + movb (%ebx), %cl + /* store the value at 0x108000 in AL */ + addl $0x100000, %ebx + movb (%ebx), %al + /* try to set one less value at 0x8000 */ + popl %ebx + movb %al, %ch + decb %ch + movb %ch, (%ebx) + /* serialize */ + outb %al, $0x80 + outb %al, $0x80 + /* obtain the value at 0x108000 in CH */ + pushl %ebx + addl $0x100000, %ebx + movb (%ebx), %ch + /* this result is 1 if A20 is on or 0 if it is off */ + subb %ch, %al + xorb $1, %al + /* restore the original */ + popl %ebx + movb %cl, (%ebx) + popl %ecx + popl %ebx + ret + +#ifdef ENABLE_LZMA +#include "lzma_decode.S" +#endif + + .p2align 2 + +LOCAL(decompressor_end): diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index aefd387b6..e76926677 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -38,13 +38,13 @@ start: bal codestart nop base: - . = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE compressed_size: .long 0 - . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE uncompressed_size: .long 0 - . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR uncompressed_addr: .long 0 codestart: diff --git a/grub-core/kern/i386/int.S b/grub-core/kern/i386/int.S index 58ccfdaab..7a2b7808a 100644 --- a/grub-core/kern/i386/int.S +++ b/grub-core/kern/i386/int.S @@ -47,7 +47,7 @@ FUNCTION(grub_bios_interrupt) movl 24(%edx), %esi movl 28(%edx), %edx - call prot_to_real + PROT_TO_REAL .code16 pushf cli @@ -98,7 +98,7 @@ intno: movw %ax, LOCAL(bios_register_es) popf - DATA32 call real_to_prot + REAL_TO_PROT .code32 popl %eax diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 6fbfab3b8..da7230c33 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -156,8 +156,7 @@ grub_machine_init (void) int grub_lower_mem; #endif - grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR - + ((_edata - _start) - GRUB_KERNEL_MACHINE_RAW_SIZE); + grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start); /* Initialize the console as early as possible. */ grub_console_init (); diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 94d4f02ee..058f9efa7 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 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 @@ -43,203 +43,30 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include - -#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) .file "startup.S" .text - /* Tell GAS to generate 16-bit instructions so that this code works - in real mode. */ - .code16 - .globl start, _start start: _start: -LOCAL (base): - /* - * Guarantee that "main" is loaded at 0x0:0x8200. - */ -#ifdef __APPLE__ - ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000) -#else - ljmp $0, $ABS(LOCAL (codestart)) -#endif - - /* - * This is a special data area. - */ - - . = _start + GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE -VARIABLE(grub_total_module_size) - .long 0 - . = _start + GRUB_KERNEL_I386_PC_COMPRESSED_SIZE -VARIABLE(grub_compressed_size) - .long 0 - . = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART -VARIABLE(grub_install_dos_part) - .long 0xFFFFFFFF - . = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART -VARIABLE(grub_install_bsd_part) - .long 0xFFFFFFFF - . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY -reed_solomon_redundancy: - .long 0 - -#ifdef APPLE_CC -bss_start: - .long 0 -bss_end: - .long 0 -#endif -/* - * This is the area for all of the special variables. - */ - -VARIABLE(grub_boot_drive) - .byte 0 - -/* the real mode code continues... */ -LOCAL (codestart): - cli /* we're not safe here! */ - - /* set up %ds, %ss, and %es */ - xorw %ax, %ax - movw %ax, %ds - movw %ax, %ss - movw %ax, %es - - /* set up the real mode/BIOS stack */ - movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp - movl %ebp, %esp - - sti /* we're safe again */ - - /* save the boot drive */ - ADDR32 movb %dl, EXT_C(grub_boot_drive) - - /* reset disk system (%ah = 0) */ - int $0x13 - - /* transition to protected mode */ - DATA32 call real_to_prot - - /* The ".code32" directive takes GAS out of 16-bit mode. */ - .code32 - - incl %eax - call grub_gate_a20 - - movl EXT_C(grub_compressed_size), %edx - addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx - movl reed_solomon_redundancy, %ecx - leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax - call EXT_C (grub_reed_solomon_recover) - jmp post_reed_solomon - -#include - - .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 $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx - addl EXT_C(grub_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, %eax - shrl $8, %eax - xorl %ebx, %ebx - cmpb $0xFF, %ah - je 1f - movb %ah, %bl - movl %ebx, EXT_C(grub_install_dos_part) -1: - cmpb $0xFF, %al - je 2f - movb %al, %bl - movl %ebx, EXT_C(grub_install_bsd_part) -2: - shrl $24, %edx - movb $0xFF, %dh - /* enter the usual booting */ - call prot_to_real - jmp LOCAL (codestart) - -post_reed_solomon: - -#ifdef ENABLE_LZMA - movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi - movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi - pushl %edi - pushl %esi - movl $(BSS_START_SYMBOL - _start), %ecx - addl EXT_C(grub_total_module_size), %ecx - subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx - pushl %ecx - leal (%edi, %ecx), %ebx - call _LzmaDecodeA - /* _LzmaDecodeA clears DF, so no need to run cld */ - popl %ecx - popl %edi - popl %esi -#endif + movl %ecx, (LOCAL(real_to_prot_addr) - _start) (%esi) + movl %edi, (LOCAL(prot_to_real_addr) - _start) (%esi) /* copy back the decompressed part (except the modules) */ - subl EXT_C(grub_total_module_size), %ecx + movl $(_edata - _start), %ecx + movl $(_start), %edi rep movsb + movl $LOCAL (cont), %esi + jmp *%esi +LOCAL(cont): + #if 0 /* copy modules before cleaning out the bss */ movl EXT_C(grub_total_module_size), %ecx @@ -255,24 +82,14 @@ post_reed_solomon: movsb #endif -#ifdef APPLE_CC - /* clean out the bss */ - bss_start_abs = ABS (bss_start) - bss_end_abs = ABS (bss_end) - - movl bss_start_abs, %edi + movl %eax, %esi - /* compute the bss length */ - movl bss_end_abs, %ecx - subl %edi, %ecx -#else /* clean out the bss */ movl $BSS_START_SYMBOL, %edi /* compute the bss length */ movl $END_SYMBOL, %ecx subl %edi, %ecx -#endif /* clean out */ xorl %eax, %eax @@ -280,172 +97,29 @@ post_reed_solomon: rep stosb + movl %esi, EXT_C(grub_install_dos_part) + movb %dl, EXT_C(grub_boot_drive) + movl %ebx, EXT_C(grub_install_bsd_part) + /* * Call the start of main body of C code. */ call EXT_C(grub_main) -#include "../realmode.S" - -/* - * grub_gate_a20(int on) - * - * Gate address-line 20 for high memory. - * - * This routine is probably overconservative in what it does, but so what? - * - * It also eats any keystrokes in the keyboard buffer. :-( - */ - -grub_gate_a20: - movl %eax, %edx - -gate_a20_test_current_state: - /* first of all, test if already in a good state */ - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_bios - ret - -gate_a20_try_bios: - /* second, try a BIOS call */ - pushl %ebp - call prot_to_real - - .code16 - movw $0x2400, %ax - testb %dl, %dl - jz 1f - incw %ax -1: int $0x15 - - DATA32 call real_to_prot - .code32 - - popl %ebp - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_system_control_port_a - ret - -gate_a20_try_system_control_port_a: - /* - * In macbook, the keyboard test would hang the machine, so we move - * this forward. - */ - /* fourth, try the system control port A */ - inb $0x92 - andb $(~0x03), %al - testb %dl, %dl - jz 6f - orb $0x02, %al -6: outb $0x92 - - /* When turning off Gate A20, do not check the state strictly, - because a failure is not fatal usually, and Gate A20 is always - on some modern machines. */ - testb %dl, %dl - jz 7f - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_keyboard_controller -7: ret - -gate_a20_flush_keyboard_buffer: - inb $0x64 - andb $0x02, %al - jnz gate_a20_flush_keyboard_buffer -2: - inb $0x64 - andb $0x01, %al - jz 3f - inb $0x60 - jmp 2b -3: - ret - -gate_a20_try_keyboard_controller: - /* third, try the keyboard controller */ - call gate_a20_flush_keyboard_buffer - - movb $0xd1, %al - outb $0x64 -4: - inb $0x64 - andb $0x02, %al - jnz 4b - - movb $0xdd, %al - testb %dl, %dl - jz 5f - orb $0x02, %al -5: outb $0x60 - call gate_a20_flush_keyboard_buffer - - /* output a dummy command (USB keyboard hack) */ - movb $0xff, %al - outb $0x64 - call gate_a20_flush_keyboard_buffer - - call gate_a20_check_state - cmpb %al, %dl - /* everything failed, so restart from the beginning */ - jnz gate_a20_try_bios - ret - -gate_a20_check_state: - /* iterate the checking for a while */ - movl $100, %ecx -1: - call 3f - cmpb %al, %dl - jz 2f - loop 1b -2: - ret -3: - pushl %ebx - pushl %ecx - xorl %eax, %eax - /* compare the byte at 0x8000 with that at 0x108000 */ - movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx - pushl %ebx - /* save the original byte in CL */ - movb (%ebx), %cl - /* store the value at 0x108000 in AL */ - addl $0x100000, %ebx - movb (%ebx), %al - /* try to set one less value at 0x8000 */ - popl %ebx - movb %al, %ch - decb %ch - movb %ch, (%ebx) - /* serialize */ - outb %al, $0x80 - outb %al, $0x80 - /* obtain the value at 0x108000 in CH */ - pushl %ebx - addl $0x100000, %ebx - movb (%ebx), %ch - /* this result is 1 if A20 is on or 0 if it is off */ - subb %ch, %al - xorb $1, %al - /* restore the original */ - popl %ebx - movb %cl, (%ebx) - popl %ecx - popl %ebx - ret +LOCAL(real_to_prot_addr): + .long 0 +LOCAL(prot_to_real_addr): + .long 0 -#ifdef ENABLE_LZMA -#include "lzma_decode.S" -#endif + .macro PROT_TO_REAL + movl LOCAL(prot_to_real_addr), %eax + call *%eax + .endm -/* - * The code beyond this point is compressed. Assert that the uncompressed - * code fits GRUB_KERNEL_MACHINE_RAW_SIZE. - */ - . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE + .macro REAL_TO_PROT + movl LOCAL(real_to_prot_addr), %eax + DATA32 call *%ax + .endm /* * grub_exit() @@ -453,7 +127,7 @@ gate_a20_check_state: * Exit the system. */ FUNCTION(grub_exit) - call prot_to_real + PROT_TO_REAL .code16 /* Tell the BIOS a boot failure. If this does not work, reboot. */ int $0x18 @@ -482,7 +156,7 @@ FUNCTION(grub_pxe_call) shll $16, %edx addl %eax, %edx - call prot_to_real + PROT_TO_REAL .code16 pushl %ebx @@ -494,7 +168,7 @@ FUNCTION(grub_pxe_call) addw $10, %sp movw %ax, %cx - DATA32 call real_to_prot + REAL_TO_PROT .code32 movzwl %cx, %eax @@ -506,3 +180,11 @@ FUNCTION(grub_pxe_call) ret #include "../int.S" + + .bss +VARIABLE(grub_boot_drive) + .byte 0 +VARIABLE(grub_install_dos_part) + .long 0xFFFFFFFF +VARIABLE(grub_install_bsd_part) + .long 0xFFFFFFFF diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S index 3e8a13892..2e16847c8 100644 --- a/grub-core/kern/i386/realmode.S +++ b/grub-core/kern/i386/realmode.S @@ -51,6 +51,14 @@ protstack: .long GRUB_MEMORY_MACHINE_PROT_STACK + .macro PROT_TO_REAL + call prot_to_real + .endm + + .macro REAL_TO_PROT + DATA32 call real_to_prot + .endm + /* * This is the Global Descriptor Table * @@ -162,6 +170,25 @@ protcseg: /* return on the old (or initialized) stack! */ ret +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,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 prot_to_real: /* just in case, set GDT */ diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 92354f700..e3b9a377c 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -19,11 +19,11 @@ #ifndef OFFSETS_HEADER #define OFFSETS_HEADER 1 -/* The offset of GRUB_TOTAL_MODULE_SIZE. */ -#define GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE 0x8 +/* The offset of GRUB_COMPRESSED_SIZE. */ +#define GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE 0x08 /* The offset of GRUB_COMPRESSED_SIZE. */ -#define GRUB_KERNEL_I386_PC_COMPRESSED_SIZE 0x0c +#define GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE 0x0c /* The offset of GRUB_INSTALL_DOS_PART. */ #define GRUB_KERNEL_I386_PC_INSTALL_DOS_PART 0x10 @@ -34,15 +34,12 @@ /* Offset of reed_solomon_redundancy. */ #define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x18 -/* The size of the first region which won't be compressed. */ -#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xc70 - #define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x6e0 /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 -#define GRUB_KERNEL_I386_PC_LINK_ADDR 0x8200 +#define GRUB_KERNEL_I386_PC_LINK_ADDR 0x9000 /* The upper memory area (starting at 640 kiB). */ #define GRUB_MEMORY_I386_PC_UPPER 0xa0000 @@ -62,7 +59,6 @@ #define GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE 12 #define GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS 0x4400 -#define GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE 0 #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 @@ -133,10 +129,12 @@ #define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG) #define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER) -#define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _RAW_SIZE) #define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_BSD_PART) #define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_DOS_PART) #define GRUB_MACHINE_LINK_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _LINK_ADDR) + +#define GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _COMPRESSED_SIZE) +#define GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _UNCOMPRESSED_SIZE) #endif #ifndef ASM_FILE diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 9369fba3d..9da72f6c9 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -54,7 +54,7 @@ #define TARGET_NO_FIELD 0xffffffff typedef enum { - COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ + COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ, COMPRESSION_LZMA } grub_compression_t; struct image_target_desc @@ -73,13 +73,13 @@ struct image_target_desc enum { PLATFORM_FLAGS_NONE = 0, - PLATFORM_FLAGS_LZMA = 1, PLATFORM_FLAGS_DECOMPRESSORS = 2, PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4, } flags; - unsigned raw_size; unsigned total_module_size; - unsigned compressed_size; + unsigned decompressor_compressed_size; + unsigned decompressor_uncompressed_size; + unsigned decompressor_uncompressed_addr; unsigned link_align; grub_uint16_t elf_target; unsigned section_align; @@ -107,9 +107,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -127,9 +128,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -146,10 +148,11 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_I386_PC, - .flags = PLATFORM_FLAGS_LZMA, - .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, - .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE, + .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, .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART, @@ -162,10 +165,11 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_I386_PC_PXE, - .flags = PLATFORM_FLAGS_LZMA, - .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, - .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE, + .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, .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART, @@ -179,9 +183,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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 @@ -201,9 +206,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_I386_IEEE1275, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -221,9 +227,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_QEMU, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -237,9 +244,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -254,9 +262,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -273,9 +282,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_FULOONG2F_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -294,9 +304,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -313,9 +324,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_PPC, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -333,9 +345,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_SPARC64_RAW, .flags = PLATFORM_FLAGS_NONE, - .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -349,9 +362,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_SPARC64_AOUT, .flags = PLATFORM_FLAGS_NONE, - .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -365,9 +379,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_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, .install_dos_part = TARGET_NO_FIELD, @@ -383,9 +398,10 @@ struct image_target_desc image_targets[] = .id = IMAGE_MIPS_ARC, .flags = (PLATFORM_FLAGS_DECOMPRESSORS | PLATFORM_FLAGS_MODULES_BEFORE_KERNEL), - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -402,9 +418,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -421,9 +438,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -440,9 +458,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -459,9 +478,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -593,7 +613,7 @@ 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, size_t raw_size) + char **core_img, size_t *core_size) { CLzmaEncProps props; unsigned char out_props[5]; @@ -606,27 +626,21 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size, props.pb = 2; props.numThreads = 1; - if (kernel_size < raw_size) - grub_util_error (_("the core image is too small")); - *core_img = xmalloc (kernel_size); - memcpy (*core_img, kernel_img, raw_size); - *core_size = kernel_size - raw_size; - if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size, - (unsigned char *) kernel_img + raw_size, - kernel_size - raw_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 (_("cannot compress the kernel image")); - - *core_size += raw_size; } #ifdef HAVE_LIBLZMA static void compress_kernel_xz (char *kernel_img, size_t kernel_size, - char **core_img, size_t *core_size, size_t raw_size) + char **core_img, size_t *core_size) { lzma_stream strm = LZMA_STREAM_INIT; lzma_ret xzret; @@ -647,20 +661,16 @@ compress_kernel_xz (char *kernel_img, size_t kernel_size, { .id = LZMA_VLI_UNKNOWN, .options = NULL} }; - if (kernel_size < raw_size) - grub_util_error (_("the core image is too small")); - xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE); if (xzret != LZMA_OK) grub_util_error (_("cannot compress the kernel image")); *core_img = xmalloc (kernel_size); - memcpy (*core_img, kernel_img, raw_size); - *core_size = kernel_size - raw_size; - strm.next_in = (unsigned char *) kernel_img + raw_size; - strm.avail_in = kernel_size - raw_size; - strm.next_out = (unsigned char *) *core_img + raw_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) @@ -674,8 +684,6 @@ compress_kernel_xz (char *kernel_img, size_t kernel_size, } *core_size -= strm.avail_out; - - *core_size += raw_size; } #endif @@ -684,19 +692,20 @@ 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_LZMA) - { - compress_kernel_lzma (kernel_img, kernel_size, core_img, - core_size, image_target->raw_size); - return; - } + 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, image_target->raw_size); + core_size); return; } #endif @@ -747,6 +756,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], 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"); @@ -903,31 +916,12 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], &core_img, &core_size, comp); free (kernel_img); - if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) - kernel_img = core_img + total_module_size; - else - kernel_img = core_img; - grub_util_info ("the core size is 0x%x", core_size); 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_uint32_t *) (core_img + image_target->total_module_size)) = grub_host_to_target32 (total_module_size); - if (image_target->compressed_size != TARGET_NO_FIELD) - *((grub_uint32_t *) (kernel_img + image_target->compressed_size)) - = grub_host_to_target32 (core_size - image_target->raw_size); - - /* If we included a drive in our prefix, let GRUB know it doesn't have to - prepend the drive told by BIOS. */ - if (image_target->install_dos_part != TARGET_NO_FIELD - && image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(') - { - *((grub_int32_t *) (kernel_img + image_target->install_dos_part)) - = grub_host_to_target32 (-2); - *((grub_int32_t *) (kernel_img + image_target->install_bsd_part)) - = grub_host_to_target32 (-2); - } if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) { @@ -941,6 +935,9 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], case COMPRESSION_XZ: name = "xz_decompress.img"; break; + case COMPRESSION_LZMA: + name = "lzma_decompress.img"; + break; case COMPRESSION_NONE: name = "none_decompress.img"; break; @@ -952,19 +949,30 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], decompress_size = grub_util_get_image_size (decompress_path); decompress_img = grub_util_read_image (decompress_path); - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE)) - = grub_host_to_target32 (core_size); + 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 (_("Decompressor is too big")); - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE)) - = grub_host_to_target32 (kernel_size + total_module_size); + 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->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR)) - = grub_host_to_target_addr (image_target->link_addr - total_module_size); - else - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR)) - = grub_host_to_target_addr (image_target->link_addr); + 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); @@ -982,6 +990,17 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], core_size = full_size; } + /* If we included a drive in our prefix, let GRUB know it doesn't have to + prepend the drive told by BIOS. */ + if (image_target->install_dos_part != TARGET_NO_FIELD + && image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(') + { + *((grub_int32_t *) (core_img + image_target->install_dos_part)) + = grub_host_to_target32 (-2); + *((grub_int32_t *) (core_img + image_target->install_bsd_part)) + = grub_host_to_target32 (-2); + } + switch (image_target->id) { case IMAGE_I386_PC: @@ -1249,7 +1268,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], rom_img = xmalloc (rom_size); memset (rom_img, 0, rom_size); - *((grub_int32_t *) (kernel_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR)) + *((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);