3 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Since the SEC is the only program in our emulation we
20 must use a Tiano mechanism to export APIs to other modules.
21 This is the role of the EFI_UNIX_THUNK_PROTOCOL.
23 The mUnixThunkTable exists so that a change to EFI_UNIX_THUNK_PROTOCOL
24 will cause an error in initializing the array if all the member functions
25 are not added. It looks like adding a element to end and not initializing
26 it may cause the table to be initaliized with the members at the end being
27 set to zero. This is bad as jumping to zero will crash.
30 gUnix is a a public exported global that contains the initialized
37 #include "Library/UnixLib.h"
39 #if defined(__APPLE__) || defined(MDE_CPU_X64)
43 int settimer_initialized
;
44 struct timeval settimer_timeval
;
45 void (*settimer_callback
)(UINT64 delta
);
47 BOOLEAN gEmulatorInterruptEnabled
= FALSE
;
51 settimer_handler (int sig
)
53 struct timeval timeval
;
56 gettimeofday (&timeval
, NULL
);
57 delta
= ((UINT64
)timeval
.tv_sec
* 1000) + (timeval
.tv_usec
/ 1000)
58 - ((UINT64
)settimer_timeval
.tv_sec
* 1000)
59 - (settimer_timeval
.tv_usec
/ 1000);
60 settimer_timeval
= timeval
;
62 if (settimer_callback
) {
63 #if defined(__APPLE__) || defined(MDE_CPU_X64)
64 ReverseGasketUint64 (settimer_callback
, delta
);
66 (*settimer_callback
)(delta
);
72 SetTimer (UINT64 PeriodMs
, VOID (*CallBack
)(UINT64 DeltaMs
))
74 struct itimerval timerval
;
77 if (!settimer_initialized
) {
80 settimer_initialized
= 1;
81 act
.sa_handler
= settimer_handler
;
83 sigemptyset (&act
.sa_mask
);
84 gEmulatorInterruptEnabled
= TRUE
;
85 if (sigaction (SIGALRM
, &act
, NULL
) != 0) {
86 printf ("SetTimer: sigaction error %s\n", strerror (errno
));
88 if (gettimeofday (&settimer_timeval
, NULL
) != 0) {
89 printf ("SetTimer: gettimeofday error %s\n", strerror (errno
));
92 timerval
.it_value
.tv_sec
= DivU64x32(PeriodMs
, 1000);
93 DivU64x32Remainder(PeriodMs
, 1000, &remainder
);
94 timerval
.it_value
.tv_usec
= remainder
* 1000;
95 timerval
.it_value
.tv_sec
= DivU64x32(PeriodMs
, 1000);
96 timerval
.it_interval
= timerval
.it_value
;
98 if (setitimer (ITIMER_REAL
, &timerval
, NULL
) != 0) {
99 printf ("SetTimer: setitimer error %s\n", strerror (errno
));
101 settimer_callback
= CallBack
;
106 UnixEnableInterrupt (void)
110 gEmulatorInterruptEnabled
= TRUE
;
111 // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
112 // by enabling/disabling SIGALRM.
113 sigemptyset (&sigset
);
114 sigaddset (&sigset
, SIGALRM
);
115 sigprocmask (SIG_UNBLOCK
, &sigset
, NULL
);
120 UnixDisableInterrupt (void)
124 // Since SetTimer() uses SIGALRM we emulate turning on and off interrupts
125 // by enabling/disabling SIGALRM.
126 sigemptyset (&sigset
);
127 sigaddset (&sigset
, SIGALRM
);
128 sigprocmask (SIG_BLOCK
, &sigset
, NULL
);
129 gEmulatorInterruptEnabled
= FALSE
;
134 UnixInterruptEanbled (void)
136 return gEmulatorInterruptEnabled
;
142 msSleep (unsigned long Milliseconds
)
144 struct timespec rq
, rm
;
145 struct timeval start
, end
;
146 unsigned long MicroSec
;
148 rq
.tv_sec
= Milliseconds
/ 1000;
149 rq
.tv_nsec
= (Milliseconds
% 1000) * 1000000;
152 // nanosleep gets interrupted by our timer tic.
153 // we need to track wall clock time or we will stall for way too long
155 gettimeofday (&start
, NULL
);
156 end
.tv_sec
= start
.tv_sec
+ rq
.tv_sec
;
157 MicroSec
= (start
.tv_usec
+ rq
.tv_nsec
/1000);
158 end
.tv_usec
= MicroSec
% 1000000;
159 if (MicroSec
> 1000000) {
163 while (nanosleep (&rq
, &rm
) == -1) {
164 if (errno
!= EINTR
) {
167 gettimeofday (&start
, NULL
);
168 if (start
.tv_sec
> end
.tv_sec
) {
170 } if ((start
.tv_sec
== end
.tv_sec
) && (start
.tv_usec
> end
.tv_usec
)) {
178 GetLocalTime (EFI_TIME
*Time
)
186 Time
->Year
= 1900 + tm
->tm_year
;
187 Time
->Month
= tm
->tm_mon
+ 1;
188 Time
->Day
= tm
->tm_mday
;
189 Time
->Hour
= tm
->tm_hour
;
190 Time
->Minute
= tm
->tm_min
;
191 Time
->Second
= tm
->tm_sec
;
192 Time
->Nanosecond
= 0;
193 Time
->TimeZone
= GetTimeZone ();
194 Time
->Daylight
= (daylight
? EFI_TIME_ADJUST_DAYLIGHT
: 0)
195 | (tm
->tm_isdst
> 0 ? EFI_TIME_IN_DAYLIGHT
: 0);
230 UgaCreate(struct _EFI_UNIX_UGA_IO_PROTOCOL
**UgaIo
, CONST CHAR16
*Title
);
232 EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable
= {
233 EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
,
234 #if defined(__APPLE__) || defined(MDE_CPU_X64)
236 // Mac OS X requires the stack to be 16-byte aligned for IA-32. So on an OS X build
237 // we add an assembly wrapper that makes sure the stack ges aligned.
238 // This has the nice benfit of being able to run EFI ABI code, like the EFI shell
239 // that is checked in to source control in the OS X version of the emulator
241 GasketmsSleep
, /* Sleep */
242 Gasketexit
, /* Exit */
280 GasketUnixPeCoffGetEntryPoint
,
281 GasketUnixPeCoffRelocateImageExtraAction
,
282 GasketUnixPeCoffUnloadImageExtraAction
,
284 GasketUnixEnableInterrupt
,
285 GasketUnixDisableInterrupt
,
305 (UnixFtruncate
)ftruncate
,
331 SecPeCoffGetEntryPoint
,
332 SecPeCoffRelocateImageExtraAction
,
333 SecPeCoffLoaderUnloadImageExtraAction
,
335 UnixDisableInterrupt
,
343 EFI_UNIX_THUNK_PROTOCOL
*gUnix
= &mUnixThunkTable
;