;;  pollux.asm : Extended-IPL/Gemini, 1st stage.
;;
;;	multi OS boot utility for IBM PC/AT and compatibles, Since 1993
;;
;;					Auther : takamiti@tsden.org
;;					last update : 2001/07/01
;;
;;	This program requires NASM - "The Netwide Assembler"
;;		(http://www.web-sites.co.uk/nasm/)
;;
;;  $Id: pollux.asm,v 1.3 2001/07/02 15:35:12 takamiti Exp $
;;

%include	"biosdef.inc"
%include	"gemini.inc"

		bits	16
		section .text

;=======================================================
;		pollux
;=======================================================
%ifdef COM_DEBUG
%include	"debugmcr.inc"
		org	0x100		;; BOOT_LOC
		xor	dx,dx
		jmp	short boot_active
%else
		org	0x600
%endif

lba_packet	equ	BOOT_LOC + SECTOR_SIZE
offset		equ	lba_packet + 8

		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
		jmp	start - BIOS_LOC + BOOT_LOC


%ifndef TAURUS
%include	"gemini.key"

start:		mov	ax,0x0211
		mov	bx,BOOT_LOC + SECTOR_SIZE
		mov	cx,2
%ifdef FDTEST
		xor	dx,dx
%else
		mov	dx,0x0080
%endif
		int	DISKBIOS
		jc	dskerr_relay
		mov	di,bx
		mov	si,extipl_key
		mov	cx,extipl_key_ln
		rep cmpsb
		jnz	boot_active
		call	di
%else
start:
%endif

boot_active:	mov	bp,BOOT_LOC + PART_TBL_OFS
		test	dl,0x80
		jnz	dsk_probe
		mov	ax,0x0201		;; legacy access
		mov	bx,BIOS_LOC
		mov	cx,1
		mov	dx,0x0080
		int	DISKBIOS
		jnc	mv_tbl
dskerr_relay:	jmp	diskerr_hlt

mv_tbl:		mov	si,BIOS_LOC + PART_TBL_OFS
		mov	di,bp
		mov	cx,32
		rep movsw

dsk_probe:	mov	bx,0x55aa
		mov	ah,0x41
		int	DISKBIOS
		jc	chk_activflg
		and	cl,1
		jz	chk_activflg
		mov	word [mkParam_func],mk_lbaParam

chk_activflg:	call	disk_reset			;; safe for very old BIOS
		xor	ax,ax				;; init offset value
		mov	di,offset
		stosw
		stosw
		stosw
		stosw
search_flag:	mov	cx,4
search_loop:	mov	al,[bp + 4]
		or	al,al
		jz	next_part
		test	byte [bp],0x80
		jnz	foundit
next_part:	add	bp,byte MBR_PART_SIZE
		loop	search_loop
		mov	si,msg_NoActive
		jmp	short hlt_relay

foundit:	cmp	al,EXTDOS_PART
		jz	dig_slice
		cmp	al,EXTLINUX_PART
		jz	dig_slice
		cmp	al,EXTDOSLBA_PART
		jnz	boot
dig_slice:	mov	si,[base_slice]
		or	si,si
		jz	dig_setbase
		add	si,byte 8
		mov	di,offset
		lodsw
		stosw
		lodsw
		stosw
		xor	ax,ax
		stosw
		stosw
		jmp	short dig_rd
dig_setbase:	mov	[base_slice],bp
dig_rd:		call	disk_read
dig_try_nxt:	mov	bp,BIOS_LOC + PART_TBL_OFS
		jmp	short search_flag

boot:		call	disk_read
chk_aa55:	cmp	word [bx + IPL_MAGIC_OFS],IPL_MAGIC
		jnz	corrupt_ipl
		cmp	word [bx],0
		jnz	final
corrupt_ipl:	mov	si,msg_CorruptIPL
hlt_relay:	jmp	halt_msg

final:		mov	si,[base_slice]
		or	si,si
		jnz	kickOS
		mov	si,bp

kickOS:
%ifdef COM_DEBUG
		DebugDump 0,si,1
		DebugDump 0,bx,16
		ReturnDos
%else
		jmp	bx			;; BIOS_LOC
%endif


;; =====================================================
;;		sub-routines
;; =====================================================


;;	bp = param address
mk_legacyParam:	mov	dx,[bp]
		mov	cx,[bp + 2]
		mov	ax,0x0201
		ret

mk_lbaParam:	mov	di,lba_packet
		push	di			;; save packet address
		mov	ax,16
		stosw				;; size of packet
		mov	al,1
		stosw				;; blocks of transfer
		mov	ax,bx
		stosw				;; transfer buffer-Lo
		mov	ax,ds
		stosw				;; transfer buffer-Hi
		mov	si,di
		lodsw
		add	ax,[bp + 8]
		stosw				;; sector address(Lo-l)
		lodsw
		adc	ax,[bp + 10]
		stosw				;; sector address(Lo-h)
		lodsw
		adc	ax,0
		stosw				;; sector address(Hi-l)
		xor	ax,ax
		stosw				;; sector address(Hi-h)
		mov	ah,0x42
		pop	si
		ret

;;	dl = drive unit
disk_reset:	mov	ah,0			;; reset
		int	DISKBIOS
return:		ret

;;	bp = parameter block address
disk_read:	mov	bx,BIOS_LOC
		mov	cx,5			;; retry count
dsk_retry_loop:	push	cx
		push	bp
		push	bx
		call	word [mkParam_func]
		mov	dl,0x80
		int	DISKBIOS
		pop	bx
		pop	bp
		pop	cx
		jnc	return

dskrd_retry:	call	disk_reset
		loop	dsk_retry_loop

	;; never return, if disk error.

diskerr_hlt:	xchg	ah,al
		call	hex2
		mov	si,msg_DiskErr
halt_msg:	call	putstr
		mov	si,msg_reboot
		call	putstr
%ifdef COM_DEBUG
		ReturnDos
%else
		mov	ah,0
		int	KEYBIOS
		int	0x19
%endif

putstr:		lodsb
		or	al,al
		jz	tty_out9
outch:		call	tty_out
		jmp	short putstr

hex2:		push	ax
		mov	cl,4
		shr	al,cl
		call	hex1
		pop	ax
hex1:		and	al,0x0F
		add	al,0x30
		cmp	al,0x3A
		jc	tty_out
		add	al,7
tty_out:	mov	ah,14
tty_out0:	int	VIDEOBIOS
tty_out9:	ret


%ifdef COM_DEBUG
%include	"debugsub.inc"
%endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		align 2
mkParam_func:	dw	mk_legacyParam
base_slice:	dw	0
msg_NoActive:	db	"No active",0
msg_CorruptIPL:	db	"Bad IPL",0
msg_DiskErr:	db	":Disk Err", 0
msg_reboot:	db	CR,LF,"Any key to reboot",0
%ifdef SECTOR_IMAGE
		times 510 - ($ - $$) db 0xff
		dw	0xaa55
%endif

;; end of extipl/Gemini::pollux.asm
