|
|
1.1 root 1: /*
2: * Copyright (c) 1995-1994 The University of Utah and
3: * the Computer Systems Laboratory at the University of Utah (CSL).
4: * All rights reserved.
5: *
6: * Permission to use, copy, modify and distribute this software is hereby
7: * granted provided that (1) source code retains these copyright, permission,
8: * and disclaimer notices, and (2) redistributions including binaries
9: * reproduce the notices in supporting documentation, and (3) all advertising
10: * materials mentioning features or use of this software display the following
11: * acknowledgement: ``This product includes software developed by the
12: * Computer Systems Laboratory at the University of Utah.''
13: *
14: * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
15: * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
16: * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17: *
18: * CSL requests users of this software to return to [email protected] any
19: * improvements that they make and grant CSL redistribution rights.
20: *
21: * Author: Bryan Ford, University of Utah CSL
22: */
23:
24: #include <mach/machine/asm.h>
25:
26: #include "config.h"
27: #include "i16_crt0.h"
28:
29: .code16
30: .text
31:
32: ENTRY(i16_entry)
33: /* DOS starts us up with our stack pointer pointing
34: to the very top of our BSS segment.
35: ds and es point to the PSP. */
36:
37: #define DELAY jmp 1f; 1: jmp 1f; 1: jmp 1f; 1:
38:
39: /* Check to make sure we're running on a 386 or higher -
40: _without_ using any 32-bit instructions of course.
41: Tricky, since gas doesn't support 16-bit addressing modes. :-)
42: We can't produce any 16-bit relocations either,
43: because ELF doesn't support them.
44: This code is basically straight out of the Pentium manual,
45: except gassed of coursed. */
46: pushfw
47: DELAY
48: popw %bx
49: movw $0xfff,%ax
50: andw %bx,%ax
51: pushw %ax
52: DELAY
53: popfw
54: DELAY
55: pushfw
56: DELAY
57: popw %ax
58: and $0xf000,%ax
59: cmpw $0xf000,%ax
60:
61: je 1f
62: orw $0xf000,%bx
63: pushw %bx
64: DELAY
65: popfw
66: DELAY
67: pushfw
68: DELAY
69: popw %ax
70: andw $0xf000,%ax
71: jnz 4f
72: 1:
73: /* Gak! We're running on an 8086/8088/80286! */
74: callw 5f
75: .ascii "This program requires a 386 or better.\r\n\0"
76: 5: popw %si
77: movw %cs,%ax
78: movw %ax,%ds
79: cld
80: 2: lodsb
81: orb %al,%al
82: jz 3f
83: movb $0x02,%ah
84: movb %al,%dl
85: int $0x21
86: jmp 2b
87: 3: movw $0x4c02,%ax
88: int $0x21
89: 4:
90: /* Now we can use 32-bit instructions all we want. */
91:
92: /* Save the PSP segment address (dx). */
93: movw %ds,%dx
94:
95: /* Find our real-mode code segment (ax). */
96: movw %cs,%ax
97:
98: #ifdef ENABLE_PAGE_ALIGNED_KERNEL
99: /* Move our code and data so that everything is on a page boundary.
100: Theoretically we _could_ go past the end of available memory,
101: since we're not checking, but it's enormously unlikely. */
102: std
103: movw %ax,%ds
104: addw $0xff,%ax
105: andw $0xff00,%ax
106: movw %ax,%es
107: movl $EXT(edata),%ecx
108: subl $EXT(i16_entry_2),%ecx
109: movl $EXT(edata)-1,%esi
110: movw %si,%di
111: rep
112: movsb
113:
114: /* Start running at the new address. */
115: pushl $EXT(i16_entry_2)
116: movw %ax,2(%esp)
117: lretw
118:
119: ENTRY(i16_entry_2)
120: /* We're now page aligned. */
121: #endif ENABLE_PAGE_ALIGNED_KERNEL
122:
123: /* Load the data segment registers appropriately. */
124: movw %ax,%es
125: movw %ax,%ss
126:
127: /* Start using a real stack. */
128: movl $EXT(crt0_stack)+CRT0_STACK_SIZE,%esp
129:
130: /* Clear our BSS segment. */
131: movl $EXT(edata),%edi
132: movl $EXT(end),%ecx
133: subw %di,%cx
134: xorb %al,%al
135: cld
136: rep
137: stosb
138:
139: /* Find the size of the environment array (si)
140: and the number of environment variables plus one (bx).
141: The PSP segment is still in dx. */
142: movw %dx,%ds
143: movw 0x2c,%ds
144: xorw %si,%si
145: 1: lodsb
146: orb %al,%al
147: jnz 1b
148: lodsb
149: orb %al,%al
150: jnz 1b
151:
152: /* Allocate space for the environment array on the stack.
153: Also make sure the top 16 bits of ESP are cleared,
154: and that the stack pointer is longword aligned. */
155: subw %si,%sp
156: andl $0x0000fffc,%esp
157:
158: /* Copy the environment array to the local stack.
159: We present it backwards, but big deal - shouldn't matter. */
160: xorl %edi,%edi
161: movw %sp,%di
162: xorl %esi,%esi
163: pushl %esi
164: jmp 3f
165: 2: pushl %edi
166: stosb
167: 1: lodsb
168: stosb
169: orb %al,%al
170: jnz 1b
171: 3: lodsb
172: orb %al,%al
173: jnz 2b
174: movl %esp,%cs:EXT(environ)
175:
176: /* Copy the program name to the local stack;
177: it will be used as argv[0]. */
178: lodsw
179: movw %si,%bx
180: 1: pushw $0
181: lodsb
182: orb %al,%al
183: jz 2f
184: lodsb
185: orb %al,%al
186: jnz 1b
187: 2: movw %bx,%si
188: movw %sp,%di
189: 3: lodsb
190: stosb
191: orb %al,%al
192: jnz 3b
193: movl %esp,%ebp
194:
195: /* Build argv[1..n] from the command tail in the PSP.
196: Count the arguments in ebx. */
197: movw %dx,%ds
198: xorl %ecx,%ecx
199: xorl %ebx,%ebx
200: movb 0x80,%cl /* get size of command tail */
201: incw %cx /* plus the return character */
202: movw $0x80,%si
203: addw %cx,%si /* si = ptr to return character */
204: movw %sp,%di
205: decw %di
206: subw %cx,%sp /* allocate space on the stack */
207: andw $0xfffc,%sp
208: pushl %ebx
209: std
210: 1: xorb %al,%al /* store a null terminator for this arg */
211: stosb
212: incl %ebx
213: 2: cmpw $0x80,%si
214: je 5f
215: lodsb /* scan backwards for the end of an arg */
216: cmpb $0x20,%al
217: jbe 2b
218: 3: stosb /* copy the arg */
219: cmpw $0x80,%si
220: je 4f
221: lodsb
222: cmpb $0x20,%al
223: ja 3b
224: 4: movw %di,%cx /* push an arg pointer */
225: incw %cx
226: pushl %ecx
227: jmp 1b
228: 5:
229:
230: /* Push the argv[0] pointer. */
231: pushl %ebp
232:
233: /* Push the argument and envirnonment parameters on the stack. */
234: movl %esp,%eax
235: pushl %cs:EXT(environ)
236: pushl %eax
237: pushl %ebx
238:
239: /* Release all conventional memory above the top of our BSS.
240: The PSP segment is still in dx. */
241: movl $EXT(end)+15,%ebx
242: shrw $4,%bx
243: movw %cs,%ax
244: addw %ax,%bx
245: subw %dx,%bx
246: movw %dx,%es
247: movb $0x4a,%ah
248: int $0x21
249:
250: /* Load the normal data segment registers. */
251: movw %cs,%ax
252: movw %ax,%ds
253: movw %ax,%es
254:
255: /* GCC wants the direction flag cleared at all times. */
256: cld
257:
258: /* Initialize the bss and run the program. */
259: call EXT(i16_main)
260:
261: .globl EXT(crt0_stack)
262: .comm EXT(crt0_stack),CRT0_STACK_SIZE
263:
264: .globl EXT(environ)
265: .comm EXT(environ),4
266:
267:
268: .data
269:
270: .section .anno,"aw",@progbits
271: P2ALIGN(4)
272: .globl __ANNO_START__
273: __ANNO_START__:
274:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.