-;; $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
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
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
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
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
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?
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
; 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
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
%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]
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)
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
;
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
;
; 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
.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
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"