2 Produces Simple Text Input Protocl, 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.
20 Free notify functions list.
22 @param ListHead The list head
24 @retval EFI_SUCCESS Free the notify list successfully.
25 @retval EFI_INVALID_PARAMETER ListHead is NULL.
29 TerminalFreeNotifyList (
30 IN OUT LIST_ENTRY
*ListHead
36 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
37 TerminalDriverBindingSupported
,
38 TerminalDriverBindingStart
,
39 TerminalDriverBindingStop
,
46 EFI_GUID
*gTerminalType
[] = {
54 TERMINAL_DEV mTerminalDevTemplate
= {
55 TERMINAL_DEV_SIGNATURE
,
62 TerminalConInReadKeyStroke
,
67 TerminalConOutOutputString
,
68 TerminalConOutTestString
,
69 TerminalConOutQueryMode
,
70 TerminalConOutSetMode
,
71 TerminalConOutSetAttribute
,
72 TerminalConOutClearScreen
,
73 TerminalConOutSetCursorPosition
,
74 TerminalConOutEnableCursor
,
77 { // SimpleTextOutputMode
80 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
), // Attribute
101 NULL
, // ControllerNameTable
106 { // SimpleTextInputEx
107 TerminalConInResetEx
,
108 TerminalConInReadKeyStrokeEx
,
110 TerminalConInSetState
,
111 TerminalConInRegisterKeyNotify
,
112 TerminalConInUnregisterKeyNotify
,
122 Test to see if this driver supports Controller.
124 @param This Protocol instance pointer.
125 @param Controller Handle of device to test
126 @param RemainingDevicePath Optional parameter use to pick a specific child
129 @retval EFI_SUCCESS This driver supports this device.
130 @retval EFI_ALREADY_STARTED This driver is already running on this device.
131 @retval other This driver does not support this device.
136 TerminalDriverBindingSupported (
137 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
138 IN EFI_HANDLE Controller
,
139 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
143 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
144 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
145 VENDOR_DEVICE_PATH
*Node
;
148 // If remaining device path is not NULL, then make sure it is a
149 // device path that describes a terminal communications protocol.
151 if (RemainingDevicePath
!= NULL
) {
153 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
155 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
156 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
157 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
159 return EFI_UNSUPPORTED
;
163 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
165 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
166 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
167 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
168 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
170 return EFI_UNSUPPORTED
;
174 // Open the IO Abstraction(s) needed to perform the supported test
176 Status
= gBS
->OpenProtocol (
178 &gEfiDevicePathProtocolGuid
,
179 (VOID
**) &ParentDevicePath
,
180 This
->DriverBindingHandle
,
182 EFI_OPEN_PROTOCOL_BY_DRIVER
184 if (Status
== EFI_ALREADY_STARTED
) {
188 if (EFI_ERROR (Status
)) {
194 &gEfiDevicePathProtocolGuid
,
195 This
->DriverBindingHandle
,
200 // The Controller must support the Serial I/O Protocol.
201 // This driver is a bus driver with at most 1 child device, so it is
202 // ok for it to be already started.
204 Status
= gBS
->OpenProtocol (
206 &gEfiSerialIoProtocolGuid
,
208 This
->DriverBindingHandle
,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
212 if (Status
== EFI_ALREADY_STARTED
) {
216 if (EFI_ERROR (Status
)) {
220 // Close the I/O Abstraction(s) used to perform the supported test
224 &gEfiSerialIoProtocolGuid
,
225 This
->DriverBindingHandle
,
233 Start this driver on Controller by opening a Serial IO protocol,
234 reading Device Path, and creating a child handle with a Simple Text In,
235 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
236 And store Console Device Environment Variables.
238 @param This Protocol instance pointer.
239 @param Controller Handle of device to bind driver to
240 @param RemainingDevicePath Optional parameter use to pick a specific child
243 @retval EFI_SUCCESS This driver is added to Controller.
244 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
245 @retval other This driver does not support this device.
250 TerminalDriverBindingStart (
251 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
252 IN EFI_HANDLE Controller
,
253 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
257 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
258 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
259 VENDOR_DEVICE_PATH
*Node
;
260 VENDOR_DEVICE_PATH
*DefaultNode
;
261 EFI_SERIAL_IO_MODE
*Mode
;
262 UINTN SerialInTimeOut
;
263 TERMINAL_DEV
*TerminalDevice
;
265 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
268 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
270 TerminalDevice
= NULL
;
273 // Get the Device Path Protocol to build the device path of the child device
275 Status
= gBS
->OpenProtocol (
277 &gEfiDevicePathProtocolGuid
,
278 (VOID
**) &ParentDevicePath
,
279 This
->DriverBindingHandle
,
281 EFI_OPEN_PROTOCOL_BY_DRIVER
283 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
288 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
290 Status
= gBS
->OpenProtocol (
292 &gEfiSerialIoProtocolGuid
,
294 This
->DriverBindingHandle
,
296 EFI_OPEN_PROTOCOL_BY_DRIVER
298 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
302 if (Status
!= EFI_ALREADY_STARTED
) {
304 // If Serial I/O is not already open by this driver, then tag the handle
305 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
306 // StdErrDev variables with the list of possible terminal types on this
309 Status
= gBS
->OpenProtocol (
313 This
->DriverBindingHandle
,
315 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
317 if (EFI_ERROR (Status
)) {
318 Status
= gBS
->InstallMultipleProtocolInterfaces (
321 DuplicateDevicePath (ParentDevicePath
),
324 if (EFI_ERROR (Status
)) {
328 // if the serial device is a hot plug device, do not update the
329 // ConInDev, ConOutDev, and StdErrDev variables.
331 Status
= gBS
->OpenProtocol (
333 &gEfiHotPlugDeviceGuid
,
335 This
->DriverBindingHandle
,
337 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
339 if (EFI_ERROR (Status
)) {
340 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
341 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
342 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
347 // Make sure a child handle does not already exist. This driver can only
348 // produce one child per serial port.
350 Status
= gBS
->OpenProtocolInformation (
352 &gEfiSerialIoProtocolGuid
,
356 if (!EFI_ERROR (Status
)) {
357 Status
= EFI_SUCCESS
;
358 for (Index
= 0; Index
< EntryCount
; Index
++) {
359 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
360 Status
= EFI_ALREADY_STARTED
;
364 FreePool (OpenInfoBuffer
);
365 if (EFI_ERROR (Status
)) {
370 // If RemainingDevicePath is NULL, then create default device path node
372 if (RemainingDevicePath
== NULL
) {
373 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
374 if (DefaultNode
== NULL
) {
375 Status
= EFI_OUT_OF_RESOURCES
;
379 TerminalType
= FixedPcdGet8 (PcdDefaultTerminalType
);
381 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)
383 ASSERT (TerminalType
<= VTUTF8TYPE
);
385 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
386 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
389 // Use the RemainingDevicePath to determine the terminal type
391 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
392 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
393 TerminalType
= PCANSITYPE
;
394 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
395 TerminalType
= VT100TYPE
;
396 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
397 TerminalType
= VT100PLUSTYPE
;
398 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
399 TerminalType
= VTUTF8TYPE
;
406 // Initialize the Terminal Dev
408 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
409 if (TerminalDevice
== NULL
) {
410 Status
= EFI_OUT_OF_RESOURCES
;
414 TerminalDevice
->TerminalType
= TerminalType
;
415 TerminalDevice
->SerialIo
= SerialIo
;
417 InitializeListHead (&TerminalDevice
->NotifyList
);
418 Status
= gBS
->CreateEvent (
421 TerminalConInWaitForKeyEx
,
422 &TerminalDevice
->SimpleInputEx
,
423 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
425 if (EFI_ERROR (Status
)) {
430 Status
= gBS
->CreateEvent (
433 TerminalConInWaitForKey
,
434 &TerminalDevice
->SimpleInput
,
435 &TerminalDevice
->SimpleInput
.WaitForKey
437 if (EFI_ERROR (Status
)) {
441 // initialize the FIFO buffer used for accommodating
442 // the pre-read pending characters
444 InitializeRawFiFo (TerminalDevice
);
445 InitializeUnicodeFiFo (TerminalDevice
);
446 InitializeEfiKeyFiFo (TerminalDevice
);
449 // Set the timeout value of serial buffer for
450 // keystroke response performance issue
452 Mode
= TerminalDevice
->SerialIo
->Mode
;
455 if (Mode
->BaudRate
!= 0) {
456 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
459 Status
= TerminalDevice
->SerialIo
->SetAttributes (
460 TerminalDevice
->SerialIo
,
462 Mode
->ReceiveFifoDepth
,
463 (UINT32
) SerialInTimeOut
,
464 (EFI_PARITY_TYPE
) (Mode
->Parity
),
465 (UINT8
) Mode
->DataBits
,
466 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
468 if (EFI_ERROR (Status
)) {
470 // if set attributes operation fails, invalidate
471 // the value of SerialInTimeOut,thus make it
472 // inconsistent with the default timeout value
473 // of serial buffer. This will invoke the recalculation
474 // in the readkeystroke routine.
476 TerminalDevice
->SerialInTimeOut
= 0;
478 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
481 // Build the device path for the child device
483 Status
= SetTerminalDevicePath (
484 TerminalDevice
->TerminalType
,
486 &TerminalDevice
->DevicePath
488 if (EFI_ERROR (Status
)) {
492 DevicePath
= TerminalDevice
->DevicePath
;
494 Status
= TerminalDevice
->SimpleInput
.Reset (
495 &TerminalDevice
->SimpleInput
,
498 if (EFI_ERROR (Status
)) {
500 // Need to report Error Code first
505 // Simple Text Output Protocol
507 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
508 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
509 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
510 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
511 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
512 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
513 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
514 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
515 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
516 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
518 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 3;
520 // For terminal devices, cursor is always visible
522 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
523 Status
= TerminalDevice
->SimpleTextOutput
.SetAttribute (
524 &TerminalDevice
->SimpleTextOutput
,
525 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
527 if (EFI_ERROR (Status
)) {
531 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
532 &TerminalDevice
->SimpleTextOutput
,
535 if (EFI_ERROR (Status
)) {
539 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
540 &TerminalDevice
->SimpleTextOutput
,
543 if (EFI_ERROR (Status
)) {
547 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
548 &TerminalDevice
->SimpleTextOutput
,
551 if (EFI_ERROR (Status
)) {
555 Status
= gBS
->CreateEvent (
560 &TerminalDevice
->TwoSecondTimeOut
564 // Build the component name for the child device
566 TerminalDevice
->ControllerNameTable
= NULL
;
567 switch (TerminalDevice
->TerminalType
) {
571 gTerminalComponentName
.SupportedLanguages
,
572 &TerminalDevice
->ControllerNameTable
,
573 (CHAR16
*)L
"PC-ANSI Serial Console",
578 gTerminalComponentName2
.SupportedLanguages
,
579 &TerminalDevice
->ControllerNameTable
,
580 (CHAR16
*)L
"PC-ANSI Serial Console",
589 gTerminalComponentName
.SupportedLanguages
,
590 &TerminalDevice
->ControllerNameTable
,
591 (CHAR16
*)L
"VT-100 Serial Console",
596 gTerminalComponentName2
.SupportedLanguages
,
597 &TerminalDevice
->ControllerNameTable
,
598 (CHAR16
*)L
"VT-100 Serial Console",
607 gTerminalComponentName
.SupportedLanguages
,
608 &TerminalDevice
->ControllerNameTable
,
609 (CHAR16
*)L
"VT-100+ Serial Console",
614 gTerminalComponentName2
.SupportedLanguages
,
615 &TerminalDevice
->ControllerNameTable
,
616 (CHAR16
*)L
"VT-100+ Serial Console",
625 gTerminalComponentName
.SupportedLanguages
,
626 &TerminalDevice
->ControllerNameTable
,
627 (CHAR16
*)L
"VT-UTF8 Serial Console",
632 gTerminalComponentName2
.SupportedLanguages
,
633 &TerminalDevice
->ControllerNameTable
,
634 (CHAR16
*)L
"VT-UTF8 Serial Console",
641 // Install protocol interfaces for the serial device.
643 Status
= gBS
->InstallMultipleProtocolInterfaces (
644 &TerminalDevice
->Handle
,
645 &gEfiDevicePathProtocolGuid
,
646 TerminalDevice
->DevicePath
,
647 &gEfiSimpleTextInProtocolGuid
,
648 &TerminalDevice
->SimpleInput
,
649 &gEfiSimpleTextInputExProtocolGuid
,
650 &TerminalDevice
->SimpleInputEx
,
651 &gEfiSimpleTextOutProtocolGuid
,
652 &TerminalDevice
->SimpleTextOutput
,
655 if (EFI_ERROR (Status
)) {
659 // if the serial device is a hot plug device, attaches the HotPlugGuid
660 // onto the terminal device handle.
662 Status
= gBS
->OpenProtocol (
664 &gEfiHotPlugDeviceGuid
,
666 This
->DriverBindingHandle
,
668 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
670 if (!EFI_ERROR (Status
)) {
671 Status
= gBS
->InstallMultipleProtocolInterfaces (
672 &TerminalDevice
->Handle
,
673 &gEfiHotPlugDeviceGuid
,
679 // Register the Parent-Child relationship via
680 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
682 Status
= gBS
->OpenProtocol (
684 &gEfiSerialIoProtocolGuid
,
685 (VOID
**) &TerminalDevice
->SerialIo
,
686 This
->DriverBindingHandle
,
687 TerminalDevice
->Handle
,
688 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
690 if (EFI_ERROR (Status
)) {
694 if (DefaultNode
!= NULL
) {
695 FreePool (DefaultNode
);
702 // Report error code before exiting
704 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
705 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
706 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
712 // Use the Stop() function to free all resources allocated in Start()
714 if (TerminalDevice
!= NULL
) {
716 if (TerminalDevice
->Handle
!= NULL
) {
717 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
720 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
721 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
724 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
725 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
728 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
729 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
732 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
734 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
735 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
738 if (TerminalDevice
->DevicePath
!= NULL
) {
739 FreePool (TerminalDevice
->DevicePath
);
742 FreePool (TerminalDevice
);
746 if (DefaultNode
!= NULL
) {
747 FreePool (DefaultNode
);
750 This
->Stop (This
, Controller
, 0, NULL
);
756 Stop this driver on Controller by closing Simple Text In, Simple Text
757 In Ex, Simple Text Out protocol, and removing parent device path from
758 Console Device Environment Variables.
760 @param This Protocol instance pointer.
761 @param Controller Handle of device to stop driver on
762 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
763 children is zero stop the entire bus driver.
764 @param ChildHandleBuffer List of Child Handles to Stop.
766 @retval EFI_SUCCESS This driver is removed Controller.
767 @retval other This driver could not be removed from this device.
772 TerminalDriverBindingStop (
773 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
774 IN EFI_HANDLE Controller
,
775 IN UINTN NumberOfChildren
,
776 IN EFI_HANDLE
*ChildHandleBuffer
781 BOOLEAN AllChildrenStopped
;
782 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
783 TERMINAL_DEV
*TerminalDevice
;
784 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
785 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
786 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
788 Status
= gBS
->HandleProtocol (
790 &gEfiDevicePathProtocolGuid
,
791 (VOID
**) &DevicePath
793 if (EFI_ERROR (Status
)) {
798 // Complete all outstanding transactions to Controller.
799 // Don't allow any new transaction to Controller to be started.
801 if (NumberOfChildren
== 0) {
803 // Close the bus driver
805 Status
= gBS
->OpenProtocol (
808 (VOID
**) &ParentDevicePath
,
809 This
->DriverBindingHandle
,
811 EFI_OPEN_PROTOCOL_GET_PROTOCOL
813 if (!EFI_ERROR (Status
)) {
815 // Remove Parent Device Path from
816 // the Console Device Environment Variables
818 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
819 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
820 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
823 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
825 Status
= gBS
->UninstallMultipleProtocolInterfaces (
833 // Free the ParentDevicePath that was duplicated in Start()
835 if (!EFI_ERROR (Status
)) {
836 FreePool (ParentDevicePath
);
842 &gEfiSerialIoProtocolGuid
,
843 This
->DriverBindingHandle
,
849 &gEfiDevicePathProtocolGuid
,
850 This
->DriverBindingHandle
,
857 AllChildrenStopped
= TRUE
;
859 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
861 Status
= gBS
->OpenProtocol (
862 ChildHandleBuffer
[Index
],
863 &gEfiSimpleTextOutProtocolGuid
,
864 (VOID
**) &SimpleTextOutput
,
865 This
->DriverBindingHandle
,
866 ChildHandleBuffer
[Index
],
867 EFI_OPEN_PROTOCOL_GET_PROTOCOL
869 if (!EFI_ERROR (Status
)) {
871 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
875 &gEfiSerialIoProtocolGuid
,
876 This
->DriverBindingHandle
,
877 ChildHandleBuffer
[Index
]
880 Status
= gBS
->UninstallMultipleProtocolInterfaces (
881 ChildHandleBuffer
[Index
],
882 &gEfiSimpleTextInProtocolGuid
,
883 &TerminalDevice
->SimpleInput
,
884 &gEfiSimpleTextInputExProtocolGuid
,
885 &TerminalDevice
->SimpleInputEx
,
886 &gEfiSimpleTextOutProtocolGuid
,
887 &TerminalDevice
->SimpleTextOutput
,
888 &gEfiDevicePathProtocolGuid
,
889 TerminalDevice
->DevicePath
,
892 if (EFI_ERROR (Status
)) {
895 &gEfiSerialIoProtocolGuid
,
897 This
->DriverBindingHandle
,
898 ChildHandleBuffer
[Index
],
899 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
903 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
904 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
907 Status
= gBS
->OpenProtocol (
908 ChildHandleBuffer
[Index
],
909 &gEfiHotPlugDeviceGuid
,
911 This
->DriverBindingHandle
,
913 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
915 if (!EFI_ERROR (Status
)) {
916 Status
= gBS
->UninstallMultipleProtocolInterfaces (
917 ChildHandleBuffer
[Index
],
918 &gEfiHotPlugDeviceGuid
,
923 Status
= EFI_SUCCESS
;
926 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
927 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
928 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
929 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
930 FreePool (TerminalDevice
->DevicePath
);
931 FreePool (TerminalDevice
);
935 if (EFI_ERROR (Status
)) {
936 AllChildrenStopped
= FALSE
;
940 if (!AllChildrenStopped
) {
941 return EFI_DEVICE_ERROR
;
949 Free notify functions list.
951 @param ListHead The list head
953 @retval EFI_SUCCESS Free the notify list successfully.
954 @retval EFI_INVALID_PARAMETER ListHead is NULL.
958 TerminalFreeNotifyList (
959 IN OUT LIST_ENTRY
*ListHead
962 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
964 if (ListHead
== NULL
) {
965 return EFI_INVALID_PARAMETER
;
967 while (!IsListEmpty (ListHead
)) {
969 ListHead
->ForwardLink
,
970 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
972 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
974 RemoveEntryList (ListHead
->ForwardLink
);
975 FreePool (NotifyNode
);
983 Update terminal device path in Console Device Environment Variables.
985 @param VariableName The Console Device Environment Variable.
986 @param ParentDevicePath The terminal devcie path to be updated.
992 TerminalUpdateConsoleDevVariable (
993 IN CHAR16
*VariableName
,
994 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1000 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1001 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1002 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1007 // Get global variable and its size according to the name given.
1009 Variable
= TerminalGetVariableAndSize (
1011 &gEfiGlobalVariableGuid
,
1015 // Append terminal device path onto the variable.
1017 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1018 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1019 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
1020 if (Variable
!= NULL
) {
1021 FreePool (Variable
);
1024 if (TempDevicePath
!= NULL
) {
1025 FreePool (TempDevicePath
);
1028 Variable
= NewVariable
;
1031 VariableSize
= GetDevicePathSize (Variable
);
1033 Status
= gRT
->SetVariable (
1035 &gEfiGlobalVariableGuid
,
1036 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1040 ASSERT_EFI_ERROR (Status
);
1041 FreePool (Variable
);
1048 Remove terminal device path from Console Device Environment Variables.
1050 @param VariableName Console Device Environment Variables.
1051 @param ParentDevicePath The terminal devcie path to be updated.
1057 TerminalRemoveConsoleDevVariable (
1058 IN CHAR16
*VariableName
,
1059 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1068 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1069 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1070 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1071 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1072 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1073 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1079 // Get global variable and its size according to the name given.
1081 Variable
= TerminalGetVariableAndSize (
1083 &gEfiGlobalVariableGuid
,
1086 if (Variable
== NULL
) {
1091 OriginalVariable
= Variable
;
1095 // Get first device path instance from Variable
1097 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1098 if (Instance
== NULL
) {
1099 FreePool (OriginalVariable
);
1103 // Loop through all the device path instances of Variable
1107 // Loop through all the terminal types that this driver supports
1110 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1112 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1115 // Compare the genterated device path to the current device path instance
1117 if (TempDevicePath
!= NULL
) {
1118 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1123 FreePool (TempDevicePath
);
1127 // If a match was not found, then keep the current device path instance
1130 SavedNewVariable
= NewVariable
;
1131 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1132 if (SavedNewVariable
!= NULL
) {
1133 FreePool (SavedNewVariable
);
1137 // Get next device path instance from Variable
1139 FreePool (Instance
);
1140 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1141 } while (Instance
!= NULL
);
1143 FreePool (OriginalVariable
);
1146 VariableSize
= GetDevicePathSize (NewVariable
);
1148 Status
= gRT
->SetVariable (
1150 &gEfiGlobalVariableGuid
,
1151 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1155 ASSERT_EFI_ERROR (Status
);
1158 if (NewVariable
!= NULL
) {
1159 FreePool (NewVariable
);
1167 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1168 buffer, and the size of the buffer. On failure return NULL.
1170 @param Name String part of EFI variable name
1171 @param VendorGuid GUID part of EFI variable name
1172 @param VariableSize Returns the size of the EFI variable that was read
1174 @return Dynamically allocated memory that contains a copy of the EFI variable.
1175 Caller is repsoncible freeing the buffer. If variable was not read,
1180 TerminalGetVariableAndSize (
1182 IN EFI_GUID
*VendorGuid
,
1183 OUT UINTN
*VariableSize
1193 // Pass in a small size buffer to find the actual variable size.
1196 Buffer
= AllocatePool (BufferSize
);
1197 if (Buffer
== NULL
) {
1202 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1204 if (Status
== EFI_SUCCESS
) {
1205 *VariableSize
= BufferSize
;
1208 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1210 // Allocate the buffer to return
1213 Buffer
= AllocatePool (BufferSize
);
1214 if (Buffer
== NULL
) {
1219 // Read variable into the allocated buffer.
1221 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1222 if (EFI_ERROR (Status
)) {
1229 // Variable not found or other errors met.
1236 *VariableSize
= BufferSize
;
1241 Build termial device path according to terminal type.
1243 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1244 @param ParentDevicePath Parent devcie path.
1245 @param TerminalDevicePath Returned terminal device path, if building successfully.
1247 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1248 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1249 @retval EFI_SUCCESS Build terminal device path successfully.
1253 SetTerminalDevicePath (
1254 IN UINT8 TerminalType
,
1255 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1256 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1259 VENDOR_DEVICE_PATH Node
;
1261 *TerminalDevicePath
= NULL
;
1262 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1263 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1266 // Generate terminal device path node according to terminal type.
1268 switch (TerminalType
) {
1271 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1275 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1279 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1283 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1287 return EFI_UNSUPPORTED
;
1291 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1293 SetDevicePathNodeLength (
1295 sizeof (VENDOR_DEVICE_PATH
)
1299 // Append the terminal node onto parent device path
1300 // to generate a complete terminal device path.
1302 *TerminalDevicePath
= AppendDevicePathNode (
1304 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1306 if (*TerminalDevicePath
== NULL
) {
1307 return EFI_OUT_OF_RESOURCES
;
1314 Initialize the Raw Data FIFO.
1316 @param TerminalDevice The terminal device.
1323 IN TERMINAL_DEV
*TerminalDevice
1327 // Make the raw fifo empty.
1329 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1333 Initialize the Unicode FIFO.
1335 @param TerminalDevice The terminal device.
1341 InitializeUnicodeFiFo (
1342 IN TERMINAL_DEV
*TerminalDevice
1346 // Make the unicode fifo empty
1348 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1352 Initialize the EFI Key FIFO.
1354 @param TerminalDevice The terminal device.
1360 InitializeEfiKeyFiFo (
1361 IN TERMINAL_DEV
*TerminalDevice
1365 // Make the efi key fifo empty
1367 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;
1372 The user Entry Point for module Terminal. The user code starts with this function.
1374 @param ImageHandle The firmware allocated handle for the EFI image.
1375 @param SystemTable A pointer to the EFI System Table.
1377 @retval EFI_SUCCESS The entry point is executed successfully.
1378 @retval other Some error occurs when executing this entry point.
1384 IN EFI_HANDLE ImageHandle
,
1385 IN EFI_SYSTEM_TABLE
*SystemTable
1391 // Install driver model protocol(s).
1393 Status
= EfiLibInstallDriverBindingComponentName2 (
1396 &gTerminalDriverBinding
,
1398 &gTerminalComponentName
,
1399 &gTerminalComponentName2
1401 ASSERT_EFI_ERROR (Status
);