* grub-core/loader/i386/coreboot/chainloader.c: Support lzma-compressed

payload.
This commit is contained in:
Vladimir Serbinenko 2013-11-10 20:53:27 +01:00
parent 3617c59bab
commit 8997730612
3 changed files with 61 additions and 4 deletions

View file

@ -1,3 +1,8 @@
2013-11-10 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/loader/i386/coreboot/chainloader.c: Support lzma-compressed
payload.
2013-11-10 Vladimir Serbinenko <phcoder@gmail.com> 2013-11-10 Vladimir Serbinenko <phcoder@gmail.com>
* include/grub/lib/LzmaDec.h: Fix to include LzmaTypes.h and * include/grub/lib/LzmaDec.h: Fix to include LzmaTypes.h and

View file

@ -1685,6 +1685,7 @@ module = {
efi = loader/efi/chainloader.c; efi = loader/efi/chainloader.c;
i386_pc = loader/i386/pc/chainloader.c; i386_pc = loader/i386/pc/chainloader.c;
i386_coreboot = loader/i386/coreboot/chainloader.c; i386_coreboot = loader/i386/coreboot/chainloader.c;
i386_coreboot = lib/LzmaDec.c;
enable = i386_pc; enable = i386_pc;
enable = i386_coreboot; enable = i386_coreboot;
enable = efi; enable = efi;

View file

@ -30,6 +30,7 @@
#include <grub/command.h> #include <grub/command.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/cbfs_core.h> #include <grub/cbfs_core.h>
#include <grub/lib/LzmaDec.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -124,16 +125,21 @@ load_elf (grub_file_t file, const char *filename)
return GRUB_ERR_NONE; 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 static grub_err_t
load_segment (grub_file_t file, const char *filename, load_segment (grub_file_t file, const char *filename,
void *load_addr, grub_uint32_t comp, void *load_addr, grub_uint32_t comp,
grub_size_t size) grub_size_t *size, grub_size_t max_size)
{ {
switch (comp) switch (comp)
{ {
case grub_cpu_to_be32_compile_time (CBFS_COMPRESS_NONE): case grub_cpu_to_be32_compile_time (CBFS_COMPRESS_NONE):
if (grub_file_read (file, load_addr, size) if (grub_file_read (file, load_addr, *size)
!= (grub_ssize_t) size) != (grub_ssize_t) *size)
{ {
if (!grub_errno) if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, 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_errno;
} }
return GRUB_ERR_NONE; 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: default:
return grub_error (GRUB_ERR_BAD_OS, "unsupported compression %d", return grub_error (GRUB_ERR_BAD_OS, "unsupported compression %d",
grub_be_to_cpu32 (comp)); grub_be_to_cpu32 (comp));
@ -192,6 +241,8 @@ load_chewed (grub_file_t file, const char *filename)
if (memsize < filesize) if (memsize < filesize)
memsize = filesize; memsize = filesize;
grub_dprintf ("chain", "%x+%x\n", target, memsize);
err = grub_relocator_alloc_chunk_addr (relocator, &ch, err = grub_relocator_alloc_chunk_addr (relocator, &ch,
target, memsize); target, memsize);
if (err) if (err)
@ -206,7 +257,7 @@ load_chewed (grub_file_t file, const char *filename)
return grub_errno; return grub_errno;
err = load_segment (file, filename, load_addr, err = load_segment (file, filename, load_addr,
segment.compression, filesize); segment.compression, &filesize, memsize);
if (err) if (err)
return err; return err;
} }