;  mbr.S -- Master Boot Record to boot first partition marked active
;
; Copyright 2002-2003 John Coffman.
; All rights reserved.
;
; Licensed under the terms contained in the file 'COPYING' in the 
; source directory.
;

#define DEBUG 0			/* set to 1 for debugging output */

#define JRC_NOCOMPACT
#define JRC_MBR
#define DELL_DIRTY_HACK

#define LILO_ASM
#include "lilo.h"


	.text

	.globl	_main

	.org	PARTS_LOAD

zero:
_main:	cli			! NT 4 blows up if this is missing
	jmp	start
	nop

#if DEBUG
bout:	push	ax		! convert & output hex byte in AL
	shr	al,#4		! high nibble
	call	nout
	pop	ax		! low nibble
nout:	and	al,#0x0F	! write the nibble in low half of AL
	daa			! convert to upper case hex character
	add	al,#0xF0	! **
	adc	al,#0x40	! **
cout:	push	bx		! write character to the console
	mov	ah,#0x0E	! video BIOS function 14
	mov	bx,#0007	! will work in graphics mode too
	int	0x10		! video interrupt
	pop	bx
	ret
#endif

say:	pop	si		! get CS:SI pointer to character string
say1:	lodsb			! but DS==CS, so this works
	or	al,al		! NUL terminated?
	jz	say9
#if DEBUG
	call	cout
#else
	mov	ah,#0x0E	! in-line character write routine
	mov	bx,#0007	! will work in graphics mode too
	int	0x10		! video interrupt
#endif
	jmp	say1
say9:
#if DEBUG
	jmp	si		! return from "say:"
#endif
stop:
#if 0
	hlt			! wait for interrupt
	jmp	stop		! loop back after interrupt
#else
	mov	cx,#3<<4	! delay 3 seconds, DX doesn't matter
	mov	ah,#0x86
	int	0x15		! delay call

	int	0x18		! exit to BIOS
#endif

start:
	xor	ax,ax			! all addressing from 0000:0000
	mov	ss,ax			! set up the stack
	mov	sp,#BOOTSEG*16		! #0x7C00
	sti				! enable interrupts
	cld				! clear direction flag (UP)
	mov	ds,ax			! DS=0
	mov	es,ax			! ES=0
	mov	di,#PARTS_LOAD		! move to here 0000:0600
	mov	si,sp			! from here 0000:7C00
	mov	cx,#SECTOR_SIZE/2	! one sector worth
	rep
	  movsw				! move words
#if 0
	push	es			! continue with code
	push	#go			! the .org above is important
	retf				! goto...
#else
	jmpi	go,0			! intersegment jump 0:go
#endif
go:
#ifdef DELL_DIRTY_HACK
#if 0
	mov	al,[0x449]		! get video mode
	cbw
#else
	mov	ax,#0x1200	! enable video (VGA)
	mov	bl,#0x36	! (probably a nop on EGA or MDA)
#endif
	int	0x10		! 
#endif
#if DEBUG
	call	say			! debugging dump of DL
	.ascii	"DL = "
	.byte	0
	mov	ax,dx
	call	bout			! write the byte in AL
	call	say
	.byte	13,10,0
#endif	
	mov	si,#p_table		! scan the partition table 
	mov	cx,#4			! 4 entries
find_active:
	test	byte ptr (si),dl	! really test hi-bit
	mov	bp,si			! save possible ptr
	js	one_found		! found Active if sign bit set
	add	si,#16			! move to next entry
	loop	find_active		! & loop back

	call	say			! comment & quit
	.ascii	"No partition active"
	.byte	13,10,0
#if DEBUG
	jmp	stop
#endif

find_more:				! check for more that one partition
	test	byte ptr (si),dl	! with active bit set
	jns	one_found
	call	say			! oops, a second partition is active
	.ascii	"Invalid partition table"
	.byte	13,10,0			! comment & quit
#if DEBUG
	br	stop
#endif

one_found:				! one partition is active
	add	si,#16			! go on & test others
	loop	find_more		! continue the loop

; BP points at the only active partition

	mov	si,bp		; now SI points at active partition
	mov	bx,sp		; read to ES:BX
	mov	cx,#12		; make 12 tries; we don`t give up easy
read_loop:
	push	cx		; save try counter
	mov	cx,(si+8)	; get pointer to partition start
	mov	di,(si+8+2)	; (high half of 32-bit sector address)
	call	lba_read	; read sector
	pop	cx		; restore try counter
	jnc	boot_it		; read was okay

#if DEBUG
	push	ax
#endif
	xor	ax,ax		; reset the disk system
	int	0x13		;
#if DEBUG
	pop	ax
#endif
	loop	read_loop	; go try again

#if DEBUG
	xchg	al,ah		; error code to AL
	call	bout
	call	say
	.ascii	" = "
	.byte	0
#endif
	call	say		; something is wrong with the disk read
	.ascii	"Disk read error"
	.byte	13,10,0
#if DEBUG
	br	stop
#endif

no_boot: call	say
	.ascii	"No boot signature"
#if !DEBUG
	.ascii	" in partition"
#endif
	.byte	13,10,0
#if DEBUG
	br	stop
#endif

boot_it:
;;;	seg	es			! DS==ES, so don't need prefix
	cmp	word ptr (bx+0x1FE),#0xAA55	! look for boot signature
	jne	no_boot			! not bootable if no sig.

	push	es		; branch to start of boot code
	push	bx		; at 0000:7C00
#ifdef LCF_COHERENT
	mov	(si),dl		; move into partition table
#endif
	xor	ax,ax		; signal no disk error
	retf			; transfer to boot record

#include "read.S"


	.org	PARTS_LOAD+MAX_BOOT_SIZE	!
	.blkb	8		! space for NT and DRDOS dirty hacks

!!!	.org	0x1be		! spot for the partition table
p_table:
	.blkb	16		! the partition table is filled in
	.blkb	16		! when this Master Boot Record is installed
	.blkb	16		! just leave space
	.blkb	16		! here
	.word	0xAA55		! boot block signature goes here

theend:				! better be at 0000:0800
