diff options
author | hpa <hpa> | 1999-09-21 12:48:17 +0000 |
---|---|---|
committer | hpa <hpa> | 1999-09-21 12:48:17 +0000 |
commit | c5d1716757291afde85cf9bc2faa7388efe267d1 (patch) | |
tree | 4943d7a4809e787a62f945f93380f360b1f05048 | |
parent | 92d1bc56d1894c2a985501493aba656852a6cc92 (diff) | |
download | syslinux.git-c5d1716757291afde85cf9bc2faa7388efe267d1.tar.gz syslinux.git-c5d1716757291afde85cf9bc2faa7388efe267d1.tar.xz syslinux.git-c5d1716757291afde85cf9bc2faa7388efe267d1.zip |
Add final timeout for PXELINUX; better documentation; hopefully
better handling of ERROR packets and timeouts in general. Prepare
version 1.47.
-rw-r--r-- | NEWS | 16 | ||||
-rw-r--r-- | pxelinux.asm | 176 | ||||
-rw-r--r-- | pxelinux.doc | 106 | ||||
-rw-r--r-- | version | 2 |
4 files changed, 189 insertions, 111 deletions
@@ -1,7 +1,17 @@ +Changes in 1.47: + * PXELINUX: RFC 1123 states that a TFTP implementation MUST + use adaptive timeout, "at least an exponential backoff of + retransmission timeout is necessary." Implement a very + simple exponential backoff for retransmits. + * PXELINUX: Updated documentation, including pointer to new + TFTP server. + * PXELINUX: When sending ERROR due to bad OACK, use the proper + destination port number (why are TFTP port numbers so odd?) + Changes in 1.46: - * New program PXELINUX to do network booting over the PXE - (Pre-Execution Environment) network booting protocol. See - pxelinux.doc for details. + * New program PXELINUX to do network booting using a + PXE-compliant (Pre-Execution Environment) network booting + PROM. See pxelinux.doc for details. Changes in 1.45: * Serial console support. See syslinux.doc for details. diff --git a/pxelinux.asm b/pxelinux.asm index c5f2d4e4..0d83b364 100644 --- a/pxelinux.asm +++ b/pxelinux.asm @@ -35,15 +35,15 @@ ; max_cmd_len equ 255 ; Must be odd; 255 is the kernel limit FILENAME_MAX equ 32 ; Including final null; should be a power of 2 -retry_count equ 6 ; How patient are we with the disk? +REBOOT_TIME equ 5*60 ; If failure, time until full reset HIGHMEM_MAX equ 038000000h ; Highest address for an initrd HIGHMEM_SLOP equ 128*1024 ; Avoid this much memory near the top DEFAULT_BAUD equ 9600 ; Default baud rate for serial port BAUD_DIVISOR equ 115200 ; Serial port parameter MAX_SOCKETS equ 64 ; Max number of open sockets TFTP_PORT equ htons(69) ; Default TFTP port -PKT_RETRY equ 8 ; Packet transmit retry count -PKT_TIMEOUT equ 20 ; Timer ticks @ 55 ms +PKT_RETRY equ 6 ; Packet transmit retry count +PKT_TIMEOUT equ 8 ; Initial timeout, timer ticks @ 55 ms TFTP_BLOCKSIZE equ 512 ; Bytes/block LOG_TFTP_BLOCKSIZE equ 9 ; log2(TFTP_BLOCKSIZE) @@ -257,7 +257,10 @@ tftp_filesize resd 1 ; Total file size absolute 0400h serial_base resw 4 ; Base addresses for 4 serial ports - + absolute 046Ch +BIOS_timer resw 1 ; Timer ticks + absolute 0472h +BIOS_magic resw 1 ; BIOS reset magic absolute 0484h BIOS_vidrows resb 1 ; Number of screen rows @@ -311,6 +314,7 @@ SetupSecs resw 1 ; Number of setup sectors A20Test resw 1 ; Counter for testing status of A20 ServerPort resw 1 ; TFTP server port ConfigFile resw 1 ; Socket for config file +PktTimeout resw 1 ; Timeout for current packet TextAttrBX equ $ TextAttribute resb 1 ; Text attribute for message file TextPage resb 1 ; Active display page @@ -983,8 +987,7 @@ time_loop: push cx tick_loop: push dx call pollchar jnz get_char_pop - xor ax,ax - int 1Ah ; Get time "of day" + mov dx,[BIOS_timer] ; Get time "of day" pop ax cmp dx,ax ; Has the timer advanced? je tick_loop @@ -2076,25 +2079,37 @@ ac_ret1: ret ; -; kaboom: write a message and bail out. +; kaboom: write a message and bail out. Wait for quite a while, or a user keypress, +; then do a hard reboot. ; kaboom: lss sp,[cs:Stack] pop ds + sti .patch: mov si,bailmsg call writestr ; Returns with AL = 0 - call unload_pxe -.drain: mov ah,1 - int 16h ; Keypress there? +.drain: call pollchar jz .drained - xor ah,ah - int 16h + call getchar jmp short .drain -.drained: xor ah,ah - int 16h ; Wait for keypress - int 19h ; And try once more to boot... -.norge: jmp short .norge ; If int 19h returned; this is the end - +.drained: + mov cx,18 +.wait1: push cx + mov cx,REBOOT_TIME +.wait2: mov dx,[BIOS_timer] +.wait3: call pollchar + jnz .keypress + cmp dx,[BIOS_timer] + je .wait3 + loop .wait2 + mov al,'.' + call writechr + pop cx + loop .wait1 +.keypress: + call crlf + mov word [BIOS_magic],0 ; Cold reboot + jmp 0F000h:0FFF0h ; Reset vector address ; ; searchdir: ; @@ -2119,6 +2134,7 @@ searchdir: jz near .error mov ax,PKT_RETRY ; Retry counter + mov word [PktTimeout],PKT_TIMEOUT ; Initial timeout .sendreq: push ax ; [bp-2] - Retry counter push si ; [bp-4] - File name @@ -2160,11 +2176,8 @@ searchdir: ; ; Packet transmitted OK, now we need to receive -.getpacket: push word PKT_TIMEOUT ; [bp-10] - - xor ax,ax - int 1Ah - push dx ; [bp-12] +.getpacket: push word [PktTimeout] ; [bp-10] + push word [BIOS_timer] ; [bp-12] .pkt_loop: mov bx,[bp-8] ; TID mov di,packet_buf @@ -2180,8 +2193,7 @@ searchdir: and ax,ax jz .got_packet ; Wait for packet .no_packet: - xor ax,ax - int 1Ah + mov dx,[BIOS_timer] cmp dx,[bp-12] je .pkt_loop mov [bp-12],dx @@ -2189,6 +2201,7 @@ searchdir: jnz .pkt_loop pop ax ; Adjust stack pop ax + shl word [PktTimeout],1 ; Exponential backoff jmp .failure .got_packet: @@ -2200,6 +2213,9 @@ searchdir: jne .no_packet mov [si+tftp_remoteip],eax + ; Got packet - reset timeout + mov word [PktTimeout],PKT_TIMEOUT + pop ax ; Adjust stack pop ax @@ -2278,6 +2294,8 @@ searchdir: ret .err_reply: ; Option negotiation error. Send ERROR reply. + mov ax,[pxe_udp_read_pkt.rport] + mov word [pxe_udp_write_pkt.rport],ax mov word [pxe_udp_write_pkt.buffer],tftp_opt_err mov word [pxe_udp_write_pkt.buffersize],tftp_opt_err_len mov di,pxe_udp_write_pkt @@ -2688,7 +2706,7 @@ writehex_common: ; pollchar: check if we have an input character pending (ZF = 0) ; pollchar: - pusha + pushad mov ah,1 ; Poll keyboard int 16h jnz .done ; Keyboard response @@ -2698,7 +2716,7 @@ pollchar: add dx,byte 5 ; Serial status register in al,dx test al,1 ; ZF = 0 if traffic -.done: popa +.done: popad ret ; @@ -2728,18 +2746,6 @@ getchar: .func_key: ret ; -; -; kaboom2: once everything is loaded, replace the part of kaboom -; starting with "kaboom.patch" with this part - -kaboom2: - mov si,err_bootfailed - call cwritestr - call getchar - int 19h ; And try once more to boot... -.norge: jmp short .norge ; If int 19h returned; this is the end - -; ; open,getc: Load a file a character at a time for parsing in a manner ; similar to the C library getc routine. Only one simultaneous ; use is supported. Note: "open" trashes the trackbuf. @@ -3134,7 +3140,7 @@ getfssec: .packet_loop: push cx ; <A> Save count push es ; <B> Save buffer pointer - push bx ; <C> + push bx ; <C> Block pointer mov ax,ds mov es,ax @@ -3142,26 +3148,27 @@ getfssec: ; Start by ACKing the previous packet; this should cause the ; next packet to be sent. mov cx,PKT_RETRY + mov word [PktTimeout],PKT_TIMEOUT -.send_ack: push cx ; <D> +.send_ack: push cx ; <D> Retry count mov eax,[si+tftp_filepos] shr eax,LOG_TFTP_BLOCKSIZE xchg ah,al ; Network byte order call ack_packet ; Send ACK - jz .send_ok - pop cx ; <D> - loop .send_ack - jmp kaboom ; Failed to send ACK + ; We used to test the error code here, but sometimes + ; PXE would return negative status even though we really + ; did send the ACK. Now, just treat a failed send as + ; a normally lost packet, and let it time out in due + ; course of events. .send_ok: ; Now wait for packet. - xor ax,ax - int 1Ah ; Get current time + mov dx,[BIOS_timer] ; Get current time - mov cx,PKT_TIMEOUT -.send_loop: push cx ; <E> - push dx ; <F> + mov cx,[PktTimeout] +.wait_data: push cx ; <E> Timeout + push dx ; <F> Old time mov bx,packet_buf mov [pxe_udp_read_pkt.buffer],bx @@ -3183,15 +3190,15 @@ getfssec: je .recv_ok ; No packet, or receive failure - xor ax,ax - int 1Ah ; Get time - pop ax ; Old time - pop cx + mov dx,[BIOS_timer] + pop ax ; <F> Old time + pop cx ; <E> Timeout cmp ax,dx ; Same time -> don't advance timeout - je .send_loop - loop .send_loop ; Decrease timeout + je .wait_data ; Same clock tick + loop .wait_data ; Decrease timeout - pop cx ; Didn't get any, send another ACK + pop cx ; <D> Didn't get any, send another ACK + shl word [PktTimeout],1 ; Exponential backoff loop .send_ack jmp kaboom ; Forget it... @@ -3199,10 +3206,10 @@ getfssec: pop cx ; <E> cmp word [pxe_udp_read_pkt.buffersize],byte 4 - jb .send_loop ; Bad size for a DATA packet + jb .wait_data ; Bad size for a DATA packet cmp word [packet_buf],TFTP_DATA ; Not a data packet? - jne .send_loop ; Then wait for something else + jne .wait_data ; Then wait for something else mov eax,[si+tftp_filepos] shr eax,LOG_TFTP_BLOCKSIZE @@ -3331,40 +3338,39 @@ unload_pxe: ; Various initialized or semi-initialized variables ; copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin' - db 0Dh, 0Ah, 0 + db 13, 10, 0 boot_prompt db 'boot: ', 0 wipe_char db 08h, ' ', 08h, 0 err_notfound db 'Could not find kernel image: ',0 -err_notkernel db 0Dh, 0Ah, 'Invalid or corrupt kernel image.', 0Dh, 0Ah, 0 +err_notkernel db 13, 10, 'Invalid or corrupt kernel image.', 13, 10, 0 err_not386 db 'It appears your computer uses a 286 or lower CPU.' - db 0Dh, 0Ah + db 13, 10 db 'You cannot run Linux unless you have a 386 or higher CPU' - db 0Dh, 0Ah + db 13, 10 db 'in your machine. If you get this message in error, hold' - db 0Dh, 0Ah + db 13, 10 db 'down the Ctrl key while booting, and I will take your' - db 0Dh, 0Ah - db 'word for it.', 0Dh, 0Ah, 0 -err_badcfg db 'Unknown keyword in config file.', 0Dh, 0Ah, 0 -err_noparm db 'Missing parameter in config file.', 0Dh, 0Ah, 0 -err_noinitrd db 0Dh, 0Ah, 'Could not find ramdisk image: ', 0 -err_nohighmem db 'Not enough memory to load specified kernel.', 0Dh, 0Ah, 0 -err_highload db 0Dh, 0Ah, 'Kernel transfer failure.', 0Dh, 0Ah, 0 + db 13, 10 + db 'word for it.', 13, 10, 0 +err_badcfg db 'Unknown keyword in config file.', 13, 10, 0 +err_noparm db 'Missing parameter in config file.', 13, 10, 0 +err_noinitrd db 13, 10, 'Could not find ramdisk image: ', 0 +err_nohighmem db 'Not enough memory to load specified kernel.', 13, 10, 0 +err_highload db 13, 10, 'Kernel transfer failure.', 13, 10, 0 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' - db 0Dh, 0Ah, 0 -err_notdos db ': attempted DOS system call', 0Dh, 0Ah, 0 -err_comlarge db 'COMBOOT image too large.', 0Dh, 0Ah, 0 -err_bootsec db 'Invalid or corrupt boot sector image.', 0Dh, 0Ah, 0 -err_a20 db 0Dh, 0Ah, 'A20 gate not responding!', 0Dh, 0Ah, 0 -err_bootfailed db 0Dh, 0Ah, 'Boot failed: please change disks and press ' - db 'a key to continue.', 0Dh, 0Ah, 0 + db 13, 10, 0 +err_notdos db ': attempted DOS system call', 13, 10, 0 +err_comlarge db 'COMBOOT image too large.', 13, 10, 0 +err_bootsec db 'Invalid or corrupt boot sector image.', 13, 10, 0 +err_a20 db 13, 10, 'A20 gate not responding!', 13, 10, 0 +err_bootfailed db 13, 10, 'Boot failed: press a key to retry, or wait for reset...', 13, 10, 0 bailmsg equ err_bootfailed -err_nopxe db 'Cannot find !PXE structure, I want my mommy!' ,0Dh, 0Ah, 0 +err_nopxe db 'Cannot find !PXE structure, I want my mommy!' ,13, 10, 0 err_pxefailed db 'PXE API call failed, error ', 0 -err_udpinit db 'Failed to initialize UDP stack', 0Dh, 0Ah, 0 -err_oldtftp db 'TFTP server does not support the tsize option', 0Dh, 0Ah, 0 -found_pxenv db 'Found PXENV+ structure', 0Dh, 0Ah, 0 -using_pxenv_msg db 'Old PXE API detected, using PXENV+ structure', 0Dh, 0Ah, 0 +err_udpinit db 'Failed to initialize UDP stack', 13, 10, 0 +err_oldtftp db 'TFTP server does not support the tsize option', 13, 10, 0 +found_pxenv db 'Found PXENV+ structure', 13, 10, 0 +using_pxenv_msg db 'Old PXE API detected, using PXENV+ structure', 13, 10, 0 apiver_str db 'PXE API version is ',0 pxeentry_msg db 'PXE entry point found (we hope) at ', 0 myipaddr_msg db 'My IP address seems to be ',0 @@ -3375,11 +3381,11 @@ loading_msg db 'Loading ', 0 dotdot_msg db '.' dot_msg db '.', 0 aborted_msg db ' aborted.' ; Fall through to crlf_msg! -crlf_msg db 0Dh, 0Ah, 0 -crff_msg db 0Dh, 0Ch, 0 +crlf_msg db 13, 10, 0 +crff_msg db 13, 0Ch, 0 default_str db 'default', 0 default_len equ ($-default_str) -pxelinux_banner db 0Dh, 0Ah, 'PXELINUX ', version_str, ' ', date, ' ', 0 +pxelinux_banner db 13, 10, 'PXELINUX ', version_str, ' ', date, ' ', 0 cfgprefix db 'pxelinux.cfg/' ; No final null! cfgprefix_len equ ($-cfgprefix) diff --git a/pxelinux.doc b/pxelinux.doc index a9428107..bdf18632 100644 --- a/pxelinux.doc +++ b/pxelinux.doc @@ -58,34 +58,90 @@ server in the following way: case). It should be noted that all filename references are relative to the -/tftpboot directory, or whatever directory the pxelinux.bin lives in. -PXELINUX generally requires that filenames are 31 characters or -shorter in length. +directory pxelinux.bin lives in (usually /tftpboot). PXELINUX +generally requires that filenames are 31 characters or shorter in +length. PXELINUX does not support MTFTP, and I have no immediate plans of doing so. - ++++ SETTING UP A BOOTP SERVER ++++ + ++++ SETTING UP A DHCP SERVER ++++ -The PXE protocol is very complex, but I have successfully booted an -Intel Nightshade-based PXE host (with "Intel LANDesk(R) Service Agent -II"), using a DHCP-enabled BOOTP server with the following -configuration in /etc/bootptab: +The PXE protocol uses a very complex set of extensions to DHCP or +BOOTP, but it seems that at least existing implementations don't +really require all of them; in fact, the only necessary option appears +to be the dhcp-class-identifier "PXEClient". -<hostname>:hn:ht=ether:ha=<ethernet_address>:ip=<ip>:\ - :bf=/tftpboot/pxelinux.bin:\ - :T60=505845436c69656e74:\ - :T43=0603:\ - :T43=08000001ssssssss:\ - :sm=<netmask>:\ - :gw=<default_gateway>:\ - :ds=<dns_servers>: +Using ISC dhcpd.conf syntax: -... where "ssssssss" is the IP address of the boot server, in -hexadecimal. +configuration: -Your mileage may vary. + allow booting; + allow bootp; + + filename "/tftpboot/pxelinux.bin" ; + next-server <TFTP server>; + option dhcp-class-identifier "PXEClient"; + + option domain-name "<domain name>"; + option subnet-mask <subnet mask>; + option broadcast-address <broadcast address>; + option domain-name-servers <dns servers>; + option routers <default router>; + + host <hostname> { + hardware ethernet <ethernet address>; + fixed-address <hostname>; + } + + +The configuration above works even if the DHCP and TFTP servers are +not the same machine. + +Note that if your particular TFTP daemon runs under chroot, it may be +that the filename parameter should not include the /tftpboot prefix. + +I have successfully booted an Intel N440BX ("Nightshade") motherboard +with onboard Ethernet and "Intel LANDesk(R) Service Agent II version +0.99c", using ISC dhcpd 2.0. + +Unfortunately, this particular version of Intel LANDesk Service Agent +II seems to have a rather serious bug: it requests the TFTP "blksize" +option, but will be mortally confused if this option is actually +accepted! There are two possible workarounds for this bug: + +1. Use a TFTP server with doesn't support "blksize". + + Unfortunately, PXELINUX requires the "tsize" option to be + supported, and it is very unusual for TFTP servers to implement one + and not the other. I have therefore produced a TFTP server which + supports options, but let them be disabled with an option (-r + <optionname>). This TFTP server is available at: + + http://www.kernel.org/pub/software/network/tftp/ + ftp://www.kernel.org/pub/software/network/tftp/ + + ... and on any kernel.org mirror (see http://www.kernel.org/mirrors/). + +2. Add the following DHCP option: + + "option vendor-encapsulated-options 08:00:00:01:7f:00:00:01 ;" + + That line is not supposed to be necessary, and in fact makes + booting significantly slower, since it will attempt (and fail) an + MTFTP transfer before falling back to TFTP. For some reason, the + boot PROM doesn't request the "blksize" option if it has already + failed an MTFTP transfer, and thus the bug is avoided. + + + ++++ SOME NOTES ++++ + +If the boot fails, PXELINUX (unlike SYSLINUX) will not wait forever; +rather, if it has not received any input for approximately five +minutes after displaying an error message, it will reset the machine. +This allows the machine to recover in case it had bad enough luck of +trying to boot at the same time the TFTP server goes down. ++++ PXELINUX IS STILL BETA ++++ @@ -98,10 +154,16 @@ at the end of syslinux.doc. Thanks! Currently known problems: + Requires a TFTP server which supports the "tsize" option. -+ Probably doesn't work if the BOOTP/DHCP server and the TFTP server - aren't the same. -+ The error recovery routine doesn't work quite right. ++ The error recovery routine doesn't work quite right. For right now, + just do a hard reset. + There may be funnies with memory management. The PXE spec has no decent way of telling it to free up all memory and unchain any interrupts; it allows the base stack to be unloaded, but not the UNDI driver. ++ There seems to be a problem with sending ACK "storms"; a number of + ACK packets fired off without the proper delay in between. I + suspect this is a PXE firmware problem, rather than a PXELINUX + problem. ++ We should probably call the UDP receive function in the keyboard + entry loop, so that we answer ARP requests. ++ COMBOOT images or boot sectors don't work yet. @@ -1 +1 @@ -1.46 +1.47 |