/*
 * Block driver for the various disk image formats used by Bochs
 * Currently only for "growing" type in read-only mode
 * 
 * Copyright (c) 2005 Alex Beregszaszi
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "vl.h"
#include "block_int.h"

/**************************************************************/

#define HEADER_MAGIC "Bochs Virtual HD Image"
#define HEADER_VERSION 0x00010000
#define HEADER_SIZE 512

#define REDOLOG_TYPE "Redolog"
#define GROWING_TYPE "Growing"

// not allocated: 0xffffffff

// always little-endian
struct bochs_header {
    char magic[32]; // "Bochs Virtual HD Image"
    char type[16]; // "Redolog"
    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
    uint32_t version;
    uint32_t header; // size of header
    
    union {
	struct {
	    uint32_t catalog; // num of entries
	    uint32_t bitmap; // bitmap size
	    uint32_t extent; // extent size
	    uint64_t disk; // disk size
	    char padding[HEADER_SIZE - 64 - 8 - 20];
	} redolog;
	char padding[HEADER_SIZE - 64 - 8];
    } extra;
};

typedef struct BDRVBochsState {
    int fd;

    uint32_t *catalog_bitmap;
    int catalog_size;
    
    int data_offset;
    
    int bitmap_blocks;
    int extent_blocks;
    int extent_size;
} BDRVBochsState;

static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
{
    const struct bochs_header *bochs = (const void *)buf;
    
    if (buf_size < HEADER_SIZE)
	return 0;

    if (!strcmp(bochs->magic, HEADER_MAGIC) &&
	!strcmp(bochs->type, REDOLOG_TYPE) &&
	!strcmp(bochs->subtype, GROWING_TYPE) &&
	(le32_to_cpu(bochs->version) == HEADER_VERSION))
	return 100;

    return 0;
}

static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
{
    BDRVBochsState *s = bs->opaque;
    int fd, i;
    struct bochs_header bochs;

    fd = open(filename, O_RDWR | O_BINARY);
    if (fd < 0) {
        fd = open(filename, O_RDONLY | O_BINARY);
        if (fd < 0)
            return -1;
    }
    
    bs->read_only = 1; // no write support yet
    
    s->fd = fd;

    if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
        goto fail;
    }

    if (strcmp(bochs.magic, HEADER_MAGIC) ||
        strcmp(bochs.type, REDOLOG_TYPE) ||
        strcmp(bochs.subtype, GROWING_TYPE) ||
	(le32_to_cpu(bochs.version) != HEADER_VERSION)) {
        goto fail;
    }

    bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;

    lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);

    s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
    s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
    if (!s->catalog_bitmap)
	goto fail;
    if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
	s->catalog_size * 4)
	goto fail;
    for (i = 0; i < s->catalog_size; i++)
	le32_to_cpus(&s->catalog_bitmap[i]);

    s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);

    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
    s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
    
    s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);

    return 0;
 fail:
    close(fd);
    return -1;
}

static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
{
    BDRVBochsState *s = bs->opaque;
    int64_t offset = sector_num * 512;
    int64_t extent_index, extent_offset, bitmap_offset, block_offset;
    char bitmap_entry;

    // seek to sector
    extent_index = offset / s->extent_size;
    extent_offset = (offset % s->extent_size) / 512;
    
    if (s->catalog_bitmap[extent_index] == 0xffffffff)
    {
//	fprintf(stderr, "page not allocated [%x - %x:%x]\n",
//	    sector_num, extent_index, extent_offset);
	return -1; // not allocated
    }

    bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
	(s->extent_blocks + s->bitmap_blocks));
    block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
    
//    fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
//	sector_num, extent_index, extent_offset,
//	le32_to_cpu(s->catalog_bitmap[extent_index]),
//	bitmap_offset, block_offset);
    
    // read in bitmap for current extent
    lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET);
    
    read(s->fd, &bitmap_entry, 1);
    
    if (!((bitmap_entry >> (extent_offset % 8)) & 1))
    {
//	fprintf(stderr, "sector (%x) in bitmap not allocated\n",
//	    sector_num);
	return -1; // not allocated
    }

    lseek(s->fd, block_offset, SEEK_SET);
    
    return 0;
}

static int bochs_read(BlockDriverState *bs, int64_t sector_num, 
                    uint8_t *buf, int nb_sectors)
{
    BDRVBochsState *s = bs->opaque;
    int ret;

    while (nb_sectors > 0) {
	if (!seek_to_sector(bs, sector_num))
	{
	    ret = read(s->fd, buf, 512);
	    if (ret != 512)
		return -1;
	}
	else
            memset(buf, 0, 512);
        nb_sectors--;
        sector_num++;
        buf += 512;
    }
    return 0;
}

static void bochs_close(BlockDriverState *bs)
{
    BDRVBochsState *s = bs->opaque;
    qemu_free(s->catalog_bitmap);
    close(s->fd);
}

BlockDriver bdrv_bochs = {
    "bochs",
    sizeof(BDRVBochsState),
    bochs_probe,
    bochs_open,
    bochs_read,
    NULL,
    bochs_close,
};
