]> git.saurik.com Git - apple/boot.git/blob - i386/libsaio/asm.s
382eed0fdf88d373002c577c25b583ef4ae34899
[apple/boot.git] / i386 / libsaio / asm.s
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Mach Operating System
26 * Copyright (c) 1990 Carnegie-Mellon University
27 * Copyright (c) 1989 Carnegie-Mellon University
28 * All rights reserved. The CMU software License Agreement specifies
29 * the terms and conditions for use and redistribution.
30 */
31 /*
32 * HISTORY
33 * $Log: asm.s,v $
34 * Revision 1.5 2002/11/05 20:34:26 jliu
35 * Integrating:
36 * 3051234 boot shouldnt require Graphics = Yes
37 * 3091627 Need support for refresh rate adjustment
38 *
39 * Revision 1.4 2002/10/02 00:06:18 curtisg
40 * Integrating PR-3032510.
41 *
42 * Revision 1.3.6.1 2002/08/30 21:16:29 curtisg
43 * KERNBOOTSTRUCT is going away in favor of KernelBootArgs_t in <pexpert/i386/boot.h>.
44 *
45 * Revision 1.3 2002/07/09 14:06:21 jliu
46 * Merging changes from PR-2954224 branch in boot/i386.
47 *
48 * Revision 1.2.30.1 2002/07/05 16:24:51 jliu
49 * Merged UFS/HFS/HFS+ filesystem support from BootX.
50 * Moved boot2 load address due to increased size. boot0/boot1 also changed.
51 * Updated boot graphics and CLUT.
52 * Added support to chain load foreign booters.
53 * Fixed param passing bug in network loader.
54 * Misc cleanup in libsaio.
55 *
56 * Revision 1.2 2000/05/23 23:01:11 lindak
57 * Merged PR-2309530 into Kodiak (liu i386 booter: does not support label-less
58 * ufs partitions)
59 *
60 * Revision 1.1.1.2.4.1 2000/05/13 17:07:39 jliu
61 * New boot0 (boot1 has been deprecated). Booter must now reside in its own partition, no disk label required.
62 *
63 * Revision 1.1.1.2 1999/08/04 21:16:57 wsanchez
64 * Impoort of boot-66
65 *
66 * Revision 1.3 1999/08/04 21:12:12 wsanchez
67 * Update APSL
68 *
69 * Revision 1.2 1999/03/25 05:48:30 wsanchez
70 * Add APL.
71 * Remove unused gzip code.
72 * Remove unused Adobe fonts.
73 *
74 * Revision 1.1.1.1.66.2 1999/03/16 16:08:54 wsanchez
75 * Substitute License
76 *
77 * Revision 1.1.1.1.66.1 1999/03/16 07:33:21 wsanchez
78 * Add APL
79 *
80 * Revision 1.1.1.1 1997/12/05 21:57:57 wsanchez
81 * Import of boot-25 (~mwatson)
82 *
83 * Revision 2.1.1.2 90//03//22 17:59:50 rvb
84 * Added _sp() => where is the stack at. [kupfer]
85 *
86 * Revision 2.1.1.1 90//02//09 17:25:04 rvb
87 * Add Intel copyright
88 * [90//02//09 rvb]
89 *
90 */
91
92
93 // INTEL CORPORATION PROPRIETARY INFORMATION
94 //
95 // This software is supplied under the terms of a license agreement or
96 // nondisclosure agreement with Intel Corporation and may not be copied
97 // nor disclosed except in accordance with the terms of that agreement.
98 //
99 // Copyright 1988 Intel Corporation
100 // Copyright 1988, 1989 by Intel Corporation
101 //
102
103 #include <architecture/i386/asm_help.h>
104 #include "memory.h"
105
106 #define data32 .byte 0x66
107 #define addr32 .byte 0x67
108
109 .file "asm.s"
110
111 CR0_PE_ON = 0x1
112 CR0_PE_OFF = 0x7ffffff0
113
114 STACK32_BASE = ADDR32(STACK_SEG, 0)
115 STACK16_SEG = STACK_SEG
116 CODE32_BASE = ADDR32(BASE_SEG, 0)
117 CODE16_SEG = BASE_SEG
118
119 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
120 // Pointer to 6-bytes in memory that contains the base address and the limit
121 // (size of GDT table in bytes) of the GDT. The LGDT is the only instruction
122 // that directly loads a linear address (not a segment relative address) and
123 // a limit in protected mode.
124
125 .globl _Gdtr
126 .data
127 .align 2, 0x90
128 _Gdtr:
129 .word GDTLIMIT
130 .long vtop(_Gdt)
131
132 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
133 // Data area for __switch_stack.
134 //
135 save_sp: .long STACK_OFS
136 save_ss: .long STACK_SEG
137
138 .text
139
140 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
141 // real_to_prot()
142 //
143 // Transfer from real mode to protected mode.
144 // Preserves all registers except EAX.
145 //
146 LABEL(__real_to_prot)
147
148 // Interrupts are disabled in protected mode.
149
150 cli
151
152 // Load the Global Descriptor Table Register (GDTR).
153
154 addr32
155 data32
156 lgdt OFFSET16(_Gdtr)
157
158 // Enter protected mode by setting the PE bit in CR0.
159
160 mov %cr0, %eax
161 data32
162 or $CR0_PE_ON, %eax
163 mov %eax, %cr0
164
165 // Make intrasegment jump to flush the processor pipeline and
166 // reload CS register.
167
168 data32
169 ljmp $0x08, $xprot
170
171 xprot:
172 // we are in USE32 mode now
173 // set up the protected mode segment registers : DS, SS, ES, FS, GS
174
175 mov $0x10, %eax
176 movw %ax, %ds
177 movw %ax, %ss
178 movw %ax, %es
179 movw %ax, %fs
180 movw %ax, %gs
181
182 // Convert STACK_SEG:SP to 32-bit linear stack pointer.
183
184 movzwl %sp, %eax
185 addl $STACK32_BASE, %eax
186 movl %eax, %esp
187
188 // Convert STACK_SEG:BP to 32-bit linear base pointer.
189
190 movzwl %bp, %eax
191 addl $STACK32_BASE, %eax
192 movl %eax, %ebp
193
194 // Modify the caller's return address on the stack from
195 // segment offset to linear address.
196
197 popl %eax
198 addl $CODE32_BASE, %eax
199 pushl %eax
200
201 ret
202
203 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
204 // prot_to_real()
205 //
206 // Transfer from protected mode to real mode.
207 // Preserves all registers except EAX.
208 //
209 LABEL(__prot_to_real)
210
211 // Set up segment registers appropriate for real mode.
212
213 movw $0x30, %ax
214 movw %ax, %ds
215 movw %ax, %es
216 movw %ax, %fs
217 movw %ax, %gs
218 movw %ax, %ss
219
220 ljmp $0x18, $x16 // change to USE16 mode
221
222 x16:
223 mov %cr0, %eax // clear the PE bit of CR0
224 data32
225 and $CR0_PE_OFF, %eax
226 mov %eax, %cr0
227
228 // make intersegment jmp to flush the processor pipeline
229 // and reload CS register
230
231 data32
232 ljmp $CODE16_SEG, $xreal - CODE32_BASE
233
234 xreal:
235 // we are in real mode now
236 // set up the real mode segment registers : DS, DS, ES, FS, GS
237
238 movw %cs, %ax
239 movw %ax, %ds
240 movw %ax, %es
241 movw %ax, %fs
242 movw %ax, %gs
243
244 // load stack segment register SS.
245
246 data32
247 movl $STACK16_SEG, %eax
248 movw %ax, %ss
249
250 // clear top 16-bits of ESP and EBP.
251
252 data32
253 movzwl %sp, %esp
254 data32
255 movzwl %bp, %ebp
256
257 // Modify caller's return address on the stack
258 // from linear address to segment offset.
259
260 data32
261 popl %eax
262 data32
263 movzwl %ax, %eax
264 data32
265 pushl %eax
266
267 // Reenable maskable interrupts.
268
269 sti
270
271 data32
272 ret
273
274 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
275 // halt()
276 //
277 LABEL(_halt)
278 hlt
279 jmp _halt
280
281 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282 // startprog(phyaddr, arg)
283 // Start the program on protected mode where phyaddr is the entry point.
284 // Passes arg to the program in %eax.
285 //
286 LABEL(_startprog)
287 push %ebp
288 mov %esp, %ebp
289
290 mov 0xc(%ebp), %eax // argument to program
291 mov 0x8(%ebp), %ecx // entry offset
292 mov $0x28, %ebx // segment
293 push %ebx
294 push %ecx
295
296 // set up %ds and %es
297
298 mov $0x20, %ebx
299 movw %bx, %ds
300 movw %bx, %es
301
302 lret
303
304 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
305 // Returns the current stack pointer.
306 //
307 LABEL(__sp)
308 mov %esp, %eax
309 ret
310
311 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
312 // Returns the current frame pointer.
313 //
314 LABEL(__bp)
315 mov %ebp, %eax
316 ret
317
318 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
319 // switch_stack()
320 //
321 // Switches stack pointer between SS:SP and memory save_ss:save_sp.
322 // Call this function from real mode only!!!
323 //
324 // AX, DI, and SI are clobbered.
325 //
326 LABEL(__switch_stack)
327 popl %eax # save return address
328 popl %edi # discard upper 16-bit
329
330 data32
331 addr32
332 movl OFFSET16(save_ss), %esi # new SS to SI
333
334 data32
335 addr32
336 movl OFFSET16(save_sp), %edi # new SP to DI
337
338 addr32
339 mov %ss, OFFSET16(save_ss) # save current SS to memory
340
341 data32
342 addr32
343 movl %esp, OFFSET16(save_sp) # save current SP to memory
344
345 cli
346 mov %si, %ss # switch stack
347 mov %di, %sp
348 sti
349
350 pushl %eax # push IP of caller onto the new stack
351
352 xorl %eax, %eax
353 xorl %esi, %esi
354 xorl %edi, %edi
355
356 ret
357
358 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
359 // loader()
360 //
361 // Issue a request to the network loader.
362 //
363 LABEL(_loader)
364 enter $0, $0
365 pushal
366
367 #
368 # Pass a far pointer to the command structure
369 # to the INT call through DX:CX.
370 #
371 # The command code is in BX.
372 #
373
374 movw 8(%ebp), %bx # 8[EBP] = command code
375 movw 12(%ebp), %cx # 12[EBP] = command structure offset
376 movw 14(%ebp), %dx # 14[EBP] = command structure segment
377
378 call __prot_to_real # Revert to real mode
379
380 ###### Real Mode Begin ######
381
382 data32
383 call __switch_stack # Switch to NBP stack
384
385 int $0x2b # Call NBP
386
387 data32
388 call __switch_stack # Restore stack
389
390 data32
391 call __real_to_prot # Back to protected mode
392
393 ###### Real Mode End ######
394
395 popal
396 leave
397 ret
398
399 #if 0
400 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
401 // pcpy(src, dst, cnt)
402 // where src is a virtual address and dst is a physical address
403 //
404 LABEL(_pcpy)
405 push %ebp
406 mov %esp, %ebp
407 push %es
408 push %esi
409 push %edi
410 push %ecx
411
412 cld
413
414 // set %es to point at the flat segment
415
416 mov $0x20, %eax
417 movw %ax , %es
418
419 mov 0x8(%ebp), %esi // source
420 mov 0xc(%ebp), %edi // destination
421 mov 0x10(%ebp), %ecx // count
422
423 rep
424 movsb
425
426 pop %ecx
427 pop %edi
428 pop %esi
429 pop %es
430 pop %ebp
431
432 ret
433 #endif