From c1b3d04474c24e4908868e6c7bedb5824d15b066 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 27 Aug 2008 16:23:24 -0700 Subject: 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 --- modules/Makefile | 63 ++++++ modules/pxechain.asm | 561 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 624 insertions(+) create mode 100644 modules/Makefile create mode 100644 modules/pxechain.asm (limited to 'modules') 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 -- cgit v1.2.1