diff options
-rw-r--r-- | Makefile | 23 | ||||
-rw-r--r-- | ldlinux.asm | 6 | ||||
-rw-r--r-- | parseconfig.inc | 342 | ||||
-rw-r--r-- | pxelinux.asm | 293 |
4 files changed, 363 insertions, 301 deletions
@@ -25,6 +25,8 @@ NINCLUDE = BINDIR = /usr/bin LIBDIR = /usr/lib/syslinux +PERL = perl + VERSION = $(shell cat version) .c.o: @@ -57,7 +59,7 @@ INSTALL_LIB = pxelinux.0 isolinux.bin isolinux-debug.bin \ # official release. Otherwise, substitute a hex string that is pretty much # guaranteed to be unique to be unique from build to build. ifndef HEXDATE -HEXDATE := $(shell perl now.pl ldlinux.asm pxelinux.asm isolinux.asm) +HEXDATE := $(shell $(PERL) now.pl ldlinux.asm pxelinux.asm isolinux.asm) endif ifndef DATE DATE := $(HEXDATE) @@ -77,24 +79,27 @@ samples: memdisk: $(MAKE) -C memdisk all -ldlinux.bin: ldlinux.asm +kwdhash.inc: keywords + $(PERL) genhash.pl < keywords > kwdhash.inc + +ldlinux.bin: ldlinux.asm kwdhash.inc $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ -dHEXDATE="$(HEXDATE)" \ -l ldlinux.lst -o ldlinux.bin ldlinux.asm - perl genstupid.pl < ldlinux.lst + $(PERL) genstupid.pl < ldlinux.lst -pxelinux.0: pxelinux.asm pxe.inc +pxelinux.0: pxelinux.asm kwdhash.inc $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ -dHEXDATE="$(HEXDATE)" \ -l pxelinux.lst -o pxelinux.0 pxelinux.asm -isolinux.bin: isolinux.asm +isolinux.bin: isolinux.asm kwdhash.inc $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ -dHEXDATE="$(HEXDATE)" \ -l isolinux.lst -o isolinux.bin isolinux.asm # Special verbose version of isolinux.bin -isolinux-debug.bin: isolinux.asm +isolinux-debug.bin: isolinux.asm kwdhash.inc $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ -dHEXDATE="$(HEXDATE)" -dDEBUG_MESSAGES \ -l isolinux-debug.lst -o isolinux-debug.bin isolinux.asm @@ -115,10 +120,10 @@ copybs.com: copybs.asm $(NASM) -f bin -l copybs.lst -o copybs.com copybs.asm bootsect_bin.c: ldlinux.bss bin2c.pl - perl bin2c.pl bootsect < ldlinux.bss > bootsect_bin.c + $(PERL) bin2c.pl bootsect < ldlinux.bss > bootsect_bin.c ldlinux_bin.c: ldlinux.sys bin2c.pl - perl bin2c.pl ldlinux < ldlinux.sys > ldlinux_bin.c + $(PERL) bin2c.pl ldlinux < ldlinux.sys > ldlinux_bin.c syslinux: syslinux.o bootsect_bin.o ldlinux_bin.o stupid.o $(CC) $(LDFLAGS) -o syslinux \ @@ -128,7 +133,7 @@ ldlinux.lst: ldlinux.bin : Generated by side effect stupid.c: ldlinux.lst genstupid.pl - perl genstupid.pl < ldlinux.lst + $(PERL) genstupid.pl < ldlinux.lst stupid.inc: stupid.c : Generated by side effect diff --git a/ldlinux.asm b/ldlinux.asm index 4c83e0d2..bbdc1bf3 100644 --- a/ldlinux.asm +++ b/ldlinux.asm @@ -37,6 +37,8 @@ ; my_id equ syslinux_id max_cmd_len equ 255 ; Must be odd; 255 is the kernel limit +FILENAME_MAX_LG2 equ 4 ; log2(Max filename size Including final null) +FILENAME_MAX equ 11 ; Max mangled filename size retry_count equ 6 ; How patient are we with the disk? HIGHMEM_MAX equ 037FFFFFFh ; DEFAULT highest address for an initrd DEFAULT_BAUD equ 9600 ; Default baud rate for serial port @@ -62,8 +64,8 @@ BAUD_DIVISOR equ 115200 ; Serial port parameter %define vk_size (1 << vk_shift) ; Size of a vkernel buffer struc vkernel -vk_vname: resb 11 ; Virtual name **MUST BE FIRST!** -vk_rname: resb 11 ; Real name +vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!** +vk_rname: resb FILENAME_MAX ; Real name vk_appendlen: resw 1 alignb 4 vk_append: resb max_cmd_len+1 ; Command line diff --git a/parseconfig.inc b/parseconfig.inc new file mode 100644 index 00000000..fd323666 --- /dev/null +++ b/parseconfig.inc @@ -0,0 +1,342 @@ +;; $Id$ +;; ----------------------------------------------------------------------- +;; +;; 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 +;; + +; +; Main loop for configuration file parsing +; +parse_config: + call getcommand + jnc parse_config ; If not EOF do it again + ret ; Return on EOF + +; +; "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 my_id == pxelinux_id +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 my_id == pxelinux_id || my_id == isolinux_id +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 + +; +; "display" command +; +pc_display: call pc_getfile + jz .err ; File not found? + call get_msg_file ; Load and display file +.err: ret + +; +; "prompt" command +; +pc_prompt: call getint + jc .err + mov [ForcePrompt],bx +.err: ret + +; +; "implicit" command +; +pc_implicit: call getint + jc .err + mov [AllowImplicit],bx +.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 parse_config_2 ; < 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,pxelinux_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 +; +; This relies on the fact that [si] points to the address of the entrypoint +; +pc_f1: nop +pc_f2: nop +pc_f3: nop +pc_f4: nop +pc_f5: nop +pc_f6: nop +pc_f7: nop +pc_f8: nop +pc_f9: nop +pc_f10: + mov cx,[si] + sub cx,pc_f1 + push cx + mov ax,1 + shl ax,cl + or [FKeyMap], ax ; Mark that we have this loaded + mov di,trackbuf + push di + call getline ; Get filename to display + pop si + pop di + shl di,FILENAME_MAX_LG2 ; Convert to offset + add di,FKeyName + 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 + mov al,[IPAppend] ; Default ipappend==global ipappend + mov [VKernelBuf+vk_ipappend],al + ret + +; +; "font" command +; +pc_font: call pc_getfile ; "font" command + jz .err ; File not found? + call loadfont ; Load and install font +.err: ret + +; +; "kbd" command +; +pc_kbd: call pc_getfile ; "kbd" command + jz .err + call loadkeys +.err: 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 + +; +; pc_getfile: For command line options that take file argument, this +; routine decodes the file argument and runs it through searchdir +; +pc_getfile: mov di,trackbuf + push di + call getline + pop si + mov di,MNameBuf + push di + call mangle_name + pop di + jmp searchdir ; tailcall + +; +; 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 + +; +; End of configuration file +; +; Commit vkernel and then return +; +end_config_file equ commit_vk + diff --git a/pxelinux.asm b/pxelinux.asm index 18299f89..38b77a86 100644 --- a/pxelinux.asm +++ b/pxelinux.asm @@ -808,296 +808,7 @@ config_scan: ; Now we have the config file open ; .success: add sp,byte 16 ; Adjust stack -parse_config: - call getkeyword - jc near end_config_file ; Config file loaded - cmp ax,'de' ; DEfault - je pc_default - cmp ax,'ap' ; APpend - je pc_append - cmp ax,'ti' ; TImeout - je near pc_timeout - cmp ax,'pr' ; PRompt - je near pc_prompt - cmp ax,'fo' ; FOnt - je near pc_font - cmp ax,'kb' ; KBd - je near pc_kbd - cmp ax,'di' ; DIsplay - je near pc_display - cmp ax,'la' ; LAbel - je near pc_label - cmp ax,'ke' ; KErnel - je near pc_kernel - cmp ax,'im' ; IMplicit - je near pc_implicit - cmp ax,'se' ; SErial - je near pc_serial - cmp ax,'sa' ; SAy - je near pc_say - cmp ax,'ip' ; IPappend - je pc_ipappend - cmp ax,'lo' ; LOcalboot - je pc_localboot - cmp al,'f' ; F-key - jne parse_config - jmp pc_fkey - -pc_default: mov di,default_cmd ; "default" command - call getline - xor al,al - stosb ; null-terminate - jmp short parse_config - -pc_append: cmp word [VKernelCtr],byte 0 ; "append" command - ja pc_append_vk - mov di,AppendBuf - call getline - sub di,AppendBuf -pc_app1: mov [AppendLen],di - jmp short parse_config_2 -pc_append_vk: mov di,VKernelBuf+vk_append ; "append" command (vkernel) - call getline - sub di,VKernelBuf+vk_append - cmp di,byte 2 - jne pc_app2 - cmp byte [VKernelBuf+vk_append],'-' - jne pc_app2 - mov di,0 ; If "append -" -> null string -pc_app2: mov [VKernelBuf+vk_appendlen],di - jmp short parse_config_2 - -pc_ipappend: call getint ; "ipappend" command - jc parse_config_2 - and bx,bx - setnz bl - cmp word [VKernelCtr], byte 0 - jne .vk - mov [IPAppend],bl - jmp short parse_config_2 -.vk: mov [VKernelBuf+vk_ipappend],bl - jmp short parse_config_2 - -pc_localboot: call getint ; "localboot" command - cmp word [VKernelCtr],byte 0 ; ("label" section only) - je parse_config_2 - mov [VKernelBuf+vk_rname], byte 0 ; Null kernel name - mov [VKernelBuf+vk_rname+1], bx ; Return type - jmp short parse_config_2 - -pc_kernel: cmp word [VKernelCtr],byte 0 ; "kernel" command - je parse_config_2 ; ("label" section only) - mov di,trackbuf - push di - call getline - pop si - mov di,VKernelBuf+vk_rname - call mangle_name - jmp short parse_config_2 - -pc_timeout: call getint ; "timeout" command - jc parse_config_2 - mov ax,0D215h ; There are approx 1.D215h - mul bx ; clock ticks per 1/10 s - add bx,dx - mov [KbdTimeOut],bx -parse_config_2: jmp parse_config - -pc_display: call pc_getfile ; "display" command - jz parse_config_2 ; File not found? - call get_msg_file ; Load and display file - jmp short parse_config_2 - -pc_prompt: call getint ; "prompt" command - jc parse_config_2 - mov [ForcePrompt],bx - jmp short parse_config_2 - -pc_implicit: call getint ; "implicit" command - jc parse_config_2 - mov [AllowImplicit],bx - jmp short parse_config_2 - -pc_serial: call getint ; "serial" command - jc parse_config_2 - push bx ; Serial port # - call skipspace - jc parse_config_2 - 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 parse_config_2 ; < 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,pxelinux_banner - call write_serial_str - mov si,copyright_str - call write_serial_str - - jmp short parse_config_3 - -.serial_port_bad: - mov [SerialPort], word 0 - jmp short parse_config_3 - -pc_fkey: sub ah,'1' - jnb pc_fkey1 - mov ah,9 ; F10 -pc_fkey1: xor cx,cx - mov cl,ah - push cx - mov ax,1 - shl ax,cl - or [FKeyMap], ax ; Mark that we have this loaded - mov di,trackbuf - push di - call getline ; Get filename to display - pop si - pop di - shl di,FILENAME_MAX_LG2 ; Convert to offset - add di,FKeyName - call mangle_name ; Mangle file name - jmp short parse_config_3 - -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 - mov al,[IPAppend] ; Default ipappend==global ipappend - mov [VKernelBuf+vk_ipappend],al - jmp near parse_config_3 - -pc_font: call pc_getfile ; "font" command - jz parse_config_3 ; File not found? - call loadfont ; Load and install font - jmp short parse_config_3 - -pc_kbd: call pc_getfile ; "kbd" command - jz parse_config_3 - call loadkeys -parse_config_3: jmp parse_config - -pc_say: mov di,trackbuf ; "say" command - push di - call getline - xor al,al - stosb ; Null-terminate - pop si - call writestr - call crlf - jmp short parse_config_3 - -; -; pc_getfile: For command line options that take file argument, this -; routine decodes the file argument and runs it through searchdir -; -pc_getfile: mov di,trackbuf - push di - call getline - pop si - mov di,MNameBuf - push di - call mangle_name - pop di - jmp searchdir ; Tailcall - -; -; 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 - -; -; End of configuration file -; -end_config_file: - call commit_vk ; Commit any current vkernel + call parse_config ; Parse configuration file no_config_file: ; ; Check whether or not we are supposed to display the boot prompt. @@ -3668,6 +3379,8 @@ genipopt: %include "writestr.inc" ; String output writestr equ cwritestr %include "writehex.inc" ; Hexadecimal output +%include "parseconfig.inc" ; High-level config file handling +%include "parsecmd.inc" ; Low-level config file handling %include "font.inc" ; VGA font stuff %include "graphics.inc" ; VGA graphics |