;; ----------------------------------------------------------------------- ;; ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin ;; ;; 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" or "ui" command, with level (1 = default, 2 = ui) ; pc_default: cmp ax,[DefaultLevel] jb skipline ; == call skipline + ret mov [DefaultLevel],ax 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 ; %if HAS_LOCALBOOT pc_localboot: call getint cmp byte [VKernel],0 ; ("label" section only) je .err mov [VKernelBuf+vk_rname],bx mov byte [VKernelBuf+vk_type],VK_LOCALBOOT .err: ret %endif ; HAS_LOCALBOOT ; ; "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 # xor eax,eax mov [FlowControl],eax ; Default to no flow control call skipspace jc .nobaud call ungetc call getint 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,0F00Bh ; 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 ; call sirq_cleanup_nowipe ; Cleanup existing IRQ handler lea dx,[di+3] ; DX -> LCR mov al,83h ; Enable DLAB slow_out dx,al pop ax ; Divisor mov dx,di ; DX -> LS slow_out dx,al inc dx ; DX -> MS mov al,ah slow_out dx,al mov al,03h ; Disable DLAB inc dx ; DX -> LCR inc dx slow_out dx,al in al,dx ; Read back LCR (detect missing hw) cmp al,03h ; If nothing here we'll read 00 or FF jne .err ; Assume serial port busted dec dx ; DX -> IIR/FCR mov al,01h slow_out dx,al ; Enable FIFOs if present in al,dx cmp al,0C0h ; FIFOs enabled and usable? jae .fifo_ok xor ax,ax ; Disable FIFO if unusable slow_out dx,al .fifo_ok: inc dx inc dx ; DX -> MCR mov al,[FlowOutput] ; Assert bits slow_out dx,al ; Enable interrupts if requested test al,8 jz .noirq call sirq_install .noirq: ; 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 .err: mov [SerialPort], word 0 ret ; ; Store mangled filename command (F-keys, "initrd") ; pc_filename: 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 byte [InitRD+NULLOFFSET],NULLFILE ; No "initrd" statement 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 mov cx,FILENAME_MAX-1 .loop: lodsb cmp al,' ' jna .done stosb loop .loop .done: mov byte [VKernel],1 ; We've seen a "label" statement mov si,VKernelBuf+vk_vname ; By default, rname == mangled vname mov di,VKernelBuf+vk_rname call mangle_name 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 skipline ; 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: cmp byte [VKernel],0 jz .nolabel ; Nothing to commit... mov di,VKernelBuf+vk_append add di,[VKernelBuf+vk_appendlen] ; If we have an initrd statement, append it to the ; append statement cmp byte [InitRD+NULLOFFSET],NULLFILE je .noinitrd mov si,str_initrd mov cx,7 ; "initrd=" rep movsb mov si,InitRD call unmangle_name mov al,' ' stosb ; For better compression, clean up the append field .noinitrd: mov ax,di sub ax,VKernelBuf+vk_append mov [VKernelBuf+vk_appendlen],ax mov cx,max_cmd_len+1 sub cx,ax xor ax,ax rep stosb ; Pack into high memory mov esi,VKernelBuf mov edi,[VKernelEnd] mov ecx,vk_size call rllpack mov [VKernelEnd],edi .nolabel: 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 alignz 4 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 NoComplete dw 0 ; No label completion on TAB key AllowImplicit dw 1 ; Allow implicit kernels AllowOptions dw 1 ; User-specified options allowed IncludeLevel dw 1 ; Nesting level DefaultLevel dw 0 ; The current level of default 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"