2 Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and
3 Simple Text Output Protocol upon Serial IO Protocol.
5 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
23 TerminalDriverBindingSupported
,
24 TerminalDriverBindingStart
,
25 TerminalDriverBindingStop
,
32 EFI_GUID
*gTerminalType
[] = {
40 TERMINAL_DEV mTerminalDevTemplate
= {
41 TERMINAL_DEV_SIGNATURE
,
48 TerminalConInReadKeyStroke
,
53 TerminalConOutOutputString
,
54 TerminalConOutTestString
,
55 TerminalConOutQueryMode
,
56 TerminalConOutSetMode
,
57 TerminalConOutSetAttribute
,
58 TerminalConOutClearScreen
,
59 TerminalConOutSetCursorPosition
,
60 TerminalConOutEnableCursor
,
63 { // SimpleTextOutputMode
66 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
), // Attribute
77 NULL
, // ControllerNameTable
79 NULL
, // TwoSecondTimeOut
83 { // SimpleTextInputEx
85 TerminalConInReadKeyStrokeEx
,
87 TerminalConInSetState
,
88 TerminalConInRegisterKeyNotify
,
89 TerminalConInUnregisterKeyNotify
,
98 Test to see if this driver supports Controller.
100 @param This Protocol instance pointer.
101 @param Controller Handle of device to test
102 @param RemainingDevicePath Optional parameter use to pick a specific child
105 @retval EFI_SUCCESS This driver supports this device.
106 @retval EFI_ALREADY_STARTED This driver is already running on this device.
107 @retval other This driver does not support this device.
112 TerminalDriverBindingSupported (
113 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
114 IN EFI_HANDLE Controller
,
115 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
119 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
120 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
121 VENDOR_DEVICE_PATH
*Node
;
124 // If remaining device path is not NULL, then make sure it is a
125 // device path that describes a terminal communications protocol.
127 if (RemainingDevicePath
!= NULL
) {
129 // Check if RemainingDevicePath is the End of Device Path Node,
130 // if yes, go on checking other conditions
132 if (!IsDevicePathEnd (RemainingDevicePath
)) {
134 // If RemainingDevicePath isn't the End of Device Path Node,
135 // check its validation
137 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
139 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
140 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
141 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
143 return EFI_UNSUPPORTED
;
147 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
149 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
150 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
151 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
152 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
154 return EFI_UNSUPPORTED
;
159 // Open the IO Abstraction(s) needed to perform the supported test
160 // The Controller must support the Serial I/O Protocol.
161 // This driver is a bus driver with at most 1 child device, so it is
162 // ok for it to be already started.
164 Status
= gBS
->OpenProtocol (
166 &gEfiSerialIoProtocolGuid
,
168 This
->DriverBindingHandle
,
170 EFI_OPEN_PROTOCOL_BY_DRIVER
172 if (Status
== EFI_ALREADY_STARTED
) {
176 if (EFI_ERROR (Status
)) {
181 // Close the I/O Abstraction(s) used to perform the supported test
185 &gEfiSerialIoProtocolGuid
,
186 This
->DriverBindingHandle
,
191 // Open the EFI Device Path protocol needed to perform the supported test
193 Status
= gBS
->OpenProtocol (
195 &gEfiDevicePathProtocolGuid
,
196 (VOID
**) &ParentDevicePath
,
197 This
->DriverBindingHandle
,
199 EFI_OPEN_PROTOCOL_BY_DRIVER
201 if (Status
== EFI_ALREADY_STARTED
) {
205 if (EFI_ERROR (Status
)) {
210 // Close protocol, don't use device path protocol in the Support() function
214 &gEfiDevicePathProtocolGuid
,
215 This
->DriverBindingHandle
,
223 Build the terminal device path for the child device according to the
226 @param ParentDevicePath Parent device path.
227 @param RemainingDevicePath A specific child device.
229 @return The child device path built.
232 EFI_DEVICE_PATH_PROTOCOL
*
234 BuildTerminalDevpath (
235 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
236 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
239 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
241 VENDOR_DEVICE_PATH
*Node
;
244 TerminalDevicePath
= NULL
;
245 TerminalType
= PCANSITYPE
;
248 // Use the RemainingDevicePath to determine the terminal type
250 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
252 TerminalType
= PCANSITYPE
;
254 } else if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
256 TerminalType
= PCANSITYPE
;
258 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
260 TerminalType
= VT100TYPE
;
262 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
264 TerminalType
= VT100PLUSTYPE
;
266 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
268 TerminalType
= VTUTF8TYPE
;
275 // Build the device path for the child device
277 Status
= SetTerminalDevicePath (
282 if (EFI_ERROR (Status
)) {
285 return TerminalDevicePath
;
289 Compare a device path data structure to that of all the nodes of a
290 second device path instance.
292 @param Multi A pointer to a multi-instance device path data structure.
293 @param Single A pointer to a single-instance device path data structure.
295 @retval TRUE If the Single is contained within Multi.
296 @retval FALSE The Single is not match within Multi.
301 IN EFI_DEVICE_PATH_PROTOCOL
*Multi
,
302 IN EFI_DEVICE_PATH_PROTOCOL
*Single
305 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
306 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
310 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
312 // Search for the match of 'Single' in 'Multi'
314 while (DevicePathInst
!= NULL
) {
316 // If the single device path is found in multiple device paths,
319 if (CompareMem (Single
, DevicePathInst
, Size
) == 0) {
320 FreePool (DevicePathInst
);
324 FreePool (DevicePathInst
);
325 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
332 Check whether the terminal device path is in the global variable.
334 @param VariableName Pointer to one global variable.
335 @param TerminalDevicePath Pointer to the terminal device's device path.
337 @retval TRUE The devcie is in the global variable.
338 @retval FALSE The devcie is not in the global variable.
342 IsTerminalInConsoleVariable (
343 IN CHAR16
*VariableName
,
344 IN EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
347 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
351 // Get global variable and its size according to the name given.
353 Variable
= GetEfiGlobalVariable (VariableName
);
354 if (Variable
== NULL
) {
359 // Check whether the terminal device path is one of the variable instances.
361 ReturnFlag
= MatchDevicePaths (Variable
, TerminalDevicePath
);
369 Free notify functions list.
371 @param ListHead The list head
373 @retval EFI_SUCCESS Free the notify list successfully.
374 @retval EFI_INVALID_PARAMETER ListHead is NULL.
378 TerminalFreeNotifyList (
379 IN OUT LIST_ENTRY
*ListHead
382 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
384 if (ListHead
== NULL
) {
385 return EFI_INVALID_PARAMETER
;
387 while (!IsListEmpty (ListHead
)) {
389 ListHead
->ForwardLink
,
390 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
392 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
394 RemoveEntryList (ListHead
->ForwardLink
);
395 FreePool (NotifyNode
);
403 Start this driver on Controller by opening a Serial IO protocol,
404 reading Device Path, and creating a child handle with a Simple Text In,
405 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
406 And store Console Device Environment Variables.
408 @param This Protocol instance pointer.
409 @param Controller Handle of device to bind driver to
410 @param RemainingDevicePath Optional parameter use to pick a specific child
413 @retval EFI_SUCCESS This driver is added to Controller.
414 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
415 @retval other This driver does not support this device.
420 TerminalDriverBindingStart (
421 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
422 IN EFI_HANDLE Controller
,
423 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
427 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
428 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
429 VENDOR_DEVICE_PATH
*Node
;
430 VENDOR_DEVICE_PATH
*DefaultNode
;
431 EFI_SERIAL_IO_MODE
*Mode
;
432 UINTN SerialInTimeOut
;
433 TERMINAL_DEV
*TerminalDevice
;
435 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
438 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
439 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
440 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleTextInput
;
441 BOOLEAN ConInSelected
;
442 BOOLEAN ConOutSelected
;
443 BOOLEAN NullRemaining
;
444 BOOLEAN SimTxtInInstalled
;
445 BOOLEAN SimTxtOutInstalled
;
448 TerminalDevice
= NULL
;
450 ConInSelected
= FALSE
;
451 ConOutSelected
= FALSE
;
452 NullRemaining
= TRUE
;
453 SimTxtInInstalled
= FALSE
;
454 SimTxtOutInstalled
= FALSE
;
457 // Get the Device Path Protocol to build the device path of the child device
459 Status
= gBS
->OpenProtocol (
461 &gEfiDevicePathProtocolGuid
,
462 (VOID
**) &ParentDevicePath
,
463 This
->DriverBindingHandle
,
465 EFI_OPEN_PROTOCOL_BY_DRIVER
467 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
472 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
474 Status
= gBS
->OpenProtocol (
476 &gEfiSerialIoProtocolGuid
,
478 This
->DriverBindingHandle
,
480 EFI_OPEN_PROTOCOL_BY_DRIVER
482 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
486 if (Status
!= EFI_ALREADY_STARTED
) {
488 // the serial I/O protocol never be opened before, it is the first
489 // time to start the serial Io controller
495 // Serial I/O is not already open by this driver, then tag the handle
496 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
497 // StdErrDev variables with the list of possible terminal types on this
500 Status
= gBS
->OpenProtocol (
504 This
->DriverBindingHandle
,
506 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
508 if (EFI_ERROR (Status
)) {
509 Status
= gBS
->InstallMultipleProtocolInterfaces (
512 DuplicateDevicePath (ParentDevicePath
),
515 if (EFI_ERROR (Status
)) {
519 if (!IsHotPlugDevice (ParentDevicePath
)) {
521 // if the serial device is a hot plug device, do not update the
522 // ConInDev, ConOutDev, and StdErrDev variables.
524 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
525 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
526 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
531 // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols
533 // Simple In/Out Protocol will not be installed onto the handle if the
534 // device path to the handle is not present in the ConIn/ConOut
535 // environment variable. But If RemainingDevicePath is NULL, then always
536 // produce both Simple In and Simple Text Output Protocols. This is required
537 // for the connect all sequences to make sure all possible consoles are
538 // produced no matter what the current values of ConIn, ConOut, or StdErr are.
540 if (RemainingDevicePath
== NULL
) {
541 NullRemaining
= TRUE
;
544 DevicePath
= BuildTerminalDevpath (ParentDevicePath
, RemainingDevicePath
);
545 if (DevicePath
!= NULL
) {
546 ConInSelected
= IsTerminalInConsoleVariable (L
"ConIn", DevicePath
);
547 ConOutSelected
= IsTerminalInConsoleVariable (L
"ConOut", DevicePath
);
548 FreePool (DevicePath
);
553 // Not create the child terminal handle if both Simple In/In Ex and
554 // Simple text Out protocols are not required to be published
556 if ((!ConInSelected
)&&(!ConOutSelected
)&&(!NullRemaining
)) {
561 // create the child terminal handle during first entry
565 // First enther the start funciton
569 // Make sure a child handle does not already exist. This driver can only
570 // produce one child per serial port.
572 Status
= gBS
->OpenProtocolInformation (
574 &gEfiSerialIoProtocolGuid
,
578 if (!EFI_ERROR (Status
)) {
579 Status
= EFI_SUCCESS
;
580 for (Index
= 0; Index
< EntryCount
; Index
++) {
581 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
582 Status
= EFI_ALREADY_STARTED
;
586 FreePool (OpenInfoBuffer
);
587 if (EFI_ERROR (Status
)) {
593 // If RemainingDevicePath is NULL, then create default device path node
595 if (RemainingDevicePath
== NULL
) {
596 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
597 if (DefaultNode
== NULL
) {
598 Status
= EFI_OUT_OF_RESOURCES
;
602 TerminalType
= PcdGet8 (PcdDefaultTerminalType
);
604 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)
606 ASSERT (TerminalType
<= VTUTF8TYPE
);
608 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
609 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
610 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
612 // If RemainingDevicePath isn't the End of Device Path Node,
613 // Use the RemainingDevicePath to determine the terminal type
615 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
616 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
617 TerminalType
= PCANSITYPE
;
618 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
619 TerminalType
= VT100TYPE
;
620 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
621 TerminalType
= VT100PLUSTYPE
;
622 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
623 TerminalType
= VTUTF8TYPE
;
629 // If RemainingDevicePath is the End of Device Path Node,
630 // skip enumerate any device and return EFI_SUCESSS
636 // Initialize the Terminal Dev
638 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
639 if (TerminalDevice
== NULL
) {
640 Status
= EFI_OUT_OF_RESOURCES
;
644 TerminalDevice
->TerminalType
= TerminalType
;
645 TerminalDevice
->SerialIo
= SerialIo
;
647 InitializeListHead (&TerminalDevice
->NotifyList
);
648 Status
= gBS
->CreateEvent (
651 TerminalConInWaitForKeyEx
,
653 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
655 if (EFI_ERROR (Status
)) {
659 Status
= gBS
->CreateEvent (
662 TerminalConInWaitForKey
,
664 &TerminalDevice
->SimpleInput
.WaitForKey
666 if (EFI_ERROR (Status
)) {
670 // Allocates and initializes the FIFO buffer to be zero, used for accommodating
671 // the pre-read pending characters.
673 TerminalDevice
->RawFiFo
= AllocateZeroPool (sizeof (RAW_DATA_FIFO
));
674 if (TerminalDevice
->RawFiFo
== NULL
) {
677 TerminalDevice
->UnicodeFiFo
= AllocateZeroPool (sizeof (UNICODE_FIFO
));
678 if (TerminalDevice
->UnicodeFiFo
== NULL
) {
681 TerminalDevice
->EfiKeyFiFo
= AllocateZeroPool (sizeof (EFI_KEY_FIFO
));
682 if (TerminalDevice
->EfiKeyFiFo
== NULL
) {
687 // Set the timeout value of serial buffer for
688 // keystroke response performance issue
690 Mode
= TerminalDevice
->SerialIo
->Mode
;
693 if (Mode
->BaudRate
!= 0) {
694 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
697 Status
= TerminalDevice
->SerialIo
->SetAttributes (
698 TerminalDevice
->SerialIo
,
700 Mode
->ReceiveFifoDepth
,
701 (UINT32
) SerialInTimeOut
,
702 (EFI_PARITY_TYPE
) (Mode
->Parity
),
703 (UINT8
) Mode
->DataBits
,
704 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
706 if (EFI_ERROR (Status
)) {
708 // if set attributes operation fails, invalidate
709 // the value of SerialInTimeOut,thus make it
710 // inconsistent with the default timeout value
711 // of serial buffer. This will invoke the recalculation
712 // in the readkeystroke routine.
714 TerminalDevice
->SerialInTimeOut
= 0;
716 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
719 // Set Simple Text Output Protocol from template.
721 SimpleTextOutput
= CopyMem (
722 &TerminalDevice
->SimpleTextOutput
,
723 &mTerminalDevTemplate
.SimpleTextOutput
,
724 sizeof (mTerminalDevTemplate
.SimpleTextOutput
)
726 SimpleTextOutput
->Mode
= &TerminalDevice
->SimpleTextOutputMode
;
728 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= TERMINAL_MAX_MODE
;
730 // For terminal devices, cursor is always visible
732 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
733 Status
= TerminalConOutSetAttribute (
735 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
737 if (EFI_ERROR (Status
)) {
742 // Build the component name for the child device
744 TerminalDevice
->ControllerNameTable
= NULL
;
745 switch (TerminalDevice
->TerminalType
) {
749 gTerminalComponentName
.SupportedLanguages
,
750 &TerminalDevice
->ControllerNameTable
,
751 (CHAR16
*)L
"PC-ANSI Serial Console",
756 gTerminalComponentName2
.SupportedLanguages
,
757 &TerminalDevice
->ControllerNameTable
,
758 (CHAR16
*)L
"PC-ANSI Serial Console",
767 gTerminalComponentName
.SupportedLanguages
,
768 &TerminalDevice
->ControllerNameTable
,
769 (CHAR16
*)L
"VT-100 Serial Console",
774 gTerminalComponentName2
.SupportedLanguages
,
775 &TerminalDevice
->ControllerNameTable
,
776 (CHAR16
*)L
"VT-100 Serial Console",
785 gTerminalComponentName
.SupportedLanguages
,
786 &TerminalDevice
->ControllerNameTable
,
787 (CHAR16
*)L
"VT-100+ Serial Console",
792 gTerminalComponentName2
.SupportedLanguages
,
793 &TerminalDevice
->ControllerNameTable
,
794 (CHAR16
*)L
"VT-100+ Serial Console",
803 gTerminalComponentName
.SupportedLanguages
,
804 &TerminalDevice
->ControllerNameTable
,
805 (CHAR16
*)L
"VT-UTF8 Serial Console",
810 gTerminalComponentName2
.SupportedLanguages
,
811 &TerminalDevice
->ControllerNameTable
,
812 (CHAR16
*)L
"VT-UTF8 Serial Console",
820 // Build the device path for the child device
822 Status
= SetTerminalDevicePath (
823 TerminalDevice
->TerminalType
,
825 &TerminalDevice
->DevicePath
827 if (EFI_ERROR (Status
)) {
831 Status
= TerminalConOutReset (SimpleTextOutput
, FALSE
);
832 if (EFI_ERROR (Status
)) {
836 Status
= TerminalConOutSetMode (SimpleTextOutput
, 0);
837 if (EFI_ERROR (Status
)) {
841 Status
= TerminalConOutEnableCursor (SimpleTextOutput
, TRUE
);
842 if (EFI_ERROR (Status
)) {
846 Status
= gBS
->CreateEvent (
847 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
849 TerminalConInTimerHandler
,
851 &TerminalDevice
->TimerEvent
853 ASSERT_EFI_ERROR (Status
);
855 Status
= gBS
->SetTimer (
856 TerminalDevice
->TimerEvent
,
858 KEYBOARD_TIMER_INTERVAL
860 ASSERT_EFI_ERROR (Status
);
862 Status
= gBS
->CreateEvent (
867 &TerminalDevice
->TwoSecondTimeOut
869 ASSERT_EFI_ERROR (Status
);
871 Status
= gBS
->InstallProtocolInterface (
872 &TerminalDevice
->Handle
,
873 &gEfiDevicePathProtocolGuid
,
874 EFI_NATIVE_INTERFACE
,
875 TerminalDevice
->DevicePath
877 if (EFI_ERROR (Status
)) {
882 // Register the Parent-Child relationship via
883 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
885 Status
= gBS
->OpenProtocol (
887 &gEfiSerialIoProtocolGuid
,
888 (VOID
**) &TerminalDevice
->SerialIo
,
889 This
->DriverBindingHandle
,
890 TerminalDevice
->Handle
,
891 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
893 if (EFI_ERROR (Status
)) {
899 // Find the child handle, and get its TerminalDevice private data
901 Status
= gBS
->OpenProtocolInformation (
903 &gEfiSerialIoProtocolGuid
,
907 if (!EFI_ERROR (Status
)) {
908 Status
= EFI_NOT_FOUND
;
909 ASSERT (OpenInfoBuffer
!= NULL
);
910 for (Index
= 0; Index
< EntryCount
; Index
++) {
911 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
913 // Find the child terminal handle.
914 // Test whether the SimpleTxtIn and SimpleTxtOut have been published
916 Status
= gBS
->OpenProtocol (
917 OpenInfoBuffer
[Index
].ControllerHandle
,
918 &gEfiSimpleTextInProtocolGuid
,
919 (VOID
**) &SimpleTextInput
,
920 This
->DriverBindingHandle
,
921 OpenInfoBuffer
[Index
].ControllerHandle
,
922 EFI_OPEN_PROTOCOL_GET_PROTOCOL
924 if (!EFI_ERROR (Status
)) {
925 SimTxtInInstalled
= TRUE
;
926 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput
);
929 Status
= gBS
->OpenProtocol (
930 OpenInfoBuffer
[Index
].ControllerHandle
,
931 &gEfiSimpleTextOutProtocolGuid
,
932 (VOID
**) &SimpleTextOutput
,
933 This
->DriverBindingHandle
,
934 OpenInfoBuffer
[Index
].ControllerHandle
,
935 EFI_OPEN_PROTOCOL_GET_PROTOCOL
937 if (!EFI_ERROR (Status
)) {
938 SimTxtOutInstalled
= TRUE
;
939 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
941 Status
= EFI_SUCCESS
;
946 FreePool (OpenInfoBuffer
);
947 if (EFI_ERROR (Status
)) {
954 ASSERT (TerminalDevice
!= NULL
);
956 // Only do the reset if the device path is in the Conout variable
958 if (ConInSelected
&& !SimTxtInInstalled
) {
959 Status
= TerminalDevice
->SimpleInput
.Reset (
960 &TerminalDevice
->SimpleInput
,
963 if (EFI_ERROR (Status
)) {
965 // Need to report Error Code first
972 // Only output the configure string to remote terminal if the device path
973 // is in the Conout variable
975 if (ConOutSelected
&& !SimTxtOutInstalled
) {
976 Status
= TerminalDevice
->SimpleTextOutput
.SetAttribute (
977 &TerminalDevice
->SimpleTextOutput
,
978 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
980 if (EFI_ERROR (Status
)) {
984 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
985 &TerminalDevice
->SimpleTextOutput
,
988 if (EFI_ERROR (Status
)) {
992 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
993 &TerminalDevice
->SimpleTextOutput
,
996 if (EFI_ERROR (Status
)) {
1000 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
1001 &TerminalDevice
->SimpleTextOutput
,
1004 if (EFI_ERROR (Status
)) {
1010 // Simple In/Out Protocol will not be installed onto the handle if the
1011 // device path to the handle is not present in the ConIn/ConOut
1012 // environment variable. But If RemainingDevicePath is NULL, then always
1013 // produce both Simple In and Simple Text Output Protocols. This is required
1014 // for the connect all sequences to make sure all possible consoles are
1015 // produced no matter what the current values of ConIn, ConOut, or StdErr are.
1017 if (!SimTxtInInstalled
&& (ConInSelected
|| NullRemaining
)) {
1018 Status
= gBS
->InstallMultipleProtocolInterfaces (
1019 &TerminalDevice
->Handle
,
1020 &gEfiSimpleTextInProtocolGuid
,
1021 &TerminalDevice
->SimpleInput
,
1022 &gEfiSimpleTextInputExProtocolGuid
,
1023 &TerminalDevice
->SimpleInputEx
,
1026 if (EFI_ERROR (Status
)) {
1031 if (!SimTxtOutInstalled
&& (ConOutSelected
|| NullRemaining
)) {
1032 Status
= gBS
->InstallProtocolInterface (
1033 &TerminalDevice
->Handle
,
1034 &gEfiSimpleTextOutProtocolGuid
,
1035 EFI_NATIVE_INTERFACE
,
1036 &TerminalDevice
->SimpleTextOutput
1038 if (EFI_ERROR (Status
)) {
1042 if (DefaultNode
!= NULL
) {
1043 FreePool (DefaultNode
);
1050 // Report error code before exiting
1052 DevicePath
= ParentDevicePath
;
1053 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1054 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1055 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
1061 // Use the Stop() function to free all resources allocated in Start()
1063 if (TerminalDevice
!= NULL
) {
1065 if (TerminalDevice
->Handle
!= NULL
) {
1066 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
1069 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
1070 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
1073 if (TerminalDevice
->TimerEvent
!= NULL
) {
1074 gBS
->CloseEvent (TerminalDevice
->TimerEvent
);
1077 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
1078 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
1081 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
1082 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
1085 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
1087 if (TerminalDevice
->RawFiFo
!= NULL
) {
1088 FreePool (TerminalDevice
->RawFiFo
);
1090 if (TerminalDevice
->UnicodeFiFo
!= NULL
) {
1091 FreePool (TerminalDevice
->UnicodeFiFo
);
1093 if (TerminalDevice
->EfiKeyFiFo
!= NULL
) {
1094 FreePool (TerminalDevice
->EfiKeyFiFo
);
1097 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
1098 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
1101 if (TerminalDevice
->DevicePath
!= NULL
) {
1102 FreePool (TerminalDevice
->DevicePath
);
1105 FreePool (TerminalDevice
);
1109 if (DefaultNode
!= NULL
) {
1110 FreePool (DefaultNode
);
1113 This
->Stop (This
, Controller
, 0, NULL
);
1119 Stop this driver on Controller by closing Simple Text In, Simple Text
1120 In Ex, Simple Text Out protocol, and removing parent device path from
1121 Console Device Environment Variables.
1123 @param This Protocol instance pointer.
1124 @param Controller Handle of device to stop driver on
1125 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1126 children is zero stop the entire bus driver.
1127 @param ChildHandleBuffer List of Child Handles to Stop.
1129 @retval EFI_SUCCESS This driver is removed Controller.
1130 @retval other This driver could not be removed from this device.
1135 TerminalDriverBindingStop (
1136 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1137 IN EFI_HANDLE Controller
,
1138 IN UINTN NumberOfChildren
,
1139 IN EFI_HANDLE
*ChildHandleBuffer
1144 BOOLEAN AllChildrenStopped
;
1145 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
1146 TERMINAL_DEV
*TerminalDevice
;
1147 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1148 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1149 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1151 Status
= gBS
->HandleProtocol (
1153 &gEfiDevicePathProtocolGuid
,
1154 (VOID
**) &DevicePath
1156 if (EFI_ERROR (Status
)) {
1161 // Complete all outstanding transactions to Controller.
1162 // Don't allow any new transaction to Controller to be started.
1164 if (NumberOfChildren
== 0) {
1166 // Close the bus driver
1168 Status
= gBS
->OpenProtocol (
1171 (VOID
**) &ParentDevicePath
,
1172 This
->DriverBindingHandle
,
1174 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1176 if (!EFI_ERROR (Status
)) {
1178 // Remove Parent Device Path from
1179 // the Console Device Environment Variables
1181 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
1182 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
1183 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
1186 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
1188 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1196 // Free the ParentDevicePath that was duplicated in Start()
1198 if (!EFI_ERROR (Status
)) {
1199 FreePool (ParentDevicePath
);
1203 gBS
->CloseProtocol (
1205 &gEfiSerialIoProtocolGuid
,
1206 This
->DriverBindingHandle
,
1210 gBS
->CloseProtocol (
1212 &gEfiDevicePathProtocolGuid
,
1213 This
->DriverBindingHandle
,
1220 AllChildrenStopped
= TRUE
;
1222 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1224 Status
= gBS
->OpenProtocol (
1225 ChildHandleBuffer
[Index
],
1226 &gEfiSimpleTextOutProtocolGuid
,
1227 (VOID
**) &SimpleTextOutput
,
1228 This
->DriverBindingHandle
,
1229 ChildHandleBuffer
[Index
],
1230 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1232 if (!EFI_ERROR (Status
)) {
1234 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
1236 gBS
->CloseProtocol (
1238 &gEfiSerialIoProtocolGuid
,
1239 This
->DriverBindingHandle
,
1240 ChildHandleBuffer
[Index
]
1243 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1244 ChildHandleBuffer
[Index
],
1245 &gEfiSimpleTextInProtocolGuid
,
1246 &TerminalDevice
->SimpleInput
,
1247 &gEfiSimpleTextInputExProtocolGuid
,
1248 &TerminalDevice
->SimpleInputEx
,
1249 &gEfiSimpleTextOutProtocolGuid
,
1250 &TerminalDevice
->SimpleTextOutput
,
1251 &gEfiDevicePathProtocolGuid
,
1252 TerminalDevice
->DevicePath
,
1255 if (EFI_ERROR (Status
)) {
1258 &gEfiSerialIoProtocolGuid
,
1259 (VOID
**) &SerialIo
,
1260 This
->DriverBindingHandle
,
1261 ChildHandleBuffer
[Index
],
1262 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1266 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
1267 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
1270 gBS
->CloseEvent (TerminalDevice
->TimerEvent
);
1271 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
1272 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
1273 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
1274 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
1275 FreePool (TerminalDevice
->DevicePath
);
1276 FreePool (TerminalDevice
);
1280 if (EFI_ERROR (Status
)) {
1281 AllChildrenStopped
= FALSE
;
1285 if (!AllChildrenStopped
) {
1286 return EFI_DEVICE_ERROR
;
1293 Update terminal device path in Console Device Environment Variables.
1295 @param VariableName The Console Device Environment Variable.
1296 @param ParentDevicePath The terminal device path to be updated.
1300 TerminalUpdateConsoleDevVariable (
1301 IN CHAR16
*VariableName
,
1302 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1308 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1309 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1310 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1313 // Get global variable and its size according to the name given.
1315 Variable
= GetEfiGlobalVariable (VariableName
);
1316 if (Variable
== NULL
) {
1321 // Append terminal device path onto the variable.
1323 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1324 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1325 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
1326 if (Variable
!= NULL
) {
1327 FreePool (Variable
);
1330 if (TempDevicePath
!= NULL
) {
1331 FreePool (TempDevicePath
);
1334 Variable
= NewVariable
;
1337 VariableSize
= GetDevicePathSize (Variable
);
1339 Status
= gRT
->SetVariable (
1341 &gEfiGlobalVariableGuid
,
1342 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1346 ASSERT_EFI_ERROR (Status
);
1347 FreePool (Variable
);
1354 Remove terminal device path from Console Device Environment Variables.
1356 @param VariableName Console Device Environment Variables.
1357 @param ParentDevicePath The terminal device path to be updated.
1361 TerminalRemoveConsoleDevVariable (
1362 IN CHAR16
*VariableName
,
1363 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1372 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1373 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1374 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1375 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1376 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1377 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1382 // Get global variable and its size according to the name given.
1384 Variable
= GetEfiGlobalVariable (VariableName
);
1385 if (Variable
== NULL
) {
1390 OriginalVariable
= Variable
;
1394 // Get first device path instance from Variable
1396 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1397 if (Instance
== NULL
) {
1398 FreePool (OriginalVariable
);
1402 // Loop through all the device path instances of Variable
1406 // Loop through all the terminal types that this driver supports
1409 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1411 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1414 // Compare the generated device path to the current device path instance
1416 if (TempDevicePath
!= NULL
) {
1417 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1422 FreePool (TempDevicePath
);
1426 // If a match was not found, then keep the current device path instance
1429 SavedNewVariable
= NewVariable
;
1430 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1431 if (SavedNewVariable
!= NULL
) {
1432 FreePool (SavedNewVariable
);
1436 // Get next device path instance from Variable
1438 FreePool (Instance
);
1439 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1440 } while (Instance
!= NULL
);
1442 FreePool (OriginalVariable
);
1445 VariableSize
= GetDevicePathSize (NewVariable
);
1447 Status
= gRT
->SetVariable (
1449 &gEfiGlobalVariableGuid
,
1450 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1454 ASSERT_EFI_ERROR (Status
);
1457 if (NewVariable
!= NULL
) {
1458 FreePool (NewVariable
);
1465 Build terminal device path according to terminal type.
1467 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1468 @param ParentDevicePath Parent device path.
1469 @param TerminalDevicePath Returned terminal device path, if building successfully.
1471 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1472 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1473 @retval EFI_SUCCESS Build terminal device path successfully.
1477 SetTerminalDevicePath (
1478 IN UINT8 TerminalType
,
1479 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1480 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1483 VENDOR_DEVICE_PATH Node
;
1485 *TerminalDevicePath
= NULL
;
1486 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1487 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1490 // Generate terminal device path node according to terminal type.
1492 switch (TerminalType
) {
1495 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1499 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1503 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1507 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1511 return EFI_UNSUPPORTED
;
1515 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1517 SetDevicePathNodeLength (
1519 sizeof (VENDOR_DEVICE_PATH
)
1523 // Append the terminal node onto parent device path
1524 // to generate a complete terminal device path.
1526 *TerminalDevicePath
= AppendDevicePathNode (
1528 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1530 if (*TerminalDevicePath
== NULL
) {
1531 return EFI_OUT_OF_RESOURCES
;
1538 The user Entry Point for module Terminal. The user code starts with this function.
1540 @param ImageHandle The firmware allocated handle for the EFI image.
1541 @param SystemTable A pointer to the EFI System Table.
1543 @retval EFI_SUCCESS The entry point is executed successfully.
1544 @retval other Some error occurs when executing this entry point.
1550 IN EFI_HANDLE ImageHandle
,
1551 IN EFI_SYSTEM_TABLE
*SystemTable
1557 // Install driver model protocol(s).
1559 Status
= EfiLibInstallDriverBindingComponentName2 (
1562 &gTerminalDriverBinding
,
1564 &gTerminalComponentName
,
1565 &gTerminalComponentName2
1567 ASSERT_EFI_ERROR (Status
);
1573 Check if the device supports hot-plug through its device path.
1575 This function could be updated to check more types of Hot Plug devices.
1576 Currently, it checks USB and PCCard device.
1578 @param DevicePath Pointer to device's device path.
1580 @retval TRUE The devcie is a hot-plug device
1581 @retval FALSE The devcie is not a hot-plug device.
1586 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1589 EFI_DEVICE_PATH_PROTOCOL
*CheckDevicePath
;
1591 CheckDevicePath
= DevicePath
;
1592 while (!IsDevicePathEnd (CheckDevicePath
)) {
1594 // Check device whether is hot plug device or not throught Device Path
1596 if ((DevicePathType (CheckDevicePath
) == MESSAGING_DEVICE_PATH
) &&
1597 (DevicePathSubType (CheckDevicePath
) == MSG_USB_DP
||
1598 DevicePathSubType (CheckDevicePath
) == MSG_USB_CLASS_DP
||
1599 DevicePathSubType (CheckDevicePath
) == MSG_USB_WWID_DP
)) {
1601 // If Device is USB device
1605 if ((DevicePathType (CheckDevicePath
) == HARDWARE_DEVICE_PATH
) &&
1606 (DevicePathSubType (CheckDevicePath
) == HW_PCCARD_DP
)) {
1608 // If Device is PCCard
1613 CheckDevicePath
= NextDevicePathNode (CheckDevicePath
);