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