1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2009 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,(VERSION_MAJOR << 8)+VERSION_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
610 mov P_CH,al ; Mode (el torito/cbios/ebios)
617 ; INT 22h AX=000Bh Get Serial Console Configuration
628 test byte [DisplayCon],01h
637 ; INT 22h AX=000Ch Perform final cleanup
641 ; Unload PXE if requested
644 sub bp,sp ; unload_pxe may move the stack around
646 add bp,sp ; restore frame pointer...
647 %elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
648 ; Restore original FDC table
649 mov eax,[OrigFDCTabPtr]
652 ; Reset the floppy disk subsystem
660 ; INT 22h AX=000Dh Clean up then replace bootstrap
665 mov [trackbuf+4],eax ; Copy from
667 mov [trackbuf+8],eax ; Total bytes
669 mov [trackbuf],eax ; Copy to
670 mov [EntryPoint],eax ; CS:IP entry point
674 jmp replace_bootstrap_one
678 ; INT 22h AX=000Eh Get configuration file name
687 ; INT 22h AX=000Fh Get IPAPPEND strings
692 mov P_CX,numIPAppends
699 IPAppends dw IPOption
701 numIPAppends equ ($-IPAppends)/2
704 comapi_ipappend equ comapi_err
710 ; INT 22h AX=0010h Resolve hostname
721 comapi_dnsresolv equ comapi_err
727 ; INT 22h AX=0011h Maximum number of shuffle descriptors
730 mov P_CX,trackbufsize/12
734 ; INT 22h AX=0012h Cleanup, shuffle and boot
737 cmp P_CX,(2*trackbufsize)/12
743 push cx ; On stack: descriptor count
745 lea cx,[ecx+ecx*2] ; CX *= 3
750 push di ; On stack: descriptor list address
751 fs rep movsd ; Copy the list
754 mov [EntryPoint],eax ; CS:IP entry point
758 jmp replace_bootstrap
764 ; INT 22h AX=0013h Idle call
768 ; The idle call seems to have detrimental effects on some machines when
769 ; called from a COM32 context (WHY?) -- disable it for now.
770 ; *** IS THIS STILL TRUE? ***
779 comapi_idle equ comapi_err
783 ; INT 22h AX=0014h Local boot
790 comapi_localboot equ comapi_err
791 %endif ; HAS_LOCALBOOT
794 ; INT 22h AX=0015h Feature flags
798 mov P_BX,feature_flags
799 mov P_CX,feature_flags_len
804 ; INT 22h AX=0016h Run kernel image
820 ; The kernel image was found, so we can load it...
824 ; It's not just possible, but quite likely, that ES:BX
825 ; points into real_mode_seg, so we need to exercise some
826 ; special care here... use xfer_buf_seg as an intermediary
846 ; Copy the command line into its proper place
856 mov byte [es:di-1],' ' ; Simulate APPEND
860 mov word [CmdOptPtr],zero_string
861 jmp kernel_good_saved
863 .error equ comapi_shuffle.error
866 ; INT 22h AX=0017h Report video mode change
870 cmp ax,0Fh ; Unknown flags = failure
888 ; INT 22h AX=0018h Query custom font
903 ; INT 22h AX=0019h Read disk
905 %if IS_SYSLINUX || IS_MDSLINUX || IS_ISOLINUX || IS_EXTLINUX
907 mov esi,P_ESI ; Enforce ESI == EDI == 0, these
908 or esi,P_EDI ; are reserved for future expansion
913 mov bp,P_CX ; WE CANNOT use P_* after touching bp!
921 comapi_readdisk equ comapi_err
925 ; INT 22h AX=001Ah Cleanup, shuffle and boot to flat protected mode
928 cmp P_CX,(2*trackbufsize)/12
934 push cx ; On stack: descriptor count
936 lea cx,[ecx+ecx*2] ; CX *= 3
941 push di ; On stack: descriptor list address
942 fs rep movsd ; Copy the list
946 mov edi,TrampolineBuf
947 mov al,0B8h ; MOV EAX opcode
951 inc ax ; Next register opcode
952 fs movsd ; immediate value
954 mov byte [di-5],0E9h ; Last opcode is JMP
955 sub [di-4],edi ; Make JMP target relative
957 mov dword [EntryPoint],trampoline_to_pm
958 xor bx,bx ; DS on entry
959 jmp replace_bootstrap
965 ; INT 22h AX=001Bh Cleanup, shuffle and boot with register setting
968 cmp P_CX,(2*trackbufsize)/12
974 push cx ; On stack: descriptor count
976 lea cx,[ecx+ecx*2] ; CX *= 3
981 push di ; On stack: descriptor list address
982 fs rep movsd ; Copy the list
988 ; Generate segment-loading instructions
989 mov bx,0C08Eh ; MOV ES,AX
990 mov cl,6 ; 6 segment registers (incl CS)
993 stosb ; MOV AX,imm16 opcode
1000 ; Clobber the MOV CS,AX instruction.
1001 mov word [di-22], 9090h ; NOP NOP
1003 ; Generate GPR-loading instructions
1004 mov ax,0B866h ; MOV EAX,imm32
1007 stosw ; MOV ExX,imm32 opcode
1012 mov al,0EAh ; JMP FAR imm16:imm16 opcode
1016 mov dword [EntryPoint],TrampolineBuf
1017 jmp replace_bootstrap
1023 ; INT 22h AX=001Ch Get pointer to auxillary data vector
1032 ; INT 22h AX=001Dh Write auxillary data vector
1034 comapi_writeadv equ adv_write
1037 ; INT 22h AX=001Eh Keyboard remapping table
1041 mov P_AX,1 ; Version
1042 mov P_CX,256 ; Length
1051 ; INT 22h AX=001Fh Get current working directory
1055 mov P_BX,CurrentDirName
1060 ; INT 22h AX=0020h Open directory
1071 jnz comapi_err ; Didn't find a directory
1073 jz comapi_err ; Found nothing
1077 mov P_CX,SECTOR_SIZE
1082 comapi_opendir equ comapi_err
1086 ; INT 22h AX=0021h Read directory
1100 comapi_readdir equ comapi_err
1104 ; INT 22h AX=0022h Close directory
1113 comapi_closedir equ comapi_err
1124 int21 00h, comboot_return
1125 int21 01h, comboot_getkey
1126 int21 02h, comboot_writechr
1127 int21 04h, comboot_writeserial
1128 int21 08h, comboot_getkeynoecho
1129 int21 09h, comboot_writestr
1130 int21 0Bh, comboot_checkkey
1131 int21 30h, comboot_checkver
1132 int21 4Ch, comboot_return
1133 int21 -1, comboot_bad_int21
1134 int21_count equ ($-int21_table)/3
1138 dw comapi_err ; 0000 unimplemented syscall
1139 dw comapi_get_version ; 0001 get SYSLINUX version
1140 dw comapi_writestr ; 0002 write string
1141 dw comapi_run ; 0003 run specified command
1142 dw comapi_run_default ; 0004 run default command
1143 dw comapi_textmode ; 0005 force text mode
1144 dw comapi_open ; 0006 open file
1145 dw comapi_read ; 0007 read file
1146 dw comapi_close ; 0008 close file
1147 dw comapi_pxecall ; 0009 call PXE stack
1148 dw comapi_derinfo ; 000A derivative-specific info
1149 dw comapi_serialcfg ; 000B get serial port config
1150 dw comapi_cleanup ; 000C perform final cleanup
1151 dw comapi_chainboot ; 000D clean up then bootstrap
1152 dw comapi_configfile ; 000E get name of config file
1153 dw comapi_ipappend ; 000F get ipappend strings
1154 dw comapi_dnsresolv ; 0010 resolve hostname
1155 dw comapi_maxshuffle ; 0011 maximum shuffle descriptors
1156 dw comapi_shuffle ; 0012 cleanup, shuffle and boot
1157 dw comapi_idle ; 0013 idle call
1158 dw comapi_localboot ; 0014 local boot
1159 dw comapi_features ; 0015 feature flags
1160 dw comapi_runkernel ; 0016 run kernel image
1161 dw comapi_usingvga ; 0017 report video mode change
1162 dw comapi_userfont ; 0018 query custom font
1163 dw comapi_readdisk ; 0019 read disk
1164 dw comapi_shufflepm ; 001A cleanup, shuffle and boot to pm
1165 dw comapi_shufflerm ; 001B cleanup, shuffle and boot to rm
1166 dw comapi_getadv ; 001C get pointer to ADV
1167 dw comapi_writeadv ; 001D write ADV to disk
1168 dw comapi_kbdtable ; 001E keyboard remapping table
1169 dw comapi_getcwd ; 001F get current working directory
1170 dw comapi_opendir ; 0020 open directory
1171 dw comapi_readdir ; 0021 read directory
1172 dw comapi_closedir ; 0022 close directory
1173 int22_count equ ($-int22_table)/2
1178 zero_string db 0 ; Empty, null-terminated string
1181 ; This is the feature flag array for INT 22h AX=0015h
1183 ; Note: PXELINUX clears the idle is noop flag if appropriate
1184 ; in pxe_detect_nic_type
1187 db 3 ; Have local boot, idle is noop
1188 feature_flags_len equ ($-feature_flags)
1190 err_notdos db ': attempted DOS system call INT ',0
1191 err_comlarge db 'COMBOOT image too large.', CR, LF, 0
1195 DOSErrTramp resd 33 ; Error trampolines
1196 ConfigName resb FILENAME_MAX
1197 CurrentDirName resb FILENAME_MAX