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