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 - 2009, Intel Corporation. <BR>
6 All rights reserved. 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
78 NULL
, // TwoSecondTimeOut
82 { // SimpleTextInputEx
84 TerminalConInReadKeyStrokeEx
,
86 TerminalConInSetState
,
87 TerminalConInRegisterKeyNotify
,
88 TerminalConInUnregisterKeyNotify
,
97 Test to see if this driver supports Controller.
99 @param This Protocol instance pointer.
100 @param Controller Handle of device to test
101 @param RemainingDevicePath Optional parameter use to pick a specific child
104 @retval EFI_SUCCESS This driver supports this device.
105 @retval EFI_ALREADY_STARTED This driver is already running on this device.
106 @retval other This driver does not support this device.
111 TerminalDriverBindingSupported (
112 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
113 IN EFI_HANDLE Controller
,
114 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
118 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
119 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
120 VENDOR_DEVICE_PATH
*Node
;
123 // If remaining device path is not NULL, then make sure it is a
124 // device path that describes a terminal communications protocol.
126 if (RemainingDevicePath
!= NULL
) {
128 // Check if RemainingDevicePath is the End of Device Path Node,
129 // if yes, go on checking other conditions
131 if (!IsDevicePathEnd (RemainingDevicePath
)) {
133 // If RemainingDevicePath isn't the End of Device Path Node,
134 // check its validation
136 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
138 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
139 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
140 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
142 return EFI_UNSUPPORTED
;
146 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
148 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
149 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
150 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
151 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
153 return EFI_UNSUPPORTED
;
158 // Open the IO Abstraction(s) needed to perform the supported test
159 // The Controller must support the Serial I/O Protocol.
160 // This driver is a bus driver with at most 1 child device, so it is
161 // ok for it to be already started.
163 Status
= gBS
->OpenProtocol (
165 &gEfiSerialIoProtocolGuid
,
167 This
->DriverBindingHandle
,
169 EFI_OPEN_PROTOCOL_BY_DRIVER
171 if (Status
== EFI_ALREADY_STARTED
) {
175 if (EFI_ERROR (Status
)) {
180 // Close the I/O Abstraction(s) used to perform the supported test
184 &gEfiSerialIoProtocolGuid
,
185 This
->DriverBindingHandle
,
190 // Open the EFI Device Path protocol needed to perform the supported test
192 Status
= gBS
->OpenProtocol (
194 &gEfiDevicePathProtocolGuid
,
195 (VOID
**) &ParentDevicePath
,
196 This
->DriverBindingHandle
,
198 EFI_OPEN_PROTOCOL_BY_DRIVER
200 if (Status
== EFI_ALREADY_STARTED
) {
204 if (EFI_ERROR (Status
)) {
209 // Close protocol, don't use device path protocol in the Support() function
213 &gEfiDevicePathProtocolGuid
,
214 This
->DriverBindingHandle
,
222 Start this driver on Controller by opening a Serial IO protocol,
223 reading Device Path, and creating a child handle with a Simple Text In,
224 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
225 And store Console Device Environment Variables.
227 @param This Protocol instance pointer.
228 @param Controller Handle of device to bind driver to
229 @param RemainingDevicePath Optional parameter use to pick a specific child
232 @retval EFI_SUCCESS This driver is added to Controller.
233 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
234 @retval other This driver does not support this device.
239 TerminalDriverBindingStart (
240 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
241 IN EFI_HANDLE Controller
,
242 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
246 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
247 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
248 VENDOR_DEVICE_PATH
*Node
;
249 VENDOR_DEVICE_PATH
*DefaultNode
;
250 EFI_SERIAL_IO_MODE
*Mode
;
251 UINTN SerialInTimeOut
;
252 TERMINAL_DEV
*TerminalDevice
;
254 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
257 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
258 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
260 TerminalDevice
= NULL
;
263 // Get the Device Path Protocol to build the device path of the child device
265 Status
= gBS
->OpenProtocol (
267 &gEfiDevicePathProtocolGuid
,
268 (VOID
**) &ParentDevicePath
,
269 This
->DriverBindingHandle
,
271 EFI_OPEN_PROTOCOL_BY_DRIVER
273 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
278 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
280 Status
= gBS
->OpenProtocol (
282 &gEfiSerialIoProtocolGuid
,
284 This
->DriverBindingHandle
,
286 EFI_OPEN_PROTOCOL_BY_DRIVER
288 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
292 if (Status
!= EFI_ALREADY_STARTED
) {
294 // If Serial I/O is not already open by this driver, then tag the handle
295 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
296 // StdErrDev variables with the list of possible terminal types on this
299 Status
= gBS
->OpenProtocol (
303 This
->DriverBindingHandle
,
305 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
307 if (EFI_ERROR (Status
)) {
308 Status
= gBS
->InstallMultipleProtocolInterfaces (
311 DuplicateDevicePath (ParentDevicePath
),
314 if (EFI_ERROR (Status
)) {
318 if (!IsHotPlugDevice (ParentDevicePath
)) {
320 // if the serial device is a hot plug device, do not update the
321 // ConInDev, ConOutDev, and StdErrDev variables.
323 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
324 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
325 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
330 // Make sure a child handle does not already exist. This driver can only
331 // produce one child per serial port.
333 Status
= gBS
->OpenProtocolInformation (
335 &gEfiSerialIoProtocolGuid
,
339 if (!EFI_ERROR (Status
)) {
340 Status
= EFI_SUCCESS
;
341 for (Index
= 0; Index
< EntryCount
; Index
++) {
342 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
343 Status
= EFI_ALREADY_STARTED
;
347 FreePool (OpenInfoBuffer
);
348 if (EFI_ERROR (Status
)) {
353 // If RemainingDevicePath is NULL, then create default device path node
355 if (RemainingDevicePath
== NULL
) {
356 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
357 if (DefaultNode
== NULL
) {
358 Status
= EFI_OUT_OF_RESOURCES
;
362 TerminalType
= FixedPcdGet8 (PcdDefaultTerminalType
);
364 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)
366 ASSERT (TerminalType
<= VTUTF8TYPE
);
368 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
369 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
370 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
372 // If RemainingDevicePath isn't the End of Device Path Node,
373 // Use the RemainingDevicePath to determine the terminal type
375 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
376 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
377 TerminalType
= PCANSITYPE
;
378 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
379 TerminalType
= VT100TYPE
;
380 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
381 TerminalType
= VT100PLUSTYPE
;
382 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
383 TerminalType
= VTUTF8TYPE
;
389 // If RemainingDevicePath is the End of Device Path Node,
390 // skip enumerate any device and return EFI_SUCESSS
396 // Initialize the Terminal Dev
398 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
399 if (TerminalDevice
== NULL
) {
400 Status
= EFI_OUT_OF_RESOURCES
;
404 TerminalDevice
->TerminalType
= TerminalType
;
405 TerminalDevice
->SerialIo
= SerialIo
;
407 InitializeListHead (&TerminalDevice
->NotifyList
);
408 Status
= gBS
->CreateEvent (
411 TerminalConInWaitForKeyEx
,
412 &TerminalDevice
->SimpleInputEx
,
413 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
415 if (EFI_ERROR (Status
)) {
420 Status
= gBS
->CreateEvent (
423 TerminalConInWaitForKey
,
424 &TerminalDevice
->SimpleInput
,
425 &TerminalDevice
->SimpleInput
.WaitForKey
427 if (EFI_ERROR (Status
)) {
431 // Allocates and initializes the FIFO buffer to be zero, used for accommodating
432 // the pre-read pending characters.
434 TerminalDevice
->RawFiFo
= AllocateZeroPool (sizeof (RAW_DATA_FIFO
));
435 if (TerminalDevice
->RawFiFo
== NULL
) {
438 TerminalDevice
->UnicodeFiFo
= AllocateZeroPool (sizeof (UNICODE_FIFO
));
439 if (TerminalDevice
->UnicodeFiFo
== NULL
) {
442 TerminalDevice
->EfiKeyFiFo
= AllocateZeroPool (sizeof (EFI_KEY_FIFO
));
443 if (TerminalDevice
->EfiKeyFiFo
== NULL
) {
448 // Set the timeout value of serial buffer for
449 // keystroke response performance issue
451 Mode
= TerminalDevice
->SerialIo
->Mode
;
454 if (Mode
->BaudRate
!= 0) {
455 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
458 Status
= TerminalDevice
->SerialIo
->SetAttributes (
459 TerminalDevice
->SerialIo
,
461 Mode
->ReceiveFifoDepth
,
462 (UINT32
) SerialInTimeOut
,
463 (EFI_PARITY_TYPE
) (Mode
->Parity
),
464 (UINT8
) Mode
->DataBits
,
465 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
467 if (EFI_ERROR (Status
)) {
469 // if set attributes operation fails, invalidate
470 // the value of SerialInTimeOut,thus make it
471 // inconsistent with the default timeout value
472 // of serial buffer. This will invoke the recalculation
473 // in the readkeystroke routine.
475 TerminalDevice
->SerialInTimeOut
= 0;
477 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
480 // Build the device path for the child device
482 Status
= SetTerminalDevicePath (
483 TerminalDevice
->TerminalType
,
485 &TerminalDevice
->DevicePath
487 if (EFI_ERROR (Status
)) {
491 DevicePath
= TerminalDevice
->DevicePath
;
493 Status
= TerminalDevice
->SimpleInput
.Reset (
494 &TerminalDevice
->SimpleInput
,
497 if (EFI_ERROR (Status
)) {
499 // Need to report Error Code first
504 // Set Simple Text Output Protocol from template.
506 SimpleTextOutput
= CopyMem (
507 &TerminalDevice
->SimpleTextOutput
,
508 &mTerminalDevTemplate
.SimpleTextOutput
,
509 sizeof (mTerminalDevTemplate
.SimpleTextOutput
)
511 SimpleTextOutput
->Mode
= &TerminalDevice
->SimpleTextOutputMode
;
513 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 3;
515 // For terminal devices, cursor is always visible
517 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
518 Status
= TerminalConOutSetAttribute (
520 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
522 if (EFI_ERROR (Status
)) {
526 Status
= TerminalConOutReset (SimpleTextOutput
, FALSE
);
527 if (EFI_ERROR (Status
)) {
531 Status
= TerminalConOutSetMode (SimpleTextOutput
, 0);
532 if (EFI_ERROR (Status
)) {
536 Status
= TerminalConOutEnableCursor (SimpleTextOutput
, TRUE
);
537 if (EFI_ERROR (Status
)) {
541 Status
= gBS
->CreateEvent (
546 &TerminalDevice
->TwoSecondTimeOut
550 // Build the component name for the child device
552 TerminalDevice
->ControllerNameTable
= NULL
;
553 switch (TerminalDevice
->TerminalType
) {
557 gTerminalComponentName
.SupportedLanguages
,
558 &TerminalDevice
->ControllerNameTable
,
559 (CHAR16
*)L
"PC-ANSI Serial Console",
564 gTerminalComponentName2
.SupportedLanguages
,
565 &TerminalDevice
->ControllerNameTable
,
566 (CHAR16
*)L
"PC-ANSI Serial Console",
575 gTerminalComponentName
.SupportedLanguages
,
576 &TerminalDevice
->ControllerNameTable
,
577 (CHAR16
*)L
"VT-100 Serial Console",
582 gTerminalComponentName2
.SupportedLanguages
,
583 &TerminalDevice
->ControllerNameTable
,
584 (CHAR16
*)L
"VT-100 Serial Console",
593 gTerminalComponentName
.SupportedLanguages
,
594 &TerminalDevice
->ControllerNameTable
,
595 (CHAR16
*)L
"VT-100+ Serial Console",
600 gTerminalComponentName2
.SupportedLanguages
,
601 &TerminalDevice
->ControllerNameTable
,
602 (CHAR16
*)L
"VT-100+ Serial Console",
611 gTerminalComponentName
.SupportedLanguages
,
612 &TerminalDevice
->ControllerNameTable
,
613 (CHAR16
*)L
"VT-UTF8 Serial Console",
618 gTerminalComponentName2
.SupportedLanguages
,
619 &TerminalDevice
->ControllerNameTable
,
620 (CHAR16
*)L
"VT-UTF8 Serial Console",
627 // Install protocol interfaces for the serial device.
629 Status
= gBS
->InstallMultipleProtocolInterfaces (
630 &TerminalDevice
->Handle
,
631 &gEfiDevicePathProtocolGuid
,
632 TerminalDevice
->DevicePath
,
633 &gEfiSimpleTextInProtocolGuid
,
634 &TerminalDevice
->SimpleInput
,
635 &gEfiSimpleTextInputExProtocolGuid
,
636 &TerminalDevice
->SimpleInputEx
,
637 &gEfiSimpleTextOutProtocolGuid
,
638 &TerminalDevice
->SimpleTextOutput
,
641 if (EFI_ERROR (Status
)) {
646 // Register the Parent-Child relationship via
647 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
649 Status
= gBS
->OpenProtocol (
651 &gEfiSerialIoProtocolGuid
,
652 (VOID
**) &TerminalDevice
->SerialIo
,
653 This
->DriverBindingHandle
,
654 TerminalDevice
->Handle
,
655 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
657 if (EFI_ERROR (Status
)) {
661 if (DefaultNode
!= NULL
) {
662 FreePool (DefaultNode
);
669 // Report error code before exiting
671 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
672 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
673 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
679 // Use the Stop() function to free all resources allocated in Start()
681 if (TerminalDevice
!= NULL
) {
683 if (TerminalDevice
->Handle
!= NULL
) {
684 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
687 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
688 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
691 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
692 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
695 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
696 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
699 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
701 if (TerminalDevice
->RawFiFo
!= NULL
) {
702 FreePool (TerminalDevice
->RawFiFo
);
704 if (TerminalDevice
->UnicodeFiFo
!= NULL
) {
705 FreePool (TerminalDevice
->UnicodeFiFo
);
707 if (TerminalDevice
->EfiKeyFiFo
!= NULL
) {
708 FreePool (TerminalDevice
->EfiKeyFiFo
);
711 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
712 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
715 if (TerminalDevice
->DevicePath
!= NULL
) {
716 FreePool (TerminalDevice
->DevicePath
);
719 FreePool (TerminalDevice
);
723 if (DefaultNode
!= NULL
) {
724 FreePool (DefaultNode
);
727 This
->Stop (This
, Controller
, 0, NULL
);
733 Stop this driver on Controller by closing Simple Text In, Simple Text
734 In Ex, Simple Text Out protocol, and removing parent device path from
735 Console Device Environment Variables.
737 @param This Protocol instance pointer.
738 @param Controller Handle of device to stop driver on
739 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
740 children is zero stop the entire bus driver.
741 @param ChildHandleBuffer List of Child Handles to Stop.
743 @retval EFI_SUCCESS This driver is removed Controller.
744 @retval other This driver could not be removed from this device.
749 TerminalDriverBindingStop (
750 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
751 IN EFI_HANDLE Controller
,
752 IN UINTN NumberOfChildren
,
753 IN EFI_HANDLE
*ChildHandleBuffer
758 BOOLEAN AllChildrenStopped
;
759 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
760 TERMINAL_DEV
*TerminalDevice
;
761 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
762 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
763 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
765 Status
= gBS
->HandleProtocol (
767 &gEfiDevicePathProtocolGuid
,
768 (VOID
**) &DevicePath
770 if (EFI_ERROR (Status
)) {
775 // Complete all outstanding transactions to Controller.
776 // Don't allow any new transaction to Controller to be started.
778 if (NumberOfChildren
== 0) {
780 // Close the bus driver
782 Status
= gBS
->OpenProtocol (
785 (VOID
**) &ParentDevicePath
,
786 This
->DriverBindingHandle
,
788 EFI_OPEN_PROTOCOL_GET_PROTOCOL
790 if (!EFI_ERROR (Status
)) {
792 // Remove Parent Device Path from
793 // the Console Device Environment Variables
795 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
796 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
797 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
800 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
802 Status
= gBS
->UninstallMultipleProtocolInterfaces (
810 // Free the ParentDevicePath that was duplicated in Start()
812 if (!EFI_ERROR (Status
)) {
813 FreePool (ParentDevicePath
);
819 &gEfiSerialIoProtocolGuid
,
820 This
->DriverBindingHandle
,
826 &gEfiDevicePathProtocolGuid
,
827 This
->DriverBindingHandle
,
834 AllChildrenStopped
= TRUE
;
836 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
838 Status
= gBS
->OpenProtocol (
839 ChildHandleBuffer
[Index
],
840 &gEfiSimpleTextOutProtocolGuid
,
841 (VOID
**) &SimpleTextOutput
,
842 This
->DriverBindingHandle
,
843 ChildHandleBuffer
[Index
],
844 EFI_OPEN_PROTOCOL_GET_PROTOCOL
846 if (!EFI_ERROR (Status
)) {
848 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
852 &gEfiSerialIoProtocolGuid
,
853 This
->DriverBindingHandle
,
854 ChildHandleBuffer
[Index
]
857 Status
= gBS
->UninstallMultipleProtocolInterfaces (
858 ChildHandleBuffer
[Index
],
859 &gEfiSimpleTextInProtocolGuid
,
860 &TerminalDevice
->SimpleInput
,
861 &gEfiSimpleTextInputExProtocolGuid
,
862 &TerminalDevice
->SimpleInputEx
,
863 &gEfiSimpleTextOutProtocolGuid
,
864 &TerminalDevice
->SimpleTextOutput
,
865 &gEfiDevicePathProtocolGuid
,
866 TerminalDevice
->DevicePath
,
869 if (EFI_ERROR (Status
)) {
872 &gEfiSerialIoProtocolGuid
,
874 This
->DriverBindingHandle
,
875 ChildHandleBuffer
[Index
],
876 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
880 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
881 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
884 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
885 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
886 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
887 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
888 FreePool (TerminalDevice
->DevicePath
);
889 FreePool (TerminalDevice
);
893 if (EFI_ERROR (Status
)) {
894 AllChildrenStopped
= FALSE
;
898 if (!AllChildrenStopped
) {
899 return EFI_DEVICE_ERROR
;
907 Free notify functions list.
909 @param ListHead The list head
911 @retval EFI_SUCCESS Free the notify list successfully.
912 @retval EFI_INVALID_PARAMETER ListHead is NULL.
916 TerminalFreeNotifyList (
917 IN OUT LIST_ENTRY
*ListHead
920 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
922 if (ListHead
== NULL
) {
923 return EFI_INVALID_PARAMETER
;
925 while (!IsListEmpty (ListHead
)) {
927 ListHead
->ForwardLink
,
928 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
930 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
932 RemoveEntryList (ListHead
->ForwardLink
);
933 FreePool (NotifyNode
);
941 Update terminal device path in Console Device Environment Variables.
943 @param VariableName The Console Device Environment Variable.
944 @param ParentDevicePath The terminal device path to be updated.
948 TerminalUpdateConsoleDevVariable (
949 IN CHAR16
*VariableName
,
950 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
956 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
957 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
958 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
963 // Get global variable and its size according to the name given.
965 Variable
= TerminalGetVariableAndSize (
967 &gEfiGlobalVariableGuid
,
971 // Append terminal device path onto the variable.
973 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
974 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
975 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
976 if (Variable
!= NULL
) {
980 if (TempDevicePath
!= NULL
) {
981 FreePool (TempDevicePath
);
984 Variable
= NewVariable
;
987 VariableSize
= GetDevicePathSize (Variable
);
989 Status
= gRT
->SetVariable (
991 &gEfiGlobalVariableGuid
,
992 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
996 ASSERT_EFI_ERROR (Status
);
1004 Remove terminal device path from Console Device Environment Variables.
1006 @param VariableName Console Device Environment Variables.
1007 @param ParentDevicePath The terminal device path to be updated.
1011 TerminalRemoveConsoleDevVariable (
1012 IN CHAR16
*VariableName
,
1013 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1022 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1023 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1024 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1025 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1026 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1027 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1033 // Get global variable and its size according to the name given.
1035 Variable
= TerminalGetVariableAndSize (
1037 &gEfiGlobalVariableGuid
,
1040 if (Variable
== NULL
) {
1045 OriginalVariable
= Variable
;
1049 // Get first device path instance from Variable
1051 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1052 if (Instance
== NULL
) {
1053 FreePool (OriginalVariable
);
1057 // Loop through all the device path instances of Variable
1061 // Loop through all the terminal types that this driver supports
1064 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1066 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1069 // Compare the generated device path to the current device path instance
1071 if (TempDevicePath
!= NULL
) {
1072 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1077 FreePool (TempDevicePath
);
1081 // If a match was not found, then keep the current device path instance
1084 SavedNewVariable
= NewVariable
;
1085 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1086 if (SavedNewVariable
!= NULL
) {
1087 FreePool (SavedNewVariable
);
1091 // Get next device path instance from Variable
1093 FreePool (Instance
);
1094 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1095 } while (Instance
!= NULL
);
1097 FreePool (OriginalVariable
);
1100 VariableSize
= GetDevicePathSize (NewVariable
);
1102 Status
= gRT
->SetVariable (
1104 &gEfiGlobalVariableGuid
,
1105 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1109 ASSERT_EFI_ERROR (Status
);
1112 if (NewVariable
!= NULL
) {
1113 FreePool (NewVariable
);
1121 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1122 buffer, and the size of the buffer. On failure return NULL.
1124 @param Name String part of EFI variable name
1125 @param VendorGuid GUID part of EFI variable name
1126 @param VariableSize Returns the size of the EFI variable that was read
1128 @return Dynamically allocated memory that contains a copy of the EFI variable.
1129 Caller is responsible freeing the buffer. If variable was not read,
1134 TerminalGetVariableAndSize (
1136 IN EFI_GUID
*VendorGuid
,
1137 OUT UINTN
*VariableSize
1147 // Pass in a small size buffer to find the actual variable size.
1150 Buffer
= AllocatePool (BufferSize
);
1151 if (Buffer
== NULL
) {
1156 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1158 if (Status
== EFI_SUCCESS
) {
1159 *VariableSize
= BufferSize
;
1162 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1164 // Allocate the buffer to return
1167 Buffer
= AllocatePool (BufferSize
);
1168 if (Buffer
== NULL
) {
1173 // Read variable into the allocated buffer.
1175 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1176 if (EFI_ERROR (Status
)) {
1183 // Variable not found or other errors met.
1190 *VariableSize
= BufferSize
;
1195 Build terminal device path according to terminal type.
1197 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1198 @param ParentDevicePath Parent device path.
1199 @param TerminalDevicePath Returned terminal device path, if building successfully.
1201 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1202 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1203 @retval EFI_SUCCESS Build terminal device path successfully.
1207 SetTerminalDevicePath (
1208 IN UINT8 TerminalType
,
1209 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1210 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1213 VENDOR_DEVICE_PATH Node
;
1215 *TerminalDevicePath
= NULL
;
1216 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1217 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1220 // Generate terminal device path node according to terminal type.
1222 switch (TerminalType
) {
1225 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1229 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1233 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1237 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1241 return EFI_UNSUPPORTED
;
1245 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1247 SetDevicePathNodeLength (
1249 sizeof (VENDOR_DEVICE_PATH
)
1253 // Append the terminal node onto parent device path
1254 // to generate a complete terminal device path.
1256 *TerminalDevicePath
= AppendDevicePathNode (
1258 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1260 if (*TerminalDevicePath
== NULL
) {
1261 return EFI_OUT_OF_RESOURCES
;
1268 The user Entry Point for module Terminal. The user code starts with this function.
1270 @param ImageHandle The firmware allocated handle for the EFI image.
1271 @param SystemTable A pointer to the EFI System Table.
1273 @retval EFI_SUCCESS The entry point is executed successfully.
1274 @retval other Some error occurs when executing this entry point.
1280 IN EFI_HANDLE ImageHandle
,
1281 IN EFI_SYSTEM_TABLE
*SystemTable
1287 // Install driver model protocol(s).
1289 Status
= EfiLibInstallDriverBindingComponentName2 (
1292 &gTerminalDriverBinding
,
1294 &gTerminalComponentName
,
1295 &gTerminalComponentName2
1297 ASSERT_EFI_ERROR (Status
);
1303 Check if the device supports hot-plug through its device path.
1305 This function could be updated to check more types of Hot Plug devices.
1306 Currently, it checks USB and PCCard device.
1308 @param DevicePath Pointer to device's device path.
1310 @retval TRUE The devcie is a hot-plug device
1311 @retval FALSE The devcie is not a hot-plug device.
1316 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1319 EFI_DEVICE_PATH_PROTOCOL
*CheckDevicePath
;
1321 CheckDevicePath
= DevicePath
;
1322 while (!IsDevicePathEnd (CheckDevicePath
)) {
1324 // Check device whether is hot plug device or not throught Device Path
1326 if ((DevicePathType (CheckDevicePath
) == MESSAGING_DEVICE_PATH
) &&
1327 (DevicePathSubType (CheckDevicePath
) == MSG_USB_DP
||
1328 DevicePathSubType (CheckDevicePath
) == MSG_USB_CLASS_DP
||
1329 DevicePathSubType (CheckDevicePath
) == MSG_USB_WWID_DP
)) {
1331 // If Device is USB device
1335 if ((DevicePathType (CheckDevicePath
) == HARDWARE_DEVICE_PATH
) &&
1336 (DevicePathSubType (CheckDevicePath
) == HW_PCCARD_DP
)) {
1338 // If Device is PCCard
1343 CheckDevicePath
= NextDevicePathNode (CheckDevicePath
);