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.
21 TerminalFreeNotifyList (
22 IN OUT LIST_ENTRY
*ListHead
28 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
29 TerminalDriverBindingSupported
,
30 TerminalDriverBindingStart
,
31 TerminalDriverBindingStop
,
38 EFI_GUID
*gTerminalType
[] = {
46 TERMINAL_DEV gTerminalDevTemplate
= {
47 TERMINAL_DEV_SIGNATURE
,
54 TerminalConInReadKeyStroke
,
59 TerminalConOutOutputString
,
60 TerminalConOutTestString
,
61 TerminalConOutQueryMode
,
62 TerminalConOutSetMode
,
63 TerminalConOutSetAttribute
,
64 TerminalConOutClearScreen
,
65 TerminalConOutSetCursorPosition
,
66 TerminalConOutEnableCursor
,
69 { // SimpleTextOutputMode
72 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
), // Attribute
93 NULL
, // ControllerNameTable
98 { // SimpleTextInputEx
100 TerminalConInReadKeyStrokeEx
,
102 TerminalConInSetState
,
103 TerminalConInRegisterKeyNotify
,
104 TerminalConInUnregisterKeyNotify
,
116 TerminalDriverBindingSupported (
117 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
118 IN EFI_HANDLE Controller
,
119 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
123 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
124 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
125 VENDOR_DEVICE_PATH
*Node
;
128 // If remaining device path is not NULL, then make sure it is a
129 // device path that describes a terminal communications protocol.
131 if (RemainingDevicePath
!= NULL
) {
133 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
135 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
136 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
137 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
139 return EFI_UNSUPPORTED
;
143 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
145 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
146 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
147 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
148 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
150 return EFI_UNSUPPORTED
;
154 // Open the IO Abstraction(s) needed to perform the supported test
156 Status
= gBS
->OpenProtocol (
158 &gEfiDevicePathProtocolGuid
,
159 (VOID
**) &ParentDevicePath
,
160 This
->DriverBindingHandle
,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
164 if (Status
== EFI_ALREADY_STARTED
) {
168 if (EFI_ERROR (Status
)) {
174 &gEfiDevicePathProtocolGuid
,
175 This
->DriverBindingHandle
,
180 // The Controller must support the Serial I/O Protocol.
181 // This driver is a bus driver with at most 1 child device, so it is
182 // ok for it to be already started.
184 Status
= gBS
->OpenProtocol (
186 &gEfiSerialIoProtocolGuid
,
188 This
->DriverBindingHandle
,
190 EFI_OPEN_PROTOCOL_BY_DRIVER
192 if (Status
== EFI_ALREADY_STARTED
) {
196 if (EFI_ERROR (Status
)) {
200 // Close the I/O Abstraction(s) used to perform the supported test
204 &gEfiSerialIoProtocolGuid
,
205 This
->DriverBindingHandle
,
214 TerminalDriverBindingStart (
215 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
216 IN EFI_HANDLE Controller
,
217 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
223 Start the controller.
227 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
228 Controller - The handle of the controller to start.
229 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
238 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
239 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
240 VENDOR_DEVICE_PATH
*Node
;
241 VENDOR_DEVICE_PATH
*DefaultNode
;
242 EFI_SERIAL_IO_MODE
*Mode
;
243 UINTN SerialInTimeOut
;
244 TERMINAL_DEV
*TerminalDevice
;
246 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
249 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
251 TerminalDevice
= NULL
;
254 // Get the Device Path Protocol to build the device path of the child device
256 Status
= gBS
->OpenProtocol (
258 &gEfiDevicePathProtocolGuid
,
259 (VOID
**) &ParentDevicePath
,
260 This
->DriverBindingHandle
,
262 EFI_OPEN_PROTOCOL_BY_DRIVER
264 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
269 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
271 Status
= gBS
->OpenProtocol (
273 &gEfiSerialIoProtocolGuid
,
275 This
->DriverBindingHandle
,
277 EFI_OPEN_PROTOCOL_BY_DRIVER
279 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
283 if (Status
!= EFI_ALREADY_STARTED
) {
285 // If Serial I/O is not already open by this driver, then tag the handle
286 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
287 // StdErrDev variables with the list of possible terminal types on this
290 Status
= gBS
->OpenProtocol (
294 This
->DriverBindingHandle
,
296 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
298 if (EFI_ERROR (Status
)) {
299 Status
= gBS
->InstallMultipleProtocolInterfaces (
302 DuplicateDevicePath (ParentDevicePath
),
305 if (EFI_ERROR (Status
)) {
309 // if the serial device is a hot plug device, do not update the
310 // ConInDev, ConOutDev, and StdErrDev variables.
312 Status
= gBS
->OpenProtocol (
314 &gEfiHotPlugDeviceGuid
,
316 This
->DriverBindingHandle
,
318 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
320 if (EFI_ERROR (Status
)) {
321 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
322 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
323 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
328 // Make sure a child handle does not already exist. This driver can only
329 // produce one child per serial port.
331 Status
= gBS
->OpenProtocolInformation (
333 &gEfiSerialIoProtocolGuid
,
337 if (!EFI_ERROR (Status
)) {
338 Status
= EFI_SUCCESS
;
339 for (Index
= 0; Index
< EntryCount
; Index
++) {
340 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
341 Status
= EFI_ALREADY_STARTED
;
345 FreePool (OpenInfoBuffer
);
346 if (EFI_ERROR (Status
)) {
351 // If RemainingDevicePath is NULL, then create default device path node
353 if (RemainingDevicePath
== NULL
) {
354 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
355 if (DefaultNode
== NULL
) {
356 Status
= EFI_OUT_OF_RESOURCES
;
360 TerminalType
= FixedPcdGet8 (PcdDefaultTerminalType
);
361 // must be between PcAnsiType (0) and VTUTF8Type (3)
362 ASSERT (TerminalType
<= VTUTF8Type
);
364 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
365 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)DefaultNode
;
368 // Use the RemainingDevicePath to determine the terminal type
370 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
371 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
372 TerminalType
= PcAnsiType
;
373 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
374 TerminalType
= VT100Type
;
375 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
376 TerminalType
= VT100PlusType
;
377 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
378 TerminalType
= VTUTF8Type
;
385 // Initialize the Terminal Dev
387 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &gTerminalDevTemplate
);
388 if (TerminalDevice
== NULL
) {
389 Status
= EFI_OUT_OF_RESOURCES
;
393 TerminalDevice
->TerminalType
= TerminalType
;
394 TerminalDevice
->SerialIo
= SerialIo
;
396 InitializeListHead (&TerminalDevice
->NotifyList
);
397 Status
= gBS
->CreateEvent (
400 TerminalConInWaitForKeyEx
,
401 &TerminalDevice
->SimpleInputEx
,
402 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
404 if (EFI_ERROR (Status
)) {
409 Status
= gBS
->CreateEvent (
412 TerminalConInWaitForKey
,
413 &TerminalDevice
->SimpleInput
,
414 &TerminalDevice
->SimpleInput
.WaitForKey
416 if (EFI_ERROR (Status
)) {
420 // initialize the FIFO buffer used for accommodating
421 // the pre-read pending characters
423 InitializeRawFiFo (TerminalDevice
);
424 InitializeUnicodeFiFo (TerminalDevice
);
425 InitializeEfiKeyFiFo (TerminalDevice
);
428 // Set the timeout value of serial buffer for
429 // keystroke response performance issue
431 Mode
= TerminalDevice
->SerialIo
->Mode
;
434 if (Mode
->BaudRate
!= 0) {
435 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
438 Status
= TerminalDevice
->SerialIo
->SetAttributes (
439 TerminalDevice
->SerialIo
,
441 Mode
->ReceiveFifoDepth
,
442 (UINT32
) SerialInTimeOut
,
443 (EFI_PARITY_TYPE
) (Mode
->Parity
),
444 (UINT8
) Mode
->DataBits
,
445 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
447 if (EFI_ERROR (Status
)) {
449 // if set attributes operation fails, invalidate
450 // the value of SerialInTimeOut,thus make it
451 // inconsistent with the default timeout value
452 // of serial buffer. This will invoke the recalculation
453 // in the readkeystroke routine.
455 TerminalDevice
->SerialInTimeOut
= 0;
457 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
460 // Build the device path for the child device
462 Status
= SetTerminalDevicePath (
463 TerminalDevice
->TerminalType
,
465 &TerminalDevice
->DevicePath
467 if (EFI_ERROR (Status
)) {
471 DevicePath
= TerminalDevice
->DevicePath
;
473 Status
= TerminalDevice
->SimpleInput
.Reset (
474 &TerminalDevice
->SimpleInput
,
477 if (EFI_ERROR (Status
)) {
479 // Need to report Error Code first
484 // Simple Text Output Protocol
486 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
487 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
488 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
489 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
490 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
491 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
492 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
493 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
494 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
495 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
497 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 3;
499 // For terminal devices, cursor is always visible
501 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
502 Status
= TerminalDevice
->SimpleTextOutput
.SetAttribute (
503 &TerminalDevice
->SimpleTextOutput
,
504 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
506 if (EFI_ERROR (Status
)) {
510 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
511 &TerminalDevice
->SimpleTextOutput
,
514 if (EFI_ERROR (Status
)) {
518 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
519 &TerminalDevice
->SimpleTextOutput
,
522 if (EFI_ERROR (Status
)) {
526 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
527 &TerminalDevice
->SimpleTextOutput
,
530 if (EFI_ERROR (Status
)) {
534 Status
= gBS
->CreateEvent (
539 &TerminalDevice
->TwoSecondTimeOut
543 // Build the component name for the child device
545 TerminalDevice
->ControllerNameTable
= NULL
;
546 switch (TerminalDevice
->TerminalType
) {
550 gTerminalComponentName
.SupportedLanguages
,
551 &TerminalDevice
->ControllerNameTable
,
552 (CHAR16
*)L
"PC-ANSI Serial Console",
557 gTerminalComponentName2
.SupportedLanguages
,
558 &TerminalDevice
->ControllerNameTable
,
559 (CHAR16
*)L
"PC-ANSI Serial Console",
568 gTerminalComponentName
.SupportedLanguages
,
569 &TerminalDevice
->ControllerNameTable
,
570 (CHAR16
*)L
"VT-100 Serial Console",
575 gTerminalComponentName2
.SupportedLanguages
,
576 &TerminalDevice
->ControllerNameTable
,
577 (CHAR16
*)L
"VT-100 Serial Console",
586 gTerminalComponentName
.SupportedLanguages
,
587 &TerminalDevice
->ControllerNameTable
,
588 (CHAR16
*)L
"VT-100+ Serial Console",
593 gTerminalComponentName2
.SupportedLanguages
,
594 &TerminalDevice
->ControllerNameTable
,
595 (CHAR16
*)L
"VT-100+ Serial Console",
604 gTerminalComponentName
.SupportedLanguages
,
605 &TerminalDevice
->ControllerNameTable
,
606 (CHAR16
*)L
"VT-UTF8 Serial Console",
611 gTerminalComponentName2
.SupportedLanguages
,
612 &TerminalDevice
->ControllerNameTable
,
613 (CHAR16
*)L
"VT-UTF8 Serial Console",
620 // Install protocol interfaces for the serial device.
622 Status
= gBS
->InstallMultipleProtocolInterfaces (
623 &TerminalDevice
->Handle
,
624 &gEfiDevicePathProtocolGuid
,
625 TerminalDevice
->DevicePath
,
626 &gEfiSimpleTextInProtocolGuid
,
627 &TerminalDevice
->SimpleInput
,
628 &gEfiSimpleTextInputExProtocolGuid
,
629 &TerminalDevice
->SimpleInputEx
,
630 &gEfiSimpleTextOutProtocolGuid
,
631 &TerminalDevice
->SimpleTextOutput
,
634 if (EFI_ERROR (Status
)) {
638 // if the serial device is a hot plug device, attaches the HotPlugGuid
639 // onto the terminal device handle.
641 Status
= gBS
->OpenProtocol (
643 &gEfiHotPlugDeviceGuid
,
645 This
->DriverBindingHandle
,
647 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
649 if (!EFI_ERROR (Status
)) {
650 Status
= gBS
->InstallMultipleProtocolInterfaces (
651 &TerminalDevice
->Handle
,
652 &gEfiHotPlugDeviceGuid
,
658 // Register the Parent-Child relationship via
659 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
661 Status
= gBS
->OpenProtocol (
663 &gEfiSerialIoProtocolGuid
,
664 (VOID
**) &TerminalDevice
->SerialIo
,
665 This
->DriverBindingHandle
,
666 TerminalDevice
->Handle
,
667 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
669 if (EFI_ERROR (Status
)) {
673 if (DefaultNode
!= NULL
) {
674 FreePool (DefaultNode
);
681 // Report error code before exiting
683 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
684 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
685 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
691 // Use the Stop() function to free all resources allocated in Start()
693 if (TerminalDevice
!= NULL
) {
695 if (TerminalDevice
->Handle
!= NULL
) {
696 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
699 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
700 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
703 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
704 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
707 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
708 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
711 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
713 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
714 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
717 if (TerminalDevice
->DevicePath
!= NULL
) {
718 FreePool (TerminalDevice
->DevicePath
);
721 FreePool (TerminalDevice
);
725 if (DefaultNode
!= NULL
) {
726 FreePool (DefaultNode
);
729 This
->Stop (This
, Controller
, 0, NULL
);
736 TerminalDriverBindingStop (
737 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
738 IN EFI_HANDLE Controller
,
739 IN UINTN NumberOfChildren
,
740 IN EFI_HANDLE
*ChildHandleBuffer
746 Stop a device controller.
750 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
751 Controller - A handle to the device being stopped.
752 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
753 ChildHandleBuffer - An array of child handles to be freed.
757 EFI_SUCCESS - Operation successful.
758 EFI_DEVICE_ERROR - Devices error.
764 BOOLEAN AllChildrenStopped
;
765 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
766 TERMINAL_DEV
*TerminalDevice
;
767 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
768 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
769 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
771 Status
= gBS
->HandleProtocol (
773 &gEfiDevicePathProtocolGuid
,
774 (VOID
**) &DevicePath
776 if (EFI_ERROR (Status
)) {
781 // Complete all outstanding transactions to Controller.
782 // Don't allow any new transaction to Controller to be started.
784 if (NumberOfChildren
== 0) {
786 // Close the bus driver
788 Status
= gBS
->OpenProtocol (
791 (VOID
**) &ParentDevicePath
,
792 This
->DriverBindingHandle
,
794 EFI_OPEN_PROTOCOL_GET_PROTOCOL
796 if (!EFI_ERROR (Status
)) {
798 // Remove Parent Device Path from
799 // the Console Device Environment Variables
801 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
802 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
803 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
806 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
808 Status
= gBS
->UninstallMultipleProtocolInterfaces (
816 // Free the ParentDevicePath that was duplicated in Start()
818 if (!EFI_ERROR (Status
)) {
819 FreePool (ParentDevicePath
);
825 &gEfiSerialIoProtocolGuid
,
826 This
->DriverBindingHandle
,
832 &gEfiDevicePathProtocolGuid
,
833 This
->DriverBindingHandle
,
840 AllChildrenStopped
= TRUE
;
842 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
844 Status
= gBS
->OpenProtocol (
845 ChildHandleBuffer
[Index
],
846 &gEfiSimpleTextOutProtocolGuid
,
847 (VOID
**) &SimpleTextOutput
,
848 This
->DriverBindingHandle
,
849 ChildHandleBuffer
[Index
],
850 EFI_OPEN_PROTOCOL_GET_PROTOCOL
852 if (!EFI_ERROR (Status
)) {
854 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
858 &gEfiSerialIoProtocolGuid
,
859 This
->DriverBindingHandle
,
860 ChildHandleBuffer
[Index
]
863 Status
= gBS
->UninstallMultipleProtocolInterfaces (
864 ChildHandleBuffer
[Index
],
865 &gEfiSimpleTextInProtocolGuid
,
866 &TerminalDevice
->SimpleInput
,
867 &gEfiSimpleTextInputExProtocolGuid
,
868 &TerminalDevice
->SimpleInputEx
,
869 &gEfiSimpleTextOutProtocolGuid
,
870 &TerminalDevice
->SimpleTextOutput
,
871 &gEfiDevicePathProtocolGuid
,
872 TerminalDevice
->DevicePath
,
875 if (EFI_ERROR (Status
)) {
878 &gEfiSerialIoProtocolGuid
,
880 This
->DriverBindingHandle
,
881 ChildHandleBuffer
[Index
],
882 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
886 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
887 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
890 Status
= gBS
->OpenProtocol (
891 ChildHandleBuffer
[Index
],
892 &gEfiHotPlugDeviceGuid
,
894 This
->DriverBindingHandle
,
896 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
898 if (!EFI_ERROR (Status
)) {
899 Status
= gBS
->UninstallMultipleProtocolInterfaces (
900 ChildHandleBuffer
[Index
],
901 &gEfiHotPlugDeviceGuid
,
906 Status
= EFI_SUCCESS
;
909 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
910 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
911 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
912 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
913 FreePool (TerminalDevice
->DevicePath
);
914 FreePool (TerminalDevice
);
918 if (EFI_ERROR (Status
)) {
919 AllChildrenStopped
= FALSE
;
923 if (!AllChildrenStopped
) {
924 return EFI_DEVICE_ERROR
;
932 TerminalFreeNotifyList (
933 IN OUT LIST_ENTRY
*ListHead
941 ListHead - The list head
945 EFI_SUCCESS - Free the notify list successfully
946 EFI_INVALID_PARAMETER - ListHead is invalid.
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 gBS
->FreePool (NotifyNode
);
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
);
1027 TerminalRemoveConsoleDevVariable (
1028 IN CHAR16
*VariableName
,
1029 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1033 Routine Description:
1035 Remove console device variable.
1039 VariableName - A pointer to the variable name.
1040 ParentDevicePath - A pointer to the parent device path.
1052 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1053 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1054 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1055 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1056 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1057 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1063 // Get global variable and its size according to the name given.
1065 Variable
= TerminalGetVariableAndSize (
1067 &gEfiGlobalVariableGuid
,
1070 if (Variable
== NULL
) {
1075 OriginalVariable
= Variable
;
1079 // Get first device path instance from Variable
1081 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1082 if (Instance
== NULL
) {
1083 FreePool (OriginalVariable
);
1087 // Loop through all the device path instances of Variable
1091 // Loop through all the terminal types that this driver supports
1094 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
1096 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1099 // Compare the genterated device path to the current device path instance
1101 if (TempDevicePath
!= NULL
) {
1102 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1107 FreePool (TempDevicePath
);
1111 // If a match was not found, then keep the current device path instance
1114 SavedNewVariable
= NewVariable
;
1115 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1116 if (SavedNewVariable
!= NULL
) {
1117 FreePool (SavedNewVariable
);
1121 // Get next device path instance from Variable
1123 FreePool (Instance
);
1124 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1125 } while (Instance
!= NULL
);
1127 FreePool (OriginalVariable
);
1130 VariableSize
= GetDevicePathSize (NewVariable
);
1132 Status
= gRT
->SetVariable (
1134 &gEfiGlobalVariableGuid
,
1135 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1139 ASSERT_EFI_ERROR (Status
);
1142 if (NewVariable
!= NULL
) {
1143 FreePool (NewVariable
);
1150 TerminalGetVariableAndSize (
1152 IN EFI_GUID
*VendorGuid
,
1153 OUT UINTN
*VariableSize
1157 Routine Description:
1158 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1159 buffer, and the size of the buffer. On failure return NULL.
1162 Name - String part of EFI variable name
1164 VendorGuid - GUID part of EFI variable name
1166 VariableSize - Returns the size of the EFI variable that was read
1169 Dynamically allocated memory that contains a copy of the EFI variable.
1170 Caller is repsoncible freeing the buffer.
1172 NULL - Variable was not read
1183 // Pass in a small size buffer to find the actual variable size.
1186 Buffer
= AllocatePool (BufferSize
);
1187 if (Buffer
== NULL
) {
1192 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1194 if (Status
== EFI_SUCCESS
) {
1195 *VariableSize
= BufferSize
;
1198 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1200 // Allocate the buffer to return
1203 Buffer
= AllocatePool (BufferSize
);
1204 if (Buffer
== NULL
) {
1209 // Read variable into the allocated buffer.
1211 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1212 if (EFI_ERROR (Status
)) {
1219 // Variable not found or other errors met.
1226 *VariableSize
= BufferSize
;
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
) {
1281 return EFI_UNSUPPORTED
;
1285 SetDevicePathNodeLength (
1287 sizeof (VENDOR_DEVICE_PATH
)
1290 // append the terminal node onto parent device path
1291 // to generate a complete terminal device path.
1293 *TerminalDevicePath
= AppendDevicePathNode (
1295 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1297 if (*TerminalDevicePath
== NULL
) {
1298 return EFI_OUT_OF_RESOURCES
;
1306 IN TERMINAL_DEV
*TerminalDevice
1310 // Make the raw fifo empty.
1312 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1316 InitializeUnicodeFiFo (
1317 IN TERMINAL_DEV
*TerminalDevice
1321 // Make the unicode fifo empty
1323 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1327 InitializeEfiKeyFiFo (
1328 IN TERMINAL_DEV
*TerminalDevice
1332 // Make the efi key fifo empty
1334 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;
1339 The user Entry Point for module Terminal. The user code starts with this function.
1341 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1342 @param[in] SystemTable A pointer to the EFI System Table.
1344 @retval EFI_SUCCESS The entry point is executed successfully.
1345 @retval other Some error occurs when executing this entry point.
1351 IN EFI_HANDLE ImageHandle
,
1352 IN EFI_SYSTEM_TABLE
*SystemTable
1358 // Install driver model protocol(s).
1360 Status
= EfiLibInstallDriverBindingComponentName2 (
1363 &gTerminalDriverBinding
,
1365 &gTerminalComponentName
,
1366 &gTerminalComponentName2
1368 ASSERT_EFI_ERROR (Status
);