new disk image layer

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1037 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard
2004-08-01 21:59:26 +00:00
parent e4d4fe3c34
commit ea2384d36e
7 changed files with 2381 additions and 419 deletions
+263
View File
@@ -0,0 +1,263 @@
/*
* Block driver for the COW format
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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.
*/
#ifndef _WIN32
#include "vl.h"
#include "block_int.h"
#include <sys/mman.h>
/**************************************************************/
/* COW block driver using file system holes */
/* user mode linux compatible COW file */
#define COW_MAGIC 0x4f4f4f4d /* MOOO */
#define COW_VERSION 2
struct cow_header_v2 {
uint32_t magic;
uint32_t version;
char backing_file[1024];
int32_t mtime;
uint64_t size;
uint32_t sectorsize;
};
typedef struct BDRVCowState {
int fd;
uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
int cow_bitmap_size;
int64_t cow_sectors_offset;
} BDRVCowState;
static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const struct cow_header_v2 *cow_header = (const void *)buf;
if (be32_to_cpu(cow_header->magic) == COW_MAGIC &&
be32_to_cpu(cow_header->version) == COW_VERSION)
return 100;
else
return 0;
}
static int cow_open(BlockDriverState *bs, const char *filename)
{
BDRVCowState *s = bs->opaque;
int fd;
struct cow_header_v2 cow_header;
int64_t size;
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;
}
s->fd = fd;
/* see if it is a cow image */
if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
goto fail;
}
if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
be32_to_cpu(cow_header.version) != COW_VERSION) {
goto fail;
}
/* cow image found */
size = be64_to_cpu(cow_header.size);
bs->total_sectors = size / 512;
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
cow_header.backing_file);
#if 0
if (cow_header.backing_file[0] != '\0') {
if (stat(cow_header.backing_file, &st) != 0) {
fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
goto fail;
}
if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
goto fail;
}
fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
if (fd < 0)
goto fail;
bs->fd = fd;
}
#endif
/* mmap the bitmap */
s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
s->cow_bitmap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, s->fd, 0);
if (s->cow_bitmap_addr == MAP_FAILED)
goto fail;
s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
return 0;
fail:
close(fd);
return -1;
}
static inline void set_bit(uint8_t *bitmap, int64_t bitnum)
{
bitmap[bitnum / 8] |= (1 << (bitnum%8));
}
static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
{
return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
}
/* Return true if first block has been changed (ie. current version is
* in COW file). Set the number of continuous blocks for which that
* is true. */
static inline int is_changed(uint8_t *bitmap,
int64_t sector_num, int nb_sectors,
int *num_same)
{
int changed;
if (!bitmap || nb_sectors == 0) {
*num_same = nb_sectors;
return 0;
}
changed = is_bit_set(bitmap, sector_num);
for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
if (is_bit_set(bitmap, sector_num + *num_same) != changed)
break;
}
return changed;
}
static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVCowState *s = bs->opaque;
return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
}
static int cow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, n;
while (nb_sectors > 0) {
if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
lseek64(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
} else {
memset(buf, 0, n * 512);
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int cow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, i;
lseek64(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = write(s->fd, buf, nb_sectors * 512);
if (ret != nb_sectors * 512)
return -1;
for (i = 0; i < nb_sectors; i++)
set_bit(s->cow_bitmap, sector_num + i);
return 0;
}
static int cow_close(BlockDriverState *bs)
{
BDRVCowState *s = bs->opaque;
munmap(s->cow_bitmap_addr, s->cow_bitmap_size);
close(s->fd);
}
static int cow_create(const char *filename, int64_t image_sectors,
const char *image_filename, int flags)
{
int fd, cow_fd;
struct cow_header_v2 cow_header;
struct stat st;
if (flags)
return -ENOTSUP;
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (cow_fd < 0)
return -1;
memset(&cow_header, 0, sizeof(cow_header));
cow_header.magic = cpu_to_be32(COW_MAGIC);
cow_header.version = cpu_to_be32(COW_VERSION);
if (image_filename) {
fd = open(image_filename, O_RDONLY | O_BINARY);
if (fd < 0) {
close(cow_fd);
return -1;
}
if (fstat(fd, &st) != 0) {
close(fd);
return -1;
}
close(fd);
cow_header.mtime = cpu_to_be32(st.st_mtime);
realpath(image_filename, cow_header.backing_file);
}
cow_header.sectorsize = cpu_to_be32(512);
cow_header.size = cpu_to_be64(image_sectors * 512);
write(cow_fd, &cow_header, sizeof(cow_header));
/* resize to include at least all the bitmap */
ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
close(cow_fd);
return 0;
}
BlockDriver bdrv_cow = {
"cow",
sizeof(BDRVCowState),
cow_probe,
cow_open,
cow_read,
cow_write,
cow_close,
cow_create,
cow_is_allocated,
};
#endif
+677
View File
File diff suppressed because it is too large Load Diff
+278
View File
@@ -0,0 +1,278 @@
/*
* Block driver for the VMDK format
*
* Copyright (c) 2004 Fabrice Bellard
*
* 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"
/* XXX: this code is untested */
/* XXX: add write support */
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
typedef struct {
uint32_t version;
uint32_t flags;
uint32_t disk_sectors;
uint32_t granularity;
uint32_t l1dir_offset;
uint32_t l1dir_size;
uint32_t file_sectors;
uint32_t cylinders;
uint32_t heads;
uint32_t sectors_per_track;
} VMDK3Header;
typedef struct {
uint32_t version;
uint32_t flags;
int64_t capacity;
int64_t granularity;
int64_t desc_offset;
int64_t desc_size;
int32_t num_gtes_per_gte;
int64_t rgd_offset;
int64_t gd_offset;
int64_t grain_offset;
char filler[1];
char check_bytes[4];
} VMDK4Header;
#define L2_CACHE_SIZE 16
typedef struct BDRVVmdkState {
int fd;
int64_t l1_table_offset;
uint32_t *l1_table;
unsigned int l1_size;
uint32_t l1_entry_sectors;
unsigned int l2_size;
uint32_t *l2_cache;
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
uint32_t l2_cache_counts[L2_CACHE_SIZE];
unsigned int cluster_sectors;
} BDRVVmdkState;
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
{
uint32_t magic;
if (buf_size < 4)
return 0;
magic = be32_to_cpu(*(uint32_t *)buf);
if (magic == VMDK3_MAGIC ||
magic == VMDK4_MAGIC)
return 100;
else
return 0;
}
static int vmdk_open(BlockDriverState *bs, const char *filename)
{
BDRVVmdkState *s = bs->opaque;
int fd, i;
uint32_t magic;
int l1_size;
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
goto fail;
magic = le32_to_cpu(magic);
if (magic == VMDK3_MAGIC) {
VMDK3Header header;
if (read(fd, &header, sizeof(header)) !=
sizeof(header))
goto fail;
s->cluster_sectors = le32_to_cpu(header.granularity);
s->l2_size = 1 << 9;
s->l1_size = 1 << 6;
bs->total_sectors = le32_to_cpu(header.disk_sectors);
s->l1_table_offset = le32_to_cpu(header.l1dir_offset) * 512;
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
} else if (magic == VMDK4_MAGIC) {
VMDK4Header header;
if (read(fd, &header, sizeof(header)) != sizeof(header))
goto fail;
bs->total_sectors = le32_to_cpu(header.capacity);
s->cluster_sectors = le32_to_cpu(header.granularity);
s->l2_size = le32_to_cpu(header.num_gtes_per_gte);
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
if (s->l1_entry_sectors <= 0)
goto fail;
s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
/ s->l1_entry_sectors;
s->l1_table_offset = le64_to_cpu(header.rgd_offset) * 512;
} else {
goto fail;
}
/* read the L1 table */
l1_size = s->l1_size * sizeof(uint32_t);
s->l1_table = qemu_malloc(l1_size);
if (!s->l1_table)
goto fail;
if (read(s->fd, s->l1_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_table[i]);
}
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
if (!s->l2_cache)
goto fail;
s->fd = fd;
/* XXX: currently only read only */
bs->read_only = 1;
return 0;
fail:
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(fd);
return -1;
}
static uint64_t get_cluster_offset(BlockDriverState *bs,
uint64_t offset)
{
BDRVVmdkState *s = bs->opaque;
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
uint32_t min_count, *l2_table;
uint64_t cluster_offset;
l1_index = (offset >> 9) / s->l1_entry_sectors;
if (l1_index >= s->l1_size)
return 0;
l2_offset = s->l1_table[l1_index];
if (!l2_offset)
return 0;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (l2_offset == s->l2_cache_offsets[i]) {
/* increment the hit count */
if (++s->l2_cache_counts[i] == 0xffffffff) {
for(j = 0; j < L2_CACHE_SIZE; j++) {
s->l2_cache_counts[j] >>= 1;
}
}
l2_table = s->l2_cache + (i * s->l2_size);
goto found;
}
}
/* not found: load a new entry in the least used one */
min_index = 0;
min_count = 0xffffffff;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (s->l2_cache_counts[i] < min_count) {
min_count = s->l2_cache_counts[i];
min_index = i;
}
}
l2_table = s->l2_cache + (min_index * s->l2_size);
lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) !=
s->l2_size * sizeof(uint32_t))
return 0;
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
found:
l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
cluster_offset = le32_to_cpu(l2_table[l2_index]);
cluster_offset <<= 9;
return cluster_offset;
}
static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVVmdkState *s = bs->opaque;
int index_in_cluster, n;
uint64_t cluster_offset;
cluster_offset = get_cluster_offset(bs, sector_num << 9);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
*pnum = n;
return (cluster_offset != 0);
}
static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
memset(buf, 0, 512 * n);
} else {
lseek64(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
return -1;
}
static int vmdk_close(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(s->fd);
}
BlockDriver bdrv_vmdk = {
"vmdk",
sizeof(BDRVVmdkState),
vmdk_probe,
vmdk_open,
vmdk_read,
vmdk_write,
vmdk_close,
NULL, /* no create yet */
vmdk_is_allocated,
};
+350 -271
View File
File diff suppressed because it is too large Load Diff
+77
View File
@@ -0,0 +1,77 @@
/*
* QEMU System Emulator block driver
*
* Copyright (c) 2003 Fabrice Bellard
*
* 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.
*/
#ifndef BLOCK_INT_H
#define BLOCK_INT_H
struct BlockDriver {
const char *format_name;
int instance_size;
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
int (*bdrv_open)(BlockDriverState *bs, const char *filename);
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
int (*bdrv_close)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, int64_t total_sectors,
const char *backing_file, int flags);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
struct BlockDriver *next;
};
struct BlockDriverState {
int64_t total_sectors;
int read_only; /* if true, the media is read only */
int inserted; /* if true, the media is present */
int removable; /* if true, the media can be removed */
int locked; /* if true, the media cannot temporarily be ejected */
int encrypted; /* if true, the media is encrypted */
/* event callback when inserting/removing */
void (*change_cb)(void *opaque);
void *change_opaque;
BlockDriver *drv;
void *opaque;
int boot_sector_enabled;
uint8_t boot_sector_data[512];
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
int is_temporary;
BlockDriverState *backing_hd;
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs;
int type;
char device_name[32];
BlockDriverState *next;
};
#endif /* BLOCK_INT_H */
+677
View File
File diff suppressed because it is too large Load Diff
+59 -148
View File
@@ -48,8 +48,21 @@
#define lseek64 _lseeki64
#endif
#ifdef QEMU_TOOL
/* we use QEMU_TOOL in the command line tools which do not depend on
the target CPU type */
#include "config-host.h"
#include <setjmp.h>
#include "osdep.h"
#include "bswap.h"
#else
#include "cpu.h"
#endif /* !defined(QEMU_TOOL) */
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
@@ -57,153 +70,6 @@
#define tostring(s) #s
#endif
#if defined(WORDS_BIGENDIAN)
static inline uint32_t be32_to_cpu(uint32_t v)
{
return v;
}
static inline uint16_t be16_to_cpu(uint16_t v)
{
return v;
}
static inline uint32_t cpu_to_be32(uint32_t v)
{
return v;
}
static inline uint16_t cpu_to_be16(uint16_t v)
{
return v;
}
static inline uint32_t le32_to_cpu(uint32_t v)
{
return bswap32(v);
}
static inline uint16_t le16_to_cpu(uint16_t v)
{
return bswap16(v);
}
static inline uint32_t cpu_to_le32(uint32_t v)
{
return bswap32(v);
}
static inline uint16_t cpu_to_le16(uint16_t v)
{
return bswap16(v);
}
#else
static inline uint32_t be32_to_cpu(uint32_t v)
{
return bswap32(v);
}
static inline uint16_t be16_to_cpu(uint16_t v)
{
return bswap16(v);
}
static inline uint32_t cpu_to_be32(uint32_t v)
{
return bswap32(v);
}
static inline uint16_t cpu_to_be16(uint16_t v)
{
return bswap16(v);
}
static inline uint32_t le32_to_cpu(uint32_t v)
{
return v;
}
static inline uint16_t le16_to_cpu(uint16_t v)
{
return v;
}
static inline uint32_t cpu_to_le32(uint32_t v)
{
return v;
}
static inline uint16_t cpu_to_le16(uint16_t v)
{
return v;
}
#endif
static inline void cpu_to_le16w(uint16_t *p, uint16_t v)
{
*p = cpu_to_le16(v);
}
static inline void cpu_to_le32w(uint32_t *p, uint32_t v)
{
*p = cpu_to_le32(v);
}
static inline uint16_t le16_to_cpup(const uint16_t *p)
{
return le16_to_cpu(*p);
}
static inline uint32_t le32_to_cpup(const uint32_t *p)
{
return le32_to_cpu(*p);
}
/* unaligned versions (optimized for frequent unaligned accesses)*/
#if defined(__i386__) || defined(__powerpc__)
#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
#define le16_to_cpupu(p) le16_to_cpup(p)
#define le32_to_cpupu(p) le32_to_cpup(p)
#else
static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
}
static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
p1[2] = v >> 16;
p1[3] = v >> 24;
}
static inline uint16_t le16_to_cpupu(const uint16_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8);
}
static inline uint32_t le32_to_cpupu(const uint32_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
}
#endif
/* vl.c */
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
@@ -233,6 +99,8 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque);
void qemu_system_reset_request(void);
void qemu_system_shutdown_request(void);
void main_loop_wait(int timeout);
extern int audio_enabled;
extern int ram_size;
extern int bios_size;
@@ -301,6 +169,7 @@ void qemu_del_fd_read_handler(int fd);
/* character device */
#define CHR_EVENT_BREAK 0 /* serial break char */
#define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */
typedef void IOEventHandler(void *opaque, int event);
@@ -310,11 +179,13 @@ typedef struct CharDriverState {
IOCanRWHandler *fd_can_read,
IOReadHandler *fd_read, void *opaque);
IOEventHandler *chr_event;
IOEventHandler *chr_send_event;
void *opaque;
} CharDriverState;
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
void qemu_chr_send_event(CharDriverState *s, int event);
void qemu_chr_add_read_handler(CharDriverState *s,
IOCanRWHandler *fd_can_read,
IOReadHandler *fd_read, void *opaque);
@@ -464,10 +335,23 @@ void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
/* block.c */
typedef struct BlockDriverState BlockDriverState;
typedef struct BlockDriver BlockDriver;
extern BlockDriver bdrv_raw;
extern BlockDriver bdrv_cow;
extern BlockDriver bdrv_qcow;
extern BlockDriver bdrv_vmdk;
void bdrv_init(void);
BlockDriver *bdrv_find_format(const char *format_name);
int bdrv_create(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, int flags);
BlockDriverState *bdrv_new(const char *device_name);
void bdrv_delete(BlockDriverState *bs);
int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot);
int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
BlockDriver *drv);
void bdrv_close(BlockDriverState *bs);
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
@@ -494,11 +378,21 @@ int bdrv_is_locked(BlockDriverState *bs);
void bdrv_set_locked(BlockDriverState *bs, int locked);
void bdrv_set_change_cb(BlockDriverState *bs,
void (*change_cb)(void *opaque), void *opaque);
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
void bdrv_info(void);
BlockDriverState *bdrv_find(const char *name);
void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
int bdrv_is_encrypted(BlockDriverState *bs);
int bdrv_set_key(BlockDriverState *bs, const char *key);
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
void *opaque);
const char *bdrv_get_device_name(BlockDriverState *bs);
int qcow_get_cluster_size(BlockDriverState *bs);
int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf);
#ifndef QEMU_TOOL
/* ISA bus */
extern target_phys_addr_t isa_mem_base;
@@ -823,11 +717,28 @@ void adb_mouse_init(ADBBusState *bus);
extern ADBBusState adb_bus;
int cuda_init(openpic_t *openpic, int irq);
#endif /* defined(QEMU_TOOL) */
/* monitor.c */
void monitor_init(CharDriverState *hd, int show_banner);
void term_puts(const char *str);
void term_vprintf(const char *fmt, va_list ap);
void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
void term_flush(void);
void term_print_help(void);
void monitor_readline(const char *prompt, int is_password,
char *buf, int buf_size);
/* readline.c */
typedef void ReadLineFunc(void *opaque, const char *str);
extern int completion_index;
void add_completion(const char *str);
void readline_handle_byte(int ch);
void readline_find_completion(const char *cmdline);
const char *readline_get_history(unsigned int index);
void readline_start(const char *prompt, int is_password,
ReadLineFunc *readline_func, void *opaque);
/* gdbstub.c */