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