blob: 90c1f3c9c2caadd2ac72c9644f81181a659edc68 [file] [log] [blame]
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2008 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,
;; Boston 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
;;
section .text
;
; "default" command
;
pc_default: mov di,default_cmd
call getline
mov byte [di-1],0 ; null-terminate
ret
;
; "ontimeout" command
;
pc_ontimeout: mov di,Ontimeout
call getline
sub di,Ontimeout+1 ; Don't need final space
mov [OntimeoutLen],di
ret
;
; "onerror" command
;
pc_onerror: mov di,Onerror
call getline
sub di,Onerror
mov [OnerrorLen],di
ret
;
; "append" command
;
pc_append: cmp byte [VKernel],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
cmp byte [VKernel],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 byte [VKernel],0 ; ("label" section only)
je .err
mov di,VKernelBuf+vk_rname
xor ax,ax
mov cx,FILENAME_MAX
rep stosb ; Null kernel name
%if IS_PXELINUX
; PXELINUX uses the first 4 bytes of vk_rname for the
; mangled IP address
mov [VKernelBuf+vk_rname+5], bx ; Return type
%else
mov [VKernelBuf+vk_rname+1], bx ; Return type
%endif
.err: ret
%endif
;
; "kernel", "config", ... command
;
pc_kernel: cmp byte [VKernel],0
je .err ; ("label" section only)
mov [VKernelBuf+vk_type],al
call pc_getline
mov di,VKernelBuf+vk_rname
call mangle_name
.err: ret
;
; "timeout", "totaltimeout" command
;
; N.B. 1/10 s ~ 1.D2162AABh clock ticks
;
pc_timeout: push ax
call getint
pop si
jc .err
mov eax,0D2162AABh
mul ebx ; clock ticks per 1/10 s
add ebx,edx
mov [si],ebx
.err: ret
;
; "totaltimeout" command
;
pc_totaltimeout:
;
; 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:
; "font", "kbdmap",
;
pc_filecmd: push ax ; Function to tailcall
call pc_getline
mov di,MNameBuf
call mangle_name
call searchdir
jnz .ok
pop ax ; Drop the successor function
.ok: ret ; Tailcall if OK, error return
;
; Commands that expect the file to be opened on top of the getc stack.
; "display", "include"
;
pc_opencmd: push ax ; Function to tailcall
call pc_getline
mov di,MNameBuf
call mangle_name
call open
jnz .ok
pop ax ; Drop the successor function
.ok: ret ; Tailcall if OK, error return
;
; "include" command (invoked from pc_opencmd)
;
pc_include: inc word [IncludeLevel]
.err: ret
;
; "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
mov [BaudDivisor],ax
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
;
; Begin code to actually set up the serial port
;
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
inc dx ; DX -> LCR
inc dx
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
dec dx
dec dx ; DX -> IER
xor al,al ; IRQ disable
call slow_out
inc dx ; DX -> FCR/IIR
mov al,01h
call slow_out ; Enable FIFOs if present
in al,dx
cmp al,0C0h ; FIFOs enabled and usable?
jae .fifo_ok
xor ax,ax ; Disable FIFO if unusable
call slow_out
.fifo_ok:
inc dx
inc dx ; DX -> MCR
in al,dx
or al,[FlowOutput] ; Assert bits
call slow_out
; Show some life
cmp byte [SerialNotice],0
je .notfirst
mov byte [SerialNotice],0
mov si,syslinux_banner
call write_serial_str
mov si,copyright_str
call write_serial_str
.notfirst:
ret
.serial_port_bad:
mov [SerialPort], word 0
ret
;
; "F"-key command
;
pc_fkey: push ax
call pc_getline
pop di
call mangle_name ; Mangle file name
ret
;
; "label" command
;
pc_label: call commit_vk ; Commit any current vkernel
mov di,VKernelBuf ; Erase the vkernelbuf for better compression
mov cx,(vk_size >> 1)
xor ax,ax
rep stosw
call pc_getline
mov di,VKernelBuf+vk_vname
call mangle_name ; Mangle virtual name
mov byte [VKernel],1 ; We've seen a "label" statement
mov si,VKernelBuf+vk_vname ; By default, rname == vname
; mov di,VKernelBuf+vk_rname ; -- already set
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: call pc_getline ; "say" command
call writestr
jmp crlf ; tailcall
;
; "text" command; ignore everything until we get an "endtext" line
;
pc_text: call pc_getline ; Ignore rest of line
.loop:
call pc_getline
jc .eof
; Leading spaces are already removed...
lodsd
and eax,0xdfdfdfdf ; Upper case
cmp eax,'ENDT'
jne .loop
lodsd
and eax,0x00dfdfdf ; Upper case and mask
cmp eax,'EXT'
jne .loop
; If we get here we hit ENDTEXT
.eof:
ret
;
; Comment line
;
pc_comment: ; Fall into pc_getline
;
; Common subroutine: load line into trackbuf; returns with SI -> trackbuf
; CF is set on EOF.
;
pc_getline: mov di,trackbuf
push di
call getline
mov byte [di],0 ; Null-terminate
pop si
ret
;
; Main loop for configuration file parsing
;
parse_config:
mov di,VKernelBuf ; Clear VKernelBuf at start
xor ax,ax
mov cx,vk_size
rep stosb
.again:
call getcommand ; Parse one command
jnc .again ; If not EOF...
call close
dec word [IncludeLevel] ; Still parsing?
jnz .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:
; For better compression, clean up the append field
mov ax,[VKernelBuf+vk_appendlen]
mov di,VKernelBuf+vk_append
add di,ax
mov cx,max_cmd_len+1
sub cx,ax
xor ax,ax
rep stosb
; Pack into high memory
mov si,VKernelBuf
mov edi,[VKernelEnd]
mov cx,vk_size
call rllpack
mov [VKernelEnd],edi
ret
.overflow:
mov si,vk_overflow_msg
call writestr
ret
section .data
vk_overflow_msg db 'Out of memory parsing config file', CR, LF, 0
SerialNotice db 1 ; Only print this once
section .bss
alignb 4
VKernelEnd resd 1 ; Lowest high memory address used
; This symbol should be used by loaders to indicate
; the highest address *they* are allowed to use.
HighMemRsvd equ VKernelEnd
; by vkernels
section .config
align 4, db 0
KbdTimeout dd 0 ; Keyboard timeout (if any)
TotalTimeout dd 0 ; Total timeout (if any)
AppendLen dw 0 ; Bytes in append= command
OntimeoutLen dw 0 ; Bytes in ontimeout command
OnerrorLen dw 0 ; Bytes in onerror command
CmdLinePtr dw cmd_line_here ; Command line advancing pointer
ForcePrompt dw 0 ; Force prompt
NoEscape dw 0 ; No escape
AllowImplicit dw 1 ; Allow implicit kernels
AllowOptions dw 1 ; User-specified options allowed
IncludeLevel dw 1 ; Nesting level
SerialPort dw 0 ; Serial port base (or 0 for no serial port)
VKernel db 0 ; Have we seen any "label" statements?
%if IS_PXELINUX
IPAppend db 0 ; Default IPAPPEND option
%endif
section .uibss
alignb 4 ; For the good of REP MOVSD
command_line resb max_cmd_len+2 ; Command line buffer
alignb 4
default_cmd resb max_cmd_len+1 ; "default" command line
%include "rllpack.inc"