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