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