1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 ;; Boston MA 02111-1307, USA; either version 2 of the License, or
9 ;; (at your option) any later version; incorporated herein by reference.
11 ;; -----------------------------------------------------------------------
14 ; This file should be entered with the config file open (for getc)
16 call parse_config ; Parse configuration file
19 ; Check whether or not we are supposed to display the boot prompt.
22 cmp word [ForcePrompt],0 ; Force prompt?
24 test byte [KbdFlags],5Bh ; Shift Alt Caps Scroll
25 jz auto_boot ; If neither, default boot
28 cmp word [NoEscape],0 ; If NOESCAPE, no prompt,
29 jne auto_boot ; always run default cmd
34 mov byte [FuncFlag],0 ; <Ctrl-F> not pressed
38 ; get the very first character -- we can either time
39 ; out, or receive a character press at this time. Some dorky BIOSes stuff
40 ; a return in the buffer on bootup, so wipe the keyboard buffer first.
42 clear_buffer: mov ah,11h ; Check for pending char
47 jmp short clear_buffer
49 ; For the first character, both KbdTimeout and
50 ; TotalTimeout apply; after that, only TotalTimeout.
53 mov eax,[TotalTimeout]
60 and dword [ThisKbdTo],0 ; For the next time...
65 got_ascii: cmp al,7Fh ; <DEL> == <BS>
70 cmp di,command_line ; Space must not be first
72 enter_char: test byte [FuncFlag],1
80 .not_ctrl_f: cmp di,max_cmd_len+command_line ; Check there's space
83 call writechr ; Echo to screen
85 not_ascii: mov byte [FuncFlag],0
88 cmp al,'F' & 1Fh ; <Ctrl-F>
90 cmp al,'U' & 1Fh ; <Ctrl-U>
91 je kill_command ; Kill input line
92 cmp al,'V' & 1Fh ; <Ctrl-V>
94 cmp al,'X' & 1Fh ; <Ctrl-X>
96 cmp al,08h ; Backspace
98 backspace: cmp di,command_line ; Make sure there is anything
99 je get_char ; to erase
100 dec di ; Unstore one character
101 mov si,wipe_char ; and erase it from the screen
114 mov byte [FuncFlag],1
118 ctrl_f_0: add al,10 ; <Ctrl-F>0 == F10
124 ; AL = 0 if we get here
130 show_help: ; AX = func key # (0 = F1, 9 = F10)
131 push di ; Save end-of-cmdline pointer
132 shl ax,FILENAME_MAX_LG2 ; Convert to pointer
135 cmp byte [di+NULLOFFSET],NULLFILE
136 je short fk_nofile ; Undefined F-key
138 jz short fk_nofile ; File not found
146 push di ; Command line write pointer
147 mov si,syslinux_banner
156 ; ... fall through ...
158 ; Write the boot prompt and command line again and
159 ; wait for input. Note that this expects the cursor
160 ; to already have been CRLF'd, and that the old value
161 ; of DI (the command line write pointer) is on the stack.
165 pop di ; Command line write pointer
167 mov byte [di],0 ; Null-terminate command line
169 call cwritestr ; Write command line so far
174 ; Jump here to run the default command line
179 mov cx,(max_cmd_len+4) >> 2
181 jmp short load_kernel
184 ; Jump here when the command line is completed
188 cmp di,command_line ; Did we just hit return?
190 xor al,al ; Store a final null
193 load_kernel: ; Load the kernel now
195 ; First we need to mangle the kernel name the way DOS would...
205 ; Fast-forward to first option (we start over from the beginning, since
206 ; mangle_name doesn't necessarily return a consistent ending state.)
211 clin_is_wsp: and al,al
216 clin_opt_ptr: dec si ; Point to first nonblank
217 mov [CmdOptPtr],si ; Save ptr to first option
219 ; If "allowoptions 0", put a null character here in order to ignore any
220 ; user-specified options.
222 mov ax,[AllowOptions]
229 ; Now check if it is a "virtual kernel"
232 xor si,si ; Beginning of vk_seg
234 cmp si,[VKernelBytes]
244 ; SI updated on return
246 sub di,cx ; Return to beginning of buf
256 ; We *are* using a "virtual kernel"
260 push word real_mode_seg
263 mov si,VKernelBuf+vk_append
264 mov cx,[VKernelBuf+vk_appendlen]
266 mov [CmdLinePtr],di ; Where to add rest of cmd
270 mov si,VKernelBuf+vk_rname
271 mov cx,FILENAME_MAX ; We need ECX == CX later
275 mov al,[VKernelBuf+vk_ipappend]
278 xor bx,bx ; Try only one version
280 %if IS_PXELINUX || IS_ISOLINUX
281 ; Is this a "localboot" pseudo-kernel?
283 cmp byte [VKernelBuf+vk_rname+4], 0
285 cmp byte [VKernelBuf+vk_rname], 0
287 jne get_kernel ; No, it's real, go get it
289 mov ax, [VKernelBuf+vk_rname+1]
298 ; Not a "virtual kernel" - check that's OK and construct the command line
300 cmp word [AllowImplicit],byte 0
316 ; Find the kernel on disk
318 get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/extension
319 %if IS_SYSLINUX || IS_MDSLINUX ; SYSLINUX has to deal with DOS mangled names...
320 mov eax,[KernelName+8] ; Save initial extension
321 mov [exten_table_end],eax ; Last case == initial ext.
323 mov di,KernelName+4*IS_PXELINUX
325 mov cx,FILENAME_MAX-5 ; Need 4 chars + null
326 repne scasb ; Scan for final null
328 dec di ; Point to final null
329 .no_skip: mov [KernelExtPtr],di
332 .search_loop: push bx
333 mov di,KernelName ; Search on disk
337 mov eax,[bx] ; Try a different extension
338 %if IS_SYSLINUX || IS_MDSLINUX
339 mov [KernelName+8],eax
341 mov si,[KernelExtPtr]
346 cmp bx,exten_table_end
347 jna .search_loop ; allow == case (final case)
348 ; Fall into bad_kernel
350 ; bad_kernel: Kernel image not found
351 ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
362 call unmangle_name ; Get human form
363 mov si,err_notfound ; Complain about missing kernel
368 jmp abort_load ; Ask user for clue
371 ; on_error: bad kernel, but we have onerror set
382 pop di ; <E> di == command_line
383 pop bx ; <D> bx == [OnerrorLen]
384 je bad_kernel.really ; Onerror matches command_line already
385 neg bx ; bx == -[OnerrorLen]
386 lea cx,[max_cmd_len+bx]
387 ; CX == max_cmd_len-[OnerrorLen]
388 mov di,command_line+max_cmd_len-1
389 mov byte [di+1],0 ; Enforce null-termination
392 rep movsb ; Make space in command_line
394 pop cx ; <C> cx == [OnerrorLen]
395 pop di ; <B> di == command_line
396 pop si ; <A> si == Onerror
401 ; kernel_corrupt: Called if the kernel file does not seem healthy
403 kernel_corrupt: mov si,err_notkernel
407 ; Get a key, observing ThisKbdTO and ThisTotalTO -- those are timeouts
408 ; which can be adjusted by the caller based on the corresponding
409 ; master variables; on return they're updated.
411 ; This cheats. If we say "no timeout" we actually get a timeout of
419 push word [BIOS_timer]
423 cmp ax,[BIOS_timer] ; Has the timer advanced?
427 dec dword [ThisKbdTo]
429 dec dword [ThisTotalTo]
434 pop cx ; Discard return address
436 mov si,Ontimeout ; Copy ontimeout command
438 mov cx,[OntimeoutLen] ; if we have one...
449 ; This is it! We have a name (and location on the disk)... let's load
450 ; that sucker!! First we have to decide what kind of file this is; base
451 ; that decision on the file extension. The following extensions are
452 ; recognized; case insensitive:
454 ; .com - COMBOOT image
455 ; .cbt - COMBOOT image
458 ; .0 - PXE bootstrap program (PXELINUX only)
460 ; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only)
461 ; .img - Floppy image (ISOLINUX only)
463 ; Anything else is assumed to be a Linux kernel.
472 ; Alternate entry point for which the return from
473 ; searchdir is stored in memory. This is used for
474 ; COMBOOT function INT 22h, AX=0016h.
477 mov dx,[Kernel_EAX+2]
485 mov [KernelCNameLen],di
488 %if IS_SYSLINUX || IS_MDSLINUX
489 mov ecx,[KernelName+7]
494 mov di,KernelName+4*IS_PXELINUX
500 .one_step: mov ecx,[di-4] ; 4 bytes before end
506 ; At this point, DX:AX contains the size of the kernel, and SI contains
507 ; the file handle/cluster pointer.
509 or ecx,20202000h ; Force lower case (except dot)
525 %if IS_SYSLINUX || IS_MDSLINUX
538 ; Otherwise Linux kernel
542 ThisKbdTo resd 1 ; Temporary holder for KbdTimeout
543 ThisTotalTo resd 1 ; Temporary holder for TotalTimeout
544 KernelExtPtr resw 1 ; During search, final null pointer
545 CmdOptPtr resw 1 ; Pointer to first option on cmd line
546 KbdFlags resb 1 ; Check for keyboard escapes
547 FuncFlag resb 1 ; Escape sequences received from keyboard