/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
+ * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
+ * Source License Version 2.0 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
/*
* HISTORY
* $Log: asm.s,v $
+ * Revision 1.8 2005/06/24 22:47:12 curtisg
+ * Merging changes for 4159531 to pass data to the kernel in EFI format.
+ *
+ * Revision 1.7 2004/05/13 17:58:38 curtisg
+ * Integrating:
+ * <rdar://problem/3094680>: (Silent boot)
+ * <rdar://problem/3363893>: (5 sec boot timeout is too short)
+ * <rdar://problem/3533781>: (Boot option to display graphics modes)
+ * <rdar://problem/3545539>: (Default graphics mode should be 32-bit)
+ * <rdar://problem/3643065>: (Booter should always find a video mode)
+ * <rdar://problem/3643815>: (Booter displays "0MB" VRAM)
+ *
+ * Revision 1.6 2003/11/05 20:51:02 curtisg
+ * Integrated 3069695,3331770,3370488,3371823
+ *
+ * Revision 1.5.26.1 2003/10/27 23:57:59 curtisg
+ * Added printing of volume names, better handling of extended
+ * partitions, and updated Apple license strings.
+ * New chain booter should work better with foreign operating
+ * systems.
+ *
+ * Revision 1.5 2002/11/05 20:34:26 jliu
+ * Integrating:
+ * 3051234 boot shouldnt require Graphics = Yes
+ * 3091627 Need support for refresh rate adjustment
+ *
+ * Revision 1.4 2002/10/02 00:06:18 curtisg
+ * Integrating PR-3032510.
+ *
+ * Revision 1.3.6.1 2002/08/30 21:16:29 curtisg
+ * KERNBOOTSTRUCT is going away in favor of KernelBootArgs_t in <pexpert/i386/boot.h>.
+ *
+ * Revision 1.3 2002/07/09 14:06:21 jliu
+ * Merging changes from PR-2954224 branch in boot/i386.
+ *
+ * Revision 1.2.30.1 2002/07/05 16:24:51 jliu
+ * Merged UFS/HFS/HFS+ filesystem support from BootX.
+ * Moved boot2 load address due to increased size. boot0/boot1 also changed.
+ * Updated boot graphics and CLUT.
+ * Added support to chain load foreign booters.
+ * Fixed param passing bug in network loader.
+ * Misc cleanup in libsaio.
+ *
* Revision 1.2 2000/05/23 23:01:11 lindak
* Merged PR-2309530 into Kodiak (liu i386 booter: does not support label-less
* ufs partitions)
* Import of boot-25 (~mwatson)
*
* Revision 2.1.1.2 90//03//22 17:59:50 rvb
- * Added _sp() => where is the stack at. [kupfer]
+ * Added _sp() => where is the stack at. [kupfer]
*
* Revision 2.1.1.1 90//02//09 17:25:04 rvb
- * Add Intel copyright
- * [90//02//09 rvb]
+ * Add Intel copyright
+ * [90//02//09 rvb]
*
*/
.file "asm.s"
-BOOTSEG = BASE_SEG
+CR0_PE_ON = 0x1
+CR0_PE_OFF = 0x7ffffff0
+
+STACK32_BASE = ADDR32(STACK_SEG, 0)
+STACK16_SEG = STACK_SEG
+CODE32_BASE = ADDR32(BASE_SEG, 0)
+CODE16_SEG = BASE_SEG
-CR0_PE_ON = 0x1
-CR0_PE_OFF = 0xfffffffe
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Pointer to 6-bytes in memory that contains the base address and the limit
+// (size of GDT table in bytes) of the GDT. The LGDT is the only instruction
+// that directly loads a linear address (not a segment relative address) and
+// a limit in protected mode.
.globl _Gdtr
.data
- .align 2,0x90
+ .align 2, 0x90
_Gdtr:
- .word 0x2F
-// .long _Gdt+4096
+ .word GDTLIMIT
.long vtop(_Gdt)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Data area for __switch_stack.
//
-save_sp: .long STACK_ADDR
-save_ss: .long 0
-
+save_sp: .long STACK_OFS
+save_ss: .long STACK_SEG
.text
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// real_to_prot()
-// transfer from real mode to protected mode.
-// preserves all registers except eax
+//
+// Transfer from real mode to protected mode.
+// Preserves all registers except EAX.
//
LABEL(__real_to_prot)
- // guarantee that interrupt is disabled when in prot mode
+
+ // Interrupts are disabled in protected mode.
+
cli
- addr32 // load the gdtr
+ // Load the Global Descriptor Table Register (GDTR).
+
+ addr32
data32
- lgdt _Gdtr
+ lgdt OFFSET16(_Gdtr)
- // set the PE bit of CR0 to go to protected mode
+ // Enter protected mode by setting the PE bit in CR0.
mov %cr0, %eax
data32
or $CR0_PE_ON, %eax
- mov %eax, %cr0
+ mov %eax, %cr0
- // make intrasegment jump to flush the processor pipeline and
- // reload CS register
+ // Make intrasegment jump to flush the processor pipeline and
+ // reload CS register.
data32
ljmp $0x08, $xprot
xprot:
// we are in USE32 mode now
- // set up the protected mode segment registers : DS, SS, ES
+ // set up the protected mode segment registers : DS, SS, ES, FS, GS
mov $0x10, %eax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ // Convert STACK_SEG:SP to 32-bit linear stack pointer.
- xorl %eax, %eax // clear garbage from upper word of esp
- movw %sp, %ax
+ movzwl %sp, %eax
+ addl $STACK32_BASE, %eax
movl %eax, %esp
+ // Convert STACK_SEG:BP to 32-bit linear base pointer.
+
+ movzwl %bp, %eax
+ addl $STACK32_BASE, %eax
+ movl %eax, %ebp
+
+ // Modify the caller's return address on the stack from
+ // segment offset to linear address.
+
+ popl %eax
+ addl $CODE32_BASE, %eax
+ pushl %eax
+
ret
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// prot_to_real()
-// transfer from protected mode to real mode
-// preserves all registers except eax
+//
+// Transfer from protected mode to real mode.
+// Preserves all registers except EAX.
//
LABEL(__prot_to_real)
+ // Set up segment registers appropriate for real mode.
+
+ movw $0x30, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
ljmp $0x18, $x16 // change to USE16 mode
x16:
// and reload CS register
data32
- ljmp $BOOTSEG, $xreal
+ ljmp $CODE16_SEG, $xreal - CODE32_BASE
xreal:
// we are in real mode now
- // set up the real mode segment registers : DS, SS, ES
+ // set up the real mode segment registers : DS, DS, ES, FS, GS
movw %cs, %ax
movw %ax, %ds
- movw %ax, %ss
movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ // load stack segment register SS.
data32
- ret
+ movl $STACK16_SEG, %eax
+ movw %ax, %ss
-#if defined(DEFINE_INLINE_FUNCTIONS)
+ // clear top 16-bits of ESP and EBP.
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// outb(port, byte)
-//
-LABEL(_outb)
- push %ebp
- mov %esp, %ebp
- push %edx
+ data32
+ movzwl %sp, %esp
+ data32
+ movzwl %bp, %ebp
- movw 8(%ebp), %dx
- movb 12(%ebp), %al
- outb %al, %dx
+ // Modify caller's return address on the stack
+ // from linear address to segment offset.
- pop %edx
- pop %ebp
- ret
+ data32
+ popl %eax
+ data32
+ movzwl %ax, %eax
+ data32
+ pushl %eax
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// inb(port)
-//
-LABEL(_inb)
- push %ebp
- mov %esp, %ebp
- push %edx
+ // Reenable maskable interrupts.
- movw 8(%ebp), %dx
- subw %ax, %ax
- inb %dx, %al
+ sti
- pop %edx
- pop %ebp
+ data32
ret
-#endif /* DEFINE_INLINE_FUNCTIONS */
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// halt()
//
LABEL(_halt)
-// call _getchar
- hlt
+ call _bgetc
jmp _halt
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// startprog(phyaddr)
-// Start the program on protected mode where phyaddr is the entry point
+// startprog(phyaddr, arg)
+// Start the program on protected mode where phyaddr is the entry point.
+// Passes arg to the program in %eax.
//
LABEL(_startprog)
push %ebp
mov %esp, %ebp
- mov 0x8(%ebp), %ecx // entry offset
- mov $0x28, %ebx // segment
+ mov 0xc(%ebp), %eax // argument to program
+ mov 0x8(%ebp), %ecx // entry offset
+ mov $0x28, %ebx // segment
push %ebx
push %ecx
ret
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-// Returns the current stack pointer.
+// Returns the current frame pointer.
//
LABEL(__bp)
mov %ebp, %eax
ret
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Switch stack.
-# Switches between registers SS:SP and memory save_ss:save_sp.
-# Call this function from real mode only!!!
-#
-# AX, DI, and SI are modified.
-#
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// switch_stack()
+//
+// Switches stack pointer between SS:SP and memory save_ss:save_sp.
+// Call this function from real mode only!!!
+//
+// AX, DI, and SI are clobbered.
+//
LABEL(__switch_stack)
- popl %eax # save return address
- popl %edi # discard upper 16-bit
-
- data32
- addr32
- movl save_ss, %esi # copy new SS to ESI
-
- data32
- addr32
- movl save_sp, %edi # copy new SP to EDI
-
- addr32
- mov %ss, save_ss # save current SS
-
- data32
- addr32
- movl %esp, save_sp # Save current SP
-
- cli
- mov %si, %ss # Perform stack switch
- mov %di, %sp
- sti
-
- pushl %eax # push IP of caller onto the new stack
-
- xorl %eax, %eax
- xorl %esi, %esi
- xorl %edi, %edi
-
- ret
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Issue a request to the network loader.
-#
+ popl %eax # save return address
+ popl %edi # discard upper 16-bit
+
+ data32
+ addr32
+ movl OFFSET16(save_ss), %esi # new SS to SI
+
+ data32
+ addr32
+ movl OFFSET16(save_sp), %edi # new SP to DI
+
+ addr32
+ mov %ss, OFFSET16(save_ss) # save current SS to memory
+
+ data32
+ addr32
+ movl %esp, OFFSET16(save_sp) # save current SP to memory
+
+ cli
+ mov %si, %ss # switch stack
+ mov %di, %sp
+ sti
+
+ pushl %eax # push IP of caller onto the new stack
+
+ xorl %eax, %eax
+ xorl %esi, %esi
+ xorl %edi, %edi
+
+ ret
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// loader()
+//
+// Issue a request to the network loader.
+//
LABEL(_loader)
- enter $0, $0
- pushal
+ enter $0, $0
+ pushal
- #
- # Pass a far pointer to the command structure
- # to the INT call through DI:CX.
- #
- # The command code is in BX.
- #
+ #
+ # Pass a far pointer to the command structure
+ # to the INT call through DX:CX.
+ #
+ # The command code is in BX.
+ #
- movw 8(%ebp), %bx # 8[EBP] = command code
- movw 12(%ebp), %cx # 12[EBP] = command structure offset
- movw 14(%ebp), %di # 14[EBP] = command structure segment
+ movw 8(%ebp), %bx # 8[EBP] = command code
+ movw 12(%ebp), %cx # 12[EBP] = command structure offset
+ movw 14(%ebp), %dx # 14[EBP] = command structure segment
- call __prot_to_real # Revert to real mode
+ call __prot_to_real # Revert to real mode
- ###### Real Mode Begin ######
+ ###### Real Mode Begin ######
- data32
- call __switch_stack # Switch to NBP stack
+ data32
+ call __switch_stack # Switch to NBP stack
- int $0x2b # Call NBP
+ int $0x2b # Call NBP
- data32
- call __switch_stack # Restore stack
+ data32
+ call __switch_stack # Restore stack
- data32
- call __real_to_prot # Back to protected mode
-
- ###### Real Mode End ######
-
- popal
- leave
- ret
+ data32
+ call __real_to_prot # Back to protected mode
+
+ ###### Real Mode End ######
+
+ popal
+ leave
+ ret
-#if 0
+#if UNUSED
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// pcpy(src, dst, cnt)
// where src is a virtual address and dst is a physical address