]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/loader/i386/coreboot/chainloader.c: Support lzma-compressed
authorVladimir Serbinenko <phcoder@gmail.com>
Sun, 10 Nov 2013 19:53:27 +0000 (20:53 +0100)
committerVladimir Serbinenko <phcoder@gmail.com>
Sun, 10 Nov 2013 19:53:27 +0000 (20:53 +0100)
payload.

ChangeLog
grub-core/Makefile.core.def
grub-core/loader/i386/coreboot/chainloader.c

index 394464900e9dde64e2b212d01a6258e147a9539c..7580e1d8a1d6058bc47f5b406de8c084af38323d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * include/grub/lib/LzmaDec.h: Fix to include LzmaTypes.h and
index 20951aab7eae5c1e1cc71a9c59ce664d702ab8e5..b9188358cf9245c3f246b4a4180436d9568de76d 100644 (file)
@@ -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;
index ea304891221f7b983ee62a925f4beb757608da3e..8df1fa607312b79f2e0f8cca0b66e89f4c187b35 100644 (file)
@@ -30,6 +30,7 @@
 #include <grub/command.h>
 #include <grub/i18n.h>
 #include <grub/cbfs_core.h>
+#include <grub/lib/LzmaDec.h>
 
 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;
              }