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;
63 Success
= GetConsoleMode (GetStdHandle (STD_INPUT_HANDLE
), &Mode
);
66 // Disable buffer (line input), echo, mouse, window
68 Mode
&= ~(ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
);
70 #if defined(NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
72 // Enable virtual terminal input for Win10 above TH2
74 Mode
|= ENABLE_VIRTUAL_TERMINAL_INPUT
;
77 Success
= SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE
), Mode
);
80 #if defined(NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
82 // Enable terminal mode for Win10 above TH2
85 Success
= GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE
), &Mode
);
87 Success
= SetConsoleMode (
88 GetStdHandle (STD_OUTPUT_HANDLE
),
89 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)) {
132 Success
= PeekConsoleInput (
133 GetStdHandle (STD_INPUT_HANDLE
),
138 if (Success
&& (RecordNum
== 1)) {
139 if (Record
.EventType
== KEY_EVENT
&& Record
.Event
.KeyEvent
.bKeyDown
) {
143 // Consume the non-key event.
145 Success
= ReadConsoleInput (
146 GetStdHandle (STD_INPUT_HANDLE
),
161 IN UINTN NumberOfBytes
169 if (!SecPollStdIn ()) {
172 Success
= ReadConsoleInput (
173 GetStdHandle (STD_INPUT_HANDLE
),
178 ASSERT (Success
&& (RecordNum
== 1) && (Record
.EventType
== KEY_EVENT
) && (Record
.Event
.KeyEvent
.bKeyDown
));
179 NumberOfBytes
= MIN (Record
.Event
.KeyEvent
.wRepeatCount
, NumberOfBytes
);
180 BytesReturn
= NumberOfBytes
;
181 while (NumberOfBytes
-- != 0) {
182 Buffer
[NumberOfBytes
] = Record
.Event
.KeyEvent
.uChar
.AsciiChar
;
193 return malloc ((size_t)Size
);
201 if (EfiSystemMemoryRange (Ptr
)) {
202 // If an address range is in the EFI memory map it was alloced via EFI.
203 // 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
) {
263 // Suspend the main thread until we are done.
264 // Enter the critical section before suspending
265 // and leave the critical section after resuming
266 // to avoid deadlock between main and timer thread.
268 EnterCriticalSection (&mNtCriticalSection
);
269 SuspendThread (mNtMainThreadHandle
);
272 // If the timer thread is being canceled, then bail immediately.
273 // We check again here because there's a small window of time from when
274 // this thread was kicked off and when we suspended the main thread above.
276 if (mCancelTimerThread
) {
277 ResumeThread (mNtMainThreadHandle
);
278 LeaveCriticalSection (&mNtCriticalSection
);
279 timeKillEvent (wTimerID
);
280 mMMTimerThreadID
= 0;
284 while (!mInterruptEnabled
) {
286 // Resume the main thread
288 ResumeThread (mNtMainThreadHandle
);
289 LeaveCriticalSection (&mNtCriticalSection
);
292 // Wait for interrupts to be enabled.
294 while (!mInterruptEnabled
) {
299 // Suspend the main thread until we are done
301 EnterCriticalSection (&mNtCriticalSection
);
302 SuspendThread (mNtMainThreadHandle
);
306 // Get the current system tick
308 CurrentTick
= GetTickCount ();
309 Delta
= CurrentTick
- mNtLastTick
;
310 mNtLastTick
= CurrentTick
;
313 // If delay was more then 1 second, ignore it (probably debugging case)
318 // Only invoke the callback function if a Non-NULL handler has been
319 // registered. Assume all other handlers are legal.
321 if (mTimerNotifyFunction
!= NULL
) {
322 mTimerNotifyFunction (Delta
);
327 // Resume the main thread
329 ResumeThread (mNtMainThreadHandle
);
330 LeaveCriticalSection (&mNtCriticalSection
);
332 timeKillEvent (wTimerID
);
333 mMMTimerThreadID
= 0;
340 IN UINT64 TimerPeriod
,
341 IN EMU_SET_TIMER_CALLBACK Callback
345 // If TimerPeriod is 0, then the timer thread should be canceled
347 if (TimerPeriod
== 0) {
349 // Cancel the timer thread
351 EnterCriticalSection (&mNtCriticalSection
);
353 mCancelTimerThread
= TRUE
;
355 LeaveCriticalSection (&mNtCriticalSection
);
358 // Wait for the timer thread to exit
361 if (mMMTimerThreadID
!= 0) {
362 timeKillEvent (mMMTimerThreadID
);
363 mMMTimerThreadID
= 0;
367 // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread
369 EnterCriticalSection (&mNtCriticalSection
);
371 mCancelTimerThread
= FALSE
;
373 LeaveCriticalSection (&mNtCriticalSection
);
376 // Get the starting tick location if we are just starting the timer thread
378 mNtLastTick
= GetTickCount ();
380 if (mMMTimerThreadID
) {
381 timeKillEvent (mMMTimerThreadID
);
386 THREAD_PRIORITY_HIGHEST
389 mMMTimerThreadID
= timeSetEvent (
394 TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
| TIME_CALLBACK_FUNCTION
397 mTimerNotifyFunction
= Callback
;
405 InitializeCriticalSection (&mNtCriticalSection
);
408 GetCurrentProcess (),
410 GetCurrentProcess (),
411 &mNtMainThreadHandle
,
414 DUPLICATE_SAME_ACCESS
423 mInterruptEnabled
= TRUE
;
428 SecDisableInterrupt (
432 mInterruptEnabled
= FALSE
;
437 SecQueryPerformanceFrequency (
441 // Hard code to nanoseconds
442 return 1000000000ULL;
446 SecQueryPerformanceCounter (
457 IN UINT64 Nanoseconds
460 Sleep ((DWORD
)DivU64x32 (Nanoseconds
, 1000000));
485 OUT EFI_TIME_CAPABILITIES
*Capabilities OPTIONAL
488 SYSTEMTIME SystemTime
;
489 TIME_ZONE_INFORMATION TimeZone
;
491 GetLocalTime (&SystemTime
);
492 GetTimeZoneInformation (&TimeZone
);
494 Time
->Year
= (UINT16
)SystemTime
.wYear
;
495 Time
->Month
= (UINT8
)SystemTime
.wMonth
;
496 Time
->Day
= (UINT8
)SystemTime
.wDay
;
497 Time
->Hour
= (UINT8
)SystemTime
.wHour
;
498 Time
->Minute
= (UINT8
)SystemTime
.wMinute
;
499 Time
->Second
= (UINT8
)SystemTime
.wSecond
;
500 Time
->Nanosecond
= (UINT32
)(SystemTime
.wMilliseconds
* 1000000);
501 Time
->TimeZone
= (INT16
)TimeZone
.Bias
;
503 if (Capabilities
!= NULL
) {
504 Capabilities
->Resolution
= 1;
505 Capabilities
->Accuracy
= 50000000;
506 Capabilities
->SetsToZero
= FALSE
;
510 if (TimeZone
.StandardDate
.wMonth
) {
511 Time
->Daylight
= (UINT8
)TimeZone
.StandardDate
.wMonth
;
520 TIME_ZONE_INFORMATION TimeZone
;
521 SYSTEMTIME SystemTime
;
525 // Set Daylight savings time information and Time Zone
527 GetTimeZoneInformation (&TimeZone
);
528 TimeZone
.StandardDate
.wMonth
= Time
->Daylight
;
529 TimeZone
.Bias
= Time
->TimeZone
;
530 Flag
= SetTimeZoneInformation (&TimeZone
);
532 return EFI_DEVICE_ERROR
;
535 SystemTime
.wYear
= Time
->Year
;
536 SystemTime
.wMonth
= Time
->Month
;
537 SystemTime
.wDay
= Time
->Day
;
538 SystemTime
.wHour
= Time
->Hour
;
539 SystemTime
.wMinute
= Time
->Minute
;
540 SystemTime
.wSecond
= Time
->Second
;
541 SystemTime
.wMilliseconds
= (INT16
)(Time
->Nanosecond
/ 1000000);
543 Flag
= SetLocalTime (&SystemTime
);
546 return EFI_DEVICE_ERROR
;
552 EMU_THUNK_PROTOCOL gEmuThunkProtocol
= {
561 SecPeCoffGetEntryPoint
,
562 PeCoffLoaderRelocateImageExtraAction
,
563 PeCoffLoaderUnloadImageExtraAction
,
566 SecQueryPerformanceFrequency
,
567 SecQueryPerformanceCounter
,
578 #pragma warning(default : 4996)
579 #pragma warning(default : 4232)