2 ;; -----------------------------------------------------------------------
4 ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
6 ;; This program is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 ;; Boston MA 02111-1307, USA; either version 2 of the License, or
10 ;; (at your option) any later version; incorporated herein by reference.
12 ;; -----------------------------------------------------------------------
15 ; This file should be entered with the config file open (for getc)
17 call parse_config ; Parse configuration file
20 ; Check whether or not we are supposed to display the boot prompt.
23 cmp word [ForcePrompt],byte 0 ; Force prompt?
27 jz auto_boot ; If neither, default boot
33 mov byte [FuncFlag],0 ; <Ctrl-F> not pressed
36 ; get the very first character -- we can either time
37 ; out, or receive a character press at this time. Some dorky BIOSes stuff
38 ; a return in the buffer on bootup, so wipe the keyboard buffer first.
40 clear_buffer: mov ah,11h ; Check for pending char
45 jmp short clear_buffer
51 jz get_char ; Timeout == 0 -> no timeout
52 inc cx ; The first loop will happen
53 ; immediately as we don't
54 ; know the appropriate DX value
59 mov dx,[BIOS_timer] ; Get time "of day"
61 cmp dx,ax ; Has the timer advanced?
65 loop time_loop ; If so, decrement counter
69 mov si,Ontimeout ; Copy ontimeout command
70 mov cx,[OntimeoutLen] ; if we have one...
75 get_char_pop: pop eax ; Clear stack
83 got_ascii: cmp al,7Fh ; <DEL> == <BS>
88 cmp di,command_line ; Space must not be first
90 enter_char: test byte [FuncFlag],1
98 .not_ctrl_f: cmp di,max_cmd_len+command_line ; Check there's space
101 call writechr ; Echo to screen
103 not_ascii: mov byte [FuncFlag],0
106 cmp al,'F' & 1Fh ; <Ctrl-F>
108 cmp al,'U' & 1Fh ; <Ctrl-U>
109 je kill_command ; Kill input line
110 cmp al,'V' & 1Fh ; <Ctrl-V>
112 cmp al,'X' & 1Fh ; <Ctrl-X>
114 cmp al,08h ; Backspace
116 backspace: cmp di,command_line ; Make sure there is anything
117 je get_char ; to erase
118 dec di ; Unstore one character
119 mov si,wipe_char ; and erase it from the screen
132 mov byte [FuncFlag],1
136 ctrl_f_0: add al,10 ; <Ctrl-F>0 == F10
142 ; AL = 0 if we get here
148 show_help: ; AX = func key # (0 = F1, 9 = F10)
149 push di ; Save end-of-cmdline pointer
150 shl ax,FILENAME_MAX_LG2 ; Convert to pointer
153 cmp byte [di+NULLOFFSET],NULLFILE
154 je short fk_nofile ; Undefined F-key
156 jz short fk_nofile ; File not found
164 push di ; Command line write pointer
165 mov si,syslinux_banner
170 ; ... fall through ...
172 ; Write the boot prompt and command line again and
173 ; wait for input. Note that this expects the cursor
174 ; to already have been CRLF'd, and that the old value
175 ; of DI (the command line write pointer) is on the stack.
179 pop di ; Command line write pointer
181 mov byte [di],0 ; Null-terminate command line
183 call cwritestr ; Write command line so far
189 mov cx,(max_cmd_len+4) >> 2
191 jmp short load_kernel
194 cmp di,command_line ; Did we just hit return?
196 xor al,al ; Store a final null
199 load_kernel: ; Load the kernel now
201 ; First we need to mangle the kernel name the way DOS would...
211 ; Fast-forward to first option (we start over from the beginning, since
212 ; mangle_name doesn't necessarily return a consistent ending state.)
217 clin_is_wsp: and al,al
222 clin_opt_ptr: dec si ; Point to first nonblank
223 mov [CmdOptPtr],si ; Save ptr to first option
225 ; If "allowoptions 0", put a null character here in order to ignore any
226 ; user-specified options.
228 mov ax,[AllowOptions]
235 ; Now check if it is a "virtual kernel"
238 xor si,si ; Beginning of vk_seg
240 cmp si,[VKernelBytes]
250 ; SI updated on return
252 sub di,cx ; Return to beginning of buf
262 ; We *are* using a "virtual kernel"
266 push word real_mode_seg
269 mov si,VKernelBuf+vk_append
270 mov cx,[VKernelBuf+vk_appendlen]
272 mov [CmdLinePtr],di ; Where to add rest of cmd
276 mov si,VKernelBuf+vk_rname
277 mov cx,FILENAME_MAX ; We need ECX == CX later
281 mov al,[VKernelBuf+vk_ipappend]
284 xor bx,bx ; Try only one version
286 %if IS_PXELINUX || IS_ISOLINUX
287 ; Is this a "localboot" pseudo-kernel?
289 cmp byte [VKernelBuf+vk_rname+4], 0
291 cmp byte [VKernelBuf+vk_rname], 0
293 jne get_kernel ; No, it's real, go get it
295 mov ax, [VKernelBuf+vk_rname+1]
304 ; Not a "virtual kernel" - check that's OK and construct the command line
306 cmp word [AllowImplicit],byte 0
322 ; Find the kernel on disk
324 get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/extension
325 %if IS_SYSLINUX || IS_MDSLINUX ; SYSLINUX has to deal with DOS mangled names...
326 mov eax,[KernelName+8] ; Save initial extension
327 mov [exten_table_end],eax ; Last case == initial ext.
329 mov di,KernelName+4*IS_PXELINUX
331 mov cx,FILENAME_MAX-5 ; Need 4 chars + null
332 repne scasb ; Scan for final null
334 dec di ; Point to final null
335 .no_skip: mov [KernelExtPtr],di
338 .search_loop: push bx
339 mov di,KernelName ; Search on disk
343 mov eax,[bx] ; Try a different extension
344 %if IS_SYSLINUX || IS_MDSLINUX
345 mov [KernelName+8],eax
347 mov si,[KernelExtPtr]
352 cmp bx,exten_table_end
353 jna .search_loop ; allow == case (final case)
354 ; Fall into bad_kernel
356 ; bad_kernel: Kernel image not found
357 ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
368 call unmangle_name ; Get human form
369 mov si,err_notfound ; Complain about missing kernel
374 jmp abort_load ; Ask user for clue
377 ; on_error: bad kernel, but we have onerror set
388 pop di ; <E> di == command_line
389 pop bx ; <D> bx == [OnerrorLen]
390 je bad_kernel.really ; Onerror matches command_line already
391 neg bx ; bx == -[OnerrorLen]
392 lea cx,[max_cmd_len+bx]
393 ; CX == max_cmd_len-[OnerrorLen]
394 mov di,command_line+max_cmd_len-1
395 mov byte [di+1],0 ; Enforce null-termination
398 rep movsb ; Make space in command_line
400 pop cx ; <C> cx == [OnerrorLen]
401 pop di ; <B> di == command_line
402 pop si ; <A> si == Onerror
407 ; kernel_corrupt: Called if the kernel file does not seem healthy
409 kernel_corrupt: mov si,err_notkernel
412 ; This is it! We have a name (and location on the disk)... let's load
413 ; that sucker!! First we have to decide what kind of file this is; base
414 ; that decision on the file extension. The following extensions are
415 ; recognized; case insensitive:
417 ; .com - COMBOOT image
418 ; .cbt - COMBOOT image
421 ; .0 - PXE bootstrap program (PXELINUX only)
423 ; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only)
424 ; .img - Floppy image (ISOLINUX only)
426 ; Anything else is assumed to be a Linux kernel.
434 mov [KernelCNameLen],di
437 %if IS_SYSLINUX || IS_MDSLINUX
438 mov ecx,[KernelName+7]
443 mov di,KernelName+4*IS_PXELINUX
449 .one_step: mov ecx,[di-4] ; 4 bytes before end
455 ; At this point, DX:AX contains the size of the kernel, and SI contains
456 ; the file handle/cluster pointer.
458 or ecx,20202000h ; Force lower case
474 %if IS_SYSLINUX || IS_MDSLINUX
487 ; Otherwise Linux kernel
490 KbdFlagMask db 5Bh ; Caps, Scroll, Shift, Alt
494 KernelExtPtr resw 1 ; During search, final null pointer
495 CmdOptPtr resw 1 ; Pointer to first option on cmd line
496 KbdFlags resb 1 ; Check for keyboard escapes
497 FuncFlag resb 1 ; Escape sequences received from keyboard