TianoCore EDK2 master
Loading...
Searching...
No Matches
WinThunk.c
Go to the documentation of this file.
1
24#include "WinHost.h"
25
26STATIC BOOLEAN mEmulatorStdInConfigured = FALSE;
27STATIC DWORD mOldStdInMode;
28#if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
29STATIC DWORD mOldStdOutMode;
30#endif
31
32STATIC UINT64 mPerformanceFrequency = 0;
33
35SecWriteStdErr (
36 IN UINT8 *Buffer,
37 IN UINTN NumberOfBytes
38 )
39{
40 BOOL Success;
41 DWORD CharCount;
42
43 CharCount = (DWORD)NumberOfBytes;
44 Success = WriteFile (
45 GetStdHandle (STD_ERROR_HANDLE),
46 Buffer,
47 CharCount,
48 &CharCount,
49 NULL
50 );
51
52 return Success ? CharCount : 0;
53}
54
56SecConfigStdIn (
57 VOID
58 )
59{
60 BOOL Success;
61 DWORD Mode;
62
63 Success = GetConsoleMode (GetStdHandle (STD_INPUT_HANDLE), &Mode);
64 if (Success) {
65 if (!mEmulatorStdInConfigured) {
66 //
67 // Save the original state of the console so it can be restored on exit
68 //
69 mOldStdInMode = Mode;
70 }
71
72 //
73 // Disable buffer (line input), echo, mouse, window
74 //
75 Mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
76
77 #if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
78 //
79 // Enable virtual terminal input for Win10 above TH2
80 //
81 Mode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
82 #endif
83
84 Success = SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE), Mode);
85 }
86
87 #if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
88 //
89 // Enable terminal mode for Win10 above TH2
90 //
91 if (Success) {
92 Success = GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE), &Mode);
93 if (!mEmulatorStdInConfigured) {
94 //
95 // Save the original state of the console so it can be restored on exit
96 //
97 mOldStdOutMode = Mode;
98 }
99
100 if (Success) {
101 Success = SetConsoleMode (
102 GetStdHandle (STD_OUTPUT_HANDLE),
103 Mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN
104 );
105 }
106 }
107
108 #endif
109 if (Success) {
110 mEmulatorStdInConfigured = TRUE;
111 }
112
113 return Success ? EFI_SUCCESS : EFI_DEVICE_ERROR;
114}
115
116UINTN
117SecWriteStdOut (
118 IN UINT8 *Buffer,
119 IN UINTN NumberOfBytes
120 )
121{
122 BOOL Success;
123 DWORD CharCount;
124
125 CharCount = (DWORD)NumberOfBytes;
126 Success = WriteFile (
127 GetStdHandle (STD_OUTPUT_HANDLE),
128 Buffer,
129 CharCount,
130 &CharCount,
131 NULL
132 );
133
134 return Success ? CharCount : 0;
135}
136
137BOOLEAN
138SecPollStdIn (
139 VOID
140 )
141{
142 BOOL Success;
143 INPUT_RECORD Record;
144 DWORD RecordNum;
145
146 do {
147 Success = GetNumberOfConsoleInputEvents (GetStdHandle (STD_INPUT_HANDLE), &RecordNum);
148 if (!Success || (RecordNum == 0)) {
149 break;
150 }
151
152 Success = PeekConsoleInput (
153 GetStdHandle (STD_INPUT_HANDLE),
154 &Record,
155 1,
156 &RecordNum
157 );
158 if (Success && (RecordNum == 1)) {
159 if ((Record.EventType == KEY_EVENT) && Record.Event.KeyEvent.bKeyDown) {
160 return TRUE;
161 } else {
162 //
163 // Consume the non-key event.
164 //
165 Success = ReadConsoleInput (
166 GetStdHandle (STD_INPUT_HANDLE),
167 &Record,
168 1,
169 &RecordNum
170 );
171 }
172 }
173 } while (Success);
174
175 return FALSE;
176}
177
178UINTN
179SecReadStdIn (
180 IN UINT8 *Buffer,
181 IN UINTN NumberOfBytes
182 )
183{
184 BOOL Success;
185 INPUT_RECORD Record;
186 DWORD RecordNum;
187 UINTN BytesReturn;
188
189 if (!SecPollStdIn ()) {
190 return 0;
191 }
192
193 Success = ReadConsoleInput (
194 GetStdHandle (STD_INPUT_HANDLE),
195 &Record,
196 1,
197 &RecordNum
198 );
199 ASSERT (Success && (RecordNum == 1) && (Record.EventType == KEY_EVENT) && (Record.Event.KeyEvent.bKeyDown));
200 NumberOfBytes = MIN (Record.Event.KeyEvent.wRepeatCount, NumberOfBytes);
201 BytesReturn = NumberOfBytes;
202 while (NumberOfBytes-- != 0) {
203 Buffer[NumberOfBytes] = Record.Event.KeyEvent.uChar.AsciiChar;
204 }
205
206 return BytesReturn;
207}
208
209VOID *
210SecAlloc (
211 IN UINTN Size
212 )
213{
214 return malloc ((size_t)Size);
215}
216
217BOOLEAN
218SecFree (
219 IN VOID *Ptr
220 )
221{
222 if (EfiSystemMemoryRange (Ptr)) {
223 // If an address range is in the EFI memory map it was alloced via EFI.
224 // So don't free those ranges and let the caller know.
225 return FALSE;
226 }
227
228 free (Ptr);
229 return TRUE;
230}
231
232//
233// Define a global that we can use to shut down the NT timer thread when
234// the timer is canceled.
235//
236BOOLEAN mCancelTimerThread = FALSE;
237
238//
239// The notification function to call on every timer interrupt
240//
241EMU_SET_TIMER_CALLBACK *mTimerNotifyFunction = NULL;
242
243//
244// The thread handle for this driver
245//
246HANDLE mNtMainThreadHandle;
247
248//
249// The timer value from the last timer interrupt
250//
251UINT32 mNtLastTick;
252
253//
254// Critical section used to update varibles shared between the main thread and
255// the timer interrupt thread.
256//
257CRITICAL_SECTION mNtCriticalSection;
258
259//
260// Worker Functions
261//
262UINT mMMTimerThreadID = 0;
263
264volatile BOOLEAN mInterruptEnabled = FALSE;
265
266VOID
267CALLBACK
268MMTimerThread (
269 UINT wTimerID,
270 UINT msg,
271 DWORD_PTR dwUser,
272 DWORD_PTR dw1,
273 DWORD_PTR dw2
274 )
275{
276 UINT32 CurrentTick;
277 UINT32 Delta;
278
279 if (!mCancelTimerThread) {
280 //
281 // Suspend the main thread until we are done.
282 // Enter the critical section before suspending
283 // and leave the critical section after resuming
284 // to avoid deadlock between main and timer thread.
285 //
286 EnterCriticalSection (&mNtCriticalSection);
287 SuspendThread (mNtMainThreadHandle);
288
289 //
290 // If the timer thread is being canceled, then bail immediately.
291 // We check again here because there's a small window of time from when
292 // this thread was kicked off and when we suspended the main thread above.
293 //
294 if (mCancelTimerThread) {
295 ResumeThread (mNtMainThreadHandle);
296 LeaveCriticalSection (&mNtCriticalSection);
297 timeKillEvent (wTimerID);
298 mMMTimerThreadID = 0;
299 return;
300 }
301
302 while (!mInterruptEnabled) {
303 //
304 // Resume the main thread
305 //
306 ResumeThread (mNtMainThreadHandle);
307 LeaveCriticalSection (&mNtCriticalSection);
308
309 //
310 // Wait for interrupts to be enabled.
311 //
312 while (!mInterruptEnabled) {
313 Sleep (1);
314 }
315
316 //
317 // Suspend the main thread until we are done
318 //
319 EnterCriticalSection (&mNtCriticalSection);
320 SuspendThread (mNtMainThreadHandle);
321 }
322
323 //
324 // Get the current system tick
325 //
326 CurrentTick = GetTickCount ();
327 Delta = CurrentTick - mNtLastTick;
328 mNtLastTick = CurrentTick;
329
330 //
331 // If delay was more then 1 second, ignore it (probably debugging case)
332 //
333 if (Delta < 1000) {
334 //
335 // Only invoke the callback function if a Non-NULL handler has been
336 // registered. Assume all other handlers are legal.
337 //
338 if (mTimerNotifyFunction != NULL) {
339 mTimerNotifyFunction (Delta);
340 }
341 }
342
343 //
344 // Resume the main thread
345 //
346 ResumeThread (mNtMainThreadHandle);
347 LeaveCriticalSection (&mNtCriticalSection);
348 } else {
349 timeKillEvent (wTimerID);
350 mMMTimerThreadID = 0;
351 }
352}
353
354VOID
355SecSetTimer (
356 IN UINT64 TimerPeriod,
357 IN EMU_SET_TIMER_CALLBACK Callback
358 )
359{
360 //
361 // If TimerPeriod is 0, then the timer thread should be canceled
362 //
363 if (TimerPeriod == 0) {
364 //
365 // Cancel the timer thread
366 //
367 EnterCriticalSection (&mNtCriticalSection);
368
369 mCancelTimerThread = TRUE;
370
371 LeaveCriticalSection (&mNtCriticalSection);
372
373 //
374 // Wait for the timer thread to exit
375 //
376
377 if (mMMTimerThreadID != 0) {
378 timeKillEvent (mMMTimerThreadID);
379 mMMTimerThreadID = 0;
380 }
381 } else {
382 //
383 // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread
384 //
385 EnterCriticalSection (&mNtCriticalSection);
386
387 mCancelTimerThread = FALSE;
388
389 LeaveCriticalSection (&mNtCriticalSection);
390
391 //
392 // Get the starting tick location if we are just starting the timer thread
393 //
394 mNtLastTick = GetTickCount ();
395
396 if (mMMTimerThreadID) {
397 timeKillEvent (mMMTimerThreadID);
398 }
399
400 SetThreadPriority (
401 GetCurrentThread (),
402 THREAD_PRIORITY_HIGHEST
403 );
404
405 mMMTimerThreadID = timeSetEvent (
406 (UINT)TimerPeriod,
407 0,
408 MMTimerThread,
409 (DWORD_PTR)NULL,
410 TIME_PERIODIC | TIME_KILL_SYNCHRONOUS | TIME_CALLBACK_FUNCTION
411 );
412 }
413
414 mTimerNotifyFunction = Callback;
415}
416
417VOID
418SecInitializeThunk (
419 VOID
420 )
421{
422 InitializeCriticalSection (&mNtCriticalSection);
423
424 DuplicateHandle (
425 GetCurrentProcess (),
426 GetCurrentThread (),
427 GetCurrentProcess (),
428 &mNtMainThreadHandle,
429 0,
430 FALSE,
431 DUPLICATE_SAME_ACCESS
432 );
433}
434
435VOID
436SecEnableInterrupt (
437 VOID
438 )
439{
440 mInterruptEnabled = TRUE;
441}
442
443VOID
444SecDisableInterrupt (
445 VOID
446 )
447{
448 mInterruptEnabled = FALSE;
449}
450
451UINT64
452SecQueryPerformanceFrequency (
453 VOID
454 )
455{
456 if (mPerformanceFrequency) {
457 return mPerformanceFrequency;
458 }
459
460 QueryPerformanceFrequency ((LARGE_INTEGER *)&mPerformanceFrequency);
461
462 return mPerformanceFrequency;
463}
464
465UINT64
466SecQueryPerformanceCounter (
467 VOID
468 )
469{
470 UINT64 PerformanceCount;
471
472 QueryPerformanceCounter ((LARGE_INTEGER *)&PerformanceCount);
473
474 return PerformanceCount;
475}
476
477VOID
478SecSleep (
479 IN UINT64 Nanoseconds
480 )
481{
482 Sleep ((DWORD)DivU64x32 (Nanoseconds, 1000000));
483}
484
485VOID
486SecCpuSleep (
487 VOID
488 )
489{
490 Sleep (1);
491}
492
493VOID
494SecExit (
495 UINTN Status
496 )
497{
498 if (mEmulatorStdInConfigured) {
499 //
500 // Reset the console back to its original state
501 //
502 #if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
503 BOOL Success = SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE), mOldStdInMode);
504 if (Success) {
505 SetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE), mOldStdOutMode);
506 }
507
508 #else
509 SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE), mOldStdInMode);
510 #endif
511 }
512
513 exit ((int)Status);
514}
515
516VOID
517SecGetTime (
518 OUT EFI_TIME *Time,
519 OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
520 )
521{
522 SYSTEMTIME SystemTime;
523 TIME_ZONE_INFORMATION TimeZone;
524
525 GetLocalTime (&SystemTime);
526 GetTimeZoneInformation (&TimeZone);
527
528 Time->Year = (UINT16)SystemTime.wYear;
529 Time->Month = (UINT8)SystemTime.wMonth;
530 Time->Day = (UINT8)SystemTime.wDay;
531 Time->Hour = (UINT8)SystemTime.wHour;
532 Time->Minute = (UINT8)SystemTime.wMinute;
533 Time->Second = (UINT8)SystemTime.wSecond;
534 Time->Nanosecond = (UINT32)(SystemTime.wMilliseconds * 1000000);
535 Time->TimeZone = (INT16)TimeZone.Bias;
536
537 if (Capabilities != NULL) {
538 Capabilities->Resolution = 1;
539 Capabilities->Accuracy = 50000000;
540 Capabilities->SetsToZero = FALSE;
541 }
542
543 Time->Daylight = 0;
544 if (TimeZone.StandardDate.wMonth) {
545 Time->Daylight = (UINT8)TimeZone.StandardDate.wMonth;
546 }
547}
548
550SecSetTime (
551 IN EFI_TIME *Time
552 )
553{
554 TIME_ZONE_INFORMATION TimeZone;
555 SYSTEMTIME SystemTime;
556 BOOL Flag;
557
558 //
559 // Set Daylight savings time information and Time Zone
560 //
561 GetTimeZoneInformation (&TimeZone);
562 TimeZone.StandardDate.wMonth = Time->Daylight;
563 TimeZone.Bias = Time->TimeZone;
564 Flag = SetTimeZoneInformation (&TimeZone);
565 if (!Flag) {
566 return EFI_DEVICE_ERROR;
567 }
568
569 SystemTime.wYear = Time->Year;
570 SystemTime.wMonth = Time->Month;
571 SystemTime.wDay = Time->Day;
572 SystemTime.wHour = Time->Hour;
573 SystemTime.wMinute = Time->Minute;
574 SystemTime.wSecond = Time->Second;
575 SystemTime.wMilliseconds = (INT16)(Time->Nanosecond / 1000000);
576
577 Flag = SetLocalTime (&SystemTime);
578
579 if (!Flag) {
580 return EFI_DEVICE_ERROR;
581 } else {
582 return EFI_SUCCESS;
583 }
584}
585
586EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
587 SecWriteStdErr,
588 SecConfigStdIn,
589 SecWriteStdOut,
590 SecReadStdIn,
591 SecPollStdIn,
592 SecAlloc,
593 NULL,
594 SecFree,
595 SecPeCoffGetEntryPoint,
598 SecEnableInterrupt,
599 SecDisableInterrupt,
600 SecQueryPerformanceFrequency,
601 SecQueryPerformanceCounter,
602 SecSleep,
603 SecCpuSleep,
604 SecExit,
605 SecGetTime,
606 SecSetTime,
607 SecSetTimer,
608 GetNextThunkProtocol
609};
610
611#pragma warning(default : 4996)
612#pragma warning(default : 4232)
UINT64 UINTN
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
VOID EFIAPI PeCoffLoaderUnloadImageExtraAction(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
VOID EFIAPI PeCoffLoaderRelocateImageExtraAction(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112