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.
24 // Include common header file for this module.
26 #include "CommonHeader.h"
30 #include "FrameworkDxe.h"
35 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
36 TerminalDriverBindingSupported
,
37 TerminalDriverBindingStart
,
38 TerminalDriverBindingStop
,
47 TerminalDriverBindingSupported (
48 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
49 IN EFI_HANDLE Controller
,
50 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
54 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
55 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
56 VENDOR_DEVICE_PATH
*Node
;
59 // If remaining device path is not NULL, then make sure it is a
60 // device path that describes a terminal communications protocol.
62 if (RemainingDevicePath
!= NULL
) {
64 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
66 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
67 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
68 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
70 return EFI_UNSUPPORTED
;
74 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
76 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
77 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
78 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
79 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
81 return EFI_UNSUPPORTED
;
85 // Open the IO Abstraction(s) needed to perform the supported test
87 Status
= gBS
->OpenProtocol (
89 &gEfiDevicePathProtocolGuid
,
90 (VOID
**) &ParentDevicePath
,
91 This
->DriverBindingHandle
,
93 EFI_OPEN_PROTOCOL_BY_DRIVER
95 if (Status
== EFI_ALREADY_STARTED
) {
99 if (EFI_ERROR (Status
)) {
105 &gEfiDevicePathProtocolGuid
,
106 This
->DriverBindingHandle
,
111 // The Controller must support the Serial I/O Protocol.
112 // This driver is a bus driver with at most 1 child device, so it is
113 // ok for it to be already started.
115 Status
= gBS
->OpenProtocol (
117 &gEfiSerialIoProtocolGuid
,
119 This
->DriverBindingHandle
,
121 EFI_OPEN_PROTOCOL_BY_DRIVER
123 if (Status
== EFI_ALREADY_STARTED
) {
127 if (EFI_ERROR (Status
)) {
131 // Close the I/O Abstraction(s) used to perform the supported test
135 &gEfiSerialIoProtocolGuid
,
136 This
->DriverBindingHandle
,
145 TerminalDriverBindingStart (
146 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
147 IN EFI_HANDLE Controller
,
148 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
154 Start the controller.
158 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
159 Controller - The handle of the controller to start.
160 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
169 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
170 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
171 VENDOR_DEVICE_PATH
*Node
;
172 VENDOR_DEVICE_PATH
*DefaultNode
;
173 EFI_SERIAL_IO_MODE
*Mode
;
174 UINTN SerialInTimeOut
;
175 TERMINAL_DEV
*TerminalDevice
;
177 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
180 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
182 TerminalDevice
= NULL
;
185 // Get the Device Path Protocol to build the device path of the child device
187 Status
= gBS
->OpenProtocol (
189 &gEfiDevicePathProtocolGuid
,
190 (VOID
**) &ParentDevicePath
,
191 This
->DriverBindingHandle
,
193 EFI_OPEN_PROTOCOL_BY_DRIVER
195 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
199 // Report that the remote terminal is being enabled
201 DevicePath
= ParentDevicePath
;
202 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
204 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_ENABLE
,
209 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
211 Status
= gBS
->OpenProtocol (
213 &gEfiSerialIoProtocolGuid
,
215 This
->DriverBindingHandle
,
217 EFI_OPEN_PROTOCOL_BY_DRIVER
219 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
223 if (Status
!= EFI_ALREADY_STARTED
) {
225 // If Serial I/O is not already open by this driver, then tag the handle
226 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
227 // StdErrDev variables with the list of possible terminal types on this
230 Status
= gBS
->OpenProtocol (
234 This
->DriverBindingHandle
,
236 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
238 if (EFI_ERROR (Status
)) {
239 Status
= gBS
->InstallMultipleProtocolInterfaces (
242 DuplicateDevicePath (ParentDevicePath
),
245 if (EFI_ERROR (Status
)) {
249 // if the serial device is a hot plug device, do not update the
250 // ConInDev, ConOutDev, and StdErrDev variables.
252 Status
= gBS
->OpenProtocol (
254 &gEfiHotPlugDeviceGuid
,
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
260 if (EFI_ERROR (Status
)) {
261 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
262 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
263 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
268 // Make sure a child handle does not already exist. This driver can only
269 // produce one child per serial port.
271 Status
= gBS
->OpenProtocolInformation (
273 &gEfiSerialIoProtocolGuid
,
277 if (!EFI_ERROR (Status
)) {
278 Status
= EFI_SUCCESS
;
279 for (Index
= 0; Index
< EntryCount
; Index
++) {
280 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
281 Status
= EFI_ALREADY_STARTED
;
285 FreePool (OpenInfoBuffer
);
286 if (EFI_ERROR (Status
)) {
291 // If RemainingDevicePath is NULL, then create default device path node
293 if (RemainingDevicePath
== NULL
) {
294 DefaultNode
= AllocatePool (sizeof (VENDOR_DEVICE_PATH
));
295 if (DefaultNode
== NULL
) {
296 Status
= EFI_OUT_OF_RESOURCES
;
300 CopyMem (&DefaultNode
->Guid
, &gEfiPcAnsiGuid
, sizeof (EFI_GUID
));
301 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
304 // Use the RemainingDevicePath to determine the terminal type
306 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
308 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
310 TerminalType
= PcAnsiType
;
312 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
314 TerminalType
= VT100Type
;
316 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
318 TerminalType
= VT100PlusType
;
320 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
322 TerminalType
= VTUTF8Type
;
328 // Initialize the Terminal Dev
330 TerminalDevice
= AllocatePool (sizeof (TERMINAL_DEV
));
331 if (TerminalDevice
== NULL
) {
332 Status
= EFI_OUT_OF_RESOURCES
;
336 ZeroMem (TerminalDevice
, sizeof (TERMINAL_DEV
));
338 TerminalDevice
->Signature
= TERMINAL_DEV_SIGNATURE
;
340 TerminalDevice
->TerminalType
= TerminalType
;
342 TerminalDevice
->SerialIo
= SerialIo
;
345 // Simple Input Protocol
347 TerminalDevice
->SimpleInput
.Reset
= TerminalConInReset
;
348 TerminalDevice
->SimpleInput
.ReadKeyStroke
= TerminalConInReadKeyStroke
;
350 Status
= gBS
->CreateEvent (
353 TerminalConInWaitForKey
,
354 &TerminalDevice
->SimpleInput
,
355 &TerminalDevice
->SimpleInput
.WaitForKey
357 if (EFI_ERROR (Status
)) {
361 // initialize the FIFO buffer used for accommodating
362 // the pre-read pending characters
364 InitializeRawFiFo (TerminalDevice
);
365 InitializeUnicodeFiFo (TerminalDevice
);
366 InitializeEfiKeyFiFo (TerminalDevice
);
369 // Set the timeout value of serial buffer for
370 // keystroke response performance issue
372 Mode
= TerminalDevice
->SerialIo
->Mode
;
375 if (Mode
->BaudRate
!= 0) {
376 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
379 Status
= TerminalDevice
->SerialIo
->SetAttributes (
380 TerminalDevice
->SerialIo
,
382 Mode
->ReceiveFifoDepth
,
383 (UINT32
) SerialInTimeOut
,
384 (EFI_PARITY_TYPE
) (Mode
->Parity
),
385 (UINT8
) Mode
->DataBits
,
386 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
388 if (EFI_ERROR (Status
)) {
390 // if set attributes operation fails, invalidate
391 // the value of SerialInTimeOut,thus make it
392 // inconsistent with the default timeout value
393 // of serial buffer. This will invoke the recalculation
394 // in the readkeystroke routine.
396 TerminalDevice
->SerialInTimeOut
= 0;
398 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
401 // Build the device path for the child device
403 Status
= SetTerminalDevicePath (
404 TerminalDevice
->TerminalType
,
406 &TerminalDevice
->DevicePath
408 if (EFI_ERROR (Status
)) {
412 DevicePath
= TerminalDevice
->DevicePath
;
414 Status
= TerminalDevice
->SimpleInput
.Reset (
415 &TerminalDevice
->SimpleInput
,
418 if (EFI_ERROR (Status
)) {
420 // Need to report Error Code first
425 // Simple Text Output Protocol
427 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
428 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
429 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
430 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
431 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
432 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
433 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
434 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
435 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
436 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
438 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 1;
440 // For terminal devices, cursor is always visible
442 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
443 TerminalDevice
->SimpleTextOutputMode
.Attribute
= EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
);
445 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
446 &TerminalDevice
->SimpleTextOutput
,
449 if (EFI_ERROR (Status
)) {
453 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
454 &TerminalDevice
->SimpleTextOutput
,
457 if (EFI_ERROR (Status
)) {
461 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
462 &TerminalDevice
->SimpleTextOutput
,
465 if (EFI_ERROR (Status
)) {
471 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
472 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
474 Status
= gBS
->CreateEvent (
479 &TerminalDevice
->TwoSecondTimeOut
483 // Build the component name for the child device
485 TerminalDevice
->ControllerNameTable
= NULL
;
486 switch (TerminalDevice
->TerminalType
) {
490 gTerminalComponentName
.SupportedLanguages
,
491 &TerminalDevice
->ControllerNameTable
,
492 (CHAR16
*)L
"PC-ANSI Serial Console"
499 gTerminalComponentName
.SupportedLanguages
,
500 &TerminalDevice
->ControllerNameTable
,
501 (CHAR16
*)L
"VT-100 Serial Console"
508 gTerminalComponentName
.SupportedLanguages
,
509 &TerminalDevice
->ControllerNameTable
,
510 (CHAR16
*)L
"VT-100+ Serial Console"
517 gTerminalComponentName
.SupportedLanguages
,
518 &TerminalDevice
->ControllerNameTable
,
519 (CHAR16
*)L
"VT-UTF8 Serial Console"
524 // Install protocol interfaces for the serial device.
526 Status
= gBS
->InstallMultipleProtocolInterfaces (
527 &TerminalDevice
->Handle
,
528 &gEfiDevicePathProtocolGuid
,
529 TerminalDevice
->DevicePath
,
530 &gEfiSimpleTextInProtocolGuid
,
531 &TerminalDevice
->SimpleInput
,
532 &gEfiSimpleTextOutProtocolGuid
,
533 &TerminalDevice
->SimpleTextOutput
,
536 if (EFI_ERROR (Status
)) {
540 // if the serial device is a hot plug device, attaches the HotPlugGuid
541 // onto the terminal device handle.
543 Status
= gBS
->OpenProtocol (
545 &gEfiHotPlugDeviceGuid
,
547 This
->DriverBindingHandle
,
549 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
551 if (!EFI_ERROR (Status
)) {
552 Status
= gBS
->InstallMultipleProtocolInterfaces (
553 &TerminalDevice
->Handle
,
554 &gEfiHotPlugDeviceGuid
,
560 // Register the Parent-Child relationship via
561 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
563 Status
= gBS
->OpenProtocol (
565 &gEfiSerialIoProtocolGuid
,
566 (VOID
**) &TerminalDevice
->SerialIo
,
567 This
->DriverBindingHandle
,
568 TerminalDevice
->Handle
,
569 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
571 if (EFI_ERROR (Status
)) {
575 if (DefaultNode
!= NULL
) {
576 FreePool (DefaultNode
);
583 // Report error code before exiting
585 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
586 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
587 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
593 // Use the Stop() function to free all resources allocated in Start()
595 if (TerminalDevice
!= NULL
) {
597 if (TerminalDevice
->Handle
!= NULL
) {
598 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
601 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
602 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
605 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
606 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
609 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
610 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
613 if (TerminalDevice
->DevicePath
!= NULL
) {
614 FreePool (TerminalDevice
->DevicePath
);
617 FreePool (TerminalDevice
);
621 if (DefaultNode
!= NULL
) {
622 FreePool (DefaultNode
);
625 This
->Stop (This
, Controller
, 0, NULL
);
632 TerminalDriverBindingStop (
633 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
634 IN EFI_HANDLE Controller
,
635 IN UINTN NumberOfChildren
,
636 IN EFI_HANDLE
*ChildHandleBuffer
642 Stop a device controller.
646 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
647 Controller - A handle to the device being stopped.
648 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
649 ChildHandleBuffer - An array of child handles to be freed.
653 EFI_SUCCESS - Operation successful.
654 EFI_DEVICE_ERROR - Devices error.
660 BOOLEAN AllChildrenStopped
;
661 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
662 TERMINAL_DEV
*TerminalDevice
;
663 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
664 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
665 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
667 Status
= gBS
->HandleProtocol (
669 &gEfiDevicePathProtocolGuid
,
670 (VOID
**) &DevicePath
672 if (EFI_ERROR (Status
)) {
676 // Report that the remote terminal is being disabled
678 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
680 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_DISABLE
,
685 // Complete all outstanding transactions to Controller.
686 // Don't allow any new transaction to Controller to be started.
688 if (NumberOfChildren
== 0) {
690 // Close the bus driver
692 Status
= gBS
->OpenProtocol (
695 (VOID
**) &ParentDevicePath
,
696 This
->DriverBindingHandle
,
698 EFI_OPEN_PROTOCOL_GET_PROTOCOL
700 if (!EFI_ERROR (Status
)) {
702 // Remove Parent Device Path from
703 // the Console Device Environment Variables
705 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
706 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
707 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
710 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
712 Status
= gBS
->UninstallMultipleProtocolInterfaces (
720 // Free the ParentDevicePath that was duplicated in Start()
722 if (!EFI_ERROR (Status
)) {
723 FreePool (ParentDevicePath
);
729 &gEfiSerialIoProtocolGuid
,
730 This
->DriverBindingHandle
,
736 &gEfiDevicePathProtocolGuid
,
737 This
->DriverBindingHandle
,
744 AllChildrenStopped
= TRUE
;
746 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
748 Status
= gBS
->OpenProtocol (
749 ChildHandleBuffer
[Index
],
750 &gEfiSimpleTextOutProtocolGuid
,
751 (VOID
**) &SimpleTextOutput
,
752 This
->DriverBindingHandle
,
753 ChildHandleBuffer
[Index
],
754 EFI_OPEN_PROTOCOL_GET_PROTOCOL
756 if (!EFI_ERROR (Status
)) {
758 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
762 &gEfiSerialIoProtocolGuid
,
763 This
->DriverBindingHandle
,
764 ChildHandleBuffer
[Index
]
767 Status
= gBS
->UninstallMultipleProtocolInterfaces (
768 ChildHandleBuffer
[Index
],
769 &gEfiSimpleTextInProtocolGuid
,
770 &TerminalDevice
->SimpleInput
,
771 &gEfiSimpleTextOutProtocolGuid
,
772 &TerminalDevice
->SimpleTextOutput
,
773 &gEfiDevicePathProtocolGuid
,
774 TerminalDevice
->DevicePath
,
777 if (EFI_ERROR (Status
)) {
780 &gEfiSerialIoProtocolGuid
,
782 This
->DriverBindingHandle
,
783 ChildHandleBuffer
[Index
],
784 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
788 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
789 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
792 Status
= gBS
->OpenProtocol (
793 ChildHandleBuffer
[Index
],
794 &gEfiHotPlugDeviceGuid
,
796 This
->DriverBindingHandle
,
798 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
800 if (!EFI_ERROR (Status
)) {
801 Status
= gBS
->UninstallMultipleProtocolInterfaces (
802 ChildHandleBuffer
[Index
],
803 &gEfiHotPlugDeviceGuid
,
808 Status
= EFI_SUCCESS
;
811 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
812 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
813 FreePool (TerminalDevice
->DevicePath
);
814 FreePool (TerminalDevice
);
818 if (EFI_ERROR (Status
)) {
819 AllChildrenStopped
= FALSE
;
823 if (!AllChildrenStopped
) {
824 return EFI_DEVICE_ERROR
;
831 TerminalUpdateConsoleDevVariable (
832 IN CHAR16
*VariableName
,
833 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
839 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
840 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
841 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
846 // Get global variable and its size according to the name given.
848 Variable
= TerminalGetVariableAndSize (
850 &gEfiGlobalVariableGuid
,
854 // Append terminal device path onto the variable.
856 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
857 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
858 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
859 if (Variable
!= NULL
) {
863 if (TempDevicePath
!= NULL
) {
864 FreePool (TempDevicePath
);
867 Variable
= NewVariable
;
870 VariableSize
= GetDevicePathSize (Variable
);
872 Status
= gRT
->SetVariable (
874 &gEfiGlobalVariableGuid
,
875 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
879 ASSERT_EFI_ERROR (Status
);
886 TerminalRemoveConsoleDevVariable (
887 IN CHAR16
*VariableName
,
888 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
894 Remove console device variable.
898 VariableName - A pointer to the variable name.
899 ParentDevicePath - A pointer to the parent device path.
911 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
912 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
913 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
914 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
915 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
916 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
922 // Get global variable and its size according to the name given.
924 Variable
= TerminalGetVariableAndSize (
926 &gEfiGlobalVariableGuid
,
929 if (Variable
== NULL
) {
934 OriginalVariable
= Variable
;
938 // Get first device path instance from Variable
940 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
941 if (Instance
== NULL
) {
942 FreePool (OriginalVariable
);
946 // Loop through all the device path instances of Variable
950 // Loop through all the terminal types that this driver supports
953 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
955 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
958 // Compare the genterated device path to the current device path instance
960 if (TempDevicePath
!= NULL
) {
961 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
966 FreePool (TempDevicePath
);
970 // If a match was not found, then keep the current device path instance
973 SavedNewVariable
= NewVariable
;
974 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
975 if (SavedNewVariable
!= NULL
) {
976 FreePool (SavedNewVariable
);
980 // Get next device path instance from Variable
983 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
984 } while (Instance
!= NULL
);
986 FreePool (OriginalVariable
);
989 VariableSize
= GetDevicePathSize (NewVariable
);
991 Status
= gRT
->SetVariable (
993 &gEfiGlobalVariableGuid
,
994 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
998 ASSERT_EFI_ERROR (Status
);
1001 if (NewVariable
!= NULL
) {
1002 FreePool (NewVariable
);
1009 TerminalGetVariableAndSize (
1011 IN EFI_GUID
*VendorGuid
,
1012 OUT UINTN
*VariableSize
1016 Routine Description:
1017 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1018 buffer, and the size of the buffer. On failure return NULL.
1021 Name - String part of EFI variable name
1023 VendorGuid - GUID part of EFI variable name
1025 VariableSize - Returns the size of the EFI variable that was read
1028 Dynamically allocated memory that contains a copy of the EFI variable.
1029 Caller is repsoncible freeing the buffer.
1031 NULL - Variable was not read
1042 // Pass in a small size buffer to find the actual variable size.
1045 Buffer
= AllocatePool (BufferSize
);
1046 if (Buffer
== NULL
) {
1051 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1053 if (Status
== EFI_SUCCESS
) {
1054 *VariableSize
= BufferSize
;
1057 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1059 // Allocate the buffer to return
1062 Buffer
= AllocatePool (BufferSize
);
1063 if (Buffer
== NULL
) {
1068 // Read variable into the allocated buffer.
1070 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1071 if (EFI_ERROR (Status
)) {
1078 // Variable not found or other errors met.
1085 *VariableSize
= BufferSize
;
1090 SetTerminalDevicePath (
1091 IN UINT8 TerminalType
,
1092 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1093 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1096 VENDOR_DEVICE_PATH Node
;
1098 *TerminalDevicePath
= NULL
;
1099 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1100 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1103 // generate terminal device path node according to terminal type.
1105 switch (TerminalType
) {
1140 return EFI_UNSUPPORTED
;
1144 SetDevicePathNodeLength (
1146 sizeof (VENDOR_DEVICE_PATH
)
1149 // append the terminal node onto parent device path
1150 // to generate a complete terminal device path.
1152 *TerminalDevicePath
= AppendDevicePathNode (
1154 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1156 if (*TerminalDevicePath
== NULL
) {
1157 return EFI_OUT_OF_RESOURCES
;
1165 IN TERMINAL_DEV
*TerminalDevice
1169 // Make the raw fifo empty.
1171 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1175 InitializeUnicodeFiFo (
1176 IN TERMINAL_DEV
*TerminalDevice
1180 // Make the unicode fifo empty
1182 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1186 InitializeEfiKeyFiFo (
1187 IN TERMINAL_DEV
*TerminalDevice
1191 // Make the efi key fifo empty
1193 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;