4 * Copyright IBM, Corp. 2011
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.
15 #include "qemu-char.h"
23 const char *qtest_chrdev;
24 const char *qtest_log;
25 int qtest_allowed = 0;
27 static FILE *qtest_log_fp;
28 static CharDriverState *qtest_chr;
29 static GString *inbuf;
30 static int irq_levels[MAX_IRQ];
31 static struct timeval start_time;
32 static bool qtest_opened;
34 #define FMT_timeval "%" PRId64 ".%06" PRId64
39 * Line based protocol, request/response based. Server can send async messages
40 * so clients should always handle many async messages before the response
66 * > write ADDR SIZE DATA
69 * Valid async messages:
74 * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.
76 * DATA is an arbitrarily long hex number prefixed with '0x'. If it's smaller
77 * than the expected size, the value will be zero filled at the end of the data
80 * NUM is an IRQ number.
83 static int hex2nib(char ch)
85 if (ch >= '0' && ch <= '9') {
87 } else if (ch >= 'a' && ch <= 'f') {
88 return 10 + (ch - 'a');
89 } else if (ch >= 'A' && ch <= 'F') {
90 return 10 + (ch - 'a');
96 static void qtest_get_time(struct timeval *tv)
98 gettimeofday(tv, NULL);
99 tv->tv_sec -= start_time.tv_sec;
100 tv->tv_usec -= start_time.tv_usec;
101 if (tv->tv_usec < 0) {
102 tv->tv_usec += 1000000;
107 static void qtest_send_prefix(CharDriverState *chr)
111 if (!qtest_log_fp || !qtest_opened) {
116 fprintf(qtest_log_fp, "[S +" FMT_timeval "] ",
117 tv.tv_sec, tv.tv_usec);
120 static void qtest_send(CharDriverState *chr, const char *fmt, ...)
127 len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
130 qemu_chr_fe_write(chr, (uint8_t *)buffer, len);
131 if (qtest_log_fp && qtest_opened) {
132 fprintf(qtest_log_fp, "%s", buffer);
136 static void qtest_process_command(CharDriverState *chr, gchar **words)
138 const gchar *command;
149 fprintf(qtest_log_fp, "[R +" FMT_timeval "]",
150 tv.tv_sec, tv.tv_usec);
151 for (i = 0; words[i]; i++) {
152 fprintf(qtest_log_fp, " %s", words[i]);
154 fprintf(qtest_log_fp, "\n");
158 if (strcmp(words[0], "outb") == 0 ||
159 strcmp(words[0], "outw") == 0 ||
160 strcmp(words[0], "outl") == 0) {
164 g_assert(words[1] && words[2]);
165 addr = strtol(words[1], NULL, 0);
166 value = strtol(words[2], NULL, 0);
168 if (words[0][3] == 'b') {
169 cpu_outb(addr, value);
170 } else if (words[0][3] == 'w') {
171 cpu_outw(addr, value);
172 } else if (words[0][3] == 'l') {
173 cpu_outl(addr, value);
175 qtest_send_prefix(chr);
176 qtest_send(chr, "OK\n");
177 } else if (strcmp(words[0], "inb") == 0 ||
178 strcmp(words[0], "inw") == 0 ||
179 strcmp(words[0], "inl") == 0) {
181 uint32_t value = -1U;
184 addr = strtol(words[1], NULL, 0);
186 if (words[0][2] == 'b') {
187 value = cpu_inb(addr);
188 } else if (words[0][2] == 'w') {
189 value = cpu_inw(addr);
190 } else if (words[0][2] == 'l') {
191 value = cpu_inl(addr);
193 qtest_send_prefix(chr);
194 qtest_send(chr, "OK 0x%04x\n", value);
195 } else if (strcmp(words[0], "read") == 0) {
196 uint64_t addr, len, i;
199 g_assert(words[1] && words[2]);
200 addr = strtoul(words[1], NULL, 0);
201 len = strtoul(words[2], NULL, 0);
203 data = g_malloc(len);
204 cpu_physical_memory_read(addr, data, len);
206 qtest_send_prefix(chr);
207 qtest_send(chr, "OK 0x");
208 for (i = 0; i < len; i++) {
209 qtest_send(chr, "%02x", data[i]);
211 qtest_send(chr, "\n");
214 } else if (strcmp(words[0], "write") == 0) {
215 uint64_t addr, len, i;
219 g_assert(words[1] && words[2] && words[3]);
220 addr = strtoul(words[1], NULL, 0);
221 len = strtoul(words[2], NULL, 0);
223 data_len = strlen(words[3]);
225 qtest_send(chr, "ERR invalid argument size\n");
229 data = g_malloc(len);
230 for (i = 0; i < len; i++) {
231 if ((i * 2 + 4) <= data_len) {
232 data[i] = hex2nib(words[3][i * 2 + 2]) << 4;
233 data[i] |= hex2nib(words[3][i * 2 + 3]);
238 cpu_physical_memory_write(addr, data, len);
241 qtest_send_prefix(chr);
242 qtest_send(chr, "OK\n");
244 qtest_send_prefix(chr);
245 qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]);
249 static void qtest_process_inbuf(CharDriverState *chr, GString *inbuf)
253 while ((end = strchr(inbuf->str, '\n')) != NULL) {
258 offset = end - inbuf->str;
260 cmd = g_string_new_len(inbuf->str, offset);
261 g_string_erase(inbuf, 0, offset + 1);
263 words = g_strsplit(cmd->str, " ", 0);
264 qtest_process_command(chr, words);
267 g_string_free(cmd, TRUE);
271 static void qtest_read(void *opaque, const uint8_t *buf, int size)
273 CharDriverState *chr = opaque;
275 g_string_append_len(inbuf, (const gchar *)buf, size);
276 qtest_process_inbuf(chr, inbuf);
279 static int qtest_can_read(void *opaque)
284 static void qtest_event(void *opaque, int event)
289 case CHR_EVENT_OPENED:
290 qemu_system_reset(false);
291 for (i = 0; i < ARRAY_SIZE(irq_levels); i++) {
294 gettimeofday(&start_time, NULL);
297 fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n",
298 start_time.tv_sec, start_time.tv_usec);
301 case CHR_EVENT_CLOSED:
302 qtest_opened = false;
306 fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n",
307 tv.tv_sec, tv.tv_usec);
315 static void qtest_set_irq(void *opaque, int irq, int level)
317 CharDriverState *chr = qtest_chr;
320 changed = (irq_levels[irq] != level);
321 irq_levels[irq] = level;
324 qtest_send_prefix(chr);
325 qtest_send(chr, "IRQ %s %d\n",
326 level ? "raise" : "lower", irq);
332 CharDriverState *chr;
334 g_assert(qtest_chrdev != NULL);
336 chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
338 qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
339 qemu_chr_fe_set_echo(chr, true);
341 inbuf = g_string_new("");
344 if (strcmp(qtest_log, "none") != 0) {
345 qtest_log_fp = fopen(qtest_log, "w+");
348 qtest_log_fp = stderr;