3 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Since the SEC is the only windows program in our emulation we
19 must use a Tiano mechanism to export Win32 APIs to other modules.
20 This is the role of the EFI_WIN_NT_THUNK_PROTOCOL.
22 The mWinNtThunkTable exists so that a change to EFI_WIN_NT_THUNK_PROTOCOL
23 will cause an error in initializing the array if all the member functions
24 are not added. It looks like adding a element to end and not initializing
25 it may cause the table to be initaliized with the members at the end being
26 set to zero. This is bad as jumping to zero will case the NT32 to crash.
28 All the member functions in mWinNtThunkTable are Win32
29 API calls, so please reference Microsoft documentation.
32 gWinNt is a a public exported global that contains the initialized
42 IN UINTN NumberOfBytes
48 CharCount
= (DWORD
)NumberOfBytes
;
50 GetStdHandle (STD_ERROR_HANDLE
),
57 return Success
? CharCount
: 0;
69 Success
= GetConsoleMode (GetStdHandle (STD_INPUT_HANDLE
), &Mode
);
72 // Disable buffer (line input), echo, mouse, window
74 Mode
&= ~(ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
);
76 #if defined(NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
78 // Enable virtual terminal input for Win10 above TH2
80 Mode
|= ENABLE_VIRTUAL_TERMINAL_INPUT
;
83 Success
= SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE
), Mode
);
86 #if defined(NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
88 // Enable terminal mode for Win10 above TH2
91 Success
= GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE
), &Mode
);
93 Success
= SetConsoleMode (
94 GetStdHandle (STD_OUTPUT_HANDLE
),
95 Mode
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
| DISABLE_NEWLINE_AUTO_RETURN
100 return Success
? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
106 IN UINTN NumberOfBytes
112 CharCount
= (DWORD
)NumberOfBytes
;
113 Success
= WriteFile (
114 GetStdHandle (STD_OUTPUT_HANDLE
),
121 return Success
? CharCount
: 0;
134 Success
= GetNumberOfConsoleInputEvents (GetStdHandle (STD_INPUT_HANDLE
), &RecordNum
);
135 if (!Success
|| (RecordNum
== 0)) {
138 Success
= PeekConsoleInput (
139 GetStdHandle (STD_INPUT_HANDLE
),
144 if (Success
&& (RecordNum
== 1)) {
145 if (Record
.EventType
== KEY_EVENT
&& Record
.Event
.KeyEvent
.bKeyDown
) {
149 // Consume the non-key event.
151 Success
= ReadConsoleInput (
152 GetStdHandle (STD_INPUT_HANDLE
),
167 IN UINTN NumberOfBytes
175 if (!SecPollStdIn ()) {
178 Success
= ReadConsoleInput (
179 GetStdHandle (STD_INPUT_HANDLE
),
184 ASSERT (Success
&& (RecordNum
== 1) && (Record
.EventType
== KEY_EVENT
) && (Record
.Event
.KeyEvent
.bKeyDown
));
185 NumberOfBytes
= MIN (Record
.Event
.KeyEvent
.wRepeatCount
, NumberOfBytes
);
186 BytesReturn
= NumberOfBytes
;
187 while (NumberOfBytes
-- != 0) {
188 Buffer
[NumberOfBytes
] = Record
.Event
.KeyEvent
.uChar
.AsciiChar
;
199 return malloc ((size_t)Size
);
207 if (EfiSystemMemoryRange (Ptr
)) {
208 // If an address range is in the EFI memory map it was alloced via EFI.
209 // So don't free those ranges and let the caller know.
220 // Define a global that we can use to shut down the NT timer thread when
221 // the timer is canceled.
223 BOOLEAN mCancelTimerThread
= FALSE
;
226 // The notification function to call on every timer interrupt
228 EMU_SET_TIMER_CALLBACK
*mTimerNotifyFunction
= NULL
;
231 // The thread handle for this driver
233 HANDLE mNtMainThreadHandle
;
236 // The timer value from the last timer interrupt
241 // Critical section used to update varibles shared between the main thread and
242 // the timer interrupt thread.
244 CRITICAL_SECTION mNtCriticalSection
;
249 UINT mMMTimerThreadID
= 0;
251 volatile BOOLEAN mInterruptEnabled
= FALSE
;
266 if (!mCancelTimerThread
) {
269 // Suspend the main thread until we are done.
270 // Enter the critical section before suspending
271 // and leave the critical section after resuming
272 // to avoid deadlock between main and timer thread.
274 EnterCriticalSection (&mNtCriticalSection
);
275 SuspendThread (mNtMainThreadHandle
);
278 // If the timer thread is being canceled, then bail immediately.
279 // We check again here because there's a small window of time from when
280 // this thread was kicked off and when we suspended the main thread above.
282 if (mCancelTimerThread
) {
283 ResumeThread (mNtMainThreadHandle
);
284 LeaveCriticalSection (&mNtCriticalSection
);
285 timeKillEvent (wTimerID
);
286 mMMTimerThreadID
= 0;
290 while (!mInterruptEnabled
) {
292 // Resume the main thread
294 ResumeThread (mNtMainThreadHandle
);
295 LeaveCriticalSection (&mNtCriticalSection
);
298 // Wait for interrupts to be enabled.
300 while (!mInterruptEnabled
) {
305 // Suspend the main thread until we are done
307 EnterCriticalSection (&mNtCriticalSection
);
308 SuspendThread (mNtMainThreadHandle
);
312 // Get the current system tick
314 CurrentTick
= GetTickCount ();
315 Delta
= CurrentTick
- mNtLastTick
;
316 mNtLastTick
= CurrentTick
;
319 // If delay was more then 1 second, ignore it (probably debugging case)
324 // Only invoke the callback function if a Non-NULL handler has been
325 // registered. Assume all other handlers are legal.
327 if (mTimerNotifyFunction
!= NULL
) {
328 mTimerNotifyFunction (Delta
);
333 // Resume the main thread
335 ResumeThread (mNtMainThreadHandle
);
336 LeaveCriticalSection (&mNtCriticalSection
);
338 timeKillEvent (wTimerID
);
339 mMMTimerThreadID
= 0;
346 IN UINT64 TimerPeriod
,
347 IN EMU_SET_TIMER_CALLBACK Callback
351 // If TimerPeriod is 0, then the timer thread should be canceled
353 if (TimerPeriod
== 0) {
355 // Cancel the timer thread
357 EnterCriticalSection (&mNtCriticalSection
);
359 mCancelTimerThread
= TRUE
;
361 LeaveCriticalSection (&mNtCriticalSection
);
364 // Wait for the timer thread to exit
367 if (mMMTimerThreadID
!= 0) {
368 timeKillEvent (mMMTimerThreadID
);
369 mMMTimerThreadID
= 0;
373 // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread
375 EnterCriticalSection (&mNtCriticalSection
);
377 mCancelTimerThread
= FALSE
;
379 LeaveCriticalSection (&mNtCriticalSection
);
382 // Get the starting tick location if we are just starting the timer thread
384 mNtLastTick
= GetTickCount ();
386 if (mMMTimerThreadID
) {
387 timeKillEvent (mMMTimerThreadID
);
392 THREAD_PRIORITY_HIGHEST
395 mMMTimerThreadID
= timeSetEvent (
400 TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
| TIME_CALLBACK_FUNCTION
403 mTimerNotifyFunction
= Callback
;
411 InitializeCriticalSection (&mNtCriticalSection
);
414 GetCurrentProcess (),
416 GetCurrentProcess (),
417 &mNtMainThreadHandle
,
420 DUPLICATE_SAME_ACCESS
429 mInterruptEnabled
= TRUE
;
434 SecDisableInterrupt (
438 mInterruptEnabled
= FALSE
;
443 SecQueryPerformanceFrequency (
447 // Hard code to nanoseconds
448 return 1000000000ULL;
452 SecQueryPerformanceCounter (
463 IN UINT64 Nanoseconds
466 Sleep ((DWORD
)DivU64x32 (Nanoseconds
, 1000000));
491 OUT EFI_TIME_CAPABILITIES
*Capabilities OPTIONAL
494 SYSTEMTIME SystemTime
;
495 TIME_ZONE_INFORMATION TimeZone
;
497 GetLocalTime (&SystemTime
);
498 GetTimeZoneInformation (&TimeZone
);
500 Time
->Year
= (UINT16
)SystemTime
.wYear
;
501 Time
->Month
= (UINT8
)SystemTime
.wMonth
;
502 Time
->Day
= (UINT8
)SystemTime
.wDay
;
503 Time
->Hour
= (UINT8
)SystemTime
.wHour
;
504 Time
->Minute
= (UINT8
)SystemTime
.wMinute
;
505 Time
->Second
= (UINT8
)SystemTime
.wSecond
;
506 Time
->Nanosecond
= (UINT32
)(SystemTime
.wMilliseconds
* 1000000);
507 Time
->TimeZone
= (INT16
)TimeZone
.Bias
;
509 if (Capabilities
!= NULL
) {
510 Capabilities
->Resolution
= 1;
511 Capabilities
->Accuracy
= 50000000;
512 Capabilities
->SetsToZero
= FALSE
;
516 if (TimeZone
.StandardDate
.wMonth
) {
517 Time
->Daylight
= (UINT8
)TimeZone
.StandardDate
.wMonth
;
526 TIME_ZONE_INFORMATION TimeZone
;
527 SYSTEMTIME SystemTime
;
531 // Set Daylight savings time information and Time Zone
533 GetTimeZoneInformation (&TimeZone
);
534 TimeZone
.StandardDate
.wMonth
= Time
->Daylight
;
535 TimeZone
.Bias
= Time
->TimeZone
;
536 Flag
= SetTimeZoneInformation (&TimeZone
);
538 return EFI_DEVICE_ERROR
;
541 SystemTime
.wYear
= Time
->Year
;
542 SystemTime
.wMonth
= Time
->Month
;
543 SystemTime
.wDay
= Time
->Day
;
544 SystemTime
.wHour
= Time
->Hour
;
545 SystemTime
.wMinute
= Time
->Minute
;
546 SystemTime
.wSecond
= Time
->Second
;
547 SystemTime
.wMilliseconds
= (INT16
)(Time
->Nanosecond
/ 1000000);
549 Flag
= SetLocalTime (&SystemTime
);
552 return EFI_DEVICE_ERROR
;
558 EMU_THUNK_PROTOCOL gEmuThunkProtocol
= {
567 SecPeCoffGetEntryPoint
,
568 PeCoffLoaderRelocateImageExtraAction
,
569 PeCoffLoaderUnloadImageExtraAction
,
572 SecQueryPerformanceFrequency
,
573 SecQueryPerformanceCounter
,
584 #pragma warning(default : 4996)
585 #pragma warning(default : 4232)