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
;
146 rq
.tv_sec
= Milliseconds
/ 1000;
147 rq
.tv_nsec
= (Milliseconds
% 1000) * 1000000;
149 while (nanosleep (&rq
, &rm
) != -1) {
150 if (errno
!= EINTR
) {
159 GetLocalTime (EFI_TIME
*Time
)
167 Time
->Year
= 1900 + tm
->tm_year
;
168 Time
->Month
= tm
->tm_mon
+ 1;
169 Time
->Day
= tm
->tm_mday
;
170 Time
->Hour
= tm
->tm_hour
;
171 Time
->Minute
= tm
->tm_min
;
172 Time
->Second
= tm
->tm_sec
;
173 Time
->Nanosecond
= 0;
174 Time
->TimeZone
= GetTimeZone ();
175 Time
->Daylight
= (daylight
? EFI_TIME_ADJUST_DAYLIGHT
: 0)
176 | (tm
->tm_isdst
> 0 ? EFI_TIME_IN_DAYLIGHT
: 0);
211 UgaCreate(struct _EFI_UNIX_UGA_IO_PROTOCOL
**UgaIo
, CONST CHAR16
*Title
);
213 EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable
= {
214 EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
,
215 #if defined(__APPLE__) || defined(MDE_CPU_X64)
217 // Mac OS X requires the stack to be 16-byte aligned for IA-32. So on an OS X build
218 // we add an assembly wrapper that makes sure the stack ges aligned.
219 // This has the nice benfit of being able to run EFI ABI code, like the EFI shell
220 // that is checked in to source control in the OS X version of the emulator
222 GasketmsSleep
, /* Sleep */
223 Gasketexit
, /* Exit */
261 GasketUnixPeCoffGetEntryPoint
,
262 GasketUnixPeCoffRelocateImageExtraAction
,
263 GasketUnixPeCoffUnloadImageExtraAction
,
265 GasketUnixEnableInterrupt
,
266 GasketUnixDisableInterrupt
,
286 (UnixFtruncate
)ftruncate
,
312 SecPeCoffGetEntryPoint
,
313 SecPeCoffRelocateImageExtraAction
,
314 SecPeCoffLoaderUnloadImageExtraAction
,
316 UnixDisableInterrupt
,
324 EFI_UNIX_THUNK_PROTOCOL
*gUnix
= &mUnixThunkTable
;