1 ; "$Id: pxechain.asm,v 1.2 2007/12/16 08:15:39 jhutz Exp $"
2 ; -*- fundamental -*- (asm-mode sucks) vim:noet:com=\:;
3 ; ****************************************************************************
7 ; A comboot program to chain from PXELINUX to another PXE network
8 ; bootstrap program (NBP). This improves on PXELINUX's built-in PXE
9 ; chaining support by arranging for the server address and boot filename
10 ; reported by the PXE stack to be those from which the new NBP was
11 ; loaded, allowing PXELINUX to be used to select from multiple NBP's,
12 ; such as gPXE, another PXELINUX(*), Windows RIS, and so on.
14 ; (*) This seems unnecessary at first, but it is very helpful when
15 ; selecting from among self-contained network boot images.
17 ; Copyright (c) 2007 Carnegie Mellon University
18 ; Copyright (C) 1994-2007 H. Peter Anvin
20 ; This program is free software; you can redistribute it and/or modify
21 ; it under the terms of the GNU General Public License as published by
22 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
23 ; Boston MA 02111-1307, USA; either version 2 of the License, or
24 ; (at your option) any later version; incorporated herein by reference.
26 ; ****************************************************************************
47 mov dl,(%1 >> 8) & 0xff
50 mov dl,(%1 >> 16) & 0xff
53 mov dl,(%1 >> 24) & 0xff
87 ; There should be exactly one command-line argument, which is of the form
88 ; [[ipaddress]::]tftp_filename, just like filenames given to PXELINUX.
89 ; Too few or too many arguments is an error.
91 ; This code is based on mangle_name in pxelinux.asm
99 je near usage
; no args is bad
110 cmp word [si],'::' ; Leading ::?
126 mov ax,0x0e ; get config file name
155 SHOWD
cl ; assume it's <256 for debugging
200 cmp si,di ; is it the same place?
202 mov [tftp_siaddr
],eax
208 mov ax,0x0010 ; DNS resolve
212 mov [tftp_siaddr
],eax
226 ; SI points at the filename, plus remaining arguments,
227 ; CX contains their combined length.
228 ; DI points to where the filename should be stored
229 ; BX says how much space is left for the filename and NUL
232 jz usage
; no args is bad
249 ; get PXE cached data
251 mov ax,0x0009 ; call PXE stack
252 mov bx,0x0071 ; PXENV_GET_CACHED_INFO
262 mov bx,[gci_bufferseg
]
265 mov eax,[es:bx+12] ; save our address (ciaddr)
266 mov [open_ciaddr
],eax ; ... in case we have to do UDP open
267 mov eax,[tftp_siaddr
]
271 mov eax,[es:bx+20] ; siaddr
272 mov [tftp_siaddr
],eax
277 mov si,tftp_filename
; copy the new filename...
278 lea di,[es:bx+108] ; to the "cached DHCP response"
281 mov bx,ds ; restore es before proceeding
284 ; print out what we are doing
286 mov ah,0x02 ; write character
287 mov dl,0x0d ; print a CRLF first
292 mov ax,0x0002 ; write string
295 mov ebx,[tftp_siaddr
]
297 mov ah,0x02 ; write character
300 mov ax,0x0002 ; write string
303 mov ah,0x02 ; write character
310 mov ax,0x0009 ; call PXE stack
311 mov bx,0x0031 ; PXENV_UDP_CLOSE
314 mov cx,[close_status
]
319 mov ax,0x0009 ; call PXE stack
320 mov bx,0x0073 ; PXENV_RESTART_TFTP
321 mov di,PXERestartTFTPParms
327 mov ax,0x0009 ; call PXE stack
328 mov bx,0x0030 ; PXENV_UDP_OPEN
345 mov ah,0x02 ; write character
346 mov dl,0x0d ; print a CRLF first
351 mov ax,0x0002 ; write string
352 mov bx,msg_progname
; print our name
354 mov bx,si ; ... the error message
356 mov ah,0x02 ; write character
358 mov dl,' ' ; ... and the error code, in []
364 mov ah,0x02 ; write character
368 mov dl,0x0d ; and finally a CRLF
377 ; Take a 16-bit integer in BX and print it as 2 hex digits.
378 ; Destroys AX and DL.
388 mov ah,0x02 ; write character
396 mov ah,0x02 ; write character
406 mov ah,0x02 ; write character
414 mov ah,0x02 ; write character
421 ; Take an 8-bit integer in AL and print it in decimal.
422 ; Destroys AX and DL.
426 jb .lt10
; If so, skip first 2 digits
429 jb .lt100
; If so, skip first digit
432 ; Now AH = 100-digit; AL = remainder
440 ; Now AH = 10-digit; AL = remainder
456 ; Take an IP address (in network byte order) in EBX and print it
458 ; Destroys EAX, EBX, ECX, EDX
469 ror ebx,8 ; Move next char into LSB
477 ; Read a dot-quad pathname in DS:SI and output an IP
478 ; address in EAX, with SI pointing to the first
479 ; nonmatching character.
481 ; Return CF=1 on error.
483 ; No segment assumptions permitted.
497 aad ; AL += 10 * AH; AH = 0;
512 loop .realerror
; If CX := 1 then we're done
518 dec si ; CF unchanged!
523 msg_booting: db 'TFTP boot: ',0
524 msg_progname: db 'pxechain: ',0
525 msg_usage: db 'usage: pxechain.cbt [[ipaddress]::]filename',0dh,0ah,0
526 msg_too_long: db 'pxechain: filename is too long (max 127)',0dh,0ah,0
527 msg_get_cache: db 'PXENV_GET_CACHED_INFO',0
528 msg_rst_tftp: db 'PXENV_RESTART_TFTP',0
529 msg_udp_close: db 'PXENV_UDP_CLOSE',0
530 msg_udp_open: db 'PXENV_UDP_OPEN',0
534 gci_packettype: dw 3 ; PXENV_PACKET_TYPE_CACHED_REPLY
542 tftp_filename: times
128 db 0
543 tftp_bufsize: dd 0x00090000 ; available memory for NBP
544 tftp_bufaddr: dd 0x00007c00 ; PXE NBP load address