[SerialICE] New patch to review for serialice: 1c63586 SerialICE: rewrite for Qemu [NOTFORMERGE]
Kyösti Mälkki (kyosti.malkki@gmail.com)
gerrit at coreboot.org
Mon May 7 20:00:43 CEST 2012
Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1017
-gerrit
commit 1c63586632823e2858fd1e3f9829198ce5b27ea8
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date: Mon May 7 20:31:52 2012 +0300
SerialICE: rewrite for Qemu [NOTFORMERGE]
These are the final results of splitting lua scripting and serial
communication protocol to two separate files. Compatibility to the
single-file serialice.lua is broken, you have to fetch the
modular version of the scripts from git.
At the time of writing, I have not found an approvable way of
pushing this progressively.
Change-Id: Iefe6c44a4a0b8241dd02ea03fed94d2a8f79a917
Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
Makefile | 2 +-
qemu-0.15.x/Makefile | 4 +
qemu-0.15.x/Makefile.target | 2 +-
qemu-0.15.x/ioport.c | 33 +
qemu-0.15.x/ioport.h | 3 +
qemu-0.15.x/serialice-com.c | 462 ++++++++++++++
qemu-0.15.x/serialice-lua.c | 551 +++++++++++++++++
qemu-0.15.x/serialice.c | 1163 ++++-------------------------------
qemu-0.15.x/serialice.h | 67 ++-
qemu-0.15.x/target-i386/cpu.h | 4 +
qemu-0.15.x/target-i386/op_helper.c | 138 +++--
11 files changed, 1295 insertions(+), 1134 deletions(-)
diff --git a/Makefile b/Makefile
index 009fa23..8a77582 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@
##
# Qemu version
-VERSION=0.11.0
+VERSION=0.15.x
# SerialICE revision when plain Qemu $(VERSION) was checked in.
REVISION=32
diff --git a/qemu-0.15.x/Makefile b/qemu-0.15.x/Makefile
index 076b0ec..09cb260 100644
--- a/qemu-0.15.x/Makefile
+++ b/qemu-0.15.x/Makefile
@@ -121,9 +121,13 @@ version.o: $(SRC_PATH)/version.rc config-host.mak
ifdef CONFIG_SERIALICE
serialice.o: serialice.c serialice.h
+serialice-com.o: serialice-com.c serialice.h
+serialice-lua.o: serialice-lua.c serialice.h
endif
serialice.o: QEMU_CFLAGS += $(SERIALICE_CFLAGS)
+serialice-com.o: QEMU_CFLAGS += $(SERIALICE_CFLAGS)
+serialice-lua.o: QEMU_CFLAGS += $(SERIALICE_CFLAGS)
version-obj-$(CONFIG_WIN32) += version.o
######################################################################
diff --git a/qemu-0.15.x/Makefile.target b/qemu-0.15.x/Makefile.target
index 22c8ff1..445949d 100644
--- a/qemu-0.15.x/Makefile.target
+++ b/qemu-0.15.x/Makefile.target
@@ -226,7 +226,7 @@ ifdef CONFIG_SERIALICE
QEMU_CFLAGS += $(SERIALICE_CFLAGS)
LIBS+=-lm
endif
-obj-$(CONFIG_SERIALICE) += serialice.o
+obj-$(CONFIG_SERIALICE) += serialice.o serialice-com.o serialice-lua.o
# Hardware support
obj-i386-y += vga.o
diff --git a/qemu-0.15.x/ioport.c b/qemu-0.15.x/ioport.c
index 0d2611d..aca38f2 100644
--- a/qemu-0.15.x/ioport.c
+++ b/qemu-0.15.x/ioport.c
@@ -313,3 +313,36 @@ uint32_t cpu_inl(pio_addr_t addr)
LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
return val;
}
+
+uint32_t cpu_io_read_wrapper(uint16_t port, unsigned int size)
+{
+ switch (size) {
+ case 1:
+ return cpu_inb(port);
+ case 2:
+ return cpu_inw(port);
+ case 4:
+ return cpu_inl(port);
+ default:
+ break;
+ }
+ return -1;
+}
+
+void cpu_io_write_wrapper(uint16_t port, unsigned int size, uint32_t data)
+{
+ switch (size) {
+ case 1:
+ cpu_outb(port, (uint8_t) data);
+ return;
+ case 2:
+ cpu_outw(port, (uint16_t) data);
+ return;
+ case 4:
+ cpu_outl(port, (uint32_t) data);
+ return;
+ default:
+ break;
+ }
+ return;
+}
diff --git a/qemu-0.15.x/ioport.h b/qemu-0.15.x/ioport.h
index 82ffd9d..18a1658 100644
--- a/qemu-0.15.x/ioport.h
+++ b/qemu-0.15.x/ioport.h
@@ -48,8 +48,11 @@ bool isa_is_ioport_assigned(pio_addr_t start);
void cpu_outb(pio_addr_t addr, uint8_t val);
void cpu_outw(pio_addr_t addr, uint16_t val);
void cpu_outl(pio_addr_t addr, uint32_t val);
+void cpu_io_write_wrapper(uint16_t port, unsigned int size, uint32_t data);
+
uint8_t cpu_inb(pio_addr_t addr);
uint16_t cpu_inw(pio_addr_t addr);
uint32_t cpu_inl(pio_addr_t addr);
+uint32_t cpu_io_read_wrapper(uint16_t port, unsigned int size);
#endif /* IOPORT_H */
diff --git a/qemu-0.15.x/serialice-com.c b/qemu-0.15.x/serialice-com.c
new file mode 100644
index 0000000..91bc643
--- /dev/null
+++ b/qemu-0.15.x/serialice-com.c
@@ -0,0 +1,462 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2009 coresystems GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* System includes */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#include <conio.h>
+#else
+#include <fcntl.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#endif
+
+#include "serialice.h"
+#include "sysemu.h"
+
+#define SERIALICE_DEBUG 3
+#define BUFFER_SIZE 1024
+typedef struct {
+#ifdef WIN32
+ HANDLE fd;
+#else
+ int fd;
+#endif
+ int handshake_mode;
+ char *buffer;
+ char *command;
+} SerialICEState;
+
+SerialICEState *s;
+static const SerialICE_target serialice_protocol;
+
+#ifndef WIN32
+static struct termios options;
+#endif
+
+// **************************************************************************
+// low level communication with the SerialICE shell (serial communication)
+
+static int serialice_read(SerialICEState * state, void *buf, size_t nbyte)
+{
+ int bytes_read = 0;
+
+ while (1) {
+#ifdef WIN32
+ int ret = 0;
+ ReadFile(state->fd, buf, nbyte - bytes_read, &ret, NULL);
+ if (!ret) {
+ break;
+ }
+#else
+ int ret = read(state->fd, buf, nbyte - bytes_read);
+
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ }
+
+ if (ret == -1) {
+ break;
+ }
+#endif
+
+ bytes_read += ret;
+ buf += ret;
+
+ if (bytes_read >= (int)nbyte) {
+ break;
+ }
+ }
+
+ return bytes_read;
+}
+
+static int serialice_write(SerialICEState * state, const void *buf,
+ size_t nbyte)
+{
+ char *buffer = (char *)buf;
+ char c;
+ int i;
+
+ for (i = 0; i < (int)nbyte; i++) {
+#ifdef WIN32
+ int ret = 0;
+ while (ret == 0) {
+ WriteFile(state->fd, buffer + i, 1, &ret, NULL);
+ }
+ ret = 0;
+ while (ret == 0) {
+ ReadFile(state->fd, &c, 1, &ret, NULL);
+ }
+#else
+ while (write(state->fd, buffer + i, 1) != 1) ;
+ while (read(state->fd, &c, 1) != 1) ;
+#endif
+ if (c != buffer[i] && !state->handshake_mode) {
+ printf("Readback error! %x/%x\n", c, buffer[i]);
+ }
+ }
+
+ return nbyte;
+}
+
+static int serialice_wait_prompt(void)
+{
+ char buf[3];
+ int l;
+
+ l = serialice_read(s, buf, 3);
+
+ if (l == -1) {
+ perror("SerialICE: Could not read from target");
+ exit(1);
+ }
+
+ while (buf[0] != '\n' || buf[1] != '>' || buf[2] != ' ') {
+ buf[0] = buf[1];
+ buf[1] = buf[2];
+ l = serialice_read(s, buf + 2, 1);
+ if (l == -1) {
+ perror("SerialICE: Could not read from target");
+ exit(1);
+ }
+ }
+
+ return 0;
+}
+
+static void serialice_command(const char *command, int reply_len)
+{
+#if SERIALICE_DEBUG > 5
+ int i;
+#endif
+ int l;
+
+ serialice_wait_prompt();
+
+ serialice_write(s, command, strlen(command));
+
+ memset(s->buffer, 0, reply_len + 1); // clear enough of the buffer
+
+ l = serialice_read(s, s->buffer, reply_len);
+
+ if (l == -1) {
+ perror("SerialICE: Could not read from target");
+ exit(1);
+ }
+ // compensate for CR on the wire. Needed on Win32
+ if (s->buffer[0] == '\r') {
+ memmove(s->buffer, s->buffer + 1, reply_len);
+ serialice_read(s, s->buffer + reply_len - 1, 1);
+ }
+
+ if (l != reply_len) {
+ printf("SerialICE: command was not answered sufficiently: "
+ "(%d/%d bytes)\n'%s'\n", l, reply_len, s->buffer);
+ exit(1);
+ }
+#if SERIALICE_DEBUG > 5
+ for (i = 0; i < reply_len; i++) {
+ printf("%02x ", s->buffer[i]);
+ }
+ printf("\n");
+#endif
+}
+
+const SerialICE_target *serialice_com_init(void)
+{
+ s = qemu_mallocz(sizeof(SerialICEState));
+
+ printf("SerialICE: Open connection to target hardware...\n");
+
+ if (serialice_device == NULL) {
+ printf("You need to specify a serial device to use SerialICE.\n");
+ exit(1);
+ }
+#ifdef WIN32
+ s->fd = CreateFile(serialice_device, GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (s->fd == INVALID_HANDLE_VALUE) {
+ perror("SerialICE: Could not connect to target TTY");
+ exit(1);
+ }
+
+ DCB dcb;
+ if (!GetCommState(s->fd, &dcb)) {
+ perror("SerialICE: Could not load config for target TTY");
+ exit(1);
+ }
+
+ dcb.BaudRate = CBR_115200;
+ dcb.ByteSize = 8;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+
+ if (!SetCommState(s->fd, &dcb)) {
+ perror("SerialICE: Could not store config for target TTY");
+ exit(1);
+ }
+#else
+ s->fd = open(serialice_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+ if (s->fd == -1) {
+ perror("SerialICE: Could not connect to target TTY");
+ exit(1);
+ }
+
+ if (ioctl(s->fd, TIOCEXCL) == -1) {
+ perror("SerialICE: TTY not exclusively available");
+ exit(1);
+ }
+
+ if (fcntl(s->fd, F_SETFL, 0) == -1) {
+ perror("SerialICE: Could not switch to blocking I/O");
+ exit(1);
+ }
+
+ if (tcgetattr(s->fd, &options) == -1) {
+ perror("SerialICE: Could not get TTY attributes");
+ exit(1);
+ }
+
+ cfsetispeed(&options, B115200);
+ cfsetospeed(&options, B115200);
+
+ /* set raw input, 1 second timeout */
+ options.c_cflag |= (CLOCAL | CREAD);
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ options.c_oflag &= ~OPOST;
+ options.c_iflag |= IGNCR;
+ options.c_cc[VMIN] = 0;
+ options.c_cc[VTIME] = 100;
+
+ tcsetattr(s->fd, TCSANOW, &options);
+
+ tcflush(s->fd, TCIOFLUSH);
+#endif
+
+ s->buffer = qemu_mallocz(BUFFER_SIZE);
+ s->command = qemu_mallocz(BUFFER_SIZE);
+
+ printf("SerialICE: Waiting for handshake with target... ");
+
+ s->handshake_mode = 1; // Readback errors are to be expected in this phase.
+
+ /* Trigger a prompt */
+ serialice_write(s, "@", 1);
+
+ /* ... and wait for it to appear */
+ if (serialice_wait_prompt() == 0) {
+ printf("target alive!\n");
+ } else {
+ printf("target not ok!\n");
+ exit(1);
+ }
+
+ /* Each serialice_command() waits for a prompt, so trigger one for the
+ * first command, as we consumed the last one for the handshake
+ */
+ serialice_write(s, "@", 1);
+
+ s->handshake_mode = 0; // from now on, warn about readback errors.
+ return &serialice_protocol;
+}
+
+void serialice_com_exit(void)
+{
+ qemu_free(s->command);
+ qemu_free(s->buffer);
+ qemu_free(s);
+}
+
+// **************************************************************************
+// high level communication with the SerialICE shell
+
+static void serialice_get_version(void)
+{
+ int len = 0;
+ printf("SerialICE: Version.....: ");
+ serialice_command("*vi", 0);
+
+ memset(s->buffer, 0, BUFFER_SIZE);
+ serialice_read(s, s->buffer, 1);
+ serialice_read(s, s->buffer, 1);
+ while (s->buffer[len++] != '\n') {
+ serialice_read(s, s->buffer + len, 1);
+ }
+ s->buffer[len - 1] = '\0';
+
+ printf("%s\n", s->buffer);
+}
+
+static void serialice_get_mainboard(void)
+{
+ int len = 31;
+
+ printf("SerialICE: Mainboard...: ");
+ serialice_command("*mb", 32);
+ while (len && s->buffer[len] == ' ') {
+ s->buffer[len--] = '\0';
+ }
+ serialice_mainboard = strdup(s->buffer + 1);
+ printf("%s\n", serialice_mainboard);
+}
+
+static uint32_t cmd_io_read(uint16_t port, unsigned int size)
+{
+ switch (size) {
+ case 1:
+ sprintf(s->command, "*ri%04x.b", port);
+ // command read back: "\n00" (3 characters)
+ serialice_command(s->command, 3);
+ return (uint8_t) strtoul(s->buffer + 1, (char **)NULL, 16);
+ case 2:
+ sprintf(s->command, "*ri%04x.w", port);
+ // command read back: "\n0000" (5 characters)
+ serialice_command(s->command, 5);
+ return (uint16_t) strtoul(s->buffer + 1, (char **)NULL, 16);
+ case 4:
+ sprintf(s->command, "*ri%04x.l", port);
+ // command read back: "\n00000000" (9 characters)
+ serialice_command(s->command, 9);
+ return strtoul(s->buffer + 1, (char **)NULL, 16);
+ default:
+ printf("WARNING: unknown read access size %d @%08x\n", size, port);
+ return -1;
+ }
+}
+
+static void cmd_io_write(uint16_t port, unsigned int size, uint32_t data)
+{
+ switch (size) {
+ case 1:
+ sprintf(s->command, "*wi%04x.b=%02x", port, (uint8_t) data);
+ serialice_command(s->command, 0);
+ return;
+ case 2:
+ sprintf(s->command, "*wi%04x.w=%04x", port, (uint16_t) data);
+ serialice_command(s->command, 0);
+ return;
+ case 4:
+ sprintf(s->command, "*wi%04x.l=%08x", port, data);
+ serialice_command(s->command, 0);
+ return;
+ default:
+ printf("WARNING: unknown write access size %d @%08x\n", size, port);
+ }
+ return;
+}
+
+static uint32_t cmd_load(uint32_t addr, unsigned int size)
+{
+ switch (size) {
+ case 1:
+ sprintf(s->command, "*rm%08x.b", addr);
+ // command read back: "\n00" (3 characters)
+ serialice_command(s->command, 3);
+ return (uint8_t) strtoul(s->buffer + 1, (char **)NULL, 16);
+ case 2:
+ sprintf(s->command, "*rm%08x.w", addr);
+ // command read back: "\n0000" (5 characters)
+ serialice_command(s->command, 5);
+ return (uint16_t) strtoul(s->buffer + 1, (char **)NULL, 16);
+ case 4:
+ sprintf(s->command, "*rm%08x.l", addr);
+ // command read back: "\n00000000" (9 characters)
+ serialice_command(s->command, 9);
+ return (uint32_t) strtoul(s->buffer + 1, (char **)NULL, 16);
+ default:
+ printf("WARNING: unknown read access size %d @%08x\n", size, addr);
+ }
+ return 0;
+}
+
+static void cmd_store(uint32_t addr, unsigned int size, uint32_t data)
+{
+ switch (size) {
+ case 1:
+ sprintf(s->command, "*wm%08x.b=%02x", addr, (uint8_t) data);
+ serialice_command(s->command, 0);
+ break;
+ case 2:
+ sprintf(s->command, "*wm%08x.w=%04x", addr, (uint16_t) data);
+ serialice_command(s->command, 0);
+ break;
+ case 4:
+ sprintf(s->command, "*wm%08x.l=%08x", addr, data);
+ serialice_command(s->command, 0);
+ break;
+ default:
+ printf("WARNING: unknown write access size %d @%08x\n", size, addr);
+ }
+}
+
+static void cmd_rdmsr(uint32_t addr, uint32_t key, uint32_t * hi, uint32_t * lo)
+{
+ sprintf(s->command, "*rc%08x.%08x", addr, key);
+ // command read back: "\n00000000.00000000" (18 characters)
+ serialice_command(s->command, 18);
+ s->buffer[9] = 0; // . -> \0
+ *hi = (uint32_t) strtoul(s->buffer + 1, (char **)NULL, 16);
+ *lo = (uint32_t) strtoul(s->buffer + 10, (char **)NULL, 16);
+}
+
+static void cmd_wrmsr(uint32_t addr, uint32_t key, uint32_t hi, uint32_t lo)
+{
+ sprintf(s->command, "*wc%08x.%08x=%08x.%08x", addr, key, hi, lo);
+ serialice_command(s->command, 0);
+}
+
+static void cmd_cpuid(uint32_t eax, uint32_t ecx, cpuid_regs_t * ret)
+{
+ sprintf(s->command, "*ci%08x.%08x", eax, ecx);
+ // command read back: "\n000006f2.00000000.00001234.12340324"
+ // (36 characters)
+ serialice_command(s->command, 36);
+ s->buffer[9] = 0; // . -> \0
+ s->buffer[18] = 0; // . -> \0
+ s->buffer[27] = 0; // . -> \0
+ ret->eax = (uint32_t) strtoul(s->buffer + 1, (char **)NULL, 16);
+ ret->ebx = (uint32_t) strtoul(s->buffer + 10, (char **)NULL, 16);
+ ret->ecx = (uint32_t) strtoul(s->buffer + 19, (char **)NULL, 16);
+ ret->edx = (uint32_t) strtoul(s->buffer + 28, (char **)NULL, 16);
+}
+
+static const SerialICE_target serialice_protocol = {
+ .version = serialice_get_version,
+ .mainboard = serialice_get_mainboard,
+ .io_read = cmd_io_read,
+ .io_write = cmd_io_write,
+ .load = cmd_load,
+ .store = cmd_store,
+ .rdmsr = cmd_rdmsr,
+ .wrmsr = cmd_wrmsr,
+ .cpuid = cmd_cpuid,
+};
diff --git a/qemu-0.15.x/serialice-lua.c b/qemu-0.15.x/serialice-lua.c
new file mode 100644
index 0000000..7e126e5
--- /dev/null
+++ b/qemu-0.15.x/serialice-lua.c
@@ -0,0 +1,551 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2009 coresystems GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Indented with:
+ * gnuindent -npro -kr -i4 -nut -bap -sob -l80 -ss -ncs serialice.*
+ */
+
+/* System includes */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+/* LUA includes */
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+/* Local includes */
+#include "hw/hw.h"
+#include "serialice.h"
+#include "sysemu.h"
+
+static lua_State *L;
+static const SerialICE_filter lua_ops;
+
+#define LOG_IO (1<<0)
+#define LOG_MEMORY (1<<1)
+#define LOG_MSR (1<<2)
+
+// **************************************************************************
+// LUA scripting interface and callbacks
+
+static int serialice_register_physical(lua_State * luastate)
+{
+ int n = lua_gettop(luastate);
+ static uint8_t num = 1;
+ uint32_t addr, size;
+ ram_addr_t phys;
+ char ram_name[16];
+
+ if (n != 2) {
+ fprintf(stderr,
+ "ERROR: Not called as SerialICE_register_physical(<addr> <size>)\n");
+ return 0;
+ }
+
+ addr = lua_tointeger(luastate, 1);
+ size = lua_tointeger(luastate, 2);
+
+ if (num > 99) {
+ fprintf(stderr, "To much memory ranges registered\n");
+ exit(1);
+ }
+ printf("Registering physical memory at 0x%08x (0x%08x bytes)\n", addr,
+ size);
+ sprintf(ram_name, "serialice_ram%u", num);
+ phys = qemu_ram_alloc(NULL, ram_name, size);
+ cpu_register_physical_memory(addr, size, phys);
+ num++;
+ return 0;
+}
+
+static int serialice_system_reset(lua_State * luastate)
+{
+ printf("Rebooting the emulated host CPU\n");
+ qemu_system_reset_request();
+ return 0;
+}
+
+// **************************************************************************
+// LUA register access
+
+// some macros from target-i386/exec.h, which we can't include directly
+#define env first_cpu
+#define EAX (env->regs[R_EAX])
+#define ECX (env->regs[R_ECX])
+#define EDX (env->regs[R_EDX])
+#define EBX (env->regs[R_EBX])
+#define ESP (env->regs[R_ESP])
+#define EBP (env->regs[R_EBP])
+#define ESI (env->regs[R_ESI])
+#define EDI (env->regs[R_EDI])
+#define EIP (env->eip)
+#define CS (env->segs[R_CS].base)
+static int register_set(lua_State * L)
+{
+ const char *key = luaL_checkstring(L, 2);
+ int val = luaL_checkint(L, 3);
+ int ret = 1;
+
+ if (strcmp(key, "eax") == 0) {
+ EAX = val;
+ } else if (strcmp(key, "ecx") == 0) {
+ ECX = val;
+ } else if (strcmp(key, "edx") == 0) {
+ EDX = val;
+ } else if (strcmp(key, "ebx") == 0) {
+ EBX = val;
+ } else if (strcmp(key, "esp") == 0) {
+ ESP = val;
+ } else if (strcmp(key, "ebp") == 0) {
+ EBP = val;
+ } else if (strcmp(key, "esi") == 0) {
+ ESI = val;
+ } else if (strcmp(key, "edi") == 0) {
+ EDI = val;
+ } else if (strcmp(key, "eip") == 0) {
+ EIP = val;
+ } else if (strcmp(key, "cs") == 0) {
+ CS = (val << 4);
+ } else {
+ lua_pushstring(L, "No such register.");
+ lua_error(L);
+ ret = 0;
+ }
+ return ret;
+}
+
+static int register_get(lua_State * L)
+{
+ const char *key = luaL_checkstring(L, 2);
+ int ret = 1;
+ if (strcmp(key, "eax") == 0) {
+ lua_pushinteger(L, EAX);
+ } else if (strcmp(key, "ecx") == 0) {
+ lua_pushinteger(L, ECX);
+ } else if (strcmp(key, "edx") == 0) {
+ lua_pushinteger(L, EDX);
+ } else if (strcmp(key, "ebx") == 0) {
+ lua_pushinteger(L, EBX);
+ } else if (strcmp(key, "esp") == 0) {
+ lua_pushinteger(L, ESP);
+ } else if (strcmp(key, "ebp") == 0) {
+ lua_pushinteger(L, EBP);
+ } else if (strcmp(key, "esi") == 0) {
+ lua_pushinteger(L, ESI);
+ } else if (strcmp(key, "edi") == 0) {
+ lua_pushinteger(L, EDI);
+ } else if (strcmp(key, "eip") == 0) {
+ lua_pushinteger(L, EIP);
+ } else if (strcmp(key, "cs") == 0) {
+ lua_pushinteger(L, (CS >> 4));
+ } else {
+ lua_pushstring(L, "No such register.");
+ lua_error(L);
+ ret = 0;
+ }
+ return ret;
+}
+
+#undef env
+
+static int serialice_lua_registers(void)
+{
+ const struct luaL_Reg registermt[] = {
+ {"__index", register_get},
+ {"__newindex", register_set},
+ {NULL, NULL}
+ };
+
+ lua_newuserdata(L, sizeof(void *));
+ luaL_newmetatable(L, "registermt");
+#if LUA_VERSION_NUM <= 501
+ luaL_register(L, NULL, registermt);
+#elif LUA_VERSION_NUM >= 502
+ luaL_setfuncs(L, registermt, 0);
+#endif
+ lua_setmetatable(L, -2);
+ lua_setglobal(L, "regs");
+
+ return 0;
+}
+
+const SerialICE_filter * serialice_lua_init(const char *serialice_lua_script)
+{
+ int status;
+
+ printf("SerialICE: LUA init...\n");
+
+ /* Create a LUA context and load LUA libraries */
+ L = luaL_newstate();
+ luaL_openlibs(L);
+
+ /* Register C function callbacks */
+ lua_register(L, "SerialICE_register_physical", serialice_register_physical);
+ lua_register(L, "SerialICE_system_reset", serialice_system_reset);
+
+ /* Set global variable SerialICE_mainboard */
+ lua_pushstring(L, serialice_mainboard);
+ lua_setglobal(L, "SerialICE_mainboard");
+
+ /* Enable Register Access */
+ serialice_lua_registers();
+
+ /* Load the script file */
+ status = luaL_loadfile(L, serialice_lua_script);
+ if (status) {
+ fprintf(stderr, "Couldn't load SerialICE script: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ /* Ask Lua to run our little script */
+ status = lua_pcall(L, 0, 1, 0);
+ if (status) {
+ fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1));
+ exit(1);
+ }
+ lua_pop(L, 1);
+
+ return &lua_ops;
+}
+
+void serialice_lua_exit(void)
+{
+ lua_close(L);
+}
+
+const char *serialice_lua_execute(const char *cmd)
+{
+ int error;
+ char *errstring = NULL;
+ error = luaL_loadbuffer(L, cmd, strlen(cmd), "line")
+ || lua_pcall(L, 0, 0, 0);
+ if (error) {
+ errstring = strdup(lua_tostring(L, -1));
+ lua_pop(L, 1);
+ }
+
+ return errstring;
+}
+
+static int io_read_pre(uint16_t port, int size)
+{
+ int ret = 0, result;
+
+ lua_getglobal(L, "SerialICE_io_read_filter");
+ lua_pushinteger(L, port); // port
+ lua_pushinteger(L, size); // datasize
+
+ result = lua_pcall(L, 2, 2, 0);
+ if (result) {
+ fprintf(stderr, "Failed to run function SerialICE_io_read_filter: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ ret |= lua_toboolean(L, -1) ? READ_FROM_QEMU : 0;
+ ret |= lua_toboolean(L, -2) ? READ_FROM_SERIALICE : 0;
+ lua_pop(L, 2);
+ return ret;
+}
+
+static int io_write_pre(uint32_t * data, uint16_t port, int size)
+{
+ int ret = 0, result;
+
+ lua_getglobal(L, "SerialICE_io_write_filter");
+ lua_pushinteger(L, port); // port
+ lua_pushinteger(L, size); // datasize
+ lua_pushinteger(L, *data); // data
+
+ result = lua_pcall(L, 3, 3, 0);
+ if (result) {
+ fprintf(stderr,
+ "Failed to run function SerialICE_io_write_filter: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ *data = lua_tointeger(L, -1);
+ ret |= lua_toboolean(L, -2) ? WRITE_TO_QEMU : 0;
+ ret |= lua_toboolean(L, -3) ? WRITE_TO_SERIALICE : 0;
+ lua_pop(L, 3);
+ return ret;
+}
+
+static int memory_read_pre(uint32_t addr, int size)
+{
+ int ret = 0, result;
+
+ lua_getglobal(L, "SerialICE_memory_read_filter");
+ lua_pushinteger(L, addr);
+ lua_pushinteger(L, size);
+
+ result = lua_pcall(L, 2, 2, 0);
+ if (result) {
+ fprintf(stderr,
+ "Failed to run function SerialICE_memory_read_filter: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ ret |= lua_toboolean(L, -1) ? READ_FROM_QEMU : 0;
+ ret |= lua_toboolean(L, -2) ? READ_FROM_SERIALICE : 0;
+ lua_pop(L, 2);
+ return ret;
+}
+
+static int memory_write_pre(uint32_t addr, int size, uint32_t * data)
+{
+ int ret = 0, result;
+
+ lua_getglobal(L, "SerialICE_memory_write_filter");
+ lua_pushinteger(L, addr); // address
+ lua_pushinteger(L, size); // datasize
+ lua_pushinteger(L, *data); // data
+
+ result = lua_pcall(L, 3, 3, 0);
+ if (result) {
+ fprintf(stderr,
+ "Failed to run function SerialICE_memory_write_filter: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ *data = lua_tointeger(L, -1);
+ ret |= lua_toboolean(L, -2) ? WRITE_TO_QEMU : 0;
+ ret |= lua_toboolean(L, -3) ? WRITE_TO_SERIALICE : 0;
+ lua_pop(L, 3);
+ return ret;
+}
+
+static int wrmsr_pre(uint32_t addr, uint32_t * hi, uint32_t * lo)
+{
+ int ret = 0, result;
+
+ lua_getglobal(L, "SerialICE_msr_write_filter");
+ lua_pushinteger(L, addr); // port
+ lua_pushinteger(L, *hi); // high
+ lua_pushinteger(L, *lo); // low
+
+ result = lua_pcall(L, 3, 4, 0);
+ if (result) {
+ fprintf(stderr,
+ "Failed to run function SerialICE_msr_write_filter: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ *lo = lua_tointeger(L, -1);
+ *hi = lua_tointeger(L, -2);
+ ret |= lua_toboolean(L, -3) ? WRITE_TO_QEMU : 0;
+ ret |= lua_toboolean(L, -4) ? WRITE_TO_SERIALICE : 0;
+ lua_pop(L, 4);
+ return ret;
+}
+
+static int rdmsr_pre(uint32_t addr)
+{
+ int ret = 0, result;
+
+ lua_getglobal(L, "SerialICE_msr_read_filter");
+ lua_pushinteger(L, addr);
+
+ result = lua_pcall(L, 1, 2, 0);
+ if (result) {
+ fprintf(stderr,
+ "Failed to run function SerialICE_msr_read_filter: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ ret |= lua_toboolean(L, -1) ? WRITE_TO_QEMU : 0;
+ ret |= lua_toboolean(L, -2) ? WRITE_TO_SERIALICE : 0;
+ lua_pop(L, 2);
+ return ret;
+}
+
+static int cpuid_pre(uint32_t eax, uint32_t ecx)
+{
+ int ret = 0, result;
+
+ lua_getglobal(L, "SerialICE_cpuid_filter");
+ lua_pushinteger(L, eax); // eax before calling
+ lua_pushinteger(L, ecx); // ecx before calling
+
+ result = lua_pcall(L, 2, 2, 0);
+ if (result) {
+ fprintf(stderr,
+ "Failed to run function SerialICE_cpuid_filter: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ ret |= lua_toboolean(L, -1) ? WRITE_TO_QEMU : 0;
+ ret |= lua_toboolean(L, -2) ? WRITE_TO_SERIALICE : 0;
+ lua_pop(L, 2);
+ return ret;
+}
+
+/* SerialICE output loggers */
+
+static void read_post(int flags, uint32_t * data)
+{
+ int result;
+
+ if (flags & LOG_MEMORY) {
+ lua_getglobal(L, "SerialICE_memory_read_log");
+ } else if (flags & LOG_IO) {
+ lua_getglobal(L, "SerialICE_io_read_log");
+ } else {
+ fprintf(stderr, "serialice_read_log: bad type\n");
+ exit(1);
+ }
+
+ lua_pushinteger(L, *data);
+
+ result = lua_pcall(L, 1, 1, 0);
+ if (result) {
+ fprintf(stderr, "Failed to run function SerialICE_%s_read_log: %s\n",
+ (flags & LOG_MEMORY) ? "memory" : "io", lua_tostring(L, -1));
+ exit(1);
+ }
+
+ *data = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+}
+
+static void memory_read_post(uint32_t * data)
+{
+ read_post(LOG_MEMORY, data);
+}
+
+static void io_read_post(uint32_t * data)
+{
+ read_post(LOG_IO, data);
+}
+
+static void write_post(int flags)
+{
+ int result;
+
+ if (flags & LOG_MEMORY) {
+ lua_getglobal(L, "SerialICE_memory_write_log");
+ } else if (flags & LOG_IO) {
+ lua_getglobal(L, "SerialICE_io_write_log");
+ } else if (flags & LOG_MSR) {
+ lua_getglobal(L, "SerialICE_msr_write_log");
+ } else {
+ fprintf(stderr, "serialice_write_log: bad type\n");
+ exit(1);
+ }
+
+ result = lua_pcall(L, 0, 0, 0);
+ if (result) {
+ fprintf(stderr, "Failed to run function SerialICE_%s_write_log: %s\n",
+ (flags & LOG_MEMORY) ? "memory" : "io", lua_tostring(L, -1));
+ exit(1);
+ }
+}
+
+static void memory_write_post(void)
+{
+ write_post(LOG_MEMORY);
+}
+
+static void io_write_post(void)
+{
+ write_post(LOG_IO);
+}
+
+static void wrmsr_post(void)
+{
+ write_post(LOG_MSR);
+}
+
+static void cpuid_post(cpuid_regs_t * res)
+{
+ int result;
+
+ lua_getglobal(L, "SerialICE_cpuid_log");
+ lua_pushinteger(L, res->eax); // output: eax
+ lua_pushinteger(L, res->ebx); // output: ebx
+ lua_pushinteger(L, res->ecx); // output: ecx
+ lua_pushinteger(L, res->edx); // output: edx
+
+ result = lua_pcall(L, 4, 4, 0);
+ if (result) {
+ fprintf(stderr, "Failed to run function SerialICE_cpuid_log: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ res->edx = lua_tointeger(L, -1);
+ res->ecx = lua_tointeger(L, -2);
+ res->ebx = lua_tointeger(L, -3);
+ res->eax = lua_tointeger(L, -4);
+ lua_pop(L, 4);
+}
+
+static void rdmsr_post(uint32_t * hi, uint32_t * lo)
+{
+ int result;
+
+ lua_getglobal(L, "SerialICE_msr_read_log");
+ lua_pushinteger(L, *hi);
+ lua_pushinteger(L, *lo);
+
+ result = lua_pcall(L, 2, 2, 0);
+ if (result) {
+ fprintf(stderr, "Failed to run function SerialICE_msr_read_log: %s\n",
+ lua_tostring(L, -1));
+ exit(1);
+ }
+
+ *hi = lua_tointeger(L, -2);
+ *lo = lua_tointeger(L, -1);
+ lua_pop(L, 2);
+}
+
+static const SerialICE_filter lua_ops = {
+ .io_read_pre = io_read_pre,
+ .io_read_post = io_read_post,
+ .io_write_pre = io_write_pre,
+ .io_write_post = io_write_post,
+ .load_pre = memory_read_pre,
+ .load_post = memory_read_post,
+ .store_pre = memory_write_pre,
+ .store_post = memory_write_post,
+ .rdmsr_pre = rdmsr_pre,
+ .rdmsr_post = rdmsr_post,
+ .wrmsr_pre = wrmsr_pre,
+ .wrmsr_post = wrmsr_post,
+ .cpuid_pre = cpuid_pre,
+ .cpuid_post = cpuid_post,
+};
+
diff --git a/qemu-0.15.x/serialice.c b/qemu-0.15.x/serialice.c
index a91f9c6..d259a11 100644
--- a/qemu-0.15.x/serialice.c
+++ b/qemu-0.15.x/serialice.c
@@ -32,19 +32,6 @@
#include <stdint.h>
#include <unistd.h>
#include <string.h>
-#ifdef WIN32
-#include <windows.h>
-#include <conio.h>
-#else
-#include <fcntl.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#endif
-
-/* LUA includes */
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
/* Local includes */
#include "hw/hw.h"
@@ -60,915 +47,103 @@
#include "serialice_banner.h"
#endif
+#define SERIALICE_LUA_SCRIPT "serialice.lua"
+
#define DEFAULT_RAM_SIZE 128
#define BIOS_FILENAME "bios.bin"
-#define SERIALICE_DEBUG 3
-#define BUFFER_SIZE 1024
typedef struct {
-#ifdef WIN32
- HANDLE fd;
-#else
- int fd;
-#endif
DisplayState *ds;
- char *buffer;
- char *command;
-} SerialICEState;
+} SerialICEScreen;
-static SerialICEState *s;
+SerialICEScreen *d;
-int serialice_active = 0;
-const char *serialice_lua_script = "serialice.lua";
+const SerialICE_target *stgt;
+const SerialICE_filter *sfil;
+int serialice_active = 0;
const char *serialice_mainboard = NULL;
-#ifndef WIN32
-static struct termios options;
-#endif
-
-static lua_State *L;
-
-// **************************************************************************
-// LUA scripting interface and callbacks
-
-static int serialice_register_physical(lua_State * luastate)
-{
- int n = lua_gettop(luastate);
- static uint8_t num = 1;
- uint32_t addr, size;
- ram_addr_t phys;
- char ram_name[16];
-
- if (n != 2) {
- fprintf(stderr,
- "ERROR: Not called as SerialICE_register_physical(<addr> <size>)\n");
- return 0;
- }
-
- addr = lua_tointeger(luastate, 1);
- size = lua_tointeger(luastate, 2);
-
- if (num > 99) {
- fprintf(stderr,"To much memory ranges registered\n");
- exit(1);
- }
- printf("Registering physical memory at 0x%08x (0x%08x bytes)\n", addr, size);
- sprintf(ram_name, "serialice_ram%u", num);
- phys = qemu_ram_alloc(NULL, ram_name, size);
- cpu_register_physical_memory(addr, size, phys);
- num++;
- return 0;
-}
-
-static int serialice_system_reset(lua_State * luastate)
-{
- printf("Rebooting the emulated host CPU\n");
- qemu_system_reset_request();
- return 0;
-}
-
-// **************************************************************************
-// LUA register access
-
-// some macros from target-i386/exec.h, which we can't include directly
-#define env first_cpu
-#define EAX (env->regs[R_EAX])
-#define ECX (env->regs[R_ECX])
-#define EDX (env->regs[R_EDX])
-#define EBX (env->regs[R_EBX])
-#define ESP (env->regs[R_ESP])
-#define EBP (env->regs[R_EBP])
-#define ESI (env->regs[R_ESI])
-#define EDI (env->regs[R_EDI])
-#define EIP (env->eip)
-#define CS (env->segs[R_CS].base)
-static int register_set(lua_State * L)
-{
- const char *key = luaL_checkstring(L, 2);
- int val = luaL_checkint(L, 3);
- int ret = 1;
-
- if (strcmp(key, "eax") == 0) {
- EAX = val;
- } else if (strcmp(key, "ecx") == 0) {
- ECX = val;
- } else if (strcmp(key, "edx") == 0) {
- EDX = val;
- } else if (strcmp(key, "ebx") == 0) {
- EBX = val;
- } else if (strcmp(key, "esp") == 0) {
- ESP = val;
- } else if (strcmp(key, "ebp") == 0) {
- EBP = val;
- } else if (strcmp(key, "esi") == 0) {
- ESI = val;
- } else if (strcmp(key, "edi") == 0) {
- EDI = val;
- } else if (strcmp(key, "eip") == 0) {
- EIP = val;
- } else if (strcmp(key, "cs") == 0) {
- CS = (val << 4);
- } else {
- lua_pushstring(L, "No such register.");
- lua_error(L);
- ret = 0;
- }
- return ret;
-}
-
-static int register_get(lua_State * L)
-{
- const char *key = luaL_checkstring(L, 2);
- int ret = 1;
- if (strcmp(key, "eax") == 0) {
- lua_pushinteger(L, EAX);
- } else if (strcmp(key, "ecx") == 0) {
- lua_pushinteger(L, ECX);
- } else if (strcmp(key, "edx") == 0) {
- lua_pushinteger(L, EDX);
- } else if (strcmp(key, "ebx") == 0) {
- lua_pushinteger(L, EBX);
- } else if (strcmp(key, "esp") == 0) {
- lua_pushinteger(L, ESP);
- } else if (strcmp(key, "ebp") == 0) {
- lua_pushinteger(L, EBP);
- } else if (strcmp(key, "esi") == 0) {
- lua_pushinteger(L, ESI);
- } else if (strcmp(key, "edi") == 0) {
- lua_pushinteger(L, EDI);
- } else if (strcmp(key, "eip") == 0) {
- lua_pushinteger(L, EIP);
- } else if (strcmp(key, "cs") == 0) {
- lua_pushinteger(L, (CS >> 4));
- } else {
- lua_pushstring(L, "No such register.");
- lua_error(L);
- ret = 0;
- }
- return ret;
-}
-
-#undef env
-
-static int serialice_lua_registers(void)
-{
- const struct luaL_Reg registermt[] = {
- {"__index", register_get},
- {"__newindex", register_set},
- {NULL, NULL}
- };
-
- lua_newuserdata(L, sizeof(void *));
- luaL_newmetatable(L, "registermt");
-#if LUA_VERSION_NUM <= 501
- luaL_register(L, NULL, registermt);
-#elif LUA_VERSION_NUM >= 502
- luaL_setfuncs(L, registermt, 0);
-#endif
- lua_setmetatable(L, -2);
- lua_setglobal(L, "regs");
-
- return 0;
-}
-
-static int serialice_lua_init(void)
-{
- int status;
-
- /* Create a LUA context and load LUA libraries */
- L = luaL_newstate();
- luaL_openlibs(L);
-
- /* Register C function callbacks */
- lua_register(L, "SerialICE_register_physical", serialice_register_physical);
- lua_register(L, "SerialICE_system_reset", serialice_system_reset);
-
- /* Set global variable SerialICE_mainboard */
- lua_pushstring(L, serialice_mainboard);
- lua_setglobal(L, "SerialICE_mainboard");
-
- /* Enable Register Access */
- serialice_lua_registers();
-
- /* Load the script file */
- status = luaL_loadfile(L, serialice_lua_script);
- if (status) {
- fprintf(stderr, "Couldn't load SerialICE script: %s\n",
- lua_tostring(L, -1));
- exit(1);
- }
-
- /* Ask Lua to run our little script */
- status = lua_pcall(L, 0, 1, 0);
- if (status) {
- fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1));
- exit(1);
- }
- lua_pop(L, 1);
-
- return 0;
-}
-
-static int serialice_lua_exit(void)
-{
- lua_close(L);
- return 0;
-}
-
-const char *serialice_lua_execute(const char *cmd)
-{
- int error;
- char *errstring = NULL;
- error = luaL_loadbuffer(L, cmd, strlen(cmd), "line")
- || lua_pcall(L, 0, 0, 0);
- if (error) {
- errstring = strdup(lua_tostring(L, -1));
- lua_pop(L, 1);
- }
-
- return errstring;
-}
-
-static int serialice_io_read_filter(uint32_t * data, uint16_t port, int size)
-{
- int ret, result;
-
- lua_getglobal(L, "SerialICE_io_read_filter");
- lua_pushinteger(L, port); // port
- lua_pushinteger(L, size); // datasize
- result = lua_pcall(L, 2, 2, 0);
- if (result) {
- fprintf(stderr, "Failed to run function SerialICE_io_read_filter: %s\n",
- lua_tostring(L, -1));
- exit(1);
- }
- *data = lua_tointeger(L, -1);
- ret = lua_toboolean(L, -2);
- lua_pop(L, 2);
-
- return ret;
-}
-
-static int serialice_io_write_filter(uint32_t * data, uint16_t port, int size)
-{
- int ret, result;
-
- lua_getglobal(L, "SerialICE_io_write_filter");
- lua_pushinteger(L, port); // port
- lua_pushinteger(L, size); // datasize
- lua_pushinteger(L, *data); // data
-
- result = lua_pcall(L, 3, 2, 0);
- if (result) {
- fprintf(stderr,
- "Failed to run function SerialICE_io_write_filter: %s\n",
- lua_tostring(L, -1));
- exit(1);
- }
- *data = lua_tointeger(L, -1);
- ret = lua_toboolean(L, -2);
- lua_pop(L, 2);
-
- return ret;
-}
-
-#define READ_FROM_QEMU (1 << 0)
-#define READ_FROM_SERIALICE (1 << 1)
-static int serialice_memory_read_filter(uint32_t addr, uint32_t * data,
- int size)
-{
- int ret = 0, result;
-
- lua_getglobal(L, "SerialICE_memory_read_filter");
- lua_pushinteger(L, addr); // addr
- lua_pushinteger(L, size); // datasize
- result = lua_pcall(L, 2, 3, 0);
- if (result) {
- fprintf(stderr,
- "Failed to run function SerialICE_memory_read_filter: %s\n",
- lua_tostring(L, -1));
- exit(1);
- }
-
- *data = lua_tointeger(L, -1); // result
-
- ret |= lua_toboolean(L, -2) ? READ_FROM_QEMU : 0; // to_qemu
- ret |= lua_toboolean(L, -3) ? READ_FROM_SERIALICE : 0; // to_hw
-
- lua_pop(L, 3);
-
- return ret;
-}
-
-#define WRITE_TO_QEMU (1 << 0)
-#define WRITE_TO_SERIALICE (1 << 1)
-
-static int serialice_memory_write_filter(uint32_t addr, int size,
- uint32_t * data)
-{
- int ret = 0, result;
- int write_to_qemu, write_to_serialice;
-
- lua_getglobal(L, "SerialICE_memory_write_filter");
- lua_pushinteger(L, addr); // address
- lua_pushinteger(L, size); // datasize
- lua_pushinteger(L, *data); // data
- result = lua_pcall(L, 3, 3, 0);
- if (result) {
- fprintf(stderr,
- "Failed to run function SerialICE_memory_write_filter: %s\n",
- lua_tostring(L, -1));
- exit(1);
- }
- *data = lua_tointeger(L, -1);
- write_to_qemu = lua_toboolean(L, -2);
- write_to_serialice = lua_toboolean(L, -3);
- lua_pop(L, 3);
-
- ret |= write_to_qemu ? WRITE_TO_QEMU : 0;
- ret |= write_to_serialice ? WRITE_TO_SERIALICE : 0;
-
- return ret;
-}
-
-#define FILTER_READ 0
-#define FILTER_WRITE 1
-
-static int serialice_msr_filter(int flags, uint32_t addr, uint32_t * hi,
- uint32_t * lo)
-{
- int ret, result;
-
- if (flags & FILTER_WRITE) {
- lua_getglobal(L, "SerialICE_msr_write_filter");
- } else {
- lua_getglobal(L, "SerialICE_msr_read_filter");
- }
-
- lua_pushinteger(L, addr); // port
- lua_pushinteger(L, *hi); // high
- lua_pushinteger(L, *lo); // low
- result = lua_pcall(L, 3, 3, 0);
- if (result) {
- fprintf(stderr,
- "Failed to run function SerialICE_msr_%s_filter: %s\n",
- (flags & FILTER_WRITE) ? "write" : "read", lua_tostring(L, -1));
- exit(1);
- }
- ret = lua_toboolean(L, -3);
- if (ret) {
- *hi = lua_tointeger(L, -1);
- *lo = lua_tointeger(L, -2);
- }
- lua_pop(L, 3);
-
- return ret;
-}
-
-static int serialice_cpuid_filter(uint32_t eax, uint32_t ecx,
- cpuid_regs_t * regs)
-{
- int ret, result;
-
- lua_getglobal(L, "SerialICE_cpuid_filter");
-
- lua_pushinteger(L, eax); // eax before calling
- lua_pushinteger(L, ecx); // ecx before calling
- // and the registers after calling cpuid
- lua_pushinteger(L, regs->eax); // eax
- lua_pushinteger(L, regs->ebx); // ebx
- lua_pushinteger(L, regs->ecx); // ecx
- lua_pushinteger(L, regs->edx); // edx
- result = lua_pcall(L, 6, 5, 0);
- if (result) {
- fprintf(stderr,
- "Failed to run function SerialICE_cpuid_filter: %s\n",
- lua_tostring(L, -1));
- exit(1);
- }
-
- ret = lua_toboolean(L, -5);
- if (ret) {
- regs->eax = lua_tointeger(L, -4);
- regs->ebx = lua_tointeger(L, -3);
- regs->ecx = lua_tointeger(L, -2);
- regs->edx = lua_tointeger(L, -1);
- }
- lua_pop(L, 5);
-
- return ret;
-}
-
-/* SerialICE output loggers */
-
-#define LOG_IO 0
-#define LOG_MEMORY 1
-#define LOG_READ 0
-#define LOG_WRITE 2
-// these two are separate
-#define LOG_QEMU 4
-#define LOG_TARGET 8
-
-static void serialice_log(int flags, uint32_t data, uint32_t addr, int size)
-{
- int result;
-
- if ((flags & LOG_WRITE) && (flags & LOG_MEMORY)) {
- lua_getglobal(L, "SerialICE_memory_write_log");
- } else if (!(flags & LOG_WRITE) && (flags & LOG_MEMORY)) {
- lua_getglobal(L, "SerialICE_memory_read_log");
- } else if ((flags & LOG_WRITE) && !(flags & LOG_MEMORY)) {
- lua_getglobal(L, "SerialICE_io_write_log");
- } else { // if (!(flags & LOG_WRITE) && !(flags & LOG_MEMORY))
- lua_getglobal(L, "SerialICE_io_read_log");
- }
-
- lua_pushinteger(L, addr); // addr/port
- lua_pushinteger(L, size); // datasize
- lua_pushinteger(L, data); // data
- lua_pushboolean(L, ((flags & LOG_TARGET) != 0));
-
- result = lua_pcall(L, 4, 0, 0);
- if (result) {
- fprintf(stderr, "Failed to run function SerialICE_%s_%s_log: %s\n",
- (flags & LOG_MEMORY) ? "memory" : "io",
- (flags & LOG_WRITE) ? "write" : "read", lua_tostring(L, -1));
- exit(1);
- }
-}
-
-static void serialice_msr_log(int flags, uint32_t addr, uint32_t hi,
- uint32_t lo, int filtered)
-{
- int result;
-
- if (flags & LOG_WRITE) {
- lua_getglobal(L, "SerialICE_msr_write_log");
- } else { // if (!(flags & LOG_WRITE))
- lua_getglobal(L, "SerialICE_msr_read_log");
- }
-
- lua_pushinteger(L, addr); // addr/port
- lua_pushinteger(L, hi); // datasize
- lua_pushinteger(L, lo); // data
- lua_pushboolean(L, filtered); // data
- result = lua_pcall(L, 4, 0, 0);
- if (result) {
- fprintf(stderr, "Failed to run function SerialICE_msr_%s_log: %s\n",
- (flags & LOG_WRITE) ? "write" : "read", lua_tostring(L, -1));
- exit(1);
- }
-}
-
-static void serialice_cpuid_log(uint32_t eax, uint32_t ecx, cpuid_regs_t res,
- int filtered)
-{
- int result;
-
- lua_getglobal(L, "SerialICE_cpuid_log");
-
- lua_pushinteger(L, eax); // input: eax
- lua_pushinteger(L, ecx); // input: ecx
- lua_pushinteger(L, res.eax); // output: eax
- lua_pushinteger(L, res.ebx); // output: ebx
- lua_pushinteger(L, res.ecx); // output: ecx
- lua_pushinteger(L, res.edx); // output: edx
- lua_pushboolean(L, filtered); // data
- result = lua_pcall(L, 7, 0, 0);
- if (result) {
- fprintf(stderr, "Failed to run function SerialICE_cpuid_log: %s\n",
- lua_tostring(L, -1));
- exit(1);
- }
-}
-
-// **************************************************************************
-// low level communication with the SerialICE shell (serial communication)
-
-static int serialice_read(SerialICEState * state, void *buf, size_t nbyte)
+/* FIXME */
+#if 1
+static void fix_data(uint32_t * data, unsigned int size)
{
- int bytes_read = 0;
-
- while (1) {
-#ifdef WIN32
- int ret = 0;
- ReadFile(state->fd, buf, nbyte - bytes_read, &ret, NULL);
- if (!ret) {
- break;
- }
-#else
- int ret = read(state->fd, buf, nbyte - bytes_read);
-
- if (ret == -1 && errno == EINTR) {
- continue;
- }
-
- if (ret == -1) {
- break;
- }
-#endif
-
- bytes_read += ret;
- buf += ret;
-
- if (bytes_read >= (int)nbyte) {
- break;
- }
+ switch (size) {
+ case 1:
+ *data &= 0xff;
+ return;
+ case 2:
+ *data &= 0xffff;
+ return;
+ case 4:
+ *data &= 0xffffffff;
+ return;
}
-
- return bytes_read;
+ return;
}
-
-static int handshake_mode = 0;
-
-static int serialice_write(SerialICEState * state, const void *buf,
- size_t nbyte)
-{
- char *buffer = (char *)buf;
- char c;
- int i;
-
- for (i = 0; i < (int)nbyte; i++) {
-#ifdef WIN32
- int ret = 0;
- while (ret == 0) {
- WriteFile(state->fd, buffer + i, 1, &ret, NULL);
- }
- ret = 0;
- while (ret == 0) {
- ReadFile(state->fd, &c, 1, &ret, NULL);
- }
#else
- while (write(state->fd, buffer + i, 1) != 1) ;
- while (read(state->fd, &c, 1) != 1) ;
-#endif
- if (c != buffer[i] && !handshake_mode) {
- printf("Readback error! %x/%x\n", c, buffer[i]);
- }
- }
-
- return nbyte;
-}
-
-static int serialice_wait_prompt(void)
-{
- char buf[3];
- int l;
-
- l = serialice_read(s, buf, 3);
-
- if (l == -1) {
- perror("SerialICE: Could not read from target");
- exit(1);
- }
-
- while (buf[0] != '\n' || buf[1] != '>' || buf[2] != ' ') {
- buf[0] = buf[1];
- buf[1] = buf[2];
- l = serialice_read(s, buf + 2, 1);
- if (l == -1) {
- perror("SerialICE: Could not read from target");
- exit(1);
- }
- }
-
- return 0;
-}
-
-static void serialice_command(const char *command, int reply_len)
-{
-#if SERIALICE_DEBUG > 5
- int i;
+#define fix_data(x)
#endif
- int l;
-
- serialice_wait_prompt();
-
- serialice_write(s, command, strlen(command));
- memset(s->buffer, 0, reply_len + 1); // clear enough of the buffer
-
- l = serialice_read(s, s->buffer, reply_len);
-
- if (l == -1) {
- perror("SerialICE: Could not read from target");
- exit(1);
- }
- // compensate for CR on the wire. Needed on Win32
- if (s->buffer[0] == '\r') {
- memmove(s->buffer, s->buffer + 1, reply_len);
- serialice_read(s, s->buffer + reply_len - 1, 1);
- }
-
- if (l != reply_len) {
- printf("SerialICE: command was not answered sufficiently: "
- "(%d/%d bytes)\n'%s'\n", l, reply_len, s->buffer);
- exit(1);
- }
-#if SERIALICE_DEBUG > 5
- for (i = 0; i < reply_len; i++) {
- printf("%02x ", s->buffer[i]);
- }
- printf("\n");
-#endif
-}
-
-// **************************************************************************
-// high level communication with the SerialICE shell
-
-static void serialice_get_version(void)
-{
- int len = 0;
- printf("SerialICE: Version.....: ");
- serialice_command("*vi", 0);
-
- memset(s->buffer, 0, BUFFER_SIZE);
- serialice_read(s, s->buffer, 1);
- serialice_read(s, s->buffer, 1);
- while (s->buffer[len++] != '\n') {
- serialice_read(s, s->buffer + len, 1);
- }
- s->buffer[len - 1] = '\0';
-
- printf("%s\n", s->buffer);
-}
-
-static void serialice_get_mainboard(void)
-{
- int len = 31;
-
- printf("SerialICE: Mainboard...: ");
- serialice_command("*mb", 32);
- while (len && s->buffer[len] == ' ') {
- s->buffer[len--] = '\0';
- }
- serialice_mainboard = strdup(s->buffer + 1);
- printf("%s\n", serialice_mainboard);
-}
-
-uint8_t serialice_inb(uint16_t port)
-{
- uint8_t ret;
- uint32_t data;
- int filtered;
-
- filtered = serialice_io_read_filter(&data, port, 1);
-
- if (filtered) {
- ret = data & 0xff;
- } else {
- sprintf(s->command, "*ri%04x.b", port);
- // command read back: "\n00" (3 characters)
- serialice_command(s->command, 3);
- ret = (uint8_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- }
-
- serialice_log(LOG_READ | LOG_IO, ret, port, 1);
-
- return ret;
-}
-
-uint16_t serialice_inw(uint16_t port)
-{
- uint16_t ret;
- uint32_t data;
- int filtered;
-
- filtered = serialice_io_read_filter(&data, port, 2);
-
- if (filtered) {
- ret = data & 0xffff;
- } else {
- sprintf(s->command, "*ri%04x.w", port);
- // command read back: "\n0000" (5 characters)
- serialice_command(s->command, 5);
- ret = (uint16_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- }
-
- serialice_log(LOG_READ | LOG_IO, ret, port, 2);
-
- return ret;
-}
-
-uint32_t serialice_inl(uint16_t port)
-{
- uint32_t ret;
- uint32_t data;
- int filtered;
-
- filtered = serialice_io_read_filter(&data, port, 4);
-
- if (filtered) {
- ret = data;
- } else {
- sprintf(s->command, "*ri%04x.l", port);
- // command read back: "\n00000000" (9 characters)
- serialice_command(s->command, 9);
- ret = (uint32_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- }
-
- serialice_log(LOG_READ | LOG_IO, ret, port, 4);
-
- return ret;
-}
-
-void serialice_outb(uint8_t data, uint16_t port)
-{
- uint32_t filtered_data = (uint32_t) data;
- int filtered;
-
- filtered = serialice_io_write_filter(&filtered_data, port, 1);
-
- if (filtered) {
- data = (uint8_t) filtered_data;
- } else {
- data = (uint8_t) filtered_data;
- sprintf(s->command, "*wi%04x.b=%02x", port, data);
- serialice_command(s->command, 0);
- }
-
- serialice_log(LOG_WRITE | LOG_IO, data, port, 1);
-}
-
-void serialice_outw(uint16_t data, uint16_t port)
-{
- uint32_t filtered_data = (uint32_t) data;
- int filtered;
-
- filtered = serialice_io_write_filter(&filtered_data, port, 2);
-
- if (filtered) {
- data = (uint16_t) filtered_data;
- } else {
- data = (uint16_t) filtered_data;
- sprintf(s->command, "*wi%04x.w=%04x", port, data);
- serialice_command(s->command, 0);
- }
-
- serialice_log(LOG_WRITE | LOG_IO, data, port, 2);
-}
-
-void serialice_outl(uint32_t data, uint16_t port)
-{
- uint32_t filtered_data = data;
- int filtered;
-
- filtered = serialice_io_write_filter(&filtered_data, port, 4);
-
- if (filtered) {
- data = filtered_data;
- } else {
- data = filtered_data;
- sprintf(s->command, "*wi%04x.l=%08x", port, data);
- serialice_command(s->command, 0);
- }
-
- serialice_log(LOG_WRITE | LOG_IO, data, port, 4);
-}
-
-uint8_t serialice_readb(uint32_t addr)
-{
- uint8_t ret;
- sprintf(s->command, "*rm%08x.b", addr);
- // command read back: "\n00" (3 characters)
- serialice_command(s->command, 3);
- ret = (uint8_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- return ret;
-}
-
-uint16_t serialice_readw(uint32_t addr)
-{
- uint16_t ret;
- sprintf(s->command, "*rm%08x.w", addr);
- // command read back: "\n0000" (5 characters)
- serialice_command(s->command, 5);
- ret = (uint16_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- return ret;
-}
-
-uint32_t serialice_readl(uint32_t addr)
-{
- uint32_t ret;
- sprintf(s->command, "*rm%08x.l", addr);
- // command read back: "\n00000000" (9 characters)
- serialice_command(s->command, 9);
- ret = (uint32_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- return ret;
-}
-
-void serialice_writeb(uint8_t data, uint32_t addr)
-{
- sprintf(s->command, "*wm%08x.b=%02x", addr, data);
- serialice_command(s->command, 0);
-}
-
-void serialice_writew(uint16_t data, uint32_t addr)
-{
- sprintf(s->command, "*wm%08x.w=%04x", addr, data);
- serialice_command(s->command, 0);
-}
-
-void serialice_writel(uint32_t data, uint32_t addr)
-{
- sprintf(s->command, "*wm%08x.l=%08x", addr, data);
- serialice_command(s->command, 0);
-}
+/* SerialICE output loggers */
uint64_t serialice_rdmsr(uint32_t addr, uint32_t key)
{
- uint32_t hi, lo;
- uint64_t ret;
- int filtered;
+ uint32_t hi = 0, lo = 0;
+ uint64_t data;
- filtered = serialice_msr_filter(FILTER_READ, addr, &hi, &lo);
- if (!filtered) {
- sprintf(s->command, "*rc%08x.%08x", addr, key);
+ int source = sfil->rdmsr_pre(addr);
- // command read back: "\n00000000.00000000" (18 characters)
- serialice_command(s->command, 18);
+ if (source & READ_FROM_SERIALICE)
+ stgt->rdmsr(addr, key, &hi, &lo);
- s->buffer[9] = 0; // . -> \0
- hi = (uint32_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- lo = (uint32_t) strtoul(s->buffer + 10, (char **)NULL, 16);
+ if (source & READ_FROM_QEMU) {
+ data = cpu_rdmsr(addr);
+ hi = (data >> 32);
+ lo = (data & 0xffffffff);
}
- ret = hi;
- ret <<= 32;
- ret |= lo;
-
- serialice_msr_log(LOG_READ, addr, hi, lo, filtered);
-
- return ret;
+ sfil->rdmsr_post(&hi, &lo);
+ data = hi;
+ data <<= 32;
+ data |= lo;
+ return data;
}
void serialice_wrmsr(uint64_t data, uint32_t addr, uint32_t key)
{
- uint32_t hi, lo;
- int filtered;
-
- hi = (data >> 32);
- lo = (data & 0xffffffff);
+ uint32_t hi = (data >> 32);
+ uint32_t lo = (data & 0xffffffff);
- filtered = serialice_msr_filter(FILTER_WRITE, addr, &hi, &lo);
+ int target = sfil->wrmsr_pre(addr, &hi, &lo);
- if (!filtered) {
- sprintf(s->command, "*wc%08x.%08x=%08x.%08x", addr, key, hi, lo);
- serialice_command(s->command, 0);
+ if (target & WRITE_TO_SERIALICE)
+ stgt->wrmsr(addr, key, hi, lo);
+ if (target & WRITE_TO_QEMU) {
+ data = lo | ((uint64_t) hi) << 32;
+ cpu_wrmsr(addr, data);
}
-
- serialice_msr_log(LOG_WRITE, addr, hi, lo, filtered);
+ sfil->wrmsr_post();
}
cpuid_regs_t serialice_cpuid(uint32_t eax, uint32_t ecx)
{
cpuid_regs_t ret;
- int filtered;
+ ret.eax = ret.ebx = ret.ecx = ret.edx = 0;
+ int source = sfil->cpuid_pre(eax, ecx);
- ret.eax = eax;
- ret.ebx = 0; // either set by filter or by target
- ret.ecx = ecx;
- ret.edx = 0; // either set by filter or by target
-
- sprintf(s->command, "*ci%08x.%08x", eax, ecx);
-
- // command read back: "\n000006f2.00000000.00001234.12340324"
- // (36 characters)
- serialice_command(s->command, 36);
-
- s->buffer[9] = 0; // . -> \0
- s->buffer[18] = 0; // . -> \0
- s->buffer[27] = 0; // . -> \0
- ret.eax = (uint32_t) strtoul(s->buffer + 1, (char **)NULL, 16);
- ret.ebx = (uint32_t) strtoul(s->buffer + 10, (char **)NULL, 16);
- ret.ecx = (uint32_t) strtoul(s->buffer + 19, (char **)NULL, 16);
- ret.edx = (uint32_t) strtoul(s->buffer + 28, (char **)NULL, 16);
-
- filtered = serialice_cpuid_filter(eax, ecx, &ret);
-
- serialice_cpuid_log(eax, ecx, ret, filtered);
+ if (source & READ_FROM_SERIALICE)
+ stgt->cpuid(eax, ecx, &ret);
+ if (source & READ_FROM_QEMU)
+ ret = cpu_cpuid(eax, ecx);
+ sfil->cpuid_post(&ret);
return ret;
}
// **************************************************************************
// memory load handling
-static uint32_t serialice_load_wrapper(uint32_t addr, unsigned int size)
-{
- switch (size) {
- case 1:
- return (uint32_t) serialice_readb(addr);
- case 2:
- return (uint32_t) serialice_readw(addr);
- case 4:
- return (uint32_t) serialice_readl(addr);
- default:
- printf("WARNING: unknown read access size %d @%08x\n", size, addr);
- }
- return 0;
-}
-
/**
* This function is called by the softmmu engine to update the status
* of a load cycle
@@ -976,12 +151,7 @@ static uint32_t serialice_load_wrapper(uint32_t addr, unsigned int size)
void serialice_log_load(int caught, uint32_t addr, uint32_t result,
unsigned int data_size)
{
- if (caught) {
- serialice_log(LOG_READ | LOG_MEMORY | LOG_TARGET, result, addr,
- data_size);
- } else {
- serialice_log(LOG_READ | LOG_MEMORY, result, addr, data_size);
- }
+ sfil->load_post(&result);
}
/* This function can grab Qemu load ops and forward them to the SerialICE
@@ -989,81 +159,64 @@ void serialice_log_load(int caught, uint32_t addr, uint32_t result,
*
* @return 0: pass on to Qemu; 1: handled locally.
*/
-int serialice_handle_load(uint32_t addr, uint32_t * result,
- unsigned int data_size)
+int serialice_handle_load(uint32_t addr, uint32_t * data, unsigned int size)
{
- int source;
-
- source = serialice_memory_read_filter(addr, result, data_size);
-
- if (source & READ_FROM_SERIALICE) {
- *result = serialice_load_wrapper(addr, data_size);
- return 1;
- }
+ int source = sfil->load_pre(addr, size);
- if (source & READ_FROM_QEMU) {
- return 0;
- }
+ if (source & READ_FROM_SERIALICE)
+ *data = stgt->load(addr, size);
- /* No source for load, so the source is the script */
- return 1;
+ return !(source & READ_FROM_QEMU);
}
// **************************************************************************
// memory store handling
-static void serialice_store_wrapper(uint32_t addr, unsigned int size,
- uint32_t data)
-{
- switch (size) {
- case 1:
- serialice_writeb((uint8_t) data, addr);
- break;
- case 2:
- serialice_writew((uint16_t) data, addr);
- break;
- case 4:
- serialice_writel((uint32_t) data, addr);
- break;
- default:
- printf("WARNING: unknown write access size %d @%08x\n", size, addr);
- }
-}
-
-static void serialice_log_store(int caught, uint32_t addr, uint32_t val,
- unsigned int data_size)
-{
- if (caught) {
- serialice_log(LOG_WRITE | LOG_MEMORY | LOG_TARGET, val, addr,
- data_size);
- } else {
- serialice_log(LOG_WRITE | LOG_MEMORY, val, addr, data_size);
- }
-}
-
/* This function can grab Qemu store ops and forward them to the SerialICE
* target
*
* @return 0: Qemu exclusive or shared; 1: SerialICE exclusive.
*/
-int serialice_handle_store(uint32_t addr, uint32_t val, unsigned int data_size)
+int serialice_handle_store(uint32_t addr, uint32_t data, unsigned int size)
{
- int write_to_target, write_to_qemu, ret;
- uint32_t filtered_data = val;
+ int target = sfil->store_pre(addr, size, &data);
- ret = serialice_memory_write_filter(addr, data_size, &filtered_data);
+ if (target & WRITE_TO_SERIALICE)
+ stgt->store(addr, size, data);
- write_to_target = ((ret & WRITE_TO_SERIALICE) != 0);
- write_to_qemu = ((ret & WRITE_TO_QEMU) != 0);
+ sfil->store_post();
- serialice_log_store(write_to_target, addr, filtered_data, data_size);
+ return !(target & WRITE_TO_QEMU);
+}
- if (write_to_target) {
- serialice_store_wrapper(addr, data_size, filtered_data);
- }
+uint32_t serialice_io_read(uint16_t port, unsigned int size)
+{
+ uint32_t data = 0;
+ int source = sfil->io_read_pre(port, size);
+
+ if (source & READ_FROM_QEMU)
+ data = cpu_io_read_wrapper(port, size);
+ if (source & READ_FROM_SERIALICE)
+ data = stgt->io_read(port, size);
+
+ sfil->io_read_post(&data);
+ fix_data(&data, size);
+ return data;
+}
+
+void serialice_io_write(uint16_t port, unsigned int size, uint32 data)
+{
+ fix_data(&data, size);
+ int target = sfil->io_write_pre(&data, port, size);
+ fix_data(&data, size);
+
+ if (target & WRITE_TO_QEMU)
+ cpu_io_write_wrapper(port, size, data);
+ if (target & WRITE_TO_SERIALICE)
+ stgt->io_write(port, size, data);
- return (write_to_qemu == 0);
+ sfil->io_write_post();
}
static int screen_invalid = 1;
@@ -1077,11 +230,11 @@ static void serialice_refresh(void *opaque)
return;
}
- dest = ds_get_data(s->ds);
- bpp = (ds_get_bits_per_pixel(s->ds) + 7) >> 3;
- linesize = ds_get_linesize(s->ds);
+ dest = ds_get_data(d->ds);
+ bpp = (ds_get_bits_per_pixel(d->ds) + 7) >> 3;
+ linesize = ds_get_linesize(d->ds);
- memset(dest, 0x00, linesize * ds_get_height(s->ds));
+ memset(dest, 0x00, linesize * ds_get_height(d->ds));
#if SERIALICE_BANNER
int x, y;
if (bpp == 4) {
@@ -1099,7 +252,7 @@ static void serialice_refresh(void *opaque)
}
#endif
- dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
+ dpy_update(d->ds, 0, 0, ds_get_width(d->ds), ds_get_height(d->ds));
screen_invalid = 0;
}
@@ -1111,114 +264,23 @@ static void serialice_invalidate(void *opaque)
// **************************************************************************
// initialization and exit
-void serialice_init(void)
+static void serialice_screen(void)
{
- s = qemu_mallocz(sizeof(SerialICEState));
-
- s->ds = graphic_console_init(serialice_refresh, serialice_invalidate,
- NULL, NULL, s);
- qemu_console_resize(s->ds, 320, 240);
-
- printf("SerialICE: Open connection to target hardware...\n");
-
- if (serialice_device == NULL) {
- printf("You need to specify a serial device to use SerialICE.\n");
- exit(1);
- }
-#ifdef WIN32
- s->fd = CreateFile(serialice_device, GENERIC_READ | GENERIC_WRITE,
- 0, NULL, OPEN_EXISTING, 0, NULL);
-
- if (s->fd == INVALID_HANDLE_VALUE) {
- perror("SerialICE: Could not connect to target TTY");
- exit(1);
- }
-
- DCB dcb;
- if (!GetCommState(s->fd, &dcb)) {
- perror("SerialICE: Could not load config for target TTY");
- exit(1);
- }
-
- dcb.BaudRate = CBR_115200;
- dcb.ByteSize = 8;
- dcb.Parity = NOPARITY;
- dcb.StopBits = ONESTOPBIT;
-
- if (!SetCommState(s->fd, &dcb)) {
- perror("SerialICE: Could not store config for target TTY");
- exit(1);
- }
-#else
- s->fd = open(serialice_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
-
- if (s->fd == -1) {
- perror("SerialICE: Could not connect to target TTY");
- exit(1);
- }
-
- if (ioctl(s->fd, TIOCEXCL) == -1) {
- perror("SerialICE: TTY not exclusively available");
- exit(1);
- }
-
- if (fcntl(s->fd, F_SETFL, 0) == -1) {
- perror("SerialICE: Could not switch to blocking I/O");
- exit(1);
- }
-
- if (tcgetattr(s->fd, &options) == -1) {
- perror("SerialICE: Could not get TTY attributes");
- exit(1);
- }
-
- cfsetispeed(&options, B115200);
- cfsetospeed(&options, B115200);
-
- /* set raw input, 1 second timeout */
- options.c_cflag |= (CLOCAL | CREAD);
- options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
- options.c_oflag &= ~OPOST;
- options.c_iflag |= IGNCR;
- options.c_cc[VMIN] = 0;
- options.c_cc[VTIME] = 100;
-
- tcsetattr(s->fd, TCSANOW, &options);
-
- tcflush(s->fd, TCIOFLUSH);
-#endif
-
- s->buffer = qemu_mallocz(BUFFER_SIZE);
- s->command = qemu_mallocz(BUFFER_SIZE);
-
- printf("SerialICE: Waiting for handshake with target... ");
-
- handshake_mode = 1; // Readback errors are to be expected in this phase.
-
- /* Trigger a prompt */
- serialice_write(s, "@", 1);
-
- /* ... and wait for it to appear */
- if (serialice_wait_prompt() == 0) {
- printf("target alive!\n");
- } else {
- printf("target not ok!\n");
- exit(1);
- }
-
- /* Each serialice_command() waits for a prompt, so trigger one for the
- * first command, as we consumed the last one for the handshake
- */
- serialice_write(s, "@", 1);
-
- handshake_mode = 0; // from now on, warn about readback errors.
+ d = qemu_mallocz(sizeof(SerialICEScreen));
+ d->ds = graphic_console_init(serialice_refresh, serialice_invalidate,
+ NULL, NULL, d);
+ qemu_console_resize(d->ds, 320, 240);
+}
- serialice_get_version();
+void serialice_init(void)
+{
+ serialice_screen();
- serialice_get_mainboard();
+ stgt = serialice_com_init();
+ stgt->version();
+ stgt->mainboard();
- printf("SerialICE: LUA init...\n");
- serialice_lua_init();
+ sfil = serialice_lua_init(SERIALICE_LUA_SCRIPT);
/* Let the rest of Qemu know we're alive */
serialice_active = 1;
@@ -1227,9 +289,8 @@ void serialice_init(void)
void serialice_exit(void)
{
serialice_lua_exit();
- qemu_free(s->command);
- qemu_free(s->buffer);
- qemu_free(s);
+ serialice_com_exit();
+ qemu_free(d);
}
static void pc_init_serialice(ram_addr_t ram_size,
diff --git a/qemu-0.15.x/serialice.h b/qemu-0.15.x/serialice.h
index a651618..94072d4 100644
--- a/qemu-0.15.x/serialice.h
+++ b/qemu-0.15.x/serialice.h
@@ -32,28 +32,19 @@
#error "SerialICE currently only supports x86 and x64 platforms."
#endif
+#define WRITE_TO_QEMU (1 << 0)
+#define WRITE_TO_SERIALICE (1 << 1)
+#define READ_FROM_QEMU (1 << 0)
+#define READ_FROM_SERIALICE (1 << 1)
+
extern const char *serialice_device;
extern int serialice_active;
void serialice_init(void);
void serialice_exit(void);
-const char *serialice_lua_execute(const char *cmd);
-
-uint8_t serialice_inb(uint16_t port);
-uint16_t serialice_inw(uint16_t port);
-uint32_t serialice_inl(uint16_t port);
-
-void serialice_outb(uint8_t data, uint16_t port);
-void serialice_outw(uint16_t data, uint16_t port);
-void serialice_outl(uint32_t data, uint16_t port);
-
-uint8_t serialice_readb(uint32_t addr);
-uint16_t serialice_readw(uint32_t addr);
-uint32_t serialice_readl(uint32_t addr);
-void serialice_writeb(uint8_t data, uint32_t addr);
-void serialice_writew(uint16_t data, uint32_t addr);
-void serialice_writel(uint32_t data, uint32_t addr);
+uint32_t serialice_io_read(uint16_t port, unsigned int size);
+void serialice_io_write(uint16_t port, unsigned int size, uint32_t data);
uint64_t serialice_rdmsr(uint32_t addr, uint32_t key);
void serialice_wrmsr(uint64_t data, uint32_t addr, uint32_t key);
@@ -70,4 +61,48 @@ void serialice_log_load(int caught, uint32_t addr, uint32_t result,
unsigned int data_size);
int serialice_handle_store(uint32_t addr, uint32_t val, unsigned int data_size);
+/* serialice protocol */
+typedef struct {
+ void (*version) (void);
+ void (*mainboard) (void);
+ uint32_t (*io_read) (uint16_t port, unsigned int size);
+ void (*io_write) (uint16_t port, unsigned int size, uint32_t data);
+ uint32_t (*load) (uint32_t addr, unsigned int size);
+ void (*store) (uint32_t addr, unsigned int size, uint32_t data);
+ void (*rdmsr) (uint32_t addr, uint32_t key, uint32_t * hi, uint32_t * lo);
+ void (*wrmsr) (uint32_t addr, uint32_t key, uint32_t hi, uint32_t lo);
+ void (*cpuid) (uint32_t eax, uint32_t ecx, cpuid_regs_t * ret);
+} SerialICE_target;
+
+const SerialICE_target *serialice_com_init(void);
+void serialice_com_exit(void);
+
+/* serialice-lua */
+
+extern const char *serialice_mainboard;
+
+typedef struct {
+ int (*io_read_pre) (uint16_t port, int size);
+ void (*io_read_post) (uint32_t * data);
+ int (*io_write_pre) (uint32_t * data, uint16_t port, int size);
+ void (*io_write_post) (void);
+
+ int (*load_pre) (uint32_t addr, int size);
+ void (*load_post) (uint32_t * data);
+ int (*store_pre) (uint32_t addr, int size, uint32_t * data);
+ void (*store_post) (void);
+
+ int (*rdmsr_pre) (uint32_t addr);
+ void (*rdmsr_post) (uint32_t * hi, uint32_t * lo);
+ int (*wrmsr_pre) (uint32_t addr, uint32_t * hi, uint32_t * lo);
+ void (*wrmsr_post) (void);
+
+ int (*cpuid_pre) (uint32_t eax, uint32_t ecx);
+ void (*cpuid_post) (cpuid_regs_t * res);
+} SerialICE_filter;
+
+const SerialICE_filter *serialice_lua_init(const char *serialice_lua_script);
+void serialice_lua_exit(void);
+const char *serialice_lua_execute(const char *cmd);
+
#endif
diff --git a/qemu-0.15.x/target-i386/cpu.h b/qemu-0.15.x/target-i386/cpu.h
index 9819b5f..44f9353 100644
--- a/qemu-0.15.x/target-i386/cpu.h
+++ b/qemu-0.15.x/target-i386/cpu.h
@@ -1055,6 +1055,10 @@ void do_smm_enter(CPUState *env1);
void svm_check_intercept(CPUState *env1, uint32_t type);
+void cpu_wrmsr(uint64_t val, uint32_t addr);
+uint64_t cpu_rdmsr(uint32_t addr);
+cpuid_regs_t cpu_cpuid(uint32_t in_eax, uint32_t in_ecx);
+
uint32_t cpu_cc_compute_all(CPUState *env1, int op);
#endif /* CPU_I386_H */
diff --git a/qemu-0.15.x/target-i386/op_helper.c b/qemu-0.15.x/target-i386/op_helper.c
index 81c8075..1823c74 100644
--- a/qemu-0.15.x/target-i386/op_helper.c
+++ b/qemu-0.15.x/target-i386/op_helper.c
@@ -559,7 +559,7 @@ void helper_outb(uint32_t port, uint32_t data)
{
#ifdef CONFIG_SERIALICE
if (serialice_active) {
- serialice_outb(data & 0xff, port);
+ serialice_io_write(port, 1, data);
return;
}
#endif
@@ -570,7 +570,7 @@ target_ulong helper_inb(uint32_t port)
{
#ifdef CONFIG_SERIALICE
if (serialice_active) {
- return (target_ulong) serialice_inb(port);
+ return (target_ulong) serialice_io_read(port, 1);
}
#endif
return cpu_inb(port);
@@ -580,7 +580,7 @@ void helper_outw(uint32_t port, uint32_t data)
{
#ifdef CONFIG_SERIALICE
if (serialice_active) {
- serialice_outw(data & 0xffff, port);
+ serialice_io_write(port, 2, data);
return;
}
#endif
@@ -591,7 +591,7 @@ target_ulong helper_inw(uint32_t port)
{
#ifdef CONFIG_SERIALICE
if (serialice_active) {
- return (target_ulong) serialice_inw(port);
+ return (target_ulong) serialice_io_read(port, 2);
}
#endif
return cpu_inw(port);
@@ -601,7 +601,7 @@ void helper_outl(uint32_t port, uint32_t data)
{
#ifdef CONFIG_SERIALICE
if (serialice_active) {
- serialice_outl(data & 0xffffffff, port);
+ serialice_io_write(port, 4, data);
return;
}
#endif
@@ -612,7 +612,7 @@ target_ulong helper_inl(uint32_t port)
{
#ifdef CONFIG_SERIALICE
if (serialice_active) {
- return (target_ulong) serialice_inl(port);
+ return (target_ulong) serialice_io_read(port, 4);
}
#endif
return cpu_inl(port);
@@ -2010,29 +2010,31 @@ void helper_single_step(void)
raise_exception(EXCP01_DB);
}
-void helper_cpuid(void)
+cpuid_regs_t cpu_cpuid(uint32_t in_eax, uint32_t in_ecx)
{
- uint32_t eax, ebx, ecx, edx;
+ cpuid_regs_t ret;
+ cpu_x86_cpuid(env, in_eax, in_ecx, &ret.eax, &ret.ebx, &ret.ecx, &ret.edx);
+ return ret;
+}
+void helper_cpuid(void)
+{
+ cpuid_regs_t ret;
helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
#ifdef CONFIG_SERIALICE
- if (serialice_active) {
- cpuid_regs_t ret;
+ if (serialice_active)
ret = serialice_cpuid((uint32_t) EAX, (uint32_t) ECX);
- EAX = ret.eax;
- EBX = ret.ebx;
- ECX = ret.ecx;
- EDX = ret.edx;
- return;
- }
+ else
+ ret = cpu_cpuid((uint32_t) EAX, (uint32_t) ECX);
+#else
+ cpu_x86_cpuid(env, (uint32_t) EAX, (uint32_t) ECX, &ret.eax, &ret.ebx, &ret.ecx, &ret.edx);
#endif
- cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
- EAX = eax;
- EBX = ebx;
- ECX = ecx;
- EDX = edx;
+ EAX = ret.eax;
+ EBX = ret.ebx;
+ ECX = ret.ecx;
+ EDX = ret.edx;
}
void helper_enter_level(int level, int data32, target_ulong t1)
@@ -3091,22 +3093,10 @@ void helper_rdmsr(void)
{
}
#else
-void helper_wrmsr(void)
-{
- uint64_t val;
-
- helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
-
- val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
-
-#ifdef CONFIG_SERIALICE
- if (serialice_active) {
- serialice_wrmsr(val, (uint32_t) ECX, (uint32_t) EDI);
- return;
- }
-#endif
- switch((uint32_t)ECX) {
+void cpu_wrmsr(uint64_t val, uint32_t addr)
+{
+ switch(addr) {
case MSR_IA32_SYSENTER_CS:
env->sysenter_cs = val & 0xffff;
break;
@@ -3176,7 +3166,7 @@ void helper_wrmsr(void)
case MSR_MTRRphysBase(5):
case MSR_MTRRphysBase(6):
case MSR_MTRRphysBase(7):
- env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
+ env->mtrr_var[(addr - MSR_MTRRphysBase(0)) / 2].base = val;
break;
case MSR_MTRRphysMask(0):
case MSR_MTRRphysMask(1):
@@ -3186,14 +3176,14 @@ void helper_wrmsr(void)
case MSR_MTRRphysMask(5):
case MSR_MTRRphysMask(6):
case MSR_MTRRphysMask(7):
- env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
+ env->mtrr_var[(addr - MSR_MTRRphysMask(0)) / 2].mask = val;
break;
case MSR_MTRRfix64K_00000:
- env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
+ env->mtrr_fixed[addr - MSR_MTRRfix64K_00000] = val;
break;
case MSR_MTRRfix16K_80000:
case MSR_MTRRfix16K_A0000:
- env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
+ env->mtrr_fixed[addr - MSR_MTRRfix16K_80000 + 1] = val;
break;
case MSR_MTRRfix4K_C0000:
case MSR_MTRRfix4K_C8000:
@@ -3203,7 +3193,7 @@ void helper_wrmsr(void)
case MSR_MTRRfix4K_E8000:
case MSR_MTRRfix4K_F0000:
case MSR_MTRRfix4K_F8000:
- env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
+ env->mtrr_fixed[addr - MSR_MTRRfix4K_C0000 + 3] = val;
break;
case MSR_MTRRdefType:
env->mtrr_deftype = val;
@@ -3220,9 +3210,9 @@ void helper_wrmsr(void)
env->tsc_aux = val;
break;
default:
- if ((uint32_t)ECX >= MSR_MC0_CTL
- && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
- uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
+ if (addr >= MSR_MC0_CTL
+ && addr < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
+ uint32_t offset = addr - MSR_MC0_CTL;
if ((offset & 0x3) != 0
|| (val == 0 || val == ~(uint64_t)0))
env->mce_banks[offset] = val;
@@ -3233,22 +3223,11 @@ void helper_wrmsr(void)
}
}
-void helper_rdmsr(void)
+uint64_t cpu_rdmsr(uint32_t addr)
{
uint64_t val;
- helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
-
-#ifdef CONFIG_SERIALICE
- if (serialice_active) {
- val = serialice_rdmsr((uint32_t) ECX, (uint32_t) EDI);
- EAX = (uint32_t) (val);
- EDX = (uint32_t) (val >> 32);
- return;
- }
-#endif
-
- switch((uint32_t)ECX) {
+ switch(addr) {
case MSR_IA32_SYSENTER_CS:
val = env->sysenter_cs;
break;
@@ -3310,7 +3289,7 @@ void helper_rdmsr(void)
case MSR_MTRRphysBase(5):
case MSR_MTRRphysBase(6):
case MSR_MTRRphysBase(7):
- val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;
+ val = env->mtrr_var[(addr - MSR_MTRRphysBase(0)) / 2].base;
break;
case MSR_MTRRphysMask(0):
case MSR_MTRRphysMask(1):
@@ -3320,14 +3299,14 @@ void helper_rdmsr(void)
case MSR_MTRRphysMask(5):
case MSR_MTRRphysMask(6):
case MSR_MTRRphysMask(7):
- val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;
+ val = env->mtrr_var[(addr - MSR_MTRRphysMask(0)) / 2].mask;
break;
case MSR_MTRRfix64K_00000:
val = env->mtrr_fixed[0];
break;
case MSR_MTRRfix16K_80000:
case MSR_MTRRfix16K_A0000:
- val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];
+ val = env->mtrr_fixed[addr - MSR_MTRRfix16K_80000 + 1];
break;
case MSR_MTRRfix4K_C0000:
case MSR_MTRRfix4K_C8000:
@@ -3337,7 +3316,7 @@ void helper_rdmsr(void)
case MSR_MTRRfix4K_E8000:
case MSR_MTRRfix4K_F0000:
case MSR_MTRRfix4K_F8000:
- val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];
+ val = env->mtrr_fixed[addr - MSR_MTRRfix4K_C0000 + 3];
break;
case MSR_MTRRdefType:
val = env->mtrr_deftype;
@@ -3362,9 +3341,9 @@ void helper_rdmsr(void)
val = env->mcg_status;
break;
default:
- if ((uint32_t)ECX >= MSR_MC0_CTL
- && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
- uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
+ if (addr >= MSR_MC0_CTL
+ && addr < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
+ uint32_t offset = addr - MSR_MC0_CTL;
val = env->mce_banks[offset];
break;
}
@@ -3372,10 +3351,39 @@ void helper_rdmsr(void)
val = 0;
break;
}
+ return val;
+}
+
+void helper_wrmsr(void)
+{
+ uint64_t val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
+ helper_svm_check_intercept_param(SVM_EXIT_MSR, 1);
+#ifdef CONFIG_SERIALICE
+ if (serialice_active)
+ serialice_wrmsr(val, (uint32_t)ECX, (uint32_t) EDI);
+ else
+ cpu_wrmsr(val, (uint32_t)ECX);
+#else
+ cpu_wrmsr(val, (uint32_t)ECX);
+#endif
+}
+
+void helper_rdmsr(void)
+{
+ uint64_t val;
+ helper_svm_check_intercept_param(SVM_EXIT_MSR, 0);
+#ifdef CONFIG_SERIALICE
+ if (serialice_active)
+ val = serialice_rdmsr((uint32_t) ECX, (uint32_t) EDI);
+ else
+ val = cpu_rdmsr((uint32_t) ECX);
+#else
+ val = cpu_rdmsr((uint32_t) ECX);
+#endif
EAX = (uint32_t)(val);
EDX = (uint32_t)(val >> 32);
}
-#endif
+#endif /* CONFIG_USER_ONLY */
target_ulong helper_lsl(target_ulong selector1)
{
More information about the SerialICE
mailing list