11e8a1faeSThomas Huth /* 21e8a1faeSThomas Huth * Boot order test cases. 31e8a1faeSThomas Huth * 41e8a1faeSThomas Huth * Copyright (c) 2013 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 #include "qemu/osdep.h" 141e8a1faeSThomas Huth #include "libqos/fw_cfg.h" 15907b5105SMarc-André Lureau #include "libqtest.h" 161e8a1faeSThomas Huth #include "qapi/qmp/qdict.h" 171e8a1faeSThomas Huth #include "standard-headers/linux/qemu_fw_cfg.h" 181e8a1faeSThomas Huth 191e8a1faeSThomas Huth typedef struct { 201e8a1faeSThomas Huth const char *args; 211e8a1faeSThomas Huth uint64_t expected_boot; 221e8a1faeSThomas Huth uint64_t expected_reboot; 231e8a1faeSThomas Huth } boot_order_test; 241e8a1faeSThomas Huth 251e8a1faeSThomas Huth static void test_a_boot_order(const char *machine, 261e8a1faeSThomas Huth const char *test_args, 271e8a1faeSThomas Huth uint64_t (*read_boot_order)(QTestState *), 281e8a1faeSThomas Huth uint64_t expected_boot, 291e8a1faeSThomas Huth uint64_t expected_reboot) 301e8a1faeSThomas Huth { 311e8a1faeSThomas Huth uint64_t actual; 321e8a1faeSThomas Huth QTestState *qts; 331e8a1faeSThomas Huth 34*0a8ecb41SThomas Huth if (!qtest_has_machine(machine)) { 35d6a3dd74SThomas Huth g_test_skip("Machine is not available"); 36d6a3dd74SThomas Huth return; 37d6a3dd74SThomas Huth } 38d6a3dd74SThomas Huth 391e8a1faeSThomas Huth qts = qtest_initf("-nodefaults%s%s %s", machine ? " -M " : "", 401e8a1faeSThomas Huth machine ?: "", test_args); 411e8a1faeSThomas Huth actual = read_boot_order(qts); 421e8a1faeSThomas Huth g_assert_cmphex(actual, ==, expected_boot); 43855436dbSDaniel P. Berrangé qtest_qmp_assert_success(qts, "{ 'execute': 'system_reset' }"); 441e8a1faeSThomas Huth /* 451e8a1faeSThomas Huth * system_reset only requests reset. We get a RESET event after 461e8a1faeSThomas Huth * the actual reset completes. Need to wait for that. 471e8a1faeSThomas Huth */ 481e8a1faeSThomas Huth qtest_qmp_eventwait(qts, "RESET"); 491e8a1faeSThomas Huth actual = read_boot_order(qts); 501e8a1faeSThomas Huth g_assert_cmphex(actual, ==, expected_reboot); 511e8a1faeSThomas Huth qtest_quit(qts); 521e8a1faeSThomas Huth } 531e8a1faeSThomas Huth 541e8a1faeSThomas Huth static void test_boot_orders(const char *machine, 551e8a1faeSThomas Huth uint64_t (*read_boot_order)(QTestState *), 561e8a1faeSThomas Huth const boot_order_test *tests) 571e8a1faeSThomas Huth { 581e8a1faeSThomas Huth int i; 591e8a1faeSThomas Huth 601e8a1faeSThomas Huth for (i = 0; tests[i].args; i++) { 611e8a1faeSThomas Huth test_a_boot_order(machine, tests[i].args, 621e8a1faeSThomas Huth read_boot_order, 631e8a1faeSThomas Huth tests[i].expected_boot, 641e8a1faeSThomas Huth tests[i].expected_reboot); 651e8a1faeSThomas Huth } 661e8a1faeSThomas Huth } 671e8a1faeSThomas Huth 681e8a1faeSThomas Huth static uint8_t read_mc146818(QTestState *qts, uint16_t port, uint8_t reg) 691e8a1faeSThomas Huth { 701e8a1faeSThomas Huth qtest_outb(qts, port, reg); 711e8a1faeSThomas Huth return qtest_inb(qts, port + 1); 721e8a1faeSThomas Huth } 731e8a1faeSThomas Huth 741e8a1faeSThomas Huth static uint64_t read_boot_order_pc(QTestState *qts) 751e8a1faeSThomas Huth { 761e8a1faeSThomas Huth uint8_t b1 = read_mc146818(qts, 0x70, 0x38); 771e8a1faeSThomas Huth uint8_t b2 = read_mc146818(qts, 0x70, 0x3d); 781e8a1faeSThomas Huth 791e8a1faeSThomas Huth return b1 | (b2 << 8); 801e8a1faeSThomas Huth } 811e8a1faeSThomas Huth 821e8a1faeSThomas Huth static const boot_order_test test_cases_pc[] = { 831e8a1faeSThomas Huth { "", 841e8a1faeSThomas Huth 0x1230, 0x1230 }, 851e8a1faeSThomas Huth { "-no-fd-bootchk", 861e8a1faeSThomas Huth 0x1231, 0x1231 }, 871e8a1faeSThomas Huth { "-boot c", 881e8a1faeSThomas Huth 0x0200, 0x0200 }, 891e8a1faeSThomas Huth { "-boot nda", 901e8a1faeSThomas Huth 0x3410, 0x3410 }, 911e8a1faeSThomas Huth { "-boot order=", 921e8a1faeSThomas Huth 0, 0 }, 931e8a1faeSThomas Huth { "-boot order= -boot order=c", 941e8a1faeSThomas Huth 0x0200, 0x0200 }, 951e8a1faeSThomas Huth { "-boot once=a", 961e8a1faeSThomas Huth 0x0100, 0x1230 }, 971e8a1faeSThomas Huth { "-boot once=a -no-fd-bootchk", 981e8a1faeSThomas Huth 0x0101, 0x1231 }, 991e8a1faeSThomas Huth { "-boot once=a,order=c", 1001e8a1faeSThomas Huth 0x0100, 0x0200 }, 1011e8a1faeSThomas Huth { "-boot once=d -boot order=nda", 1021e8a1faeSThomas Huth 0x0300, 0x3410 }, 1031e8a1faeSThomas Huth { "-boot once=a -boot once=b -boot once=c", 1041e8a1faeSThomas Huth 0x0200, 0x1230 }, 1051e8a1faeSThomas Huth {} 1061e8a1faeSThomas Huth }; 1071e8a1faeSThomas Huth 1081e8a1faeSThomas Huth static void test_pc_boot_order(void) 1091e8a1faeSThomas Huth { 110*0a8ecb41SThomas Huth test_boot_orders("pc", read_boot_order_pc, test_cases_pc); 1111e8a1faeSThomas Huth } 1121e8a1faeSThomas Huth 1131e8a1faeSThomas Huth static uint64_t read_boot_order_pmac(QTestState *qts) 1141e8a1faeSThomas Huth { 11577c24259SPan Nengyuan g_autoptr(QFWCFG) fw_cfg = mm_fw_cfg_init(qts, 0xf0000510); 1161e8a1faeSThomas Huth 1171e8a1faeSThomas Huth return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE); 1181e8a1faeSThomas Huth } 1191e8a1faeSThomas Huth 1201e8a1faeSThomas Huth static const boot_order_test test_cases_fw_cfg[] = { 1211e8a1faeSThomas Huth { "", 'c', 'c' }, 1221e8a1faeSThomas Huth { "-boot c", 'c', 'c' }, 1231e8a1faeSThomas Huth { "-boot d", 'd', 'd' }, 1241e8a1faeSThomas Huth { "-boot once=d,order=c", 'd', 'c' }, 1251e8a1faeSThomas Huth {} 1261e8a1faeSThomas Huth }; 1271e8a1faeSThomas Huth 1281e8a1faeSThomas Huth static void test_pmac_oldworld_boot_order(void) 1291e8a1faeSThomas Huth { 1301e8a1faeSThomas Huth test_boot_orders("g3beige", read_boot_order_pmac, test_cases_fw_cfg); 1311e8a1faeSThomas Huth } 1321e8a1faeSThomas Huth 1331e8a1faeSThomas Huth static void test_pmac_newworld_boot_order(void) 1341e8a1faeSThomas Huth { 1351e8a1faeSThomas Huth test_boot_orders("mac99", read_boot_order_pmac, test_cases_fw_cfg); 1361e8a1faeSThomas Huth } 1371e8a1faeSThomas Huth 1381e8a1faeSThomas Huth static uint64_t read_boot_order_sun4m(QTestState *qts) 1391e8a1faeSThomas Huth { 14077c24259SPan Nengyuan g_autoptr(QFWCFG) fw_cfg = mm_fw_cfg_init(qts, 0xd00000510ULL); 1411e8a1faeSThomas Huth 1421e8a1faeSThomas Huth return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE); 1431e8a1faeSThomas Huth } 1441e8a1faeSThomas Huth 1451e8a1faeSThomas Huth static void test_sun4m_boot_order(void) 1461e8a1faeSThomas Huth { 1471e8a1faeSThomas Huth test_boot_orders("SS-5", read_boot_order_sun4m, test_cases_fw_cfg); 1481e8a1faeSThomas Huth } 1491e8a1faeSThomas Huth 1501e8a1faeSThomas Huth static uint64_t read_boot_order_sun4u(QTestState *qts) 1511e8a1faeSThomas Huth { 15277c24259SPan Nengyuan g_autoptr(QFWCFG) fw_cfg = io_fw_cfg_init(qts, 0x510); 1531e8a1faeSThomas Huth 1541e8a1faeSThomas Huth return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE); 1551e8a1faeSThomas Huth } 1561e8a1faeSThomas Huth 1571e8a1faeSThomas Huth static void test_sun4u_boot_order(void) 1581e8a1faeSThomas Huth { 1591e8a1faeSThomas Huth test_boot_orders("sun4u", read_boot_order_sun4u, test_cases_fw_cfg); 1601e8a1faeSThomas Huth } 1611e8a1faeSThomas Huth 1621e8a1faeSThomas Huth int main(int argc, char *argv[]) 1631e8a1faeSThomas Huth { 1641e8a1faeSThomas Huth const char *arch = qtest_get_arch(); 1651e8a1faeSThomas Huth 1661e8a1faeSThomas Huth g_test_init(&argc, &argv, NULL); 1671e8a1faeSThomas Huth 1681e8a1faeSThomas Huth if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 1691e8a1faeSThomas Huth qtest_add_func("boot-order/pc", test_pc_boot_order); 1701e8a1faeSThomas Huth } else if (strcmp(arch, "ppc") == 0 || strcmp(arch, "ppc64") == 0) { 1711e8a1faeSThomas Huth qtest_add_func("boot-order/pmac_oldworld", 1721e8a1faeSThomas Huth test_pmac_oldworld_boot_order); 1731e8a1faeSThomas Huth qtest_add_func("boot-order/pmac_newworld", 1741e8a1faeSThomas Huth test_pmac_newworld_boot_order); 1751e8a1faeSThomas Huth } else if (strcmp(arch, "sparc") == 0) { 1761e8a1faeSThomas Huth qtest_add_func("boot-order/sun4m", test_sun4m_boot_order); 1771e8a1faeSThomas Huth } else if (strcmp(arch, "sparc64") == 0) { 1781e8a1faeSThomas Huth qtest_add_func("boot-order/sun4u", test_sun4u_boot_order); 1791e8a1faeSThomas Huth } 1801e8a1faeSThomas Huth 1811e8a1faeSThomas Huth return g_test_run(); 1821e8a1faeSThomas Huth } 183