From db9fad13f192963786c7ac90d305467ac00bd145 Mon Sep 17 00:00:00 2001 From: Joshua Alan Wise Date: Tue, 18 Aug 2009 21:04:37 -0400 Subject: [PATCH] Apply patches from jdpotter@google.com, as submitted to NetWatch Maintainer Team in messageid 7e6c8d660908181741y5787d3eaga2db4ede5a248a30@mail.gmail.com --- include/cpuid.h | 50 +++ include/minilib.h | 2 + include/output.h | 6 + include/state.h | 99 ++++++ lib/cpuid.S | 56 ++++ lib/crc32.c | 2 +- lib/minilib.c | 17 + lib/state.c | 239 +++++++++++++ lwip/src/include/lwipopts.h | 8 +- net/http/fs.c | 39 ++- netwatch/keyboard.c | 313 ++++++++++-------- .../{pagingstub-asm.s => pagingstub-asm.S} | 0 netwatch/pagingstub.c | 39 ++- netwatch/traps.c | 142 +++++--- 14 files changed, 805 insertions(+), 207 deletions(-) create mode 100644 include/cpuid.h create mode 100644 include/state.h create mode 100644 lib/cpuid.S create mode 100644 lib/state.c rename netwatch/{pagingstub-asm.s => pagingstub-asm.S} (100%) diff --git a/include/cpuid.h b/include/cpuid.h new file mode 100644 index 0000000..d6a54a1 --- /dev/null +++ b/include/cpuid.h @@ -0,0 +1,50 @@ +/* cpuid.h + * Definitions needed for CPUID wrapper + * NetWatch system management mode administration console + * + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CPUID_H +#define __CPUID_H + +#include + +struct cpuid_result { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +}; + +void cpuid(int eax, struct cpuid_result *output); + +#endif /* __CPUID_H */ + diff --git a/include/minilib.h b/include/minilib.h index 2e7eca6..d5afd2b 100644 --- a/include/minilib.h +++ b/include/minilib.h @@ -15,6 +15,7 @@ extern void memcpy(void *dest, const void *src, int bytes); extern void memset(void *dest, int data, int bytes); +extern void *memchr(const void *buf, char c, int maxlen); extern void memmove(void *dest, void *src, int bytes); extern int memcmp(const char *a2, const char *a1, int bytes); extern int strcmp(const char *a2, const char *a1); @@ -24,6 +25,7 @@ extern void strcat(char *dest, char *src); extern void strcpy(char *a2, const char *a1); extern void puts(const char *c); extern void tohex(char *s, unsigned long l); +extern void btohex(char *s, unsigned char c); extern void puthex(unsigned long l); extern int vsprintf(char *s, const char *fmt, va_list args); extern int vsnprintf(char *s, int size, const char *fmt, va_list args); diff --git a/include/output.h b/include/output.h index 5c1101a..7964f03 100644 --- a/include/output.h +++ b/include/output.h @@ -14,4 +14,10 @@ extern void (*output)(const char *s); extern void (*outputf)(const char *s, ...); +#if DEBUG80 +#define DBG(x) outb(0x80, x) +#else +#define DBG(x) +#endif + #endif diff --git a/include/state.h b/include/state.h new file mode 100644 index 0000000..fd19612 --- /dev/null +++ b/include/state.h @@ -0,0 +1,99 @@ +/* state.h + * Definitions for SMM saved-state manipulation functions. + * NetWatch system management mode administration console + * + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STATE_H +#define __STATE_H + +#include + +enum state_reg_t { + /* Common registers */ + STATE_REV, + STATE_REG_SMBASE, + STATE_REG_IORESTART, + STATE_REG_HALTRESTART, + + /* 32-bit registers (still available in 64-bit mode) */ + STATE_REG_EAX, + STATE_REG_EBX, + STATE_REG_ECX, + STATE_REG_EDX, + STATE_REG_ESI, + STATE_REG_EDI, + STATE_REG_ESP, + STATE_REG_EBP, + STATE_REG_EIP, + STATE_REG_EFLAGS, + STATE_REG_CR0, + STATE_REG_CR3, + + STATE_REG_CS, + STATE_REG_SS, + STATE_REG_DS, + STATE_REG_ES, + STATE_REG_FS, + STATE_REG_GS, + + /* 64-bit registers */ + STATE_REG_RAX, + STATE_REG_RBX, + STATE_REG_RCX, + STATE_REG_RDX, + STATE_REG_RSI, + STATE_REG_RDI, + STATE_REG_RSP, + STATE_REG_RBP, + STATE_REG_R8, + STATE_REG_R9, + STATE_REG_R10, + STATE_REG_R11, + STATE_REG_R12, + STATE_REG_R13, + STATE_REG_R14, + STATE_REG_R15, + STATE_REG_RIP +}; + +enum smm_type { + SMM_TYPE_UNKNOWN, + SMM_TYPE_32, + SMM_TYPE_64 +}; + +uint64_t state_get_reg (enum state_reg_t reg); +int state_reg_size (enum state_reg_t reg); +int state_set_reg (enum state_reg_t reg, uint64_t value); + +#endif /* __STATE_H */ + diff --git a/lib/cpuid.S b/lib/cpuid.S new file mode 100644 index 0000000..6216a56 --- /dev/null +++ b/lib/cpuid.S @@ -0,0 +1,56 @@ +/* cpuid.S + * CPUID wrapper + * NetWatch system management mode administration console + * + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.global cpuid +cpuid: + // Save registers + push %ebx + push %edi + + // Load arguments from stack + mov 12(%esp), %eax + mov 16(%esp), %edi + + cpuid + + // Save results into output pointer + mov %eax, (%edi) + mov %ebx, 4(%edi) + mov %ecx, 8(%edi) + mov %edx, 12(%edi) + + // All done! + pop %edi + pop %ebx + ret diff --git a/lib/crc32.c b/lib/crc32.c index 43f9d7a..a5512f6 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -3,7 +3,7 @@ /* code from http://www.faqs.org/faqs/compression-faq/part1/section-26.html, * presumed public domain */ -uint32_t crc32_table[256]; +static uint32_t crc32_table[256]; uint32_t crc32(uint8_t *buf, int len, uint32_t crc0) { diff --git a/lib/minilib.c b/lib/minilib.c index 392eae7..935d0c4 100644 --- a/lib/minilib.c +++ b/lib/minilib.c @@ -74,6 +74,17 @@ void memset(void *dest, int data, int bytes) *(cdest++) = (unsigned char)data; } +void *memchr(const void *buf, char c, int maxlen) +{ + const char * cbuf = buf; + while (maxlen--) + { + if (*cbuf == c) return (void *)cbuf; + cbuf++; + } + return 0; +} + void memmove(void *dest, void *src, int bytes) { char * cdest = dest; @@ -157,6 +168,12 @@ void tohex(char *s, unsigned long l) } } +void btohex(char *s, unsigned char c) +{ + s[0] = hexarr[c >> 4]; + s[1] = hexarr[c & 0xF]; +} + void puthex(unsigned long l) { char d[9]; diff --git a/lib/state.c b/lib/state.c new file mode 100644 index 0000000..368029b --- /dev/null +++ b/lib/state.c @@ -0,0 +1,239 @@ +/* state.c + * SMM saved state manipulation functions. + * NetWatch system management mode administration console + * + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "state.h" +#include + +/* Size flags. */ +#define SZ_BYTE 0x10000000 +#define SZ_WORD 0x20000000 +#define SZ_DWORD 0x40000000 +#define SZ_QWORD 0x80000000 +#define OFFSET_MASK 0x0FFFFFFF + +static const uint32_t offset_table_legacy[] = { + [STATE_REV] = 0xfefc | SZ_DWORD, + [STATE_REG_SMBASE] = 0xfef8 | SZ_DWORD, + [STATE_REG_IORESTART] = 0xff00 | SZ_WORD, + [STATE_REG_HALTRESTART] = 0xff02 | SZ_WORD, + + [STATE_REG_EAX] = 0xffd0 | SZ_DWORD, + [STATE_REG_EBX] = 0xffdc | SZ_DWORD, + [STATE_REG_ECX] = 0xffd4 | SZ_DWORD, + [STATE_REG_EDX] = 0xffd8 | SZ_DWORD, + [STATE_REG_ESI] = 0xffe8 | SZ_DWORD, + [STATE_REG_EDI] = 0xffec | SZ_DWORD, + [STATE_REG_ESP] = 0xffe0 | SZ_DWORD, + [STATE_REG_EBP] = 0xffe4 | SZ_DWORD, + [STATE_REG_EIP] = 0xfff0 | SZ_DWORD, + [STATE_REG_EFLAGS] = 0xfff4 | SZ_DWORD, + [STATE_REG_CR0] = 0xfffc | SZ_DWORD, + [STATE_REG_CR3] = 0xfff8 | SZ_DWORD, + + [STATE_REG_CS] = 0xffac | SZ_DWORD, + [STATE_REG_SS] = 0xffb0 | SZ_DWORD, + [STATE_REG_DS] = 0xffb4 | SZ_DWORD, + [STATE_REG_ES] = 0xffa8 | SZ_DWORD, + [STATE_REG_FS] = 0xffb8 | SZ_DWORD, + [STATE_REG_GS] = 0xffbc | SZ_DWORD +}; + +#define MAX_REG_LEGACY (sizeof(offset_table_legacy)/sizeof(uint32_t)) + +static const uint32_t offset_table_amd64[] = { + [STATE_REV] = 0xfefc | SZ_DWORD, + [STATE_REG_SMBASE] = 0xff00 | SZ_DWORD, + [STATE_REG_IORESTART] = 0xfec8 | SZ_BYTE, + [STATE_REG_HALTRESTART] = 0xfec9 | SZ_BYTE, + + [STATE_REG_EAX] = 0xfff8 | SZ_DWORD, + [STATE_REG_EBX] = 0xffe0 | SZ_DWORD, + [STATE_REG_ECX] = 0xfff0 | SZ_DWORD, + [STATE_REG_EDX] = 0xffe8 | SZ_DWORD, + [STATE_REG_ESI] = 0xffc8 | SZ_DWORD, + [STATE_REG_EDI] = 0xffc0 | SZ_DWORD, + [STATE_REG_ESP] = 0xffd8 | SZ_DWORD, + [STATE_REG_EBP] = 0xffd0 | SZ_DWORD, + [STATE_REG_EIP] = 0xff78 | SZ_DWORD, + [STATE_REG_EFLAGS] = 0xff70 | SZ_DWORD, + [STATE_REG_CR0] = 0xff58 | SZ_DWORD, + [STATE_REG_CR3] = 0xff50 | SZ_DWORD, + + [STATE_REG_CS] = 0xfe10 | SZ_DWORD, + [STATE_REG_SS] = 0xfe20 | SZ_DWORD, + [STATE_REG_DS] = 0xfe30 | SZ_DWORD, + [STATE_REG_ES] = 0xfe00 | SZ_DWORD, + [STATE_REG_FS] = 0xfe40 | SZ_DWORD, + [STATE_REG_GS] = 0xfe50 | SZ_DWORD, + + [STATE_REG_RAX] = 0xfff8 | SZ_QWORD, + [STATE_REG_RBX] = 0xffe0 | SZ_QWORD, + [STATE_REG_RCX] = 0xfff0 | SZ_QWORD, + [STATE_REG_RDX] = 0xffe8 | SZ_QWORD, + [STATE_REG_RSI] = 0xffc8 | SZ_QWORD, + [STATE_REG_RDI] = 0xffc0 | SZ_QWORD, + [STATE_REG_RSP] = 0xffd8 | SZ_QWORD, + [STATE_REG_RBP] = 0xffd0 | SZ_QWORD, + [STATE_REG_R8] = 0xffb8 | SZ_QWORD, + [STATE_REG_R9] = 0xffb0 | SZ_QWORD, + [STATE_REG_R10] = 0xffa8 | SZ_QWORD, + [STATE_REG_R11] = 0xffa0 | SZ_QWORD, + [STATE_REG_R12] = 0xff98 | SZ_QWORD, + [STATE_REG_R13] = 0xff90 | SZ_QWORD, + [STATE_REG_R14] = 0xff88 | SZ_QWORD, + [STATE_REG_R15] = 0xff80 | SZ_QWORD, + [STATE_REG_RIP] = 0xff78 | SZ_QWORD +}; + +#define MAX_REG_AMD64 (sizeof(offset_table_amd64)/sizeof(uint32_t)) + +static enum smm_type smm_type = SMM_TYPE_64; + +/* Probe CPUID to figure out what kind of processor this actually is. + * We memoize this in 'smm_type', so cpuid only needs to happen once. + */ + +static void check_smm_type (void) { + + struct cpuid_result r; + + if (smm_type != SMM_TYPE_UNKNOWN) + return; + + cpuid(0x80000000, &r); + + if (r.eax < 0x80000001) { + smm_type = SMM_TYPE_32; + return; + } + + cpuid(0x80000001, &r); + + if (r.edx & 0x20000000) { + smm_type = SMM_TYPE_64; + } else { + smm_type = SMM_TYPE_32; + } +} + +/* Get the offset of a register, by looking up in the appropriate table. + */ + +static unsigned long get_offset(enum state_reg_t reg) { + + check_smm_type(); + + if (smm_type == SMM_TYPE_32 && reg < MAX_REG_LEGACY) + return offset_table_legacy[reg]; + else if (smm_type == SMM_TYPE_64 && reg < MAX_REG_AMD64) + return offset_table_amd64[reg]; + else + return 0; +} + +/* Which variety of processor are we running on? + */ + +enum smm_type state_get_type (void) { + check_smm_type(); + return smm_type; +} + +/* Get a register. + * + * We assume that Aseg is always direct-mapped at 0xA0000. This may + * not be the case in the future, with multiple cores, but it is a + * safe assumption now. + */ + +uint64_t state_get_reg (enum state_reg_t reg) { + unsigned long offset = get_offset(reg); + void * addr; + uint64_t value; + + if (!offset) + return 0; + + addr = (void *)((offset & OFFSET_MASK) + 0xA0000); + + if (offset & SZ_BYTE) + value = *(uint8_t *)addr; + else if (offset & SZ_WORD) + value = *(uint16_t *)addr; + else if (offset & SZ_DWORD) + value = *(uint32_t *)addr; + else + value = *(uint64_t *)addr; + + return value; +} + +/* Get the size of a register, extracted from the saved state offset table. + */ + +int state_reg_size (enum state_reg_t reg) { + unsigned long offset = get_offset(reg); + + if (offset & SZ_BYTE) return 1; + else if (offset & SZ_WORD) return 2; + else if (offset & SZ_DWORD) return 4; + else if (offset & SZ_QWORD) return 8; + else return 0; +} + +/* Modify a saved register. + * + * The same caveat about aseg's location applies here as well. + */ + +int state_set_reg (enum state_reg_t reg, uint64_t value) { + unsigned long offset = get_offset(reg); + void * addr; + + if (!offset) + return -1; + + addr = (void *)((offset & OFFSET_MASK) + 0xA0000); + + if (offset & SZ_BYTE) + *(uint8_t *)addr = (uint8_t) value; + else if (offset & SZ_WORD) + *(uint16_t *)addr = (uint16_t) value; + else if (offset & SZ_DWORD) + *(uint32_t *)addr = (uint32_t) value; + else + *(uint64_t *)addr = value; + + return 0; +} diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index 368bf86..31a53f1 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -29,7 +29,11 @@ extern void _memcpy(void *dest, const void *src, int bytes); #define LWIP_STATS 1 #define LWIP_STATS_DISPLAY 1 -#define U16_F "d" -#define U32_F "d" +#define U16_F "u" +#define S16_F "d" +#define X16_F "x" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" #endif diff --git a/net/http/fs.c b/net/http/fs.c index 0bf11cb..4fe2c41 100644 --- a/net/http/fs.c +++ b/net/http/fs.c @@ -38,13 +38,13 @@ #include #include +static char http_output_buffer[1024]; + /*-----------------------------------------------------------------------------------*/ void handle_regs(struct fs_file *file) { - static char buf[2048]; - - sprintf(buf, + file->len = snprintf(http_output_buffer, sizeof(http_output_buffer), "Registers" "

At the time you requested this page, the system's registers were:

" "
"
@@ -64,54 +64,57 @@ void handle_regs(struct fs_file *file)
     *(unsigned long*)0xAFFF8,
     *(unsigned long*)0xAFFF0,
     *(unsigned long*)0xAFFF4);
-    
   
-  file->data = buf;
-  file->len = strlen(buf)-1;
+  file->data = http_output_buffer;
 }
 
+#define LEFT (sizeof(http_output_buffer) - len)
+
 void handle_backtrace(struct fs_file *file)
 {
-  static char buf[2048];
-  static char buf2[64];
   int i = 10;
+  int len;
   unsigned long *pebp, *peip;
   unsigned long ebp;
   unsigned long cr3;
+
+  char * buf = http_output_buffer;
   
   strcpy(buf, "Backtrace
");
+  len = strlen(buf);
   ebp = *(unsigned long *)0xAFFE4;
   cr3 = *(unsigned long *)0xAFFF8;
   
-  sprintf(buf2, "0x%08x, from\n", *(unsigned long*)0xAFFF0);
-  strcat(buf, buf2);
+  len += snprintf(buf + len, LEFT, "0x%08x, from\n", *(unsigned long*)0xAFFF0);
   
   /* I never thought I'd do this again. */
   while ((peip = demap(cr3, ebp+4)) != 0x0 && i--)
   {
-    sprintf(buf2, "0x%08x, from\n", *peip);
-    strcat(buf, buf2);
+    len += snprintf(buf + len, LEFT, "0x%08x, from\n", *peip);
+
     pebp = demap(cr3, ebp);
     if (!pebp)
     {
-      strcat(buf, "<unreadable %ebp>\n");
+      len += snprintf(buf + len, LEFT, "<unreadable %ebp>\n");
       break;
     }
     if (ebp >= *pebp && *pebp)
     {
-      strcat(buf, "<recursive %ebp>\n");
+      len += snprintf(buf + len, LEFT, "<recursive %ebp>\n");
       break;
     }
     ebp = *pebp;
   }
+
   if (i == -1)
-    strcat(buf, "...\n");
+    len += snprintf(buf + len, LEFT, "...\n");
   else
-    strcat(buf, "<root>");
-  strcat(buf, "
"); + len += snprintf(buf + len, LEFT, "<root>"); + + len += snprintf(buf + len, LEFT, "
"); file->data = buf; - file->len = strlen(buf)-1; + file->len = len; } void handle_reboot(struct fs_file *file) diff --git a/netwatch/keyboard.c b/netwatch/keyboard.c index 64be445..b4f1b58 100644 --- a/netwatch/keyboard.c +++ b/netwatch/keyboard.c @@ -18,126 +18,153 @@ static int kbd_inj_start = 0; static int kbd_inj_end = 0; int kbd_mode = 1; -static const char scancodes2[][2][8] = { - ['a'] = { "\x1c", "\xf0\x1c" }, - ['b'] = { "\x32", "\xf0\x32" }, - ['c'] = { "\x21", "\xf0\x21" }, - ['d'] = { "\x23", "\xf0\x23" }, - ['e'] = { "\x24", "\xf0\x24" }, - ['f'] = { "\x2b", "\xf0\x2b" }, - ['g'] = { "\x34", "\xf0\x34" }, - ['h'] = { "\x33", "\xf0\x33" }, - ['i'] = { "\x43", "\xf0\x43" }, - ['j'] = { "\x3b", "\xf0\x3b" }, - ['k'] = { "\x42", "\xf0\x42" }, - ['l'] = { "\x4b", "\xf0\x4b" }, - ['m'] = { "\x3a", "\xf0\x3a" }, - ['n'] = { "\x31", "\xf0\x31" }, - ['o'] = { "\x44", "\xf0\x44" }, - ['p'] = { "\x4d", "\xf0\x4d" }, - ['q'] = { "\x15", "\xf0\x15" }, - ['r'] = { "\x2d", "\xf0\x2d" }, - ['s'] = { "\x1b", "\xf0\x1b" }, - ['t'] = { "\x2c", "\xf0\x2c" }, - ['u'] = { "\x3c", "\xf0\x3c" }, - ['v'] = { "\x2a", "\xf0\x2a" }, - ['w'] = { "\x1d", "\xf0\x1d" }, - ['x'] = { "\x22", "\xf0\x22" }, - ['y'] = { "\x35", "\xf0\x35" }, - ['z'] = { "\x1a", "\xf0\x1a" }, - ['A'] = { "\x12\x1c", "\xf0\x1c\xf0\x12" }, - ['B'] = { "\x12\x32", "\xf0\x32\xf0\x12" }, - ['C'] = { "\x12\x21", "\xf0\x21\xf0\x12" }, - ['D'] = { "\x12\x23", "\xf0\x23\xf0\x12" }, - ['E'] = { "\x12\x24", "\xf0\x24\xf0\x12" }, - ['F'] = { "\x12\x2b", "\xf0\x2b\xf0\x12" }, - ['G'] = { "\x12\x34", "\xf0\x34\xf0\x12" }, - ['H'] = { "\x12\x33", "\xf0\x33\xf0\x12" }, - ['I'] = { "\x12\x43", "\xf0\x43\xf0\x12" }, - ['J'] = { "\x12\x3b", "\xf0\x3b\xf0\x12" }, - ['K'] = { "\x12\x42", "\xf0\x42\xf0\x12" }, - ['L'] = { "\x12\x4b", "\xf0\x4b\xf0\x12" }, - ['M'] = { "\x12\x3a", "\xf0\x3a\xf0\x12" }, - ['N'] = { "\x12\x31", "\xf0\x31\xf0\x12" }, - ['O'] = { "\x12\x44", "\xf0\x44\xf0\x12" }, - ['P'] = { "\x12\x4d", "\xf0\x4d\xf0\x12" }, - ['Q'] = { "\x12\x15", "\xf0\x15\xf0\x12" }, - ['R'] = { "\x12\x2d", "\xf0\x2d\xf0\x12" }, - ['S'] = { "\x12\x1b", "\xf0\x1b\xf0\x12" }, - ['T'] = { "\x12\x2c", "\xf0\x2c\xf0\x12" }, - ['U'] = { "\x12\x3c", "\xf0\x3c\xf0\x12" }, - ['V'] = { "\x12\x2a", "\xf0\x2a\xf0\x12" }, - ['W'] = { "\x12\x1d", "\xf0\x1d\xf0\x12" }, - ['X'] = { "\x12\x22", "\xf0\x22\xf0\x12" }, - ['Y'] = { "\x12\x35", "\xf0\x35\xf0\x12" }, - ['Z'] = { "\x12\x1a", "\xf0\x1a\xf0\x12" }, - ['`'] = { "\x0e", "\xf0\x0e" }, - ['~'] = { "\x12\x0e", "\xf0\x0e\xf0\x12" }, - ['1'] = { "\x16", "\xf0\x16" }, - ['!'] = { "\x12\x16", "\xf0\x16\xf0\x12" }, - ['2'] = { "\x1e", "\xf0\x1e" }, - ['@'] = { "\x12\x1e", "\xf0\x1e\xf0\x12" }, - ['3'] = { "\x26", "\xf0\x26" }, - ['#'] = { "\x12\x26", "\xf0\x26\xf0\x12" }, - ['4'] = { "\x25", "\xf0\x25" }, - ['$'] = { "\x12\x25", "\xf0\x25\xf0\x12" }, - ['5'] = { "\x2e", "\xf0\x2e" }, - ['%'] = { "\x12\x2e", "\xf0\x2e\xf0\x12" }, - ['6'] = { "\x36", "\xf0\x36" }, - ['^'] = { "\x12\x36", "\xf0\x36\xf0\x12" }, - ['7'] = { "\x3d", "\xf0\x3d" }, - ['&'] = { "\x12\x3d", "\xf0\x3d\xf0\x12" }, - ['8'] = { "\x3e", "\xf0\x3e" }, - ['*'] = { "\x12\x3e", "\xf0\x3e\xf0\x12" }, - ['9'] = { "\x46", "\xf0\x46" }, - ['('] = { "\x12\x46", "\xf0\x46\xf0\x12" }, - ['0'] = { "\x45", "\xf0\x45" }, - [')'] = { "\x12\x45", "\xf0\x45\xf0\x12" }, - ['-'] = { "\x4e", "\xf0\x4e" }, - ['_'] = { "\x12\x4e", "\xf0\x4e\xf0\x12" }, - ['='] = { "\x55", "\xf0\x55" }, - ['+'] = { "\x12\x55", "\xf0\x55\xf0\x12" }, - ['['] = { "\x54", "\xf0\x54" }, - ['{'] = { "\x12\x54", "\xf0\x54\xf0\x12" }, - [']'] = { "\x5b", "\xf0\x5b" }, - ['}'] = { "\x12\x5b", "\xf0\x5b\xf0\x12" }, - ['\\'] = { "\x5d", "\xf0\x5d" }, - ['|'] = { "\x12\x5d", "\xf0\x5d\xf0\x12" }, - [';'] = { "\x4c", "\xf0\x4c" }, - [':'] = { "\x12\x4c", "\xf0\x4c\xf0\x12" }, - ['\''] = { "\x52", "\xf0\x52" }, - ['"'] = { "\x12\x52", "\xf0\x52\xf0\x12" }, - [','] = { "\x41", "\xf0\x41" }, - ['<'] = { "\x12\x41", "\xf0\x41\xf0\x12" }, - ['.'] = { "\x49", "\xf0\x49" }, - ['>'] = { "\x12\x49", "\xf0\x49\xf0\x12" }, - ['/'] = { "\x4a", "\xf0\x4a" }, - [' '] = { "\x29", "\xf0\x29" }, - ['?'] = { "\x12\x4a", "\xf0\x4a\xf0\x12" } +/* To save space, we don't store the first 32 characters in scancodes2, since + * they're control characters. Thus, the offset is the amount to subtract + * from a character before looking it up. */ + +#define SC2_OFFSET 32 +#define SC2(x) ((x)-SC2_OFFSET) + +/* Keys are stored in somewhat compressed form, to save on data space. + * + * The "press" and "release" strings contain scancodes to be injected + * into the buffer. However, they are modified beforehand, since two + * bytes isn't enough for all keys. + * + * Rules: + * - If press starts with \x12 (shift down), then \xf0\x12 (shift up) + * will be appended to release. + * - If press starts with \xe0, then \xe0 is *pre*pended to release. + */ + +struct keyspec { + char press[2]; + char release[2]; }; +static const struct keyspec scancodes2[] = { + [SC2('a')] = { "\x1c", "\xf0\x1c" }, + [SC2('b')] = { "\x32", "\xf0\x32" }, + [SC2('c')] = { "\x21", "\xf0\x21" }, + [SC2('d')] = { "\x23", "\xf0\x23" }, + [SC2('e')] = { "\x24", "\xf0\x24" }, + [SC2('f')] = { "\x2b", "\xf0\x2b" }, + [SC2('g')] = { "\x34", "\xf0\x34" }, + [SC2('h')] = { "\x33", "\xf0\x33" }, + [SC2('i')] = { "\x43", "\xf0\x43" }, + [SC2('j')] = { "\x3b", "\xf0\x3b" }, + [SC2('k')] = { "\x42", "\xf0\x42" }, + [SC2('l')] = { "\x4b", "\xf0\x4b" }, + [SC2('m')] = { "\x3a", "\xf0\x3a" }, + [SC2('n')] = { "\x31", "\xf0\x31" }, + [SC2('o')] = { "\x44", "\xf0\x44" }, + [SC2('p')] = { "\x4d", "\xf0\x4d" }, + [SC2('q')] = { "\x15", "\xf0\x15" }, + [SC2('r')] = { "\x2d", "\xf0\x2d" }, + [SC2('s')] = { "\x1b", "\xf0\x1b" }, + [SC2('t')] = { "\x2c", "\xf0\x2c" }, + [SC2('u')] = { "\x3c", "\xf0\x3c" }, + [SC2('v')] = { "\x2a", "\xf0\x2a" }, + [SC2('w')] = { "\x1d", "\xf0\x1d" }, + [SC2('x')] = { "\x22", "\xf0\x22" }, + [SC2('y')] = { "\x35", "\xf0\x35" }, + [SC2('z')] = { "\x1a", "\xf0\x1a" }, + [SC2('A')] = { "\x12\x1c", "\xf0\x1c" }, + [SC2('B')] = { "\x12\x32", "\xf0\x32" }, + [SC2('C')] = { "\x12\x21", "\xf0\x21" }, + [SC2('D')] = { "\x12\x23", "\xf0\x23" }, + [SC2('E')] = { "\x12\x24", "\xf0\x24" }, + [SC2('F')] = { "\x12\x2b", "\xf0\x2b" }, + [SC2('G')] = { "\x12\x34", "\xf0\x34" }, + [SC2('H')] = { "\x12\x33", "\xf0\x33" }, + [SC2('I')] = { "\x12\x43", "\xf0\x43" }, + [SC2('J')] = { "\x12\x3b", "\xf0\x3b" }, + [SC2('K')] = { "\x12\x42", "\xf0\x42" }, + [SC2('L')] = { "\x12\x4b", "\xf0\x4b" }, + [SC2('M')] = { "\x12\x3a", "\xf0\x3a" }, + [SC2('N')] = { "\x12\x31", "\xf0\x31" }, + [SC2('O')] = { "\x12\x44", "\xf0\x44" }, + [SC2('P')] = { "\x12\x4d", "\xf0\x4d" }, + [SC2('Q')] = { "\x12\x15", "\xf0\x15" }, + [SC2('R')] = { "\x12\x2d", "\xf0\x2d" }, + [SC2('S')] = { "\x12\x1b", "\xf0\x1b" }, + [SC2('T')] = { "\x12\x2c", "\xf0\x2c" }, + [SC2('U')] = { "\x12\x3c", "\xf0\x3c" }, + [SC2('V')] = { "\x12\x2a", "\xf0\x2a" }, + [SC2('W')] = { "\x12\x1d", "\xf0\x1d" }, + [SC2('X')] = { "\x12\x22", "\xf0\x22" }, + [SC2('Y')] = { "\x12\x35", "\xf0\x35" }, + [SC2('Z')] = { "\x12\x1a", "\xf0\x1a" }, + [SC2('`')] = { "\x0e", "\xf0\x0e" }, + [SC2('~')] = { "\x12\x0e", "\xf0\x0e" }, + [SC2('1')] = { "\x16", "\xf0\x16" }, + [SC2('!')] = { "\x12\x16", "\xf0\x16" }, + [SC2('2')] = { "\x1e", "\xf0\x1e" }, + [SC2('@')] = { "\x12\x1e", "\xf0\x1e" }, + [SC2('3')] = { "\x26", "\xf0\x26" }, + [SC2('#')] = { "\x12\x26", "\xf0\x26" }, + [SC2('4')] = { "\x25", "\xf0\x25" }, + [SC2('$')] = { "\x12\x25", "\xf0\x25" }, + [SC2('5')] = { "\x2e", "\xf0\x2e" }, + [SC2('%')] = { "\x12\x2e", "\xf0\x2e" }, + [SC2('6')] = { "\x36", "\xf0\x36" }, + [SC2('^')] = { "\x12\x36", "\xf0\x36" }, + [SC2('7')] = { "\x3d", "\xf0\x3d" }, + [SC2('&')] = { "\x12\x3d", "\xf0\x3d" }, + [SC2('8')] = { "\x3e", "\xf0\x3e" }, + [SC2('*')] = { "\x12\x3e", "\xf0\x3e" }, + [SC2('9')] = { "\x46", "\xf0\x46" }, + [SC2('(')] = { "\x12\x46", "\xf0\x46" }, + [SC2('0')] = { "\x45", "\xf0\x45" }, + [SC2(')')] = { "\x12\x45", "\xf0\x45" }, + [SC2('-')] = { "\x4e", "\xf0\x4e" }, + [SC2('_')] = { "\x12\x4e", "\xf0\x4e" }, + [SC2('=')] = { "\x55", "\xf0\x55" }, + [SC2('+')] = { "\x12\x55", "\xf0\x55" }, + [SC2('[')] = { "\x54", "\xf0\x54" }, + [SC2('{')] = { "\x12\x54", "\xf0\x54" }, + [SC2(']')] = { "\x5b", "\xf0\x5b" }, + [SC2('}')] = { "\x12\x5b", "\xf0\x5b" }, + [SC2('\\')] = { "\x5d", "\xf0\x5d" }, + [SC2('|')] = { "\x12\x5d", "\xf0\x5d" }, + [SC2(';')] = { "\x4c", "\xf0\x4c" }, + [SC2(':')] = { "\x12\x4c", "\xf0\x4c" }, + [SC2('\'')] = { "\x52", "\xf0\x52" }, + [SC2('"')] = { "\x12\x52", "\xf0\x52" }, + [SC2(',')] = { "\x41", "\xf0\x41" }, + [SC2('<')] = { "\x12\x41", "\xf0\x41" }, + [SC2('.')] = { "\x49", "\xf0\x49" }, + [SC2('>')] = { "\x12\x49", "\xf0\x49" }, + [SC2('/')] = { "\x4a", "\xf0\x4a" }, + [SC2(' ')] = { "\x29", "\xf0\x29" }, + [SC2('?')] = { "\x12\x4a", "\xf0\x4a" } +}; -static const char scancodes2high[][2][8] = { - [0x08] = { "\x66", "\xf0\x66" }, - [0x09] = { "\x0d", "\xf0\x0d" }, - [0x0d] = { "\x5a", "\xf0\x5a" }, - [0x1b] = { "\x76", "\xf0\x76" }, - [0x63] = { "\xE0\x70", "\xE0\xF0\x70" }, - [0xff] = { "\xE0\x71", "\xE0\xF0\x71" }, - [0x50] = { "\xE0\x6C", "\xE0\xF0\x6C" }, - [0x57] = { "\xE0\x69", "\xE0\xF0\x69" }, - [0x55] = { "\xE0\x75", "\xE0\xF0\x75" }, - [0x56] = { "\xE0\x7A", "\xE0\xF0\x7A" }, - [0x51] = { "\xE0\x74", "\xE0\xF0\x74" }, - [0x52] = { "\xE0\x75", "\xE0\xF0\x75" }, - [0x53] = { "\xE0\x6B", "\xE0\xF0\x6B" }, - [0x54] = { "\xE0\x72", "\xE0\xF0\x72" }, - [0xe1] = { "\x12", "\xf0\x12" }, - [0xe2] = { "\x59", "\xf0\x59" }, - [0xe3] = { "\x14", "\xf0\x14" }, - [0xe4] = { "\xE0\x14", "\xE0\xF0\x14" }, - [0xe9] = { "\x11", "\xf0\x11" }, - [0xea] = { "\xE0\x11", "\xE0\xF0\x11" } +static const struct { + char index; + struct keyspec data; +} scancodes2high[] = { + { 0x08, { "\x66", "\xf0\x66" } }, + { 0x09, { "\x0d", "\xf0\x0d" } }, + { 0x0d, { "\x5a", "\xf0\x5a" } }, + { 0x1b, { "\x76", "\xf0\x76" } }, + { 0x63, { "\xe0\x70", "\xF0\x70" } }, + { 0xff, { "\xe0\x71", "\xF0\x71" } }, + { 0x50, { "\xe0\x6C", "\xF0\x6C" } }, + { 0x57, { "\xe0\x69", "\xF0\x69" } }, + { 0x55, { "\xe0\x75", "\xF0\x75" } }, + { 0x56, { "\xe0\x7A", "\xF0\x7A" } }, + { 0x51, { "\xe0\x74", "\xF0\x74" } }, + { 0x52, { "\xe0\x75", "\xF0\x75" } }, + { 0x53, { "\xe0\x6B", "\xF0\x6B" } }, + { 0x54, { "\xe0\x72", "\xF0\x72" } }, + { 0xe1, { "\x12", "" } }, + { 0xe2, { "\x59", "\xf0\x59" } }, + { 0xe3, { "\x14", "\xf0\x14" } }, + { 0xe4, { "\xe0\x14", "\xF0\x14" } }, + { 0xe9, { "\x11", "\xf0\x11" } }, + { 0xea, { "\xe0\x11", "\xF0\x11" } }, + { 0x00, { "", "" } } }; const unsigned char convert_table[] = { @@ -180,6 +207,11 @@ unsigned char sc_convert_1(unsigned char in) void kbd_inject_scancode (unsigned char sc) { + if (kbd_mode == 1) { + sc = sc_convert_1(sc); + if (!sc) return; + } + outputf("Buffering %02x", sc); kbd_inj_buffer[kbd_inj_end] = sc; kbd_inj_end += 1; @@ -188,30 +220,45 @@ void kbd_inject_scancode (unsigned char sc) void kbd_inject_keysym(uint32_t k, int downflag) { - const char * c; + const struct keyspec * ks = 0; + const char * c = 0; + int i; - if ((k & 0xFFFFFF00) == 0) + if ((k & 0xFFFFFF00) == 0 && (k & 0xFF) > SC2_OFFSET) { - c = scancodes2[k & 0xFF][downflag ? 0 : 1]; + ks = &scancodes2[SC2(k & 0xFF)]; } else if ((k & 0xFFFFFF00) == 0xFF00) { - c = scancodes2high[k & 0xFF][downflag ? 0 : 1]; + for (i = 0; scancodes2high[i].index; i++) { + if ((k & 0xff) == scancodes2high[i].index) { + ks = &scancodes2high[i].data; + break; + } + } } else { return; } - if (!c) return; + if (!ks) return; - if (kbd_mode == 1) { - while (*c) { - char cconv = sc_convert_1(*c); - if (cconv) kbd_inject_scancode(cconv); - c++; - } - } else { - while (*c) { - kbd_inject_scancode(*c); - c++; - } + if (downflag) + c = ks->press; + else + c = ks->release; + + i = 0; + + if (ks->press[0] == '\xe0' && !downflag) + kbd_inject_scancode('\xe0'); + + while (*c && i < 2) { + kbd_inject_scancode(*c); + c++; + i++; + } + + if (ks->press[0] == '\x12' && !downflag) { + kbd_inject_scancode('\xf0'); + kbd_inject_scancode('\x12'); } } diff --git a/netwatch/pagingstub-asm.s b/netwatch/pagingstub-asm.S similarity index 100% rename from netwatch/pagingstub-asm.s rename to netwatch/pagingstub-asm.S diff --git a/netwatch/pagingstub.c b/netwatch/pagingstub.c index 5ba1857..4041bdc 100644 --- a/netwatch/pagingstub.c +++ b/netwatch/pagingstub.c @@ -54,6 +54,7 @@ void ps_switch_stack (void (*call)(), int stack); #define CR0_PG 0x80000000 #define CR4_PSE 0x00000010 +#define CR4_OSFXSR 0x00000200 #define MAP_FLAGS (PTE_PRESENT | PTE_READ_WRITE) @@ -183,54 +184,66 @@ static void pt_setup(int tseg_start, int tseg_size) { void init_and_run(void) { + DBG(0x0A); + if (!initialized) { + DBG(0x0B); smi_init(); initialized = 1; } + DBG(0x0C); smi_entry(); + + DBG(0xCC); } void c_entry(void) { paging_enb = 0; - outb(0x80, 0x01); + DBG(0x01); + if (!initialized) pt_setup(0x1FF80000, 0x80000); - outb(0x80, 0x02); - + + DBG(0x02); + /* Enable paging. */ set_cr3((unsigned long)pd); - set_cr4(get_cr4() | CR4_PSE); /* ITT, we 4MByte page. */ + set_cr4(get_cr4() | CR4_PSE | CR4_OSFXSR); /* ITT, we 4MByte page. */ set_cr0(get_cr0() | CR0_PG); - outb(0x80, 0x03); + + DBG(0x03); paging_enb = 1; /* If this is the first goround, copy in data. */ if (!initialized) { unsigned char *p; - - outb(0x80, 0x04); + + DBG(0x04); + for (p = (void *)0x200000; (void *)p < (void *)&_bss; p++) *p = *(p + 0x100000); for (p = (void *)&_bss; (void *)p < (void *)&_bssend; p++) *p = 0; - outb(0x80, 0x05); + + DBG(0x05); /* Only now is it safe to call other functions. */ serial_init(); + DBG(0x06); dolog("Evacuation to TSEG complete."); + DBG(0x07); } - - outb(0x80, 0x06); + DBG(0x08); traps_install(); - outb(0x80, 0x07); + DBG(0x09); + ps_switch_stack(init_and_run, 0xa2000); - ps_switch_stack(init_and_run, 0x270000); - outb(0x80, 0xFA); + DBG(0xFA); } diff --git a/netwatch/traps.c b/netwatch/traps.c index bf5ca80..25a404c 100644 --- a/netwatch/traps.c +++ b/netwatch/traps.c @@ -14,15 +14,31 @@ #include "traps.h" -#define CS_SEGSEL 0x8 +#define CS_SEGSEL 0x10 + +asm ( + "fault_wrapper_common:\n" + "push %eax\n" + "mov %cr2, %eax\n" + "push %eax\n" + "push %esp\n" + "call die\n" +); + +#define FAULT_WRAPPER(func_name, code) asm ( \ + ".global " #func_name "_wrapper\n" \ + #func_name "_wrapper:\n" \ + "mov $" #code ", %eax\n" \ + "jmp fault_wrapper_common\n" \ +); void func_name##_wrapper(void); -#define FAULT_WRAPPER(func_name) asm ( \ +#define FAULT_WRAPPER1(func_name, code) asm ( \ ".global " #func_name "_wrapper\n" \ #func_name "_wrapper:\n" \ - "mov %cr2, %eax\n" \ + "mov $0, %eax\n" \ "push %eax\n" \ - "push %esp\n" \ - "call " #func_name "\n" \ + "mov $" #code ", %eax\n" \ + "jmp fault_wrapper_common\n" \ ); void func_name##_wrapper(void); #define WRAPPER_INSTALL(idt, idt4_value, func_name, int_number) { \ @@ -36,58 +52,83 @@ /* The 16 bits at offset 4 from the start of an interrupt gate are a * bitfield, according to the Intel spec: * 15 P - Segment Present - set to 1 - * 14-13 DPL - Descriptor privilege level - set to 11 for trap/int, 00 for IPI + * 14-13 DPL - Descriptor privilege level - set to 00, since we're always in ring 0 * 12-8 01111 for 32-bit trap gates, 01110 for 32-bit interrupt gates * 7-0 Set to 0 - * Trap: binary 11101111 0000000, hex EF00. - * Interrupt: binary 11101110 0000000, hex EE00. */ -#define TRAP 0xEF00 -#define INTERRUPT 0xEE00 +#define TRAP 0x8F00 typedef struct trap_t { int cr2; + int fault_code; int error_code; int eip; int cs; int eflags; - int esp; - int ss; } trap_t; +static const char const * trapcodes[20] = { + "Divide by Zero", + "Debug Trap", + "NMI", + "Breakpoint Trap", + "Overflow Trap", + "Bound Range Fault", + "Invalid Opcode", + "Device Not Available", + "Double Fault", + "Coprocessor Overrun", + "Invalid TSS", + "Segmnet Not Present", + "Stack Fault", + "GPF", + "Page Fault", + "Reserved Trap", + "x87 FPE Pending", + "Alignment Check", + "Machine Check", + "SIMD FPE Fault" +}; + void die(struct trap_t * trap) { - outputf("Error %08x %%eip %08x", trap->error_code, trap->eip); - outputf("%%esp %08x %%eflags %08x", trap->esp, trap->eflags); - while(1) asm("hlt"); -} -void fault_gp(struct trap_t * trap) { - outputf("GENERAL PROTECTION FAULT"); - die(trap); -} + DBG(0x40 + trap->fault_code); -void fault_page(struct trap_t * trap) { - outputf("PAGE FAULT: %08x", trap->cr2); - die(trap); -} -void fault_divide(struct trap_t * trap) { - outputf("DIVISION FAULT"); - die(trap); -} -void double_fault(struct trap_t * trap) { - outputf("DOUBLE FAULT"); - die(trap); + if (trap->fault_code < 20) { + outputf("---\n%s", trapcodes[trap->fault_code]); + } else { + outputf("---\nUNKNOWN FAULT"); + } + + outputf("Error %08x %%eip %08x", trap->error_code, trap->eip); + outputf("%%cr2 %08x %%eflags %08x", trap->cr2, trap->eflags); + while(1) asm("hlt"); } -FAULT_WRAPPER(fault_gp); -FAULT_WRAPPER(fault_page); -FAULT_WRAPPER(fault_divide); -FAULT_WRAPPER(double_fault); +FAULT_WRAPPER1(fault_divide, 0); +FAULT_WRAPPER1(fault_db, 1); +FAULT_WRAPPER1(fault_nmi, 2); +FAULT_WRAPPER1(fault_3, 3); +FAULT_WRAPPER1(fault_overflow, 4); +FAULT_WRAPPER1(fault_oob, 5); +FAULT_WRAPPER1(fault_opcode, 6); +FAULT_WRAPPER1(fault_enofpu, 7); +FAULT_WRAPPER(double_fault, 8); +FAULT_WRAPPER1(fault_fpu, 9); +FAULT_WRAPPER(fault_invalid_tss, 10); +FAULT_WRAPPER(fault_noseg, 11); +FAULT_WRAPPER(fault_stack, 12); +FAULT_WRAPPER(fault_gp, 13); +FAULT_WRAPPER(fault_page, 14); +FAULT_WRAPPER1(fault_fpe, 16); +FAULT_WRAPPER(fault_ac, 17); +FAULT_WRAPPER1(fault_machine, 18); +FAULT_WRAPPER1(fault_other, 19); /* pseudo_descriptor and x86_gate structs from 15-410 basis code. */ struct x86_gate { -unsigned int filler[2]; //64 bits; or 8 bytes. + unsigned int filler[2]; //64 bits, or 8 bytes. }; static struct x86_gate idt[64]; @@ -99,17 +140,38 @@ struct pseudo_descriptor { } __attribute__((packed)); void traps_install(void) { + DBG(0xCA); + int i; struct pseudo_descriptor pdesc; pdesc.limit = sizeof(idt) - 1; - pdesc.linear_base = v2p(&idt); + pdesc.linear_base = (int)&idt; //v2p(&idt); + + DBG(0xCB); + + for (i = 0; i < 32; i++) + WRAPPER_INSTALL(idt, TRAP, fault_other, i); WRAPPER_INSTALL(idt, TRAP, fault_divide, T_DIVIDE_ERROR); + WRAPPER_INSTALL(idt, TRAP, fault_db, T_DEBUG); + WRAPPER_INSTALL(idt, TRAP, fault_nmi, T_NMI); + WRAPPER_INSTALL(idt, TRAP, fault_3, T_INT3); + WRAPPER_INSTALL(idt, TRAP, fault_overflow, T_OVERFLOW); + WRAPPER_INSTALL(idt, TRAP, fault_oob, T_OUT_OF_BOUNDS); + WRAPPER_INSTALL(idt, TRAP, fault_opcode, T_INVALID_OPCODE); + WRAPPER_INSTALL(idt, TRAP, fault_enofpu, T_NO_FPU); + WRAPPER_INSTALL(idt, TRAP, double_fault, T_DOUBLE_FAULT); + WRAPPER_INSTALL(idt, TRAP, fault_fpu, T_FPU_FAULT); + WRAPPER_INSTALL(idt, TRAP, fault_invalid_tss, T_INVALID_TSS); + WRAPPER_INSTALL(idt, TRAP, fault_noseg, T_SEGMENT_NOT_PRESENT); + WRAPPER_INSTALL(idt, TRAP, fault_stack, T_STACK_FAULT); WRAPPER_INSTALL(idt, TRAP, fault_gp, T_GENERAL_PROTECTION); WRAPPER_INSTALL(idt, TRAP, fault_page, T_PAGE_FAULT); - WRAPPER_INSTALL(idt, TRAP, double_fault, T_DOUBLE_FAULT); + WRAPPER_INSTALL(idt, TRAP, fault_fpe, T_FLOATING_POINT_ERROR); + WRAPPER_INSTALL(idt, TRAP, fault_ac, T_ALIGNMENT_CHECK); + WRAPPER_INSTALL(idt, TRAP, fault_machine, T_MACHINE_CHECK); - outb(0x80, 0xCC); + DBG(0xCC); asm volatile("lidt %0" : : "m" (pdesc.limit)); - outb(0x80, 0xCD); + DBG(0xCE); } -- 2.39.2