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