--- /dev/null
+/* 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 <stdint.h>
+
+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 */
+
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);
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);
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
--- /dev/null
+/* 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 <stdint.h>
+
+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 */
+
--- /dev/null
+/* 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
/* 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)
{
*(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;
}
}
+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];
--- /dev/null
+/* 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 <cpuid.h>
+
+/* 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;
+}
#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
#include <paging.h>
#include <output.h>
+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),
"<html><head><title>Registers</title></head><body>"
"<p>At the time you requested this page, the system's registers were:</p>"
"<tt><pre>"
*(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, "<html><head><title>Backtrace</title></head><body><tt><pre>");
+ 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, "</pre></tt></body></html>");
+ len += snprintf(buf + len, LEFT, "<root>");
+
+ len += snprintf(buf + len, LEFT, "</pre></tt></body></html>");
file->data = buf;
- file->len = strlen(buf)-1;
+ file->len = len;
}
void handle_reboot(struct fs_file *file)
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[] = {
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;
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');
}
}
#define CR0_PG 0x80000000
#define CR4_PSE 0x00000010
+#define CR4_OSFXSR 0x00000200
#define MAP_FLAGS (PTE_PRESENT | PTE_READ_WRITE)
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);
}
#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) { \
/* 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];
} __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);
}