+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ ConsoleOut.c\r
+\r
+Abstract:\r
+\r
+ Console based on Win32 APIs. \r
+\r
+ This file creates an Win32 window and attaches a SimpleTextOut protocol.\r
+\r
+--*/\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <Uefi.h>\r
+#include <WinNtDxe.h>\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/WinNtIo.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/ComponentName.h>\r
+#include <Protocol/DriverBinding.h>\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+\r
+#include "Console.h"\r
+//\r
+// Private worker functions.\r
+//\r
+\r
+STATIC\r
+VOID\r
+WinNtSimpleTextOutScrollScreen (\r
+ IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console\r
+ );\r
+\r
+STATIC\r
+VOID\r
+WinNtSimpleTextOutPutChar (\r
+ IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console,\r
+ IN CHAR16 Char\r
+ );\r
+\r
+//\r
+// Modeule Global for Simple Text Out Mode.\r
+//\r
+#define MAX_SIMPLE_TEXT_OUT_MODE \\r
+ (sizeof(mWinNtSimpleTextOutSupportedModes)/sizeof(WIN_NT_SIMPLE_TEXT_OUT_MODE))\r
+\r
+STATIC WIN_NT_SIMPLE_TEXT_OUT_MODE mWinNtSimpleTextOutSupportedModes[] = {\r
+ { 80, 25 }, \r
+ { 80, 50 }, \r
+ { 80, 43 }, \r
+ { 100, 100 }, \r
+ { 100, 999 } \r
+};\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutReset (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ ExtendedVerification - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ WinNtSimpleTextOutSetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK));\r
+\r
+ WinNtSimpleTextOutSetMode (This, 0);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutOutputString (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN CHAR16 *String\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ String - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+ CHAR16 *Str;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ for (Str = String; *Str != '\0'; Str++) {\r
+ switch (*Str) {\r
+ case '\n':\r
+ if (Private->Possition.Y == (Private->MaxScreenSize.Y - 1)) {\r
+ WinNtSimpleTextOutScrollScreen (Private);\r
+ }\r
+\r
+ if (Private->Possition.Y < (Private->MaxScreenSize.Y - 1)) {\r
+ Private->Possition.Y++;\r
+ This->Mode->CursorRow++;\r
+ }\r
+ break;\r
+\r
+ case '\r':\r
+ Private->Possition.X = 0;\r
+ This->Mode->CursorColumn = 0;\r
+ break;\r
+\r
+ case '\b':\r
+ if (Private->Possition.X > 0) {\r
+ Private->Possition.X--;\r
+ This->Mode->CursorColumn--;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ WinNtSimpleTextOutPutChar (Private, *Str);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID\r
+WinNtSimpleTextOutPutChar (\r
+ IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console,\r
+ IN CHAR16 Char\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Console - TODO: add argument description\r
+ Char - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ SMALL_RECT Region;\r
+ COORD StrCoordinate;\r
+ COORD StrSize;\r
+ CHAR_INFO CharInfo;\r
+ BOOL Flag;\r
+\r
+ CharInfo.Char.UnicodeChar = Char;\r
+ CharInfo.Attributes = Console->Attribute;\r
+\r
+ StrSize.X = 1;\r
+ StrSize.Y = 1;\r
+ StrCoordinate.X = 0;\r
+ StrCoordinate.Y = 0;\r
+\r
+ Region.Left = (INT16) Console->Possition.X;\r
+ Region.Top = (INT16) Console->Possition.Y;\r
+ Region.Right = (INT16) (Console->Possition.X + 1);\r
+ Region.Bottom = (INT16) Console->Possition.Y;\r
+\r
+ Console->WinNtThunk->WriteConsoleOutput (\r
+ Console->NtOutHandle,\r
+ &CharInfo,\r
+ StrSize,\r
+ StrCoordinate,\r
+ &Region\r
+ );\r
+\r
+ if (Console->Possition.X >= (Console->MaxScreenSize.X - 1)) {\r
+ //\r
+ // If you print off the end wrap around\r
+ //\r
+ Console->SimpleTextOut.OutputString (&Console->SimpleTextOut, L"\n\r");\r
+ } else {\r
+ Console->Possition.X++;\r
+ Console->SimpleTextOut.Mode->CursorColumn++;\r
+ }\r
+\r
+ Flag = Console->WinNtThunk->SetConsoleCursorPosition (Console->NtOutHandle, Console->Possition);\r
+}\r
+\r
+STATIC\r
+VOID\r
+WinNtSimpleTextOutScrollScreen (\r
+ IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Console - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ SMALL_RECT Scroll;\r
+ CHAR_INFO CharInfo;\r
+ COORD Origin;\r
+\r
+ CharInfo.Char.UnicodeChar = ' ';\r
+ CharInfo.Attributes = Console->Attribute;\r
+\r
+ Origin.X = 0;\r
+ Origin.Y = 0;\r
+\r
+ Scroll.Top = 1;\r
+ Scroll.Left = 0;\r
+ Scroll.Right = (INT16) Console->MaxScreenSize.X;\r
+ Scroll.Bottom = (INT16) Console->MaxScreenSize.Y;\r
+\r
+ Console->WinNtThunk->ScrollConsoleScreenBuffer (\r
+ Console->NtOutHandle,\r
+ &Scroll,\r
+ NULL,\r
+ Origin,\r
+ &CharInfo\r
+ );\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutTestString (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN CHAR16 *String\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ String - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // BugBug: The correct answer would be a function of what code pages\r
+ // are currently loaded? For now we will just return success.\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutQueryMode (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN UINTN ModeNumber,\r
+ OUT UINTN *Columns,\r
+ OUT UINTN *Rows\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ ModeNumber - TODO: add argument description\r
+ Columns - TODO: add argument description\r
+ Rows - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_INVALID_PARAMETER - TODO: Add description for return value\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (ModeNumber > MAX_SIMPLE_TEXT_OUT_MODE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Columns = mWinNtSimpleTextOutSupportedModes[ModeNumber].ColumnsX;\r
+ *Rows = mWinNtSimpleTextOutSupportedModes[ModeNumber].RowsY;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutSetMode (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN UINTN ModeNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ ModeNumber - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_INVALID_PARAMETER - TODO: Add description for return value\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (ModeNumber > MAX_SIMPLE_TEXT_OUT_MODE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private->MaxScreenSize.X = (WORD) mWinNtSimpleTextOutSupportedModes[ModeNumber].ColumnsX;\r
+ Private->MaxScreenSize.Y = (WORD) mWinNtSimpleTextOutSupportedModes[ModeNumber].RowsY;\r
+\r
+ Private->WinNtThunk->SetConsoleScreenBufferSize (Private->NtOutHandle, Private->MaxScreenSize);\r
+ Private->WinNtThunk->SetConsoleActiveScreenBuffer (Private->NtOutHandle);\r
+\r
+ This->Mode->Mode = (INT32) ModeNumber;\r
+\r
+ This->EnableCursor (This, TRUE);\r
+ This->ClearScreen (This);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutSetAttribute (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN UINTN Attribute\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ Attribute - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Private->Attribute = (WORD) Attribute;\r
+ This->Mode->Attribute = (INT32) Attribute;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutClearScreen (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+ DWORD ConsoleWindow;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ This->SetCursorPosition (This, 0, 0);\r
+\r
+ Private->WinNtThunk->FillConsoleOutputCharacter (\r
+ Private->NtOutHandle,\r
+ ' ',\r
+ Private->MaxScreenSize.X * Private->MaxScreenSize.Y,\r
+ Private->Possition,\r
+ &ConsoleWindow\r
+ );\r
+ Private->WinNtThunk->FillConsoleOutputAttribute (\r
+ Private->NtOutHandle,\r
+ Private->Attribute,\r
+ Private->MaxScreenSize.X * Private->MaxScreenSize.Y,\r
+ Private->Possition,\r
+ &ConsoleWindow\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutSetCursorPosition (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN UINTN Column,\r
+ IN UINTN Row\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ Column - TODO: add argument description\r
+ Row - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Private->Possition.X = (WORD) Column;\r
+ This->Mode->CursorColumn = (INT32) Column;\r
+\r
+ Private->Possition.Y = (WORD) Row;\r
+ This->Mode->CursorRow = (INT32) Row;\r
+ Private->WinNtThunk->SetConsoleCursorPosition (Private->NtOutHandle, Private->Possition);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+WinNtSimpleTextOutEnableCursor (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN BOOLEAN Enable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ This - TODO: add argument description\r
+ Enable - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private;\r
+ CONSOLE_CURSOR_INFO Info;\r
+\r
+ Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This);\r
+ Private->CursorEnable = Enable;\r
+ This->Mode->CursorVisible = Enable;\r
+\r
+ Private->WinNtThunk->GetConsoleCursorInfo (Private->NtOutHandle, &Info);\r
+ Info.bVisible = Enable;\r
+ Private->WinNtThunk->SetConsoleCursorInfo (Private->NtOutHandle, &Info);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+WinNtSimpleTextOutOpenWindow (\r
+ IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Private - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;\r
+ CHAR16 *WindowName;\r
+\r
+ WindowName = Private->WinNtIo->EnvString;\r
+ Private->Attribute = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY;\r
+ if (*WindowName == '?') {\r
+ Private->Attribute = BACKGROUND_RED | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;\r
+ WindowName = L"EFI Emulator Error Console";\r
+ }\r
+\r
+ AddUnicodeString (\r
+ "eng",\r
+ gWinNtConsoleComponentName.SupportedLanguages,\r
+ &Private->ControllerNameTable,\r
+ WindowName\r
+ );\r
+\r
+ //\r
+ // Fill in protocol member functions\r
+ //\r
+ SimpleTextOut = &Private->SimpleTextOut;\r
+ SimpleTextOut->Reset = WinNtSimpleTextOutReset;\r
+ SimpleTextOut->OutputString = WinNtSimpleTextOutOutputString;\r
+ SimpleTextOut->TestString = WinNtSimpleTextOutTestString;\r
+ SimpleTextOut->QueryMode = WinNtSimpleTextOutQueryMode;\r
+ SimpleTextOut->SetMode = WinNtSimpleTextOutSetMode;\r
+ SimpleTextOut->SetAttribute = WinNtSimpleTextOutSetAttribute;\r
+ SimpleTextOut->ClearScreen = WinNtSimpleTextOutClearScreen;\r
+ SimpleTextOut->SetCursorPosition = WinNtSimpleTextOutSetCursorPosition;\r
+ SimpleTextOut->EnableCursor = WinNtSimpleTextOutEnableCursor;\r
+\r
+ //\r
+ // Initialize SimpleTextOut protocol mode structure\r
+ //\r
+ SimpleTextOut->Mode = &Private->SimpleTextOutMode;\r
+ SimpleTextOut->Mode->MaxMode = MAX_SIMPLE_TEXT_OUT_MODE;\r
+ SimpleTextOut->Mode->Attribute = (INT32) Private->Attribute;\r
+\r
+ //\r
+ // Open the window an initialize it!\r
+ //\r
+ Private->NtOutHandle = Private->WinNtThunk->CreateConsoleScreenBuffer (\r
+ GENERIC_WRITE | GENERIC_READ,\r
+ FILE_SHARE_WRITE | FILE_SHARE_READ,\r
+ NULL,\r
+ CONSOLE_TEXTMODE_BUFFER,\r
+ NULL\r
+ );\r
+ Private->WinNtThunk->SetConsoleTitle (WindowName);\r
+\r
+ return SimpleTextOut->SetMode (SimpleTextOut, 0);\r
+}\r
+\r
+EFI_STATUS\r
+WinNtSimpleTextOutCloseWindow (\r
+ IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Console - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+ Console->WinNtThunk->CloseHandle (Console->NtOutHandle);\r
+ return EFI_SUCCESS;\r
+}\r