3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 TerminalFreeNotifyList (
28 IN OUT LIST_ENTRY
*ListHead
34 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
35 TerminalDriverBindingSupported
,
36 TerminalDriverBindingStart
,
37 TerminalDriverBindingStop
,
44 EFI_GUID
*gTerminalType
[] = {
52 TERMINAL_DEV gTerminalDevTemplate
= {
53 TERMINAL_DEV_SIGNATURE
,
60 TerminalConInReadKeyStroke
,
65 TerminalConOutOutputString
,
66 TerminalConOutTestString
,
67 TerminalConOutQueryMode
,
68 TerminalConOutSetMode
,
69 TerminalConOutSetAttribute
,
70 TerminalConOutClearScreen
,
71 TerminalConOutSetCursorPosition
,
72 TerminalConOutEnableCursor
,
75 { // SimpleTextOutputMode
78 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
), // Attribute
99 NULL
, // ControllerNameTable
104 { // SimpleTextInputEx
105 TerminalConInResetEx
,
106 TerminalConInReadKeyStrokeEx
,
108 TerminalConInSetState
,
109 TerminalConInRegisterKeyNotify
,
110 TerminalConInUnregisterKeyNotify
,
122 TerminalDriverBindingSupported (
123 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
124 IN EFI_HANDLE Controller
,
125 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
129 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
130 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
131 VENDOR_DEVICE_PATH
*Node
;
134 // If remaining device path is not NULL, then make sure it is a
135 // device path that describes a terminal communications protocol.
137 if (RemainingDevicePath
!= NULL
) {
139 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
141 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
142 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
143 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
145 return EFI_UNSUPPORTED
;
149 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
151 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
152 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
153 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
154 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
156 return EFI_UNSUPPORTED
;
160 // Open the IO Abstraction(s) needed to perform the supported test
162 Status
= gBS
->OpenProtocol (
164 &gEfiDevicePathProtocolGuid
,
165 (VOID
**) &ParentDevicePath
,
166 This
->DriverBindingHandle
,
168 EFI_OPEN_PROTOCOL_BY_DRIVER
170 if (Status
== EFI_ALREADY_STARTED
) {
174 if (EFI_ERROR (Status
)) {
180 &gEfiDevicePathProtocolGuid
,
181 This
->DriverBindingHandle
,
186 // The Controller must support the Serial I/O Protocol.
187 // This driver is a bus driver with at most 1 child device, so it is
188 // ok for it to be already started.
190 Status
= gBS
->OpenProtocol (
192 &gEfiSerialIoProtocolGuid
,
194 This
->DriverBindingHandle
,
196 EFI_OPEN_PROTOCOL_BY_DRIVER
198 if (Status
== EFI_ALREADY_STARTED
) {
202 if (EFI_ERROR (Status
)) {
206 // Close the I/O Abstraction(s) used to perform the supported test
210 &gEfiSerialIoProtocolGuid
,
211 This
->DriverBindingHandle
,
220 TerminalDriverBindingStart (
221 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
222 IN EFI_HANDLE Controller
,
223 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
229 Start the controller.
233 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
234 Controller - The handle of the controller to start.
235 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
244 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
245 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
246 VENDOR_DEVICE_PATH
*Node
;
247 VENDOR_DEVICE_PATH
*DefaultNode
;
248 EFI_SERIAL_IO_MODE
*Mode
;
249 UINTN SerialInTimeOut
;
250 TERMINAL_DEV
*TerminalDevice
;
252 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
255 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
257 TerminalDevice
= NULL
;
260 // Get the Device Path Protocol to build the device path of the child device
262 Status
= gBS
->OpenProtocol (
264 &gEfiDevicePathProtocolGuid
,
265 (VOID
**) &ParentDevicePath
,
266 This
->DriverBindingHandle
,
268 EFI_OPEN_PROTOCOL_BY_DRIVER
270 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
275 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
277 Status
= gBS
->OpenProtocol (
279 &gEfiSerialIoProtocolGuid
,
281 This
->DriverBindingHandle
,
283 EFI_OPEN_PROTOCOL_BY_DRIVER
285 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
289 if (Status
!= EFI_ALREADY_STARTED
) {
291 // If Serial I/O is not already open by this driver, then tag the handle
292 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
293 // StdErrDev variables with the list of possible terminal types on this
296 Status
= gBS
->OpenProtocol (
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
304 if (EFI_ERROR (Status
)) {
305 Status
= gBS
->InstallMultipleProtocolInterfaces (
308 DuplicateDevicePath (ParentDevicePath
),
311 if (EFI_ERROR (Status
)) {
315 // if the serial device is a hot plug device, do not update the
316 // ConInDev, ConOutDev, and StdErrDev variables.
318 Status
= gBS
->OpenProtocol (
320 &gEfiHotPlugDeviceGuid
,
322 This
->DriverBindingHandle
,
324 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
326 if (EFI_ERROR (Status
)) {
327 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
328 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
329 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
334 // Make sure a child handle does not already exist. This driver can only
335 // produce one child per serial port.
337 Status
= gBS
->OpenProtocolInformation (
339 &gEfiSerialIoProtocolGuid
,
343 if (!EFI_ERROR (Status
)) {
344 Status
= EFI_SUCCESS
;
345 for (Index
= 0; Index
< EntryCount
; Index
++) {
346 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
347 Status
= EFI_ALREADY_STARTED
;
351 FreePool (OpenInfoBuffer
);
352 if (EFI_ERROR (Status
)) {
357 // If RemainingDevicePath is NULL, then create default device path node
359 if (RemainingDevicePath
== NULL
) {
360 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
361 if (DefaultNode
== NULL
) {
362 Status
= EFI_OUT_OF_RESOURCES
;
366 TerminalType
= FixedPcdGet8 (PcdDefaultTerminalType
);
367 // must be between PcAnsiType (0) and VTUTF8Type (3)
368 ASSERT (TerminalType
<= VTUTF8Type
);
370 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
371 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)DefaultNode
;
374 // Use the RemainingDevicePath to determine the terminal type
376 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
377 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
378 TerminalType
= PcAnsiType
;
379 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
380 TerminalType
= VT100Type
;
381 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
382 TerminalType
= VT100PlusType
;
383 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
384 TerminalType
= VTUTF8Type
;
391 // Initialize the Terminal Dev
393 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &gTerminalDevTemplate
);
394 if (TerminalDevice
== NULL
) {
395 Status
= EFI_OUT_OF_RESOURCES
;
399 TerminalDevice
->TerminalType
= TerminalType
;
400 TerminalDevice
->SerialIo
= SerialIo
;
402 InitializeListHead (&TerminalDevice
->NotifyList
);
403 Status
= gBS
->CreateEvent (
406 TerminalConInWaitForKeyEx
,
407 &TerminalDevice
->SimpleInputEx
,
408 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
410 if (EFI_ERROR (Status
)) {
415 Status
= gBS
->CreateEvent (
418 TerminalConInWaitForKey
,
419 &TerminalDevice
->SimpleInput
,
420 &TerminalDevice
->SimpleInput
.WaitForKey
422 if (EFI_ERROR (Status
)) {
426 // initialize the FIFO buffer used for accommodating
427 // the pre-read pending characters
429 InitializeRawFiFo (TerminalDevice
);
430 InitializeUnicodeFiFo (TerminalDevice
);
431 InitializeEfiKeyFiFo (TerminalDevice
);
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 // Simple Text Output Protocol
492 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
493 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
494 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
495 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
496 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
497 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
498 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
499 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
500 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
501 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
503 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 2;
505 // For terminal devices, cursor is always visible
507 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
508 Status
= TerminalDevice
->SimpleTextOutput
.SetAttribute (
509 &TerminalDevice
->SimpleTextOutput
,
510 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
512 if (EFI_ERROR (Status
)) {
516 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
517 &TerminalDevice
->SimpleTextOutput
,
520 if (EFI_ERROR (Status
)) {
524 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
525 &TerminalDevice
->SimpleTextOutput
,
528 if (EFI_ERROR (Status
)) {
532 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
533 &TerminalDevice
->SimpleTextOutput
,
536 if (EFI_ERROR (Status
)) {
540 Status
= gBS
->CreateEvent (
545 &TerminalDevice
->TwoSecondTimeOut
549 // Build the component name for the child device
551 TerminalDevice
->ControllerNameTable
= NULL
;
552 switch (TerminalDevice
->TerminalType
) {
556 gTerminalComponentName
.SupportedLanguages
,
557 &TerminalDevice
->ControllerNameTable
,
558 (CHAR16
*)L
"PC-ANSI Serial Console",
563 gTerminalComponentName2
.SupportedLanguages
,
564 &TerminalDevice
->ControllerNameTable
,
565 (CHAR16
*)L
"PC-ANSI Serial Console",
574 gTerminalComponentName
.SupportedLanguages
,
575 &TerminalDevice
->ControllerNameTable
,
576 (CHAR16
*)L
"VT-100 Serial Console",
581 gTerminalComponentName2
.SupportedLanguages
,
582 &TerminalDevice
->ControllerNameTable
,
583 (CHAR16
*)L
"VT-100 Serial Console",
592 gTerminalComponentName
.SupportedLanguages
,
593 &TerminalDevice
->ControllerNameTable
,
594 (CHAR16
*)L
"VT-100+ Serial Console",
599 gTerminalComponentName2
.SupportedLanguages
,
600 &TerminalDevice
->ControllerNameTable
,
601 (CHAR16
*)L
"VT-100+ Serial Console",
610 gTerminalComponentName
.SupportedLanguages
,
611 &TerminalDevice
->ControllerNameTable
,
612 (CHAR16
*)L
"VT-UTF8 Serial Console",
617 gTerminalComponentName2
.SupportedLanguages
,
618 &TerminalDevice
->ControllerNameTable
,
619 (CHAR16
*)L
"VT-UTF8 Serial Console",
626 // Install protocol interfaces for the serial device.
628 Status
= gBS
->InstallMultipleProtocolInterfaces (
629 &TerminalDevice
->Handle
,
630 &gEfiDevicePathProtocolGuid
,
631 TerminalDevice
->DevicePath
,
632 &gEfiSimpleTextInProtocolGuid
,
633 &TerminalDevice
->SimpleInput
,
634 &gEfiSimpleTextInputExProtocolGuid
,
635 &TerminalDevice
->SimpleInputEx
,
636 &gEfiSimpleTextOutProtocolGuid
,
637 &TerminalDevice
->SimpleTextOutput
,
640 if (EFI_ERROR (Status
)) {
644 // if the serial device is a hot plug device, attaches the HotPlugGuid
645 // onto the terminal device handle.
647 Status
= gBS
->OpenProtocol (
649 &gEfiHotPlugDeviceGuid
,
651 This
->DriverBindingHandle
,
653 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
655 if (!EFI_ERROR (Status
)) {
656 Status
= gBS
->InstallMultipleProtocolInterfaces (
657 &TerminalDevice
->Handle
,
658 &gEfiHotPlugDeviceGuid
,
664 // Register the Parent-Child relationship via
665 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
667 Status
= gBS
->OpenProtocol (
669 &gEfiSerialIoProtocolGuid
,
670 (VOID
**) &TerminalDevice
->SerialIo
,
671 This
->DriverBindingHandle
,
672 TerminalDevice
->Handle
,
673 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
675 if (EFI_ERROR (Status
)) {
679 if (DefaultNode
!= NULL
) {
680 FreePool (DefaultNode
);
687 // Report error code before exiting
689 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
690 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
691 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
697 // Use the Stop() function to free all resources allocated in Start()
699 if (TerminalDevice
!= NULL
) {
701 if (TerminalDevice
->Handle
!= NULL
) {
702 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
705 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
706 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
709 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
710 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
713 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
714 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
717 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
719 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
720 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
723 if (TerminalDevice
->DevicePath
!= NULL
) {
724 FreePool (TerminalDevice
->DevicePath
);
727 FreePool (TerminalDevice
);
731 if (DefaultNode
!= NULL
) {
732 FreePool (DefaultNode
);
735 This
->Stop (This
, Controller
, 0, NULL
);
742 TerminalDriverBindingStop (
743 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
744 IN EFI_HANDLE Controller
,
745 IN UINTN NumberOfChildren
,
746 IN EFI_HANDLE
*ChildHandleBuffer
752 Stop a device controller.
756 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
757 Controller - A handle to the device being stopped.
758 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
759 ChildHandleBuffer - An array of child handles to be freed.
763 EFI_SUCCESS - Operation successful.
764 EFI_DEVICE_ERROR - Devices error.
770 BOOLEAN AllChildrenStopped
;
771 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
772 TERMINAL_DEV
*TerminalDevice
;
773 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
774 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
775 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
777 Status
= gBS
->HandleProtocol (
779 &gEfiDevicePathProtocolGuid
,
780 (VOID
**) &DevicePath
782 if (EFI_ERROR (Status
)) {
787 // Complete all outstanding transactions to Controller.
788 // Don't allow any new transaction to Controller to be started.
790 if (NumberOfChildren
== 0) {
792 // Close the bus driver
794 Status
= gBS
->OpenProtocol (
797 (VOID
**) &ParentDevicePath
,
798 This
->DriverBindingHandle
,
800 EFI_OPEN_PROTOCOL_GET_PROTOCOL
802 if (!EFI_ERROR (Status
)) {
804 // Remove Parent Device Path from
805 // the Console Device Environment Variables
807 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
808 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
809 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
812 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
814 Status
= gBS
->UninstallMultipleProtocolInterfaces (
822 // Free the ParentDevicePath that was duplicated in Start()
824 if (!EFI_ERROR (Status
)) {
825 FreePool (ParentDevicePath
);
831 &gEfiSerialIoProtocolGuid
,
832 This
->DriverBindingHandle
,
838 &gEfiDevicePathProtocolGuid
,
839 This
->DriverBindingHandle
,
846 AllChildrenStopped
= TRUE
;
848 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
850 Status
= gBS
->OpenProtocol (
851 ChildHandleBuffer
[Index
],
852 &gEfiSimpleTextOutProtocolGuid
,
853 (VOID
**) &SimpleTextOutput
,
854 This
->DriverBindingHandle
,
855 ChildHandleBuffer
[Index
],
856 EFI_OPEN_PROTOCOL_GET_PROTOCOL
858 if (!EFI_ERROR (Status
)) {
860 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
864 &gEfiSerialIoProtocolGuid
,
865 This
->DriverBindingHandle
,
866 ChildHandleBuffer
[Index
]
869 Status
= gBS
->UninstallMultipleProtocolInterfaces (
870 ChildHandleBuffer
[Index
],
871 &gEfiSimpleTextInProtocolGuid
,
872 &TerminalDevice
->SimpleInput
,
873 &gEfiSimpleTextInputExProtocolGuid
,
874 &TerminalDevice
->SimpleInputEx
,
875 &gEfiSimpleTextOutProtocolGuid
,
876 &TerminalDevice
->SimpleTextOutput
,
877 &gEfiDevicePathProtocolGuid
,
878 TerminalDevice
->DevicePath
,
881 if (EFI_ERROR (Status
)) {
884 &gEfiSerialIoProtocolGuid
,
886 This
->DriverBindingHandle
,
887 ChildHandleBuffer
[Index
],
888 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
892 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
893 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
896 Status
= gBS
->OpenProtocol (
897 ChildHandleBuffer
[Index
],
898 &gEfiHotPlugDeviceGuid
,
900 This
->DriverBindingHandle
,
902 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
904 if (!EFI_ERROR (Status
)) {
905 Status
= gBS
->UninstallMultipleProtocolInterfaces (
906 ChildHandleBuffer
[Index
],
907 &gEfiHotPlugDeviceGuid
,
912 Status
= EFI_SUCCESS
;
915 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
916 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
917 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
918 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
919 FreePool (TerminalDevice
->DevicePath
);
920 FreePool (TerminalDevice
);
924 if (EFI_ERROR (Status
)) {
925 AllChildrenStopped
= FALSE
;
929 if (!AllChildrenStopped
) {
930 return EFI_DEVICE_ERROR
;
938 TerminalFreeNotifyList (
939 IN OUT LIST_ENTRY
*ListHead
947 ListHead - The list head
951 EFI_SUCCESS - Free the notify list successfully
952 EFI_INVALID_PARAMETER - ListHead is invalid.
956 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
958 if (ListHead
== NULL
) {
959 return EFI_INVALID_PARAMETER
;
961 while (!IsListEmpty (ListHead
)) {
963 ListHead
->ForwardLink
,
964 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
966 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
968 RemoveEntryList (ListHead
->ForwardLink
);
969 gBS
->FreePool (NotifyNode
);
978 TerminalUpdateConsoleDevVariable (
979 IN CHAR16
*VariableName
,
980 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
986 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
987 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
988 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
993 // Get global variable and its size according to the name given.
995 Variable
= TerminalGetVariableAndSize (
997 &gEfiGlobalVariableGuid
,
1001 // Append terminal device path onto the variable.
1003 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
1004 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1005 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
1006 if (Variable
!= NULL
) {
1007 FreePool (Variable
);
1010 if (TempDevicePath
!= NULL
) {
1011 FreePool (TempDevicePath
);
1014 Variable
= NewVariable
;
1017 VariableSize
= GetDevicePathSize (Variable
);
1019 Status
= gRT
->SetVariable (
1021 &gEfiGlobalVariableGuid
,
1022 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1026 ASSERT_EFI_ERROR (Status
);
1027 FreePool (Variable
);
1033 TerminalRemoveConsoleDevVariable (
1034 IN CHAR16
*VariableName
,
1035 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1039 Routine Description:
1041 Remove console device variable.
1045 VariableName - A pointer to the variable name.
1046 ParentDevicePath - A pointer to the parent device path.
1058 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1059 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1060 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1061 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1062 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1063 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1069 // Get global variable and its size according to the name given.
1071 Variable
= TerminalGetVariableAndSize (
1073 &gEfiGlobalVariableGuid
,
1076 if (Variable
== NULL
) {
1081 OriginalVariable
= Variable
;
1085 // Get first device path instance from Variable
1087 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1088 if (Instance
== NULL
) {
1089 FreePool (OriginalVariable
);
1093 // Loop through all the device path instances of Variable
1097 // Loop through all the terminal types that this driver supports
1100 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
1102 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1105 // Compare the genterated device path to the current device path instance
1107 if (TempDevicePath
!= NULL
) {
1108 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1113 FreePool (TempDevicePath
);
1117 // If a match was not found, then keep the current device path instance
1120 SavedNewVariable
= NewVariable
;
1121 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1122 if (SavedNewVariable
!= NULL
) {
1123 FreePool (SavedNewVariable
);
1127 // Get next device path instance from Variable
1129 FreePool (Instance
);
1130 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1131 } while (Instance
!= NULL
);
1133 FreePool (OriginalVariable
);
1136 VariableSize
= GetDevicePathSize (NewVariable
);
1138 Status
= gRT
->SetVariable (
1140 &gEfiGlobalVariableGuid
,
1141 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1145 ASSERT_EFI_ERROR (Status
);
1148 if (NewVariable
!= NULL
) {
1149 FreePool (NewVariable
);
1156 TerminalGetVariableAndSize (
1158 IN EFI_GUID
*VendorGuid
,
1159 OUT UINTN
*VariableSize
1163 Routine Description:
1164 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1165 buffer, and the size of the buffer. On failure return NULL.
1168 Name - String part of EFI variable name
1170 VendorGuid - GUID part of EFI variable name
1172 VariableSize - Returns the size of the EFI variable that was read
1175 Dynamically allocated memory that contains a copy of the EFI variable.
1176 Caller is repsoncible freeing the buffer.
1178 NULL - Variable was not read
1189 // Pass in a small size buffer to find the actual variable size.
1192 Buffer
= AllocatePool (BufferSize
);
1193 if (Buffer
== NULL
) {
1198 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1200 if (Status
== EFI_SUCCESS
) {
1201 *VariableSize
= BufferSize
;
1204 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1206 // Allocate the buffer to return
1209 Buffer
= AllocatePool (BufferSize
);
1210 if (Buffer
== NULL
) {
1215 // Read variable into the allocated buffer.
1217 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1218 if (EFI_ERROR (Status
)) {
1225 // Variable not found or other errors met.
1232 *VariableSize
= BufferSize
;
1237 SetTerminalDevicePath (
1238 IN UINT8 TerminalType
,
1239 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1240 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1243 VENDOR_DEVICE_PATH Node
;
1245 *TerminalDevicePath
= NULL
;
1246 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1247 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1250 // generate terminal device path node according to terminal type.
1252 switch (TerminalType
) {
1287 return EFI_UNSUPPORTED
;
1291 SetDevicePathNodeLength (
1293 sizeof (VENDOR_DEVICE_PATH
)
1296 // append the terminal node onto parent device path
1297 // to generate a complete terminal device path.
1299 *TerminalDevicePath
= AppendDevicePathNode (
1301 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1303 if (*TerminalDevicePath
== NULL
) {
1304 return EFI_OUT_OF_RESOURCES
;
1312 IN TERMINAL_DEV
*TerminalDevice
1316 // Make the raw fifo empty.
1318 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1322 InitializeUnicodeFiFo (
1323 IN TERMINAL_DEV
*TerminalDevice
1327 // Make the unicode fifo empty
1329 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1333 InitializeEfiKeyFiFo (
1334 IN TERMINAL_DEV
*TerminalDevice
1338 // Make the efi key fifo empty
1340 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;
1345 The user Entry Point for module Terminal. The user code starts with this function.
1347 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1348 @param[in] SystemTable A pointer to the EFI System Table.
1350 @retval EFI_SUCCESS The entry point is executed successfully.
1351 @retval other Some error occurs when executing this entry point.
1357 IN EFI_HANDLE ImageHandle
,
1358 IN EFI_SYSTEM_TABLE
*SystemTable
1364 // Install driver model protocol(s).
1366 Status
= EfiLibInstallDriverBindingComponentName2 (
1369 &gTerminalDriverBinding
,
1371 &gTerminalComponentName
,
1372 &gTerminalComponentName2
1374 ASSERT_EFI_ERROR (Status
);