#if 0
;  first.S  -  LILO first stage boot loader with LBA32 support */
Copyright 1992-1998 Werner Almesberger.
Copyright 1999-2002 John Coffman.
All rights reserved.

Licensed under the terms contained in the file 'COPYING' in the 
source directory.

#endif

#define JRC_NOCOMPACT
#define DELL_DIRTY_HACK

#define LILO_ASM
#include "lilo.h"
get common.s		/* as86 "include" will bypass the CPP */


	.text

	.globl	_main

	.org	0

zero:
_main:	cli			! NT 4 blows up if this is missing
	jmp	start
	nop
;;	.org	4
reloc:	.word	theend-zero	! size of the code & params

	.org	6

! Boot device parameters. They are set by the installer.

sig:	.ascii	"LILO"
stage:	.word	STAGE_FIRST
vers:	.word	VERSION


port:	.byte	0		! COM port (0 = unused, 1 = COM1, etc.)
sparam:	.byte	0		! serial port parameters (0 = unused)

raid:	.long	0		! raid sector offset
tstamp:	.long	0		! timestamp

timeout:.word	0		! input timeout
delay:	.word	0		! boot delay
dataend: .word	DATAEND>>4+0x20 ! allow for kernel command line (parmline)

ms_len:	.word	0		! initial greeting message
ms_cx:	.word	0
ms_dx:	.word	0
ms_al:	.byte	0		! (unused)

#if 0
d1_cx:	.word	0		! first descriptor sector address
d1_dx:	.word	0
d1_al:	.byte	0		! (unused)

d2_addr: .blkb	MAX_DESCR_SECS_asm*sa_size - sa_size
#endif

dc_cx:	.word	0		! default command-line sector address
dc_dx:	.word	0
dc_al:	.byte	0		! (unused)

prompt:	.byte	0		! indicates whether to always enter prompt
				! (also used as alignment byte)

kt_cx:	.word	0		! keyboard translation table
kt_dx:	.word	0
kt_al:	.byte	0

d_addr:	.word	0		! second stage sector map of addresses
	.word	0
	.byte	0

;;;	.word	0,0		! terminate the chain

;;;	.org	CODE_START_1
#if 0
!  These locations are referenced as EX_OFF and must be at CODE_START_1
ext_si:	.word	0		! external interface
ext_es:	.word	0		! these locations are referenced in second.S
ext_bx:	.word	0		! do not disturb the ordering
ext_dl:	.byte	0		! second.S will check this magic number
ext_dh:	.byte	0		! not referenced, but must align stack
ext_stack:
#endif
	
start:
	call	start2
start2:
	pop	ax		! get reloc source from old stack
	sub	ax,#start2-zero
	mov	di,cs
	shr	ax,#4		! make into paragraph offset
	add	ax,di		! relocate the segment

	mov	ss,ax
	mov	sp,#SETUP_STACKSIZE	! set the stack for First Stage
	sti			! now it is safe

	push	dx		! set ext_dl (and ext_dh, which is not used)
	push	bx		! WATCH the order of pushes
	push	es		! set ext_es
	push	si		! set ext_si

#define JRC_DS_EQ_SS

	cld			! do not forget to do this !!!
	mov	ds,ax		! address data area
	mov	es,ax		! address data area
#ifdef DELL_DIRTY_HACK
#if 0
	mov	ah,#15		! get video mode
	int	0x10
	cbw
#else
	mov	ax,#0x1200	! enable video (VGA)
	mov	bl,#0x36	! (probably a nop on EGA or MDA)
#endif
	int	0x10		! set video mode
#endif
	mov	al,#0x0d	! gimme a CR ...
	call	display
	mov	al,#0x0a	! ... an LF ...
	call	display
	mov	al,#0x4c	! ... an 'L' ...
	call	display

lagain:
	mov	si,#d_addr	! ready to load the second stage loader
	mov	bx,#map2	! read second stage map to ES:BX
	push	bx		! save for later in SI
	call	pread		! read using pointer in DS:SI
	mov	ah,#0x99	! possible error code
#ifdef LCF_M386
	cmp	dword (bx-4),#EX_MAG_HL	! "LILO"
#else
	cmp	word (bx-4),#EX_MAG_L
	jne	no2idx
	cmp	word (bx-4+2),#EX_MAG_H
#endif
	jne	no2idx
	pop	si		! point at #map2

	int	0x12		! get memory available
	shl	ax,#6		! convert to paragraphs
	sub	ax,[dataend]	! allow for PARMLINE
	push	ax
	pop	es
	xor	bx,bx

sload:	call	pread		! read using map at DS:SI
	jnz	sload		! into memory at ES:BX (auto increment)

! Verify second stage loader signature
	
	mov	si,#sig		! pointer to signature area
	mov	di,si
#ifdef LCF_M386
	cmpsd			! check Signature 1 & 2
#else
	cmpsw
	jne	no2nd		! check Signature 1
	cmpsw
#endif
	jne	no2nd		! check Signature 2
	seg es
	  cmp	byte (di),#STAGE_SECOND
	jne	no2nd
	cmpsw		! skip Stage & Flags

	cmpsw			! check VERSION
;;;	je	rdone
	jne	no2nd

! Start the second stage loader     DS=location of Params

rdone:	mov	al,#0x49	! display an 'I'
	call	display

	push	es
	push	#0
	retf

! error exits below

no2nd:
	mov	ah,#0x9A
no2idx:	push	cx		! display error 99 or 9A

! no return from error
error:
	pop	cx		! pop return address to  pread or errAH
#ifndef LCF_NO1STDIAG
        mov	al,#32          ! display a space
	call	display

	call	bout
#endif
	xor	ax,ax		! reset the FDC
	int	0x13
	dec	byte [zero]		!  CLI == 0xFA == 250
	jnz	lagain		! redo from start
#if 0
zzz:	hlt
	jmp	zzz		! spin; wait for Ctrl-Alt-Del
#else
	mov	cx,#3<<4	! delay 3 seconds, DX does not matter
	mov	ah,#0x86
	int	0x15		! delay call

	int	0x18		! exit to BIOS
#endif

! Pointer Read -- read using pointer in DS:SI

pread:	lodsw			! get CX
	xchg	cx,ax
	
        lodsb
	test    al,#LINEAR_FLAG|LBA32_FLAG
        jnz     use_linear

        dec     si
	lodsw
	mov     dx,ax
	or      ax,cx
	jz      done
	lodsb

        mov     ah,#2           ! read command
        int     0x13            ! BIOS read
        jmp     rd_done

use_linear:
	xchg	dx,ax		! was mov dl,al
	lodsw
	test    dl,#LBA32_FLAG
	jnz     is_lba
	xor     ah,ah           ! was LINEAR, zero the hi-nibble (was count)
is_lba:
        xchg    ax,di
	test	dl,#RAID_REL_FLAG
	jz	skip_reloc
	add	cx,raid		! **** RAID *****
	adc	di,raid+2	! **** RAID *****
skip_reloc:

	call	lba_read
rd_done:
	jc	error		! error -> start over again
	add	bh,#2    	! next sector
done:	ret

#ifndef LCF_NO1STDIAG
bout:	rol     ax,4            ! bring hi-nibble to position
	call	nout
	rol     ax,4            ! bring lo-nibble to position
nout:	and	al,#0x0F	! display one nibble
	daa			! shorter conversion routine
	add	al,#0xF0
	adc	al,#0x40	! is now a hex char 0..9A..F
#endif
display:  push  ax              ! new display does not affect AX
	push	bx		!   nor does it change BX
	mov	bx,#7		!  BH=0, BL=07
	mov	ah,#14
	int	0x10
	pop	bx
	pop     ax
	ret			! side effect, BH=0

#include "read.S"

theend:

!
!   If 'first' loads as the MBR, then there must be space for the partition
!   table.  If 'first' loads as the boot record of some partition, then
!   the space reserved below is not used.  But we must reserve the area
!   as a hedge against the first case.
!
!
	.org	MAX_BOOT_SIZE	!
	.word	0,0,0,0		! space for NT and DRDOS dirty hacks

!!!	.org	0x1be		! spot for the partition table
p_table:
	.blkb	16
	.blkb	16
	.blkb	16
	.blkb	16
	.word	0xAA55		! boot block signature

;map2	equ	*+BOOTSEG*16
map2	equ	*		! addressed as ES:[map2]
