/* * Bootstrap loader. Starts at 0x10000 (where pbs puts it) * and memmoves kernel (at 0x11000) into standard * kernel location. */ #include "x16.h" #include "/sys/src/9/pc/mem.h" #define WRMSR BYTE $0x0F; BYTE $0x30 /* WRMSR, argument in AX/DX (lo/hi) */ #define RDTSC BYTE $0x0F; BYTE $0x31 /* RDTSC, result in AX/DX (lo/hi) */ #define RDMSR BYTE $0x0F; BYTE $0x32 /* RDMSR, result in AX/DX (lo/hi) */ #define BSWAP(r) BYTE $0x0F; BYTE $(0xC8+r) /* BSWAP AX, 486+ only */ /*#define ScreenBlank*/ /*#define ResetDiscs*/ TEXT origin(SB), $0 /* * This part of l.s is used only in the boot kernel. * It assumes that we are in real address mode, i.e., * that we look like an 8086. * * Make sure the segments are reasonable. * If we were started directly from the BIOS * (i.e. no MS-DOS) then DS may not be * right. */ MOVW CS, AX MOVW AX, DS #ifndef ScreenBlank /* * Get the current video mode. If it isn't mode 3, * set text mode 3. * Well, no. Windows95 won't co-operate here so we have * to explicitly set mode 3. */ XORL AX, AX MOVB $0x0F, AH INT $0x10 /* get current video mode in AL */ CMPB AL, $03 JEQ resetdiscs #endif /* !ScreenBlank */ XORL AX, AX MOVB $0x03, AL INT $0x10 /* set video mode in AL */ resetdiscs: #ifdef ResetDiscs XORL AX, AX /* reset disc system */ XORL DX, DX MOVB $0x80, DL INT $0x13 #endif /* ResetDiscs */ _real: /* * turn off interrupts */ CLI /* * goto protected mode */ /* MOVL loadgdtptr(SB),GDTR /**/ BYTE $0x0f BYTE $0x01 BYTE $0x16 WORD $loadgdtptr(SB) LWI(1, rAX) /* MOV AX,MSW */ BYTE $0x0F; BYTE $0x01; BYTE $0xF0 /* * clear prefetch queue (weird code to avoid optimizations) */ /* JMP .+2 */ BYTE $0xEB BYTE $0x00 /* * set all segs */ /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/ BYTE $0xc7 BYTE $0xc0 WORD $SELECTOR(1, SELGDT, 0) MOVW AX,DS MOVW AX,SS MOVW AX,ES MOVW AX,FS MOVW AX,GS /* JMPFAR SELECTOR(2, SELGDT, 0):$main(SB) /**/ BYTE $0x66 BYTE $0xEA LONG $_main(SB) WORD $SELECTOR(2, SELGDT, 0) /* * pointer to initial gdt */ TEXT loadgdtptr(SB),$0 WORD $(4*8) LONG $loadgdt(SB) /* * gdt to get us to 32-bit/segmented/unpaged mode */ TEXT loadgdt(SB),$0 /* null descriptor */ LONG $0 LONG $0 /* data segment descriptor for 4 gigabytes (PL 0) */ LONG $(0xFFFF) LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) /* exec segment descriptor for 4 gigabytes (PL 0) */ LONG $(0xFFFF) LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) /* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */ LONG $(0xFFFF) LONG $(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) /* * output a byte */ TEXT outb(SB),$0 MOVL p+0(FP),DX MOVL b+4(FP),AX OUTB RET /* * input a byte */ TEXT inb(SB),$0 MOVL p+0(FP),DX XORL AX,AX INB RET