aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-08-27 16:23:24 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-08-27 16:23:24 -0700
commitc1b3d04474c24e4908868e6c7bedb5824d15b066 (patch)
treecf82cbb2589003c1a44bc5bc6e8cdf94eb49547a
parent2a6fef03f88e7aa56009f608dccd17e6f24dde97 (diff)
downloadsyslinux-elf-c1b3d04474c24e4908868e6c7bedb5824d15b066.tar.gz
syslinux-elf-c1b3d04474c24e4908868e6c7bedb5824d15b066.tar.xz
syslinux-elf-c1b3d04474c24e4908868e6c7bedb5824d15b066.zip
Add pxechain.com; new modules direction; reorganize installation
Add the pxechain module from Jeffery Hutzelman at CMU. Create new modules directory for non-com32 modules. Centralize installation, since we have three types of install, and only one of them was distributed. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--Makefile18
-rw-r--r--com32/menu/Makefile2
-rw-r--r--com32/modules/Makefile2
-rw-r--r--modules/Makefile63
-rw-r--r--modules/pxechain.asm561
5 files changed, 635 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index 6c056d8b..040a7ed1 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,11 @@ include $(topdir)/MCONFIG
# directories.
#
+# List of module objects that should be installed for all derivatives
+MODULES = memdisk/memdisk memdump/memdump.com \
+ modules/*.com com32/menu/*.c32 com32/modules/*.c32
+
+
# syslinux.exe is BTARGET so as to not require everyone to have the
# mingw suite installed
BTARGET = version.gen version.h version.mk
@@ -35,7 +40,7 @@ BOBJECTS = $(BTARGET) \
mbr/mbr.bin mbr/gptmbr.bin \
core/pxelinux.0 core/isolinux.bin core/isolinux-debug.bin \
gpxe/gpxelinux.0 dos/syslinux.com win32/syslinux.exe \
- memdisk/memdisk memdump/memdump.com
+ $(MODULES)
# BSUBDIRs build the on-target binary components.
# ISUBDIRs build the installer (host) components.
@@ -58,20 +63,19 @@ INSTALL_SBIN = extlinux/extlinux
INSTALL_AUX = core/pxelinux.0 gpxe/gpxelinux.0 core/isolinux.bin \
core/isolinux-debug.bin \
dos/syslinux.com dos/copybs.com win32/syslinux.exe \
- memdisk/memdisk memdump/memdump.com \
- mbr/mbr.bin mbr/gptmbr.bin
+ mbr/mbr.bin mbr/gptmbr.bin \
+ $(MODULES)
INSTALL_AUX_OPT = win32/syslinux.exe
# These directories manage their own installables
INSTALLSUBDIRS = com32 utils
# Things to install in /boot/extlinux
-EXTBOOTINSTALL = memdisk/memdisk memdump/memdump.com \
- com32/menu/*.c32 com32/modules/*.c32
+EXTBOOTINSTALL = $(MODULES)
# Things to install in /tftpboot
-NETINSTALLABLE = core/pxelinux.0 gpxe/gpxelinux.0 memdisk/memdisk \
- memdump/memdump.com com32/menu/*.c32 com32/modules/*.c32
+NETINSTALLABLE = core/pxelinux.0 gpxe/gpxelinux.0 \
+ $(MODULES)
all:
$(MAKE) all-local
diff --git a/com32/menu/Makefile b/com32/menu/Makefile
index 9b856c2e..44212c3b 100644
--- a/com32/menu/Makefile
+++ b/com32/menu/Makefile
@@ -44,7 +44,5 @@ spotless: clean
rm -f *~ \#*
install: all
- mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR)
- install -m 644 $(MODULES) $(INSTALLROOT)$(AUXDIR)
-include .*.d
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 691e929a..eb3a9a1e 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -47,7 +47,5 @@ spotless: clean
rm -f *~ \#*
install: all
- mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR)
- install -m 644 $(MODULES) $(INSTALLROOT)$(AUXDIR)
-include .*.d
diff --git a/modules/Makefile b/modules/Makefile
new file mode 100644
index 00000000..5caf5e6e
--- /dev/null
+++ b/modules/Makefile
@@ -0,0 +1,63 @@
+## -----------------------------------------------------------------------
+##
+## Copyright 2001-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.
+##
+## -----------------------------------------------------------------------
+
+##
+## Non-COM32 simple Syslinux modules
+##
+
+topdir = ..
+include $(topdir)/MCONFIG.embedded
+
+INCLUDES = -I$(com32)/include
+
+BINS = pxechain.com
+
+all: $(BINS)
+
+.PRECIOUS: %.o
+%.o: %.S
+ $(CC) $(SFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.o
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.elf
+%.elf: c32entry.o %.o $(LIB)
+ $(LD) -Ttext 0x101000 -e _start -o $@ $^
+
+%.c32: %.elf
+ $(OBJCOPY) -O binary $< $@
+
+%.com: %.asm
+ $(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $<
+
+$(LIB): $(LIBOBJS)
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
+
+%.lss: %.ppm.gz $(PPMTOLSS16)
+ $(GZIPPROG) -cd $< | \
+ $(PPMTOLSS16) \#000000=0 \#d0d0d0=7 \#f6f6f6=15 \
+ > $@
+
+%.ppm.gz: %.png
+ $(PNGTOPNM) $< | gzip -9 > $@
+
+tidy dist:
+ rm -f *.o *.a *.lst *.elf
+
+clean: tidy
+ rm -f $(BINS)
+
+spotless: clean
diff --git a/modules/pxechain.asm b/modules/pxechain.asm
new file mode 100644
index 00000000..b11d0ea9
--- /dev/null
+++ b/modules/pxechain.asm
@@ -0,0 +1,561 @@
+; "$Id: pxechain.asm,v 1.2 2007/12/16 08:15:39 jhutz Exp $"
+; -*- fundamental -*- (asm-mode sucks) vim:noet:com=\:;
+; ****************************************************************************
+;
+; pxechain.asm
+;
+; A comboot program to chain from PXELINUX to another PXE network
+; bootstrap program (NBP). This improves on PXELINUX's built-in PXE
+; chaining support by arranging for the server address and boot filename
+; reported by the PXE stack to be those from which the new NBP was
+; loaded, allowing PXELINUX to be used to select from multiple NBP's,
+; such as gPXE, another PXELINUX(*), Windows RIS, and so on.
+;
+; (*) This seems unnecessary at first, but it is very helpful when
+; selecting from among self-contained network boot images.
+;
+; Copyright (c) 2007 Carnegie Mellon University
+; Copyright (C) 1994-2007 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.
+;
+; ****************************************************************************
+
+;%define DEBUG
+;%define NO_RUN
+
+ absolute 0
+pspInt20: resw 1
+pspNextP: resw 1
+ resb 124
+pspCmdLen: resb 1
+pspCmdArg: resb 127
+
+ section .text
+ org 0x100
+
+%ifdef DEBUG
+%macro MARK 1.nolist
+ mov ah,0x02
+ mov dl,%1&0xff
+ int 0x21
+%if (%1 >> 8) & 0xff
+ mov dl,(%1 >> 8) & 0xff
+ int 0x21
+%if (%1 >> 16) & 0xff
+ mov dl,(%1 >> 16) & 0xff
+ int 0x21
+%if (%1 >> 24) & 0xff
+ mov dl,(%1 >> 24) & 0xff
+ int 0x21
+%endif
+%endif
+%endif
+ mov dl,' '
+ int 0x21
+%endmacro
+%macro SHOWD 1.nolist
+ mov al,%1
+ call print_dec
+ mov ah,0x02
+ mov dl,' '
+ int 0x21
+%endmacro
+%macro SHOWX 1.nolist
+ mov bx,%1
+ call print_hex
+ mov ah,0x02
+ mov dl,' '
+ int 0x21
+%endmacro
+%else
+%macro MARK 1.nolist
+%endmacro
+%macro SHOWD 1.nolist
+%endmacro
+%macro SHOWX 1.nolist
+%endmacro
+%endif
+
+_start:
+ MARK 'INIT'
+
+; There should be exactly one command-line argument, which is of the form
+; [[ipaddress]::]tftp_filename, just like filenames given to PXELINUX.
+; Too few or too many arguments is an error.
+;
+; This code is based on mangle_name in pxelinux.asm
+parse_args:
+ cld
+ xor cx,cx
+ mov cl,[pspCmdLen]
+ dec cx
+ mov si,pspCmdArg+1
+ and cx,cx
+ je near usage ; no args is bad
+ add si,cx
+ dec si
+ std
+.chomp: lodsb
+ cmp al,' '
+ loopz .chomp
+ inc cx
+ cld
+ mov [pspCmdLen],cl
+ mov si,pspCmdArg+1
+ cmp word [si],'::' ; Leading ::?
+ je near gotprefix
+ dec cx
+ jz noip
+ MARK 'SCAN'
+
+.more:
+ inc si
+ cmp byte [si],' '
+ je near usage
+ cmp word [si],'::'
+ je near parse_ip
+ loop .more
+
+noip:
+ MARK 'NOIP'
+ mov ax,0x0e ; get config file name
+ int 0x22
+ mov si,bx
+%ifdef DEBUG
+ mov ah,0x02
+ mov dl,'['
+ int 0x21
+ mov ax,0x02
+ int 0x22
+ mov ah,0x02
+ mov dl,']'
+ int 0x21
+ mov dl,' '
+ int 0x21
+%endif
+ push ds
+ push es
+ pop ds
+ pop es
+ push es
+.find_prefix:
+ lodsb
+ and al,al
+ jnz .find_prefix
+ dec si
+
+ mov cx,si
+ sub cx,bx
+ MARK 'LEN'
+ SHOWD cl ; assume it's <256 for debugging
+ dec si
+ std
+.find_slash:
+ lodsb
+ cmp al,'/'
+ je .slash
+ loop .find_slash
+.slash:
+ cmp cx,127
+ cld
+ jna .copy_prefix
+ pop ds
+ jmp too_long
+
+.copy_prefix:
+ SHOWD cl
+ MARK 'PFX'
+ mov si,bx
+ mov di,tftp_filename
+ mov bx,128
+ sub bx,cx
+ rep movsb
+ pop ds
+
+ mov cl,[pspCmdLen]
+ mov si,pspCmdArg+1
+ jmp prefix_done
+
+usage:
+ xor cx,cx
+ mov si,msg_usage
+ jmp fail
+
+too_long:
+ xor cx,cx
+ mov si,msg_too_long
+ jmp fail
+
+parse_ip:
+ MARK 'PIP'
+ mov di,si
+ mov si,pspCmdArg+1
+ call parse_dotquad
+ jc .notdq
+ cmp si,di ; is it the same place?
+ jne .notdq
+ mov [tftp_siaddr],eax
+ jmp gotprefix
+.notdq:
+ MARK 'NDQ'
+ mov si,di
+ mov bx,pspCmdArg+1
+ mov ax,0x0010 ; DNS resolve
+ int 0x22
+ and eax,eax
+ jz noip
+ mov [tftp_siaddr],eax
+gotprefix:
+ MARK 'GOTP'
+ dec cx ; skip the ::
+ dec cx
+ inc si
+ inc si
+ mov di,tftp_filename
+ mov bx,128
+
+prefix_done:
+ SHOWD bl
+ MARK 'LEFT'
+
+; SI points at the filename, plus remaining arguments,
+; CX contains their combined length.
+; DI points to where the filename should be stored
+; BX says how much space is left for the filename and NUL
+
+ and cx,cx
+ jz usage ; no args is bad
+.copy_filename:
+ lodsb
+%ifdef DEBUG
+ mov dl,al
+ mov ah,0x2
+ int 0x21
+%endif
+ cmp al,' '
+ je usage
+ dec bx
+ jz too_long
+ stosb
+ loop .copy_filename
+ xor eax,eax
+ stosb
+
+; get PXE cached data
+ MARK 'GCI'
+ mov ax,0x0009 ; call PXE stack
+ mov bx,0x0071 ; PXENV_GET_CACHED_INFO
+ mov di,PXECacheParms
+ int 0x22
+ and eax,eax
+ jz .fix_siaddr
+ mov cx,[gci_status]
+ mov si,msg_get_cache
+ jmp fail
+
+.fix_siaddr:
+ mov bx,[gci_bufferseg]
+ mov es,bx
+ mov bx,[gci_buffer]
+ mov eax,[es:bx+12] ; save our address (ciaddr)
+ mov [open_ciaddr],eax ; ... in case we have to do UDP open
+ mov eax,[tftp_siaddr]
+ and eax,eax
+ jnz .replace_addr
+ MARK 'ADDR'
+ mov eax,[es:bx+20] ; siaddr
+ mov [tftp_siaddr],eax
+ jmp .addr_done
+.replace_addr:
+ mov [es:bx+20],eax
+.addr_done:
+ mov si,tftp_filename ; copy the new filename...
+ lea di,[es:bx+108] ; to the "cached DHCP response"
+ mov cx,128
+ rep movsb
+ mov bx,ds ; restore es before proceeding
+ mov es,bx
+
+; print out what we are doing
+%ifdef DEBUG
+ mov ah,0x02 ; write character
+ mov dl,0x0d ; print a CRLF first
+ int 0x21
+ mov dl,0x0a
+ int 0x21
+%endif
+ mov ax,0x0002 ; write string
+ mov bx,msg_booting
+ int 0x22
+ mov ebx,[tftp_siaddr]
+ call print_dotquad
+ mov ah,0x02 ; write character
+ mov dl,' '
+ int 0x21
+ mov ax,0x0002 ; write string
+ mov bx,tftp_filename
+ int 0x22
+ mov ah,0x02 ; write character
+ mov dl,0x0d
+ int 0x21
+ mov dl,0x0a
+ int 0x21
+
+%ifndef NO_RUN
+ mov ax,0x0009 ; call PXE stack
+ mov bx,0x0031 ; PXENV_UDP_CLOSE
+ mov di,PXECloseParms
+ int 0x22
+ mov cx,[close_status]
+ mov si,msg_udp_close
+ and ax,ax
+ jnz fail
+
+ mov ax,0x0009 ; call PXE stack
+ mov bx,0x0073 ; PXENV_RESTART_TFTP
+ mov di,PXERestartTFTPParms
+ int 0x22
+ mov cx,[tftp_status]
+ mov si,msg_rst_tftp
+ call fail
+
+ mov ax,0x0009 ; call PXE stack
+ mov bx,0x0030 ; PXENV_UDP_OPEN
+ mov di,PXEOpenParms
+ int 0x22
+ mov cx,[open_status]
+ mov si,msg_udp_open
+ and ax,ax
+ jnz fail
+ ret
+%endif
+
+fail:
+ MARK 'FAIL'
+ SHOWX cs
+ SHOWX ds
+ SHOWX es
+ SHOWX si
+%ifdef DEBUG
+ mov ah,0x02 ; write character
+ mov dl,0x0d ; print a CRLF first
+ int 0x21
+ mov dl,0x0a
+ int 0x21
+%endif
+ mov ax,0x0002 ; write string
+ mov bx,msg_progname ; print our name
+ int 0x22
+ mov bx,si ; ... the error message
+ int 0x22
+ mov ah,0x02 ; write character
+ jcxz .done
+ mov dl,' ' ; ... and the error code, in []
+ int 0x21
+ mov dl,'['
+ int 0x21
+ mov bx,cx
+ call print_hex
+ mov ah,0x02 ; write character
+ mov dl,']'
+ int 0x21
+.done:
+ mov dl,0x0d ; and finally a CRLF
+ int 0x21
+ mov dl,0x0a
+ int 0x21
+ ret
+
+
+; print_hex
+;
+; Take a 16-bit integer in BX and print it as 2 hex digits.
+; Destroys AX and DL.
+;
+print_hex:
+ mov al,bh
+ aam 16
+ cmp ah,10
+ jb .lt_a000
+ add ah,'A'-'0'-10
+.lt_a000: add ah,'0'
+ mov dl,ah
+ mov ah,0x02 ; write character
+ int 0x21
+
+ cmp al,10
+ jb .lt_a00
+ add al,'A'-'0'-10
+.lt_a00: add al,'0'
+ mov dl,al
+ mov ah,0x02 ; write character
+ int 0x21
+
+ mov al,bl
+ aam 16
+ cmp ah,10
+ jb .lt_a0
+ add ah,'A'-'0'-10
+.lt_a0: add ah,'0'
+ mov dl,ah
+ mov ah,0x02 ; write character
+ int 0x21
+
+ cmp al,10
+ jb .lt_a
+ add al,'A'-'0'-10
+.lt_a: add al,'0'
+ mov dl,al
+ mov ah,0x02 ; write character
+ int 0x21
+ ret
+
+
+; print_dec
+;
+; Take an 8-bit integer in AL and print it in decimal.
+; Destroys AX and DL.
+;
+print_dec:
+ cmp al,10 ; < 10?
+ jb .lt10 ; If so, skip first 2 digits
+
+ cmp al,100 ; < 100
+ jb .lt100 ; If so, skip first digit
+
+ aam 100
+ ; Now AH = 100-digit; AL = remainder
+ add ah,'0'
+ mov dl,ah
+ mov ah,0x02
+ int 0x21
+
+.lt100:
+ aam 10
+ ; Now AH = 10-digit; AL = remainder
+ add ah,'0'
+ mov dl,ah
+ mov ah,0x02
+ int 0x21
+
+.lt10:
+ add al,'0'
+ mov dl,al
+ mov ah,0x02
+ int 0x21
+ ret
+
+
+; print_dotquad
+;
+; Take an IP address (in network byte order) in EBX and print it
+; as a dotted quad.
+; Destroys EAX, EBX, ECX, EDX
+;
+print_dotquad:
+ mov cx,3
+.octet:
+ mov al,bl
+ call print_dec
+ jcxz .done
+ mov ah,0x02
+ mov dl,'.'
+ int 0x21
+ ror ebx,8 ; Move next char into LSB
+ dec cx
+ jmp .octet
+.done:
+ ret
+
+
+; parse_dotquad:
+; Read a dot-quad pathname in DS:SI and output an IP
+; address in EAX, with SI pointing to the first
+; nonmatching character.
+;
+; Return CF=1 on error.
+;
+; No segment assumptions permitted.
+;
+parse_dotquad:
+ push cx
+ mov cx,4
+ xor eax,eax
+.parseloop:
+ mov ch,ah
+ mov ah,al
+ lodsb
+ sub al,'0'
+ jb .notnumeric
+ cmp al,9
+ ja .notnumeric
+ aad ; AL += 10 * AH; AH = 0;
+ xchg ah,ch
+ jmp .parseloop
+.notnumeric:
+ cmp al,'.'-'0'
+ pushf
+ mov al,ah
+ mov ah,ch
+ xor ch,ch
+ ror eax,8
+ popf
+ jne .error
+ loop .parseloop
+ jmp .done
+.error:
+ loop .realerror ; If CX := 1 then we're done
+ clc
+ jmp .done
+.realerror:
+ stc
+.done:
+ dec si ; CF unchanged!
+ pop cx
+ ret
+
+ section .data
+msg_booting: db 'TFTP boot: ',0
+msg_progname: db 'pxechain: ',0
+msg_usage: db 'usage: pxechain.cbt [[ipaddress]::]filename',0dh,0ah,0
+msg_too_long: db 'pxechain: filename is too long (max 127)',0dh,0ah,0
+msg_get_cache: db 'PXENV_GET_CACHED_INFO',0
+msg_rst_tftp: db 'PXENV_RESTART_TFTP',0
+msg_udp_close: db 'PXENV_UDP_CLOSE',0
+msg_udp_open: db 'PXENV_UDP_OPEN',0
+
+PXECacheParms:
+gci_status: dw 0
+gci_packettype: dw 3 ; PXENV_PACKET_TYPE_CACHED_REPLY
+gci_buffersize: dw 0
+gci_buffer: dw 0
+gci_bufferseg: dw 0
+gci_bufferlim: dw 0
+
+PXERestartTFTPParms:
+tftp_status: dw 0
+tftp_filename: times 128 db 0
+tftp_bufsize: dd 0x00090000 ; available memory for NBP
+tftp_bufaddr: dd 0x00007c00 ; PXE NBP load address
+tftp_siaddr: dd 0
+tftp_giaddr: dd 0
+tftp_mcaddr: dd 0
+tftp_mcport: dw 0
+tftp_msport: dw 0
+tftp_timeout: dw 0
+tftp_reopendly: dw 0
+
+PXECloseParms:
+close_status: dw 0
+
+PXEOpenParms:
+open_status: dw 0
+open_ciaddr: dd 0
+
+ section .bss
+ipaddrbuf: resb 16