]>
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; |
b5b1aca9 | 145 | struct timeval start, end; |
146 | unsigned long MicroSec; | |
147 | ||
b9c8e50e | 148 | rq.tv_sec = Milliseconds / 1000; |
149 | rq.tv_nsec = (Milliseconds % 1000) * 1000000; | |
804405e7 | 150 | |
b5b1aca9 | 151 | // |
152 | // nanosleep gets interrupted by our timer tic. | |
153 | // we need to track wall clock time or we will stall for way too long | |
154 | // | |
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) { | |
160 | end.tv_sec++; | |
161 | } | |
162 | ||
163 | while (nanosleep (&rq, &rm) == -1) { | |
b9c8e50e | 164 | if (errno != EINTR) { |
165 | break; | |
166 | } | |
b5b1aca9 | 167 | gettimeofday (&start, NULL); |
168 | if (start.tv_sec > end.tv_sec) { | |
169 | break; | |
170 | } if ((start.tv_sec == end.tv_sec) && (start.tv_usec > end.tv_usec)) { | |
171 | break; | |
172 | } | |
b9c8e50e | 173 | rq = rm; |
2ff79f2e | 174 | } |
804405e7 | 175 | } |
176 | ||
177 | void | |
178 | GetLocalTime (EFI_TIME *Time) | |
179 | { | |
180 | struct tm *tm; | |
181 | time_t t; | |
182 | ||
183 | t = time (NULL); | |
184 | tm = localtime (&t); | |
185 | ||
186 | Time->Year = 1900 + tm->tm_year; | |
be5d189f | 187 | Time->Month = tm->tm_mon + 1; |
804405e7 | 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; | |
bb111c23 | 193 | Time->TimeZone = GetTimeZone (); |
804405e7 | 194 | Time->Daylight = (daylight ? EFI_TIME_ADJUST_DAYLIGHT : 0) |
195 | | (tm->tm_isdst > 0 ? EFI_TIME_IN_DAYLIGHT : 0); | |
196 | } | |
197 | ||
7492c63d | 198 | void |
804405e7 | 199 | TzSet (void) |
200 | { | |
7492c63d | 201 | STATIC int done = 0; |
804405e7 | 202 | if (!done) { |
203 | tzset (); | |
204 | done = 1; | |
205 | } | |
206 | } | |
207 | ||
208 | long | |
209 | GetTimeZone(void) | |
210 | { | |
211 | TzSet (); | |
212 | return timezone; | |
213 | } | |
214 | ||
215 | int | |
216 | GetDayLight(void) | |
217 | { | |
218 | TzSet (); | |
219 | return daylight; | |
220 | } | |
221 | ||
222 | int | |
223 | GetErrno(void) | |
224 | { | |
225 | return errno; | |
226 | } | |
227 | ||
ccd55824 | 228 | |
804405e7 | 229 | extern EFI_STATUS |
230 | UgaCreate(struct _EFI_UNIX_UGA_IO_PROTOCOL **UgaIo, CONST CHAR16 *Title); | |
231 | ||
232 | EFI_UNIX_THUNK_PROTOCOL mUnixThunkTable = { | |
233 | EFI_UNIX_THUNK_PROTOCOL_SIGNATURE, | |
3ff2e324 | 234 | #if defined(__APPLE__) || defined(MDE_CPU_X64) |
ccd55824 | 235 | // |
236 | // Mac OS X requires the stack to be 16-byte aligned for IA-32. So on an OS X build | |
2ff79f2e | 237 | // we add an assembly wrapper that makes sure the stack ges aligned. |
ccd55824 | 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 | |
240 | // | |
241 | GasketmsSleep, /* Sleep */ | |
242 | Gasketexit, /* Exit */ | |
243 | GasketSetTimer, | |
244 | GasketGetLocalTime, | |
245 | Gasketgmtime, | |
246 | GasketGetTimeZone, | |
247 | GasketGetDayLight, | |
b9c8e50e | 248 | Gasketpoll, |
249 | Gasketread, | |
250 | Gasketwrite, | |
ccd55824 | 251 | Gasketgetenv, |
b9c8e50e | 252 | Gasketopen, |
253 | Gasketlseek, | |
254 | Gasketftruncate, | |
ccd55824 | 255 | Gasketclose, |
256 | Gasketmkdir, | |
257 | Gasketrmdir, | |
258 | Gasketunlink, | |
259 | GasketGetErrno, | |
260 | Gasketopendir, | |
b9c8e50e | 261 | Gasketrewinddir, |
ccd55824 | 262 | Gasketreaddir, |
263 | Gasketclosedir, | |
264 | Gasketstat, | |
265 | Gasketstatfs, | |
266 | Gasketrename, | |
267 | Gasketmktime, | |
268 | Gasketfsync, | |
269 | Gasketchmod, | |
270 | Gasketutime, | |
271 | Gaskettcflush, | |
272 | GasketUgaCreate, | |
273 | Gasketperror, | |
274 | Gasketioctl, | |
275 | Gasketfcntl, | |
276 | Gasketcfsetispeed, | |
277 | Gasketcfsetospeed, | |
278 | Gaskettcgetattr, | |
279 | Gaskettcsetattr, | |
2ff79f2e | 280 | GasketUnixPeCoffGetEntryPoint, |
281 | GasketUnixPeCoffRelocateImageExtraAction, | |
282 | GasketUnixPeCoffUnloadImageExtraAction, | |
283 | ||
284 | GasketUnixEnableInterrupt, | |
285 | GasketUnixDisableInterrupt, | |
286 | ||
287 | Gasketgetifaddrs, | |
288 | Gasketfreeifaddrs, | |
289 | Gasketsocket, | |
ccd55824 | 290 | |
291 | #else | |
804405e7 | 292 | msSleep, /* Sleep */ |
293 | exit, /* Exit */ | |
294 | SetTimer, | |
295 | GetLocalTime, | |
296 | gmtime, | |
297 | GetTimeZone, | |
298 | GetDayLight, | |
299 | (UnixPoll)poll, | |
300 | (UnixRead)read, | |
301 | (UnixWrite)write, | |
302 | getenv, | |
303 | (UnixOpen)open, | |
ccd55824 | 304 | (UnixSeek)lseek, |
305 | (UnixFtruncate)ftruncate, | |
804405e7 | 306 | close, |
307 | mkdir, | |
308 | rmdir, | |
309 | unlink, | |
310 | GetErrno, | |
311 | opendir, | |
312 | rewinddir, | |
313 | readdir, | |
314 | closedir, | |
7ee3b613 | 315 | (UnixStat)stat, |
804405e7 | 316 | statfs, |
317 | rename, | |
318 | mktime, | |
319 | fsync, | |
320 | chmod, | |
321 | utime, | |
322 | tcflush, | |
323 | UgaCreate, | |
324 | perror, | |
325 | ioctl, | |
326 | fcntl, | |
327 | cfsetispeed, | |
328 | cfsetospeed, | |
329 | tcgetattr, | |
398b646f | 330 | tcsetattr, |
ccd55824 | 331 | SecPeCoffGetEntryPoint, |
332 | SecPeCoffRelocateImageExtraAction, | |
2ff79f2e | 333 | SecPeCoffLoaderUnloadImageExtraAction, |
334 | UnixEnableInterrupt, | |
335 | UnixDisableInterrupt, | |
336 | getifaddrs, | |
337 | freeifaddrs, | |
338 | socket | |
ccd55824 | 339 | #endif |
804405e7 | 340 | }; |
341 | ||
342 | ||
343 | EFI_UNIX_THUNK_PROTOCOL *gUnix = &mUnixThunkTable; |