VESA library: add support for reading lss16 images
[profile/ivi/syslinux.git] / ui.inc
diff --git a/ui.inc b/ui.inc
index 2872ee5..0677733 100644 (file)
--- a/ui.inc
+++ b/ui.inc
@@ -1,7 +1,6 @@
-;; $Id$
 ;; -----------------------------------------------------------------------
-;;   
-;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
+;;
+;;   Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
 ;;
 ;;   This program is free software; you can redistribute it and/or modify
 ;;   it under the terms of the GNU General Public License as published by
 ;
 ; This file should be entered with the config file open (for getc)
 ;
+load_config_file:
                call parse_config               ; Parse configuration file
 no_config_file:
+
+               call adv_init
+;
+; Check for an ADV boot-once entry
+;
+               mov dl,ADV_BOOTONCE
+               call adv_get
+               jcxz .no_bootonce
+
+.have_bootone:
+               ; We apparently have a boot-once set; clear it and
+               ; then execute the boot-once...
+
+               ; Save the boot-once data; SI = data, CX = length
+               mov di,command_line
+               rep movsb
+               xor ax,ax
+               stosb
+
+               ; Clear the boot-once data from the ADV
+               xor cx,cx                       ; Set to zero = delete
+               call adv_set
+               jc .err
+               call adv_write
+.err:          jmp load_kernel
+
+.no_bootonce:
+
 ;
 ; Check whether or not we are supposed to display the boot prompt.
 ;
 check_for_key:
-               cmp word [ForcePrompt],byte 0   ; Force prompt?
+               cmp word [ForcePrompt],0        ; Force prompt?
                jnz enter_command
-               test byte [KbdFlags],5Bh        ; Caps, Scroll, Shift, Alt
+               test byte [KbdFlags],5Bh        ; Shift Alt Caps Scroll
                jz auto_boot                    ; If neither, default boot
 
 enter_command:
+               cmp word [NoEscape],0           ; If NOESCAPE, no prompt,
+               jne auto_boot                   ; always run default cmd
+
                mov si,boot_prompt
                call cwritestr
 
                mov byte [FuncFlag],0           ; <Ctrl-F> not pressed
                mov di,command_line
+
 ;
 ; get the very first character -- we can either time
 ; out, or receive a character press at this time.  Some dorky BIOSes stuff
@@ -42,40 +74,20 @@ clear_buffer:       mov ah,11h                      ; Check for pending char
                mov ah,10h                      ; Get char
                int 16h
                jmp short clear_buffer
-get_char_time: 
-               call vgashowcursor
-               RESET_IDLE
-               mov cx,[KbdTimeOut]
-               and cx,cx
-               jz get_char                     ; Timeout == 0 -> no timeout
-               inc cx                          ; The first loop will happen
-                                               ; immediately as we don't
-                                               ; know the appropriate DX value
-time_loop:     push cx
-tick_loop:     push dx
-               call pollchar
-               jnz get_char_pop
-               mov dx,[BIOS_timer]             ; Get time "of day"
-               pop ax
-               cmp dx,ax                       ; Has the timer advanced?
-               je tick_loop
-               pop cx
-               DO_IDLE
-               loop time_loop                  ; If so, decrement counter
 
-               ; Timeout!!!!
-               call vgahidecursor
-               mov si,Ontimeout                ; Copy ontimeout command
-               mov cx,[OntimeoutLen]           ; if we have one...
-               rep movsb
-.stddefault:
-               jmp command_done
+               ; For the first character, both KbdTimeout and
+               ; TotalTimeout apply; after that, only TotalTimeout.
+
+get_char_time:
+               mov eax,[TotalTimeout]
+               mov [ThisTotalTo],eax
+               mov eax,[KbdTimeout]
+               mov [ThisKbdTo],eax
 
-get_char_pop:  pop eax                         ; Clear stack
 get_char:
-               call vgashowcursor
-               call getchar
-               call vgahidecursor
+               call getchar_timeout
+               and dword [ThisKbdTo],0         ; For the next time...
+
                and al,al
                jz func_key
 
@@ -87,27 +99,27 @@ got_ascii:  cmp al,7Fh                      ; <DEL> == <BS>
                cmp di,command_line             ; Space must not be first
                je short get_char
 enter_char:    test byte [FuncFlag],1
-               jz .not_ctrl_f
-               mov byte [FuncFlag],0
-               cmp al,'0'
-               jb .not_ctrl_f
-               je ctrl_f_0
-               cmp al,'9'
-               jbe ctrl_f
-.not_ctrl_f:   cmp di,max_cmd_len+command_line ; Check there's space
+               jnz ctrl_f                      ; Keystroke after <Ctrl-F>
+               cmp di,max_cmd_len+command_line ; Check there's space
                jnb short get_char
                stosb                           ; Save it
                call writechr                   ; Echo to screen
                jmp short get_char
-not_ascii:     mov byte [FuncFlag],0
+not_ascii:
                cmp al,0Dh                      ; Enter
                je command_done
-               cmp al,06h                      ; <Ctrl-F>
+               cmp al,'F' & 1Fh                ; <Ctrl-F>
                je set_func_flag
-               cmp al,15h                      ; <Ctrl-U>
+%if IS_PXELINUX
+               cmp al,'N' & 1Fh                ; <Ctrl-N>
+               je show_network_info
+%endif
+               cmp al,'U' & 1Fh                ; <Ctrl-U>
                je kill_command                 ; Kill input line
-               cmp al,16h                      ; <Ctrl-V>
+               cmp al,'V' & 1Fh                ; <Ctrl-V>
                je print_version
+               cmp al,'X' & 1Fh                ; <Ctrl-X>
+               je force_text_mode
                cmp al,08h                      ; Backspace
                jne get_char
 backspace:     cmp di,command_line             ; Make sure there is anything
@@ -115,41 +127,68 @@ backspace:        cmp di,command_line             ; Make sure there is anything
                dec di                          ; Unstore one character
                mov si,wipe_char                ; and erase it from the screen
                call cwritestr
-               jmp short get_char_2
+get_char_2:
+               jmp short get_char
 
 kill_command:
                call crlf
                jmp enter_command
 
+force_text_mode:
+               call vgaclearmode
+               jmp enter_command
+
 set_func_flag:
                mov byte [FuncFlag],1
-get_char_2:
-               jmp short get_char
+               jmp short get_char_2
 
-ctrl_f_0:      add al,10                       ; <Ctrl-F>0 == F10
-ctrl_f:                sub al,'1'
+ctrl_f:
                xor ah,ah
-               jmp short show_help
+               mov [FuncFlag],ah
+               cmp al,'0'
+               jb get_char_2
+               je .zero                        ; <Ctrl-F>0 = F10
+               or al,20h                       ; Lower case
+               cmp al,'9'
+               jna .digit
+               cmp al,'a'                      ; F10-F12 = <Ctrl-F>A, B, C
+               jb get_char_2
+               cmp al,'c'
+               ja get_char_2
+               sub al,'a'-10
+               jmp show_help
+.zero:
+               mov al,10
+               jmp show_help
+.digit:
+               sub al,'1'
+               jmp show_help
 
 func_key:
                ; AL = 0 if we get here
                xchg al,ah
-               cmp al,68                       ; F10
-               ja short get_char_2
-               sub al,59                       ; F1
-               jb short get_char_2
-show_help:     ; AX = func key # (0 = F1, 9 = F10)
+               cmp al,44h                      ; F10
+               ja .f11_f12
+               sub al,3Bh                      ; F1
+               jb get_char_2
+               jmp show_help
+.f11_f12:
+               cmp al,85h                      ; F11
+               jb get_char_2
+               cmp al,86h                      ; F12
+               ja get_char_2
+               sub al,85h-10
+
+show_help:     ; AX = func key # (0 = F1, 9 = F10, 11 = F12)
                push di                         ; Save end-of-cmdline pointer
                shl ax,FILENAME_MAX_LG2         ; Convert to pointer
                add ax,FKeyName
                xchg di,ax
-               cmp byte [di],NULLFILE
+               cmp byte [di+NULLOFFSET],NULLFILE
                je short fk_nofile              ; Undefined F-key
-               call searchdir
+               call open
                jz short fk_nofile              ; File not found
-               push si
                call crlf
-               pop si
                call get_msg_file
                jmp short fk_wrcmd
 
@@ -157,6 +196,10 @@ print_version:
                push di                         ; Command line write pointer
                mov si,syslinux_banner
                call cwritestr
+%ifdef HAVE_BIOSNAME
+               mov si,[BIOSName]
+               call cwritestr
+%endif
                mov si,copyright_str
                call cwritestr
 
@@ -175,13 +218,41 @@ fk_wrcmd:
                mov si,command_line
                call cwritestr                  ; Write command line so far
 fk_nofile:     pop di
-               jmp short get_char_2
+               jmp get_char
+
+;
+; Show network info (in the form of the ipappend strings)
+;
+%if IS_PXELINUX
+show_network_info:
+               push di                         ; Command line write pointer
+               call crlf
+               mov si,IPAppends                ; See comboot.doc
+               mov cx,numIPAppends
+.loop:
+               lodsw
+               push si
+               mov si,ax
+               call cwritestr
+               call crlf
+               pop si
+               loop .loop
+               jmp fk_wrcmd
+%endif
+
+;
+; Jump here to run the default command line
+;
 auto_boot:
                mov si,default_cmd
                mov di,command_line
                mov cx,(max_cmd_len+4) >> 2
                rep movsd
                jmp short load_kernel
+
+;
+; Jump here when the command line is completed
+;
 command_done:
                call crlf
                cmp di,command_line             ; Did we just hit return?
@@ -196,9 +267,7 @@ load_kernel:                                        ; Load the kernel now
                mov si,command_line
                 mov di,KernelName
                 push si
-                push di
                call mangle_name
-               pop di
                 pop si
 ;
 ; Fast-forward to first option (we start over from the beginning, since
@@ -228,19 +297,14 @@ clin_opt_ok:
 ; Now check if it is a "virtual kernel"
 ;
 vk_check:
-               xor si,si                       ; Beginning of vk_seg
+               mov esi,[HighMemSize]           ; Start from top of memory
 .scan:
-               cmp si,[VKernelBytes]
-               jae .not_vk
-
-               push ds
-               push word vk_seg
-               pop ds
+               cmp esi,[VKernelEnd]
+               jbe .not_vk
 
                mov di,VKernelBuf
                call rllunpack
-               pop ds
-               ; SI updated on return
+               ; ESI updated on return
 
                sub di,cx                       ; Return to beginning of buf
                push si
@@ -265,7 +329,7 @@ vk_check:
                mov [CmdLinePtr],di             ; Where to add rest of cmd
                pop es
                mov di,KernelName
-               push di 
+               push di
                mov si,VKernelBuf+vk_rname
                mov cx,FILENAME_MAX             ; We need ECX == CX later
                rep movsb
@@ -276,9 +340,16 @@ vk_check:
 %endif
                xor bx,bx                       ; Try only one version
 
+               mov al, [VKernelBuf+vk_type]
+               mov [KernelType], al
+
 %if IS_PXELINUX || IS_ISOLINUX
                ; Is this a "localboot" pseudo-kernel?
+%if IS_PXELINUX
+               cmp byte [VKernelBuf+vk_rname+4], 0
+%else
                cmp byte [VKernelBuf+vk_rname], 0
+%endif
                jne get_kernel          ; No, it's real, go get it
 
                mov ax, [VKernelBuf+vk_rname+1]
@@ -307,36 +378,30 @@ vk_check:
                 pop di
                 pop si
                 pop es
+
+               mov [KernelType], cl            ; CL == 0 here
+
 ;
 ; Find the kernel on disk
 ;
 get_kernel:     mov byte [KernelName+FILENAME_MAX],0   ; Zero-terminate filename/extension
-%if IS_SYSLINUX || IS_MDSLINUX                 ; SYSLINUX has to deal with DOS mangled names...
-               mov eax,[KernelName+8]          ; Save initial extension
-               mov [exten_table_end],eax       ; Last case == initial ext.
-%else
-               mov di,KernelName
+               mov di,KernelName+4*IS_PXELINUX
                xor al,al
                mov cx,FILENAME_MAX-5           ; Need 4 chars + null
                repne scasb                     ; Scan for final null
                jne .no_skip
-               dec di                          ; Point to final null 
+               dec di                          ; Point to final null
 .no_skip:      mov [KernelExtPtr],di
-%endif
                mov bx,exten_table
 .search_loop:  push bx
-                mov di,KernelName              ; Search on disk
+                mov di,KernelName              ; Search on disk
                 call searchdir
                pop bx
                 jnz kernel_good
                mov eax,[bx]                    ; Try a different extension
-%if IS_SYSLINUX || IS_MDSLINUX
-               mov [KernelName+8],eax
-%else
                mov si,[KernelExtPtr]
                mov [si],eax
                mov byte [si+4],0
-%endif
                add bx,byte 4
                cmp bx,exten_table_end
                jna .search_loop                ; allow == case (final case)
@@ -363,7 +428,7 @@ bad_kernel:
                 jmp abort_load                  ; Ask user for clue
 
 ;
-; on_error: bad kernel, but we have onerror set
+; on_error: bad kernel, but we have onerror set; CX = OnerrorLen
 ;
 on_error:
                mov si,Onerror
@@ -397,13 +462,56 @@ on_error:
 ;
 kernel_corrupt: mov si,err_notkernel
                 jmp abort_load
+
+;
+; Get a key, observing ThisKbdTO and ThisTotalTO -- those are timeouts
+; which can be adjusted by the caller based on the corresponding
+; master variables; on return they're updated.
+;
+; This cheats.  If we say "no timeout" we actually get a timeout of
+; 7.5 years.
+;
+getchar_timeout:
+               call vgashowcursor
+               RESET_IDLE
+
+.loop:
+               push word [BIOS_timer]
+               call pollchar
+               jnz .got_char
+               pop ax
+               cmp ax,[BIOS_timer]             ; Has the timer advanced?
+               je .loop
+               DO_IDLE
+
+               dec dword [ThisKbdTo]
+               jz .timeout
+               dec dword [ThisTotalTo]
+               jnz .loop
+
+.timeout:
+               ; Timeout!!!!
+               pop cx                          ; Discard return address
+               call vgahidecursor
+               mov si,Ontimeout                ; Copy ontimeout command
+               mov di,command_line
+               mov cx,[OntimeoutLen]           ; if we have one...
+               rep movsb
+               jmp command_done
+
+.got_char:
+               pop cx                          ; Discard
+               call getchar
+               call vgahidecursor
+               ret
+
 ;
 ; This is it!  We have a name (and location on the disk)... let's load
 ; that sucker!!  First we have to decide what kind of file this is; base
 ; that decision on the file extension.  The following extensions are
 ; recognized; case insensitive:
 ;
-; .com         - COMBOOT image
+; .com - COMBOOT image
 ; .cbt - COMBOOT image
 ; .c32  - COM32 image
 ; .bs  - Boot sector
@@ -414,22 +522,37 @@ kernel_corrupt: mov si,err_notkernel
 ;
 ; Anything else is assumed to be a Linux kernel.
 ;
+               section .bss
+               alignb 4
+Kernel_EAX     resd 1
+Kernel_SI      resw 1
+
+               section .text
+kernel_good_saved:
+               ; Alternate entry point for which the return from
+               ; searchdir is stored in memory.  This is used for
+               ; COMBOOT function INT 22h, AX=0016h.
+               mov si,[Kernel_SI]
+               mov eax,[Kernel_EAX]
+
 kernel_good:
-               pusha
+               pushad
+
                mov si,KernelName
                mov di,KernelCName
                call unmangle_name
                sub di,KernelCName
                mov [KernelCNameLen],di
-               popa
-               
-%if IS_SYSLINUX || IS_MDSLINUX
-               mov ecx,[KernelName+7]
-               mov cl,'.'
-%else
+
+               ; Default memory limit, can be overridden by image loaders
+               mov eax,[HighMemRsvd]
+               mov [MyHighMemSize],eax
+
+               popad
+
                push di
                push ax
-               mov di,KernelName
+               mov di,KernelName+4*IS_PXELINUX
                xor al,al
                mov cx,FILENAME_MAX
                repne scasb
@@ -438,13 +561,17 @@ kernel_good:
 .one_step:     mov ecx,[di-4]                  ; 4 bytes before end
                pop ax
                pop di
-%endif
 
 ;
-; At this point, DX:AX contains the size of the kernel, and SI contains
-; the file handle/cluster pointer.
+; At this point, EAX contains the size of the kernel, SI contains
+; the file handle/cluster pointer, and ECX contains the extension (if any.)
 ;
-               or ecx,20202000h                ; Force lower case
+               movzx di,byte [KernelType]
+               add di,di
+               jmp [kerneltype_table+di]
+
+is_unknown_filetype:
+               or ecx,20202000h                ; Force lower case (except dot)
 
                cmp ecx,'.com'
                je is_comboot_image
@@ -460,26 +587,97 @@ kernel_good:
                je is_bss_sector
                cmp ecx,'.bin'
                je is_bootsector
-%if IS_SYSLINUX || IS_MDSLINUX
-               cmp ecx,'.bs '
-               je is_bootsector
-               cmp ecx,'.0  '
-               je is_bootsector
-%else
                shr ecx,8
                cmp ecx,'.bs'
                je is_bootsector
                shr ecx,8
                cmp cx,'.0'
                je is_bootsector
-%endif
+
                ; Otherwise Linux kernel
+               jmp is_linux_kernel
+
+is_config_file:
+               pusha
+               mov si,KernelCName              ; Save the config file name, for posterity
+               mov di,ConfigName
+               call strcpy
+               popa
+               call openfd
+               call reset_config
+               jmp load_config_file
+
+; This is an image type we can't deal with
+is_bad_image:
+               mov si,err_badimage
+               call cwritestr
+               jmp enter_command
+
+%if IS_SYSLINUX || IS_MDSLINUX
+               ; ok
+%else
+is_bss_sector  equ is_bad_image
+%endif
+%if IS_ISOLINUX
+               ; ok
+%else
+is_disk_image  equ is_bad_image
+%endif
+
+               section .data
+boot_prompt    db 'boot: ', 0
+wipe_char      db BS, ' ', BS, 0
+err_badimage   db 'Invalid image type for this media type!', CR, LF, 0
+err_notfound   db 'Could not find kernel image: ',0
+err_notkernel  db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
+
+
+               align 2, db 0
+kerneltype_table:
+               dw is_unknown_filetype  ; VK_KERNEL
+               dw is_linux_kernel      ; VK_LINUX
+               dw is_bootsector        ; VK_BOOT
+               dw is_bss_sector        ; VK_BSS
+               dw is_bootsector        ; VK_PXE
+               dw is_disk_image        ; VK_FDIMAGE
+               dw is_comboot_image     ; VK_COMBOOT
+               dw is_com32_image       ; VK_COM32
+               dw is_config_file       ; VK_CONFIG
 
                section .bss
-               alignb 2
+               alignb 4
+ThisKbdTo      resd 1                  ; Temporary holder for KbdTimeout
+ThisTotalTo    resd 1                  ; Temporary holder for TotalTimeout
 KernelExtPtr   resw 1                  ; During search, final null pointer
 CmdOptPtr       resw 1                 ; Pointer to first option on cmd line
 KbdFlags       resb 1                  ; Check for keyboard escapes
 FuncFlag       resb 1                  ; Escape sequences received from keyboard
+KernelType     resb 1                  ; Kernel type, from vkernel, if known
 
                section .text
+;
+; Linux kernel loading code is common.
+;
+%include "runkernel.inc"
+
+;
+; COMBOOT-loading code
+;
+%include "comboot.inc"
+%include "com32.inc"
+%include "cmdline.inc"
+
+;
+; Boot sector loading code
+;
+%include "bootsect.inc"
+
+;
+; Abort loading code
+;
+%include "abort.inc"
+
+;
+; Hardware cleanup common code
+;
+%include "cleanup.inc"