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);
126 return malloc ((size_t)Size
);
140 settimer_handler (int sig
)
142 struct timeval timeval
;
145 gettimeofday (&timeval
, NULL
);
146 delta
= ((UINT64
)timeval
.tv_sec
* 1000) + (timeval
.tv_usec
/ 1000)
147 - ((UINT64
)settimer_timeval
.tv_sec
* 1000)
148 - (settimer_timeval
.tv_usec
/ 1000);
149 settimer_timeval
= timeval
;
151 if (settimer_callback
) {
152 ReverseGasketUint64 (settimer_callback
, delta
);
159 IN EMU_SET_TIMER_CALLBACK CallBack
162 struct itimerval timerval
;
165 if (!settimer_initialized
) {
166 struct sigaction act
;
168 settimer_initialized
= 1;
169 act
.sa_handler
= settimer_handler
;
171 sigemptyset (&act
.sa_mask
);
172 gEmulatorInterruptEnabled
= TRUE
;
173 if (sigaction (SIGALRM
, &act
, NULL
) != 0) {
174 printf ("SetTimer: sigaction error %s\n", strerror (errno
));
176 if (gettimeofday (&settimer_timeval
, NULL
) != 0) {
177 printf ("SetTimer: gettimeofday error %s\n", strerror (errno
));
180 timerval
.it_value
.tv_sec
= DivU64x32(PeriodMs
, 1000);
181 DivU64x32Remainder(PeriodMs
, 1000, &remainder
);
182 timerval
.it_value
.tv_usec
= remainder
* 1000;
183 timerval
.it_value
.tv_sec
= DivU64x32(PeriodMs
, 1000);
184 timerval
.it_interval
= timerval
.it_value
;
186 if (setitimer (ITIMER_REAL
, &timerval
, NULL
) != 0) {
187 printf ("SetTimer: setitimer error %s\n", strerror (errno
));
189 settimer_callback
= CallBack
;
200 gEmulatorInterruptEnabled
= TRUE
;
201 // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
202 // by enabling/disabling SIGALRM.
203 sigemptyset (&sigset
);
204 sigaddset (&sigset
, SIGALRM
);
205 pthread_sigmask (SIG_UNBLOCK
, &sigset
, NULL
);
210 SecDisableInterrupt (
216 // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
217 // by enabling/disabling SIGALRM.
218 sigemptyset (&sigset
);
219 sigaddset (&sigset
, SIGALRM
);
220 pthread_sigmask (SIG_BLOCK
, &sigset
, NULL
);
221 gEmulatorInterruptEnabled
= FALSE
;
226 SecInterruptEanbled (void)
228 return gEmulatorInterruptEnabled
;
233 QueryPerformanceFrequency (
237 // Hard code to nanoseconds
238 return 1000000000ULL;
242 QueryPerformanceCounter (
248 Nanoseconds elapsedNano
;
250 Start
= mach_absolute_time ();
252 // Convert to nanoseconds.
254 // Have to do some pointer fun because AbsoluteToNanoseconds
255 // works in terms of UnsignedWide, which is a structure rather
256 // than a proper 64-bit integer.
257 elapsedNano
= AbsoluteToNanoseconds (*(AbsoluteTime
*) &Start
);
259 return *(uint64_t *) &elapsedNano
;
261 // Need to figure out what to do for Linux?
270 IN UINT64 Nanoseconds
273 struct timespec rq
, rm
;
274 struct timeval start
, end
;
275 unsigned long MicroSec
;
277 rq
.tv_sec
= DivU64x32 (Nanoseconds
, 1000000000);
278 rq
.tv_nsec
= ModU64x32 (Nanoseconds
, 1000000000);
281 // nanosleep gets interrupted by our timer tic.
282 // we need to track wall clock time or we will stall for way too long
284 gettimeofday (&start
, NULL
);
285 end
.tv_sec
= start
.tv_sec
+ rq
.tv_sec
;
286 MicroSec
= (start
.tv_usec
+ rq
.tv_nsec
/1000);
287 end
.tv_usec
= MicroSec
% 1000000;
288 if (MicroSec
> 1000000) {
292 while (nanosleep (&rq
, &rm
) == -1) {
293 if (errno
!= EINTR
) {
296 gettimeofday (&start
, NULL
);
297 if (start
.tv_sec
> end
.tv_sec
) {
299 } if ((start
.tv_sec
== end
.tv_sec
) && (start
.tv_usec
> end
.tv_usec
)) {
312 struct timespec rq
, rm
;
314 // nanosleep gets interrupted by the timer tic
318 nanosleep (&rq
, &rm
);
334 OUT EFI_TIME_CAPABILITIES
*Capabilities OPTIONAL
343 Time
->Year
= 1900 + tm
->tm_year
;
344 Time
->Month
= tm
->tm_mon
+ 1;
345 Time
->Day
= tm
->tm_mday
;
346 Time
->Hour
= tm
->tm_hour
;
347 Time
->Minute
= tm
->tm_min
;
348 Time
->Second
= tm
->tm_sec
;
349 Time
->Nanosecond
= 0;
350 Time
->TimeZone
= timezone
;
351 Time
->Daylight
= (daylight
? EFI_TIME_ADJUST_DAYLIGHT
: 0)
352 | (tm
->tm_isdst
> 0 ? EFI_TIME_IN_DAYLIGHT
: 0);
354 if (Capabilities
!= NULL
) {
355 Capabilities
->Resolution
= 1;
356 Capabilities
->Accuracy
= 50000000;
357 Capabilities
->SetsToZero
= FALSE
;
368 // Don't change the time on the system
369 // We could save delta to localtime() and have SecGetTime adjust return values?
376 IN BOOLEAN EmuBusDriver
,
377 OUT EMU_IO_THUNK_PROTOCOL
**Instance OPTIONAL
380 return GetNextThunkProtocol (EmuBusDriver
, Instance
);
384 EMU_THUNK_PROTOCOL gEmuThunkProtocol
= {
385 GasketSecWriteStdErr
,
386 GasketSecConfigStdIn
,
387 GasketSecWriteStdOut
,
392 GasketSecPeCoffGetEntryPoint
,
393 GasketSecPeCoffRelocateImageExtraAction
,
394 GasketSecPeCoffUnloadImageExtraAction
,
395 GasketSecEnableInterrupt
,
396 GasketSecDisableInterrupt
,
397 GasketQueryPerformanceFrequency
,
398 GasketQueryPerformanceCounter
,
405 GasketSecGetNextProtocol
410 SecInitThunkProtocol (
414 // timezone and daylight lib globals depend on tzset be called 1st.