/*
 * bootp.S86  -  BOOTP record handling routines for netboot boot images
 *
 * Copyright (C) 2002-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: bootp.S86,v 1.5 2007/01/06 18:30:51 gkminix Exp $
 *
 *====================================================================
 */


#include <common.i86>
#include <net/bootp.i86>

.file __FILE__
.line __LINE__



/*
 *====================================================================
 *
 * Start of the text segment and definition of all public entry points
 */

	.text

	.global	btpini			# define global symbols
	.global	btptag



/*
 *====================================================================
 *
 * Initialize BOOTP/DHCP record handling. We need to copy the
 * whole record out of the bootrom area.
 * Input:  FS:SI -  Pointer to bootp record
 * Output: SI    -  Offset to error message, zero if none
 * Changed registers: AX, BX, CX, DX, SI, DI
 */
btpini:	cmp	byte ptr fs:bootp_op[si],BOOTP_OP_REPLY
	jne	1f			# op code must indicate reply
	cmp	dword ptr fs:bootp_vend[si],BOOTP_VM_RFC1048
	je	2f			# vendor area must have valid magic ID
1:	mov	si,offset noberr
	jmp	9f

2:	cld
	push	ds
	mov	ax,fs
	mov	ds,ax
	mov	bx,si
	xor	cx,cx			# CX is NOP counter
	add	si,_I(bootp_vend) + BOOTP_VM_SIZE
4:	lodsb
	cmp	al,VEND_RFC_NOP		# handle NOP tag
	jne	5f
	inc	cx
	cmp	cx,16			# more than 16 NOP tags is VERY unusual
	jb	4b			# so the bootp record maybe broken
8:	pop	ds
	mov	si,offset btperr
	jmp	9f

5:	cmp	al,VEND_RFC_END		# handle END tag
	jne	6f
	mov	dx,si
	sub	dx,bx			# compute length of bootp record
	cmp	dx,BOOTP_MIN_SIZE
	jae	7f
	mov	dx,BOOTP_MIN_SIZE	# use minimum size
	jmp	7f

6:	lodsb				# handle all other tags
	movzx	cx,al
	add	si,cx			# jump to next tag
	xor	cx,cx			# reset NOP counter
	jmp	4b			# proceed with next tag

7:	cmp	dx,BOOTP_MAX_SIZE	# check if BOOTP records fits
	jae	8b
	mov	cx,dx
	mov	si,bx			# restore source pointer
	mov	di,offset bootpbuf
	rep	movsb			# save the bootp record
	pop	ds
	mov	[bootplen],dx		# set length of bootp record
	xor	si,si			# return with no error
9:	ret



/*
 *====================================================================
 *
 * Find a vendor tag in the BOOTP record.
 * Input:  AL    -  Tag number
 * Output: DS:DI -  Pointer to tag string
 *         CX    -  String length (zero if tag not found)
 * Changed registers: AX, CX, DI
 */
btptag:	push	si
	push	bx
	mov	di,offset bootpbuf
	mov	si,di
	add	si,[bootplen]		# let DS:SI point to last bootp byte
	add	di,_I(bootp_vend) + BOOTP_VM_SIZE

	xor	bx,bx
1:	mov	ah,[di]			# load current vendor tag
	inc	di
	cmp	ah,VEND_RFC_NOP		# NOP tag --> continue
	je	1b
	cmp	ah,VEND_RFC_END		# END tag --> abort
	je	3f
	movzx	cx,byte ptr [di]	# get length of current tag
	inc	di
	cmp	al,ah			# we got our tag
	je	9f
	or	bx,bx			# check for overload flag only once
	jnz	2f
	cmp	ah,VEND_RFC_OVERLOAD	# check for option overload
	jne	2f
	mov	bl,[di]			# get option overload flag
	inc	bh			# set to not accept another overload
2:	add	di,cx			# proceed with next tag
	cmp	di,si
	jb	1b			# got at end of bootp record

3:	test	bl,VEND_OVR_FILE
	jz	4f
	lea	di,bootp_file[bootpbuf]
	lea	si,bootp_vend[bootpbuf]
	and	bl,0 - VEND_OVR_FILE - 1
	jmp	1b			# scan file section of BOOTP record

4:	test	bl,VEND_OVR_SNAME
	jz	8f
	lea	di,bootp_sname[bootpbuf]
	lea	si,bootp_file[bootpbuf]
	and	bl,0 - VEND_OVR_SNAME - 1
	jmp	1b			# scan server name section

8:	xor	cx,cx
9:	pop	bx
	pop	si
	ret




/*
 *====================================================================
 *
 * String and constants definitions
 */
	_rodata


/*
 * Error messages
 */
noberr:	.asciz	"BOOTP/DHCP record missing"
btperr:	.asciz	"BOOTP/DHCP record too large"




/*
 *====================================================================
 *
 * Variable definitions
 */
	.bss

	.global	bootplen		# define global symbols
	.global	bootpbuf

	.lcomm	bootplen,2		# length of bootp record
	.lcomm	bootpbuf,BOOTP_MAX_SIZE	# space to hold BOOTP record




/*
 *====================================================================
 */
	.end

