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/StatusCode.h>
27 // Function Prototypes
31 TerminalDriverBindingSupported (
32 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
33 IN EFI_HANDLE Controller
,
34 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
39 TerminalDriverBindingStart (
40 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
41 IN EFI_HANDLE Controller
,
42 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
47 TerminalDriverBindingStop (
48 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
49 IN EFI_HANDLE Controller
,
50 IN UINTN NumberOfChildren
,
51 IN EFI_HANDLE
*ChildHandleBuffer
57 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
58 TerminalDriverBindingSupported
,
59 TerminalDriverBindingStart
,
60 TerminalDriverBindingStop
,
69 TerminalDriverBindingSupported (
70 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
71 IN EFI_HANDLE Controller
,
72 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
76 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
77 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
78 VENDOR_DEVICE_PATH
*Node
;
81 // If remaining device path is not NULL, then make sure it is a
82 // device path that describes a terminal communications protocol.
84 if (RemainingDevicePath
!= NULL
) {
86 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
88 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
89 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
90 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
92 return EFI_UNSUPPORTED
;
96 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
98 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
99 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
100 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
101 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
103 return EFI_UNSUPPORTED
;
107 // Open the IO Abstraction(s) needed to perform the supported test
109 Status
= gBS
->OpenProtocol (
111 &gEfiDevicePathProtocolGuid
,
112 (VOID
**) &ParentDevicePath
,
113 This
->DriverBindingHandle
,
115 EFI_OPEN_PROTOCOL_BY_DRIVER
117 if (Status
== EFI_ALREADY_STARTED
) {
121 if (EFI_ERROR (Status
)) {
127 &gEfiDevicePathProtocolGuid
,
128 This
->DriverBindingHandle
,
133 // The Controller must support the Serial I/O Protocol.
134 // This driver is a bus driver with at most 1 child device, so it is
135 // ok for it to be already started.
137 Status
= gBS
->OpenProtocol (
139 &gEfiSerialIoProtocolGuid
,
141 This
->DriverBindingHandle
,
143 EFI_OPEN_PROTOCOL_BY_DRIVER
145 if (Status
== EFI_ALREADY_STARTED
) {
149 if (EFI_ERROR (Status
)) {
153 // Close the I/O Abstraction(s) used to perform the supported test
157 &gEfiSerialIoProtocolGuid
,
158 This
->DriverBindingHandle
,
167 TerminalDriverBindingStart (
168 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
169 IN EFI_HANDLE Controller
,
170 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
176 Start the controller.
180 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
181 Controller - The handle of the controller to start.
182 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
191 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
192 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
193 VENDOR_DEVICE_PATH
*Node
;
194 VENDOR_DEVICE_PATH
*DefaultNode
;
195 EFI_SERIAL_IO_MODE
*Mode
;
196 UINTN SerialInTimeOut
;
197 TERMINAL_DEV
*TerminalDevice
;
199 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
202 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
204 TerminalDevice
= NULL
;
207 // Get the Device Path Protocol to build the device path of the child device
209 Status
= gBS
->OpenProtocol (
211 &gEfiDevicePathProtocolGuid
,
212 (VOID
**) &ParentDevicePath
,
213 This
->DriverBindingHandle
,
215 EFI_OPEN_PROTOCOL_BY_DRIVER
217 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
221 // Report that the remote terminal is being enabled
223 DevicePath
= ParentDevicePath
;
224 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
226 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_ENABLE
,
231 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
233 Status
= gBS
->OpenProtocol (
235 &gEfiSerialIoProtocolGuid
,
237 This
->DriverBindingHandle
,
239 EFI_OPEN_PROTOCOL_BY_DRIVER
241 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
245 if (Status
!= EFI_ALREADY_STARTED
) {
247 // If Serial I/O is not already open by this driver, then tag the handle
248 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
249 // StdErrDev variables with the list of possible terminal types on this
252 Status
= gBS
->OpenProtocol (
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
260 if (EFI_ERROR (Status
)) {
261 Status
= gBS
->InstallMultipleProtocolInterfaces (
264 DuplicateDevicePath (ParentDevicePath
),
267 if (EFI_ERROR (Status
)) {
271 // if the serial device is a hot plug device, do not update the
272 // ConInDev, ConOutDev, and StdErrDev variables.
274 Status
= gBS
->OpenProtocol (
276 &gEfiHotPlugDeviceGuid
,
278 This
->DriverBindingHandle
,
280 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
282 if (EFI_ERROR (Status
)) {
283 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
284 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
285 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
290 // Make sure a child handle does not already exist. This driver can only
291 // produce one child per serial port.
293 Status
= gBS
->OpenProtocolInformation (
295 &gEfiSerialIoProtocolGuid
,
299 if (!EFI_ERROR (Status
)) {
300 Status
= EFI_SUCCESS
;
301 for (Index
= 0; Index
< EntryCount
; Index
++) {
302 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
303 Status
= EFI_ALREADY_STARTED
;
307 gBS
->FreePool (OpenInfoBuffer
);
308 if (EFI_ERROR (Status
)) {
313 // If RemainingDevicePath is NULL, then create default device path node
315 if (RemainingDevicePath
== NULL
) {
316 DefaultNode
= AllocatePool (sizeof (VENDOR_DEVICE_PATH
));
317 if (DefaultNode
== NULL
) {
318 Status
= EFI_OUT_OF_RESOURCES
;
322 CopyMem (&DefaultNode
->Guid
, &gEfiPcAnsiGuid
, sizeof (EFI_GUID
));
323 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
326 // Use the RemainingDevicePath to determine the terminal type
328 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
330 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
332 TerminalType
= PcAnsiType
;
334 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
336 TerminalType
= VT100Type
;
338 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
340 TerminalType
= VT100PlusType
;
342 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
344 TerminalType
= VTUTF8Type
;
350 // Initialize the Terminal Dev
352 TerminalDevice
= AllocatePool (sizeof (TERMINAL_DEV
));
353 if (TerminalDevice
== NULL
) {
354 Status
= EFI_OUT_OF_RESOURCES
;
358 ZeroMem (TerminalDevice
, sizeof (TERMINAL_DEV
));
360 TerminalDevice
->Signature
= TERMINAL_DEV_SIGNATURE
;
362 TerminalDevice
->TerminalType
= TerminalType
;
364 TerminalDevice
->SerialIo
= SerialIo
;
367 // Simple Input Protocol
369 TerminalDevice
->SimpleInput
.Reset
= TerminalConInReset
;
370 TerminalDevice
->SimpleInput
.ReadKeyStroke
= TerminalConInReadKeyStroke
;
372 Status
= gBS
->CreateEvent (
373 EFI_EVENT_NOTIFY_WAIT
,
375 TerminalConInWaitForKey
,
376 &TerminalDevice
->SimpleInput
,
377 &TerminalDevice
->SimpleInput
.WaitForKey
379 if (EFI_ERROR (Status
)) {
383 // initialize the FIFO buffer used for accommodating
384 // the pre-read pending characters
386 InitializeRawFiFo (TerminalDevice
);
387 InitializeUnicodeFiFo (TerminalDevice
);
388 InitializeEfiKeyFiFo (TerminalDevice
);
391 // Set the timeout value of serial buffer for
392 // keystroke response performance issue
394 Mode
= TerminalDevice
->SerialIo
->Mode
;
397 if (Mode
->BaudRate
!= 0) {
398 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
401 Status
= TerminalDevice
->SerialIo
->SetAttributes (
402 TerminalDevice
->SerialIo
,
404 Mode
->ReceiveFifoDepth
,
405 (UINT32
) SerialInTimeOut
,
407 (UINT8
) Mode
->DataBits
,
410 if (EFI_ERROR (Status
)) {
412 // if set attributes operation fails, invalidate
413 // the value of SerialInTimeOut,thus make it
414 // inconsistent with the default timeout value
415 // of serial buffer. This will invoke the recalculation
416 // in the readkeystroke routine.
418 TerminalDevice
->SerialInTimeOut
= 0;
420 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
423 // Build the device path for the child device
425 Status
= SetTerminalDevicePath (
426 TerminalDevice
->TerminalType
,
428 &TerminalDevice
->DevicePath
430 if (EFI_ERROR (Status
)) {
434 DevicePath
= TerminalDevice
->DevicePath
;
436 Status
= TerminalDevice
->SimpleInput
.Reset (
437 &TerminalDevice
->SimpleInput
,
440 if (EFI_ERROR (Status
)) {
442 // Need to report Error Code first
447 // Simple Text Output Protocol
449 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
450 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
451 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
452 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
453 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
454 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
455 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
456 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
457 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
458 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
460 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 1;
462 // For terminal devices, cursor is always visible
464 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
465 TerminalDevice
->SimpleTextOutputMode
.Attribute
= EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
);
467 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
468 &TerminalDevice
->SimpleTextOutput
,
471 if (EFI_ERROR (Status
)) {
475 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
476 &TerminalDevice
->SimpleTextOutput
,
479 if (EFI_ERROR (Status
)) {
483 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
484 &TerminalDevice
->SimpleTextOutput
,
487 if (EFI_ERROR (Status
)) {
493 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
494 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
496 Status
= gBS
->CreateEvent (
501 &TerminalDevice
->TwoSecondTimeOut
505 // Build the component name for the child device
507 TerminalDevice
->ControllerNameTable
= NULL
;
508 switch (TerminalDevice
->TerminalType
) {
512 gTerminalComponentName
.SupportedLanguages
,
513 &TerminalDevice
->ControllerNameTable
,
514 (CHAR16
*)L
"PC-ANSI Serial Console"
521 gTerminalComponentName
.SupportedLanguages
,
522 &TerminalDevice
->ControllerNameTable
,
523 (CHAR16
*)L
"VT-100 Serial Console"
530 gTerminalComponentName
.SupportedLanguages
,
531 &TerminalDevice
->ControllerNameTable
,
532 (CHAR16
*)L
"VT-100+ Serial Console"
539 gTerminalComponentName
.SupportedLanguages
,
540 &TerminalDevice
->ControllerNameTable
,
541 (CHAR16
*)L
"VT-UTF8 Serial Console"
546 // Install protocol interfaces for the serial device.
548 Status
= gBS
->InstallMultipleProtocolInterfaces (
549 &TerminalDevice
->Handle
,
550 &gEfiDevicePathProtocolGuid
,
551 TerminalDevice
->DevicePath
,
552 &gEfiSimpleTextInProtocolGuid
,
553 &TerminalDevice
->SimpleInput
,
554 &gEfiSimpleTextOutProtocolGuid
,
555 &TerminalDevice
->SimpleTextOutput
,
558 if (EFI_ERROR (Status
)) {
562 // if the serial device is a hot plug device, attaches the HotPlugGuid
563 // onto the terminal device handle.
565 Status
= gBS
->OpenProtocol (
567 &gEfiHotPlugDeviceGuid
,
569 This
->DriverBindingHandle
,
571 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
573 if (!EFI_ERROR (Status
)) {
574 Status
= gBS
->InstallMultipleProtocolInterfaces (
575 &TerminalDevice
->Handle
,
576 &gEfiHotPlugDeviceGuid
,
582 // Register the Parent-Child relationship via
583 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
585 Status
= gBS
->OpenProtocol (
587 &gEfiSerialIoProtocolGuid
,
588 (VOID
**) &TerminalDevice
->SerialIo
,
589 This
->DriverBindingHandle
,
590 TerminalDevice
->Handle
,
591 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
593 if (EFI_ERROR (Status
)) {
597 if (DefaultNode
!= NULL
) {
598 gBS
->FreePool (DefaultNode
);
605 // Report error code before exiting
607 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
608 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
609 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
615 // Use the Stop() function to free all resources allocated in Start()
617 if (TerminalDevice
!= NULL
) {
619 if (TerminalDevice
->Handle
!= NULL
) {
620 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
623 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
624 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
627 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
628 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
631 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
632 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
635 if (TerminalDevice
->DevicePath
!= NULL
) {
636 gBS
->FreePool (TerminalDevice
->DevicePath
);
639 gBS
->FreePool (TerminalDevice
);
643 if (DefaultNode
!= NULL
) {
644 gBS
->FreePool (DefaultNode
);
647 This
->Stop (This
, Controller
, 0, NULL
);
654 TerminalDriverBindingStop (
655 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
656 IN EFI_HANDLE Controller
,
657 IN UINTN NumberOfChildren
,
658 IN EFI_HANDLE
*ChildHandleBuffer
664 Stop a device controller.
668 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
669 Controller - A handle to the device being stopped.
670 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
671 ChildHandleBuffer - An array of child handles to be freed.
675 EFI_SUCCESS - Operation successful.
676 EFI_DEVICE_ERROR - Devices error.
682 BOOLEAN AllChildrenStopped
;
683 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*SimpleTextOutput
;
684 TERMINAL_DEV
*TerminalDevice
;
685 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
686 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
687 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
689 Status
= gBS
->HandleProtocol (
691 &gEfiDevicePathProtocolGuid
,
692 (VOID
**) &DevicePath
694 if (EFI_ERROR (Status
)) {
698 // Report that the remote terminal is being disabled
700 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
702 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_DISABLE
,
707 // Complete all outstanding transactions to Controller.
708 // Don't allow any new transaction to Controller to be started.
710 if (NumberOfChildren
== 0) {
712 // Close the bus driver
714 Status
= gBS
->OpenProtocol (
717 (VOID
**) &ParentDevicePath
,
718 This
->DriverBindingHandle
,
720 EFI_OPEN_PROTOCOL_GET_PROTOCOL
722 if (!EFI_ERROR (Status
)) {
724 // Remove Parent Device Path from
725 // the Console Device Environment Variables
727 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
728 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
729 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
732 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
734 Status
= gBS
->UninstallMultipleProtocolInterfaces (
742 // Free the ParentDevicePath that was duplicated in Start()
744 if (!EFI_ERROR (Status
)) {
745 gBS
->FreePool (ParentDevicePath
);
751 &gEfiSerialIoProtocolGuid
,
752 This
->DriverBindingHandle
,
758 &gEfiDevicePathProtocolGuid
,
759 This
->DriverBindingHandle
,
766 AllChildrenStopped
= TRUE
;
768 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
770 Status
= gBS
->OpenProtocol (
771 ChildHandleBuffer
[Index
],
772 &gEfiSimpleTextOutProtocolGuid
,
773 (VOID
**) &SimpleTextOutput
,
774 This
->DriverBindingHandle
,
775 ChildHandleBuffer
[Index
],
776 EFI_OPEN_PROTOCOL_GET_PROTOCOL
778 if (!EFI_ERROR (Status
)) {
780 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
784 &gEfiSerialIoProtocolGuid
,
785 This
->DriverBindingHandle
,
786 ChildHandleBuffer
[Index
]
789 Status
= gBS
->UninstallMultipleProtocolInterfaces (
790 ChildHandleBuffer
[Index
],
791 &gEfiSimpleTextInProtocolGuid
,
792 &TerminalDevice
->SimpleInput
,
793 &gEfiSimpleTextOutProtocolGuid
,
794 &TerminalDevice
->SimpleTextOutput
,
795 &gEfiDevicePathProtocolGuid
,
796 TerminalDevice
->DevicePath
,
799 if (EFI_ERROR (Status
)) {
802 &gEfiSerialIoProtocolGuid
,
804 This
->DriverBindingHandle
,
805 ChildHandleBuffer
[Index
],
806 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
810 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
811 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
814 Status
= gBS
->OpenProtocol (
815 ChildHandleBuffer
[Index
],
816 &gEfiHotPlugDeviceGuid
,
818 This
->DriverBindingHandle
,
820 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
822 if (!EFI_ERROR (Status
)) {
823 Status
= gBS
->UninstallMultipleProtocolInterfaces (
824 ChildHandleBuffer
[Index
],
825 &gEfiHotPlugDeviceGuid
,
830 Status
= EFI_SUCCESS
;
833 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
834 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
835 gBS
->FreePool (TerminalDevice
->DevicePath
);
836 gBS
->FreePool (TerminalDevice
);
840 if (EFI_ERROR (Status
)) {
841 AllChildrenStopped
= FALSE
;
845 if (!AllChildrenStopped
) {
846 return EFI_DEVICE_ERROR
;
853 TerminalUpdateConsoleDevVariable (
854 IN CHAR16
*VariableName
,
855 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
861 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
862 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
863 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
868 // Get global variable and its size according to the name given.
870 Variable
= TerminalGetVariableAndSize (
872 &gEfiGlobalVariableGuid
,
876 // Append terminal device path onto the variable.
878 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
879 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
880 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
881 if (Variable
!= NULL
) {
882 gBS
->FreePool (Variable
);
885 if (TempDevicePath
!= NULL
) {
886 gBS
->FreePool (TempDevicePath
);
889 Variable
= NewVariable
;
892 VariableSize
= GetDevicePathSize (Variable
);
894 Status
= gRT
->SetVariable (
896 &gEfiGlobalVariableGuid
,
897 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
901 gBS
->FreePool (Variable
);
907 TerminalRemoveConsoleDevVariable (
908 IN CHAR16
*VariableName
,
909 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
915 Remove console device variable.
919 VariableName - A pointer to the variable name.
920 ParentDevicePath - A pointer to the parent device path.
932 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
933 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
934 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
935 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
936 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
937 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
943 // Get global variable and its size according to the name given.
945 Variable
= TerminalGetVariableAndSize (
947 &gEfiGlobalVariableGuid
,
950 if (Variable
== NULL
) {
955 OriginalVariable
= Variable
;
959 // Get first device path instance from Variable
961 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
962 if (Instance
== NULL
) {
963 gBS
->FreePool (OriginalVariable
);
967 // Loop through all the device path instances of Variable
971 // Loop through all the terminal types that this driver supports
974 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
976 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
979 // Compare the genterated device path to the current device path instance
981 if (TempDevicePath
!= NULL
) {
982 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
987 gBS
->FreePool (TempDevicePath
);
991 // If a match was not found, then keep the current device path instance
994 SavedNewVariable
= NewVariable
;
995 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
996 if (SavedNewVariable
!= NULL
) {
997 gBS
->FreePool (SavedNewVariable
);
1001 // Get next device path instance from Variable
1003 gBS
->FreePool (Instance
);
1004 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1005 } while (Instance
!= NULL
);
1007 gBS
->FreePool (OriginalVariable
);
1010 VariableSize
= GetDevicePathSize (NewVariable
);
1012 Status
= gRT
->SetVariable (
1014 &gEfiGlobalVariableGuid
,
1015 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1021 if (NewVariable
!= NULL
) {
1022 gBS
->FreePool (NewVariable
);
1029 TerminalGetVariableAndSize (
1031 IN EFI_GUID
*VendorGuid
,
1032 OUT UINTN
*VariableSize
1036 Routine Description:
1037 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1038 buffer, and the size of the buffer. On failure return NULL.
1041 Name - String part of EFI variable name
1043 VendorGuid - GUID part of EFI variable name
1045 VariableSize - Returns the size of the EFI variable that was read
1048 Dynamically allocated memory that contains a copy of the EFI variable.
1049 Caller is repsoncible freeing the buffer.
1051 NULL - Variable was not read
1062 // Pass in a small size buffer to find the actual variable size.
1065 Buffer
= AllocatePool (BufferSize
);
1066 if (Buffer
== NULL
) {
1071 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1073 if (Status
== EFI_SUCCESS
) {
1074 *VariableSize
= BufferSize
;
1077 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1079 // Allocate the buffer to return
1081 gBS
->FreePool (Buffer
);
1082 Buffer
= AllocatePool (BufferSize
);
1083 if (Buffer
== NULL
) {
1088 // Read variable into the allocated buffer.
1090 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1091 if (EFI_ERROR (Status
)) {
1093 gBS
->FreePool (Buffer
);
1098 // Variable not found or other errors met.
1101 gBS
->FreePool (Buffer
);
1105 *VariableSize
= BufferSize
;
1110 SetTerminalDevicePath (
1111 IN UINT8 TerminalType
,
1112 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1113 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1116 VENDOR_DEVICE_PATH Node
;
1118 *TerminalDevicePath
= NULL
;
1119 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1120 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1123 // generate terminal device path node according to terminal type.
1125 switch (TerminalType
) {
1160 return EFI_UNSUPPORTED
;
1164 SetDevicePathNodeLength (
1166 sizeof (VENDOR_DEVICE_PATH
)
1169 // append the terminal node onto parent device path
1170 // to generate a complete terminal device path.
1172 *TerminalDevicePath
= AppendDevicePathNode (
1174 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1176 if (*TerminalDevicePath
== NULL
) {
1177 return EFI_OUT_OF_RESOURCES
;
1185 IN TERMINAL_DEV
*TerminalDevice
1189 // Make the raw fifo empty.
1191 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1195 InitializeUnicodeFiFo (
1196 IN TERMINAL_DEV
*TerminalDevice
1200 // Make the unicode fifo empty
1202 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1206 InitializeEfiKeyFiFo (
1207 IN TERMINAL_DEV
*TerminalDevice
1211 // Make the efi key fifo empty
1213 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;