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.
26 // Function Prototypes
30 TerminalDriverBindingSupported (
31 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
32 IN EFI_HANDLE Controller
,
33 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
38 TerminalDriverBindingStart (
39 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
40 IN EFI_HANDLE Controller
,
41 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
46 TerminalDriverBindingStop (
47 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
48 IN EFI_HANDLE Controller
,
49 IN UINTN NumberOfChildren
,
50 IN EFI_HANDLE
*ChildHandleBuffer
56 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
57 TerminalDriverBindingSupported
,
58 TerminalDriverBindingStart
,
59 TerminalDriverBindingStop
,
68 TerminalDriverBindingSupported (
69 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
70 IN EFI_HANDLE Controller
,
71 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
75 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
76 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
77 VENDOR_DEVICE_PATH
*Node
;
80 // If remaining device path is not NULL, then make sure it is a
81 // device path that describes a terminal communications protocol.
83 if (RemainingDevicePath
!= NULL
) {
85 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
87 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
88 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
89 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
91 return EFI_UNSUPPORTED
;
95 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
97 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
98 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
99 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
100 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
102 return EFI_UNSUPPORTED
;
106 // Open the IO Abstraction(s) needed to perform the supported test
108 Status
= gBS
->OpenProtocol (
110 &gEfiDevicePathProtocolGuid
,
111 (VOID
**) &ParentDevicePath
,
112 This
->DriverBindingHandle
,
114 EFI_OPEN_PROTOCOL_BY_DRIVER
116 if (Status
== EFI_ALREADY_STARTED
) {
120 if (EFI_ERROR (Status
)) {
126 &gEfiDevicePathProtocolGuid
,
127 This
->DriverBindingHandle
,
132 // The Controller must support the Serial I/O Protocol.
133 // This driver is a bus driver with at most 1 child device, so it is
134 // ok for it to be already started.
136 Status
= gBS
->OpenProtocol (
138 &gEfiSerialIoProtocolGuid
,
140 This
->DriverBindingHandle
,
142 EFI_OPEN_PROTOCOL_BY_DRIVER
144 if (Status
== EFI_ALREADY_STARTED
) {
148 if (EFI_ERROR (Status
)) {
152 // Close the I/O Abstraction(s) used to perform the supported test
156 &gEfiSerialIoProtocolGuid
,
157 This
->DriverBindingHandle
,
166 TerminalDriverBindingStart (
167 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
168 IN EFI_HANDLE Controller
,
169 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
175 Start the controller.
179 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
180 Controller - The handle of the controller to start.
181 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
190 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
191 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
192 VENDOR_DEVICE_PATH
*Node
;
193 VENDOR_DEVICE_PATH
*DefaultNode
;
194 EFI_SERIAL_IO_MODE
*Mode
;
195 UINTN SerialInTimeOut
;
196 TERMINAL_DEV
*TerminalDevice
;
198 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
201 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
203 TerminalDevice
= NULL
;
206 // Get the Device Path Protocol to build the device path of the child device
208 Status
= gBS
->OpenProtocol (
210 &gEfiDevicePathProtocolGuid
,
211 (VOID
**) &ParentDevicePath
,
212 This
->DriverBindingHandle
,
214 EFI_OPEN_PROTOCOL_BY_DRIVER
216 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
220 // Report that the remote terminal is being enabled
222 DevicePath
= ParentDevicePath
;
223 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
225 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_ENABLE
,
230 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
232 Status
= gBS
->OpenProtocol (
234 &gEfiSerialIoProtocolGuid
,
236 This
->DriverBindingHandle
,
238 EFI_OPEN_PROTOCOL_BY_DRIVER
240 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
244 if (Status
!= EFI_ALREADY_STARTED
) {
246 // If Serial I/O is not already open by this driver, then tag the handle
247 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
248 // StdErrDev variables with the list of possible terminal types on this
251 Status
= gBS
->OpenProtocol (
255 This
->DriverBindingHandle
,
257 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
259 if (EFI_ERROR (Status
)) {
260 Status
= gBS
->InstallMultipleProtocolInterfaces (
263 DuplicateDevicePath (ParentDevicePath
),
266 if (EFI_ERROR (Status
)) {
270 // if the serial device is a hot plug device, do not update the
271 // ConInDev, ConOutDev, and StdErrDev variables.
273 Status
= gBS
->OpenProtocol (
275 &gEfiHotPlugDeviceGuid
,
277 This
->DriverBindingHandle
,
279 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
281 if (EFI_ERROR (Status
)) {
282 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
283 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
284 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
289 // Make sure a child handle does not already exist. This driver can only
290 // produce one child per serial port.
292 Status
= gBS
->OpenProtocolInformation (
294 &gEfiSerialIoProtocolGuid
,
298 if (!EFI_ERROR (Status
)) {
299 Status
= EFI_SUCCESS
;
300 for (Index
= 0; Index
< EntryCount
; Index
++) {
301 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
302 Status
= EFI_ALREADY_STARTED
;
306 gBS
->FreePool (OpenInfoBuffer
);
307 if (EFI_ERROR (Status
)) {
312 // If RemainingDevicePath is NULL, then create default device path node
314 if (RemainingDevicePath
== NULL
) {
315 DefaultNode
= AllocatePool (sizeof (VENDOR_DEVICE_PATH
));
316 if (DefaultNode
== NULL
) {
317 Status
= EFI_OUT_OF_RESOURCES
;
321 CopyMem (&DefaultNode
->Guid
, &gEfiPcAnsiGuid
, sizeof (EFI_GUID
));
322 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
325 // Use the RemainingDevicePath to determine the terminal type
327 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
329 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
331 TerminalType
= PcAnsiType
;
333 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
335 TerminalType
= VT100Type
;
337 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
339 TerminalType
= VT100PlusType
;
341 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
343 TerminalType
= VTUTF8Type
;
349 // Initialize the Terminal Dev
351 TerminalDevice
= AllocatePool (sizeof (TERMINAL_DEV
));
352 if (TerminalDevice
== NULL
) {
353 Status
= EFI_OUT_OF_RESOURCES
;
357 ZeroMem (TerminalDevice
, sizeof (TERMINAL_DEV
));
359 TerminalDevice
->Signature
= TERMINAL_DEV_SIGNATURE
;
361 TerminalDevice
->TerminalType
= TerminalType
;
363 TerminalDevice
->SerialIo
= SerialIo
;
366 // Simple Input Protocol
368 TerminalDevice
->SimpleInput
.Reset
= TerminalConInReset
;
369 TerminalDevice
->SimpleInput
.ReadKeyStroke
= TerminalConInReadKeyStroke
;
371 Status
= gBS
->CreateEvent (
372 EFI_EVENT_NOTIFY_WAIT
,
374 TerminalConInWaitForKey
,
375 &TerminalDevice
->SimpleInput
,
376 &TerminalDevice
->SimpleInput
.WaitForKey
378 if (EFI_ERROR (Status
)) {
382 // initialize the FIFO buffer used for accommodating
383 // the pre-read pending characters
385 InitializeRawFiFo (TerminalDevice
);
386 InitializeUnicodeFiFo (TerminalDevice
);
387 InitializeEfiKeyFiFo (TerminalDevice
);
390 // Set the timeout value of serial buffer for
391 // keystroke response performance issue
393 Mode
= TerminalDevice
->SerialIo
->Mode
;
396 if (Mode
->BaudRate
!= 0) {
397 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
400 Status
= TerminalDevice
->SerialIo
->SetAttributes (
401 TerminalDevice
->SerialIo
,
403 Mode
->ReceiveFifoDepth
,
404 (UINT32
) SerialInTimeOut
,
406 (UINT8
) Mode
->DataBits
,
409 if (EFI_ERROR (Status
)) {
411 // if set attributes operation fails, invalidate
412 // the value of SerialInTimeOut,thus make it
413 // inconsistent with the default timeout value
414 // of serial buffer. This will invoke the recalculation
415 // in the readkeystroke routine.
417 TerminalDevice
->SerialInTimeOut
= 0;
419 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
422 // Build the device path for the child device
424 Status
= SetTerminalDevicePath (
425 TerminalDevice
->TerminalType
,
427 &TerminalDevice
->DevicePath
429 if (EFI_ERROR (Status
)) {
433 DevicePath
= TerminalDevice
->DevicePath
;
435 Status
= TerminalDevice
->SimpleInput
.Reset (
436 &TerminalDevice
->SimpleInput
,
439 if (EFI_ERROR (Status
)) {
441 // Need to report Error Code first
446 // Simple Text Output Protocol
448 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
449 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
450 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
451 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
452 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
453 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
454 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
455 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
456 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
457 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
459 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 1;
461 // For terminal devices, cursor is always visible
463 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
464 TerminalDevice
->SimpleTextOutputMode
.Attribute
= EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
);
466 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
467 &TerminalDevice
->SimpleTextOutput
,
470 if (EFI_ERROR (Status
)) {
474 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
475 &TerminalDevice
->SimpleTextOutput
,
478 if (EFI_ERROR (Status
)) {
482 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
483 &TerminalDevice
->SimpleTextOutput
,
486 if (EFI_ERROR (Status
)) {
492 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
493 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
495 Status
= gBS
->CreateEvent (
500 &TerminalDevice
->TwoSecondTimeOut
504 // Build the component name for the child device
506 TerminalDevice
->ControllerNameTable
= NULL
;
507 switch (TerminalDevice
->TerminalType
) {
511 gTerminalComponentName
.SupportedLanguages
,
512 &TerminalDevice
->ControllerNameTable
,
513 (CHAR16
*)L
"PC-ANSI Serial Console"
520 gTerminalComponentName
.SupportedLanguages
,
521 &TerminalDevice
->ControllerNameTable
,
522 (CHAR16
*)L
"VT-100 Serial Console"
529 gTerminalComponentName
.SupportedLanguages
,
530 &TerminalDevice
->ControllerNameTable
,
531 (CHAR16
*)L
"VT-100+ Serial Console"
538 gTerminalComponentName
.SupportedLanguages
,
539 &TerminalDevice
->ControllerNameTable
,
540 (CHAR16
*)L
"VT-UTF8 Serial Console"
545 // Install protocol interfaces for the serial device.
547 Status
= gBS
->InstallMultipleProtocolInterfaces (
548 &TerminalDevice
->Handle
,
549 &gEfiDevicePathProtocolGuid
,
550 TerminalDevice
->DevicePath
,
551 &gEfiSimpleTextInProtocolGuid
,
552 &TerminalDevice
->SimpleInput
,
553 &gEfiSimpleTextOutProtocolGuid
,
554 &TerminalDevice
->SimpleTextOutput
,
557 if (EFI_ERROR (Status
)) {
561 // if the serial device is a hot plug device, attaches the HotPlugGuid
562 // onto the terminal device handle.
564 Status
= gBS
->OpenProtocol (
566 &gEfiHotPlugDeviceGuid
,
568 This
->DriverBindingHandle
,
570 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
572 if (!EFI_ERROR (Status
)) {
573 Status
= gBS
->InstallMultipleProtocolInterfaces (
574 &TerminalDevice
->Handle
,
575 &gEfiHotPlugDeviceGuid
,
581 // Register the Parent-Child relationship via
582 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
584 Status
= gBS
->OpenProtocol (
586 &gEfiSerialIoProtocolGuid
,
587 (VOID
**) &TerminalDevice
->SerialIo
,
588 This
->DriverBindingHandle
,
589 TerminalDevice
->Handle
,
590 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
592 if (EFI_ERROR (Status
)) {
596 if (DefaultNode
!= NULL
) {
597 gBS
->FreePool (DefaultNode
);
604 // Report error code before exiting
606 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
607 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
608 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
614 // Use the Stop() function to free all resources allocated in Start()
616 if (TerminalDevice
!= NULL
) {
618 if (TerminalDevice
->Handle
!= NULL
) {
619 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
622 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
623 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
626 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
627 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
630 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
631 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
634 if (TerminalDevice
->DevicePath
!= NULL
) {
635 gBS
->FreePool (TerminalDevice
->DevicePath
);
638 gBS
->FreePool (TerminalDevice
);
642 if (DefaultNode
!= NULL
) {
643 gBS
->FreePool (DefaultNode
);
646 This
->Stop (This
, Controller
, 0, NULL
);
653 TerminalDriverBindingStop (
654 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
655 IN EFI_HANDLE Controller
,
656 IN UINTN NumberOfChildren
,
657 IN EFI_HANDLE
*ChildHandleBuffer
663 Stop a device controller.
667 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
668 Controller - A handle to the device being stopped.
669 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
670 ChildHandleBuffer - An array of child handles to be freed.
674 EFI_SUCCESS - Operation successful.
675 EFI_DEVICE_ERROR - Devices error.
681 BOOLEAN AllChildrenStopped
;
682 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*SimpleTextOutput
;
683 TERMINAL_DEV
*TerminalDevice
;
684 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
685 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
686 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
688 Status
= gBS
->HandleProtocol (
690 &gEfiDevicePathProtocolGuid
,
691 (VOID
**) &DevicePath
693 if (EFI_ERROR (Status
)) {
697 // Report that the remote terminal is being disabled
699 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
701 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_DISABLE
,
706 // Complete all outstanding transactions to Controller.
707 // Don't allow any new transaction to Controller to be started.
709 if (NumberOfChildren
== 0) {
711 // Close the bus driver
713 Status
= gBS
->OpenProtocol (
716 (VOID
**) &ParentDevicePath
,
717 This
->DriverBindingHandle
,
719 EFI_OPEN_PROTOCOL_GET_PROTOCOL
721 if (!EFI_ERROR (Status
)) {
723 // Remove Parent Device Path from
724 // the Console Device Environment Variables
726 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
727 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
728 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
731 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
733 Status
= gBS
->UninstallMultipleProtocolInterfaces (
741 // Free the ParentDevicePath that was duplicated in Start()
743 if (!EFI_ERROR (Status
)) {
744 gBS
->FreePool (ParentDevicePath
);
750 &gEfiSerialIoProtocolGuid
,
751 This
->DriverBindingHandle
,
757 &gEfiDevicePathProtocolGuid
,
758 This
->DriverBindingHandle
,
765 AllChildrenStopped
= TRUE
;
767 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
769 Status
= gBS
->OpenProtocol (
770 ChildHandleBuffer
[Index
],
771 &gEfiSimpleTextOutProtocolGuid
,
772 (VOID
**) &SimpleTextOutput
,
773 This
->DriverBindingHandle
,
774 ChildHandleBuffer
[Index
],
775 EFI_OPEN_PROTOCOL_GET_PROTOCOL
777 if (!EFI_ERROR (Status
)) {
779 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
783 &gEfiSerialIoProtocolGuid
,
784 This
->DriverBindingHandle
,
785 ChildHandleBuffer
[Index
]
788 Status
= gBS
->UninstallMultipleProtocolInterfaces (
789 ChildHandleBuffer
[Index
],
790 &gEfiSimpleTextInProtocolGuid
,
791 &TerminalDevice
->SimpleInput
,
792 &gEfiSimpleTextOutProtocolGuid
,
793 &TerminalDevice
->SimpleTextOutput
,
794 &gEfiDevicePathProtocolGuid
,
795 TerminalDevice
->DevicePath
,
798 if (EFI_ERROR (Status
)) {
801 &gEfiSerialIoProtocolGuid
,
803 This
->DriverBindingHandle
,
804 ChildHandleBuffer
[Index
],
805 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
809 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
810 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
813 Status
= gBS
->OpenProtocol (
814 ChildHandleBuffer
[Index
],
815 &gEfiHotPlugDeviceGuid
,
817 This
->DriverBindingHandle
,
819 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
821 if (!EFI_ERROR (Status
)) {
822 Status
= gBS
->UninstallMultipleProtocolInterfaces (
823 ChildHandleBuffer
[Index
],
824 &gEfiHotPlugDeviceGuid
,
829 Status
= EFI_SUCCESS
;
832 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
833 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
834 gBS
->FreePool (TerminalDevice
->DevicePath
);
835 gBS
->FreePool (TerminalDevice
);
839 if (EFI_ERROR (Status
)) {
840 AllChildrenStopped
= FALSE
;
844 if (!AllChildrenStopped
) {
845 return EFI_DEVICE_ERROR
;
852 TerminalUpdateConsoleDevVariable (
853 IN CHAR16
*VariableName
,
854 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
860 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
861 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
862 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
867 // Get global variable and its size according to the name given.
869 Variable
= TerminalGetVariableAndSize (
871 &gEfiGlobalVariableGuid
,
875 // Append terminal device path onto the variable.
877 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
878 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
879 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
880 if (Variable
!= NULL
) {
881 gBS
->FreePool (Variable
);
884 if (TempDevicePath
!= NULL
) {
885 gBS
->FreePool (TempDevicePath
);
888 Variable
= NewVariable
;
891 VariableSize
= GetDevicePathSize (Variable
);
893 Status
= gRT
->SetVariable (
895 &gEfiGlobalVariableGuid
,
896 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
900 gBS
->FreePool (Variable
);
906 TerminalRemoveConsoleDevVariable (
907 IN CHAR16
*VariableName
,
908 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
914 Remove console device variable.
918 VariableName - A pointer to the variable name.
919 ParentDevicePath - A pointer to the parent device path.
931 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
932 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
933 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
934 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
935 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
936 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
942 // Get global variable and its size according to the name given.
944 Variable
= TerminalGetVariableAndSize (
946 &gEfiGlobalVariableGuid
,
949 if (Variable
== NULL
) {
954 OriginalVariable
= Variable
;
958 // Get first device path instance from Variable
960 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
961 if (Instance
== NULL
) {
962 gBS
->FreePool (OriginalVariable
);
966 // Loop through all the device path instances of Variable
970 // Loop through all the terminal types that this driver supports
973 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
975 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
978 // Compare the genterated device path to the current device path instance
980 if (TempDevicePath
!= NULL
) {
981 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
986 gBS
->FreePool (TempDevicePath
);
990 // If a match was not found, then keep the current device path instance
993 SavedNewVariable
= NewVariable
;
994 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
995 if (SavedNewVariable
!= NULL
) {
996 gBS
->FreePool (SavedNewVariable
);
1000 // Get next device path instance from Variable
1002 gBS
->FreePool (Instance
);
1003 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1004 } while (Instance
!= NULL
);
1006 gBS
->FreePool (OriginalVariable
);
1009 VariableSize
= GetDevicePathSize (NewVariable
);
1011 Status
= gRT
->SetVariable (
1013 &gEfiGlobalVariableGuid
,
1014 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1020 if (NewVariable
!= NULL
) {
1021 gBS
->FreePool (NewVariable
);
1028 TerminalGetVariableAndSize (
1030 IN EFI_GUID
*VendorGuid
,
1031 OUT UINTN
*VariableSize
1035 Routine Description:
1036 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1037 buffer, and the size of the buffer. On failure return NULL.
1040 Name - String part of EFI variable name
1042 VendorGuid - GUID part of EFI variable name
1044 VariableSize - Returns the size of the EFI variable that was read
1047 Dynamically allocated memory that contains a copy of the EFI variable.
1048 Caller is repsoncible freeing the buffer.
1050 NULL - Variable was not read
1061 // Pass in a small size buffer to find the actual variable size.
1064 Buffer
= AllocatePool (BufferSize
);
1065 if (Buffer
== NULL
) {
1070 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1072 if (Status
== EFI_SUCCESS
) {
1073 *VariableSize
= BufferSize
;
1076 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1078 // Allocate the buffer to return
1080 gBS
->FreePool (Buffer
);
1081 Buffer
= AllocatePool (BufferSize
);
1082 if (Buffer
== NULL
) {
1087 // Read variable into the allocated buffer.
1089 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1090 if (EFI_ERROR (Status
)) {
1092 gBS
->FreePool (Buffer
);
1097 // Variable not found or other errors met.
1100 gBS
->FreePool (Buffer
);
1104 *VariableSize
= BufferSize
;
1109 SetTerminalDevicePath (
1110 IN UINT8 TerminalType
,
1111 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1112 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1115 VENDOR_DEVICE_PATH Node
;
1117 *TerminalDevicePath
= NULL
;
1118 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1119 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1122 // generate terminal device path node according to terminal type.
1124 switch (TerminalType
) {
1159 return EFI_UNSUPPORTED
;
1163 SetDevicePathNodeLength (
1165 sizeof (VENDOR_DEVICE_PATH
)
1168 // append the terminal node onto parent device path
1169 // to generate a complete terminal device path.
1171 *TerminalDevicePath
= AppendDevicePathNode (
1173 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1175 if (*TerminalDevicePath
== NULL
) {
1176 return EFI_OUT_OF_RESOURCES
;
1184 IN TERMINAL_DEV
*TerminalDevice
1188 // Make the raw fifo empty.
1190 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1194 InitializeUnicodeFiFo (
1195 IN TERMINAL_DEV
*TerminalDevice
1199 // Make the unicode fifo empty
1201 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1205 InitializeEfiKeyFiFo (
1206 IN TERMINAL_DEV
*TerminalDevice
1210 // Make the efi key fifo empty
1212 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;