1 ; -*- fundamental -*- (asm-mode sucks)
2 ; ****************************************************************************
6 ; A program to boot Linux kernels off a TFTP server using the Intel PXE
7 ; network booting API. It is based on the SYSLINUX boot loader for
10 ; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
11 ; Copyright 2009 Intel Corporation; author: H. Peter Anvin
13 ; This program is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
16 ; Boston MA 02111-1307, USA; either version 2 of the License, or
17 ; (at your option) any later version; incorporated herein by reference.
19 ; ****************************************************************************
25 ; gPXE extensions support
29 ; Some semi-configurable constants... change on your own risk.
32 NULLFILE
equ 0 ; Zero byte == null file name
33 NULLOFFSET
equ 0 ; Position in which to look
34 REBOOT_TIME
equ 5*60 ; If failure, time until full reset
35 %assign HIGHMEM_SLOP
128*1024 ; Avoid this much memory near the top
36 TFTP_BLOCKSIZE_LG2
equ 9 ; log2(bytes/block)
37 TFTP_BLOCKSIZE
equ (1 << TFTP_BLOCKSIZE_LG2
)
39 SECTOR_SHIFT
equ TFTP_BLOCKSIZE_LG2
40 SECTOR_SIZE
equ TFTP_BLOCKSIZE
42 ; ---------------------------------------------------------------------------
44 ; ---------------------------------------------------------------------------
47 ; Memory below this point is reserved for the BIOS and the MBR
52 trackbuf resb trackbufsize
; Track buffer goes here
55 ; These fields save information from before the time
56 ; .bss is zeroed... must be in .earlybss
62 PXEStack resd
1 ; Saved stack during PXE call
65 global DHCPMagic
, RebootTime
, StrucPtr
, BIOSName
66 RebootTime resd
1 ; Reboot timeout, if set by option
67 StrucPtr resw
2 ; Pointer to PXENV+ or !PXE structure
68 LocalBootType resw
1 ; Local boot return code
69 DHCPMagic resb
1 ; PXELINUX magic flags
70 BIOSName resw
1 ; Dummy variable - always 0
74 StackBuf
equ STACK_TOP
-44 ; Base of stack if we use our own
75 StackHome
equ StackBuf
77 ; PXE loads the whole file, but assume it can't be more
78 ; than (384-31)K in size.
82 ; Primary entry point.
86 jmp 0:_start1
; Canonicalize the address and skip
90 ; Patch area for adding hardwired DHCP options
94 hcdhcp_magic
dd 0x2983c8ac ; Magic number
95 hcdhcp_len
dd 7*4 ; Size of this structure
96 hcdhcp_flags
dd 0 ; Reserved for the future
97 ; Parameters to be parsed before the ones from PXE
98 bdhcp_offset
dd 0 ; Offset (entered by patcher)
99 bdhcp_len
dd 0 ; Length (entered by patcher)
100 ; Parameters to be parsed *after* the ones from PXE
101 adhcp_offset
dd 0 ; Offset (entered by patcher)
102 adhcp_len
dd 0 ; Length (entered by patcher)
105 pushfd ; Paranoia... in case of return to PXE
106 pushad ; ... save as much state as possible
117 %if
0 ; debugging code only... not intended for production use
118 ; Clobber the stack segment, to test for specific pathologies
120 mov cx,STACK_LEN
>> 1
124 ; Clobber the tail of the 64K segment, too
127 sub cx,di ; CX = 0 previously
132 ; That is all pushed onto the PXE stack. Save the pointer
133 ; to it and switch to an internal stack.
138 sti ; Stack set up and ready
141 ; Initialize screen (if we're using one)
146 ; Tell the user we got this far
148 mov si,syslinux_banner
171 ; Initialize the idle mechanism
177 ; Now we're all set to start with our *real* business.
179 ; In previous versions I avoided using 32-bit registers because of a
180 ; rumour some BIOSes clobbered the upper half of 32-bit registers at
181 ; random. I figure, though, that if there are any of those still left
182 ; they probably won't be trying to install Linux on them...
184 ; The code is still ripe with 16-bitisms, though. Not worth the hassle
185 ; to take'm out. In fact, we may want to put them back if we're going
186 ; to boot ELKS at some point.
190 ; Linux kernel loading code is common. However, we need to define
191 ; a couple of helper macros...
195 %define HAVE_UNLOAD_PREP
201 ; Jump to 32-bit ELF space
204 jmp kaboom
; load_env32() shouldn't return. If it does, then kaboom!
212 ; Save hardwired DHCP options. This is done before the C environment
213 ; is initialized, so it has to be done in assembly.
215 %define MAX_DHCP_OPTS
4096
219 global bdhcp_data
, adhcp_data
220 bdhcp_data: resb MAX_DHCP_OPTS
221 adhcp_data: resb MAX_DHCP_OPTS
225 mov eax,MAX_DHCP_OPTS
226 movzx ecx,word [bdhcp_len
]
232 mov esi,[bdhcp_offset
]
240 movzx ecx,word [adhcp_len
]
246 mov esi,[adhcp_offset
]
256 ; As core/ui.inc used to be included here in core/pxelinux.asm, and it's no
257 ; longer used, its global variables that were previously used by
258 ; core/pxelinux.asm are now declared here.
266 ThisKbdTo resd
1 ; Temporary holder for KbdTimeout
267 ThisTotalTo resd
1 ; Temporary holder for TotalTimeout
268 KernelExtPtr resw
1 ; During search, final null pointer
269 FuncFlag resb
1 ; Escape sequences received from keyboard
270 KernelType resb
1 ; Kernel type, from vkernel, if known
272 KernelName resb FILENAME_MAX
; Mangled name for kernel
276 ; COMBOOT-loading code
278 %include "comboot.inc"
282 ; Boot sector loading code
290 ; Hardware cleanup common code
294 global local_boot16:function hidden
296 mov [LocalBootType
],ax
303 mov ax,[cs:LocalBootType
]
304 cmp ax,-1 ; localboot -1 == INT 18h
315 ; kaboom: write a message and bail out. Wait for quite a while,
316 ; or a user keypress, then do a hard reboot.
318 ; Note: use BIOS_timer here; we may not have jiffies set up.
322 RESET_STACK_AND_SEGS
AX
323 .
patch: mov si,bailmsg
324 call writestr_early
; Returns with AL = 0
325 .
drain: call pollchar
332 and al,09h ; Magic+Timeout
340 .
wait2: mov dx,[BIOS_timer
]
341 .
wait3: call pollchar
353 mov word [BIOS_magic
],0 ; Cold reboot
354 jmp 0F000h:0FFF0h
; Reset vector address
359 ; This is the main PXENV+/!PXE entry point, using the PXENV+
360 ; calling convention. This is a separate local routine so
361 ; we can hook special things from it if necessary. In particular,
362 ; some PXE stacks seem to not like being invoked from anything but
363 ; the initial stack, so humour it.
365 ; While we're at it, save and restore all registers.
372 ; We may be removing ourselves from memory
373 cmp bx,PXENV_RESTART_TFTP
375 cmp bx,PXENV_FILE_EXEC
379 call bios_timer_cleanup
384 inc word [cs:PXEStackLock
]
387 mov [cs:PXEStack
+2],ss
388 lss sp,[cs:InitStack
]
392 ; Pre-clear the Status field
395 ; This works either for the PXENV+ or the !PXE calling
396 ; convention, as long as we ignore CF (which is redundant
403 mov [cs:PXEStatus
],ax
407 dec word [cs:PXEStackLock
]
415 setnz [bp+32] ; If AX != 0 set CF on return
417 ; This clobbers the AX return, but we already saved it into
418 ; the PXEStatus variable.
421 ; If the call failed, it could return.
422 cmp bx,PXENV_RESTART_TFTP
424 cmp bx,PXENV_FILE_EXEC
431 popfd ; Restore flags (incl. IF, DF)
434 ; Must be after function def due to NASM bug
436 PXEEntry
equ pxenv.jump
+1
439 ; The PXEStackLock keeps us from switching stacks if we take an interrupt
440 ; (which ends up calling pxenv) while we are already on the PXE stack.
441 ; It will be -1 normally, 0 inside a PXE call, and a positive value
442 ; inside a *nested* PXE call.
454 ; Invoke INT 1Ah on the PXE stack. This is used by the "Plan C" method
455 ; for finding the PXE entry point.
460 mov [cs:PXEStack
+2],ss
461 lss sp,[cs:InitStack
]
463 int 1Ah ; May trash registers
469 ; Special unload for gPXE: this switches the InitStack from
470 ; gPXE to the ROM PXE stack.
475 mov bx,PXENV_FILE_EXIT_HOOK
476 mov di,pxe_file_exit_hook
480 ; Now we actually need to exit back to gPXE, which will
481 ; give control back to us on the *new* "original stack"...
499 ; gPXE will have a stack frame looking much like our
500 ; InitStack, except it has a magic cookie at the top,
501 ; and the segment registers are in reverse order.
511 mov [cs:InitStack
],sp
512 mov [cs:InitStack
+2],ss
537 .
offset: dw gpxe_unload.resume
543 ; -----------------------------------------------------------------------------
545 ; -----------------------------------------------------------------------------
548 %include "pxeisr.inc"
551 ; -----------------------------------------------------------------------------
553 ; -----------------------------------------------------------------------------
555 %include "common.inc" ; Universal modules
557 ; -----------------------------------------------------------------------------
559 ; -----------------------------------------------------------------------------
563 global copyright_str
, syslinux_banner
564 copyright_str
db 'Copyright (C) 1994-'
566 db ' H. Peter Anvin et al', CR
, LF
, 0
567 err_bootfailed
db CR
, LF
, 'Boot failed: press a key to retry, or wait for reset...', CR
, LF
, 0
568 bailmsg
equ err_bootfailed
569 localboot_msg
db 'Booting from local disk...', CR
, LF
, 0
570 syslinux_banner
db CR
, LF
, MY_NAME
, ' ', VERSION_STR
, ' ', MY_TYPE
, ' '
574 ; Misc initialized (data) variables
578 KeepPXE
db 0 ; Should PXE be kept around?