/*
 * 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)
{
    BDRVVPCState *s = bs->opaque;
    int fd, i;
    struct vpc_subheader header;

    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
    if (fd < 0) {
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
        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,
};
