]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Use decompressors framework on i386-pc. It increases core size
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 12 Nov 2011 18:53:25 +0000 (19:53 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 12 Nov 2011 18:53:25 +0000 (19:53 +0100)
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.

12 files changed:
ChangeLog
grub-core/Makefile.core.def
grub-core/boot/i386/pc/lnxboot.S
grub-core/boot/i386/pc/lzma_decode.S [moved from grub-core/kern/i386/pc/lzma_decode.S with 100% similarity]
grub-core/boot/i386/pc/startup_raw.S [new file with mode: 0644]
grub-core/boot/mips/startup_raw.S
grub-core/kern/i386/int.S
grub-core/kern/i386/pc/init.c
grub-core/kern/i386/pc/startup.S
grub-core/kern/i386/realmode.S
include/grub/offsets.h
util/grub-mkimage.c

index 409a41ca5a2bb823bc47bdbed7a1499aff8f2ed8..eeb9bda57591bc854719f24a3ad024edcaea5bef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2011-11-12  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       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  <phcoder@gmail.com>
 
        * configure.ac: Add -fno-asynchronous-unwind-tables.
index 9590188fb8cf176682fd6968df5f00172f4ea4da..18264f98f16dc469162ca3b904cc117d1820fb14 100644 (file)
@@ -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;
index bb43ed73cf1636305e36687f39a73201802d6b59..e5227d1744695712058402c92ba93a2c61202e13 100644 (file)
@@ -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/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S
new file mode 100644 (file)
index 0000000..4820e34
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/offsets.h>
+#include <grub/machine/boot.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
+
+#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 <rs_decoder.S>
+
+       .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):
index aefd387b6c1e550af7ab158800e3325eb5e82dac..e769266777acc84975ccb240776c68e0bad2dc4d 100644 (file)
@@ -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:
index 58ccfdaaba083be2b4a24672cd5cdbb0218a68fb..7a2b7808ab8aba50fde466704aeba4d4f1eeaef8 100644 (file)
@@ -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
index 6fbfab3b8353a8288dc3d3ae03dbff777222a986..da7230c33a609ae9bc0574c893a3897c0b1096f9 100644 (file)
@@ -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 ();
index 94d4f02eed0b76a6a9b74279b8c233e00079cf0f..058f9efa73ad09ff824036054f53d3bb8135bb7f 100644 (file)
@@ -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
 
 #include <config.h>
 #include <grub/symbol.h>
-#include <grub/machine/boot.h>
-#include <grub/machine/memory.h>
-#include <grub/machine/console.h>
-#include <grub/cpu/linux.h>
-#include <grub/machine/kernel.h>
-#include <grub/term.h>
 #include <multiboot.h>
-#include <multiboot2.h>
-
-#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 <rs_decoder.S>
-
-       .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
index 3e8a13892aa3a503f37fdf1d30deb4cc069359d9..2e16847c8bed19a20ed092fe5d785177c9cda478 100644 (file)
 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/i386/pc/memory.h>
 
 prot_to_real:
        /* just in case, set GDT */
index 92354f7008cea99b191d7e6168bd61b7bf58ddcf..e3b9a377cb3724d17ac15d2bed606cfd8f34aab3 100644 (file)
 #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
 /* 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
 
 #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
index 9369fba3dcea179d37698cbda5cfb05420f7fdea..9da72f6c9c1d6cd0ab63c6afd1c18bb1a389920b 100644 (file)
@@ -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);