909 lines · 14.3 KB · Assembly
RawDownload
#include "x16.h"#include "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) */ #ifdef PXE#define PDB		0x90000		/* temporary page tables (24KB) */#else#define PDB		0x08000#endif PXE #define NoScreenBlank	1/*#define ResetDiscs	1*/ 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 #ifdef NoScreenBlank	/*	 * 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	sayhello#endif /* NoScreenBlank */	XORL	AX, AX	MOVB	$0x03, AL	INT	$0x10			/* set video mode in AL */ sayhello:	LWI(hello(SB), rSI)	CALL16(biosputs(SB)) #ifdef ResetDiscs	XORL	AX, AX			/* reset disc system */	XORL	DX, DX	MOVB	$0x80, DL	INT	$0x13#endif /* ResetDiscs */ #ifdef DOTCOM/* *	relocate everything to a half meg and jump there *	- looks weird because it is being assembled by a 32 bit *	  assembler for a 16 bit world * *	only b.com does this - not 9load */	MOVL	$0,BX	INCL	BX	SHLL	$15,BX	MOVL	BX,CX	MOVW	BX,ES	MOVL	$0,SI	MOVL	SI,DI	CLD	REP	MOVSL 	/*	 * Jump to the copied image;	 * fix up the DS for the new location.	 */	FARJUMP16(0x8000, _start8000(SB)) TEXT _start8000(SB), $0	MFSR(rCS, rAX)			/* fix up DS, ES (0x8000) */	MTSR(rAX, rDS)	MTSR(rAX, rES) 	/*	 * If we are already in protected mode, have to get back	 * to real mode before trying any privileged operations	 * (like going into protected mode...).	 * Try to reset with a restart vector.	 */	MFCR(rCR0, rAX)			/* are we in protected mode? */	ANDI(0x0001, rAX)	JEQ	_real 	CLR(rBX)	MTSR(rBX, rES) 	LWI(0x0467, rBX)		/* reset entry point */	LWI(_start8000(SB), rAX)	/* offset within segment */	BYTE	$0x26	BYTE	$0x89	BYTE	$0x07			/* MOVW	AX, ES:[BX] */	LBI(0x69, rBL)	MFSR(rCS, rAX)			/* segment */	BYTE	$0x26	BYTE	$0x89	BYTE	$0x07			/* MOVW	AX, ES:[BX] */ 	CLR(rDX)	OUTPORTB(0x70, 0x8F)	OUTPORTB(0x71, 0x0A) 	FARJUMP16(0xFFFF, 0x0000)		/* reset */#endif /* DOTCOM */ _real: /* *	do things that need to be done in real mode. *	the results get written to CONFADDR (0x1200) *	in a series of <4-byte-magic-number><block-of-data> *	the data length is dependent on the magic number. * *	this gets parsed by conf.c:/^readlsconf * *	N.B. CALL16 kills rDI, so we can't call anything. */	LWI(0x0000, rAX)	MTSR(rAX, rES)#include "real820.s" 	LWI(0x1200, rDI) /* *	turn off interrupts */	CLI /* *	detect APM1.2 bios support */	/* save DI */	SW(rDI, rock(SB)) 	/* disconnect anyone else */	LWI(0x5304, rAX)	LWI(0x0000, rBX)	INT $0x15 	/* connect */	CLC	LWI(0x5303, rAX)	LWI(0x0000, rBX)	INT $0x15	CLI	/* apm put interrupts back? */ 	JC noapm 	OPSIZE; PUSHR(rSI)	OPSIZE; PUSHR(rBX)	PUSHR(rDI)	PUSHR(rDX)	PUSHR(rCX)	PUSHR(rAX) 	/* put DI, ES back */	LW(rock(SB), rDI)	LWI(0x0000, rAX)	MTSR(rAX, rES) 	/*	 * write APM data.  first four bytes are APM\0.	 */	LWI(0x5041, rAX)	STOSW 	LWI(0x004d, rAX)	STOSW 	LWI(8, rCX)apmmove:	POPR(rAX)	STOSW	LOOP apmmove noapm: /* *	end of real mode hacks: write terminator, put ES back. */	LWI(0x0000, rAX)	STOSW	STOSW 	MFSR(rCS, rAX)			/* fix up ES (0x8000) */	MTSR(rAX, rES) /* * 	goto protected mode *//*	MOVL	tgdtptr(SB),GDTR /**/	 BYTE	$0x0f	 BYTE	$0x01	 BYTE	$0x16	 WORD	$tgdtptr(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):$mode32bit(SB) /**/	 BYTE	$0x66	 BYTE	$0xEA	 LONG	$mode32bit-KZERO(SB)	 WORD	$SELECTOR(2, SELGDT, 0) TEXT	mode32bit(SB),$0	/*	 *  make a bottom level page table page that maps the first	 *  16 meg of physical memory	 */	MOVL	$PDB, DI			/* clear 6 pages for the tables etc. */	XORL	AX, AX	MOVL	$(6*BY2PG), CX	SHRL	$2, CX 	CLD	REP;	STOSL 	MOVL	$PDB, AX		/* phys addr of temporary page table */	MOVL	$(4*1024),CX		/* pte's per page */	MOVL	$((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BXsetpte:	MOVL	BX,-4(AX)(CX*4)	SUBL	$(1<<PGSHIFT),BX	LOOP	setpte 	/*	 *  make a top level page table page that maps the first	 *  16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg	 */	MOVL	AX,BX	ADDL	$(4*BY2PG),AX	ADDL	$(PTEVALID|PTEKERNEL|PTEWRITE),BX	MOVL	BX,0(AX)	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)	ADDL	$BY2PG,BX	MOVL	BX,4(AX)	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)	ADDL	$BY2PG,BX	MOVL	BX,8(AX)	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)	ADDL	$BY2PG,BX	MOVL	BX,12(AX)	MOVL	BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX) 	/*	 *  point processor to top level page & turn on paging	 *	 *  this produces the apparently harmless "VMX|F(125):468 Dis 0x0:0x0"	 *  message in the VMware log.	 */	MOVL	AX,CR3	MOVL	CR0,AX	ORL	$0X80000000,AX	MOVL	AX,CR0 	/*	 *  use a jump to an absolute location to get the PC into	 *  KZERO.	 */	LEAL	tokzero(SB),AX	JMP*	AX /* * When we load 9load from DOS, the bootstrap jumps * to the instruction right after `JUMP', which gets * us into kzero. * * The name prevents it from being optimized away. */TEXT jumplabel(SB), $0	BYTE $'J'; BYTE $'U'; BYTE $'M'; BYTE $'P' 	LEAL	tokzero(SB),AX	JMP*	AX TEXT	tokzero(SB),$0	/*	 * Clear BSS	 */	LEAL	edata(SB),SI	MOVL	SI,DI	ADDL	$4,DI	MOVL	$0,AX	MOVL	AX,(SI)	LEAL	end(SB),CX	SUBL	DI,CX	SHRL	$2,CX	CLD	REP	MOVSL 	/*	 *  stack and mach	 */	MOVL	$mach0(SB),SP	MOVL	SP,m(SB)	MOVL	$0,0(SP)	ADDL	$(MACHSIZE-4),SP	/* start stack above machine struct */ 	CALL	main(SB) loop:	JMP	loop GLOBL	mach0+0(SB), $MACHSIZEGLOBL	m(SB), $4 /* *  gdt to get us to 32-bit/segmented/unpaged mode */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) 	/* exec segment descriptor for 4 gigabytes (PL 0) 16-bit */	LONG	$(0xFFFF)	LONG	$(SEGG|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) /* *  pointer to initial gdt */TEXT	tgdtptr(SB),$0	WORD	$(4*8)	LONG	$tgdt-KZERO(SB) /* * Output a string to the display. * String argument is in rSI. */TEXT biosputs(SB), $0	PUSHA	CLR(rBX)_BIOSputs:	LODSB	ORB(rAL, rAL)	JEQ _BIOSputsret 	LBI(0x0E, rAH)	BIOSCALL(0x10)	JMP _BIOSputs _BIOSputsret:	POPA	RET /* *  input a byte */TEXT	inb(SB),$0 	MOVL	p+0(FP),DX	XORL	AX,AX	INB	RET /* * input a short from a port */TEXT	ins(SB), $0 	MOVL	p+0(FP), DX	XORL	AX, AX	OPSIZE; INL	RET /* * input a long from a port */TEXT	inl(SB), $0 	MOVL	p+0(FP), DX	XORL	AX, AX	INL	RET /* *  output a byte */TEXT	outb(SB),$0 	MOVL	p+0(FP),DX	MOVL	b+4(FP),AX	OUTB	RET /* * output a short to a port */TEXT	outs(SB), $0	MOVL	p+0(FP), DX	MOVL	s+4(FP), AX	OPSIZE; OUTL	RET /* * output a long to a port */TEXT	outl(SB), $0	MOVL	p+0(FP), DX	MOVL	s+4(FP), AX	OUTL	RET /* *  input a string of bytes from a port */TEXT	insb(SB),$0 	MOVL	p+0(FP),DX	MOVL	a+4(FP),DI	MOVL	c+8(FP),CX	CLD; REP; INSB	RET /* *  input a string of shorts from a port */TEXT	inss(SB),$0	MOVL	p+0(FP),DX	MOVL	a+4(FP),DI	MOVL	c+8(FP),CX	CLD	REP; OPSIZE; INSL	RET /* *  output a string of bytes to a port */TEXT	outsb(SB),$0 	MOVL	p+0(FP),DX	MOVL	a+4(FP),SI	MOVL	c+8(FP),CX	CLD; REP; OUTSB	RET /* *  output a string of shorts to a port */TEXT	outss(SB),$0	MOVL	p+0(FP),DX	MOVL	a+4(FP),SI	MOVL	c+8(FP),CX	CLD	REP; OPSIZE; OUTSL	RET /* *  input a string of longs from a port */TEXT	insl(SB),$0 	MOVL	p+0(FP),DX	MOVL	a+4(FP),DI

Lines 1–500 of 909.