code: 9ferno

ref: b548687a8ed1d0a159c9d3f3f921d93bbb56908e
dir: /os/boot/pc/pbs.s/

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

#define RELOC 0x7c00

TEXT _magic(SB), $0
	BYTE $0xEB; BYTE $0x58;		/* jmp .+ 0x58  (_start0x5A) */
	BYTE $0x90			/* nop */
TEXT _version(SB), $0
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
TEXT _sectsize(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _clustsize(SB), $0
	BYTE $0x00
TEXT _nresrv(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _nfats(SB), $0
	BYTE $0x00
TEXT _rootsize(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _volsize(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _mediadesc(SB), $0
	BYTE $0x00
TEXT _fatsize(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _trksize(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _nheads(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _nhiddenlo(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _nhiddenhi(SB), $0
	BYTE $0x00; BYTE $0x00;
TEXT _bigvolsize(SB), $0
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
/* FAT32 structure, starting @0x24 */
TEXT _fatsz32lo(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _fatsz32hi(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _extflags(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _fsver(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _rootclust(SB), $0
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
TEXT _fsinfo(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _bkboot(SB), $0
	BYTE $0x00; BYTE $0x00
TEXT _reserved0(SB), $0
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
TEXT _driveno(SB), $0
	BYTE $0x00
TEXT _reserved1(SB), $0
	BYTE $0x00
TEXT _bootsig(SB), $0
	BYTE $0x00
TEXT _volid(SB), $0
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
TEXT _label(SB), $0
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00
	BYTE $0x00; BYTE $0x00; BYTE $0x00
TEXT _type(SB), $0
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00;
	BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00

_start0x5A:
	CLI
	CLR(rAX)
	MTSR(rAX, rSS)			/* 0000 -> rSS */
	MTSR(rAX, rDS)			/* 0000 -> rDS, source segment */
	MTSR(rAX, rES)

	LWI(0x100, rCX)
	LWI(RELOC, rSI)
	MW(rSI, rSP)
	LWI(_magic(SB), rDI)
	CLD
	REP; MOVSL			/* MOV DS:[(E)SI] -> ES:[(E)DI] */

	MW(rSP, rBP)

	PUSHR(rCX)
	PUSHI(start16(SB))
	BYTE $0xCB			/* FAR RET */

TEXT start16(SB), $0
	STI

	LWI(hello(SB), rSI)
	CALL16(print16(SB))

	STB(rDL, _driveno(SB))

	CLR(rDX)
	LW(_fatsize(SB), rAX)
	CLR(rCX)
	LB(_nfats(SB), rCL)
	MUL(rCX)
	OR(rAX, rAX)
	JNE _fatszok	/* zero? it's FAT32 */

	LW(_fatsz32hi(SB), rBX)
	IMUL(rCX, rBX)
	LW(_fatsz32lo(SB), rAX)
	MUL(rCX)
	ADD(rBX, rDX)

_fatszok:
	LW(_nhiddenlo(SB), rCX)
	ADD(rCX, rAX)
	LW(_nhiddenhi(SB), rCX)
	ADC(rCX, rDX)

	CLR(rBX)
	LW(_nresrv(SB), rCX)
	ADD(rCX, rAX)
	ADC(rDX, rBX)

	SW(rAX, _volid(SB))	/* save for later use */
	SW(rBX, _volid+2(SB))

	PUSHR(rBP)
	LW(_sectsize(SB), rCX)
	SUB(rCX, rSP)
	MW(rSP, rBP)
	MW(rSP, rSI)

_nextsect:
	CALL16(readsect16(SB))
	LW(_sectsize(SB), rCX)
	SHRI(5, rCX)

_nextdir:
	PUSHR(rCX)
	PUSHR(rSI)			/* save for later if it matches */
	LWI(bootname(SB), rDI)
	LW(bootnamelen(SB), rCX)
	CLD
	REP
	CMPSB
	POPR(rSI)
	POPR(rCX)
	JEQ _found
	ADDI(0x20, rSI)	
	LOOP _nextdir
	ADDI(1, rAX)
	ADC(rCX, rBX)
	JMP _nextsect

_found:
	CLR(rBX)
	LW(_rootsize(SB), rAX)		/* calculate and save Xrootsz */
	LWI(0x20, rCX)
	MUL(rCX)
	LW(_sectsize(SB), rCX)
	DEC(rCX)
	ADD(rCX, rAX)
	ADC(rBX, rDX)
	INC(rCX)
	DIV(rCX)
	PUSHR(rAX)			/* Xrootsz */

	CLR(rCX)
	LXW(0x1a, xSI, rAX)		/* start cluster low */
	LXW(0x14, xSI, rBX)		/* start cluster high */
	SUBI(2, rAX)			/* cluster -= 2 */
	SBB(rCX, rBX)

	LB(_clustsize(SB), rCL)		/* convert to sectors (AX:DX) */
	IMUL(rCX, rBX)
	MUL(rCX)
	ADD(rBX, rDX)

	LW(_volid(SB), rCX)		/* Xrootlo */
	ADD(rCX, rAX)
	LW(_volid+2(SB), rCX)		/* Xroothi */
	ADC(rCX, rDX)

	CLR(rBX)
	POPR(rCX)			/* Xrootsz */
	ADD(rCX, rAX)
	ADC(rBX, rDX)

	PUSHR(rAX)			/* calculate how many sectors to read (CX) */
	PUSHR(rDX)
	LXW(0x1c, xSI, rAX)
	LXW(0x1e, xSI, rDX)
	LW(_sectsize(SB), rCX)
	DEC(rCX)
	ADD(rCX, rAX)
	ADC(rBX, rDX)
	INC(rCX)
	DIV(rCX)
	MW(rAX, rCX)
	POPR(rBX)
	POPR(rAX)

	LWI(RELOC, rSI)
	PUSHR(rSI)	/* entry */

_loadnext:
	CALL16(readsect16(SB))

	LW(_sectsize(SB), rDX)
	ADD(rDX, rSI)

	CLR(rDX)
	ADDI(1, rAX)
	ADC(rDX, rBX)

	LOOP _loadnext

	LWI(ok(SB), rSI)
	CALL16(print16(SB))

	LB(_driveno(SB), rDL)
	CLI
	RET

TEXT print16(SB), $0
	PUSHA
	CLR(rBX)
_printnext:
	LODSB
	ORB(rAL, rAL)
	JEQ _printret
	LBI(0x0E, rAH)
	BIOSCALL(0x10)
	JMP _printnext
_printret:
	POPA
	RET

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

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

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

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

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

	MW(rSP, rSI)
	LB(_driveno(SB), rDL)
	LWI(0x4200, rAX)
	BIOSCALL(0x13)
	JCC _readok
	LWI((0x0E00|'!'), rAX)
	BIOSCALL(0x10)
	ADDI(0x10, rSP)
	POPA
	JMP _retry
_readok:
	LWI((0x0E00|'.'), rAX)
	BIOSCALL(0x10)
	ADDI(0x10, rSP)
	POPA
	RET

TEXT bootnamelen(SB), $0
	WORD $8
TEXT bootname(SB), $0
	BYTE $'9'; BYTE $'B'; BYTE $'O'; BYTE $'O';
	BYTE $'T'; BYTE $'F'; BYTE $'A'; BYTE $'T';
	BYTE $0

TEXT hello(SB), $0
	BYTE $'p'; BYTE $'b'; BYTE $'s'; BYTE $0
TEXT ok(SB), $0
	BYTE $'o'; BYTE $'k'; BYTE $'\r'; BYTE $'\n';
	BYTE $0