/*
 * Block driver for Conectix/Microsoft Virtual PC images
 * 
 * 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_SIZE 512

//#define CACHE

// always big-endian
struct vpc_subheader {
    char magic[8]; // "conectix" / "cxsparse"
    union {
	struct {
	    uint32_t unk1[2];
	    uint32_t unk2; // always zero?
	    uint32_t subheader_offset;
	    uint32_t unk3; // some size?
	    char creator[4]; // "vpc "
	    uint16_t major;
	    uint16_t minor;
	    char guest[4]; // "Wi2k"
	    uint32_t unk4[7];
	    uint8_t vnet_id[16]; // virtual network id, purpose unknown
	    // next 16 longs are used, but dunno the purpose
	    // next 6 longs unknown, following 7 long maybe a serial
	    char padding[HEADER_SIZE - 84];
	} main;
	struct {
	    uint32_t unk1[2]; // all bits set
	    uint32_t unk2; // always zero?
	    uint32_t pagetable_offset;
	    uint32_t unk3;
	    uint32_t pagetable_entries; // 32bit/entry
	    uint32_t pageentry_size; // 512*8*512
	    uint32_t nb_sectors;
	    char padding[HEADER_SIZE - 40];
	} sparse;
	char padding[HEADER_SIZE - 8];
    } type;
};

typedef struct BDRVVPCState {
    int fd;
    
    int pagetable_entries;
    uint32_t *pagetable;

    uint32_t pageentry_size;
#ifdef CACHE
    uint8_t *pageentry_u8;
    uint32_t *pageentry_u32;
    uint16_t *pageentry_u16;
    
    uint64_t last_bitmap;
#endif
} BDRVVPCState;

static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
{
    if (buf_size >= 8 && !strncmp(buf, "conectix", 8))
	return 100;
    return 0;
}

static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
{
    BDRVVPCState *s = bs->opaque;
    int fd, i;
    struct vpc_subheader header;

    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, &header, HEADER_SIZE) != HEADER_SIZE)
        goto fail;

    if (strncmp(header.magic, "conectix", 8))
        goto fail;
    lseek(s->fd, be32_to_cpu(header.type.main.subheader_offset), SEEK_SET);

    if (read(fd, &header, HEADER_SIZE) != HEADER_SIZE)
        goto fail;

    if (strncmp(header.magic, "cxsparse", 8))
	goto fail;

    bs->total_sectors = ((uint64_t)be32_to_cpu(header.type.sparse.pagetable_entries) *
			be32_to_cpu(header.type.sparse.pageentry_size)) / 512;

    lseek(s->fd, be32_to_cpu(header.type.sparse.pagetable_offset), SEEK_SET);

    s->pagetable_entries = be32_to_cpu(header.type.sparse.pagetable_entries);
    s->pagetable = qemu_malloc(s->pagetable_entries * 4);
    if (!s->pagetable)
	goto fail;
    if (read(s->fd, s->pagetable, s->pagetable_entries * 4) !=
	s->pagetable_entries * 4)
	goto fail;
    for (i = 0; i < s->pagetable_entries; i++)
	be32_to_cpus(&s->pagetable[i]);

    s->pageentry_size = be32_to_cpu(header.type.sparse.pageentry_size);
#ifdef CACHE
    s->pageentry_u8 = qemu_malloc(512);
    if (!s->pageentry_u8)
	goto fail;
    s->pageentry_u32 = s->pageentry_u8;
    s->pageentry_u16 = s->pageentry_u8;
    s->last_pagetable = -1;
#endif

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

static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
{
    BDRVVPCState *s = bs->opaque;
    uint64_t offset = sector_num * 512;
    uint64_t bitmap_offset, block_offset;
    uint32_t pagetable_index, pageentry_index;

    pagetable_index = offset / s->pageentry_size;
    pageentry_index = (offset % s->pageentry_size) / 512;
    
    if (pagetable_index > s->pagetable_entries || s->pagetable[pagetable_index] == 0xffffffff)
	return -1; // not allocated

    bitmap_offset = 512 * s->pagetable[pagetable_index];
    block_offset = bitmap_offset + 512 + (512 * pageentry_index);
    
//    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
//	sector_num, pagetable_index, pageentry_index,
//	bitmap_offset, block_offset);

// disabled by reason
#if 0
#ifdef CACHE
    if (bitmap_offset != s->last_bitmap)
    {
	lseek(s->fd, bitmap_offset, SEEK_SET);

	s->last_bitmap = bitmap_offset;
	
	// Scary! Bitmap is stored as big endian 32bit entries,
	// while we used to look it up byte by byte
	read(s->fd, s->pageentry_u8, 512);
	for (i = 0; i < 128; i++)
	    be32_to_cpus(&s->pageentry_u32[i]);
    }

    if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1)
	return -1;
#else
    lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);
	
    read(s->fd, &bitmap_entry, 1);

    if ((bitmap_entry >> (pageentry_index % 8)) & 1)
	return -1; // not allocated
#endif
#endif
    lseek(s->fd, block_offset, SEEK_SET);

    return 0;
}

static int vpc_read(BlockDriverState *bs, int64_t sector_num, 
                    uint8_t *buf, int nb_sectors)
{
    BDRVVPCState *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 vpc_close(BlockDriverState *bs)
{
    BDRVVPCState *s = bs->opaque;
    qemu_free(s->pagetable);
#ifdef CACHE
    qemu_free(s->pageentry_u8);
#endif
    close(s->fd);
}

BlockDriver bdrv_vpc = {
    "vpc",
    sizeof(BDRVVPCState),
    vpc_probe,
    vpc_open,
    vpc_read,
    NULL,
    vpc_close,
};
