Allow compression algorithm specification

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-21 20:30:28 +02:00
parent e0a8ef26e4
commit 758194b076
5 changed files with 208 additions and 55 deletions

View file

@ -276,9 +276,10 @@ image = {
}; };
image = { image = {
name = decompress; name = xz_decompress;
mips = boot/mips/startup_raw.S; mips = boot/mips/startup_raw.S;
common = boot/decompressor.c; common = boot/decompressor/minilib.c;
common = boot/decompressor/xz.c;
common = lib/xzembed/xz_dec_bcj.c; common = lib/xzembed/xz_dec_bcj.c;
common = lib/xzembed/xz_dec_lzma2.c; common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c; common = lib/xzembed/xz_dec_stream.c;
@ -293,6 +294,19 @@ image = {
enable = mips; 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 = { image = {
name = fwstart; name = fwstart;
mips_yeeloong = boot/mips/yeeloong/fwstart.S; mips_yeeloong = boot/mips/yeeloong/fwstart.S;

View file

@ -20,9 +20,6 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/decompressor.h> #include <grub/decompressor.h>
#include "xz.h"
#include "xz_stream.h"
void * void *
memset (void *s, int c, grub_size_t len) memset (void *s, int c, grub_size_t len)
{ {
@ -100,39 +97,3 @@ find_scratch (void *src, void *dst, unsigned long srcsize,
grub_decompressor_scratch = (char *) dst + dstsize; grub_decompressor_scratch = (char *) dst + dstsize;
return; return;
} }
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,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

@ -46,6 +46,11 @@
#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
#define TARGET_NO_FIELD 0xffffffff #define TARGET_NO_FIELD 0xffffffff
typedef enum {
COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ
} grub_compression_t;
struct image_target_desc struct image_target_desc
{ {
const char *name; const char *name;
@ -60,7 +65,8 @@ struct image_target_desc
enum enum
{ {
PLATFORM_FLAGS_NONE = 0, PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_LZMA = 1 PLATFORM_FLAGS_LZMA = 1,
PLATFORM_FLAGS_DECOMPRESSORS = 2
} flags; } flags;
unsigned prefix; unsigned prefix;
unsigned prefix_end; unsigned prefix_end;
@ -75,6 +81,7 @@ struct image_target_desc
unsigned install_dos_part, install_bsd_part; unsigned install_dos_part, install_bsd_part;
grub_uint64_t link_addr; grub_uint64_t link_addr;
unsigned mod_gap, mod_align; unsigned mod_gap, mod_align;
grub_compression_t default_compression;
}; };
struct image_target_desc image_targets[] = struct image_target_desc image_targets[] =
@ -248,7 +255,7 @@ struct image_target_desc image_targets[] =
.voidp_sizeof = 4, .voidp_sizeof = 4,
.bigendian = 0, .bigendian = 0,
.id = IMAGE_YEELOONG_FLASH, .id = IMAGE_YEELOONG_FLASH,
.flags = PLATFORM_FLAGS_LZMA, .flags = PLATFORM_FLAGS_DECOMPRESSORS,
.prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
.prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
.raw_size = 0, .raw_size = 0,
@ -261,14 +268,15 @@ struct image_target_desc image_targets[] =
.install_bsd_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD,
.link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
.elf_target = EM_MIPS, .elf_target = EM_MIPS,
.link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN,
.default_compression = COMPRESSION_XZ
}, },
{ {
.name = "mipsel-yeeloong-elf", .name = "mipsel-yeeloong-elf",
.voidp_sizeof = 4, .voidp_sizeof = 4,
.bigendian = 0, .bigendian = 0,
.id = IMAGE_YEELOONG_ELF, .id = IMAGE_YEELOONG_ELF,
.flags = PLATFORM_FLAGS_LZMA, .flags = PLATFORM_FLAGS_DECOMPRESSORS,
.prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX,
.prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END,
.raw_size = 0, .raw_size = 0,
@ -281,7 +289,8 @@ struct image_target_desc image_targets[] =
.install_bsd_part = TARGET_NO_FIELD, .install_bsd_part = TARGET_NO_FIELD,
.link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR,
.elf_target = EM_MIPS, .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", .name = "powerpc-ieee1275",
@ -483,7 +492,39 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size,
memcpy (*core_img, kernel_img, raw_size); memcpy (*core_img, kernel_img, raw_size);
*core_size = kernel_size - raw_size; *core_size = kernel_size - raw_size;
if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size, if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size - raw_size,
(unsigned char *) kernel_img + raw_size,
kernel_size - raw_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;
}
static void
compress_kernel_xz (char *kernel_img, size_t kernel_size,
char **core_img, size_t *core_size, size_t raw_size)
{
CLzmaEncProps props;
unsigned char out_props[5];
size_t out_props_size = 5;
LzmaEncProps_Init(&props);
props.dictSize = 1 << 16;
props.lc = 3;
props.lp = 0;
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 - raw_size,
(unsigned char *) kernel_img + raw_size, (unsigned char *) kernel_img + raw_size,
kernel_size - raw_size, kernel_size - raw_size,
&props, out_props, &out_props_size, &props, out_props, &out_props_size,
@ -495,7 +536,8 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size,
static void static void
compress_kernel (struct image_target_desc *image_target, char *kernel_img, 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) if (image_target->flags & PLATFORM_FLAGS_LZMA)
{ {
@ -504,6 +546,14 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img,
return; return;
} }
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;
}
*core_img = xmalloc (kernel_size); *core_img = xmalloc (kernel_size);
memcpy (*core_img, kernel_img, kernel_size); memcpy (*core_img, kernel_img, kernel_size);
*core_size = kernel_size; *core_size = kernel_size;
@ -527,7 +577,8 @@ struct fixup_block_list
static void static void
generate_image (const char *dir, char *prefix, FILE *out, char *mods[], generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
char *memdisk_path, char *config_path, 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; char *kernel_img, *core_img;
size_t kernel_size, total_module_size, core_size, exec_size; size_t kernel_size, total_module_size, core_size, exec_size;
@ -539,6 +590,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
grub_uint64_t start_address; grub_uint64_t start_address;
void *rel_section; void *rel_section;
grub_size_t reloc_size, align; 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); path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
kernel_path = grub_util_get_path (dir, "kernel.img"); kernel_path = grub_util_get_path (dir, "kernel.img");
@ -655,7 +710,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_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, 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); grub_util_info ("the core size is 0x%x", core_size);
@ -680,15 +735,27 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
= grub_host_to_target32 (-2); = grub_host_to_target32 (-2);
} }
if (image_target->id == IMAGE_YEELOONG_FLASH if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
|| image_target->id == IMAGE_YEELOONG_ELF)
{ {
char *full_img; char *full_img;
size_t full_size; size_t full_size;
char *decompress_path, *decompress_img; char *decompress_path, *decompress_img;
size_t decompress_size; size_t decompress_size;
const char *name;
decompress_path = grub_util_get_path (dir, "decompress.img"); 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_size = grub_util_get_image_size (decompress_path);
decompress_img = grub_util_read_image (decompress_path); decompress_img = grub_util_read_image (decompress_path);
@ -1253,6 +1320,7 @@ static struct option options[] =
{"output", required_argument, 0, 'o'}, {"output", required_argument, 0, 'o'},
{"note", no_argument, 0, 'n'}, {"note", no_argument, 0, 'n'},
{"format", required_argument, 0, 'O'}, {"format", required_argument, 0, 'O'},
{"compression", required_argument, 0, 'C'},
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'}, {"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'}, {"verbose", no_argument, 0, 'v'},
@ -1295,6 +1363,7 @@ Make a bootable image of GRUB.\n\
-o, --output=FILE output a generated image to FILE [default=stdout]\n\ -o, --output=FILE output a generated image to FILE [default=stdout]\n\
-O, --format=FORMAT generate an image in format\n\ -O, --format=FORMAT generate an image in format\n\
available formats: %s\n\ available formats: %s\n\
-C, --compression=(xz|none|auto) choose the compression to use\n\
-h, --help display this message and exit\n\ -h, --help display this message and exit\n\
-V, --version print version information and exit\n\ -V, --version print version information and exit\n\
-v, --verbose print verbose messages\n\ -v, --verbose print verbose messages\n\
@ -1321,6 +1390,7 @@ main (int argc, char *argv[])
FILE *fp = stdout; FILE *fp = stdout;
int note = 0; int note = 0;
struct image_target_desc *image_target = NULL; struct image_target_desc *image_target = NULL;
grub_compression_t comp = COMPRESSION_AUTO;
set_program_name (argv[0]); set_program_name (argv[0]);
@ -1328,7 +1398,7 @@ main (int argc, char *argv[])
while (1) 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) if (c == -1)
break; break;
@ -1385,6 +1455,15 @@ main (int argc, char *argv[])
config = xstrdup (optarg); config = xstrdup (optarg);
break; break;
case 'C':
if (grub_strcmp (optarg, "xz") == 0)
comp = COMPRESSION_XZ;
else if (grub_strcmp (optarg, "none") == 0)
comp = COMPRESSION_NONE;
else
grub_util_error ("Unknown compression format %s", optarg);
break;
case 'h': case 'h':
usage (0); usage (0);
break; break;
@ -1443,7 +1522,7 @@ main (int argc, char *argv[])
generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp,
argv + optind, memdisk, config, argv + optind, memdisk, config,
image_target, note); image_target, note, comp);
fclose (fp); fclose (fp);