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
87 NULL
, // ControllerNameTable
88 NULL
, // TwoSecondTimeOut
92 { // SimpleTextInputEx
94 TerminalConInReadKeyStrokeEx
,
96 TerminalConInSetState
,
97 TerminalConInRegisterKeyNotify
,
98 TerminalConInUnregisterKeyNotify
,
107 Test to see if this driver supports Controller.
109 @param This Protocol instance pointer.
110 @param Controller Handle of device to test
111 @param RemainingDevicePath Optional parameter use to pick a specific child
114 @retval EFI_SUCCESS This driver supports this device.
115 @retval EFI_ALREADY_STARTED This driver is already running on this device.
116 @retval other This driver does not support this device.
121 TerminalDriverBindingSupported (
122 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
123 IN EFI_HANDLE Controller
,
124 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
128 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
129 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
130 VENDOR_DEVICE_PATH
*Node
;
133 // If remaining device path is not NULL, then make sure it is a
134 // device path that describes a terminal communications protocol.
136 if (RemainingDevicePath
!= NULL
) {
138 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
140 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
141 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
142 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
144 return EFI_UNSUPPORTED
;
148 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
150 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
151 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
152 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
153 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
155 return EFI_UNSUPPORTED
;
159 // Open the IO Abstraction(s) needed to perform the supported test
161 Status
= gBS
->OpenProtocol (
163 &gEfiDevicePathProtocolGuid
,
164 (VOID
**) &ParentDevicePath
,
165 This
->DriverBindingHandle
,
167 EFI_OPEN_PROTOCOL_BY_DRIVER
169 if (Status
== EFI_ALREADY_STARTED
) {
173 if (EFI_ERROR (Status
)) {
179 &gEfiDevicePathProtocolGuid
,
180 This
->DriverBindingHandle
,
185 // The Controller must support the Serial I/O Protocol.
186 // This driver is a bus driver with at most 1 child device, so it is
187 // ok for it to be already started.
189 Status
= gBS
->OpenProtocol (
191 &gEfiSerialIoProtocolGuid
,
193 This
->DriverBindingHandle
,
195 EFI_OPEN_PROTOCOL_BY_DRIVER
197 if (Status
== EFI_ALREADY_STARTED
) {
201 if (EFI_ERROR (Status
)) {
205 // Close the I/O Abstraction(s) used to perform the supported test
209 &gEfiSerialIoProtocolGuid
,
210 This
->DriverBindingHandle
,
218 Start this driver on Controller by opening a Serial IO protocol,
219 reading Device Path, and creating a child handle with a Simple Text In,
220 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
221 And store Console Device Environment Variables.
223 @param This Protocol instance pointer.
224 @param Controller Handle of device to bind driver to
225 @param RemainingDevicePath Optional parameter use to pick a specific child
228 @retval EFI_SUCCESS This driver is added to Controller.
229 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
230 @retval other This driver does not support this device.
235 TerminalDriverBindingStart (
236 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
237 IN EFI_HANDLE Controller
,
238 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
242 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
243 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
244 VENDOR_DEVICE_PATH
*Node
;
245 VENDOR_DEVICE_PATH
*DefaultNode
;
246 EFI_SERIAL_IO_MODE
*Mode
;
247 UINTN SerialInTimeOut
;
248 TERMINAL_DEV
*TerminalDevice
;
250 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
253 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
254 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOutput
;
256 TerminalDevice
= NULL
;
259 // Get the Device Path Protocol to build the device path of the child device
261 Status
= gBS
->OpenProtocol (
263 &gEfiDevicePathProtocolGuid
,
264 (VOID
**) &ParentDevicePath
,
265 This
->DriverBindingHandle
,
267 EFI_OPEN_PROTOCOL_BY_DRIVER
269 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
274 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
276 Status
= gBS
->OpenProtocol (
278 &gEfiSerialIoProtocolGuid
,
280 This
->DriverBindingHandle
,
282 EFI_OPEN_PROTOCOL_BY_DRIVER
284 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
288 if (Status
!= EFI_ALREADY_STARTED
) {
290 // If Serial I/O is not already open by this driver, then tag the handle
291 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
292 // StdErrDev variables with the list of possible terminal types on this
295 Status
= gBS
->OpenProtocol (
299 This
->DriverBindingHandle
,
301 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
303 if (EFI_ERROR (Status
)) {
304 Status
= gBS
->InstallMultipleProtocolInterfaces (
307 DuplicateDevicePath (ParentDevicePath
),
310 if (EFI_ERROR (Status
)) {
314 // if the serial device is a hot plug device, do not update the
315 // ConInDev, ConOutDev, and StdErrDev variables.
317 Status
= gBS
->OpenProtocol (
319 &gEfiHotPlugDeviceGuid
,
321 This
->DriverBindingHandle
,
323 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
325 if (EFI_ERROR (Status
)) {
326 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
327 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
328 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
333 // Make sure a child handle does not already exist. This driver can only
334 // produce one child per serial port.
336 Status
= gBS
->OpenProtocolInformation (
338 &gEfiSerialIoProtocolGuid
,
342 if (!EFI_ERROR (Status
)) {
343 Status
= EFI_SUCCESS
;
344 for (Index
= 0; Index
< EntryCount
; Index
++) {
345 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
346 Status
= EFI_ALREADY_STARTED
;
350 FreePool (OpenInfoBuffer
);
351 if (EFI_ERROR (Status
)) {
356 // If RemainingDevicePath is NULL, then create default device path node
358 if (RemainingDevicePath
== NULL
) {
359 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
360 if (DefaultNode
== NULL
) {
361 Status
= EFI_OUT_OF_RESOURCES
;
365 TerminalType
= FixedPcdGet8 (PcdDefaultTerminalType
);
367 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)
369 ASSERT (TerminalType
<= VTUTF8TYPE
);
371 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
372 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
375 // Use the RemainingDevicePath to determine the terminal type
377 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
378 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
379 TerminalType
= PCANSITYPE
;
380 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
381 TerminalType
= VT100TYPE
;
382 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
383 TerminalType
= VT100PLUSTYPE
;
384 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
385 TerminalType
= VTUTF8TYPE
;
392 // Initialize the Terminal Dev
394 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
395 if (TerminalDevice
== NULL
) {
396 Status
= EFI_OUT_OF_RESOURCES
;
400 TerminalDevice
->TerminalType
= TerminalType
;
401 TerminalDevice
->SerialIo
= SerialIo
;
403 InitializeListHead (&TerminalDevice
->NotifyList
);
404 Status
= gBS
->CreateEvent (
407 TerminalConInWaitForKeyEx
,
408 &TerminalDevice
->SimpleInputEx
,
409 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
411 if (EFI_ERROR (Status
)) {
416 Status
= gBS
->CreateEvent (
419 TerminalConInWaitForKey
,
420 &TerminalDevice
->SimpleInput
,
421 &TerminalDevice
->SimpleInput
.WaitForKey
423 if (EFI_ERROR (Status
)) {
427 // initialize the FIFO buffer used for accommodating
428 // the pre-read pending characters
430 InitializeRawFiFo (TerminalDevice
);
431 InitializeUnicodeFiFo (TerminalDevice
);
432 InitializeEfiKeyFiFo (TerminalDevice
);
435 // Set the timeout value of serial buffer for
436 // keystroke response performance issue
438 Mode
= TerminalDevice
->SerialIo
->Mode
;
441 if (Mode
->BaudRate
!= 0) {
442 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
445 Status
= TerminalDevice
->SerialIo
->SetAttributes (
446 TerminalDevice
->SerialIo
,
448 Mode
->ReceiveFifoDepth
,
449 (UINT32
) SerialInTimeOut
,
450 (EFI_PARITY_TYPE
) (Mode
->Parity
),
451 (UINT8
) Mode
->DataBits
,
452 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
454 if (EFI_ERROR (Status
)) {
456 // if set attributes operation fails, invalidate
457 // the value of SerialInTimeOut,thus make it
458 // inconsistent with the default timeout value
459 // of serial buffer. This will invoke the recalculation
460 // in the readkeystroke routine.
462 TerminalDevice
->SerialInTimeOut
= 0;
464 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
467 // Build the device path for the child device
469 Status
= SetTerminalDevicePath (
470 TerminalDevice
->TerminalType
,
472 &TerminalDevice
->DevicePath
474 if (EFI_ERROR (Status
)) {
478 DevicePath
= TerminalDevice
->DevicePath
;
480 Status
= TerminalDevice
->SimpleInput
.Reset (
481 &TerminalDevice
->SimpleInput
,
484 if (EFI_ERROR (Status
)) {
486 // Need to report Error Code first
491 // Simple Text Output Protocol
493 SimpleTextOutput
= TerminalDevice
->SimpleTextOutput
;
495 SimpleTextOutput
.Reset
= TerminalConOutReset
;
496 SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
497 SimpleTextOutput
.TestString
= TerminalConOutTestString
;
498 SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
499 SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
500 SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
501 SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
502 SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
503 SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
504 SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
506 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 3;
508 // For terminal devices, cursor is always visible
510 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
511 Status
= SimpleTextOutput
.SetAttribute (
512 &TerminalDevice
->SimpleTextOutput
,
513 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
515 if (EFI_ERROR (Status
)) {
519 Status
= SimpleTextOutput
.Reset (
520 &TerminalDevice
->SimpleTextOutput
,
523 if (EFI_ERROR (Status
)) {
527 Status
= SimpleTextOutput
.SetMode (
528 &TerminalDevice
->SimpleTextOutput
,
531 if (EFI_ERROR (Status
)) {
535 Status
= SimpleTextOutput
.EnableCursor (
536 &TerminalDevice
->SimpleTextOutput
,
539 if (EFI_ERROR (Status
)) {
543 Status
= gBS
->CreateEvent (
548 &TerminalDevice
->TwoSecondTimeOut
552 // Build the component name for the child device
554 TerminalDevice
->ControllerNameTable
= NULL
;
555 switch (TerminalDevice
->TerminalType
) {
559 gTerminalComponentName
.SupportedLanguages
,
560 &TerminalDevice
->ControllerNameTable
,
561 (CHAR16
*)L
"PC-ANSI Serial Console",
566 gTerminalComponentName2
.SupportedLanguages
,
567 &TerminalDevice
->ControllerNameTable
,
568 (CHAR16
*)L
"PC-ANSI Serial Console",
577 gTerminalComponentName
.SupportedLanguages
,
578 &TerminalDevice
->ControllerNameTable
,
579 (CHAR16
*)L
"VT-100 Serial Console",
584 gTerminalComponentName2
.SupportedLanguages
,
585 &TerminalDevice
->ControllerNameTable
,
586 (CHAR16
*)L
"VT-100 Serial Console",
595 gTerminalComponentName
.SupportedLanguages
,
596 &TerminalDevice
->ControllerNameTable
,
597 (CHAR16
*)L
"VT-100+ Serial Console",
602 gTerminalComponentName2
.SupportedLanguages
,
603 &TerminalDevice
->ControllerNameTable
,
604 (CHAR16
*)L
"VT-100+ Serial Console",
613 gTerminalComponentName
.SupportedLanguages
,
614 &TerminalDevice
->ControllerNameTable
,
615 (CHAR16
*)L
"VT-UTF8 Serial Console",
620 gTerminalComponentName2
.SupportedLanguages
,
621 &TerminalDevice
->ControllerNameTable
,
622 (CHAR16
*)L
"VT-UTF8 Serial Console",
629 // Install protocol interfaces for the serial device.
631 Status
= gBS
->InstallMultipleProtocolInterfaces (
632 &TerminalDevice
->Handle
,
633 &gEfiDevicePathProtocolGuid
,
634 TerminalDevice
->DevicePath
,
635 &gEfiSimpleTextInProtocolGuid
,
636 &TerminalDevice
->SimpleInput
,
637 &gEfiSimpleTextInputExProtocolGuid
,
638 &TerminalDevice
->SimpleInputEx
,
639 &gEfiSimpleTextOutProtocolGuid
,
640 &TerminalDevice
->SimpleTextOutput
,
643 if (EFI_ERROR (Status
)) {
647 // if the serial device is a hot plug device, attaches the HotPlugGuid
648 // onto the terminal device handle.
650 Status
= gBS
->OpenProtocol (
652 &gEfiHotPlugDeviceGuid
,
654 This
->DriverBindingHandle
,
656 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
658 if (!EFI_ERROR (Status
)) {
659 Status
= gBS
->InstallMultipleProtocolInterfaces (
660 &TerminalDevice
->Handle
,
661 &gEfiHotPlugDeviceGuid
,
667 // Register the Parent-Child relationship via
668 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
670 Status
= gBS
->OpenProtocol (
672 &gEfiSerialIoProtocolGuid
,
673 (VOID
**) &TerminalDevice
->SerialIo
,
674 This
->DriverBindingHandle
,
675 TerminalDevice
->Handle
,
676 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
678 if (EFI_ERROR (Status
)) {
682 if (DefaultNode
!= NULL
) {
683 FreePool (DefaultNode
);
690 // Report error code before exiting
692 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
693 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
694 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
700 // Use the Stop() function to free all resources allocated in Start()
702 if (TerminalDevice
!= NULL
) {
704 if (TerminalDevice
->Handle
!= NULL
) {
705 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
708 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
709 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
712 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
713 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
716 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
717 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
720 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
722 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
723 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
726 if (TerminalDevice
->DevicePath
!= NULL
) {
727 FreePool (TerminalDevice
->DevicePath
);
730 FreePool (TerminalDevice
);
734 if (DefaultNode
!= NULL
) {
735 FreePool (DefaultNode
);
738 This
->Stop (This
, Controller
, 0, NULL
);
744 Stop this driver on Controller by closing Simple Text In, Simple Text
745 In Ex, Simple Text Out protocol, and removing parent device path from
746 Console Device Environment Variables.
748 @param This Protocol instance pointer.
749 @param Controller Handle of device to stop driver on
750 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
751 children is zero stop the entire bus driver.
752 @param ChildHandleBuffer List of Child Handles to Stop.
754 @retval EFI_SUCCESS This driver is removed Controller.
755 @retval other This driver could not be removed from this device.
760 TerminalDriverBindingStop (
761 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
762 IN EFI_HANDLE Controller
,
763 IN UINTN NumberOfChildren
,
764 IN EFI_HANDLE
*ChildHandleBuffer
769 BOOLEAN AllChildrenStopped
;
770 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
771 TERMINAL_DEV
*TerminalDevice
;
772 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
773 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
774 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
776 Status
= gBS
->HandleProtocol (
778 &gEfiDevicePathProtocolGuid
,
779 (VOID
**) &DevicePath
781 if (EFI_ERROR (Status
)) {
786 // Complete all outstanding transactions to Controller.
787 // Don't allow any new transaction to Controller to be started.
789 if (NumberOfChildren
== 0) {
791 // Close the bus driver
793 Status
= gBS
->OpenProtocol (
796 (VOID
**) &ParentDevicePath
,
797 This
->DriverBindingHandle
,
799 EFI_OPEN_PROTOCOL_GET_PROTOCOL
801 if (!EFI_ERROR (Status
)) {
803 // Remove Parent Device Path from
804 // the Console Device Environment Variables
806 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
807 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
808 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
811 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
813 Status
= gBS
->UninstallMultipleProtocolInterfaces (
821 // Free the ParentDevicePath that was duplicated in Start()
823 if (!EFI_ERROR (Status
)) {
824 FreePool (ParentDevicePath
);
830 &gEfiSerialIoProtocolGuid
,
831 This
->DriverBindingHandle
,
837 &gEfiDevicePathProtocolGuid
,
838 This
->DriverBindingHandle
,
845 AllChildrenStopped
= TRUE
;
847 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
849 Status
= gBS
->OpenProtocol (
850 ChildHandleBuffer
[Index
],
851 &gEfiSimpleTextOutProtocolGuid
,
852 (VOID
**) &SimpleTextOutput
,
853 This
->DriverBindingHandle
,
854 ChildHandleBuffer
[Index
],
855 EFI_OPEN_PROTOCOL_GET_PROTOCOL
857 if (!EFI_ERROR (Status
)) {
859 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
863 &gEfiSerialIoProtocolGuid
,
864 This
->DriverBindingHandle
,
865 ChildHandleBuffer
[Index
]
868 Status
= gBS
->UninstallMultipleProtocolInterfaces (
869 ChildHandleBuffer
[Index
],
870 &gEfiSimpleTextInProtocolGuid
,
871 &TerminalDevice
->SimpleInput
,
872 &gEfiSimpleTextInputExProtocolGuid
,
873 &TerminalDevice
->SimpleInputEx
,
874 &gEfiSimpleTextOutProtocolGuid
,
875 &TerminalDevice
->SimpleTextOutput
,
876 &gEfiDevicePathProtocolGuid
,
877 TerminalDevice
->DevicePath
,
880 if (EFI_ERROR (Status
)) {
883 &gEfiSerialIoProtocolGuid
,
885 This
->DriverBindingHandle
,
886 ChildHandleBuffer
[Index
],
887 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
891 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
892 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
895 Status
= gBS
->OpenProtocol (
896 ChildHandleBuffer
[Index
],
897 &gEfiHotPlugDeviceGuid
,
899 This
->DriverBindingHandle
,
901 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
903 if (!EFI_ERROR (Status
)) {
904 Status
= gBS
->UninstallMultipleProtocolInterfaces (
905 ChildHandleBuffer
[Index
],
906 &gEfiHotPlugDeviceGuid
,
911 Status
= EFI_SUCCESS
;
914 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
915 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
916 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
917 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
918 FreePool (TerminalDevice
->DevicePath
);
919 FreePool (TerminalDevice
);
923 if (EFI_ERROR (Status
)) {
924 AllChildrenStopped
= FALSE
;
928 if (!AllChildrenStopped
) {
929 return EFI_DEVICE_ERROR
;
937 Free notify functions list.
939 @param ListHead The list head
941 @retval EFI_SUCCESS Free the notify list successfully.
942 @retval EFI_INVALID_PARAMETER ListHead is NULL.
946 TerminalFreeNotifyList (
947 IN OUT LIST_ENTRY
*ListHead
950 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
952 if (ListHead
== NULL
) {
953 return EFI_INVALID_PARAMETER
;
955 while (!IsListEmpty (ListHead
)) {
957 ListHead
->ForwardLink
,
958 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
960 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
962 RemoveEntryList (ListHead
->ForwardLink
);
963 FreePool (NotifyNode
);
971 Update terminal device path in Console Device Environment Variables.
973 @param VariableName The Console Device Environment Variable.
974 @param ParentDevicePath The terminal device path to be updated.
980 TerminalUpdateConsoleDevVariable (
981 IN CHAR16
*VariableName
,
982 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
988 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
989 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
990 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
995 // Get global variable and its size according to the name given.
997 Variable
= TerminalGetVariableAndSize (
999 &gEfiGlobalVariableGuid
,
1003 // Append terminal device path onto the variable.
1005 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1006 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1007 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
1008 if (Variable
!= NULL
) {
1009 FreePool (Variable
);
1012 if (TempDevicePath
!= NULL
) {
1013 FreePool (TempDevicePath
);
1016 Variable
= NewVariable
;
1019 VariableSize
= GetDevicePathSize (Variable
);
1021 Status
= gRT
->SetVariable (
1023 &gEfiGlobalVariableGuid
,
1024 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1028 ASSERT_EFI_ERROR (Status
);
1029 FreePool (Variable
);
1036 Remove terminal device path from Console Device Environment Variables.
1038 @param VariableName Console Device Environment Variables.
1039 @param ParentDevicePath The terminal device path to be updated.
1045 TerminalRemoveConsoleDevVariable (
1046 IN CHAR16
*VariableName
,
1047 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1056 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1057 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1058 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1059 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1060 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1061 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1067 // Get global variable and its size according to the name given.
1069 Variable
= TerminalGetVariableAndSize (
1071 &gEfiGlobalVariableGuid
,
1074 if (Variable
== NULL
) {
1079 OriginalVariable
= Variable
;
1083 // Get first device path instance from Variable
1085 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1086 if (Instance
== NULL
) {
1087 FreePool (OriginalVariable
);
1091 // Loop through all the device path instances of Variable
1095 // Loop through all the terminal types that this driver supports
1098 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1100 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1103 // Compare the generated device path to the current device path instance
1105 if (TempDevicePath
!= NULL
) {
1106 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1111 FreePool (TempDevicePath
);
1115 // If a match was not found, then keep the current device path instance
1118 SavedNewVariable
= NewVariable
;
1119 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1120 if (SavedNewVariable
!= NULL
) {
1121 FreePool (SavedNewVariable
);
1125 // Get next device path instance from Variable
1127 FreePool (Instance
);
1128 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1129 } while (Instance
!= NULL
);
1131 FreePool (OriginalVariable
);
1134 VariableSize
= GetDevicePathSize (NewVariable
);
1136 Status
= gRT
->SetVariable (
1138 &gEfiGlobalVariableGuid
,
1139 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1143 ASSERT_EFI_ERROR (Status
);
1146 if (NewVariable
!= NULL
) {
1147 FreePool (NewVariable
);
1155 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1156 buffer, and the size of the buffer. On failure return NULL.
1158 @param Name String part of EFI variable name
1159 @param VendorGuid GUID part of EFI variable name
1160 @param VariableSize Returns the size of the EFI variable that was read
1162 @return Dynamically allocated memory that contains a copy of the EFI variable.
1163 Caller is responsible freeing the buffer. If variable was not read,
1168 TerminalGetVariableAndSize (
1170 IN EFI_GUID
*VendorGuid
,
1171 OUT UINTN
*VariableSize
1181 // Pass in a small size buffer to find the actual variable size.
1184 Buffer
= AllocatePool (BufferSize
);
1185 if (Buffer
== NULL
) {
1190 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1192 if (Status
== EFI_SUCCESS
) {
1193 *VariableSize
= BufferSize
;
1196 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1198 // Allocate the buffer to return
1201 Buffer
= AllocatePool (BufferSize
);
1202 if (Buffer
== NULL
) {
1207 // Read variable into the allocated buffer.
1209 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1210 if (EFI_ERROR (Status
)) {
1217 // Variable not found or other errors met.
1224 *VariableSize
= BufferSize
;
1229 Build terminal device path according to terminal type.
1231 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1232 @param ParentDevicePath Parent device path.
1233 @param TerminalDevicePath Returned terminal device path, if building successfully.
1235 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1236 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1237 @retval EFI_SUCCESS Build terminal device path successfully.
1241 SetTerminalDevicePath (
1242 IN UINT8 TerminalType
,
1243 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1244 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1247 VENDOR_DEVICE_PATH Node
;
1249 *TerminalDevicePath
= NULL
;
1250 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1251 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1254 // Generate terminal device path node according to terminal type.
1256 switch (TerminalType
) {
1259 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1263 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1267 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1271 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1275 return EFI_UNSUPPORTED
;
1279 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1281 SetDevicePathNodeLength (
1283 sizeof (VENDOR_DEVICE_PATH
)
1287 // Append the terminal node onto parent device path
1288 // to generate a complete terminal device path.
1290 *TerminalDevicePath
= AppendDevicePathNode (
1292 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1294 if (*TerminalDevicePath
== NULL
) {
1295 return EFI_OUT_OF_RESOURCES
;
1302 Initialize the Raw Data FIFO.
1304 @param TerminalDevice The terminal device.
1311 IN TERMINAL_DEV
*TerminalDevice
1315 // Make the raw FIFO empty.
1317 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1321 Initialize the Unicode FIFO.
1323 @param TerminalDevice The terminal device.
1329 InitializeUnicodeFiFo (
1330 IN TERMINAL_DEV
*TerminalDevice
1334 // Make the unicode FIFO empty
1336 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1340 Initialize the EFI Key FIFO.
1342 @param TerminalDevice The terminal device.
1348 InitializeEfiKeyFiFo (
1349 IN TERMINAL_DEV
*TerminalDevice
1353 // Make the efi key FIFO empty
1355 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;
1360 The user Entry Point for module Terminal. The user code starts with this function.
1362 @param ImageHandle The firmware allocated handle for the EFI image.
1363 @param SystemTable A pointer to the EFI System Table.
1365 @retval EFI_SUCCESS The entry point is executed successfully.
1366 @retval other Some error occurs when executing this entry point.
1372 IN EFI_HANDLE ImageHandle
,
1373 IN EFI_SYSTEM_TABLE
*SystemTable
1379 // Install driver model protocol(s).
1381 Status
= EfiLibInstallDriverBindingComponentName2 (
1384 &gTerminalDriverBinding
,
1386 &gTerminalComponentName
,
1387 &gTerminalComponentName2
1389 ASSERT_EFI_ERROR (Status
);