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