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