Enable LZMA compression in bmpbklk_utility.

LZMA has better compression ratio and is also supported in u-boot already.
ARM BIOS will use LZMA to compress BMP files.

BUG=chromium-os:11017
TEST=manual
$ make
$ make runbmptests

Change-Id: I6b791e3284b65eb3085b0de548bd241eab2ee598

Review URL: http://codereview.chromium.org/6523019
This commit is contained in:
Tom Wai-Hong Tam
2011-02-17 12:58:58 +08:00
parent 686dd5cefb
commit ee2bc91d43
5 changed files with 105 additions and 9 deletions

View File

@@ -117,7 +117,7 @@ typedef enum ImageFormat {
typedef enum Compression {
COMPRESS_NONE = 0,
COMPRESS_EFIv1, /* The x86 BIOS only supports this */
COMPRESS_TBD, /* Only on ARM? */
COMPRESS_LZMA1, /* The ARM BIOS supports LZMA1 */
MAX_COMPRESS,
} Compression;

View File

@@ -89,19 +89,27 @@ class TestPackUnpack(unittest.TestCase):
self.assertEqual(0, rc)
os.chdir('..')
def testPackUnpackZ(self):
"""Create, unpack, recreate with explicit compression"""
rc, out, err = runprog(prog, '-z', '1', '-c', 'case_simple.yaml', 'FOO')
def doPackUnpackZ(self, comp):
"""Create, unpack, recreate with a given compression"""
rc, out, err = runprog(prog, '-z', comp, '-c', 'case_simple.yaml', 'FOO')
self.assertEqual(0, rc)
rc, out, err = runprog(prog, '-x', '-d', './FOO_DIR', 'FOO')
self.assertEqual(0, rc)
os.chdir('./FOO_DIR')
rc, out, err = runprog(prog, '-z', '1', '-c', 'config.yaml', 'BAR')
rc, out, err = runprog(prog, '-z', comp, '-c', 'config.yaml', 'BAR')
self.assertEqual(0, rc)
rc, out, err = runprog('/usr/bin/cmp', '../FOO', 'BAR')
self.assertEqual(0, rc)
os.chdir('..')
def testPackUnpackZ1(self):
"""Create, unpack, recreate with EFIv1 compression"""
self.doPackUnpackZ('1');
def testPackUnpackZ2(self):
"""Create, unpack, recreate with LZMA compression"""
self.doPackUnpackZ('2');
def tearDown(self):
rc, out, err = runprog('/bin/rm', '-rf', './FOO_DIR', 'FOO')
self.assertEqual(0, rc)

View File

@@ -60,7 +60,7 @@ ${BUILD_ROOT}/gbb_utility: gbb_utility.cc
$(CXX) -DWITH_UTIL_MAIN $(CFLAGS) $< -o $@
${BUILD_ROOT}/bmpblk_utility.o: bmpblk_utility.cc
$(CXX) -DWITH_UTIL_MAIN -lyaml $(CFLAGS) -c $< -o $@
$(CXX) -DWITH_UTIL_MAIN $(CFLAGS) -c $< -o $@
${BUILD_ROOT}/bmpblk_util.o: bmpblk_util.c
$(CC) $(CFLAGS) -c $< -o $@
@@ -75,7 +75,7 @@ ${BUILD_ROOT}/bmpblk_utility: ${BUILD_ROOT}/bmpblk_utility.o \
${BUILD_ROOT}/bmpblk_util.o \
${BUILD_ROOT}/eficompress.o \
${BUILD_ROOT}/efidecompress.o
$(CXX) -DWITH_UTIL_MAIN -lyaml $(CFLAGS) $^ -o $@
$(CXX) -llzma -lyaml $(CFLAGS) $^ -o $@
${BUILD_ROOT}/load_kernel_test: load_kernel_test.c $(LIBS)
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto

View File

@@ -5,6 +5,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <lzma.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
@@ -99,7 +100,7 @@ static void *do_efi_decompress(ImageInfo *img) {
uint32_t osize;
EFI_STATUS r;
ibuf = ((void *)img) + sizeof(ImageInfo);
ibuf = (void*)(img + 1);
isize = img->compressed_size;
r = EfiGetInfo(ibuf, isize, &osize, &ssize);
@@ -139,6 +140,50 @@ static void *do_efi_decompress(ImageInfo *img) {
}
static void *do_lzma_decompress(ImageInfo *img) {
void *ibuf;
void *obuf;
uint32_t isize;
uint32_t osize;
lzma_stream stream = LZMA_STREAM_INIT;
lzma_ret result;
ibuf = (void*)(img + 1);
isize = img->compressed_size;
osize = img->original_size;
obuf = malloc(osize);
if (!obuf) {
fprintf(stderr, "Can't allocate %d bytes: %s\n",
osize,
strerror(errno));
return 0;
}
result = lzma_auto_decoder(&stream, -1, 0);
if (result != LZMA_OK) {
fprintf(stderr, "Unable to initialize auto decoder (error: %d)!\n",
result);
free(obuf);
return 0;
}
stream.next_in = ibuf;
stream.avail_in = isize;
stream.next_out = obuf;
stream.avail_out = osize;
result = lzma_code(&stream, LZMA_FINISH);
if (result != LZMA_STREAM_END) {
fprintf(stderr, "Unalbe to decode data (error: %d)!\n", result);
free(obuf);
return 0;
}
lzma_end(&stream);
return obuf;
}
// Show what's inside. If todir is NULL, just print. Otherwise unpack.
int dump_bmpblock(const char *infile, int show_as_yaml,
const char *todir, int overwrite) {
@@ -266,6 +311,16 @@ int dump_bmpblock(const char *infile, int show_as_yaml,
}
free_data = 1;
break;
case COMPRESS_LZMA1:
data_ptr = do_lzma_decompress(img);
if (!data_ptr) {
fclose(bfp);
fclose(yfp);
discard_file(ptr, length);
return 1;
}
free_data = 1;
break;
default:
fprintf(stderr, "Unsupported compression method encountered.\n");
fclose(bfp);

View File

@@ -10,6 +10,7 @@
#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <lzma.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -326,6 +327,38 @@ void BmpBlockUtil::load_all_image_files() {
free(tmpbuf);
}
break;
case COMPRESS_LZMA1:
{
// Calculate the worst case of buffer size.
uint32_t tmpsize = lzma_stream_buffer_bound(content.size());
uint8_t *tmpbuf = (uint8_t *)malloc(tmpsize);
lzma_stream stream = LZMA_STREAM_INIT;
lzma_options_lzma options;
lzma_ret result;
lzma_lzma_preset(&options, 9);
result = lzma_alone_encoder(&stream, &options);
if (result != LZMA_OK) {
error("Unable to initialize easy encoder (error: %d)!\n", result);
}
stream.next_in = (uint8_t *)content.data();
stream.avail_in = content.size();
stream.next_out = tmpbuf;
stream.avail_out = tmpsize;
result = lzma_code(&stream, LZMA_FINISH);
if (result != LZMA_STREAM_END) {
error("Unable to encode data (error: %d)!\n", result);
}
it->second.data.compression = compression_;
it->second.compressed_content.assign((const char *)tmpbuf,
tmpsize - stream.avail_out);
it->second.data.compressed_size = tmpsize - stream.avail_out;
lzma_end(&stream);
free(tmpbuf);
}
break;
default:
error("Unsupported compression method attempted.\n");
}
@@ -535,7 +568,7 @@ static void usagehelp_exit(const char *prog_name) {
" -z NUM = compression algorithm to use\n"
" 0 = none\n"
" 1 = EFIv1\n"
" 2 = TBD\n"
" 2 = LZMA1\n"
"\n", prog_name);
printf(
"To display the contents of a BMPBLOCK:\n"