1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "boot-sector.h"
15#include "libqtest.h"
16
17#define LOW(x) ((x) & 0xff)
18#define HIGH(x) ((x) >> 8)
19
20#define SIGNATURE 0xdead
21#define SIGNATURE_OFFSET 0x10
22#define BOOT_SECTOR_ADDRESS 0x7c00
23#define SIGNATURE_ADDR (BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET)
24
25
26
27
28static uint8_t x86_boot_sector[512] = {
29
30
31
32
33
34
35
36
37
38 [0x00] = 0xb8,
39 [0x01] = 0x00,
40 [0x02] = 0x00,
41
42 [0x03] = 0x8e,
43 [0x04] = 0xd8,
44
45
46 [0x05] = 0xb8,
47 [0x06] = LOW(SIGNATURE),
48 [0x07] = HIGH(SIGNATURE),
49
50 [0x08] = 0xa3,
51 [0x09] = LOW(SIGNATURE_ADDR),
52 [0x0a] = HIGH(SIGNATURE_ADDR),
53
54
55 [0x0b] = 0xfa,
56
57 [0x0c] = 0xf4,
58
59 [0x0d] = 0xeb,
60 [0x0e] = LOW(-3),
61
62 [SIGNATURE_OFFSET] = LOW(0xface),
63 [SIGNATURE_OFFSET + 1] = HIGH(0xface),
64
65 [0x1FE] = 0x55,
66 [0x1FF] = 0xAA,
67};
68
69
70static const uint8_t s390x_psw_and_magic[] = {
71 0x00, 0x08, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
72 0x02, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x50,
73 0x02, 0x00, 0x00, 0x68, 0x60, 0x00, 0x00, 0x50,
74 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
75};
76static const uint8_t s390x_code[] = {
77 0xa7, 0xf4, 0x00, 0x08,
78 0x00, 0x00, 0x00, 0x00,
79 'S', '3', '9', '0',
80 'E', 'P', 0x00, 0x01,
81 0xa7, 0x39, HIGH(SIGNATURE_ADDR), LOW(SIGNATURE_ADDR),
82 0xa7, 0x48, LOW(SIGNATURE), HIGH(SIGNATURE),
83 0x40, 0x40, 0x30, 0x00,
84 0xa7, 0xf4, 0xff, 0xfa
85};
86
87
88int boot_sector_init(char *fname)
89{
90 int fd, ret;
91 size_t len;
92 char *boot_code;
93 const char *arch = qtest_get_arch();
94
95 fd = mkstemp(fname);
96 if (fd < 0) {
97 fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno));
98 return 1;
99 }
100
101 if (g_str_equal(arch, "i386") || g_str_equal(arch, "x86_64")) {
102
103 len = MAX(0x7e000, sizeof(x86_boot_sector));
104 boot_code = g_malloc0(len);
105 memcpy(boot_code, x86_boot_sector, sizeof(x86_boot_sector));
106 } else if (g_str_equal(arch, "ppc64")) {
107
108 boot_code = g_strdup_printf("\\ Bootscript\n%x %x c! %x %x c!\n",
109 LOW(SIGNATURE), SIGNATURE_ADDR,
110 HIGH(SIGNATURE), SIGNATURE_ADDR + 1);
111 len = strlen(boot_code);
112 } else if (g_str_equal(arch, "s390x")) {
113 len = 0x10000 + sizeof(s390x_code);
114 boot_code = g_malloc0(len);
115 memcpy(boot_code, s390x_psw_and_magic, sizeof(s390x_psw_and_magic));
116 memcpy(&boot_code[0x10000], s390x_code, sizeof(s390x_code));
117 } else {
118 g_assert_not_reached();
119 }
120
121 ret = write(fd, boot_code, len);
122 close(fd);
123
124 g_free(boot_code);
125
126 if (ret != len) {
127 fprintf(stderr, "Could not write \"%s\"", fname);
128 return 1;
129 }
130
131 return 0;
132}
133
134
135void boot_sector_test(QTestState *qts)
136{
137 uint8_t signature_low;
138 uint8_t signature_high;
139 uint16_t signature;
140 QDict *qrsp, *qret;
141 int i;
142
143
144#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
145#define TEST_CYCLES MAX((600 * G_USEC_PER_SEC / TEST_DELAY), 1)
146
147
148
149
150
151 for (i = 0; i < TEST_CYCLES; ++i) {
152 signature_low = qtest_readb(qts, SIGNATURE_ADDR);
153 signature_high = qtest_readb(qts, SIGNATURE_ADDR + 1);
154 signature = (signature_high << 8) | signature_low;
155 if (signature == SIGNATURE) {
156 break;
157 }
158
159
160 qrsp = qtest_qmp(qts, "{ 'execute': 'query-status' }");
161 qret = qdict_get_qdict(qrsp, "return");
162 g_assert_nonnull(qret);
163 g_assert_cmpstr(qdict_get_try_str(qret, "status"), ==, "running");
164 qobject_unref(qrsp);
165
166 g_usleep(TEST_DELAY);
167 }
168
169 g_assert_cmphex(signature, ==, SIGNATURE);
170}
171
172
173void boot_sector_cleanup(const char *fname)
174{
175 unlink(fname);
176}
177