From 89977306124f56762603ca80cb79a0e0265adba8 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sun, 10 Nov 2013 20:53:27 +0100 Subject: [PATCH] * grub-core/loader/i386/coreboot/chainloader.c: Support lzma-compressed payload. --- ChangeLog | 5 ++ grub-core/Makefile.core.def | 1 + grub-core/loader/i386/coreboot/chainloader.c | 59 ++++++++++++++++++-- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 394464900..7580e1d8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-11-10 Vladimir Serbinenko + + * grub-core/loader/i386/coreboot/chainloader.c: Support lzma-compressed + payload. + 2013-11-10 Vladimir Serbinenko * include/grub/lib/LzmaDec.h: Fix to include LzmaTypes.h and diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 20951aab7..b9188358c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1685,6 +1685,7 @@ module = { efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; i386_coreboot = loader/i386/coreboot/chainloader.c; + i386_coreboot = lib/LzmaDec.c; enable = i386_pc; enable = i386_coreboot; enable = efi; diff --git a/grub-core/loader/i386/coreboot/chainloader.c b/grub-core/loader/i386/coreboot/chainloader.c index ea3048912..8df1fa607 100644 --- a/grub-core/loader/i386/coreboot/chainloader.c +++ b/grub-core/loader/i386/coreboot/chainloader.c @@ -30,6 +30,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -124,16 +125,21 @@ load_elf (grub_file_t file, const char *filename) return GRUB_ERR_NONE; } +static void *SzAlloc(void *p __attribute__ ((unused)), size_t size) { return grub_malloc (size); } +static void SzFree(void *p __attribute__ ((unused)), void *address) { grub_free (address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + + static grub_err_t load_segment (grub_file_t file, const char *filename, void *load_addr, grub_uint32_t comp, - grub_size_t size) + grub_size_t *size, grub_size_t max_size) { switch (comp) { case grub_cpu_to_be32_compile_time (CBFS_COMPRESS_NONE): - if (grub_file_read (file, load_addr, size) - != (grub_ssize_t) size) + if (grub_file_read (file, load_addr, *size) + != (grub_ssize_t) *size) { if (!grub_errno) grub_error (GRUB_ERR_FILE_READ_ERROR, @@ -142,6 +148,49 @@ load_segment (grub_file_t file, const char *filename, return grub_errno; } return GRUB_ERR_NONE; + case grub_cpu_to_be32_compile_time (CBFS_COMPRESS_LZMA): + { + grub_uint8_t *buf; + grub_size_t outsize, insize; + SRes res; + SizeT src_len, dst_len; + ELzmaStatus status; + if (*size < 13) + return grub_error (GRUB_ERR_BAD_OS, "invalid compressed chunk"); + buf = grub_malloc (*size); + if (!buf) + return grub_errno; + if (grub_file_read (file, load_addr, *size) + != (grub_ssize_t) *size) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, + N_("premature end of file %s"), + filename); + grub_free (buf); + return grub_errno; + } + outsize = grub_get_unaligned64 (buf + 5); + if (outsize > max_size) + { + grub_free (buf); + return grub_error (GRUB_ERR_BAD_OS, "invalid compressed chunk"); + } + insize = *size - 13; + + src_len = insize; + dst_len = outsize; + res = LzmaDecode (load_addr, &dst_len, buf + 13, &src_len, + buf, 5, LZMA_FINISH_END, &status, &g_Alloc); + /* ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc)*/ + grub_free (buf); + if (res != SZ_OK + || src_len != insize || dst_len != outsize) + return grub_error (GRUB_ERR_BAD_OS, "decompression failure %d", res); + *size = outsize; + } + return GRUB_ERR_NONE; default: return grub_error (GRUB_ERR_BAD_OS, "unsupported compression %d", grub_be_to_cpu32 (comp)); @@ -192,6 +241,8 @@ load_chewed (grub_file_t file, const char *filename) if (memsize < filesize) memsize = filesize; + grub_dprintf ("chain", "%x+%x\n", target, memsize); + err = grub_relocator_alloc_chunk_addr (relocator, &ch, target, memsize); if (err) @@ -206,7 +257,7 @@ load_chewed (grub_file_t file, const char *filename) return grub_errno; err = load_segment (file, filename, load_addr, - segment.compression, filesize); + segment.compression, &filesize, memsize); if (err) return err; }