/*
* 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
|