Kyösti Mälkki (kyosti.malkki@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@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@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) {