1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2008 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 ;; -----------------------------------------------------------------------
16 ;; Common code for running a COMBOOT image
21 ; Parameter registers definition; this is the definition
22 ; of the stack frame used by INT 21h and INT 22h.
23 %define P_FLAGS word [bp+44]
24 %define P_FLAGSL byte [bp+44]
25 %define P_FLAGSH byte [bp+45]
26 %define P_CS word [bp+42]
27 %define P_IP word [bp+40]
28 %define P_CSIP dword [bp+40]
29 %define P_DS word [bp+38]
30 %define P_ES word [bp+36]
31 %define P_FS word [bp+34]
32 %define P_GS word [bp+32]
33 %define P_EAX dword [bp+28]
34 %define P_AX word [bp+28]
35 %define P_HAX word [bp+30]
36 %define P_AL byte [bp+28]
37 %define P_AH byte [bp+29]
38 %define P_ECX dword [bp+24]
39 %define P_CX word [bp+24]
40 %define P_HCX word [bp+26]
41 %define P_CL byte [bp+24]
42 %define P_CH byte [bp+25]
43 %define P_EDX dword [bp+20]
44 %define P_DX word [bp+20]
45 %define P_HDX word [bp+22]
46 %define P_DL byte [bp+20]
47 %define P_DH byte [bp+21]
48 %define P_EBX dword [bp+16]
49 %define P_BX word [bp+16]
50 %define P_HBX word [bp+18]
51 %define P_BL byte [bp+16]
52 %define P_BH byte [bp+17]
53 %define P_EBP dword [bp+8]
54 %define P_BP word [bp+8]
55 %define P_HBP word [bp+10]
56 %define P_ESI dword [bp+4]
57 %define P_SI word [bp+4]
58 %define P_HSI word [bp+6]
59 %define P_EDI dword [bp]
60 %define P_DI word [bp]
61 %define P_HDI word [bp+2]
63 ; Looks like a COMBOOT image but too large
71 ; Load a COMBOOT image. A COMBOOT image is basically a DOS .COM file,
72 ; except that it may, of course, not contain any DOS system calls. We
73 ; do, however, allow the execution of INT 20h to return to SYSLINUX.
76 push si ; Save file handle
78 call make_plain_cmdline
80 call comboot_setup_api
86 mov cx,64 ; 256 bytes (size of PSP)
87 xor eax,eax ; Clear PSP
90 mov word [es:0], 020CDh ; INT 20h instruction
91 ; First non-free paragraph
92 ; This is valid because comboot_seg == real_mode_seg
93 ; == the highest segment used by all derivatives
94 int 12h ; Get DOS memory size
95 shl ax,6 ; Kilobytes -> paragraphs
99 %if real_mode_seg != comboot_seg
100 %error "This code assumes real_mode_seg == comboot_seg"
103 ; Copy the command line from high memory
105 mov cx,125 ; Max cmdline len (minus space and CR)
106 mov di,081h ; Offset in PSP for command line
107 mov al,' ' ; DOS command lines begin with a space
117 mov al,0Dh ; CR after last character
120 sub al,82h ; Include space but not CR
121 mov [es:80h],al ; Store command line length
123 ; Now actually load the file...
125 mov bx,100h ; Load at <seg>:0100h
126 mov cx,10000h >> SECTOR_SHIFT
127 ; Absolute maximum # of sectors
129 cmp ecx,65536-256-2 ; Maximum size
132 ; And invoke the program...
137 push word 0 ; Return to address 0 -> exit
139 jmp comboot_seg:100h ; Run it
141 ; Proper return vector
142 ; Note: this gets invoked both via INT 21h and directly via INT 20h.
143 ; We don't need to cld explicitly here, because comboot_exit does that
144 ; when invoking RESET_STACK_AND_SEGS.
145 comboot_return: cli ; Don't trust anyone
146 push enter_command ; Normal return to command prompt
150 ; Set up the COMBOOT API interrupt vectors. This is also used
154 mov di,DOSErrTramp ; Error trampolines
157 mov eax,02EB206Ah ; push 20h; jmp $+4
163 mov ax,comboot_bogus-2
168 mov si,4*20h ; DOS interrupt vectors
169 mov bx,comboot_vectors
170 mov di,DOSSaveVectors
182 DOSSaveVectors resd 32
185 %define comboot_err(x) (DOSErrTramp+4*((x)-20h))
188 dw comboot_return ; INT 20 = exit
189 dw comboot_int21 ; INT 21 = DOS-compatible system calls
190 dw comboot_int22 ; INT 22 = native system calls
191 dw comboot_err(23h) ; INT 23 = DOS Ctrl-C handler
192 dw comboot_err(24h) ; INT 24 = DOS critical error handler
193 dw comboot_err(25h) ; INT 25 = DOS absolute disk read
194 dw comboot_err(26h) ; INT 26 = DOS absolute disk write
195 dw comboot_err(27h) ; INT 27 = DOS TSR
196 dw comboot_int28 ; INT 28 = DOS idle interrupt
197 dw comboot_int29 ; INT 29 = DOS fast console output
198 dw comboot_err(2Ah) ; INT 2A = DOS network API (NetBIOS)
199 dw comboot_err(2Bh) ; INT 2B = DOS reserved
200 dw comboot_err(2Ch) ; INT 2C = DOS reserved
201 dw comboot_iret ; INT 2D = DOS reserved, AMIS
202 dw comboot_err(2Eh) ; INT 2E = DOS run command
203 dw comboot_iret ; INT 2F = DOS multiplex interrupt
204 dw comboot_err(30h) ; INT 30 = DOS CP/M system calls
205 dw comboot_err(31h) ; INT 31 = DPMI
206 dw comboot_err(32h) ; INT 32 = DOS reserved
207 dw comboot_iret ; INT 33 = DOS mouse API
208 dw comboot_err(34h) ; INT 34 = DOS FPU emulation
209 dw comboot_err(35h) ; INT 35 = DOS FPU emulation
210 dw comboot_err(36h) ; INT 36 = DOS FPU emulation
211 dw comboot_err(37h) ; INT 37 = DOS FPU emulation
212 dw comboot_err(38h) ; INT 38 = DOS FPU emulation
213 dw comboot_err(39h) ; INT 39 = DOS FPU emulation
214 dw comboot_err(3Ah) ; INT 3A = DOS FPU emulation
215 dw comboot_err(3Bh) ; INT 3B = DOS FPU emulation
216 dw comboot_err(3Ch) ; INT 3C = DOS FPU emulation
217 dw comboot_err(3Dh) ; INT 3D = DOS FPU emulation
218 dw comboot_err(3Eh) ; INT 3E = DOS FPU emulation
219 dw comboot_err(3Fh) ; INT 3F = DOS overlay manager
223 ; INT 21h: generic DOS system call
234 mov bp,sp ; Set up stack frame
236 call adjust_screen ; The COMBOOT program might have changed the screen
244 ; The last function in the list is the
245 ; "no such function" function
247 call ax ; Call the invoked function
249 mov bp,sp ; In case the function clobbers BP
250 setc P_FLAGSL ; Propagate CF->error
265 ; Attempted to execute invalid DOS system call
266 ; The interrupt number is on the stack.
267 comboot_bogus: cli ; Don't trust anyone
268 pop dx ; Interrupt number
271 push comboot_bogus_tail
275 call writehex2 ; Interrupt number
279 call writehex4 ; Function number (AX)
283 call writehex8 ; CS:IP of the origin
288 ; Generic COMBOOT return to command line code
289 ; stack -> where to go next
290 ; CX -> message (for _msg version)
295 pop bx ; Return address
296 RESET_STACK_AND_SEGS SI ; Contains cld
297 call adjust_screen ; The COMBOOT program might have changed the screen
299 mov si,DOSSaveVectors
302 rep movsd ; Restore DOS-range vectors
313 ; INT 21h system calls
315 comboot_getkey: ; 01 = get key with echo
323 comboot_writechr: ; 02 = writechr
329 comboot_writeserial: ; 04 = write serial port
335 comboot_getkeynoecho: ; 08 = get key w/o echo
340 comboot_writestr: ; 09 = write DOS string
344 cmp al,'$' ; End string with $ - bizarre
351 comboot_checkkey: ; 0B = check keyboard status
352 cmp byte [APIKeyFlag],00h
356 dec al ; AL = 0FFh if present, 0 if not
361 comboot_checkver: ; 30 = check DOS version
362 ; We return 0 in all DOS-compatible version registers,
363 ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
371 cmp byte [APIKeyFlag],00h
373 call getchar ; If not queued get input
374 and al,al ; Function key? (CF <- 0)
376 mov [APIKeyWait],ah ; High part of key
377 inc byte [APIKeyFlag] ; Set flag
380 .queued: mov al,[APIKeyWait]
381 dec byte [APIKeyFlag]
403 comboot_int28 equ comboot_iret
407 ; INT 29h - DOS fast write character
412 call writechr ; Preserves registers!
416 ; INT 22h - SYSLINUX-specific system calls
417 ; System call number in ax
430 mov bp,sp ; Set up stack frame
432 call adjust_screen ; The COMBOOT program might have changed the screen
436 xor ax,ax ; Function 0 -> unimplemented
440 call [bx+int22_table]
441 jmp comboot_resume ; On return
444 ; INT 22h AX=0000h Unimplemented call
451 ; INT 22h AX=0001h Get SYSLINUX version
454 ; Number of API functions supported
457 mov P_CX,(VER_MAJOR << 8)+VER_MINOR
458 ; SYSLINUX derivative ID byte
461 mov P_BX,cs ; cs == 0
464 ; ES:SI -> version banner
465 mov P_SI,syslinux_banner
466 ; ES:DI -> copyright string
467 mov P_DI,copyright_str
474 ; INT 22h AX=0002h Write string
476 ; Write null-terminated string in ES:BX
486 ; INT 22h AX=0003h Run command
488 ; Terminates the COMBOOT program and executes the command line in
489 ; ES:BX as if it had been entered by the user.
496 push load_kernel ; Run a new kernel
497 jmp comboot_exit ; Terminate task, clean up
500 ; INT 22h AX=0004h Run default command
502 ; Terminates the COMBOOT program and executes the default command line
503 ; as if a timeout had happened or the user pressed <Enter>.
510 ; INT 22h AX=0005h Force text mode
512 ; Puts the video in standard text mode
520 ; INT 22h AX=0006h Open file
538 ; INT 22h AX=0007h Read file
547 xor si,si ; SI <- 0 on EOF, CF <- 0
553 ; INT 22h AX=0008h Close file
562 ; INT 22h AX=0009h Call PXE stack
574 comapi_pxecall equ comapi_err ; Not available
578 ; INT 22h AX=000Ah Get Derivative-Specific Info
596 mov P_CL,SECTOR_SHIFT
601 %if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
613 ; INT 22h AX=000Bh Get Serial Console Configuration
624 test byte [DisplayCon],01h
633 ; INT 22h AX=000Ch Perform final cleanup
637 ; Unload PXE if requested
640 sub bp,sp ; unload_pxe may move the stack around
642 add bp,sp ; restore frame pointer...
643 %elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
644 ; Restore original FDC table
645 mov eax,[OrigFDCTabPtr]
648 ; Reset the floppy disk subsystem
656 ; INT 22h AX=000Dh Clean up then replace bootstrap
661 mov [trackbuf+4],eax ; Copy from
663 mov [trackbuf+8],eax ; Total bytes
665 mov [trackbuf],eax ; Copy to
666 mov [EntryPoint],eax ; CS:IP entry point
670 jmp replace_bootstrap_one
674 ; INT 22h AX=000Eh Get configuration file name
683 ; INT 22h AX=000Fh Get IPAPPEND strings
688 mov P_CX,numIPAppends
695 IPAppends dw IPOption
697 numIPAppends equ ($-IPAppends)/2
700 comapi_ipappend equ comapi_err
706 ; INT 22h AX=0010h Resolve hostname
717 comapi_dnsresolv equ comapi_err
723 ; INT 22h AX=0011h Maximum number of shuffle descriptors
726 mov P_CX,trackbufsize/12
730 ; INT 22h AX=0012h Cleanup, shuffle and boot
733 cmp P_CX,(2*trackbufsize)/12
739 push cx ; On stack: descriptor count
741 lea cx,[ecx+ecx*2] ; CX *= 3
746 push di ; On stack: descriptor list address
747 fs rep movsd ; Copy the list
750 mov [EntryPoint],eax ; CS:IP entry point
754 jmp replace_bootstrap
760 ; INT 22h AX=0013h Idle call
764 ; The idle call seems to have detrimental effects on some machines when
765 ; called from a COM32 context (WHY?) -- disable it for now.
766 ; *** IS THIS STILL TRUE? ***
775 comapi_idle equ comapi_err
779 ; INT 22h AX=0014h Local boot
786 comapi_localboot equ comapi_err
787 %endif ; HAS_LOCALBOOT
790 ; INT 22h AX=0015h Feature flags
794 mov P_BX,feature_flags
795 mov P_CX,feature_flags_len
800 ; INT 22h AX=0016h Run kernel image
816 ; The kernel image was found, so we can load it...
820 ; It's not just possible, but quite likely, that ES:BX
821 ; points into real_mode_seg, so we need to exercise some
822 ; special care here... use xfer_buf_seg as an intermediary
842 ; Copy the command line into its proper place
852 mov byte [es:di-1],' ' ; Simulate APPEND
856 mov word [CmdOptPtr],zero_string
857 jmp kernel_good_saved
859 .error equ comapi_shuffle.error
862 ; INT 22h AX=0017h Report video mode change
866 cmp ax,0Fh ; Unknown flags = failure
884 ; INT 22h AX=0018h Query custom font
899 ; INT 22h AX=0019h Read disk
901 %if IS_SYSLINUX || IS_MDSLINUX || IS_ISOLINUX || IS_EXTLINUX
903 mov esi,P_ESI ; Enforce ESI == EDI == 0, these
904 or esi,P_EDI ; are reserved for future expansion
909 mov bp,P_CX ; WE CANNOT use P_* after touching bp!
917 comapi_readdisk equ comapi_err
921 ; INT 22h AX=001Ah Cleanup, shuffle and boot to flat protected mode
924 cmp P_CX,(2*trackbufsize)/12
930 push cx ; On stack: descriptor count
932 lea cx,[ecx+ecx*2] ; CX *= 3
937 push di ; On stack: descriptor list address
938 fs rep movsd ; Copy the list
942 mov edi,TrampolineBuf
943 mov al,0B8h ; MOV EAX opcode
947 inc ax ; Next register opcode
948 fs movsd ; immediate value
950 mov byte [di-5],0E9h ; Last opcode is JMP
951 sub [di-4],edi ; Make JMP target relative
953 mov dword [EntryPoint],trampoline_to_pm
954 xor bx,bx ; DS on entry
955 jmp replace_bootstrap
961 ; INT 22h AX=001Bh Cleanup, shuffle and boot with register setting
964 cmp P_CX,(2*trackbufsize)/12
970 push cx ; On stack: descriptor count
972 lea cx,[ecx+ecx*2] ; CX *= 3
977 push di ; On stack: descriptor list address
978 fs rep movsd ; Copy the list
984 ; Generate segment-loading instructions
985 mov bx,0C08Eh ; MOV ES,AX
986 mov cl,6 ; 6 segment registers (incl CS)
989 stosb ; MOV AX,imm16 opcode
996 ; Clobber the MOV CS,AX instruction.
997 mov word [di-22], 9090h ; NOP NOP
999 ; Generate GPR-loading instructions
1000 mov ax,0B866h ; MOV EAX,imm32
1003 stosw ; MOV ExX,imm32 opcode
1008 mov al,0EAh ; JMP FAR imm16:imm16 opcode
1012 mov dword [EntryPoint],TrampolineBuf
1013 jmp replace_bootstrap
1019 ; INT 22h AX=001Ch Get pointer to auxillary data vector
1028 ; INT 22h AX=001Dh Write auxillary data vector
1030 comapi_writeadv equ adv_write
1040 int21 00h, comboot_return
1041 int21 01h, comboot_getkey
1042 int21 02h, comboot_writechr
1043 int21 04h, comboot_writeserial
1044 int21 08h, comboot_getkeynoecho
1045 int21 09h, comboot_writestr
1046 int21 0Bh, comboot_checkkey
1047 int21 30h, comboot_checkver
1048 int21 4Ch, comboot_return
1049 int21 -1, comboot_bad_int21
1050 int21_count equ ($-int21_table)/3
1054 dw comapi_err ; 0000 unimplemented syscall
1055 dw comapi_get_version ; 0001 get SYSLINUX version
1056 dw comapi_writestr ; 0002 write string
1057 dw comapi_run ; 0003 run specified command
1058 dw comapi_run_default ; 0004 run default command
1059 dw comapi_textmode ; 0005 force text mode
1060 dw comapi_open ; 0006 open file
1061 dw comapi_read ; 0007 read file
1062 dw comapi_close ; 0008 close file
1063 dw comapi_pxecall ; 0009 call PXE stack
1064 dw comapi_derinfo ; 000A derivative-specific info
1065 dw comapi_serialcfg ; 000B get serial port config
1066 dw comapi_cleanup ; 000C perform final cleanup
1067 dw comapi_chainboot ; 000D clean up then bootstrap
1068 dw comapi_configfile ; 000E get name of config file
1069 dw comapi_ipappend ; 000F get ipappend strings
1070 dw comapi_dnsresolv ; 0010 resolve hostname
1071 dw comapi_maxshuffle ; 0011 maximum shuffle descriptors
1072 dw comapi_shuffle ; 0012 cleanup, shuffle and boot
1073 dw comapi_idle ; 0013 idle call
1074 dw comapi_localboot ; 0014 local boot
1075 dw comapi_features ; 0015 feature flags
1076 dw comapi_runkernel ; 0016 run kernel image
1077 dw comapi_usingvga ; 0017 report video mode change
1078 dw comapi_userfont ; 0018 query custom font
1079 dw comapi_readdisk ; 0019 read disk
1080 dw comapi_shufflepm ; 001A cleanup, shuffle and boot to pm
1081 dw comapi_shufflerm ; 001B cleanup, shuffle and boot to rm
1082 dw comapi_getadv ; 001C get pointer to ADV
1083 dw comapi_writeadv ; 001D write ADV to disk
1084 int22_count equ ($-int22_table)/2
1089 zero_string db 0 ; Empty, null-terminated string
1092 ; This is the feature flag array for INT 22h AX=0015h
1094 ; Note: PXELINUX clears the idle is noop flag if appropriate
1095 ; in pxe_detect_nic_type
1098 db 3 ; Have local boot, idle is noop
1099 feature_flags_len equ ($-feature_flags)
1101 err_notdos db ': attempted DOS system call INT ',0
1102 err_comlarge db 'COMBOOT image too large.', CR, LF, 0
1106 DOSErrTramp resd 33 ; Error trampolines
1107 ConfigName resb FILENAME_MAX