qemu/tests/boot-order-test.c
<<
>>
Prefs
   1/*
   2 * Boot order test cases.
   3 *
   4 * Copyright (c) 2013 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#include "qemu/osdep.h"
  14#include "libqos/fw_cfg.h"
  15#include "libqtest.h"
  16
  17#include "hw/nvram/fw_cfg_keys.h"
  18
  19typedef struct {
  20    const char *args;
  21    uint64_t expected_boot;
  22    uint64_t expected_reboot;
  23} boot_order_test;
  24
  25static void test_a_boot_order(const char *machine,
  26                              const char *test_args,
  27                              uint64_t (*read_boot_order)(void),
  28                              uint64_t expected_boot,
  29                              uint64_t expected_reboot)
  30{
  31    uint64_t actual;
  32
  33    global_qtest = qtest_startf("-nodefaults%s%s %s",
  34                                machine ? " -M " : "",
  35                                machine ?: "",
  36                                test_args);
  37    actual = read_boot_order();
  38    g_assert_cmphex(actual, ==, expected_boot);
  39    qmp_discard_response("{ 'execute': 'system_reset' }");
  40    /*
  41     * system_reset only requests reset.  We get a RESET event after
  42     * the actual reset completes.  Need to wait for that.
  43     */
  44    qmp_eventwait("RESET");
  45    actual = read_boot_order();
  46    g_assert_cmphex(actual, ==, expected_reboot);
  47    qtest_quit(global_qtest);
  48}
  49
  50static void test_boot_orders(const char *machine,
  51                             uint64_t (*read_boot_order)(void),
  52                             const boot_order_test *tests)
  53{
  54    int i;
  55
  56    for (i = 0; tests[i].args; i++) {
  57        test_a_boot_order(machine, tests[i].args,
  58                          read_boot_order,
  59                          tests[i].expected_boot,
  60                          tests[i].expected_reboot);
  61    }
  62}
  63
  64static uint8_t read_mc146818(uint16_t port, uint8_t reg)
  65{
  66    outb(port, reg);
  67    return inb(port + 1);
  68}
  69
  70static uint64_t read_boot_order_pc(void)
  71{
  72    uint8_t b1 = read_mc146818(0x70, 0x38);
  73    uint8_t b2 = read_mc146818(0x70, 0x3d);
  74
  75    return b1 | (b2 << 8);
  76}
  77
  78static const boot_order_test test_cases_pc[] = {
  79    { "",
  80      0x1230, 0x1230 },
  81    { "-no-fd-bootchk",
  82      0x1231, 0x1231 },
  83    { "-boot c",
  84      0x0200, 0x0200 },
  85    { "-boot nda",
  86      0x3410, 0x3410 },
  87    { "-boot order=",
  88      0, 0 },
  89    { "-boot order= -boot order=c",
  90      0x0200, 0x0200 },
  91    { "-boot once=a",
  92      0x0100, 0x1230 },
  93    { "-boot once=a -no-fd-bootchk",
  94      0x0101, 0x1231 },
  95    { "-boot once=a,order=c",
  96      0x0100, 0x0200 },
  97    { "-boot once=d -boot order=nda",
  98      0x0300, 0x3410 },
  99    { "-boot once=a -boot once=b -boot once=c",
 100      0x0200, 0x1230 },
 101    {}
 102};
 103
 104static void test_pc_boot_order(void)
 105{
 106    test_boot_orders(NULL, read_boot_order_pc, test_cases_pc);
 107}
 108
 109static uint8_t read_m48t59(uint64_t addr, uint16_t reg)
 110{
 111    writeb(addr, reg & 0xff);
 112    writeb(addr + 1, reg >> 8);
 113    return readb(addr + 3);
 114}
 115
 116static uint64_t read_boot_order_prep(void)
 117{
 118    return read_m48t59(0x80000000 + 0x74, 0x34);
 119}
 120
 121static const boot_order_test test_cases_prep[] = {
 122    { "", 'c', 'c' },
 123    { "-boot c", 'c', 'c' },
 124    { "-boot d", 'd', 'd' },
 125    {}
 126};
 127
 128static void test_prep_boot_order(void)
 129{
 130    test_boot_orders("prep", read_boot_order_prep, test_cases_prep);
 131}
 132
 133static uint64_t read_boot_order_pmac(void)
 134{
 135    QFWCFG *fw_cfg = mm_fw_cfg_init(global_qtest, 0xf0000510);
 136
 137    return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE);
 138}
 139
 140static const boot_order_test test_cases_fw_cfg[] = {
 141    { "", 'c', 'c' },
 142    { "-boot c", 'c', 'c' },
 143    { "-boot d", 'd', 'd' },
 144    { "-boot once=d,order=c", 'd', 'c' },
 145    {}
 146};
 147
 148static void test_pmac_oldworld_boot_order(void)
 149{
 150    test_boot_orders("g3beige", read_boot_order_pmac, test_cases_fw_cfg);
 151}
 152
 153static void test_pmac_newworld_boot_order(void)
 154{
 155    test_boot_orders("mac99", read_boot_order_pmac, test_cases_fw_cfg);
 156}
 157
 158static uint64_t read_boot_order_sun4m(void)
 159{
 160    QFWCFG *fw_cfg = mm_fw_cfg_init(global_qtest, 0xd00000510ULL);
 161
 162    return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE);
 163}
 164
 165static void test_sun4m_boot_order(void)
 166{
 167    test_boot_orders("SS-5", read_boot_order_sun4m, test_cases_fw_cfg);
 168}
 169
 170static uint64_t read_boot_order_sun4u(void)
 171{
 172    QFWCFG *fw_cfg = io_fw_cfg_init(global_qtest, 0x510);
 173
 174    return qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_DEVICE);
 175}
 176
 177static void test_sun4u_boot_order(void)
 178{
 179    test_boot_orders("sun4u", read_boot_order_sun4u, test_cases_fw_cfg);
 180}
 181
 182int main(int argc, char *argv[])
 183{
 184    const char *arch = qtest_get_arch();
 185
 186    g_test_init(&argc, &argv, NULL);
 187
 188    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
 189        qtest_add_func("boot-order/pc", test_pc_boot_order);
 190    } else if (strcmp(arch, "ppc") == 0 || strcmp(arch, "ppc64") == 0) {
 191        qtest_add_func("boot-order/prep", test_prep_boot_order);
 192        qtest_add_func("boot-order/pmac_oldworld",
 193                       test_pmac_oldworld_boot_order);
 194        qtest_add_func("boot-order/pmac_newworld",
 195                       test_pmac_newworld_boot_order);
 196    } else if (strcmp(arch, "sparc") == 0) {
 197        qtest_add_func("boot-order/sun4m", test_sun4m_boot_order);
 198    } else if (strcmp(arch, "sparc64") == 0) {
 199        qtest_add_func("boot-order/sun4u", test_sun4u_boot_order);
 200    }
 201
 202    return g_test_run();
 203}
 204