;; $Id: parseconfig.inc,v 1.5 2002/04/30 03:33:27 hpa Exp $
;; -----------------------------------------------------------------------
;;   
;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
;;
;;   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, Inc., 53 Temple Place Ste 330,
;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
;;   (at your option) any later version; incorporated herein by reference.
;;
;; -----------------------------------------------------------------------

;;
;; parseconfig.inc
;;
;; Configuration file operations
;;

;
; "default" command
; 
pc_default:	mov di,default_cmd
		call getline
		xor al,al
		stosb				; null-terminate
		ret

;
; "append" command
;
pc_append:      cmp word [VKernelCtr],byte 0
		ja .vk
                mov di,AppendBuf
		call getline
                sub di,AppendBuf
.app1:        	mov [AppendLen],di
		ret
.vk:		mov di,VKernelBuf+vk_append	; "append" command (vkernel)
		call getline
		sub di,VKernelBuf+vk_append
                cmp di,byte 2
                jne .app2
                cmp byte [VKernelBuf+vk_append],'-'
                jne .app2
                xor di,di			; If "append -" -> null string
.app2:		mov [VKernelBuf+vk_appendlen],di
		ret

;
; "ipappend" command (PXELINUX only)
;
%if IS_PXELINUX
pc_ipappend:	call getint
		jc .err
		and bx,bx
		setnz bl
		cmp word [VKernelCtr], byte 0
		jne .vk
		mov [IPAppend],bl
.err:		ret
.vk:		mov [VKernelBuf+vk_ipappend],bl
		ret
%endif

;
; "localboot" command (PXELINUX, ISOLINUX)
;
%if IS_PXELINUX || IS_ISOLINUX
pc_localboot:	call getint
		cmp word [VKernelCtr],byte 0	; ("label" section only)
		je .err
		mov [VKernelBuf+vk_rname], byte 0	; Null kernel name
		mov [VKernelBuf+vk_rname+1], bx	; Return type
.err:		ret
%endif

;
; "kernel" command
pc_kernel:	cmp word [VKernelCtr],byte 0
		je .err				; ("label" section only)
		mov di,trackbuf
		push di
		call getline
		pop si
		mov di,VKernelBuf+vk_rname
		call mangle_name
.err:		ret

;
; "timeout" command
;
pc_timeout:	call getint
		jc .err
		mov ax,0D215h			; There are approx 1.D215h
		mul bx				; clock ticks per 1/10 s
		add bx,dx
		mov [KbdTimeOut],bx
.err:		ret

;
; Generic integer variable setting commands:
; "prompt", "implicit"
;
pc_setint16:
		push ax
		call getint
		pop si
		jc .err
		mov [si],bx
.err:		ret

;
; Generic file-processing commands:
; "display", "font", "kbdmap"
;
pc_filecmd:	push ax				; Function to tailcall
		mov di,trackbuf
		push di
		call getline
		pop si
		mov di,MNameBuf
		push di
		call mangle_name
		pop di
		call searchdir			; tailcall
		jnz .ok
		pop ax				; Drop the successor function
.ok:		ret				; Tailcall if OK, error return

;
; "serial" command
;
pc_serial:	call getint
		jc .err
		push bx				; Serial port #
		call skipspace
		jnc .ok
		pop bx
.err:		ret
.ok:
		call ungetc
		call getint
		mov [FlowControl], word 0	; Default to no flow control
		jc .nobaud
.valid_baud:	
		push ebx
		call skipspace
		jc .no_flow
		call ungetc
		call getint			; Hardware flow control?
		jnc .valid_flow
.no_flow:
		xor bx,bx			; Default -> no flow control
.valid_flow:
		and bh,0Fh			; FlowIgnore
		shl bh,4
		mov [FlowIgnore],bh
		mov bh,bl
		and bx,0F003h			; Valid bits
		mov [FlowControl],bx
		pop ebx				; Baud rate
		jmp short .parse_baud
.nobaud:
		mov ebx,DEFAULT_BAUD		; No baud rate given
.parse_baud:
		pop di				; Serial port #
		cmp ebx,byte 75
		jb .err				; < 75 baud == bogus
		mov eax,BAUD_DIVISOR
		cdq
		div ebx
		push ax				; Baud rate divisor
		cmp di,3
		ja .port_is_io			; If port > 3 then port is I/O addr
		shl di,1
		mov di,[di+serial_base]		; Get the I/O port from the BIOS
.port_is_io:
		mov [SerialPort],di
		lea dx,[di+3]			; DX -> LCR
		mov al,83h			; Enable DLAB
		call slow_out
		pop ax				; Divisor
		mov dx,di			; DX -> LS
		call slow_out
		inc dx				; DX -> MS
		mov al,ah
		call slow_out
		mov al,03h			; Disable DLAB
		add dx,byte 2			; DX -> LCR
		call slow_out
		in al,dx			; Read back LCR (detect missing hw)
		cmp al,03h			; If nothing here we'll read 00 or FF
		jne .serial_port_bad		; Assume serial port busted
		sub dx,byte 2			; DX -> IER
		xor al,al			; IRQ disable
		call slow_out

		add dx,byte 3			; DX -> MCR
		in al,dx
		or al,[FlowOutput]		; Assert bits
		call slow_out

		; Show some life
		mov si,syslinux_banner
		call write_serial_str
		mov si,copyright_str
		call write_serial_str
		ret

.serial_port_bad:
		mov [SerialPort], word 0
		ret

;
; "F"-key command
;
pc_fkey:	push ax
		mov di,trackbuf
		push di
		call getline			; Get filename to display
		pop si
		pop di
		call mangle_name		; Mangle file name
		ret

;
; "label" command
;
pc_label:	call commit_vk			; Commit any current vkernel
		mov di,trackbuf			; Get virtual filename
		push di
		call getline
		pop si
		mov di,VKernelBuf+vk_vname
		call mangle_name		; Mangle virtual name
		inc word [VKernelCtr]		; One more vkernel
		mov si,VKernelBuf+vk_vname 	; By default, rname == vname
		mov di,VKernelBuf+vk_rname
		mov cx,FILENAME_MAX
		rep movsb
                mov si,AppendBuf         	; Default append==global append
                mov di,VKernelBuf+vk_append
                mov cx,[AppendLen]
                mov [VKernelBuf+vk_appendlen],cx
                rep movsb
%if IS_PXELINUX					; PXELINUX only
		mov al,[IPAppend]		; Default ipappend==global ipappend
		mov [VKernelBuf+vk_ipappend],al
%endif
		ret

;
; "say" command
;
pc_say:		mov di,trackbuf			; "say" command
		push di
		call getline
		xor al,al
		stosb				; Null-terminate
		pop si
		call writestr
		jmp crlf			; tailcall

;
; Main loop for configuration file parsing
;
parse_config:
		call getcommand
                jnc parse_config		; If not EOF do it again
		;
		; The fall through to commit_vk to commit any final
		; VKernel being read
		;
;
; commit_vk: Store the current VKernelBuf into buffer segment
;
commit_vk:
		cmp word [VKernelCtr],byte 0
		je cvk_ret			; No VKernel = return
		cmp word [VKernelCtr],max_vk	; Above limit?
		ja cvk_overflow
		mov di,[VKernelCtr]
		dec di
		shl di,vk_shift
		mov si,VKernelBuf
		mov cx,(vk_size >> 2)
		push es
		push word vk_seg
		pop es
		rep movsd			; Copy to buffer segment
		pop es
cvk_ret:	ret
cvk_overflow:	mov word [VKernelCtr],max_vk	; No more than max_vk, please
		ret
