--- trunk/mkinitrd-magellan/isolinux/ui.inc 2010/08/19 08:27:19 1132 +++ trunk/mkinitrd-magellan/isolinux/ui.inc 2010/08/19 09:50:43 1133 @@ -1,7 +1,7 @@ -;; $Id: ui.inc,v 1.1 2007-09-01 22:44:05 niro Exp $ ;; ----------------------------------------------------------------------- -;; -;; Copyright 1994-2005 H. Peter Anvin - All Rights Reserved +;; +;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved +;; Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin ;; ;; 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 @@ -14,23 +14,54 @@ ; ; 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],0 ; Force prompt? - jnz enter_command test byte [KbdFlags],5Bh ; Shift Alt Caps Scroll - jz auto_boot ; If neither, default boot + jnz enter_command + cmp word [ForcePrompt],0 ; Force prompt? + jz auto_boot + cmp word [DefaultLevel],1 ; Active UI statement? + ja auto_boot enter_command: cmp word [NoEscape],0 ; If NOESCAPE, no prompt, jne auto_boot ; always run default cmd mov si,boot_prompt - call cwritestr + call writestr mov byte [FuncFlag],0 ; not pressed mov di,command_line @@ -71,23 +102,23 @@ 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 + 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,09h ; Tab + je display_labels cmp al,'F' & 1Fh ; je set_func_flag +%if IS_PXELINUX + cmp al,'N' & 1Fh ; + je show_network_info +%endif cmp al,'U' & 1Fh ; je kill_command ; Kill input line cmp al,'V' & 1Fh ; @@ -100,8 +131,9 @@ je get_char ; to erase dec di ; Unstore one character mov si,wipe_char ; and erase it from the screen - call cwritestr - jmp short get_char_2 + call writestr +get_char_2: + jmp short get_char kill_command: call crlf @@ -113,46 +145,111 @@ set_func_flag: mov byte [FuncFlag],1 -get_char_2: - jmp short get_char + jmp short get_char_2 + +display_labels: + cmp word [NoComplete],0 ; Label completion enabled? + jne get_char_2 + push di ; Save pointer + mov cx,di + sub cx,command_line + call crlf + mov esi,[HighMemSize] ; Start from top of memory +.scan: + cmp esi,[VKernelEnd] + jbe .not_vk -ctrl_f_0: add al,10 ; 0 == F10 -ctrl_f: sub al,'1' + push cx ; save command line size + + mov edi,VKernelBuf + call rllunpack + ; ESI updated on return + + sub di,cx ; Return to beginning of buf + pop cx ; restore command line size + push si ; save SI + cmp cx,0 + jz .print + push di + push cx + mov si,command_line + es repe cmpsb + pop cx + pop di + jne .next +.print: + mov al,' ' + call writechr + + mov si,di + call writestr +.next: + pop si ; restore SI + jmp .scan +.not_vk: + call crlf + jmp fk_wrcmd + +ctrl_f: xor ah,ah - jmp short show_help + mov [FuncFlag],ah + cmp al,'0' + jb get_char_2 + je .zero ; 0 = F10 + or al,20h ; Lower case + cmp al,'9' + jna .digit + cmp al,'a' ; F10-F12 = 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+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 print_version: push di ; Command line write pointer mov si,syslinux_banner - call cwritestr + call writestr %ifdef HAVE_BIOSNAME mov si,[BIOSName] - call cwritestr + call writestr %endif mov si,copyright_str - call cwritestr + call writestr ; ... fall through ... @@ -162,25 +259,60 @@ ; of DI (the command line write pointer) is on the stack. fk_wrcmd: mov si,boot_prompt - call cwritestr + call writestr pop di ; Command line write pointer push di mov byte [di],0 ; Null-terminate command line mov si,command_line - call cwritestr ; Write command line so far + call writestr ; 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 writestr + call crlf + pop si + loop .loop + jmp fk_wrcmd +%endif ; ; Jump here to run the default command line ; auto_boot: + cmp word [DefaultLevel],0 ; No UI or DEFAULT? + jne .have_default + mov si,no_default_msg + call writestr + cmp word [NoEscape],0 ; NOESCAPE but no DEFAULT? + jne kaboom ; If so, we're stuck! + jmp enter_command + +.have_default: mov si,default_cmd mov di,command_line mov cx,(max_cmd_len+4) >> 2 rep movsd jmp short load_kernel + section .data +no_default_msg db 'No DEFAULT or UI configuration directive found!' + db CR, LF, 0 + + section .text + ; ; Jump here when the command line is completed ; @@ -198,9 +330,7 @@ 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 @@ -230,28 +360,31 @@ ; 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 + cmp esi,[VKernelEnd] + jbe .not_vk - push ds - push word vk_seg - pop ds - - mov di,VKernelBuf + mov edi,VKernelBuf call rllunpack - pop ds - ; SI updated on return + ; ESI updated on return sub di,cx ; Return to beginning of buf push si - mov si,KernelName - mov cx,FILENAME_MAX - es repe cmpsb + mov si,command_line +.loop: + lodsb + cmp al,' ' + jbe .done + scasb + je .loop +.nomatch: pop si - je .found jmp .scan +.done: + cmp byte [di],0 ; Must match end of string + jne .nomatch + pop si ; ; We *are* using a "virtual kernel" @@ -267,7 +400,7 @@ 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 @@ -278,23 +411,18 @@ %endif xor bx,bx ; Try only one version -%if IS_PXELINUX || IS_ISOLINUX + mov al,[VKernelBuf+vk_type] + mov [KernelType],al + +%if HAS_LOCALBOOT ; Is this a "localboot" pseudo-kernel? -%if IS_PXELINUX - cmp byte [VKernelBuf+vk_rname+4], 0 -%else - cmp byte [VKernelBuf+vk_rname], 0 + cmp al,VK_LOCALBOOT ; al == KernelType + mov ax,[VKernelBuf+vk_rname] ; Possible localboot type + je local_boot %endif - jne get_kernel ; No, it's real, go get it - - mov ax, [VKernelBuf+vk_rname+1] - jmp local_boot -%else jmp get_kernel -%endif .not_vk: - ; ; Not a "virtual kernel" - check that's OK and construct the command line ; @@ -313,36 +441,32 @@ 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+4*IS_PXELINUX + cmp byte [di],' ' + jbe bad_kernel ; Missing kernel name 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) @@ -362,14 +486,14 @@ push di call unmangle_name ; Get human form mov si,err_notfound ; Complain about missing kernel - call cwritestr + call writestr pop si ; KernelCName - call cwritestr + call writestr mov si,crlf_msg 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 @@ -414,17 +538,17 @@ ; getchar_timeout: call vgashowcursor - RESET_IDLE + call reset_idle .loop: push word [BIOS_timer] call pollchar jnz .got_char + call do_idle pop ax cmp ax,[BIOS_timer] ; Has the timer advanced? je .loop - DO_IDLE - + dec dword [ThisKbdTo] jz .timeout dec dword [ThisTotalTo] @@ -452,7 +576,7 @@ ; 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 @@ -475,21 +599,31 @@ ; COMBOOT function INT 22h, AX=0016h. mov si,[Kernel_SI] mov eax,[Kernel_EAX] - mov dx,[Kernel_EAX+2] kernel_good: - pusha + pushad + ; + ; Common initialization for all kernel types + ; + xor ax,ax + mov [InitRDPtr],ax + mov [QuietBoot],al +%if IS_PXELINUX + mov [KeepPXE],al +%endif + 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+4*IS_PXELINUX @@ -501,13 +635,17 @@ .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 @@ -523,20 +661,62 @@ 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 writestr + jmp enter_command + +%if IS_SYSLINUX + ; 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 + + + alignz 2 +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 4 @@ -546,5 +726,32 @@ 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"