1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <inttypes.h>
4 #include <stdint.h>
5 
6 #include "xg_private.h"
7 #include "xc_dom_decompress.h"
8 
9 #define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
10 
11 typedef uint8_t u8;
12 typedef uint16_t u16;
13 typedef uint32_t u32;
14 typedef uint64_t u64;
15 
16 #define likely(a) a
17 #define unlikely(a) a
18 
le16_to_cpup(const unsigned char * buf)19 static inline uint_fast16_t le16_to_cpup(const unsigned char *buf)
20 {
21     return buf[0] | (buf[1] << 8);
22 }
23 
le32_to_cpup(const unsigned char * buf)24 static inline uint_fast32_t le32_to_cpup(const unsigned char *buf)
25 {
26     return le16_to_cpup(buf) | ((uint32_t)le16_to_cpup(buf + 2) << 16);
27 }
28 
29 #include "../../xen/include/xen/lz4.h"
30 #include "../../xen/common/decompress.h"
31 
32 #ifndef __MINIOS__
33 
34 #include "../../xen/common/lz4/decompress.c"
35 
36 #define ARCHIVE_MAGICNUMBER 0x184C2102
37 
xc_try_lz4_decode(struct xc_dom_image * dom,void ** blob,size_t * psize)38 int xc_try_lz4_decode(
39 	struct xc_dom_image *dom, void **blob, size_t *psize)
40 {
41 	int ret = -1;
42 	unsigned char *inp = *blob, *output, *outp;
43 	ssize_t size = *psize - 4;
44 	size_t out_len, dest_len, chunksize;
45 	const char *msg;
46 
47 	if (size < 4) {
48 		msg = "input too small";
49 		goto exit_0;
50 	}
51 
52 	out_len = get_unaligned_le32(inp + size);
53 	if (xc_dom_kernel_check_size(dom, out_len)) {
54 		msg = "Decompressed image too large";
55 		goto exit_0;
56 	}
57 
58 	output = malloc(out_len);
59 	if (!output) {
60 		msg = "Could not allocate output buffer";
61 		goto exit_0;
62 	}
63 	outp = output;
64 
65 	chunksize = get_unaligned_le32(inp);
66 	if (chunksize == ARCHIVE_MAGICNUMBER) {
67 		inp += 4;
68 		size -= 4;
69 	} else {
70 		msg = "invalid header";
71 		goto exit_2;
72 	}
73 
74 	for (;;) {
75 		if (size < 4) {
76 			msg = "missing data";
77 			goto exit_2;
78 		}
79 		chunksize = get_unaligned_le32(inp);
80 		if (chunksize == ARCHIVE_MAGICNUMBER) {
81 			inp += 4;
82 			size -= 4;
83 			continue;
84 		}
85 		inp += 4;
86 		size -= 4;
87 		if (chunksize > size) {
88 			msg = "insufficient input data";
89 			goto exit_2;
90 		}
91 
92 		dest_len = out_len - (outp - output);
93 		ret = lz4_decompress_unknownoutputsize(inp, chunksize, outp,
94 				&dest_len);
95 		if (ret < 0) {
96 			msg = "decoding failed";
97 			goto exit_2;
98 		}
99 
100 		ret = -1;
101 		outp += dest_len;
102 		size -= chunksize;
103 
104 		if (size == 0)
105 		{
106 			if ( xc_dom_register_external(dom, output, out_len) )
107 			{
108 				msg = "Error registering stream output";
109 				goto exit_2;
110 			}
111 			*blob = output;
112 			*psize = out_len;
113 			return 0;
114 		}
115 
116 		if (size < 0) {
117 			msg = "data corrupted";
118 			goto exit_2;
119 		}
120 
121 		inp += chunksize;
122 	}
123 
124 exit_2:
125 	free(output);
126 exit_0:
127 	DOMPRINTF("LZ4 decompression error: %s\n", msg);
128 	return ret;
129 }
130 
131 #else /* __MINIOS__ */
132 
133 #include "../../xen/common/unlz4.c"
134 
xc_try_lz4_decode(struct xc_dom_image * dom,void ** blob,size_t * size)135 int xc_try_lz4_decode(
136     struct xc_dom_image *dom, void **blob, size_t *size)
137 {
138     return xc_dom_decompress_unsafe(unlz4, dom, blob, size);
139 }
140 
141 #endif
142