Fix "timeoutcmd"
[profile/ivi/syslinux.git] / ui.inc
1 ;; $Id$
2 ;; -----------------------------------------------------------------------
3 ;;   
4 ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
5 ;;
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 ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
10 ;;   (at your option) any later version; incorporated herein by reference.
11 ;;
12 ;; -----------------------------------------------------------------------
13
14 ;
15 ; This file should be entered with the config file open (for getc)
16 ;
17                 call parse_config               ; Parse configuration file
18 no_config_file:
19 ;
20 ; Check whether or not we are supposed to display the boot prompt.
21 ;
22 check_for_key:
23                 cmp word [ForcePrompt],byte 0   ; Force prompt?
24                 jnz enter_command
25                 test byte [KbdFlags],5Bh        ; Caps, Scroll, Shift, Alt
26                 jz auto_boot                    ; If neither, default boot
27
28 enter_command:
29                 mov si,boot_prompt
30                 call cwritestr
31
32                 mov byte [FuncFlag],0           ; <Ctrl-F> not pressed
33                 mov di,command_line
34 ;
35 ; get the very first character -- we can either time
36 ; out, or receive a character press at this time.  Some dorky BIOSes stuff
37 ; a return in the buffer on bootup, so wipe the keyboard buffer first.
38 ;
39 clear_buffer:   mov ah,1                        ; Check for pending char
40                 int 16h
41                 jz get_char_time
42                 xor ax,ax                       ; Get char
43                 int 16h
44                 jmp short clear_buffer
45 get_char_time:  
46                 call vgashowcursor
47                 mov cx,[KbdTimeOut]
48                 and cx,cx
49                 jz get_char                     ; Timeout == 0 -> no timeout
50                 inc cx                          ; The first loop will happen
51                                                 ; immediately as we don't
52                                                 ; know the appropriate DX value
53 time_loop:      push cx
54 tick_loop:      push dx
55                 call pollchar
56                 jnz get_char_pop
57                 mov dx,[BIOS_timer]             ; Get time "of day"
58                 pop ax
59                 cmp dx,ax                       ; Has the timer advanced?
60                 je tick_loop
61                 pop cx
62                 loop time_loop                  ; If so, decrement counter
63
64                 ; Timeout!!!!
65                 call vgahidecursor
66                 mov si,TimeOutCmd               ; Copy timeoutcommand if we have one...
67                 mov cx,[TimeOutCmdLen]
68                 rep movsb
69 .stddefault:
70                 jmp command_done
71
72 get_char_pop:   pop eax                         ; Clear stack
73 get_char:
74                 call vgashowcursor
75                 call getchar
76                 call vgahidecursor
77                 and al,al
78                 jz func_key
79
80 got_ascii:      cmp al,7Fh                      ; <DEL> == <BS>
81                 je backspace
82                 cmp al,' '                      ; ASCII?
83                 jb not_ascii
84                 ja enter_char
85                 cmp di,command_line             ; Space must not be first
86                 je short get_char
87 enter_char:     test byte [FuncFlag],1
88                 jz .not_ctrl_f
89                 mov byte [FuncFlag],0
90                 cmp al,'0'
91                 jb .not_ctrl_f
92                 je ctrl_f_0
93                 cmp al,'9'
94                 jbe ctrl_f
95 .not_ctrl_f:    cmp di,max_cmd_len+command_line ; Check there's space
96                 jnb short get_char
97                 stosb                           ; Save it
98                 call writechr                   ; Echo to screen
99                 jmp short get_char
100 not_ascii:      mov byte [FuncFlag],0
101                 cmp al,0Dh                      ; Enter
102                 je command_done
103                 cmp al,06h                      ; <Ctrl-F>
104                 je set_func_flag
105                 cmp al,16h                      ; <Ctrl-V>
106                 je print_version
107                 cmp al,08h                      ; Backspace
108                 jne get_char
109 backspace:      cmp di,command_line             ; Make sure there is anything
110                 je get_char                     ; to erase
111                 dec di                          ; Unstore one character
112                 mov si,wipe_char                ; and erase it from the screen
113                 call cwritestr
114                 jmp short get_char_2
115
116 set_func_flag:
117                 mov byte [FuncFlag],1
118 get_char_2:
119                 jmp short get_char
120
121 ctrl_f_0:       add al,10                       ; <Ctrl-F>0 == F10
122 ctrl_f:         sub al,'1'
123                 xor ah,ah
124                 jmp short show_help
125
126 func_key:
127                 ; AL = 0 if we get here
128                 xchg al,ah
129                 cmp al,68                       ; F10
130                 ja short get_char_2
131                 sub al,59                       ; F1
132                 jb short get_char_2
133 show_help:      ; AX = func key # (0 = F1, 9 = F10)
134                 push di                         ; Save end-of-cmdline pointer
135                 shl ax,FILENAME_MAX_LG2         ; Convert to pointer
136                 add ax,FKeyName
137                 xchg di,ax
138                 cmp byte [di],NULLFILE
139                 je short fk_nofile              ; Undefined F-key
140                 call searchdir
141                 jz short fk_nofile              ; File not found
142                 push si
143                 call crlf
144                 pop si
145                 call get_msg_file
146                 jmp short fk_wrcmd
147
148 print_version:
149                 push di                         ; Command line write pointer
150                 mov si,syslinux_banner
151                 call cwritestr
152                 mov si,copyright_str
153                 call cwritestr
154
155                 ; ... fall through ...
156
157                 ; Write the boot prompt and command line again and
158                 ; wait for input.  Note that this expects the cursor
159                 ; to already have been CRLF'd, and that the old value
160                 ; of DI (the command line write pointer) is on the stack.
161 fk_wrcmd:
162                 mov si,boot_prompt
163                 call cwritestr
164                 pop di                          ; Command line write pointer
165                 push di
166                 mov byte [di],0                 ; Null-terminate command line
167                 mov si,command_line
168                 call cwritestr                  ; Write command line so far
169 fk_nofile:      pop di
170                 jmp short get_char_2
171 auto_boot:
172                 mov si,default_cmd
173                 mov di,command_line
174                 mov cx,(max_cmd_len+4) >> 2
175                 rep movsd
176                 jmp short load_kernel
177 command_done:
178                 call crlf
179                 cmp di,command_line             ; Did we just hit return?
180                 je auto_boot
181                 xor al,al                       ; Store a final null
182                 stosb
183
184 load_kernel:                                    ; Load the kernel now
185 ;
186 ; First we need to mangle the kernel name the way DOS would...
187 ;
188                 mov si,command_line
189                 mov di,KernelName
190                 push si
191                 push di
192                 call mangle_name
193                 pop di
194                 pop si
195 ;
196 ; Fast-forward to first option (we start over from the beginning, since
197 ; mangle_name doesn't necessarily return a consistent ending state.)
198 ;
199 clin_non_wsp:   lodsb
200                 cmp al,' '
201                 ja clin_non_wsp
202 clin_is_wsp:    and al,al
203                 jz clin_opt_ptr
204                 lodsb
205                 cmp al,' '
206                 jbe clin_is_wsp
207 clin_opt_ptr:   dec si                          ; Point to first nonblank
208                 mov [CmdOptPtr],si              ; Save ptr to first option
209 ;
210 ; Now check if it is a "virtual kernel"
211 ;
212                 mov cx,[VKernelCtr]
213                 push ds
214                 push word vk_seg
215                 pop ds
216                 cmp cx,byte 0
217                 je not_vk
218                 xor si,si                       ; Point to first vkernel
219 vk_check:       pusha
220                 mov cx,FILENAME_MAX
221                 repe cmpsb                      ; Is this it?
222                 je vk_found
223                 popa
224                 add si,vk_size
225                 loop vk_check
226 not_vk:         pop ds
227 ;
228 ; Not a "virtual kernel" - check that's OK and construct the command line
229 ;
230                 cmp word [AllowImplicit],byte 0
231                 je bad_implicit
232                 push es
233                 push si
234                 push di
235                 mov di,real_mode_seg
236                 mov es,di
237                 mov si,AppendBuf
238                 mov di,cmd_line_here
239                 mov cx,[AppendLen]
240                 rep movsb
241                 mov [CmdLinePtr],di
242                 pop di
243                 pop si
244                 pop es
245 ;
246 ; Find the kernel on disk
247 ;
248 get_kernel:     mov byte [KernelName+FILENAME_MAX],0    ; Zero-terminate filename/extension
249 %if IS_SYSLINUX || IS_MDSLINUX                  ; SYSLINUX has to deal with DOS mangled names...
250                 mov eax,[KernelName+8]          ; Save initial extension
251                 mov [exten_table_end],eax       ; Last case == initial ext.
252 %else
253                 mov di,KernelName
254                 xor al,al
255                 mov cx,FILENAME_MAX-5           ; Need 4 chars + null
256                 repne scasb                     ; Scan for final null
257                 jne .no_skip
258                 dec di                          ; Point to final null 
259 .no_skip:       mov [KernelExtPtr],di
260 %endif
261                 mov bx,exten_table
262 .search_loop:   push bx
263                 mov di,KernelName               ; Search on disk
264                 call searchdir
265                 pop bx
266                 jnz kernel_good
267                 mov eax,[bx]                    ; Try a different extension
268 %if IS_SYSLINUX || IS_MDSLINUX
269                 mov [KernelName+8],eax
270 %else
271                 mov si,[KernelExtPtr]
272                 mov [si],eax
273                 mov byte [si+4],0
274 %endif
275                 add bx,byte 4
276                 cmp bx,exten_table_end
277                 jna .search_loop                ; allow == case (final case)
278 bad_kernel:     
279                 mov si,KernelName
280                 mov di,KernelCName
281                 push di
282                 call unmangle_name              ; Get human form
283                 mov si,err_notfound             ; Complain about missing kernel
284                 call cwritestr
285                 pop si                          ; KernelCName
286                 call cwritestr
287                 mov si,crlf_msg
288                 jmp abort_load                  ; Ask user for clue
289 ;
290 ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
291 ;
292 bad_implicit:   mov si,KernelName               ; For the error message
293                 mov di,KernelCName
294                 call unmangle_name
295                 jmp short bad_kernel
296 ;
297 ; vk_found: We *are* using a "virtual kernel"
298 ;
299 vk_found:       popa
300                 push di
301                 mov di,VKernelBuf
302                 mov cx,vk_size >> 2
303                 rep movsd
304                 push es                         ; Restore old DS
305                 pop ds
306                 push es
307                 push word real_mode_seg
308                 pop es
309                 mov di,cmd_line_here
310                 mov si,VKernelBuf+vk_append
311                 mov cx,[VKernelBuf+vk_appendlen]
312                 rep movsb
313                 mov [CmdLinePtr],di             ; Where to add rest of cmd
314                 pop es
315                 pop di                          ; DI -> KernelName
316                 push di 
317                 mov si,VKernelBuf+vk_rname
318                 mov cx,FILENAME_MAX             ; We need ECX == CX later
319                 rep movsb
320                 pop di
321 %if IS_PXELINUX
322                 mov al,[VKernelBuf+vk_ipappend]
323                 mov [IPAppend],al
324 %endif
325                 xor bx,bx                       ; Try only one version
326
327 %if IS_SYSLINUX || IS_MDSLINUX
328                 jmp get_kernel
329 %else
330                 ; Is this a "localboot" pseudo-kernel?
331                 cmp byte [VKernelBuf+vk_rname], 0
332                 jne get_kernel          ; No, it's real, go get it
333
334                 mov ax, [VKernelBuf+vk_rname+1]
335                 jmp local_boot
336 %endif
337
338 ;
339 ; kernel_corrupt: Called if the kernel file does not seem healthy
340 ;
341 kernel_corrupt: mov si,err_notkernel
342                 jmp abort_load
343 ;
344 ; This is it!  We have a name (and location on the disk)... let's load
345 ; that sucker!!  First we have to decide what kind of file this is; base
346 ; that decision on the file extension.  The following extensions are
347 ; recognized; case insensitive:
348 ;
349 ; .com  - COMBOOT image
350 ; .cbt  - COMBOOT image
351 ; .c32  - COM32 image
352 ; .bs   - Boot sector
353 ; .0    - PXE bootstrap program (PXELINUX only)
354 ; .bin  - Boot sector
355 ; .bss  - Boot sector, but transfer over DOS superblock (SYSLINUX only)
356 ; .img  - Floppy image (ISOLINUX only)
357 ;
358 ; Anything else is assumed to be a Linux kernel.
359 ;
360 kernel_good:
361                 pusha
362                 mov si,KernelName
363                 mov di,KernelCName
364                 call unmangle_name
365                 sub di,KernelCName
366                 mov [KernelCNameLen],di
367                 popa
368                 
369 %if IS_SYSLINUX || IS_MDSLINUX
370                 mov ecx,[KernelName+7]
371                 mov cl,'.'
372 %else
373                 push di
374                 push ax
375                 mov di,KernelName
376                 xor al,al
377                 mov cx,FILENAME_MAX
378                 repne scasb
379                 jne .one_step
380                 dec di
381 .one_step:      mov ecx,[di-4]                  ; 4 bytes before end
382                 pop ax
383                 pop di
384 %endif
385
386 ;
387 ; At this point, DX:AX contains the size of the kernel, and SI contains
388 ; the file handle/cluster pointer.
389 ;
390                 or ecx,20202000h                ; Force lower case
391
392                 cmp ecx,'.com'
393                 je is_comboot_image
394                 cmp ecx,'.cbt'
395                 je is_comboot_image
396                 cmp ecx,'.c32'
397                 je is_com32_image
398 %if IS_ISOLINUX
399                 cmp ecx,'.img'
400                 je is_disk_image
401 %endif
402                 cmp ecx,'.bss'
403                 je is_bss_sector
404                 cmp ecx,'.bin'
405                 je is_bootsector
406 %if IS_SYSLINUX || IS_MDSLINUX
407                 cmp ecx,'.bs '
408                 je is_bootsector
409                 cmp ecx,'.0  '
410                 je is_bootsector
411 %else
412                 shr ecx,8
413                 cmp ecx,'.bs'
414                 je is_bootsector
415                 shr ecx,8
416                 cmp cx,'.0'
417                 je is_bootsector
418 %endif
419                 ; Otherwise Linux kernel
420