1 /*
2  * Xen domain builder -- bzImage bits
3  *
4  * Parse and load bzImage kernel images.
5  *
6  * This relies on version 2.08 of the boot protocol, which contains an
7  * ELF file embedded in the bzImage.  The loader extracts this ELF
8  * image and passes it off to the standard ELF loader.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation;
13  * version 2.1 of the License.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; If not, see <http://www.gnu.org/licenses/>.
22  *
23  * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
24  * written 2007 by Jeremy Fitzhardinge <jeremy@xensource.com>
25  * written 2008 by Ian Campbell <ijc@hellion.org.uk>
26  * written 2009 by Chris Lalancette <clalance@redhat.com>
27  *
28  */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <inttypes.h>
33 
34 #include "xg_private.h"
35 #include "xg_dom_decompress.h"
36 
37 #include <xen-tools/common-macros.h>
38 
39 #ifndef __MINIOS__
40 
41 #if defined(HAVE_BZLIB)
42 
43 #include <bzlib.h>
44 
xc_try_bzip2_decode(struct xc_dom_image * dom,void ** blob,size_t * size)45 static int xc_try_bzip2_decode(
46     struct xc_dom_image *dom, void **blob, size_t *size)
47 {
48     bz_stream stream;
49     int ret;
50     char *out_buf;
51     int retval = -1;
52     unsigned int insize, outsize;
53 
54     stream.bzalloc = NULL;
55     stream.bzfree = NULL;
56     stream.opaque = NULL;
57 
58     if ( *size <= 8 )
59     {
60         DOMPRINTF("BZIP2: insufficient input data");
61         return -1;
62     }
63 
64     ret = BZ2_bzDecompressInit(&stream, 0, 0);
65     if ( ret != BZ_OK )
66     {
67         DOMPRINTF("BZIP2: Error initting stream");
68         return -1;
69     }
70 
71     insize = *size - 4;
72     outsize = get_unaligned_le32(*blob + insize);
73 
74     /*
75      * stream.avail_in and insize are unsigned int, while *size
76      * is a size_t. Check we aren't overflowing.
77      */
78     if ( insize + 4 != *size )
79     {
80         DOMPRINTF("BZIP2: Input too large");
81         goto bzip2_cleanup;
82     }
83 
84     if ( xc_dom_kernel_check_size(dom, outsize) )
85     {
86         DOMPRINTF("BZIP2: output too large");
87         goto bzip2_cleanup;
88     }
89 
90     out_buf = malloc(outsize);
91     if ( out_buf == NULL )
92     {
93         DOMPRINTF("BZIP2: Failed to alloc memory");
94         goto bzip2_cleanup;
95     }
96 
97     stream.next_in = dom->kernel_blob;
98     stream.avail_in = insize;
99 
100     stream.next_out = out_buf;
101     stream.avail_out = outsize;
102 
103     ret = BZ2_bzDecompress(&stream);
104     if ( ret == BZ_STREAM_END )
105         DOMPRINTF("BZIP2: Saw data stream end");
106     else if ( ret != BZ_OK )
107     {
108         DOMPRINTF("BZIP2: error %d", ret);
109         free(out_buf);
110         goto bzip2_cleanup;
111     }
112 
113     if ( stream.total_out_lo32 != outsize || stream.total_out_hi32 )
114     {
115         DOMPRINTF("BZIP2: got 0x%x%08x bytes instead of 0x%09x",
116                   stream.total_out_hi32, stream.total_out_lo32, outsize);
117         free(out_buf);
118         goto bzip2_cleanup;
119     }
120 
121     if ( stream.avail_in )
122         DOMPRINTF("BZIP2: Warning: %#x unconsumed bytes", stream.avail_in);
123 
124     if ( xc_dom_register_external(dom, out_buf, outsize) )
125     {
126         DOMPRINTF("BZIP2: Error registering stream output");
127         free(out_buf);
128         goto bzip2_cleanup;
129     }
130 
131     DOMPRINTF("%s: BZIP2 decompress OK, 0x%zx -> 0x%x",
132               __FUNCTION__, *size, outsize);
133 
134     *blob = out_buf;
135     *size = outsize;
136     retval = 0;
137 
138  bzip2_cleanup:
139     BZ2_bzDecompressEnd(&stream);
140 
141     return retval;
142 }
143 
144 #else /* !defined(HAVE_BZLIB) */
145 
xc_try_bzip2_decode(struct xc_dom_image * dom,void ** blob,size_t * size)146 static int xc_try_bzip2_decode(
147     struct xc_dom_image *dom, void **blob, size_t *size)
148 {
149     xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
150                  "%s: BZIP2 decompress support unavailable",
151                  __FUNCTION__);
152     return -1;
153 }
154 
155 #endif
156 
157 #if defined(HAVE_LZMA)
158 
159 #include <lzma.h>
160 
_xc_try_lzma_decode(struct xc_dom_image * dom,void ** blob,size_t * size,lzma_stream * stream,const char * what)161 static int _xc_try_lzma_decode(
162     struct xc_dom_image *dom, void **blob, size_t *size,
163     lzma_stream *stream, const char *what)
164 {
165     lzma_ret ret;
166     lzma_action action = LZMA_RUN;
167     unsigned char *out_buf;
168     int retval = -1;
169     size_t insize, outsize;
170 
171     if ( *size < 8 )
172     {
173         DOMPRINTF("%s: insufficient input data", what);
174         goto lzma_cleanup;
175     }
176 
177     insize = *size - 4;
178     outsize = get_unaligned_le32(*blob + insize);
179 
180     if ( xc_dom_kernel_check_size(dom, outsize) )
181     {
182         DOMPRINTF("%s: output too large", what);
183         goto lzma_cleanup;
184     }
185 
186     out_buf = malloc(outsize);
187     if ( out_buf == NULL )
188     {
189         DOMPRINTF("%s: Failed to alloc memory", what);
190         goto lzma_cleanup;
191     }
192 
193     stream->next_in = dom->kernel_blob;
194     stream->avail_in = insize;
195 
196     stream->next_out = out_buf;
197     stream->avail_out = outsize;
198 
199     ret = lzma_code(stream, action);
200     if ( ret == LZMA_STREAM_END )
201         DOMPRINTF("%s: Saw data stream end", what);
202     else if ( ret != LZMA_OK )
203     {
204         const char *msg;
205 
206         switch ( ret )
207         {
208         case LZMA_MEM_ERROR:
209             msg = strerror(ENOMEM);
210             break;
211 
212         case LZMA_MEMLIMIT_ERROR:
213             msg = "Memory usage limit reached";
214             break;
215 
216         case LZMA_FORMAT_ERROR:
217             msg = "File format not recognized";
218             break;
219 
220         case LZMA_OPTIONS_ERROR:
221             // FIXME: Better message?
222             msg = "Unsupported compression options";
223             break;
224 
225         case LZMA_DATA_ERROR:
226             msg = "File is corrupt";
227             break;
228 
229         case LZMA_BUF_ERROR:
230             msg = "Unexpected end of input";
231             break;
232 
233          default:
234             msg = "Internal program error (bug)";
235             break;
236         }
237 
238         DOMPRINTF("%s: %s decompression error: %s",
239                   __FUNCTION__, what, msg);
240         free(out_buf);
241         goto lzma_cleanup;
242     }
243 
244     if ( stream->total_out != outsize )
245     {
246         DOMPRINTF("%s: got 0x%"PRIx64" bytes instead of 0x%zx",
247                   what, stream->total_out, outsize);
248         free(out_buf);
249         goto lzma_cleanup;
250     }
251 
252     if ( stream->avail_in )
253         DOMPRINTF("%s: Warning: %#zx unconsumed bytes", what, stream->avail_in);
254 
255     if ( xc_dom_register_external(dom, out_buf, outsize) )
256     {
257         DOMPRINTF("%s: Error registering stream output", what);
258         free(out_buf);
259         goto lzma_cleanup;
260     }
261 
262     DOMPRINTF("%s: %s decompress OK, 0x%zx -> 0x%zx",
263               __FUNCTION__, what, *size, outsize);
264 
265     *blob = out_buf;
266     *size = outsize;
267     retval = 0;
268 
269  lzma_cleanup:
270     lzma_end(stream);
271 
272     return retval;
273 }
274 
275 /* 128 Mb is the minimum size (half-way) documented to work for all inputs. */
276 #define LZMA_BLOCK_SIZE (128*1024*1024)
277 
xc_try_xz_decode(struct xc_dom_image * dom,void ** blob,size_t * size)278 static int xc_try_xz_decode(
279     struct xc_dom_image *dom, void **blob, size_t *size)
280 {
281     lzma_stream stream = LZMA_STREAM_INIT;
282 
283     if ( lzma_stream_decoder(&stream, LZMA_BLOCK_SIZE, 0) != LZMA_OK )
284     {
285         DOMPRINTF("XZ: Failed to init decoder");
286         return -1;
287     }
288 
289     return _xc_try_lzma_decode(dom, blob, size, &stream, "XZ");
290 }
291 
xc_try_lzma_decode(struct xc_dom_image * dom,void ** blob,size_t * size)292 static int xc_try_lzma_decode(
293     struct xc_dom_image *dom, void **blob, size_t *size)
294 {
295     lzma_stream stream = LZMA_STREAM_INIT;
296 
297     if ( lzma_alone_decoder(&stream, LZMA_BLOCK_SIZE) != LZMA_OK )
298     {
299         DOMPRINTF("LZMA: Failed to init decoder");
300         return -1;
301     }
302 
303     return _xc_try_lzma_decode(dom, blob, size, &stream, "LZMA");
304 }
305 
306 #else /* !defined(HAVE_LZMA) */
307 
xc_try_xz_decode(struct xc_dom_image * dom,void ** blob,size_t * size)308 static int xc_try_xz_decode(
309     struct xc_dom_image *dom, void **blob, size_t *size)
310 {
311     xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
312                  "%s: XZ decompress support unavailable",
313                  __FUNCTION__);
314     return -1;
315 }
316 
xc_try_lzma_decode(struct xc_dom_image * dom,void ** blob,size_t * size)317 static int xc_try_lzma_decode(
318     struct xc_dom_image *dom, void **blob, size_t *size)
319 {
320     xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
321                  "%s: LZMA decompress support unavailable",
322                  __FUNCTION__);
323     return -1;
324 }
325 
326 #endif
327 
328 #if defined(HAVE_LZO1X)
329 
330 #include <lzo/lzo1x.h>
331 
332 #define LZOP_HEADER_HAS_FILTER 0x00000800
333 #define LZOP_MAX_BLOCK_SIZE (64*1024*1024)
334 
lzo_read_16(const unsigned char * buf)335 static inline uint_fast16_t lzo_read_16(const unsigned char *buf)
336 {
337     return buf[1] | (buf[0] << 8);
338 }
339 
lzo_read_32(const unsigned char * buf)340 static inline uint_fast32_t lzo_read_32(const unsigned char *buf)
341 {
342     return lzo_read_16(buf + 2) | ((uint32_t)lzo_read_16(buf) << 16);
343 }
344 
xc_try_lzo1x_decode(struct xc_dom_image * dom,void ** blob,size_t * size)345 static int xc_try_lzo1x_decode(
346     struct xc_dom_image *dom, void **blob, size_t *size)
347 {
348     int ret;
349     const unsigned char *cur = dom->kernel_blob;
350     unsigned char *out_buf;
351     size_t left = dom->kernel_size, outsize, outtot;
352     const char *msg;
353     unsigned version;
354     static const unsigned char magic[] = {
355         0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a
356     };
357 
358     /*
359      * lzo_uint should match size_t. Check that this is the case to be
360      * sure we won't overflow various lzo_uint fields.
361      */
362     BUILD_BUG_ON(sizeof(lzo_uint) != sizeof(size_t));
363 
364     ret = lzo_init();
365     if ( ret != LZO_E_OK )
366     {
367         DOMPRINTF("LZO1x: Failed to init library (%d)\n", ret);
368         return -1;
369     }
370 
371     if ( left < 16 || memcmp(cur, magic, 9) )
372     {
373         DOMPRINTF("LZO1x: Unrecognized magic\n");
374         return -1;
375     }
376 
377     left -= 4;
378     outtot = get_unaligned_le32(*blob + left);
379 
380     if ( xc_dom_kernel_check_size(dom, outtot) )
381     {
382         DOMPRINTF("LZO1x: output too large");
383         return -1;
384     }
385 
386     /* get version (2bytes), skip library version (2),
387      * 'need to be extracted' version (2) and method (1) */
388     version = lzo_read_16(cur + 9);
389     cur += 16;
390     left -= 16;
391 
392     if ( version >= 0x0940 )
393     {
394         /* skip level */
395         ++cur;
396         if ( left )
397             --left;
398     }
399 
400     if ( left >= 4 && (lzo_read_32(cur) & LZOP_HEADER_HAS_FILTER) )
401         ret = 8; /* flags + filter info */
402     else
403         ret = 4; /* flags */
404 
405     /* skip mode and mtime_low */
406     ret += 8;
407     if ( version >= 0x0940 )
408         ret += 4; /* skip mtime_high */
409 
410     /* don't care about the file name, and skip checksum */
411     if ( left > ret )
412         ret += 1 + cur[ret] + 4;
413 
414     if ( left < ret )
415     {
416         DOMPRINTF("LZO1x: Incomplete header\n");
417         return -1;
418     }
419     cur += ret;
420     left -= ret;
421 
422     out_buf = malloc(outtot);
423     if ( !out_buf )
424     {
425         DOMPRINTF("LZO1x: failed to alloc memory");
426         return -1;
427     }
428 
429     for ( outsize = 0; ; )
430     {
431         lzo_uint src_len, dst_len, out_len;
432 
433         msg = "Short input";
434         if ( left < 4 )
435             break;
436 
437         dst_len = lzo_read_32(cur);
438         if ( !dst_len )
439         {
440             msg = "Unexpected output size";
441             if ( outsize != outtot )
442                 break;
443 
444             if ( left != 4 )
445                 DOMPRINTF("LZO1x: Warning: %#zx unconsumed bytes", left - 4);
446 
447             msg = "Error registering stream output";
448             if ( xc_dom_register_external(dom, out_buf, outsize) )
449                 break;
450 
451             DOMPRINTF("%s: LZO decompress OK, 0x%zx -> 0x%zx",
452                       __FUNCTION__, *size, outsize);
453 
454             *blob = out_buf;
455             *size = outsize;
456 
457             return 0;
458         }
459 
460         if ( dst_len > LZOP_MAX_BLOCK_SIZE )
461         {
462             msg = "Block size too large";
463             break;
464         }
465 
466         if ( left < 12 )
467             break;
468 
469         src_len = lzo_read_32(cur + 4);
470         cur += 12; /* also skip block checksum info */
471         left -= 12;
472 
473         msg = "Bad source length";
474         if ( src_len <= 0 || src_len > dst_len || src_len > left )
475             break;
476 
477         msg = "Output buffer overflow";
478         if ( dst_len > outtot - outsize )
479             break;
480 
481         out_len = dst_len;
482 
483         ret = lzo1x_decompress_safe(cur, src_len,
484                                     out_buf + outsize, &out_len, NULL);
485         switch ( ret )
486         {
487         case LZO_E_OK:
488             msg = "Input underrun";
489             if ( out_len != dst_len )
490                 break;
491 
492             outsize += out_len;
493             cur += src_len;
494             left -= src_len;
495             continue;
496 
497         case LZO_E_INPUT_NOT_CONSUMED:
498             msg = "Unconsumed input";
499             break;
500 
501         case LZO_E_OUTPUT_OVERRUN:
502             msg = "Output overrun";
503             break;
504 
505         case LZO_E_INPUT_OVERRUN:
506             msg = "Input overrun";
507             break;
508 
509         case LZO_E_LOOKBEHIND_OVERRUN:
510             msg = "Look-behind overrun";
511             break;
512 
513         case LZO_E_EOF_NOT_FOUND:
514             msg = "No EOF marker";
515             break;
516 
517         case LZO_E_ERROR:
518             msg = "General error";
519             break;
520 
521         default:
522             msg = "Internal program error (bug)";
523             break;
524         }
525 
526         break;
527     }
528 
529     free(out_buf);
530     DOMPRINTF("LZO1x decompression error: %s\n", msg);
531 
532     return -1;
533 }
534 
535 #else /* !defined(HAVE_LZO1X) */
536 
xc_try_lzo1x_decode(struct xc_dom_image * dom,void ** blob,size_t * size)537 static int xc_try_lzo1x_decode(
538     struct xc_dom_image *dom, void **blob, size_t *size)
539 {
540     xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
541                  "%s: LZO1x decompress support unavailable\n",
542                  __FUNCTION__);
543     return -1;
544 }
545 
546 #endif
547 
548 #if defined(HAVE_ZSTD)
549 
550 #include <zstd.h>
551 
xc_try_zstd_decode(struct xc_dom_image * dom,void ** blob,size_t * size)552 static int xc_try_zstd_decode(
553     struct xc_dom_image *dom, void **blob, size_t *size)
554 {
555     size_t outsize, insize, actual;
556     unsigned char *outbuf;
557 
558     /* Magic, descriptor byte, and trailing size field. */
559     if ( *size <= 9 )
560     {
561         DOMPRINTF("ZSTD: insufficient input data");
562         return -1;
563     }
564 
565     insize = *size - 4;
566     outsize = get_unaligned_le32(*blob + insize);
567 
568     if ( xc_dom_kernel_check_size(dom, outsize) )
569     {
570         DOMPRINTF("ZSTD: output too large");
571         return -1;
572     }
573 
574     outbuf = malloc(outsize);
575     if ( !outbuf )
576     {
577         DOMPRINTF("ZSTD: failed to alloc memory");
578         return -1;
579     }
580 
581     actual = ZSTD_decompress(outbuf, outsize, *blob, insize);
582 
583     if ( ZSTD_isError(actual) )
584     {
585         DOMPRINTF("ZSTD: error: %s", ZSTD_getErrorName(actual));
586         free(outbuf);
587         return -1;
588     }
589 
590     if ( actual != outsize )
591     {
592         DOMPRINTF("ZSTD: got 0x%zx bytes instead of 0x%zx",
593                   actual, outsize);
594         free(outbuf);
595         return -1;
596     }
597 
598     if ( xc_dom_register_external(dom, outbuf, outsize) )
599     {
600         DOMPRINTF("ZSTD: error registering stream output");
601         free(outbuf);
602         return -1;
603     }
604 
605     DOMPRINTF("%s: ZSTD decompress OK, 0x%zx -> 0x%zx",
606               __FUNCTION__, insize, outsize);
607 
608     *blob = outbuf;
609     *size = outsize;
610 
611     return 0;
612 }
613 
614 #else /* !defined(HAVE_ZSTD) */
615 
xc_try_zstd_decode(struct xc_dom_image * dom,void ** blob,size_t * size)616 static int xc_try_zstd_decode(
617     struct xc_dom_image *dom, void **blob, size_t *size)
618 {
619     xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
620                  "%s: ZSTD decompress support unavailable\n",
621                  __FUNCTION__);
622     return -1;
623 }
624 
625 #endif
626 
627 #endif /* !__MINIOS__ */
628 
629 struct setup_header {
630     uint8_t  _pad0[0x1f1];  /* skip uninteresting stuff */
631     uint8_t  setup_sects;
632     uint16_t root_flags;
633     uint32_t syssize;
634     uint16_t ram_size;
635     uint16_t vid_mode;
636     uint16_t root_dev;
637     uint16_t boot_flag;
638     uint16_t jump;
639     uint32_t header;
640 #define HDR_MAGIC  "HdrS"
641 #define HDR_MAGIC_SZ 4
642     uint16_t version;
643 #define VERSION(h,l) (((h)<<8) | (l))
644     uint32_t realmode_swtch;
645     uint16_t start_sys;
646     uint16_t kernel_version;
647     uint8_t  type_of_loader;
648     uint8_t  loadflags;
649     uint16_t setup_move_size;
650     uint32_t code32_start;
651     uint32_t ramdisk_image;
652     uint32_t ramdisk_size;
653     uint32_t bootsect_kludge;
654     uint16_t heap_end_ptr;
655     uint16_t _pad1;
656     uint32_t cmd_line_ptr;
657     uint32_t initrd_addr_max;
658     uint32_t kernel_alignment;
659     uint8_t  relocatable_kernel;
660     uint8_t  _pad2[3];
661     uint32_t cmdline_size;
662     uint32_t hardware_subarch;
663     uint64_t hardware_subarch_data;
664     uint32_t payload_offset;
665     uint32_t payload_length;
666 } __attribute__((packed));
667 
668 extern struct xc_dom_loader elf_loader;
669 
check_magic(struct xc_dom_image * dom,const void * magic,size_t len)670 static int check_magic(struct xc_dom_image *dom, const void *magic, size_t len)
671 {
672     if (len > dom->kernel_size)
673         return 0;
674 
675     return (memcmp(dom->kernel_blob, magic, len) == 0);
676 }
677 
xc_dom_probe_bzimage_kernel(struct xc_dom_image * dom)678 static int xc_dom_probe_bzimage_kernel(struct xc_dom_image *dom)
679 {
680     struct setup_header *hdr;
681     uint64_t payload_offset, payload_length;
682     int ret;
683 
684     if ( dom->kernel_blob == NULL )
685     {
686         xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
687                      "%s: no kernel image loaded", __FUNCTION__);
688         return -EINVAL;
689     }
690 
691     if ( dom->kernel_size < sizeof(struct setup_header) )
692     {
693         xc_dom_printf(dom->xch, "%s: kernel image too small", __FUNCTION__);
694         return -EINVAL;
695     }
696 
697     hdr = dom->kernel_blob;
698 
699     if ( memcmp(&hdr->header, HDR_MAGIC, HDR_MAGIC_SZ) != 0 )
700     {
701         xc_dom_printf(dom->xch, "%s: kernel is not a bzImage", __FUNCTION__);
702         return -EINVAL;
703     }
704 
705     if ( hdr->version < VERSION(2,8) )
706     {
707         xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: boot protocol"
708                      " too old (%04x)", __FUNCTION__, hdr->version);
709         return -EINVAL;
710     }
711 
712 
713     /* upcast to 64 bits to avoid overflow */
714     /* setup_sects is u8 and so cannot overflow */
715     payload_offset = (hdr->setup_sects + 1) * 512;
716     payload_offset += hdr->payload_offset;
717     payload_length = hdr->payload_length;
718 
719     if ( payload_offset >= dom->kernel_size )
720     {
721         xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: payload offset overflow",
722                      __FUNCTION__);
723         return -EINVAL;
724     }
725     if ( (payload_offset + payload_length) > dom->kernel_size )
726     {
727         xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: payload length overflow",
728                      __FUNCTION__);
729         return -EINVAL;
730     }
731 
732     dom->kernel_blob = dom->kernel_blob + payload_offset;
733     dom->kernel_size = payload_length;
734 
735     if ( check_magic(dom, "\037\213", 2) )
736     {
737         ret = xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
738         if ( ret == -1 )
739         {
740             xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: unable to"
741                          " gzip decompress kernel", __FUNCTION__);
742             return -EINVAL;
743         }
744     }
745     else if ( check_magic(dom, "\102\132\150", 3) )
746     {
747         ret = xc_try_bzip2_decode(dom, &dom->kernel_blob, &dom->kernel_size);
748         if ( ret < 0 )
749         {
750             xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
751                          "%s unable to BZIP2 decompress kernel",
752                          __FUNCTION__);
753             return -EINVAL;
754         }
755     }
756     else if ( check_magic(dom, "\3757zXZ", 6) )
757     {
758         ret = xc_try_xz_decode(dom, &dom->kernel_blob, &dom->kernel_size);
759         if ( ret < 0 )
760         {
761             xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
762                          "%s unable to XZ decompress kernel",
763                          __FUNCTION__);
764             return -EINVAL;
765         }
766     }
767     else if ( check_magic(dom, "\x28\xb5\x2f\xfd", 4) )
768     {
769         ret = xc_try_zstd_decode(dom, &dom->kernel_blob, &dom->kernel_size);
770         if ( ret < 0 )
771         {
772             xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
773                          "%s unable to ZSTD decompress kernel",
774                          __FUNCTION__);
775             return -EINVAL;
776         }
777     }
778     else if ( check_magic(dom, "\135\000", 2) )
779     {
780         ret = xc_try_lzma_decode(dom, &dom->kernel_blob, &dom->kernel_size);
781         if ( ret < 0 )
782         {
783             xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
784                          "%s unable to LZMA decompress kernel",
785                          __FUNCTION__);
786             return -EINVAL;
787         }
788     }
789     else if ( check_magic(dom, "\x89LZO", 5) )
790     {
791         ret = xc_try_lzo1x_decode(dom, &dom->kernel_blob, &dom->kernel_size);
792         if ( ret < 0 )
793         {
794             xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
795                          "%s unable to LZO decompress kernel\n",
796                          __FUNCTION__);
797             return -EINVAL;
798         }
799     }
800     else if ( check_magic(dom, "\x02\x21", 2) )
801     {
802         ret = xc_try_lz4_decode(dom, &dom->kernel_blob, &dom->kernel_size);
803         if ( ret < 0 )
804         {
805             xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
806                          "%s unable to LZ4 decompress kernel\n",
807                          __FUNCTION__);
808             return -EINVAL;
809         }
810     }
811     else
812     {
813         xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
814                      "%s: unknown compression format", __FUNCTION__);
815         return -EINVAL;
816     }
817 
818     return elf_loader.probe(dom);
819 }
820 
xc_dom_parse_bzimage_kernel(struct xc_dom_image * dom)821 static int xc_dom_parse_bzimage_kernel(struct xc_dom_image *dom)
822 {
823     return elf_loader.parser(dom);
824 }
825 
xc_dom_load_bzimage_kernel(struct xc_dom_image * dom)826 static int xc_dom_load_bzimage_kernel(struct xc_dom_image *dom)
827 {
828     return elf_loader.loader(dom);
829 }
830 
831 static struct xc_dom_loader bzimage_loader = {
832     .name = "Linux bzImage",
833     .probe = xc_dom_probe_bzimage_kernel,
834     .parser = xc_dom_parse_bzimage_kernel,
835     .loader = xc_dom_load_bzimage_kernel,
836 };
837 
register_loader(void)838 static void __init register_loader(void)
839 {
840     xc_dom_register_loader(&bzimage_loader);
841 }
842 
843 /*
844  * Local variables:
845  * mode: C
846  * c-file-style: "BSD"
847  * c-basic-offset: 4
848  * tab-width: 4
849  * indent-tabs-mode: nil
850  * End:
851  */
852