On 07.12.2014 18:26, Andrei Borzenkov wrote: > В Sun, 07 Dec 2014 18:18:47 +0100 > Vladimir 'φ-coder/phcoder' Serbinenko <[email protected]> пишет: > >> 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 <[email protected]> >>> 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 <[email protected]> >>> >>> 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 > [email protected] > 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;
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Grub-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/grub-devel
