On 07.12.2014 18:26, Andrei Borzenkov wrote:
> В Sun, 07 Dec 2014 18:18:47 +0100
> Vladimir 'φ-coder/phcoder' Serbinenko <phco...@gmail.com> пишет:
> 
>> On 30.11.2014 14:34, Ian Campbell wrote:
>>> On Sun, 2014-11-30 at 11:51 +0000, Ian Campbell wrote:
>>>> On Sun, 2014-11-30 at 14:31 +0300, Andrei Borzenkov wrote:
>>>>> if [ x$grub_platform = xxen ]; then
>>>>>   insmod xzio
>>>>> fi
>>>>
>>>> I think that could work.
>>>
>>> Indeed it does, so how about this instead of the patch at the start of
>>> the thread?
>>>
>> This should probably have been autoloaded.
> 
> File filters are not autoloaded and I do not see how it can really be
> done. OTOH unconditionally loading them may have unwanted side effect
> where we assumed files were not decompressed.
> 
> In this specific case extending grub-file to detect compression type
> used by kernel is probably OK.
Please test attached file.
> 
>>                                            Can you send me privately a
>> kernel you use, so I can reproduce your tests?
>>> >From f4199776eca80dfad4e9378a01ddb5866face3d7 Mon Sep 17 00:00:00 2001
>>> From: Ian Campbell <i...@debian.org>
>>> Date: Sun, 30 Nov 2014 12:12:52 +0000
>>> Subject: [PATCH] Arrange to insmod xzio when booting a kernel as a Xen guest
>>>
>>> This is needed in case the Linux kernel is compiled with CONFIG_KERNEL_XZ
>>> rather than CONFIG_KERNEL_GZ (gzio is already loaded by grub.cfg).
>>>
>>> Signed-off-by: Ian Campbell <i...@debian.org>
>>>
>>> Patch-Name: insmod-xzio-on-xen.patch
>>> ---
>>>  util/grub.d/10_linux.in | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
>>> index 79fa03a..86e35f2 100644
>>> --- a/util/grub.d/10_linux.in
>>> +++ b/util/grub.d/10_linux.in
>>> @@ -150,6 +150,7 @@ linux_entry ()
>>>    fi
>>>  
>>>    echo "   insmod gzio" | sed "s/^/$submenu_indentation/"
>>> +  echo "   if [ x\$grub_platform = xxen ]; then insmod xzio; insmod 
>>> lzopio; fi" | sed "s/^/$submenu_indentation/"
>>>  
>>>    if [ x$dirname = x/ ]; then
>>>      if [ -z "${prepare_root_cache}" ]; then
>>>
>>
>>
> 
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
> 

diff --git a/grub-core/loader/i386/xen_file.c b/grub-core/loader/i386/xen_file.c
index 5836218..90e0a6e 100644
--- a/grub-core/loader/i386/xen_file.c
+++ b/grub-core/loader/i386/xen_file.c
@@ -20,12 +20,99 @@
 #include <grub/i386/linux.h>
 #include <grub/misc.h>
 
+#define LZOP_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
+#define LZOP_MAGIC_SIZE 9
+#define XZ_MAGIC "\3757zXZ\0"
+#define XZ_MAGIC_SIZE 6
+#define ELF_MAGIC "\177ELF"
+#define ELF_MAGIC_SIZE 4
+#define GZ_MAGIC "\x1F\x8B"
+#define GZ_MAGIC_SIZE 2
+#define GZ_OLD_MAGIC "\x1F\x9E"
+#define GZ_OLD_MAGIC_SIZE 2
+
+#ifndef GRUB_UTIL
+
+#include <grub/dl.h>
+
+static grub_uint8_t
+mod_31 (grub_uint16_t v)
+{
+  /* At most 2 iterations for any number that
+     we can get here.
+     In any case faster than real division.  */
+  while (v > 0x1f)
+    v = (v & 0x1f) + (v >> 5);
+  if (v == 0x1f)
+    return 0;
+  return v;
+}
+
+static int
+is_zlib (grub_uint8_t *head)
+{
+  grub_uint8_t cmf, flg;
+ 
+  cmf = head[0];
+  flg = head[1];
+
+  if ((cmf & 0xf) != 8)
+    return 0;
+
+  if (mod_31 (cmf + flg * 4) != 0)
+    return 0;
+
+  if (flg & 0x20)
+    return 0;
+  
+  return 1;
+}
+
+static void
+autoload_filters (grub_file_t file, grub_uint32_t payload_offset)
+{
+  grub_uint8_t payload_header[LZOP_MAGIC_SIZE];
+
+  grub_file_seek (file, payload_offset);
+
+  if (grub_file_read (file, &payload_header, sizeof (payload_header)) != sizeof (payload_header))
+    {
+      grub_print_error ();
+      return;
+    }
+
+  if (grub_memcmp (payload_header, ELF_MAGIC, ELF_MAGIC_SIZE) == 0)
+    {
+      /* Uncompressed.  */
+    }
+  else if (grub_memcmp (payload_header, XZ_MAGIC, XZ_MAGIC_SIZE) == 0)
+    {
+      grub_dl_load("xzio");
+      grub_print_error ();
+    }
+  else if (grub_memcmp (payload_header, LZOP_MAGIC, LZOP_MAGIC_SIZE) == 0)
+    {
+      grub_dl_load("lzopio");
+      grub_print_error ();
+    }
+  else if (grub_memcmp (payload_header, GZ_MAGIC, GZ_MAGIC_SIZE) == 0
+	   || grub_memcmp (payload_header, GZ_OLD_MAGIC, GZ_OLD_MAGIC_SIZE) == 0
+	   || is_zlib (payload_header))
+    {
+      grub_dl_load("gzio");
+      grub_print_error ();
+    }
+}
+
+#endif
+
 grub_elf_t
 grub_xen_file (grub_file_t file)
 {
   grub_elf_t elf;
   struct linux_kernel_header lh;
   grub_file_t off_file;
+  grub_uint32_t payload_offset;
 
   elf = grub_elf_file (file, file->name);
   if (elf)
@@ -46,19 +133,24 @@ grub_xen_file (grub_file_t file)
       return NULL;
     }
 
-  if (lh.payload_length < 4)
+  if (lh.payload_length < LZOP_MAGIC_SIZE)
     {
       grub_error (GRUB_ERR_BAD_OS, "payload too short");
       return NULL;
     }
 
+  payload_offset = (lh.setup_sects + 1) * 512 + lh.payload_offset;
+
+#ifndef GRUB_UTIL
+  autoload_filters (file, payload_offset);
+#endif
+
   grub_dprintf ("xen", "found bzimage payload 0x%llx-0x%llx\n",
 		(unsigned long long) (lh.setup_sects + 1) * 512
 		+ lh.payload_offset,
 		(unsigned long long) lh.payload_length - 4);
 
-  off_file = grub_file_offset_open (file, (lh.setup_sects + 1) * 512
-				    + lh.payload_offset,
+  off_file = grub_file_offset_open (file, payload_offset,
 				    lh.payload_length - 4);
   if (!off_file)
     goto fail;

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to