| 1 | /****************************************************************************** |
|---|
| 2 | * xg_private.c |
|---|
| 3 | * |
|---|
| 4 | * Helper functions for the rest of the library. |
|---|
| 5 | */ |
|---|
| 6 | |
|---|
| 7 | #include <stdlib.h> |
|---|
| 8 | #include <unistd.h> |
|---|
| 9 | #include <zlib.h> |
|---|
| 10 | #include <strings.h> |
|---|
| 11 | |
|---|
| 12 | #include "xg_private.h" |
|---|
| 13 | |
|---|
| 14 | int lock_pages(void *addr, size_t len) |
|---|
| 15 | { |
|---|
| 16 | int e = 0; |
|---|
| 17 | #ifndef __sun__ |
|---|
| 18 | e = mlock(addr, len); |
|---|
| 19 | #endif |
|---|
| 20 | return (e); |
|---|
| 21 | } |
|---|
| 22 | |
|---|
| 23 | void unlock_pages(void *addr, size_t len) |
|---|
| 24 | { |
|---|
| 25 | #ifndef __sun__ |
|---|
| 26 | safe_munlock(addr, len); |
|---|
| 27 | #endif |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | char *xc_read_image(const char *filename, unsigned long *size) |
|---|
| 31 | { |
|---|
| 32 | int kernel_fd = -1; |
|---|
| 33 | gzFile kernel_gfd = NULL; |
|---|
| 34 | char *image = NULL, *tmp; |
|---|
| 35 | unsigned int bytes; |
|---|
| 36 | |
|---|
| 37 | if ( (filename == NULL) || (size == NULL) ) |
|---|
| 38 | return NULL; |
|---|
| 39 | |
|---|
| 40 | if ( (kernel_fd = open(filename, O_RDONLY)) < 0 ) |
|---|
| 41 | { |
|---|
| 42 | PERROR("Could not open kernel image"); |
|---|
| 43 | goto out; |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL ) |
|---|
| 47 | { |
|---|
| 48 | PERROR("Could not allocate decompression state for state file"); |
|---|
| 49 | goto out; |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | *size = 0; |
|---|
| 53 | |
|---|
| 54 | #define CHUNK 1*1024*1024 |
|---|
| 55 | while(1) |
|---|
| 56 | { |
|---|
| 57 | if ( (tmp = realloc(image, *size + CHUNK)) == NULL ) |
|---|
| 58 | { |
|---|
| 59 | PERROR("Could not allocate memory for kernel image"); |
|---|
| 60 | free(image); |
|---|
| 61 | image = NULL; |
|---|
| 62 | goto out; |
|---|
| 63 | } |
|---|
| 64 | image = tmp; |
|---|
| 65 | |
|---|
| 66 | bytes = gzread(kernel_gfd, image + *size, CHUNK); |
|---|
| 67 | switch (bytes) |
|---|
| 68 | { |
|---|
| 69 | case -1: |
|---|
| 70 | PERROR("Error reading kernel image"); |
|---|
| 71 | free(image); |
|---|
| 72 | image = NULL; |
|---|
| 73 | goto out; |
|---|
| 74 | case 0: /* EOF */ |
|---|
| 75 | goto out; |
|---|
| 76 | default: |
|---|
| 77 | *size += bytes; |
|---|
| 78 | break; |
|---|
| 79 | } |
|---|
| 80 | } |
|---|
| 81 | #undef CHUNK |
|---|
| 82 | |
|---|
| 83 | out: |
|---|
| 84 | if ( *size == 0 ) |
|---|
| 85 | { |
|---|
| 86 | PERROR("Could not read kernel image"); |
|---|
| 87 | free(image); |
|---|
| 88 | image = NULL; |
|---|
| 89 | } |
|---|
| 90 | else if ( image ) |
|---|
| 91 | { |
|---|
| 92 | /* Shrink allocation to fit image. */ |
|---|
| 93 | tmp = realloc(image, *size); |
|---|
| 94 | if ( tmp ) |
|---|
| 95 | image = tmp; |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | if ( kernel_gfd != NULL ) |
|---|
| 99 | gzclose(kernel_gfd); |
|---|
| 100 | else if ( kernel_fd >= 0 ) |
|---|
| 101 | close(kernel_fd); |
|---|
| 102 | return image; |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | char *xc_inflate_buffer(const char *in_buf, unsigned long in_size, |
|---|
| 106 | unsigned long *out_size) |
|---|
| 107 | { |
|---|
| 108 | int sts; |
|---|
| 109 | z_stream zStream; |
|---|
| 110 | unsigned long out_len; |
|---|
| 111 | char *out_buf; |
|---|
| 112 | |
|---|
| 113 | /* Not compressed? Then return the original buffer. */ |
|---|
| 114 | if ( ((unsigned char)in_buf[0] != 0x1F) || |
|---|
| 115 | ((unsigned char)in_buf[1] != 0x8B) ) |
|---|
| 116 | { |
|---|
| 117 | if ( out_size != NULL ) |
|---|
| 118 | *out_size = in_size; |
|---|
| 119 | return (char *)in_buf; |
|---|
| 120 | } |
|---|
| 121 | |
|---|
| 122 | out_len = (unsigned char)in_buf[in_size-4] + |
|---|
| 123 | (256 * ((unsigned char)in_buf[in_size-3] + |
|---|
| 124 | (256 * ((unsigned char)in_buf[in_size-2] + |
|---|
| 125 | (256 * (unsigned char)in_buf[in_size-1]))))); |
|---|
| 126 | |
|---|
| 127 | bzero(&zStream, sizeof(zStream)); |
|---|
| 128 | out_buf = malloc(out_len + 16); /* Leave a little extra space */ |
|---|
| 129 | if ( out_buf == NULL ) |
|---|
| 130 | { |
|---|
| 131 | ERROR("Error mallocing buffer\n"); |
|---|
| 132 | return NULL; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | zStream.next_in = (unsigned char *)in_buf; |
|---|
| 136 | zStream.avail_in = in_size; |
|---|
| 137 | zStream.next_out = (unsigned char *)out_buf; |
|---|
| 138 | zStream.avail_out = out_len+16; |
|---|
| 139 | sts = inflateInit2(&zStream, (MAX_WBITS+32)); /* +32 means "handle gzip" */ |
|---|
| 140 | if ( sts != Z_OK ) |
|---|
| 141 | { |
|---|
| 142 | ERROR("inflateInit failed, sts %d\n", sts); |
|---|
| 143 | free(out_buf); |
|---|
| 144 | return NULL; |
|---|
| 145 | } |
|---|
| 146 | |
|---|
| 147 | /* Inflate in one pass/call */ |
|---|
| 148 | sts = inflate(&zStream, Z_FINISH); |
|---|
| 149 | if ( sts != Z_STREAM_END ) |
|---|
| 150 | { |
|---|
| 151 | ERROR("inflate failed, sts %d\n", sts); |
|---|
| 152 | free(out_buf); |
|---|
| 153 | return NULL; |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | if ( out_size != NULL ) |
|---|
| 157 | *out_size = out_len; |
|---|
| 158 | |
|---|
| 159 | return out_buf; |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | /*******************/ |
|---|
| 163 | |
|---|
| 164 | int pin_table( |
|---|
| 165 | int xc_handle, unsigned int type, unsigned long mfn, domid_t dom) |
|---|
| 166 | { |
|---|
| 167 | struct mmuext_op op; |
|---|
| 168 | |
|---|
| 169 | op.cmd = type; |
|---|
| 170 | op.arg1.mfn = mfn; |
|---|
| 171 | |
|---|
| 172 | if ( xc_mmuext_op(xc_handle, &op, 1, dom) < 0 ) |
|---|
| 173 | return 1; |
|---|
| 174 | |
|---|
| 175 | return 0; |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | /* This is shared between save and restore, and may generally be useful. */ |
|---|
| 179 | unsigned long csum_page(void *page) |
|---|
| 180 | { |
|---|
| 181 | int i; |
|---|
| 182 | unsigned long *p = page; |
|---|
| 183 | unsigned long long sum=0; |
|---|
| 184 | |
|---|
| 185 | for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ ) |
|---|
| 186 | sum += p[i]; |
|---|
| 187 | |
|---|
| 188 | return sum ^ (sum>>32); |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | __attribute__((weak)) |
|---|
| 192 | int xc_hvm_build(int xc_handle, |
|---|
| 193 | uint32_t domid, |
|---|
| 194 | int memsize, |
|---|
| 195 | const char *image_name) |
|---|
| 196 | { |
|---|
| 197 | errno = ENOSYS; |
|---|
| 198 | return -1; |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | /* |
|---|
| 202 | * Local variables: |
|---|
| 203 | * mode: C |
|---|
| 204 | * c-set-style: "BSD" |
|---|
| 205 | * c-basic-offset: 4 |
|---|
| 206 | * tab-width: 4 |
|---|
| 207 | * indent-tabs-mode: nil |
|---|
| 208 | * End: |
|---|
| 209 | */ |
|---|