;;  sample of extIPL construction kit
;;
;;  caps-fd.asm:
;; 	multi OS boot utility for IBM PC/AT and compatibles
;;					Auther: takamiti@tsden.org
;;

NULL		equ 00h
BELL		equ 07h
CR		equ 0Dh
LF		equ 0Ah
ENTER_SCAN	equ 01Ch
EXEC_KEY	equ 4F00h		; END key

CAPS_BIT	equ 40h
NUM_BIT		equ 20h
SCROL_BIT	equ 10h
ALT_BIT		equ 08h
CTRL_BIT	equ 04h
SHFT_BIT	equ 03h

VIDEOBIOS	equ 10h
DISKBIOS	equ 13h
KEYBIOS		equ 16h

BIOS_LOC	equ 7C00h
BOOT_LOC	equ 0600h
IPLMAGICVAL	equ 0AA55h

PART_TAB	equ BOOT_LOC + 01BEh

magicval	equ BOOT_LOC + 01FEh
kbd_stat	equ 0417h
fd_stat		equ 043Fh
nr_hdds		equ 0475h


DGROUP		group	_DATA, _BSS
		assume	cs:_TEXT, ds:DGROUP

_DATA		segment word public 'DATA'
_DATA		ends

_BSS		segment word public 'BSS'
_BSS		ends

_TEXT		segment byte public 'CODE'
		assume cs:_TEXT

		org	0

ipl		proc	near
		cli
		xor	ax,ax
		mov	ss,ax
		mov	es,ax
		mov	ds,ax
		mov	sp,BIOS_LOC
		mov	si,sp
		sti
		cld
		mov	di,BOOT_LOC
		mov	cx,256
		repnz	movsw
		mov	ax,offset ipl_start + BOOT_LOC
		push	ax
		ret

ipl_start:	push	ax
		mov	dx,80h
		call	gettable
		mov	al,90h
		mov	byte ptr DGROUP:[fdhook + BOOT_LOC],al	; ^^;
		pop	ax

		mov	ah,02h
		int	KEYBIOS
		and	al,CAPS_BIT
		jnz	chktable

		mov	cx,4
		mov	di,PART_TAB
		mov	dh,30h
auto1:		inc	dh
		test	byte ptr DGROUP:[di],80h
		jnz	boot1
		add	di,16
		loop	auto1

chktable:	call	initCRT
		mov	cx,4
		mov	di,PART_TAB
		mov	dx,3130h
		mov	si,offset guidmsg + BOOT_LOC
		call	putstr
chtabloop:	inc	dx
		test	byte ptr [di],80h
		jz	prntab
		mov	dh,dl
		and	byte ptr [di],7Fh
prntab:		mov	ah,2
		mov	al,dl
		call	putSPC
		mov	bl,[di+4]
		or	bl,bl
		jz	nosys
		mov	ax,0673h
		call	putSPC
		xchg	ax,bx
		call	hex2
nosys:		call	putCRLF
		add	di,16
		loop	chtabloop
		call	putCRLF
retry:		mov	si,offset selmsg + BOOT_LOC
		call	putstr
keyin:		mov	al,dh
		call	putch
keyin1:		xor	ah,ah
		int	KEYBIOS
		cmp	al,30h
		jc	selok
		cmp	al,34h
		ja	keyin1
		mov	dh,al		; save
		jmp	short retry

selok:		cmp	ax,EXEC_KEY
		jz	boot1
		cmp	ah,ENTER_SCAN		; scan code
		jnz	keyin1
boot1:		mov	di,dx
		sub	dh,30h
		jz	switchHD

		xchg	ax,bp
		dec	dh
		mov	al,16
		mul	dh
		add	ax,PART_TAB
		xchg	ax,si			; partition table address
		cmp	byte ptr [si+4],0
		jz	wrongsys
		mov	dx,[si]
		mov	dl,byte ptr DGROUP:[drive + BOOT_LOC]
		add	dl,50h
		mov	cx,[si+2]
		push	bp
		push	di
		call	HDread
		pop	di
		pop	ax
		cmp	al,LF			; <Ctrl>+<Enter>
		jz	execloader
		cmp	word ptr [bx + 1feh],IPLMAGICVAL
		jz	execloader
wrongsys:	push	ax
		mov	al,BELL
		call	putch
		mov	dx,di
		pop	ax
		cmp	ax,offset ipl_start + BOOT_LOC
		jnz	retry
		jmp	chktable

execloader:	mov	byte ptr [si],dl
		call	initCRT
		db	0EAh
		dw	BIOS_LOC
		dw	0		; jmp	far BIOS_LOC

; read IPL sector from next HD 
switchHD:	mov	al,byte ptr DGROUP:[drive + BOOT_LOC]
		sub	al,30h
		inc	ax
		cmp	al,byte ptr DGROUP:[nr_hdds]
		jc	swhd1
		xor	ax,ax
swhd1:		push	ax
		add	al,30h
		mov	byte ptr DGROUP:[drive + BOOT_LOC],al
		pop	dx
		or	dl,80h
		xor	dh,dh
gettable:	mov	cx,1
		call	HDread
		mov	si,BIOS_LOC + 01BEh
		mov	di,PART_TAB
		mov	cx,33
		repnz	movsw
fdhook:		ret
		jmp	chktable

HDread:		mov	bx,BIOS_LOC		; load address[0000:7C00]
		mov	di,8
HDretry:	mov	ax,0201h		; read a sector in BIOS_LOC
		int	DISKBIOS
		jnc	exit
		dec	di
		jns	HDretry
error:		push	ax		; error starus
		mov	ax,033fh
		call	putSPC
		pop	ax
		mov	al,ah
		call	hex2
		hlt
		jmp	$

putspace:	mov	al,20h
putch:		push	bx
		mov	ah,14
		mov	bx,1
		int	VIDEOBIOS
		pop	bx
exit:		ret

putSPC:		push	ax
		push	cx
		mov	cl,ah
spcloop:	call	putspace
		loop	spcloop
		pop	cx
		pop	ax
		jmp	short putch

putCRLF:	mov	si,offset crlfmsg + BOOT_LOC
putstr:		lodsb
		or	al,al
		jz	exit
		call	putch
		jmp	short putstr
hex2:		push	ax
		push	cx
		mov	cl,4
		shr	al,cl
		pop	cx
		call	hex1
		pop	ax
hex1:		and	al,0Fh
		add	al,30h
		cmp	al,3Ah
		jc	prhex
		add	al,7
prhex:		jmp	short putch

initCRT:	mov	ax,2
		int	VIDEOBIOS
		ret

guidmsg:	db	"Part.  System"
crlfmsg:	db	CR, LF, NULL
selmsg:		db	CR
		db	"Boot #"
drive:		db	30h
		db	":"
		db	NULL
is1st:		db	0
		db	"(C)takamiti@tsden.org"
		db	30 dup(0ffh)
ipl		endp

_TEXT		ends

		end
