This commit was generated by cvs2svn to compensate for changes in r1815,
[bootcd.git] / syslinux / comboot.inc
diff --git a/syslinux/comboot.inc b/syslinux/comboot.inc
new file mode 100644 (file)
index 0000000..afd2c24
--- /dev/null
@@ -0,0 +1,693 @@
+;; $Id: comboot.inc,v 1.39 2005/01/20 18:43:22 hpa Exp $
+;; -----------------------------------------------------------------------
+;;   
+;;   Copyright 1994-2005 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
+;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+;;   Boston MA 02111-1307, USA; either version 2 of the License, or
+;;   (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+;;
+;; comboot.inc
+;; 
+;; Common code for running a COMBOOT image
+;;
+
+               section .text
+
+; Parameter registers definition; this is the definition
+; of the stack frame used by INT 21h and INT 22h.
+%define                P_FLAGS         word [bp+44]
+%define                P_FLAGSL        byte [bp+44]
+%define                P_FLAGSH        byte [bp+45]
+%define                P_CS            word [bp+42]
+%define                P_IP            word [bp+40]
+%define                P_DS            word [bp+38]
+%define                P_ES            word [bp+36]
+%define                P_FS            word [bp+34]
+%define                P_GS            word [bp+32]
+%define                P_EAX           dword [bp+28]
+%define                P_AX            word [bp+28]
+%define                P_HAX           word [bp+30]
+%define                P_AL            byte [bp+28]
+%define                P_AH            byte [bp+29]
+%define                P_ECX           dword [bp+24]
+%define                P_CX            word [bp+24]
+%define                P_HCX           word [bp+26]
+%define                P_CL            byte [bp+24]
+%define                P_CH            byte [bp+25]
+%define                P_EDX           dword [bp+20]
+%define                P_DX            word [bp+20]
+%define                P_HDX           word [bp+22]
+%define                P_DL            byte [bp+20]
+%define                P_DH            byte [bp+21]
+%define                P_EBX           dword [bp+16]
+%define                P_BX            word [bp+16]
+%define                P_HBX           word [bp+18]
+%define                P_BL            byte [bp+16]
+%define                P_BH            byte [bp+17]
+%define                P_EBP           dword [bp+8]
+%define                P_BP            word [bp+8]
+%define                P_HBP           word [bp+10]
+%define                P_ESI           dword [bp+4]
+%define                P_SI            word [bp+4]
+%define                P_HSI           word [bp+6]
+%define                P_EDI           dword [bp]
+%define                P_DI            word [bp]
+%define                P_HDI           word [bp+2]
+
+; Looks like a COMBOOT image but too large
+comboot_too_large:
+               mov si,err_comlarge
+               call cwritestr
+               jmp enter_command
+
+;
+; Load a COMBOOT image.  A COMBOOT image is basically a DOS .COM file,
+; except that it may, of course, not contain any DOS system calls.  We
+; do, however, allow the execution of INT 20h to return to SYSLINUX.
+;
+is_comboot_image:
+               and dx,dx
+               jnz comboot_too_large
+               cmp ax,0ff00h           ; Max size in bytes
+               jae comboot_too_large
+
+               push si                 ; Save file handle
+
+               call make_plain_cmdline
+
+               call comboot_setup_api
+
+               mov cx,comboot_seg
+               mov es,cx
+
+               xor di,di
+               mov cx,64               ; 256 bytes (size of PSP)
+               xor eax,eax             ; Clear PSP
+               rep stosd
+
+               mov word [es:0], 020CDh ; INT 20h instruction
+               ; First non-free paragraph
+               ; This is valid because comboot_seg == real_mode_seg
+               ; == the highest segment used by all derivatives
+               int 12h                 ; Get DOS memory size
+               shl ax,6                ; Kilobytes -> paragraphs
+               mov word [es:02h],ax
+
+%ifndef DEPEND
+%if real_mode_seg != comboot_seg
+%error "This code assumes real_mode_seg == comboot_seg"
+%endif
+%endif
+               ; Copy the command line from high memory
+               mov si,cmd_line_here
+               mov cx,125              ; Max cmdline len (minus space and CR)
+               mov di,081h             ; Offset in PSP for command line
+               mov al,' '              ; DOS command lines begin with a space
+               stosb
+
+.loop:         es lodsb
+               and al,al
+               jz .done
+               stosb
+               loop .loop
+.done:
+
+               mov al,0Dh              ; CR after last character
+               stosb
+               mov ax,di
+               sub al,82h              ; Include space but not CR
+               mov [es:80h],al         ; Store command line length
+
+               ; Now actually load the file...
+               pop si                  ; File handle
+               mov bx,100h             ; Load at <seg>:0100h
+               mov cx,0FF00h >> SECTOR_SHIFT
+                                       ; Absolute maximum # of sectors
+               call getfssec
+
+               ; And invoke the program...
+               mov [SavedSSSP],sp
+               mov [SavedSSSP+2],ss    ; Save away SS:SP
+
+               mov ax,es
+               mov ds,ax
+               mov ss,ax
+               xor sp,sp
+               push word 0             ; Return to address 0 -> exit
+
+               jmp comboot_seg:100h    ; Run it
+
+; Proper return vector
+comboot_return:        cli                     ; Don't trust anyone
+               xor ax,ax
+               jmp comboot_exit
+
+;
+; Set up the COMBOOT API interrupt vectors.  This is also used
+; by the COM32 code.
+;
+comboot_setup_api:
+               mov di,4*0x20           ; DOS interrupt vectors
+               mov eax,comboot_return  ; INT 20h = exit
+               stosd
+               mov ax,comboot_int21    ; INT 21h = DOS-compatible syscalls
+               stosd
+               mov ax,comboot_int22    ; INT 22h = proprietary syscalls
+               stosd
+               mov ax,comboot_bogus
+               mov cx,29               ; All remaining DOS vectors
+               rep stosd
+               ret
+
+; INT 21h: generic DOS system call
+comboot_int21: cli
+               push ds
+               push es
+               push fs
+               push gs
+               pushad
+               cld
+               mov bp,cs
+               mov ds,bp
+               mov es,bp
+               mov bp,sp                       ; Set up stack frame
+
+               call adjust_screen              ; The COMBOOT program might have changed the screen
+
+               mov cx,int21_count
+               mov si,int21_table
+.again:                lodsb
+               cmp al,P_AH
+               lodsw
+               loopne .again
+               ; The last function in the list is the
+               ; "no such function" function
+               clc
+               call ax                 ; Call the invoked function
+comboot_resume:
+               setc P_FLAGSL           ; Propagate CF->error
+               popad
+               pop gs
+               pop fs
+               pop es
+               pop ds
+               iret
+
+; Attempted to execute non-21h DOS system call
+comboot_bogus: cli                     ; Don't trust anyone
+               mov ax,err_notdos
+;
+; Generic COMBOOT return to command line code
+;  AX -> message (if any)
+;  BX -> where to go next
+;
+comboot_exit:
+               mov bx,enter_command    ; Normal return to command prompt
+comboot_exit_special:
+               xor dx,dx
+               mov ds,dx
+               mov es,dx
+               lss sp,[SavedSSSP]
+               sti
+               cld
+               call adjust_screen      ; The COMBOOT program might have changed the screen
+               and ax,ax
+               je .nomsg
+               mov si,KernelCName
+               call cwritestr
+               xchg si,ax
+               call cwritestr
+.nomsg:                jmp bx
+
+;
+; INT 21h system calls
+;
+comboot_getkey:                                ; 01 = get key with echo
+               call vgashowcursor
+               call comboot_getchar
+               call vgahidecursor
+               call writechr
+               clc
+               ret
+
+comboot_writechr:                      ; 02 = writechr
+               mov al,P_DL
+               call writechr
+               clc
+               ret
+
+comboot_writeserial:                   ; 04 = write serial port
+               mov al,P_DL
+               call write_serial
+               clc
+               ret
+
+comboot_getkeynoecho:                  ; 08 = get key w/o echo
+               call comboot_getchar
+               clc
+               ret
+
+comboot_writestr:                      ; 09 = write DOS string
+               mov es,P_DS
+               mov si,P_DX
+.loop:         es lodsb
+               cmp al,'$'              ; End string with $ - bizarre
+               je .done
+               call writechr
+               jmp short .loop
+.done:         clc
+               ret
+
+comboot_checkkey:                      ; 0B = check keyboard status
+               cmp byte [APIKeyFlag],00h
+               jnz .waiting
+               call pollchar
+.waiting:      setz al
+               dec al                  ; AL = 0FFh if present, 0 if not
+               mov P_AL,al
+               clc
+               ret
+
+comboot_checkver:                      ; 30 = check DOS version
+               ; We return 0 in all DOS-compatible version registers,
+               ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
+               mov P_EAX,'SY' << 16
+               mov P_EBX,'SL' << 16
+               mov P_ECX,'IN' << 16
+               mov P_EDX,'UX' << 16
+               ret
+
+comboot_getchar:
+               cmp byte [APIKeyFlag],00h
+               jne .queued
+               call getchar            ; If not queued get input
+               and al,al               ; Function key?  (CF <- 0)
+               jnz .done
+               mov [APIKeyWait],ah     ; High part of key
+               inc byte [APIKeyFlag]   ; Set flag
+.done:         mov P_AL,al
+               ret
+.queued:       mov al,[APIKeyWait]
+               dec byte [APIKeyFlag]
+               jmp .done
+
+;
+; INT 22h - SYSLINUX-specific system calls
+;           System call number in ax
+;
+comboot_int22:
+               cli
+               push ds
+               push es
+               push fs
+               push gs
+               pushad
+               cld
+               mov bp,cs
+               mov ds,bp
+               mov es,bp
+               mov bp,sp                       ; Set up stack frame
+
+               call adjust_screen              ; The COMBOOT program might have changed the screen
+
+               cmp ax,int22_count
+               jb .ok
+               xor ax,ax                       ; Function 0 -> unimplemented
+.ok:
+               xchg ax,bx
+               add bx,bx                       ; CF <- 0
+               call [bx+int22_table]
+               jmp comboot_resume              ; On return
+
+;
+; INT 22h AX=0000h     Unimplemented call
+;
+comapi_err:
+               stc
+               ret
+
+;
+; INT 22h AX=0001h     Get SYSLINUX version
+;
+comapi_get_version:
+               ; Number of API functions supported
+               mov P_AX,int22_count
+               ; SYSLINUX version
+               mov P_CX,(VER_MAJOR << 8)+VER_MINOR
+               ; SYSLINUX derivative ID byte
+               mov P_DX,my_id
+               ; For future use
+               mov P_BX,cs     ; cs == 0
+
+               mov P_ES,ds
+               ; ES:SI -> version banner
+               mov P_SI,syslinux_banner
+               ; ES:DI -> copyright string
+               mov P_DI,copyright_str
+
+comapi_nop:
+               clc
+               ret
+
+;
+; INT 22h AX=0002h     Write string
+;
+; Write null-terminated string in ES:BX
+;
+comapi_writestr:
+               mov ds,P_ES
+               mov si,P_BX
+               call writestr
+               clc
+               ret
+
+;
+; INT 22h AX=0003h     Run command
+;
+; Terminates the COMBOOT program and executes the command line in
+; ES:BX as if it had been entered by the user.
+;
+comapi_run:
+               mov ds,P_ES
+               mov si,P_BX
+               mov di,command_line
+               call strcpy
+               xor ax,ax
+               mov bx,load_kernel              ; Run a new kernel
+               jmp comboot_exit_special        ; Terminate task, clean up
+
+;
+; INT 22h AX=0004h     Run default command             
+;
+; Terminates the COMBOOT program and executes the default command line
+; as if a timeout had happened or the user pressed <Enter>.
+;
+comapi_run_default:
+               mov bx,auto_boot
+               jmp comboot_exit_special
+
+;
+; INT 22h AX=0005h     Force text mode
+;
+; Puts the video in standard text mode
+;
+comapi_textmode:
+               call vgaclearmode
+               clc
+               ret
+
+;
+; INT 22h AX=0006h     Open file
+;
+comapi_open:
+               push ds
+               mov ds,P_ES
+               mov si,P_SI
+               mov di,InitRD
+               push di
+               call mangle_name
+               pop di
+               pop ds
+               call searchdir
+               jz .err
+               mov P_AX,ax
+               mov P_HAX,dx
+               mov P_CX,SECTOR_SIZE
+               mov P_SI,si
+               clc
+               ret
+.err:
+               stc
+               ret
+
+
+;
+; INT 22h AX=0007h     Read file
+;
+comapi_read:
+               mov es,P_ES
+               mov bx,P_BX
+               mov si,P_SI
+               mov cx,P_CX
+               call getfssec
+               jnc .noteof
+               xor si,si               ; SI <- 0 on EOF, CF <- 0
+.noteof:       mov P_SI,si
+               ret
+
+;
+; INT 22h AX=0008h     Close file
+;
+comapi_close:
+               ; Do nothing for now.  Eventually implement
+               ; an internal API for this.
+               clc
+               ret
+
+;
+; INT 22h AX=0009h     Call PXE stack
+;
+%if IS_PXELINUX
+comapi_pxecall:
+               mov bx,P_BX
+               mov es,P_ES
+               mov di,P_DI
+               call pxenv
+               mov P_AX,ax
+               clc
+               ret
+%else
+comapi_pxecall equ comapi_err                  ; Not available
+%endif
+
+;
+; INT 22h AX=000Ah     Get Derivative-Specific Info
+;
+comapi_derinfo:
+               mov P_AL,my_id
+%if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
+               mov al,[DriveNumber]
+               mov P_DL,al
+               mov P_ES,cs
+               mov P_BX,PartInfo
+%elif IS_PXELINUX
+               mov ax,[APIVer]
+               mov P_DX,ax
+               mov ax,[StrucPtr]
+               mov P_BX,ax
+               mov ax,[StrucPtr+2]
+               mov P_ES,ax
+               mov ax,[InitStack]
+               mov P_SI,ax
+               mov ax,[InitStack+2]
+               mov P_FS,ax
+%elif IS_ISOLINUX
+               mov al,[DriveNo]
+               mov P_DL,al
+               mov P_ES,cs
+               mov P_BX,spec_packet
+%endif
+               clc
+               ret
+
+;
+; INT 22h AX=000Bh     Get Serial Console Configuration
+;
+comapi_serialcfg:
+               mov ax,[SerialPort]
+               mov P_DX,ax
+               mov ax,[BaudDivisor]
+               mov P_CX,ax
+               mov ax,[FlowControl]
+               or al,ah
+               mov ah,[FlowIgnore]
+               shr ah,4
+               test byte [DisplayCon],01h
+               jnz .normalconsole
+               or ah,80h
+.normalconsole:
+               mov P_BX,ax
+               clc
+               ret
+
+;
+; INT 22h AX=000Ch     Perform final cleanup
+;
+comapi_cleanup:
+%if IS_PXELINUX
+               ; Unload PXE if requested
+               test dl,3
+               setnz [KeepPXE]
+               sub bp,sp               ; unload_pxe may move the stack around
+               call unload_pxe
+               add bp,sp               ; restore frame pointer...
+%elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
+               ; Restore original FDC table
+               mov eax,[OrigFDCTabPtr]
+               mov [fdctab],eax
+%endif
+               ; Reset the floppy disk subsystem
+               xor ax,ax
+               xor dx,dx
+               int 13h
+               clc
+               ret
+
+;
+; INT 22h AX=000Dh     Clean up then replace bootstrap
+;
+comapi_chainboot:
+               call comapi_cleanup
+               mov eax,P_EDI
+               mov [trackbuf+4],eax            ; Copy from
+               mov eax,P_ECX
+               mov [trackbuf+8],eax            ; Total bytes
+               mov eax,7C00h
+               mov [trackbuf],eax              ; Copy to
+               mov [EntryPoint],eax            ; CS:IP entry point
+               mov esi,P_ESI
+               mov edx,P_EBX
+               mov bx,P_DS
+               jmp replace_bootstrap_one
+
+
+;
+; INT 22h AX=000Eh     Get configuration file name
+;
+comapi_configfile:
+               mov P_ES,cs
+               mov P_BX,ConfigName
+               clc
+               ret
+
+;
+; INT 22h AX=000Fh     Get IPAPPEND strings
+;
+%if IS_PXELINUX
+comapi_ipappend:
+               mov P_ES,cs
+               mov P_CX,numIPAppends
+               mov P_BX,IPAppends
+               clc
+               ret
+
+               section .data
+               alignb 2, db 0
+IPAppends      dw IPOption
+               dw BOOTIFStr
+numIPAppends   equ ($-IPAppends)/2
+
+%else
+comapi_ipappend equ comapi_err
+%endif
+
+;
+; INT 22h AX=0010h     Resolve hostname
+;
+%if IS_PXELINUX
+comapi_dnsresolv:
+               mov ds,P_ES
+               mov si,P_BX
+               call dns_resolv
+               mov P_EAX,eax
+               ret
+%else
+comapi_dnsresolv equ comapi_err
+%endif
+               
+               section .data
+%macro                 int21 2
+               db %1
+               dw %2
+%endmacro
+
+
+;
+; INT 22h AX=0011h     Maximum number of shuffle descriptors
+;
+comapi_maxshuffle:
+               mov P_CX,(2*trackbufsize)/12
+               ret
+
+;
+; INT 22h AX=0012h     Cleanup, shuffle and boot
+;
+comapi_shuffle:
+               call comapi_cleanup
+               mov cx,P_CX
+               cmp cx,(2*trackbufsize)/12
+               ja .error
+
+               push cx                         ; On stack: descriptor count
+
+               lea cx,[ecx+ecx*2]              ; CX *= 3
+
+               mov fs,P_ES
+               mov si,P_DI
+               mov di,trackbuf
+               push di                         ; On stack: descriptor list address
+               fs rep movsd                    ; Copy the list
+
+               mov eax,P_EBP
+               mov [EntryPoint],eax            ; CS:IP entry point
+               mov esi,P_ESI
+               mov edx,P_EBX
+               mov bx,P_DS
+               jmp replace_bootstrap
+.error:
+               stc
+               ret
+
+;
+; INT 22h AX=0013h     Idle call
+;
+comapi_idle:
+               DO_IDLE
+               clc
+               ret
+
+int21_table:
+               int21   00h, comboot_return
+               int21   01h, comboot_getkey
+               int21   02h, comboot_writechr
+               int21   04h, comboot_writeserial
+               int21   08h, comboot_getkeynoecho
+               int21   09h, comboot_writestr
+               int21   0Bh, comboot_checkkey
+               int21   30h, comboot_checkver
+               int21   4Ch, comboot_return
+               int21    -1, comboot_bogus
+int21_count    equ ($-int21_table)/3
+
+               align 2, db 0
+int22_table:
+               dw comapi_err           ; 0000 unimplemented syscall
+               dw comapi_get_version   ; 0001 get SYSLINUX version
+               dw comapi_writestr      ; 0002 write string
+               dw comapi_run           ; 0003 run specified command
+               dw comapi_run_default   ; 0004 run default command
+               dw comapi_textmode      ; 0005 force text mode
+               dw comapi_open          ; 0006 open file
+               dw comapi_read          ; 0007 read file
+               dw comapi_close         ; 0008 close file
+               dw comapi_pxecall       ; 0009 call PXE stack
+               dw comapi_derinfo       ; 000A derivative-specific info
+               dw comapi_serialcfg     ; 000B get serial port config
+               dw comapi_cleanup       ; 000C perform final cleanup
+               dw comapi_chainboot     ; 000D clean up then bootstrap
+               dw comapi_configfile    ; 000E get name of config file
+               dw comapi_ipappend      ; 000F get ipappend strings
+               dw comapi_dnsresolv     ; 0010 resolve hostname
+               dw comapi_maxshuffle    ; 0011 maximum shuffle descriptors
+               dw comapi_shuffle       ; 0012 cleanup, shuffle and boot
+               dw comapi_idle          ; 0013 idle call
+int22_count    equ ($-int22_table)/2
+
+APIKeyWait     db 0
+APIKeyFlag     db 0