Across-the-board stealth whitespace cleanup
[profile/ivi/syslinux.git] / ui.inc
1 ;; $Id$
2 ;; -----------------------------------------------------------------------
3 ;;
4 ;;   Copyright 1994-2005 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 ;;   Boston 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],0        ; Force prompt?
24                 jnz enter_command
25                 test byte [KbdFlags],5Bh        ; Shift Alt Caps Scroll
26                 jz auto_boot                    ; If neither, default boot
27
28 enter_command:
29                 cmp word [NoEscape],0           ; If NOESCAPE, no prompt,
30                 jne auto_boot                   ; always run default cmd
31
32                 mov si,boot_prompt
33                 call cwritestr
34
35                 mov byte [FuncFlag],0           ; <Ctrl-F> not pressed
36                 mov di,command_line
37
38 ;
39 ; get the very first character -- we can either time
40 ; out, or receive a character press at this time.  Some dorky BIOSes stuff
41 ; a return in the buffer on bootup, so wipe the keyboard buffer first.
42 ;
43 clear_buffer:   mov ah,11h                      ; Check for pending char
44                 int 16h
45                 jz get_char_time
46                 mov ah,10h                      ; Get char
47                 int 16h
48                 jmp short clear_buffer
49
50                 ; For the first character, both KbdTimeout and
51                 ; TotalTimeout apply; after that, only TotalTimeout.
52
53 get_char_time:
54                 mov eax,[TotalTimeout]
55                 mov [ThisTotalTo],eax
56                 mov eax,[KbdTimeout]
57                 mov [ThisKbdTo],eax
58
59 get_char:
60                 call getchar_timeout
61                 and dword [ThisKbdTo],0         ; For the next time...
62
63                 and al,al
64                 jz func_key
65
66 got_ascii:      cmp al,7Fh                      ; <DEL> == <BS>
67                 je backspace
68                 cmp al,' '                      ; ASCII?
69                 jb not_ascii
70                 ja enter_char
71                 cmp di,command_line             ; Space must not be first
72                 je short get_char
73 enter_char:     test byte [FuncFlag],1
74                 jz .not_ctrl_f
75                 mov byte [FuncFlag],0
76                 cmp al,'0'
77                 jb .not_ctrl_f
78                 je ctrl_f_0
79                 cmp al,'9'
80                 jbe ctrl_f
81 .not_ctrl_f:    cmp di,max_cmd_len+command_line ; Check there's space
82                 jnb short get_char
83                 stosb                           ; Save it
84                 call writechr                   ; Echo to screen
85                 jmp short get_char
86 not_ascii:      mov byte [FuncFlag],0
87                 cmp al,0Dh                      ; Enter
88                 je command_done
89                 cmp al,'F' & 1Fh                ; <Ctrl-F>
90                 je set_func_flag
91                 cmp al,'U' & 1Fh                ; <Ctrl-U>
92                 je kill_command                 ; Kill input line
93                 cmp al,'V' & 1Fh                ; <Ctrl-V>
94                 je print_version
95                 cmp al,'X' & 1Fh                ; <Ctrl-X>
96                 je force_text_mode
97                 cmp al,08h                      ; Backspace
98                 jne get_char
99 backspace:      cmp di,command_line             ; Make sure there is anything
100                 je get_char                     ; to erase
101                 dec di                          ; Unstore one character
102                 mov si,wipe_char                ; and erase it from the screen
103                 call cwritestr
104                 jmp short get_char_2
105
106 kill_command:
107                 call crlf
108                 jmp enter_command
109
110 force_text_mode:
111                 call vgaclearmode
112                 jmp enter_command
113
114 set_func_flag:
115                 mov byte [FuncFlag],1
116 get_char_2:
117                 jmp short get_char
118
119 ctrl_f_0:       add al,10                       ; <Ctrl-F>0 == F10
120 ctrl_f:         sub al,'1'
121                 xor ah,ah
122                 jmp short show_help
123
124 func_key:
125                 ; AL = 0 if we get here
126                 xchg al,ah
127                 cmp al,68                       ; F10
128                 ja short get_char_2
129                 sub al,59                       ; F1
130                 jb short get_char_2
131 show_help:      ; AX = func key # (0 = F1, 9 = F10)
132                 push di                         ; Save end-of-cmdline pointer
133                 shl ax,FILENAME_MAX_LG2         ; Convert to pointer
134                 add ax,FKeyName
135                 xchg di,ax
136                 cmp byte [di+NULLOFFSET],NULLFILE
137                 je short fk_nofile              ; Undefined F-key
138                 call searchdir
139                 jz short fk_nofile              ; File not found
140                 push si
141                 call crlf
142                 pop si
143                 call get_msg_file
144                 jmp short fk_wrcmd
145
146 print_version:
147                 push di                         ; Command line write pointer
148                 mov si,syslinux_banner
149                 call cwritestr
150 %ifdef HAVE_BIOSNAME
151                 mov si,[BIOSName]
152                 call cwritestr
153 %endif
154                 mov si,copyright_str
155                 call cwritestr
156
157                 ; ... fall through ...
158
159                 ; Write the boot prompt and command line again and
160                 ; wait for input.  Note that this expects the cursor
161                 ; to already have been CRLF'd, and that the old value
162                 ; of DI (the command line write pointer) is on the stack.
163 fk_wrcmd:
164                 mov si,boot_prompt
165                 call cwritestr
166                 pop di                          ; Command line write pointer
167                 push di
168                 mov byte [di],0                 ; Null-terminate command line
169                 mov si,command_line
170                 call cwritestr                  ; Write command line so far
171 fk_nofile:      pop di
172                 jmp short get_char_2
173
174 ;
175 ; Jump here to run the default command line
176 ;
177 auto_boot:
178                 mov si,default_cmd
179                 mov di,command_line
180                 mov cx,(max_cmd_len+4) >> 2
181                 rep movsd
182                 jmp short load_kernel
183
184 ;
185 ; Jump here when the command line is completed
186 ;
187 command_done:
188                 call crlf
189                 cmp di,command_line             ; Did we just hit return?
190                 je auto_boot
191                 xor al,al                       ; Store a final null
192                 stosb
193
194 load_kernel:                                    ; Load the kernel now
195 ;
196 ; First we need to mangle the kernel name the way DOS would...
197 ;
198                 mov si,command_line
199                 mov di,KernelName
200                 push si
201                 push di
202                 call mangle_name
203                 pop di
204                 pop si
205 ;
206 ; Fast-forward to first option (we start over from the beginning, since
207 ; mangle_name doesn't necessarily return a consistent ending state.)
208 ;
209 clin_non_wsp:   lodsb
210                 cmp al,' '
211                 ja clin_non_wsp
212 clin_is_wsp:    and al,al
213                 jz clin_opt_ptr
214                 lodsb
215                 cmp al,' '
216                 jbe clin_is_wsp
217 clin_opt_ptr:   dec si                          ; Point to first nonblank
218                 mov [CmdOptPtr],si              ; Save ptr to first option
219 ;
220 ; If "allowoptions 0", put a null character here in order to ignore any
221 ; user-specified options.
222 ;
223                 mov ax,[AllowOptions]
224                 and ax,ax
225                 jnz clin_opt_ok
226                 mov [si],al
227 clin_opt_ok:
228
229 ;
230 ; Now check if it is a "virtual kernel"
231 ;
232 vk_check:
233                 xor si,si                       ; Beginning of vk_seg
234 .scan:
235                 cmp si,[VKernelBytes]
236                 jae .not_vk
237
238                 push ds
239                 push word vk_seg
240                 pop ds
241
242                 mov di,VKernelBuf
243                 call rllunpack
244                 pop ds
245                 ; SI updated on return
246
247                 sub di,cx                       ; Return to beginning of buf
248                 push si
249                 mov si,KernelName
250                 mov cx,FILENAME_MAX
251                 es repe cmpsb
252                 pop si
253                 je .found
254                 jmp .scan
255
256 ;
257 ; We *are* using a "virtual kernel"
258 ;
259 .found:
260                 push es
261                 push word real_mode_seg
262                 pop es
263                 mov di,cmd_line_here
264                 mov si,VKernelBuf+vk_append
265                 mov cx,[VKernelBuf+vk_appendlen]
266                 rep movsb
267                 mov [CmdLinePtr],di             ; Where to add rest of cmd
268                 pop es
269                 mov di,KernelName
270                 push di
271                 mov si,VKernelBuf+vk_rname
272                 mov cx,FILENAME_MAX             ; We need ECX == CX later
273                 rep movsb
274                 pop di
275 %if IS_PXELINUX
276                 mov al,[VKernelBuf+vk_ipappend]
277                 mov [IPAppend],al
278 %endif
279                 xor bx,bx                       ; Try only one version
280
281 %if IS_PXELINUX || IS_ISOLINUX
282                 ; Is this a "localboot" pseudo-kernel?
283 %if IS_PXELINUX
284                 cmp byte [VKernelBuf+vk_rname+4], 0
285 %else
286                 cmp byte [VKernelBuf+vk_rname], 0
287 %endif
288                 jne get_kernel          ; No, it's real, go get it
289
290                 mov ax, [VKernelBuf+vk_rname+1]
291                 jmp local_boot
292 %else
293                 jmp get_kernel
294 %endif
295
296 .not_vk:
297
298 ;
299 ; Not a "virtual kernel" - check that's OK and construct the command line
300 ;
301                 cmp word [AllowImplicit],byte 0
302                 je bad_implicit
303                 push es
304                 push si
305                 push di
306                 mov di,real_mode_seg
307                 mov es,di
308                 mov si,AppendBuf
309                 mov di,cmd_line_here
310                 mov cx,[AppendLen]
311                 rep movsb
312                 mov [CmdLinePtr],di
313                 pop di
314                 pop si
315                 pop es
316 ;
317 ; Find the kernel on disk
318 ;
319 get_kernel:     mov byte [KernelName+FILENAME_MAX],0    ; Zero-terminate filename/extension
320 %if IS_SYSLINUX || IS_MDSLINUX                  ; SYSLINUX has to deal with DOS mangled names...
321                 mov eax,[KernelName+8]          ; Save initial extension
322                 mov [exten_table_end],eax       ; Last case == initial ext.
323 %else
324                 mov di,KernelName+4*IS_PXELINUX
325                 xor al,al
326                 mov cx,FILENAME_MAX-5           ; Need 4 chars + null
327                 repne scasb                     ; Scan for final null
328                 jne .no_skip
329                 dec di                          ; Point to final null
330 .no_skip:       mov [KernelExtPtr],di
331 %endif
332                 mov bx,exten_table
333 .search_loop:   push bx
334                 mov di,KernelName               ; Search on disk
335                 call searchdir
336                 pop bx
337                 jnz kernel_good
338                 mov eax,[bx]                    ; Try a different extension
339 %if IS_SYSLINUX || IS_MDSLINUX
340                 mov [KernelName+8],eax
341 %else
342                 mov si,[KernelExtPtr]
343                 mov [si],eax
344                 mov byte [si+4],0
345 %endif
346                 add bx,byte 4
347                 cmp bx,exten_table_end
348                 jna .search_loop                ; allow == case (final case)
349                 ; Fall into bad_kernel
350 ;
351 ; bad_kernel: Kernel image not found
352 ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
353 ;
354 bad_implicit:
355 bad_kernel:
356                 mov cx,[OnerrorLen]
357                 and cx,cx
358                 jnz on_error
359 .really:
360                 mov si,KernelName
361                 mov di,KernelCName
362                 push di
363                 call unmangle_name              ; Get human form
364                 mov si,err_notfound             ; Complain about missing kernel
365                 call cwritestr
366                 pop si                          ; KernelCName
367                 call cwritestr
368                 mov si,crlf_msg
369                 jmp abort_load                  ; Ask user for clue
370
371 ;
372 ; on_error: bad kernel, but we have onerror set
373 ;
374 on_error:
375                 mov si,Onerror
376                 mov di,command_line
377                 push si                         ; <A>
378                 push di                         ; <B>
379                 push cx                         ; <C>
380                 push cx                         ; <D>
381                 push di                         ; <E>
382                 repe cmpsb
383                 pop di                          ; <E> di == command_line
384                 pop bx                          ; <D> bx == [OnerrorLen]
385                 je bad_kernel.really            ; Onerror matches command_line already
386                 neg bx                          ; bx == -[OnerrorLen]
387                 lea cx,[max_cmd_len+bx]
388                 ; CX == max_cmd_len-[OnerrorLen]
389                 mov di,command_line+max_cmd_len-1
390                 mov byte [di+1],0               ; Enforce null-termination
391                 lea si,[di+bx]
392                 std
393                 rep movsb                       ; Make space in command_line
394                 cld
395                 pop cx                          ; <C> cx == [OnerrorLen]
396                 pop di                          ; <B> di == command_line
397                 pop si                          ; <A> si  == Onerror
398                 rep movsb
399                 jmp load_kernel
400
401 ;
402 ; kernel_corrupt: Called if the kernel file does not seem healthy
403 ;
404 kernel_corrupt: mov si,err_notkernel
405                 jmp abort_load
406
407 ;
408 ; Get a key, observing ThisKbdTO and ThisTotalTO -- those are timeouts
409 ; which can be adjusted by the caller based on the corresponding
410 ; master variables; on return they're updated.
411 ;
412 ; This cheats.  If we say "no timeout" we actually get a timeout of
413 ; 7.5 years.
414 ;
415 getchar_timeout:
416                 call vgashowcursor
417                 RESET_IDLE
418
419 .loop:
420                 push word [BIOS_timer]
421                 call pollchar
422                 jnz .got_char
423                 pop ax
424                 cmp ax,[BIOS_timer]             ; Has the timer advanced?
425                 je .loop
426                 DO_IDLE
427
428                 dec dword [ThisKbdTo]
429                 jz .timeout
430                 dec dword [ThisTotalTo]
431                 jnz .loop
432
433 .timeout:
434                 ; Timeout!!!!
435                 pop cx                          ; Discard return address
436                 call vgahidecursor
437                 mov si,Ontimeout                ; Copy ontimeout command
438                 mov di,command_line
439                 mov cx,[OntimeoutLen]           ; if we have one...
440                 rep movsb
441                 jmp command_done
442
443 .got_char:
444                 pop cx                          ; Discard
445                 call getchar
446                 call vgahidecursor
447                 ret
448
449 ;
450 ; This is it!  We have a name (and location on the disk)... let's load
451 ; that sucker!!  First we have to decide what kind of file this is; base
452 ; that decision on the file extension.  The following extensions are
453 ; recognized; case insensitive:
454 ;
455 ; .com  - COMBOOT image
456 ; .cbt  - COMBOOT image
457 ; .c32  - COM32 image
458 ; .bs   - Boot sector
459 ; .0    - PXE bootstrap program (PXELINUX only)
460 ; .bin  - Boot sector
461 ; .bss  - Boot sector, but transfer over DOS superblock (SYSLINUX only)
462 ; .img  - Floppy image (ISOLINUX only)
463 ;
464 ; Anything else is assumed to be a Linux kernel.
465 ;
466                 section .bss
467                 alignb 4
468 Kernel_EAX      resd 1
469 Kernel_SI       resw 1
470
471                 section .text
472 kernel_good_saved:
473                 ; Alternate entry point for which the return from
474                 ; searchdir is stored in memory.  This is used for
475                 ; COMBOOT function INT 22h, AX=0016h.
476                 mov si,[Kernel_SI]
477                 mov eax,[Kernel_EAX]
478                 mov dx,[Kernel_EAX+2]
479
480 kernel_good:
481                 pusha
482                 mov si,KernelName
483                 mov di,KernelCName
484                 call unmangle_name
485                 sub di,KernelCName
486                 mov [KernelCNameLen],di
487                 popa
488
489 %if IS_SYSLINUX || IS_MDSLINUX
490                 mov ecx,[KernelName+7]
491                 mov cl,'.'
492 %else
493                 push di
494                 push ax
495                 mov di,KernelName+4*IS_PXELINUX
496                 xor al,al
497                 mov cx,FILENAME_MAX
498                 repne scasb
499                 jne .one_step
500                 dec di
501 .one_step:      mov ecx,[di-4]                  ; 4 bytes before end
502                 pop ax
503                 pop di
504 %endif
505
506 ;
507 ; At this point, DX:AX contains the size of the kernel, and SI contains
508 ; the file handle/cluster pointer.
509 ;
510                 or ecx,20202000h                ; Force lower case
511
512                 cmp ecx,'.com'
513                 je is_comboot_image
514                 cmp ecx,'.cbt'
515                 je is_comboot_image
516                 cmp ecx,'.c32'
517                 je is_com32_image
518 %if IS_ISOLINUX
519                 cmp ecx,'.img'
520                 je is_disk_image
521 %endif
522                 cmp ecx,'.bss'
523                 je is_bss_sector
524                 cmp ecx,'.bin'
525                 je is_bootsector
526 %if IS_SYSLINUX || IS_MDSLINUX
527                 cmp ecx,'.bs '
528                 je is_bootsector
529                 cmp ecx,'.0  '
530                 je is_bootsector
531 %else
532                 shr ecx,8
533                 cmp ecx,'.bs'
534                 je is_bootsector
535                 shr ecx,8
536                 cmp cx,'.0'
537                 je is_bootsector
538 %endif
539                 ; Otherwise Linux kernel
540
541                 section .bss
542                 alignb 4
543 ThisKbdTo       resd 1                  ; Temporary holder for KbdTimeout
544 ThisTotalTo     resd 1                  ; Temporary holder for TotalTimeout
545 KernelExtPtr    resw 1                  ; During search, final null pointer
546 CmdOptPtr       resw 1                  ; Pointer to first option on cmd line
547 KbdFlags        resb 1                  ; Check for keyboard escapes
548 FuncFlag        resb 1                  ; Escape sequences received from keyboard
549
550                 section .text