+ if (Status != EFI_ALREADY_STARTED) {\r
+ //\r
+ // the serial I/O protocol never be opened before, it is the first\r
+ // time to start the serial Io controller\r
+ //\r
+ FirstEnter = TRUE;\r
+ }\r
+\r
+ //\r
+ // Serial I/O is not already open by this driver, then tag the handle\r
+ // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
+ // StdErrDev variables with the list of possible terminal types on this\r
+ // serial port.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiCallerIdGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Controller,\r
+ &gEfiCallerIdGuid,\r
+ DuplicateDevicePath (ParentDevicePath),\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ if (!IsHotPlugDevice (ParentDevicePath)) {\r
+ //\r
+ // if the serial device is a hot plug device, do not update the\r
+ // ConInDev, ConOutDev, and StdErrDev variables.\r
+ //\r
+ TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
+ TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
+ TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols\r
+ //\r
+ // Simple In/Out Protocol will not be installed onto the handle if the\r
+ // device path to the handle is not present in the ConIn/ConOut\r
+ // environment variable. But If RemainingDevicePath is NULL, then always\r
+ // produce both Simple In and Simple Text Output Protocols. This is required\r
+ // for the connect all sequences to make sure all possible consoles are\r
+ // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
+ //\r
+ if (RemainingDevicePath == NULL) {\r
+ NullRemaining = TRUE;\r
+ }\r
+\r
+ DevicePath = BuildTerminalDevpath (ParentDevicePath, RemainingDevicePath);\r
+ if (DevicePath != NULL) {\r
+ ConInSelected = IsTerminalInConsoleVariable (L"ConIn", DevicePath);\r
+ ConOutSelected = IsTerminalInConsoleVariable (L"ConOut", DevicePath);\r
+ FreePool (DevicePath);\r
+ } else {\r
+ goto Error;\r
+ }\r
+ //\r
+ // Not create the child terminal handle if both Simple In/In Ex and\r
+ // Simple text Out protocols are not required to be published\r
+ //\r
+ if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // create the child terminal handle during first entry\r
+ //\r
+ if (FirstEnter) {\r
+ //\r
+ // First enther the start function\r
+ //\r
+ FirstEnter = FALSE;\r
+ //\r
+ // Make sure a child handle does not already exist. This driver can only\r
+ // produce one child per serial port.\r
+ //\r
+ Status = gBS->OpenProtocolInformation (\r
+ Controller,\r
+ &gEfiSerialIoProtocolGuid,\r
+ &OpenInfoBuffer,\r
+ &EntryCount\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_SUCCESS;\r
+ for (Index = 0; Index < EntryCount; Index++) {\r
+ if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+ Status = EFI_ALREADY_STARTED;\r
+ }\r
+ }\r
+\r
+ FreePool (OpenInfoBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If RemainingDevicePath is NULL, use default terminal type\r
+ //\r
+ if (RemainingDevicePath == NULL) {\r
+ TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
+ //\r
+ // Must be between PCANSITYPE (0) and TTYTERMTYPE (4)\r
+ //\r
+ ASSERT (TerminalType <= TTYTERMTYPE);\r
+ } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+ //\r
+ // If RemainingDevicePath isn't the End of Device Path Node,\r
+ // Use the RemainingDevicePath to determine the terminal type\r
+ //\r
+ Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
+ if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
+ TerminalType = PCANSITYPE;\r
+ } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
+ TerminalType = VT100TYPE;\r
+ } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
+ TerminalType = VT100PLUSTYPE;\r
+ } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
+ TerminalType = VTUTF8TYPE;\r
+ } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
+ TerminalType = TTYTERMTYPE;\r
+ } else {\r
+ goto Error;\r
+ }\r
+ } else {\r
+ //\r
+ // If RemainingDevicePath is the End of Device Path Node,\r
+ // skip enumerate any device and return EFI_SUCESSS\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Initialize the Terminal Dev\r
+ //\r
+ TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
+ if (TerminalDevice == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ TerminalDevice->TerminalType = TerminalType;\r
+ TerminalDevice->SerialIo = SerialIo;\r
+\r
+ InitializeListHead (&TerminalDevice->NotifyList);\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ TerminalConInWaitForKeyEx,\r
+ TerminalDevice,\r
+ &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ TerminalConInWaitForKey,\r
+ TerminalDevice,\r
+ &TerminalDevice->SimpleInput.WaitForKey\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ //\r
+ // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
+ // the pre-read pending characters.\r
+ //\r
+ TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
+ if (TerminalDevice->RawFiFo == NULL) {\r
+ goto Error;\r
+ }\r
+ TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
+ if (TerminalDevice->UnicodeFiFo == NULL) {\r
+ goto Error;\r
+ }\r
+ TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+ if (TerminalDevice->EfiKeyFiFo == NULL) {\r
+ goto Error;\r
+ }\r
+ TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
+ if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // Set the timeout value of serial buffer for\r
+ // keystroke response performance issue\r
+ //\r
+ Mode = TerminalDevice->SerialIo->Mode;\r
+\r
+ SerialInTimeOut = 0;\r
+ if (Mode->BaudRate != 0) {\r
+ SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
+ }\r
+\r
+ Status = TerminalDevice->SerialIo->SetAttributes (\r
+ TerminalDevice->SerialIo,\r
+ Mode->BaudRate,\r
+ Mode->ReceiveFifoDepth,\r
+ (UINT32) SerialInTimeOut,\r
+ (EFI_PARITY_TYPE) (Mode->Parity),\r
+ (UINT8) Mode->DataBits,\r
+ (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // if set attributes operation fails, invalidate\r
+ // the value of SerialInTimeOut,thus make it\r
+ // inconsistent with the default timeout value\r
+ // of serial buffer. This will invoke the recalculation\r
+ // in the readkeystroke routine.\r
+ //\r
+ TerminalDevice->SerialInTimeOut = 0;\r
+ } else {\r
+ TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
+ }\r
+ //\r
+ // Set Simple Text Output Protocol from template.\r
+ //\r
+ SimpleTextOutput = CopyMem (\r
+ &TerminalDevice->SimpleTextOutput,\r
+ &mTerminalDevTemplate.SimpleTextOutput,\r
+ sizeof (mTerminalDevTemplate.SimpleTextOutput)\r
+ );\r
+ SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
+ \r
+ Status = InitializeTerminalConsoleTextMode (&ModeCount, &TerminalDevice->TerminalConsoleModeData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
+ }\r
+ TerminalDevice->SimpleTextOutputMode.MaxMode = (INT32) ModeCount;\r
+ \r
+ //\r
+ // For terminal devices, cursor is always visible\r
+ //\r
+ TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
+ Status = TerminalConOutSetAttribute (\r
+ SimpleTextOutput,\r
+ EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
+ }\r
+\r
+ //\r
+ // Build the component name for the child device\r
+ //\r
+ TerminalDevice->ControllerNameTable = NULL;\r
+ switch (TerminalDevice->TerminalType) {\r
+ case PCANSITYPE:\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gTerminalComponentName.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"PC-ANSI Serial Console",\r
+ TRUE\r
+ );\r
+ AddUnicodeString2 (\r
+ "en",\r
+ gTerminalComponentName2.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"PC-ANSI Serial Console",\r
+ FALSE\r
+ );\r
+\r
+ break;\r
+\r
+ case VT100TYPE:\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gTerminalComponentName.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"VT-100 Serial Console",\r
+ TRUE\r
+ );\r
+ AddUnicodeString2 (\r
+ "en",\r
+ gTerminalComponentName2.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"VT-100 Serial Console",\r
+ FALSE\r
+ );\r
+\r
+ break;\r
+\r
+ case VT100PLUSTYPE:\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gTerminalComponentName.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"VT-100+ Serial Console",\r
+ TRUE\r
+ );\r
+ AddUnicodeString2 (\r
+ "en",\r
+ gTerminalComponentName2.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"VT-100+ Serial Console",\r
+ FALSE\r
+ );\r
+\r
+ break;\r
+\r
+ case VTUTF8TYPE:\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gTerminalComponentName.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"VT-UTF8 Serial Console",\r
+ TRUE\r
+ );\r
+ AddUnicodeString2 (\r
+ "en",\r
+ gTerminalComponentName2.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"VT-UTF8 Serial Console",\r
+ FALSE\r
+ );\r
+\r
+ break;\r
+\r
+ case TTYTERMTYPE:\r
+ AddUnicodeString2 (\r
+ "eng",\r
+ gTerminalComponentName.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"Tty Terminal Serial Console",\r
+ TRUE\r
+ );\r
+ AddUnicodeString2 (\r
+ "en",\r
+ gTerminalComponentName2.SupportedLanguages,\r
+ &TerminalDevice->ControllerNameTable,\r
+ (CHAR16 *)L"Tty Terminal Serial Console",\r
+ FALSE\r
+ );\r
+\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Build the device path for the child device\r
+ //\r
+ Status = SetTerminalDevicePath (\r
+ TerminalDevice->TerminalType,\r
+ ParentDevicePath,\r
+ &TerminalDevice->DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
+ }\r
+\r
+ Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
+ }\r
+\r
+ Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReportError;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ TerminalConInTimerHandler,\r
+ TerminalDevice,\r
+ &TerminalDevice->TimerEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->SetTimer (\r
+ TerminalDevice->TimerEvent,\r
+ TimerPeriodic,\r
+ KEYBOARD_TIMER_INTERVAL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &TerminalDevice->TwoSecondTimeOut\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ TerminalDevice,\r
+ &TerminalDevice->KeyNotifyProcessEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->InstallProtocolInterface (\r
+ &TerminalDevice->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ TerminalDevice->DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r