pxe, tftp: make TimeoutTable static
[syslinux.git] / core / ui.inc
blob6ef24984add88d272d7db578cc82393dbb9b5fc5
1 ;; -----------------------------------------------------------------------
2 ;;
3 ;;   Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
4 ;;   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
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.
12 ;; -----------------------------------------------------------------------
15 ; This file should be entered with the config file open (for getc)
17 load_config_file:
18                 call parse_config               ; Parse configuration file
19 no_config_file:
21                 call adv_init
23 ; Check for an ADV boot-once entry
25                 mov dl,ADV_BOOTONCE
26                 call adv_get
27                 jcxz .no_bootonce
29 .have_bootone:
30                 ; We apparently have a boot-once set; clear it and
31                 ; then execute the boot-once...
33                 ; Save the boot-once data; SI = data, CX = length
34                 mov di,command_line
35                 rep movsb
36                 xor ax,ax
37                 stosb
39                 ; Clear the boot-once data from the ADV
40                 xor cx,cx                       ; Set to zero = delete
41                 call adv_set
42                 jc .err
43                 call adv_write
44 .err:           jmp load_kernel
46 .no_bootonce:
49 ; Check whether or not we are supposed to display the boot prompt.
51 check_for_key:
52                 test byte [KbdFlags],5Bh        ; Shift Alt Caps Scroll
53                 jnz enter_command
54                 cmp word [ForcePrompt],0        ; Force prompt?
55                 jz auto_boot
56                 cmp word [DefaultLevel],1       ; Active UI statement?
57                 ja auto_boot
59 enter_command:
60                 cmp word [NoEscape],0           ; If NOESCAPE, no prompt,
61                 jne auto_boot                   ; always run default cmd
63                 mov si,boot_prompt
64                 call writestr
66                 mov byte [FuncFlag],0           ; <Ctrl-F> not pressed
67                 mov di,command_line
70 ; get the very first character -- we can either time
71 ; out, or receive a character press at this time.  Some dorky BIOSes stuff
72 ; a return in the buffer on bootup, so wipe the keyboard buffer first.
74 clear_buffer:   mov ah,11h                      ; Check for pending char
75                 int 16h
76                 jz get_char_time
77                 mov ah,10h                      ; Get char
78                 int 16h
79                 jmp short clear_buffer
81                 ; For the first character, both KbdTimeout and
82                 ; TotalTimeout apply; after that, only TotalTimeout.
84 get_char_time:
85                 mov eax,[TotalTimeout]
86                 mov [ThisTotalTo],eax
87                 mov eax,[KbdTimeout]
88                 mov [ThisKbdTo],eax
90 get_char:
91                 call getchar_timeout
92                 and dword [ThisKbdTo],0         ; For the next time...
94                 and al,al
95                 jz func_key
97 got_ascii:      cmp al,7Fh                      ; <DEL> == <BS>
98                 je backspace
99                 cmp al,' '                      ; ASCII?
100                 jb not_ascii
101                 ja enter_char
102                 cmp di,command_line             ; Space must not be first
103                 je short get_char
104 enter_char:     test byte [FuncFlag],1
105                 jnz ctrl_f                      ; Keystroke after <Ctrl-F>
106                 cmp di,max_cmd_len+command_line ; Check there's space
107                 jnb short get_char
108                 stosb                           ; Save it
109                 call writechr                   ; Echo to screen
110                 jmp short get_char
111 not_ascii:
112                 cmp al,0Dh                      ; Enter
113                 je command_done
114                 cmp al,09h                      ; Tab
115                 je display_labels
116                 cmp al,'F' & 1Fh                ; <Ctrl-F>
117                 je set_func_flag
118                 cmp al,'N' & 1Fh                ; <Ctrl-N>
119                 je show_system_info
120                 cmp al,'U' & 1Fh                ; <Ctrl-U>
121                 je kill_command                 ; Kill input line
122                 cmp al,'V' & 1Fh                ; <Ctrl-V>
123                 je print_version
124                 cmp al,'X' & 1Fh                ; <Ctrl-X>
125                 je force_text_mode
126                 cmp al,08h                      ; Backspace
127                 jne get_char
128 backspace:      cmp di,command_line             ; Make sure there is anything
129                 je get_char                     ; to erase
130                 dec di                          ; Unstore one character
131                 mov si,wipe_char                ; and erase it from the screen
132                 call writestr
133 get_char_2:
134                 jmp short get_char
136 kill_command:
137                 call crlf
138                 jmp enter_command
140 force_text_mode:
141                 call vgaclearmode
142                 jmp enter_command
144 set_func_flag:
145                 mov byte [FuncFlag],1
146                 jmp short get_char_2
148 display_labels:
149                 cmp word [NoComplete],0         ; Label completion enabled?
150                 jne get_char_2
151                 push di                         ; Save pointer
152                 mov cx,di
153                 sub cx,command_line
154                 call crlf
155                 mov esi,[MallocStart]           ; Start from top of memory
156 .scan:
157                 cmp esi,[VKernelEnd]
158                 jbe .not_vk
160                 push cx                         ; save command line size
162                 mov edi,VKernelBuf
163                 pm_call rllunpack
164                 ; ESI updated on return
166                 sub di,cx                       ; Return to beginning of buf
167                 pop cx                          ; restore command line size
168                 push si                         ; save SI
169                 cmp cx,0
170                 jz .print
171                 push di
172                 push cx
173                 mov si,command_line
174                 es repe cmpsb
175                 pop cx
176                 pop di
177                 jne .next
178 .print:
179                 mov al,' '
180                 call writechr
182                 mov si,di
183                 call writestr
184 .next:
185                 pop si                          ; restore SI
186                 jmp .scan
187 .not_vk:
188                 call crlf
189                 jmp fk_wrcmd
191 ctrl_f:
192                 xor ah,ah
193                 mov [FuncFlag],ah
194                 cmp al,'0'
195                 jb get_char_2
196                 je .zero                        ; <Ctrl-F>0 = F10
197                 or al,20h                       ; Lower case
198                 cmp al,'9'
199                 jna .digit
200                 cmp al,'a'                      ; F10-F12 = <Ctrl-F>A, B, C
201                 jb get_char_2
202                 cmp al,'c'
203                 ja get_char_2
204                 sub al,'a'-10
205                 jmp show_help
206 .zero:
207                 mov al,10
208                 jmp show_help
209 .digit:
210                 sub al,'1'
211                 jmp show_help
213 func_key:
214                 ; AL = 0 if we get here
215                 xchg al,ah
216                 cmp al,44h                      ; F10
217                 ja .f11_f12
218                 sub al,3Bh                      ; F1
219                 jb get_char_2
220                 jmp show_help
221 .f11_f12:
222                 cmp al,85h                      ; F11
223                 jb get_char_2
224                 cmp al,86h                      ; F12
225                 ja get_char_2
226                 sub al,85h-10
228 show_help:      ; AX = func key # (0 = F1, 9 = F10, 11 = F12)
229                 push di                         ; Save end-of-cmdline pointer
230                 shl ax,FILENAME_MAX_LG2         ; Convert to pointer
231                 add ax,FKeyName
232                 xchg di,ax
233                 cmp byte [di+NULLOFFSET],NULLFILE
234                 je short fk_nofile              ; Undefined F-key
235                 call core_open
236                 jz short fk_nofile              ; File not found
237                 call crlf
238                 call get_msg_file
239                 jmp short fk_wrcmd
241 print_version:
242                 push di                         ; Command line write pointer
243                 mov si,syslinux_banner
244                 call writestr
245 %ifdef HAVE_BIOSNAME
246                 mov si,[BIOSName]
247                 call writestr
248 %endif
249                 mov si,copyright_str
250                 call writestr
252                 ; ... fall through ...
254                 ; Write the boot prompt and command line again and
255                 ; wait for input.  Note that this expects the cursor
256                 ; to already have been CRLF'd, and that the old value
257                 ; of DI (the command line write pointer) is on the stack.
258 fk_wrcmd:
259                 mov si,boot_prompt
260                 call writestr
261                 pop di                          ; Command line write pointer
262                 push di
263                 mov byte [di],0                 ; Null-terminate command line
264                 mov si,command_line
265                 call writestr                   ; Write command line so far
266 fk_nofile:      pop di
267                 jmp get_char
270 ; Show system info (in the form of the sysappend strings)
272 show_system_info:
273                 call crlf
274                 pm_call print_sysappend
275                 jmp fk_wrcmd
278 ; Jump here to run the default command line
280 auto_boot:
281                 cmp word [DefaultLevel],0       ; No UI or DEFAULT?
282                 jne .have_default
283                 mov si,no_default_msg
284                 call writestr
285                 cmp word [NoEscape],0           ; NOESCAPE but no DEFAULT?
286                 jne kaboom                      ; If so, we're stuck!
287                 jmp enter_command
289 .have_default:
290                 mov si,default_cmd
291                 mov di,command_line
292                 mov cx,(max_cmd_len+4) >> 2
293                 rep movsd
294                 jmp short load_kernel
296                 section .data16
297 no_default_msg  db 'No DEFAULT or UI configuration directive found!'
298                 db CR, LF, 0
300                 section .text16
303 ; Jump here when the command line is completed
305 command_done:
306                 call crlf
307                 cmp di,command_line             ; Did we just hit return?
308                 je auto_boot
309                 xor al,al                       ; Store a final null
310                 stosb
312 load_kernel:                                    ; Load the kernel now
314 ; First we need to mangle the kernel name the way DOS would...
316                 mov si,command_line
317                 mov di,KernelName
318                 push si
319                 pm_call pm_mangle_name
320                 pop si
322 ; Fast-forward to first option (we start over from the beginning, since
323 ; pm_mangle_name doesn't necessarily return a consistent ending state.)
325 clin_non_wsp:   lodsb
326                 cmp al,' '
327                 ja clin_non_wsp
328 clin_is_wsp:    and al,al
329                 jz clin_opt_ptr
330                 lodsb
331                 cmp al,' '
332                 jbe clin_is_wsp
333 clin_opt_ptr:   dec si                          ; Point to first nonblank
334                 mov [CmdOptPtr],si              ; Save ptr to first option
336 ; If "allowoptions 0", put a null character here in order to ignore any
337 ; user-specified options.
339                 mov ax,[AllowOptions]
340                 and ax,ax
341                 jnz clin_opt_ok
342                 mov [si],al
343 clin_opt_ok:
346 ; Now check if it is a "virtual kernel"
348 vk_check:
349                 mov esi,[MallocStart]           ; Start from top of memory
350 .scan:
351                 cmp esi,[VKernelEnd]
352                 jbe .not_vk
354                 mov edi,VKernelBuf
355                 pm_call rllunpack
356                 ; ESI updated on return
358                 sub di,cx                       ; Return to beginning of buf
359                 push si
360                 mov si,command_line
361 .loop:
362                 lodsb
363                 cmp al,' '
364                 jbe .done
365                 scasb
366                 je .loop
367 .nomatch:
368                 pop si
369                 jmp .scan
370 .done:
371                 cmp byte [di],0                 ; Must match end of string
372                 jne .nomatch
373                 pop si
376 ; We *are* using a "virtual kernel"
378 .found:
379                 push es
380                 push word real_mode_seg
381                 pop es
382                 mov di,cmd_line_here
383                 mov si,VKernelBuf+vk_append
384                 mov cx,[VKernelBuf+vk_appendlen]
385                 rep movsb
386                 mov byte [es:di],cl             ; Null-terminate
387                 mov [CmdLinePtr],di             ; Where to add rest of cmd
388                 pop es
389                 mov di,KernelName
390                 push di
391                 mov si,VKernelBuf+vk_rname
392                 mov cx,FILENAME_MAX             ; We need ECX == CX later
393                 rep movsb
394                 pop di
395                 mov eax,[VKernelBuf+vk_sysappend]
396                 mov [SysAppends],eax
397                 xor bx,bx                       ; Try only one version
399                 mov al,[VKernelBuf+vk_type]
400                 mov [KernelType],al
402                 ; Is this a "localboot" pseudo-kernel?
403                 cmp al,VK_LOCALBOOT             ; al == KernelType
404                 mov ax,[VKernelBuf+vk_rname]    ; Possible localboot type
405                 je local_boot
406                 jmp get_kernel
408 .not_vk:
410 ; Not a "virtual kernel" - check that's OK and construct the command line
412                 cmp word [AllowImplicit],byte 0
413                 je bad_implicit
414                 push es
415                 push si
416                 push di
417                 mov di,real_mode_seg
418                 mov es,di
419                 mov si,AppendBuf
420                 mov di,cmd_line_here
421                 mov cx,[AppendLen]
422                 rep movsb
423                 mov byte [es:di],cl             ; Null-terminate
424                 mov [CmdLinePtr],di
425                 pop di
426                 pop si
427                 pop es
429                 mov [KernelType], cl            ; CL == 0 here
432 ; Find the kernel on disk
434 get_kernel:     mov byte [KernelName+FILENAME_MAX],0    ; Zero-terminate filename/extension
435                 mov di,KernelName
436                 cmp byte [di],' '
437                 jbe bad_kernel                  ; Missing kernel name
438                 xor al,al
439                 mov cx,FILENAME_MAX-5           ; Need 4 chars + null
440                 repne scasb                     ; Scan for final null
441                 jne .no_skip
442                 dec di                          ; Point to final null
443 .no_skip:       mov [KernelExtPtr],di
444                 mov bx,exten_table
445 .search_loop:   push bx
446                 mov di,KernelName               ; Search on disk
447                 pm_call pm_searchdir
448                 pop bx
449                 jnz kernel_good
450                 mov eax,[bx]                    ; Try a different extension
451                 mov si,[KernelExtPtr]
452                 mov [si],eax
453                 mov byte [si+4],0
454                 add bx,byte 4
455                 cmp bx,exten_table_end
456                 jna .search_loop                ; allow == case (final case)
457                 ; Fall into bad_kernel
459 ; bad_kernel: Kernel image not found
460 ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
462 bad_implicit:
463 bad_kernel:
464                 mov cx,[OnerrorLen]
465                 and cx,cx
466                 jnz on_error
467 .really:
468                 mov si,err_notfound             ; Complain about missing kernel
469                 call writestr
470                 mov si,KernelName
471                 call writestr
472                 mov si,crlf_msg
473                 jmp abort_load                  ; Ask user for clue
476 ; on_error: bad kernel, but we have onerror set; CX = OnerrorLen
478 on_error:
479                 mov si,Onerror
480                 mov di,command_line
481                 push si                         ; <A>
482                 push di                         ; <B>
483                 push cx                         ; <C>
484                 push cx                         ; <D>
485                 push di                         ; <E>
486                 repe cmpsb
487                 pop di                          ; <E> di == command_line
488                 pop bx                          ; <D> bx == [OnerrorLen]
489                 je bad_kernel.really            ; Onerror matches command_line already
490                 neg bx                          ; bx == -[OnerrorLen]
491                 lea cx,[max_cmd_len+bx]
492                 ; CX == max_cmd_len-[OnerrorLen]
493                 mov di,command_line+max_cmd_len-1
494                 mov byte [di+1],0               ; Enforce null-termination
495                 lea si,[di+bx]
496                 std
497                 rep movsb                       ; Make space in command_line
498                 cld
499                 pop cx                          ; <C> cx == [OnerrorLen]
500                 pop di                          ; <B> di == command_line
501                 pop si                          ; <A> si  == Onerror
502                 rep movsb
503                 jmp load_kernel
506 ; kernel_corrupt: Called if the kernel file does not seem healthy
508 kernel_corrupt: mov si,err_notkernel
509                 jmp abort_load
512 ; Get a key, observing ThisKbdTO and ThisTotalTO -- those are timeouts
513 ; which can be adjusted by the caller based on the corresponding
514 ; master variables; on return they're updated.
516 ; This cheats.  If we say "no timeout" we actually get a timeout of
517 ; 7.5 years.
519 getchar_timeout:
520                 call vgashowcursor
521                 call reset_idle
523 .loop:
524                 push word [__jiffies]
525                 call pollchar
526                 jnz .got_char
527                 call do_idle
528                 pop ax
529                 cmp ax,[__jiffies]              ; Has the timer advanced?
530                 je .loop
532                 dec dword [ThisKbdTo]
533                 jz .timeout
534                 dec dword [ThisTotalTo]
535                 jnz .loop
537 .timeout:
538                 ; Timeout!!!!
539                 pop cx                          ; Discard return address
540                 call vgahidecursor
541                 mov si,Ontimeout                ; Copy ontimeout command
542                 mov di,command_line
543                 mov cx,[OntimeoutLen]           ; if we have one...
544                 rep movsb
545                 jmp command_done
547 .got_char:
548                 pop cx                          ; Discard
549                 call getchar
550                 call vgahidecursor
551                 ret
554 ; This is it!  We have a name (and location on the disk)... let's load
555 ; that sucker!!  First we have to decide what kind of file this is; base
556 ; that decision on the file extension.  The following extensions are
557 ; recognized; case insensitive:
559 ; .com  - COMBOOT image
560 ; .cbt  - COMBOOT image
561 ; .c32  - COM32 image
562 ; .bs   - Boot sector
563 ; .0    - PXE bootstrap program (PXELINUX only)
564 ; .bin  - Boot sector
565 ; .bss  - Boot sector, but transfer over DOS superblock (SYSLINUX only)
566 ; .img  - Floppy image (ISOLINUX only)
568 ; Anything else is assumed to be a Linux kernel.
570                 section .bss16
571                 alignb 4
572 Kernel_EAX      resd 1
573 Kernel_SI       resw 1
575                 section .text16
576 kernel_good_saved:
577                 ; Alternate entry point for which the return from
578                 ; searchdir is stored in memory.  This is used for
579                 ; COMBOOT function INT 22h, AX=0016h.
580                 mov si,[Kernel_SI]
581                 mov eax,[Kernel_EAX]
583 kernel_good:
584                 pushad
585                 ;
586                 ; Common initialization for all kernel types
587                 ;
588                 xor ax,ax
589                 mov [InitRDPtr],ax
590                 mov [QuietBoot],al
591 %if IS_PXELINUX
592                 mov [KeepPXE],al
593 %endif
595                 ; Default memory limit, can be overridden by image loaders
596                 mov eax,[HighMemRsvd]
597                 mov [MyHighMemSize],eax
599                 popad
601                 push di
602                 push ax
603                 mov di,KernelName
604                 xor al,al
605                 mov cx,FILENAME_MAX
606                 repne scasb
607                 jne .one_step
608                 dec di
609 .one_step:      mov ecx,[di-4]                  ; 4 bytes before end
610                 pop ax
611                 pop di
614 ; At this point, EAX contains the size of the kernel, SI contains
615 ; the file handle/cluster pointer, and ECX contains the extension (if any.)
617                 movzx di,byte [KernelType]
618                 add di,di
619                 jmp [kerneltype_table+di]
621 is_unknown_filetype:
622                 or ecx,20202000h                ; Force lower case (except dot)
624                 cmp ecx,'.com'
625                 je is_comboot_image
626                 cmp ecx,'.cbt'
627                 je is_comboot_image
628                 cmp ecx,'.c32'
629                 je is_com32_image
630                 cmp ecx,'.bss'
631                 je is_bss_sector
632                 cmp ecx,'.bin'
633                 je is_bootsector
634                 shr ecx,8
635                 cmp ecx,'.bs'
636                 je is_bootsector
637                 shr ecx,8
638                 cmp cx,'.0'
639                 je is_bootsector
641                 ; Otherwise Linux kernel
642                 jmp is_linux_kernel
644 is_config_file:
645                 push si
646                 call make_plain_cmdline
647                 pm_call pm_is_config_file
648                 pop si
649                 call openfd
650                 call reset_config
651                 jmp load_config_file
653 ; This is an image type we can't deal with
654 is_bad_image:
655                 mov si,err_badimage
656                 call writestr
657                 jmp enter_command
659 %if IS_SYSLINUX
660                 ; ok
661 %else
662 is_bss_sector   equ is_bad_image
663 %endif
665 is_disk_image   equ is_bad_image        ; No longer supported
667                 section .data16
668 boot_prompt     db 'boot: ', 0
669 wipe_char       db BS, ' ', BS, 0
670 err_badimage    db 'Invalid image type for this media type!', CR, LF, 0
671 err_notfound    db 'Could not find kernel image: ',0
672 err_notkernel   db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
675                 alignz 2
676 kerneltype_table:
677                 dw is_unknown_filetype  ; VK_KERNEL
678                 dw is_linux_kernel      ; VK_LINUX
679                 dw is_bootsector        ; VK_BOOT
680                 dw is_bss_sector        ; VK_BSS
681                 dw is_bootsector        ; VK_PXE
682                 dw is_disk_image        ; VK_FDIMAGE
683                 dw is_comboot_image     ; VK_COMBOOT
684                 dw is_com32_image       ; VK_COM32
685                 dw is_config_file       ; VK_CONFIG
687                 section .bss16
688                 alignb 4
689 ThisKbdTo       resd 1                  ; Temporary holder for KbdTimeout
690 ThisTotalTo     resd 1                  ; Temporary holder for TotalTimeout
691 KernelExtPtr    resw 1                  ; During search, final null pointer
692 CmdOptPtr       resw 1                  ; Pointer to first option on cmd line
693 KbdFlags        resb 1                  ; Check for keyboard escapes
694 FuncFlag        resb 1                  ; Escape sequences received from keyboard
695 KernelType      resb 1                  ; Kernel type, from vkernel, if known
697                 section .text16
699 ; Linux kernel loading code is common.
701 %include "runkernel.inc"
704 ; COMBOOT-loading code
706 %include "comboot.inc"
707 %include "com32.inc"
708 %include "cmdline.inc"
711 ; Boot sector loading code
713 %include "bootsect.inc"
716 ; Abort loading code
718 %include "abort.inc"
721 ; Hardware cleanup common code
723 %include "cleanup.inc"