aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--parseconfig.inc6
-rw-r--r--pxelinux.asm153
-rw-r--r--pxelinux.doc20
-rw-r--r--ui.inc8
5 files changed, 161 insertions, 32 deletions
diff --git a/NEWS b/NEWS
index 5802c457..1336ad30 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,12 @@ Changes in 3.00:
key to display the prompt" behaviour.
* New simple menu system, as an alternative to the advanced
menu system already present. See README.menu for details.
+ * PXELINUX: Filenames can now be prefixed with an IP address
+ plus :: (e.g. 192.0.2.1::filename), which downloads a file
+ from an alternate TFTP server, or just a ::
+ (e.g. ::filename), which suppresses the common pathname
+ prefix. See pxelinux.doc.
+
Changes in 2.13:
* MEMDISK: Fix command-line parsing "brown paper bag" class
diff --git a/parseconfig.inc b/parseconfig.inc
index c72a5692..1db13a1e 100644
--- a/parseconfig.inc
+++ b/parseconfig.inc
@@ -90,7 +90,13 @@ pc_localboot: call getint
xor ax,ax
mov cx,FILENAME_MAX
rep stosb ; Null kernel name
+%if IS_PXELINUX
+ ; PXELINUX uses the first 4 bytes of vk_rname for the
+ ; mangled IP address
+ mov [VKernelBuf+vk_rname+5], bx ; Return type
+%else
mov [VKernelBuf+vk_rname+1], bx ; Return type
+%endif
.err: ret
%endif
diff --git a/pxelinux.asm b/pxelinux.asm
index 4763670b..a0328f41 100644
--- a/pxelinux.asm
+++ b/pxelinux.asm
@@ -189,7 +189,8 @@ RBFB_brainfuck resb 800h
alignb FILENAME_MAX
BootFile resb 256 ; Boot file from DHCP packet
-ConfigName resb 256 ; Configuration file from DHCP option
+ConfigServer resd 1 ; Null prefix for mangled config name
+ConfigName resb 256-4 ; Configuration file from DHCP option
PathPrefix resb 256 ; Path prefix derived from boot file
DotQuadBuf resb 16 ; Buffer for dotted-quad IP address
IPOption resb 80 ; ip= option buffer
@@ -720,16 +721,21 @@ find_config:
; Begin looking for configuration file
;
config_scan:
+ mov di,ConfigServer
+ xor eax,eax
+ stosd ; The config file is always from the server
+
test byte [DHCPMagic], 02h
jz .no_option
; We got a DHCP option, try it first
mov si,trying_msg
call writestr
- mov di,ConfigName
+ ; mov di,ConfigName ; - already the case
mov si,di
call writestr
call crlf
+ mov di,ConfigServer
call open
jnz .success
@@ -751,6 +757,7 @@ config_scan:
mov si,di
call writestr
call crlf
+ mov di,ConfigServer
call open
pop di
jnz .success
@@ -790,6 +797,7 @@ config_scan:
mov si,di
call writestr
call crlf
+ mov di,ConfigServer
call open
popa
jnz .success
@@ -1071,7 +1079,7 @@ memory_scan_for_pxenv_struct:
; Open a TFTP connection to the server
;
; On entry:
-; DS:DI = filename
+; DS:DI = mangled filename
; If successful:
; ZF clear
; SI = socket pointer
@@ -1096,28 +1104,46 @@ searchdir:
.sendreq: push ax ; [bp-2] - Retry counter
push si ; [bp-4] - File name
- push bx ; [bp-6] - TFTP block
- mov bx,[bx]
- push bx ; [bp-8] - TID (local port no)
- mov eax,[ServerIP] ; Server IP
- mov [pxe_udp_write_pkt.status],byte 0
- mov [pxe_udp_write_pkt.sip],eax
- mov eax,[UseGW]
- mov [pxe_udp_write_pkt.gip],eax
- mov [pxe_udp_write_pkt.lport],bx
- mov ax,[ServerPort]
- mov [pxe_udp_write_pkt.rport],ax
mov di,packet_buf
mov [pxe_udp_write_pkt.buffer],di
+
mov ax,TFTP_RRQ ; TFTP opcode
stosw
+
+ lodsd ; EAX <- server override (if any)
+ and eax,eax
+ jnz .noprefix ; No prefix, and we have the server
+
push si ; Add common prefix
mov si,PathPrefix
call strcpy
dec di
pop si
+
+ mov eax,[ServerIP] ; Get default server
+
+.noprefix:
call strcpy ; Filename
+
+ mov [bx+tftp_remoteip],eax
+
+ push bx ; [bp-6] - TFTP block
+ mov bx,[bx]
+ push bx ; [bp-8] - TID (local port no)
+
+ mov [pxe_udp_write_pkt.status],byte 0
+ mov [pxe_udp_write_pkt.sip],eax
+ ; Now figure out the gateway
+ xor eax,[MyIP]
+ and eax,[Netmask]
+ jz .nogwneeded
+ mov eax,[Gateway]
+.nogwneeded:
+ mov [pxe_udp_write_pkt.gip],eax
+ mov [pxe_udp_write_pkt.lport],bx
+ mov ax,[ServerPort]
+ mov [pxe_udp_write_pkt.rport],ax
mov si,tftp_tail
mov cx,tftp_tail_len
rep movsb
@@ -1170,10 +1196,9 @@ searchdir:
mov si,[bp-6] ; TFTP pointer
mov bx,[bp-8] ; TID
- mov eax,[ServerIP]
+ mov eax,[si+tftp_remoteip]
cmp [pxe_udp_read_pkt.sip],eax ; This is technically not to the TFTP spec?
jne .no_packet
- mov [si+tftp_remoteip],eax
; Got packet - reset timeout
mov word [PktTimeout],PKT_TIMEOUT
@@ -1382,6 +1407,50 @@ free_socket:
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.
+;
+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
+;
; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
; to by ES:DI; ends on encountering any whitespace.
;
@@ -1389,8 +1458,32 @@ free_socket:
; and doesn't contain whitespace, and zero-pads the output buffer,
; so "repe cmpsb" can do a compare.
;
+; The first four bytes of the manged name is the IP address of
+; the download host.
+;
mangle_name:
- mov cx,FILENAME_MAX-1
+ push si
+ mov eax,[ServerIP]
+ cmp word [si],'::' ; Leading ::?
+ je .gotprefix
+ call parse_dotquad
+ jc .noip
+ cmp word [si],'::'
+ je .gotprefix
+.noip:
+ pop si
+ xor eax,eax
+ jmp .prefix_done
+
+.gotprefix:
+ pop cx ; Adjust stack
+ inc si ; Skip double colon
+ inc si
+
+.prefix_done:
+ stosd ; Save IP address prefix
+ mov cx,FILENAME_MAX-5
+
.mn_loop:
lodsb
cmp al,' ' ; If control or space, end
@@ -1416,8 +1509,18 @@ mangle_name:
; On return, DI points to the first byte after the output name,
; which is set to a null byte.
;
-unmangle_name: call strcpy
+unmangle_name:
+ push eax
+ lodsd
+ and eax,eax
+ jz .noip
+ call gendotquad
+ mov ax,'::'
+ stosw
+.noip:
+ call strcpy
dec di ; Point to final null byte
+ pop eax
ret
;
@@ -1848,10 +1951,9 @@ reset_pxe:
; output a dotted quad string to ES:DI.
; DI points to terminal null at end of string on exit.
;
-; CX is destroyed.
-;
gendotquad:
push eax
+ push cx
mov cx,4
.genchar:
push eax
@@ -1884,6 +1986,7 @@ gendotquad:
loop .genchar
dec di
mov [es:di], byte 0
+ pop cx
pop eax
ret
@@ -1900,7 +2003,6 @@ gendotquad:
; ServerIP - boot server IP address
; Netmask - network mask
; Gateway - default gateway router IP
-; UseGW - zero if ServerIP local, otherwise Gateway
; BootFile - boot file name
;
; This assumes the DHCP packet is in "trackbuf" and the length
@@ -1952,14 +2054,6 @@ parse_dhcp:
mov cx,64
call parse_dhcp_options
.nosnameoverload:
- ; Now adjust the gateway
- mov eax,[MyIP]
- xor eax,[ServerIP]
- and eax,[Netmask]
- jz .nogwneeded
- mov eax,[Gateway]
-.nogwneeded:
- mov [UseGW],eax
ret
;
@@ -2402,7 +2496,6 @@ MyIP dd 0 ; My IP address
ServerIP dd 0 ; IP address of boot server
Netmask dd 0 ; Netmask of this subnet
Gateway dd 0 ; Default router
-UseGW dd 0 ; Router to use to get to ServerIP
ServerPort dw TFTP_PORT ; TFTP server port
;
diff --git a/pxelinux.doc b/pxelinux.doc
index 2bc22c38..2fe2c2aa 100644
--- a/pxelinux.doc
+++ b/pxelinux.doc
@@ -308,6 +308,26 @@ If you used this from a client whose Ethernet address was
"/tftpboot/pxelinux.cfg/1:58:fa:84:cf:55:e".
+ ++++ ALTERNATE TFTP SERVERS ++++
+
+PXELINUX supports the following special pathname conventions:
+
+::filename
+
+ Suppresses the common filename prefix, i.e. passes the string
+ "filename" unmodified to the server.
+
+IP address::filename (e.g. 192.0.2.1::filename)
+
+ Suppresses the common filename prefix, *and* sends a request
+ to an alternate TFTP server.
+
+:: was chosen because it is unlikely to conflict with operating system
+usage. However, if you happen to have an environment for which the
+special treatment of :: is a problem, please contact the SYSLINUX
+mailing list.
+
+
++++ SOME NOTES ++++
If the boot fails, PXELINUX (unlike SYSLINUX) will not wait forever;
diff --git a/ui.inc b/ui.inc
index 2872ee55..33b69ddf 100644
--- a/ui.inc
+++ b/ui.inc
@@ -278,7 +278,11 @@ vk_check:
%if IS_PXELINUX || IS_ISOLINUX
; Is this a "localboot" pseudo-kernel?
+%if IS_PXELINUX
+ cmp byte [VKernelBuf+vk_rname+4], 0
+%else
cmp byte [VKernelBuf+vk_rname], 0
+%endif
jne get_kernel ; No, it's real, go get it
mov ax, [VKernelBuf+vk_rname+1]
@@ -315,7 +319,7 @@ get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/e
mov eax,[KernelName+8] ; Save initial extension
mov [exten_table_end],eax ; Last case == initial ext.
%else
- mov di,KernelName
+ mov di,KernelName+4*IS_PXELINUX
xor al,al
mov cx,FILENAME_MAX-5 ; Need 4 chars + null
repne scasb ; Scan for final null
@@ -429,7 +433,7 @@ kernel_good:
%else
push di
push ax
- mov di,KernelName
+ mov di,KernelName+4*IS_PXELINUX
xor al,al
mov cx,FILENAME_MAX
repne scasb