From: Jacob Potter Date: Mon, 3 Nov 2008 09:14:18 +0000 (-0500) Subject: add paging fork of aseg; totally not working yet. X-Git-Url: http://git.joshuawise.com/netwatch.git/commitdiff_plain/9e2a82e4e9495f33b8e6423c335a9a157f056254?ds=inline add paging fork of aseg; totally not working yet. --- diff --git a/aseg-paging/Makefile b/aseg-paging/Makefile new file mode 100644 index 0000000..ec2474e --- /dev/null +++ b/aseg-paging/Makefile @@ -0,0 +1,22 @@ +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 diff --git a/aseg-paging/aseg.lds b/aseg-paging/aseg.lds new file mode 100644 index 0000000..760fe92 --- /dev/null +++ b/aseg-paging/aseg.lds @@ -0,0 +1,45 @@ +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); + } + +} diff --git a/aseg-paging/entry.asm b/aseg-paging/entry.asm new file mode 100644 index 0000000..03dd7c4 --- /dev/null +++ b/aseg-paging/entry.asm @@ -0,0 +1,45 @@ + 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 diff --git a/aseg-paging/firstrun.c b/aseg-paging/firstrun.c new file mode 100644 index 0000000..649583b --- /dev/null +++ b/aseg-paging/firstrun.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include "vga-overlay.h" +#include +#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); +} + diff --git a/aseg-paging/pagetable.c b/aseg-paging/pagetable.c new file mode 100644 index 0000000..83a1e54 --- /dev/null +++ b/aseg-paging/pagetable.c @@ -0,0 +1,59 @@ +#include "vm_flags.h" +#include + +#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; +} diff --git a/aseg-paging/pagetable.h b/aseg-paging/pagetable.h new file mode 100644 index 0000000..49e7013 --- /dev/null +++ b/aseg-paging/pagetable.h @@ -0,0 +1 @@ +void * pt_setup(int smbase); diff --git a/aseg-paging/paging.c b/aseg-paging/paging.c new file mode 100644 index 0000000..fd5d15d --- /dev/null +++ b/aseg-paging/paging.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#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(); +} + diff --git a/aseg-paging/pagingstub-asm.s b/aseg-paging/pagingstub-asm.s new file mode 100644 index 0000000..0d30a6d --- /dev/null +++ b/aseg-paging/pagingstub-asm.s @@ -0,0 +1,13 @@ + +.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 + diff --git a/aseg-paging/pagingstub.c b/aseg-paging/pagingstub.c new file mode 100644 index 0000000..6c85157 --- /dev/null +++ b/aseg-paging/pagingstub.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#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(); +} diff --git a/aseg-paging/smi.c b/aseg-paging/smi.c new file mode 100644 index 0000000..33536eb --- /dev/null +++ b/aseg-paging/smi.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#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(); +} + diff --git a/aseg-paging/vga-overlay.c b/aseg-paging/vga-overlay.c new file mode 100644 index 0000000..4d19c3b --- /dev/null +++ b/aseg-paging/vga-overlay.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include + +#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)); +} + diff --git a/aseg-paging/vm_flags.h b/aseg-paging/vm_flags.h new file mode 100644 index 0000000..d89c9a8 --- /dev/null +++ b/aseg-paging/vm_flags.h @@ -0,0 +1,38 @@ +/** 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 */