1187767Sluigi/*- 2187767Sluigi * Copyright (c) 2014 Marcel Moolenaar 3187767Sluigi * All rights reserved. 4187767Sluigi * 5187767Sluigi * Redistribution and use in source and binary forms, with or without 6187767Sluigi * modification, are permitted provided that the following conditions 7187767Sluigi * are met: 8187767Sluigi * 1. Redistributions of source code must retain the above copyright 9187767Sluigi * notice, this list of conditions and the following disclaimer. 10187767Sluigi * 2. Redistributions in binary form must reproduce the above copyright 11187767Sluigi * notice, this list of conditions and the following disclaimer in the 12187767Sluigi * documentation and/or other materials provided with the distribution. 13187767Sluigi * 14187767Sluigi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15187767Sluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16187767Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17187767Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18187767Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19187767Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20187767Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21187767Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22187767Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23187767Sluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24187767Sluigi * SUCH DAMAGE. 25187767Sluigi */ 26187767Sluigi 27187767Sluigi#include <sys/cdefs.h> 28187767Sluigi__FBSDID("$FreeBSD: releng/11.0/usr.bin/mkimg/qcow.c 275721 2014-12-12 06:13:31Z marcel $"); 29187767Sluigi 30187767Sluigi#include <sys/types.h> 31187767Sluigi#include <sys/endian.h> 32187767Sluigi#include <sys/errno.h> 33187767Sluigi#include <stdint.h> 34187767Sluigi#include <stdio.h> 35187767Sluigi#include <stdlib.h> 36187767Sluigi#include <string.h> 37187767Sluigi#include <unistd.h> 38204591Sluigi 39187767Sluigi#include "image.h" 40187767Sluigi#include "format.h" 41187767Sluigi#include "mkimg.h" 42187767Sluigi 43187767Sluigi/* Default cluster sizes. */ 44187767Sluigi#define QCOW1_CLSTR_LOG2SZ 12 /* 4KB */ 45187767Sluigi#define QCOW2_CLSTR_LOG2SZ 16 /* 64KB */ 46187767Sluigi 47187767Sluigi/* Flag bits in cluster offsets */ 48187767Sluigi#define QCOW_CLSTR_COMPRESSED (1ULL << 62) 49187767Sluigi#define QCOW_CLSTR_COPIED (1ULL << 63) 50187767Sluigi 51187767Sluigistruct qcow_header { 52187767Sluigi uint32_t magic; 53187767Sluigi#define QCOW_MAGIC 0x514649fb 54187767Sluigi uint32_t version; 55187767Sluigi#define QCOW_VERSION_1 1 56187767Sluigi#define QCOW_VERSION_2 2 57187767Sluigi uint64_t path_offset; 58187767Sluigi uint32_t path_length; 59187767Sluigi uint32_t clstr_log2sz; /* v2 only */ 60187767Sluigi uint64_t disk_size; 61187767Sluigi union { 62187767Sluigi struct { 63187767Sluigi uint8_t clstr_log2sz; 64187767Sluigi uint8_t l2_log2sz; 65187767Sluigi uint16_t _pad; 66187767Sluigi uint32_t encryption; 67187767Sluigi uint64_t l1_offset; 68187767Sluigi } v1; 69187767Sluigi struct { 70187767Sluigi uint32_t encryption; 71187767Sluigi uint32_t l1_entries; 72187767Sluigi uint64_t l1_offset; 73187767Sluigi uint64_t refcnt_offset; 74187769Sluigi uint32_t refcnt_clstrs; 75187769Sluigi uint32_t snapshot_count; 76187769Sluigi uint64_t snapshot_offset; 77187769Sluigi } v2; 78187769Sluigi } u; 79187769Sluigi}; 80187769Sluigi 81187769Sluigistatic u_int clstr_log2sz; 82187769Sluigi 83187769Sluigistatic uint64_t 84187769Sluigiround_clstr(uint64_t ofs) 85204591Sluigi{ 86187769Sluigi uint64_t clstrsz; 87204591Sluigi 88204591Sluigi clstrsz = 1UL << clstr_log2sz; 89187769Sluigi return ((ofs + clstrsz - 1) & ~(clstrsz - 1)); 90187769Sluigi} 91187769Sluigi 92187769Sluigistatic int 93187769Sluigiqcow_resize(lba_t imgsz, u_int version) 94187769Sluigi{ 95187769Sluigi uint64_t imagesz; 96187769Sluigi 97187769Sluigi switch (version) { 98187769Sluigi case QCOW_VERSION_1: 99187769Sluigi clstr_log2sz = QCOW1_CLSTR_LOG2SZ; 100187769Sluigi break; 101190633Spiso case QCOW_VERSION_2: 102187769Sluigi clstr_log2sz = QCOW2_CLSTR_LOG2SZ; 103187769Sluigi break; 104187769Sluigi default: 105187769Sluigi return (EDOOFUS); 106187769Sluigi } 107187769Sluigi 108187769Sluigi imagesz = round_clstr(imgsz * secsz); 109187769Sluigi 110187769Sluigi if (verbose) 111187769Sluigi fprintf(stderr, "QCOW: image size = %ju, cluster size = %u\n", 112187769Sluigi (uintmax_t)imagesz, (u_int)(1U << clstr_log2sz)); 113187769Sluigi 114187769Sluigi return (image_set_size(imagesz / secsz)); 115187769Sluigi} 116187769Sluigi 117187769Sluigistatic int 118187769Sluigiqcow1_resize(lba_t imgsz) 119187769Sluigi{ 120187769Sluigi 121187769Sluigi return (qcow_resize(imgsz, QCOW_VERSION_1)); 122187769Sluigi} 123187769Sluigi 124187769Sluigistatic int 125187769Sluigiqcow2_resize(lba_t imgsz) 126187769Sluigi{ 127187769Sluigi 128205169Sluigi return (qcow_resize(imgsz, QCOW_VERSION_2)); 129187769Sluigi} 130187769Sluigi 131187769Sluigistatic int 132187769Sluigiqcow_write(int fd, u_int version) 133187769Sluigi{ 134187769Sluigi struct qcow_header *hdr; 135187769Sluigi uint64_t *l1tbl, *l2tbl, *rctbl; 136187769Sluigi uint16_t *rcblk; 137187769Sluigi uint64_t clstr_imgsz, clstr_l2tbls, clstr_l1tblsz; 138187769Sluigi uint64_t clstr_rcblks, clstr_rctblsz; 139187769Sluigi uint64_t n, imagesz, nclstrs, ofs, ofsflags; 140187769Sluigi lba_t blk, blkofs, blk_imgsz; 141187769Sluigi u_int l1clno, l2clno, rcclno; 142187769Sluigi u_int blk_clstrsz, refcnt_clstrs; 143187769Sluigi u_int clstrsz, l1idx, l2idx; 144187769Sluigi int error; 145187769Sluigi 146187769Sluigi if (clstr_log2sz == 0) 147187769Sluigi return (EDOOFUS); 148187769Sluigi 149187769Sluigi clstrsz = 1U << clstr_log2sz; 150187769Sluigi blk_clstrsz = clstrsz / secsz; 151187769Sluigi blk_imgsz = image_get_size(); 152187769Sluigi imagesz = blk_imgsz * secsz; 153187769Sluigi clstr_imgsz = imagesz >> clstr_log2sz; 154187769Sluigi clstr_l2tbls = round_clstr(clstr_imgsz * 8) >> clstr_log2sz; 155187769Sluigi clstr_l1tblsz = round_clstr(clstr_l2tbls * 8) >> clstr_log2sz; 156187769Sluigi nclstrs = clstr_imgsz + clstr_l2tbls + clstr_l1tblsz + 1; 157187769Sluigi clstr_rcblks = clstr_rctblsz = 0; 158204591Sluigi do { 159204591Sluigi n = clstr_rcblks + clstr_rctblsz; 160187769Sluigi clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz; 161187769Sluigi clstr_rctblsz = round_clstr(clstr_rcblks * 8) >> clstr_log2sz; 162204591Sluigi } while (n < (clstr_rcblks + clstr_rctblsz)); 163194930Soleg 164187769Sluigi /* 165187769Sluigi * We got all the sizes in clusters. Start the layout. 166187769Sluigi * 0 - header 167187769Sluigi * 1 - L1 table 168204591Sluigi * 2 - RC table (v2 only) 169187769Sluigi * 3 - L2 tables 170204591Sluigi * 4 - RC block (v2 only) 171204591Sluigi * 5 - data 172204591Sluigi */ 173204591Sluigi 174204591Sluigi l1clno = 1; 175187769Sluigi rcclno = 0; 176187769Sluigi rctbl = l2tbl = l1tbl = NULL; 177187769Sluigi rcblk = NULL; 178187769Sluigi 179187769Sluigi hdr = calloc(1, clstrsz); 180187769Sluigi if (hdr == NULL) 181187769Sluigi return (errno); 182187769Sluigi 183187769Sluigi be32enc(&hdr->magic, QCOW_MAGIC); 184187769Sluigi be32enc(&hdr->version, version); 185187769Sluigi be64enc(&hdr->disk_size, imagesz); 186187769Sluigi switch (version) { 187187769Sluigi case QCOW_VERSION_1: 188187769Sluigi ofsflags = 0; 189187769Sluigi l2clno = l1clno + clstr_l1tblsz; 190187769Sluigi hdr->u.v1.clstr_log2sz = clstr_log2sz; 191187769Sluigi hdr->u.v1.l2_log2sz = clstr_log2sz - 3; 192187769Sluigi be64enc(&hdr->u.v1.l1_offset, clstrsz * l1clno); 193187769Sluigi break; 194187769Sluigi case QCOW_VERSION_2: 195187769Sluigi ofsflags = QCOW_CLSTR_COPIED; 196187769Sluigi rcclno = l1clno + clstr_l1tblsz; 197187769Sluigi l2clno = rcclno + clstr_rctblsz; 198187769Sluigi be32enc(&hdr->clstr_log2sz, clstr_log2sz); 199187769Sluigi be32enc(&hdr->u.v2.l1_entries, clstr_l2tbls); 200187769Sluigi be64enc(&hdr->u.v2.l1_offset, clstrsz * l1clno); 201200567Sluigi be64enc(&hdr->u.v2.refcnt_offset, clstrsz * rcclno); 202215179Sluigi refcnt_clstrs = round_clstr(clstr_rcblks * 8) >> clstr_log2sz; 203187769Sluigi be32enc(&hdr->u.v2.refcnt_clstrs, refcnt_clstrs); 204187767Sluigi break; 205187767Sluigi default: 206187767Sluigi return (EDOOFUS); 207187767Sluigi } 208204591Sluigi 209204591Sluigi if (sparse_write(fd, hdr, clstrsz) < 0) { 210187767Sluigi error = errno; 211206843Sluigi goto out; 212187787Sluigi } 213187767Sluigi 214187767Sluigi free(hdr); 215187767Sluigi hdr = NULL; 216187767Sluigi 217187770Sluigi ofs = clstrsz * l2clno; 218187767Sluigi nclstrs = 1 + clstr_l1tblsz + clstr_rctblsz; 219187769Sluigi 220187767Sluigi l1tbl = calloc(1, clstrsz * clstr_l1tblsz); 221187770Sluigi if (l1tbl == NULL) { 222187769Sluigi error = ENOMEM; 223187770Sluigi goto out; 224187770Sluigi } 225187769Sluigi 226187769Sluigi for (n = 0; n < clstr_imgsz; n++) { 227187769Sluigi blk = n * blk_clstrsz; 228187769Sluigi if (image_data(blk, blk_clstrsz)) { 229187770Sluigi nclstrs++; 230187769Sluigi l1idx = n >> (clstr_log2sz - 3); 231187819Sluigi if (l1tbl[l1idx] == 0) { 232187819Sluigi be64enc(l1tbl + l1idx, ofs + ofsflags); 233187819Sluigi ofs += clstrsz; 234187819Sluigi nclstrs++; 235187819Sluigi } 236187819Sluigi } 237187819Sluigi } 238187819Sluigi 239187819Sluigi if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) { 240187983Sluigi error = errno; 241187819Sluigi goto out; 242187819Sluigi } 243187819Sluigi 244187769Sluigi clstr_rcblks = 0; 245187767Sluigi do { 246187767Sluigi n = clstr_rcblks; 247187767Sluigi clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz; 248187767Sluigi } while (n < clstr_rcblks); 249187767Sluigi 250187767Sluigi if (rcclno > 0) { 251187767Sluigi rctbl = calloc(1, clstrsz * clstr_rctblsz); 252187770Sluigi if (rctbl == NULL) { 253204591Sluigi error = ENOMEM; 254187767Sluigi goto out; 255187767Sluigi } 256187767Sluigi for (n = 0; n < clstr_rcblks; n++) { 257204591Sluigi be64enc(rctbl + n, ofs); 258187767Sluigi ofs += clstrsz; 259204591Sluigi nclstrs++; 260204591Sluigi } 261187767Sluigi if (sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) { 262187767Sluigi error = errno; 263187767Sluigi goto out; 264187767Sluigi } 265187983Sluigi free(rctbl); 266187983Sluigi rctbl = NULL; 267187983Sluigi } 268187983Sluigi 269187983Sluigi l2tbl = malloc(clstrsz); 270187983Sluigi if (l2tbl == NULL) { 271187770Sluigi error = ENOMEM; 272204591Sluigi goto out; 273204591Sluigi } 274187769Sluigi 275187769Sluigi for (l1idx = 0; l1idx < clstr_l2tbls; l1idx++) { 276187770Sluigi if (l1tbl[l1idx] == 0) 277187770Sluigi continue; 278187819Sluigi memset(l2tbl, 0, clstrsz); 279187819Sluigi blkofs = (lba_t)l1idx * blk_clstrsz * (clstrsz >> 3); 280187819Sluigi for (l2idx = 0; l2idx < (clstrsz >> 3); l2idx++) { 281187819Sluigi blk = blkofs + (lba_t)l2idx * blk_clstrsz; 282187770Sluigi if (blk >= blk_imgsz) 283187819Sluigi break; 284187819Sluigi if (image_data(blk, blk_clstrsz)) { 285187770Sluigi be64enc(l2tbl + l2idx, ofs + ofsflags); 286187819Sluigi ofs += clstrsz; 287187770Sluigi } 288187819Sluigi } 289187819Sluigi if (sparse_write(fd, l2tbl, clstrsz) < 0) { 290 error = errno; 291 goto out; 292 } 293 } 294 295 free(l2tbl); 296 l2tbl = NULL; 297 free(l1tbl); 298 l1tbl = NULL; 299 300 if (rcclno > 0) { 301 rcblk = calloc(1, clstrsz * clstr_rcblks); 302 if (rcblk == NULL) { 303 error = ENOMEM; 304 goto out; 305 } 306 for (n = 0; n < nclstrs; n++) 307 be16enc(rcblk + n, 1); 308 if (sparse_write(fd, rcblk, clstrsz * clstr_rcblks) < 0) { 309 error = errno; 310 goto out; 311 } 312 free(rcblk); 313 rcblk = NULL; 314 } 315 316 error = 0; 317 for (n = 0; n < clstr_imgsz; n++) { 318 blk = n * blk_clstrsz; 319 if (image_data(blk, blk_clstrsz)) { 320 error = image_copyout_region(fd, blk, blk_clstrsz); 321 if (error) 322 break; 323 } 324 } 325 if (!error) 326 error = image_copyout_done(fd); 327 328 out: 329 if (rcblk != NULL) 330 free(rcblk); 331 if (l2tbl != NULL) 332 free(l2tbl); 333 if (rctbl != NULL) 334 free(rctbl); 335 if (l1tbl != NULL) 336 free(l1tbl); 337 if (hdr != NULL) 338 free(hdr); 339 return (error); 340} 341 342static int 343qcow1_write(int fd) 344{ 345 346 return (qcow_write(fd, QCOW_VERSION_1)); 347} 348 349static int 350qcow2_write(int fd) 351{ 352 353 return (qcow_write(fd, QCOW_VERSION_2)); 354} 355 356static struct mkimg_format qcow1_format = { 357 .name = "qcow", 358 .description = "QEMU Copy-On-Write, version 1", 359 .resize = qcow1_resize, 360 .write = qcow1_write, 361}; 362FORMAT_DEFINE(qcow1_format); 363 364static struct mkimg_format qcow2_format = { 365 .name = "qcow2", 366 .description = "QEMU Copy-On-Write, version 2", 367 .resize = qcow2_resize, 368 .write = qcow2_write, 369}; 370FORMAT_DEFINE(qcow2_format); 371