Werner Zeh has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/36016 )
Change subject: x86 gdb: Extend GDB stub with I/O read and write commands ......................................................................
x86 gdb: Extend GDB stub with I/O read and write commands
Provide functionality in the GDB stub to read and write I/O ports on x86 CPUs.
NOT FOR MERGE!!!
Change-Id: I8718c576bba149475444947b6cc3d4932547e6eb Signed-off-by: Werner Zeh werner.zeh@siemens.com --- M src/arch/x86/exception.c 1 file changed, 86 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/16/36016/1
diff --git a/src/arch/x86/exception.c b/src/arch/x86/exception.c index b88f4a7..c2783d5 100644 --- a/src/arch/x86/exception.c +++ b/src/arch/x86/exception.c @@ -21,6 +21,7 @@ #include <cpu/x86/lapic.h> #include <stdint.h> #include <string.h> +#include <arch/io.h>
#if CONFIG(GDB_STUB)
@@ -335,6 +336,8 @@ /* now, read until a # or end of buffer is found */ while (count < BUFMAX) { ch = stub_getc() & 0x7f; + if (!ch) + continue; if (ch == '#') break; checksum = checksum + ch; @@ -412,7 +415,7 @@ put_packet(out_buffer);
while (1) { - unsigned long addr, length; + unsigned long addr, length, val; char *ptr; out_buffer[0] = '\0'; out_buffer[1] = '\0'; @@ -462,6 +465,88 @@ } else memcpy(out_buffer, "E02", 4); break; + case 'n': + /* nAA..AA,LLLL,w Read I/O port given by AA..AA. */ + /* Use access width defined with w (b:byte, w:word, + * l:long) and read LLLL number of entries */ + ptr = &in_buffer[1]; + if (parse_ulong(&ptr, &addr) && + (*(ptr++) == ',') && + parse_ulong(&ptr, &length) && + (*(ptr++) == ',') && + ((*(ptr) == 'b') || (*(ptr) == 'w') || + (*(ptr) == 'l'))) { + char width = *(ptr++), len; + char *out_buf_ptr = out_buffer; + unsigned long i, tmp; + /* Read desired amount of I/O ports */ + for (i = 0; i < length; i++) { + switch (width) { + case 'l': + tmp = inl(addr); + /* Rotate the byte order as */ + /* copy_to_hex() works on a */ + /* byte stream. */ + val = (((tmp >> 24) & 0xff) | + (((tmp >> 16) & 0xff) << 8) | + (((tmp >> 8) & 0xff) << 16) | + ((tmp & 0xff) << 24)); + len = 4; + break; + case 'w': + tmp = inw(addr); + /* Rotate the byte order as */ + /* copy_to_hex() works on a */ + /* byte stream. */ + val = (((tmp >> 8) & 0xff) | + ((tmp & 0xff) << 8)); + len = 2; + break; + case 'b': + default: + val = inb(addr); + len = 1; + break; + + } + copy_to_hex(out_buf_ptr, (void *)&val, + len); + out_buf_ptr += len << 1; + addr += len; + } + } else + memcpy(out_buffer, "E03", 4); + break; + case 'N': + /* nAA..AA,VVVV,w: Write I/O port given by AA..AA. */ + /* Use access width defined with w (b:byte, w:word, + * l:long) and write value given by VVVV. */ + ptr = &in_buffer[1]; + if (parse_ulong(&ptr, &addr) && + (*(ptr++) == ',') && + parse_ulong(&ptr, &val) && + (*(ptr++) == ',') && + ((*(ptr) == 'b') || (*(ptr) == 'w') || + (*(ptr) == 'l')) && + (*(++ptr) == ':')) { + char width = *(ptr - 1); + + switch (width) { + case 'l': + outl(val, addr); + break; + case 'w': + outw(val, addr); + break; + case 'b': + default: + outb(val, addr); + break; + } + memcpy(out_buffer, "OK", 3); + } else + memcpy(out_buffer, "E04", 4); + break; case 's': case 'c': /* cAA..AA Continue at address AA..AA(optional)