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