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