COMBOOT API: Add calls for directory functions; Implement for FAT
[syslinux.git] / core / comboot.inc
blob2ff5f33ee121c35103ca1338de67727b036913f6
1 ;; -----------------------------------------------------------------------
2 ;;
3 ;;   Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
4 ;;
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 ;; comboot.inc
16 ;; Common code for running a COMBOOT image
19                 section .text
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
64 comboot_too_large:
65                 call close_file
66                 mov si,err_comlarge
67                 call writestr
68                 jmp enter_command
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.
75 is_comboot_image:
76                 push si                 ; Save file handle
78                 call make_plain_cmdline
80                 call comboot_setup_api
82                 mov cx,comboot_seg
83                 mov es,cx
85                 xor di,di
86                 mov cx,64               ; 256 bytes (size of PSP)
87                 xor eax,eax             ; Clear PSP
88                 rep stosd
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
96                 mov word [es:02h],ax
98 %ifndef DEPEND
99 %if real_mode_seg != comboot_seg
100 %error "This code assumes real_mode_seg == comboot_seg"
101 %endif
102 %endif
103                 ; Copy the command line from high memory
104                 mov si,cmd_line_here
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
108                 stosb
110 .loop:          es lodsb
111                 and al,al
112                 jz .done
113                 stosb
114                 loop .loop
115 .done:
117                 mov al,0Dh              ; CR after last character
118                 stosb
119                 mov ax,di
120                 sub al,82h              ; Include space but not CR
121                 mov [es:80h],al         ; Store command line length
123                 ; Now actually load the file...
124                 pop si                  ; File handle
125                 mov bx,100h             ; Load at <seg>:0100h
126                 mov cx,10000h >> SECTOR_SHIFT
127                                         ; Absolute maximum # of sectors
128                 call getfssec
129                 cmp ecx,65536-256-2     ; Maximum size
130                 ja comboot_too_large
132                 ; And invoke the program...
133                 mov ax,es
134                 mov ds,ax
135                 mov ss,ax
136                 xor sp,sp
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
147                 jmp comboot_exit
150 ; Set up the COMBOOT API interrupt vectors.  This is also used
151 ; by the COM32 code.
153 comboot_setup_api:
154                 mov di,DOSErrTramp      ; Error trampolines
155                 mov cx,32
156                 push cx
157                 mov eax,02EB206Ah       ; push 20h; jmp $+4
158 .loop1:         stosd
159                 inc ah
160                 loop .loop1
161                 dec di
162                 mov byte [di-1],0E9h
163                 mov ax,comboot_bogus-2
164                 sub ax,di
165                 stosw
167                 pop cx                  ; CX <- 32
168                 mov si,4*20h            ; DOS interrupt vectors
169                 mov bx,comboot_vectors
170                 mov di,DOSSaveVectors
171 .loop2:
172                 movsd
173                 movzx eax,word [bx]
174                 inc bx
175                 inc bx
176                 mov [si-4],eax
177                 loop .loop2
178                 ret
180                 section .bss
181                 alignb 4
182 DOSSaveVectors  resd 32
184                 section .data
185 %define comboot_err(x) (DOSErrTramp+4*((x)-20h))
187 comboot_vectors:
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
221                 section .text
223 ; INT 21h: generic DOS system call
224 comboot_int21:  cli
225                 push ds
226                 push es
227                 push fs
228                 push gs
229                 pushad
230                 cld
231                 mov bp,cs
232                 mov ds,bp
233                 mov es,bp
234                 mov bp,sp                       ; Set up stack frame
236                 call adjust_screen              ; The COMBOOT program might have changed the screen
238                 mov cx,int21_count
239                 mov si,int21_table
240 .again:         lodsb
241                 cmp al,P_AH
242                 lodsw
243                 loopne .again
244                 ; The last function in the list is the
245                 ; "no such function" function
246                 clc
247                 call ax                 ; Call the invoked function
248 comboot_resume:
249                 mov bp,sp               ; In case the function clobbers BP
250                 setc P_FLAGSL           ; Propagate CF->error
251                 popad
252                 pop gs
253                 pop fs
254                 pop es
255                 pop ds
256 comboot_iret:
257                 iret
259 comboot_bad_int21:
260                 mov ax,P_AX
261                 push P_CSIP
262                 push 21h
263                 ; Fall through
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
269                 pop edi                 ; CS:IP
270                 mov cx,err_notdos
271                 push comboot_bogus_tail
272                 jmp comboot_exit_msg
273 comboot_bogus_tail:
274                 xchg ax,dx
275                 call writehex2          ; Interrupt number
276                 mov al,' '
277                 call writechr
278                 xchg ax,dx
279                 call writehex4          ; Function number (AX)
280                 mov al,' '
281                 call writechr
282                 mov eax,edi
283                 call writehex8          ; CS:IP of the origin
284                 call crlf
285                 jmp enter_command
288 ; Generic COMBOOT return to command line code
289 ;  stack -> where to go next
290 ;     CX -> message (for _msg version)
292 comboot_exit:
293                 xor cx,cx
294 comboot_exit_msg:
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
298                 pusha
299                 mov si,DOSSaveVectors
300                 mov di,4*20h
301                 mov cx,20h
302                 rep movsd               ; Restore DOS-range vectors
303                 popa
304                 jcxz .nomsg
305                 mov si,KernelCName
306                 call writestr
307                 mov si,cx
308                 call writestr
309 .nomsg:
310                 jmp bx
313 ; INT 21h system calls
315 comboot_getkey:                         ; 01 = get key with echo
316                 call vgashowcursor
317                 call comboot_getchar
318                 call vgahidecursor
319                 call writechr
320                 clc
321                 ret
323 comboot_writechr:                       ; 02 = writechr
324                 mov al,P_DL
325                 call writechr
326                 clc
327                 ret
329 comboot_writeserial:                    ; 04 = write serial port
330                 mov al,P_DL
331                 call write_serial
332                 clc
333                 ret
335 comboot_getkeynoecho:                   ; 08 = get key w/o echo
336                 call comboot_getchar
337                 clc
338                 ret
340 comboot_writestr:                       ; 09 = write DOS string
341                 mov es,P_DS
342                 mov si,P_DX
343 .loop:          es lodsb
344                 cmp al,'$'              ; End string with $ - bizarre
345                 je .done
346                 call writechr
347                 jmp short .loop
348 .done:          clc
349                 ret
351 comboot_checkkey:                       ; 0B = check keyboard status
352                 cmp byte [APIKeyFlag],00h
353                 jnz .waiting
354                 call pollchar
355 .waiting:       setz al
356                 dec al                  ; AL = 0FFh if present, 0 if not
357                 mov P_AL,al
358                 clc
359                 ret
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"
364                 mov P_EAX,'SY' << 16
365                 mov P_EBX,'SL' << 16
366                 mov P_ECX,'IN' << 16
367                 mov P_EDX,'UX' << 16
368                 ret
370 comboot_getchar:
371                 cmp byte [APIKeyFlag],00h
372                 jne .queued
373                 call getchar            ; If not queued get input
374                 and al,al               ; Function key?  (CF <- 0)
375                 jnz .done
376                 mov [APIKeyWait],ah     ; High part of key
377                 inc byte [APIKeyFlag]   ; Set flag
378 .done:          mov P_AL,al
379                 ret
380 .queued:        mov al,[APIKeyWait]
381                 dec byte [APIKeyFlag]
382                 jmp .done
385 ; INT 28h - DOS idle
387 %ifdef HAVE_IDLE
388 comboot_int28:
389                 cli
390                 cld
391                 pushad
392                 xor ax,ax
393                 push ds
394                 push es
395                 mov ds,ax
396                 mov es,ax
397                 DO_IDLE
398                 pop es
399                 pop ds
400                 popad
401                 iret
402 %else
403 comboot_int28   equ comboot_iret
404 %endif
407 ; INT 29h - DOS fast write character
409 comboot_int29:
410                 cli
411                 cld
412                 call writechr                   ; Preserves registers!
413                 iret
416 ; INT 22h - SYSLINUX-specific system calls
417 ;           System call number in ax
419 comboot_int22:
420                 cli
421                 push ds
422                 push es
423                 push fs
424                 push gs
425                 pushad
426                 cld
427                 mov bp,cs
428                 mov ds,bp
429                 mov es,bp
430                 mov bp,sp                       ; Set up stack frame
432                 call adjust_screen              ; The COMBOOT program might have changed the screen
434                 cmp ax,int22_count
435                 jb .ok
436                 xor ax,ax                       ; Function 0 -> unimplemented
437 .ok:
438                 xchg ax,bx
439                 add bx,bx                       ; CF <- 0
440                 call [bx+int22_table]
441                 jmp comboot_resume              ; On return
444 ; INT 22h AX=0000h      Unimplemented call
446 comapi_err:
447                 stc
448                 ret
451 ; INT 22h AX=0001h      Get SYSLINUX version
453 comapi_get_version:
454                 ; Number of API functions supported
455                 mov P_AX,int22_count
456                 ; SYSLINUX version
457                 mov P_CX,(VERSION_MAJOR << 8)+VERSION_MINOR
458                 ; SYSLINUX derivative ID byte
459                 mov P_DX,my_id
460                 ; For future use
461                 mov P_BX,cs     ; cs == 0
463                 mov P_ES,ds
464                 ; ES:SI -> version banner
465                 mov P_SI,syslinux_banner
466                 ; ES:DI -> copyright string
467                 mov P_DI,copyright_str
469 comapi_nop:
470                 clc
471                 ret
474 ; INT 22h AX=0002h      Write string
476 ; Write null-terminated string in ES:BX
478 comapi_writestr:
479                 mov ds,P_ES
480                 mov si,P_BX
481                 call writestr
482                 clc
483                 ret
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.
491 comapi_run:
492                 mov ds,P_ES
493                 mov si,P_BX
494                 mov di,command_line
495                 call strcpy
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>.
505 comapi_run_default:
506                 push auto_boot
507                 jmp comboot_exit
510 ; INT 22h AX=0005h      Force text mode
512 ; Puts the video in standard text mode
514 comapi_textmode:
515                 call vgaclearmode
516                 clc
517                 ret
520 ; INT 22h AX=0006h      Open file
522 comapi_open:
523                 push ds
524                 mov ds,P_ES
525                 mov si,P_SI
526                 mov di,InitRD
527                 call mangle_name
528                 pop ds
529                 call searchdir
530                 jz comapi_err
531                 mov P_EAX,eax
532                 mov P_CX,SECTOR_SIZE
533                 mov P_SI,si
534                 clc
535                 ret
538 ; INT 22h AX=0007h      Read file
540 comapi_read:
541                 mov es,P_ES
542                 mov bx,P_BX
543                 mov si,P_SI
544                 mov cx,P_CX
545                 call getfssec
546                 jnc .noteof
547                 xor si,si               ; SI <- 0 on EOF, CF <- 0
548 .noteof:        mov P_SI,si
549                 mov P_ECX,ecx
550                 ret
553 ; INT 22h AX=0008h      Close file
555 comapi_close:
556                 mov si,P_SI
557                 call close_file
558                 clc
559                 ret
562 ; INT 22h AX=0009h      Call PXE stack
564 %if IS_PXELINUX
565 comapi_pxecall:
566                 mov bx,P_BX
567                 mov es,P_ES
568                 mov di,P_DI
569                 call pxenv
570                 mov ax,[PXEStatus]
571                 mov P_AX,ax
572                 ret
573 %else
574 comapi_pxecall  equ comapi_err                  ; Not available
575 %endif
578 ; INT 22h AX=000Ah      Get Derivative-Specific Info
580 comapi_derinfo:
581                 mov P_AL,my_id
582 %if IS_PXELINUX
583                 mov ax,[APIVer]
584                 mov P_DX,ax
585                 mov ax,[StrucPtr]
586                 mov P_BX,ax
587                 mov ax,[StrucPtr+2]
588                 mov P_ES,ax
589                 mov ax,[InitStack]
590                 mov P_SI,ax
591                 mov ax,[InitStack+2]
592                 mov P_FS,ax
593 %else
594                 ; Physical medium...
596                 mov P_CL,SECTOR_SHIFT
597                 mov al,[DriveNumber]
598                 mov P_DL,al
599                 mov P_FS,cs
600                 mov P_SI,OrigESDI
601 %if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
602                 mov P_ES,cs
603                 mov P_BX,PartInfo
604 %elif IS_ISOLINUX
605                 mov P_ES,cs
606                 mov P_BX,spec_packet
607                 mov ax,[BIOSType]
608                 sub ax,bios_cdrom
609                 shr ax,2
610                 mov P_CH,al             ; Mode (el torito/cbios/ebios)
611 %endif
612 %endif
613                 clc
614                 ret
617 ; INT 22h AX=000Bh      Get Serial Console Configuration
619 comapi_serialcfg:
620                 mov ax,[SerialPort]
621                 mov P_DX,ax
622                 mov ax,[BaudDivisor]
623                 mov P_CX,ax
624                 mov ax,[FlowControl]
625                 or al,ah
626                 mov ah,[FlowIgnore]
627                 shr ah,4
628                 test byte [DisplayCon],01h
629                 jnz .normalconsole
630                 or ah,80h
631 .normalconsole:
632                 mov P_BX,ax
633                 clc
634                 ret
637 ; INT 22h AX=000Ch      Perform final cleanup
639 comapi_cleanup:
640 %if IS_PXELINUX
641                 ; Unload PXE if requested
642                 test dl,3
643                 setnz [KeepPXE]
644                 sub bp,sp               ; unload_pxe may move the stack around
645                 call unload_pxe
646                 add bp,sp               ; restore frame pointer...
647 %elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
648                 ; Restore original FDC table
649                 mov eax,[OrigFDCTabPtr]
650                 mov [fdctab],eax
651 %endif
652                 ; Reset the floppy disk subsystem
653                 xor ax,ax
654                 xor dx,dx
655                 int 13h
656                 clc
657                 ret
660 ; INT 22h AX=000Dh      Clean up then replace bootstrap
662 comapi_chainboot:
663                 call comapi_cleanup
664                 mov eax,P_EDI
665                 mov [trackbuf+4],eax            ; Copy from
666                 mov eax,P_ECX
667                 mov [trackbuf+8],eax            ; Total bytes
668                 mov eax,7C00h
669                 mov [trackbuf],eax              ; Copy to
670                 mov [EntryPoint],eax            ; CS:IP entry point
671                 mov esi,P_ESI
672                 mov edx,P_EBX
673                 mov bx,P_DS
674                 jmp replace_bootstrap_one
678 ; INT 22h AX=000Eh      Get configuration file name
680 comapi_configfile:
681                 mov P_ES,cs
682                 mov P_BX,ConfigName
683                 clc
684                 ret
687 ; INT 22h AX=000Fh      Get IPAPPEND strings
689 %if IS_PXELINUX
690 comapi_ipappend:
691                 mov P_ES,cs
692                 mov P_CX,numIPAppends
693                 mov P_BX,IPAppends
694                 clc
695                 ret
697                 section .data
698                 alignb 2, db 0
699 IPAppends       dw IPOption
700                 dw BOOTIFStr
701 numIPAppends    equ ($-IPAppends)/2
703 %else
704 comapi_ipappend equ comapi_err
705 %endif
707                 section .text
710 ; INT 22h AX=0010h      Resolve hostname
712 %if IS_PXELINUX
713 comapi_dnsresolv:
714                 mov ds,P_ES
715                 mov si,P_BX
716                 call dns_resolv
717                 mov P_EAX,eax
718                 clc
719                 ret
720 %else
721 comapi_dnsresolv equ comapi_err
722 %endif
724                 section .text
727 ; INT 22h AX=0011h      Maximum number of shuffle descriptors
729 comapi_maxshuffle:
730                 mov P_CX,trackbufsize/12
731                 ret
734 ; INT 22h AX=0012h      Cleanup, shuffle and boot
736 comapi_shuffle:
737                 cmp P_CX,(2*trackbufsize)/12
738                 ja .error
740                 call comapi_cleanup
742                 mov cx, P_CX
743                 push cx                         ; On stack: descriptor count
745                 lea cx,[ecx+ecx*2]              ; CX *= 3
747                 mov fs,P_ES
748                 mov si,P_DI
749                 mov di,trackbuf
750                 push di                         ; On stack: descriptor list address
751                 fs rep movsd                    ; Copy the list
753                 mov eax,P_EBP
754                 mov [EntryPoint],eax            ; CS:IP entry point
755                 mov esi,P_ESI
756                 mov edx,P_EBX
757                 mov bx,P_DS
758                 jmp replace_bootstrap
759 .error:
760                 stc
761                 ret
764 ; INT 22h AX=0013h      Idle call
767 ; *** FIX THIS ***
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? ***
772 %ifdef HAVE_IDLE
773 comapi_idle:
774                 DO_IDLE
775                 clc
776                 ret
778 %else
779 comapi_idle     equ comapi_err
780 %endif
783 ; INT 22h AX=0014h      Local boot
785 %if HAS_LOCALBOOT
786 comapi_localboot:
787                 mov ax,P_DX
788                 jmp local_boot
789 %else
790 comapi_localboot equ comapi_err
791 %endif ; HAS_LOCALBOOT
794 ; INT 22h AX=0015h      Feature flags
796 comapi_features:
797                 mov P_ES,cs
798                 mov P_BX,feature_flags
799                 mov P_CX,feature_flags_len
800                 clc
801                 ret
804 ; INT 22h AX=0016h      Run kernel image
806 comapi_runkernel:
807                 mov al,P_DL
808                 cmp al,VK_TYPES-1
809                 ja .error
810                 mov [KernelType],al
811                 push ds
812                 mov ds,P_DS
813                 mov si,P_SI
814                 mov di,KernelName
815                 call mangle_name
816                 pop ds
817                 call searchdir
818                 jz comapi_err
820                 ; The kernel image was found, so we can load it...
821                 mov [Kernel_SI],si
822                 mov [Kernel_EAX],eax
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
827                 push ds
828                 push es
829                 mov ax,xfer_buf_seg
830                 mov ds,P_ES
831                 mov si,P_BX
832                 mov es,ax
833                 xor di,di
834                 call strcpy
835                 pop es
836                 pop ds
838 %if IS_PXELINUX
839                 mov al,P_CL
840                 mov [IPAppend],al
841 %endif
843                 call comboot_exit
845 .finish:
846                 ; Copy the command line into its proper place
847                 push ds
848                 push es
849                 mov ax,xfer_buf_seg
850                 mov dx,real_mode_seg
851                 mov ds,ax
852                 mov es,dx
853                 xor si,si
854                 mov di,cmd_line_here
855                 call strcpy
856                 mov byte [es:di-1],' '          ; Simulate APPEND
857                 pop es
858                 pop ds
859                 mov [CmdLinePtr],di
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
868 comapi_usingvga:
869                 mov ax,P_BX
870                 cmp ax,0Fh              ; Unknown flags = failure
871                 ja .error
872                 mov [UsingVGA],al
873                 mov cx,P_CX
874                 mov dx,P_DX
875                 mov [GXPixCols],cx
876                 mov [GXPixRows],dx
877                 test al,08h
878                 jnz .notext
879                 call adjust_screen
880 .notext:
881                 clc
882                 ret
883 .error:
884                 stc
885                 ret
888 ; INT 22h AX=0018h  Query custom font
890 comapi_userfont:
891                 mov al,[UserFont]
892                 and al,al
893                 jz .done
894                 mov al,[VGAFontSize]
895                 mov P_ES,ds
896                 mov P_BX,vgafontbuf
898 .done:          ; CF=0 here
899                 mov P_AL,al
900                 ret
903 ; INT 22h AX=0019h  Read disk
905 %if IS_SYSLINUX || IS_MDSLINUX || IS_ISOLINUX || IS_EXTLINUX
906 comapi_readdisk:
907                 mov esi,P_ESI           ; Enforce ESI == EDI == 0, these
908                 or esi,P_EDI            ; are reserved for future expansion
909                 jnz .err
910                 mov eax,P_EDX
911                 mov es,P_ES
912                 mov bx,P_BX
913                 mov bp,P_CX             ; WE CANNOT use P_* after touching bp!
914                 call getlinsec
915                 clc
916                 ret
917 .err:
918                 stc
919                 ret
920 %else
921 comapi_readdisk equ comapi_err
922 %endif
925 ; INT 22h AX=001Ah      Cleanup, shuffle and boot to flat protected mode
927 comapi_shufflepm:
928                 cmp P_CX,(2*trackbufsize)/12
929                 ja .error
931                 call comapi_cleanup
933                 mov cx, P_CX
934                 push cx                         ; On stack: descriptor count
936                 lea cx,[ecx+ecx*2]              ; CX *= 3
938                 mov fs,P_ES
939                 mov si,P_DI
940                 mov di,trackbuf
941                 push di                         ; On stack: descriptor list address
942                 fs rep movsd                    ; Copy the list
944                 mov fs,P_DS
945                 mov si,P_SI
946                 mov edi,TrampolineBuf
947                 mov al,0B8h                     ; MOV EAX opcode
948                 mov cl,9
949 .maketramp:
950                 stosb                           ; MOV opcode
951                 inc ax                          ; Next register opcode
952                 fs movsd                        ; immediate value
953                 loop .maketramp
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
960 .error:
961                 stc
962                 ret
965 ; INT 22h AX=001Bh      Cleanup, shuffle and boot with register setting
967 comapi_shufflerm:
968                 cmp P_CX,(2*trackbufsize)/12
969                 ja .error
971                 call comapi_cleanup
973                 mov cx, P_CX
974                 push cx                         ; On stack: descriptor count
976                 lea cx,[ecx+ecx*2]              ; CX *= 3
978                 mov fs,P_ES
979                 mov si,P_DI
980                 mov di,trackbuf
981                 push di                         ; On stack: descriptor list address
982                 fs rep movsd                    ; Copy the list
984                 mov fs,P_DS
985                 mov si,P_SI
986                 mov di,TrampolineBuf
988                 ; Generate segment-loading instructions
989                 mov bx,0C08Eh                   ; MOV ES,AX
990                 mov cl,6                        ; 6 segment registers (incl CS)
991 .segtramp:
992                 mov al,0B8h
993                 stosb                           ; MOV AX,imm16 opcode
994                 fs movsw                        ; imm16
995                 mov ax,bx
996                 add bh,8
997                 stosw                           ; MOV xS,AX
998                 loop .segtramp
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
1005                 mov cl,8                        ; 8 GPRs
1006 .gprtramp:
1007                 stosw                           ; MOV ExX,imm32 opcode
1008                 fs movsd                        ; imm32
1009                 inc ah
1010                 loop .gprtramp
1012                 mov al,0EAh                     ; JMP FAR imm16:imm16 opcode
1013                 stosb
1014                 fs movsd                        ; CS:IP
1016                 mov dword [EntryPoint],TrampolineBuf
1017                 jmp replace_bootstrap
1018 .error:
1019                 stc
1020                 ret
1023 ; INT 22h AX=001Ch      Get pointer to auxillary data vector
1025 comapi_getadv:
1026                 mov P_ES,ds
1027                 mov P_BX,adv0.data
1028                 mov P_CX,ADV_LEN
1029                 ret
1032 ; INT 22h AX=001Dh      Write auxillary data vector
1034 comapi_writeadv equ adv_write
1037 ; INT 22h AX=001Eh      Keyboard remapping table
1038 comapi_kbdtable:
1039                 cmp P_DX,0
1040                 jne .err
1041                 mov P_AX,1                      ; Version
1042                 mov P_CX,256                    ; Length
1043                 mov P_ES,cs
1044                 mov P_BX,KbdMap
1045                 ret
1046 .err:
1047                 stc
1048                 ret
1051 ; INT 22h AX=001Fh      Get current working directory
1053 comapi_getcwd:
1054                 mov P_ES,cs
1055                 mov P_BX,CurrentDirName
1056                 clc
1057                 ret
1060 ; INT 22h AX=0020h      Open directory
1062 %if IS_SYSLINUX
1063 comapi_opendir:
1064                 push ds
1065                 mov ds,P_ES
1066                 mov si,P_SI
1067                 mov di,InitRD
1068                 call mangle_name
1069                 pop ds
1070                 call searchdir
1071                 jnz comapi_err  ; Didn't find a directory
1072                 cmp eax,0
1073                 jz comapi_err   ; Found nothing
1074                         ;ZF is unset
1075                 call alloc_fill_dir
1076                 mov P_EAX,eax
1077                 mov P_CX,SECTOR_SIZE
1078                 mov P_SI,si
1079                 clc
1080                 ret
1081 %else
1082 comapi_opendir  equ comapi_err
1083 %endif
1086 ; INT 22h AX=0021h      Read directory
1088 %if IS_SYSLINUX
1089 comapi_readdir:
1090                 mov es,P_ES
1091                 mov di,P_DI
1092                 mov si,P_SI
1093                 call readdir
1094                 mov P_EAX,eax
1095                 mov P_DL,dl
1096                 mov P_EBX,ebx
1097                 mov P_SI,si
1098                 ret
1099 %else
1100 comapi_readdir  equ comapi_err
1101 %endif
1104 ; INT 22h AX=0022h      Close directory
1106 %if IS_SYSLINUX
1107 comapi_closedir:
1108                 mov si,P_SI
1109                 call close_dir
1110                 clc
1111                 ret
1112 %else
1113 comapi_closedir equ comapi_err
1114 %endif
1116                 section .data
1118 %macro          int21 2
1119                 db %1
1120                 dw %2
1121 %endmacro
1123 int21_table:
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
1136                 align 2, db 0
1137 int22_table:
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
1175 APIKeyWait      db 0
1176 APIKeyFlag      db 0
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
1186 feature_flags:
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
1193                 section .bss1
1194                 alignb 4
1195 DOSErrTramp     resd    33              ; Error trampolines
1196 ConfigName      resb    FILENAME_MAX
1197 CurrentDirName  resb    FILENAME_MAX