=== modified file 'ChangeLog' --- old/ChangeLog 2010-09-14 22:39:49 +0000 +++ new/ChangeLog 2010-09-15 23:05:16 +0000 @@ -1,3 +1,16 @@ +2010-09-16 Szymon Janc + + Move some xz generic code from grub-core/io/xzio.c to + grub-core/lib/xzembed/xz_misc.{h|c}. It will be used in xzmemdisk. + + * grub-core/lib/xzembed/xz_dec_stream.h: New defines + XZ_STREAM_FOOTER_SIZE, XZ_CRC_SIZE, VLI_MAX_DIGITS. + * grub-core/lib/xzembed/xz_misc.h: New file. + * grub-core/lib/xzembed/xz_misc.c: New file. + * grub-core/io/xzio.c (test_footer): Rewritten to use helper functions + from grub-core/lib/xzembed/xz_misc.h. + * grub-core/Makefile.core.def (xzio): Include lib/xzembed/xz_misc.c. + 2010-09-15 Szymon Janc * grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block === modified file 'grub-core/Makefile.core.def' --- old/grub-core/Makefile.core.def 2010-09-14 20:32:33 +0000 +++ new/grub-core/Makefile.core.def 2010-09-15 23:05:16 +0000 @@ -1424,6 +1424,7 @@ common = lib/xzembed/xz_dec_bcj.c; common = lib/xzembed/xz_dec_lzma2.c; common = lib/xzembed/xz_dec_stream.c; + common = lib/xzembed/xz_misc.c; cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; }; === modified file 'grub-core/io/xzio.c' --- old/grub-core/io/xzio.c 2010-09-05 15:12:13 +0000 +++ new/grub-core/io/xzio.c 2010-09-15 23:05:16 +0000 @@ -26,10 +26,9 @@ #include "xz.h" #include "xz_stream.h" +#include "xz_misc.h" #define XZBUFSIZ 0x2000 -#define VLI_MAX_DIGITS 9 -#define XZ_STREAM_FOOTER_SIZE 12 struct grub_xzio { @@ -44,46 +43,6 @@ typedef struct grub_xzio *grub_xzio_t; static struct grub_fs grub_xzio_fs; -static grub_size_t -decode_vli (const grub_uint8_t buf[], grub_size_t size_max, - grub_uint64_t * num) -{ - if (size_max == 0) - return 0; - - if (size_max > VLI_MAX_DIGITS) - size_max = VLI_MAX_DIGITS; - - *num = buf[0] & 0x7F; - grub_size_t i = 0; - - while (buf[i++] & 0x80) - { - if (i >= size_max || buf[i] == 0x00) - return 0; - - *num |= (uint64_t) (buf[i] & 0x7F) << (i * 7); - } - - return i; -} - -static grub_ssize_t -read_vli (grub_file_t file, grub_uint64_t * num) -{ - grub_uint8_t buf[VLI_MAX_DIGITS]; - grub_ssize_t read; - grub_size_t dec; - - read = grub_file_read (file, buf, VLI_MAX_DIGITS); - if (read < 0) - return -1; - - dec = decode_vli (buf, read, num); - grub_file_seek (file, file->offset - (read - dec)); - return dec; -} - /* Function xz_dec_run() should consume header and ask for more (XZ_OK) * else file is corrupted (or options not supported) or not xz. */ static int @@ -121,55 +80,43 @@ static int test_footer (grub_file_t file) { + grub_xzio_t xzio = file->data; - grub_uint8_t footer[FOOTER_MAGIC_SIZE]; + grub_uint8_t footer[XZ_STREAM_FOOTER_SIZE]; grub_uint32_t backsize; - grub_uint8_t imarker; - grub_uint64_t uncompressed_size_total = 0; grub_uint64_t uncompressed_size; - grub_uint64_t records; - - grub_file_seek (xzio->file, xzio->file->size - FOOTER_MAGIC_SIZE); - if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) != - FOOTER_MAGIC_SIZE - || grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0) - goto ERROR; - - grub_file_seek (xzio->file, xzio->file->size - 8); - if (grub_file_read (xzio->file, &backsize, sizeof (backsize)) - != sizeof (backsize)) - goto ERROR; - - /* Calculate real backward size. */ - backsize = (grub_le_to_cpu32 (backsize) + 1) * 4; + grub_uint8_t *index = 0; + + grub_file_seek (xzio->file, xzio->file->size - XZ_STREAM_FOOTER_SIZE); + if (grub_file_read (xzio->file, footer, XZ_STREAM_FOOTER_SIZE) != XZ_STREAM_FOOTER_SIZE) + { + goto ERROR; + } + + /* Test footer and calculate real backward size. */ + backsize = xz_test_footer(footer, XZ_STREAM_FOOTER_SIZE); + if(backsize == 0) + { + goto ERROR; + } /* Set file to the beginning of stream index. */ - grub_file_seek (xzio->file, - xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize); - - /* Test index marker. */ - if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) != - sizeof (imarker) && imarker != 0x00) - goto ERROR; - - if (read_vli (xzio->file, &records) <= 0) - goto ERROR; - - for (; records != 0; records--) + grub_file_seek (xzio->file, xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize); + + /* Test index. */ + index = grub_malloc(backsize); + if(!index || grub_file_read(xzio->file, index, backsize) != (grub_ssize_t)backsize + || !xz_test_index(index, backsize, &uncompressed_size)) { - if (read_vli (xzio->file, &uncompressed_size) <= 0) /* Ignore unpadded. */ - goto ERROR; - if (read_vli (xzio->file, &uncompressed_size) <= 0) /* Uncompressed. */ - goto ERROR; - - uncompressed_size_total += uncompressed_size; + goto ERROR; } - file->size = uncompressed_size_total; + file->size = uncompressed_size; grub_file_seek (xzio->file, STREAM_HEADER_SIZE); return 1; ERROR: + grub_free(index); grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "bad footer magic"); return 0; } === added file 'grub-core/lib/xzembed/xz_misc.c' --- old/grub-core/lib/xzembed/xz_misc.c 1970-01-01 00:00:00 +0000 +++ new/grub-core/lib/xzembed/xz_misc.c 2010-09-15 23:05:16 +0000 @@ -0,0 +1,88 @@ +/* xz_misc.c - Common helper functions for xz file format decoder. */ +/* + * 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 . + */ + +#include "xz_misc.h" + +static grub_size_t +xz_decode_vli (const grub_uint8_t buf[], grub_size_t size_max, + grub_uint64_t * num) +{ + if (size_max == 0) + return 0; + + if (size_max > VLI_MAX_DIGITS) + size_max = VLI_MAX_DIGITS; + + *num = buf[0] & 0x7F; + grub_size_t i = 0; + + while (buf[i++] & 0x80) + { + if (i >= size_max || buf[i] == 0x00) + return 0; + + *num |= (uint64_t) (buf[i] & 0x7F) << (i * 7); + } + + return i; +} + +int +xz_test_index (const grub_uint8_t * index, grub_size_t size, + grub_uint64_t * usize) +{ + if (size == 0 || index[0] != 0x00) + return 0; + + index++; + size--; + + grub_uint64_t records; + *usize = 0; + grub_uint64_t uncompressed_size; + grub_size_t ret; + + ret = xz_decode_vli (index, size, &records); + index += ret; + size -= ret; + + for (; records != 0; records--) + { + ret = xz_decode_vli (index, size, &uncompressed_size); /* Ignore unpadded. */ + index += ret; + size -= ret; + + ret = xz_decode_vli (index, size, &uncompressed_size); /* Uncompressed. */ + index += ret; + size -= ret; + + *usize += uncompressed_size; + } + + /* Check padding. */ + while (size % 4) + { + if (size == 0 || *index != 0) + return 0; + index++; + size--; + } + + return (size == XZ_CRC_SIZE); +} === added file 'grub-core/lib/xzembed/xz_misc.h' --- old/grub-core/lib/xzembed/xz_misc.h 1970-01-01 00:00:00 +0000 +++ new/grub-core/lib/xzembed/xz_misc.h 2010-09-15 23:05:16 +0000 @@ -0,0 +1,42 @@ +/* xz_misc.h - Common helper functions for xz file format decoder. */ +/* + * 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 . + */ + +#ifndef XZ_MISC_H +#define XZ_MISC_H + +#include +#include +#include "xz_stream.h" + +/* On success returns calculated backward size or 0 if error occurred. */ +inline static grub_uint32_t +xz_test_footer(const grub_uint8_t *buf, grub_size_t size) +{ + return (size == XZ_STREAM_FOOTER_SIZE + && grub_memcmp(buf + XZ_STREAM_FOOTER_SIZE - FOOTER_MAGIC_SIZE, + FOOTER_MAGIC, FOOTER_MAGIC_SIZE) == 0) + ? (grub_le_to_cpu32 (*(grub_uint32_t*)(buf + XZ_CRC_SIZE)) + 1) * 4 : 0; +} + +/* Test index and get uncompressed data size (on success). */ +int +xz_test_index(const grub_uint8_t index[], grub_size_t size, + grub_uint64_t *usize); + +#endif === modified file 'grub-core/lib/xzembed/xz_stream.h' --- old/grub-core/lib/xzembed/xz_stream.h 2010-09-05 15:12:13 +0000 +++ new/grub-core/lib/xzembed/xz_stream.h 2010-09-15 23:05:16 +0000 @@ -24,6 +24,8 @@ #ifndef XZ_STREAM_H #define XZ_STREAM_H +#include + /* * See the .xz file format specification at * http://tukaani.org/xz/xz-file-format.txt @@ -38,6 +40,9 @@ #define FOOTER_MAGIC "YZ" #define FOOTER_MAGIC_SIZE 2 +#define XZ_STREAM_FOOTER_SIZE 12 +#define XZ_CRC_SIZE 4 + /* * Variable-length integer can hold a 63-bit unsigned integer, or a special * value to indicate that the value is unknown. @@ -49,5 +54,6 @@ /* Maximum encoded size of a VLI */ #define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7) +#define VLI_MAX_DIGITS 9 #endif