cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

hd-geo-test.c (27696B)


      1/*
      2 * Hard disk geometry test cases.
      3 *
      4 * Copyright (c) 2012 Red Hat Inc.
      5 *
      6 * Authors:
      7 *  Markus Armbruster <armbru@redhat.com>,
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10 * See the COPYING file in the top-level directory.
     11 */
     12
     13/*
     14 * Covers only IDE and tests only CMOS contents.  Better than nothing.
     15 * Improvements welcome.
     16 */
     17
     18#include "qemu/osdep.h"
     19#include "qemu-common.h"
     20#include "qemu/bswap.h"
     21#include "qapi/qmp/qlist.h"
     22#include "libqos/libqtest.h"
     23#include "libqos/fw_cfg.h"
     24#include "libqos/libqos.h"
     25#include "standard-headers/linux/qemu_fw_cfg.h"
     26
     27#define ARGV_SIZE 256
     28
     29static char *create_test_img(int secs)
     30{
     31    char *template = strdup("/tmp/qtest.XXXXXX");
     32    int fd, ret;
     33
     34    fd = mkstemp(template);
     35    g_assert(fd >= 0);
     36    ret = ftruncate(fd, (off_t)secs * 512);
     37    close(fd);
     38
     39    if (ret) {
     40        free(template);
     41        template = NULL;
     42    }
     43
     44    return template;
     45}
     46
     47typedef struct {
     48    int cyls, heads, secs, trans;
     49} CHST;
     50
     51typedef enum {
     52    mbr_blank, mbr_lba, mbr_chs,
     53    mbr_last
     54} MBRcontents;
     55
     56typedef enum {
     57    /* order is relevant */
     58    backend_small, backend_large, backend_empty,
     59    backend_last
     60} Backend;
     61
     62static const int img_secs[backend_last] = {
     63    [backend_small] = 61440,
     64    [backend_large] = 8388608,
     65    [backend_empty] = -1,
     66};
     67
     68static const CHST hd_chst[backend_last][mbr_last] = {
     69    [backend_small] = {
     70        [mbr_blank] = { 60, 16, 63, 0 },
     71        [mbr_lba]   = { 60, 16, 63, 2 },
     72        [mbr_chs]   = { 60, 16, 63, 0 }
     73    },
     74    [backend_large] = {
     75        [mbr_blank] = { 8322, 16, 63, 1 },
     76        [mbr_lba]   = { 8322, 16, 63, 1 },
     77        [mbr_chs]   = { 8322, 16, 63, 0 }
     78    },
     79};
     80
     81static char *img_file_name[backend_last];
     82
     83static const CHST *cur_ide[4];
     84
     85static bool is_hd(const CHST *expected_chst)
     86{
     87    return expected_chst && expected_chst->cyls;
     88}
     89
     90static void test_cmos_byte(QTestState *qts, int reg, int expected)
     91{
     92    enum { cmos_base = 0x70 };
     93    int actual;
     94
     95    qtest_outb(qts, cmos_base + 0, reg);
     96    actual = qtest_inb(qts, cmos_base + 1);
     97    g_assert(actual == expected);
     98}
     99
    100static void test_cmos_bytes(QTestState *qts, int reg0, int n,
    101                            uint8_t expected[])
    102{
    103    int i;
    104
    105    for (i = 0; i < 9; i++) {
    106        test_cmos_byte(qts, reg0 + i, expected[i]);
    107    }
    108}
    109
    110static void test_cmos_disk_data(QTestState *qts)
    111{
    112    test_cmos_byte(qts, 0x12,
    113                   (is_hd(cur_ide[0]) ? 0xf0 : 0) |
    114                   (is_hd(cur_ide[1]) ? 0x0f : 0));
    115}
    116
    117static void test_cmos_drive_cyl(QTestState *qts, int reg0,
    118                                const CHST *expected_chst)
    119{
    120    if (is_hd(expected_chst)) {
    121        int c = expected_chst->cyls;
    122        int h = expected_chst->heads;
    123        int s = expected_chst->secs;
    124        uint8_t expected_bytes[9] = {
    125            c & 0xff, c >> 8, h, 0xff, 0xff, 0xc0 | ((h > 8) << 3),
    126            c & 0xff, c >> 8, s
    127        };
    128        test_cmos_bytes(qts, reg0, 9, expected_bytes);
    129    } else {
    130        int i;
    131
    132        for (i = 0; i < 9; i++) {
    133            test_cmos_byte(qts, reg0 + i, 0);
    134        }
    135    }
    136}
    137
    138static void test_cmos_drive1(QTestState *qts)
    139{
    140    test_cmos_byte(qts, 0x19, is_hd(cur_ide[0]) ? 47 : 0);
    141    test_cmos_drive_cyl(qts, 0x1b, cur_ide[0]);
    142}
    143
    144static void test_cmos_drive2(QTestState *qts)
    145{
    146    test_cmos_byte(qts, 0x1a, is_hd(cur_ide[1]) ? 47 : 0);
    147    test_cmos_drive_cyl(qts, 0x24, cur_ide[1]);
    148}
    149
    150static void test_cmos_disktransflag(QTestState *qts)
    151{
    152    int val, i;
    153
    154    val = 0;
    155    for (i = 0; i < ARRAY_SIZE(cur_ide); i++) {
    156        if (is_hd(cur_ide[i])) {
    157            val |= cur_ide[i]->trans << (2 * i);
    158        }
    159    }
    160    test_cmos_byte(qts, 0x39, val);
    161}
    162
    163static void test_cmos(QTestState *qts)
    164{
    165    test_cmos_disk_data(qts);
    166    test_cmos_drive1(qts);
    167    test_cmos_drive2(qts);
    168    test_cmos_disktransflag(qts);
    169}
    170
    171static int append_arg(int argc, char *argv[], int argv_sz, char *arg)
    172{
    173    g_assert(argc + 1 < argv_sz);
    174    argv[argc++] = arg;
    175    argv[argc] = NULL;
    176    return argc;
    177}
    178
    179static int setup_common(char *argv[], int argv_sz)
    180{
    181    memset(cur_ide, 0, sizeof(cur_ide));
    182    return append_arg(0, argv, argv_sz,
    183                      g_strdup("-nodefaults"));
    184}
    185
    186static void setup_mbr(int img_idx, MBRcontents mbr)
    187{
    188    static const uint8_t part_lba[16] = {
    189        /* chs 0,1,1 (lba 63) to chs 0,127,63 (8001 sectors) */
    190        0x80, 1, 1, 0, 6, 127, 63, 0, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
    191    };
    192    static const uint8_t part_chs[16] = {
    193        /* chs 0,1,1 (lba 63) to chs 7,15,63 (8001 sectors) */
    194        0x80, 1, 1, 0, 6,  15, 63, 7, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
    195    };
    196    uint8_t buf[512];
    197    int fd, ret;
    198
    199    memset(buf, 0, sizeof(buf));
    200
    201    if (mbr != mbr_blank) {
    202        buf[0x1fe] = 0x55;
    203        buf[0x1ff] = 0xAA;
    204        memcpy(buf + 0x1BE, mbr == mbr_lba ? part_lba : part_chs, 16);
    205    }
    206
    207    fd = open(img_file_name[img_idx], O_WRONLY);
    208    g_assert(fd >= 0);
    209    ret = write(fd, buf, sizeof(buf));
    210    g_assert(ret == sizeof(buf));
    211    close(fd);
    212}
    213
    214static int setup_ide(int argc, char *argv[], int argv_sz,
    215                     int ide_idx, const char *dev, int img_idx,
    216                     MBRcontents mbr)
    217{
    218    char *s1, *s2, *s3;
    219
    220    s1 = g_strdup_printf("-drive id=drive%d,if=%s",
    221                         ide_idx, dev ? "none" : "ide");
    222    s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx);
    223
    224    if (img_secs[img_idx] >= 0) {
    225        setup_mbr(img_idx, mbr);
    226        s3 = g_strdup_printf(",format=raw,file=%s", img_file_name[img_idx]);
    227    } else {
    228        s3 = g_strdup(",media=cdrom");
    229    }
    230    argc = append_arg(argc, argv, argv_sz,
    231                      g_strdup_printf("%s%s%s", s1, s2, s3));
    232    g_free(s1);
    233    g_free(s2);
    234    g_free(s3);
    235
    236    if (dev) {
    237        argc = append_arg(argc, argv, argv_sz,
    238                          g_strdup_printf("-device %s,drive=drive%d,"
    239                                          "bus=ide.%d,unit=%d",
    240                                          dev, ide_idx,
    241                                          ide_idx / 2, ide_idx % 2));
    242    }
    243    return argc;
    244}
    245
    246/*
    247 * Test case: no IDE devices
    248 */
    249static void test_ide_none(void)
    250{
    251    char **argv = g_new0(char *, ARGV_SIZE);
    252    char *args;
    253    QTestState *qts;
    254
    255    setup_common(argv, ARGV_SIZE);
    256    args = g_strjoinv(" ", argv);
    257    qts = qtest_init(args);
    258    g_strfreev(argv);
    259    g_free(args);
    260    test_cmos(qts);
    261    qtest_quit(qts);
    262}
    263
    264static void test_ide_mbr(bool use_device, MBRcontents mbr)
    265{
    266    char **argv = g_new0(char *, ARGV_SIZE);
    267    char *args;
    268    int argc;
    269    Backend i;
    270    const char *dev;
    271    QTestState *qts;
    272
    273    argc = setup_common(argv, ARGV_SIZE);
    274    for (i = 0; i < backend_last; i++) {
    275        cur_ide[i] = &hd_chst[i][mbr];
    276        dev = use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : NULL;
    277        argc = setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr);
    278    }
    279    args = g_strjoinv(" ", argv);
    280    qts = qtest_init(args);
    281    g_strfreev(argv);
    282    g_free(args);
    283    test_cmos(qts);
    284    qtest_quit(qts);
    285}
    286
    287/*
    288 * Test case: IDE devices (if=ide) with blank MBRs
    289 */
    290static void test_ide_drive_mbr_blank(void)
    291{
    292    test_ide_mbr(false, mbr_blank);
    293}
    294
    295/*
    296 * Test case: IDE devices (if=ide) with MBRs indicating LBA is in use
    297 */
    298static void test_ide_drive_mbr_lba(void)
    299{
    300    test_ide_mbr(false, mbr_lba);
    301}
    302
    303/*
    304 * Test case: IDE devices (if=ide) with MBRs indicating CHS is in use
    305 */
    306static void test_ide_drive_mbr_chs(void)
    307{
    308    test_ide_mbr(false, mbr_chs);
    309}
    310
    311/*
    312 * Test case: IDE devices (if=none) with blank MBRs
    313 */
    314static void test_ide_device_mbr_blank(void)
    315{
    316    test_ide_mbr(true, mbr_blank);
    317}
    318
    319/*
    320 * Test case: IDE devices (if=none) with MBRs indicating LBA is in use
    321 */
    322static void test_ide_device_mbr_lba(void)
    323{
    324    test_ide_mbr(true, mbr_lba);
    325}
    326
    327/*
    328 * Test case: IDE devices (if=none) with MBRs indicating CHS is in use
    329 */
    330static void test_ide_device_mbr_chs(void)
    331{
    332    test_ide_mbr(true, mbr_chs);
    333}
    334
    335static void test_ide_drive_user(const char *dev, bool trans)
    336{
    337    char **argv = g_new0(char *, ARGV_SIZE);
    338    char *args, *opts;
    339    int argc;
    340    int secs = img_secs[backend_small];
    341    const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };
    342    QTestState *qts;
    343
    344    argc = setup_common(argv, ARGV_SIZE);
    345    opts = g_strdup_printf("%s,%scyls=%d,heads=%d,secs=%d",
    346                           dev, trans ? "bios-chs-trans=lba," : "",
    347                           expected_chst.cyls, expected_chst.heads,
    348                           expected_chst.secs);
    349    cur_ide[0] = &expected_chst;
    350    argc = setup_ide(argc, argv, ARGV_SIZE, 0, opts, backend_small, mbr_chs);
    351    g_free(opts);
    352    args = g_strjoinv(" ", argv);
    353    qts = qtest_init(args);
    354    g_strfreev(argv);
    355    g_free(args);
    356    test_cmos(qts);
    357    qtest_quit(qts);
    358}
    359
    360/*
    361 * Test case: IDE device (if=none) with explicit CHS
    362 */
    363static void test_ide_device_user_chs(void)
    364{
    365    test_ide_drive_user("ide-hd", false);
    366}
    367
    368/*
    369 * Test case: IDE device (if=none) with explicit CHS and translation
    370 */
    371static void test_ide_device_user_chst(void)
    372{
    373    test_ide_drive_user("ide-hd", true);
    374}
    375
    376/*
    377 * Test case: IDE devices (if=ide), but use index=0 for CD-ROM
    378 */
    379static void test_ide_drive_cd_0(void)
    380{
    381    char **argv = g_new0(char *, ARGV_SIZE);
    382    char *args;
    383    int argc, ide_idx;
    384    Backend i;
    385    QTestState *qts;
    386
    387    argc = setup_common(argv, ARGV_SIZE);
    388    for (i = 0; i <= backend_empty; i++) {
    389        ide_idx = backend_empty - i;
    390        cur_ide[ide_idx] = &hd_chst[i][mbr_blank];
    391        argc = setup_ide(argc, argv, ARGV_SIZE, ide_idx, NULL, i, mbr_blank);
    392    }
    393    args = g_strjoinv(" ", argv);
    394    qts = qtest_init(args);
    395    g_strfreev(argv);
    396    g_free(args);
    397    test_cmos(qts);
    398    qtest_quit(qts);
    399}
    400
    401typedef struct {
    402    bool active;
    403    uint32_t head;
    404    uint32_t sector;
    405    uint32_t cyl;
    406    uint32_t end_head;
    407    uint32_t end_sector;
    408    uint32_t end_cyl;
    409    uint32_t start_sect;
    410    uint32_t nr_sects;
    411} MBRpartitions[4];
    412
    413static MBRpartitions empty_mbr = { {false, 0, 0, 0, 0, 0, 0, 0, 0},
    414                                   {false, 0, 0, 0, 0, 0, 0, 0, 0},
    415                                   {false, 0, 0, 0, 0, 0, 0, 0, 0},
    416                                   {false, 0, 0, 0, 0, 0, 0, 0, 0} };
    417
    418static char *create_qcow2_with_mbr(MBRpartitions mbr, uint64_t sectors)
    419{
    420    const char *template = "/tmp/qtest.XXXXXX";
    421    char *raw_path = strdup(template);
    422    char *qcow2_path = strdup(template);
    423    char cmd[100 + 2 * PATH_MAX];
    424    uint8_t buf[512] = {};
    425    int i, ret, fd, offset;
    426    uint64_t qcow2_size = sectors * 512;
    427    uint8_t status, parttype, head, sector, cyl;
    428    char *qemu_img_path;
    429    char *qemu_img_abs_path;
    430
    431    offset = 0xbe;
    432
    433    for (i = 0; i < 4; i++) {
    434        status = mbr[i].active ? 0x80 : 0x00;
    435        g_assert(mbr[i].head < 256);
    436        g_assert(mbr[i].sector < 64);
    437        g_assert(mbr[i].cyl < 1024);
    438        head = mbr[i].head;
    439        sector = mbr[i].sector + ((mbr[i].cyl & 0x300) >> 2);
    440        cyl = mbr[i].cyl & 0xff;
    441
    442        buf[offset + 0x0] = status;
    443        buf[offset + 0x1] = head;
    444        buf[offset + 0x2] = sector;
    445        buf[offset + 0x3] = cyl;
    446
    447        parttype = 0;
    448        g_assert(mbr[i].end_head < 256);
    449        g_assert(mbr[i].end_sector < 64);
    450        g_assert(mbr[i].end_cyl < 1024);
    451        head = mbr[i].end_head;
    452        sector = mbr[i].end_sector + ((mbr[i].end_cyl & 0x300) >> 2);
    453        cyl = mbr[i].end_cyl & 0xff;
    454
    455        buf[offset + 0x4] = parttype;
    456        buf[offset + 0x5] = head;
    457        buf[offset + 0x6] = sector;
    458        buf[offset + 0x7] = cyl;
    459
    460        stl_le_p(&buf[offset + 0x8], mbr[i].start_sect);
    461        stl_le_p(&buf[offset + 0xc], mbr[i].nr_sects);
    462
    463        offset += 0x10;
    464    }
    465
    466    fd = mkstemp(raw_path);
    467    g_assert(fd >= 0);
    468    close(fd);
    469
    470    fd = open(raw_path, O_WRONLY);
    471    g_assert(fd >= 0);
    472    ret = write(fd, buf, sizeof(buf));
    473    g_assert(ret == sizeof(buf));
    474    close(fd);
    475
    476    fd = mkstemp(qcow2_path);
    477    g_assert(fd >= 0);
    478    close(fd);
    479
    480    qemu_img_path = getenv("QTEST_QEMU_IMG");
    481    g_assert(qemu_img_path);
    482    qemu_img_abs_path = realpath(qemu_img_path, NULL);
    483    g_assert(qemu_img_abs_path);
    484
    485    ret = snprintf(cmd, sizeof(cmd),
    486                   "%s convert -f raw -O qcow2 %s %s > /dev/null",
    487                   qemu_img_abs_path,
    488                   raw_path, qcow2_path);
    489    g_assert((0 < ret) && (ret <= sizeof(cmd)));
    490    ret = system(cmd);
    491    g_assert(ret == 0);
    492
    493    ret = snprintf(cmd, sizeof(cmd),
    494                   "%s resize %s %" PRIu64 " > /dev/null",
    495                   qemu_img_abs_path,
    496                   qcow2_path, qcow2_size);
    497    g_assert((0 < ret) && (ret <= sizeof(cmd)));
    498    ret = system(cmd);
    499    g_assert(ret == 0);
    500
    501    free(qemu_img_abs_path);
    502
    503    unlink(raw_path);
    504    free(raw_path);
    505
    506    return qcow2_path;
    507}
    508
    509#define BIOS_GEOMETRY_MAX_SIZE 10000
    510
    511typedef struct {
    512    uint32_t c;
    513    uint32_t h;
    514    uint32_t s;
    515} CHS;
    516
    517typedef struct {
    518    const char *dev_path;
    519    CHS chs;
    520} CHSResult;
    521
    522static void read_bootdevices(QFWCFG *fw_cfg, CHSResult expected[])
    523{
    524    char *buf = g_malloc0(BIOS_GEOMETRY_MAX_SIZE);
    525    char *cur;
    526    GList *results = NULL, *cur_result;
    527    CHSResult *r;
    528    int i;
    529    int res;
    530    bool found;
    531
    532    qfw_cfg_get_file(fw_cfg, "bios-geometry", buf, BIOS_GEOMETRY_MAX_SIZE);
    533
    534    for (cur = buf; *cur; cur++) {
    535        if (*cur == '\n') {
    536            *cur = '\0';
    537        }
    538    }
    539    cur = buf;
    540
    541    while (strlen(cur)) {
    542
    543        r = g_malloc0(sizeof(*r));
    544        r->dev_path = g_malloc0(strlen(cur) + 1);
    545        res = sscanf(cur, "%s %" PRIu32 " %" PRIu32 " %" PRIu32,
    546                     (char *)r->dev_path,
    547                     &(r->chs.c), &(r->chs.h), &(r->chs.s));
    548
    549        g_assert(res == 4);
    550
    551        results = g_list_prepend(results, r);
    552
    553        cur += strlen(cur) + 1;
    554    }
    555
    556    i = 0;
    557
    558    while (expected[i].dev_path) {
    559        found = false;
    560        cur_result = results;
    561        while (cur_result) {
    562            r = cur_result->data;
    563            if (!strcmp(r->dev_path, expected[i].dev_path) &&
    564                !memcmp(&(r->chs), &(expected[i].chs), sizeof(r->chs))) {
    565                found = true;
    566                break;
    567            }
    568            cur_result = g_list_next(cur_result);
    569        }
    570        g_assert(found);
    571        g_free((char *)((CHSResult *)cur_result->data)->dev_path);
    572        g_free(cur_result->data);
    573        results = g_list_delete_link(results, cur_result);
    574        i++;
    575    }
    576
    577    g_assert(results == NULL);
    578
    579    g_free(buf);
    580}
    581
    582#define MAX_DRIVES 30
    583
    584typedef struct {
    585    char **argv;
    586    int argc;
    587    char **drives;
    588    int n_drives;
    589    int n_scsi_disks;
    590    int n_scsi_controllers;
    591    int n_virtio_disks;
    592} TestArgs;
    593
    594static TestArgs *create_args(void)
    595{
    596    TestArgs *args = g_malloc0(sizeof(*args));
    597    args->argv = g_new0(char *, ARGV_SIZE);
    598    args->argc = append_arg(args->argc, args->argv,
    599                            ARGV_SIZE, g_strdup("-nodefaults"));
    600    args->drives = g_new0(char *, MAX_DRIVES);
    601    return args;
    602}
    603
    604static void add_drive_with_mbr(TestArgs *args,
    605                               MBRpartitions mbr, uint64_t sectors)
    606{
    607    char *img_file_name;
    608    char part[300];
    609    int ret;
    610
    611    g_assert(args->n_drives < MAX_DRIVES);
    612
    613    img_file_name = create_qcow2_with_mbr(mbr, sectors);
    614
    615    args->drives[args->n_drives] = img_file_name;
    616    ret = snprintf(part, sizeof(part),
    617                   "-drive file=%s,if=none,format=qcow2,id=disk%d",
    618                   img_file_name, args->n_drives);
    619    g_assert((0 < ret) && (ret <= sizeof(part)));
    620    args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
    621    args->n_drives++;
    622}
    623
    624static void add_ide_disk(TestArgs *args,
    625                         int drive_idx, int bus, int unit, int c, int h, int s)
    626{
    627    char part[300];
    628    int ret;
    629
    630    ret = snprintf(part, sizeof(part),
    631                   "-device ide-hd,drive=disk%d,bus=ide.%d,unit=%d,"
    632                   "lcyls=%d,lheads=%d,lsecs=%d",
    633                   drive_idx, bus, unit, c, h, s);
    634    g_assert((0 < ret) && (ret <= sizeof(part)));
    635    args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
    636}
    637
    638static void add_scsi_controller(TestArgs *args,
    639                                const char *type,
    640                                const char *bus,
    641                                int addr)
    642{
    643    char part[300];
    644    int ret;
    645
    646    ret = snprintf(part, sizeof(part),
    647                   "-device %s,id=scsi%d,bus=%s,addr=%d",
    648                   type, args->n_scsi_controllers, bus, addr);
    649    g_assert((0 < ret) && (ret <= sizeof(part)));
    650    args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
    651    args->n_scsi_controllers++;
    652}
    653
    654static void add_scsi_disk(TestArgs *args,
    655                          int drive_idx, int bus,
    656                          int channel, int scsi_id, int lun,
    657                          int c, int h, int s)
    658{
    659    char part[300];
    660    int ret;
    661
    662    ret = snprintf(part, sizeof(part),
    663                   "-device scsi-hd,id=scsi-disk%d,drive=disk%d,"
    664                   "bus=scsi%d.0,"
    665                   "channel=%d,scsi-id=%d,lun=%d,"
    666                   "lcyls=%d,lheads=%d,lsecs=%d",
    667                   args->n_scsi_disks, drive_idx, bus, channel, scsi_id, lun,
    668                   c, h, s);
    669    g_assert((0 < ret) && (ret <= sizeof(part)));
    670    args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
    671    args->n_scsi_disks++;
    672}
    673
    674static void add_virtio_disk(TestArgs *args,
    675                            int drive_idx, const char *bus, int addr,
    676                            int c, int h, int s)
    677{
    678    char part[300];
    679    int ret;
    680
    681    ret = snprintf(part, sizeof(part),
    682                   "-device virtio-blk-pci,id=virtio-disk%d,"
    683                   "drive=disk%d,bus=%s,addr=%d,"
    684                   "lcyls=%d,lheads=%d,lsecs=%d",
    685                   args->n_virtio_disks, drive_idx, bus, addr, c, h, s);
    686    g_assert((0 < ret) && (ret <= sizeof(part)));
    687    args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
    688    args->n_virtio_disks++;
    689}
    690
    691static void test_override(TestArgs *args, CHSResult expected[])
    692{
    693    QTestState *qts;
    694    char *joined_args;
    695    QFWCFG *fw_cfg;
    696    int i;
    697
    698    joined_args = g_strjoinv(" ", args->argv);
    699
    700    qts = qtest_init(joined_args);
    701    fw_cfg = pc_fw_cfg_init(qts);
    702
    703    read_bootdevices(fw_cfg, expected);
    704
    705    g_free(joined_args);
    706    qtest_quit(qts);
    707
    708    g_free(fw_cfg);
    709
    710    for (i = 0; i < args->n_drives; i++) {
    711        unlink(args->drives[i]);
    712        free(args->drives[i]);
    713    }
    714    g_free(args->drives);
    715    g_strfreev(args->argv);
    716    g_free(args);
    717}
    718
    719static void test_override_ide(void)
    720{
    721    TestArgs *args = create_args();
    722    CHSResult expected[] = {
    723        {"/pci@i0cf8/ide@1,1/drive@0/disk@0", {10000, 120, 30} },
    724        {"/pci@i0cf8/ide@1,1/drive@0/disk@1", {9000, 120, 30} },
    725        {"/pci@i0cf8/ide@1,1/drive@1/disk@0", {0, 1, 1} },
    726        {"/pci@i0cf8/ide@1,1/drive@1/disk@1", {1, 0, 0} },
    727        {NULL, {0, 0, 0} }
    728    };
    729    add_drive_with_mbr(args, empty_mbr, 1);
    730    add_drive_with_mbr(args, empty_mbr, 1);
    731    add_drive_with_mbr(args, empty_mbr, 1);
    732    add_drive_with_mbr(args, empty_mbr, 1);
    733    add_ide_disk(args, 0, 0, 0, 10000, 120, 30);
    734    add_ide_disk(args, 1, 0, 1, 9000, 120, 30);
    735    add_ide_disk(args, 2, 1, 0, 0, 1, 1);
    736    add_ide_disk(args, 3, 1, 1, 1, 0, 0);
    737    test_override(args, expected);
    738}
    739
    740static void test_override_scsi(void)
    741{
    742    TestArgs *args = create_args();
    743    CHSResult expected[] = {
    744        {"/pci@i0cf8/scsi@3/channel@0/disk@0,0", {10000, 120, 30} },
    745        {"/pci@i0cf8/scsi@3/channel@0/disk@1,0", {9000, 120, 30} },
    746        {"/pci@i0cf8/scsi@3/channel@0/disk@2,0", {1, 0, 0} },
    747        {"/pci@i0cf8/scsi@3/channel@0/disk@3,0", {0, 1, 0} },
    748        {NULL, {0, 0, 0} }
    749    };
    750    add_drive_with_mbr(args, empty_mbr, 1);
    751    add_drive_with_mbr(args, empty_mbr, 1);
    752    add_drive_with_mbr(args, empty_mbr, 1);
    753    add_drive_with_mbr(args, empty_mbr, 1);
    754    add_scsi_controller(args, "lsi53c895a", "pci.0", 3);
    755    add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
    756    add_scsi_disk(args, 1, 0, 0, 1, 0, 9000, 120, 30);
    757    add_scsi_disk(args, 2, 0, 0, 2, 0, 1, 0, 0);
    758    add_scsi_disk(args, 3, 0, 0, 3, 0, 0, 1, 0);
    759    test_override(args, expected);
    760}
    761
    762static void test_override_scsi_2_controllers(void)
    763{
    764    TestArgs *args = create_args();
    765    CHSResult expected[] = {
    766        {"/pci@i0cf8/scsi@3/channel@0/disk@0,0", {10000, 120, 30} },
    767        {"/pci@i0cf8/scsi@3/channel@0/disk@1,0", {9000, 120, 30} },
    768        {"/pci@i0cf8/scsi@4/channel@0/disk@0,1", {1, 0, 0} },
    769        {"/pci@i0cf8/scsi@4/channel@0/disk@1,2", {0, 1, 0} },
    770        {NULL, {0, 0, 0} }
    771    };
    772    add_drive_with_mbr(args, empty_mbr, 1);
    773    add_drive_with_mbr(args, empty_mbr, 1);
    774    add_drive_with_mbr(args, empty_mbr, 1);
    775    add_drive_with_mbr(args, empty_mbr, 1);
    776    add_scsi_controller(args, "lsi53c895a", "pci.0", 3);
    777    add_scsi_controller(args, "virtio-scsi-pci", "pci.0", 4);
    778    add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
    779    add_scsi_disk(args, 1, 0, 0, 1, 0, 9000, 120, 30);
    780    add_scsi_disk(args, 2, 1, 0, 0, 1, 1, 0, 0);
    781    add_scsi_disk(args, 3, 1, 0, 1, 2, 0, 1, 0);
    782    test_override(args, expected);
    783}
    784
    785static void test_override_virtio_blk(void)
    786{
    787    TestArgs *args = create_args();
    788    CHSResult expected[] = {
    789        {"/pci@i0cf8/scsi@3/disk@0,0", {10000, 120, 30} },
    790        {"/pci@i0cf8/scsi@4/disk@0,0", {9000, 120, 30} },
    791        {NULL, {0, 0, 0} }
    792    };
    793    add_drive_with_mbr(args, empty_mbr, 1);
    794    add_drive_with_mbr(args, empty_mbr, 1);
    795    add_virtio_disk(args, 0, "pci.0", 3, 10000, 120, 30);
    796    add_virtio_disk(args, 1, "pci.0", 4, 9000, 120, 30);
    797    test_override(args, expected);
    798}
    799
    800static void test_override_zero_chs(void)
    801{
    802    TestArgs *args = create_args();
    803    CHSResult expected[] = {
    804        {NULL, {0, 0, 0} }
    805    };
    806    add_drive_with_mbr(args, empty_mbr, 1);
    807    add_ide_disk(args, 0, 1, 1, 0, 0, 0);
    808    test_override(args, expected);
    809}
    810
    811static void test_override_scsi_hot_unplug(void)
    812{
    813    QTestState *qts;
    814    char *joined_args;
    815    QFWCFG *fw_cfg;
    816    QDict *response;
    817    int i;
    818    TestArgs *args = create_args();
    819    CHSResult expected[] = {
    820        {"/pci@i0cf8/scsi@2/channel@0/disk@0,0", {10000, 120, 30} },
    821        {"/pci@i0cf8/scsi@2/channel@0/disk@1,0", {20, 20, 20} },
    822        {NULL, {0, 0, 0} }
    823    };
    824    CHSResult expected2[] = {
    825        {"/pci@i0cf8/scsi@2/channel@0/disk@1,0", {20, 20, 20} },
    826        {NULL, {0, 0, 0} }
    827    };
    828    add_drive_with_mbr(args, empty_mbr, 1);
    829    add_drive_with_mbr(args, empty_mbr, 1);
    830    add_scsi_controller(args, "virtio-scsi-pci", "pci.0", 2);
    831    add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
    832    add_scsi_disk(args, 1, 0, 0, 1, 0, 20, 20, 20);
    833
    834    joined_args = g_strjoinv(" ", args->argv);
    835
    836    qts = qtest_init(joined_args);
    837    fw_cfg = pc_fw_cfg_init(qts);
    838
    839    read_bootdevices(fw_cfg, expected);
    840
    841    /* unplug device an restart */
    842    response = qtest_qmp(qts,
    843                         "{ 'execute': 'device_del',"
    844                         "  'arguments': {'id': 'scsi-disk0' }}");
    845    g_assert(response);
    846    g_assert(!qdict_haskey(response, "error"));
    847    qobject_unref(response);
    848    response = qtest_qmp(qts,
    849                         "{ 'execute': 'system_reset', 'arguments': { }}");
    850    g_assert(response);
    851    g_assert(!qdict_haskey(response, "error"));
    852    qobject_unref(response);
    853
    854    qtest_qmp_eventwait(qts, "RESET");
    855
    856    read_bootdevices(fw_cfg, expected2);
    857
    858    g_free(joined_args);
    859    qtest_quit(qts);
    860
    861    g_free(fw_cfg);
    862
    863    for (i = 0; i < args->n_drives; i++) {
    864        unlink(args->drives[i]);
    865        free(args->drives[i]);
    866    }
    867    g_free(args->drives);
    868    g_strfreev(args->argv);
    869    g_free(args);
    870}
    871
    872static void test_override_virtio_hot_unplug(void)
    873{
    874    QTestState *qts;
    875    char *joined_args;
    876    QFWCFG *fw_cfg;
    877    QDict *response;
    878    int i;
    879    TestArgs *args = create_args();
    880    CHSResult expected[] = {
    881        {"/pci@i0cf8/scsi@2/disk@0,0", {10000, 120, 30} },
    882        {"/pci@i0cf8/scsi@3/disk@0,0", {20, 20, 20} },
    883        {NULL, {0, 0, 0} }
    884    };
    885    CHSResult expected2[] = {
    886        {"/pci@i0cf8/scsi@3/disk@0,0", {20, 20, 20} },
    887        {NULL, {0, 0, 0} }
    888    };
    889    add_drive_with_mbr(args, empty_mbr, 1);
    890    add_drive_with_mbr(args, empty_mbr, 1);
    891    add_virtio_disk(args, 0, "pci.0", 2, 10000, 120, 30);
    892    add_virtio_disk(args, 1, "pci.0", 3, 20, 20, 20);
    893
    894    joined_args = g_strjoinv(" ", args->argv);
    895
    896    qts = qtest_init(joined_args);
    897    fw_cfg = pc_fw_cfg_init(qts);
    898
    899    read_bootdevices(fw_cfg, expected);
    900
    901    /* unplug device an restart */
    902    response = qtest_qmp(qts,
    903                         "{ 'execute': 'device_del',"
    904                         "  'arguments': {'id': 'virtio-disk0' }}");
    905    g_assert(response);
    906    g_assert(!qdict_haskey(response, "error"));
    907    qobject_unref(response);
    908    response = qtest_qmp(qts,
    909                         "{ 'execute': 'system_reset', 'arguments': { }}");
    910    g_assert(response);
    911    g_assert(!qdict_haskey(response, "error"));
    912    qobject_unref(response);
    913
    914    qtest_qmp_eventwait(qts, "RESET");
    915
    916    read_bootdevices(fw_cfg, expected2);
    917
    918    g_free(joined_args);
    919    qtest_quit(qts);
    920
    921    g_free(fw_cfg);
    922
    923    for (i = 0; i < args->n_drives; i++) {
    924        unlink(args->drives[i]);
    925        free(args->drives[i]);
    926    }
    927    g_free(args->drives);
    928    g_strfreev(args->argv);
    929    g_free(args);
    930}
    931
    932int main(int argc, char **argv)
    933{
    934    Backend i;
    935    int ret;
    936
    937    g_test_init(&argc, &argv, NULL);
    938
    939    for (i = 0; i < backend_last; i++) {
    940        if (img_secs[i] >= 0) {
    941            img_file_name[i] = create_test_img(img_secs[i]);
    942            if (!img_file_name[i]) {
    943                g_test_message("Could not create test images.");
    944                goto test_add_done;
    945            }
    946        } else {
    947            img_file_name[i] = NULL;
    948        }
    949    }
    950
    951    qtest_add_func("hd-geo/ide/none", test_ide_none);
    952    qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank);
    953    qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba);
    954    qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs);
    955    qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0);
    956    qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blank);
    957    qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba);
    958    qtest_add_func("hd-geo/ide/device/mbr/chs", test_ide_device_mbr_chs);
    959    qtest_add_func("hd-geo/ide/device/user/chs", test_ide_device_user_chs);
    960    qtest_add_func("hd-geo/ide/device/user/chst", test_ide_device_user_chst);
    961    if (have_qemu_img()) {
    962        qtest_add_func("hd-geo/override/ide", test_override_ide);
    963        qtest_add_func("hd-geo/override/scsi", test_override_scsi);
    964        qtest_add_func("hd-geo/override/scsi_2_controllers",
    965                       test_override_scsi_2_controllers);
    966        qtest_add_func("hd-geo/override/virtio_blk", test_override_virtio_blk);
    967        qtest_add_func("hd-geo/override/zero_chs", test_override_zero_chs);
    968        qtest_add_func("hd-geo/override/scsi_hot_unplug",
    969                       test_override_scsi_hot_unplug);
    970        qtest_add_func("hd-geo/override/virtio_hot_unplug",
    971                       test_override_virtio_hot_unplug);
    972    } else {
    973        g_test_message("QTEST_QEMU_IMG not set or qemu-img missing; "
    974                       "skipping hd-geo/override/* tests");
    975    }
    976
    977test_add_done:
    978    ret = g_test_run();
    979
    980    for (i = 0; i < backend_last; i++) {
    981        if (img_file_name[i]) {
    982            unlink(img_file_name[i]);
    983            free(img_file_name[i]);
    984        }
    985    }
    986
    987    return ret;
    988}