]> Joshua Wise's Git repositories - netwatch.git/commitdiff
Commit GDB patch from Jacob Potter.
authorJoshua Wise <joshua@escape.wv.cc.cmu.edu>
Wed, 2 Sep 2009 05:09:56 +0000 (01:09 -0400)
committerJoshua Wise <joshua@escape.wv.cc.cmu.edu>
Wed, 2 Sep 2009 05:09:56 +0000 (01:09 -0400)
21 files changed:
gdb/proto.c [new file with mode: 0644]
gdb/proto.h [new file with mode: 0644]
gdb/stub.c [new file with mode: 0644]
gdb/stub.h [new file with mode: 0644]
include/demap.h [new file with mode: 0644]
include/paging.h
include/reg-k8-msr.h [new file with mode: 0644]
include/reg-x86.h [new file with mode: 0644]
include/state.h
include/tables.h [new file with mode: 0644]
lib/demap.c [new file with mode: 0644]
lib/state.c
lwip/src/core/memp.c
net/http/fs.c
net/http/fsdata.c
net/http/httpd.c
net/net.c
net/rfb.c
net/rfb.h [deleted file]
netwatch/netwatch-large.lds [moved from netwatch/aseg.lds with 83% similarity]
netwatch/pagingstub-asm.S

diff --git a/gdb/proto.c b/gdb/proto.c
new file mode 100644 (file)
index 0000000..f532a16
--- /dev/null
@@ -0,0 +1,362 @@
+/* proto.c
+ * GDB remote serial protocol implementation
+ * 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.
+ */
+
+#define GDB_BUF_SIZE           1024
+
+#include <minilib.h>
+#include <demap.h>
+#include <tables.h>
+
+#include <lwip/tcp.h>
+
+#include "stub.h"
+
+#define GDB_PORT       2159
+
+enum fsm_result { NEEDMORE, OK, FAIL };
+
+static struct tcp_pcb * last_conn = NULL;
+
+void enhexificate (void * ibuf, char * obuf, int len) {
+       unsigned char * cibuf = ibuf;
+       while (len > 0) {
+               btohex(obuf, *(cibuf++));
+               obuf += 2;
+               len--;
+       }
+
+       *obuf = '\0';
+}
+
+void rle (char * buf) {
+       char * inptr = buf;
+       char * outptr = buf;
+       int lastchar = buf[0];
+       int repcount = 0;
+
+       do {
+               if (*inptr == lastchar && repcount < 97) {
+                       repcount += 1;
+               } else {
+                       *(outptr++) = lastchar;
+
+                       if (repcount == 2)
+                               *(outptr++) = lastchar;
+
+                       while (repcount == 6 || repcount == 7) {
+                               *(outptr++) = lastchar;
+                               repcount--;
+                       }
+
+                       if (repcount > 2) {
+                               *(outptr++) = '*';
+                               *(outptr++) = repcount + 29;
+                       }
+
+                       repcount = 1;
+                       lastchar = *inptr;
+               }
+
+               inptr++;
+       } while (lastchar);
+
+       *(outptr) = 0;
+}
+
+
+struct gdb_state {
+       char data[128];
+       int writepos;
+       int readpos;
+};
+
+
+static void close_conn(struct tcp_pcb *pcb, struct gdb_state *state) {
+       outputf("close_conn: bailing");
+       set_run_mode(RM_UNENCUMBERED);
+       last_conn = NULL;
+       tcp_arg(pcb, NULL);
+       tcp_sent(pcb, NULL);
+       tcp_recv(pcb, NULL);
+       mem_free(state);
+       tcp_close(pcb);
+       outputf("close_conn: done");
+}
+
+static int dehexbyte (char * p) {
+       int v0, v1;
+       v0 = dehexit (p[0]);
+       v1 = dehexit (p[1]);
+       if (v0 < 0 || v1 < 0) return -1;
+       return v0 << 4 | v1;
+}
+
+static void finish_and_send(struct tcp_pcb *pcb, char * output_buf, int datalength) {
+       char * p;
+       unsigned char checksum = 0;
+
+       output_buf[0] = '+';
+       output_buf[1] = '$';
+
+       for (p = output_buf + 2; p < output_buf + datalength + 2; p++)
+               checksum += *(unsigned char *)p;
+
+       output_buf[datalength + 2] = '#';
+
+       btohex(output_buf + datalength + 3, checksum);
+       tcp_write(pcb, output_buf, datalength + 5, TCP_WRITE_FLAG_COPY);
+}
+
+void send_stop_packet() {
+       if (!last_conn) return;
+       tcp_write(last_conn, "$T05thread:01;#07", 17, 0);
+}
+
+static enum fsm_result recv_fsm(struct tcp_pcb *pcb, struct gdb_state *state) {
+       char * endp;
+       char * p;
+       unsigned char checksum = 0;
+       int i;
+       uint64_t addr;
+       uint64_t length;
+
+       char output_buf[256];
+
+       /* Make sure we have at least 4 bytes (the size of the smallest legal
+          packet), and that the packet does in fact start with $. */
+
+       if ((state->data[0] == '+') || (state->data[0] == '-')) {
+               outputf("GDB: chomp");
+               state->readpos++;
+               return OK;
+       }
+
+       if (state->writepos < 4) return NEEDMORE;
+
+       if (state->data[0] != '$') return FAIL;
+
+       /* Find the end; make sure there's room for the checksum after. */
+
+       endp = memchr(state->data, '#', state->writepos);
+
+       if ((!endp) || (endp - state->data > state->writepos - 3))
+               return NEEDMORE;
+
+       /* Checksum. */
+
+       for (p = state->data + 1; p < endp; p++)
+               checksum += *(unsigned char *)p;
+
+       if (checksum != dehexbyte(endp + 1))
+       {
+               outputf("GDB: bad checksum: %d vs %d", checksum , dehexbyte(endp + 1));
+               return FAIL;
+       }
+
+       /* Null-terminate, for processing convenience */
+       *endp = '\0';
+
+       outputf("GDB: Got \'%s\'", state->data + 1);
+
+       /* OK, process the packet */
+
+       switch (state->data[1]) {
+       case '?':
+               tcp_write(pcb, "+$T05thread:01;#07", 18, 0);
+               break;
+       case 'g':
+               read_registers_32(output_buf + 2);
+               finish_and_send(pcb, output_buf, 128);
+               break;
+
+       case 'm':
+               /* Parse the address */
+               p = memchr(state->data, ',', endp - state->data);
+               if (!p) return FAIL;
+               *p = '\0';
+               addr = 0;
+               length = 0;
+
+               if (!dehexstring(&addr, state->data + 2, -1)) return FAIL;
+               if (!dehexstring(&length, p + 1, -1)) return FAIL;
+
+               outputf("GDB: read %d from %d", (uint32_t)length, (uint32_t)addr);
+
+               if (length > 120) length = 120;
+
+               for (i = 0; i < length; i++) {
+                       p = demap(addr++);
+                       if (!p) break;
+                       btohex(output_buf + 2 + (2*i), *(char *)p);
+               }
+
+               finish_and_send(pcb, output_buf, 2*i);
+               break;
+
+       case 's':
+               /* Step. */
+               set_run_mode(RM_STEPPING);
+               tcp_write(pcb, "+", 1, 0);
+               break;
+               
+       default:
+               tcp_write(pcb, "+$#00", 5, 0);
+               break;
+       }
+
+       state->readpos += (endp - state->data) + 3;
+
+       return OK;
+}
+
+err_t
+gdb_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
+       struct gdb_state *state = arg;
+       uint16_t copylen;
+
+       if (err != ERR_OK) {
+               outputf("GDB: recv err %d", err);
+               /* FIXME do something better here? */
+               return ERR_OK;
+       }
+
+       if (p == NULL) {
+               outputf("GDB: Connection closed");
+               close_conn(pcb, state);
+               return ERR_OK;
+       }
+
+       if (p->tot_len > (GDB_BUF_SIZE - state->writepos)) {
+               /* Overflow! */
+               outputf("GDB: Overflow!");
+               close_conn(pcb, state);
+               return ERR_OK;
+       }
+
+       copylen = pbuf_copy_partial(p, state->data + state->writepos, p->tot_len, 0);
+
+       outputf("GDB: Processing %d, wp %d, cp %d", p->tot_len, state->writepos, copylen);
+
+       state->writepos += p->tot_len;
+
+       tcp_recved(pcb, p->tot_len);
+       pbuf_free(p);
+
+       while (1) {
+               switch (recv_fsm(pcb, state)) {
+               case NEEDMORE:
+                       outputf("GDB FSM: blocking");
+                       goto doneprocessing;
+
+               case OK:
+                       if (state->readpos == state->writepos) {
+                               state->readpos = 0;
+                               state->writepos = 0;
+                               goto doneprocessing;
+                       } else {
+                               memmove(state->data,
+                                       state->data + state->readpos,
+                                       state->writepos - state->readpos);
+                               state->writepos -= state->readpos;
+                               state->readpos = 0;
+                       }
+                       break;
+               case FAIL:
+                       /* Shit */
+                       outputf("GDB: Protocol error");
+                       close_conn(pcb, state);
+                       return ERR_OK;
+               }
+       }
+
+doneprocessing:
+       return ERR_OK;
+}
+
+static err_t gdb_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
+/*
+       struct gdb_state *state = arg;
+       send_fsm(pcb, state);
+*/
+       return ERR_OK;
+}
+
+static err_t gdb_poll(void *arg, struct tcp_pcb *pcb) {
+       /* Nothing? */
+       return ERR_OK;
+}
+
+
+static err_t gdb_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
+       struct gdb_state *state;
+
+       LWIP_UNUSED_ARG(arg);
+       LWIP_UNUSED_ARG(err);
+
+       outputf("GDB: accept");
+
+       last_conn = pcb;
+
+       set_run_mode(RM_STOPPED);
+
+       state = (struct gdb_state *)mem_malloc(sizeof(struct gdb_state));
+
+       if (!state)
+       {
+               outputf("gdb_accept: out of memory\n");
+               return ERR_MEM;
+       }
+
+       memset(state, 0, sizeof(struct gdb_state));
+
+       tcp_arg(pcb, state);
+       tcp_recv(pcb, gdb_recv);
+       tcp_sent(pcb, gdb_sent);
+       tcp_poll(pcb, gdb_poll, 1);
+/*
+       tcp_err(pcb, gdb_err);
+*/
+       return ERR_OK;
+}
+
+
+void gdb_init() {
+       struct tcp_pcb *pcb;
+       pcb = tcp_new();
+       tcp_bind(pcb, IP_ADDR_ANY, GDB_PORT);
+       pcb = tcp_listen(pcb);
+       tcp_accept(pcb, gdb_accept);
+} 
+
+PROTOCOL(gdb_init);
diff --git a/gdb/proto.h b/gdb/proto.h
new file mode 100644 (file)
index 0000000..7fea289
--- /dev/null
@@ -0,0 +1,41 @@
+/* gdb.h
+ * GDB server
+ * 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 _GDB_PROTO_H
+#define _GDB_PROTO_H
+
+void enhexificate (void * ibuf, char * obuf, int len);
+void gdb_init(void);
+
+#endif /* _GDB_PROTO_H */
diff --git a/gdb/stub.c b/gdb/stub.c
new file mode 100644 (file)
index 0000000..0c49756
--- /dev/null
@@ -0,0 +1,285 @@
+/* stub.c
+ * GDB stub system manipultion code.
+ * 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 <stdint.h>
+#include <msr.h>
+#include <output.h>
+#include <state.h>
+#include <demap.h>
+#include <paging.h>
+#include <reg-x86.h>
+#include "proto.h"
+#include "stub.h"
+
+void send_stop_packet();
+
+uint16_t saved_db_entry;
+uint64_t saved_db_entry_location;
+enum operating_mode step_start_mode;
+uint64_t saved_cs_base;
+uint64_t saved_eflags;
+uint64_t saved_cs_limit;
+uint64_t saved_cs_attrib;
+uint64_t saved_ss_base;
+uint64_t saved_ss_limit;
+uint64_t saved_ss_attrib;
+
+#define P64(x) (uint32_t)((x)>>32), (uint32_t)(x)
+
+static const enum state_reg_t regs32 [] = {
+       STATE_REG_EAX, STATE_REG_ECX, STATE_REG_EDX, STATE_REG_EBX,
+       STATE_REG_ESP, STATE_REG_EBP, STATE_REG_ESI, STATE_REG_EDI,
+       STATE_REG_EIP, STATE_REG_EFLAGS, STATE_REG_CS, STATE_REG_SS,
+       STATE_REG_DS, STATE_REG_ES, STATE_REG_FS, STATE_REG_GS
+};
+
+static enum run_mode run_mode;
+
+void set_run_mode(enum run_mode mode) {
+       run_mode = mode;
+}
+
+int gdb_post_smi_hook() {
+       uint64_t r, entry;
+       uint32_t * ptr;
+       uint16_t * entry_v;
+       enum operating_mode m = get_operating_mode();
+
+
+       switch (run_mode) {
+       case RM_STOPPED:
+               /* Until we have a better way of handling this - spin in
+                * a loop. */
+               return 1;
+
+       case RM_STEPPING:
+               /* First, set RFLAGS.TF */
+               r = state_get_reg(STATE_REG_EFLAGS);
+               saved_eflags = r;
+               r |= EFLAGS_TF;
+               /* We also don't want to deal with interrupts. */
+               r &= ~EFLAGS_IF;
+               state_set_reg(STATE_REG_EFLAGS, r);
+
+               /* Track down the handler for a debug exception */
+               r = state_get_reg(STATE_REG_IDT_LIMIT);
+               r = state_get_reg(STATE_REG_IDT_BASE);
+               if (m == LONG_64BIT || m == LONG_COMPAT) {
+                       /* 64-bit. Index up 16 bytes to get to the
+                        * debug trap descriptor. */
+                       ptr = demap(r + 16);
+                       entry = (*ptr) & 0xFFFF;
+                       ptr = demap(r + 20);
+                       entry |= (*ptr) & 0xFFFF0000;
+                       ptr = demap(r + 24);
+                       entry |= (uint64_t)(*ptr) << 32;
+               } else {
+                       /* Assume 32-bit for now. */
+                       ptr = demap(r + 8);
+                       entry = (*ptr) & 0xFFFF;
+                       ptr = demap(r + 12);
+                       entry |= (*ptr) & 0xFFFF0000;
+               }
+
+               outputf("entry is at %08x %08x", (uint32_t)(entry>>32), (uint32_t)entry);
+               /* MAGIC_BREAK */
+               saved_db_entry_location = demap_phys(entry);
+               entry_v = p2v(saved_db_entry_location);
+               outputf("entry_v mapped to %08x", entry_v);
+               if (!entry_v)  {
+                       run_mode = RM_UNENCUMBERED; break;
+               }
+               saved_db_entry = *entry_v;
+               *entry_v = 0xB2E6;              /* "out %al, $0xb2" */
+
+               step_start_mode = m;
+
+               /* Turn off the safety */
+               WRMSR(0xc0010054, 0x8002);
+               outputf("Have fun!");
+
+               saved_cs_base = state_get_reg(STATE_REG_CS_BASE);
+               saved_cs_limit = state_get_reg(STATE_REG_CS_LIMIT);
+               saved_cs_attrib = state_get_reg(STATE_REG_CS_ATTRIB);
+               saved_ss_base = state_get_reg(STATE_REG_SS_BASE);
+               saved_ss_limit = state_get_reg(STATE_REG_SS_LIMIT);
+               saved_ss_attrib = state_get_reg(STATE_REG_SS_ATTRIB);
+
+               break;
+
+       case RM_CONTINUING:
+               /* There may be breakpoints. Fall through to
+                * "unencumbered" for now. */   
+
+       case RM_UNENCUMBERED:
+               /* Nada. */
+               return 0;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+#define READ_QWORD(pa) ({ uint64_t * p = demap(pa); if (!p) goto fail; outputf("pq %08x %08x", (uint32_t)((*p)>>32), (uint32_t)(*p)); *p; })
+#define READ_WORD(pa)  ({ uint16_t * p = demap(pa); if (!p) goto fail; outputf("p %04x", (*p)); *p; })
+
+static void gdb_unmangle_stepped_system() {
+       uint64_t r;
+       uint16_t * entry_v;
+
+       /* The unexpected breakpoint has caused an interrupt stack to be
+        * built, which we must get rid of. */
+
+       if (step_start_mode == LONG_64BIT) {
+               r = state_get_reg(STATE_REG_RSP);
+               state_set_reg(STATE_REG_RIP, READ_QWORD(r));
+               state_set_reg(STATE_REG_CS, READ_WORD(r+8));
+               state_set_reg(STATE_REG_RFLAGS, READ_QWORD(r+16));
+               state_set_reg(STATE_REG_RSP, READ_QWORD(r+24));
+               state_set_reg(STATE_REG_SS, READ_WORD(r+32));
+       } else if (step_start_mode == LONG_COMPAT) {
+               r = state_get_reg(STATE_REG_RSP);
+               state_set_reg(STATE_REG_RIP, READ_QWORD(r) & 0xFFFFFFFF);
+               state_set_reg(STATE_REG_CS, READ_WORD(r+8));
+               state_set_reg(STATE_REG_RFLAGS, READ_QWORD(r+16) & 0xFFFFFFFF);
+               state_set_reg(STATE_REG_RSP, READ_QWORD(r+24) & 0xFFFFFFFF);
+               state_set_reg(STATE_REG_SS, READ_WORD(r+32));
+       }
+               entry_v = p2v(saved_db_entry_location);
+               *entry_v = saved_db_entry;
+
+       state_set_reg(STATE_REG_CS_BASE, saved_cs_base);
+       state_set_reg(STATE_REG_CS_LIMIT, saved_cs_limit);
+       state_set_reg(STATE_REG_CS_ATTRIB, saved_cs_attrib);
+       state_set_reg(STATE_REG_SS_BASE, saved_ss_base);
+       state_set_reg(STATE_REG_SS_LIMIT, saved_ss_limit);
+       state_set_reg(STATE_REG_SS_ATTRIB, saved_ss_attrib);
+       state_set_reg(STATE_REG_EFLAGS, saved_eflags);
+
+       /* Put us back in "stopped" mode, until the GDB server gets around
+        * to handling the step.
+        */
+
+       reset_operating_mode_memo();
+       run_mode = RM_STOPPED;
+
+       send_stop_packet();
+       return;
+
+fail:
+       outputf("ERROR: Failed to restore state!");
+       while(1);
+}
+
+void gdb_pre_smi_hook() {
+       enum operating_mode m = get_operating_mode();
+       uint64_t ip, break_phys;
+
+       if (run_mode == RM_STEPPING) {
+               /* Oh hey, we are probably stopped on a breakpoint.
+                * Let's check. */
+               ip = state_get_reg(
+                       (m == LONG_64BIT)
+                       ? STATE_REG_RIP : STATE_REG_EIP
+               );
+               break_phys = demap_phys(ip);
+
+               if ((break_phys != saved_db_entry_location)
+                && (break_phys != saved_db_entry_location + 2)) {
+                       /* Some other event caused us to enter SMM. We'll deal
+                        * with the single step when we *actually* get to
+                        * the breakpoint. */
+                       return;
+               }
+
+               /* Great. Now we have caused a debug exception.
+                *
+                * "Your problems just got worse. Think: what have you done?"
+                *
+                * We don't want the running system to know that anything
+                * ever happened, so we manually unwind the stack and undo
+                * everything that happened.
+                */
+
+               gdb_unmangle_stepped_system();
+       }
+}
+
+
+void read_registers_32 (char * buf) {
+       int i, r = 0, offset = 0, size = 0;
+
+       /* Dump registers to buffer. */
+
+       for (i = 0; i < (sizeof(regs32) / sizeof(enum state_reg_t)); i++) {
+               enum state_reg_t reg = regs32[i];
+               r = state_get_reg(reg);
+               //size = state_reg_size(reg);
+               size = 4;
+               enhexificate(&r, buf + offset, size);
+               offset += (size * 2);
+       }
+
+       /* XXX: The rest of the buffer "should be" filled with floating point
+          stuff. We'll worry about that later. */
+}
+
+void write_registers_32 (char * buf) {
+       //int size = 0, i;
+
+
+       uint32_t *ubuf = (uint32_t *)buf;
+       
+       state_set_reg(STATE_REG_EAX, ubuf[0]);
+       state_set_reg(STATE_REG_ECX, ubuf[1]);
+       state_set_reg(STATE_REG_EDX, ubuf[2]);
+       state_set_reg(STATE_REG_EBX, ubuf[3]);
+       state_set_reg(STATE_REG_ESP, ubuf[4]);
+       state_set_reg(STATE_REG_EBP, ubuf[5]);
+       state_set_reg(STATE_REG_ESI, ubuf[6]);
+       state_set_reg(STATE_REG_EDI, ubuf[7]);
+
+       state_set_reg(STATE_REG_EIP, ubuf[8]);
+       state_set_reg(STATE_REG_EFLAGS, ubuf[9]);
+       state_set_reg(STATE_REG_CS, ubuf[10]);
+       state_set_reg(STATE_REG_SS, ubuf[11]);
+       state_set_reg(STATE_REG_DS, ubuf[12]);
+       state_set_reg(STATE_REG_ES, ubuf[13]);
+       state_set_reg(STATE_REG_FS, ubuf[14]);
+       state_set_reg(STATE_REG_GS, ubuf[15]);
+
+       /* XXX: Again, need to deal with floating point. */
+}
diff --git a/gdb/stub.h b/gdb/stub.h
new file mode 100644 (file)
index 0000000..eb697d9
--- /dev/null
@@ -0,0 +1,50 @@
+/* stub.h
+ * Headers for GDB stub system manipulation.
+ * 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 __STUB_H
+#define __STUB_H
+
+void read_registers_32 (char * buf);
+void write_registers_32 (char * buf);
+
+enum run_mode {
+       RM_UNENCUMBERED,
+       RM_STOPPED,
+       RM_STEPPING,
+       RM_CONTINUING
+};
+
+void set_run_mode(enum run_mode mode);
+
+#endif
diff --git a/include/demap.h b/include/demap.h
new file mode 100644 (file)
index 0000000..e727bd1
--- /dev/null
@@ -0,0 +1,56 @@
+/* demap.h
+ * Definitions for system page table de-mapping
+ * 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 __DEMAP_H
+#define __DEMAP_H
+
+#include <stdint.h>
+
+enum operating_mode {
+        UNKNOWN = 0,
+        LONG_64BIT,
+        LONG_COMPAT,
+        PROTECTED_PAGING,
+        PROTECTED_NOPAGING,
+        REAL,
+        V8086
+};
+
+enum operating_mode get_operating_mode(void);
+void reset_operating_mode_memo(void);
+
+uint64_t demap_phys (uint64_t vaddr);
+void * demap (uint64_t vaddr);
+
+#endif
index 4a27bb94e57a55be71026c691a679f67b2e91a74..86f5676ab2818202fbee252f12f755b42c481ddc 100644 (file)
 #ifndef __PAGING_H
 #define __PAGING_H
 
 #ifndef __PAGING_H
 #define __PAGING_H
 
+#include <stdint.h>
+
 extern unsigned long v2p(void *virt);
 extern void *p2v(unsigned long phys);
 extern unsigned long v2p(void *virt);
 extern void *p2v(unsigned long phys);
+extern void *p2v64(uint64_t phys);
 extern int addmap(unsigned long vaddr, unsigned long paddr);
 extern int addmap_4m(unsigned long vaddr, unsigned long paddr);
 extern int addmap(unsigned long vaddr, unsigned long paddr);
 extern int addmap_4m(unsigned long vaddr, unsigned long paddr);
-extern void *demap(unsigned long _pd, unsigned long vaddr);
 
 #endif
 
 #endif
diff --git a/include/reg-k8-msr.h b/include/reg-k8-msr.h
new file mode 100644 (file)
index 0000000..25cad75
--- /dev/null
@@ -0,0 +1,50 @@
+/* reg-k8-msr.h
+ * K8 / AMD64 architectural MSR macros.
+ * 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 REG_K8_MSR_H
+#define REG_K8_MSR_H
+
+#define SMM_ADDR_MSR   0xC0010112
+#define SMM_MASK_MSR   0xC0010113
+
+#define HWCR_MSR       0xC0010015
+
+#define HWCR_MSR_SMMLOCK       (1 << 0)
+
+#define EFER_MSR       0xC0000080
+
+#define EFER_MSR_LMA           (1 << 10)
+
+
+#endif
diff --git a/include/reg-x86.h b/include/reg-x86.h
new file mode 100644 (file)
index 0000000..94dd53b
--- /dev/null
@@ -0,0 +1,84 @@
+/* reg-x86.h
+ * X86 standard registers
+ * 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 __REG_X86_H
+#define __REG_X86_H
+
+#define CR0_PE         (1<<0)
+#define CR0_MP         (1<<1)
+#define CR0_EM         (1<<2)
+#define CR0_TS         (1<<3)
+#define CR0_ET         (1<<4)
+#define CR0_NE         (1<<5)
+#define CR0_WP         (1<<16)
+#define CR0_AM         (1<<18)
+#define CR0_NW         (1<<29)
+#define CR0_CD         (1<<30)
+#define CR0_PG         (1<<31)
+
+#define CR3_PWT                (1<<3)
+#define CR3_PCD                (1<<4)
+
+#define CR4_VME                (1<<0)
+#define CR4_PVI                (1<<1)
+#define CR4_TSD                (1<<2)
+#define CR4_DE         (1<<3)
+#define CR4_PSE                (1<<4)
+#define CR4_PAE                (1<<5)
+#define CR4_MCE                (1<<6)
+#define CR4_PGE                (1<<7)
+#define CR4_PCE                (1<<8)
+#define CR4_OSFXSR     (1<<9)
+#define CR4_OSXMMEXCPT (1<<10)
+
+#define EFLAGS_CF      (1<<0)
+#define EFLAGS_PF      (1<<2)
+#define EFLAGS_AF      (1<<4)
+#define EFLAGS_ZF      (1<<6)
+#define EFLAGS_SF      (1<<7)
+#define EFLAGS_TF      (1<<8)
+#define EFLAGS_IF      (1<<9)
+#define EFLAGS_DF      (1<<10)
+#define EFLAGS_OF      (1<<11)
+#define EFLAGS_IOPL    (3<<12)
+#define EFLAGS_NT      (1<<14)
+#define EFLAGS_RF      (1<<16)
+#define EFLAGS_VM      (1<<17)
+#define EFLAGS_AC      (1<<18)
+#define EFLAGS_VIF     (1<<19)
+#define EFLAGS_VIP     (1<<20)
+#define EFLAGS_ID      (1<<21)
+
+#endif /* __REG_X86_H */
+
index fd19612cdb8222283e2a5a8839699ab45d78fc6b..9bc4b9060c3719f7bc8d99c7b89ccd18f5db20fa 100644 (file)
@@ -59,11 +59,31 @@ enum state_reg_t {
        STATE_REG_CR3,
 
        STATE_REG_CS,
        STATE_REG_CR3,
 
        STATE_REG_CS,
+       STATE_REG_CS_ATTRIB,
+       STATE_REG_CS_BASE,
+       STATE_REG_CS_LIMIT,
        STATE_REG_SS,
        STATE_REG_SS,
+       STATE_REG_SS_ATTRIB,
+       STATE_REG_SS_BASE,
+       STATE_REG_SS_LIMIT,
        STATE_REG_DS,
        STATE_REG_DS,
+       STATE_REG_DS_ATTRIB,
+       STATE_REG_DS_BASE,
+       STATE_REG_DS_LIMIT,
        STATE_REG_ES,
        STATE_REG_ES,
+       STATE_REG_ES_ATTRIB,
+       STATE_REG_ES_BASE,
+       STATE_REG_ES_LIMIT,
        STATE_REG_FS,
        STATE_REG_FS,
+       STATE_REG_FS_ATTRIB,
+       STATE_REG_FS_BASE,
+       STATE_REG_FS_LIMIT,
        STATE_REG_GS,
        STATE_REG_GS,
+       STATE_REG_GS_ATTRIB,
+       STATE_REG_GS_BASE,
+       STATE_REG_GS_LIMIT,
+       STATE_REG_IDT_BASE,
+       STATE_REG_IDT_LIMIT,
 
        /* 64-bit registers */
        STATE_REG_RAX,
 
        /* 64-bit registers */
        STATE_REG_RAX,
@@ -82,18 +102,28 @@ enum state_reg_t {
        STATE_REG_R13,
        STATE_REG_R14,
        STATE_REG_R15,
        STATE_REG_R13,
        STATE_REG_R14,
        STATE_REG_R15,
-       STATE_REG_RIP
+       STATE_REG_RIP,
+       STATE_REG_RFLAGS,
+
+       STATE_REG_EFER,
+
+       NUM_REGISTERS
 };
 
 };
 
+
 enum smm_type {
         SMM_TYPE_UNKNOWN,
         SMM_TYPE_32,
         SMM_TYPE_64
 };
 
 enum smm_type {
         SMM_TYPE_UNKNOWN,
         SMM_TYPE_32,
         SMM_TYPE_64
 };
 
+enum smm_type state_get_type(void);
+
 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);
 
 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);
 
+int state_dump_reg(char * dest, int max, enum state_reg_t reg);
+
 #endif /* __STATE_H */
 
 #endif /* __STATE_H */
 
diff --git a/include/tables.h b/include/tables.h
new file mode 100644 (file)
index 0000000..13ee0df
--- /dev/null
@@ -0,0 +1,71 @@
+/* tables.h
+ * Linker table helper macros.
+ * 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 __TABLES_H
+#define __TABLES_H
+
+/* Linker tables are a beautiful, evil piece of magic.
+ *
+ * The idea is this;
+ * - For each table, define start and end pointers as zero-length arrays.
+ * - Define however many data values as constants of the appropriate type
+ * - Put each in its own section. For example, 'start' is in section
+ *   .table.foo; the data elemnts are in section .table.foo.1 (or other values
+ *   for explicit ordering); and 'end' is in .table.foo.END.
+ * - Merge the sections together with the following linker script entry:
+ *   *(SORT(.table.*))
+ *
+ * This has the effect that the start symbol points to the first value in the
+ * table, and the end symbol points to the last. The number of values is
+ * simply (table_foo_end - table_foo_start).
+ *
+ * And everything Just Works. Etherboot and the Linux kernel both use this
+ * for identifying linked-in modules; they have a somewhat more elaborate
+ * macro infastructure, but at the moment there are only two tables in
+ * NetWatch (network protocols and built-in drivers), so less is needed.
+ */
+
+#define PROTOCOL(x) void (* const x##_ptr)(void) \
+       __attribute__((section(".table.protocols.1"))) = x
+
+
+
+#define TABLE(typ, name) \
+       typ name##_table[0] __attribute__((section(".table." #name )));         \
+       typ name##_table_end[0] __attribute__((section(".table." #name ".END")));
+
+#define TABLE_LENGTH(name)     (name##_table_end - name##_table)
+
+#endif /* __TABLES_H */
+
diff --git a/lib/demap.c b/lib/demap.c
new file mode 100644 (file)
index 0000000..5eb303a
--- /dev/null
@@ -0,0 +1,202 @@
+/* demap.h
+ * Paging lookup 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 <msr.h>
+#include <reg-k8-msr.h>
+#include <reg-x86.h>
+#include <paging.h>
+#include <output.h>
+#include <demap.h>
+
+#define REG_CS_ATTRIB_L                (1<<9)
+#define PTE_PRESENT            (1<<0)
+#define PTE_LARGE              (1<<7)
+
+#define PTE_FOR(x)      (((unsigned int)(x) >> 12) & 0x3FF)
+#define PDE_FOR(x)      ((unsigned int)(x) >> 22)
+#define ADDR_12_MASK(x) ((unsigned int)(x) & ~((1 << 12) - 1))
+
+/* Keep a memoized copy of the operating mode the CPU was in when we
+ * entered SMM, so we don't have to look it up every time.
+ */
+
+static enum operating_mode mode;
+
+void reset_operating_mode_memo() {
+       mode = UNKNOWN;
+}
+
+/* Check the saved state map to determine what mode we were in. */
+
+void probe_operating_mode() {
+       unsigned long cr0;
+
+       if (state_get_type() == SMM_TYPE_64) {
+               /* This is a 64-bit processor, so we may be in 64-bit
+                * full or compatibility mode. Check if we are. */
+
+               uint64_t efer = state_get_reg(STATE_REG_EFER);
+
+               if (efer & EFER_MSR_LMA) {
+                       /* We are in long mode. Is this full 64-bit, or
+                        * comatibility mode? Check the "L" bit of the
+                        * saved CS descriptor to be sure. */
+
+                       if (state_get_reg(STATE_REG_CS_ATTRIB)
+                           & REG_CS_ATTRIB_L) {
+                               mode = LONG_64BIT;
+                       } else {
+                               mode = LONG_COMPAT;
+                       }
+
+                       return;
+               }
+               /* Otherwise, we are in legacy mode, so do the normal
+                * 32-bit probes. */
+       }
+
+       /* Either we are on a 32-bit processor, or we are on a 64-bit
+        * processor in legacy mode. */
+
+       if (state_get_reg(STATE_REG_EFLAGS) & EFLAGS_VM) {
+               mode = V8086;
+               return;
+       }
+
+       cr0 = state_get_reg(STATE_REG_CR0);
+
+       if (cr0 & CR0_PE)
+               if (cr0 & CR0_PG)
+                       mode = PROTECTED_PAGING;
+               else
+                       mode = PROTECTED_NOPAGING;
+       else
+               mode = REAL;
+}
+
+enum operating_mode get_operating_mode() {
+       if (mode == UNKNOWN)
+               probe_operating_mode();
+
+       return mode;
+}
+
+#define LONG_ADDR_MASK 0x000FFFFFFFFFF000
+#define PAGE_1G_MASK   0x000FFFFFC0000000
+#define PAGE_2M_MASK   0x000FFFFFFFE00000
+
+#define LONG_ADDR_SECTION(addr, offset)        ((((addr) >> (offset)) & 0x1FF) * 8)
+
+#define READ_PHYS_QWORD(pa)    ({ uint64_t * p = p2v(pa); if (!p) return 0; *p; })
+
+/* Given a virtual address from the current CPU context, determine what the
+ * actual corresponding physical address would be, then convert that back
+ * to a virtual address suitable for use within NetWatch.
+ *
+ * If the given address is not mapped in to RAM or is mapped to RAM which
+ * cannot be accessed, returns null.
+ *
+ * XXX: This currently handles both long and 32-bit modes, but only knows
+ * how to parse standard 4-kbyte pages. It assumes all segments span the full
+ * 32-bit address space. Thus, it will return correct results for most
+ * userspace environments in most sane OS kernels, but not necessarily kernel
+ * space (likely to be mapped with large pages) or anything that plays tricks
+ * with segmentation (like NaCl).
+ */
+
+uint64_t demap_phys (uint64_t vaddr) {
+
+       uint64_t pa = state_get_reg(STATE_REG_CR3) & LONG_ADDR_MASK;
+       uint64_t entry;
+
+       if (mode == UNKNOWN)
+               probe_operating_mode();
+
+outputf("demapping %08x %08x m %d", (uint32_t)(vaddr>>32), (uint32_t)vaddr, mode);
+       switch (mode) {
+       case LONG_64BIT:
+       case LONG_COMPAT: {
+               /* Get PML4 entry */
+               entry = READ_PHYS_QWORD(pa + LONG_ADDR_SECTION(vaddr, 39));
+               if (!(entry & PTE_PRESENT)) return 0;
+               pa = entry & LONG_ADDR_MASK;
+
+               /* Get PDP entry */
+               entry = READ_PHYS_QWORD(pa + LONG_ADDR_SECTION(vaddr, 30));
+               if (!(entry & PTE_PRESENT)) return 0;
+               pa = entry & LONG_ADDR_MASK;
+
+               if (entry & PTE_LARGE)
+                       return (entry & PAGE_1G_MASK) + (vaddr & 0x3FFFFFFF);
+
+               /* Get PDE */
+               entry = READ_PHYS_QWORD(pa + LONG_ADDR_SECTION(vaddr, 21));
+               if (!(entry & PTE_PRESENT)) return 0;
+               pa = entry & LONG_ADDR_MASK;
+
+               if (entry & PTE_LARGE)
+                       return (entry & PAGE_2M_MASK) + (vaddr & 0x1FFFFF);
+
+               /* Get PTE */
+               entry = READ_PHYS_QWORD(pa + LONG_ADDR_SECTION(vaddr, 12));
+               if (!(entry & PTE_PRESENT)) return 0;
+               pa = entry & LONG_ADDR_MASK;
+
+               return pa + (vaddr & 0xFFF);
+       }
+       case PROTECTED_NOPAGING:
+       case REAL:
+               return vaddr;
+
+       default: {
+               unsigned long pde = ((unsigned long *)p2v(pa))[PDE_FOR(vaddr)];
+               unsigned long pte;
+
+               if (!(pde & PTE_PRESENT)) return 0; 
+               pte = ((unsigned long *)p2v(ADDR_12_MASK(pde)))[PTE_FOR(vaddr)];
+               if (!(pte & PTE_PRESENT)) return 0;
+
+               return (pte & ~0xFFF) + (vaddr & 0xFFF);
+       }
+       }
+}
+
+void *demap(uint64_t vaddr) {
+       uint64_t paddr = demap_phys(vaddr);
+       outputf("demap: paddr 0x%08x %08x", (uint32_t)(paddr>>32), (uint32_t)paddr);
+       if (!paddr) return 0;
+       return p2v(paddr);
+}
+
index 368029b16bc9f4ed8bfa3609737c05841ab6efea..46a56e8ee7c35221a7d2a4464c90cf4ecab0285c 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "state.h"
 #include <cpuid.h>
 
 #include "state.h"
 #include <cpuid.h>
+#include <output.h>
+#include <minilib.h>
 
 /* Size flags. */
 #define SZ_BYTE                0x10000000
 
 /* Size flags. */
 #define SZ_BYTE                0x10000000
@@ -66,7 +68,8 @@ static const uint32_t offset_table_legacy[] = {
        [STATE_REG_DS]          = 0xffb4 | SZ_DWORD,
        [STATE_REG_ES]          = 0xffa8 | SZ_DWORD,
        [STATE_REG_FS]          = 0xffb8 | 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
+       [STATE_REG_GS]          = 0xffbc | SZ_DWORD,
+       [STATE_REG_IDT_BASE]    = 0xff94 | SZ_DWORD
 };
 
 #define MAX_REG_LEGACY (sizeof(offset_table_legacy)/sizeof(uint32_t))
 };
 
 #define MAX_REG_LEGACY (sizeof(offset_table_legacy)/sizeof(uint32_t))
@@ -87,15 +90,35 @@ static const uint32_t offset_table_amd64[] = {
        [STATE_REG_EBP]         = 0xffd0 | SZ_DWORD,
        [STATE_REG_EIP]         = 0xff78 | SZ_DWORD,
        [STATE_REG_EFLAGS]      = 0xff70 | 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_CR0]         = 0xff58 | SZ_QWORD,
+       [STATE_REG_CR3]         = 0xff50 | SZ_QWORD,
+
+       [STATE_REG_CS]          = 0xfe10 | SZ_WORD,
+       [STATE_REG_CS_ATTRIB]   = 0xfe12 | SZ_WORD,
+       [STATE_REG_CS_BASE]     = 0xfe18 | SZ_QWORD,
+       [STATE_REG_CS_LIMIT]    = 0xfe14 | SZ_DWORD,
+       [STATE_REG_SS]          = 0xfe20 | SZ_WORD,
+       [STATE_REG_SS_ATTRIB]   = 0xfe22 | SZ_WORD,
+       [STATE_REG_SS_BASE]     = 0xfe28 | SZ_QWORD,
+       [STATE_REG_SS_LIMIT]    = 0xfe24 | SZ_DWORD,
+       [STATE_REG_DS]          = 0xfe30 | SZ_WORD,
+       [STATE_REG_DS_ATTRIB]   = 0xfe32 | SZ_WORD,
+       [STATE_REG_DS_BASE]     = 0xfe38 | SZ_QWORD,
+       [STATE_REG_DS_LIMIT]    = 0xfe34 | SZ_DWORD,
+       [STATE_REG_ES]          = 0xfe00 | SZ_WORD,
+       [STATE_REG_ES_ATTRIB]   = 0xfe02 | SZ_WORD,
+       [STATE_REG_ES_BASE]     = 0xfe08 | SZ_QWORD,
+       [STATE_REG_ES_LIMIT]    = 0xfe04 | SZ_DWORD,
+       [STATE_REG_FS]          = 0xfe40 | SZ_WORD,
+       [STATE_REG_FS_ATTRIB]   = 0xfe42 | SZ_WORD,
+       [STATE_REG_FS_BASE]     = 0xfe48 | SZ_QWORD,
+       [STATE_REG_FS_LIMIT]    = 0xfe44 | SZ_DWORD,
+       [STATE_REG_GS]          = 0xfe50 | SZ_WORD,
+       [STATE_REG_GS_ATTRIB]   = 0xfe52 | SZ_WORD,
+       [STATE_REG_GS_BASE]     = 0xfe58 | SZ_QWORD,
+       [STATE_REG_GS_LIMIT]    = 0xfe54 | SZ_DWORD,
+       [STATE_REG_IDT_BASE]    = 0xfe88 | SZ_QWORD,
+       [STATE_REG_IDT_LIMIT]   = 0xfe84 | SZ_DWORD,
 
        [STATE_REG_RAX]         = 0xfff8 | SZ_QWORD,
        [STATE_REG_RBX]         = 0xffe0 | SZ_QWORD,
 
        [STATE_REG_RAX]         = 0xfff8 | SZ_QWORD,
        [STATE_REG_RBX]         = 0xffe0 | SZ_QWORD,
@@ -113,7 +136,75 @@ static const uint32_t offset_table_amd64[] = {
        [STATE_REG_R13]         = 0xff90 | SZ_QWORD,
        [STATE_REG_R14]         = 0xff88 | SZ_QWORD,
        [STATE_REG_R15]         = 0xff80 | 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
+       [STATE_REG_RIP]         = 0xff78 | SZ_QWORD,
+       [STATE_REG_RFLAGS]      = 0xff70 | SZ_QWORD,
+
+       [STATE_REG_EFER]        = 0xfed0 | SZ_QWORD
+};
+
+static const char register_names[][4] = {
+       [STATE_REV]             = "sREV",
+       [STATE_REG_SMBASE]      = "sBSE",
+       [STATE_REG_IORESTART]   = "IOrs",
+       [STATE_REG_HALTRESTART] = "HLrs",
+
+       [STATE_REG_EAX]         = "%eax",
+       [STATE_REG_EBX]         = "%ebx",
+       [STATE_REG_ECX]         = "%ecx",
+       [STATE_REG_EDX]         = "%edx",
+       [STATE_REG_ESI]         = "%esi",
+       [STATE_REG_EDI]         = "%edi",
+       [STATE_REG_ESP]         = "%esp",
+       [STATE_REG_EBP]         = "%ebp",
+       [STATE_REG_EIP]         = "%eip",
+       [STATE_REG_EFLAGS]      = "%eFL",
+       [STATE_REG_CR0]         = "%cr0",
+       [STATE_REG_CR3]         = "%cr3",
+
+       [STATE_REG_CS]          = "%cs ",
+       [STATE_REG_CS_ATTRIB]   = "csAT",
+       [STATE_REG_CS_BASE]     = "csBA",
+       [STATE_REG_CS_LIMIT]    = "csLI",
+       [STATE_REG_SS]          = "%ss ",
+       [STATE_REG_SS_ATTRIB]   = "ssAT",
+       [STATE_REG_SS_BASE]     = "ssBA",
+       [STATE_REG_SS_LIMIT]    = "ssLI",
+       [STATE_REG_DS]          = "%ds ",
+       [STATE_REG_DS_ATTRIB]   = "dsAT",
+       [STATE_REG_DS_BASE]     = "dsBA",
+       [STATE_REG_DS_LIMIT]    = "dsLI",
+       [STATE_REG_ES]          = "%es ",
+       [STATE_REG_ES_ATTRIB]   = "esAT",
+       [STATE_REG_ES_BASE]     = "esBA",
+       [STATE_REG_ES_LIMIT]    = "esLI",
+       [STATE_REG_FS]          = "%fs ",
+       [STATE_REG_FS_ATTRIB]   = "fsAT",
+       [STATE_REG_FS_BASE]     = "fsBA",
+       [STATE_REG_FS_LIMIT]    = "fsLI",
+       [STATE_REG_GS]          = "%gs ",
+       [STATE_REG_GS_ATTRIB]   = "gsAT",
+       [STATE_REG_GS_BASE]     = "gsBA",
+       [STATE_REG_GS_LIMIT]    = "gsLI",
+
+       [STATE_REG_RAX]         = "%rax",
+       [STATE_REG_RBX]         = "%rbx",
+       [STATE_REG_RCX]         = "%rcx",
+       [STATE_REG_RDX]         = "%rdx",
+       [STATE_REG_RSI]         = "%rsi",
+       [STATE_REG_RDI]         = "%rdi",
+       [STATE_REG_RSP]         = "%rsp",
+       [STATE_REG_RBP]         = "%rbp",
+       [STATE_REG_R8]          = "%r8 ",
+       [STATE_REG_R9]          = "%r9 ",
+       [STATE_REG_R10]         = "%r10",
+       [STATE_REG_R11]         = "%r11",
+       [STATE_REG_R12]         = "%r12",
+       [STATE_REG_R13]         = "%r13",
+       [STATE_REG_R14]         = "%r14",
+       [STATE_REG_R15]         = "%r15",
+       [STATE_REG_RIP]         = "%rip",
+
+       [STATE_REG_EFER]        = "EFER"
 };
 
 #define MAX_REG_AMD64 (sizeof(offset_table_amd64)/sizeof(uint32_t))
 };
 
 #define MAX_REG_AMD64 (sizeof(offset_table_amd64)/sizeof(uint32_t))
@@ -237,3 +328,30 @@ int state_set_reg (enum state_reg_t reg, uint64_t value) {
 
        return 0;
 }
 
        return 0;
 }
+
+/* Dump the name and contents of a register to a string.
+ *
+ * Returns: The number of bytes written.
+ */
+
+int state_dump_reg(char * dest, int max, enum state_reg_t reg) {
+       const char const * name = register_names[reg];
+       switch (state_reg_size(reg)) {
+       case 1:
+               return snprintf(dest, max, "%.4s: 0x%02x\n",
+                       name, (unsigned int)state_get_reg(reg));
+       case 2:
+               return snprintf(dest, max, "%.4s: 0x%04x\n",
+                       name, (unsigned int)state_get_reg(reg));
+       case 4:
+               return snprintf(dest, max, "%.4s: 0x%08x\n",
+                       name, (unsigned int)state_get_reg(reg));
+       case 8: {
+               uint64_t v = state_get_reg(reg);
+               return snprintf(dest, max, "%.4s: 0x%08x%08x\n",
+                       name, (unsigned int)(v>>32), (unsigned int)v);
+       }
+       default:
+               return 0;
+       }
+}
index 0ef283999c0b1897a2cda7676cf067468429a694..cce0892543d7006c982a9da8af621e3f8b1abcd9 100644 (file)
@@ -325,7 +325,7 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
                 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
     memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
   } else {
                 ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
     memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
   } else {
-    LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
+    LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: OOM in pool %s\n", memp_desc[type]));
 #if MEMP_STATS
     ++lwip_stats.memp[type].err;
 #endif /* MEMP_STATS */
 #if MEMP_STATS
     ++lwip_stats.memp[type].err;
 #endif /* MEMP_STATS */
index 4fe2c41100c27ec94b60f8665bcb3e5e687d5cab..832d3dddddf1672f47942df24f343f78f29f848a 100644 (file)
 #include <io.h>
 #include <minilib.h>
 #include <paging.h>
 #include <io.h>
 #include <minilib.h>
 #include <paging.h>
+#include <demap.h>
 #include <output.h>
 #include <output.h>
+#include <state.h>
 
 
-static char http_output_buffer[1024];
+static char http_output_buffer[1280];
 
 /*-----------------------------------------------------------------------------------*/
 
 void handle_regs(struct fs_file *file)
 {
 
 /*-----------------------------------------------------------------------------------*/
 
 void handle_regs(struct fs_file *file)
 {
-  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>"
-    "%%eax: 0x%08x    %%ebx: 0x%08x    %%ecx: 0x%08x    %%edx: 0x%08x\n"
-    "%%ebp: 0x%08x    %%esi: 0x%08x    %%edi: 0x%08x    %%esp: 0x%08x\n"
-    "%%cr0: 0x%08x    %%cr3: 0x%08x    %%eip: 0x%08x    %%eflags: 0x%08x\n"
-    "</pre></tt></body></html>",
-    *(unsigned long*)0xAFFD0,
-    *(unsigned long*)0xAFFDC,
-    *(unsigned long*)0xAFFD4,
-    *(unsigned long*)0xAFFD8,
-    *(unsigned long*)0xAFFE4,
-    *(unsigned long*)0xAFFE8,
-    *(unsigned long*)0xAFFEC,
-    *(unsigned long*)0xAFFE0,
-    *(unsigned long*)0xAFFFC,
-    *(unsigned long*)0xAFFF8,
-    *(unsigned long*)0xAFFF0,
-    *(unsigned long*)0xAFFF4);
-  
+  int i;
+  int len;
+
+  len = snprintf(http_output_buffer, sizeof(http_output_buffer), "<html><pre>");
+
+  for (i = 0; i < NUM_REGISTERS; i++) {
+    len += state_dump_reg(http_output_buffer + len, sizeof(http_output_buffer) - len, i);
+  }
+
+  file->len = len;
   file->data = http_output_buffer;
 }
 
   file->data = http_output_buffer;
 }
 
@@ -74,36 +65,56 @@ void handle_backtrace(struct fs_file *file)
 {
   int i = 10;
   int len;
 {
   int i = 10;
   int len;
-  unsigned long *pebp, *peip;
-  unsigned long ebp;
-  unsigned long cr3;
+  void *pebp, *peip;
+  uint64_t bp, next;
+
+  int longmode = (get_operating_mode() == LONG_64BIT);
 
   char * buf = http_output_buffer;
   
   strcpy(buf, "<html><head><title>Backtrace</title></head><body><tt><pre>");
   len = strlen(buf);
 
   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;
+
+  bp = state_get_reg(STATE_REG_RIP);
+
+  if (longmode)
+    len += snprintf(buf + len, LEFT, "0x%08x%08x, from\n", (uint32_t)(bp >> 32), (uint32_t)bp);
+  else
+    len += snprintf(buf + len, LEFT, "0x%08x, from\n", (uint32_t)bp);
   
   
-  len += snprintf(buf + len, LEFT, "0x%08x, from\n", *(unsigned long*)0xAFFF0);
+  bp = state_get_reg(STATE_REG_RBP);
   
   /* I never thought I'd do this again. */
   
   /* I never thought I'd do this again. */
-  while ((peip = demap(cr3, ebp+4)) != 0x0 && i--)
+  while ((peip = demap(bp+(longmode?8:4))) != 0x0 && i--)
   {
   {
-    len += snprintf(buf + len, LEFT, "0x%08x, from\n", *peip);
+    if (longmode) {
+      next = *(uint64_t *)peip;
+      len += snprintf(buf + len, LEFT, "0x%08x%08x, from\n", (uint32_t)(next >> 32), (uint32_t)next);
+    } else {
+      next = *(uint32_t *)peip;
+      len += snprintf(buf + len, LEFT, "0x%08x, from\n", (uint32_t)next);
+    }
+
+    pebp = demap(bp);
 
 
-    pebp = demap(cr3, ebp);
     if (!pebp)
     {
     if (!pebp)
     {
-      len += snprintf(buf + len, LEFT, "&lt;unreadable %ebp&gt;\n");
+      len += snprintf(buf + len, LEFT, "&lt;unreadable frame&gt;\n");
       break;
     }
       break;
     }
-    if (ebp >= *pebp && *pebp)
+
+    if (longmode)
+      next = *(uint64_t *)pebp;
+    else
+      next = *(uint32_t *)pebp;
+
+    if (bp >= next && next)
     {
     {
-      len += snprintf(buf + len, LEFT, "&lt;recursive %ebp&gt;\n");
+      len += snprintf(buf + len, LEFT, "&lt;recursive frame&gt;\n");
       break;
     }
       break;
     }
-    ebp = *pebp;
+
+    bp = next;
   }
 
   if (i == -1)
   }
 
   if (i == -1)
index 066f058b2582c73cf7b63cf1abb6253589f9a238..e42d5ad9a7bd244dd0fc04e5bd6506fa9838a5d9 100644 (file)
@@ -5,9 +5,9 @@ static const char data_404_html[] =
 
 static const char data_index_html[] =
   "<html><head><title>NetWatch</title></head>"
 
 static const char data_index_html[] =
   "<html><head><title>NetWatch</title></head>"
-  "<body><h1>NetWatch</h1>"
-  "<iframe src=\"registers.html\" height=100 width=600></iframe><br>"
-  "<iframe src=\"backtrace.html\" height=250 width=150></iframe>"
+  "<body><h1>NetWatch</h1><table cellpadding=0 cellspacing=0 border=0><tr valign=top><td>"
+  "<iframe src=\"registers.html\" height=500 width=300></iframe></td><td>"
+  "<iframe src=\"backtrace.html\" height=250 width=150></iframe></td></tr></table>"
   "<form action=reboot type=post><input type=submit value=\"Reboot!\"></form>"
   "</body></html>";
 
   "<form action=reboot type=post><input type=submit value=\"Reboot!\"></form>"
   "</body></html>";
 
index ed08b0ccbce75081e69e131d6a519fdc6162f84e..81d4a3f457c397ba0c657a3b184fdd2bc441f92e 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <minilib.h>
 #include <output.h>
 
 #include <minilib.h>
 #include <output.h>
+#include <tables.h>
 #include "lwip/debug.h"
 
 #include "lwip/stats.h"
 #include "lwip/debug.h"
 
 #include "lwip/stats.h"
@@ -258,3 +259,4 @@ httpd_init(void)
 }
 /*-----------------------------------------------------------------------------------*/
 
 }
 /*-----------------------------------------------------------------------------------*/
 
+PROTOCOL(httpd_init);
index 1462f09e30ae44c466140949299598820b99e743..d762b47fa85c9949b74dcc9595c02217e85cb07b 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -13,6 +13,7 @@
 #include <pci-bother.h>
 #include <output.h>
 #include <minilib.h>
 #include <pci-bother.h>
 #include <output.h>
 #include <minilib.h>
+#include <tables.h>
 #include <lwip/init.h>
 #include "net.h"
 
 #include <lwip/init.h>
 #include "net.h"
 
@@ -28,8 +29,6 @@
 #include "netif/etharp.h"
 #include "netif/ppp_oe.h"
 
 #include "netif/etharp.h"
 #include "netif/ppp_oe.h"
 
-#include "rfb.h"
-
 static struct nic *_nic = 0x0;
 static struct netif _netif;
 
 static struct nic *_nic = 0x0;
 static struct netif _netif;
 
@@ -139,15 +138,19 @@ int eth_register(struct nic *nic)
        return 0;
 }
 
        return 0;
 }
 
+typedef void(*thunk_t)();
+
+TABLE(thunk_t, protocols);
+
 void eth_init()
 {
 void eth_init()
 {
-       extern void httpd_init();
+       int i;
        
        /* Required for DMA to work. :( */
        smram_tseg_set_state(SMRAM_TSEG_OPEN);
        
        /* Required for DMA to work. :( */
        smram_tseg_set_state(SMRAM_TSEG_OPEN);
-       lwip_init();
-       httpd_init();
 
 
-       rfb_init();
+       lwip_init();
 
 
+       for (i = 0; i < TABLE_LENGTH(protocols); i++)
+               protocols_table[i]();
 }
 }
index 514dfc71e0837b4061984c2a6a065a873d948531..de816887f5481932e2d98b3f84f28e8b86a2f09a 100644 (file)
--- a/net/rfb.c
+++ b/net/rfb.c
 #include <output.h>
 #include <fb.h>
 #include <keyboard.h>
 #include <output.h>
 #include <fb.h>
 #include <keyboard.h>
+#include <tables.h>
 
 #include "lwip/tcp.h"
 #include "lwip/stats.h"
 
 
 #include "lwip/tcp.h"
 #include "lwip/stats.h"
 
-#include "rfb.h"
+#define RFB_PORT               5900
 
 #define SET_PIXEL_FORMAT       0
 #define SET_ENCODINGS          2
 
 #define SET_PIXEL_FORMAT       0
 #define SET_ENCODINGS          2
@@ -654,7 +655,7 @@ static err_t rfb_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
        return ERR_OK;
 }
 
        return ERR_OK;
 }
 
-void rfb_init() {
+static void rfb_init() {
        struct tcp_pcb *pcb;
 
        init_server_info();
        struct tcp_pcb *pcb;
 
        init_server_info();
@@ -664,3 +665,5 @@ void rfb_init() {
        pcb = tcp_listen(pcb);
        tcp_accept(pcb, rfb_accept);
 }
        pcb = tcp_listen(pcb);
        tcp_accept(pcb, rfb_accept);
 }
+
+PROTOCOL(rfb_init);
diff --git a/net/rfb.h b/net/rfb.h
deleted file mode 100644 (file)
index 25fa3fb..0000000
--- a/net/rfb.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* rfb.h
- * Remote framebuffer server
- * NetWatch system management mode administration console
- *
- * Copyright (c) 2008 Jacob Potter and Joshua Wise.  All rights reserved.
- * This program is free software; you can redistribute and/or modify it under
- * the terms found in the file LICENSE in the root of this source tree.
- *
- */
-
-#ifndef _RFB_H
-#define _RFB_H
-
-void rfb_init(void);
-
-#define RFB_PORT       5900
-
-#endif /* _RFB_H */
similarity index 83%
rename from netwatch/aseg.lds
rename to netwatch/netwatch-large.lds
index cf14790b025752b87bbda39f029cb834f7f50ec4..9bf3b8a52dc3f0ae336d5ba4652622fffd5270e1 100644 (file)
@@ -19,8 +19,11 @@ SECTIONS
 
        . = 0x200000;
 
 
        . = 0x200000;
 
-       .text : { *(.text); }
-       .data : { *(.data); }
+       .text : {
+               *(.text);
+               *(SORT(.table.*));
+       }
+       .data : { *(.data); *(.data2); }
        .rodata : { *(.rodata); }
        .text : { *(.text); }
        
        .rodata : { *(.rodata); }
        .text : { *(.text); }
        
@@ -32,7 +35,7 @@ SECTIONS
        .stack : { 
                . = . + 0x10000;
                . = ALIGN(0x10);
        .stack : { 
                . = . + 0x10000;
                . = ALIGN(0x10);
-               _stacktop = .;
+               _primary_stack_top = .;
        }
 
        . = 0x10000;
        }
 
        . = 0x10000;
index 964d06ed9c2b96b559a9bab0e6314ae38e8401ec..7440a7a6d56d7256936589cb73f8d83c95c0c5d0 100644 (file)
@@ -23,5 +23,11 @@ set_cr0_cont:                           # Hey, here we are!
 ps_switch_stack:
   mov 4(%esp), %eax
   mov 8(%esp), %esp   
 ps_switch_stack:
   mov 4(%esp), %eax
   mov 8(%esp), %esp   
+  # Put a sentinel value (FEEDFACE) at the top of the stack
+  mov $0xCEFAEDFE, %edx
+  push %edx
+  push %edx
+  push %edx
+  push %edx
   call *%eax
   rsm
   call *%eax
   rsm
This page took 0.313401 seconds and 4 git commands to generate.