Formatting changes; comboot bug fix(?)
[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                 ; 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 cx,125              ; Max cmdline len (minus space and CR)
108                 mov si,[CmdOptPtr]
109                 mov di,081h             ; Offset in PSP for command line
110                 mov al,' '              ; DOS command lines begin with a space
111                 stosb
112
113 comboot_cmd_cp: es lodsb
114                 and al,al
115                 jz comboot_end_cmd
116                 stosb
117                 loop comboot_cmd_cp
118 comboot_end_cmd: mov al,0Dh             ; CR after last character
119                 stosb
120                 mov al,126              ; Include space but not CR
121                 sub al,cl
122                 mov [es:80h], al        ; Store command line length
123
124                 mov [SavedSSSP],sp
125                 mov [SavedSSSP+2],ss    ; Save away SS:SP
126
127                 mov ax,es
128                 mov ds,ax
129                 mov ss,ax
130                 xor sp,sp
131                 push word 0             ; Return to address 0 -> exit
132
133                 jmp comboot_seg:100h    ; Run it
134
135 ; Proper return vector
136 comboot_return: cli                     ; Don't trust anyone
137                 xor ax,ax
138                 jmp comboot_exit
139
140 ;
141 ; Set up the COMBOOT API interrupt vectors.  This is also used
142 ; by the COM32 code.
143 ;
144 comboot_setup_api:
145                 mov di,4*0x20           ; DOS interrupt vectors
146                 mov eax,comboot_return  ; INT 20h = exit
147                 stosd
148                 mov ax,comboot_int21    ; INT 21h = DOS-compatible syscalls
149                 stosd
150                 mov ax,comboot_int22    ; INT 22h = proprietary syscalls
151                 stosd
152                 mov ax,comboot_bogus
153                 mov cx,29               ; All remaining DOS vectors
154                 rep stosd
155                 ret
156
157 ; INT 21h: generic DOS system call
158 comboot_int21:  cli
159                 push ds
160                 push es
161                 push fs
162                 push gs
163                 pushad
164                 cld
165                 mov bp,cs
166                 mov ds,bp
167                 mov es,bp
168                 mov bp,sp                       ; Set up stack frame
169
170                 mov cx,int21_count
171                 mov si,int21_table
172 .again:         lodsb
173                 cmp al,P_AH
174                 lodsw
175                 loopne .again
176                 ; The last function in the list is the
177                 ; "no such function" function
178
179                 call ax                 ; Call the invoked function
180 comboot_resume:
181                 setc P_FLAGSL           ; Propagate CF->error
182                 popad
183                 pop gs
184                 pop fs
185                 pop es
186                 pop ds
187                 iret
188
189 ; Attempted to execute non-21h DOS system call
190 comboot_bogus:  cli                     ; Don't trust anyone
191                 mov ax,err_notdos
192 ;
193 ; Generic COMBOOT return to command line code
194 ;  AX -> message (if any)
195 ;  BX -> where to go next
196 ;
197 comboot_exit:
198                 mov bx,enter_command    ; Normal return to command prompt
199 comboot_exit_special:
200                 xor dx,dx
201                 mov ds,dx
202                 mov es,dx
203                 lss sp,[SavedSSSP]
204                 sti
205                 cld
206                 and ax,ax
207                 je .nomsg
208                 mov si,KernelCName
209                 call cwritestr
210                 xchg si,ax
211                 call cwritestr
212 .nomsg:         jmp bx
213
214 ;
215 ; INT 21h system calls
216 ;
217 comboot_getkey:                         ; 01 = get key with echo
218                 call vgashowcursor
219                 call comboot_getchar
220                 call vgahidecursor
221                 call writechr
222                 clc
223                 ret
224
225 comboot_writechr:                       ; 02 = writechr
226                 mov al,P_DL
227                 call writechr
228                 clc
229                 ret
230
231 comboot_writeserial:                    ; 04 = write serial port
232                 mov al,P_DL
233                 call write_serial
234                 clc
235                 ret
236
237 comboot_getkeynoecho:                   ; 08 = get key w/o echo
238                 call comboot_getchar
239                 clc
240                 ret
241
242 comboot_writestr:                       ; 09 = write string
243                 mov es,P_DS
244                 mov si,P_DX
245 .loop:          es lodsb
246                 cmp al,'$'              ; End string with $ - bizarre
247                 je .done
248                 call writechr
249                 jmp short .loop
250 .done:          clc
251                 ret
252
253 comboot_checkkey:                       ; 0B = check keyboard status
254                 cmp byte [APIKeyFlag],00h
255                 jnz .waiting
256                 call pollchar
257 .waiting:       setz al
258                 dec al                  ; AL = 0FFh if present, 0 if not
259                 mov P_AL,al
260                 clc
261                 ret
262
263 comboot_checkver:                       ; 30 = check DOS version
264                 ; We return 0 in all DOS-compatible version registers,
265                 ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX"
266                 mov P_EAX,'SY' << 16
267                 mov P_EBX,'SL' << 16
268                 mov P_ECX,'IN' << 16
269                 mov P_EDX,'UX' << 16
270                 clc
271                 ret
272
273 comboot_getchar:
274                 cmp byte [APIKeyFlag],00h
275                 jne .queued
276                 call getchar            ; If not queued get input
277                 and al,al               ; Function key?
278                 jnz .done
279                 mov [APIKeyWait],ah     ; High part of key
280                 inc byte [APIKeyFlag]   ; Set flag
281 .done:          mov P_AL,al
282                 ret
283 .queued:        mov al,[APIKeyWait]
284                 dec byte [APIKeyFlag]
285                 jmp .done
286
287 ;
288 ; INT 22h - SYSLINUX-specific system calls
289 ;           System call number in ax
290 ;
291 comboot_int22:
292                 cli
293                 push ds
294                 push es
295                 push fs
296                 push gs
297                 pushad
298                 cld
299                 mov bp,cs
300                 mov ds,bp
301                 mov es,bp
302                 mov bp,sp                       ; Set up stack frame
303
304                 cmp ax,int22_count
305                 jb .ok
306                 xor ax,ax                       ; Function 0 -> unimplemented
307 .ok:
308                 xchg ax,bx
309                 add bx,bx
310                 call [bx+int22_table]
311                 jmp comboot_resume              ; On return
312
313 ;
314 ; INT 22h AX=0000h      Unimplemented call
315 ;
316 comapi_err:
317                 stc
318                 ret
319
320 ;
321 ; INT 22h AX=0001h      Get SYSLINUX version
322 ;
323 comapi_get_version:
324                 ; Number of API functions supported
325                 mov P_AX,int22_count
326                 ; SYSLINUX version
327                 mov P_CX,(VER_MAJOR << 8)+VER_MINOR
328                 ; SYSLINUX derivative ID byte
329                 mov P_DX,my_id
330                 ; For future use
331                 mov P_BX,cs     ; cs == 0
332
333                 mov P_ES,ds
334                 ; ES:SI -> version banner
335                 mov P_SI,syslinux_banner
336                 ; ES:DI -> copyright string
337                 mov P_DI,copyright_str
338
339 comapi_nop:
340                 clc
341                 ret
342
343 ;
344 ; INT 22h AX=0002h      Write string
345 ;
346 ; Write null-terminated string in ES:BX
347 ;
348 comapi_writestr:
349                 mov ds,P_ES
350                 mov si,P_BX
351                 call writestr
352                 clc
353                 ret
354
355 ;
356 ; INT 22h AX=0003h      Run command
357 ;
358 ; Terminates the COMBOOT program and executes the command line in
359 ; ES:BX as if it had been entered by the user.
360 ;
361 comapi_run:
362                 mov ds,P_ES
363                 mov si,P_BX
364                 mov di,command_line
365 .copyloop:
366                 lodsb
367                 stosb
368                 and al,al
369                 jnz .copyloop
370                 xor ax,ax
371                 mov bx,load_kernel              ; Run a new kernel
372                 jmp comboot_exit_special        ; Terminate task, clean up
373
374 ;
375 ; INT 22h AX=0004h      Run default command             
376 ;
377 ; Terminates the COMBOOT program and executes the default command line
378 ; as if a timeout had happened or the user pressed <Enter>.
379 ;
380 comapi_run_default:
381                 mov bx,auto_boot
382                 jmp comboot_exit_special
383
384 ;
385 ; INT 22h AX=0005h      Force text mode
386 ;
387 ; Puts the video in standard text mode
388 ;
389 comapi_textmode:
390                 call vgaclearmode
391                 clc
392                 ret
393
394 ;
395 ; INT 22h AX=0006h      Open file
396 ;
397 comapi_open:
398                 push ds
399                 mov ds,P_ES
400                 mov si,P_SI
401                 mov di,InitRD
402                 push di
403                 call mangle_name
404                 pop di
405                 pop ds
406                 call searchdir
407                 jz .err
408                 mov P_AX,ax
409                 mov P_HAX,dx
410                 mov ax,[ClustSize]
411                 mov P_CX,ax
412                 clc
413                 ret
414 .err:
415                 stc
416                 ret
417
418
419 ;
420 ; INT 22h AX=0007h      Read file
421 ;
422 comapi_read:
423                 mov ax,P_BX
424                 mov si,P_SI
425                 call getfssec
426                 jnc .noteof
427                 xor si,si               ; SI <- 0 on EOF, CF <- 0
428 .noteof:        mov P_SI,si
429                 ret
430
431 ;
432 ; INT 22h AX=0008h      Close file
433 ;
434 comapi_close:
435                 ; Do nothing for now.  Eventually implement
436                 ; an internal API for this.
437                 clc
438                 ret
439
440 ;
441 ; INT 22h AX=0009h      Call PXE stack
442 ;
443 %if IS_PXELINUX
444 comapi_pxecall:
445                 mov bx,P_BX
446                 mov es,P_ES
447                 mov di,P_DI
448                 call pxenv
449                 mov P_AX,ax
450                 clc
451                 ret
452 %else
453 comapi_pxecall  equ comapi_err                  ; Not available
454 %endif
455
456 ;
457 ; INT 22h AX=000Ah      Get Derivative-Specific Info
458 ;
459 comapi_derinfo:
460                 mov P_AL,my_id
461 %if IS_SYSLINUX || IS_MDSLINUX
462                 mov al,[bsDriveNumber]
463                 mov P_DL,al
464                 mov P_ES,cs
465                 mov P_BX,PartInfo
466 %elif IS_PXELINUX
467                 mov ax,[APIVer]
468                 mov P_DX,ax
469                 mov ax,[StrucPtr]
470                 mov P_BX,ax
471                 mov ax,[StrucPtr+2]
472                 mov P_ES,ax
473                 mov ax,[InitStack]
474                 mov P_SI,ax
475                 mov ax,[InitStack+2]
476                 mov P_FS,ax
477 %elif IS_ISOLINUX
478                 mov al,[DriveNo]
479                 mov P_DL,al
480                 mov P_ES,cs
481                 mov P_BX,spec_packet
482 %endif
483                 clc
484                 ret
485
486 ;
487 ; INT 22h AX=000Bh      Get Serial Console Configuration
488 ;
489 comapi_serialcfg:
490                 mov ax,[SerialPort]
491                 mov P_DX,ax
492                 mov ax,[BaudDivisor]
493                 mov P_CX,ax
494                 mov ax,[FlowControl]
495                 or al,ah
496                 mov ah,[FlowIgnore]
497                 shr ah,4
498                 mov P_BX,ax
499                 clc
500                 ret
501
502 ;
503 ; INT 22h AX=000Ch      Perform final cleanup
504 ;
505 comapi_cleanup:
506 %if IS_PXELINUX
507                 ; Unload PXE if requested
508                 test dl,3
509                 setnz [KeepPXE]
510                 call unload_pxe
511 %elif IS_SYSLINUX || IS_MDSLINUX
512                 ; Restore original FDC table
513                 mov eax,[OrigFDCTabPtr]
514                 mov [fdctab],eax
515 %endif
516                 ; Reset the floppy disk subsystem
517                 xor ax,ax
518                 xor dx,dx
519                 int 13h
520                 clc
521                 ret
522
523 ;
524 ; This stuff should really be in the data section...
525 ;
526 %macro          int21 2
527                 db %1
528                 dw %2
529 %endmacro
530
531 int21_table:
532                 int21   00h, comboot_return
533                 int21   01h, comboot_getkey
534                 int21   02h, comboot_writechr
535                 int21   04h, comboot_writeserial
536                 int21   08h, comboot_getkey
537                 int21   09h, comboot_writestr
538                 int21   0Bh, comboot_checkkey
539                 int21   30h, comboot_checkver
540                 int21   4Ch, comboot_return
541                 int21    -1, comboot_bogus
542 int21_count     equ ($-int21_table)/3
543
544                 align 2, db 0
545 int22_table:
546                 dw comapi_err                   ; 0000 unimplemented syscall
547                 dw comapi_get_version           ; 0001 get SYSLINUX version
548                 dw comapi_writestr              ; 0002 write string
549                 dw comapi_run                   ; 0003 run specified command
550                 dw comapi_run_default           ; 0004 run default command
551                 dw comapi_textmode              ; 0005 force text mode
552                 dw comapi_open                  ; 0006 open file
553                 dw comapi_read                  ; 0007 read file
554                 dw comapi_close                 ; 0008 close file
555                 dw comapi_pxecall               ; 0009 call PXE stack
556                 dw comapi_derinfo               ; 000A derivative-specific info
557                 dw comapi_serialcfg             ; 000B get serial port config
558                 dw comapi_cleanup               ; 000C perform final cleanup
559 int22_count     equ ($-int22_table)/2
560
561 APIKeyWait      db 0
562 APIKeyFlag      db 0