1 /* 2 * QEMU Block driver for DMG images 3 * 4 * Copyright (c) 2004 Johannes E. Schindelin 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #include "qemu-common.h" 25 #include "block/block_int.h" 26 #include "qemu/bswap.h" 27 #include "qemu/module.h" 28 #include <zlib.h> 29 30 enum { 31 /* Limit chunk sizes to prevent unreasonable amounts of memory being used 32 * or truncating when converting to 32-bit types 33 */ 34 DMG_LENGTHS_MAX = 64 * 1024 * 1024, /* 64 MB */ 35 DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512, 36 }; 37 38 typedef struct BDRVDMGState { 39 CoMutex lock; 40 /* each chunk contains a certain number of sectors, 41 * offsets[i] is the offset in the .dmg file, 42 * lengths[i] is the length of the compressed chunk, 43 * sectors[i] is the sector beginning at offsets[i], 44 * sectorcounts[i] is the number of sectors in that chunk, 45 * the sectors array is ordered 46 * 0<=i<n_chunks */ 47 48 uint32_t n_chunks; 49 uint32_t* types; 50 uint64_t* offsets; 51 uint64_t* lengths; 52 uint64_t* sectors; 53 uint64_t* sectorcounts; 54 uint32_t current_chunk; 55 uint8_t *compressed_chunk; 56 uint8_t *uncompressed_chunk; 57 z_stream zstream; 58 } BDRVDMGState; 59 60 static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename) 61 { 62 int len; 63 64 if (!filename) { 65 return 0; 66 } 67 68 len = strlen(filename); 69 if (len > 4 && !strcmp(filename + len - 4, ".dmg")) { 70 return 2; 71 } 72 return 0; 73 } 74 75 static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result) 76 { 77 uint64_t buffer; 78 int ret; 79 80 ret = bdrv_pread(bs->file, offset, &buffer, 8); 81 if (ret < 0) { 82 return ret; 83 } 84 85 *result = be64_to_cpu(buffer); 86 return 0; 87 } 88 89 static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result) 90 { 91 uint32_t buffer; 92 int ret; 93 94 ret = bdrv_pread(bs->file, offset, &buffer, 4); 95 if (ret < 0) { 96 return ret; 97 } 98 99 *result = be32_to_cpu(buffer); 100 return 0; 101 } 102 103 /* Increase max chunk sizes, if necessary. This function is used to calculate 104 * the buffer sizes needed for compressed/uncompressed chunk I/O. 105 */ 106 static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk, 107 uint32_t *max_compressed_size, 108 uint32_t *max_sectors_per_chunk) 109 { 110 uint32_t compressed_size = 0; 111 uint32_t uncompressed_sectors = 0; 112 113 switch (s->types[chunk]) { 114 case 0x80000005: /* zlib compressed */ 115 compressed_size = s->lengths[chunk]; 116 uncompressed_sectors = s->sectorcounts[chunk]; 117 break; 118 case 1: /* copy */ 119 uncompressed_sectors = (s->lengths[chunk] + 511) / 512; 120 break; 121 case 2: /* zero */ 122 uncompressed_sectors = s->sectorcounts[chunk]; 123 break; 124 } 125 126 if (compressed_size > *max_compressed_size) { 127 *max_compressed_size = compressed_size; 128 } 129 if (uncompressed_sectors > *max_sectors_per_chunk) { 130 *max_sectors_per_chunk = uncompressed_sectors; 131 } 132 } 133 134 static int dmg_open(BlockDriverState *bs, QDict *options, int flags, 135 Error **errp) 136 { 137 BDRVDMGState *s = bs->opaque; 138 uint64_t info_begin, info_end, last_in_offset, last_out_offset; 139 uint32_t count, tmp; 140 uint32_t max_compressed_size = 1, max_sectors_per_chunk = 1, i; 141 int64_t offset; 142 int ret; 143 144 bs->read_only = 1; 145 s->n_chunks = 0; 146 s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; 147 148 /* read offset of info blocks */ 149 offset = bdrv_getlength(bs->file); 150 if (offset < 0) { 151 ret = offset; 152 goto fail; 153 } 154 offset -= 0x1d8; 155 156 ret = read_uint64(bs, offset, &info_begin); 157 if (ret < 0) { 158 goto fail; 159 } else if (info_begin == 0) { 160 ret = -EINVAL; 161 goto fail; 162 } 163 164 ret = read_uint32(bs, info_begin, &tmp); 165 if (ret < 0) { 166 goto fail; 167 } else if (tmp != 0x100) { 168 ret = -EINVAL; 169 goto fail; 170 } 171 172 ret = read_uint32(bs, info_begin + 4, &count); 173 if (ret < 0) { 174 goto fail; 175 } else if (count == 0) { 176 ret = -EINVAL; 177 goto fail; 178 } 179 info_end = info_begin + count; 180 181 offset = info_begin + 0x100; 182 183 /* read offsets */ 184 last_in_offset = last_out_offset = 0; 185 while (offset < info_end) { 186 uint32_t type; 187 188 ret = read_uint32(bs, offset, &count); 189 if (ret < 0) { 190 goto fail; 191 } else if (count == 0) { 192 ret = -EINVAL; 193 goto fail; 194 } 195 offset += 4; 196 197 ret = read_uint32(bs, offset, &type); 198 if (ret < 0) { 199 goto fail; 200 } 201 202 if (type == 0x6d697368 && count >= 244) { 203 size_t new_size; 204 uint32_t chunk_count; 205 206 offset += 4; 207 offset += 200; 208 209 chunk_count = (count - 204) / 40; 210 new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count); 211 s->types = g_realloc(s->types, new_size / 2); 212 s->offsets = g_realloc(s->offsets, new_size); 213 s->lengths = g_realloc(s->lengths, new_size); 214 s->sectors = g_realloc(s->sectors, new_size); 215 s->sectorcounts = g_realloc(s->sectorcounts, new_size); 216 217 for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) { 218 ret = read_uint32(bs, offset, &s->types[i]); 219 if (ret < 0) { 220 goto fail; 221 } 222 offset += 4; 223 if (s->types[i] != 0x80000005 && s->types[i] != 1 && 224 s->types[i] != 2) { 225 if (s->types[i] == 0xffffffff && i > 0) { 226 last_in_offset = s->offsets[i - 1] + s->lengths[i - 1]; 227 last_out_offset = s->sectors[i - 1] + 228 s->sectorcounts[i - 1]; 229 } 230 chunk_count--; 231 i--; 232 offset += 36; 233 continue; 234 } 235 offset += 4; 236 237 ret = read_uint64(bs, offset, &s->sectors[i]); 238 if (ret < 0) { 239 goto fail; 240 } 241 s->sectors[i] += last_out_offset; 242 offset += 8; 243 244 ret = read_uint64(bs, offset, &s->sectorcounts[i]); 245 if (ret < 0) { 246 goto fail; 247 } 248 offset += 8; 249 250 if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) { 251 error_report("sector count %" PRIu64 " for chunk %" PRIu32 252 " is larger than max (%u)", 253 s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX); 254 ret = -EINVAL; 255 goto fail; 256 } 257 258 ret = read_uint64(bs, offset, &s->offsets[i]); 259 if (ret < 0) { 260 goto fail; 261 } 262 s->offsets[i] += last_in_offset; 263 offset += 8; 264 265 ret = read_uint64(bs, offset, &s->lengths[i]); 266 if (ret < 0) { 267 goto fail; 268 } 269 offset += 8; 270 271 if (s->lengths[i] > DMG_LENGTHS_MAX) { 272 error_report("length %" PRIu64 " for chunk %" PRIu32 273 " is larger than max (%u)", 274 s->lengths[i], i, DMG_LENGTHS_MAX); 275 ret = -EINVAL; 276 goto fail; 277 } 278 279 update_max_chunk_size(s, i, &max_compressed_size, 280 &max_sectors_per_chunk); 281 } 282 s->n_chunks += chunk_count; 283 } 284 } 285 286 /* initialize zlib engine */ 287 s->compressed_chunk = qemu_try_blockalign(bs->file, 288 max_compressed_size + 1); 289 s->uncompressed_chunk = qemu_try_blockalign(bs->file, 290 512 * max_sectors_per_chunk); 291 if (s->compressed_chunk == NULL || s->uncompressed_chunk == NULL) { 292 ret = -ENOMEM; 293 goto fail; 294 } 295 296 if (inflateInit(&s->zstream) != Z_OK) { 297 ret = -EINVAL; 298 goto fail; 299 } 300 301 s->current_chunk = s->n_chunks; 302 303 qemu_co_mutex_init(&s->lock); 304 return 0; 305 306 fail: 307 g_free(s->types); 308 g_free(s->offsets); 309 g_free(s->lengths); 310 g_free(s->sectors); 311 g_free(s->sectorcounts); 312 qemu_vfree(s->compressed_chunk); 313 qemu_vfree(s->uncompressed_chunk); 314 return ret; 315 } 316 317 static inline int is_sector_in_chunk(BDRVDMGState* s, 318 uint32_t chunk_num, uint64_t sector_num) 319 { 320 if (chunk_num >= s->n_chunks || s->sectors[chunk_num] > sector_num || 321 s->sectors[chunk_num] + s->sectorcounts[chunk_num] <= sector_num) { 322 return 0; 323 } else { 324 return -1; 325 } 326 } 327 328 static inline uint32_t search_chunk(BDRVDMGState *s, uint64_t sector_num) 329 { 330 /* binary search */ 331 uint32_t chunk1 = 0, chunk2 = s->n_chunks, chunk3; 332 while (chunk1 != chunk2) { 333 chunk3 = (chunk1 + chunk2) / 2; 334 if (s->sectors[chunk3] > sector_num) { 335 chunk2 = chunk3; 336 } else if (s->sectors[chunk3] + s->sectorcounts[chunk3] > sector_num) { 337 return chunk3; 338 } else { 339 chunk1 = chunk3; 340 } 341 } 342 return s->n_chunks; /* error */ 343 } 344 345 static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) 346 { 347 BDRVDMGState *s = bs->opaque; 348 349 if (!is_sector_in_chunk(s, s->current_chunk, sector_num)) { 350 int ret; 351 uint32_t chunk = search_chunk(s, sector_num); 352 353 if (chunk >= s->n_chunks) { 354 return -1; 355 } 356 357 s->current_chunk = s->n_chunks; 358 switch (s->types[chunk]) { 359 case 0x80000005: { /* zlib compressed */ 360 /* we need to buffer, because only the chunk as whole can be 361 * inflated. */ 362 ret = bdrv_pread(bs->file, s->offsets[chunk], 363 s->compressed_chunk, s->lengths[chunk]); 364 if (ret != s->lengths[chunk]) { 365 return -1; 366 } 367 368 s->zstream.next_in = s->compressed_chunk; 369 s->zstream.avail_in = s->lengths[chunk]; 370 s->zstream.next_out = s->uncompressed_chunk; 371 s->zstream.avail_out = 512 * s->sectorcounts[chunk]; 372 ret = inflateReset(&s->zstream); 373 if (ret != Z_OK) { 374 return -1; 375 } 376 ret = inflate(&s->zstream, Z_FINISH); 377 if (ret != Z_STREAM_END || 378 s->zstream.total_out != 512 * s->sectorcounts[chunk]) { 379 return -1; 380 } 381 break; } 382 case 1: /* copy */ 383 ret = bdrv_pread(bs->file, s->offsets[chunk], 384 s->uncompressed_chunk, s->lengths[chunk]); 385 if (ret != s->lengths[chunk]) { 386 return -1; 387 } 388 break; 389 case 2: /* zero */ 390 memset(s->uncompressed_chunk, 0, 512 * s->sectorcounts[chunk]); 391 break; 392 } 393 s->current_chunk = chunk; 394 } 395 return 0; 396 } 397 398 static int dmg_read(BlockDriverState *bs, int64_t sector_num, 399 uint8_t *buf, int nb_sectors) 400 { 401 BDRVDMGState *s = bs->opaque; 402 int i; 403 404 for (i = 0; i < nb_sectors; i++) { 405 uint32_t sector_offset_in_chunk; 406 if (dmg_read_chunk(bs, sector_num + i) != 0) { 407 return -1; 408 } 409 sector_offset_in_chunk = sector_num + i - s->sectors[s->current_chunk]; 410 memcpy(buf + i * 512, 411 s->uncompressed_chunk + sector_offset_in_chunk * 512, 512); 412 } 413 return 0; 414 } 415 416 static coroutine_fn int dmg_co_read(BlockDriverState *bs, int64_t sector_num, 417 uint8_t *buf, int nb_sectors) 418 { 419 int ret; 420 BDRVDMGState *s = bs->opaque; 421 qemu_co_mutex_lock(&s->lock); 422 ret = dmg_read(bs, sector_num, buf, nb_sectors); 423 qemu_co_mutex_unlock(&s->lock); 424 return ret; 425 } 426 427 static void dmg_close(BlockDriverState *bs) 428 { 429 BDRVDMGState *s = bs->opaque; 430 431 g_free(s->types); 432 g_free(s->offsets); 433 g_free(s->lengths); 434 g_free(s->sectors); 435 g_free(s->sectorcounts); 436 qemu_vfree(s->compressed_chunk); 437 qemu_vfree(s->uncompressed_chunk); 438 439 inflateEnd(&s->zstream); 440 } 441 442 static BlockDriver bdrv_dmg = { 443 .format_name = "dmg", 444 .instance_size = sizeof(BDRVDMGState), 445 .bdrv_probe = dmg_probe, 446 .bdrv_open = dmg_open, 447 .bdrv_read = dmg_co_read, 448 .bdrv_close = dmg_close, 449 }; 450 451 static void bdrv_dmg_init(void) 452 { 453 bdrv_register(&bdrv_dmg); 454 } 455 456 block_init(bdrv_dmg_init); 457