1/*
2 * Copyright (c) 2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include <i386/asm.h>
30#include <i386/asm64.h>
31
32#include <assym.s>
33
34/*
35 * Copy "count" bytes from "src" to %esp, using
36 * "tmpindex" for a scratch counter and %eax
37 */
38#define COPY_STACK(src, count, tmpindex) \
39	mov	$0, tmpindex	/* initial scratch counter */ ; \
401: \
41	mov	0(src,tmpindex,1), %eax	 /* copy one 32-bit word from source... */ ; \
42	mov	%eax, 0(%esp,tmpindex,1) /* ... to stack */ ; \
43	add	$4, tmpindex		 /* increment counter */ ; \
44	cmp	count, tmpindex		 /* exit it stack has been copied */ ; \
45	jne 1b
46
47/*
48	void
49	pal_efi_call_in_64bit_mode_asm(uint64_t func,
50	                           struct pal_efi_registers *efi_reg,
51	                           void *stack_contents,
52	                           size_t stack_contents_size)
53
54	* Switch from compatibility mode to long mode, and
55	* then execute the function pointer with the specified
56	* register and stack contents (based at %rsp). Afterwards,
57	* collect the return value, restore the original state,
58	* and return.
59*/
60ENTRY(_pal_efi_call_in_64bit_mode_asm)
61	FRAME
62
63	/* save non-volatile registers */
64	push	%ebx
65	push	%esi
66	push	%edi
67
68	sub	$12, %esp	/* align to 16-byte boundary */
69	mov	16(%ebp), %esi	/* load efi_reg into %esi */
70	mov	20(%ebp), %edx	/* load stack_contents into %edx */
71	mov	24(%ebp), %ecx	/* load s_c_s into %ecx */
72	sub	%ecx, %esp	/* make room for stack contents */
73
74	COPY_STACK(%edx, %ecx, %edi)
75
76	ENTER_64BIT_MODE()
77
78	/* load efi_reg into real registers */
79	mov	0(%rsi),  %rcx
80	mov	8(%rsi),  %rdx
81	mov	16(%rsi), %r8
82	mov	24(%rsi), %r9
83	mov	32(%rsi), %rax
84
85	mov	8(%rbp), %rdi		/* load func pointer */
86	call	*%rdi			/* call EFI runtime */
87
88	mov	16(%rbp), %esi		/* load efi_reg into %esi */
89	mov	%rax, 32(%rsi)		/* save RAX back */
90
91	ENTER_COMPAT_MODE()
92
93	add	24(%ebp), %esp	/* discard stack contents */
94	add	$12, %esp	/* restore stack pointer */
95
96	pop	%edi
97	pop	%esi
98	pop	%ebx
99
100	EMARF
101	ret
102
103/*
104	void
105	pal_efi_call_in_32bit_mode_asm(uint32_t func,
106	                           struct pal_efi_registers *efi_reg,
107	                           void *stack_contents,
108	                           size_t stack_contents_size)
109*/
110ENTRY(_pal_efi_call_in_32bit_mode_asm)
111	FRAME
112
113	/* save non-volatile registers */
114	push	%ebx
115	push	%esi
116	push	%edi
117
118	sub	$12, %esp	/* align to 16-byte boundary */
119	mov	12(%ebp), %esi	/* load efi_reg into %esi */
120	mov	16(%ebp), %edx	/* load stack_contents into %edx */
121	mov	20(%ebp), %ecx	/* load s_c_s into %ecx */
122	sub	%ecx, %esp	/* make room for stack contents */
123
124	COPY_STACK(%edx, %ecx, %edi)
125
126	/* load efi_reg into real registers */
127	mov	0(%esi),  %ecx
128	mov	8(%esi),  %edx
129	mov	32(%esi), %eax
130
131	mov	8(%ebp), %edi		/* load func pointer */
132	call	*%edi			/* call EFI runtime */
133
134	mov	12(%ebp), %esi		/* load efi_reg into %esi */
135	mov	%eax, 32(%esi)		/* save RAX back */
136	movl	$0, 36(%esi)		/* zero out high bits of RAX */
137
138	add	20(%ebp), %esp	/* discard stack contents */
139	add	$12, %esp	/* restore stack pointer */
140
141	pop	%edi
142	pop	%esi
143	pop	%ebx
144
145	EMARF
146	ret
147
148
149/* void             _rtc_nanotime_store(uint64_t                tsc,
150	                                uint64_t                nsec,
151	                                uint32_t                scale,
152	                                uint32_t                shift,
153	                                rtc_nanotime_t  *dst) ;
154*/
155
156ENTRY(_pal_rtc_nanotime_store)
157	push		%ebp
158	movl		%esp,%ebp
159	push		%esi
160
161	mov		32(%ebp),%edx				/* get ptr to rtc_nanotime_info */
162
163	movl		RNT_GENERATION(%edx),%esi		/* get current generation */
164	movl		$0,RNT_GENERATION(%edx)			/* flag data as being updated */
165
166	mov		8(%ebp),%eax
167	mov		%eax,RNT_TSC_BASE(%edx)
168	mov		12(%ebp),%eax
169	mov		%eax,RNT_TSC_BASE+4(%edx)
170
171	mov		24(%ebp),%eax
172	mov		%eax,RNT_SCALE(%edx)
173
174	mov		28(%ebp),%eax
175	mov		%eax,RNT_SHIFT(%edx)
176
177	mov		16(%ebp),%eax
178	mov		%eax,RNT_NS_BASE(%edx)
179	mov		20(%ebp),%eax
180	mov		%eax,RNT_NS_BASE+4(%edx)
181
182	incl		%esi					/* next generation */
183	jnz		1f
184	incl		%esi					/* skip 0, which is a flag */
1851:	movl		%esi,RNT_GENERATION(%edx)		/* update generation and make usable */
186
187	pop		%esi
188	pop		%ebp
189
190	ret
191
192
193