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