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 - 2008, 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 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
130 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
131 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
132 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
134 return EFI_UNSUPPORTED
;
138 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
140 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
141 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
142 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
143 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
145 return EFI_UNSUPPORTED
;
149 // Open the IO Abstraction(s) needed to perform the supported test
151 Status
= gBS
->OpenProtocol (
153 &gEfiDevicePathProtocolGuid
,
154 (VOID
**) &ParentDevicePath
,
155 This
->DriverBindingHandle
,
157 EFI_OPEN_PROTOCOL_BY_DRIVER
159 if (Status
== EFI_ALREADY_STARTED
) {
163 if (EFI_ERROR (Status
)) {
169 &gEfiDevicePathProtocolGuid
,
170 This
->DriverBindingHandle
,
175 // The Controller must support the Serial I/O Protocol.
176 // This driver is a bus driver with at most 1 child device, so it is
177 // ok for it to be already started.
179 Status
= gBS
->OpenProtocol (
181 &gEfiSerialIoProtocolGuid
,
183 This
->DriverBindingHandle
,
185 EFI_OPEN_PROTOCOL_BY_DRIVER
187 if (Status
== EFI_ALREADY_STARTED
) {
191 if (EFI_ERROR (Status
)) {
195 // Close the I/O Abstraction(s) used to perform the supported test
199 &gEfiSerialIoProtocolGuid
,
200 This
->DriverBindingHandle
,
208 Start this driver on Controller by opening a Serial IO protocol,
209 reading Device Path, and creating a child handle with a Simple Text In,
210 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
211 And store Console Device Environment Variables.
213 @param This Protocol instance pointer.
214 @param Controller Handle of device to bind driver to
215 @param RemainingDevicePath Optional parameter use to pick a specific child
218 @retval EFI_SUCCESS This driver is added to Controller.
219 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
220 @retval other This driver does not support this device.
225 TerminalDriverBindingStart (
226 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
227 IN EFI_HANDLE Controller
,
228 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
232 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
233 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
234 VENDOR_DEVICE_PATH
*Node
;
235 VENDOR_DEVICE_PATH
*DefaultNode
;
236 EFI_SERIAL_IO_MODE
*Mode
;
237 UINTN SerialInTimeOut
;
238 TERMINAL_DEV
*TerminalDevice
;
240 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
243 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
244 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
246 TerminalDevice
= NULL
;
249 // Get the Device Path Protocol to build the device path of the child device
251 Status
= gBS
->OpenProtocol (
253 &gEfiDevicePathProtocolGuid
,
254 (VOID
**) &ParentDevicePath
,
255 This
->DriverBindingHandle
,
257 EFI_OPEN_PROTOCOL_BY_DRIVER
259 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
264 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
266 Status
= gBS
->OpenProtocol (
268 &gEfiSerialIoProtocolGuid
,
270 This
->DriverBindingHandle
,
272 EFI_OPEN_PROTOCOL_BY_DRIVER
274 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
278 if (Status
!= EFI_ALREADY_STARTED
) {
280 // If Serial I/O is not already open by this driver, then tag the handle
281 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
282 // StdErrDev variables with the list of possible terminal types on this
285 Status
= gBS
->OpenProtocol (
289 This
->DriverBindingHandle
,
291 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
293 if (EFI_ERROR (Status
)) {
294 Status
= gBS
->InstallMultipleProtocolInterfaces (
297 DuplicateDevicePath (ParentDevicePath
),
300 if (EFI_ERROR (Status
)) {
304 if (!IsHotPlugDevice (ParentDevicePath
)) {
306 // if the serial device is a hot plug device, do not update the
307 // ConInDev, ConOutDev, and StdErrDev variables.
309 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
310 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
311 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
316 // Make sure a child handle does not already exist. This driver can only
317 // produce one child per serial port.
319 Status
= gBS
->OpenProtocolInformation (
321 &gEfiSerialIoProtocolGuid
,
325 if (!EFI_ERROR (Status
)) {
326 Status
= EFI_SUCCESS
;
327 for (Index
= 0; Index
< EntryCount
; Index
++) {
328 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
329 Status
= EFI_ALREADY_STARTED
;
333 FreePool (OpenInfoBuffer
);
334 if (EFI_ERROR (Status
)) {
339 // If RemainingDevicePath is NULL, then create default device path node
341 if (RemainingDevicePath
== NULL
) {
342 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
343 if (DefaultNode
== NULL
) {
344 Status
= EFI_OUT_OF_RESOURCES
;
348 TerminalType
= FixedPcdGet8 (PcdDefaultTerminalType
);
350 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)
352 ASSERT (TerminalType
<= VTUTF8TYPE
);
354 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
355 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
358 // Use the RemainingDevicePath to determine the terminal type
360 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
361 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
362 TerminalType
= PCANSITYPE
;
363 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
364 TerminalType
= VT100TYPE
;
365 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
366 TerminalType
= VT100PLUSTYPE
;
367 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
368 TerminalType
= VTUTF8TYPE
;
375 // Initialize the Terminal Dev
377 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
378 if (TerminalDevice
== NULL
) {
379 Status
= EFI_OUT_OF_RESOURCES
;
383 TerminalDevice
->TerminalType
= TerminalType
;
384 TerminalDevice
->SerialIo
= SerialIo
;
386 InitializeListHead (&TerminalDevice
->NotifyList
);
387 Status
= gBS
->CreateEvent (
390 TerminalConInWaitForKeyEx
,
391 &TerminalDevice
->SimpleInputEx
,
392 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
394 if (EFI_ERROR (Status
)) {
399 Status
= gBS
->CreateEvent (
402 TerminalConInWaitForKey
,
403 &TerminalDevice
->SimpleInput
,
404 &TerminalDevice
->SimpleInput
.WaitForKey
406 if (EFI_ERROR (Status
)) {
410 // Allocates and initializes the FIFO buffer to be zero, used for accommodating
411 // the pre-read pending characters.
413 TerminalDevice
->RawFiFo
= AllocateZeroPool (sizeof (RAW_DATA_FIFO
));
414 if (TerminalDevice
->RawFiFo
== NULL
) {
417 TerminalDevice
->UnicodeFiFo
= AllocateZeroPool (sizeof (UNICODE_FIFO
));
418 if (TerminalDevice
->UnicodeFiFo
== NULL
) {
421 TerminalDevice
->EfiKeyFiFo
= AllocateZeroPool (sizeof (EFI_KEY_FIFO
));
422 if (TerminalDevice
->EfiKeyFiFo
== NULL
) {
427 // Set the timeout value of serial buffer for
428 // keystroke response performance issue
430 Mode
= TerminalDevice
->SerialIo
->Mode
;
433 if (Mode
->BaudRate
!= 0) {
434 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
437 Status
= TerminalDevice
->SerialIo
->SetAttributes (
438 TerminalDevice
->SerialIo
,
440 Mode
->ReceiveFifoDepth
,
441 (UINT32
) SerialInTimeOut
,
442 (EFI_PARITY_TYPE
) (Mode
->Parity
),
443 (UINT8
) Mode
->DataBits
,
444 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
446 if (EFI_ERROR (Status
)) {
448 // if set attributes operation fails, invalidate
449 // the value of SerialInTimeOut,thus make it
450 // inconsistent with the default timeout value
451 // of serial buffer. This will invoke the recalculation
452 // in the readkeystroke routine.
454 TerminalDevice
->SerialInTimeOut
= 0;
456 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
459 // Build the device path for the child device
461 Status
= SetTerminalDevicePath (
462 TerminalDevice
->TerminalType
,
464 &TerminalDevice
->DevicePath
466 if (EFI_ERROR (Status
)) {
470 DevicePath
= TerminalDevice
->DevicePath
;
472 Status
= TerminalDevice
->SimpleInput
.Reset (
473 &TerminalDevice
->SimpleInput
,
476 if (EFI_ERROR (Status
)) {
478 // Need to report Error Code first
483 // Set Simple Text Output Protocol from template.
485 SimpleTextOutput
= CopyMem (
486 &TerminalDevice
->SimpleTextOutput
,
487 &mTerminalDevTemplate
.SimpleTextOutput
,
488 sizeof (mTerminalDevTemplate
.SimpleTextOutput
)
490 SimpleTextOutput
->Mode
= &TerminalDevice
->SimpleTextOutputMode
;
492 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 3;
494 // For terminal devices, cursor is always visible
496 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
497 Status
= TerminalConOutSetAttribute (
499 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
501 if (EFI_ERROR (Status
)) {
505 Status
= TerminalConOutReset (SimpleTextOutput
, FALSE
);
506 if (EFI_ERROR (Status
)) {
510 Status
= TerminalConOutSetMode (SimpleTextOutput
, 0);
511 if (EFI_ERROR (Status
)) {
515 Status
= TerminalConOutEnableCursor (SimpleTextOutput
, TRUE
);
516 if (EFI_ERROR (Status
)) {
520 Status
= gBS
->CreateEvent (
525 &TerminalDevice
->TwoSecondTimeOut
529 // Build the component name for the child device
531 TerminalDevice
->ControllerNameTable
= NULL
;
532 switch (TerminalDevice
->TerminalType
) {
536 gTerminalComponentName
.SupportedLanguages
,
537 &TerminalDevice
->ControllerNameTable
,
538 (CHAR16
*)L
"PC-ANSI Serial Console",
543 gTerminalComponentName2
.SupportedLanguages
,
544 &TerminalDevice
->ControllerNameTable
,
545 (CHAR16
*)L
"PC-ANSI Serial Console",
554 gTerminalComponentName
.SupportedLanguages
,
555 &TerminalDevice
->ControllerNameTable
,
556 (CHAR16
*)L
"VT-100 Serial Console",
561 gTerminalComponentName2
.SupportedLanguages
,
562 &TerminalDevice
->ControllerNameTable
,
563 (CHAR16
*)L
"VT-100 Serial Console",
572 gTerminalComponentName
.SupportedLanguages
,
573 &TerminalDevice
->ControllerNameTable
,
574 (CHAR16
*)L
"VT-100+ Serial Console",
579 gTerminalComponentName2
.SupportedLanguages
,
580 &TerminalDevice
->ControllerNameTable
,
581 (CHAR16
*)L
"VT-100+ Serial Console",
590 gTerminalComponentName
.SupportedLanguages
,
591 &TerminalDevice
->ControllerNameTable
,
592 (CHAR16
*)L
"VT-UTF8 Serial Console",
597 gTerminalComponentName2
.SupportedLanguages
,
598 &TerminalDevice
->ControllerNameTable
,
599 (CHAR16
*)L
"VT-UTF8 Serial Console",
606 // Install protocol interfaces for the serial device.
608 Status
= gBS
->InstallMultipleProtocolInterfaces (
609 &TerminalDevice
->Handle
,
610 &gEfiDevicePathProtocolGuid
,
611 TerminalDevice
->DevicePath
,
612 &gEfiSimpleTextInProtocolGuid
,
613 &TerminalDevice
->SimpleInput
,
614 &gEfiSimpleTextInputExProtocolGuid
,
615 &TerminalDevice
->SimpleInputEx
,
616 &gEfiSimpleTextOutProtocolGuid
,
617 &TerminalDevice
->SimpleTextOutput
,
620 if (EFI_ERROR (Status
)) {
625 // Register the Parent-Child relationship via
626 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
628 Status
= gBS
->OpenProtocol (
630 &gEfiSerialIoProtocolGuid
,
631 (VOID
**) &TerminalDevice
->SerialIo
,
632 This
->DriverBindingHandle
,
633 TerminalDevice
->Handle
,
634 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
636 if (EFI_ERROR (Status
)) {
640 if (DefaultNode
!= NULL
) {
641 FreePool (DefaultNode
);
648 // Report error code before exiting
650 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
651 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
652 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
658 // Use the Stop() function to free all resources allocated in Start()
660 if (TerminalDevice
!= NULL
) {
662 if (TerminalDevice
->Handle
!= NULL
) {
663 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
666 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
667 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
670 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
671 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
674 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
675 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
678 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
680 if (TerminalDevice
->RawFiFo
!= NULL
) {
681 FreePool (TerminalDevice
->RawFiFo
);
683 if (TerminalDevice
->UnicodeFiFo
!= NULL
) {
684 FreePool (TerminalDevice
->UnicodeFiFo
);
686 if (TerminalDevice
->EfiKeyFiFo
!= NULL
) {
687 FreePool (TerminalDevice
->EfiKeyFiFo
);
690 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
691 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
694 if (TerminalDevice
->DevicePath
!= NULL
) {
695 FreePool (TerminalDevice
->DevicePath
);
698 FreePool (TerminalDevice
);
702 if (DefaultNode
!= NULL
) {
703 FreePool (DefaultNode
);
706 This
->Stop (This
, Controller
, 0, NULL
);
712 Stop this driver on Controller by closing Simple Text In, Simple Text
713 In Ex, Simple Text Out protocol, and removing parent device path from
714 Console Device Environment Variables.
716 @param This Protocol instance pointer.
717 @param Controller Handle of device to stop driver on
718 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
719 children is zero stop the entire bus driver.
720 @param ChildHandleBuffer List of Child Handles to Stop.
722 @retval EFI_SUCCESS This driver is removed Controller.
723 @retval other This driver could not be removed from this device.
728 TerminalDriverBindingStop (
729 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
730 IN EFI_HANDLE Controller
,
731 IN UINTN NumberOfChildren
,
732 IN EFI_HANDLE
*ChildHandleBuffer
737 BOOLEAN AllChildrenStopped
;
738 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
739 TERMINAL_DEV
*TerminalDevice
;
740 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
741 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
742 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
744 Status
= gBS
->HandleProtocol (
746 &gEfiDevicePathProtocolGuid
,
747 (VOID
**) &DevicePath
749 if (EFI_ERROR (Status
)) {
754 // Complete all outstanding transactions to Controller.
755 // Don't allow any new transaction to Controller to be started.
757 if (NumberOfChildren
== 0) {
759 // Close the bus driver
761 Status
= gBS
->OpenProtocol (
764 (VOID
**) &ParentDevicePath
,
765 This
->DriverBindingHandle
,
767 EFI_OPEN_PROTOCOL_GET_PROTOCOL
769 if (!EFI_ERROR (Status
)) {
771 // Remove Parent Device Path from
772 // the Console Device Environment Variables
774 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
775 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
776 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
779 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
781 Status
= gBS
->UninstallMultipleProtocolInterfaces (
789 // Free the ParentDevicePath that was duplicated in Start()
791 if (!EFI_ERROR (Status
)) {
792 FreePool (ParentDevicePath
);
798 &gEfiSerialIoProtocolGuid
,
799 This
->DriverBindingHandle
,
805 &gEfiDevicePathProtocolGuid
,
806 This
->DriverBindingHandle
,
813 AllChildrenStopped
= TRUE
;
815 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
817 Status
= gBS
->OpenProtocol (
818 ChildHandleBuffer
[Index
],
819 &gEfiSimpleTextOutProtocolGuid
,
820 (VOID
**) &SimpleTextOutput
,
821 This
->DriverBindingHandle
,
822 ChildHandleBuffer
[Index
],
823 EFI_OPEN_PROTOCOL_GET_PROTOCOL
825 if (!EFI_ERROR (Status
)) {
827 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
831 &gEfiSerialIoProtocolGuid
,
832 This
->DriverBindingHandle
,
833 ChildHandleBuffer
[Index
]
836 Status
= gBS
->UninstallMultipleProtocolInterfaces (
837 ChildHandleBuffer
[Index
],
838 &gEfiSimpleTextInProtocolGuid
,
839 &TerminalDevice
->SimpleInput
,
840 &gEfiSimpleTextInputExProtocolGuid
,
841 &TerminalDevice
->SimpleInputEx
,
842 &gEfiSimpleTextOutProtocolGuid
,
843 &TerminalDevice
->SimpleTextOutput
,
844 &gEfiDevicePathProtocolGuid
,
845 TerminalDevice
->DevicePath
,
848 if (EFI_ERROR (Status
)) {
851 &gEfiSerialIoProtocolGuid
,
853 This
->DriverBindingHandle
,
854 ChildHandleBuffer
[Index
],
855 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
859 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
860 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
863 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
864 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
865 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
866 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
867 FreePool (TerminalDevice
->DevicePath
);
868 FreePool (TerminalDevice
);
872 if (EFI_ERROR (Status
)) {
873 AllChildrenStopped
= FALSE
;
877 if (!AllChildrenStopped
) {
878 return EFI_DEVICE_ERROR
;
886 Free notify functions list.
888 @param ListHead The list head
890 @retval EFI_SUCCESS Free the notify list successfully.
891 @retval EFI_INVALID_PARAMETER ListHead is NULL.
895 TerminalFreeNotifyList (
896 IN OUT LIST_ENTRY
*ListHead
899 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
901 if (ListHead
== NULL
) {
902 return EFI_INVALID_PARAMETER
;
904 while (!IsListEmpty (ListHead
)) {
906 ListHead
->ForwardLink
,
907 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
909 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
911 RemoveEntryList (ListHead
->ForwardLink
);
912 FreePool (NotifyNode
);
920 Update terminal device path in Console Device Environment Variables.
922 @param VariableName The Console Device Environment Variable.
923 @param ParentDevicePath The terminal device path to be updated.
927 TerminalUpdateConsoleDevVariable (
928 IN CHAR16
*VariableName
,
929 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
935 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
936 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
937 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
942 // Get global variable and its size according to the name given.
944 Variable
= TerminalGetVariableAndSize (
946 &gEfiGlobalVariableGuid
,
950 // Append terminal device path onto the variable.
952 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
953 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
954 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
955 if (Variable
!= NULL
) {
959 if (TempDevicePath
!= NULL
) {
960 FreePool (TempDevicePath
);
963 Variable
= NewVariable
;
966 VariableSize
= GetDevicePathSize (Variable
);
968 Status
= gRT
->SetVariable (
970 &gEfiGlobalVariableGuid
,
971 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
975 ASSERT_EFI_ERROR (Status
);
983 Remove terminal device path from Console Device Environment Variables.
985 @param VariableName Console Device Environment Variables.
986 @param ParentDevicePath The terminal device path to be updated.
990 TerminalRemoveConsoleDevVariable (
991 IN CHAR16
*VariableName
,
992 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1001 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1002 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1003 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1004 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1005 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1006 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1012 // Get global variable and its size according to the name given.
1014 Variable
= TerminalGetVariableAndSize (
1016 &gEfiGlobalVariableGuid
,
1019 if (Variable
== NULL
) {
1024 OriginalVariable
= Variable
;
1028 // Get first device path instance from Variable
1030 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1031 if (Instance
== NULL
) {
1032 FreePool (OriginalVariable
);
1036 // Loop through all the device path instances of Variable
1040 // Loop through all the terminal types that this driver supports
1043 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1045 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1048 // Compare the generated device path to the current device path instance
1050 if (TempDevicePath
!= NULL
) {
1051 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1056 FreePool (TempDevicePath
);
1060 // If a match was not found, then keep the current device path instance
1063 SavedNewVariable
= NewVariable
;
1064 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1065 if (SavedNewVariable
!= NULL
) {
1066 FreePool (SavedNewVariable
);
1070 // Get next device path instance from Variable
1072 FreePool (Instance
);
1073 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1074 } while (Instance
!= NULL
);
1076 FreePool (OriginalVariable
);
1079 VariableSize
= GetDevicePathSize (NewVariable
);
1081 Status
= gRT
->SetVariable (
1083 &gEfiGlobalVariableGuid
,
1084 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1088 ASSERT_EFI_ERROR (Status
);
1091 if (NewVariable
!= NULL
) {
1092 FreePool (NewVariable
);
1100 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1101 buffer, and the size of the buffer. On failure return NULL.
1103 @param Name String part of EFI variable name
1104 @param VendorGuid GUID part of EFI variable name
1105 @param VariableSize Returns the size of the EFI variable that was read
1107 @return Dynamically allocated memory that contains a copy of the EFI variable.
1108 Caller is responsible freeing the buffer. If variable was not read,
1113 TerminalGetVariableAndSize (
1115 IN EFI_GUID
*VendorGuid
,
1116 OUT UINTN
*VariableSize
1126 // Pass in a small size buffer to find the actual variable size.
1129 Buffer
= AllocatePool (BufferSize
);
1130 if (Buffer
== NULL
) {
1135 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1137 if (Status
== EFI_SUCCESS
) {
1138 *VariableSize
= BufferSize
;
1141 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1143 // Allocate the buffer to return
1146 Buffer
= AllocatePool (BufferSize
);
1147 if (Buffer
== NULL
) {
1152 // Read variable into the allocated buffer.
1154 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1155 if (EFI_ERROR (Status
)) {
1162 // Variable not found or other errors met.
1169 *VariableSize
= BufferSize
;
1174 Build terminal device path according to terminal type.
1176 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1177 @param ParentDevicePath Parent device path.
1178 @param TerminalDevicePath Returned terminal device path, if building successfully.
1180 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1181 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1182 @retval EFI_SUCCESS Build terminal device path successfully.
1186 SetTerminalDevicePath (
1187 IN UINT8 TerminalType
,
1188 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1189 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1192 VENDOR_DEVICE_PATH Node
;
1194 *TerminalDevicePath
= NULL
;
1195 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1196 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1199 // Generate terminal device path node according to terminal type.
1201 switch (TerminalType
) {
1204 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1208 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1212 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1216 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1220 return EFI_UNSUPPORTED
;
1224 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1226 SetDevicePathNodeLength (
1228 sizeof (VENDOR_DEVICE_PATH
)
1232 // Append the terminal node onto parent device path
1233 // to generate a complete terminal device path.
1235 *TerminalDevicePath
= AppendDevicePathNode (
1237 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1239 if (*TerminalDevicePath
== NULL
) {
1240 return EFI_OUT_OF_RESOURCES
;
1247 The user Entry Point for module Terminal. The user code starts with this function.
1249 @param ImageHandle The firmware allocated handle for the EFI image.
1250 @param SystemTable A pointer to the EFI System Table.
1252 @retval EFI_SUCCESS The entry point is executed successfully.
1253 @retval other Some error occurs when executing this entry point.
1259 IN EFI_HANDLE ImageHandle
,
1260 IN EFI_SYSTEM_TABLE
*SystemTable
1266 // Install driver model protocol(s).
1268 Status
= EfiLibInstallDriverBindingComponentName2 (
1271 &gTerminalDriverBinding
,
1273 &gTerminalComponentName
,
1274 &gTerminalComponentName2
1276 ASSERT_EFI_ERROR (Status
);
1282 Check if the device supports hot-plug through its device path.
1284 This function could be updated to check more types of Hot Plug devices.
1285 Currently, it checks USB and PCCard device.
1287 @param DevicePath Pointer to device's device path.
1289 @retval TRUE The devcie is a hot-plug device
1290 @retval FALSE The devcie is not a hot-plug device.
1295 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1298 EFI_DEVICE_PATH_PROTOCOL
*CheckDevicePath
;
1300 CheckDevicePath
= DevicePath
;
1301 while (!IsDevicePathEnd (CheckDevicePath
)) {
1303 // Check device whether is hot plug device or not throught Device Path
1305 if ((DevicePathType (CheckDevicePath
) == MESSAGING_DEVICE_PATH
) &&
1306 (DevicePathSubType (CheckDevicePath
) == MSG_USB_DP
||
1307 DevicePathSubType (CheckDevicePath
) == MSG_USB_CLASS_DP
||
1308 DevicePathSubType (CheckDevicePath
) == MSG_USB_WWID_DP
)) {
1310 // If Device is USB device
1314 if ((DevicePathType (CheckDevicePath
) == HARDWARE_DEVICE_PATH
) &&
1315 (DevicePathSubType (CheckDevicePath
) == HW_PCCARD_DP
)) {
1317 // If Device is PCCard
1322 CheckDevicePath
= NextDevicePathNode (CheckDevicePath
);