xref: /qemu/tests/qtest/prom-env-test.c (revision 3e40bdb15e2ba6e55ee92d148b0cefb7050fad20)
1fcbf4a3cSThomas Huth /*
2b95b5a0aSThomas Huth  * Test Open-Firmware-based machines.
3fcbf4a3cSThomas Huth  *
4b95b5a0aSThomas Huth  * Copyright (c) 2016, 2017 Red Hat Inc.
5fcbf4a3cSThomas Huth  *
6fcbf4a3cSThomas Huth  * Author:
7fcbf4a3cSThomas Huth  *    Thomas Huth <thuth@redhat.com>
8fcbf4a3cSThomas Huth  *
9fcbf4a3cSThomas Huth  * This work is licensed under the terms of the GNU GPL, version 2
10fcbf4a3cSThomas Huth  * or later. See the COPYING file in the top-level directory.
11fcbf4a3cSThomas Huth  *
1253687348SDavid Gibson  * This test is used to check that some Open Firmware based machines (i.e.
1353687348SDavid Gibson  * OpenBIOS or SLOF) can be started successfully in TCG mode. To do this, we
1453687348SDavid Gibson  * first put some Forth code into the "boot-command" Open Firmware environment
1553687348SDavid Gibson  * variable. This Forth code writes a well-known magic value to a known location
1653687348SDavid Gibson  * in memory. Then we start the guest so that the firmware can boot and finally
1753687348SDavid Gibson  * run the Forth code.
18fcbf4a3cSThomas Huth  * The testing code here then can finally check whether the value has been
19fcbf4a3cSThomas Huth  * successfully written into the guest memory.
20fcbf4a3cSThomas Huth  */
21fcbf4a3cSThomas Huth 
22fcbf4a3cSThomas Huth #include "qemu/osdep.h"
23907b5105SMarc-André Lureau #include "libqtest.h"
24*3e40bdb1SNicholas Piggin #include "ppc-util.h"
25fcbf4a3cSThomas Huth 
26fcbf4a3cSThomas Huth #define MAGIC   0xcafec0de
27fcbf4a3cSThomas Huth #define ADDRESS 0x4000
28fcbf4a3cSThomas Huth 
check_guest_memory(QTestState * qts)29dc4c1587SThomas Huth static void check_guest_memory(QTestState *qts)
30fcbf4a3cSThomas Huth {
31fcbf4a3cSThomas Huth     uint32_t signature;
32fcbf4a3cSThomas Huth     int i;
33fcbf4a3cSThomas Huth 
34b95b5a0aSThomas Huth     /* Poll until code has run and modified memory. Wait at most 600 seconds */
35b95b5a0aSThomas Huth     for (i = 0; i < 60000; ++i) {
36dc4c1587SThomas Huth         signature = qtest_readl(qts, ADDRESS);
37fcbf4a3cSThomas Huth         if (signature == MAGIC) {
38fcbf4a3cSThomas Huth             break;
39fcbf4a3cSThomas Huth         }
40fcbf4a3cSThomas Huth         g_usleep(10000);
41fcbf4a3cSThomas Huth     }
42fcbf4a3cSThomas Huth 
43fcbf4a3cSThomas Huth     g_assert_cmphex(signature, ==, MAGIC);
44fcbf4a3cSThomas Huth }
45fcbf4a3cSThomas Huth 
test_machine(const void * machine)46fcbf4a3cSThomas Huth static void test_machine(const void *machine)
47fcbf4a3cSThomas Huth {
48ba3b40deSDavid Gibson     const char *extra_args = "";
49dc4c1587SThomas Huth     QTestState *qts;
50fcbf4a3cSThomas Huth 
51ba3b40deSDavid Gibson     /*
52ba3b40deSDavid Gibson      * The pseries firmware boots much faster without the default
53ba3b40deSDavid Gibson      * devices, it also needs Spectre/Meltdown workarounds disabled to
54ba3b40deSDavid Gibson      * avoid warnings with TCG
55ba3b40deSDavid Gibson      */
56ba3b40deSDavid Gibson     if (strcmp(machine, "pseries") == 0) {
57ba3b40deSDavid Gibson         extra_args = "-nodefaults"
5863d57c8fSGreg Kurz             " -machine " PSERIES_DEFAULT_CAPABILITIES;
59ba3b40deSDavid Gibson     }
6061eedf7aSThomas Huth 
6194add6eeSBin Meng     qts = qtest_initf("-M %s -accel tcg %s -prom-env \"use-nvramrc?=true\" "
6294add6eeSBin Meng                       "-prom-env \"nvramrc=%x %x l!\" ", (const char *)machine,
63dc4c1587SThomas Huth                       extra_args, MAGIC, ADDRESS);
64dc4c1587SThomas Huth     check_guest_memory(qts);
65dc4c1587SThomas Huth     qtest_quit(qts);
66fcbf4a3cSThomas Huth }
67fcbf4a3cSThomas Huth 
add_tests(const char * machines[])68fcbf4a3cSThomas Huth static void add_tests(const char *machines[])
69fcbf4a3cSThomas Huth {
70fcbf4a3cSThomas Huth     int i;
71fcbf4a3cSThomas Huth     char *name;
72fcbf4a3cSThomas Huth 
73fcbf4a3cSThomas Huth     for (i = 0; machines[i] != NULL; i++) {
74719051caSThomas Huth         if (qtest_has_machine(machines[i])) {
75fcbf4a3cSThomas Huth             name = g_strdup_printf("prom-env/%s", machines[i]);
76fcbf4a3cSThomas Huth             qtest_add_data_func(name, machines[i], test_machine);
77fcbf4a3cSThomas Huth             g_free(name);
78fcbf4a3cSThomas Huth         }
79fcbf4a3cSThomas Huth     }
80719051caSThomas Huth }
81fcbf4a3cSThomas Huth 
main(int argc,char * argv[])82fcbf4a3cSThomas Huth int main(int argc, char *argv[])
83fcbf4a3cSThomas Huth {
84fcbf4a3cSThomas Huth     const char *sparc_machines[] = { "SPARCbook", "Voyager", "SS-20", NULL };
856b591ad6SThomas Huth     const char *sparc64_machines[] = { "sun4u", NULL };
8653687348SDavid Gibson     const char *ppc_machines[] = { "mac99", "g3beige", NULL };
87fcbf4a3cSThomas Huth     const char *arch = qtest_get_arch();
88fcbf4a3cSThomas Huth 
89fcbf4a3cSThomas Huth     g_test_init(&argc, &argv, NULL);
90fcbf4a3cSThomas Huth 
9153687348SDavid Gibson     if (!strcmp(arch, "ppc")) {
9253687348SDavid Gibson         add_tests(ppc_machines);
9353687348SDavid Gibson     } else if (!strcmp(arch, "ppc64")) {
94b95b5a0aSThomas Huth         add_tests(ppc_machines);
95b95b5a0aSThomas Huth         if (g_test_slow()) {
96b95b5a0aSThomas Huth             qtest_add_data_func("prom-env/pseries", "pseries", test_machine);
97b95b5a0aSThomas Huth         }
98fcbf4a3cSThomas Huth     } else if (!strcmp(arch, "sparc")) {
99fcbf4a3cSThomas Huth         add_tests(sparc_machines);
100fcbf4a3cSThomas Huth     } else if (!strcmp(arch, "sparc64")) {
101fcbf4a3cSThomas Huth         add_tests(sparc64_machines);
102fcbf4a3cSThomas Huth     } else {
103fcbf4a3cSThomas Huth         g_assert_not_reached();
104fcbf4a3cSThomas Huth     }
105fcbf4a3cSThomas Huth 
106fcbf4a3cSThomas Huth     return g_test_run();
107fcbf4a3cSThomas Huth }
108