1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2007 H. Peter Anvin - All Rights Reserved
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.
11 ;; -----------------------------------------------------------------------
14 ; This file should be entered with the config file open (for getc)
17 call parse_config ; Parse configuration file
22 ; Check for an ADV boot-once entry
29 ; We apparently have a boot-once set; clear it and
30 ; then execute the boot-once...
32 ; Save the boot-once data; SI = data, CX = length
38 ; Clear the boot-once data from the ADV
39 xor cx,cx ; Set to zero = delete
48 ; Check whether or not we are supposed to display the boot prompt.
51 cmp word [ForcePrompt],0 ; Force prompt?
53 test byte [KbdFlags],5Bh ; Shift Alt Caps Scroll
54 jz auto_boot ; If neither, default boot
57 cmp word [NoEscape],0 ; If NOESCAPE, no prompt,
58 jne auto_boot ; always run default cmd
63 mov byte [FuncFlag],0 ; <Ctrl-F> not pressed
67 ; get the very first character -- we can either time
68 ; out, or receive a character press at this time. Some dorky BIOSes stuff
69 ; a return in the buffer on bootup, so wipe the keyboard buffer first.
71 clear_buffer: mov ah,11h ; Check for pending char
76 jmp short clear_buffer
78 ; For the first character, both KbdTimeout and
79 ; TotalTimeout apply; after that, only TotalTimeout.
82 mov eax,[TotalTimeout]
89 and dword [ThisKbdTo],0 ; For the next time...
94 got_ascii: cmp al,7Fh ; <DEL> == <BS>
99 cmp di,command_line ; Space must not be first
101 enter_char: test byte [FuncFlag],1
102 jnz ctrl_f ; Keystroke after <Ctrl-F>
103 cmp di,max_cmd_len+command_line ; Check there's space
106 call writechr ; Echo to screen
111 cmp al,'F' & 1Fh ; <Ctrl-F>
114 cmp al,'N' & 1Fh ; <Ctrl-N>
117 cmp al,'U' & 1Fh ; <Ctrl-U>
118 je kill_command ; Kill input line
119 cmp al,'V' & 1Fh ; <Ctrl-V>
121 cmp al,'X' & 1Fh ; <Ctrl-X>
123 cmp al,08h ; Backspace
125 backspace: cmp di,command_line ; Make sure there is anything
126 je get_char ; to erase
127 dec di ; Unstore one character
128 mov si,wipe_char ; and erase it from the screen
142 mov byte [FuncFlag],1
150 je .zero ; <Ctrl-F>0 = F10
151 or al,20h ; Lower case
154 cmp al,'a' ; F10-F12 = <Ctrl-F>A, B, C
168 ; AL = 0 if we get here
182 show_help: ; AX = func key # (0 = F1, 9 = F10, 11 = F12)
183 push di ; Save end-of-cmdline pointer
184 shl ax,FILENAME_MAX_LG2 ; Convert to pointer
187 cmp byte [di+NULLOFFSET],NULLFILE
188 je short fk_nofile ; Undefined F-key
190 jz short fk_nofile ; File not found
198 push di ; Command line write pointer
199 mov si,syslinux_banner
208 ; ... fall through ...
210 ; Write the boot prompt and command line again and
211 ; wait for input. Note that this expects the cursor
212 ; to already have been CRLF'd, and that the old value
213 ; of DI (the command line write pointer) is on the stack.
217 pop di ; Command line write pointer
219 mov byte [di],0 ; Null-terminate command line
221 call cwritestr ; Write command line so far
226 ; Show network info (in the form of the ipappend strings)
230 push di ; Command line write pointer
232 mov si,IPAppends ; See comboot.doc
246 ; Jump here to run the default command line
251 mov cx,(max_cmd_len+4) >> 2
253 jmp short load_kernel
256 ; Jump here when the command line is completed
260 cmp di,command_line ; Did we just hit return?
262 xor al,al ; Store a final null
265 load_kernel: ; Load the kernel now
267 ; First we need to mangle the kernel name the way DOS would...
275 ; Fast-forward to first option (we start over from the beginning, since
276 ; mangle_name doesn't necessarily return a consistent ending state.)
281 clin_is_wsp: and al,al
286 clin_opt_ptr: dec si ; Point to first nonblank
287 mov [CmdOptPtr],si ; Save ptr to first option
289 ; If "allowoptions 0", put a null character here in order to ignore any
290 ; user-specified options.
292 mov ax,[AllowOptions]
299 ; Now check if it is a "virtual kernel"
302 xor si,si ; Beginning of vk_seg
304 cmp si,[VKernelBytes]
314 ; SI updated on return
316 sub di,cx ; Return to beginning of buf
326 ; We *are* using a "virtual kernel"
330 push word real_mode_seg
333 mov si,VKernelBuf+vk_append
334 mov cx,[VKernelBuf+vk_appendlen]
336 mov [CmdLinePtr],di ; Where to add rest of cmd
340 mov si,VKernelBuf+vk_rname
341 mov cx,FILENAME_MAX ; We need ECX == CX later
345 mov al,[VKernelBuf+vk_ipappend]
348 xor bx,bx ; Try only one version
350 mov al, [VKernelBuf+vk_type]
353 %if IS_PXELINUX || IS_ISOLINUX
354 ; Is this a "localboot" pseudo-kernel?
356 cmp byte [VKernelBuf+vk_rname+4], 0
358 cmp byte [VKernelBuf+vk_rname], 0
360 jne get_kernel ; No, it's real, go get it
362 mov ax, [VKernelBuf+vk_rname+1]
371 ; Not a "virtual kernel" - check that's OK and construct the command line
373 cmp word [AllowImplicit],byte 0
389 mov [KernelType], cl ; CL == 0 here
392 ; Find the kernel on disk
394 get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/extension
395 mov di,KernelName+4*IS_PXELINUX
397 mov cx,FILENAME_MAX-5 ; Need 4 chars + null
398 repne scasb ; Scan for final null
400 dec di ; Point to final null
401 .no_skip: mov [KernelExtPtr],di
403 .search_loop: push bx
404 mov di,KernelName ; Search on disk
408 mov eax,[bx] ; Try a different extension
409 mov si,[KernelExtPtr]
413 cmp bx,exten_table_end
414 jna .search_loop ; allow == case (final case)
415 ; Fall into bad_kernel
417 ; bad_kernel: Kernel image not found
418 ; bad_implicit: The user entered a nonvirtual kernel name, with "implicit 0"
429 call unmangle_name ; Get human form
430 mov si,err_notfound ; Complain about missing kernel
435 jmp abort_load ; Ask user for clue
438 ; on_error: bad kernel, but we have onerror set; CX = OnerrorLen
449 pop di ; <E> di == command_line
450 pop bx ; <D> bx == [OnerrorLen]
451 je bad_kernel.really ; Onerror matches command_line already
452 neg bx ; bx == -[OnerrorLen]
453 lea cx,[max_cmd_len+bx]
454 ; CX == max_cmd_len-[OnerrorLen]
455 mov di,command_line+max_cmd_len-1
456 mov byte [di+1],0 ; Enforce null-termination
459 rep movsb ; Make space in command_line
461 pop cx ; <C> cx == [OnerrorLen]
462 pop di ; <B> di == command_line
463 pop si ; <A> si == Onerror
468 ; kernel_corrupt: Called if the kernel file does not seem healthy
470 kernel_corrupt: mov si,err_notkernel
474 ; Get a key, observing ThisKbdTO and ThisTotalTO -- those are timeouts
475 ; which can be adjusted by the caller based on the corresponding
476 ; master variables; on return they're updated.
478 ; This cheats. If we say "no timeout" we actually get a timeout of
486 push word [BIOS_timer]
490 cmp ax,[BIOS_timer] ; Has the timer advanced?
494 dec dword [ThisKbdTo]
496 dec dword [ThisTotalTo]
501 pop cx ; Discard return address
503 mov si,Ontimeout ; Copy ontimeout command
505 mov cx,[OntimeoutLen] ; if we have one...
516 ; This is it! We have a name (and location on the disk)... let's load
517 ; that sucker!! First we have to decide what kind of file this is; base
518 ; that decision on the file extension. The following extensions are
519 ; recognized; case insensitive:
521 ; .com - COMBOOT image
522 ; .cbt - COMBOOT image
525 ; .0 - PXE bootstrap program (PXELINUX only)
527 ; .bss - Boot sector, but transfer over DOS superblock (SYSLINUX only)
528 ; .img - Floppy image (ISOLINUX only)
530 ; Anything else is assumed to be a Linux kernel.
539 ; Alternate entry point for which the return from
540 ; searchdir is stored in memory. This is used for
541 ; COMBOOT function INT 22h, AX=0016h.
544 mov dx,[Kernel_EAX+2]
552 mov [KernelCNameLen],di
557 mov di,KernelName+4*IS_PXELINUX
563 .one_step: mov ecx,[di-4] ; 4 bytes before end
568 ; At this point, DX:AX contains the size of the kernel, SI contains
569 ; the file handle/cluster pointer, and ECX contains the extension (if any.)
571 movzx di,byte [KernelType]
573 jmp [kerneltype_table+di]
576 or ecx,20202000h ; Force lower case (except dot)
599 ; Otherwise Linux kernel
604 mov si,KernelCName ; Save the config file name, for posterity
612 ; This is an image type we can't deal with
618 %if IS_SYSLINUX || IS_MDSLINUX
621 is_bss_sector equ is_bad_image
626 is_disk_image equ is_bad_image
630 boot_prompt db 'boot: ', 0
631 wipe_char db BS, ' ', BS, 0
632 err_badimage db 'Invalid image type for this media type!', CR, LF, 0
633 err_notfound db 'Could not find kernel image: ',0
634 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
639 dw is_unknown_filetype ; VK_KERNEL
640 dw is_linux_kernel ; VK_LINUX
641 dw is_bootsector ; VK_BOOT
642 dw is_bss_sector ; VK_BSS
643 dw is_bootsector ; VK_PXE
644 dw is_disk_image ; VK_FDIMAGE
645 dw is_comboot_image ; VK_COMBOOT
646 dw is_com32_image ; VK_COM32
647 dw is_config_file ; VK_CONFIG
651 ThisKbdTo resd 1 ; Temporary holder for KbdTimeout
652 ThisTotalTo resd 1 ; Temporary holder for TotalTimeout
653 KernelExtPtr resw 1 ; During search, final null pointer
654 CmdOptPtr resw 1 ; Pointer to first option on cmd line
655 KbdFlags resb 1 ; Check for keyboard escapes
656 FuncFlag resb 1 ; Escape sequences received from keyboard
657 KernelType resb 1 ; Kernel type, from vkernel, if known
661 ; Linux kernel loading code is common.
663 %include "runkernel.inc"
666 ; COMBOOT-loading code
668 %include "comboot.inc"
670 %include "cmdline.inc"
673 ; Boot sector loading code
675 %include "bootsect.inc"
683 ; Hardware cleanup common code
685 %include "cleanup.inc"