3 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Since the SEC is the only windows program in our emulation we
13 must use a Tiano mechanism to export Win32 APIs to other modules.
14 This is the role of the EFI_WIN_NT_THUNK_PROTOCOL.
16 The mWinNtThunkTable exists so that a change to EFI_WIN_NT_THUNK_PROTOCOL
17 will cause an error in initializing the array if all the member functions
18 are not added. It looks like adding a element to end and not initializing
19 it may cause the table to be initaliized with the members at the end being
20 set to zero. This is bad as jumping to zero will case the NT32 to crash.
22 All the member functions in mWinNtThunkTable are Win32
23 API calls, so please reference Microsoft documentation.
26 gWinNt is a a public exported global that contains the initialized
36 IN UINTN NumberOfBytes
42 CharCount
= (DWORD
)NumberOfBytes
;
44 GetStdHandle (STD_ERROR_HANDLE
),
51 return Success
? CharCount
: 0;
62 Success
= GetConsoleMode (GetStdHandle (STD_INPUT_HANDLE
), &Mode
);
65 // Disable buffer (line input), echo, mouse, window
67 Mode
&= ~(ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
);
69 #if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
71 // Enable virtual terminal input for Win10 above TH2
73 Mode
|= ENABLE_VIRTUAL_TERMINAL_INPUT
;
76 Success
= SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE
), Mode
);
79 #if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
81 // Enable terminal mode for Win10 above TH2
84 Success
= GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE
), &Mode
);
86 Success
= SetConsoleMode (
87 GetStdHandle (STD_OUTPUT_HANDLE
),
88 Mode
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
| DISABLE_NEWLINE_AUTO_RETURN
94 return Success
? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
100 IN UINTN NumberOfBytes
106 CharCount
= (DWORD
)NumberOfBytes
;
107 Success
= WriteFile (
108 GetStdHandle (STD_OUTPUT_HANDLE
),
115 return Success
? CharCount
: 0;
128 Success
= GetNumberOfConsoleInputEvents (GetStdHandle (STD_INPUT_HANDLE
), &RecordNum
);
129 if (!Success
|| (RecordNum
== 0)) {
133 Success
= PeekConsoleInput (
134 GetStdHandle (STD_INPUT_HANDLE
),
139 if (Success
&& (RecordNum
== 1)) {
140 if ((Record
.EventType
== KEY_EVENT
) && Record
.Event
.KeyEvent
.bKeyDown
) {
144 // Consume the non-key event.
146 Success
= ReadConsoleInput (
147 GetStdHandle (STD_INPUT_HANDLE
),
162 IN UINTN NumberOfBytes
170 if (!SecPollStdIn ()) {
174 Success
= ReadConsoleInput (
175 GetStdHandle (STD_INPUT_HANDLE
),
180 ASSERT (Success
&& (RecordNum
== 1) && (Record
.EventType
== KEY_EVENT
) && (Record
.Event
.KeyEvent
.bKeyDown
));
181 NumberOfBytes
= MIN (Record
.Event
.KeyEvent
.wRepeatCount
, NumberOfBytes
);
182 BytesReturn
= NumberOfBytes
;
183 while (NumberOfBytes
-- != 0) {
184 Buffer
[NumberOfBytes
] = Record
.Event
.KeyEvent
.uChar
.AsciiChar
;
195 return malloc ((size_t)Size
);
203 if (EfiSystemMemoryRange (Ptr
)) {
204 // If an address range is in the EFI memory map it was alloced via EFI.
205 // So don't free those ranges and let the caller know.
214 // Define a global that we can use to shut down the NT timer thread when
215 // the timer is canceled.
217 BOOLEAN mCancelTimerThread
= FALSE
;
220 // The notification function to call on every timer interrupt
222 EMU_SET_TIMER_CALLBACK
*mTimerNotifyFunction
= NULL
;
225 // The thread handle for this driver
227 HANDLE mNtMainThreadHandle
;
230 // The timer value from the last timer interrupt
235 // Critical section used to update varibles shared between the main thread and
236 // the timer interrupt thread.
238 CRITICAL_SECTION mNtCriticalSection
;
243 UINT mMMTimerThreadID
= 0;
245 volatile BOOLEAN mInterruptEnabled
= FALSE
;
260 if (!mCancelTimerThread
) {
262 // Suspend the main thread until we are done.
263 // Enter the critical section before suspending
264 // and leave the critical section after resuming
265 // to avoid deadlock between main and timer thread.
267 EnterCriticalSection (&mNtCriticalSection
);
268 SuspendThread (mNtMainThreadHandle
);
271 // If the timer thread is being canceled, then bail immediately.
272 // We check again here because there's a small window of time from when
273 // this thread was kicked off and when we suspended the main thread above.
275 if (mCancelTimerThread
) {
276 ResumeThread (mNtMainThreadHandle
);
277 LeaveCriticalSection (&mNtCriticalSection
);
278 timeKillEvent (wTimerID
);
279 mMMTimerThreadID
= 0;
283 while (!mInterruptEnabled
) {
285 // Resume the main thread
287 ResumeThread (mNtMainThreadHandle
);
288 LeaveCriticalSection (&mNtCriticalSection
);
291 // Wait for interrupts to be enabled.
293 while (!mInterruptEnabled
) {
298 // Suspend the main thread until we are done
300 EnterCriticalSection (&mNtCriticalSection
);
301 SuspendThread (mNtMainThreadHandle
);
305 // Get the current system tick
307 CurrentTick
= GetTickCount ();
308 Delta
= CurrentTick
- mNtLastTick
;
309 mNtLastTick
= CurrentTick
;
312 // If delay was more then 1 second, ignore it (probably debugging case)
316 // Only invoke the callback function if a Non-NULL handler has been
317 // registered. Assume all other handlers are legal.
319 if (mTimerNotifyFunction
!= NULL
) {
320 mTimerNotifyFunction (Delta
);
325 // Resume the main thread
327 ResumeThread (mNtMainThreadHandle
);
328 LeaveCriticalSection (&mNtCriticalSection
);
330 timeKillEvent (wTimerID
);
331 mMMTimerThreadID
= 0;
337 IN UINT64 TimerPeriod
,
338 IN EMU_SET_TIMER_CALLBACK Callback
342 // If TimerPeriod is 0, then the timer thread should be canceled
344 if (TimerPeriod
== 0) {
346 // Cancel the timer thread
348 EnterCriticalSection (&mNtCriticalSection
);
350 mCancelTimerThread
= TRUE
;
352 LeaveCriticalSection (&mNtCriticalSection
);
355 // Wait for the timer thread to exit
358 if (mMMTimerThreadID
!= 0) {
359 timeKillEvent (mMMTimerThreadID
);
360 mMMTimerThreadID
= 0;
364 // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread
366 EnterCriticalSection (&mNtCriticalSection
);
368 mCancelTimerThread
= FALSE
;
370 LeaveCriticalSection (&mNtCriticalSection
);
373 // Get the starting tick location if we are just starting the timer thread
375 mNtLastTick
= GetTickCount ();
377 if (mMMTimerThreadID
) {
378 timeKillEvent (mMMTimerThreadID
);
383 THREAD_PRIORITY_HIGHEST
386 mMMTimerThreadID
= timeSetEvent (
391 TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
| TIME_CALLBACK_FUNCTION
395 mTimerNotifyFunction
= Callback
;
403 InitializeCriticalSection (&mNtCriticalSection
);
406 GetCurrentProcess (),
408 GetCurrentProcess (),
409 &mNtMainThreadHandle
,
412 DUPLICATE_SAME_ACCESS
421 mInterruptEnabled
= TRUE
;
425 SecDisableInterrupt (
429 mInterruptEnabled
= FALSE
;
433 SecQueryPerformanceFrequency (
437 // Hard code to nanoseconds
438 return 1000000000ULL;
442 SecQueryPerformanceCounter (
451 IN UINT64 Nanoseconds
454 Sleep ((DWORD
)DivU64x32 (Nanoseconds
, 1000000));
476 OUT EFI_TIME_CAPABILITIES
*Capabilities OPTIONAL
479 SYSTEMTIME SystemTime
;
480 TIME_ZONE_INFORMATION TimeZone
;
482 GetLocalTime (&SystemTime
);
483 GetTimeZoneInformation (&TimeZone
);
485 Time
->Year
= (UINT16
)SystemTime
.wYear
;
486 Time
->Month
= (UINT8
)SystemTime
.wMonth
;
487 Time
->Day
= (UINT8
)SystemTime
.wDay
;
488 Time
->Hour
= (UINT8
)SystemTime
.wHour
;
489 Time
->Minute
= (UINT8
)SystemTime
.wMinute
;
490 Time
->Second
= (UINT8
)SystemTime
.wSecond
;
491 Time
->Nanosecond
= (UINT32
)(SystemTime
.wMilliseconds
* 1000000);
492 Time
->TimeZone
= (INT16
)TimeZone
.Bias
;
494 if (Capabilities
!= NULL
) {
495 Capabilities
->Resolution
= 1;
496 Capabilities
->Accuracy
= 50000000;
497 Capabilities
->SetsToZero
= FALSE
;
501 if (TimeZone
.StandardDate
.wMonth
) {
502 Time
->Daylight
= (UINT8
)TimeZone
.StandardDate
.wMonth
;
511 TIME_ZONE_INFORMATION TimeZone
;
512 SYSTEMTIME SystemTime
;
516 // Set Daylight savings time information and Time Zone
518 GetTimeZoneInformation (&TimeZone
);
519 TimeZone
.StandardDate
.wMonth
= Time
->Daylight
;
520 TimeZone
.Bias
= Time
->TimeZone
;
521 Flag
= SetTimeZoneInformation (&TimeZone
);
523 return EFI_DEVICE_ERROR
;
526 SystemTime
.wYear
= Time
->Year
;
527 SystemTime
.wMonth
= Time
->Month
;
528 SystemTime
.wDay
= Time
->Day
;
529 SystemTime
.wHour
= Time
->Hour
;
530 SystemTime
.wMinute
= Time
->Minute
;
531 SystemTime
.wSecond
= Time
->Second
;
532 SystemTime
.wMilliseconds
= (INT16
)(Time
->Nanosecond
/ 1000000);
534 Flag
= SetLocalTime (&SystemTime
);
537 return EFI_DEVICE_ERROR
;
543 EMU_THUNK_PROTOCOL gEmuThunkProtocol
= {
552 SecPeCoffGetEntryPoint
,
553 PeCoffLoaderRelocateImageExtraAction
,
554 PeCoffLoaderUnloadImageExtraAction
,
557 SecQueryPerformanceFrequency
,
558 SecQueryPerformanceCounter
,
568 #pragma warning(default : 4996)
569 #pragma warning(default : 4232)