|
|
1.1 root 1: /* netboot
2: *
3: * start.s,v
4: # Revision 1.1 1993/07/08 16:04:11 brezak
5: # Diskless boot prom code from Jim McKim ([email protected])
6: #
7: * Revision 1.3 1993/06/30 20:19:14 mckim
8: * Exit to BIOS support added.
9: *
10: * Revision 1.2 1993/05/28 20:01:30 mckim
11: * Fixed various StartProg() problems.
12: *
13: * Revision 1.1.1.1 1993/05/28 11:41:08 mckim
14: * Initial version.
15: *
16: */
17:
18: #include "asm.h"
19:
20: /* At entry, the processor is in 16 bit real mode and the code is being
21: * executed from an address it was not linked to. Code must be pic and
22: * 32 bit sensitive until things are fixed up.
23: */
24:
25: .word 0xaa55 /* bios extension signature */
26: .byte 0 /* no. of 512B blocks */
27: jmp 1f /* enter from bios here */
28: .byte 0 /* checksum */
29: 1:
30: cli
31: # save the bios return address in these registers until protected
32: # mode %ds is set up
33: # mov (%esp), %edx
34: # mov 2(%esp), %ebp
35: pop %dx /* return offset */
36: pop %ebp /* return segment */
37:
38: /* save stack [, data] context in case we are under dos */
39: mov %esp, %ecx
40: mov %ss, %ax
41: mov %eax, %ebx
42:
43: /* set up a usable stack */
44: .byte 0xb8 /* (mov $0xa000, %ax) */
45: .word 0xa000
46: mov %ax, %ss
47: xor %esp, %esp
48:
49: push %ebp /* return segment */
50: push %dx /* return offset */
51: push %ds
52:
53: #if 0
54: jmp ret16
55: #endif
56:
57:
58: #ifdef CHECK_386
59: # check if 386 or later
60: # from Intel i486 programmer\'s reference manual, section 22.10
61: # Care must be taken with the first few instructions to ensure
62: # operations are compatible with 386 progenitors - no operand
63: # or address size overrides, all operations must be 16 bit.
64: # Real mode not well supported by gas so it looks a bit crufty
65:
66: # TBD - there is little stack space, although the routine below
67: # uses only two bytes; might set up new stack first thing, then
68: # check processor type - would mean carrying sp, ss in two gp
69: # registers for a while. also make alternate provisions for saving
70: # ds: below.
71:
72: pushf
73: pop %ebx
74: .byte 0x81, 0xe3 /* (and 0x0fff, %ebx) */
75: .word 0x0fff
76: push %ebx
77: popf
78: pushf
79: pop %eax
80: .byte 0x25 /* (and 0xf000, %eax) */
81: .word 0xf000
82: .byte 0x3d /* (cmp 0xf000, %eax) */
83: .word 0xf000
84: jz Lwrong_cpu /* \'86 */
85: .byte 0x81, 0xcb /* (or 0xf000, %ebx) */
86: .word 0xf000
87: push %ebx
88: popf
89: pushf
90: pop %eax
91: .byte 0x25 /* (and 0xf000, %eax) */
92: .word 0xf000
93: jnz Lcpu_ok /* else is \'286 */
94:
95: Lwrong_cpu:
96: .byte 0xbb /* (mov bad_cpu_msg, %ebx) */
97: .word bad_cpu_msg
98: .byte 0xe8 /* (call xputs) */
99: .word xputs-.-2
100: lret
101:
102: xputc: /* print byte in %al */
103: data32
104: pusha
105: .byte 0xbb /* (mov $0x1, %ebx) %bh=0, %bl=1 (blue) */
106: .word 0x0001
107: movb $0xe, %ah
108: # sti
109: int $0x10 /* display a byte */
110: # cli
111: data32
112: popa
113: ret
114:
115: xputs: /* print string pointed to by cs:bx */
116: data32
117: pusha
118: 1:
119: cs
120: .byte 0x8a, 0x07 /* (mov (%ebx), %al) */
121: cmpb $0, %al
122: jz 1f
123: push %ebx
124: .byte 0xe8 /* (call xputc) */
125: .word xputc-.-2
126: pop %ebx
127: inc %ebx
128: jmp 1b
129: 1:
130: data32
131: popa
132: ret
133:
134: bad_cpu_msg: .asciz "netboot: cpu cannot execute '386 instructions, net boot not done.\n\r"
135:
136: Lcpu_ok:
137: # at this point it is known this can execute 386 instructions
138: # so operand and address size prefixes are ok
139: #endif /* CHECK_386 */
140:
141: /* copy rom to link addr, prepare for relocation */
142: xor %esi, %esi /* source */
143: opsize
144: mov $0, %edi /* destination */
145: opsize
146: mov $(RELOC)>>4, %eax
147: mov %ax, %es
148: opsize
149: mov $(ROM_SIZE), %ecx /* count */
150: cs
151: rep
152: movsb
153:
154: addrsize
155: cs
156: lgdt gdtarg-RELOC
157:
158: /* turn on protected mode */
159: cli
160: mov %cr0, %eax
161: opsize
162: or $CR0_PE, %eax
163: mov %eax, %cr0
164:
165: /* jump to relocation, flush prefetch queue, and reload %cs */
166: opsize
167: ljmp $KERN_CODE_SEG, $1f
168: 1:
169: /* reload other segment registers */
170: movl $KERN_DATA_SEG, %eax
171: movl %ax, %ds
172: movl %ax, %es
173: movl %ax, %ss
174: movl $0xa0000, %esp
175: call _main
176: call _exit
177:
178: _ExitToBios:
179: .globl _ExitToBios
180: /* set up a dummy stack frame for the second seg change. */
181: mov $(RELOC)>>4, %eax
182: pushw %ax /* real cs */
183: pushw $2f /* real pc */
184:
185: /* Change to use16 mode. */
186: ljmp $BOOT_16_SEG, $1f /* jump to a 16 bit segment */
187: 1:
188: /* clear the PE bit of CR0 */
189: mov %cr0, %eax
190: opsize
191: and $0!CR0_PE, %eax
192: mov %eax, %cr0
193:
194: /* make intersegment jmp to flush the processor pipeline
195: * using the fake stack frame set up earlier
196: * and reload CS register
197: */
198: lret
199: 2:
200: /* we are in real mode now
201: * set up the real mode segment registers : DS, SS, ES
202: */
203: movw %cs, %ax
204: movw %ax, %ds
205: movw %ax, %ss
206: movw %ax, %es
207:
208: ret16: /* temporary label - remove (TBD) */
209: /* now in dumbed down mode, caveats */
210: /* restore old context and return to whatever called us */
211: pop %ds
212: pop %dx
213: pop %ebp
214:
215: mov %ebx, %eax
216: mov %ax, %ss
217: mov %ecx, %esp
218:
219: push %ebp
220: push %dx
221: sti
222: lret
223:
224: #ifdef USE_BIOS
225: _real_to_prot:
226: .global _real_to_prot
227:
228: addrsize
229: cs
230: lgdt gdtarg-RELOC
231: cli
232: mov %cr0, %eax
233: opsize
234: or $CR0_PE, %eax
235: mov %eax, %cr0
236:
237: /* jump to relocation, flush prefetch queue, and reload %cs */
238: opsize
239: ljmp $KERN_CODE_SEG, $1f
240: 1:
241: movl $KERN_DATA_SEG, %eax
242: movl %ax, %ds
243: movl %ax, %es
244: movl %ax, %ss
245:
246: ret
247: #endif
248:
249: #ifdef USE_BIOS
250: _prot_to_real:
251: .global _prot_to_real
252:
253: /* set up a dummy stack frame for the second seg change. */
254: movl $(RELOC), %eax
255: sarl $4, %eax
256: pushw %ax /* real cs */
257: pushw $2f /* real pc */
258:
259: /* Change to use16 mode. */
260: ljmp $BOOT_16_SEG, $1f /* jump to a 16 bit segment */
261: 1:
262: /* clear the PE bit of CR0 */
263: mov %cr0, %eax
264: opsize
265: and $0!CR0_PE, %eax
266: mov %eax, %cr0
267:
268: /* make intersegment jmp to flush the processor pipeline
269: * using the fake stack frame set up earlier
270: * and reload CS register
271: */
272: lret
273: 2:
274: /* we are in real mode now
275: * set up the real mode segment registers : DS, SS, ES
276: */
277: movw %cs, %ax
278: movw %ax, %ds
279: movw %ax, %ss
280: movw %ax, %es
281:
282: opsize
283: ret
284: #endif
285:
286: .align 4
287: gdt:
288: .word 0, 0
289: .byte 0, 0x00, 0x00, 0
290:
291: /* code segment */
292: .word 0xffff, 0
293: .byte 0, 0x9f, 0xcf, 0
294:
295: /* data segment */
296: .word 0xffff, 0
297: .byte 0, 0x93, 0xcf, 0
298:
299: /* 16 bit real mode */
300: .word 0xffff, 0
301: .byte 0, 0x9e, 0x00, 0
302:
303: .align 4
304: gdtarg:
305: .word 0x1f /* limit */
306: .long gdt /* addr */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.