Actually come up with stack-switch code which has a prayer of working
[profile/ivi/syslinux.git] / comboot.inc
1 ;; $Id$
2 ;; -----------------------------------------------------------------------
3 ;;   
4 ;;   Copyright 1994-2003 H. Peter Anvin - All Rights Reserved
5 ;;
6 ;;   This program is free software; you can redistribute it and/or modify
7 ;;   it under the terms of the GNU General Public License as published by
8 ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
10 ;;   (at your option) any later version; incorporated herein by reference.
11 ;;
12 ;; -----------------------------------------------------------------------
13
14 ;;
15 ;; comboot.inc
16 ;; 
17 ;; Common code for running a COMBOOT image
18 ;;
19
20 ; Parameter registers definition; this is the definition
21 ; of the stack frame used by INT 21h and INT 22h.
22 %define         P_FLAGS         word [bp+44]
23 %define         P_FLAGSL        byte [bp+44]
24 %define         P_FLAGSH        byte [bp+45]
25 %define         P_CS            word [bp+42]
26 %define         P_IP            word [bp+40]
27 %define         P_DS            word [bp+38]
28 %define         P_ES            word [bp+36]
29 %define         P_FS            word [bp+34]
30 %define         P_GS            word [bp+32]
31 %define         P_EAX           dword [bp+28]
32 %define         P_AX            word [bp+28]
33 %define         P_HAX           word [bp+30]
34 %define         P_AL            byte [bp+28]
35 %define         P_AH            byte [bp+29]
36 %define         P_ECX           dword [bp+24]
37 %define         P_CX            word [bp+24]
38 %define         P_HCX           word [bp+26]
39 %define         P_CL            byte [bp+24]
40 %define         P_CH            byte [bp+25]
41 %define         P_EDX           dword [bp+20]
42 %define         P_DX            word [bp+20]
43 %define         P_HDX           word [bp+22]
44 %define         P_DL            byte [bp+20]
45 %define         P_DH            byte [bp+21]
46 %define         P_EBX           dword [bp+16]
47 %define         P_BX            word [bp+16]
48 %define         P_HBX           word [bp+18]
49 %define         P_BL            byte [bp+16]
50 %define         P_BH            byte [bp+17]
51 %define         P_EBP           dword [bp+8]
52 %define         P_BP            word [bp+8]
53 %define         P_HBP           word [bp+10]
54 %define         P_ESI           dword [bp+4]
55 %define         P_SI            word [bp+4]
56 %define         P_HSI           word [bp+6]
57 %define         P_EDI           dword [bp]
58 %define         P_DI            word [bp]
59 %define         P_HDI           word [bp+2]
60
61 ; Looks like a COMBOOT image but too large
62 comboot_too_large:
63                 mov si,err_comlarge
64                 call cwritestr
65                 jmp enter_command
66
67 ;
68 ; Load a COMBOOT image.  A COMBOOT image is basically a DOS .COM file,
69 ; except that it may, of course, not contain any DOS system calls.  We
70 ; do, however, allow the execution of INT 20h to return to SYSLINUX.
71 ;
72 is_comboot_image:
73                 and dx,dx
74                 jnz comboot_too_large
75                 cmp ax,0ff00h           ; Max size in bytes
76                 jae comboot_too_large
77
78                 call comboot_setup_api
79
80                 mov cx,comboot_seg
81                 mov es,cx
82
83                 mov bx,100h             ; Load at <seg>:0100h
84
85                 mov cx,[ClustPerMoby]   ; Absolute maximum # of clusters
86                 call getfssec
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                 mov word [es:02h], comboot_seg+1000h
96
97                 ; Copy the command line from high memory
98                 mov cx,125              ; Max cmdline len (minus space and CR)
99                 mov si,[CmdOptPtr]
100                 mov di,081h             ; Offset in PSP for command line
101                 mov al,' '              ; DOS command lines begin with a space
102                 stosb
103
104 comboot_cmd_cp: lodsb
105                 and al,al
106                 jz comboot_end_cmd
107                 stosb
108                 loop comboot_cmd_cp
109 comboot_end_cmd: mov al,0Dh             ; CR after last character
110                 stosb
111                 mov al,126              ; Include space but not CR
112                 sub al,cl
113                 mov [es:80h], al        ; Store command line length
114
115                 mov [SavedSSSP],sp
116                 mov [SavedSSSP+2],ss    ; Save away SS:SP
117
118                 mov ax,es
119                 mov ds,ax
120                 mov ss,ax
121                 xor sp,sp
122                 push word 0             ; Return to address 0 -> exit
123
124                 jmp comboot_seg:100h    ; Run it
125
126 ; Proper return vector
127 comboot_return: cli                     ; Don't trust anyone
128                 xor ax,ax
129                 jmp comboot_exit
130
131 ;
132 ; Set up the COMBOOT API interrupt vectors.  This is also used
133 ; by the COM32 code.
134 ;
135 comboot_setup_api:
136                 mov di,4*0x20           ; DOS interrupt vectors
137                 mov eax,comboot_return  ; INT 20h = exit
138                 stosd
139                 mov ax,comboot_int21    ; INT 21h = DOS-compatible syscalls
140                 stosd
141                 mov ax,comboot_int22    ; INT 22h = proprietary syscalls
142                 stosd
143                 mov ax,comboot_bogus
144                 mov cx,29               ; All remaining DOS vectors
145                 rep stosd
146                 ret
147
148 ; INT 21h: generic DOS system call
149 comboot_int21:  cli
150                 push ds
151                 push es
152                 push fs
153                 push gs
154                 pushad
155                 cld
156                 mov bp,cs
157                 mov ds,bp
158                 mov es,bp
159                 mov bp,sp                       ; Set up stack frame
160
161                 mov cx,int21_count
162                 mov si,int21_table
163 .again:         lodsb
164                 cmp al,P_AH
165                 lodsw
166                 loopne .again
167                 ; The last function in the list is the
168                 ; "no such function" function
169
170                 call ax                 ; Call the invoked function
171 comboot_resume:
172                 setc P_FLAGSL           ; Propagate CF->error
173                 popad
174                 pop gs
175                 pop fs
176                 pop es
177                 pop ds
178                 iret
179
180 ; Attempted to execute non-21h DOS system call
181 comboot_bogus:  cli                     ; Don't trust anyone
182                 mov ax,err_notdos
183 ;
184 ; Generic COMBOOT return to command line code
185 ;  AX -> message (if any)
186 ;  BX -> where to go next
187 ;
188 comboot_exit:
189                 mov bx,enter_command    ; Normal return to command prompt
190 comboot_exit_special:
191                 xor dx,dx
192                 mov ds,dx
193                 mov es,dx
194                 lss sp,[SavedSSSP]
195                 sti
196                 cld
197                 and ax,ax
198                 je .nomsg
199                 mov si,KernelCName
200                 call cwritestr
201                 xchg si,ax
202                 call cwritestr
203 .nomsg:         jmp bx
204
205 ;
206 ; INT 21h system calls
207 ;
208 comboot_getkey:                         ; 01 = get key with echo
209                 call vgashowcursor
210                 call comboot_getchar
211                 call vgahidecursor
212                 call writechr
213                 clc
214                 ret
215
216 comboot_writechr:                       ; 02 = writechr
217                 mov al,P_DL
218                 call writechr
219                 clc
220                 ret
221
222 comboot_writeserial:                    ; 04 = write serial port
223                 mov al,P_DL
224                 call write_serial
225                 clc
226                 ret
227
228 comboot_getkeynoecho:                   ; 08 = get key w/o echo
229                 call comboot_getchar
230                 clc
231                 ret
232
233 comboot_writestr:                       ; 09 = write string
234                 mov es,P_DS
235                 mov si,P_DX
236 .loop:          es lodsb
237                 cmp al,'$'              ; End string with $ - bizarre
238                 je .done
239                 call writechr
240                 jmp short .loop
241 .done:          clc
242                 ret
243
244 comboot_checkkey:                       ; 0B = check keyboard status
245                 cmp byte [APIKeyFlag],00h
246                 jnz .waiting
247                 call pollchar
248 .waiting:       setz al
249                 dec al                  ; AL = 0FFh if present, 0 if not
250                 mov P_AL,al
251                 clc
252                 ret
253
254 comboot_checkver:                       ; 30 = check DOS version
255                 ; We return 0 in all DOS-compatible version registers,
256                 ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
257                 mov P_EAX,'SY' << 16
258                 mov P_EBX,'SL' << 16
259                 mov P_ECX,'IN' << 16
260                 mov P_EDX,'UX' << 16
261                 clc
262                 ret
263
264 comboot_getchar:
265                 cmp byte [APIKeyFlag],00h
266                 jne .queued
267                 call getchar            ; If not queued get input
268                 and al,al               ; Function key?
269                 jnz .done
270                 mov [APIKeyWait],ah     ; High part of key
271                 inc byte [APIKeyFlag]   ; Set flag
272 .done:          mov P_AL,al
273                 ret
274 .queued:        mov al,[APIKeyWait]
275                 dec byte [APIKeyFlag]
276                 jmp .done
277
278 ;
279 ; INT 22h - SYSLINUX-specific system calls
280 ;           System call number in ax
281 ;
282 comboot_int22:
283                 cli
284                 push ds
285                 push es
286                 push fs
287                 push gs
288                 pushad
289                 cld
290                 mov bp,cs
291                 mov ds,bp
292                 mov es,bp
293                 mov bp,sp                       ; Set up stack frame
294
295                 cmp ax,int22_count
296                 jb .ok
297                 xor ax,ax                       ; Function 0 -> unimplemented
298 .ok:
299                 xchg ax,bx
300                 add bx,bx
301                 call [bx+int22_table]
302                 jmp comboot_resume              ; On return
303
304 ;
305 ; INT 22h AX=0000h      Unimplemented call
306 ;
307 comapi_err:
308                 stc
309                 ret
310
311 ;
312 ; INT 22h AX=0001h      Get SYSLINUX version
313 ;
314 comapi_get_version:
315                 ; Number of API functions supported
316                 mov P_AX,int22_count
317                 ; SYSLINUX version
318                 mov P_CX,(VER_MAJOR << 8)+VER_MINOR
319                 ; SYSLINUX derivative ID byte
320                 mov P_DX,my_id
321                 ; For future use
322                 mov P_BX,cs     ; cs == 0
323
324                 mov P_ES,ds
325                 ; ES:SI -> version banner
326                 mov P_SI,syslinux_banner
327                 ; ES:DI -> copyright string
328                 mov P_DI,copyright_str
329
330 comapi_nop:
331                 clc
332                 ret
333
334 ;
335 ; INT 22h AX=0002h      Write string
336 ;
337 ; Write null-terminated string in ES:BX
338 ;
339 comapi_writestr:
340                 mov ds,P_ES
341                 mov si,P_BX
342                 call writestr
343                 clc
344                 ret
345
346 ;
347 ; INT 22h AX=0003h      Run command
348 ;
349 ; Terminates the COMBOOT program and executes the command line in
350 ; ES:BX as if it had been entered by the user.
351 ;
352 comapi_run:
353                 mov ds,P_ES
354                 mov si,P_BX
355                 mov di,command_line
356 .copyloop:
357                 lodsb
358                 stosb
359                 and al,al
360                 jnz .copyloop
361                 xor ax,ax
362                 mov bx,load_kernel              ; Run a new kernel
363                 jmp comboot_exit_special        ; Terminate task, clean up
364
365 ;
366 ; INT 22h AX=0004h      Run default command             
367 ;
368 ; Terminates the COMBOOT program and executes the default command line
369 ; as if a timeout had happened or the user pressed <Enter>.
370 ;
371 comapi_run_default:
372                 mov bx,auto_boot
373                 jmp comboot_exit_special
374
375 ;
376 ; INT 22h AX=0005h      Force text mode
377 ;
378 ; Puts the video in standard text mode
379 ;
380 comapi_textmode:
381                 call vgaclearmode
382                 clc
383                 ret
384
385 ;
386 ; INT 22h AX=0006h      Open file
387 ;
388 comapi_open:
389                 push ds
390                 mov ds,P_ES
391                 mov si,P_SI
392                 mov di,InitRD
393                 push di
394                 call mangle_name
395                 pop di
396                 pop ds
397                 call searchdir
398                 jz .err
399                 mov P_AX,ax
400                 mov P_HAX,dx
401                 mov ax,[ClustSize]
402                 mov P_CX,ax
403                 clc
404                 ret
405 .err:
406                 stc
407                 ret
408
409
410 ;
411 ; INT 22h AX=0007h      Read file
412 ;
413 comapi_read:
414                 mov ax,P_BX
415                 mov si,P_SI
416                 call getfssec
417                 jnc .noteof
418                 xor si,si               ; SI <- 0 on EOF, CF <- 0
419 .noteof:        mov P_SI,si
420                 ret
421
422 ;
423 ; INT 22h AX=0008h      Close file
424 ;
425 comapi_close:
426                 ; Do nothing for now.  Eventually implement
427                 ; an internal API for this.
428                 clc
429                 ret
430
431 ;
432 ; INT 22h AX=0009h      Call PXE stack
433 ;
434 %if IS_PXELINUX
435 comapi_pxecall:
436                 mov bx,P_BX
437                 mov es,P_ES
438                 mov di,P_DI
439                 call far [PXENVEntry]
440                 mov P_AX,ax
441                 clc
442                 ret
443 %else
444 comapi_pxecall  equ comapi_err                  ; Not available
445 %endif
446
447 ;
448 ; INT 22h AX=000Ah      Get Derivative-Specific Info
449 ;
450 comapi_derinfo:
451                 mov P_AL,my_id
452 %if IS_SYSLINUX
453                 mov al,[bsDriveNumber]
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
476
477 ;
478 ; INT 22h AX=000Bh      Get Serial Console Configuration
479 ;
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                 mov P_BX,ax
490                 clc
491                 ret
492
493 ;
494 ; INT 22h AX=000Ch      Perform final cleanup
495 ;
496 comapi_cleanup:
497 %if IS_PXELINUX
498                 ; Unload PXE if requested
499                 test dl,3
500                 setnz [KeepPXE]
501                 call unload_pxe
502 %elif IS_SYSLINUX
503                 ; Restore original FDC table
504                 mov eax,[OrigFDCTabPtr]
505                 mov [fdctab],eax
506 %endif
507                 ; Reset the floppy disk subsystem
508                 xor ax,ax
509                 xor dx,dx
510                 int 13h
511                 clc
512                 ret
513
514 ;
515 ; This stuff should really be in the data section...
516 ;
517 %macro          int21 2
518                 db %1
519                 dw %2
520 %endmacro
521
522 int21_table:
523                 int21   00h, comboot_return
524                 int21   01h, comboot_getkey
525                 int21   02h, comboot_writechr
526                 int21   04h, comboot_writeserial
527                 int21   08h, comboot_getkey
528                 int21   09h, comboot_writestr
529                 int21   0Bh, comboot_checkkey
530                 int21   30h, comboot_checkver
531                 int21   4Ch, comboot_return
532                 int21    -1, comboot_bogus
533 int21_count     equ ($-int21_table)/3
534
535                 align 2, db 0
536 int22_table:
537                 dw comapi_err                   ; 0000 unimplemented syscall
538                 dw comapi_get_version           ; 0001 get SYSLINUX version
539                 dw comapi_writestr              ; 0002 write string
540                 dw comapi_run                   ; 0003 run specified command
541                 dw comapi_run_default           ; 0004 run default command
542                 dw comapi_textmode              ; 0005 force text mode
543                 dw comapi_open                  ; 0006 open file
544                 dw comapi_read                  ; 0007 read file
545                 dw comapi_close                 ; 0008 close file
546                 dw comapi_pxecall               ; 0009 call PXE stack
547                 dw comapi_derinfo               ; 000A derivative-specific info
548                 dw comapi_serialcfg             ; 000B get serial port config
549                 dw comapi_cleanup               ; 000C perform final cleanup
550 int22_count     equ ($-int22_table)/2
551
552 APIKeyWait      db 0
553 APIKeyFlag      db 0