1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include "qemu/osdep.h"
17#include "libqtest.h"
18#include "libqos/libqos-spapr.h"
19
20static const uint8_t bios_avr[] = {
21 0x88, 0xe0,
22 0x80, 0x93, 0xc1, 0x00,
23 0x86, 0xe0,
24 0x80, 0x93, 0xc2, 0x00,
25 0x84, 0xe5,
26 0x80, 0x93, 0xc6, 0x00,
27};
28
29static const uint8_t kernel_mcf5208[] = {
30 0x41, 0xf9, 0xfc, 0x06, 0x00, 0x00,
31 0x10, 0x3c, 0x00, 0x54,
32 0x11, 0x7c, 0x00, 0x04, 0x00, 0x08,
33 0x11, 0x40, 0x00, 0x0c,
34 0x60, 0xfa
35};
36
37static const uint8_t bios_nextcube[] = {
38 0x06, 0x00, 0x00, 0x00,
39 0x01, 0x00, 0x00, 0x08,
40 0x41, 0xf9, 0x02, 0x11, 0x80, 0x00,
41 0x10, 0x3c, 0x00, 0x54,
42 0x11, 0x7c, 0x00, 0x05, 0x00, 0x01,
43 0x11, 0x7c, 0x00, 0x68, 0x00, 0x01,
44 0x11, 0x40, 0x00, 0x03,
45 0x60, 0xfa
46};
47
48static const uint8_t kernel_pls3adsp1800[] = {
49 0xb0, 0x00, 0x84, 0x00,
50 0x30, 0x60, 0x00, 0x04,
51 0x30, 0x80, 0x00, 0x54,
52 0xf0, 0x83, 0x00, 0x00,
53 0xb8, 0x00, 0xff, 0xfc
54};
55
56static const uint8_t kernel_plml605[] = {
57 0xe0, 0x83, 0x00, 0xb0,
58 0x00, 0x10, 0x60, 0x30,
59 0x54, 0x00, 0x80, 0x30,
60 0x00, 0x00, 0x83, 0xf0,
61 0xfc, 0xff, 0x00, 0xb8
62};
63
64static const uint8_t bios_raspi2[] = {
65 0x08, 0x30, 0x9f, 0xe5,
66 0x54, 0x20, 0xa0, 0xe3,
67 0x00, 0x20, 0xc3, 0xe5,
68 0xfb, 0xff, 0xff, 0xea,
69 0x00, 0x10, 0x20, 0x3f,
70};
71
72static const uint8_t kernel_aarch64[] = {
73 0x81, 0x0a, 0x80, 0x52,
74 0x02, 0x20, 0xa1, 0xd2,
75 0x41, 0x00, 0x00, 0x39,
76 0xfd, 0xff, 0xff, 0x17,
77};
78
79static const uint8_t kernel_nrf51[] = {
80 0x00, 0x00, 0x00, 0x00,
81 0x09, 0x00, 0x00, 0x00,
82 0x04, 0x4a,
83 0x04, 0x21,
84 0x11, 0x60,
85 0x04, 0x4a,
86 0x01, 0x21,
87 0x11, 0x60,
88 0x03, 0x4a,
89 0x54, 0x21,
90 0x11, 0x60,
91 0xfe, 0xe7,
92 0x00, 0x25, 0x00, 0x40,
93 0x08, 0x20, 0x00, 0x40,
94 0x1c, 0x25, 0x00, 0x40
95};
96
97static const uint8_t kernel_stm32vldiscovery[] = {
98 0x00, 0x00, 0x00, 0x00,
99 0x1d, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00,
105 0x0b, 0x4b,
106 0x44, 0xf2, 0x04, 0x02,
107 0x1a, 0x60,
108 0x0a, 0x4b,
109 0x1a, 0x68,
110 0x22, 0xf0, 0xf0, 0x02,
111 0x1a, 0x60,
112 0x1a, 0x68,
113 0x42, 0xf0, 0xb0, 0x02,
114 0x1a, 0x60,
115 0x07, 0x4b,
116 0x45, 0x22,
117 0x1a, 0x60,
118 0x06, 0x4b,
119 0x42, 0xf2, 0x08, 0x02,
120 0x1a, 0x60,
121 0x05, 0x4b,
122 0x54, 0x22,
123 0x1a, 0x60,
124 0xfe, 0xe7,
125 0x18, 0x10, 0x02, 0x40,
126 0x04, 0x08, 0x01, 0x40,
127 0x08, 0x38, 0x01, 0x40,
128 0x0c, 0x38, 0x01, 0x40,
129 0x04, 0x38, 0x01, 0x40
130};
131
132typedef struct testdef {
133 const char *arch;
134 const char *machine;
135 const char *extra;
136 const char *expect;
137 size_t codesize;
138 const uint8_t *kernel;
139 const uint8_t *bios;
140} testdef_t;
141
142static const testdef_t tests[] = {
143 { "alpha", "clipper", "", "PCI:" },
144 { "avr", "arduino-duemilanove", "", "T", sizeof(bios_avr), NULL, bios_avr },
145 { "avr", "arduino-mega-2560-v3", "", "T", sizeof(bios_avr), NULL, bios_avr},
146 { "ppc", "ppce500", "", "U-Boot" },
147 { "ppc", "40p", "-vga none -boot d", "Trying cd:," },
148 { "ppc", "g3beige", "", "PowerPC,750" },
149 { "ppc", "mac99", "", "PowerPC,G4" },
150 { "ppc", "sam460ex", "-m 256", "DRAM: 256 MiB" },
151 { "ppc64", "ppce500", "", "U-Boot" },
152 { "ppc64", "40p", "-m 192", "Memory: 192M" },
153 { "ppc64", "mac99", "", "PowerPC,970FX" },
154 { "ppc64", "pseries",
155 "-machine " PSERIES_DEFAULT_CAPABILITIES,
156 "Open Firmware" },
157 { "ppc64", "powernv8", "", "OPAL" },
158 { "ppc64", "powernv9", "", "OPAL" },
159 { "ppc64", "sam460ex", "-device e1000", "8086 100e" },
160 { "i386", "isapc", "-cpu qemu32 -M graphics=off", "SeaBIOS" },
161 { "i386", "pc", "-M graphics=off", "SeaBIOS" },
162 { "i386", "q35", "-M graphics=off", "SeaBIOS" },
163 { "x86_64", "isapc", "-cpu qemu32 -M graphics=off", "SeaBIOS" },
164 { "x86_64", "q35", "-M graphics=off", "SeaBIOS" },
165 { "sparc", "LX", "", "TMS390S10" },
166 { "sparc", "SS-4", "", "MB86904" },
167 { "sparc", "SS-600MP", "", "TMS390Z55" },
168 { "sparc64", "sun4u", "", "UltraSPARC" },
169 { "s390x", "s390-ccw-virtio", "", "device" },
170 { "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 },
171 { "m68k", "next-cube", "", "TT", sizeof(bios_nextcube), 0, bios_nextcube },
172 { "microblaze", "petalogix-s3adsp1800", "", "TT",
173 sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 },
174 { "microblazeel", "petalogix-ml605", "", "TT",
175 sizeof(kernel_plml605), kernel_plml605 },
176 { "arm", "raspi2b", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 },
177
178 { "hppa", "hppa", "-vga none", "SeaBIOS wants SYSTEM HALT" },
179 { "aarch64", "virt", "-cpu max", "TT", sizeof(kernel_aarch64),
180 kernel_aarch64 },
181 { "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
182 { "arm", "stm32vldiscovery", "", "T",
183 sizeof(kernel_stm32vldiscovery), kernel_stm32vldiscovery },
184
185 { NULL }
186};
187
188static bool check_guest_output(QTestState *qts, const testdef_t *test, int fd)
189{
190 int nbr = 0, pos = 0, ccnt;
191 time_t now, start = time(NULL);
192 char ch;
193
194
195 while (1) {
196 ccnt = 0;
197 while (ccnt++ < 512 && (nbr = read(fd, &ch, 1)) == 1) {
198 if (ch == test->expect[pos]) {
199 pos += 1;
200 if (test->expect[pos] == '\0') {
201
202 return true;
203 }
204 } else {
205 pos = 0;
206 }
207 }
208 g_assert(nbr >= 0);
209
210 if (!qtest_probe_child(qts)) {
211 break;
212 }
213
214 now = time(NULL);
215 if (now - start >= 360) {
216 break;
217 }
218 g_usleep(10000);
219 }
220
221 return false;
222}
223
224static void test_machine(const void *data)
225{
226 const testdef_t *test = data;
227 g_autofree char *serialtmp = NULL;
228 g_autofree char *codetmp = NULL;
229 const char *codeparam = "";
230 const uint8_t *code = NULL;
231 QTestState *qts;
232 int ser_fd;
233
234 ser_fd = g_file_open_tmp("qtest-boot-serial-sXXXXXX", &serialtmp, NULL);
235 g_assert(ser_fd != -1);
236 close(ser_fd);
237
238 if (test->kernel) {
239 code = test->kernel;
240 codeparam = "-kernel";
241 } else if (test->bios) {
242 code = test->bios;
243 codeparam = "-bios";
244 }
245
246 if (code) {
247 ssize_t wlen;
248 int code_fd;
249
250 code_fd = g_file_open_tmp("qtest-boot-serial-cXXXXXX", &codetmp, NULL);
251 g_assert(code_fd != -1);
252 wlen = write(code_fd, code, test->codesize);
253 g_assert(wlen == test->codesize);
254 close(code_fd);
255 }
256
257
258
259
260
261 qts = qtest_initf("%s %s -M %s -no-shutdown "
262 "-chardev file,id=serial0,path=%s "
263 "-serial chardev:serial0 -accel tcg -accel kvm %s",
264 codeparam, code ? codetmp : "", test->machine,
265 serialtmp, test->extra);
266 if (code) {
267 unlink(codetmp);
268 }
269
270 ser_fd = open(serialtmp, O_RDONLY);
271 g_assert(ser_fd != -1);
272 if (!check_guest_output(qts, test, ser_fd)) {
273 g_error("Failed to find expected string. Please check '%s'",
274 serialtmp);
275 }
276 unlink(serialtmp);
277
278 qtest_quit(qts);
279
280 close(ser_fd);
281}
282
283int main(int argc, char *argv[])
284{
285 const char *arch = qtest_get_arch();
286 int i;
287
288 g_test_init(&argc, &argv, NULL);
289
290 if (!qtest_has_accel("tcg") && !qtest_has_accel("kvm")) {
291 g_test_skip("No KVM or TCG accelerator available");
292 return 0;
293 }
294
295 for (i = 0; tests[i].arch != NULL; i++) {
296 if (g_str_equal(arch, tests[i].arch) &&
297 qtest_has_machine(tests[i].machine)) {
298 char *name = g_strdup_printf("boot-serial/%s", tests[i].machine);
299 qtest_add_data_func(name, &tests[i], test_machine);
300 g_free(name);
301 }
302 }
303
304 return g_test_run();
305}
306