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 the serial device is a hot plug device, do not update the
305 // ConInDev, ConOutDev, and StdErrDev variables.
307 Status
= gBS
->OpenProtocol (
309 &gEfiHotPlugDeviceGuid
,
311 This
->DriverBindingHandle
,
313 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
315 if (EFI_ERROR (Status
)) {
316 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
317 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
318 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
323 // Make sure a child handle does not already exist. This driver can only
324 // produce one child per serial port.
326 Status
= gBS
->OpenProtocolInformation (
328 &gEfiSerialIoProtocolGuid
,
332 if (!EFI_ERROR (Status
)) {
333 Status
= EFI_SUCCESS
;
334 for (Index
= 0; Index
< EntryCount
; Index
++) {
335 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
336 Status
= EFI_ALREADY_STARTED
;
340 FreePool (OpenInfoBuffer
);
341 if (EFI_ERROR (Status
)) {
346 // If RemainingDevicePath is NULL, then create default device path node
348 if (RemainingDevicePath
== NULL
) {
349 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
350 if (DefaultNode
== NULL
) {
351 Status
= EFI_OUT_OF_RESOURCES
;
355 TerminalType
= FixedPcdGet8 (PcdDefaultTerminalType
);
357 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)
359 ASSERT (TerminalType
<= VTUTF8TYPE
);
361 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
362 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
365 // Use the RemainingDevicePath to determine the terminal type
367 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
368 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
369 TerminalType
= PCANSITYPE
;
370 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
371 TerminalType
= VT100TYPE
;
372 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
373 TerminalType
= VT100PLUSTYPE
;
374 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
375 TerminalType
= VTUTF8TYPE
;
382 // Initialize the Terminal Dev
384 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
385 if (TerminalDevice
== NULL
) {
386 Status
= EFI_OUT_OF_RESOURCES
;
390 TerminalDevice
->TerminalType
= TerminalType
;
391 TerminalDevice
->SerialIo
= SerialIo
;
393 InitializeListHead (&TerminalDevice
->NotifyList
);
394 Status
= gBS
->CreateEvent (
397 TerminalConInWaitForKeyEx
,
398 &TerminalDevice
->SimpleInputEx
,
399 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
401 if (EFI_ERROR (Status
)) {
406 Status
= gBS
->CreateEvent (
409 TerminalConInWaitForKey
,
410 &TerminalDevice
->SimpleInput
,
411 &TerminalDevice
->SimpleInput
.WaitForKey
413 if (EFI_ERROR (Status
)) {
417 // Allocates and initializes the FIFO buffer to be zero, used for accommodating
418 // the pre-read pending characters.
420 TerminalDevice
->RawFiFo
= AllocateZeroPool (sizeof (RAW_DATA_FIFO
));
421 if (TerminalDevice
->RawFiFo
== NULL
) {
424 TerminalDevice
->UnicodeFiFo
= AllocateZeroPool (sizeof (UNICODE_FIFO
));
425 if (TerminalDevice
->UnicodeFiFo
== NULL
) {
428 TerminalDevice
->EfiKeyFiFo
= AllocateZeroPool (sizeof (EFI_KEY_FIFO
));
429 if (TerminalDevice
->EfiKeyFiFo
== NULL
) {
434 // Set the timeout value of serial buffer for
435 // keystroke response performance issue
437 Mode
= TerminalDevice
->SerialIo
->Mode
;
440 if (Mode
->BaudRate
!= 0) {
441 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
444 Status
= TerminalDevice
->SerialIo
->SetAttributes (
445 TerminalDevice
->SerialIo
,
447 Mode
->ReceiveFifoDepth
,
448 (UINT32
) SerialInTimeOut
,
449 (EFI_PARITY_TYPE
) (Mode
->Parity
),
450 (UINT8
) Mode
->DataBits
,
451 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
453 if (EFI_ERROR (Status
)) {
455 // if set attributes operation fails, invalidate
456 // the value of SerialInTimeOut,thus make it
457 // inconsistent with the default timeout value
458 // of serial buffer. This will invoke the recalculation
459 // in the readkeystroke routine.
461 TerminalDevice
->SerialInTimeOut
= 0;
463 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
466 // Build the device path for the child device
468 Status
= SetTerminalDevicePath (
469 TerminalDevice
->TerminalType
,
471 &TerminalDevice
->DevicePath
473 if (EFI_ERROR (Status
)) {
477 DevicePath
= TerminalDevice
->DevicePath
;
479 Status
= TerminalDevice
->SimpleInput
.Reset (
480 &TerminalDevice
->SimpleInput
,
483 if (EFI_ERROR (Status
)) {
485 // Need to report Error Code first
490 // Set Simple Text Output Protocol from template.
492 SimpleTextOutput
= CopyMem (
493 &TerminalDevice
->SimpleTextOutput
,
494 &mTerminalDevTemplate
.SimpleTextOutput
,
495 sizeof (mTerminalDevTemplate
.SimpleTextOutput
)
497 SimpleTextOutput
->Mode
= &TerminalDevice
->SimpleTextOutputMode
;
499 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 3;
501 // For terminal devices, cursor is always visible
503 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
504 Status
= TerminalConOutSetAttribute (
506 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
508 if (EFI_ERROR (Status
)) {
512 Status
= TerminalConOutReset (SimpleTextOutput
, FALSE
);
513 if (EFI_ERROR (Status
)) {
517 Status
= TerminalConOutSetMode (SimpleTextOutput
, 0);
518 if (EFI_ERROR (Status
)) {
522 Status
= TerminalConOutEnableCursor (SimpleTextOutput
, TRUE
);
523 if (EFI_ERROR (Status
)) {
527 Status
= gBS
->CreateEvent (
532 &TerminalDevice
->TwoSecondTimeOut
536 // Build the component name for the child device
538 TerminalDevice
->ControllerNameTable
= NULL
;
539 switch (TerminalDevice
->TerminalType
) {
543 gTerminalComponentName
.SupportedLanguages
,
544 &TerminalDevice
->ControllerNameTable
,
545 (CHAR16
*)L
"PC-ANSI Serial Console",
550 gTerminalComponentName2
.SupportedLanguages
,
551 &TerminalDevice
->ControllerNameTable
,
552 (CHAR16
*)L
"PC-ANSI Serial Console",
561 gTerminalComponentName
.SupportedLanguages
,
562 &TerminalDevice
->ControllerNameTable
,
563 (CHAR16
*)L
"VT-100 Serial Console",
568 gTerminalComponentName2
.SupportedLanguages
,
569 &TerminalDevice
->ControllerNameTable
,
570 (CHAR16
*)L
"VT-100 Serial Console",
579 gTerminalComponentName
.SupportedLanguages
,
580 &TerminalDevice
->ControllerNameTable
,
581 (CHAR16
*)L
"VT-100+ Serial Console",
586 gTerminalComponentName2
.SupportedLanguages
,
587 &TerminalDevice
->ControllerNameTable
,
588 (CHAR16
*)L
"VT-100+ Serial Console",
597 gTerminalComponentName
.SupportedLanguages
,
598 &TerminalDevice
->ControllerNameTable
,
599 (CHAR16
*)L
"VT-UTF8 Serial Console",
604 gTerminalComponentName2
.SupportedLanguages
,
605 &TerminalDevice
->ControllerNameTable
,
606 (CHAR16
*)L
"VT-UTF8 Serial Console",
613 // Install protocol interfaces for the serial device.
615 Status
= gBS
->InstallMultipleProtocolInterfaces (
616 &TerminalDevice
->Handle
,
617 &gEfiDevicePathProtocolGuid
,
618 TerminalDevice
->DevicePath
,
619 &gEfiSimpleTextInProtocolGuid
,
620 &TerminalDevice
->SimpleInput
,
621 &gEfiSimpleTextInputExProtocolGuid
,
622 &TerminalDevice
->SimpleInputEx
,
623 &gEfiSimpleTextOutProtocolGuid
,
624 &TerminalDevice
->SimpleTextOutput
,
627 if (EFI_ERROR (Status
)) {
631 // if the serial device is a hot plug device, attaches the HotPlugGuid
632 // onto the terminal device handle.
634 Status
= gBS
->OpenProtocol (
636 &gEfiHotPlugDeviceGuid
,
638 This
->DriverBindingHandle
,
640 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
642 if (!EFI_ERROR (Status
)) {
643 Status
= gBS
->InstallMultipleProtocolInterfaces (
644 &TerminalDevice
->Handle
,
645 &gEfiHotPlugDeviceGuid
,
651 // Register the Parent-Child relationship via
652 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
654 Status
= gBS
->OpenProtocol (
656 &gEfiSerialIoProtocolGuid
,
657 (VOID
**) &TerminalDevice
->SerialIo
,
658 This
->DriverBindingHandle
,
659 TerminalDevice
->Handle
,
660 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
662 if (EFI_ERROR (Status
)) {
666 if (DefaultNode
!= NULL
) {
667 FreePool (DefaultNode
);
674 // Report error code before exiting
676 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
677 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
678 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
684 // Use the Stop() function to free all resources allocated in Start()
686 if (TerminalDevice
!= NULL
) {
688 if (TerminalDevice
->Handle
!= NULL
) {
689 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
692 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
693 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
696 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
697 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
700 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
701 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
704 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
706 if (TerminalDevice
->RawFiFo
!= NULL
) {
707 FreePool (TerminalDevice
->RawFiFo
);
709 if (TerminalDevice
->UnicodeFiFo
!= NULL
) {
710 FreePool (TerminalDevice
->UnicodeFiFo
);
712 if (TerminalDevice
->EfiKeyFiFo
!= NULL
) {
713 FreePool (TerminalDevice
->EfiKeyFiFo
);
716 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
717 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
720 if (TerminalDevice
->DevicePath
!= NULL
) {
721 FreePool (TerminalDevice
->DevicePath
);
724 FreePool (TerminalDevice
);
728 if (DefaultNode
!= NULL
) {
729 FreePool (DefaultNode
);
732 This
->Stop (This
, Controller
, 0, NULL
);
738 Stop this driver on Controller by closing Simple Text In, Simple Text
739 In Ex, Simple Text Out protocol, and removing parent device path from
740 Console Device Environment Variables.
742 @param This Protocol instance pointer.
743 @param Controller Handle of device to stop driver on
744 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
745 children is zero stop the entire bus driver.
746 @param ChildHandleBuffer List of Child Handles to Stop.
748 @retval EFI_SUCCESS This driver is removed Controller.
749 @retval other This driver could not be removed from this device.
754 TerminalDriverBindingStop (
755 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
756 IN EFI_HANDLE Controller
,
757 IN UINTN NumberOfChildren
,
758 IN EFI_HANDLE
*ChildHandleBuffer
763 BOOLEAN AllChildrenStopped
;
764 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
765 TERMINAL_DEV
*TerminalDevice
;
766 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
767 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
768 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
770 Status
= gBS
->HandleProtocol (
772 &gEfiDevicePathProtocolGuid
,
773 (VOID
**) &DevicePath
775 if (EFI_ERROR (Status
)) {
780 // Complete all outstanding transactions to Controller.
781 // Don't allow any new transaction to Controller to be started.
783 if (NumberOfChildren
== 0) {
785 // Close the bus driver
787 Status
= gBS
->OpenProtocol (
790 (VOID
**) &ParentDevicePath
,
791 This
->DriverBindingHandle
,
793 EFI_OPEN_PROTOCOL_GET_PROTOCOL
795 if (!EFI_ERROR (Status
)) {
797 // Remove Parent Device Path from
798 // the Console Device Environment Variables
800 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
801 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
802 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
805 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
807 Status
= gBS
->UninstallMultipleProtocolInterfaces (
815 // Free the ParentDevicePath that was duplicated in Start()
817 if (!EFI_ERROR (Status
)) {
818 FreePool (ParentDevicePath
);
824 &gEfiSerialIoProtocolGuid
,
825 This
->DriverBindingHandle
,
831 &gEfiDevicePathProtocolGuid
,
832 This
->DriverBindingHandle
,
839 AllChildrenStopped
= TRUE
;
841 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
843 Status
= gBS
->OpenProtocol (
844 ChildHandleBuffer
[Index
],
845 &gEfiSimpleTextOutProtocolGuid
,
846 (VOID
**) &SimpleTextOutput
,
847 This
->DriverBindingHandle
,
848 ChildHandleBuffer
[Index
],
849 EFI_OPEN_PROTOCOL_GET_PROTOCOL
851 if (!EFI_ERROR (Status
)) {
853 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
857 &gEfiSerialIoProtocolGuid
,
858 This
->DriverBindingHandle
,
859 ChildHandleBuffer
[Index
]
862 Status
= gBS
->UninstallMultipleProtocolInterfaces (
863 ChildHandleBuffer
[Index
],
864 &gEfiSimpleTextInProtocolGuid
,
865 &TerminalDevice
->SimpleInput
,
866 &gEfiSimpleTextInputExProtocolGuid
,
867 &TerminalDevice
->SimpleInputEx
,
868 &gEfiSimpleTextOutProtocolGuid
,
869 &TerminalDevice
->SimpleTextOutput
,
870 &gEfiDevicePathProtocolGuid
,
871 TerminalDevice
->DevicePath
,
874 if (EFI_ERROR (Status
)) {
877 &gEfiSerialIoProtocolGuid
,
879 This
->DriverBindingHandle
,
880 ChildHandleBuffer
[Index
],
881 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
885 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
886 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
889 Status
= gBS
->OpenProtocol (
890 ChildHandleBuffer
[Index
],
891 &gEfiHotPlugDeviceGuid
,
893 This
->DriverBindingHandle
,
895 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
897 if (!EFI_ERROR (Status
)) {
898 Status
= gBS
->UninstallMultipleProtocolInterfaces (
899 ChildHandleBuffer
[Index
],
900 &gEfiHotPlugDeviceGuid
,
905 Status
= EFI_SUCCESS
;
908 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
909 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
910 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
911 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
912 FreePool (TerminalDevice
->DevicePath
);
913 FreePool (TerminalDevice
);
917 if (EFI_ERROR (Status
)) {
918 AllChildrenStopped
= FALSE
;
922 if (!AllChildrenStopped
) {
923 return EFI_DEVICE_ERROR
;
931 Free notify functions list.
933 @param ListHead The list head
935 @retval EFI_SUCCESS Free the notify list successfully.
936 @retval EFI_INVALID_PARAMETER ListHead is NULL.
940 TerminalFreeNotifyList (
941 IN OUT LIST_ENTRY
*ListHead
944 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
946 if (ListHead
== NULL
) {
947 return EFI_INVALID_PARAMETER
;
949 while (!IsListEmpty (ListHead
)) {
951 ListHead
->ForwardLink
,
952 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
954 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
956 RemoveEntryList (ListHead
->ForwardLink
);
957 FreePool (NotifyNode
);
965 Update terminal device path in Console Device Environment Variables.
967 @param VariableName The Console Device Environment Variable.
968 @param ParentDevicePath The terminal device path to be updated.
972 TerminalUpdateConsoleDevVariable (
973 IN CHAR16
*VariableName
,
974 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
980 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
981 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
982 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
987 // Get global variable and its size according to the name given.
989 Variable
= TerminalGetVariableAndSize (
991 &gEfiGlobalVariableGuid
,
995 // Append terminal device path onto the variable.
997 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
998 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
999 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
1000 if (Variable
!= NULL
) {
1001 FreePool (Variable
);
1004 if (TempDevicePath
!= NULL
) {
1005 FreePool (TempDevicePath
);
1008 Variable
= NewVariable
;
1011 VariableSize
= GetDevicePathSize (Variable
);
1013 Status
= gRT
->SetVariable (
1015 &gEfiGlobalVariableGuid
,
1016 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1020 ASSERT_EFI_ERROR (Status
);
1021 FreePool (Variable
);
1028 Remove terminal device path from Console Device Environment Variables.
1030 @param VariableName Console Device Environment Variables.
1031 @param ParentDevicePath The terminal device path to be updated.
1035 TerminalRemoveConsoleDevVariable (
1036 IN CHAR16
*VariableName
,
1037 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1046 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1047 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1048 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1049 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1050 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1051 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1057 // Get global variable and its size according to the name given.
1059 Variable
= TerminalGetVariableAndSize (
1061 &gEfiGlobalVariableGuid
,
1064 if (Variable
== NULL
) {
1069 OriginalVariable
= Variable
;
1073 // Get first device path instance from Variable
1075 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1076 if (Instance
== NULL
) {
1077 FreePool (OriginalVariable
);
1081 // Loop through all the device path instances of Variable
1085 // Loop through all the terminal types that this driver supports
1088 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1090 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1093 // Compare the generated device path to the current device path instance
1095 if (TempDevicePath
!= NULL
) {
1096 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1101 FreePool (TempDevicePath
);
1105 // If a match was not found, then keep the current device path instance
1108 SavedNewVariable
= NewVariable
;
1109 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1110 if (SavedNewVariable
!= NULL
) {
1111 FreePool (SavedNewVariable
);
1115 // Get next device path instance from Variable
1117 FreePool (Instance
);
1118 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1119 } while (Instance
!= NULL
);
1121 FreePool (OriginalVariable
);
1124 VariableSize
= GetDevicePathSize (NewVariable
);
1126 Status
= gRT
->SetVariable (
1128 &gEfiGlobalVariableGuid
,
1129 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1133 ASSERT_EFI_ERROR (Status
);
1136 if (NewVariable
!= NULL
) {
1137 FreePool (NewVariable
);
1145 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1146 buffer, and the size of the buffer. On failure return NULL.
1148 @param Name String part of EFI variable name
1149 @param VendorGuid GUID part of EFI variable name
1150 @param VariableSize Returns the size of the EFI variable that was read
1152 @return Dynamically allocated memory that contains a copy of the EFI variable.
1153 Caller is responsible freeing the buffer. If variable was not read,
1158 TerminalGetVariableAndSize (
1160 IN EFI_GUID
*VendorGuid
,
1161 OUT UINTN
*VariableSize
1171 // Pass in a small size buffer to find the actual variable size.
1174 Buffer
= AllocatePool (BufferSize
);
1175 if (Buffer
== NULL
) {
1180 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1182 if (Status
== EFI_SUCCESS
) {
1183 *VariableSize
= BufferSize
;
1186 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1188 // Allocate the buffer to return
1191 Buffer
= AllocatePool (BufferSize
);
1192 if (Buffer
== NULL
) {
1197 // Read variable into the allocated buffer.
1199 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1200 if (EFI_ERROR (Status
)) {
1207 // Variable not found or other errors met.
1214 *VariableSize
= BufferSize
;
1219 Build terminal device path according to terminal type.
1221 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1222 @param ParentDevicePath Parent device path.
1223 @param TerminalDevicePath Returned terminal device path, if building successfully.
1225 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1226 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1227 @retval EFI_SUCCESS Build terminal device path successfully.
1231 SetTerminalDevicePath (
1232 IN UINT8 TerminalType
,
1233 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1234 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1237 VENDOR_DEVICE_PATH Node
;
1239 *TerminalDevicePath
= NULL
;
1240 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1241 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1244 // Generate terminal device path node according to terminal type.
1246 switch (TerminalType
) {
1249 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1253 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1257 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1261 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1265 return EFI_UNSUPPORTED
;
1269 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1271 SetDevicePathNodeLength (
1273 sizeof (VENDOR_DEVICE_PATH
)
1277 // Append the terminal node onto parent device path
1278 // to generate a complete terminal device path.
1280 *TerminalDevicePath
= AppendDevicePathNode (
1282 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1284 if (*TerminalDevicePath
== NULL
) {
1285 return EFI_OUT_OF_RESOURCES
;
1292 The user Entry Point for module Terminal. The user code starts with this function.
1294 @param ImageHandle The firmware allocated handle for the EFI image.
1295 @param SystemTable A pointer to the EFI System Table.
1297 @retval EFI_SUCCESS The entry point is executed successfully.
1298 @retval other Some error occurs when executing this entry point.
1304 IN EFI_HANDLE ImageHandle
,
1305 IN EFI_SYSTEM_TABLE
*SystemTable
1311 // Install driver model protocol(s).
1313 Status
= EfiLibInstallDriverBindingComponentName2 (
1316 &gTerminalDriverBinding
,
1318 &gTerminalComponentName
,
1319 &gTerminalComponentName2
1321 ASSERT_EFI_ERROR (Status
);