block.c revision 2c538c86c15d597cc875dc926e4e39285c5625df
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU System Emulator block driver
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2003 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "config-host.h"
252c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* include native header before sys-queue.h */
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/queue.h>
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h"
315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "monitor.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "block_int.h"
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "module.h"
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
352c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h>
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/stat.h>
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ioctl.h>
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef __DragonFly__
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/disk.h>
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <windows.h>
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SECTOR_BITS 9
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SECTOR_SIZE (1 << SECTOR_BITS)
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint8_t *buf, int nb_sectors);
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         const uint8_t *buf, int nb_sectors);
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverState *bdrv_first;
635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic BlockDriver *first_drv;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint _path_is_absolute(const char *path)
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* specific case for names like: "\\.\d:" */
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*path == '/' || *path == '\\')
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr(path, ':');
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p)
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p++;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = path;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/' || *p == '\\');
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/');
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if filename is absolute, just copy it to dest. Otherwise, build a
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   path to it by considering it is relative to base_path. URL are
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   supported. */
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid path_combine(char *dest, int dest_size,
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *base_path,
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *filename)
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p, *p1;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dest_size <= 0)
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (_path_is_absolute(filename)) {
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(dest, dest_size, filename);
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = strchr(base_path, ':');
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p)
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p++;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = base_path;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p1 = strrchr(base_path, '/');
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const char *p2;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p2 = strrchr(base_path, '\\');
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!p1 || p2 > p1)
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p1 = p2;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1)
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1++;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1 = base_path;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1 > p)
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = p1;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = p - base_path;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len > dest_size - 1)
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = dest_size - 1;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(dest, base_path, len);
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dest[len] = '\0';
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcat(dest, dest_size, filename);
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_register(BlockDriver *bdrv)
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv->bdrv_aio_readv) {
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add AIO emulation layer */
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!bdrv->bdrv_read) {
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add synchronous IO emulation layer */
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_read = bdrv_read_em;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_write = bdrv_write_em;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv->next = first_drv;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    first_drv = bdrv;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* create a new block device (by default it is empty) */
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriverState *bdrv_new(const char *device_name)
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState **pbs, *bs;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs = qemu_mallocz(sizeof(BlockDriverState));
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (device_name[0] != '\0') {
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* insert at the end */
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pbs = &bdrv_first;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*pbs != NULL)
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pbs = &(*pbs)->next;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pbs = bs;
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriver *bdrv_find_format(const char *format_name)
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!strcmp(drv1->format_name, format_name))
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return drv1;
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_create(BlockDriver *drv, const char* filename,
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUOptionParameter *options)
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_create)
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_create(filename, options);
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char temp_dir[MAX_PATH];
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempPath(MAX_PATH, temp_dir);
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempFileName(temp_dir, "qem", 0, filename);
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *tmpdir;
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: race condition possible */
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmpdir = getenv("TMPDIR");
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!tmpdir)
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmpdir = "/tmp";
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = mkstemp(filename);
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    close(fd);
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int is_windows_drive_prefix(const char *filename)
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            filename[1] == ':');
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint is_windows_drive(const char *filename)
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_windows_drive_prefix(filename) &&
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename[2] == '\0')
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strstart(filename, "\\\\.\\", NULL) ||
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strstart(filename, "//./", NULL))
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic BlockDriver *find_protocol(const char *filename)
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1;
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char protocol[128];
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p;
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_windows_drive(filename) ||
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_windows_drive_prefix(filename))
2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bdrv_find_format("raw");
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr(filename, ':');
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p)
2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bdrv_find_format("raw");
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = p - filename;
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > sizeof(protocol) - 1)
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = sizeof(protocol) - 1;
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy(protocol, filename, len);
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    protocol[len] = '\0';
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (drv1->protocol_name &&
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            !strcmp(drv1->protocol_name, protocol))
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return drv1;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Detect host devices. By convention, /dev/cdrom[N] is always
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * recognized as a host CDROM.
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriver *find_hdev_driver(const char *filename)
2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int score_max = 0, score;
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = NULL, *d;
2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (d = first_drv; d; d = d->next) {
2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (d->bdrv_probe_device) {
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            score = d->bdrv_probe_device(filename);
2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (score > score_max) {
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                score_max = score;
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv = d;
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv;
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic BlockDriver *find_image_format(const char *filename)
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, score, score_max;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1, *drv;
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t buf[2048];
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    drv = find_protocol(filename);
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* no need to test disk image formats for vvfat */
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (drv && strcmp(drv->format_name, "vvfat") == 0)
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return drv;
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_delete(bs);
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    score_max = 0;
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (drv1->bdrv_probe) {
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            score = drv1->bdrv_probe(buf, ret, filename);
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (score > score_max) {
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                score_max = score;
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                drv = drv1;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv;
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs = bdrv_new("");
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs);
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return ret;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs->growable = 1;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pbs = bs;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_open(BlockDriverState *bs, const char *filename, int flags)
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bdrv_open2(bs, filename, flags, NULL);
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               BlockDriver *drv)
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, open_flags;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char tmp_filename[PATH_MAX];
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char backing_filename[PATH_MAX];
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->read_only = 0;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->is_temporary = 0;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->encrypted = 0;
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs->valid_key = 0;
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* buffer_alignment defaulted to 512, drivers can change this value */
3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs->buffer_alignment = 512;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & BDRV_O_SNAPSHOT) {
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverState *bs1;
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int64_t total_size;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int is_protocol = 0;
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *bdrv_qcow2;
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        QEMUOptionParameter *options;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if snapshot, we create a temporary backing file and open it
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           instead of opening 'filename' directly */
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if there is a backing file, use it */
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs1 = bdrv_new("");
3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_open2(bs1, filename, 0, drv);
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs1);
3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs1->drv && bs1->drv->protocol_name)
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            is_protocol = 1;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs1);
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Real path is meaningless for protocols */
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_protocol)
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            snprintf(backing_filename, sizeof(backing_filename),
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     "%s", filename);
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            realpath(filename, backing_filename);
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_qcow2 = bdrv_find_format("qcow2");
3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);
3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (drv) {
3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv->format_name);
3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename = tmp_filename;
3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        drv = bdrv_qcow2;
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->is_temporary = 1;
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pstrcpy(bs->filename, sizeof(bs->filename), filename);
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & BDRV_O_FILE) {
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        drv = find_protocol(filename);
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!drv) {
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        drv = find_hdev_driver(filename);
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!drv) {
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            drv = find_image_format(filename);
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv) {
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = -ENOENT;
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto unlink_and_fail;
4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->drv = drv;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->opaque = qemu_mallocz(drv->instance_size);
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Note: for compatibility, we open disk image files as RDWR, and
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       RDONLY as fallback */
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(flags & BDRV_O_FILE))
4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        open_flags = BDRV_O_RDWR | (flags & BDRV_O_CACHE_MASK);
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = drv->bdrv_open(bs, filename, open_flags);
4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->read_only = 1;
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free(bs->opaque);
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->opaque = NULL;
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv = NULL;
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unlink_and_fail:
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->is_temporary)
4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            unlink(filename);
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return ret;
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv->bdrv_getlength) {
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef _WIN32
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->is_temporary) {
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unlink(filename);
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_file[0] != '\0') {
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if there is a backing file, use it */
4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *back_drv = NULL;
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->backing_hd = bdrv_new("");
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        path_combine(backing_filename, sizeof(backing_filename),
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     filename, bs->backing_file);
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->backing_format[0] != '\0')
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            back_drv = bdrv_find_format(bs->backing_format);
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         back_drv);
4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bdrv_close(bs);
4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv_key_required(bs)) {
4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* call the change callback */
4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->media_changed = 1;
4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->change_cb)
4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bs->change_cb(bs->change_opaque);
4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_close(BlockDriverState *bs)
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->drv) {
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->backing_hd)
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs->backing_hd);
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv->bdrv_close(bs);
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_free(bs->opaque);
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->is_temporary) {
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unlink(bs->filename);
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->opaque = NULL;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv = NULL;
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* call the change callback */
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->media_changed = 1;
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->change_cb)
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bs->change_cb(bs->change_opaque);
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_delete(BlockDriverState *bs)
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState **pbs;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pbs = &bdrv_first;
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*pbs != bs && *pbs != NULL)
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pbs = &(*pbs)->next;
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*pbs == bs)
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pbs = bs->next;
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_close(bs);
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_free(bs);
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Run consistency checks on an image
5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Returns the number of errors or -errno when an internal error occurs
5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_check(BlockDriverState *bs)
5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->drv->bdrv_check == NULL) {
5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bs->drv->bdrv_check(bs);
5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* commit COW file into the raw image */
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_commit(BlockDriverState *bs)
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t i, total_sectors;
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int n, j;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char sector[512];
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->read_only) {
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return -EACCES;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->backing_hd) {
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return -ENOTSUP;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < total_sectors;) {
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for(j = 0; j < n; j++) {
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (bdrv_read(bs, i, sector, 1) != 0) {
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return -EIO;
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return -EIO;
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i++;
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i += n;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv->bdrv_make_empty)
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return drv->bdrv_make_empty(bs);
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   size_t size)
5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int64_t len;
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv_is_inserted(bs))
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->growable)
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = bdrv_getlength(bs);
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (offset < 0)
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((offset > len) || (len - offset < size))
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              int nb_sectors)
5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return < 0 if error. See bdrv_write() for the return codes */
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_read(BlockDriverState *bs, int64_t sector_num,
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              uint8_t *buf, int nb_sectors)
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return < 0 if error. Important errors are:
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EIO         generic I/O error (may happen for all errors)
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -ENOMEDIUM   No media inserted.
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EINVAL      Invalid sector number or nb_sectors
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  -EACCES      Trying to write a read-only device
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_write(BlockDriverState *bs, int64_t sector_num,
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               const uint8_t *buf, int nb_sectors)
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv)
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->read_only)
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -EACCES;
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_pread(BlockDriverState *bs, int64_t offset,
6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               void *buf, int count1)
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t tmp_buf[SECTOR_SIZE];
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len, nb_sectors, count;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t sector_num;
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = count1;
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first read to align to sector start */
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > count)
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = count;
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sector_num = offset >> SECTOR_BITS;
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > 0) {
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count == 0)
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return count1;
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num++;
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* read the sectors "in place" */
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nb_sectors = count >> SECTOR_BITS;
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_sectors > 0) {
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num += nb_sectors;
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = nb_sectors << SECTOR_BITS;
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* add data from the last sector */
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count > 0) {
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(buf, tmp_buf, count);
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count1;
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_pwrite(BlockDriverState *bs, int64_t offset,
6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const void *buf, int count1)
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t tmp_buf[SECTOR_SIZE];
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len, nb_sectors, count;
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t sector_num;
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = count1;
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first write to align to sector start */
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > count)
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = count;
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sector_num = offset >> SECTOR_BITS;
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > 0) {
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count == 0)
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return count1;
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num++;
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* write the sectors "in place" */
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nb_sectors = count >> SECTOR_BITS;
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nb_sectors > 0) {
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sector_num += nb_sectors;
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = nb_sectors << SECTOR_BITS;
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf += len;
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        count -= len;
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* add data from the last sector */
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count > 0) {
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(tmp_buf, buf, count);
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -EIO;
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return count1;
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Truncate file to 'offset' bytes (needed only for file protocols)
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_truncate(BlockDriverState *bs, int64_t offset)
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_truncate)
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_truncate(bs, offset);
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Length of a file in bytes. Return < 0 if error or unknown.
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint64_t bdrv_getlength(BlockDriverState *bs)
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_getlength) {
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* legacy mode */
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return bs->total_sectors * SECTOR_SIZE;
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_getlength(bs);
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return 0 as number of sectors if no device present or error */
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t length;
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    length = bdrv_getlength(bs);
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (length < 0)
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        length = 0;
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        length = length >> SECTOR_BITS;
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *nb_sectors_ptr = length;
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct partition {
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t boot_ind;           /* 0x80 - active */
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t head;               /* starting head */
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t sector;             /* starting sector */
7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t cyl;                /* starting cylinder */
7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t sys_ind;            /* What partition type */
7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_head;           /* end head */
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_sector;         /* end sector */
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t end_cyl;            /* end cylinder */
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t start_sect;        /* starting sector counting from 0 */
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t nr_sects;          /* nr of sectors in partition */
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} __attribute__((packed));
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int guess_disk_lchs(BlockDriverState *bs,
7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           int *pcylinders, int *pheads, int *psectors)
7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[512];
7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret, i, heads, sectors, cylinders;
7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct partition *p;
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t nr_sects;
7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t nb_sectors;
7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry(bs, &nb_sectors);
7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bdrv_read(bs, 0, buf, 1);
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0)
7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* test msdos magic */
7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (buf[510] != 0x55 || buf[511] != 0xaa)
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < 4; i++) {
7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        p = ((struct partition *)(buf + 0x1be)) + i;
7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        nr_sects = le32_to_cpu(p->nr_sects);
7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (nr_sects && p->end_head) {
7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* We make the assumption that the partition terminates on
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner               a cylinder boundary */
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            heads = p->end_head + 1;
7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            sectors = p->end_sector & 63;
7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (sectors == 0)
7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cylinders = nb_sectors / (heads * sectors);
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (cylinders < 1 || cylinders > 16383)
7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pheads = heads;
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *psectors = sectors;
7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pcylinders = cylinders;
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            printf("guessed geometry: LCHS=%d %d %d\n",
8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   cylinders, heads, sectors);
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs)
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int translation, lba_detected = 0;
8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int cylinders, heads, secs;
8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t nb_sectors;
8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* if a geometry hint is available, use it */
8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry(bs, &nb_sectors);
8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs);
8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    translation = bdrv_get_translation_hint(bs);
8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (cylinders != 0) {
8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *pcyls = cylinders;
8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *pheads = heads;
8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *psecs = secs;
8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (heads > 16) {
8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* if heads > 16, it means that a BIOS LBA
8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   translation was active, so the default
8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   hardware geometry is OK */
8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                lba_detected = 1;
8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto default_geometry;
8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *pcyls = cylinders;
8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *pheads = heads;
8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *psecs = secs;
8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* disable any translation to be in sync with
8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   the logical geometry */
8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (translation == BIOS_ATA_TRANSLATION_AUTO) {
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_NONE);
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default_geometry:
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* if no geometry, use a standard physical disk geometry */
8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            cylinders = nb_sectors / (16 * 63);
8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (cylinders > 16383)
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                cylinders = 16383;
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            else if (cylinders < 2)
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                cylinders = 2;
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pcyls = cylinders;
8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pheads = 16;
8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *psecs = 63;
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if ((*pcyls * *pheads) <= 131072) {
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_LARGE);
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    bdrv_set_translation_hint(bs,
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                              BIOS_ATA_TRANSLATION_LBA);
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_geometry_hint(BlockDriverState *bs,
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int cyls, int heads, int secs)
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->cyls = cyls;
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->heads = heads;
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->secs = secs;
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_type_hint(BlockDriverState *bs, int type)
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->type = type;
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->removable = ((type == BDRV_TYPE_CDROM ||
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      type == BDRV_TYPE_FLOPPY));
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_translation_hint(BlockDriverState *bs, int translation)
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->translation = translation;
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_geometry_hint(BlockDriverState *bs,
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            int *pcyls, int *pheads, int *psecs)
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pcyls = bs->cyls;
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pheads = bs->heads;
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *psecs = bs->secs;
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_type_hint(BlockDriverState *bs)
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->type;
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_translation_hint(BlockDriverState *bs)
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->translation;
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_removable(BlockDriverState *bs)
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->removable;
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_read_only(BlockDriverState *bs)
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->read_only;
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_sg(BlockDriverState *bs)
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->sg;
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: no longer used */
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_change_cb(BlockDriverState *bs,
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        void (*change_cb)(void *opaque), void *opaque)
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->change_cb = change_cb;
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->change_opaque = opaque;
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_encrypted(BlockDriverState *bs)
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_hd && bs->backing_hd->encrypted)
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->encrypted;
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_key_required(BlockDriverState *bs)
9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *backing_hd = bs->backing_hd;
9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return (bs->encrypted && !bs->valid_key);
9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_set_key(BlockDriverState *bs, const char *key)
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_hd && bs->backing_hd->encrypted) {
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = bdrv_set_key(bs->backing_hd, key);
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0)
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return ret;
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!bs->encrypted)
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bs->drv->bdrv_set_key(bs, key);
9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0) {
9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->valid_key = 0;
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!bs->valid_key) {
9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->valid_key = 1;
9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* call the change callback now, we skipped it on open */
9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->media_changed = 1;
9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->change_cb)
9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bs->change_cb(bs->change_opaque);
9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv) {
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[0] = '\0';
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(buf, buf_size, bs->drv->format_name);
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_iterate_format(void (*it)(void *opaque, const char *name),
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         void *opaque)
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv;
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (drv = first_drv; drv != NULL; drv = drv->next) {
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        it(opaque, drv->format_name);
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriverState *bdrv_find(const char *name)
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!strcmp(name, bs->device_name))
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bs;
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        it(opaque, bs);
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char *bdrv_get_device_name(BlockDriverState *bs)
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->device_name;
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_flush(BlockDriverState *bs)
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs->drv)
10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->drv->bdrv_flush)
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv->bdrv_flush(bs);
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->backing_hd)
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_flush(bs->backing_hd);
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_flush_all(void)
10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs;
10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (bs = bdrv_first; bs != NULL; bs = bs->next)
10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->drv && !bdrv_is_read_only(bs) &&
10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (!bdrv_is_removable(bs) || bdrv_is_inserted(bs)))
10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bdrv_flush(bs);
10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Returns true iff the specified sector is present in the disk image. Drivers
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * not implementing the functionality are assumed to not support backing files,
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * hence all their sectors are reported as allocated.
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 'pnum' is set to the number of sectors (including and immediately following
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the specified sector) that are known to be in the same
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * allocated/unallocated state.
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 'nb_sectors' is the max value 'pnum' should be set to.
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int *pnum)
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t n;
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->drv->bdrv_is_allocated) {
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sector_num >= bs->total_sectors) {
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *pnum = 0;
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = bs->total_sectors - sector_num;
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_info(Monitor *mon)
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        monitor_printf(mon, "%s:", bs->device_name);
10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        monitor_printf(mon, " type=");
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(bs->type) {
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_HD:
10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, "hd");
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_CDROM:
10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, "cdrom");
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case BDRV_TYPE_FLOPPY:
10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, "floppy");
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        monitor_printf(mon, " removable=%d", bs->removable);
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->removable) {
10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, " locked=%d", bs->locked);
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->drv) {
10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, " file=");
10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_print_filename(mon, bs->filename);
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (bs->backing_file[0] != '\0') {
10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                monitor_printf(mon, " backing_file=");
10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                monitor_print_filename(mon, bs->backing_file);
10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, " ro=%d", bs->read_only);
10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, " drv=%s", bs->drv->format_name);
10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, " encrypted=%d", bdrv_is_encrypted(bs));
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            monitor_printf(mon, " [not inserted]");
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        monitor_printf(mon, "\n");
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* The "info blockstats" command. */
11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_info_stats(Monitor *mon)
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        monitor_printf(mon, "%s:"
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       " rd_bytes=%" PRIu64
11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       " wr_bytes=%" PRIu64
11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       " rd_operations=%" PRIu64
11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       " wr_operations=%" PRIu64
11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       "\n",
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       bs->device_name,
11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       bs->rd_bytes, bs->wr_bytes,
11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       bs->rd_ops, bs->wr_ops);
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerconst char *bdrv_get_encrypted_filename(BlockDriverState *bs)
11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->backing_hd && bs->backing_hd->encrypted)
11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs->backing_file;
11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (bs->encrypted)
11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs->filename;
11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_get_backing_filename(BlockDriverState *bs,
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               char *filename, int filename_size)
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!bs->backing_hd) {
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(filename, filename_size, "");
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(filename, filename_size, bs->backing_file);
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          const uint8_t *buf, int nb_sectors)
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_write_compressed)
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_get_info)
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(bdi, 0, sizeof(*bdi));
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_get_info(bs, bdi);
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size)
11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv)
11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv->bdrv_put_buffer)
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_put_buffer(bs, buf, pos, size);
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size)
11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv)
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOMEDIUM;
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv->bdrv_get_buffer)
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_get_buffer(bs, buf, pos, size);
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* handling of snapshots */
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_create(BlockDriverState *bs,
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         QEMUSnapshotInfo *sn_info)
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_snapshot_create)
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_snapshot_create(bs, sn_info);
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_goto(BlockDriverState *bs,
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       const char *snapshot_id)
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_snapshot_goto)
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_snapshot_goto(bs, snapshot_id);
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_snapshot_delete)
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_snapshot_delete(bs, snapshot_id);
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_snapshot_list(BlockDriverState *bs,
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       QEMUSnapshotInfo **psn_info)
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_snapshot_list)
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return drv->bdrv_snapshot_list(bs, psn_info);
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NB_SUFFIXES 4
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar *get_human_readable_size(char *buf, int buf_size, int64_t size)
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char suffixes[NB_SUFFIXES] = "KMGT";
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t base;
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size <= 999) {
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size, "%" PRId64, size);
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        base = 1024;
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(i = 0; i < NB_SUFFIXES; i++) {
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size < (10 * base)) {
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                snprintf(buf, buf_size, "%0.1f%c",
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         (double)size / base,
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         suffixes[i]);
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                snprintf(buf, buf_size, "%" PRId64 "%c",
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         ((size + (base >> 1)) / base),
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         suffixes[i]);
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            base = base * 1024;
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char buf1[128], date_buf[128], clock_buf[128];
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm *ptm;
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tm tm;
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    time_t ti;
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int64_t secs;
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!sn) {
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size,
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%-10s%-20s%7s%20s%15s",
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ti = sn->date_sec;
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ptm = localtime(&ti);
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strftime(date_buf, sizeof(date_buf),
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%Y-%m-%d %H:%M:%S", ptm);
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        localtime_r(&ti, &tm);
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strftime(date_buf, sizeof(date_buf),
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%Y-%m-%d %H:%M:%S", &tm);
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        secs = sn->vm_clock_nsec / 1000000000;
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(clock_buf, sizeof(clock_buf),
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%02d:%02d:%02d.%03d",
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)(secs / 3600),
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)((secs / 60) % 60),
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)(secs % 60),
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(buf, buf_size,
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 "%-10s%-20s%7s%20s%15s",
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 sn->id_str, sn->name,
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 date_buf,
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 clock_buf);
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* async I/Os */
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
13055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 QEMUIOVector *qiov, int nb_sectors,
13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 BlockDriverCompletionFunc *cb, void *opaque)
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *ret;
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
13135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
13145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
13175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              cb, opaque);
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret) {
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update stats even though technically transfer has not happened. */
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	bs->rd_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	bs->rd_ops ++;
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  QEMUIOVector *qiov, int nb_sectors,
13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  BlockDriverCompletionFunc *cb, void *opaque)
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *ret;
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->read_only)
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
13395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_check_request(bs, sector_num, nb_sectors))
13405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               cb, opaque);
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret) {
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update stats even though technically transfer has not happened. */
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	bs->wr_bytes += (unsigned) nb_sectors * SECTOR_SIZE;
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	bs->wr_ops ++;
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_aio_cancel(BlockDriverAIOCB *acb)
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->pool->cancel(acb);
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* async block device emulation */
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct BlockDriverAIOCBSync {
13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverAIOCB common;
13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUBH *bh;
13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* vector translation state */
13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector *qiov;
13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *bounce;
13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int is_write;
13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} BlockDriverAIOCBSync;
13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
13745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
13765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_bh_delete(acb->bh);
13775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_aio_release(acb);
13785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic AIOPool bdrv_em_aio_pool = {
13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    .aiocb_size         = sizeof(BlockDriverAIOCBSync),
13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    .cancel             = bdrv_aio_cancel_em,
13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
13845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void bdrv_aio_bh_cb(void *opaque)
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCBSync *acb = opaque;
13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!acb->is_write)
13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_vfree(acb->bounce);
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->common.cb(acb->common.opaque, acb->ret);
13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_bh_delete(acb->bh);
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_aio_release(acb);
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int64_t sector_num,
13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            QEMUIOVector *qiov,
14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int nb_sectors,
14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            BlockDriverCompletionFunc *cb,
14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            void *opaque,
14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                            int is_write)
14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCBSync *acb;
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
14095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->is_write = is_write;
14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->qiov = qiov;
14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->bounce = qemu_blockalign(bs, qiov->size);
14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!acb->bh)
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_write) {
14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_iovec_to_buffer(acb->qiov, acb->bounce);
14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->ret = bdrv_write(bs, sector_num, acb->bounce, nb_sectors);
14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->ret = bdrv_read(bs, sector_num, acb->bounce, nb_sectors);
14215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_bh_schedule(acb->bh);
14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return &acb->common;
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque)
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sync block device emulation */
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void bdrv_rw_em_cb(void *opaque, int ret)
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *(int *)opaque = ret;
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NOT_DONE 0x7fffffff
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint8_t *buf, int nb_sectors)
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int async_ret;
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
14575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct iovec iov;
14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector qiov;
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    async_ret = NOT_DONE;
14615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_base = (void *)buf;
14625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_len = nb_sectors * 512;
14635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_iovec_init_external(&qiov, &iov, 1);
14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_rw_em_cb, &async_ret);
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (acb == NULL)
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (async_ret == NOT_DONE) {
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_aio_wait();
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return async_ret;
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         const uint8_t *buf, int nb_sectors)
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int async_ret;
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
14815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct iovec iov;
14825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUIOVector qiov;
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    async_ret = NOT_DONE;
14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_base = (void *)buf;
14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iov.iov_len = nb_sectors * 512;
14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_iovec_init_external(&qiov, &iov, 1);
14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
14895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_rw_em_cb, &async_ret);
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (acb == NULL)
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (async_ret == NOT_DONE) {
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_aio_wait();
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return async_ret;
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_init(void)
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    module_call_init(MODULE_INIT_BLOCK);
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
15045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   BlockDriverCompletionFunc *cb, void *opaque)
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverAIOCB *acb;
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (pool->free_aiocb) {
15095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb = pool->free_aiocb;
15105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pool->free_aiocb = acb->next;
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb = qemu_mallocz(pool->aiocb_size);
15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        acb->pool = pool;
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->bs = bs;
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->cb = cb;
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    acb->opaque = opaque;
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return acb;
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid qemu_aio_release(void *p)
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
15245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    AIOPool *pool = acb->pool;
15255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    acb->next = pool->free_aiocb;
15265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pool->free_aiocb = acb;
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************/
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* removable device support */
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return TRUE if the media is present
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_inserted(BlockDriverState *bs)
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_is_inserted)
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = drv->bdrv_is_inserted(bs);
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return TRUE if the media changed since the last call to this
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * function. It is currently only used for floppy disks
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_media_changed(BlockDriverState *bs)
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv || !drv->bdrv_media_changed)
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = -ENOTSUP;
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = drv->bdrv_media_changed(bs);
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == -ENOTSUP)
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = bs->media_changed;
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->media_changed = 0;
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If eject_flag is TRUE, eject the media. Otherwise, close the tray
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
15695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_eject(BlockDriverState *bs, int eject_flag)
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->locked) {
15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EBUSY;
15765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv || !drv->bdrv_eject) {
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = -ENOTSUP;
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = drv->bdrv_eject(bs, eject_flag);
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == -ENOTSUP) {
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (eject_flag)
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_close(bs);
15865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = 0;
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_is_locked(BlockDriverState *bs)
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs->locked;
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lock or unlock the media (if it is locked, the user won't be able
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to eject it manually).
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_set_locked(BlockDriverState *bs, int locked)
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs->locked = locked;
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv && drv->bdrv_set_locked) {
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        drv->bdrv_set_locked(bs, locked);
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* needed for generic scsi interface */
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (drv && drv->bdrv_ioctl)
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return drv->bdrv_ioctl(bs, req, buf);
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -ENOTSUP;
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        unsigned long int req, void *buf,
16245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque)
16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = bs->drv;
16275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (drv && drv->bdrv_aio_ioctl)
16295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return drv->bdrv_aio_ioctl(bs, req, buf, cb, opaque);
16305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qemu_blockalign(BlockDriverState *bs, size_t size)
16345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_memalign((bs && bs->buffer_alignment) ? bs->buffer_alignment : 512, size);
16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1637