aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-02-16 20:54:39 -0800
committerH. Peter Anvin <hpa@zytor.com>2009-02-16 20:54:39 -0800
commit51f563a2e52d1e2668e7b7a3d480c4f1e4b89d97 (patch)
treea953e74ea09f872e26cf9def21fae4af0a6af73c /core
parenta34a0f89fc0b6f06e5958d3b3a2a0f09ced81a81 (diff)
downloadsyslinux-elf-51f563a2e52d1e2668e7b7a3d480c4f1e4b89d97.tar.gz
syslinux-elf-51f563a2e52d1e2668e7b7a3d480c4f1e4b89d97.tar.xz
syslinux-elf-51f563a2e52d1e2668e7b7a3d480c4f1e4b89d97.zip
pxelinux: clean up and correct the entry point search
Clean up and bug fixes of the entry point search. Verify that all methods work, and print the one we eventually used.
Diffstat (limited to 'core')
-rw-r--r--core/pxelinux.asm210
1 files changed, 116 insertions, 94 deletions
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index aac1ec27..4dfa7af6 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -7,7 +7,7 @@
; network booting API. It is based on the SYSLINUX boot loader for
; MS-DOS floppies.
;
-; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+; Copyright 1994-2009 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
@@ -316,15 +316,33 @@ _start1:
mov word [APIVer],0201h
;
-; Now we need to find the !PXE structure. It's *supposed* to be pointed
-; to by SS:[SP+4], but support INT 1Ah, AX=5650h method as well.
-; FIX: ES:BX should point to the PXENV+ structure on entry as well.
-; We should make that the second test, and not trash ES:BX...
+; Now we need to find the !PXE structure.
+; We search for the following, in order:
;
- cmp dword [es:bx], '!PXE'
+; a. !PXE structure as SS:[SP+4]
+; b. PXENV+ structure at [ES:BX]
+; c. INT 1Ah AX=5650h -> PXENV+
+; d. Search memory for !PXE
+; e. Search memory for PXENV+
+;
+; If we find a PXENV+ structure, we try to find a !PXE structure from
+; it if the API version is 2.1 or later.
+;
+ ; Plan A: !PXE structure as SS:[SP+4]
+ call is_pxe
je have_pxe
- ; Uh-oh, not there... try plan B
+ ; Plan B: PXENV+ structure at [ES:BX]
+ inc byte [plan]
+ les bx,[InitStack]
+ push word [es:bx+24] ; Original BX
+ mov es,[es:bx+4] ; Original ES
+ pop bx
+ call is_pxenv
+ je have_pxenv
+
+ ; Plan C: PXENV+ structure via INT 1Ah AX=5650h
+ inc byte [plan]
mov ax, 5650h
%if USE_PXE_PROVIDED_STACK == 0
lss sp,[InitStack]
@@ -334,24 +352,27 @@ _start1:
lss esp,[BaseStack]
%endif
- jc no_pxe
+ jc no_int1a
cmp ax,564Eh
- jne no_pxe
+ jne no_int1a
- ; Okay, that gave us the PXENV+ structure, find !PXE
- ; structure from that (if available)
- cmp dword [es:bx], 'PXEN'
- jne no_pxe
- cmp word [es:bx+4], 'V+'
+ call is_pxenv
je have_pxenv
- ; Nothing there either. Last-ditch: scan memory
+no_int1a:
+ ; Plan D: !PXE memory scan
+ inc byte [plan]
call memory_scan_for_pxe_struct ; !PXE scan
jnc have_pxe
+
+ ; Plan E: PXENV+ memory scan
+ inc byte [plan]
call memory_scan_for_pxenv_struct ; PXENV+ scan
jnc have_pxenv
-no_pxe: mov si,err_nopxe
+ ; Found nothing at all!!
+no_pxe:
+ mov si,err_nopxe
call writestr_early
jmp kaboom
@@ -374,7 +395,7 @@ have_pxenv:
mov si,bx
mov ax,es
les bx,[es:bx+28h] ; !PXE structure pointer
- cmp dword [es:bx],'!PXE'
+ call is_pxe
je have_pxe
; Nope, !PXE structure missing despite API 2.1+, or at least
@@ -438,7 +459,8 @@ old_api: ; Need to use a PXENV+ structure
call writechr
mov ax,[PXEEntry]
call writehex4
- call crlf
+ mov si,viaplan_msg
+ call writestr_early
jmp have_entrypoint
have_pxe:
@@ -492,7 +514,8 @@ have_pxe:
call writechr
mov ax,[PXEEntry]
call writehex4
- call crlf
+ mov si,viaplan_msg
+ call writestr_early
have_entrypoint:
push cs
@@ -908,57 +931,19 @@ kaboom:
;
; On exit, if found:
; CF = 0, ES:BX -> !PXE structure
-; Otherwise CF = 1, all registers saved
+; Otherwise CF = 1, BX destroyed
+;
+; Assumes DS == CS
;
memory_scan_for_pxe_struct:
- push ds
- pusha
- mov ax,cs
- mov ds,ax
+ push si
+ push ax
+ push dx
mov si,trymempxe_msg
- call writestr_early
+ mov dx,is_pxe
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_early
- mov es,ax
- mov edx,[es:0]
- cmp edx,'!PXE'
- jne .mismatch
- movzx cx,byte [es:4] ; Length of structure
- cmp cl,08h ; Minimum length
- jb .mismatch
- push ax
- xor ax,ax
- xor si,si
-.checksum: es lodsb
- add ah,al
- loop .checksum
- pop ax
- jnz .mismatch ; Checksum must == 0
-.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: mov si,notfound_msg
- call writestr_early
- popa
- pop ds
- stc
- ret
+ jmp memory_scan_common
;
; memory_scan_for_pxenv_struct:
@@ -968,51 +953,87 @@ memory_scan_for_pxe_struct:
;
; On exit, if found:
; CF = 0, ES:BX -> PXENV+ structure
-; Otherwise CF = 1, all registers saved
+; Otherwise:
+; CF = 1, ES, BX destroyed
+;
+; Assumes DS == CS
;
memory_scan_for_pxenv_struct:
- pusha
+ push si
+ push ax
+ push dx
mov si,trymempxenv_msg
+ mov ax,1000h ; Starting segment
+ mov dx,is_pxenv
+ ; fall through
+
+memory_scan_common:
call writestr_early
-; 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
mov es,ax
- mov edx,[es:0]
- cmp edx,'PXEN'
- jne .mismatch
- mov dx,[es:4]
- cmp dx,'V+'
+ xor bx,bx
+ call dx
jne .mismatch
- movzx cx,byte [es:8] ; Length of structure
- cmp cl,26h ; Minimum length
- jb .mismatch
- xor ax,ax
- xor si,si
-.checksum: es lodsb
- add ah,al
- loop .checksum
- and ah,ah
- jnz .mismatch ; Checksum must == 0
-.found: mov bp,sp
- mov [bp+8],bx ; Save BX into stack frame
- mov ax,bx
+.found:
+ mov ax,es
call writehex4
call crlf
clc
- ret
-.not_found: mov si,notfound_msg
+ jmp .ret
+.not_found:
+ mov si,notfound_msg
call writestr_early
- popad
stc
+.ret:
+ pop dx
+ pop ax
+ pop si
ret
;
+; is_pxe:
+; Validity check on possible !PXE structure in ES:BX
+; is_pxenv:
+; Validity check on possible PXENV+ structure in ES:BX
+;
+; Return ZF = 1 on success
+;
+is_pxe equ is_struc.pxe
+is_pxenv equ is_struc.pxenv
+is_struc:
+.pxe:
+ pusha
+ cmp dword [es:bx],'!PXE'
+ jne .bad
+ movzx cx,byte [es:bx+4]
+ cmp cx,58h
+ jae .checksum
+ jmp .bad
+.pxenv:
+ pusha
+ cmp dword [es:bx],'PXEN'
+ jne .bad
+ cmp word [es:bx+4],'V+'
+ jne .bad
+ movzx cx,[es:bx+8]
+ jb .bad
+.checksum:
+ mov si,bx
+ xor ax,ax
+.loop:
+ es lodsb
+ add ah,al
+ loop .loop
+ and ah,ah ; ZF = 1 if structure checksum OK
+.bad:
+ popa
+ ret
+
+;
; close_file:
; Deallocates a file structure (pointer in SI)
; Assumes CS == DS.
@@ -2711,8 +2732,10 @@ err_damage db 'TFTP server sent an incomprehesible reply', CR, LF, 0
found_pxenv db 'Found PXENV+ structure', CR, LF, 0
using_pxenv_msg db 'Old PXE API detected, using PXENV+ structure', CR, LF, 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
+pxeentry_msg db '!PXE entry point found (we hope) at ', 0
+pxenventry_msg db 'PXENV+ entry point found (we hope) at ', 0
+viaplan_msg db ' via plan '
+plan db 'A', CR, LF, 0
trymempxe_msg db 'Scanning memory for !PXE structure... ', 0
trymempxenv_msg db 'Scanning memory for PXENV+ structure... ', 0
undi_data_msg db 'UNDI data segment at: ',0
@@ -2725,7 +2748,6 @@ myipaddr_msg db 'My IP address seems to be ',0
tftpprefix_msg db 'TFTP prefix: ', 0
localboot_msg db 'Booting from local disk...', CR, LF, 0
trying_msg db 'Trying to load: ', 0
-fourbs_msg db BS, BS, BS, BS, 0
default_str db 'default', 0
syslinux_banner db CR, LF, 'PXELINUX ', VERSION_STR, ' ', DATE_STR, ' ', 0
cfgprefix db 'pxelinux.cfg/' ; No final null!