mov gs, ax
mov ss, ax
mov esp, [dataptr] ; Load stack pointer.
-
- mov al, [needclear] ; Has the aseg been run before?
- cmp al, 0 ; If so,
- jz noclear ; don't clear BSS.
- mov al, 0 ; Otherwise, clear BSS.
- mov edi, [dataptr+4]
- mov ecx, [dataptr+8]
- rep stosb
- mov [needclear], al
-noclear:
- mov eax, [dataptr+12] ; Load target jump address
+ mov eax, [dataptr+4] ; Load target jump address
call eax ; then jump into C.
rsm ; and leave SMM
db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x93, 0xCF, 0x00 ; data segment
db 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9B, 0xCF, 0x00 ; code segment
-needclear:
- db 0x01
-
dataptr:
; 4 bytes of stack top
- ; 4 bytes of BSS start
- ; 4 bytes of BSS length
; 4 bytes of C entry point
; These show up
_start = .;
aseg.o
LONG(_stacktop);
- LONG(_bss);
- LONG(_bssend - _bss);
LONG(smi_entry);
*(.text);
*(.data);
#include <pci.h>
#include <reg-82801b.h>
#include "vga-overlay.h"
+#include <smram.h>
+
+extern int _bss, _bssend;
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;
+
dologf("NetWatch running");
/* Try really hard to shut up USB_LEGKEY. */
outb(0x830, inb(0x830) | ICH2_SMI_EN_SWSMI_TMR_EN);
outb(0x848, ICH2_DEVTRAP_EN_KBC_TRP_EN);
smi_enable();
+
+ smram_restore_state(smram);
}
if (mbinfo->mod_cnt != 1)
panic("Expected exactly one module; cannot continue.");
-
+ outputf("Current SMRAMC state is: %02x", pci_read8(0, 0, 0, 0x70));
outputf("Current USB state is: %04x %04x", pci_read16(0, 31, 2, 0xC0), pci_read16(0, 31, 4, 0xC0));
outputf("Current SMI state is: %08x", inl(0x830));
- outputf("Current SMRAMC state is: %02x", pci_read8(0, 0, 0, 0x70));
+
smi_disable();
info->firstrun();
smram_restore_state(old_smramc);
+
+ outputf("New SMRAMC state is: %02x", pci_read8(0, 0, 0, 0x70));
puts("Waiting for a bit before returning to real mode...");
for (i=0; i<0x500000; i++)
static void safeputs(const char *s)
{
- unsigned long old = smram_save_state();
+ smram_state_t old = smram_save_state();
smram_aseg_set_state(SMRAM_ASEG_SMMONLY);
puts(s);
smram_restore_state(old);
return 0;
}
+
+int smram_tseg_set_state (int open) {
+ unsigned char smramc;
+
+ if (smram_locked())
+ return -1;
+
+ smramc = pci_read8(0, 0, 0, SMRAMC);
+
+ switch (open)
+ {
+ case SMRAM_TSEG_OPEN:
+ smramc = (smramc & 0x8F) | 0x00;
+ break;
+ default:
+ return -1;
+ }
+
+ pci_write8(0, 0, 0, SMRAMC, smramc);
+
+ return 0;
+}
extern int smram_locked();
extern smram_state_t smram_save_state();
extern void smram_restore_state(smram_state_t state);
-extern int smram_aseg_set_state (int open);
+extern int smram_aseg_set_state(int open);
+extern int smram_tseg_set_state(int open);
#define SMRAM_ASEG_CLOSED 0 /* SMRAM is not readable. */
#define SMRAM_ASEG_OPEN 1 /* SMRAM is readable by everybody. */
#define SMRAM_ASEG_SMMCODE 2 /* SMRAM is readable as SMM code only. */
#define SMRAM_ASEG_SMMONLY 3 /* SMRAM is readable as SMM code and data only. */
+#define SMRAM_TSEG_OPEN 0
+
#endif