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/1013
-gerrit
commit 096a0f5fc6cef64245f19aeee62e3990ee3c3cdf Author: Kyösti Mälkki kyosti.malkki@gmail.com Date: Sun May 6 16:30:12 2012 +0300
SerialICE: Change lua call API for IO
After the change, it is possible to divert selected IO accesses to Qemu instead of the SerialICE target. Also it is possible to modify the result of an IO read before it is given back to Qemu.
This also adds the IO wrapper functions targeting Qemu.
Change-Id: I35ecc0ac9357286f857bff3a73abae65440f544a Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- qemu-0.15.x/ioport.c | 33 +++++ qemu-0.15.x/ioport.h | 3 + qemu-0.15.x/serialice.c | 269 +++++++++++++++++------------------ qemu-0.15.x/serialice.h | 9 +- qemu-0.15.x/target-i386/op_helper.c | 12 +- 5 files changed, 172 insertions(+), 154 deletions(-)
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.c b/qemu-0.15.x/serialice.c index ca34991..10623e5 100644 --- a/qemu-0.15.x/serialice.c +++ b/qemu-0.15.x/serialice.c @@ -89,6 +89,22 @@ static struct termios options;
static lua_State *L;
+ +#define WRITE_TO_QEMU (1 << 0) +#define WRITE_TO_SERIALICE (1 << 1) + +#define READ_FROM_QEMU (1 << 0) +#define READ_FROM_SERIALICE (1 << 1) + +#define LOG_IO (1<<0) +#define LOG_MEMORY (1<<1) +#define LOG_MSR (1<<2) + +/* FIXME */ +#define LOG_TARGET (1<<3) +#define LOG_READ (1<<4) +#define LOG_WRITE (1<<5) + // ************************************************************************** // LUA scripting interface and callbacks
@@ -128,6 +144,27 @@ static int serialice_system_reset(lua_State * luastate) return 0; }
+/* FIXME */ +#if 1 +static void fix_data(uint32_t * data, unsigned int size) +{ + switch (size) { + case 1: + *data &= 0xff; + return; + case 2: + *data &= 0xffff; + return; + case 4: + *data &= 0xffffffff; + return; + } + return; +} +#else +#define fix_data(x) +#endif + // ************************************************************************** // LUA register access
@@ -290,51 +327,51 @@ const char *serialice_lua_execute(const char *cmd) return errstring; }
-static int serialice_io_read_filter(uint32_t * data, uint16_t port, int size) +static int serialice_io_read_filter(uint16_t port, int size) { - int ret, result; + 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); } - *data = lua_tointeger(L, -1); - ret = lua_toboolean(L, -2); - lua_pop(L, 2);
+ 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 serialice_io_write_filter(uint32_t * data, uint16_t port, int size) { - int ret, result; + 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, 2, 0); + 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); - lua_pop(L, 2);
+ *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; }
-#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) { @@ -361,9 +398,6 @@ static int serialice_memory_read_filter(uint32_t addr, uint32_t * data, 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) { @@ -462,13 +496,55 @@ static int serialice_cpuid_filter(uint32_t eax, uint32_t ecx,
/* 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_read_log(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 serialice_write_log(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 serialice_log(int flags, uint32_t data, uint32_t addr, int size) { @@ -707,125 +783,6 @@ static void serialice_get_mainboard(void) 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); -}
uint64_t serialice_rdmsr(uint32_t addr, uint32_t key) @@ -988,6 +945,36 @@ int serialice_handle_store(uint32_t addr, uint32_t val, unsigned int data_size) return (write_to_qemu == 0); }
+ +uint32_t serialice_io_read(uint16_t port, unsigned int size) +{ + uint32_t data = 0; + int source = serialice_io_read_filter(port, size); + + if (source & READ_FROM_QEMU) + data = cpu_io_read_wrapper(port, size); + if (source & READ_FROM_SERIALICE) + data = serialice_io_read_wrapper(port, size); + + serialice_read_log(LOG_IO, &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 = serialice_io_write_filter(&data, port, size); + fix_data(&data, size); + + if (target & WRITE_TO_QEMU) + cpu_io_write_wrapper(port, size, data); + if (target & WRITE_TO_SERIALICE) + serialice_io_write_wrapper(port, size, data); + + serialice_write_log(LOG_IO); +} + static int screen_invalid = 1;
static void serialice_refresh(void *opaque) diff --git a/qemu-0.15.x/serialice.h b/qemu-0.15.x/serialice.h index 64ae5c5..c2caefb 100644 --- a/qemu-0.15.x/serialice.h +++ b/qemu-0.15.x/serialice.h @@ -40,13 +40,8 @@ void serialice_exit(void); const char *serialice_lua_execute(const char *cmd); void serialice_command(const char *command, int reply_len);
-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); +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); diff --git a/qemu-0.15.x/target-i386/op_helper.c b/qemu-0.15.x/target-i386/op_helper.c index 81c8075..1650bba 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);