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 Success
= SetConsoleMode (
75 GetStdHandle (STD_INPUT_HANDLE
),
76 Mode
| ENABLE_VIRTUAL_TERMINAL_INPUT
& ~(ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
)
81 // Enable terminal mode
83 Success
= GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE
), &Mode
);
85 Success
= SetConsoleMode (
86 GetStdHandle (STD_OUTPUT_HANDLE
),
87 Mode
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
| DISABLE_NEWLINE_AUTO_RETURN
91 return Success
? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
97 IN UINTN NumberOfBytes
103 CharCount
= (DWORD
)NumberOfBytes
;
104 Success
= WriteFile (
105 GetStdHandle (STD_OUTPUT_HANDLE
),
112 return Success
? CharCount
: 0;
125 Success
= GetNumberOfConsoleInputEvents (GetStdHandle (STD_INPUT_HANDLE
), &RecordNum
);
126 if (!Success
|| (RecordNum
== 0)) {
129 Success
= PeekConsoleInput (
130 GetStdHandle (STD_INPUT_HANDLE
),
135 if (Success
&& (RecordNum
== 1)) {
136 if (Record
.EventType
== KEY_EVENT
&& Record
.Event
.KeyEvent
.bKeyDown
) {
140 // Consume the non-key event.
142 Success
= ReadConsoleInput (
143 GetStdHandle (STD_INPUT_HANDLE
),
158 IN UINTN NumberOfBytes
166 if (!SecPollStdIn ()) {
169 Success
= ReadConsoleInput (
170 GetStdHandle (STD_INPUT_HANDLE
),
175 ASSERT (Success
&& (RecordNum
== 1) && (Record
.EventType
== KEY_EVENT
) && (Record
.Event
.KeyEvent
.bKeyDown
));
176 NumberOfBytes
= MIN (Record
.Event
.KeyEvent
.wRepeatCount
, NumberOfBytes
);
177 BytesReturn
= NumberOfBytes
;
178 while (NumberOfBytes
-- != 0) {
179 Buffer
[NumberOfBytes
] = Record
.Event
.KeyEvent
.uChar
.AsciiChar
;
190 return malloc ((size_t)Size
);
198 if (EfiSystemMemoryRange (Ptr
)) {
199 // If an address range is in the EFI memory map it was alloced via EFI.
200 // So don't free those ranges and let the caller know.
211 // Define a global that we can use to shut down the NT timer thread when
212 // the timer is canceled.
214 BOOLEAN mCancelTimerThread
= FALSE
;
217 // The notification function to call on every timer interrupt
219 EMU_SET_TIMER_CALLBACK
*mTimerNotifyFunction
= NULL
;
222 // The thread handle for this driver
224 HANDLE mNtMainThreadHandle
;
227 // The timer value from the last timer interrupt
232 // Critical section used to update varibles shared between the main thread and
233 // the timer interrupt thread.
235 CRITICAL_SECTION mNtCriticalSection
;
240 UINT mMMTimerThreadID
= 0;
242 volatile BOOLEAN mInterruptEnabled
= FALSE
;
257 if (!mCancelTimerThread
) {
260 // Suspend the main thread until we are done.
261 // Enter the critical section before suspending
262 // and leave the critical section after resuming
263 // to avoid deadlock between main and timer thread.
265 EnterCriticalSection (&mNtCriticalSection
);
266 SuspendThread (mNtMainThreadHandle
);
269 // If the timer thread is being canceled, then bail immediately.
270 // We check again here because there's a small window of time from when
271 // this thread was kicked off and when we suspended the main thread above.
273 if (mCancelTimerThread
) {
274 ResumeThread (mNtMainThreadHandle
);
275 LeaveCriticalSection (&mNtCriticalSection
);
276 timeKillEvent (wTimerID
);
277 mMMTimerThreadID
= 0;
281 while (!mInterruptEnabled
) {
283 // Resume the main thread
285 ResumeThread (mNtMainThreadHandle
);
286 LeaveCriticalSection (&mNtCriticalSection
);
289 // Wait for interrupts to be enabled.
291 while (!mInterruptEnabled
) {
296 // Suspend the main thread until we are done
298 EnterCriticalSection (&mNtCriticalSection
);
299 SuspendThread (mNtMainThreadHandle
);
303 // Get the current system tick
305 CurrentTick
= GetTickCount ();
306 Delta
= CurrentTick
- mNtLastTick
;
307 mNtLastTick
= CurrentTick
;
310 // If delay was more then 1 second, ignore it (probably debugging case)
315 // Only invoke the callback function if a Non-NULL handler has been
316 // registered. Assume all other handlers are legal.
318 if (mTimerNotifyFunction
!= NULL
) {
319 mTimerNotifyFunction (Delta
);
324 // Resume the main thread
326 ResumeThread (mNtMainThreadHandle
);
327 LeaveCriticalSection (&mNtCriticalSection
);
329 timeKillEvent (wTimerID
);
330 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
394 mTimerNotifyFunction
= Callback
;
402 InitializeCriticalSection (&mNtCriticalSection
);
405 GetCurrentProcess (),
407 GetCurrentProcess (),
408 &mNtMainThreadHandle
,
411 DUPLICATE_SAME_ACCESS
420 mInterruptEnabled
= TRUE
;
425 SecDisableInterrupt (
429 mInterruptEnabled
= FALSE
;
434 SecQueryPerformanceFrequency (
438 // Hard code to nanoseconds
439 return 1000000000ULL;
443 SecQueryPerformanceCounter (
454 IN UINT64 Nanoseconds
457 Sleep ((DWORD
)DivU64x32 (Nanoseconds
, 1000000));
482 OUT EFI_TIME_CAPABILITIES
*Capabilities OPTIONAL
485 SYSTEMTIME SystemTime
;
486 TIME_ZONE_INFORMATION TimeZone
;
488 GetLocalTime (&SystemTime
);
489 GetTimeZoneInformation (&TimeZone
);
491 Time
->Year
= (UINT16
)SystemTime
.wYear
;
492 Time
->Month
= (UINT8
)SystemTime
.wMonth
;
493 Time
->Day
= (UINT8
)SystemTime
.wDay
;
494 Time
->Hour
= (UINT8
)SystemTime
.wHour
;
495 Time
->Minute
= (UINT8
)SystemTime
.wMinute
;
496 Time
->Second
= (UINT8
)SystemTime
.wSecond
;
497 Time
->Nanosecond
= (UINT32
)(SystemTime
.wMilliseconds
* 1000000);
498 Time
->TimeZone
= (INT16
)TimeZone
.Bias
;
500 if (Capabilities
!= NULL
) {
501 Capabilities
->Resolution
= 1;
502 Capabilities
->Accuracy
= 50000000;
503 Capabilities
->SetsToZero
= FALSE
;
507 if (TimeZone
.StandardDate
.wMonth
) {
508 Time
->Daylight
= (UINT8
)TimeZone
.StandardDate
.wMonth
;
517 TIME_ZONE_INFORMATION TimeZone
;
518 SYSTEMTIME SystemTime
;
522 // Set Daylight savings time information and Time Zone
524 GetTimeZoneInformation (&TimeZone
);
525 TimeZone
.StandardDate
.wMonth
= Time
->Daylight
;
526 TimeZone
.Bias
= Time
->TimeZone
;
527 Flag
= SetTimeZoneInformation (&TimeZone
);
529 return EFI_DEVICE_ERROR
;
532 SystemTime
.wYear
= Time
->Year
;
533 SystemTime
.wMonth
= Time
->Month
;
534 SystemTime
.wDay
= Time
->Day
;
535 SystemTime
.wHour
= Time
->Hour
;
536 SystemTime
.wMinute
= Time
->Minute
;
537 SystemTime
.wSecond
= Time
->Second
;
538 SystemTime
.wMilliseconds
= (INT16
)(Time
->Nanosecond
/ 1000000);
540 Flag
= SetLocalTime (&SystemTime
);
543 return EFI_DEVICE_ERROR
;
549 EMU_THUNK_PROTOCOL gEmuThunkProtocol
= {
558 SecPeCoffGetEntryPoint
,
559 PeCoffLoaderRelocateImageExtraAction
,
560 PeCoffLoaderUnloadImageExtraAction
,
563 SecQueryPerformanceFrequency
,
564 SecQueryPerformanceCounter
,
575 #pragma warning(default : 4996)
576 #pragma warning(default : 4232)