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;
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel