Preserve ES:DI instead of probing for $PnP
[profile/ivi/syslinux.git] / comboot.inc
1 ;; -----------------------------------------------------------------------
2 ;;
3 ;;   Copyright 1994-2007 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.
10 ;;
11 ;; -----------------------------------------------------------------------
12
13 ;;
14 ;; comboot.inc
15 ;;
16 ;; Common code for running a COMBOOT image
17 ;;
18
19                 section .text
20
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_DS            word [bp+38]
29 %define         P_ES            word [bp+36]
30 %define         P_FS            word [bp+34]
31 %define         P_GS            word [bp+32]
32 %define         P_EAX           dword [bp+28]
33 %define         P_AX            word [bp+28]
34 %define         P_HAX           word [bp+30]
35 %define         P_AL            byte [bp+28]
36 %define         P_AH            byte [bp+29]
37 %define         P_ECX           dword [bp+24]
38 %define         P_CX            word [bp+24]
39 %define         P_HCX           word [bp+26]
40 %define         P_CL            byte [bp+24]
41 %define         P_CH            byte [bp+25]
42 %define         P_EDX           dword [bp+20]
43 %define         P_DX            word [bp+20]
44 %define         P_HDX           word [bp+22]
45 %define         P_DL            byte [bp+20]
46 %define         P_DH            byte [bp+21]
47 %define         P_EBX           dword [bp+16]
48 %define         P_BX            word [bp+16]
49 %define         P_HBX           word [bp+18]
50 %define         P_BL            byte [bp+16]
51 %define         P_BH            byte [bp+17]
52 %define         P_EBP           dword [bp+8]
53 %define         P_BP            word [bp+8]
54 %define         P_HBP           word [bp+10]
55 %define         P_ESI           dword [bp+4]
56 %define         P_SI            word [bp+4]
57 %define         P_HSI           word [bp+6]
58 %define         P_EDI           dword [bp]
59 %define         P_DI            word [bp]
60 %define         P_HDI           word [bp+2]
61
62 ; Looks like a COMBOOT image but too large
63 comboot_too_large:
64                 mov si,err_comlarge
65                 call cwritestr
66                 jmp enter_command
67
68 ;
69 ; Load a COMBOOT image.  A COMBOOT image is basically a DOS .COM file,
70 ; except that it may, of course, not contain any DOS system calls.  We
71 ; do, however, allow the execution of INT 20h to return to SYSLINUX.
72 ;
73 is_comboot_image:
74                 and dx,dx
75                 jnz comboot_too_large
76                 cmp ax,0ff00h           ; Max size in bytes
77                 jae comboot_too_large
78
79                 push si                 ; Save file handle
80
81                 call make_plain_cmdline
82
83                 call comboot_setup_api
84
85                 mov cx,comboot_seg
86                 mov es,cx
87
88                 xor di,di
89                 mov cx,64               ; 256 bytes (size of PSP)
90                 xor eax,eax             ; Clear PSP
91                 rep stosd
92
93                 mov word [es:0], 020CDh ; INT 20h instruction
94                 ; First non-free paragraph
95                 ; This is valid because comboot_seg == real_mode_seg
96                 ; == the highest segment used by all derivatives
97                 int 12h                 ; Get DOS memory size
98                 shl ax,6                ; Kilobytes -> paragraphs
99                 mov word [es:02h],ax
100
101 %ifndef DEPEND
102 %if real_mode_seg != comboot_seg
103 %error "This code assumes real_mode_seg == comboot_seg"
104 %endif
105 %endif
106                 ; Copy the command line from high memory
107                 mov si,cmd_line_here
108                 mov cx,125              ; Max cmdline len (minus space and CR)
109                 mov di,081h             ; Offset in PSP for command line
110                 mov al,' '              ; DOS command lines begin with a space
111                 stosb
112
113 .loop:          es lodsb
114                 and al,al
115                 jz .done
116                 stosb
117                 loop .loop
118 .done:
119
120                 mov al,0Dh              ; CR after last character
121                 stosb
122                 mov ax,di
123                 sub al,82h              ; Include space but not CR
124                 mov [es:80h],al         ; Store command line length
125
126                 ; Now actually load the file...
127                 pop si                  ; File handle
128                 mov bx,100h             ; Load at <seg>:0100h
129                 mov cx,0FF00h >> SECTOR_SHIFT
130                                         ; Absolute maximum # of sectors
131                 call getfssec
132
133                 ; And invoke the program...
134                 mov ax,es
135                 mov ds,ax
136                 mov ss,ax
137                 xor sp,sp
138                 push word 0             ; Return to address 0 -> exit
139
140                 jmp comboot_seg:100h    ; Run it
141
142 ; Proper return vector
143 comboot_return: cli                     ; Don't trust anyone
144                 push enter_command      ; Normal return to command prompt
145                 jmp comboot_exit
146
147 ;
148 ; Set up the COMBOOT API interrupt vectors.  This is also used
149 ; by the COM32 code.
150 ;
151 comboot_setup_api:
152                 mov di,4*0x20           ; DOS interrupt vectors
153                 mov eax,comboot_return  ; INT 20h = exit
154                 stosd
155                 mov ax,comboot_int21    ; INT 21h = DOS-compatible syscalls
156                 stosd
157                 mov ax,comboot_int22    ; INT 22h = proprietary syscalls
158                 stosd
159                 mov ax,comboot_bogus
160                 mov cx,29               ; All remaining DOS vectors
161                 rep stosd
162                 ret
163
164 ; INT 21h: generic DOS system call
165 comboot_int21:  cli
166                 push ds
167                 push es
168                 push fs
169                 push gs
170                 pushad
171                 cld
172                 mov bp,cs
173                 mov ds,bp
174                 mov es,bp
175                 mov bp,sp                       ; Set up stack frame
176
177                 call adjust_screen              ; The COMBOOT program might have changed the screen
178
179                 mov cx,int21_count
180                 mov si,int21_table
181 .again:         lodsb
182                 cmp al,P_AH
183                 lodsw
184                 loopne .again
185                 ; The last function in the list is the
186                 ; "no such function" function
187                 clc
188                 call ax                 ; Call the invoked function
189 comboot_resume:
190                 mov bp,sp               ; In case the function clobbers BP
191                 setc P_FLAGSL           ; Propagate CF->error
192                 popad
193                 pop gs
194                 pop fs
195                 pop es
196                 pop ds
197                 iret
198
199 ; Attempted to execute non-21h DOS system call
200 comboot_bogus:  cli                     ; Don't trust anyone
201                 mov cx,err_notdos
202                 push enter_command
203                 jmp comboot_exit_msg
204
205 ;
206 ; Generic COMBOOT return to command line code
207 ;  stack -> where to go next
208 ;     CX -> message (for _msg version)
209 ;
210 comboot_exit:
211                 xor cx,cx
212 comboot_exit_msg:
213                 pop bx                  ; Return address
214                 RESET_STACK_AND_SEGS AX
215                 call adjust_screen      ; The COMBOOT program might have changed the screen
216                 jcxz .nomsg
217                 mov si,KernelCName
218                 call cwritestr
219                 mov si,cx
220                 call cwritestr
221 .nomsg:
222                 jmp bx
223
224 ;
225 ; INT 21h system calls
226 ;
227 comboot_getkey:                         ; 01 = get key with echo
228                 call vgashowcursor
229                 call comboot_getchar
230                 call vgahidecursor
231                 call writechr
232                 clc
233                 ret
234
235 comboot_writechr:                       ; 02 = writechr
236                 mov al,P_DL
237                 call writechr
238                 clc
239                 ret
240
241 comboot_writeserial:                    ; 04 = write serial port
242                 mov al,P_DL
243                 call write_serial
244                 clc
245                 ret
246
247 comboot_getkeynoecho:                   ; 08 = get key w/o echo
248                 call comboot_getchar
249                 clc
250                 ret
251
252 comboot_writestr:                       ; 09 = write DOS string
253                 mov es,P_DS
254                 mov si,P_DX
255 .loop:          es lodsb
256                 cmp al,'$'              ; End string with $ - bizarre
257                 je .done
258                 call writechr
259                 jmp short .loop
260 .done:          clc
261                 ret
262
263 comboot_checkkey:                       ; 0B = check keyboard status
264                 cmp byte [APIKeyFlag],00h
265                 jnz .waiting
266                 call pollchar
267 .waiting:       setz al
268                 dec al                  ; AL = 0FFh if present, 0 if not
269                 mov P_AL,al
270                 clc
271                 ret
272
273 comboot_checkver:                       ; 30 = check DOS version
274                 ; We return 0 in all DOS-compatible version registers,
275                 ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
276                 mov P_EAX,'SY' << 16
277                 mov P_EBX,'SL' << 16
278                 mov P_ECX,'IN' << 16
279                 mov P_EDX,'UX' << 16
280                 ret
281
282 comboot_getchar:
283                 cmp byte [APIKeyFlag],00h
284                 jne .queued
285                 call getchar            ; If not queued get input
286                 and al,al               ; Function key?  (CF <- 0)
287                 jnz .done
288                 mov [APIKeyWait],ah     ; High part of key
289                 inc byte [APIKeyFlag]   ; Set flag
290 .done:          mov P_AL,al
291                 ret
292 .queued:        mov al,[APIKeyWait]
293                 dec byte [APIKeyFlag]
294                 jmp .done
295
296 ;
297 ; INT 22h - SYSLINUX-specific system calls
298 ;           System call number in ax
299 ;
300 comboot_int22:
301                 cli
302                 push ds
303                 push es
304                 push fs
305                 push gs
306                 pushad
307                 cld
308                 mov bp,cs
309                 mov ds,bp
310                 mov es,bp
311                 mov bp,sp                       ; Set up stack frame
312
313                 call adjust_screen              ; The COMBOOT program might have changed the screen
314
315                 cmp ax,int22_count
316                 jb .ok
317                 xor ax,ax                       ; Function 0 -> unimplemented
318 .ok:
319                 xchg ax,bx
320                 add bx,bx                       ; CF <- 0
321                 call [bx+int22_table]
322                 jmp comboot_resume              ; On return
323
324 ;
325 ; INT 22h AX=0000h      Unimplemented call
326 ;
327 comapi_err:
328                 stc
329                 ret
330
331 ;
332 ; INT 22h AX=0001h      Get SYSLINUX version
333 ;
334 comapi_get_version:
335                 ; Number of API functions supported
336                 mov P_AX,int22_count
337                 ; SYSLINUX version
338                 mov P_CX,(VER_MAJOR << 8)+VER_MINOR
339                 ; SYSLINUX derivative ID byte
340                 mov P_DX,my_id
341                 ; For future use
342                 mov P_BX,cs     ; cs == 0
343
344                 mov P_ES,ds
345                 ; ES:SI -> version banner
346                 mov P_SI,syslinux_banner
347                 ; ES:DI -> copyright string
348                 mov P_DI,copyright_str
349
350 comapi_nop:
351                 clc
352                 ret
353
354 ;
355 ; INT 22h AX=0002h      Write string
356 ;
357 ; Write null-terminated string in ES:BX
358 ;
359 comapi_writestr:
360                 mov ds,P_ES
361                 mov si,P_BX
362                 call writestr
363                 clc
364                 ret
365
366 ;
367 ; INT 22h AX=0003h      Run command
368 ;
369 ; Terminates the COMBOOT program and executes the command line in
370 ; ES:BX as if it had been entered by the user.
371 ;
372 comapi_run:
373                 mov ds,P_ES
374                 mov si,P_BX
375                 mov di,command_line
376                 call strcpy
377                 push load_kernel                ; Run a new kernel
378                 jmp comboot_exit                ; Terminate task, clean up
379
380 ;
381 ; INT 22h AX=0004h      Run default command
382 ;
383 ; Terminates the COMBOOT program and executes the default command line
384 ; as if a timeout had happened or the user pressed <Enter>.
385 ;
386 comapi_run_default:
387                 push auto_boot
388                 jmp comboot_exit
389
390 ;
391 ; INT 22h AX=0005h      Force text mode
392 ;
393 ; Puts the video in standard text mode
394 ;
395 comapi_textmode:
396                 call vgaclearmode
397                 clc
398                 ret
399
400 ;
401 ; INT 22h AX=0006h      Open file
402 ;
403 comapi_open:
404                 push ds
405                 mov ds,P_ES
406                 mov si,P_SI
407                 mov di,InitRD
408                 call mangle_name
409                 pop ds
410                 call searchdir
411                 jz comapi_err
412                 mov P_AX,ax
413                 mov P_HAX,dx
414                 mov P_CX,SECTOR_SIZE
415                 mov P_SI,si
416                 clc
417                 ret
418
419 ;
420 ; INT 22h AX=0007h      Read file
421 ;
422 comapi_read:
423                 mov es,P_ES
424                 mov bx,P_BX
425                 mov si,P_SI
426                 mov cx,P_CX
427                 call getfssec
428                 jnc .noteof
429                 xor si,si               ; SI <- 0 on EOF, CF <- 0
430 .noteof:        mov P_SI,si
431                 ret
432
433 ;
434 ; INT 22h AX=0008h      Close file
435 ;
436 comapi_close:
437                 mov si,P_SI
438                 call close_file
439                 clc
440                 ret
441
442 ;
443 ; INT 22h AX=0009h      Call PXE stack
444 ;
445 %if IS_PXELINUX
446 comapi_pxecall:
447                 mov bx,P_BX
448                 mov es,P_ES
449                 mov di,P_DI
450                 call pxenv
451                 mov P_AX,ax
452                 clc
453                 ret
454 %else
455 comapi_pxecall  equ comapi_err                  ; Not available
456 %endif
457
458 ;
459 ; INT 22h AX=000Ah      Get Derivative-Specific Info
460 ;
461 comapi_derinfo:
462                 mov P_AL,my_id
463 %if IS_PXELINUX
464                 mov ax,[APIVer]
465                 mov P_DX,ax
466                 mov ax,[StrucPtr]
467                 mov P_BX,ax
468                 mov ax,[StrucPtr+2]
469                 mov P_ES,ax
470                 mov ax,[InitStack]
471                 mov P_SI,ax
472                 mov ax,[InitStack+2]
473                 mov P_FS,ax
474 %else
475                 ; Physical medium...
476
477                 mov P_CL,SECTOR_SHIFT
478                 mov al,[DriveNumber]
479                 mov P_DL,al
480                 mov P_FS,cs
481                 mov P_SI,OrigESDI
482 %if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
483                 mov P_ES,cs
484                 mov P_BX,PartInfo
485 %elif IS_ISOLINUX
486                 mov P_ES,cs
487                 mov P_BX,spec_packet
488 %endif
489 %endif
490                 clc
491                 ret
492
493 ;
494 ; INT 22h AX=000Bh      Get Serial Console Configuration
495 ;
496 comapi_serialcfg:
497                 mov ax,[SerialPort]
498                 mov P_DX,ax
499                 mov ax,[BaudDivisor]
500                 mov P_CX,ax
501                 mov ax,[FlowControl]
502                 or al,ah
503                 mov ah,[FlowIgnore]
504                 shr ah,4
505                 test byte [DisplayCon],01h
506                 jnz .normalconsole
507                 or ah,80h
508 .normalconsole:
509                 mov P_BX,ax
510                 clc
511                 ret
512
513 ;
514 ; INT 22h AX=000Ch      Perform final cleanup
515 ;
516 comapi_cleanup:
517 %if IS_PXELINUX
518                 ; Unload PXE if requested
519                 test dl,3
520                 setnz [KeepPXE]
521                 sub bp,sp               ; unload_pxe may move the stack around
522                 call unload_pxe
523                 add bp,sp               ; restore frame pointer...
524 %elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
525                 ; Restore original FDC table
526                 mov eax,[OrigFDCTabPtr]
527                 mov [fdctab],eax
528 %endif
529                 ; Reset the floppy disk subsystem
530                 xor ax,ax
531                 xor dx,dx
532                 int 13h
533                 clc
534                 ret
535
536 ;
537 ; INT 22h AX=000Dh      Clean up then replace bootstrap
538 ;
539 comapi_chainboot:
540                 call comapi_cleanup
541                 mov eax,P_EDI
542                 mov [trackbuf+4],eax            ; Copy from
543                 mov eax,P_ECX
544                 mov [trackbuf+8],eax            ; Total bytes
545                 mov eax,7C00h
546                 mov [trackbuf],eax              ; Copy to
547                 mov [EntryPoint],eax            ; CS:IP entry point
548                 mov esi,P_ESI
549                 mov edx,P_EBX
550                 mov bx,P_DS
551                 jmp replace_bootstrap_one
552
553
554 ;
555 ; INT 22h AX=000Eh      Get configuration file name
556 ;
557 comapi_configfile:
558                 mov P_ES,cs
559                 mov P_BX,ConfigName
560                 clc
561                 ret
562
563 ;
564 ; INT 22h AX=000Fh      Get IPAPPEND strings
565 ;
566 %if IS_PXELINUX
567 comapi_ipappend:
568                 mov P_ES,cs
569                 mov P_CX,numIPAppends
570                 mov P_BX,IPAppends
571                 clc
572                 ret
573
574                 section .data
575                 alignb 2, db 0
576 IPAppends       dw IPOption
577                 dw BOOTIFStr
578 numIPAppends    equ ($-IPAppends)/2
579
580 %else
581 comapi_ipappend equ comapi_err
582 %endif
583
584                 section .text
585
586 ;
587 ; INT 22h AX=0010h      Resolve hostname
588 ;
589 %if IS_PXELINUX
590 comapi_dnsresolv:
591                 mov ds,P_ES
592                 mov si,P_BX
593                 call dns_resolv
594                 mov P_EAX,eax
595                 ret
596 %else
597 comapi_dnsresolv equ comapi_err
598 %endif
599
600                 section .text
601
602 ;
603 ; INT 22h AX=0011h      Maximum number of shuffle descriptors
604 ;
605 comapi_maxshuffle:
606                 mov P_CX,(2*trackbufsize)/12
607                 ret
608
609 ;
610 ; INT 22h AX=0012h      Cleanup, shuffle and boot
611 ;
612 comapi_shuffle:
613                 cmp P_CX,(2*trackbufsize)/12
614                 ja .error
615
616                 call comapi_cleanup
617
618                 mov cx, P_CX
619                 push cx                         ; On stack: descriptor count
620
621                 lea cx,[ecx+ecx*2]              ; CX *= 3
622
623                 mov fs,P_ES
624                 mov si,P_DI
625                 mov di,trackbuf
626                 push di                         ; On stack: descriptor list address
627                 fs rep movsd                    ; Copy the list
628
629                 mov eax,P_EBP
630                 mov [EntryPoint],eax            ; CS:IP entry point
631                 mov esi,P_ESI
632                 mov edx,P_EBX
633                 mov bx,P_DS
634                 jmp replace_bootstrap
635 .error:
636                 stc
637                 ret
638
639 ;
640 ; INT 22h AX=0013h      Idle call
641 ;
642 ;
643 ; *** FIX THIS ***
644 ; The idle call seems to have detrimental effects on some machines when
645 ; called from a COM32 context (WHY?) --  disable it for now.
646 ;
647 %if 0 ; def HAVE_IDLE
648
649 comapi_idle:
650                 DO_IDLE
651                 clc
652                 ret
653
654 %else
655
656 comapi_idle     equ comapi_err
657
658 %endif
659
660 ;
661 ; INT 22h AX=0014h      Local boot
662 ;
663 %if IS_PXELINUX || IS_ISOLINUX
664 comapi_localboot:
665                 mov ax,P_DX
666                 jmp local_boot
667 %else
668 comapi_localboot equ comapi_err
669 %endif
670
671 ;
672 ; INT 22h AX=0015h      Feature flags
673 ;
674 comapi_features:
675                 mov P_ES,cs
676                 mov P_BX,feature_flags
677                 mov P_CX,feature_flags_len
678                 clc
679                 ret
680
681 ;
682 ; INT 22h AX=0016h      Run kernel image
683 ;
684 comapi_runkernel:
685                 mov al,P_DL
686                 cmp al,VK_TYPES-1
687                 ja .error
688                 mov [KernelType],al
689                 push ds
690                 mov ds,P_DS
691                 mov si,P_SI
692                 mov di,KernelName
693                 call mangle_name
694                 pop ds
695                 call searchdir
696                 jz comapi_err
697
698                 ; The kernel image was found, so we can load it...
699                 mov [Kernel_SI],si
700                 mov [Kernel_EAX],ax
701                 mov [Kernel_EAX+2],dx
702
703                 ; It's not just possible, but quite likely, that ES:BX
704                 ; points into real_mode_seg, so we need to exercise some
705                 ; special care here... use xfer_buf_seg as an intermediary
706                 push ds
707                 push es
708                 mov ax,xfer_buf_seg
709                 mov ds,P_ES
710                 mov si,P_BX
711                 mov es,ax
712                 xor di,di
713                 call strcpy
714                 pop es
715                 pop ds
716
717 %if IS_PXELINUX
718                 mov al,P_CL
719                 mov [IPAppend],al
720 %endif
721
722                 call comboot_exit
723
724 .finish:
725                 ; Copy the command line into its proper place
726                 push ds
727                 push es
728                 mov ax,xfer_buf_seg
729                 mov dx,real_mode_seg
730                 mov ds,ax
731                 mov es,dx
732                 xor si,si
733                 mov di,cmd_line_here
734                 call strcpy
735                 mov byte [es:di-1],' '          ; Simulate APPEND
736                 pop es
737                 pop ds
738                 mov [CmdLinePtr],di
739                 mov word [CmdOptPtr],zero_string
740                 jmp kernel_good_saved
741
742 .error          equ comapi_shuffle.error
743
744 ;
745 ; INT 22h AX=0017h  Report video mode change
746 ;
747 comapi_usingvga:
748                 mov ax,P_BX
749                 cmp ax,0Fh              ; Unknown flags = failure
750                 ja .error
751                 mov [UsingVGA],al
752                 mov cx,P_CX
753                 mov dx,P_DX
754                 mov [GXPixCols],cx
755                 mov [GXPixRows],dx
756                 test al,08h
757                 jnz .notext
758                 call adjust_screen
759 .notext:
760                 clc
761                 ret
762 .error:
763                 stc
764                 ret
765
766 ;
767 ; INT 22h AX=0018h  Query custom font
768 ;
769 comapi_userfont:
770                 mov al,[UserFont]
771                 and al,al
772                 jz .done
773                 mov al,[VGAFontSize]
774                 mov P_ES,ds
775                 mov P_BX,vgafontbuf
776
777 .done:          ; CF=0 here
778                 mov P_AL,al
779                 ret
780
781 ;
782 ; INT 22h AX=0019h  Read disk
783 ;
784 %if IS_SYSLINUX || IS_MDSLINUX || IS_ISOLINUX || IS_EXTLINUX
785 comapi_readdisk:
786                 mov esi,P_ESI           ; Enforce ESI == EDI == 0, these
787                 or esi,P_EDI            ; are reserved for future expansion
788                 jnz .err
789                 mov eax,P_EDX
790                 mov es,P_ES
791                 mov bx,P_BX
792                 mov bp,P_CX             ; WE CANNOT use P_* after touching bp!
793                 call getlinsec
794                 clc
795                 ret
796 .err:
797                 stc
798                 ret
799 %else
800 comapi_readdisk equ comapi_err
801 %endif
802
803 ;
804 ; INT 22h AX=001Ah      Cleanup, shuffle and boot to flat protected mode
805 ;
806 comapi_shufflepm:
807                 cmp P_CX,(2*trackbufsize)/12
808                 ja .error
809
810                 call comapi_cleanup
811
812                 mov cx, P_CX
813                 push cx                         ; On stack: descriptor count
814
815                 lea cx,[ecx+ecx*2]              ; CX *= 3
816
817                 mov fs,P_ES
818                 mov si,P_DI
819                 mov di,trackbuf
820                 push di                         ; On stack: descriptor list address
821                 fs rep movsd                    ; Copy the list
822
823                 mov fs,P_DS
824                 mov si,P_SI
825                 mov edi,TrampolineBuf
826                 mov al,0B8h                     ; MOV EAX opcode
827                 mov cl,9
828 .maketramp:
829                 stosb                           ; MOV opcode
830                 inc ax                          ; Next register opcode
831                 fs movsd                        ; immediate value
832                 loop .maketramp
833                 mov byte [di-5],0E9h            ; Last opcode is JMP
834                 sub [di-4],edi                  ; Make JMP target relative
835
836                 mov dword [EntryPoint],trampoline_to_pm
837                 xor bx,bx                       ; DS on entry
838                 jmp replace_bootstrap
839 .error:
840                 stc
841                 ret
842
843 ;
844 ; INT 22h AX=001Bh      Cleanup, shuffle and boot with register setting
845 ;
846 comapi_shufflerm:
847                 cmp P_CX,(2*trackbufsize)/12
848                 ja .error
849
850                 call comapi_cleanup
851
852                 mov cx, P_CX
853                 push cx                         ; On stack: descriptor count
854
855                 lea cx,[ecx+ecx*2]              ; CX *= 3
856
857                 mov fs,P_ES
858                 mov si,P_DI
859                 mov di,trackbuf
860                 push di                         ; On stack: descriptor list address
861                 fs rep movsd                    ; Copy the list
862
863                 mov fs,P_DS
864                 mov si,P_SI
865                 mov di,TrampolineBuf
866
867                 ; Generate segment-loading instructions
868                 mov bx,0C08Eh                   ; MOV ES,AX
869                 mov cl,6                        ; 6 segment registers (incl CS)
870 .segtramp:
871                 mov al,0B8h
872                 stosb                           ; MOV AX,imm16 opcode
873                 fs movsw                        ; imm16
874                 mov ax,bx
875                 add bh,8
876                 stosw                           ; MOV xS,AX
877                 loop .segtramp
878
879                 ; Clobber the MOV CS,AX instruction.
880                 mov word [di-22], 9090h         ; NOP NOP
881
882                 ; Generate GPR-loading instructions
883                 mov ax,0B866h                   ; MOV EAX,imm32
884                 mov cl,8                        ; 8 GPRs
885 .gprtramp:
886                 stosw                           ; MOV ExX,imm32 opcode
887                 fs movsd                        ; imm32
888                 inc ah
889                 loop .gprtramp
890
891                 mov al,0EAh                     ; JMP FAR imm16:imm16 opcode
892                 stosb
893                 fs movsd                        ; CS:IP
894
895                 mov dword [EntryPoint],TrampolineBuf
896                 jmp replace_bootstrap
897 .error:
898                 stc
899                 ret
900
901                 section .data
902
903 %macro          int21 2
904                 db %1
905                 dw %2
906 %endmacro
907
908 int21_table:
909                 int21   00h, comboot_return
910                 int21   01h, comboot_getkey
911                 int21   02h, comboot_writechr
912                 int21   04h, comboot_writeserial
913                 int21   08h, comboot_getkeynoecho
914                 int21   09h, comboot_writestr
915                 int21   0Bh, comboot_checkkey
916                 int21   30h, comboot_checkver
917                 int21   4Ch, comboot_return
918                 int21    -1, comboot_bogus
919 int21_count     equ ($-int21_table)/3
920
921                 align 2, db 0
922 int22_table:
923                 dw comapi_err           ; 0000 unimplemented syscall
924                 dw comapi_get_version   ; 0001 get SYSLINUX version
925                 dw comapi_writestr      ; 0002 write string
926                 dw comapi_run           ; 0003 run specified command
927                 dw comapi_run_default   ; 0004 run default command
928                 dw comapi_textmode      ; 0005 force text mode
929                 dw comapi_open          ; 0006 open file
930                 dw comapi_read          ; 0007 read file
931                 dw comapi_close         ; 0008 close file
932                 dw comapi_pxecall       ; 0009 call PXE stack
933                 dw comapi_derinfo       ; 000A derivative-specific info
934                 dw comapi_serialcfg     ; 000B get serial port config
935                 dw comapi_cleanup       ; 000C perform final cleanup
936                 dw comapi_chainboot     ; 000D clean up then bootstrap
937                 dw comapi_configfile    ; 000E get name of config file
938                 dw comapi_ipappend      ; 000F get ipappend strings
939                 dw comapi_dnsresolv     ; 0010 resolve hostname
940                 dw comapi_maxshuffle    ; 0011 maximum shuffle descriptors
941                 dw comapi_shuffle       ; 0012 cleanup, shuffle and boot
942                 dw comapi_idle          ; 0013 idle call
943                 dw comapi_localboot     ; 0014 local boot
944                 dw comapi_features      ; 0015 feature flags
945                 dw comapi_runkernel     ; 0016 run kernel image
946                 dw comapi_usingvga      ; 0017 report video mode change
947                 dw comapi_userfont      ; 0018 query custom font
948                 dw comapi_readdisk      ; 0019 read disk
949                 dw comapi_shufflepm     ; 001A cleanup, shuffle and boot to pm
950                 dw comapi_shufflerm     ; 001B cleanup, shuffle and boot to rm
951 int22_count     equ ($-int22_table)/2
952
953 APIKeyWait      db 0
954 APIKeyFlag      db 0
955
956 zero_string     db 0                    ; Empty, null-terminated string
957
958 ;
959 ; This is the feature flag array for INT 22h AX=0015h
960 feature_flags:
961 %if IS_PXELINUX
962                 db 1                    ; Have local boot, idle not noop
963 %elif IS_ISOLINUX
964                 db 3                    ; Have local boot, idle is noop
965 %else
966                 db 2                    ; No local boot, idle is noop
967 %endif
968 feature_flags_len equ ($-feature_flags)
969
970 err_notdos      db ': attempted DOS system call', CR, LF, 0
971 err_comlarge    db 'COMBOOT image too large.', CR, LF, 0
972
973                 section .bss1
974 ConfigName      resb    FILENAME_MAX