Add externs to avoid multiple definitions, and then add missing definitions.
[rrq/maintain_lilo.git] / diagnose / bios.c
1 /* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
2  * This file is part of the Linux-8086 C library and is distributed
3  * under the GNU Library General Public License.
4  */
5
6 /* Modified 14-Jan-2002 by John Coffman <johninsd@san.rr.com> for inclusion
7  * in the set of LILO diagnostics.  This code is the property of Robert
8  * de Bath, and is used with his permission.
9  */
10 #define MSDOS_TOO 1
11 #define SAVE_SP 1
12
13
14 #if !__FIRST_ARG_IN_AX__
15 #ifdef __AS386_16__
16 #ifdef __STANDALONE__
17
18 #include <bios.h>
19 #include <fcntl.h>
20 #include <errno.h>
21
22 #ifdef L_bios_start
23
24 char ** environ = { 0 };
25 int errno;
26
27 void (*__cleanup)() = 0;
28
29 #asm
30   .data
31 export ___argr
32 ___argr:
33   .word 0,0,0,0,0,0,0,0 ! A struct REGS
34 export ___argseg
35 ___argseg:
36   .word 0,0,0,0         ! A struct SREGS
37 ___argr_end:
38 defarg:
39   .word boot_str, 0
40 boot_str:
41   .asciz "boot"
42 loop_save:
43   .word 0
44
45   .text
46 #if SAVE_SP
47 sssp_save:
48   .word 0,0             ! dirty area if startup SS & SP are to be seen
49 #endif
50 export ___cstartup      ! Crt0 startup
51 ___cstartup:
52   cli
53 #if MSDOS_TOO
54   seg es
55   cmp   word ptr [0],#$20CD     ! "int 20h" at psp:  ES:0000
56   jne   not_dos
57   push  ax                      ! DOS provides us a stack
58   mov   ax,cs
59   add   ax,#$10                 ! bump CS by 0x10 
60   push  ax
61   mov   ax,#is_dos              ! resume address
62   push  ax
63   retf                          ! continue at next instruction
64 is_dos:
65   pop   ax                      ! restore saved AX
66   seg cs
67   mov   word ptr [iret_ins-2],es  ! patch return to int 20h exit
68 not_dos:
69 #endif
70 #if SAVE_SP
71   seg cs
72   mov   [sssp_save],sp
73   seg cs
74   mov   [sssp_save+2],ss        ! save startup SS:SP
75 #endif
76   mov   sp,cs
77   add   sp,#__segoff
78   mov   ss,sp
79   mov   sp,#___argr_end
80
81   push  ds
82 #if SAVE_SP
83   seg cs
84   push  [sssp_save+2]   ! startup SS
85 #else
86   push  ss
87 #endif
88   push  cs  
89   push  es
90
91 #if SAVE_SP
92   seg cs
93   push  [sssp_save]     ! startup SP to flags
94 #else
95   pushf         ! to flags, but why?
96 #endif
97   push  bp      ! to cflags
98   
99   push  di      ! save the startup registers
100   push  si      ! pushes are shorter than  mov  mem,reg
101   push  dx
102   push  cx
103   push  bx
104   push  ax
105   
106   xor   sp,sp   ! maximum stack
107   push  bp      ! perhaps bp should be zeroed first
108   sti           ! now turn on interrupts
109
110   push  ss              ! set up the ES and DS
111   pop   ds              ! equal to the SS
112   
113 zap_bss:                ! Clear the BSS
114   push  ds
115   pop   es              ! ES now = DS
116   mov   di,#__edata
117   mov   cx,#__end
118   sub   cx,di
119   xor   ax,ax
120   cld
121   rep
122    stosb
123
124   push  [_environ]
125   mov   ax,#defarg      ! Don`t define __mkargv, standalone programs don`t
126   push  ax              ! get any arguments.
127   mov   ax,#1
128   push  ax
129
130   mov   bx,#auto_start  ! Pointer to first autostart function
131 auto_run:
132   mov   [loop_save],bx
133   mov   bx,[bx]
134   test  bx,bx
135   jz    no_entry
136   call  bx              ! Call the function
137 no_entry:
138   mov   bx,[loop_save]
139   inc   bx              ! next
140   inc   bx
141   jmp   auto_run        ! And round for the next.
142
143 call_exit:              ! Last item called by above.
144   pop   bx              ! Be tidy.
145   push  ax              ! At the end the last called was main() push it`s
146   call  _exit           ! return val and call exit();
147 bad_exit:
148   jmp   bad_exit        ! Exit returned !!
149
150   loc   2
151   .word _main           ! Segment 2 is the trailing pointers, main and the
152   .word call_exit       ! routine to call exit.
153 data_start:
154
155   .text
156 export _exit
157 _exit:                  ! exit(rv) function
158   mov   bx,sp
159   push  [bx+2]          ! Copy the `rv` for the exit fuctions.
160   mov   bx,[___cleanup] ! Call exit, normally this is `__do_exit`
161   test  bx,bx
162   je    no_clean        ! But it`s default is null
163   call  bx
164 no_clean:
165   inc   sp
166   inc   sp
167
168 export __exit
169 __exit:
170   xor   ax,ax
171   mov   es,ax
172   seg   es
173   mov   [$E6*4+2],cs    !
174   seg   es
175   mov   [$E6*4],#iret_ins
176   dec   ax              ! AX = $FFFF
177   int   $E6             ! Try to exit DOSEMU
178                         ! If we get here we`re not in dosemu.
179   seg es
180   mov   [$472],#$1234   ! Warm reboot.
181   
182   jmpi  $0000,$FFFF     ! DO NOT SEPARATE
183 iret_ins:               ! THIS LABEL FROM THE  jmpi ...
184   iret                  ! interrupt return!! not  retf (==reti)
185
186 export ___mkargv        ! must resolve this reference
187 ___mkargv:
188   ret
189
190 #endasm
191
192 #endif
193
194 /****************************************************************************/
195
196 #ifdef L_bios_write
197 write(fd,buf,len)
198 int fd,len;
199 char * buf;
200 {
201    register int v, c;
202    if(fd == 1 || fd == 2)
203    {
204       for(v=len; v>0; v--)
205       {
206          c= *buf++;
207          if( c == '\n') bios_putc('\r');
208          bios_putc(c);
209       }
210       return len;
211    } 
212    return (*__files)(CMD_WRITE, fd, buf, len);
213 }
214 #endif
215
216 /****************************************************************************/
217
218 #ifdef L_bios_read
219 read(fd,buf,len)
220 int fd,len;
221 char * buf;
222 {
223    if(fd == 0) return bios_rdline(buf, len);
224    return (*__files)(CMD_READ, fd, buf, len);
225 }
226 #endif
227
228 /****************************************************************************/
229
230 #ifdef L_bios_lseek
231 long
232 lseek(fd, offt, whence)
233 int fd, whence;
234 long offt;
235 {
236    if( fd >= 0 && fd <= 2 ) errno = ESPIPE;
237    else 
238    {
239       if( (*__files)(CMD_LSEEK, fd, &offt, whence) >= 0 )
240          return offt;
241    }
242    return -1L;
243 }
244 #endif
245
246 /****************************************************************************/
247
248 #ifdef L_bios_close
249 close(fd)
250 int fd;
251 {
252    if( fd >= 0 && fd <= 2 ) errno = ENOSYS;
253    else
254       return (*__files)(CMD_CLOSE, fd);
255    return -1;
256 }
257 #endif
258
259 /****************************************************************************/
260
261 #ifdef L_bios_nofiles
262 int (*__files)() = __nofiles;
263
264 int __nofiles(cmd, fd, buf, len)
265 int cmd, fd, len;
266 char * buf;
267
268    errno = EBADF;
269    return -1;
270 }
271
272 #endif
273
274 /****************************************************************************/
275
276 #ifdef L_bios_isatty
277 isatty(fd)
278 int fd;
279 {
280    if( fd >= 0 && fd <= 2 ) return 1;
281    return 0;
282 }
283 #endif
284
285 /****************************************************************************/
286
287 #endif
288 #endif
289 #endif