Better describe what this macro does (comment fix.)
[syslinux.git] / comboot.inc
blob9a96326d9397449075f4aeec0138ad4c482838c8
1 ;; -----------------------------------------------------------------------
2 ;;
3 ;;   Copyright 1994-2005 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_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]
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
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.
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
79                 push si                 ; Save file handle
81                 call make_plain_cmdline
83                 call comboot_setup_api
85                 mov cx,comboot_seg
86                 mov es,cx
88                 xor di,di
89                 mov cx,64               ; 256 bytes (size of PSP)
90                 xor eax,eax             ; Clear PSP
91                 rep stosd
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
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
113 .loop:          es lodsb
114                 and al,al
115                 jz .done
116                 stosb
117                 loop .loop
118 .done:
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
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
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
140                 jmp comboot_seg:100h    ; Run it
142 ; Proper return vector
143 comboot_return: cli                     ; Don't trust anyone
144                 jmp comboot_exit
147 ; Set up the COMBOOT API interrupt vectors.  This is also used
148 ; by the COM32 code.
150 comboot_setup_api:
151                 mov di,4*0x20           ; DOS interrupt vectors
152                 mov eax,comboot_return  ; INT 20h = exit
153                 stosd
154                 mov ax,comboot_int21    ; INT 21h = DOS-compatible syscalls
155                 stosd
156                 mov ax,comboot_int22    ; INT 22h = proprietary syscalls
157                 stosd
158                 mov ax,comboot_bogus
159                 mov cx,29               ; All remaining DOS vectors
160                 rep stosd
161                 ret
163 ; INT 21h: generic DOS system call
164 comboot_int21:  cli
165                 push ds
166                 push es
167                 push fs
168                 push gs
169                 pushad
170                 cld
171                 mov bp,cs
172                 mov ds,bp
173                 mov es,bp
174                 mov bp,sp                       ; Set up stack frame
176                 call adjust_screen              ; The COMBOOT program might have changed the screen
178                 mov cx,int21_count
179                 mov si,int21_table
180 .again:         lodsb
181                 cmp al,P_AH
182                 lodsw
183                 loopne .again
184                 ; The last function in the list is the
185                 ; "no such function" function
186                 clc
187                 call ax                 ; Call the invoked function
188 comboot_resume:
189                 setc P_FLAGSL           ; Propagate CF->error
190                 popad
191                 pop gs
192                 pop fs
193                 pop es
194                 pop ds
195                 iret
197 ; Attempted to execute non-21h DOS system call
198 comboot_bogus:  cli                     ; Don't trust anyone
199                 mov ax,err_notdos
201 ; Generic COMBOOT return to command line code
202 ;  BX -> where to go next
204 comboot_exit:
205                 mov bx,enter_command    ; Normal return to command prompt
206 comboot_exit_special:
207                 RESET_STACK_AND_SEGS AX
208                 call adjust_screen      ; The COMBOOT program might have changed the screen
209                 jmp bx
212 ; INT 21h system calls
214 comboot_getkey:                         ; 01 = get key with echo
215                 call vgashowcursor
216                 call comboot_getchar
217                 call vgahidecursor
218                 call writechr
219                 clc
220                 ret
222 comboot_writechr:                       ; 02 = writechr
223                 mov al,P_DL
224                 call writechr
225                 clc
226                 ret
228 comboot_writeserial:                    ; 04 = write serial port
229                 mov al,P_DL
230                 call write_serial
231                 clc
232                 ret
234 comboot_getkeynoecho:                   ; 08 = get key w/o echo
235                 call comboot_getchar
236                 clc
237                 ret
239 comboot_writestr:                       ; 09 = write DOS string
240                 mov es,P_DS
241                 mov si,P_DX
242 .loop:          es lodsb
243                 cmp al,'$'              ; End string with $ - bizarre
244                 je .done
245                 call writechr
246                 jmp short .loop
247 .done:          clc
248                 ret
250 comboot_checkkey:                       ; 0B = check keyboard status
251                 cmp byte [APIKeyFlag],00h
252                 jnz .waiting
253                 call pollchar
254 .waiting:       setz al
255                 dec al                  ; AL = 0FFh if present, 0 if not
256                 mov P_AL,al
257                 clc
258                 ret
260 comboot_checkver:                       ; 30 = check DOS version
261                 ; We return 0 in all DOS-compatible version registers,
262                 ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
263                 mov P_EAX,'SY' << 16
264                 mov P_EBX,'SL' << 16
265                 mov P_ECX,'IN' << 16
266                 mov P_EDX,'UX' << 16
267                 ret
269 comboot_getchar:
270                 cmp byte [APIKeyFlag],00h
271                 jne .queued
272                 call getchar            ; If not queued get input
273                 and al,al               ; Function key?  (CF <- 0)
274                 jnz .done
275                 mov [APIKeyWait],ah     ; High part of key
276                 inc byte [APIKeyFlag]   ; Set flag
277 .done:          mov P_AL,al
278                 ret
279 .queued:        mov al,[APIKeyWait]
280                 dec byte [APIKeyFlag]
281                 jmp .done
284 ; INT 22h - SYSLINUX-specific system calls
285 ;           System call number in ax
287 comboot_int22:
288                 cli
289                 push ds
290                 push es
291                 push fs
292                 push gs
293                 pushad
294                 cld
295                 mov bp,cs
296                 mov ds,bp
297                 mov es,bp
298                 mov bp,sp                       ; Set up stack frame
300                 call adjust_screen              ; The COMBOOT program might have changed the screen
302                 cmp ax,int22_count
303                 jb .ok
304                 xor ax,ax                       ; Function 0 -> unimplemented
305 .ok:
306                 xchg ax,bx
307                 add bx,bx                       ; CF <- 0
308                 call [bx+int22_table]
309                 jmp comboot_resume              ; On return
312 ; INT 22h AX=0000h      Unimplemented call
314 comapi_err:
315                 stc
316                 ret
319 ; INT 22h AX=0001h      Get SYSLINUX version
321 comapi_get_version:
322                 ; Number of API functions supported
323                 mov P_AX,int22_count
324                 ; SYSLINUX version
325                 mov P_CX,(VER_MAJOR << 8)+VER_MINOR
326                 ; SYSLINUX derivative ID byte
327                 mov P_DX,my_id
328                 ; For future use
329                 mov P_BX,cs     ; cs == 0
331                 mov P_ES,ds
332                 ; ES:SI -> version banner
333                 mov P_SI,syslinux_banner
334                 ; ES:DI -> copyright string
335                 mov P_DI,copyright_str
337 comapi_nop:
338                 clc
339                 ret
342 ; INT 22h AX=0002h      Write string
344 ; Write null-terminated string in ES:BX
346 comapi_writestr:
347                 mov ds,P_ES
348                 mov si,P_BX
349                 call writestr
350                 clc
351                 ret
354 ; INT 22h AX=0003h      Run command
356 ; Terminates the COMBOOT program and executes the command line in
357 ; ES:BX as if it had been entered by the user.
359 comapi_run:
360                 mov ds,P_ES
361                 mov si,P_BX
362                 mov di,command_line
363                 call strcpy
364                 mov bx,load_kernel              ; Run a new kernel
365                 jmp comboot_exit_special        ; Terminate task, clean up
368 ; INT 22h AX=0004h      Run default command
370 ; Terminates the COMBOOT program and executes the default command line
371 ; as if a timeout had happened or the user pressed <Enter>.
373 comapi_run_default:
374                 mov bx,auto_boot
375                 jmp comboot_exit_special
378 ; INT 22h AX=0005h      Force text mode
380 ; Puts the video in standard text mode
382 comapi_textmode:
383                 call vgaclearmode
384                 clc
385                 ret
388 ; INT 22h AX=0006h      Open file
390 comapi_open:
391                 push ds
392                 mov ds,P_ES
393                 mov si,P_SI
394                 mov di,InitRD
395                 push di
396                 call mangle_name
397                 pop di
398                 pop ds
399                 call searchdir
400                 jz comapi_err
401                 mov P_AX,ax
402                 mov P_HAX,dx
403                 mov P_CX,SECTOR_SIZE
404                 mov P_SI,si
405                 clc
406                 ret
409 ; INT 22h AX=0007h      Read file
411 comapi_read:
412                 mov es,P_ES
413                 mov bx,P_BX
414                 mov si,P_SI
415                 mov cx,P_CX
416                 call getfssec
417                 jnc .noteof
418                 xor si,si               ; SI <- 0 on EOF, CF <- 0
419 .noteof:        mov P_SI,si
420                 ret
423 ; INT 22h AX=0008h      Close file
425 comapi_close:
426                 ; Do nothing for now.  Eventually implement
427                 ; an internal API for this.
428                 clc
429                 ret
432 ; INT 22h AX=0009h      Call PXE stack
434 %if IS_PXELINUX
435 comapi_pxecall:
436                 mov bx,P_BX
437                 mov es,P_ES
438                 mov di,P_DI
439                 call pxenv
440                 mov P_AX,ax
441                 clc
442                 ret
443 %else
444 comapi_pxecall  equ comapi_err                  ; Not available
445 %endif
448 ; INT 22h AX=000Ah      Get Derivative-Specific Info
450 comapi_derinfo:
451                 mov P_AL,my_id
452 %if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
453                 mov al,[DriveNumber]
454                 mov P_DL,al
455                 mov P_ES,cs
456                 mov P_BX,PartInfo
457 %elif IS_PXELINUX
458                 mov ax,[APIVer]
459                 mov P_DX,ax
460                 mov ax,[StrucPtr]
461                 mov P_BX,ax
462                 mov ax,[StrucPtr+2]
463                 mov P_ES,ax
464                 mov ax,[InitStack]
465                 mov P_SI,ax
466                 mov ax,[InitStack+2]
467                 mov P_FS,ax
468 %elif IS_ISOLINUX
469                 mov al,[DriveNo]
470                 mov P_DL,al
471                 mov P_ES,cs
472                 mov P_BX,spec_packet
473 %endif
474                 clc
475                 ret
478 ; INT 22h AX=000Bh      Get Serial Console Configuration
480 comapi_serialcfg:
481                 mov ax,[SerialPort]
482                 mov P_DX,ax
483                 mov ax,[BaudDivisor]
484                 mov P_CX,ax
485                 mov ax,[FlowControl]
486                 or al,ah
487                 mov ah,[FlowIgnore]
488                 shr ah,4
489                 test byte [DisplayCon],01h
490                 jnz .normalconsole
491                 or ah,80h
492 .normalconsole:
493                 mov P_BX,ax
494                 clc
495                 ret
498 ; INT 22h AX=000Ch      Perform final cleanup
500 comapi_cleanup:
501 %if IS_PXELINUX
502                 ; Unload PXE if requested
503                 test dl,3
504                 setnz [KeepPXE]
505                 sub bp,sp               ; unload_pxe may move the stack around
506                 call unload_pxe
507                 add bp,sp               ; restore frame pointer...
508 %elif IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX
509                 ; Restore original FDC table
510                 mov eax,[OrigFDCTabPtr]
511                 mov [fdctab],eax
512 %endif
513                 ; Reset the floppy disk subsystem
514                 xor ax,ax
515                 xor dx,dx
516                 int 13h
517                 clc
518                 ret
521 ; INT 22h AX=000Dh      Clean up then replace bootstrap
523 comapi_chainboot:
524                 call comapi_cleanup
525                 mov eax,P_EDI
526                 mov [trackbuf+4],eax            ; Copy from
527                 mov eax,P_ECX
528                 mov [trackbuf+8],eax            ; Total bytes
529                 mov eax,7C00h
530                 mov [trackbuf],eax              ; Copy to
531                 mov [EntryPoint],eax            ; CS:IP entry point
532                 mov esi,P_ESI
533                 mov edx,P_EBX
534                 mov bx,P_DS
535                 jmp replace_bootstrap_one
539 ; INT 22h AX=000Eh      Get configuration file name
541 comapi_configfile:
542                 mov P_ES,cs
543                 mov P_BX,ConfigName
544                 clc
545                 ret
548 ; INT 22h AX=000Fh      Get IPAPPEND strings
550 %if IS_PXELINUX
551 comapi_ipappend:
552                 mov P_ES,cs
553                 mov P_CX,numIPAppends
554                 mov P_BX,IPAppends
555                 clc
556                 ret
558                 section .data
559                 alignb 2, db 0
560 IPAppends       dw IPOption
561                 dw BOOTIFStr
562 numIPAppends    equ ($-IPAppends)/2
564 %else
565 comapi_ipappend equ comapi_err
566 %endif
568                 section .text
571 ; INT 22h AX=0010h      Resolve hostname
573 %if IS_PXELINUX
574 comapi_dnsresolv:
575                 mov ds,P_ES
576                 mov si,P_BX
577                 call dns_resolv
578                 mov P_EAX,eax
579                 ret
580 %else
581 comapi_dnsresolv equ comapi_err
582 %endif
584                 section .text
587 ; INT 22h AX=0011h      Maximum number of shuffle descriptors
589 comapi_maxshuffle:
590                 mov P_CX,(2*trackbufsize)/12
591                 ret
594 ; INT 22h AX=0012h      Cleanup, shuffle and boot
596 comapi_shuffle:
597                 call comapi_cleanup
598                 mov cx,P_CX
599                 cmp cx,(2*trackbufsize)/12
600                 ja .error
602                 push cx                         ; On stack: descriptor count
604                 lea cx,[ecx+ecx*2]              ; CX *= 3
606                 mov fs,P_ES
607                 mov si,P_DI
608                 mov di,trackbuf
609                 push di                         ; On stack: descriptor list address
610                 fs rep movsd                    ; Copy the list
612                 mov eax,P_EBP
613                 mov [EntryPoint],eax            ; CS:IP entry point
614                 mov esi,P_ESI
615                 mov edx,P_EBX
616                 mov bx,P_DS
617                 jmp replace_bootstrap
618 .error:
619                 stc
620                 ret
623 ; INT 22h AX=0013h      Idle call
626 ; *** FIX THIS ***
627 ; The idle call seems to have detrimental effects on some machines when
628 ; called from a COM32 context (WHY?) --  disable it for now.
630 %if 0 ; def HAVE_IDLE
632 comapi_idle:
633                 DO_IDLE
634                 clc
635                 ret
637 %else
639 comapi_idle     equ comapi_err
641 %endif
644 ; INT 22h AX=0014h      Local boot
646 %if IS_PXELINUX || IS_ISOLINUX
647 comapi_localboot:
648                 mov ax,P_DX
649                 jmp local_boot
650 %else
651 comapi_localboot equ comapi_err
652 %endif
655 ; INT 22h AX=0015h      Feature flags
657 comapi_features:
658                 mov P_ES,cs
659                 mov P_BX,feature_flags
660                 mov P_CX,feature_flags_len
661                 clc
662                 ret
665 ; INT 22h AX=0016h      Run kernel image
667 comapi_runkernel:
668                 push ds
669                 mov ds,P_DS
670                 mov si,P_SI
671                 mov di,KernelName
672                 push di
673                 call mangle_name
674                 pop di
675                 pop ds
676                 call searchdir
677                 jz comapi_err
679                 ; The kernel image was found, so we can load it...
680                 mov [Kernel_SI],si
681                 mov [Kernel_EAX],ax
682                 mov [Kernel_EAX+2],dx
684                 ; It's not just possible, but quite likely, that ES:BX
685                 ; points into real_mode_seg, so we need to exercise some
686                 ; special care here... use xfer_buf_seg as an intermediary
687                 push ds
688                 push es
689                 mov ax,xfer_buf_seg
690                 mov ds,P_ES
691                 mov si,P_BX
692                 mov es,ax
693                 xor di,di
694                 call strcpy
695                 pop es
696                 pop ds
698 %if IS_PXELINUX
699                 mov al,P_CL
700                 mov [IPAppend],al
701 %endif
703                 mov bx,.finish
704                 jmp comboot_exit_special
706 .finish:
707                 ; Copy the command line into its proper place
708                 push ds
709                 push es
710                 mov ax,xfer_buf_seg
711                 mov dx,real_mode_seg
712                 mov ds,ax
713                 mov es,dx
714                 xor si,si
715                 mov di,cmd_line_here
716                 call strcpy
717                 mov byte [es:di-1],' '          ; Simulate APPEND
718                 pop es
719                 pop ds
720                 mov [CmdLinePtr],di
721                 mov word [CmdOptPtr],zero_string
722                 jmp kernel_good_saved
724                 section .data
726 %macro          int21 2
727                 db %1
728                 dw %2
729 %endmacro
731 int21_table:
732                 int21   00h, comboot_return
733                 int21   01h, comboot_getkey
734                 int21   02h, comboot_writechr
735                 int21   04h, comboot_writeserial
736                 int21   08h, comboot_getkeynoecho
737                 int21   09h, comboot_writestr
738                 int21   0Bh, comboot_checkkey
739                 int21   30h, comboot_checkver
740                 int21   4Ch, comboot_return
741                 int21    -1, comboot_bogus
742 int21_count     equ ($-int21_table)/3
744                 align 2, db 0
745 int22_table:
746                 dw comapi_err           ; 0000 unimplemented syscall
747                 dw comapi_get_version   ; 0001 get SYSLINUX version
748                 dw comapi_writestr      ; 0002 write string
749                 dw comapi_run           ; 0003 run specified command
750                 dw comapi_run_default   ; 0004 run default command
751                 dw comapi_textmode      ; 0005 force text mode
752                 dw comapi_open          ; 0006 open file
753                 dw comapi_read          ; 0007 read file
754                 dw comapi_close         ; 0008 close file
755                 dw comapi_pxecall       ; 0009 call PXE stack
756                 dw comapi_derinfo       ; 000A derivative-specific info
757                 dw comapi_serialcfg     ; 000B get serial port config
758                 dw comapi_cleanup       ; 000C perform final cleanup
759                 dw comapi_chainboot     ; 000D clean up then bootstrap
760                 dw comapi_configfile    ; 000E get name of config file
761                 dw comapi_ipappend      ; 000F get ipappend strings
762                 dw comapi_dnsresolv     ; 0010 resolve hostname
763                 dw comapi_maxshuffle    ; 0011 maximum shuffle descriptors
764                 dw comapi_shuffle       ; 0012 cleanup, shuffle and boot
765                 dw comapi_idle          ; 0013 idle call
766                 dw comapi_localboot     ; 0014 local boot
767                 dw comapi_features      ; 0015 feature flags
768                 dw comapi_runkernel     ; 0016 run kernel image
769 int22_count     equ ($-int22_table)/2
771 APIKeyWait      db 0
772 APIKeyFlag      db 0
774 zero_string     db 0                    ; Empty, null-terminated string
777 ; This is the feature flag array for INT 22h AX=0015h
778 feature_flags:
779 %if IS_PXELINUX
780                 db 1                    ; Have local boot, idle not noop
781 %elif IS_ISOLINUX
782                 db 3                    ; Have local boot, idle is noop
783 %else
784                 db 2                    ; No local boot, idle is noop
785 %endif
786 feature_flags_len equ ($-feature_flags)