code: plan9front

ref: df04ea8d6c2e1e75307a77f2b086a836f480ab72
dir: /sys/src/boot/pc/l.s/

View raw version
#include "x16.h"
#include "mem.h"

#undef ORB

#define DATA32SEL SELECTOR(1, SELGDT, 0)
#define EXEC32SEL SELECTOR(2, SELGDT, 0)
#define DATA16SEL SELECTOR(3, SELGDT, 0)
#define EXEC16SEL SELECTOR(4, SELGDT, 0)

#define SEGSS BYTE $0x36
#define SEGES BYTE $0x26
#define FARRET BYTE $0xCB

TEXT origin(SB), $0
	CLI
	CLR(rCX)
	MTSR(rCX, rSS)
	OPSIZE; MOVL $origin(SB), SP
	PUSHA
	OPSIZE; ADSIZE; PUSHL SP
	OPSIZE; ADSIZE; PUSHL CX
	PUSHI(start(SB))

TEXT pmode32(SB), $0
	CLI

	/* get return pc */
	POPR(rDI)

	/* make sure stack is at 0000: */
	CLR(rCX)
	MTSR(rCX, rSS)
	OPSIZE; ANDL $0xFFFF, SP

	/* convert 16-bit return pc to far pointer */
	PUSHI(EXEC32SEL)
	PUSHR(rDI)

	/* load gdt */
	SEGSS; LGDT(tgdtptr(SB))

	/* enable protected mode */
	MFCR(rCR0, rCX)
	ORB $1, CL
	MTCR(rCX, rCR0)

	/* flush */
	FARJUMP16(EXEC16SEL, pmode32flush(SB));
TEXT pmode32flush(SB), $0

	/* load 32-bit protected mode data selector */
	LWI(DATA32SEL, rCX)

_segret:
	/* load all data segments */
	MTSR(rCX, rDS)
	MTSR(rCX, rES)
	MTSR(rCX, rFS)
	MTSR(rCX, rGS)
	MTSR(rCX, rSS)
	FARRET

TEXT rmode16(SB), $0
	/* setup farret to rmode16x */
	PUSHL $EXEC16SEL
	PUSHL $rmode16x(SB)

	/* load 16-bit protected mode data selector */
	MOVL $DATA16SEL, CX
	JMP _segret

TEXT rmode16x(SB), $0
	/* disable protected mode */
	MFCR(rCR0, rCX)
	ANDB $0xfe, CL
	MTCR(rCX, rCR0)

	/* flush */
	FARJUMP16(0, rmode16flush(SB));
TEXT rmode16flush(SB), $0

	/*
	 * load 16-bit realmode data segment 0000: and
	 * return to 32 bit return pc interpreted
	 * as 16 bit far pointer.
	 */
	CLR(rCX)
	JMP _segret

TEXT tgdt(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)

	/* data segment descriptor for (PL 0) 16-bit */
	LONG $(0xFFFF)
	LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)

	/* exec segment descriptor for (PL 0) 16-bit */
	LONG $(0xFFFF)
	LONG $((0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)

TEXT tgdtptr(SB), $0 
         WORD $(5*8) 
         LONG $tgdt(SB)

TEXT jump(SB), $0
	MOVL 4(SP), AX
	JMP *AX

TEXT halt(SB), $0
_halt:
	JMP _halt

TEXT kbdgetc(SB), $0
	CALL rmode16(SB)
	STI
	MOVB $0x01, AH
	BIOSCALL(0x16)
	JNZ _gotkey
	CLR(rAX)
	JMP _pret32
_gotkey:
	CLR(rAX)
	BIOSCALL(0x16)
	JMP _pret32
	
TEXT cgaputc(SB), $0
	MOVL 4(SP),AX
	CALL rmode16(SB)
	STI
	MOVB $0x0E, AH
	BIOSCALL(0x10)
_pret32:
	CALL16(pmode32(SB))
	ANDL $0xFFFF, AX
	RET

TEXT usleep(SB), $0
	MOVL t+4(SP), AX
	PUSHL AX
	CALL rmode16(SB)
	STI
	POPR(rDX)
	POPR(rCX)
	MOVB $0x86, AH
	BIOSCALL(0x15)
	JMP _pret32

#ifdef PXE

TEXT pxeinit(SB), $0
	CALL rmode16(SB)

	/* get pxe env structure in ES:BX */
	LWI(0x5650, rAX)
	BIOSCALL(0x1A)
	JC _pret32

	/* !PXE or PXEENV+ signature */
	SEGES; LXW(0, xBX, rAX)
	CMPI((('!'<<0)|('P'<<8)), rAX)
	JEQ _getentry
	CMPI((('P'<<0)|('X'<<8)), rAX)
	JNE _pret32

	SEGES; LXW(0x2A, xBX, rAX)
	SEGES; LXW(0x28, xBX, rBX)
	MTSR(rAX, rES)

_getentry:
	SEGES; LXW(0x12, xBX, rAX)
	SW(rAX, pxepseg(SB))
	SEGES; LXW(0x10, xBX, rAX)
	SW(rAX, pxepoff(SB))
	CLR(rAX)
	JMP _pret32

TEXT pxecallret(SB), $0
	ADDI(6, rSP)
	JMP _pret32

TEXT pxecall(SB), $0
	MOVL op+4(SP),AX
	MOVL buf+8(SP),SI
	CALL rmode16(SB)

	CLR(rCX)
	PUSHR(rCX)
	PUSHR(rSI)

	/* opcode */
	PUSHR(rAX)

	/* farcall */
	PUSHR(rCX)
	PUSHI(pxecallret(SB))

	LW(pxepseg(SB), rAX)
	PUSHR(rAX)
	LW(pxepoff(SB), rAX)
	PUSHR(rAX)

	STI

	CLR(rAX)
	CLR(rBX)
	CLR(rCX)
	CLR(rDX)
	CLR(rDI)
	CLR(rSI)
	FARRET

TEXT pxepseg(SB), $0
	WORD $0
TEXT pxepoff(SB), $0
	WORD $0

#else /* PXE */

/*
 * in:
 *	DL drive
 *	AX:BX lba32,
 *	0000:SI buffer
 */
TEXT readsect16(SB), $0
	PUSHA
	CLR(rCX)

	PUSHR(rCX)		/* qword lba */
	PUSHR(rCX)
	PUSHR(rBX)
	PUSHR(rAX)

	PUSHR(rCX)		/* dword buffer */
	PUSHR(rSI)

	INC(rCX)
	PUSHR(rCX)		/* word # of sectors */

	PUSHI(0x0010)		/* byte reserved, byte packet size */

	MW(rSP, rSI)
	LWI(0x4200, rAX)
	BIOSCALL(0x13)
	JCC _readok
	ADDI(0x10, rSP)
	POPA
	CLR(rAX)
	DEC(rAX)
	RET
_readok:
	ADDI(0x10, rSP)
	POPA
	CLR(rAX)
	RET

TEXT readsect(SB), $0
	MOVL 4(SP), DX
	MOVW 8(SP), AX
	MOVW 10(SP), BX
	MOVL 12(SP), SI 
	CALL rmode16(SB)
	STI
	CALL16(readsect16(SB))
	CALL16(pmode32(SB))
	ANDL $0xFFFF, AX
	RET

#endif

#ifdef ISO

TEXT bootname(SB), $0
	BYTE $'3'; BYTE $'8'; BYTE $'6'; BYTE $'/';
	BYTE $'9'; BYTE $'b'; BYTE $'o'; BYTE $'o';
	BYTE $'t'; BYTE $'i'; BYTE $'s'; BYTE $'o';
	BYTE $0

#endif

TEXT uart(SB), $0
	BYTE $0xff

TEXT hex(SB), $0
	BYTE $'0'; BYTE $'1'; BYTE $'2'; BYTE $'3';
	BYTE $'4'; BYTE $'5'; BYTE $'6'; BYTE $'7';
	BYTE $'8'; BYTE $'9'; BYTE $'a'; BYTE $'b';
	BYTE $'c'; BYTE $'d'; BYTE $'e'; BYTE $'f'