]>
Commit | Line | Data |
---|---|---|
804405e7 | 1 | /*++ |
2 | ||
f9b8ab56 | 3 | Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR> |
2ff79f2e | 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 | |
9 | ||
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. | |
804405e7 | 12 | |
13 | Module Name: | |
14 | ||
15 | UnixThunk.c | |
16 | ||
17 | Abstract: | |
18 | ||
2ff79f2e | 19 | Since the SEC is the only program in our emulation we |
804405e7 | 20 | must use a Tiano mechanism to export APIs to other modules. |
21 | This is the role of the EFI_UNIX_THUNK_PROTOCOL. | |
22 | ||
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. | |
2ff79f2e | 28 | |
804405e7 | 29 | |
30 | gUnix is a a public exported global that contains the initialized | |
31 | data. | |
32 | ||
33 | --*/ | |
34 | ||
35 | #include "SecMain.h" | |
b67f2798 | 36 | #include "Uefi.h" |
804405e7 | 37 | #include "Library/UnixLib.h" |
38 | ||
3ff2e324 | 39 | #if defined(__APPLE__) || defined(MDE_CPU_X64) |
7ee3b613 A |
40 | #include "Gasket.h" |
41 | #endif | |
42 | ||
7492c63d | 43 | int settimer_initialized; |
44 | struct timeval settimer_timeval; | |
45 | void (*settimer_callback)(UINT64 delta); | |
804405e7 | 46 | |
2ff79f2e | 47 | BOOLEAN gEmulatorInterruptEnabled = FALSE; |
48 | ||
49 | ||
7492c63d | 50 | void |
804405e7 | 51 | settimer_handler (int sig) |
52 | { | |
53 | struct timeval timeval; | |
54 | UINT64 delta; | |
55 | ||
56 | gettimeofday (&timeval, NULL); | |
57 | delta = ((UINT64)timeval.tv_sec * 1000) + (timeval.tv_usec / 1000) | |
2ff79f2e | 58 | - ((UINT64)settimer_timeval.tv_sec * 1000) |
804405e7 | 59 | - (settimer_timeval.tv_usec / 1000); |
60 | settimer_timeval = timeval; | |
2ff79f2e | 61 | |
b9c8e50e | 62 | if (settimer_callback) { |
3ff2e324 | 63 | #if defined(__APPLE__) || defined(MDE_CPU_X64) |
2ec364f9 | 64 | ReverseGasketUint64 (settimer_callback, delta); |
b9c8e50e | 65 | #else |
2ff79f2e | 66 | (*settimer_callback)(delta); |
b9c8e50e | 67 | #endif |
68 | } | |
804405e7 | 69 | } |
70 | ||
804405e7 | 71 | VOID |
72 | SetTimer (UINT64 PeriodMs, VOID (*CallBack)(UINT64 DeltaMs)) | |
73 | { | |
74 | struct itimerval timerval; | |
73aa7f04 | 75 | UINT32 remainder; |
804405e7 | 76 | |
77 | if (!settimer_initialized) { | |
78 | struct sigaction act; | |
79 | ||
80 | settimer_initialized = 1; | |
81 | act.sa_handler = settimer_handler; | |
82 | act.sa_flags = 0; | |
83 | sigemptyset (&act.sa_mask); | |
2ff79f2e | 84 | gEmulatorInterruptEnabled = TRUE; |
804405e7 | 85 | if (sigaction (SIGALRM, &act, NULL) != 0) { |
86 | printf ("SetTimer: sigaction error %s\n", strerror (errno)); | |
87 | } | |
88 | if (gettimeofday (&settimer_timeval, NULL) != 0) { | |
89 | printf ("SetTimer: gettimeofday error %s\n", strerror (errno)); | |
90 | } | |
91 | } | |
73aa7f04 | 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); | |
804405e7 | 96 | timerval.it_interval = timerval.it_value; |
2ff79f2e | 97 | |
804405e7 | 98 | if (setitimer (ITIMER_REAL, &timerval, NULL) != 0) { |
99 | printf ("SetTimer: setitimer error %s\n", strerror (errno)); | |
100 | } | |
101 | settimer_callback = CallBack; | |
102 | } | |
103 | ||
2ff79f2e | 104 | |
105 | void | |
106 | UnixEnableInterrupt (void) | |
107 | { | |
108 | sigset_t sigset; | |
109 | ||
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); | |
116 | } | |
117 | ||
118 | ||
119 | void | |
120 | UnixDisableInterrupt (void) | |
121 | { | |
122 | sigset_t sigset; | |
123 | ||
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; | |
130 | } | |
131 | ||
132 | ||
133 | BOOLEAN | |
134 | UnixInterruptEanbled (void) | |
135 | { | |
136 | return gEmulatorInterruptEnabled; | |
137 | } | |
138 | ||
139 | ||
140 | ||
804405e7 | 141 | void |
142 | msSleep (unsigned long Milliseconds) | |
143 | { | |
b9c8e50e | 144 | struct timespec rq, rm; |
804405e7 | 145 | |
b9c8e50e | 146 | rq.tv_sec = Milliseconds / 1000; |
147 | rq.tv_nsec = (Milliseconds % 1000) * 1000000; | |
804405e7 | 148 | |
b9c8e50e | 149 | while (nanosleep (&rq, &rm) != -1) { |
150 | if (errno != EINTR) { | |
151 | break; | |
152 | } | |
153 | rq = rm; | |
2ff79f2e | 154 | } |
3ff2e324 | 155 | |
804405e7 | 156 | } |
157 | ||
158 | void | |
159 | GetLocalTime (EFI_TIME *Time) | |
160 | { | |
161 | struct tm *tm; | |
162 | time_t t; | |
163 | ||
164 | t = time (NULL); | |
165 | tm = localtime (&t); | |
166 | ||
167 | Time->Year = 1900 + tm->tm_year; | |
be5d189f | 168 | Time->Month = tm->tm_mon + 1; |
804405e7 | 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; | |
bb111c23 | 174 | Time->TimeZone = GetTimeZone (); |
804405e7 | 175 | Time->Daylight = (daylight ? EFI_TIME_ADJUST_DAYLIGHT : 0) |
176 | | (tm->tm_isdst > 0 ? EFI_TIME_IN_DAYLIGHT : 0); | |
177 | } | |
178 | ||
7492c63d | 179 | void |
804405e7 | 180 | TzSet (void) |
181 | { | |
7492c63d | 182 | STATIC int done = 0; |
804405e7 | 183 | if (!done) { |
184 | tzset (); | |
185 | done = 1; | |
186 | } | |
187 | } | |
188 | ||
189 | long | |
190 | GetTimeZone(void) | |
191 | { | |
192 | TzSet (); | |
193 | return timezone; | |
194 | } | |
195 | ||
196 | int | |
197 | GetDayLight(void) | |
198 | { | |
199 | TzSet (); | |
200 | return daylight; | |
201 | } | |
202 | ||
203 | int | |
204 | GetErrno(void) | |
205 | { | |
206 | return errno; | |
207 | } | |
208 | ||
ccd55824 | 209 | |
804405e7 | 210 | extern EFI_STATUS |
211 | UgaCreate(struct _EFI_UNIX_UGA_IO_PROTOCOL **UgaIo, CONST CHAR16 *Title); | |
212 | ||
213 | EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable = { | |
214 | EFI_UNIX_THUNK_PROTOCOL_SIGNATURE, | |
3ff2e324 | 215 | #if defined(__APPLE__) || defined(MDE_CPU_X64) |
ccd55824 | 216 | // |
217 | // Mac OS X requires the stack to be 16-byte aligned for IA-32. So on an OS X build | |
2ff79f2e | 218 | // we add an assembly wrapper that makes sure the stack ges aligned. |
ccd55824 | 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 | |
221 | // | |
222 | GasketmsSleep, /* Sleep */ | |
223 | Gasketexit, /* Exit */ | |
224 | GasketSetTimer, | |
225 | GasketGetLocalTime, | |
226 | Gasketgmtime, | |
227 | GasketGetTimeZone, | |
228 | GasketGetDayLight, | |
b9c8e50e | 229 | Gasketpoll, |
230 | Gasketread, | |
231 | Gasketwrite, | |
ccd55824 | 232 | Gasketgetenv, |
b9c8e50e | 233 | Gasketopen, |
234 | Gasketlseek, | |
235 | Gasketftruncate, | |
ccd55824 | 236 | Gasketclose, |
237 | Gasketmkdir, | |
238 | Gasketrmdir, | |
239 | Gasketunlink, | |
240 | GasketGetErrno, | |
241 | Gasketopendir, | |
b9c8e50e | 242 | Gasketrewinddir, |
ccd55824 | 243 | Gasketreaddir, |
244 | Gasketclosedir, | |
245 | Gasketstat, | |
246 | Gasketstatfs, | |
247 | Gasketrename, | |
248 | Gasketmktime, | |
249 | Gasketfsync, | |
250 | Gasketchmod, | |
251 | Gasketutime, | |
252 | Gaskettcflush, | |
253 | GasketUgaCreate, | |
254 | Gasketperror, | |
255 | Gasketioctl, | |
256 | Gasketfcntl, | |
257 | Gasketcfsetispeed, | |
258 | Gasketcfsetospeed, | |
259 | Gaskettcgetattr, | |
260 | Gaskettcsetattr, | |
2ff79f2e | 261 | GasketUnixPeCoffGetEntryPoint, |
262 | GasketUnixPeCoffRelocateImageExtraAction, | |
263 | GasketUnixPeCoffUnloadImageExtraAction, | |
264 | ||
265 | GasketUnixEnableInterrupt, | |
266 | GasketUnixDisableInterrupt, | |
267 | ||
268 | Gasketgetifaddrs, | |
269 | Gasketfreeifaddrs, | |
270 | Gasketsocket, | |
ccd55824 | 271 | |
272 | #else | |
804405e7 | 273 | msSleep, /* Sleep */ |
274 | exit, /* Exit */ | |
275 | SetTimer, | |
276 | GetLocalTime, | |
277 | gmtime, | |
278 | GetTimeZone, | |
279 | GetDayLight, | |
280 | (UnixPoll)poll, | |
281 | (UnixRead)read, | |
282 | (UnixWrite)write, | |
283 | getenv, | |
284 | (UnixOpen)open, | |
ccd55824 | 285 | (UnixSeek)lseek, |
286 | (UnixFtruncate)ftruncate, | |
804405e7 | 287 | close, |
288 | mkdir, | |
289 | rmdir, | |
290 | unlink, | |
291 | GetErrno, | |
292 | opendir, | |
293 | rewinddir, | |
294 | readdir, | |
295 | closedir, | |
7ee3b613 | 296 | (UnixStat)stat, |
804405e7 | 297 | statfs, |
298 | rename, | |
299 | mktime, | |
300 | fsync, | |
301 | chmod, | |
302 | utime, | |
303 | tcflush, | |
304 | UgaCreate, | |
305 | perror, | |
306 | ioctl, | |
307 | fcntl, | |
308 | cfsetispeed, | |
309 | cfsetospeed, | |
310 | tcgetattr, | |
398b646f | 311 | tcsetattr, |
ccd55824 | 312 | SecPeCoffGetEntryPoint, |
313 | SecPeCoffRelocateImageExtraAction, | |
2ff79f2e | 314 | SecPeCoffLoaderUnloadImageExtraAction, |
315 | UnixEnableInterrupt, | |
316 | UnixDisableInterrupt, | |
317 | getifaddrs, | |
318 | freeifaddrs, | |
319 | socket | |
ccd55824 | 320 | #endif |
804405e7 | 321 | }; |
322 | ||
323 | ||
324 | EFI_UNIX_THUNK_PROTOCOL *gUnix = &mUnixThunkTable; |