186835cedSPrasad Joshi #include "kvm/qcow.h" 286835cedSPrasad Joshi 386835cedSPrasad Joshi #include "kvm/disk-image.h" 486835cedSPrasad Joshi #include "kvm/read-write.h" 586835cedSPrasad Joshi #include "kvm/util.h" 686835cedSPrasad Joshi 786835cedSPrasad Joshi #include <sys/types.h> 886835cedSPrasad Joshi #include <sys/stat.h> 986835cedSPrasad Joshi #include <stdbool.h> 1086835cedSPrasad Joshi #include <stdlib.h> 1186835cedSPrasad Joshi #include <string.h> 1286835cedSPrasad Joshi #include <unistd.h> 1386835cedSPrasad Joshi #include <fcntl.h> 1486835cedSPrasad Joshi 1586835cedSPrasad Joshi #include <linux/byteorder.h> 1686835cedSPrasad Joshi #include <linux/types.h> 1786835cedSPrasad Joshi 18742fce76SPrasad Joshi static inline u64 get_l1_index(struct qcow *q, u64 offset) 1986835cedSPrasad Joshi { 2086835cedSPrasad Joshi struct qcow1_header *header = q->header; 2186835cedSPrasad Joshi 2286835cedSPrasad Joshi return offset >> (header->l2_bits + header->cluster_bits); 2386835cedSPrasad Joshi } 2486835cedSPrasad Joshi 25742fce76SPrasad Joshi static inline u64 get_l2_index(struct qcow *q, u64 offset) 2686835cedSPrasad Joshi { 2786835cedSPrasad Joshi struct qcow1_header *header = q->header; 2886835cedSPrasad Joshi 2986835cedSPrasad Joshi return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1); 3086835cedSPrasad Joshi } 3186835cedSPrasad Joshi 32742fce76SPrasad Joshi static inline u64 get_cluster_offset(struct qcow *q, u64 offset) 3386835cedSPrasad Joshi { 3486835cedSPrasad Joshi struct qcow1_header *header = q->header; 3586835cedSPrasad Joshi 3686835cedSPrasad Joshi return offset & ((1 << header->cluster_bits)-1); 3786835cedSPrasad Joshi } 3886835cedSPrasad Joshi 393dac48d4SPrasad Joshi static u32 qcow1_read_cluster(struct qcow *q, u64 offset, void *dst, 403dac48d4SPrasad Joshi u32 dst_len) 4186835cedSPrasad Joshi { 4286835cedSPrasad Joshi struct qcow1_header *header = q->header; 433dac48d4SPrasad Joshi struct qcow_table *table = &q->table; 44179b71f0SPekka Enberg u64 *l2_table = NULL; 45742fce76SPrasad Joshi u64 l2_table_offset; 46742fce76SPrasad Joshi u64 l2_table_size; 473dac48d4SPrasad Joshi u64 cluster_size; 48742fce76SPrasad Joshi u64 clust_offset; 49742fce76SPrasad Joshi u64 clust_start; 50742fce76SPrasad Joshi u64 l1_idx; 51742fce76SPrasad Joshi u64 l2_idx; 523dac48d4SPrasad Joshi u32 length; 5386835cedSPrasad Joshi 54*dae803fbSPekka Enberg cluster_size = 1 << header->cluster_bits; 5586835cedSPrasad Joshi 56c5e0624bSPrasad Joshi l1_idx = get_l1_index(q, offset); 573dac48d4SPrasad Joshi if (l1_idx >= table->table_size) 5886835cedSPrasad Joshi goto out_error; 5986835cedSPrasad Joshi 603dac48d4SPrasad Joshi clust_offset = get_cluster_offset(q, offset); 613dac48d4SPrasad Joshi if (clust_offset >= cluster_size) 623dac48d4SPrasad Joshi goto out_error; 633dac48d4SPrasad Joshi 643dac48d4SPrasad Joshi length = cluster_size - clust_offset; 653dac48d4SPrasad Joshi if (length > dst_len) 663dac48d4SPrasad Joshi length = dst_len; 673dac48d4SPrasad Joshi 683dac48d4SPrasad Joshi l2_table_offset = table->l1_table[l1_idx]; 6986835cedSPrasad Joshi if (!l2_table_offset) 703dac48d4SPrasad Joshi goto zero_cluster; 7186835cedSPrasad Joshi 7286835cedSPrasad Joshi l2_table_size = 1 << header->l2_bits; 73742fce76SPrasad Joshi l2_table = calloc(l2_table_size, sizeof(u64)); 7486835cedSPrasad Joshi if (!l2_table) 7586835cedSPrasad Joshi goto out_error; 7686835cedSPrasad Joshi 773dac48d4SPrasad Joshi if (pread_in_full(q->fd, l2_table, l2_table_size * sizeof(u64), 783dac48d4SPrasad Joshi l2_table_offset) < 0) 79b6edb0ecSSasha Levin goto out_error; 8086835cedSPrasad Joshi 81c5e0624bSPrasad Joshi l2_idx = get_l2_index(q, offset); 8286835cedSPrasad Joshi if (l2_idx >= l2_table_size) 83b6edb0ecSSasha Levin goto out_error; 8486835cedSPrasad Joshi 8586835cedSPrasad Joshi clust_start = be64_to_cpu(l2_table[l2_idx]); 8686835cedSPrasad Joshi if (!clust_start) 873dac48d4SPrasad Joshi goto zero_cluster; 8886835cedSPrasad Joshi 893dac48d4SPrasad Joshi if (pread_in_full(q->fd, dst, length, clust_start + clust_offset) < 0) 90b6edb0ecSSasha Levin goto out_error; 9186835cedSPrasad Joshi 92179b71f0SPekka Enberg out: 93179b71f0SPekka Enberg free(l2_table); 943dac48d4SPrasad Joshi return length; 9586835cedSPrasad Joshi 96179b71f0SPekka Enberg zero_cluster: 97179b71f0SPekka Enberg memset(dst, 0, length); 98179b71f0SPekka Enberg goto out; 99179b71f0SPekka Enberg 10086835cedSPrasad Joshi out_error: 101179b71f0SPekka Enberg length = -1; 102179b71f0SPekka Enberg goto out; 1033dac48d4SPrasad Joshi } 104b6edb0ecSSasha Levin 1053dac48d4SPrasad Joshi static int qcow1_read_sector(struct disk_image *self, uint64_t sector, 1063dac48d4SPrasad Joshi void *dst, uint32_t dst_len) 1073dac48d4SPrasad Joshi { 1083dac48d4SPrasad Joshi struct qcow *q = self->priv; 1093dac48d4SPrasad Joshi struct qcow1_header *header = q->header; 1103dac48d4SPrasad Joshi char *buf = dst; 1113dac48d4SPrasad Joshi u64 offset; 112d8eea993SPekka Enberg u32 nr_read; 1133dac48d4SPrasad Joshi u32 nr; 1143dac48d4SPrasad Joshi 115d8eea993SPekka Enberg nr_read = 0; 116d8eea993SPekka Enberg while (nr_read < dst_len) { 1173dac48d4SPrasad Joshi offset = sector << SECTOR_SHIFT; 1183dac48d4SPrasad Joshi if (offset >= header->size) 1193dac48d4SPrasad Joshi goto out_error; 1203dac48d4SPrasad Joshi 121d8eea993SPekka Enberg nr = qcow1_read_cluster(q, offset, buf, dst_len - nr_read); 1223dac48d4SPrasad Joshi if (!nr) 1233dac48d4SPrasad Joshi goto out_error; 1243dac48d4SPrasad Joshi 125d8eea993SPekka Enberg nr_read += nr; 1263dac48d4SPrasad Joshi buf += nr; 1273dac48d4SPrasad Joshi sector += (nr >> SECTOR_SHIFT); 1283dac48d4SPrasad Joshi } 1293dac48d4SPrasad Joshi return 0; 1303dac48d4SPrasad Joshi out_error: 13186835cedSPrasad Joshi return -1; 13286835cedSPrasad Joshi } 13386835cedSPrasad Joshi 13486835cedSPrasad Joshi static int qcow1_write_sector(struct disk_image *self, uint64_t sector, void *src, uint32_t src_len) 13586835cedSPrasad Joshi { 13686835cedSPrasad Joshi return -1; 13786835cedSPrasad Joshi } 13886835cedSPrasad Joshi 13986835cedSPrasad Joshi static void qcow1_disk_close(struct disk_image *self) 14086835cedSPrasad Joshi { 14186835cedSPrasad Joshi struct qcow *q; 14286835cedSPrasad Joshi 14386835cedSPrasad Joshi if (!self) 14486835cedSPrasad Joshi return; 14586835cedSPrasad Joshi 14686835cedSPrasad Joshi q = self->priv; 14786835cedSPrasad Joshi 1486c6f79b6SPrasad Joshi free(q->table.l1_table); 14986835cedSPrasad Joshi free(q->header); 15086835cedSPrasad Joshi free(q); 15186835cedSPrasad Joshi } 15286835cedSPrasad Joshi 15386835cedSPrasad Joshi struct disk_image_operations qcow1_disk_ops = { 15486835cedSPrasad Joshi .read_sector = qcow1_read_sector, 15586835cedSPrasad Joshi .write_sector = qcow1_write_sector, 15686835cedSPrasad Joshi .close = qcow1_disk_close 15786835cedSPrasad Joshi }; 15886835cedSPrasad Joshi 15986835cedSPrasad Joshi static int qcow_read_l1_table(struct qcow *q) 16086835cedSPrasad Joshi { 16186835cedSPrasad Joshi struct qcow1_header *header = q->header; 16200adcc1bSPrasad Joshi struct qcow_table *table = &q->table; 16300adcc1bSPrasad Joshi u64 i; 16486835cedSPrasad Joshi 16500adcc1bSPrasad Joshi table->table_size = header->size / ((1 << header->l2_bits) * 16600adcc1bSPrasad Joshi (1 << header->cluster_bits)); 16786835cedSPrasad Joshi 16800adcc1bSPrasad Joshi table->l1_table = calloc(table->table_size, sizeof(u64)); 16900adcc1bSPrasad Joshi if (!table->l1_table) 17086835cedSPrasad Joshi return -1; 17186835cedSPrasad Joshi 17200adcc1bSPrasad Joshi if (pread_in_full(q->fd, table->l1_table, sizeof(u64) * 17300adcc1bSPrasad Joshi table->table_size, header->l1_table_offset) < 0) 17486835cedSPrasad Joshi return -1; 17586835cedSPrasad Joshi 17600adcc1bSPrasad Joshi for (i = 0; i < table->table_size; i++) 17700adcc1bSPrasad Joshi be64_to_cpus(&table->l1_table[i]); 17800adcc1bSPrasad Joshi 17986835cedSPrasad Joshi return 0; 18086835cedSPrasad Joshi } 18186835cedSPrasad Joshi 18286835cedSPrasad Joshi static void *qcow1_read_header(int fd) 18386835cedSPrasad Joshi { 18486835cedSPrasad Joshi struct qcow1_header *header; 18586835cedSPrasad Joshi 18686835cedSPrasad Joshi header = malloc(sizeof(struct qcow1_header)); 18786835cedSPrasad Joshi if (!header) 18886835cedSPrasad Joshi return NULL; 18986835cedSPrasad Joshi 19086835cedSPrasad Joshi if (pread_in_full(fd, header, sizeof(struct qcow1_header), 0) < 0) 19186835cedSPrasad Joshi return NULL; 19286835cedSPrasad Joshi 19386835cedSPrasad Joshi be32_to_cpus(&header->magic); 19486835cedSPrasad Joshi be32_to_cpus(&header->version); 19586835cedSPrasad Joshi be64_to_cpus(&header->backing_file_offset); 19686835cedSPrasad Joshi be32_to_cpus(&header->backing_file_size); 19786835cedSPrasad Joshi be32_to_cpus(&header->mtime); 19886835cedSPrasad Joshi be64_to_cpus(&header->size); 19986835cedSPrasad Joshi be32_to_cpus(&header->crypt_method); 20086835cedSPrasad Joshi be64_to_cpus(&header->l1_table_offset); 20186835cedSPrasad Joshi 20286835cedSPrasad Joshi return header; 20386835cedSPrasad Joshi } 20486835cedSPrasad Joshi 20586835cedSPrasad Joshi static struct disk_image *qcow1_probe(int fd) 20686835cedSPrasad Joshi { 20786835cedSPrasad Joshi struct qcow *q; 20886835cedSPrasad Joshi struct qcow1_header *h; 20986835cedSPrasad Joshi struct disk_image *disk_image; 21086835cedSPrasad Joshi 21186835cedSPrasad Joshi q = calloc(1, sizeof(struct qcow)); 21286835cedSPrasad Joshi if (!q) 21386835cedSPrasad Joshi goto error; 21486835cedSPrasad Joshi 21586835cedSPrasad Joshi q->fd = fd; 21686835cedSPrasad Joshi 21786835cedSPrasad Joshi h = q->header = qcow1_read_header(fd); 21886835cedSPrasad Joshi if (!h) 21986835cedSPrasad Joshi goto error; 22086835cedSPrasad Joshi 22186835cedSPrasad Joshi if (qcow_read_l1_table(q) < 0) 22286835cedSPrasad Joshi goto error; 22386835cedSPrasad Joshi 22486835cedSPrasad Joshi disk_image = disk_image__new(fd, h->size, &qcow1_disk_ops); 22586835cedSPrasad Joshi if (!disk_image) 22686835cedSPrasad Joshi goto error; 22786835cedSPrasad Joshi disk_image->priv = q; 22886835cedSPrasad Joshi 22986835cedSPrasad Joshi return disk_image; 23086835cedSPrasad Joshi error: 23186835cedSPrasad Joshi if (!q) 23286835cedSPrasad Joshi return NULL; 23386835cedSPrasad Joshi 2346c6f79b6SPrasad Joshi free(q->table.l1_table); 23586835cedSPrasad Joshi free(q->header); 23686835cedSPrasad Joshi free(q); 23786835cedSPrasad Joshi 23886835cedSPrasad Joshi return NULL; 23986835cedSPrasad Joshi } 24086835cedSPrasad Joshi 24186835cedSPrasad Joshi static int qcow_check_image(int fd) 24286835cedSPrasad Joshi { 24386835cedSPrasad Joshi struct qcow1_header header; 24486835cedSPrasad Joshi 24586835cedSPrasad Joshi if (pread_in_full(fd, &header, sizeof(struct qcow1_header), 0) < 0) 24686835cedSPrasad Joshi return -1; 24786835cedSPrasad Joshi 24886835cedSPrasad Joshi be32_to_cpus(&header.magic); 24986835cedSPrasad Joshi be32_to_cpus(&header.version); 25086835cedSPrasad Joshi 25186835cedSPrasad Joshi if (header.magic != QCOW_MAGIC) 25286835cedSPrasad Joshi return -1; 25386835cedSPrasad Joshi 25486835cedSPrasad Joshi if (header.version != QCOW1_VERSION) 25586835cedSPrasad Joshi return -1; 25686835cedSPrasad Joshi 25786835cedSPrasad Joshi return 0; 25886835cedSPrasad Joshi } 25986835cedSPrasad Joshi 26086835cedSPrasad Joshi struct disk_image *qcow_probe(int fd) 26186835cedSPrasad Joshi { 26286835cedSPrasad Joshi if (qcow_check_image(fd) < 0) 26386835cedSPrasad Joshi return NULL; 26486835cedSPrasad Joshi 26586835cedSPrasad Joshi return qcow1_probe(fd); 26686835cedSPrasad Joshi } 267