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