2 Since the SEC is the only program in our emulation we
3 must use a UEFI/PI mechanism to export APIs to other modules.
4 This is the role of the EFI_EMU_THUNK_PROTOCOL.
6 The mUnixThunkTable exists so that a change to EFI_EMU_THUNK_PROTOCOL
7 will cause an error in initializing the array if all the member functions
8 are not added. It looks like adding a element to end and not initializing
9 it may cause the table to be initaliized with the members at the end being
10 set to zero. This is bad as jumping to zero will crash.
12 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
13 Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 #define DebugAssert _Mangle__DebugAssert
30 #include <CoreServices/CoreServices.h>
31 #include <mach/mach.h>
32 #include <mach/mach_time.h>
37 int settimer_initialized
;
38 struct timeval settimer_timeval
;
39 void (*settimer_callback
)(UINT64 delta
);
41 BOOLEAN gEmulatorInterruptEnabled
= FALSE
;
47 IN UINTN NumberOfBytes
52 Return
= write (STDERR_FILENO
, (const void *)Buffer
, (size_t)NumberOfBytes
);
54 return (Return
== -1) ? 0 : Return
;
66 // Need to turn off line buffering, ECHO, and make it unbuffered.
68 tcgetattr (STDIN_FILENO
, &tty
);
69 tty
.c_lflag
&= ~(ICANON
| ECHO
);
70 tcsetattr (STDIN_FILENO
, TCSANOW
, &tty
);
72 // setvbuf (STDIN_FILENO, NULL, _IONBF, 0);
74 // now ioctl FIONREAD will do what we need
81 IN UINTN NumberOfBytes
86 Return
= write (STDOUT_FILENO
, (const void *)Buffer
, (size_t)NumberOfBytes
);
88 return (Return
== -1) ? 0 : Return
;
94 IN UINTN NumberOfBytes
99 Return
= read (STDIN_FILENO
, Buffer
, (size_t)NumberOfBytes
);
101 return (Return
== -1) ? 0 : Return
;
112 Result
= ioctl (STDIN_FILENO
, FIONREAD
, &Bytes
);
117 return (BOOLEAN
)(Bytes
> 0);
123 settimer_handler (int sig
)
125 struct timeval timeval
;
128 gettimeofday (&timeval
, NULL
);
129 delta
= ((UINT64
)timeval
.tv_sec
* 1000) + (timeval
.tv_usec
/ 1000)
130 - ((UINT64
)settimer_timeval
.tv_sec
* 1000)
131 - (settimer_timeval
.tv_usec
/ 1000);
132 settimer_timeval
= timeval
;
134 if (settimer_callback
) {
135 ReverseGasketUint64 (settimer_callback
, delta
);
142 IN EMU_SET_TIMER_CALLBACK CallBack
145 struct itimerval timerval
;
148 if (!settimer_initialized
) {
149 struct sigaction act
;
151 settimer_initialized
= 1;
152 act
.sa_handler
= settimer_handler
;
154 sigemptyset (&act
.sa_mask
);
155 gEmulatorInterruptEnabled
= TRUE
;
156 if (sigaction (SIGALRM
, &act
, NULL
) != 0) {
157 printf ("SetTimer: sigaction error %s\n", strerror (errno
));
159 if (gettimeofday (&settimer_timeval
, NULL
) != 0) {
160 printf ("SetTimer: gettimeofday error %s\n", strerror (errno
));
163 timerval
.it_value
.tv_sec
= DivU64x32(PeriodMs
, 1000);
164 DivU64x32Remainder(PeriodMs
, 1000, &remainder
);
165 timerval
.it_value
.tv_usec
= remainder
* 1000;
166 timerval
.it_value
.tv_sec
= DivU64x32(PeriodMs
, 1000);
167 timerval
.it_interval
= timerval
.it_value
;
169 if (setitimer (ITIMER_REAL
, &timerval
, NULL
) != 0) {
170 printf ("SetTimer: setitimer error %s\n", strerror (errno
));
172 settimer_callback
= CallBack
;
183 gEmulatorInterruptEnabled
= TRUE
;
184 // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
185 // by enabling/disabling SIGALRM.
186 sigemptyset (&sigset
);
187 sigaddset (&sigset
, SIGALRM
);
188 pthread_sigmask (SIG_UNBLOCK
, &sigset
, NULL
);
193 SecDisableInterrupt (
199 // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
200 // by enabling/disabling SIGALRM.
201 sigemptyset (&sigset
);
202 sigaddset (&sigset
, SIGALRM
);
203 pthread_sigmask (SIG_BLOCK
, &sigset
, NULL
);
204 gEmulatorInterruptEnabled
= FALSE
;
209 SecInterruptEanbled (void)
211 return gEmulatorInterruptEnabled
;
216 QueryPerformanceFrequency (
220 // Hard code to nanoseconds
221 return 1000000000ULL;
225 QueryPerformanceCounter (
231 Nanoseconds elapsedNano
;
233 Start
= mach_absolute_time ();
235 // Convert to nanoseconds.
237 // Have to do some pointer fun because AbsoluteToNanoseconds
238 // works in terms of UnsignedWide, which is a structure rather
239 // than a proper 64-bit integer.
240 elapsedNano
= AbsoluteToNanoseconds (*(AbsoluteTime
*) &Start
);
242 return *(uint64_t *) &elapsedNano
;
244 // Need to figure out what to do for Linux?
253 IN UINT64 Milliseconds
256 struct timespec rq
, rm
;
257 struct timeval start
, end
;
258 unsigned long MicroSec
;
260 rq
.tv_sec
= Milliseconds
/ 1000;
261 rq
.tv_nsec
= (Milliseconds
% 1000) * 1000000;
264 // nanosleep gets interrupted by our timer tic.
265 // we need to track wall clock time or we will stall for way too long
267 gettimeofday (&start
, NULL
);
268 end
.tv_sec
= start
.tv_sec
+ rq
.tv_sec
;
269 MicroSec
= (start
.tv_usec
+ rq
.tv_nsec
/1000);
270 end
.tv_usec
= MicroSec
% 1000000;
271 if (MicroSec
> 1000000) {
275 while (nanosleep (&rq
, &rm
) == -1) {
276 if (errno
!= EINTR
) {
279 gettimeofday (&start
, NULL
);
280 if (start
.tv_sec
> end
.tv_sec
) {
282 } if ((start
.tv_sec
== end
.tv_sec
) && (start
.tv_usec
> end
.tv_usec
)) {
301 OUT EFI_TIME_CAPABILITIES
*Capabilities OPTIONAL
310 Time
->Year
= 1900 + tm
->tm_year
;
311 Time
->Month
= tm
->tm_mon
+ 1;
312 Time
->Day
= tm
->tm_mday
;
313 Time
->Hour
= tm
->tm_hour
;
314 Time
->Minute
= tm
->tm_min
;
315 Time
->Second
= tm
->tm_sec
;
316 Time
->Nanosecond
= 0;
317 Time
->TimeZone
= timezone
;
318 Time
->Daylight
= (daylight
? EFI_TIME_ADJUST_DAYLIGHT
: 0)
319 | (tm
->tm_isdst
> 0 ? EFI_TIME_IN_DAYLIGHT
: 0);
321 if (Capabilities
!= NULL
) {
322 Capabilities
->Resolution
= 1;
323 Capabilities
->Accuracy
= 50000000;
324 Capabilities
->SetsToZero
= FALSE
;
335 // Don't change the time on the system
336 // We could save delta to localtime() and have SecGetTime adjust return values?
343 IN BOOLEAN EmuBusDriver
,
344 OUT EMU_IO_THUNK_PROTOCOL
**Instance OPTIONAL
347 return GetNextThunkProtocol (EmuBusDriver
, Instance
);
351 EMU_THUNK_PROTOCOL gEmuThunkProtocol
= {
352 GasketSecWriteStdErr
,
353 GasketSecConfigStdIn
,
354 GasketSecWriteStdOut
,
357 GasketSecPeCoffGetEntryPoint
,
358 GasketSecPeCoffRelocateImageExtraAction
,
359 GasketSecPeCoffUnloadImageExtraAction
,
360 GasketSecEnableInterrupt
,
361 GasketSecDisableInterrupt
,
362 GasketQueryPerformanceFrequency
,
363 GasketQueryPerformanceCounter
,
369 GasketSecGetNextProtocol
374 SecInitThunkProtocol (
378 // timezone and daylight lib globals depend on tzset be called 1st.