--- /dev/null
+CC=gcc
+CFLAGS=-I../include -I../include/raw \
+ -I../lwip/src/include -I../lwip/src/include/ipv4 \
+ -nostdlib -nostdinc -fno-builtin -D__RAW__ \
+ -Wall -Werror -std=gnu99
+
+STUBOBJS=entry.o pagingstub-asm.o pagingstub.o
+
+OBJS=smi.o ../ich2/smi.o ../ich2/smram-ich2.o vga-overlay.o ../pci/pci-raw.o ../lib/minilib.o ../lib/doprnt.o ../lib/sprintf.o ../lib/console.o
+
+all: aseg.elf
+
+aseg.elf: aseg.lds $(STUBOBJS) $(OBJS)
+ ld -o aseg.elf -T aseg.lds $(STUBOBJS) $(OBJS)
+
+clean:
+ rm -f $(OBJS) aseg.elf entry.bin entry.o
+
+%.o: %.asm
+ nasm -o $@.bin $<
+ objcopy -I binary -B i386 -O elf32-i386 $@.bin $@
+ rm -f $@.bin
--- /dev/null
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+
+SECTIONS
+{
+ . = 0xA8000;
+
+ .aseg : {
+ _start = .;
+ entry.o
+ LONG(0xA9FF0);
+ LONG(c_entry);
+ entry_initialized = .;
+ LONG(0);
+ pagingstub-asm.o
+ pagingstub.o
+ _aseg_end = .;
+ }
+
+ . = 0x200000;
+
+ .maincode : {
+ *(.data);
+ *(.rodata);
+ *(.text);
+ _bss = .;
+ *(.bss);
+ _bssend = .;
+ _end = .;
+ }
+
+ .stack : {
+ . = . + 0x10000;
+ . = ALIGN(0x10);
+ _stacktop = .;
+ }
+
+ . = 0x10000;
+ .info : {
+ _start = .;
+ LONG(0x5754454E);
+ LONG(__firstrun_start);
+ }
+
+}
--- /dev/null
+ org 0xA8000
+[bits 16]
+entry:
+ mov ax, 0xA800 ; Take us out of flat unreal mode,
+ mov ds, ax ; and put us in true real mode.
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ jmp 0xA800:(entry2-0xA8000) ; Long jump to a correct cs.
+entry2:
+ lgdt [(gdtr-0xA8000)] ; Set up a new GDT.
+ mov eax, 0x1
+ mov cr0, eax ; ... and enter pmode!
+ jmp long 0x10:continue ; Now longjmp into the new code.
+[bits 32]
+continue:
+ mov ax, 0x08 ; Set up segment selectors.
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ mov esp, [dataptr] ; Load stack pointer.
+
+ mov eax, [dataptr+4] ; Load target jump address
+ call eax ; then jump into C.
+
+ rsm ; and leave SMM
+
+ align 0x4
+gdtr:
+ db 0x17, 0x00
+ dd gdt
+ align 0x4
+gdt:
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; initial null entry
+ db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x93, 0xCF, 0x00 ; data segment
+ db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9B, 0xCF, 0x00 ; code segment
+
+
+dataptr:
+ ; 4 bytes of stack top
+ ; 4 bytes of C entry point
+ ; These show up
--- /dev/null
+#include <io.h>
+#include <smi.h>
+#include <pci.h>
+#include <reg-82801b.h>
+#include <output.h>
+#include "vga-overlay.h"
+#include <smram.h>
+#include "../net/net.h"
+
+extern int _bss, _bssend;
+
+extern void timer_handler(smi_event_t ev);
+extern void kbc_handler(smi_event_t ev);
+extern void gbl_rls_handler(smi_event_t ev);
+
+void __firstrun_start() {
+ unsigned char *bp;
+ smram_state_t smram;
+
+ smram = smram_save_state();
+ smram_tseg_set_state(SMRAM_TSEG_OPEN);
+/*
+ for (bp = (void *)&_bss; (void *)bp < (void *)&_bssend; bp++)
+ *bp = 0;
+
+ vga_flush_imm(0);
+*/
+
+ outputf("NetWatch running");
+
+ /* Try really hard to shut up USB_LEGKEY. */
+ pci_write16(0, 31, 2, 0xC0, pci_read16(0, 31, 2, 0xC0));
+ pci_write16(0, 31, 2, 0xC0, 0);
+ pci_write16(0, 31, 4, 0xC0, pci_read16(0, 31, 4, 0xC0));
+ pci_write16(0, 31, 4, 0xC0, 0);
+
+ /* Turn on the SMIs we want */
+ smi_disable();
+ /*
+
+ eth_init();
+
+ smi_register_handler(SMI_EVENT_FAST_TIMER, timer_handler);
+ smi_enable_event(SMI_EVENT_FAST_TIMER);
+
+ smi_register_handler(SMI_EVENT_DEVTRAP_KBC, kbc_handler);
+ smi_enable_event(SMI_EVENT_DEVTRAP_KBC);
+
+ smi_register_handler(SMI_EVENT_GBL_RLS, gbl_rls_handler);
+ smi_enable_event(SMI_EVENT_GBL_RLS);
+*/
+ smi_enable();
+
+ vga_flush_imm(1);
+
+ smram_restore_state(smram);
+}
+
--- /dev/null
+#include "vm_flags.h"
+#include <io.h>
+
+#define MAP_FLAGS (PTE_PRESENT | PTE_READ_WRITE)
+
+void * pt_setup(int smbase) {
+ int i;
+ outb(0x80, 0x51);
+
+ /* The page directory and page table live at SMBASE and SMBASE + 0x1000,
+ * respectively; clear them. */
+ int * pagedirectory = (int *) smbase;
+ int * pagetable = (int *) (smbase + 0x1000);
+
+ /* Clear out the page directory except for one entry pointing to the
+ * page table, and clear the page table entirely. */
+ outb(0x80, 0x52);
+ pagedirectory[0] = (smbase + 0x1000) | PTE_PRESENT | PTE_READ_WRITE;
+ outb(0x80, 0x53);
+ for (i = 1; i < 1024; i++)
+ {
+ pagedirectory[i] = 0;
+ }
+
+ outb(0x80, 0x54);
+ for (i = 0; i < 1024; i++)
+ {
+ pagetable[i] = 0;
+ }
+ outb(0x80, 0x55);
+
+ /* The page at 0x10000 - 0x10FFF points to the SMI entry point,
+ * SMBASE + 0x8000. */
+ pagetable[16] = (0x8000 + smbase) | MAP_FLAGS;
+
+ /* 0x11000 to 0x1EFFF map to the rest of ASEG up to SMBASE + 0xF000;
+ * the page containing the saved state is not mappped to our code
+ * region. */
+
+ for (i = 0; i < 8; i++)
+ {
+ pagetable[17 + i] = (i * 0x1000 + smbase) | MAP_FLAGS;
+ }
+
+ for (i = 0; i < 6; i++)
+ {
+ pagetable[25 + i] = (smbase + 0x9000 + i * 0x1000) | MAP_FLAGS;
+ }
+
+ outb(0x80, 0x56);
+ /* Map 0xA8000 to itself. */
+ pagetable[0xA8] = 0xA8000 | MAP_FLAGS;
+ pagetable[0xA9] = 0xA9000 | MAP_FLAGS;
+
+ /* No TSEG yet. */
+
+ outb(0x80, 0x57);
+ return pagedirectory;
+}
--- /dev/null
+void * pt_setup(int smbase);
--- /dev/null
+#include <io.h>
+#include <smram.h>
+#include <video_defines.h>
+#include <minilib.h>
+#include <smi.h>
+#include <pci-bother.h>
+#include "../net/net.h"
+#include "vga-overlay.h"
+
+#include "pagetable.h"
+
+unsigned int counter = 0;
+unsigned int lastctr = 0;
+unsigned long pcisave;
+unsigned char vgasave;
+
+void set_cr0(unsigned int);
+
+#define get_cr0() \
+ ({ \
+ register unsigned int _temp__; \
+ asm volatile("mov %%cr0, %0" : "=r" (_temp__)); \
+ _temp__; \
+ })
+
+
+#define set_cr3(value) \
+ { \
+ register unsigned int _temp__ = (value); \
+ asm volatile("mov %0, %%cr3" : : "r" (_temp__)); \
+ }
+#define CR0_PG 0x80000000
+
+
+void smi_entry(void)
+{
+/*
+ char statstr[512];
+*/
+
+ outb(0x80, 0xBB);
+ return;
+
+ char * pagedir = pt_setup(0xA0000);
+ outb(0x80, 0x43);
+ set_cr3((int)pagedir);
+ outb(0x80, 0xA5);
+
+ /* Turn paging on */
+ set_cr0(get_cr0() | CR0_PG);
+ outb(0x80, 0xAA);
+
+ pcisave = inl(0xCF8);
+ vgasave = inb(0x3D4);
+/*
+ pci_unbother_all();
+ */
+
+ counter++;
+ /*
+ sprintf(statstr, "15-412! %08x %08x", smi_status(), counter);
+ strblit(statstr, 0, 0);
+ */
+
+ /*
+ eth_poll();
+ */
+
+ if (inl(0x840) & 0x1000)
+ {
+ /*
+ pci_dump();
+ */
+ outl(0x840, 0x1100);
+ outl(0x840, 0x0100);
+ }
+
+/*
+ smi_poll();
+
+ pci_bother_all();
+ */
+ outl(0xCF8, pcisave);
+ outb(0x3D4, vgasave);
+}
+
+void timer_handler(smi_event_t ev)
+{
+ static unsigned int ticks = 0;
+
+ smi_disable_event(SMI_EVENT_FAST_TIMER);
+ smi_enable_event(SMI_EVENT_FAST_TIMER);
+
+ outb(0x80, (ticks++) & 0xFF);
+
+ outlog();
+}
+
+
+void __firstrun_start() {
+ smi_disable();
+ outb(0x80, 0x41);
+
+ smi_register_handler(SMI_EVENT_FAST_TIMER, timer_handler);
+ smi_enable_event(SMI_EVENT_FAST_TIMER);
+
+ smi_enable();
+}
+
--- /dev/null
+
+.globl set_cr0
+
+set_cr0:
+ mov 4(%esp), %eax # Load argument
+ movl %eax, %cr0 # Set CR0
+ pushw %cs # Push 16 bits of %CS
+ pushl $set_cr0_cont # Push 32 bits of %EIP
+ ljmp *(%esp) # "Far jump" (both %CS and %EIP from stack)
+set_cr0_cont: # Hey, here we are!
+ addl $6, %esp # Un-do 48 bits of pushing
+ ret
+
--- /dev/null
+#include <io.h>
+#include <smram.h>
+#include <video_defines.h>
+#include <minilib.h>
+#include <smi.h>
+#include <pci-bother.h>
+#include "../net/net.h"
+#include "vga-overlay.h"
+
+#include "vm_flags.h"
+#include "pagetable.h"
+
+void set_cr0(unsigned int);
+
+extern int entry_initialized;
+extern int _bss, _bssend, _end;
+void smi_entry();
+#define get_cr0() \
+ ({ \
+ register unsigned int _temp__; \
+ asm volatile("mov %%cr0, %0" : "=r" (_temp__)); \
+ _temp__; \
+ })
+
+
+#define set_cr3(value) \
+ { \
+ register unsigned int _temp__ = (value); \
+ asm volatile("mov %0, %%cr3" : : "r" (_temp__)); \
+ }
+#define CR0_PG 0x80000000
+
+#define MAP_FLAGS (PTE_PRESENT | PTE_READ_WRITE)
+
+void * pt_setup(int smbase) {
+ int i;
+ outb(0x80, 0x51);
+
+ /* The page directory and page table live at SMBASE and SMBASE + 0x1000,
+ * respectively; clear them. */
+ int * pagedirectory = (int *) smbase;
+ int * pagetable = (int *) (smbase + 0x1000);
+
+ /* Clear out the page directory except for one entry pointing to the
+ * page table, and clear the page table entirely. */
+ outb(0x80, 0x52);
+ pagedirectory[0] = (smbase + 0x1000) | PTE_PRESENT | PTE_READ_WRITE;
+ outb(0x80, 0x53);
+ for (i = 1; i < 1024; i++)
+ {
+ pagedirectory[i] = 0;
+ }
+
+ outb(0x80, 0x54);
+ for (i = 0; i < 1024; i++)
+ {
+ pagetable[i] = 0;
+ }
+ outb(0x80, 0x55);
+
+ /* The page at 0x10000 - 0x10FFF points to the SMI entry point,
+ * SMBASE + 0x8000. */
+ pagetable[16] = (0x8000 + smbase) | MAP_FLAGS;
+
+ /* 0x11000 to 0x1EFFF map to the rest of ASEG up to SMBASE + 0xF000;
+ * the page containing the saved state is not mappped to our code
+ * region. */
+
+ for (i = 0; i < 8; i++)
+ {
+ pagetable[17 + i] = (i * 0x1000 + smbase) | MAP_FLAGS;
+ }
+
+ for (i = 0; i < 6; i++)
+ {
+ pagetable[25 + i] = (smbase + 0x9000 + i * 0x1000) | MAP_FLAGS;
+ }
+
+ outb(0x80, 0x56);
+ /* Map 0xA8000 to itself. */
+
+ for (i = 0; i < 32; i++) {
+ pagetable[0xA0 + i] = (0xA0000 + i * 0x1000) | MAP_FLAGS;
+ }
+
+ /* Map 0x200000 to TSEG */
+ for (i = 0; i < 128; i++) {
+ pagetable[0x200 + i] = (0x1FF80000 + i * 0x1000) | MAP_FLAGS;
+ }
+
+ /* Map 0x300000 -> 0x200000, so we can copy our code out of
+ * RAM the first time around */
+ for (i = 0; i < 256; i++) {
+ /* pagetable[0x300 + i] = (0x200000 + i * 0x1000) | MAP_FLAGS;
+ */
+ pagetable[0x200 + i] = (0x200000 + i * 0x1000) | MAP_FLAGS;
+ }
+
+ outb(0x80, 0x57);
+ return pagedirectory;
+}
+
+void c_entry(void)
+{
+// unsigned char *bp;
+
+ outb(0x80, 0x41);
+ char * pagedir = pt_setup(0xA0000);
+ outb(0x80, 0x43);
+ set_cr3((int)pagedir);
+ outb(0x80, 0xA5);
+
+ /* Turn paging on */
+ set_cr0(get_cr0() | CR0_PG);
+ outb(0x80, 0xAA);
+ if (!entry_initialized) {
+ outb(0x80, 0xAB);
+/*
+ for (bp = (void *)0x200000; (void *)bp < (void *)&_bss; bp++)
+ *bp = *(bp + 0x100000);
+
+ for (bp = (void *)&_bss; (void *)bp < (void *)&_bssend; bp++)
+ *bp = 0;
+ */
+ }
+
+ smi_entry();
+}
--- /dev/null
+#include <io.h>
+#include <smram.h>
+#include <video_defines.h>
+#include <minilib.h>
+#include <smi.h>
+#include <pci-bother.h>
+#include "../net/net.h"
+#include "vga-overlay.h"
+
+#include "pagetable.h"
+
+unsigned int counter = 0;
+unsigned int lastctr = 0;
+unsigned long pcisave = 0;
+unsigned char vgasave = 0;
+
+void set_cr0(unsigned int);
+
+#define get_cr0() \
+ ({ \
+ register unsigned int _temp__; \
+ asm volatile("mov %%cr0, %0" : "=r" (_temp__)); \
+ _temp__; \
+ })
+
+
+#define set_cr3(value) \
+ { \
+ register unsigned int _temp__ = (value); \
+ asm volatile("mov %0, %%cr3" : : "r" (_temp__)); \
+ }
+#define CR0_PG 0x80000000
+
+
+void smi_entry(void)
+{
+ char statstr[512];
+ outb(0x80, 0x0B);
+ pcisave = inl(0xCF8);
+ vgasave = inb(0x3D4);
+ outb(0x80, 0x1B);
+/*
+ pci_unbother_all();
+ */
+ counter++;
+ outb(0x80, 0x2B);
+ sprintf(statstr, "15-412! %08x %08x", smi_status(), counter);
+ outb(0x80, 0x3B);
+ strblit(statstr, 0, 0);
+ outb(0x80, 0x4B);
+
+ /*
+ eth_poll();
+ */
+
+ if (inl(0x840) & 0x1000)
+ {
+ /*
+ pci_dump();
+ */
+ outl(0x840, 0x1100);
+ outl(0x840, 0x0100);
+ }
+
+/*
+ smi_poll();
+
+ pci_bother_all();
+ */
+ outl(0xCF8, pcisave);
+ outb(0x3D4, vgasave);
+}
+
+void timer_handler(smi_event_t ev)
+{
+ static unsigned int ticks = 0;
+
+ smi_disable_event(SMI_EVENT_FAST_TIMER);
+ smi_enable_event(SMI_EVENT_FAST_TIMER);
+
+ outb(0x80, (ticks++) & 0xFF);
+
+ outlog();
+}
+
+
+void __firstrun_start() {
+ smi_disable();
+ outb(0x80, 0x41);
+
+ smi_register_handler(SMI_EVENT_FAST_TIMER, timer_handler);
+ smi_enable_event(SMI_EVENT_FAST_TIMER);
+
+ smi_enable();
+}
+
--- /dev/null
+#include <io.h>
+#include <smram.h>
+#include <video_defines.h>
+#include <minilib.h>
+#include <stdarg.h>
+#include <output.h>
+
+#define LOGLEN 96
+#define LOG_ONSCREEN 4
+
+static char logents[LOGLEN][41] = {{0}};
+static int prodptr = 0;
+static int flush_imm = 0;
+
+#define VRAM_BASE 0xA0000UL
+#define TEXT_CONSOLE_OFFSET 0x18000UL
+
+#define TEXT_CONSOLE_BASE (VRAM_BASE + TEXT_CONSOLE_OFFSET)
+
+#define COLOR 0x1F
+
+void vga_flush_imm(int imm)
+{
+ flush_imm = imm;
+}
+
+static unsigned char vga_read(unsigned char idx)
+{
+ outb(CRTC_IDX_REG, idx);
+ return inb(CRTC_DATA_REG);
+}
+
+static char * vga_base()
+{
+ return (char *) (
+ TEXT_CONSOLE_BASE
+ + (((unsigned int) vga_read(CRTC_START_ADDR_MSB_IDX)) << 9)
+ + (((unsigned int) vga_read(CRTC_START_ADDR_LSB_IDX)) << 1)
+ );
+}
+
+void strblit(char *src, int row, int col)
+{
+ char *destp = vga_base() + row * 80 * 2 + col * 2;
+ outb(0x80, 0x3C);
+ smram_state_t old_state = smram_save_state();
+ outb(0x80, 0x3D);
+
+ smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+ outb(0x80, 0x3E);
+
+ while (*src)
+ {
+ *(destp++) = *(src++);
+ *(destp++) = COLOR;
+ }
+
+ outb(0x80, 0x3F);
+ smram_restore_state(old_state);
+ outb(0x80, 0x40);
+}
+
+void outlog()
+{
+ int y, x;
+ char *basep = vga_base();
+
+ smram_state_t old_state = smram_save_state();
+
+ smram_aseg_set_state(SMRAM_ASEG_SMMCODE);
+
+ for (y = 0; y < LOG_ONSCREEN; y++)
+ for (x = 40; x < 80; x++)
+ {
+ basep[y*80*2+x*2] = ' ';
+ basep[y*80*2+x*2+1] = 0x1F;
+ }
+
+ smram_restore_state(old_state);
+
+ for (y = -LOG_ONSCREEN; y < 0; y++)
+ strblit(logents[(y + prodptr) % LOGLEN], y + LOG_ONSCREEN, 40);
+}
+
+void dolog(const char *s)
+{
+ strcpy(logents[prodptr], s);
+ prodptr = (prodptr + 1) % LOGLEN;
+ if (flush_imm)
+ outlog();
+}
+void (*output)(const char *s) = dolog;
+
+void dologf(const char *fmt, ...)
+{
+}
+void (*outputf)(const char *s, ...) = dologf;
+
+void dump_log (char * target) {
+ memcpy(target, logents, sizeof(logents));
+}
+
--- /dev/null
+/** Page table and page directory flags.
+ *
+ * From intel-sys.pdf.
+ *
+ * @author Jacob Potter (jdpotter)
+ */
+
+#ifndef _VM_FLAGS_H
+#define _VM_FLAGS_H
+
+#define PDE_4M_ADDR_SHIFT 22
+#define PTE_4K_ADDR_SHIFT 12
+#define PDE_TABLE_ADDR_SHIFT 12
+#define PTE_FRAME_ADDR_MASK (~((1 << PTE_4K_ADDR_SHIFT) - 1))
+#define PDE_TABLE_ADDR_MASK (~((1 << PDE_TABLE_ADDR_SHIFT) - 1))
+
+#define PDE_ATTRIB_INDEX (1 << 12)
+#define PDE_GLOBAL (1 << 8)
+#define PDE_PAGE_SIZE (1 << 7)
+#define PDE_DIRTY (1 << 6)
+#define PDE_ACCESSED (1 << 5)
+#define PDE_NO_CACHE (1 << 4)
+#define PDE_WRITE_THROUGH (1 << 3)
+#define PDE_USER (1 << 2)
+#define PDE_READ_WRITE (1 << 1)
+#define PDE_PRESENT (1 << 0)
+
+#define PTE_GLOBAL (1 << 8)
+#define PTE_ATTRIB_INDEX (1 << 7)
+#define PTE_DIRTY (1 << 6)
+#define PTE_ACCESSED (1 << 5)
+#define PTE_NO_CACHE (1 << 4)
+#define PTE_WRITE_THROUGH (1 << 3)
+#define PTE_USER (1 << 2)
+#define PTE_READ_WRITE (1 << 1)
+#define PTE_PRESENT (1 << 0)
+
+#endif /* _VM_FLAGS_H */