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 TerminalFreeNotifyList (
21 IN OUT LIST_ENTRY
*ListHead
27 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
28 TerminalDriverBindingSupported
,
29 TerminalDriverBindingStart
,
30 TerminalDriverBindingStop
,
37 EFI_GUID
*gTerminalType
[] = {
45 TERMINAL_DEV gTerminalDevTemplate
= {
46 TERMINAL_DEV_SIGNATURE
,
53 TerminalConInReadKeyStroke
,
58 TerminalConOutOutputString
,
59 TerminalConOutTestString
,
60 TerminalConOutQueryMode
,
61 TerminalConOutSetMode
,
62 TerminalConOutSetAttribute
,
63 TerminalConOutClearScreen
,
64 TerminalConOutSetCursorPosition
,
65 TerminalConOutEnableCursor
,
68 { // SimpleTextOutputMode
71 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
), // Attribute
92 NULL
, // ControllerNameTable
97 { // SimpleTextInputEx
99 TerminalConInReadKeyStrokeEx
,
101 TerminalConInSetState
,
102 TerminalConInRegisterKeyNotify
,
103 TerminalConInUnregisterKeyNotify
,
115 TerminalDriverBindingSupported (
116 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
117 IN EFI_HANDLE Controller
,
118 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
122 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
123 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
124 VENDOR_DEVICE_PATH
*Node
;
127 // If remaining device path is not NULL, then make sure it is a
128 // device path that describes a terminal communications protocol.
130 if (RemainingDevicePath
!= NULL
) {
132 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
134 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
135 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
136 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
138 return EFI_UNSUPPORTED
;
142 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
144 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
145 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
146 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
147 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
149 return EFI_UNSUPPORTED
;
153 // Open the IO Abstraction(s) needed to perform the supported test
155 Status
= gBS
->OpenProtocol (
157 &gEfiDevicePathProtocolGuid
,
158 (VOID
**) &ParentDevicePath
,
159 This
->DriverBindingHandle
,
161 EFI_OPEN_PROTOCOL_BY_DRIVER
163 if (Status
== EFI_ALREADY_STARTED
) {
167 if (EFI_ERROR (Status
)) {
173 &gEfiDevicePathProtocolGuid
,
174 This
->DriverBindingHandle
,
179 // The Controller must support the Serial I/O Protocol.
180 // This driver is a bus driver with at most 1 child device, so it is
181 // ok for it to be already started.
183 Status
= gBS
->OpenProtocol (
185 &gEfiSerialIoProtocolGuid
,
187 This
->DriverBindingHandle
,
189 EFI_OPEN_PROTOCOL_BY_DRIVER
191 if (Status
== EFI_ALREADY_STARTED
) {
195 if (EFI_ERROR (Status
)) {
199 // Close the I/O Abstraction(s) used to perform the supported test
203 &gEfiSerialIoProtocolGuid
,
204 This
->DriverBindingHandle
,
213 Start the controller.
215 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
217 @param Controller The handle of the controller to start.
218 @param RemainingDevicePath A pointer to the remaining portion of a devcie
226 TerminalDriverBindingStart (
227 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
228 IN EFI_HANDLE Controller
,
229 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
233 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
234 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
235 VENDOR_DEVICE_PATH
*Node
;
236 VENDOR_DEVICE_PATH
*DefaultNode
;
237 EFI_SERIAL_IO_MODE
*Mode
;
238 UINTN SerialInTimeOut
;
239 TERMINAL_DEV
*TerminalDevice
;
241 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
244 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
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
) {
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
);
356 // must be between PCANSITYPE (0) and VTUTF8TYPE (3)
357 ASSERT (TerminalType
<= VTUTF8TYPE
);
359 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
360 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)DefaultNode
;
363 // Use the RemainingDevicePath to determine the terminal type
365 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
366 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
367 TerminalType
= PCANSITYPE
;
368 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
369 TerminalType
= VT100TYPE
;
370 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
371 TerminalType
= VT100PLUSTYPE
;
372 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
373 TerminalType
= VTUTF8TYPE
;
380 // Initialize the Terminal Dev
382 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &gTerminalDevTemplate
);
383 if (TerminalDevice
== NULL
) {
384 Status
= EFI_OUT_OF_RESOURCES
;
388 TerminalDevice
->TerminalType
= TerminalType
;
389 TerminalDevice
->SerialIo
= SerialIo
;
391 InitializeListHead (&TerminalDevice
->NotifyList
);
392 Status
= gBS
->CreateEvent (
395 TerminalConInWaitForKeyEx
,
396 &TerminalDevice
->SimpleInputEx
,
397 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
399 if (EFI_ERROR (Status
)) {
404 Status
= gBS
->CreateEvent (
407 TerminalConInWaitForKey
,
408 &TerminalDevice
->SimpleInput
,
409 &TerminalDevice
->SimpleInput
.WaitForKey
411 if (EFI_ERROR (Status
)) {
415 // initialize the FIFO buffer used for accommodating
416 // the pre-read pending characters
418 InitializeRawFiFo (TerminalDevice
);
419 InitializeUnicodeFiFo (TerminalDevice
);
420 InitializeEfiKeyFiFo (TerminalDevice
);
423 // Set the timeout value of serial buffer for
424 // keystroke response performance issue
426 Mode
= TerminalDevice
->SerialIo
->Mode
;
429 if (Mode
->BaudRate
!= 0) {
430 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
433 Status
= TerminalDevice
->SerialIo
->SetAttributes (
434 TerminalDevice
->SerialIo
,
436 Mode
->ReceiveFifoDepth
,
437 (UINT32
) SerialInTimeOut
,
438 (EFI_PARITY_TYPE
) (Mode
->Parity
),
439 (UINT8
) Mode
->DataBits
,
440 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
442 if (EFI_ERROR (Status
)) {
444 // if set attributes operation fails, invalidate
445 // the value of SerialInTimeOut,thus make it
446 // inconsistent with the default timeout value
447 // of serial buffer. This will invoke the recalculation
448 // in the readkeystroke routine.
450 TerminalDevice
->SerialInTimeOut
= 0;
452 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
455 // Build the device path for the child device
457 Status
= SetTerminalDevicePath (
458 TerminalDevice
->TerminalType
,
460 &TerminalDevice
->DevicePath
462 if (EFI_ERROR (Status
)) {
466 DevicePath
= TerminalDevice
->DevicePath
;
468 Status
= TerminalDevice
->SimpleInput
.Reset (
469 &TerminalDevice
->SimpleInput
,
472 if (EFI_ERROR (Status
)) {
474 // Need to report Error Code first
479 // Simple Text Output Protocol
481 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
482 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
483 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
484 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
485 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
486 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
487 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
488 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
489 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
490 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
492 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 3;
494 // For terminal devices, cursor is always visible
496 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
497 Status
= TerminalDevice
->SimpleTextOutput
.SetAttribute (
498 &TerminalDevice
->SimpleTextOutput
,
499 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
501 if (EFI_ERROR (Status
)) {
505 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
506 &TerminalDevice
->SimpleTextOutput
,
509 if (EFI_ERROR (Status
)) {
513 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
514 &TerminalDevice
->SimpleTextOutput
,
517 if (EFI_ERROR (Status
)) {
521 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
522 &TerminalDevice
->SimpleTextOutput
,
525 if (EFI_ERROR (Status
)) {
529 Status
= gBS
->CreateEvent (
534 &TerminalDevice
->TwoSecondTimeOut
538 // Build the component name for the child device
540 TerminalDevice
->ControllerNameTable
= NULL
;
541 switch (TerminalDevice
->TerminalType
) {
545 gTerminalComponentName
.SupportedLanguages
,
546 &TerminalDevice
->ControllerNameTable
,
547 (CHAR16
*)L
"PC-ANSI Serial Console",
552 gTerminalComponentName2
.SupportedLanguages
,
553 &TerminalDevice
->ControllerNameTable
,
554 (CHAR16
*)L
"PC-ANSI Serial Console",
563 gTerminalComponentName
.SupportedLanguages
,
564 &TerminalDevice
->ControllerNameTable
,
565 (CHAR16
*)L
"VT-100 Serial Console",
570 gTerminalComponentName2
.SupportedLanguages
,
571 &TerminalDevice
->ControllerNameTable
,
572 (CHAR16
*)L
"VT-100 Serial Console",
581 gTerminalComponentName
.SupportedLanguages
,
582 &TerminalDevice
->ControllerNameTable
,
583 (CHAR16
*)L
"VT-100+ Serial Console",
588 gTerminalComponentName2
.SupportedLanguages
,
589 &TerminalDevice
->ControllerNameTable
,
590 (CHAR16
*)L
"VT-100+ Serial Console",
599 gTerminalComponentName
.SupportedLanguages
,
600 &TerminalDevice
->ControllerNameTable
,
601 (CHAR16
*)L
"VT-UTF8 Serial Console",
606 gTerminalComponentName2
.SupportedLanguages
,
607 &TerminalDevice
->ControllerNameTable
,
608 (CHAR16
*)L
"VT-UTF8 Serial Console",
615 // Install protocol interfaces for the serial device.
617 Status
= gBS
->InstallMultipleProtocolInterfaces (
618 &TerminalDevice
->Handle
,
619 &gEfiDevicePathProtocolGuid
,
620 TerminalDevice
->DevicePath
,
621 &gEfiSimpleTextInProtocolGuid
,
622 &TerminalDevice
->SimpleInput
,
623 &gEfiSimpleTextInputExProtocolGuid
,
624 &TerminalDevice
->SimpleInputEx
,
625 &gEfiSimpleTextOutProtocolGuid
,
626 &TerminalDevice
->SimpleTextOutput
,
629 if (EFI_ERROR (Status
)) {
633 // if the serial device is a hot plug device, attaches the HotPlugGuid
634 // onto the terminal device handle.
636 Status
= gBS
->OpenProtocol (
638 &gEfiHotPlugDeviceGuid
,
640 This
->DriverBindingHandle
,
642 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
644 if (!EFI_ERROR (Status
)) {
645 Status
= gBS
->InstallMultipleProtocolInterfaces (
646 &TerminalDevice
->Handle
,
647 &gEfiHotPlugDeviceGuid
,
653 // Register the Parent-Child relationship via
654 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
656 Status
= gBS
->OpenProtocol (
658 &gEfiSerialIoProtocolGuid
,
659 (VOID
**) &TerminalDevice
->SerialIo
,
660 This
->DriverBindingHandle
,
661 TerminalDevice
->Handle
,
662 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
664 if (EFI_ERROR (Status
)) {
668 if (DefaultNode
!= NULL
) {
669 FreePool (DefaultNode
);
676 // Report error code before exiting
678 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
679 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
680 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
686 // Use the Stop() function to free all resources allocated in Start()
688 if (TerminalDevice
!= NULL
) {
690 if (TerminalDevice
->Handle
!= NULL
) {
691 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
694 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
695 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
698 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
699 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
702 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
703 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
706 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
708 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
709 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
712 if (TerminalDevice
->DevicePath
!= NULL
) {
713 FreePool (TerminalDevice
->DevicePath
);
716 FreePool (TerminalDevice
);
720 if (DefaultNode
!= NULL
) {
721 FreePool (DefaultNode
);
724 This
->Stop (This
, Controller
, 0, NULL
);
731 Stop a device controller.
733 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
735 @param Controller A handle to the device being stopped.
736 @param NumberOfChildren The number of child device handles in
738 @param ChildHandleBuffer An array of child handles to be freed.
740 @retval EFI_SUCCESS Operation successful.
741 @retval EFI_DEVICE_ERROR Devices error.
746 TerminalDriverBindingStop (
747 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
748 IN EFI_HANDLE Controller
,
749 IN UINTN NumberOfChildren
,
750 IN EFI_HANDLE
*ChildHandleBuffer
755 BOOLEAN AllChildrenStopped
;
756 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
757 TERMINAL_DEV
*TerminalDevice
;
758 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
759 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
760 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
762 Status
= gBS
->HandleProtocol (
764 &gEfiDevicePathProtocolGuid
,
765 (VOID
**) &DevicePath
767 if (EFI_ERROR (Status
)) {
772 // Complete all outstanding transactions to Controller.
773 // Don't allow any new transaction to Controller to be started.
775 if (NumberOfChildren
== 0) {
777 // Close the bus driver
779 Status
= gBS
->OpenProtocol (
782 (VOID
**) &ParentDevicePath
,
783 This
->DriverBindingHandle
,
785 EFI_OPEN_PROTOCOL_GET_PROTOCOL
787 if (!EFI_ERROR (Status
)) {
789 // Remove Parent Device Path from
790 // the Console Device Environment Variables
792 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
793 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
794 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
797 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
799 Status
= gBS
->UninstallMultipleProtocolInterfaces (
807 // Free the ParentDevicePath that was duplicated in Start()
809 if (!EFI_ERROR (Status
)) {
810 FreePool (ParentDevicePath
);
816 &gEfiSerialIoProtocolGuid
,
817 This
->DriverBindingHandle
,
823 &gEfiDevicePathProtocolGuid
,
824 This
->DriverBindingHandle
,
831 AllChildrenStopped
= TRUE
;
833 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
835 Status
= gBS
->OpenProtocol (
836 ChildHandleBuffer
[Index
],
837 &gEfiSimpleTextOutProtocolGuid
,
838 (VOID
**) &SimpleTextOutput
,
839 This
->DriverBindingHandle
,
840 ChildHandleBuffer
[Index
],
841 EFI_OPEN_PROTOCOL_GET_PROTOCOL
843 if (!EFI_ERROR (Status
)) {
845 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
849 &gEfiSerialIoProtocolGuid
,
850 This
->DriverBindingHandle
,
851 ChildHandleBuffer
[Index
]
854 Status
= gBS
->UninstallMultipleProtocolInterfaces (
855 ChildHandleBuffer
[Index
],
856 &gEfiSimpleTextInProtocolGuid
,
857 &TerminalDevice
->SimpleInput
,
858 &gEfiSimpleTextInputExProtocolGuid
,
859 &TerminalDevice
->SimpleInputEx
,
860 &gEfiSimpleTextOutProtocolGuid
,
861 &TerminalDevice
->SimpleTextOutput
,
862 &gEfiDevicePathProtocolGuid
,
863 TerminalDevice
->DevicePath
,
866 if (EFI_ERROR (Status
)) {
869 &gEfiSerialIoProtocolGuid
,
871 This
->DriverBindingHandle
,
872 ChildHandleBuffer
[Index
],
873 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
877 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
878 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
881 Status
= gBS
->OpenProtocol (
882 ChildHandleBuffer
[Index
],
883 &gEfiHotPlugDeviceGuid
,
885 This
->DriverBindingHandle
,
887 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
889 if (!EFI_ERROR (Status
)) {
890 Status
= gBS
->UninstallMultipleProtocolInterfaces (
891 ChildHandleBuffer
[Index
],
892 &gEfiHotPlugDeviceGuid
,
897 Status
= EFI_SUCCESS
;
900 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
901 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
902 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
903 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
904 FreePool (TerminalDevice
->DevicePath
);
905 FreePool (TerminalDevice
);
909 if (EFI_ERROR (Status
)) {
910 AllChildrenStopped
= FALSE
;
914 if (!AllChildrenStopped
) {
915 return EFI_DEVICE_ERROR
;
924 @param ListHead The list head
926 @retval EFI_SUCCESS Free the notify list successfully
927 @retval EFI_INVALID_PARAMETER ListHead is invalid.
931 TerminalFreeNotifyList (
932 IN OUT LIST_ENTRY
*ListHead
935 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
937 if (ListHead
== NULL
) {
938 return EFI_INVALID_PARAMETER
;
940 while (!IsListEmpty (ListHead
)) {
942 ListHead
->ForwardLink
,
943 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
945 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
947 RemoveEntryList (ListHead
->ForwardLink
);
948 gBS
->FreePool (NotifyNode
);
957 TerminalUpdateConsoleDevVariable (
958 IN CHAR16
*VariableName
,
959 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
965 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
966 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
967 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
972 // Get global variable and its size according to the name given.
974 Variable
= TerminalGetVariableAndSize (
976 &gEfiGlobalVariableGuid
,
980 // Append terminal device path onto the variable.
982 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
983 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
984 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
985 if (Variable
!= NULL
) {
989 if (TempDevicePath
!= NULL
) {
990 FreePool (TempDevicePath
);
993 Variable
= NewVariable
;
996 VariableSize
= GetDevicePathSize (Variable
);
998 Status
= gRT
->SetVariable (
1000 &gEfiGlobalVariableGuid
,
1001 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1005 ASSERT_EFI_ERROR (Status
);
1006 FreePool (Variable
);
1013 Remove console device variable.
1015 @param VariableName A pointer to the variable name.
1016 @param ParentDevicePath A pointer to the parent device path.
1022 TerminalRemoveConsoleDevVariable (
1023 IN CHAR16
*VariableName
,
1024 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1033 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1034 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1035 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1036 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1037 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1038 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1044 // Get global variable and its size according to the name given.
1046 Variable
= TerminalGetVariableAndSize (
1048 &gEfiGlobalVariableGuid
,
1051 if (Variable
== NULL
) {
1056 OriginalVariable
= Variable
;
1060 // Get first device path instance from Variable
1062 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1063 if (Instance
== NULL
) {
1064 FreePool (OriginalVariable
);
1068 // Loop through all the device path instances of Variable
1072 // Loop through all the terminal types that this driver supports
1075 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1077 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1080 // Compare the genterated device path to the current device path instance
1082 if (TempDevicePath
!= NULL
) {
1083 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1088 FreePool (TempDevicePath
);
1092 // If a match was not found, then keep the current device path instance
1095 SavedNewVariable
= NewVariable
;
1096 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1097 if (SavedNewVariable
!= NULL
) {
1098 FreePool (SavedNewVariable
);
1102 // Get next device path instance from Variable
1104 FreePool (Instance
);
1105 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1106 } while (Instance
!= NULL
);
1108 FreePool (OriginalVariable
);
1111 VariableSize
= GetDevicePathSize (NewVariable
);
1113 Status
= gRT
->SetVariable (
1115 &gEfiGlobalVariableGuid
,
1116 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1120 ASSERT_EFI_ERROR (Status
);
1123 if (NewVariable
!= NULL
) {
1124 FreePool (NewVariable
);
1132 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1133 buffer, and the size of the buffer. On failure return NULL.
1135 @param Name String part of EFI variable name
1136 @param VendorGuid GUID part of EFI variable name
1137 @param VariableSize Returns the size of the EFI variable that was read
1139 @return Dynamically allocated memory that contains a copy of the EFI variable.
1140 @return Caller is repsoncible freeing the buffer.
1141 @retval NULL Variable was not read
1145 TerminalGetVariableAndSize (
1147 IN EFI_GUID
*VendorGuid
,
1148 OUT UINTN
*VariableSize
1158 // Pass in a small size buffer to find the actual variable size.
1161 Buffer
= AllocatePool (BufferSize
);
1162 if (Buffer
== NULL
) {
1167 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1169 if (Status
== EFI_SUCCESS
) {
1170 *VariableSize
= BufferSize
;
1173 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1175 // Allocate the buffer to return
1178 Buffer
= AllocatePool (BufferSize
);
1179 if (Buffer
== NULL
) {
1184 // Read variable into the allocated buffer.
1186 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1187 if (EFI_ERROR (Status
)) {
1194 // Variable not found or other errors met.
1201 *VariableSize
= BufferSize
;
1206 SetTerminalDevicePath (
1207 IN UINT8 TerminalType
,
1208 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1209 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1212 VENDOR_DEVICE_PATH Node
;
1214 *TerminalDevicePath
= NULL
;
1215 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1216 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1219 // generate terminal device path node according to terminal type.
1221 switch (TerminalType
) {
1256 return EFI_UNSUPPORTED
;
1260 SetDevicePathNodeLength (
1262 sizeof (VENDOR_DEVICE_PATH
)
1265 // append the terminal node onto parent device path
1266 // to generate a complete terminal device path.
1268 *TerminalDevicePath
= AppendDevicePathNode (
1270 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1272 if (*TerminalDevicePath
== NULL
) {
1273 return EFI_OUT_OF_RESOURCES
;
1281 IN TERMINAL_DEV
*TerminalDevice
1285 // Make the raw fifo empty.
1287 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1291 InitializeUnicodeFiFo (
1292 IN TERMINAL_DEV
*TerminalDevice
1296 // Make the unicode fifo empty
1298 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1302 InitializeEfiKeyFiFo (
1303 IN TERMINAL_DEV
*TerminalDevice
1307 // Make the efi key fifo empty
1309 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;
1314 The user Entry Point for module Terminal. The user code starts with this function.
1316 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1317 @param[in] SystemTable A pointer to the EFI System Table.
1319 @retval EFI_SUCCESS The entry point is executed successfully.
1320 @retval other Some error occurs when executing this entry point.
1326 IN EFI_HANDLE ImageHandle
,
1327 IN EFI_SYSTEM_TABLE
*SystemTable
1333 // Install driver model protocol(s).
1335 Status
= EfiLibInstallDriverBindingComponentName2 (
1338 &gTerminalDriverBinding
,
1340 &gTerminalComponentName
,
1341 &gTerminalComponentName2
1343 ASSERT_EFI_ERROR (Status
);