aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhpa <hpa>1999-09-27 01:51:22 +0000
committerhpa <hpa>1999-09-27 01:51:22 +0000
commitf0fd23d73eae7a77ffc74dc8020a2cd5104c1777 (patch)
tree044a507d7280801c54a19a62ad8e66ef1a6015c4
parent275f21f7d92f377d15a821c217667c54e788e8bd (diff)
downloadsyslinux.git-f0fd23d73eae7a77ffc74dc8020a2cd5104c1777.tar.gz
syslinux.git-f0fd23d73eae7a77ffc74dc8020a2cd5104c1777.tar.xz
syslinux.git-f0fd23d73eae7a77ffc74dc8020a2cd5104c1777.zip
Many fixes and bug workarounds for PXELINUX.
-rw-r--r--NEWS7
-rw-r--r--pxelinux.asm202
2 files changed, 152 insertions, 57 deletions
diff --git a/NEWS b/NEWS
index a7270a18..9db096e9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+Changes in 1.48:
+ * PXELINUX: Workaround for PXE ROMs based on the Intel PXE PDK
+ 2.0 build 071 and earlier: missing !PXE structure pointer.
+ * PXELINUX: Handle larger BOOTP/DHCP packages.
+ * PXELINUX: The command line passing was broken; fix.
+ * PXELINUX: Make COMBOOT images work.
+
Changes in 1.47:
* PXELINUX: RFC 1123 states that a TFTP implementation MUST
use adaptive timeout, "at least an exponential backoff of
diff --git a/pxelinux.asm b/pxelinux.asm
index 73bcfb1a..a194ffda 100644
--- a/pxelinux.asm
+++ b/pxelinux.asm
@@ -318,6 +318,8 @@ 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
+CmdLineLen resw 1 ; Length of command line including null
+KernelExtPtr resw 1 ; During search, final null pointer
TextAttrBX equ $
TextAttribute resb 1 ; Text attribute for message file
TextPage resb 1 ; Active display page
@@ -357,6 +359,8 @@ bootp:
.v_flags resd 1 ; DHCP flags
.v_pad resb 56 ; Vendor options padding
+.options resb 0500h ; Additional option space
+
bootp_size equ $-bootp
alignb 16
@@ -402,7 +406,7 @@ _start1:
; to by SS:[SP+4], but support INT 1Ah, AX=5650h method as well.
;
cmp dword [es:bx], '!PXE'
- je have_pxe
+ je near have_pxe
; Uh-oh, not there... try plan B
mov ax, 5650h
@@ -461,22 +465,34 @@ old_api: ; Need to use a PXENV+ structure
mov eax,[es:bx+0Ah] ; PXE RM API
mov [PXENVEntry],eax
- jmp short have_pxe_entry
+
+ mov si,pxenventry_msg
+ call writestr
+ mov ax,[PXENVEntry+2]
+ call writehex4
+ mov al,':'
+ call writechr
+ mov ax,[PXENVEntry]
+ call writehex4
+ call crlf
+ jmp short have_entrypoint
have_pxe:
mov eax,[es:bx+10h]
mov [PXEEntry],eax
-have_pxe_entry: mov si,pxeentry_msg
+ mov si,pxeentry_msg
call writestr
- mov ax,[PXENVEntry+2]
+ mov ax,[PXEEntry+2]
call writehex4
mov al,':'
call writechr
- mov ax,[PXENVEntry]
+ mov ax,[PXEEntry]
call writehex4
call crlf
+have_entrypoint:
+
;
; Clear Sockets structures
;
@@ -489,17 +505,28 @@ have_pxe_entry: mov si,pxeentry_msg
; Now attempt to get the BOOTP/DHCP packet that brought us life (and an IP
; address)
;
-query_bootp: mov ax,0DEADh ; Something bogus
-
- mov ax,ds
+query_bootp: mov ax,ds
mov es,ax
mov di,pxe_bootp_query_pkt
mov bx,PXENV_GET_CACHED_INFO
call far [PXENVEntry]
- jc .pxe_err
+ jc .pxe_err1
cmp ax,byte 0
je .pxe_ok
+.pxe_err1:
+ mov di,pxe_bootp_size_query_pkt
+ mov bx,PXENV_GET_CACHED_INFO
+
+ call far [PXENVEntry]
+ jc .pxe_err
+ cmp ax,byte 0
+ je .pxe_size
+.pxe_size:
+ mov ax,[pxe_bootp_size_query_pkt.buffersize]
+ call writehex4
+ call crlf
+
.pxe_err:
mov si,err_pxefailed
call writestr
@@ -1176,22 +1203,30 @@ not_vk: pop ds
pop di
pop si
pop es
- mov bx,exten_count << 2 ; Alternates to try
;
; Find the kernel on disk
;
get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/extension
- mov eax,[KernelName+8] ; Save initial extension
- mov [OrigKernelExt],eax
+ mov di,KernelName
+ xor al,al
+ mov cx,FILENAME_MAX-5 ; Need 4 chars + null
+ repne scasb ; Scan for final null
+ jne .no_skip
+ dec di ; Point to final null
+.no_skip: mov [KernelExtPtr],di
+ mov bx,exten_table
.search_loop: push bx
mov di,KernelName ; Search on disk
call searchdir
pop bx
jnz kernel_good
- mov eax,[exten_table+bx] ; Try a different extension
- mov [KernelName+8],eax
- sub bx,byte 4
- jnb .search_loop
+ mov eax,[bx] ; Try a different extension
+ mov si,[KernelExtPtr]
+ mov [si],eax
+ mov byte [si+4],0
+ add bx,byte 4
+ cmp bx,exten_table_end
+ jna .search_loop ; allow == case (final case)
bad_kernel:
mov si,KernelName
mov di,KernelCName
@@ -1246,33 +1281,41 @@ kernel_corrupt: mov si,err_notkernel
; This is it! We have a name (and location on the disk)... let's load
; that sucker!! First we have to decide what kind of file this is; base
; that decision on the file extension. The following extensions are
-; recognized:
+; recognized; case insensitive:
;
-; .COM - COMBOOT image
-; .CBT - COMBOOT image
-; .BS - Boot sector
-; .BSS - Boot sector, but transfer over DOS superblock
+; .com - COMBOOT image
+; .cbt - COMBOOT image
+; .bs - Boot sector
+; .bss - Boot sector, but transfer over DOS superblock
+;
+; Boot sectors are currently not supported by PXELINUX.
;
; Anything else is assumed to be a Linux kernel.
;
kernel_good:
- pusha
- mov si,KernelName
- mov di,KernelCName
- call unmangle_name ; Get human form
- sub di,KernelCName
- mov [KernelCNameLen],di
- popa
+ push di
+ push ax
+ mov di,KernelName
+ xor al,al
+ mov cx,FILENAME_MAX
+ repne scasb
+ jne .one_step
+ dec di
+.one_step: mov ecx,[di-4] ; 4 bytes before end
+ pop ax
+ pop di
+
+ or ecx,20202000h ; Force lower case
- mov ecx,[KernelName+8] ; Get (mangled) extension
- cmp ecx,'COM'
+ cmp ecx,'.com'
je near is_comboot_image
- cmp ecx,'CBT'
+ cmp ecx,'.cbt'
je near is_comboot_image
- cmp ecx,'BS '
- je near is_bootsector
- cmp ecx,'BSS'
+ cmp ecx,'.bss'
je near is_bss_sector
+ and ecx, 00ffffffh
+ cmp ecx,'.bs'
+ je near is_bootsector
; Otherwise Linux kernel
;
; A Linux kernel consists of three parts: boot sector, setup code, and
@@ -1449,6 +1492,8 @@ is_mem_cmd:
cmdline_end:
push cs ; Restore standard DS
pop ds
+ sub di,cmd_line_here
+ mov [CmdLineLen],di ; Length including final null
;
; Now check if we have a large kernel, which needs to be loaded high
;
@@ -1629,6 +1674,12 @@ nk_noinitrd:
shl cx,7 ; Sectors -> dwords
xor si,si
xor di,di
+ fs rep movsd ; Copy setup + boot sector
+ mov si,cmd_line_here
+ mov di,si
+ mov cx,[CmdLineLen]
+ add cx,byte 3
+ shr cx,2 ; Convert to dwords
fs rep movsd
;
; Some kernels in the 1.2 ballpark but pre-bzImage have more than 4
@@ -2148,32 +2199,52 @@ kaboom:
; Otherwise CF = 1, all registers saved
;
memory_scan_for_pxe_struct:
+ push ds
pusha
+ xor ax,ax
+ mov ds,ax
+ mov si,trymempxe_msg
+ call writestr
mov ax,[BIOS_fbm] ; Starting segment
shl ax,(10-4) ; Kilobytes -> paragraphs
+; mov ax,01000h ; Start to look here
dec ax ; To skip inc ax
.mismatch:
inc ax
cmp ax,0A000h ; End of memory
jae .not_found
+ call writehex4
+ mov si,fourbs_msg
+ call writestr
mov es,ax
- mov edx,[es:si]
+ mov edx,[es:0]
cmp edx,'!PXE'
jne .mismatch
movzx cx,byte [es:4] ; Length of structure
- cmp cl,58h ; Minimum length
+ cmp cl,08h ; Minimum length
jb .mismatch
+ push ax
xor ax,ax
xor si,si
.checksum: es lodsb
add ah,al
loop .checksum
- and ah,ah
+ pop ax
jnz .mismatch ; Checksum must == 0
-.found: add sp,byte 8*2 ; Adjust stack
+.found: mov bp,sp
+ xor bx,bx
+ mov [bp+8],bx ; Save BX into stack frame (will be == 0)
+ mov ax,es
+ call writehex4
+ call crlf
+ popa
+ pop ds
clc
ret
-.not_found: popa
+.not_found: mov si,notfound_msg
+ call writestr
+ popa
+ pop ds
stc
ret
@@ -2189,8 +2260,11 @@ memory_scan_for_pxe_struct:
;
memory_scan_for_pxenv_struct:
pusha
- mov ax,[BIOS_fbm] ; Starting segment
- shl ax,(10-4) ; Kilobytes -> paragraphs
+ mov si,trymempxenv_msg
+ call writestr
+; mov ax,[BIOS_fbm] ; Starting segment
+; shl ax,(10-4) ; Kilobytes -> paragraphs
+ mov ax,01000h ; Start to look here
dec ax ; To skip inc ax
.mismatch:
inc ax
@@ -2213,10 +2287,16 @@ memory_scan_for_pxenv_struct:
loop .checksum
and ah,ah
jnz .mismatch ; Checksum must == 0
-.found: add sp,byte 8*2 ; Adjust stack
+.found: mov bp,sp
+ mov [bp+8],bx ; Save BX into stack frame
+ mov ax,bx
+ call writehex4
+ call crlf
clc
ret
-.not_found: popad
+.not_found: mov si,notfound_msg
+ call writestr
+ popad
stc
ret
@@ -3227,7 +3307,7 @@ unmangle_name: call strcpy
pxe_thunk: push es
push di
push bx
- call far [PXEEntry]
+ call far [cs:PXEEntry]
add sp,byte 6
cmp ax,byte 1
cmc ; Set CF unless ax == 0
@@ -3483,13 +3563,19 @@ 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
+pxenventry_msg db 'PXENV entry point found (we hope) at ', 0
+trymempxe_msg db 'Scanning memory for !PXE structure... ', 0
+trymempxenv_msg db 'Scanning memory for PXENV+ structure... ', 0
+notfound_msg db 'not found', 13, 10, 0
myipaddr_msg db 'My IP address seems to be ',0
tftpprefix_msg db 'TFTP prefix: ', 0
+cmdline_msg db 'Command line: ', 13, 10, 0
ready_msg db 13, 10, 'Ready to start kernel...', 13, 10, 0
trying_msg db 'Trying to load: ', 0
loading_msg db 'Loading ', 0
dotdot_msg db '.'
dot_msg db '.', 0
+fourbs_msg db 8, 8, 8, 8, 0
aborted_msg db ' aborted.' ; Fall through to crlf_msg!
crlf_msg db 13, 10, 0
crff_msg db 13, 0Ch, 0
@@ -3534,20 +3620,15 @@ keywd_table db 'ap' ; append
db 'f0' ; F10
dw 0
;
-; Extensions to search for (in *reverse* order). Note that the last
-; (lexically first) entry in the table is a placeholder for the original
-; extension, needed for error messages. The exten_table is shifted so
-; the table is 1-based; this is because a "loop" cx is used as index.
+; Extensions to search for (in *forward* order).
;
align 4, db 0
-exten_table:
-OrigKernelExt: dd 0 ; Original extension
- db 'COM',0 ; COMBOOT (same as DOS)
- db 'BS ',0 ; Boot Sector
- db 'BSS',0 ; Boot Sector (add superblock)
- db 'CBT',0 ; COMBOOT (specific)
-
-exten_count equ (($-exten_table) >> 2) - 1 ; Number of alternates
+exten_table: db '.cbt' ; COMBOOT (specific)
+ db '.bss' ; Boot Sector (add superblock)
+ db '.bs', 0 ; Boot Sector
+ db '.com' ; COMBOOT (same as DOS)
+exten_table_end:
+ dd 0, 0 ; Need 8 null bytes here
;
; PXENV entry point. If we use the !PXE API, this will point to a thunk
@@ -3560,9 +3641,16 @@ PXENVEntry dw pxe_thunk,0
;
pxe_bootp_query_pkt:
.status: dw 0 ; Status
-.packettype: dw 2 ; DHCPACK packet
+.packettype: dw 3 ; DHCPACK packet
.buffersize: dw bootp_size ; Packet size
.buffer: dw bootp, 0 ; seg:off of buffer
+.bufferlimit: dw bootp_size ; Unused
+
+pxe_bootp_size_query_pkt:
+.status: dw 0 ; Status
+.packettype: dw 3 ; DHCPACK packet
+.buffersize: dw 0 ; Packet size
+.buffer: dw 0, 0 ; seg:off of buffer
.bufferlimit: dw 0 ; Unused
pxe_udp_open_pkt: