123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- /**@file
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- Module Name:
- WinNtThunk.c
- Abstract:
- Since the SEC is the only windows program in our emulation we
- must use a Tiano mechanism to export Win32 APIs to other modules.
- This is the role of the EFI_WIN_NT_THUNK_PROTOCOL.
- The mWinNtThunkTable exists so that a change to EFI_WIN_NT_THUNK_PROTOCOL
- will cause an error in initializing the array if all the member functions
- are not added. It looks like adding a element to end and not initializing
- it may cause the table to be initaliized with the members at the end being
- set to zero. This is bad as jumping to zero will case the NT32 to crash.
- All the member functions in mWinNtThunkTable are Win32
- API calls, so please reference Microsoft documentation.
- gWinNt is a a public exported global that contains the initialized
- data.
- **/
- #include "WinHost.h"
- UINTN
- SecWriteStdErr (
- IN UINT8 *Buffer,
- IN UINTN NumberOfBytes
- )
- {
- BOOL Success;
- DWORD CharCount;
- CharCount = (DWORD)NumberOfBytes;
- Success = WriteFile (
- GetStdHandle (STD_ERROR_HANDLE),
- Buffer,
- CharCount,
- &CharCount,
- NULL
- );
- return Success ? CharCount : 0;
- }
- EFI_STATUS
- SecConfigStdIn (
- VOID
- )
- {
- BOOL Success;
- DWORD Mode;
- Success = GetConsoleMode (GetStdHandle (STD_INPUT_HANDLE), &Mode);
- if (Success) {
- //
- // Disable buffer (line input), echo, mouse, window
- //
- Mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
- #if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
- //
- // Enable virtual terminal input for Win10 above TH2
- //
- Mode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
- #endif
- Success = SetConsoleMode (GetStdHandle (STD_INPUT_HANDLE), Mode);
- }
- #if defined (NTDDI_VERSION) && defined (NTDDI_WIN10_TH2) && (NTDDI_VERSION > NTDDI_WIN10_TH2)
- //
- // Enable terminal mode for Win10 above TH2
- //
- if (Success) {
- Success = GetConsoleMode (GetStdHandle (STD_OUTPUT_HANDLE), &Mode);
- if (Success) {
- Success = SetConsoleMode (
- GetStdHandle (STD_OUTPUT_HANDLE),
- Mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN
- );
- }
- }
- #endif
- return Success ? EFI_SUCCESS : EFI_DEVICE_ERROR;
- }
- UINTN
- SecWriteStdOut (
- IN UINT8 *Buffer,
- IN UINTN NumberOfBytes
- )
- {
- BOOL Success;
- DWORD CharCount;
- CharCount = (DWORD)NumberOfBytes;
- Success = WriteFile (
- GetStdHandle (STD_OUTPUT_HANDLE),
- Buffer,
- CharCount,
- &CharCount,
- NULL
- );
- return Success ? CharCount : 0;
- }
- BOOLEAN
- SecPollStdIn (
- VOID
- )
- {
- BOOL Success;
- INPUT_RECORD Record;
- DWORD RecordNum;
- do {
- Success = GetNumberOfConsoleInputEvents (GetStdHandle (STD_INPUT_HANDLE), &RecordNum);
- if (!Success || (RecordNum == 0)) {
- break;
- }
- Success = PeekConsoleInput (
- GetStdHandle (STD_INPUT_HANDLE),
- &Record,
- 1,
- &RecordNum
- );
- if (Success && (RecordNum == 1)) {
- if ((Record.EventType == KEY_EVENT) && Record.Event.KeyEvent.bKeyDown) {
- return TRUE;
- } else {
- //
- // Consume the non-key event.
- //
- Success = ReadConsoleInput (
- GetStdHandle (STD_INPUT_HANDLE),
- &Record,
- 1,
- &RecordNum
- );
- }
- }
- } while (Success);
- return FALSE;
- }
- UINTN
- SecReadStdIn (
- IN UINT8 *Buffer,
- IN UINTN NumberOfBytes
- )
- {
- BOOL Success;
- INPUT_RECORD Record;
- DWORD RecordNum;
- UINTN BytesReturn;
- if (!SecPollStdIn ()) {
- return 0;
- }
- Success = ReadConsoleInput (
- GetStdHandle (STD_INPUT_HANDLE),
- &Record,
- 1,
- &RecordNum
- );
- ASSERT (Success && (RecordNum == 1) && (Record.EventType == KEY_EVENT) && (Record.Event.KeyEvent.bKeyDown));
- NumberOfBytes = MIN (Record.Event.KeyEvent.wRepeatCount, NumberOfBytes);
- BytesReturn = NumberOfBytes;
- while (NumberOfBytes-- != 0) {
- Buffer[NumberOfBytes] = Record.Event.KeyEvent.uChar.AsciiChar;
- }
- return BytesReturn;
- }
- VOID *
- SecAlloc (
- IN UINTN Size
- )
- {
- return malloc ((size_t)Size);
- }
- BOOLEAN
- SecFree (
- IN VOID *Ptr
- )
- {
- if (EfiSystemMemoryRange (Ptr)) {
- // If an address range is in the EFI memory map it was alloced via EFI.
- // So don't free those ranges and let the caller know.
- return FALSE;
- }
- free (Ptr);
- return TRUE;
- }
- //
- // Define a global that we can use to shut down the NT timer thread when
- // the timer is canceled.
- //
- BOOLEAN mCancelTimerThread = FALSE;
- //
- // The notification function to call on every timer interrupt
- //
- EMU_SET_TIMER_CALLBACK *mTimerNotifyFunction = NULL;
- //
- // The thread handle for this driver
- //
- HANDLE mNtMainThreadHandle;
- //
- // The timer value from the last timer interrupt
- //
- UINT32 mNtLastTick;
- //
- // Critical section used to update varibles shared between the main thread and
- // the timer interrupt thread.
- //
- CRITICAL_SECTION mNtCriticalSection;
- //
- // Worker Functions
- //
- UINT mMMTimerThreadID = 0;
- volatile BOOLEAN mInterruptEnabled = FALSE;
- VOID
- CALLBACK
- MMTimerThread (
- UINT wTimerID,
- UINT msg,
- DWORD dwUser,
- DWORD dw1,
- DWORD dw2
- )
- {
- UINT32 CurrentTick;
- UINT32 Delta;
- if (!mCancelTimerThread) {
- //
- // Suspend the main thread until we are done.
- // Enter the critical section before suspending
- // and leave the critical section after resuming
- // to avoid deadlock between main and timer thread.
- //
- EnterCriticalSection (&mNtCriticalSection);
- SuspendThread (mNtMainThreadHandle);
- //
- // If the timer thread is being canceled, then bail immediately.
- // We check again here because there's a small window of time from when
- // this thread was kicked off and when we suspended the main thread above.
- //
- if (mCancelTimerThread) {
- ResumeThread (mNtMainThreadHandle);
- LeaveCriticalSection (&mNtCriticalSection);
- timeKillEvent (wTimerID);
- mMMTimerThreadID = 0;
- return;
- }
- while (!mInterruptEnabled) {
- //
- // Resume the main thread
- //
- ResumeThread (mNtMainThreadHandle);
- LeaveCriticalSection (&mNtCriticalSection);
- //
- // Wait for interrupts to be enabled.
- //
- while (!mInterruptEnabled) {
- Sleep (1);
- }
- //
- // Suspend the main thread until we are done
- //
- EnterCriticalSection (&mNtCriticalSection);
- SuspendThread (mNtMainThreadHandle);
- }
- //
- // Get the current system tick
- //
- CurrentTick = GetTickCount ();
- Delta = CurrentTick - mNtLastTick;
- mNtLastTick = CurrentTick;
- //
- // If delay was more then 1 second, ignore it (probably debugging case)
- //
- if (Delta < 1000) {
- //
- // Only invoke the callback function if a Non-NULL handler has been
- // registered. Assume all other handlers are legal.
- //
- if (mTimerNotifyFunction != NULL) {
- mTimerNotifyFunction (Delta);
- }
- }
- //
- // Resume the main thread
- //
- ResumeThread (mNtMainThreadHandle);
- LeaveCriticalSection (&mNtCriticalSection);
- } else {
- timeKillEvent (wTimerID);
- mMMTimerThreadID = 0;
- }
- }
- VOID
- SecSetTimer (
- IN UINT64 TimerPeriod,
- IN EMU_SET_TIMER_CALLBACK Callback
- )
- {
- //
- // If TimerPeriod is 0, then the timer thread should be canceled
- //
- if (TimerPeriod == 0) {
- //
- // Cancel the timer thread
- //
- EnterCriticalSection (&mNtCriticalSection);
- mCancelTimerThread = TRUE;
- LeaveCriticalSection (&mNtCriticalSection);
- //
- // Wait for the timer thread to exit
- //
- if (mMMTimerThreadID != 0) {
- timeKillEvent (mMMTimerThreadID);
- mMMTimerThreadID = 0;
- }
- } else {
- //
- // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread
- //
- EnterCriticalSection (&mNtCriticalSection);
- mCancelTimerThread = FALSE;
- LeaveCriticalSection (&mNtCriticalSection);
- //
- // Get the starting tick location if we are just starting the timer thread
- //
- mNtLastTick = GetTickCount ();
- if (mMMTimerThreadID) {
- timeKillEvent (mMMTimerThreadID);
- }
- SetThreadPriority (
- GetCurrentThread (),
- THREAD_PRIORITY_HIGHEST
- );
- mMMTimerThreadID = timeSetEvent (
- (UINT)TimerPeriod,
- 0,
- MMTimerThread,
- (DWORD_PTR)NULL,
- TIME_PERIODIC | TIME_KILL_SYNCHRONOUS | TIME_CALLBACK_FUNCTION
- );
- }
- mTimerNotifyFunction = Callback;
- }
- VOID
- SecInitializeThunk (
- VOID
- )
- {
- InitializeCriticalSection (&mNtCriticalSection);
- DuplicateHandle (
- GetCurrentProcess (),
- GetCurrentThread (),
- GetCurrentProcess (),
- &mNtMainThreadHandle,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS
- );
- }
- VOID
- SecEnableInterrupt (
- VOID
- )
- {
- mInterruptEnabled = TRUE;
- }
- VOID
- SecDisableInterrupt (
- VOID
- )
- {
- mInterruptEnabled = FALSE;
- }
- UINT64
- SecQueryPerformanceFrequency (
- VOID
- )
- {
- // Hard code to nanoseconds
- return 1000000000ULL;
- }
- UINT64
- SecQueryPerformanceCounter (
- VOID
- )
- {
- return 0;
- }
- VOID
- SecSleep (
- IN UINT64 Nanoseconds
- )
- {
- Sleep ((DWORD)DivU64x32 (Nanoseconds, 1000000));
- }
- VOID
- SecCpuSleep (
- VOID
- )
- {
- Sleep (1);
- }
- VOID
- SecExit (
- UINTN Status
- )
- {
- exit ((int)Status);
- }
- VOID
- SecGetTime (
- OUT EFI_TIME *Time,
- OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
- )
- {
- SYSTEMTIME SystemTime;
- TIME_ZONE_INFORMATION TimeZone;
- GetLocalTime (&SystemTime);
- GetTimeZoneInformation (&TimeZone);
- Time->Year = (UINT16)SystemTime.wYear;
- Time->Month = (UINT8)SystemTime.wMonth;
- Time->Day = (UINT8)SystemTime.wDay;
- Time->Hour = (UINT8)SystemTime.wHour;
- Time->Minute = (UINT8)SystemTime.wMinute;
- Time->Second = (UINT8)SystemTime.wSecond;
- Time->Nanosecond = (UINT32)(SystemTime.wMilliseconds * 1000000);
- Time->TimeZone = (INT16)TimeZone.Bias;
- if (Capabilities != NULL) {
- Capabilities->Resolution = 1;
- Capabilities->Accuracy = 50000000;
- Capabilities->SetsToZero = FALSE;
- }
- Time->Daylight = 0;
- if (TimeZone.StandardDate.wMonth) {
- Time->Daylight = (UINT8)TimeZone.StandardDate.wMonth;
- }
- }
- EFI_STATUS
- SecSetTime (
- IN EFI_TIME *Time
- )
- {
- TIME_ZONE_INFORMATION TimeZone;
- SYSTEMTIME SystemTime;
- BOOL Flag;
- //
- // Set Daylight savings time information and Time Zone
- //
- GetTimeZoneInformation (&TimeZone);
- TimeZone.StandardDate.wMonth = Time->Daylight;
- TimeZone.Bias = Time->TimeZone;
- Flag = SetTimeZoneInformation (&TimeZone);
- if (!Flag) {
- return EFI_DEVICE_ERROR;
- }
- SystemTime.wYear = Time->Year;
- SystemTime.wMonth = Time->Month;
- SystemTime.wDay = Time->Day;
- SystemTime.wHour = Time->Hour;
- SystemTime.wMinute = Time->Minute;
- SystemTime.wSecond = Time->Second;
- SystemTime.wMilliseconds = (INT16)(Time->Nanosecond / 1000000);
- Flag = SetLocalTime (&SystemTime);
- if (!Flag) {
- return EFI_DEVICE_ERROR;
- } else {
- return EFI_SUCCESS;
- }
- }
- EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
- SecWriteStdErr,
- SecConfigStdIn,
- SecWriteStdOut,
- SecReadStdIn,
- SecPollStdIn,
- SecAlloc,
- NULL,
- SecFree,
- SecPeCoffGetEntryPoint,
- PeCoffLoaderRelocateImageExtraAction,
- PeCoffLoaderUnloadImageExtraAction,
- SecEnableInterrupt,
- SecDisableInterrupt,
- SecQueryPerformanceFrequency,
- SecQueryPerformanceCounter,
- SecSleep,
- SecCpuSleep,
- SecExit,
- SecGetTime,
- SecSetTime,
- SecSetTimer,
- GetNextThunkProtocol
- };
- #pragma warning(default : 4996)
- #pragma warning(default : 4232)
|