11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth * Hard disk geometry test cases.
31e8a1faeSThomas Huth *
41e8a1faeSThomas Huth * Copyright (c) 2012 Red Hat Inc.
51e8a1faeSThomas Huth *
61e8a1faeSThomas Huth * Authors:
71e8a1faeSThomas Huth * Markus Armbruster <armbru@redhat.com>,
81e8a1faeSThomas Huth *
91e8a1faeSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or later.
101e8a1faeSThomas Huth * See the COPYING file in the top-level directory.
111e8a1faeSThomas Huth */
121e8a1faeSThomas Huth
131e8a1faeSThomas Huth /*
141e8a1faeSThomas Huth * Covers only IDE and tests only CMOS contents. Better than nothing.
151e8a1faeSThomas Huth * Improvements welcome.
161e8a1faeSThomas Huth */
171e8a1faeSThomas Huth
181e8a1faeSThomas Huth #include "qemu/osdep.h"
191e8a1faeSThomas Huth #include "qemu/bswap.h"
201e8a1faeSThomas Huth #include "qapi/qmp/qlist.h"
21907b5105SMarc-André Lureau #include "libqtest.h"
221e8a1faeSThomas Huth #include "libqos/fw_cfg.h"
231e8a1faeSThomas Huth #include "libqos/libqos.h"
241e8a1faeSThomas Huth #include "standard-headers/linux/qemu_fw_cfg.h"
251e8a1faeSThomas Huth
261e8a1faeSThomas Huth #define ARGV_SIZE 256
271e8a1faeSThomas Huth
create_test_img(int secs)281e8a1faeSThomas Huth static char *create_test_img(int secs)
291e8a1faeSThomas Huth {
3052ca92d6SBin Meng char *template;
311e8a1faeSThomas Huth int fd, ret;
321e8a1faeSThomas Huth
3352ca92d6SBin Meng fd = g_file_open_tmp("qtest.XXXXXX", &template, NULL);
341e8a1faeSThomas Huth g_assert(fd >= 0);
351e8a1faeSThomas Huth ret = ftruncate(fd, (off_t)secs * 512);
361e8a1faeSThomas Huth close(fd);
371e8a1faeSThomas Huth
381e8a1faeSThomas Huth if (ret) {
3952ca92d6SBin Meng g_free(template);
401e8a1faeSThomas Huth template = NULL;
411e8a1faeSThomas Huth }
421e8a1faeSThomas Huth
431e8a1faeSThomas Huth return template;
441e8a1faeSThomas Huth }
451e8a1faeSThomas Huth
461e8a1faeSThomas Huth typedef struct {
471e8a1faeSThomas Huth int cyls, heads, secs, trans;
481e8a1faeSThomas Huth } CHST;
491e8a1faeSThomas Huth
501e8a1faeSThomas Huth typedef enum {
511e8a1faeSThomas Huth mbr_blank, mbr_lba, mbr_chs,
521e8a1faeSThomas Huth mbr_last
531e8a1faeSThomas Huth } MBRcontents;
541e8a1faeSThomas Huth
551e8a1faeSThomas Huth typedef enum {
561e8a1faeSThomas Huth /* order is relevant */
571e8a1faeSThomas Huth backend_small, backend_large, backend_empty,
581e8a1faeSThomas Huth backend_last
591e8a1faeSThomas Huth } Backend;
601e8a1faeSThomas Huth
611e8a1faeSThomas Huth static const int img_secs[backend_last] = {
621e8a1faeSThomas Huth [backend_small] = 61440,
631e8a1faeSThomas Huth [backend_large] = 8388608,
641e8a1faeSThomas Huth [backend_empty] = -1,
651e8a1faeSThomas Huth };
661e8a1faeSThomas Huth
671e8a1faeSThomas Huth static const CHST hd_chst[backend_last][mbr_last] = {
681e8a1faeSThomas Huth [backend_small] = {
691e8a1faeSThomas Huth [mbr_blank] = { 60, 16, 63, 0 },
701e8a1faeSThomas Huth [mbr_lba] = { 60, 16, 63, 2 },
711e8a1faeSThomas Huth [mbr_chs] = { 60, 16, 63, 0 }
721e8a1faeSThomas Huth },
731e8a1faeSThomas Huth [backend_large] = {
741e8a1faeSThomas Huth [mbr_blank] = { 8322, 16, 63, 1 },
751e8a1faeSThomas Huth [mbr_lba] = { 8322, 16, 63, 1 },
761e8a1faeSThomas Huth [mbr_chs] = { 8322, 16, 63, 0 }
771e8a1faeSThomas Huth },
781e8a1faeSThomas Huth };
791e8a1faeSThomas Huth
801e8a1faeSThomas Huth static char *img_file_name[backend_last];
811e8a1faeSThomas Huth
821e8a1faeSThomas Huth static const CHST *cur_ide[4];
831e8a1faeSThomas Huth
is_hd(const CHST * expected_chst)841e8a1faeSThomas Huth static bool is_hd(const CHST *expected_chst)
851e8a1faeSThomas Huth {
861e8a1faeSThomas Huth return expected_chst && expected_chst->cyls;
871e8a1faeSThomas Huth }
881e8a1faeSThomas Huth
test_cmos_byte(QTestState * qts,int reg,int expected)891e8a1faeSThomas Huth static void test_cmos_byte(QTestState *qts, int reg, int expected)
901e8a1faeSThomas Huth {
911e8a1faeSThomas Huth enum { cmos_base = 0x70 };
921e8a1faeSThomas Huth int actual;
931e8a1faeSThomas Huth
941e8a1faeSThomas Huth qtest_outb(qts, cmos_base + 0, reg);
951e8a1faeSThomas Huth actual = qtest_inb(qts, cmos_base + 1);
961e8a1faeSThomas Huth g_assert(actual == expected);
971e8a1faeSThomas Huth }
981e8a1faeSThomas Huth
test_cmos_bytes(QTestState * qts,int reg0,int n,uint8_t expected[])991e8a1faeSThomas Huth static void test_cmos_bytes(QTestState *qts, int reg0, int n,
1001e8a1faeSThomas Huth uint8_t expected[])
1011e8a1faeSThomas Huth {
1021e8a1faeSThomas Huth int i;
1031e8a1faeSThomas Huth
1041e8a1faeSThomas Huth for (i = 0; i < 9; i++) {
1051e8a1faeSThomas Huth test_cmos_byte(qts, reg0 + i, expected[i]);
1061e8a1faeSThomas Huth }
1071e8a1faeSThomas Huth }
1081e8a1faeSThomas Huth
test_cmos_disk_data(QTestState * qts)1091e8a1faeSThomas Huth static void test_cmos_disk_data(QTestState *qts)
1101e8a1faeSThomas Huth {
1111e8a1faeSThomas Huth test_cmos_byte(qts, 0x12,
1121e8a1faeSThomas Huth (is_hd(cur_ide[0]) ? 0xf0 : 0) |
1131e8a1faeSThomas Huth (is_hd(cur_ide[1]) ? 0x0f : 0));
1141e8a1faeSThomas Huth }
1151e8a1faeSThomas Huth
test_cmos_drive_cyl(QTestState * qts,int reg0,const CHST * expected_chst)1161e8a1faeSThomas Huth static void test_cmos_drive_cyl(QTestState *qts, int reg0,
1171e8a1faeSThomas Huth const CHST *expected_chst)
1181e8a1faeSThomas Huth {
1191e8a1faeSThomas Huth if (is_hd(expected_chst)) {
1201e8a1faeSThomas Huth int c = expected_chst->cyls;
1211e8a1faeSThomas Huth int h = expected_chst->heads;
1221e8a1faeSThomas Huth int s = expected_chst->secs;
1231e8a1faeSThomas Huth uint8_t expected_bytes[9] = {
1241e8a1faeSThomas Huth c & 0xff, c >> 8, h, 0xff, 0xff, 0xc0 | ((h > 8) << 3),
1251e8a1faeSThomas Huth c & 0xff, c >> 8, s
1261e8a1faeSThomas Huth };
1271e8a1faeSThomas Huth test_cmos_bytes(qts, reg0, 9, expected_bytes);
1281e8a1faeSThomas Huth } else {
1291e8a1faeSThomas Huth int i;
1301e8a1faeSThomas Huth
1311e8a1faeSThomas Huth for (i = 0; i < 9; i++) {
1321e8a1faeSThomas Huth test_cmos_byte(qts, reg0 + i, 0);
1331e8a1faeSThomas Huth }
1341e8a1faeSThomas Huth }
1351e8a1faeSThomas Huth }
1361e8a1faeSThomas Huth
test_cmos_drive1(QTestState * qts)1371e8a1faeSThomas Huth static void test_cmos_drive1(QTestState *qts)
1381e8a1faeSThomas Huth {
1391e8a1faeSThomas Huth test_cmos_byte(qts, 0x19, is_hd(cur_ide[0]) ? 47 : 0);
1401e8a1faeSThomas Huth test_cmos_drive_cyl(qts, 0x1b, cur_ide[0]);
1411e8a1faeSThomas Huth }
1421e8a1faeSThomas Huth
test_cmos_drive2(QTestState * qts)1431e8a1faeSThomas Huth static void test_cmos_drive2(QTestState *qts)
1441e8a1faeSThomas Huth {
1451e8a1faeSThomas Huth test_cmos_byte(qts, 0x1a, is_hd(cur_ide[1]) ? 47 : 0);
1461e8a1faeSThomas Huth test_cmos_drive_cyl(qts, 0x24, cur_ide[1]);
1471e8a1faeSThomas Huth }
1481e8a1faeSThomas Huth
test_cmos_disktransflag(QTestState * qts)1491e8a1faeSThomas Huth static void test_cmos_disktransflag(QTestState *qts)
1501e8a1faeSThomas Huth {
1511e8a1faeSThomas Huth int val, i;
1521e8a1faeSThomas Huth
1531e8a1faeSThomas Huth val = 0;
1541e8a1faeSThomas Huth for (i = 0; i < ARRAY_SIZE(cur_ide); i++) {
1551e8a1faeSThomas Huth if (is_hd(cur_ide[i])) {
1561e8a1faeSThomas Huth val |= cur_ide[i]->trans << (2 * i);
1571e8a1faeSThomas Huth }
1581e8a1faeSThomas Huth }
1591e8a1faeSThomas Huth test_cmos_byte(qts, 0x39, val);
1601e8a1faeSThomas Huth }
1611e8a1faeSThomas Huth
test_cmos(QTestState * qts)1621e8a1faeSThomas Huth static void test_cmos(QTestState *qts)
1631e8a1faeSThomas Huth {
1641e8a1faeSThomas Huth test_cmos_disk_data(qts);
1651e8a1faeSThomas Huth test_cmos_drive1(qts);
1661e8a1faeSThomas Huth test_cmos_drive2(qts);
1671e8a1faeSThomas Huth test_cmos_disktransflag(qts);
1681e8a1faeSThomas Huth }
1691e8a1faeSThomas Huth
append_arg(int argc,char * argv[],int argv_sz,char * arg)1701e8a1faeSThomas Huth static int append_arg(int argc, char *argv[], int argv_sz, char *arg)
1711e8a1faeSThomas Huth {
1721e8a1faeSThomas Huth g_assert(argc + 1 < argv_sz);
1731e8a1faeSThomas Huth argv[argc++] = arg;
1741e8a1faeSThomas Huth argv[argc] = NULL;
1751e8a1faeSThomas Huth return argc;
1761e8a1faeSThomas Huth }
1771e8a1faeSThomas Huth
setup_common(char * argv[],int argv_sz)1781e8a1faeSThomas Huth static int setup_common(char *argv[], int argv_sz)
1791e8a1faeSThomas Huth {
180fedcc379SDr. David Alan Gilbert int new_argc;
1811e8a1faeSThomas Huth memset(cur_ide, 0, sizeof(cur_ide));
182fedcc379SDr. David Alan Gilbert new_argc = append_arg(0, argv, argv_sz,
1831e8a1faeSThomas Huth g_strdup("-nodefaults"));
184fedcc379SDr. David Alan Gilbert new_argc = append_arg(new_argc, argv, argv_sz,
185fedcc379SDr. David Alan Gilbert g_strdup("-machine"));
186fedcc379SDr. David Alan Gilbert new_argc = append_arg(new_argc, argv, argv_sz,
187fedcc379SDr. David Alan Gilbert g_strdup("pc"));
188fedcc379SDr. David Alan Gilbert return new_argc;
1891e8a1faeSThomas Huth }
1901e8a1faeSThomas Huth
setup_mbr(int img_idx,MBRcontents mbr)1911e8a1faeSThomas Huth static void setup_mbr(int img_idx, MBRcontents mbr)
1921e8a1faeSThomas Huth {
1931e8a1faeSThomas Huth static const uint8_t part_lba[16] = {
1941e8a1faeSThomas Huth /* chs 0,1,1 (lba 63) to chs 0,127,63 (8001 sectors) */
1951e8a1faeSThomas Huth 0x80, 1, 1, 0, 6, 127, 63, 0, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
1961e8a1faeSThomas Huth };
1971e8a1faeSThomas Huth static const uint8_t part_chs[16] = {
1981e8a1faeSThomas Huth /* chs 0,1,1 (lba 63) to chs 7,15,63 (8001 sectors) */
1991e8a1faeSThomas Huth 0x80, 1, 1, 0, 6, 15, 63, 7, 63, 0, 0, 0, 0x41, 0x1F, 0, 0,
2001e8a1faeSThomas Huth };
2011e8a1faeSThomas Huth uint8_t buf[512];
2021e8a1faeSThomas Huth int fd, ret;
2031e8a1faeSThomas Huth
2041e8a1faeSThomas Huth memset(buf, 0, sizeof(buf));
2051e8a1faeSThomas Huth
2061e8a1faeSThomas Huth if (mbr != mbr_blank) {
2071e8a1faeSThomas Huth buf[0x1fe] = 0x55;
2081e8a1faeSThomas Huth buf[0x1ff] = 0xAA;
2091e8a1faeSThomas Huth memcpy(buf + 0x1BE, mbr == mbr_lba ? part_lba : part_chs, 16);
2101e8a1faeSThomas Huth }
2111e8a1faeSThomas Huth
2121e8a1faeSThomas Huth fd = open(img_file_name[img_idx], O_WRONLY);
2131e8a1faeSThomas Huth g_assert(fd >= 0);
2141e8a1faeSThomas Huth ret = write(fd, buf, sizeof(buf));
2151e8a1faeSThomas Huth g_assert(ret == sizeof(buf));
2161e8a1faeSThomas Huth close(fd);
2171e8a1faeSThomas Huth }
2181e8a1faeSThomas Huth
setup_ide(int argc,char * argv[],int argv_sz,int ide_idx,const char * dev,int img_idx,MBRcontents mbr)2191e8a1faeSThomas Huth static int setup_ide(int argc, char *argv[], int argv_sz,
2201e8a1faeSThomas Huth int ide_idx, const char *dev, int img_idx,
2211e8a1faeSThomas Huth MBRcontents mbr)
2221e8a1faeSThomas Huth {
2231e8a1faeSThomas Huth char *s1, *s2, *s3;
2241e8a1faeSThomas Huth
2251e8a1faeSThomas Huth s1 = g_strdup_printf("-drive id=drive%d,if=%s",
2261e8a1faeSThomas Huth ide_idx, dev ? "none" : "ide");
2271e8a1faeSThomas Huth s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx);
2281e8a1faeSThomas Huth
2291e8a1faeSThomas Huth if (img_secs[img_idx] >= 0) {
2301e8a1faeSThomas Huth setup_mbr(img_idx, mbr);
2311e8a1faeSThomas Huth s3 = g_strdup_printf(",format=raw,file=%s", img_file_name[img_idx]);
2321e8a1faeSThomas Huth } else {
2331e8a1faeSThomas Huth s3 = g_strdup(",media=cdrom");
2341e8a1faeSThomas Huth }
2351e8a1faeSThomas Huth argc = append_arg(argc, argv, argv_sz,
2361e8a1faeSThomas Huth g_strdup_printf("%s%s%s", s1, s2, s3));
2371e8a1faeSThomas Huth g_free(s1);
2381e8a1faeSThomas Huth g_free(s2);
2391e8a1faeSThomas Huth g_free(s3);
2401e8a1faeSThomas Huth
2411e8a1faeSThomas Huth if (dev) {
2421e8a1faeSThomas Huth argc = append_arg(argc, argv, argv_sz,
2431e8a1faeSThomas Huth g_strdup_printf("-device %s,drive=drive%d,"
2441e8a1faeSThomas Huth "bus=ide.%d,unit=%d",
2451e8a1faeSThomas Huth dev, ide_idx,
2461e8a1faeSThomas Huth ide_idx / 2, ide_idx % 2));
2471e8a1faeSThomas Huth }
2481e8a1faeSThomas Huth return argc;
2491e8a1faeSThomas Huth }
2501e8a1faeSThomas Huth
2511e8a1faeSThomas Huth /*
2521e8a1faeSThomas Huth * Test case: no IDE devices
2531e8a1faeSThomas Huth */
test_ide_none(void)2541e8a1faeSThomas Huth static void test_ide_none(void)
2551e8a1faeSThomas Huth {
2561e8a1faeSThomas Huth char **argv = g_new0(char *, ARGV_SIZE);
2571e8a1faeSThomas Huth char *args;
2581e8a1faeSThomas Huth QTestState *qts;
2591e8a1faeSThomas Huth
2601e8a1faeSThomas Huth setup_common(argv, ARGV_SIZE);
2611e8a1faeSThomas Huth args = g_strjoinv(" ", argv);
2621e8a1faeSThomas Huth qts = qtest_init(args);
2631e8a1faeSThomas Huth g_strfreev(argv);
2641e8a1faeSThomas Huth g_free(args);
2651e8a1faeSThomas Huth test_cmos(qts);
2661e8a1faeSThomas Huth qtest_quit(qts);
2671e8a1faeSThomas Huth }
2681e8a1faeSThomas Huth
test_ide_mbr(bool use_device,MBRcontents mbr)2691e8a1faeSThomas Huth static void test_ide_mbr(bool use_device, MBRcontents mbr)
2701e8a1faeSThomas Huth {
2711e8a1faeSThomas Huth char **argv = g_new0(char *, ARGV_SIZE);
2721e8a1faeSThomas Huth char *args;
2731e8a1faeSThomas Huth int argc;
2741e8a1faeSThomas Huth Backend i;
2751e8a1faeSThomas Huth const char *dev;
2761e8a1faeSThomas Huth QTestState *qts;
2771e8a1faeSThomas Huth
2781e8a1faeSThomas Huth argc = setup_common(argv, ARGV_SIZE);
2791e8a1faeSThomas Huth for (i = 0; i < backend_last; i++) {
2801e8a1faeSThomas Huth cur_ide[i] = &hd_chst[i][mbr];
2811e8a1faeSThomas Huth dev = use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : NULL;
2821e8a1faeSThomas Huth argc = setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr);
2831e8a1faeSThomas Huth }
2841e8a1faeSThomas Huth args = g_strjoinv(" ", argv);
2851e8a1faeSThomas Huth qts = qtest_init(args);
2861e8a1faeSThomas Huth g_strfreev(argv);
2871e8a1faeSThomas Huth g_free(args);
2881e8a1faeSThomas Huth test_cmos(qts);
2891e8a1faeSThomas Huth qtest_quit(qts);
2901e8a1faeSThomas Huth }
2911e8a1faeSThomas Huth
2921e8a1faeSThomas Huth /*
2931e8a1faeSThomas Huth * Test case: IDE devices (if=ide) with blank MBRs
2941e8a1faeSThomas Huth */
test_ide_drive_mbr_blank(void)2951e8a1faeSThomas Huth static void test_ide_drive_mbr_blank(void)
2961e8a1faeSThomas Huth {
2971e8a1faeSThomas Huth test_ide_mbr(false, mbr_blank);
2981e8a1faeSThomas Huth }
2991e8a1faeSThomas Huth
3001e8a1faeSThomas Huth /*
3011e8a1faeSThomas Huth * Test case: IDE devices (if=ide) with MBRs indicating LBA is in use
3021e8a1faeSThomas Huth */
test_ide_drive_mbr_lba(void)3031e8a1faeSThomas Huth static void test_ide_drive_mbr_lba(void)
3041e8a1faeSThomas Huth {
3051e8a1faeSThomas Huth test_ide_mbr(false, mbr_lba);
3061e8a1faeSThomas Huth }
3071e8a1faeSThomas Huth
3081e8a1faeSThomas Huth /*
3091e8a1faeSThomas Huth * Test case: IDE devices (if=ide) with MBRs indicating CHS is in use
3101e8a1faeSThomas Huth */
test_ide_drive_mbr_chs(void)3111e8a1faeSThomas Huth static void test_ide_drive_mbr_chs(void)
3121e8a1faeSThomas Huth {
3131e8a1faeSThomas Huth test_ide_mbr(false, mbr_chs);
3141e8a1faeSThomas Huth }
3151e8a1faeSThomas Huth
3161e8a1faeSThomas Huth /*
3171e8a1faeSThomas Huth * Test case: IDE devices (if=none) with blank MBRs
3181e8a1faeSThomas Huth */
test_ide_device_mbr_blank(void)3191e8a1faeSThomas Huth static void test_ide_device_mbr_blank(void)
3201e8a1faeSThomas Huth {
3211e8a1faeSThomas Huth test_ide_mbr(true, mbr_blank);
3221e8a1faeSThomas Huth }
3231e8a1faeSThomas Huth
3241e8a1faeSThomas Huth /*
3251e8a1faeSThomas Huth * Test case: IDE devices (if=none) with MBRs indicating LBA is in use
3261e8a1faeSThomas Huth */
test_ide_device_mbr_lba(void)3271e8a1faeSThomas Huth static void test_ide_device_mbr_lba(void)
3281e8a1faeSThomas Huth {
3291e8a1faeSThomas Huth test_ide_mbr(true, mbr_lba);
3301e8a1faeSThomas Huth }
3311e8a1faeSThomas Huth
3321e8a1faeSThomas Huth /*
3331e8a1faeSThomas Huth * Test case: IDE devices (if=none) with MBRs indicating CHS is in use
3341e8a1faeSThomas Huth */
test_ide_device_mbr_chs(void)3351e8a1faeSThomas Huth static void test_ide_device_mbr_chs(void)
3361e8a1faeSThomas Huth {
3371e8a1faeSThomas Huth test_ide_mbr(true, mbr_chs);
3381e8a1faeSThomas Huth }
3391e8a1faeSThomas Huth
test_ide_drive_user(const char * dev,bool trans)3401e8a1faeSThomas Huth static void test_ide_drive_user(const char *dev, bool trans)
3411e8a1faeSThomas Huth {
3421e8a1faeSThomas Huth char **argv = g_new0(char *, ARGV_SIZE);
3431e8a1faeSThomas Huth char *args, *opts;
3441e8a1faeSThomas Huth int argc;
3451e8a1faeSThomas Huth int secs = img_secs[backend_small];
3461e8a1faeSThomas Huth const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };
3471e8a1faeSThomas Huth QTestState *qts;
3481e8a1faeSThomas Huth
3491e8a1faeSThomas Huth argc = setup_common(argv, ARGV_SIZE);
3501e8a1faeSThomas Huth opts = g_strdup_printf("%s,%scyls=%d,heads=%d,secs=%d",
3511e8a1faeSThomas Huth dev, trans ? "bios-chs-trans=lba," : "",
3521e8a1faeSThomas Huth expected_chst.cyls, expected_chst.heads,
3531e8a1faeSThomas Huth expected_chst.secs);
3541e8a1faeSThomas Huth cur_ide[0] = &expected_chst;
3551e8a1faeSThomas Huth argc = setup_ide(argc, argv, ARGV_SIZE, 0, opts, backend_small, mbr_chs);
3561e8a1faeSThomas Huth g_free(opts);
3571e8a1faeSThomas Huth args = g_strjoinv(" ", argv);
3581e8a1faeSThomas Huth qts = qtest_init(args);
3591e8a1faeSThomas Huth g_strfreev(argv);
3601e8a1faeSThomas Huth g_free(args);
3611e8a1faeSThomas Huth test_cmos(qts);
3621e8a1faeSThomas Huth qtest_quit(qts);
3631e8a1faeSThomas Huth }
3641e8a1faeSThomas Huth
3651e8a1faeSThomas Huth /*
3661e8a1faeSThomas Huth * Test case: IDE device (if=none) with explicit CHS
3671e8a1faeSThomas Huth */
test_ide_device_user_chs(void)3681e8a1faeSThomas Huth static void test_ide_device_user_chs(void)
3691e8a1faeSThomas Huth {
3701e8a1faeSThomas Huth test_ide_drive_user("ide-hd", false);
3711e8a1faeSThomas Huth }
3721e8a1faeSThomas Huth
3731e8a1faeSThomas Huth /*
3741e8a1faeSThomas Huth * Test case: IDE device (if=none) with explicit CHS and translation
3751e8a1faeSThomas Huth */
test_ide_device_user_chst(void)3761e8a1faeSThomas Huth static void test_ide_device_user_chst(void)
3771e8a1faeSThomas Huth {
3781e8a1faeSThomas Huth test_ide_drive_user("ide-hd", true);
3791e8a1faeSThomas Huth }
3801e8a1faeSThomas Huth
3811e8a1faeSThomas Huth /*
3821e8a1faeSThomas Huth * Test case: IDE devices (if=ide), but use index=0 for CD-ROM
3831e8a1faeSThomas Huth */
test_ide_drive_cd_0(void)3841e8a1faeSThomas Huth static void test_ide_drive_cd_0(void)
3851e8a1faeSThomas Huth {
3861e8a1faeSThomas Huth char **argv = g_new0(char *, ARGV_SIZE);
3871e8a1faeSThomas Huth char *args;
3881e8a1faeSThomas Huth int argc, ide_idx;
3891e8a1faeSThomas Huth Backend i;
3901e8a1faeSThomas Huth QTestState *qts;
3911e8a1faeSThomas Huth
3921e8a1faeSThomas Huth argc = setup_common(argv, ARGV_SIZE);
3931e8a1faeSThomas Huth for (i = 0; i <= backend_empty; i++) {
3941e8a1faeSThomas Huth ide_idx = backend_empty - i;
3951e8a1faeSThomas Huth cur_ide[ide_idx] = &hd_chst[i][mbr_blank];
3961e8a1faeSThomas Huth argc = setup_ide(argc, argv, ARGV_SIZE, ide_idx, NULL, i, mbr_blank);
3971e8a1faeSThomas Huth }
3981e8a1faeSThomas Huth args = g_strjoinv(" ", argv);
3991e8a1faeSThomas Huth qts = qtest_init(args);
4001e8a1faeSThomas Huth g_strfreev(argv);
4011e8a1faeSThomas Huth g_free(args);
4021e8a1faeSThomas Huth test_cmos(qts);
4031e8a1faeSThomas Huth qtest_quit(qts);
4041e8a1faeSThomas Huth }
4051e8a1faeSThomas Huth
4061e8a1faeSThomas Huth typedef struct {
4071e8a1faeSThomas Huth bool active;
4081e8a1faeSThomas Huth uint32_t head;
4091e8a1faeSThomas Huth uint32_t sector;
4101e8a1faeSThomas Huth uint32_t cyl;
4111e8a1faeSThomas Huth uint32_t end_head;
4121e8a1faeSThomas Huth uint32_t end_sector;
4131e8a1faeSThomas Huth uint32_t end_cyl;
4141e8a1faeSThomas Huth uint32_t start_sect;
4151e8a1faeSThomas Huth uint32_t nr_sects;
4161e8a1faeSThomas Huth } MBRpartitions[4];
4171e8a1faeSThomas Huth
4181e8a1faeSThomas Huth static MBRpartitions empty_mbr = { {false, 0, 0, 0, 0, 0, 0, 0, 0},
4191e8a1faeSThomas Huth {false, 0, 0, 0, 0, 0, 0, 0, 0},
4201e8a1faeSThomas Huth {false, 0, 0, 0, 0, 0, 0, 0, 0},
4211e8a1faeSThomas Huth {false, 0, 0, 0, 0, 0, 0, 0, 0} };
4221e8a1faeSThomas Huth
create_qcow2_with_mbr(MBRpartitions mbr,uint64_t sectors)4231e8a1faeSThomas Huth static char *create_qcow2_with_mbr(MBRpartitions mbr, uint64_t sectors)
4241e8a1faeSThomas Huth {
42552ca92d6SBin Meng g_autofree char *raw_path = NULL;
42652ca92d6SBin Meng char *qcow2_path;
4271e8a1faeSThomas Huth char cmd[100 + 2 * PATH_MAX];
4286e9d611aSMarkus Armbruster uint8_t buf[512] = {};
4291e8a1faeSThomas Huth int i, ret, fd, offset;
4301e8a1faeSThomas Huth uint64_t qcow2_size = sectors * 512;
4311e8a1faeSThomas Huth uint8_t status, parttype, head, sector, cyl;
4321e8a1faeSThomas Huth char *qemu_img_path;
4331e8a1faeSThomas Huth char *qemu_img_abs_path;
4341e8a1faeSThomas Huth
4351e8a1faeSThomas Huth offset = 0xbe;
4361e8a1faeSThomas Huth
4371e8a1faeSThomas Huth for (i = 0; i < 4; i++) {
4381e8a1faeSThomas Huth status = mbr[i].active ? 0x80 : 0x00;
4391e8a1faeSThomas Huth g_assert(mbr[i].head < 256);
4401e8a1faeSThomas Huth g_assert(mbr[i].sector < 64);
4411e8a1faeSThomas Huth g_assert(mbr[i].cyl < 1024);
4421e8a1faeSThomas Huth head = mbr[i].head;
4431e8a1faeSThomas Huth sector = mbr[i].sector + ((mbr[i].cyl & 0x300) >> 2);
4441e8a1faeSThomas Huth cyl = mbr[i].cyl & 0xff;
4451e8a1faeSThomas Huth
4461e8a1faeSThomas Huth buf[offset + 0x0] = status;
4471e8a1faeSThomas Huth buf[offset + 0x1] = head;
4481e8a1faeSThomas Huth buf[offset + 0x2] = sector;
4491e8a1faeSThomas Huth buf[offset + 0x3] = cyl;
4501e8a1faeSThomas Huth
4511e8a1faeSThomas Huth parttype = 0;
4521e8a1faeSThomas Huth g_assert(mbr[i].end_head < 256);
4531e8a1faeSThomas Huth g_assert(mbr[i].end_sector < 64);
4541e8a1faeSThomas Huth g_assert(mbr[i].end_cyl < 1024);
4551e8a1faeSThomas Huth head = mbr[i].end_head;
4561e8a1faeSThomas Huth sector = mbr[i].end_sector + ((mbr[i].end_cyl & 0x300) >> 2);
4571e8a1faeSThomas Huth cyl = mbr[i].end_cyl & 0xff;
4581e8a1faeSThomas Huth
4591e8a1faeSThomas Huth buf[offset + 0x4] = parttype;
4601e8a1faeSThomas Huth buf[offset + 0x5] = head;
4611e8a1faeSThomas Huth buf[offset + 0x6] = sector;
4621e8a1faeSThomas Huth buf[offset + 0x7] = cyl;
4631e8a1faeSThomas Huth
4646e9d611aSMarkus Armbruster stl_le_p(&buf[offset + 0x8], mbr[i].start_sect);
4656e9d611aSMarkus Armbruster stl_le_p(&buf[offset + 0xc], mbr[i].nr_sects);
4661e8a1faeSThomas Huth
4671e8a1faeSThomas Huth offset += 0x10;
4681e8a1faeSThomas Huth }
4691e8a1faeSThomas Huth
47052ca92d6SBin Meng fd = g_file_open_tmp("qtest.XXXXXX", &raw_path, NULL);
4712c398ee5SPeter Maydell g_assert(fd >= 0);
4721e8a1faeSThomas Huth close(fd);
4731e8a1faeSThomas Huth
4741e8a1faeSThomas Huth fd = open(raw_path, O_WRONLY);
4751e8a1faeSThomas Huth g_assert(fd >= 0);
4761e8a1faeSThomas Huth ret = write(fd, buf, sizeof(buf));
4771e8a1faeSThomas Huth g_assert(ret == sizeof(buf));
4781e8a1faeSThomas Huth close(fd);
4791e8a1faeSThomas Huth
48052ca92d6SBin Meng fd = g_file_open_tmp("qtest.XXXXXX", &qcow2_path, NULL);
4812c398ee5SPeter Maydell g_assert(fd >= 0);
4821e8a1faeSThomas Huth close(fd);
4831e8a1faeSThomas Huth
4841e8a1faeSThomas Huth qemu_img_path = getenv("QTEST_QEMU_IMG");
4851e8a1faeSThomas Huth g_assert(qemu_img_path);
4861e8a1faeSThomas Huth qemu_img_abs_path = realpath(qemu_img_path, NULL);
4871e8a1faeSThomas Huth g_assert(qemu_img_abs_path);
4881e8a1faeSThomas Huth
4891e8a1faeSThomas Huth ret = snprintf(cmd, sizeof(cmd),
4901e8a1faeSThomas Huth "%s convert -f raw -O qcow2 %s %s > /dev/null",
4911e8a1faeSThomas Huth qemu_img_abs_path,
4921e8a1faeSThomas Huth raw_path, qcow2_path);
4931e8a1faeSThomas Huth g_assert((0 < ret) && (ret <= sizeof(cmd)));
4941e8a1faeSThomas Huth ret = system(cmd);
4951e8a1faeSThomas Huth g_assert(ret == 0);
4961e8a1faeSThomas Huth
4971e8a1faeSThomas Huth ret = snprintf(cmd, sizeof(cmd),
4981e8a1faeSThomas Huth "%s resize %s %" PRIu64 " > /dev/null",
4991e8a1faeSThomas Huth qemu_img_abs_path,
5001e8a1faeSThomas Huth qcow2_path, qcow2_size);
5011e8a1faeSThomas Huth g_assert((0 < ret) && (ret <= sizeof(cmd)));
5021e8a1faeSThomas Huth ret = system(cmd);
5031e8a1faeSThomas Huth g_assert(ret == 0);
5041e8a1faeSThomas Huth
5051e8a1faeSThomas Huth free(qemu_img_abs_path);
5061e8a1faeSThomas Huth
5071e8a1faeSThomas Huth unlink(raw_path);
5081e8a1faeSThomas Huth
5091e8a1faeSThomas Huth return qcow2_path;
5101e8a1faeSThomas Huth }
5111e8a1faeSThomas Huth
5121e8a1faeSThomas Huth #define BIOS_GEOMETRY_MAX_SIZE 10000
5131e8a1faeSThomas Huth
5141e8a1faeSThomas Huth typedef struct {
5151e8a1faeSThomas Huth uint32_t c;
5161e8a1faeSThomas Huth uint32_t h;
5171e8a1faeSThomas Huth uint32_t s;
5181e8a1faeSThomas Huth } CHS;
5191e8a1faeSThomas Huth
5201e8a1faeSThomas Huth typedef struct {
5211e8a1faeSThomas Huth const char *dev_path;
5221e8a1faeSThomas Huth CHS chs;
5231e8a1faeSThomas Huth } CHSResult;
5241e8a1faeSThomas Huth
read_bootdevices(QFWCFG * fw_cfg,CHSResult expected[])5251e8a1faeSThomas Huth static void read_bootdevices(QFWCFG *fw_cfg, CHSResult expected[])
5261e8a1faeSThomas Huth {
5271e8a1faeSThomas Huth char *buf = g_malloc0(BIOS_GEOMETRY_MAX_SIZE);
5281e8a1faeSThomas Huth char *cur;
5291e8a1faeSThomas Huth GList *results = NULL, *cur_result;
5301e8a1faeSThomas Huth CHSResult *r;
5311e8a1faeSThomas Huth int i;
5321e8a1faeSThomas Huth int res;
5331e8a1faeSThomas Huth bool found;
5341e8a1faeSThomas Huth
5351e8a1faeSThomas Huth qfw_cfg_get_file(fw_cfg, "bios-geometry", buf, BIOS_GEOMETRY_MAX_SIZE);
5361e8a1faeSThomas Huth
5371e8a1faeSThomas Huth for (cur = buf; *cur; cur++) {
5381e8a1faeSThomas Huth if (*cur == '\n') {
5391e8a1faeSThomas Huth *cur = '\0';
5401e8a1faeSThomas Huth }
5411e8a1faeSThomas Huth }
5421e8a1faeSThomas Huth cur = buf;
5431e8a1faeSThomas Huth
5441e8a1faeSThomas Huth while (strlen(cur)) {
5451e8a1faeSThomas Huth
5461e8a1faeSThomas Huth r = g_malloc0(sizeof(*r));
5471e8a1faeSThomas Huth r->dev_path = g_malloc0(strlen(cur) + 1);
5481e8a1faeSThomas Huth res = sscanf(cur, "%s %" PRIu32 " %" PRIu32 " %" PRIu32,
5491e8a1faeSThomas Huth (char *)r->dev_path,
5501e8a1faeSThomas Huth &(r->chs.c), &(r->chs.h), &(r->chs.s));
5511e8a1faeSThomas Huth
5521e8a1faeSThomas Huth g_assert(res == 4);
5531e8a1faeSThomas Huth
5541e8a1faeSThomas Huth results = g_list_prepend(results, r);
5551e8a1faeSThomas Huth
5561e8a1faeSThomas Huth cur += strlen(cur) + 1;
5571e8a1faeSThomas Huth }
5581e8a1faeSThomas Huth
5591e8a1faeSThomas Huth i = 0;
5601e8a1faeSThomas Huth
5611e8a1faeSThomas Huth while (expected[i].dev_path) {
5621e8a1faeSThomas Huth found = false;
5631e8a1faeSThomas Huth cur_result = results;
5641e8a1faeSThomas Huth while (cur_result) {
5651e8a1faeSThomas Huth r = cur_result->data;
5661e8a1faeSThomas Huth if (!strcmp(r->dev_path, expected[i].dev_path) &&
5671e8a1faeSThomas Huth !memcmp(&(r->chs), &(expected[i].chs), sizeof(r->chs))) {
5681e8a1faeSThomas Huth found = true;
5691e8a1faeSThomas Huth break;
5701e8a1faeSThomas Huth }
5711e8a1faeSThomas Huth cur_result = g_list_next(cur_result);
5721e8a1faeSThomas Huth }
5731e8a1faeSThomas Huth g_assert(found);
5741e8a1faeSThomas Huth g_free((char *)((CHSResult *)cur_result->data)->dev_path);
5751e8a1faeSThomas Huth g_free(cur_result->data);
5761e8a1faeSThomas Huth results = g_list_delete_link(results, cur_result);
5771e8a1faeSThomas Huth i++;
5781e8a1faeSThomas Huth }
5791e8a1faeSThomas Huth
5801e8a1faeSThomas Huth g_assert(results == NULL);
5811e8a1faeSThomas Huth
5821e8a1faeSThomas Huth g_free(buf);
5831e8a1faeSThomas Huth }
5841e8a1faeSThomas Huth
5851e8a1faeSThomas Huth #define MAX_DRIVES 30
5861e8a1faeSThomas Huth
5871e8a1faeSThomas Huth typedef struct {
5881e8a1faeSThomas Huth char **argv;
5891e8a1faeSThomas Huth int argc;
5901e8a1faeSThomas Huth char **drives;
5911e8a1faeSThomas Huth int n_drives;
5921e8a1faeSThomas Huth int n_scsi_disks;
5931e8a1faeSThomas Huth int n_scsi_controllers;
5941e8a1faeSThomas Huth int n_virtio_disks;
5951e8a1faeSThomas Huth } TestArgs;
5961e8a1faeSThomas Huth
create_args(void)5971e8a1faeSThomas Huth static TestArgs *create_args(void)
5981e8a1faeSThomas Huth {
5991e8a1faeSThomas Huth TestArgs *args = g_malloc0(sizeof(*args));
6001e8a1faeSThomas Huth args->argv = g_new0(char *, ARGV_SIZE);
6011e8a1faeSThomas Huth args->argc = append_arg(args->argc, args->argv,
6021e8a1faeSThomas Huth ARGV_SIZE, g_strdup("-nodefaults"));
6031e8a1faeSThomas Huth args->drives = g_new0(char *, MAX_DRIVES);
6041e8a1faeSThomas Huth return args;
6051e8a1faeSThomas Huth }
6061e8a1faeSThomas Huth
add_drive_with_mbr(TestArgs * args,MBRpartitions mbr,uint64_t sectors)6071e8a1faeSThomas Huth static void add_drive_with_mbr(TestArgs *args,
6081e8a1faeSThomas Huth MBRpartitions mbr, uint64_t sectors)
6091e8a1faeSThomas Huth {
6101e8a1faeSThomas Huth char *img_file_name;
6111e8a1faeSThomas Huth char part[300];
6121e8a1faeSThomas Huth int ret;
6131e8a1faeSThomas Huth
6141e8a1faeSThomas Huth g_assert(args->n_drives < MAX_DRIVES);
6151e8a1faeSThomas Huth
6161e8a1faeSThomas Huth img_file_name = create_qcow2_with_mbr(mbr, sectors);
6171e8a1faeSThomas Huth
6181e8a1faeSThomas Huth args->drives[args->n_drives] = img_file_name;
6191e8a1faeSThomas Huth ret = snprintf(part, sizeof(part),
6201e8a1faeSThomas Huth "-drive file=%s,if=none,format=qcow2,id=disk%d",
6211e8a1faeSThomas Huth img_file_name, args->n_drives);
6221e8a1faeSThomas Huth g_assert((0 < ret) && (ret <= sizeof(part)));
6231e8a1faeSThomas Huth args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
6241e8a1faeSThomas Huth args->n_drives++;
6251e8a1faeSThomas Huth }
6261e8a1faeSThomas Huth
add_ide_disk(TestArgs * args,int drive_idx,int bus,int unit,int c,int h,int s)6271e8a1faeSThomas Huth static void add_ide_disk(TestArgs *args,
6281e8a1faeSThomas Huth int drive_idx, int bus, int unit, int c, int h, int s)
6291e8a1faeSThomas Huth {
6301e8a1faeSThomas Huth char part[300];
6311e8a1faeSThomas Huth int ret;
6321e8a1faeSThomas Huth
6331e8a1faeSThomas Huth ret = snprintf(part, sizeof(part),
6341e8a1faeSThomas Huth "-device ide-hd,drive=disk%d,bus=ide.%d,unit=%d,"
6351e8a1faeSThomas Huth "lcyls=%d,lheads=%d,lsecs=%d",
6361e8a1faeSThomas Huth drive_idx, bus, unit, c, h, s);
6371e8a1faeSThomas Huth g_assert((0 < ret) && (ret <= sizeof(part)));
6381e8a1faeSThomas Huth args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
6391e8a1faeSThomas Huth }
6401e8a1faeSThomas Huth
add_scsi_controller(TestArgs * args,const char * type,const char * bus,int addr)6411e8a1faeSThomas Huth static void add_scsi_controller(TestArgs *args,
6421e8a1faeSThomas Huth const char *type,
6431e8a1faeSThomas Huth const char *bus,
6441e8a1faeSThomas Huth int addr)
6451e8a1faeSThomas Huth {
6461e8a1faeSThomas Huth char part[300];
6471e8a1faeSThomas Huth int ret;
6481e8a1faeSThomas Huth
6491e8a1faeSThomas Huth ret = snprintf(part, sizeof(part),
6501e8a1faeSThomas Huth "-device %s,id=scsi%d,bus=%s,addr=%d",
6511e8a1faeSThomas Huth type, args->n_scsi_controllers, bus, addr);
6521e8a1faeSThomas Huth g_assert((0 < ret) && (ret <= sizeof(part)));
6531e8a1faeSThomas Huth args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
6541e8a1faeSThomas Huth args->n_scsi_controllers++;
6551e8a1faeSThomas Huth }
6561e8a1faeSThomas Huth
add_scsi_disk(TestArgs * args,int drive_idx,int bus,int channel,int scsi_id,int lun,int c,int h,int s)6571e8a1faeSThomas Huth static void add_scsi_disk(TestArgs *args,
6581e8a1faeSThomas Huth int drive_idx, int bus,
6591e8a1faeSThomas Huth int channel, int scsi_id, int lun,
6601e8a1faeSThomas Huth int c, int h, int s)
6611e8a1faeSThomas Huth {
6621e8a1faeSThomas Huth char part[300];
6631e8a1faeSThomas Huth int ret;
6641e8a1faeSThomas Huth
6651e8a1faeSThomas Huth ret = snprintf(part, sizeof(part),
6661e8a1faeSThomas Huth "-device scsi-hd,id=scsi-disk%d,drive=disk%d,"
6671e8a1faeSThomas Huth "bus=scsi%d.0,"
6681e8a1faeSThomas Huth "channel=%d,scsi-id=%d,lun=%d,"
6691e8a1faeSThomas Huth "lcyls=%d,lheads=%d,lsecs=%d",
6701e8a1faeSThomas Huth args->n_scsi_disks, drive_idx, bus, channel, scsi_id, lun,
6711e8a1faeSThomas Huth c, h, s);
6721e8a1faeSThomas Huth g_assert((0 < ret) && (ret <= sizeof(part)));
6731e8a1faeSThomas Huth args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
6741e8a1faeSThomas Huth args->n_scsi_disks++;
6751e8a1faeSThomas Huth }
6761e8a1faeSThomas Huth
add_virtio_disk(TestArgs * args,int drive_idx,const char * bus,int addr,int c,int h,int s)6771e8a1faeSThomas Huth static void add_virtio_disk(TestArgs *args,
6781e8a1faeSThomas Huth int drive_idx, const char *bus, int addr,
6791e8a1faeSThomas Huth int c, int h, int s)
6801e8a1faeSThomas Huth {
6811e8a1faeSThomas Huth char part[300];
6821e8a1faeSThomas Huth int ret;
6831e8a1faeSThomas Huth
6841e8a1faeSThomas Huth ret = snprintf(part, sizeof(part),
6851e8a1faeSThomas Huth "-device virtio-blk-pci,id=virtio-disk%d,"
6861e8a1faeSThomas Huth "drive=disk%d,bus=%s,addr=%d,"
6871e8a1faeSThomas Huth "lcyls=%d,lheads=%d,lsecs=%d",
6881e8a1faeSThomas Huth args->n_virtio_disks, drive_idx, bus, addr, c, h, s);
6891e8a1faeSThomas Huth g_assert((0 < ret) && (ret <= sizeof(part)));
6901e8a1faeSThomas Huth args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, g_strdup(part));
6911e8a1faeSThomas Huth args->n_virtio_disks++;
6921e8a1faeSThomas Huth }
6931e8a1faeSThomas Huth
test_override(TestArgs * args,const char * arch,CHSResult expected[])69419bc7e3eSMichael Labiuk static void test_override(TestArgs *args, const char *arch,
69519bc7e3eSMichael Labiuk CHSResult expected[])
6961e8a1faeSThomas Huth {
6971e8a1faeSThomas Huth QTestState *qts;
6981e8a1faeSThomas Huth char *joined_args;
6991e8a1faeSThomas Huth QFWCFG *fw_cfg;
7001e8a1faeSThomas Huth int i;
7011e8a1faeSThomas Huth
7021e8a1faeSThomas Huth joined_args = g_strjoinv(" ", args->argv);
7031e8a1faeSThomas Huth
70419bc7e3eSMichael Labiuk qts = qtest_initf("-machine %s %s", arch, joined_args);
7051e8a1faeSThomas Huth fw_cfg = pc_fw_cfg_init(qts);
7061e8a1faeSThomas Huth
7071e8a1faeSThomas Huth read_bootdevices(fw_cfg, expected);
7081e8a1faeSThomas Huth
7091e8a1faeSThomas Huth g_free(joined_args);
7101e8a1faeSThomas Huth qtest_quit(qts);
7111e8a1faeSThomas Huth
7121e8a1faeSThomas Huth g_free(fw_cfg);
7131e8a1faeSThomas Huth
7141e8a1faeSThomas Huth for (i = 0; i < args->n_drives; i++) {
7151e8a1faeSThomas Huth unlink(args->drives[i]);
71652ca92d6SBin Meng g_free(args->drives[i]);
7171e8a1faeSThomas Huth }
7181e8a1faeSThomas Huth g_free(args->drives);
7191e8a1faeSThomas Huth g_strfreev(args->argv);
7201e8a1faeSThomas Huth g_free(args);
7211e8a1faeSThomas Huth }
7221e8a1faeSThomas Huth
test_override_ide(void)7231e8a1faeSThomas Huth static void test_override_ide(void)
7241e8a1faeSThomas Huth {
7251e8a1faeSThomas Huth TestArgs *args = create_args();
7261e8a1faeSThomas Huth CHSResult expected[] = {
7271e8a1faeSThomas Huth {"/pci@i0cf8/ide@1,1/drive@0/disk@0", {10000, 120, 30} },
7281e8a1faeSThomas Huth {"/pci@i0cf8/ide@1,1/drive@0/disk@1", {9000, 120, 30} },
7291e8a1faeSThomas Huth {"/pci@i0cf8/ide@1,1/drive@1/disk@0", {0, 1, 1} },
7301e8a1faeSThomas Huth {"/pci@i0cf8/ide@1,1/drive@1/disk@1", {1, 0, 0} },
7311e8a1faeSThomas Huth {NULL, {0, 0, 0} }
7321e8a1faeSThomas Huth };
7331e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7341e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7351e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7361e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7371e8a1faeSThomas Huth add_ide_disk(args, 0, 0, 0, 10000, 120, 30);
7381e8a1faeSThomas Huth add_ide_disk(args, 1, 0, 1, 9000, 120, 30);
7391e8a1faeSThomas Huth add_ide_disk(args, 2, 1, 0, 0, 1, 1);
7401e8a1faeSThomas Huth add_ide_disk(args, 3, 1, 1, 1, 0, 0);
74119bc7e3eSMichael Labiuk test_override(args, "pc", expected);
7421e8a1faeSThomas Huth }
7431e8a1faeSThomas Huth
test_override_sata(void)744c46b1260SMichael Labiuk static void test_override_sata(void)
745c46b1260SMichael Labiuk {
746c46b1260SMichael Labiuk TestArgs *args = create_args();
747c46b1260SMichael Labiuk CHSResult expected[] = {
748c46b1260SMichael Labiuk {"/pci@i0cf8/pci8086,2922@1f,2/drive@0/disk@0", {10000, 120, 30} },
749c46b1260SMichael Labiuk {"/pci@i0cf8/pci8086,2922@1f,2/drive@1/disk@0", {9000, 120, 30} },
750c46b1260SMichael Labiuk {"/pci@i0cf8/pci8086,2922@1f,2/drive@2/disk@0", {0, 1, 1} },
751c46b1260SMichael Labiuk {"/pci@i0cf8/pci8086,2922@1f,2/drive@3/disk@0", {1, 0, 0} },
752c46b1260SMichael Labiuk {NULL, {0, 0, 0} }
753c46b1260SMichael Labiuk };
754c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
755c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
756c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
757c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
758c46b1260SMichael Labiuk add_ide_disk(args, 0, 0, 0, 10000, 120, 30);
759c46b1260SMichael Labiuk add_ide_disk(args, 1, 1, 0, 9000, 120, 30);
760c46b1260SMichael Labiuk add_ide_disk(args, 2, 2, 0, 0, 1, 1);
761c46b1260SMichael Labiuk add_ide_disk(args, 3, 3, 0, 1, 0, 0);
762c46b1260SMichael Labiuk test_override(args, "q35", expected);
763c46b1260SMichael Labiuk }
764c46b1260SMichael Labiuk
test_override_scsi(void)7651e8a1faeSThomas Huth static void test_override_scsi(void)
7661e8a1faeSThomas Huth {
7671e8a1faeSThomas Huth TestArgs *args = create_args();
7681e8a1faeSThomas Huth CHSResult expected[] = {
7691e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/channel@0/disk@0,0", {10000, 120, 30} },
7701e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/channel@0/disk@1,0", {9000, 120, 30} },
7711e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/channel@0/disk@2,0", {1, 0, 0} },
7721e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/channel@0/disk@3,0", {0, 1, 0} },
7731e8a1faeSThomas Huth {NULL, {0, 0, 0} }
7741e8a1faeSThomas Huth };
7751e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7761e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7771e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7781e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
7791e8a1faeSThomas Huth add_scsi_controller(args, "lsi53c895a", "pci.0", 3);
7801e8a1faeSThomas Huth add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
7811e8a1faeSThomas Huth add_scsi_disk(args, 1, 0, 0, 1, 0, 9000, 120, 30);
7821e8a1faeSThomas Huth add_scsi_disk(args, 2, 0, 0, 2, 0, 1, 0, 0);
7831e8a1faeSThomas Huth add_scsi_disk(args, 3, 0, 0, 3, 0, 0, 1, 0);
78419bc7e3eSMichael Labiuk test_override(args, "pc", expected);
7851e8a1faeSThomas Huth }
7861e8a1faeSThomas Huth
setup_pci_bridge(TestArgs * args,const char * id)787579edbd4SAni Sinha static void setup_pci_bridge(TestArgs *args, const char *id)
788c46b1260SMichael Labiuk {
789c46b1260SMichael Labiuk
790579edbd4SAni Sinha char *br;
791579edbd4SAni Sinha br = g_strdup_printf("-device pcie-pci-bridge,bus=pcie.0,id=%s", id);
792c46b1260SMichael Labiuk
793c46b1260SMichael Labiuk args->argc = append_arg(args->argc, args->argv, ARGV_SIZE, br);
794c46b1260SMichael Labiuk }
795c46b1260SMichael Labiuk
test_override_scsi_q35(void)796c46b1260SMichael Labiuk static void test_override_scsi_q35(void)
797c46b1260SMichael Labiuk {
798c46b1260SMichael Labiuk TestArgs *args = create_args();
799c46b1260SMichael Labiuk CHSResult expected[] = {
800c46b1260SMichael Labiuk { "/pci@i0cf8/pci-bridge@1/scsi@3/channel@0/disk@0,0",
801c46b1260SMichael Labiuk {10000, 120, 30}
802c46b1260SMichael Labiuk },
803c46b1260SMichael Labiuk {"/pci@i0cf8/pci-bridge@1/scsi@3/channel@0/disk@1,0", {9000, 120, 30} },
804c46b1260SMichael Labiuk {"/pci@i0cf8/pci-bridge@1/scsi@3/channel@0/disk@2,0", {1, 0, 0} },
805c46b1260SMichael Labiuk {"/pci@i0cf8/pci-bridge@1/scsi@3/channel@0/disk@3,0", {0, 1, 0} },
806c46b1260SMichael Labiuk {NULL, {0, 0, 0} }
807c46b1260SMichael Labiuk };
808c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
809c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
810c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
811c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
812579edbd4SAni Sinha setup_pci_bridge(args, "pcie-pci-br");
813579edbd4SAni Sinha add_scsi_controller(args, "lsi53c895a", "pcie-pci-br", 3);
814c46b1260SMichael Labiuk add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
815c46b1260SMichael Labiuk add_scsi_disk(args, 1, 0, 0, 1, 0, 9000, 120, 30);
816c46b1260SMichael Labiuk add_scsi_disk(args, 2, 0, 0, 2, 0, 1, 0, 0);
817c46b1260SMichael Labiuk add_scsi_disk(args, 3, 0, 0, 3, 0, 0, 1, 0);
818c46b1260SMichael Labiuk test_override(args, "q35", expected);
819c46b1260SMichael Labiuk }
820c46b1260SMichael Labiuk
test_override_scsi_2_controllers(void)8211e8a1faeSThomas Huth static void test_override_scsi_2_controllers(void)
8221e8a1faeSThomas Huth {
8231e8a1faeSThomas Huth TestArgs *args = create_args();
8241e8a1faeSThomas Huth CHSResult expected[] = {
8251e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/channel@0/disk@0,0", {10000, 120, 30} },
8261e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/channel@0/disk@1,0", {9000, 120, 30} },
8271e8a1faeSThomas Huth {"/pci@i0cf8/scsi@4/channel@0/disk@0,1", {1, 0, 0} },
8281e8a1faeSThomas Huth {"/pci@i0cf8/scsi@4/channel@0/disk@1,2", {0, 1, 0} },
8291e8a1faeSThomas Huth {NULL, {0, 0, 0} }
8301e8a1faeSThomas Huth };
8311e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
8321e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
8331e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
8341e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
8351e8a1faeSThomas Huth add_scsi_controller(args, "lsi53c895a", "pci.0", 3);
8361e8a1faeSThomas Huth add_scsi_controller(args, "virtio-scsi-pci", "pci.0", 4);
8371e8a1faeSThomas Huth add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
8381e8a1faeSThomas Huth add_scsi_disk(args, 1, 0, 0, 1, 0, 9000, 120, 30);
8391e8a1faeSThomas Huth add_scsi_disk(args, 2, 1, 0, 0, 1, 1, 0, 0);
8401e8a1faeSThomas Huth add_scsi_disk(args, 3, 1, 0, 1, 2, 0, 1, 0);
84119bc7e3eSMichael Labiuk test_override(args, "pc", expected);
8421e8a1faeSThomas Huth }
8431e8a1faeSThomas Huth
test_override_virtio_blk(void)8441e8a1faeSThomas Huth static void test_override_virtio_blk(void)
8451e8a1faeSThomas Huth {
8461e8a1faeSThomas Huth TestArgs *args = create_args();
8471e8a1faeSThomas Huth CHSResult expected[] = {
8481e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/disk@0,0", {10000, 120, 30} },
8491e8a1faeSThomas Huth {"/pci@i0cf8/scsi@4/disk@0,0", {9000, 120, 30} },
8501e8a1faeSThomas Huth {NULL, {0, 0, 0} }
8511e8a1faeSThomas Huth };
8521e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
8531e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
8541e8a1faeSThomas Huth add_virtio_disk(args, 0, "pci.0", 3, 10000, 120, 30);
8551e8a1faeSThomas Huth add_virtio_disk(args, 1, "pci.0", 4, 9000, 120, 30);
85619bc7e3eSMichael Labiuk test_override(args, "pc", expected);
8571e8a1faeSThomas Huth }
8581e8a1faeSThomas Huth
test_override_virtio_blk_q35(void)859c46b1260SMichael Labiuk static void test_override_virtio_blk_q35(void)
860c46b1260SMichael Labiuk {
861c46b1260SMichael Labiuk TestArgs *args = create_args();
862c46b1260SMichael Labiuk CHSResult expected[] = {
863c46b1260SMichael Labiuk {"/pci@i0cf8/pci-bridge@1/scsi@3/disk@0,0", {10000, 120, 30} },
864c46b1260SMichael Labiuk {"/pci@i0cf8/pci-bridge@1/scsi@4/disk@0,0", {9000, 120, 30} },
865c46b1260SMichael Labiuk {NULL, {0, 0, 0} }
866c46b1260SMichael Labiuk };
867c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
868c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
869579edbd4SAni Sinha setup_pci_bridge(args, "pcie-pci-br");
870579edbd4SAni Sinha add_virtio_disk(args, 0, "pcie-pci-br", 3, 10000, 120, 30);
871579edbd4SAni Sinha add_virtio_disk(args, 1, "pcie-pci-br", 4, 9000, 120, 30);
872c46b1260SMichael Labiuk test_override(args, "q35", expected);
873c46b1260SMichael Labiuk }
874c46b1260SMichael Labiuk
test_override_zero_chs(void)8751e8a1faeSThomas Huth static void test_override_zero_chs(void)
8761e8a1faeSThomas Huth {
8771e8a1faeSThomas Huth TestArgs *args = create_args();
8781e8a1faeSThomas Huth CHSResult expected[] = {
8791e8a1faeSThomas Huth {NULL, {0, 0, 0} }
8801e8a1faeSThomas Huth };
8811e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
8821e8a1faeSThomas Huth add_ide_disk(args, 0, 1, 1, 0, 0, 0);
88319bc7e3eSMichael Labiuk test_override(args, "pc", expected);
8841e8a1faeSThomas Huth }
8851e8a1faeSThomas Huth
test_override_zero_chs_q35(void)886c46b1260SMichael Labiuk static void test_override_zero_chs_q35(void)
887c46b1260SMichael Labiuk {
888c46b1260SMichael Labiuk TestArgs *args = create_args();
889c46b1260SMichael Labiuk CHSResult expected[] = {
890c46b1260SMichael Labiuk {NULL, {0, 0, 0} }
891c46b1260SMichael Labiuk };
892c46b1260SMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
893c46b1260SMichael Labiuk add_ide_disk(args, 0, 0, 0, 0, 0, 0);
894c46b1260SMichael Labiuk test_override(args, "q35", expected);
895c46b1260SMichael Labiuk }
896c46b1260SMichael Labiuk
test_override_hot_unplug(TestArgs * args,const char * devid,CHSResult expected[],CHSResult expected2[])89719bc7e3eSMichael Labiuk static void test_override_hot_unplug(TestArgs *args, const char *devid,
89819bc7e3eSMichael Labiuk CHSResult expected[], CHSResult expected2[])
8991e8a1faeSThomas Huth {
9001e8a1faeSThomas Huth QTestState *qts;
9011e8a1faeSThomas Huth char *joined_args;
9021e8a1faeSThomas Huth QFWCFG *fw_cfg;
9031e8a1faeSThomas Huth QDict *response;
9041e8a1faeSThomas Huth int i;
90519bc7e3eSMichael Labiuk
90619bc7e3eSMichael Labiuk joined_args = g_strjoinv(" ", args->argv);
90719bc7e3eSMichael Labiuk
90819bc7e3eSMichael Labiuk qts = qtest_initf("%s", joined_args);
90919bc7e3eSMichael Labiuk fw_cfg = pc_fw_cfg_init(qts);
91019bc7e3eSMichael Labiuk
91119bc7e3eSMichael Labiuk read_bootdevices(fw_cfg, expected);
91219bc7e3eSMichael Labiuk
91319bc7e3eSMichael Labiuk /* unplug device an restart */
91419bc7e3eSMichael Labiuk qtest_qmp_device_del_send(qts, devid);
91519bc7e3eSMichael Labiuk
91619bc7e3eSMichael Labiuk response = qtest_qmp(qts,
91719bc7e3eSMichael Labiuk "{ 'execute': 'system_reset', 'arguments': { }}");
91819bc7e3eSMichael Labiuk g_assert(response);
91919bc7e3eSMichael Labiuk g_assert(!qdict_haskey(response, "error"));
92019bc7e3eSMichael Labiuk qobject_unref(response);
92119bc7e3eSMichael Labiuk
92219bc7e3eSMichael Labiuk qtest_qmp_eventwait(qts, "RESET");
92319bc7e3eSMichael Labiuk
92419bc7e3eSMichael Labiuk read_bootdevices(fw_cfg, expected2);
92519bc7e3eSMichael Labiuk
92619bc7e3eSMichael Labiuk g_free(joined_args);
92719bc7e3eSMichael Labiuk qtest_quit(qts);
92819bc7e3eSMichael Labiuk
92919bc7e3eSMichael Labiuk g_free(fw_cfg);
93019bc7e3eSMichael Labiuk
93119bc7e3eSMichael Labiuk for (i = 0; i < args->n_drives; i++) {
93219bc7e3eSMichael Labiuk unlink(args->drives[i]);
93319bc7e3eSMichael Labiuk g_free(args->drives[i]);
93419bc7e3eSMichael Labiuk }
93519bc7e3eSMichael Labiuk g_free(args->drives);
93619bc7e3eSMichael Labiuk g_strfreev(args->argv);
93719bc7e3eSMichael Labiuk g_free(args);
93819bc7e3eSMichael Labiuk }
93919bc7e3eSMichael Labiuk
test_override_scsi_hot_unplug(void)94019bc7e3eSMichael Labiuk static void test_override_scsi_hot_unplug(void)
94119bc7e3eSMichael Labiuk {
9421e8a1faeSThomas Huth TestArgs *args = create_args();
9431e8a1faeSThomas Huth CHSResult expected[] = {
9441e8a1faeSThomas Huth {"/pci@i0cf8/scsi@2/channel@0/disk@0,0", {10000, 120, 30} },
9451e8a1faeSThomas Huth {"/pci@i0cf8/scsi@2/channel@0/disk@1,0", {20, 20, 20} },
9461e8a1faeSThomas Huth {NULL, {0, 0, 0} }
9471e8a1faeSThomas Huth };
9481e8a1faeSThomas Huth CHSResult expected2[] = {
9491e8a1faeSThomas Huth {"/pci@i0cf8/scsi@2/channel@0/disk@1,0", {20, 20, 20} },
9501e8a1faeSThomas Huth {NULL, {0, 0, 0} }
9511e8a1faeSThomas Huth };
9521e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
9531e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
9541e8a1faeSThomas Huth add_scsi_controller(args, "virtio-scsi-pci", "pci.0", 2);
9551e8a1faeSThomas Huth add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
9561e8a1faeSThomas Huth add_scsi_disk(args, 1, 0, 0, 1, 0, 20, 20, 20);
9571e8a1faeSThomas Huth
95819bc7e3eSMichael Labiuk args->argc = append_arg(args->argc, args->argv, ARGV_SIZE,
95919bc7e3eSMichael Labiuk g_strdup("-machine pc"));
9601e8a1faeSThomas Huth
96119bc7e3eSMichael Labiuk test_override_hot_unplug(args, "scsi-disk0", expected, expected2);
9621e8a1faeSThomas Huth }
9631e8a1faeSThomas Huth
test_override_scsi_hot_unplug_q35(void)964a30433ddSMichael Labiuk static void test_override_scsi_hot_unplug_q35(void)
965a30433ddSMichael Labiuk {
966a30433ddSMichael Labiuk TestArgs *args = create_args();
967a30433ddSMichael Labiuk CHSResult expected[] = {
968a30433ddSMichael Labiuk {
969a30433ddSMichael Labiuk "/pci@i0cf8/pci-bridge@1/pci-bridge@0/scsi@2/channel@0/disk@0,0",
970a30433ddSMichael Labiuk {10000, 120, 30}
971a30433ddSMichael Labiuk },
972a30433ddSMichael Labiuk {
973a30433ddSMichael Labiuk "/pci@i0cf8/pci-bridge@1/pci-bridge@0/scsi@2/channel@0/disk@1,0",
974a30433ddSMichael Labiuk {20, 20, 20}
975a30433ddSMichael Labiuk },
976a30433ddSMichael Labiuk {NULL, {0, 0, 0} }
977a30433ddSMichael Labiuk };
978a30433ddSMichael Labiuk CHSResult expected2[] = {
979a30433ddSMichael Labiuk {
980a30433ddSMichael Labiuk "/pci@i0cf8/pci-bridge@1/pci-bridge@0/scsi@2/channel@0/disk@1,0",
981a30433ddSMichael Labiuk {20, 20, 20}
982a30433ddSMichael Labiuk },
983a30433ddSMichael Labiuk {NULL, {0, 0, 0} }
984a30433ddSMichael Labiuk };
985a30433ddSMichael Labiuk
986a30433ddSMichael Labiuk args->argc = append_arg(args->argc, args->argv, ARGV_SIZE,
987a30433ddSMichael Labiuk g_strdup("-device pcie-root-port,id=p0 "
988a30433ddSMichael Labiuk "-device pcie-pci-bridge,bus=p0,id=b1 "
989a30433ddSMichael Labiuk "-machine q35"));
990a30433ddSMichael Labiuk
991a30433ddSMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
992a30433ddSMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
993a30433ddSMichael Labiuk add_scsi_controller(args, "virtio-scsi-pci", "b1", 2);
994a30433ddSMichael Labiuk add_scsi_disk(args, 0, 0, 0, 0, 0, 10000, 120, 30);
995a30433ddSMichael Labiuk add_scsi_disk(args, 1, 0, 0, 1, 0, 20, 20, 20);
996a30433ddSMichael Labiuk
997a30433ddSMichael Labiuk test_override_hot_unplug(args, "scsi-disk0", expected, expected2);
998a30433ddSMichael Labiuk }
999a30433ddSMichael Labiuk
test_override_virtio_hot_unplug(void)10001e8a1faeSThomas Huth static void test_override_virtio_hot_unplug(void)
10011e8a1faeSThomas Huth {
10021e8a1faeSThomas Huth TestArgs *args = create_args();
10031e8a1faeSThomas Huth CHSResult expected[] = {
10041e8a1faeSThomas Huth {"/pci@i0cf8/scsi@2/disk@0,0", {10000, 120, 30} },
10051e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/disk@0,0", {20, 20, 20} },
10061e8a1faeSThomas Huth {NULL, {0, 0, 0} }
10071e8a1faeSThomas Huth };
10081e8a1faeSThomas Huth CHSResult expected2[] = {
10091e8a1faeSThomas Huth {"/pci@i0cf8/scsi@3/disk@0,0", {20, 20, 20} },
10101e8a1faeSThomas Huth {NULL, {0, 0, 0} }
10111e8a1faeSThomas Huth };
10121e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
10131e8a1faeSThomas Huth add_drive_with_mbr(args, empty_mbr, 1);
10141e8a1faeSThomas Huth add_virtio_disk(args, 0, "pci.0", 2, 10000, 120, 30);
10151e8a1faeSThomas Huth add_virtio_disk(args, 1, "pci.0", 3, 20, 20, 20);
10161e8a1faeSThomas Huth
101719bc7e3eSMichael Labiuk args->argc = append_arg(args->argc, args->argv, ARGV_SIZE,
101819bc7e3eSMichael Labiuk g_strdup("-machine pc"));
10191e8a1faeSThomas Huth
102019bc7e3eSMichael Labiuk test_override_hot_unplug(args, "virtio-disk0", expected, expected2);
10211e8a1faeSThomas Huth }
10221e8a1faeSThomas Huth
test_override_virtio_hot_unplug_q35(void)1023a30433ddSMichael Labiuk static void test_override_virtio_hot_unplug_q35(void)
1024a30433ddSMichael Labiuk {
1025a30433ddSMichael Labiuk TestArgs *args = create_args();
1026a30433ddSMichael Labiuk CHSResult expected[] = {
1027a30433ddSMichael Labiuk {
1028a30433ddSMichael Labiuk "/pci@i0cf8/pci-bridge@1/pci-bridge@0/scsi@2/disk@0,0",
1029a30433ddSMichael Labiuk {10000, 120, 30}
1030a30433ddSMichael Labiuk },
1031a30433ddSMichael Labiuk {
1032a30433ddSMichael Labiuk "/pci@i0cf8/pci-bridge@1/pci-bridge@0/scsi@3/disk@0,0",
1033a30433ddSMichael Labiuk {20, 20, 20}
1034a30433ddSMichael Labiuk },
1035a30433ddSMichael Labiuk {NULL, {0, 0, 0} }
1036a30433ddSMichael Labiuk };
1037a30433ddSMichael Labiuk CHSResult expected2[] = {
1038a30433ddSMichael Labiuk {
1039a30433ddSMichael Labiuk "/pci@i0cf8/pci-bridge@1/pci-bridge@0/scsi@3/disk@0,0",
1040a30433ddSMichael Labiuk {20, 20, 20}
1041a30433ddSMichael Labiuk },
1042a30433ddSMichael Labiuk {NULL, {0, 0, 0} }
1043a30433ddSMichael Labiuk };
1044a30433ddSMichael Labiuk
1045a30433ddSMichael Labiuk args->argc = append_arg(args->argc, args->argv, ARGV_SIZE,
1046a30433ddSMichael Labiuk g_strdup("-device pcie-root-port,id=p0 "
1047a30433ddSMichael Labiuk "-device pcie-pci-bridge,bus=p0,id=b1 "
1048a30433ddSMichael Labiuk "-machine q35"));
1049a30433ddSMichael Labiuk
1050a30433ddSMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
1051a30433ddSMichael Labiuk add_drive_with_mbr(args, empty_mbr, 1);
1052a30433ddSMichael Labiuk add_virtio_disk(args, 0, "b1", 2, 10000, 120, 30);
1053a30433ddSMichael Labiuk add_virtio_disk(args, 1, "b1", 3, 20, 20, 20);
1054a30433ddSMichael Labiuk
1055a30433ddSMichael Labiuk test_override_hot_unplug(args, "virtio-disk0", expected, expected2);
1056a30433ddSMichael Labiuk }
1057a30433ddSMichael Labiuk
main(int argc,char ** argv)10581e8a1faeSThomas Huth int main(int argc, char **argv)
10591e8a1faeSThomas Huth {
10601e8a1faeSThomas Huth Backend i;
10611e8a1faeSThomas Huth int ret;
10621e8a1faeSThomas Huth
10631e8a1faeSThomas Huth g_test_init(&argc, &argv, NULL);
10641e8a1faeSThomas Huth
10651e8a1faeSThomas Huth for (i = 0; i < backend_last; i++) {
10661e8a1faeSThomas Huth if (img_secs[i] >= 0) {
10671e8a1faeSThomas Huth img_file_name[i] = create_test_img(img_secs[i]);
10681e8a1faeSThomas Huth if (!img_file_name[i]) {
10691e8a1faeSThomas Huth g_test_message("Could not create test images.");
10701e8a1faeSThomas Huth goto test_add_done;
10711e8a1faeSThomas Huth }
10721e8a1faeSThomas Huth } else {
10731e8a1faeSThomas Huth img_file_name[i] = NULL;
10741e8a1faeSThomas Huth }
10751e8a1faeSThomas Huth }
10761e8a1faeSThomas Huth
1077*d98894d8SThomas Huth if (qtest_has_machine("pc")) {
10781e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/none", test_ide_none);
10791e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank);
10801e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba);
10811e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs);
10821e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0);
10831e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blank);
10841e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba);
10851e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/device/mbr/chs", test_ide_device_mbr_chs);
10861e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/device/user/chs", test_ide_device_user_chs);
10871e8a1faeSThomas Huth qtest_add_func("hd-geo/ide/device/user/chst", test_ide_device_user_chst);
1088*d98894d8SThomas Huth }
1089*d98894d8SThomas Huth
1090*d98894d8SThomas Huth if (!have_qemu_img()) {
1091*d98894d8SThomas Huth g_test_message("QTEST_QEMU_IMG not set or qemu-img missing; "
1092*d98894d8SThomas Huth "skipping hd-geo/override/* tests");
1093*d98894d8SThomas Huth goto test_add_done;
1094*d98894d8SThomas Huth }
1095*d98894d8SThomas Huth
1096*d98894d8SThomas Huth if (qtest_has_machine("pc")) {
10971e8a1faeSThomas Huth qtest_add_func("hd-geo/override/ide", test_override_ide);
1098961fb4b4SThomas Huth if (qtest_has_device("lsi53c895a")) {
10991e8a1faeSThomas Huth qtest_add_func("hd-geo/override/scsi", test_override_scsi);
1100a2da5e2fSFabiano Rosas if (qtest_has_device("virtio-scsi-pci")) {
11011e8a1faeSThomas Huth qtest_add_func("hd-geo/override/scsi_2_controllers",
11021e8a1faeSThomas Huth test_override_scsi_2_controllers);
1103961fb4b4SThomas Huth }
1104a2da5e2fSFabiano Rosas }
11051e8a1faeSThomas Huth qtest_add_func("hd-geo/override/zero_chs", test_override_zero_chs);
1106a2da5e2fSFabiano Rosas if (qtest_has_device("virtio-scsi-pci")) {
11071e8a1faeSThomas Huth qtest_add_func("hd-geo/override/scsi_hot_unplug",
11081e8a1faeSThomas Huth test_override_scsi_hot_unplug);
1109a2da5e2fSFabiano Rosas }
1110a2da5e2fSFabiano Rosas if (qtest_has_device("virtio-blk-pci")) {
11111e8a1faeSThomas Huth qtest_add_func("hd-geo/override/virtio_hot_unplug",
11121e8a1faeSThomas Huth test_override_virtio_hot_unplug);
1113a2da5e2fSFabiano Rosas qtest_add_func("hd-geo/override/virtio_blk",
1114a2da5e2fSFabiano Rosas test_override_virtio_blk);
1115a2da5e2fSFabiano Rosas }
1116*d98894d8SThomas Huth }
1117c46b1260SMichael Labiuk
1118c46b1260SMichael Labiuk if (qtest_has_machine("q35")) {
1119c46b1260SMichael Labiuk qtest_add_func("hd-geo/override/sata", test_override_sata);
1120c46b1260SMichael Labiuk qtest_add_func("hd-geo/override/zero_chs_q35",
1121c46b1260SMichael Labiuk test_override_zero_chs_q35);
1122c46b1260SMichael Labiuk if (qtest_has_device("lsi53c895a")) {
1123c46b1260SMichael Labiuk qtest_add_func("hd-geo/override/scsi_q35",
1124c46b1260SMichael Labiuk test_override_scsi_q35);
1125c46b1260SMichael Labiuk }
1126a2da5e2fSFabiano Rosas if (qtest_has_device("virtio-scsi-pci")) {
1127a30433ddSMichael Labiuk qtest_add_func("hd-geo/override/scsi_hot_unplug_q35",
1128a30433ddSMichael Labiuk test_override_scsi_hot_unplug_q35);
1129a2da5e2fSFabiano Rosas }
1130a2da5e2fSFabiano Rosas if (qtest_has_device("virtio-blk-pci")) {
1131a30433ddSMichael Labiuk qtest_add_func("hd-geo/override/virtio_hot_unplug_q35",
1132a30433ddSMichael Labiuk test_override_virtio_hot_unplug_q35);
1133a2da5e2fSFabiano Rosas qtest_add_func("hd-geo/override/virtio_blk_q35",
1134a2da5e2fSFabiano Rosas test_override_virtio_blk_q35);
1135a2da5e2fSFabiano Rosas }
11361e8a1faeSThomas Huth }
11371e8a1faeSThomas Huth
11381e8a1faeSThomas Huth test_add_done:
11391e8a1faeSThomas Huth ret = g_test_run();
11401e8a1faeSThomas Huth
11411e8a1faeSThomas Huth for (i = 0; i < backend_last; i++) {
11421e8a1faeSThomas Huth if (img_file_name[i]) {
11431e8a1faeSThomas Huth unlink(img_file_name[i]);
114452ca92d6SBin Meng g_free(img_file_name[i]);
11451e8a1faeSThomas Huth }
11461e8a1faeSThomas Huth }
11471e8a1faeSThomas Huth
11481e8a1faeSThomas Huth return ret;
11491e8a1faeSThomas Huth }
1150