1 /******************************************************************************
2 * xg_private.c
3 *
4 * Helper functions for the rest of the library.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation;
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <zlib.h>
23
24 #include "xg_private.h"
25
xc_read_image(xc_interface * xch,const char * filename,unsigned long * size)26 char *xc_read_image(xc_interface *xch,
27 const char *filename, unsigned long *size)
28 {
29 int kernel_fd = -1;
30 gzFile kernel_gfd = NULL;
31 char *image = NULL, *tmp;
32 unsigned int bytes;
33
34 if ( (filename == NULL) || (size == NULL) )
35 return NULL;
36
37 if ( (kernel_fd = open(filename, O_RDONLY)) < 0 )
38 {
39 PERROR("Could not open kernel image '%s'", filename);
40 goto out;
41 }
42
43 if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
44 {
45 PERROR("Could not allocate decompression state for state file");
46 goto out;
47 }
48
49 *size = 0;
50
51 #define CHUNK 1*1024*1024
52 while(1)
53 {
54 if ( (tmp = realloc(image, *size + CHUNK)) == NULL )
55 {
56 PERROR("Could not allocate memory for kernel image");
57 free(image);
58 image = NULL;
59 goto out;
60 }
61 image = tmp;
62
63 bytes = gzread(kernel_gfd, image + *size, CHUNK);
64 switch (bytes)
65 {
66 case -1:
67 PERROR("Error reading kernel image");
68 free(image);
69 image = NULL;
70 goto out;
71 case 0: /* EOF */
72 if ( *size == 0 )
73 {
74 PERROR("Could not read kernel image");
75 free(image);
76 image = NULL;
77 }
78 goto out;
79 default:
80 *size += bytes;
81 break;
82 }
83 }
84 #undef CHUNK
85
86 out:
87 if ( image )
88 {
89 /* Shrink allocation to fit image. */
90 tmp = realloc(image, *size);
91 if ( tmp )
92 image = tmp;
93 }
94
95 if ( kernel_gfd != NULL )
96 gzclose(kernel_gfd);
97 else if ( kernel_fd >= 0 )
98 close(kernel_fd);
99 return image;
100 }
101
xc_inflate_buffer(xc_interface * xch,const char * in_buf,unsigned long in_size,unsigned long * out_size)102 char *xc_inflate_buffer(xc_interface *xch,
103 const char *in_buf, unsigned long in_size,
104 unsigned long *out_size)
105 {
106 int sts;
107 z_stream zStream;
108 unsigned long out_len;
109 char *out_buf;
110
111 /* Not compressed? Then return the original buffer. */
112 if ( ((unsigned char)in_buf[0] != 0x1F) ||
113 ((unsigned char)in_buf[1] != 0x8B) )
114 {
115 if ( out_size != NULL )
116 *out_size = in_size;
117 return (char *)in_buf;
118 }
119
120 out_len = (unsigned char)in_buf[in_size-4] +
121 (256 * ((unsigned char)in_buf[in_size-3] +
122 (256 * ((unsigned char)in_buf[in_size-2] +
123 (256 * (unsigned char)in_buf[in_size-1])))));
124
125 memset(&zStream, 0, sizeof(zStream));
126 out_buf = malloc(out_len + 16); /* Leave a little extra space */
127 if ( out_buf == NULL )
128 {
129 ERROR("Error mallocing buffer\n");
130 return NULL;
131 }
132
133 zStream.next_in = (unsigned char *)in_buf;
134 zStream.avail_in = in_size;
135 zStream.next_out = (unsigned char *)out_buf;
136 zStream.avail_out = out_len+16;
137 sts = inflateInit2(&zStream, (MAX_WBITS+32)); /* +32 means "handle gzip" */
138 if ( sts != Z_OK )
139 {
140 ERROR("inflateInit failed, sts %d\n", sts);
141 free(out_buf);
142 return NULL;
143 }
144
145 /* Inflate in one pass/call */
146 sts = inflate(&zStream, Z_FINISH);
147 inflateEnd(&zStream);
148 if ( sts != Z_STREAM_END )
149 {
150 ERROR("inflate failed, sts %d\n", sts);
151 free(out_buf);
152 return NULL;
153 }
154
155 if ( out_size != NULL )
156 *out_size = out_len;
157
158 return out_buf;
159 }
160
161 /*******************/
162
pin_table(xc_interface * xch,unsigned int type,unsigned long mfn,uint32_t dom)163 int pin_table(
164 xc_interface *xch, unsigned int type, unsigned long mfn, uint32_t dom)
165 {
166 struct mmuext_op op;
167
168 op.cmd = type;
169 op.arg1.mfn = mfn;
170
171 if ( xc_mmuext_op(xch, &op, 1, dom) < 0 )
172 return 1;
173
174 return 0;
175 }
176
177 /* This is shared between save and restore, and may generally be useful. */
csum_page(void * page)178 unsigned long csum_page(void *page)
179 {
180 int i;
181 unsigned long *p = page;
182 unsigned long long sum=0;
183
184 for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ )
185 sum += p[i];
186
187 return sum ^ (sum>>32);
188 }
189
190 /*
191 * Local variables:
192 * mode: C
193 * c-file-style: "BSD"
194 * c-basic-offset: 4
195 * tab-width: 4
196 * indent-tabs-mode: nil
197 * End:
198 */
199