Add "onerror" configuration directive
[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                 DO_IDLE
63                 loop time_loop                  ; If so, decrement counter
64
65                 ; Timeout!!!!
66                 call vgahidecursor
67                 mov si,Ontimeout                ; Copy ontimeout command
68                 mov cx,[OntimeoutLen]           ; if we have one...
69                 rep movsb
70 .stddefault:
71                 jmp command_done
72
73 get_char_pop:   pop eax                         ; Clear stack
74 get_char:
75                 call vgashowcursor
76                 call getchar
77                 call vgahidecursor
78                 and al,al
79                 jz func_key
80
81 got_ascii:      cmp al,7Fh                      ; <DEL> == <BS>
82                 je backspace
83                 cmp al,' '                      ; ASCII?
84                 jb not_ascii
85                 ja enter_char
86                 cmp di,command_line             ; Space must not be first
87                 je short get_char
88 enter_char:     test byte [FuncFlag],1
89                 jz .not_ctrl_f
90                 mov byte [FuncFlag],0
91                 cmp al,'0'
92                 jb .not_ctrl_f
93                 je ctrl_f_0
94                 cmp al,'9'
95                 jbe ctrl_f
96 .not_ctrl_f:    cmp di,max_cmd_len+command_line ; Check there's space
97                 jnb short get_char
98                 stosb                           ; Save it
99                 call writechr                   ; Echo to screen
100                 jmp short get_char
101 not_ascii:      mov byte [FuncFlag],0
102                 cmp al,0Dh                      ; Enter
103                 je command_done
104                 cmp al,06h                      ; <Ctrl-F>
105                 je set_func_flag
106                 cmp al,16h                      ; <Ctrl-V>
107                 je print_version
108                 cmp al,08h                      ; Backspace
109                 jne get_char
110 backspace:      cmp di,command_line             ; Make sure there is anything
111                 je get_char                     ; to erase
112                 dec di                          ; Unstore one character
113                 mov si,wipe_char                ; and erase it from the screen
114                 call cwritestr
115                 jmp short get_char_2
116
117 set_func_flag:
118                 mov byte [FuncFlag],1
119 get_char_2:
120                 jmp short get_char
121
122 ctrl_f_0:       add al,10                       ; <Ctrl-F>0 == F10
123 ctrl_f:         sub al,'1'
124                 xor ah,ah
125                 jmp short show_help
126
127 func_key:
128                 ; AL = 0 if we get here
129                 xchg al,ah
130                 cmp al,68                       ; F10
131                 ja short get_char_2
132                 sub al,59                       ; F1
133                 jb short get_char_2
134 show_help:      ; AX = func key # (0 = F1, 9 = F10)
135                 push di                         ; Save end-of-cmdline pointer
136                 shl ax,FILENAME_MAX_LG2         ; Convert to pointer
137                 add ax,FKeyName
138                 xchg di,ax
139                 cmp byte [di],NULLFILE
140                 je short fk_nofile              ; Undefined F-key
141                 call searchdir
142                 jz short fk_nofile              ; File not found
143                 push si
144                 call crlf
145                 pop si
146                 call get_msg_file
147                 jmp short fk_wrcmd
148
149 print_version:
150                 push di                         ; Command line write pointer
151                 mov si,syslinux_banner
152                 call cwritestr
153                 mov si,copyright_str
154                 call cwritestr
155
156                 ; ... fall through ...
157
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.
162 fk_wrcmd:
163                 mov si,boot_prompt
164                 call cwritestr
165                 pop di                          ; Command line write pointer
166                 push di
167                 mov byte [di],0                 ; Null-terminate command line
168                 mov si,command_line
169                 call cwritestr                  ; Write command line so far
170 fk_nofile:      pop di
171                 jmp short get_char_2
172 auto_boot:
173                 mov si,default_cmd
174                 mov di,command_line
175                 mov cx,(max_cmd_len+4) >> 2
176                 rep movsd
177                 jmp short load_kernel
178 command_done:
179                 call crlf
180                 cmp di,command_line             ; Did we just hit return?
181                 je auto_boot
182                 xor al,al                       ; Store a final null
183                 stosb
184
185 load_kernel:                                    ; Load the kernel now
186 ;
187 ; First we need to mangle the kernel name the way DOS would...
188 ;
189                 mov si,command_line
190                 mov di,KernelName
191                 push si
192                 push di
193                 call mangle_name
194                 pop di
195                 pop si
196 ;
197 ; Fast-forward to first option (we start over from the beginning, since
198 ; mangle_name doesn't necessarily return a consistent ending state.)
199 ;
200 clin_non_wsp:   lodsb
201                 cmp al,' '
202                 ja clin_non_wsp
203 clin_is_wsp:    and al,al
204                 jz clin_opt_ptr
205                 lodsb
206                 cmp al,' '
207                 jbe clin_is_wsp
208 clin_opt_ptr:   dec si                          ; Point to first nonblank
209                 mov [CmdOptPtr],si              ; Save ptr to first option
210 ;
211 ; Now check if it is a "virtual kernel"
212 ;
213                 mov cx,[VKernelCtr]
214                 push ds
215                 push word vk_seg
216                 pop ds
217                 cmp cx,byte 0
218                 je not_vk
219                 xor si,si                       ; Point to first vkernel
220 vk_check:       pusha
221                 mov cx,FILENAME_MAX
222                 repe cmpsb                      ; Is this it?
223                 je vk_found
224                 popa
225                 add si,vk_size
226                 loop vk_check
227 not_vk:         pop ds
228 ;
229 ; Not a "virtual kernel" - check that's OK and construct the command line
230 ;
231                 cmp word [AllowImplicit],byte 0
232                 je bad_implicit
233                 push es
234                 push si
235                 push di
236                 mov di,real_mode_seg
237                 mov es,di
238                 mov si,AppendBuf
239                 mov di,cmd_line_here
240                 mov cx,[AppendLen]
241                 rep movsb
242                 mov [CmdLinePtr],di
243                 pop di
244                 pop si
245                 pop es
246 ;
247 ; Find the kernel on disk
248 ;
249 get_kernel:     mov byte [KernelName+FILENAME_MAX],0    ; Zero-terminate filename/extension
250 %if IS_SYSLINUX || IS_MDSLINUX                  ; SYSLINUX has to deal with DOS mangled names...
251                 mov eax,[KernelName+8]          ; Save initial extension
252                 mov [exten_table_end],eax       ; Last case == initial ext.
253 %else
254                 mov di,KernelName
255                 xor al,al
256                 mov cx,FILENAME_MAX-5           ; Need 4 chars + null
257                 repne scasb                     ; Scan for final null
258                 jne .no_skip
259                 dec di                          ; Point to final null 
260 .no_skip:       mov [KernelExtPtr],di
261 %endif
262                 mov bx,exten_table
263 .search_loop:   push bx
264                 mov di,KernelName               ; Search on disk
265                 call searchdir
266                 pop bx
267                 jnz kernel_good
268                 mov eax,[bx]                    ; Try a different extension
269 %if IS_SYSLINUX || IS_MDSLINUX
270                 mov [KernelName+8],eax
271 %else
272                 mov si,[KernelExtPtr]
273                 mov [si],eax
274                 mov byte [si+4],0
275 %endif
276                 add bx,byte 4
277                 cmp bx,exten_table_end
278                 jna .search_loop                ; allow == case (final case)
279                 ; Fall into bad_kernel
280 ;
281 ; bad_kernel: Kernel image not found
282 ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
283 ;
284 bad_implicit:
285 bad_kernel:
286                 mov cx,[OnerrorLen]
287                 and cx,cx
288                 jnz on_error
289 .really:
290                 mov si,KernelName
291                 mov di,KernelCName
292                 push di
293                 call unmangle_name              ; Get human form
294                 mov si,err_notfound             ; Complain about missing kernel
295                 call cwritestr
296                 pop si                          ; KernelCName
297                 call cwritestr
298                 mov si,crlf_msg
299                 jmp abort_load                  ; Ask user for clue
300
301 ;
302 ; on_error: bad kernel, but we have onerror set
303 ;
304 on_error:
305                 mov si,Onerror
306                 mov di,command_line
307                 push si                         ; <A>
308                 push di                         ; <B>
309                 push cx                         ; <C>
310                 push cx                         ; <D>
311                 push di                         ; <E>
312                 repe cmpsb
313                 pop di                          ; <E> di == command_line
314                 pop bx                          ; <D> bx == [OnerrorLen]
315                 je bad_kernel.really            ; Onerror matches command_line already
316                 neg bx                          ; bx == -[OnerrorLen]
317                 lea cx,[max_cmd_len+bx]
318                 ; CX == max_cmd_len-[OnerrorLen]
319                 mov di,command_line+max_cmd_len-1
320                 mov byte [di+1],0               ; Enforce null-termination
321                 lea si,[di+bx]
322                 std
323                 rep movsb                       ; Make space in command_line
324                 cld
325                 pop cx                          ; <C> cx == [OnerrorLen]
326                 pop di                          ; <B> di == command_line
327                 pop si                          ; <A> si  == Onerror
328                 rep movsb
329                 jmp load_kernel
330
331 ;
332 ; vk_found: We *are* using a "virtual kernel"
333 ;
334 vk_found:       popa
335                 push di
336                 mov di,VKernelBuf
337                 mov cx,vk_size >> 2
338                 rep movsd
339                 push es                         ; Restore old DS
340                 pop ds
341                 push es
342                 push word real_mode_seg
343                 pop es
344                 mov di,cmd_line_here
345                 mov si,VKernelBuf+vk_append
346                 mov cx,[VKernelBuf+vk_appendlen]
347                 rep movsb
348                 mov [CmdLinePtr],di             ; Where to add rest of cmd
349                 pop es
350                 pop di                          ; DI -> KernelName
351                 push di 
352                 mov si,VKernelBuf+vk_rname
353                 mov cx,FILENAME_MAX             ; We need ECX == CX later
354                 rep movsb
355                 pop di
356 %if IS_PXELINUX
357                 mov al,[VKernelBuf+vk_ipappend]
358                 mov [IPAppend],al
359 %endif
360                 xor bx,bx                       ; Try only one version
361
362 %if IS_SYSLINUX || IS_MDSLINUX
363                 jmp get_kernel
364 %else
365                 ; Is this a "localboot" pseudo-kernel?
366                 cmp byte [VKernelBuf+vk_rname], 0
367                 jne get_kernel          ; No, it's real, go get it
368
369                 mov ax, [VKernelBuf+vk_rname+1]
370                 jmp local_boot
371 %endif
372
373 ;
374 ; kernel_corrupt: Called if the kernel file does not seem healthy
375 ;
376 kernel_corrupt: mov si,err_notkernel
377                 jmp abort_load
378 ;
379 ; This is it!  We have a name (and location on the disk)... let's load
380 ; that sucker!!  First we have to decide what kind of file this is; base
381 ; that decision on the file extension.  The following extensions are
382 ; recognized; case insensitive:
383 ;
384 ; .com  - COMBOOT image
385 ; .cbt  - COMBOOT image
386 ; .c32  - COM32 image
387 ; .bs   - Boot sector
388 ; .0    - PXE bootstrap program (PXELINUX only)
389 ; .bin  - Boot sector
390 ; .bss  - Boot sector, but transfer over DOS superblock (SYSLINUX only)
391 ; .img  - Floppy image (ISOLINUX only)
392 ;
393 ; Anything else is assumed to be a Linux kernel.
394 ;
395 kernel_good:
396                 pusha
397                 mov si,KernelName
398                 mov di,KernelCName
399                 call unmangle_name
400                 sub di,KernelCName
401                 mov [KernelCNameLen],di
402                 popa
403                 
404 %if IS_SYSLINUX || IS_MDSLINUX
405                 mov ecx,[KernelName+7]
406                 mov cl,'.'
407 %else
408                 push di
409                 push ax
410                 mov di,KernelName
411                 xor al,al
412                 mov cx,FILENAME_MAX
413                 repne scasb
414                 jne .one_step
415                 dec di
416 .one_step:      mov ecx,[di-4]                  ; 4 bytes before end
417                 pop ax
418                 pop di
419 %endif
420
421 ;
422 ; At this point, DX:AX contains the size of the kernel, and SI contains
423 ; the file handle/cluster pointer.
424 ;
425                 or ecx,20202000h                ; Force lower case
426
427                 cmp ecx,'.com'
428                 je is_comboot_image
429                 cmp ecx,'.cbt'
430                 je is_comboot_image
431                 cmp ecx,'.c32'
432                 je is_com32_image
433 %if IS_ISOLINUX
434                 cmp ecx,'.img'
435                 je is_disk_image
436 %endif
437                 cmp ecx,'.bss'
438                 je is_bss_sector
439                 cmp ecx,'.bin'
440                 je is_bootsector
441 %if IS_SYSLINUX || IS_MDSLINUX
442                 cmp ecx,'.bs '
443                 je is_bootsector
444                 cmp ecx,'.0  '
445                 je is_bootsector
446 %else
447                 shr ecx,8
448                 cmp ecx,'.bs'
449                 je is_bootsector
450                 shr ecx,8
451                 cmp cx,'.0'
452                 je is_bootsector
453 %endif
454                 ; Otherwise Linux kernel
455