Support xz compression on yeeloong.

* Makefile.util.def (grub-mkimage): Add $(LIBLZMA).
	* configure.ac: Check for LZMA.
	* grub-core/Makefile.core.def (xz_decompress): New target.
	(none_decompress): Likewise.
	* grub-core/boot/decompressor/minilib.c: New file.
	* grub-core/boot/decompressor/none.c: Likewise.
	* grub-core/boot/decompressor/xz.c: Likewise.
	* grub-core/kern/mips/cache.S: Change to noreorder nomacro.
	* grub-core/kern/mips/cache_flush.S: Likewise.
	* grub-core/kern/i386/pc/lzma_decode.S: Remove dead code.
	* grub-core/kern/mips/startup.S: Move first stage to ...
	* grub-core/boot/mips/startup_raw.S: ...here. Change to noreorder
	nomacro.
	* grub-core/kern/mips/startup.S: Change to noreorder nomacro.
	* grub-core/lib/mips/relocator_asm.S: Change to noreorder nomacro.
	* grub-core/lib/xzembed/xz_dec_bcj.c [GRUB_EMBED_DECOMPRESSOR]:
	Allocate statically.
	* grub-core/lib/xzembed/xz_dec_lzma2.c [GRUB_EMBED_DECOMPRESSOR]:
	Allocate statically or use scratch. Don't check CRC32.
	* grub-core/lib/xzembed/xz_dec_stream.c [GRUB_EMBED_DECOMPRESSOR]:
	Allocate statically. Don't check CRC32.
	* include/grub/decompressor.h: New file.
	* include/grub/offsets.h (GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE):
	Removed.
	(GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE): New field.
	(GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE): Adjusted.
	(GRUB_KERNEL_MIPS_YEELOONG_PREFIX): Likewise.
	(GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END): Likewise.
	(GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE): New define.
	* util/grub-mkimage.c (grub_compression_t): New type.
	(PLATFORM_FLAGS_DECOMPRESSORS): New flag.
	(image_target_desc): New field default_compression.
	(image_targets): Adjust yeeloong targets.
	(compress_kernel_xz) [HAVE_LIBLZMA]: New function.
	(compress_kernel): New parameter comp.
	(generate_image): Likewise. Handle new compression case.
	(options): New option --compression
	(help): Likewise.
	(main): Handle new option.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-23 02:10:44 +02:00
commit 6d0fa83c79
19 changed files with 812 additions and 233 deletions

View file

@ -1,3 +1,47 @@
2010-09-23 Vladimir Serbinenko <phcoder@gmail.com>
Support xz compression on yeeloong.
* Makefile.util.def (grub-mkimage): Add $(LIBLZMA).
* configure.ac: Check for LZMA.
* grub-core/Makefile.core.def (xz_decompress): New target.
(none_decompress): Likewise.
* grub-core/boot/decompressor/minilib.c: New file.
* grub-core/boot/decompressor/none.c: Likewise.
* grub-core/boot/decompressor/xz.c: Likewise.
* grub-core/kern/mips/cache.S: Change to noreorder nomacro.
* grub-core/kern/mips/cache_flush.S: Likewise.
* grub-core/kern/i386/pc/lzma_decode.S: Remove dead code.
* grub-core/kern/mips/startup.S: Move first stage to ...
* grub-core/boot/mips/startup_raw.S: ...here. Change to noreorder
nomacro.
* grub-core/kern/mips/startup.S: Change to noreorder nomacro.
* grub-core/lib/mips/relocator_asm.S: Change to noreorder nomacro.
* grub-core/lib/xzembed/xz_dec_bcj.c [GRUB_EMBED_DECOMPRESSOR]:
Allocate statically.
* grub-core/lib/xzembed/xz_dec_lzma2.c [GRUB_EMBED_DECOMPRESSOR]:
Allocate statically or use scratch. Don't check CRC32.
* grub-core/lib/xzembed/xz_dec_stream.c [GRUB_EMBED_DECOMPRESSOR]:
Allocate statically. Don't check CRC32.
* include/grub/decompressor.h: New file.
* include/grub/offsets.h (GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE):
Removed.
(GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE): New field.
(GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE): Adjusted.
(GRUB_KERNEL_MIPS_YEELOONG_PREFIX): Likewise.
(GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END): Likewise.
(GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE): New define.
* util/grub-mkimage.c (grub_compression_t): New type.
(PLATFORM_FLAGS_DECOMPRESSORS): New flag.
(image_target_desc): New field default_compression.
(image_targets): Adjust yeeloong targets.
(compress_kernel_xz) [HAVE_LIBLZMA]: New function.
(compress_kernel): New parameter comp.
(generate_image): Likewise. Handle new compression case.
(options): New option --compression
(help): Likewise.
(main): Handle new option.
2010-09-22 Grégoire Sutre <gregoire.sutre@gmail.com>
* grub-core/kern/emu/hostdisk.c [__NetBSD__]: Define FLOPPY_MAJOR.
@ -14,7 +58,7 @@
2010-09-22 Vladimir Serbinenko <phcoder@gmail.com>
Implement EFI and ACPI multiboot2 extensions.
Implement EFI and ACPI multiboot2 extensions.
* grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare
new tags as supported.
@ -22,7 +66,7 @@
(grub_multiboot_get_mbi_size): Take new tags into account.
(grub_multiboot_make_mbi): Add new tags.
* include/grub/multiboot.h (GRUB_MACHINE_HAS_ACPI): New definition.
2010-09-21 Aleš Nesrsta <starous@volny.cz>
* grub-core/bus/usb/serial/common.c (grub_usbserial_attach):

View file

@ -108,6 +108,7 @@ program = {
extra_dist = util/grub-mkimagexx.c;
ldadd = libgrub.a;
ldadd = '$(LIBLZMA)';
ldadd = '$(LIBINTL) $(LIBDEVMAPPER)';
ldadd = grub-core/gnulib/libgnu.a;
cppflags = '-DGRUB_PKGLIBROOTDIR=\"$(pkglibrootdir)\"';

View file

@ -849,6 +849,12 @@ fi
AC_SUBST([LIBDEVMAPPER])
AC_CHECK_LIB([lzma], [lzma_code],
[LIBLZMA="-llzma"
AC_DEFINE([HAVE_LIBLZMA], [1],
[Define to 1 if you have the LZMA library.])],)
AC_SUBST([LIBLZMA])
AC_CHECK_LIB([zfs], [libzfs_init],
[LIBZFS="-lzfs"
AC_DEFINE([HAVE_LIBZFS], [1],

View file

@ -290,6 +290,38 @@ image = {
enable = i386_pc;
};
image = {
name = xz_decompress;
mips = boot/mips/startup_raw.S;
common = boot/decompressor/minilib.c;
common = boot/decompressor/xz.c;
common = lib/xzembed/xz_dec_bcj.c;
common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c;
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
mips_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000';
objcopyflags = '-O binary';
ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000';
cflags = '-static-libgcc';
enable = mips;
};
image = {
name = none_decompress;
mips = boot/mips/startup_raw.S;
common = boot/decompressor/none.c;
mips_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000';
objcopyflags = '-O binary';
ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000';
cflags = '-static-libgcc';
enable = mips;
};
image = {
name = fwstart;
mips_yeeloong = boot/mips/yeeloong/fwstart.S;

View file

@ -0,0 +1,102 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/types.h>
#include <grub/misc.h>
#include <grub/decompressor.h>
void *
memset (void *s, int c, grub_size_t len)
{
grub_uint8_t *ptr;
for (ptr = s; len; ptr++, len--)
*ptr = c;
return s;
}
void *
grub_memmove (void *dest, const void *src, grub_size_t n)
{
char *d = (char *) dest;
const char *s = (const char *) src;
if (d < s)
while (n--)
*d++ = *s++;
else
{
d += n;
s += n;
while (n--)
*--d = *--s;
}
return dest;
}
int
grub_memcmp (const void *s1, const void *s2, grub_size_t n)
{
const char *t1 = s1;
const char *t2 = s2;
while (n--)
{
if (*t1 != *t2)
return (int) *t1 - (int) *t2;
t1++;
t2++;
}
return 0;
}
int memcmp (const void *s1, const void *s2, grub_size_t n)
__attribute__ ((alias ("grub_memcmp")));
void *memmove (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memmove")));
void *memcpy (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memmove")));
void *grub_decompressor_scratch;
void
find_scratch (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize)
{
#ifdef _mips
/* Decoding from ROM. */
if (((grub_addr_t) src & 0x10000000))
{
grub_decompressor_scratch = (void *) ALIGN_UP((grub_addr_t) dst + dstsize,
256);
return;
}
#endif
if ((char *) src + srcsize > (char *) dst + dstsize)
grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) src + srcsize,
256);
else
grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) dst + dstsize,
256);
return;
}

View file

@ -0,0 +1,39 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/decompressor.h>
void
grub_decompress_core (void *src, void *dest, unsigned long n,
unsigned long dstsize __attribute__ ((unused)))
{
char *d = (char *) dest;
const char *s = (const char *) src;
if (d < s)
while (n--)
*d++ = *s++;
else
{
d += n;
s += n;
while (n--)
*--d = *--s;
}
}

View file

@ -0,0 +1,60 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/types.h>
#include <grub/misc.h>
#include <grub/decompressor.h>
#include "xz.h"
#include "xz_stream.h"
void
grub_decompress_core (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize)
{
struct xz_dec *dec;
struct xz_buf buf;
find_scratch (src, dst, srcsize, dstsize);
dec = xz_dec_init (GRUB_DECOMPRESSOR_DICT_SIZE);
buf.in = src;
buf.in_pos = 0;
buf.in_size = srcsize;
buf.out = dst;
buf.out_pos = 0;
buf.out_size = dstsize;
while (buf.in_pos != buf.in_size)
{
enum xz_ret xzret;
xzret = xz_dec_run (dec, &buf);
switch (xzret)
{
case XZ_MEMLIMIT_ERROR:
case XZ_FORMAT_ERROR:
case XZ_OPTIONS_ERROR:
case XZ_DATA_ERROR:
case XZ_BUF_ERROR:
return;
default:
break;
}
}
}

View file

@ -0,0 +1,187 @@
/* startup.S - Startup code for the MIPS. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/symbol.h>
#include <grub/offsets.h>
#include <grub/machine/memory.h>
#include <grub/offsets.h>
#define BASE_ADDR 8
.extern __bss_start
.extern _end
.globl __start, _start, start
.set noreorder
.set nomacro
__start:
_start:
start:
bal codestart
nop
base:
. = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
compressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE
uncompressed_size:
.long 0
codestart:
/* Save our base. */
move $s0, $ra
/* Parse arguments. Has to be done before relocation.
So need to do it in asm. */
#ifdef GRUB_MACHINE_MIPS_YEELOONG
move $s2, $zero
move $s3, $zero
move $s4, $zero
move $s5, $zero
/* $a2 has the environment. */
addiu $t0, $a2, 1
beq $t0, $zero, argdone
nop
move $t0, $a2
argcont:
lw $t1, 0($t0)
beq $t1, $zero, argdone
nop
#define DO_PARSE(str, reg) \
addiu $t2, $s0, (str-base);\
bal parsestr;\
nop ;\
beq $v0, $zero, 1f;\
nop ;\
b 2f;\
move reg, $v0; \
1:
DO_PARSE (busclockstr, $s2)
DO_PARSE (cpuclockstr, $s3)
DO_PARSE (memsizestr, $s4)
DO_PARSE (highmemsizestr, $s5)
2:
b argcont
addiu $t0, $t0, 4
parsestr:
move $v0, $zero
move $t3, $t1
3:
lb $t4, 0($t2)
lb $t5, 0($t3)
addiu $t2, $t2, 1
addiu $t3, $t3, 1
beq $t5, $zero, 1f
nop
beq $t5, $t4, 3b
nop
bne $t4, $zero, 1f
nop
addiu $t3, $t3, 0xffff
digcont:
lb $t5, 0($t3)
/* Substract '0' from digit. */
addiu $t5, $t5, 0xffd0
bltz $t5, 1f
nop
addiu $t4, $t5, 0xfff7
bgtz $t4, 1f
nop
/* Multiply $v0 by 10 with bitshifts. */
sll $v0, $v0, 1
sll $t4, $v0, 2
addu $v0, $v0, $t4
addu $v0, $v0, $t5
addiu $t3, $t3, 1
b digcont
nop
1:
jr $ra
nop
busclockstr: .asciiz "busclock="
cpuclockstr: .asciiz "cpuclock="
memsizestr: .asciiz "memsize="
highmemsizestr: .asciiz "highmemsize="
.p2align 2
argdone:
#endif
/* Copy the decompressor. */
lui $t1, %hi(base)
addiu $t1, $t1, %lo(base)
lui $t3, %hi(__bss_start)
addiu $t3, $t3, %lo(__bss_start)
move $t2, $s0
1:
beq $t1, $t3, 2f
lb $t4, 0($t2)
sb $t4, 0($t1)
addiu $t1, $t1, 1
b 1b
addiu $t2, $t2, 1
2:
/* Clean out its BSS. */
lui $t1, %hi(__bss_start)
addiu $t1, $t1, %lo(__bss_start)
lui $t2, %hi(_end)
addiu $t2, $t2, %lo(_end)
1:
beq $t1, $t2, 2f
nop
sb $zero, 0($t1)
b 1b
addiu $t1, $t1, 1
2:
/* Decompress the payload. */
lui $a0, %hi(__bss_start)
addiu $a0, $a0, %lo(__bss_start)
lui $t0, %hi(base)
addiu $t0, $t0, %lo(base)
subu $a0, $a0, $t0
addu $a0, $a0, $s0
lui $a1, %hi(GRUB_MACHINE_LINK_ADDR)
addiu $a1, %lo(GRUB_MACHINE_LINK_ADDR)
lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
move $s1, $a1
/* $a0 contains source compressed address, $a1 is destination,
$a2 is compressed size, $a3 is uncompressed size.
*/
move $s6, $a3
lui $sp, %hi(_start - 256)
bal EXT_C(grub_decompress_core)
addiu $sp, $sp, %lo(_start - 256)
move $a0, $s1
move $a1, $s6
#include "../../kern/mips/cache_flush.S"
lui $t1, %hi(GRUB_MACHINE_LINK_ADDR)
addiu $t1, %lo(GRUB_MACHINE_LINK_ADDR)
jr $t1
nop

View file

@ -77,69 +77,6 @@
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#if 0
DbgOut:
pushf
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
call _DebugPrint
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
popf
ret
/*
* int LzmaDecodeProperties(CLzmaProperties *propsRes,
* const unsigned char *propsData,
* int size);
*/
_LzmaDecodePropertiesA:
movb (%edx), %dl
xorl %ecx, %ecx
1:
cmpb $45, %dl
jb 2f
incl %ecx
subb $45, %dl
jmp 1b
2:
movl %ecx, 8(%eax) /* pb */
xorl %ecx, %ecx
1:
cmpb $9, %dl
jb 2f
incl %ecx
subb $9, %dl
2:
movl %ecx, 4(%eax) /* lp */
movb %dl, %cl
movl %ecx, (%eax) /* lc */
#endif
#ifndef ASM_FILE
xorl %eax, %eax
#endif
ret
#define out_size 8(%ebp)
#define now_pos -4(%ebp)

View file

@ -1,6 +1,9 @@
#include <grub/symbol.h>
.set noreorder
.set nomacro
FUNCTION (grub_cpu_flush_cache)
FUNCTION (grub_arch_sync_caches)
#include "cache_flush.S"

View file

@ -9,15 +9,15 @@
subu $t1, $t3, $t2
1:
cache 1, 0($t0)
addiu $t0, $t0, 0x1
addiu $t1, $t1, 0xffff
bne $t1, $zero, 1b
addiu $t0, $t0, 0x1
sync
move $t0, $t2
subu $t1, $t3, $t2
2:
cache 0, 0($t0)
addiu $t0, $t0, 0x1
addiu $t1, $t1, 0xffff
bne $t1, $zero, 2b
addiu $t0, $t0, 0x1
sync

View file

@ -22,128 +22,23 @@
#include <grub/machine/memory.h>
#include <grub/offsets.h>
#define BASE_ADDR 8
.extern __bss_start
.extern _end
#define BASE_ADDR 8
.globl __start, _start, start
.set noreorder
.set nomacro
__start:
_start:
start:
bal codestart
base:
. = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
compressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE
start:
.extern __bss_start
.extern _end
bal cont
nop
. = _start + GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE
total_module_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE
kernel_image_size:
.long 0
codestart:
/* Save our base. */
move $s0, $ra
/* Parse arguments. Has to be done before relocation.
So need to do it in asm. */
#ifdef GRUB_MACHINE_MIPS_YEELOONG
move $s2, $zero
move $s3, $zero
move $s4, $zero
move $s5, $zero
/* $a2 has the environment. */
addiu $t0, $a2, 1
beq $t0, $zero, argdone
move $t0, $a2
argcont:
lw $t1, 0($t0)
beq $t1, $zero, argdone
#define DO_PARSE(str, reg) \
addiu $t2, $s0, (str-base);\
bal parsestr;\
beq $v0, $zero, 1f;\
move reg, $v0;\
b 2f;\
1:
DO_PARSE (busclockstr, $s2)
DO_PARSE (cpuclockstr, $s3)
DO_PARSE (memsizestr, $s4)
DO_PARSE (highmemsizestr, $s5)
2:
addiu $t0, $t0, 4
b argcont
parsestr:
move $v0, $zero
move $t3, $t1
3:
lb $t4, 0($t2)
lb $t5, 0($t3)
addiu $t2, $t2, 1
addiu $t3, $t3, 1
beq $t5, $zero, 1f
beq $t5, $t4, 3b
bne $t4, $zero, 1f
addiu $t3, $t3, 0xffff
digcont:
lb $t5, 0($t3)
/* Substract '0' from digit. */
addiu $t5, $t5, 0xffd0
bltz $t5, 1f
addiu $t4, $t5, 0xfff7
bgtz $t4, 1f
/* Multiply $v0 by 10 with bitshifts. */
sll $v0, $v0, 1
sll $t4, $v0, 2
addu $v0, $v0, $t4
addu $v0, $v0, $t5
addiu $t3, $t3, 1
b digcont
1:
jr $ra
busclockstr: .asciiz "busclock="
cpuclockstr: .asciiz "cpuclock="
memsizestr: .asciiz "memsize="
highmemsizestr: .asciiz "highmemsize="
.p2align 2
argdone:
#endif
/* Decompress the payload. */
addiu $a0, $s0, GRUB_KERNEL_MACHINE_RAW_SIZE - BASE_ADDR
lui $a1, %hi(compressed)
addiu $a1, %lo(compressed)
lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
move $s1, $a1
/* $a0 contains source compressed address, $a1 is destination,
$a2 is compressed size. FIXME: put LZMA here. Don't clober $s0,
$s1, $s2, $s3, $s4 and $s5.
On return $v0 contains uncompressed size.
*/
move $v0, $a2
reloccont:
lb $t4, 0($a0)
sb $t4, 0($a1)
addiu $a1,$a1,1
addiu $a0,$a0,1
addiu $a2, 0xffff
bne $a2, $0, reloccont
move $a0, $s1
move $a1, $v0
#include "cache_flush.S"
lui $t1, %hi(cont)
addiu $t1, %lo(cont)
jr $t1
. = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
compressed:
. = _start + GRUB_KERNEL_MACHINE_PREFIX
VARIABLE(grub_prefix)
@ -166,6 +61,8 @@ VARIABLE (grub_arch_highmemsize)
.long 0
#endif
cont:
/* Save our base. */
move $s0, $ra
#ifdef GRUB_MACHINE_MIPS_YEELOONG
lui $t1, %hi(grub_arch_busclock)
@ -177,15 +74,13 @@ cont:
#endif
/* Move the modules out of BSS. */
lui $t1, %hi(_start)
addiu $t1, %lo(_start)
lw $t2, (GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE - BASE_ADDR)($s0)
addu $t2, $t1, $t2
lui $t2, %hi(__bss_start)
addiu $t2, %lo(__bss_start)
lui $t1, %hi(_end)
addiu $t1, %lo(_end)
addiu $t1, (GRUB_KERNEL_MACHINE_MOD_ALIGN-1)
li $t3, (GRUB_KERNEL_MACHINE_MOD_ALIGN-1)
addiu $t1, (GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
li $t3, (GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
nor $t3, $t3, $0
and $t1, $t1, $t3
@ -194,33 +89,38 @@ cont:
/* Backward copy. */
add $t1, $t1, $t3
add $t2, $t2, $t3
addiu $t1, $t1, 0xffff
addiu $t2, $t2, 0xffff
addiu $t1, $t1, -1
addiu $t2, $t2, -1
/* $t2 is source. $t1 is destination. $t3 is size. */
modulesmovcont:
beq $t3, $0, modulesmovdone
nop
lb $t4, 0($t2)
sb $t4, 0($t1)
addiu $t1,$t1,0xffff
addiu $t2,$t2,0xffff
addiu $t3, 0xffff
bne $t3, $0, modulesmovcont
addiu $t2, $t2, -1
addiu $t1, $t1, -1
b modulesmovcont
addiu $t3, $t3, -1
modulesmovdone:
/* Clean BSS. */
lui $t1, %hi(__bss_start)
addiu $t1, %lo(__bss_start)
addiu $t1, $t1, %lo(__bss_start)
lui $t2, %hi(_end)
addiu $t2, %lo(_end)
addiu $t2, $t2, %lo(_end)
bsscont:
sb $0,0($t1)
addiu $t1,$t1,1
sltu $t3,$t1,$t2
addiu $t1, $t1, 1
sltu $t3, $t1, $t2
bne $t3, $0, bsscont
nop
li $sp, GRUB_MACHINE_MEMORY_STACK_HIGH
lui $t1, %hi(grub_main)
addiu $t1, %lo(grub_main)
lui $sp, %hi(GRUB_MACHINE_MEMORY_STACK_HIGH)
jr $t1
addiu $sp, $sp, %lo(GRUB_MACHINE_MEMORY_STACK_HIGH)

View file

@ -20,6 +20,9 @@
.p2align 4 /* force 16-byte alignment */
.set noreorder
.set nomacro
VARIABLE (grub_relocator_forward_start)
move $a0, $9
move $a1, $10
@ -28,9 +31,9 @@ copycont1:
lb $11,0($8)
sb $11,0($9)
addiu $8, $8, 1
addiu $9, $9, 1
addiu $10, $10, -1
bne $10, $0, copycont1
addiu $9, $9, 1
#include "../../kern/mips/cache_flush.S"
@ -49,9 +52,9 @@ copycont2:
lb $11,0($8)
sb $11,0($9)
addiu $8, $8, -1
addiu $9, $9, -1
addiu $10, $10, -1
bne $10, $0, copycont2
addiu $9, $9, -1
#include "../../kern/mips/cache_flush.S"

View file

@ -520,9 +520,18 @@ enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
return s->ret;
}
#ifdef GRUB_EMBED_DECOMPRESSOR
struct xz_dec_bcj bcj;
#endif
struct xz_dec_bcj * xz_dec_bcj_create(bool single_call)
{
struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
struct xz_dec_bcj *s;
#ifdef GRUB_EMBED_DECOMPRESSOR
s = &bcj;
#else
s = kmalloc(sizeof(*s), GFP_KERNEL);
#endif
if (s != NULL)
s->single_call = single_call;

View file

@ -1100,10 +1100,16 @@ enum xz_ret xz_dec_lzma2_run(
return XZ_OK;
}
#ifdef GRUB_EMBED_DECOMPRESSOR
#include <grub/decompressor.h>
static struct xz_dec_lzma2 lzma2;
#endif
struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max)
{
struct xz_dec_lzma2 *s;
#ifndef GRUB_EMBED_DECOMPRESSOR
/* Maximum supported dictionary by this implementation is 3 GiB. */
if (dict_max > ((uint32_t)3 << 30))
return NULL;
@ -1120,6 +1126,11 @@ struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max)
}
}
#else
s = &lzma2;
s->dict.buf = grub_decompressor_scratch;
#endif
s->dict.allocated = dict_max;
return s;
@ -1135,6 +1146,7 @@ enum xz_ret xz_dec_lzma2_reset(
s->dict.size = 2 + (props & 1);
s->dict.size <<= (props >> 1) + 11;
#ifndef GRUB_EMBED_DECOMPRESSOR
if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size)
{
/* enlarge dictionary buffer */
@ -1146,7 +1158,7 @@ enum xz_ret xz_dec_lzma2_reset(
s->dict.buf = newdict;
s->dict.allocated = s->dict.size;
}
#endif
s->dict.end = s->dict.size;
s->lzma.len = 0;
@ -1159,10 +1171,12 @@ enum xz_ret xz_dec_lzma2_reset(
return XZ_OK;
}
void xz_dec_lzma2_end(struct xz_dec_lzma2 *s)
void xz_dec_lzma2_end(struct xz_dec_lzma2 *s __attribute__ ((unused)))
{
#ifndef GRUB_EMBED_DECOMPRESSOR
if (s->dict.allocated > 0)
vfree(s->dict.buf);
kfree(s);
#endif
}

View file

@ -31,7 +31,9 @@
struct xz_dec_hash {
vli_type unpadded;
vli_type uncompressed;
#ifndef GRUB_EMBED_DECOMPRESSOR
uint8_t *crc32_context;
#endif
};
struct xz_dec {
@ -247,9 +249,11 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
> s->block_header.uncompressed)
return XZ_DATA_ERROR;
#ifndef GRUB_EMBED_DECOMPRESSOR
if (s->has_crc32)
GRUB_MD_CRC32->write(s->crc32_context,b->out + s->out_start,
b->out_pos - s->out_start);
#endif
if (ret == XZ_STREAM_END) {
if (s->block_header.compressed != VLI_UNKNOWN
@ -269,8 +273,10 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
s->block.hash.uncompressed += s->block.uncompressed;
#ifndef GRUB_EMBED_DECOMPRESSOR
GRUB_MD_CRC32->write(s->block.hash.crc32_context,
(const uint8_t *)&s->block.hash, 2 * sizeof(vli_type));
#endif
++s->block.count;
}
@ -283,7 +289,9 @@ static void index_update(struct xz_dec *s, const struct xz_buf *b)
{
size_t in_used = b->in_pos - s->in_start;
s->index.size += in_used;
#ifndef GRUB_EMBED_DECOMPRESSOR
GRUB_MD_CRC32->write(s->crc32_context,b->in + s->in_start, in_used);
#endif
}
/*
@ -328,8 +336,10 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
case SEQ_INDEX_UNCOMPRESSED:
s->index.hash.uncompressed += s->vli;
#ifndef GRUB_EMBED_DECOMPRESSOR
GRUB_MD_CRC32->write(s->index.hash.crc32_context,
(const uint8_t *)&s->index.hash, 2 * sizeof(vli_type));
#endif
--s->index.count;
s->index.sequence = SEQ_INDEX_UNPADDED;
@ -346,24 +356,30 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
*/
static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b)
{
#ifndef GRUB_EMBED_DECOMPRESSOR
if(s->crc32_temp == 0)
{
GRUB_MD_CRC32->final(s->crc32_context);
s->crc32_temp = get_unaligned_be32(GRUB_MD_CRC32->read(s->crc32_context));
}
#endif
do {
if (b->in_pos == b->in_size)
return XZ_OK;
#ifndef GRUB_EMBED_DECOMPRESSOR
if (((s->crc32_temp >> s->pos) & 0xFF) != b->in[b->in_pos++])
return XZ_DATA_ERROR;
#endif
s->pos += 8;
} while (s->pos < 32);
#ifndef GRUB_EMBED_DECOMPRESSOR
GRUB_MD_CRC32->init(s->crc32_context);
#endif
s->crc32_temp = 0;
s->pos = 0;
@ -376,6 +392,7 @@ static enum xz_ret dec_stream_header(struct xz_dec *s)
if (! memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
return XZ_FORMAT_ERROR;
#ifndef GRUB_EMBED_DECOMPRESSOR
uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
GRUB_MD_CRC32->init(crc32_context);
@ -387,6 +404,7 @@ static enum xz_ret dec_stream_header(struct xz_dec *s)
if(resultcrc != readcrc)
return XZ_DATA_ERROR;
#endif
/*
* Decode the Stream Flags field. Of integrity checks, we support
@ -407,6 +425,7 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s)
if (! memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
return XZ_DATA_ERROR;
#ifndef GRUB_EMBED_DECOMPRESSOR
uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
GRUB_MD_CRC32->init(crc32_context);
@ -418,6 +437,7 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s)
if(resultcrc != readcrc)
return XZ_DATA_ERROR;
#endif
/*
* Validate Backward Size. Note that we never added the size of the
@ -447,7 +467,7 @@ static enum xz_ret dec_block_header(struct xz_dec *s)
* eight bytes so this is safe.
*/
s->temp.size -= 4;
#ifndef GRUB_EMBED_DECOMPRESSOR
uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
GRUB_MD_CRC32->init(crc32_context);
@ -459,6 +479,7 @@ static enum xz_ret dec_block_header(struct xz_dec *s)
if (resultcrc != readcrc)
return XZ_DATA_ERROR;
#endif
s->temp.pos = 2;
@ -669,6 +690,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
/* Finish the CRC32 value and Index size. */
index_update(s, b);
#ifndef GRUB_EMBED_DECOMPRESSOR
/* Compare the hashes to validate the Index field. */
GRUB_MD_CRC32->final(s->block.hash.crc32_context);
GRUB_MD_CRC32->final(s->index.hash.crc32_context);
@ -681,6 +703,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
{
return XZ_DATA_ERROR;
}
#endif
s->sequence = SEQ_INDEX_CRC32;
@ -764,12 +787,22 @@ enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b)
return ret;
}
#ifdef GRUB_EMBED_DECOMPRESSOR
struct xz_dec decoder;
#endif
struct xz_dec * xz_dec_init(uint32_t dict_max)
{
struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
struct xz_dec *s;
#ifdef GRUB_EMBED_DECOMPRESSOR
s = &decoder;
#else
s = kmalloc(sizeof(*s), GFP_KERNEL);
if (s == NULL)
return NULL;
#endif
#ifndef GRUB_EMBED_DECOMPRESSOR
/* prepare CRC32 calculators */
if(GRUB_MD_CRC32 == NULL)
{
@ -803,10 +836,11 @@ struct xz_dec * xz_dec_init(uint32_t dict_max)
GRUB_MD_CRC32->init(s->crc32_context);
s->crc32_temp = 0;
GRUB_MD_CRC32->init(s->index.hash.crc32_context);
GRUB_MD_CRC32->init(s->block.hash.crc32_context);
#endif
s->crc32_temp = 0;
s->single_call = dict_max == 0;
@ -828,7 +862,9 @@ error_lzma2:
xz_dec_bcj_end(s->bcj);
error_bcj:
#endif
#ifndef GRUB_EMBED_DECOMPRESSOR
kfree(s);
#endif
return NULL;
}
@ -839,34 +875,45 @@ void xz_dec_reset(struct xz_dec *s)
s->pos = 0;
{
#ifndef GRUB_EMBED_DECOMPRESSOR
uint8_t *t;
t = s->block.hash.crc32_context;
#endif
memzero(&s->block, sizeof(s->block));
#ifndef GRUB_EMBED_DECOMPRESSOR
s->block.hash.crc32_context = t;
t = s->index.hash.crc32_context;
#endif
memzero(&s->index, sizeof(s->index));
#ifndef GRUB_EMBED_DECOMPRESSOR
s->index.hash.crc32_context = t;
#endif
}
s->temp.pos = 0;
s->temp.size = STREAM_HEADER_SIZE;
#ifndef GRUB_EMBED_DECOMPRESSOR
GRUB_MD_CRC32->init(s->crc32_context);
s->crc32_temp = 0;
GRUB_MD_CRC32->init(s->index.hash.crc32_context);
GRUB_MD_CRC32->init(s->block.hash.crc32_context);
#endif
s->crc32_temp = 0;
}
void xz_dec_end(struct xz_dec *s)
{
if (s != NULL) {
xz_dec_lzma2_end(s->lzma2);
#ifndef GRUB_EMBED_DECOMPRESSOR
kfree(s->index.hash.crc32_context);
kfree(s->block.hash.crc32_context);
kfree(s->crc32_context);
#endif
#ifdef XZ_DEC_BCJ
xz_dec_bcj_end(s->bcj);
#endif
#ifndef GRUB_EMBED_DECOMPRESSOR
kfree(s);
#endif
}
}

View file

@ -0,0 +1,34 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/>.
*/
#ifndef GRUB_DECOMPRESSOR_HEADER
#define GRUB_DECOMPRESSOR_HEADER 1
void
grub_decompress_core (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize);
void
find_scratch (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize);
#define GRUB_DECOMPRESSOR_DICT_SIZE (1 << 16)
extern void *grub_decompressor_scratch;
#endif

View file

@ -102,13 +102,12 @@
#define GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN 32
#define GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE 0x200
#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8
#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0xc
#define GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE 0x10
#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8
#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE 0xc
#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE
#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE + 0x48
#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0x08
#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c
#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54
/* The offset of GRUB_PREFIX. */
#define GRUB_KERNEL_I386_EFI_PREFIX 0x8
@ -158,6 +157,7 @@
#define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _TOTAL_MODULE_SIZE)
#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _KERNEL_IMAGE_SIZE)
#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _COMPRESSED_SIZE)
#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_SIZE)
#define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX)
#define GRUB_KERNEL_MACHINE_PREFIX_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX_END)

View file

@ -45,7 +45,16 @@
#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
#ifdef HAVE_LIBLZMA
#include <lzma.h>
#endif
#define TARGET_NO_FIELD 0xffffffff
typedef enum {
COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ
} grub_compression_t;
struct image_target_desc
{
const char *name;
@ -60,7 +69,8 @@ struct image_target_desc
enum
{
PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_LZMA = 1
PLATFORM_FLAGS_LZMA = 1,
PLATFORM_FLAGS_DECOMPRESSORS = 2
} flags;
unsigned prefix;
unsigned prefix_end;
@ -75,6 +85,7 @@ struct image_target_desc
unsigned install_dos_part, install_bsd_part;
grub_uint64_t link_addr;
unsigned mod_gap, mod_align;
grub_compression_t default_compression;
};
struct image_target_desc image_targets[] =
@ -248,40 +259,42 @@ struct image_target_desc image_targets[] =
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_YEELOONG_FLASH,
.flags = PLATFORM_FLAGS_NONE,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
.prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
.raw_size = GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE,
.raw_size = 0,
.total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE,
.compressed_size = GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE,
.kernel_image_size = GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE,
.compressed_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
.link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN
.link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN,
.default_compression = COMPRESSION_NONE
},
{
.name = "mipsel-yeeloong-elf",
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_YEELOONG_ELF,
.flags = PLATFORM_FLAGS_NONE,
.flags = PLATFORM_FLAGS_DECOMPRESSORS,
.prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
.prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
.raw_size = GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE,
.raw_size = 0,
.total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE,
.compressed_size = GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE,
.kernel_image_size = GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE,
.compressed_size = TARGET_NO_FIELD,
.kernel_image_size = TARGET_NO_FIELD,
.section_align = 1,
.vaddr_offset = 0,
.install_dos_part = TARGET_NO_FIELD,
.install_bsd_part = TARGET_NO_FIELD,
.link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
.elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN
.link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN,
.default_compression = COMPRESSION_NONE
},
{
.name = "powerpc-ieee1275",
@ -493,9 +506,66 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size,
*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)
{
lzma_stream strm = LZMA_STREAM_INIT;
lzma_ret xzret;
lzma_options_lzma lzopts = {
.dict_size = 1 << 16,
.preset_dict = NULL,
.preset_dict_size = 0,
.lc = 3,
.lp = 0,
.pb = 2,
.mode = LZMA_MODE_NORMAL,
.nice_len = 64,
.mf = LZMA_MF_BT4,
.depth = 0,
};
lzma_filter fltrs[] = {
{ .id = LZMA_FILTER_LZMA2, .options = &lzopts},
{ .id = LZMA_VLI_UNKNOWN, .options = NULL}
};
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;
strm.avail_out = *core_size;
while (1)
{
xzret = lzma_code (&strm, LZMA_FINISH);
if (xzret == LZMA_OK)
continue;
if (xzret == LZMA_STREAM_END)
break;
grub_util_error (_("cannot compress the kernel image"));
}
*core_size -= strm.avail_out;
*core_size += raw_size;
}
#endif
static void
compress_kernel (struct image_target_desc *image_target, char *kernel_img,
size_t kernel_size, char **core_img, size_t *core_size)
size_t kernel_size, char **core_img, size_t *core_size,
grub_compression_t comp)
{
if (image_target->flags & PLATFORM_FLAGS_LZMA)
{
@ -504,6 +574,20 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img,
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);
return;
}
#endif
if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS
&& (comp != COMPRESSION_NONE))
grub_util_error ("unknown compression %d\n", comp);
*core_img = xmalloc (kernel_size);
memcpy (*core_img, kernel_img, kernel_size);
*core_size = kernel_size;
@ -527,7 +611,8 @@ struct fixup_block_list
static void
generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
char *memdisk_path, char *config_path,
struct image_target_desc *image_target, int note)
struct image_target_desc *image_target, int note,
grub_compression_t comp)
{
char *kernel_img, *core_img;
size_t kernel_size, total_module_size, core_size, exec_size;
@ -539,6 +624,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
grub_uint64_t start_address;
void *rel_section;
grub_size_t reloc_size, align;
if (comp == COMPRESSION_AUTO)
comp = image_target->default_compression;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
kernel_path = grub_util_get_path (dir, "kernel.img");
@ -653,13 +742,19 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
offset += config_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_host_to_target32 (total_module_size);
grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size);
compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
&core_img, &core_size);
&core_img, &core_size, comp);
grub_util_info ("the core size is 0x%x", core_size);
if (image_target->total_module_size != TARGET_NO_FIELD)
if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
&& image_target->total_module_size != TARGET_NO_FIELD)
*((grub_uint32_t *) (core_img + image_target->total_module_size))
= grub_host_to_target32 (total_module_size);
if (image_target->kernel_image_size != TARGET_NO_FIELD)
@ -680,6 +775,53 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
= grub_host_to_target32 (-2);
}
if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
{
char *full_img;
size_t full_size;
char *decompress_path, *decompress_img;
size_t decompress_size;
const char *name;
switch (comp)
{
case COMPRESSION_XZ:
name = "xz_decompress.img";
break;
case COMPRESSION_NONE:
name = "none_decompress.img";
break;
default:
grub_util_error ("unknown compression %d\n", comp);
}
decompress_path = grub_util_get_path (dir, name);
decompress_size = grub_util_get_image_size (decompress_path);
decompress_img = grub_util_read_image (decompress_path);
*((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE))
= grub_host_to_target32 (core_size);
*((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE))
= grub_host_to_target32 (kernel_size + total_module_size);
full_size = core_size + decompress_size;
full_img = xmalloc (full_size);
memset (full_img, 0, full_size);
memcpy (full_img, decompress_img, decompress_size);
memcpy (full_img + decompress_size, core_img, core_size);
memset (full_img + decompress_size + core_size, 0,
full_size - (decompress_size + core_size));
free (core_img);
core_img = full_img;
core_size = full_size;
}
switch (image_target->id)
{
case IMAGE_I386_PC:
@ -1218,6 +1360,7 @@ static struct option options[] =
{"output", required_argument, 0, 'o'},
{"note", no_argument, 0, 'n'},
{"format", required_argument, 0, 'O'},
{"compression", required_argument, 0, 'C'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'},
@ -1260,6 +1403,7 @@ Make a bootable image of GRUB.\n\
-o, --output=FILE output a generated image to FILE [default=stdout]\n\
-O, --format=FORMAT generate an image in format\n\
available formats: %s\n\
-C, --compression=(xz|none|auto) choose the compression to use\n\
-h, --help display this message and exit\n\
-V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\
@ -1286,6 +1430,7 @@ main (int argc, char *argv[])
FILE *fp = stdout;
int note = 0;
struct image_target_desc *image_target = NULL;
grub_compression_t comp = COMPRESSION_AUTO;
set_program_name (argv[0]);
@ -1293,7 +1438,7 @@ main (int argc, char *argv[])
while (1)
{
int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:hVvn", options, 0);
int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:C:hVvn", options, 0);
if (c == -1)
break;
@ -1350,6 +1495,22 @@ main (int argc, char *argv[])
config = xstrdup (optarg);
break;
case 'C':
if (grub_strcmp (optarg, "xz") == 0)
{
#ifdef HAVE_LIBLZMA
comp = COMPRESSION_XZ;
#else
grub_util_error ("grub-mkimage is compiled without XZ support",
optarg);
#endif
}
else if (grub_strcmp (optarg, "none") == 0)
comp = COMPRESSION_NONE;
else
grub_util_error ("Unknown compression format %s", optarg);
break;
case 'h':
usage (0);
break;
@ -1408,7 +1569,7 @@ main (int argc, char *argv[])
generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp,
argv + optind, memdisk, config,
image_target, note);
image_target, note, comp);
fclose (fp);