2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1990 Carnegie-Mellon University
28 * Copyright (c) 1989 Carnegie-Mellon University
29 * All rights reserved. The CMU software License Agreement specifies
30 * the terms and conditions for use and redistribution.
35 * Revision 1.5 2002/11/05 20:34:26 jliu
37 * 3051234 boot shouldnt require Graphics = Yes
38 * 3091627 Need support for refresh rate adjustment
40 * Revision 1.4 2002/10/02 00:06:18 curtisg
41 * Integrating PR-3032510.
43 * Revision 1.3.6.1 2002/08/30 21:16:29 curtisg
44 * KERNBOOTSTRUCT is going away in favor of KernelBootArgs_t in <pexpert/i386/boot.h>.
46 * Revision 1.3 2002/07/09 14:06:21 jliu
47 * Merging changes from PR-2954224 branch in boot/i386.
49 * Revision 1.2.30.1 2002/07/05 16:24:51 jliu
50 * Merged UFS/HFS/HFS+ filesystem support from BootX.
51 * Moved boot2 load address due to increased size. boot0/boot1 also changed.
52 * Updated boot graphics and CLUT.
53 * Added support to chain load foreign booters.
54 * Fixed param passing bug in network loader.
55 * Misc cleanup in libsaio.
57 * Revision 1.2 2000/05/23 23:01:11 lindak
58 * Merged PR-2309530 into Kodiak (liu i386 booter: does not support label-less
61 * Revision 1.1.1.2.4.1 2000/05/13 17:07:39 jliu
62 * New boot0 (boot1 has been deprecated). Booter must now reside in its own partition, no disk label required.
64 * Revision 1.1.1.2 1999/08/04 21:16:57 wsanchez
67 * Revision 1.3 1999/08/04 21:12:12 wsanchez
70 * Revision 1.2 1999/03/25 05:48:30 wsanchez
72 * Remove unused gzip code.
73 * Remove unused Adobe fonts.
75 * Revision 1.1.1.1.66.2 1999/03/16 16:08:54 wsanchez
78 * Revision 1.1.1.1.66.1 1999/03/16 07:33:21 wsanchez
81 * Revision 1.1.1.1 1997/12/05 21:57:57 wsanchez
82 * Import of boot-25 (~mwatson)
84 * Revision 2.1.1.2 90//03//22 17:59:50 rvb
85 * Added _sp() => where is the stack at. [kupfer]
87 * Revision 2.1.1.1 90//02//09 17:25:04 rvb
94 // INTEL CORPORATION PROPRIETARY INFORMATION
96 // This software is supplied under the terms of a license agreement or
97 // nondisclosure agreement with Intel Corporation and may not be copied
98 // nor disclosed except in accordance with the terms of that agreement.
100 // Copyright 1988 Intel Corporation
101 // Copyright 1988, 1989 by Intel Corporation
104 #include <architecture/i386/asm_help.h>
107 #define data32 .byte 0x66
108 #define addr32 .byte 0x67
113 CR0_PE_OFF = 0x7ffffff0
115 STACK32_BASE = ADDR32(STACK_SEG, 0)
116 STACK16_SEG = STACK_SEG
117 CODE32_BASE = ADDR32(BASE_SEG, 0)
118 CODE16_SEG = BASE_SEG
120 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121 // Pointer to 6-bytes in memory that contains the base address and the limit
122 // (size of GDT table in bytes) of the GDT. The LGDT is the only instruction
123 // that directly loads a linear address (not a segment relative address) and
124 // a limit in protected mode.
133 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134 // Data area for __switch_stack.
136 save_sp: .long STACK_OFS
137 save_ss: .long STACK_SEG
141 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
144 // Transfer from real mode to protected mode.
145 // Preserves all registers except EAX.
147 LABEL(__real_to_prot)
149 // Interrupts are disabled in protected mode.
153 // Load the Global Descriptor Table Register (GDTR).
159 // Enter protected mode by setting the PE bit in CR0.
166 // Make intrasegment jump to flush the processor pipeline and
167 // reload CS register.
173 // we are in USE32 mode now
174 // set up the protected mode segment registers : DS, SS, ES, FS, GS
183 // Convert STACK_SEG:SP to 32-bit linear stack pointer.
186 addl $STACK32_BASE, %eax
189 // Convert STACK_SEG:BP to 32-bit linear base pointer.
192 addl $STACK32_BASE, %eax
195 // Modify the caller's return address on the stack from
196 // segment offset to linear address.
199 addl $CODE32_BASE, %eax
204 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
207 // Transfer from protected mode to real mode.
208 // Preserves all registers except EAX.
210 LABEL(__prot_to_real)
212 // Set up segment registers appropriate for real mode.
221 ljmp $0x18, $x16 // change to USE16 mode
224 mov %cr0, %eax // clear the PE bit of CR0
226 and $CR0_PE_OFF, %eax
229 // make intersegment jmp to flush the processor pipeline
230 // and reload CS register
233 ljmp $CODE16_SEG, $xreal - CODE32_BASE
236 // we are in real mode now
237 // set up the real mode segment registers : DS, DS, ES, FS, GS
245 // load stack segment register SS.
248 movl $STACK16_SEG, %eax
251 // clear top 16-bits of ESP and EBP.
258 // Modify caller's return address on the stack
259 // from linear address to segment offset.
268 // Reenable maskable interrupts.
275 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
283 // startprog(phyaddr, arg)
284 // Start the program on protected mode where phyaddr is the entry point.
285 // Passes arg to the program in %eax.
291 mov 0xc(%ebp), %eax // argument to program
292 mov 0x8(%ebp), %ecx // entry offset
293 mov $0x28, %ebx // segment
297 // set up %ds and %es
305 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
306 // Returns the current stack pointer.
312 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
313 // Returns the current frame pointer.
319 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
322 // Switches stack pointer between SS:SP and memory save_ss:save_sp.
323 // Call this function from real mode only!!!
325 // AX, DI, and SI are clobbered.
327 LABEL(__switch_stack)
328 popl %eax # save return address
329 popl %edi # discard upper 16-bit
333 movl OFFSET16(save_ss), %esi # new SS to SI
337 movl OFFSET16(save_sp), %edi # new SP to DI
340 mov %ss, OFFSET16(save_ss) # save current SS to memory
344 movl %esp, OFFSET16(save_sp) # save current SP to memory
347 mov %si, %ss # switch stack
351 pushl %eax # push IP of caller onto the new stack
359 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
362 // Issue a request to the network loader.
369 # Pass a far pointer to the command structure
370 # to the INT call through DX:CX.
372 # The command code is in BX.
375 movw 8(%ebp), %bx # 8[EBP] = command code
376 movw 12(%ebp), %cx # 12[EBP] = command structure offset
377 movw 14(%ebp), %dx # 14[EBP] = command structure segment
379 call __prot_to_real # Revert to real mode
381 ###### Real Mode Begin ######
384 call __switch_stack # Switch to NBP stack
389 call __switch_stack # Restore stack
392 call __real_to_prot # Back to protected mode
394 ###### Real Mode End ######
401 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
402 // pcpy(src, dst, cnt)
403 // where src is a virtual address and dst is a physical address
415 // set %es to point at the flat segment
420 mov 0x8(%ebp), %esi // source
421 mov 0xc(%ebp), %edi // destination
422 mov 0x10(%ebp), %ecx // count