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.
28 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
29 TerminalDriverBindingSupported
,
30 TerminalDriverBindingStart
,
31 TerminalDriverBindingStop
,
40 TerminalDriverBindingSupported (
41 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
42 IN EFI_HANDLE Controller
,
43 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
47 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
48 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
49 VENDOR_DEVICE_PATH
*Node
;
52 // If remaining device path is not NULL, then make sure it is a
53 // device path that describes a terminal communications protocol.
55 if (RemainingDevicePath
!= NULL
) {
57 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
59 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
60 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
61 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
63 return EFI_UNSUPPORTED
;
67 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
69 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
70 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
71 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
72 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
74 return EFI_UNSUPPORTED
;
78 // Open the IO Abstraction(s) needed to perform the supported test
80 Status
= gBS
->OpenProtocol (
82 &gEfiDevicePathProtocolGuid
,
83 (VOID
**) &ParentDevicePath
,
84 This
->DriverBindingHandle
,
86 EFI_OPEN_PROTOCOL_BY_DRIVER
88 if (Status
== EFI_ALREADY_STARTED
) {
92 if (EFI_ERROR (Status
)) {
98 &gEfiDevicePathProtocolGuid
,
99 This
->DriverBindingHandle
,
104 // The Controller must support the Serial I/O Protocol.
105 // This driver is a bus driver with at most 1 child device, so it is
106 // ok for it to be already started.
108 Status
= gBS
->OpenProtocol (
110 &gEfiSerialIoProtocolGuid
,
112 This
->DriverBindingHandle
,
114 EFI_OPEN_PROTOCOL_BY_DRIVER
116 if (Status
== EFI_ALREADY_STARTED
) {
120 if (EFI_ERROR (Status
)) {
124 // Close the I/O Abstraction(s) used to perform the supported test
128 &gEfiSerialIoProtocolGuid
,
129 This
->DriverBindingHandle
,
138 TerminalDriverBindingStart (
139 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
140 IN EFI_HANDLE Controller
,
141 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
147 Start the controller.
151 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
152 Controller - The handle of the controller to start.
153 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
162 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
163 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
164 VENDOR_DEVICE_PATH
*Node
;
165 VENDOR_DEVICE_PATH
*DefaultNode
;
166 EFI_SERIAL_IO_MODE
*Mode
;
167 UINTN SerialInTimeOut
;
168 TERMINAL_DEV
*TerminalDevice
;
170 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
173 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
175 TerminalDevice
= NULL
;
178 // Get the Device Path Protocol to build the device path of the child device
180 Status
= gBS
->OpenProtocol (
182 &gEfiDevicePathProtocolGuid
,
183 (VOID
**) &ParentDevicePath
,
184 This
->DriverBindingHandle
,
186 EFI_OPEN_PROTOCOL_BY_DRIVER
188 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
192 // Report that the remote terminal is being enabled
194 DevicePath
= ParentDevicePath
;
195 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
197 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_ENABLE
,
202 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
204 Status
= gBS
->OpenProtocol (
206 &gEfiSerialIoProtocolGuid
,
208 This
->DriverBindingHandle
,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
212 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
216 if (Status
!= EFI_ALREADY_STARTED
) {
218 // If Serial I/O is not already open by this driver, then tag the handle
219 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
220 // StdErrDev variables with the list of possible terminal types on this
223 Status
= gBS
->OpenProtocol (
227 This
->DriverBindingHandle
,
229 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
231 if (EFI_ERROR (Status
)) {
232 Status
= gBS
->InstallMultipleProtocolInterfaces (
235 DuplicateDevicePath (ParentDevicePath
),
238 if (EFI_ERROR (Status
)) {
242 // if the serial device is a hot plug device, do not update the
243 // ConInDev, ConOutDev, and StdErrDev variables.
245 Status
= gBS
->OpenProtocol (
247 &gEfiHotPlugDeviceGuid
,
249 This
->DriverBindingHandle
,
251 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
253 if (EFI_ERROR (Status
)) {
254 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
255 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
256 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
261 // Make sure a child handle does not already exist. This driver can only
262 // produce one child per serial port.
264 Status
= gBS
->OpenProtocolInformation (
266 &gEfiSerialIoProtocolGuid
,
270 if (!EFI_ERROR (Status
)) {
271 Status
= EFI_SUCCESS
;
272 for (Index
= 0; Index
< EntryCount
; Index
++) {
273 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
274 Status
= EFI_ALREADY_STARTED
;
278 gBS
->FreePool (OpenInfoBuffer
);
279 if (EFI_ERROR (Status
)) {
284 // If RemainingDevicePath is NULL, then create default device path node
286 if (RemainingDevicePath
== NULL
) {
287 DefaultNode
= AllocatePool (sizeof (VENDOR_DEVICE_PATH
));
288 if (DefaultNode
== NULL
) {
289 Status
= EFI_OUT_OF_RESOURCES
;
293 CopyMem (&DefaultNode
->Guid
, &gEfiPcAnsiGuid
, sizeof (EFI_GUID
));
294 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
297 // Use the RemainingDevicePath to determine the terminal type
299 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
301 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
303 TerminalType
= PcAnsiType
;
305 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
307 TerminalType
= VT100Type
;
309 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
311 TerminalType
= VT100PlusType
;
313 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
315 TerminalType
= VTUTF8Type
;
321 // Initialize the Terminal Dev
323 TerminalDevice
= AllocatePool (sizeof (TERMINAL_DEV
));
324 if (TerminalDevice
== NULL
) {
325 Status
= EFI_OUT_OF_RESOURCES
;
329 ZeroMem (TerminalDevice
, sizeof (TERMINAL_DEV
));
331 TerminalDevice
->Signature
= TERMINAL_DEV_SIGNATURE
;
333 TerminalDevice
->TerminalType
= TerminalType
;
335 TerminalDevice
->SerialIo
= SerialIo
;
338 // Simple Input Protocol
340 TerminalDevice
->SimpleInput
.Reset
= TerminalConInReset
;
341 TerminalDevice
->SimpleInput
.ReadKeyStroke
= TerminalConInReadKeyStroke
;
343 Status
= gBS
->CreateEvent (
344 EFI_EVENT_NOTIFY_WAIT
,
346 TerminalConInWaitForKey
,
347 &TerminalDevice
->SimpleInput
,
348 &TerminalDevice
->SimpleInput
.WaitForKey
350 if (EFI_ERROR (Status
)) {
354 // initialize the FIFO buffer used for accommodating
355 // the pre-read pending characters
357 InitializeRawFiFo (TerminalDevice
);
358 InitializeUnicodeFiFo (TerminalDevice
);
359 InitializeEfiKeyFiFo (TerminalDevice
);
362 // Set the timeout value of serial buffer for
363 // keystroke response performance issue
365 Mode
= TerminalDevice
->SerialIo
->Mode
;
368 if (Mode
->BaudRate
!= 0) {
369 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
372 Status
= TerminalDevice
->SerialIo
->SetAttributes (
373 TerminalDevice
->SerialIo
,
375 Mode
->ReceiveFifoDepth
,
376 (UINT32
) SerialInTimeOut
,
377 (EFI_PARITY_TYPE
) (Mode
->Parity
),
378 (UINT8
) Mode
->DataBits
,
379 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
381 if (EFI_ERROR (Status
)) {
383 // if set attributes operation fails, invalidate
384 // the value of SerialInTimeOut,thus make it
385 // inconsistent with the default timeout value
386 // of serial buffer. This will invoke the recalculation
387 // in the readkeystroke routine.
389 TerminalDevice
->SerialInTimeOut
= 0;
391 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
394 // Build the device path for the child device
396 Status
= SetTerminalDevicePath (
397 TerminalDevice
->TerminalType
,
399 &TerminalDevice
->DevicePath
401 if (EFI_ERROR (Status
)) {
405 DevicePath
= TerminalDevice
->DevicePath
;
407 Status
= TerminalDevice
->SimpleInput
.Reset (
408 &TerminalDevice
->SimpleInput
,
411 if (EFI_ERROR (Status
)) {
413 // Need to report Error Code first
418 // Simple Text Output Protocol
420 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
421 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
422 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
423 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
424 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
425 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
426 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
427 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
428 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
429 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
431 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 1;
433 // For terminal devices, cursor is always visible
435 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
436 TerminalDevice
->SimpleTextOutputMode
.Attribute
= EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
);
438 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
439 &TerminalDevice
->SimpleTextOutput
,
442 if (EFI_ERROR (Status
)) {
446 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
447 &TerminalDevice
->SimpleTextOutput
,
450 if (EFI_ERROR (Status
)) {
454 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
455 &TerminalDevice
->SimpleTextOutput
,
458 if (EFI_ERROR (Status
)) {
464 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
465 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
467 Status
= gBS
->CreateEvent (
472 &TerminalDevice
->TwoSecondTimeOut
476 // Build the component name for the child device
478 TerminalDevice
->ControllerNameTable
= NULL
;
479 switch (TerminalDevice
->TerminalType
) {
483 gTerminalComponentName
.SupportedLanguages
,
484 &TerminalDevice
->ControllerNameTable
,
485 (CHAR16
*)L
"PC-ANSI Serial Console"
492 gTerminalComponentName
.SupportedLanguages
,
493 &TerminalDevice
->ControllerNameTable
,
494 (CHAR16
*)L
"VT-100 Serial Console"
501 gTerminalComponentName
.SupportedLanguages
,
502 &TerminalDevice
->ControllerNameTable
,
503 (CHAR16
*)L
"VT-100+ Serial Console"
510 gTerminalComponentName
.SupportedLanguages
,
511 &TerminalDevice
->ControllerNameTable
,
512 (CHAR16
*)L
"VT-UTF8 Serial Console"
517 // Install protocol interfaces for the serial device.
519 Status
= gBS
->InstallMultipleProtocolInterfaces (
520 &TerminalDevice
->Handle
,
521 &gEfiDevicePathProtocolGuid
,
522 TerminalDevice
->DevicePath
,
523 &gEfiSimpleTextInProtocolGuid
,
524 &TerminalDevice
->SimpleInput
,
525 &gEfiSimpleTextOutProtocolGuid
,
526 &TerminalDevice
->SimpleTextOutput
,
529 if (EFI_ERROR (Status
)) {
533 // if the serial device is a hot plug device, attaches the HotPlugGuid
534 // onto the terminal device handle.
536 Status
= gBS
->OpenProtocol (
538 &gEfiHotPlugDeviceGuid
,
540 This
->DriverBindingHandle
,
542 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
544 if (!EFI_ERROR (Status
)) {
545 Status
= gBS
->InstallMultipleProtocolInterfaces (
546 &TerminalDevice
->Handle
,
547 &gEfiHotPlugDeviceGuid
,
553 // Register the Parent-Child relationship via
554 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
556 Status
= gBS
->OpenProtocol (
558 &gEfiSerialIoProtocolGuid
,
559 (VOID
**) &TerminalDevice
->SerialIo
,
560 This
->DriverBindingHandle
,
561 TerminalDevice
->Handle
,
562 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
564 if (EFI_ERROR (Status
)) {
568 if (DefaultNode
!= NULL
) {
569 gBS
->FreePool (DefaultNode
);
576 // Report error code before exiting
578 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
579 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
580 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
586 // Use the Stop() function to free all resources allocated in Start()
588 if (TerminalDevice
!= NULL
) {
590 if (TerminalDevice
->Handle
!= NULL
) {
591 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
594 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
595 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
598 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
599 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
602 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
603 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
606 if (TerminalDevice
->DevicePath
!= NULL
) {
607 gBS
->FreePool (TerminalDevice
->DevicePath
);
610 gBS
->FreePool (TerminalDevice
);
614 if (DefaultNode
!= NULL
) {
615 gBS
->FreePool (DefaultNode
);
618 This
->Stop (This
, Controller
, 0, NULL
);
625 TerminalDriverBindingStop (
626 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
627 IN EFI_HANDLE Controller
,
628 IN UINTN NumberOfChildren
,
629 IN EFI_HANDLE
*ChildHandleBuffer
635 Stop a device controller.
639 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
640 Controller - A handle to the device being stopped.
641 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
642 ChildHandleBuffer - An array of child handles to be freed.
646 EFI_SUCCESS - Operation successful.
647 EFI_DEVICE_ERROR - Devices error.
653 BOOLEAN AllChildrenStopped
;
654 EFI_SIMPLE_TEXT_OUT_PROTOCOL
*SimpleTextOutput
;
655 TERMINAL_DEV
*TerminalDevice
;
656 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
657 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
658 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
660 Status
= gBS
->HandleProtocol (
662 &gEfiDevicePathProtocolGuid
,
663 (VOID
**) &DevicePath
665 if (EFI_ERROR (Status
)) {
669 // Report that the remote terminal is being disabled
671 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
673 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_DISABLE
,
678 // Complete all outstanding transactions to Controller.
679 // Don't allow any new transaction to Controller to be started.
681 if (NumberOfChildren
== 0) {
683 // Close the bus driver
685 Status
= gBS
->OpenProtocol (
688 (VOID
**) &ParentDevicePath
,
689 This
->DriverBindingHandle
,
691 EFI_OPEN_PROTOCOL_GET_PROTOCOL
693 if (!EFI_ERROR (Status
)) {
695 // Remove Parent Device Path from
696 // the Console Device Environment Variables
698 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
699 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
700 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
703 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
705 Status
= gBS
->UninstallMultipleProtocolInterfaces (
713 // Free the ParentDevicePath that was duplicated in Start()
715 if (!EFI_ERROR (Status
)) {
716 gBS
->FreePool (ParentDevicePath
);
722 &gEfiSerialIoProtocolGuid
,
723 This
->DriverBindingHandle
,
729 &gEfiDevicePathProtocolGuid
,
730 This
->DriverBindingHandle
,
737 AllChildrenStopped
= TRUE
;
739 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
741 Status
= gBS
->OpenProtocol (
742 ChildHandleBuffer
[Index
],
743 &gEfiSimpleTextOutProtocolGuid
,
744 (VOID
**) &SimpleTextOutput
,
745 This
->DriverBindingHandle
,
746 ChildHandleBuffer
[Index
],
747 EFI_OPEN_PROTOCOL_GET_PROTOCOL
749 if (!EFI_ERROR (Status
)) {
751 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
755 &gEfiSerialIoProtocolGuid
,
756 This
->DriverBindingHandle
,
757 ChildHandleBuffer
[Index
]
760 Status
= gBS
->UninstallMultipleProtocolInterfaces (
761 ChildHandleBuffer
[Index
],
762 &gEfiSimpleTextInProtocolGuid
,
763 &TerminalDevice
->SimpleInput
,
764 &gEfiSimpleTextOutProtocolGuid
,
765 &TerminalDevice
->SimpleTextOutput
,
766 &gEfiDevicePathProtocolGuid
,
767 TerminalDevice
->DevicePath
,
770 if (EFI_ERROR (Status
)) {
773 &gEfiSerialIoProtocolGuid
,
775 This
->DriverBindingHandle
,
776 ChildHandleBuffer
[Index
],
777 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
781 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
782 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
785 Status
= gBS
->OpenProtocol (
786 ChildHandleBuffer
[Index
],
787 &gEfiHotPlugDeviceGuid
,
789 This
->DriverBindingHandle
,
791 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
793 if (!EFI_ERROR (Status
)) {
794 Status
= gBS
->UninstallMultipleProtocolInterfaces (
795 ChildHandleBuffer
[Index
],
796 &gEfiHotPlugDeviceGuid
,
801 Status
= EFI_SUCCESS
;
804 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
805 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
806 gBS
->FreePool (TerminalDevice
->DevicePath
);
807 gBS
->FreePool (TerminalDevice
);
811 if (EFI_ERROR (Status
)) {
812 AllChildrenStopped
= FALSE
;
816 if (!AllChildrenStopped
) {
817 return EFI_DEVICE_ERROR
;
824 TerminalUpdateConsoleDevVariable (
825 IN CHAR16
*VariableName
,
826 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
832 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
833 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
834 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
839 // Get global variable and its size according to the name given.
841 Variable
= TerminalGetVariableAndSize (
843 &gEfiGlobalVariableGuid
,
847 // Append terminal device path onto the variable.
849 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
850 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
851 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
852 if (Variable
!= NULL
) {
853 gBS
->FreePool (Variable
);
856 if (TempDevicePath
!= NULL
) {
857 gBS
->FreePool (TempDevicePath
);
860 Variable
= NewVariable
;
863 VariableSize
= GetDevicePathSize (Variable
);
865 Status
= gRT
->SetVariable (
867 &gEfiGlobalVariableGuid
,
868 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
872 ASSERT_EFI_ERROR (Status
);
873 gBS
->FreePool (Variable
);
879 TerminalRemoveConsoleDevVariable (
880 IN CHAR16
*VariableName
,
881 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
887 Remove console device variable.
891 VariableName - A pointer to the variable name.
892 ParentDevicePath - A pointer to the parent device path.
904 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
905 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
906 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
907 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
908 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
909 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
915 // Get global variable and its size according to the name given.
917 Variable
= TerminalGetVariableAndSize (
919 &gEfiGlobalVariableGuid
,
922 if (Variable
== NULL
) {
927 OriginalVariable
= Variable
;
931 // Get first device path instance from Variable
933 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
934 if (Instance
== NULL
) {
935 gBS
->FreePool (OriginalVariable
);
939 // Loop through all the device path instances of Variable
943 // Loop through all the terminal types that this driver supports
946 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
948 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
951 // Compare the genterated device path to the current device path instance
953 if (TempDevicePath
!= NULL
) {
954 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
959 gBS
->FreePool (TempDevicePath
);
963 // If a match was not found, then keep the current device path instance
966 SavedNewVariable
= NewVariable
;
967 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
968 if (SavedNewVariable
!= NULL
) {
969 gBS
->FreePool (SavedNewVariable
);
973 // Get next device path instance from Variable
975 gBS
->FreePool (Instance
);
976 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
977 } while (Instance
!= NULL
);
979 gBS
->FreePool (OriginalVariable
);
982 VariableSize
= GetDevicePathSize (NewVariable
);
984 Status
= gRT
->SetVariable (
986 &gEfiGlobalVariableGuid
,
987 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
991 ASSERT_EFI_ERROR (Status
);
994 if (NewVariable
!= NULL
) {
995 gBS
->FreePool (NewVariable
);
1002 TerminalGetVariableAndSize (
1004 IN EFI_GUID
*VendorGuid
,
1005 OUT UINTN
*VariableSize
1009 Routine Description:
1010 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1011 buffer, and the size of the buffer. On failure return NULL.
1014 Name - String part of EFI variable name
1016 VendorGuid - GUID part of EFI variable name
1018 VariableSize - Returns the size of the EFI variable that was read
1021 Dynamically allocated memory that contains a copy of the EFI variable.
1022 Caller is repsoncible freeing the buffer.
1024 NULL - Variable was not read
1035 // Pass in a small size buffer to find the actual variable size.
1038 Buffer
= AllocatePool (BufferSize
);
1039 if (Buffer
== NULL
) {
1044 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1046 if (Status
== EFI_SUCCESS
) {
1047 *VariableSize
= BufferSize
;
1050 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1052 // Allocate the buffer to return
1054 gBS
->FreePool (Buffer
);
1055 Buffer
= AllocatePool (BufferSize
);
1056 if (Buffer
== NULL
) {
1061 // Read variable into the allocated buffer.
1063 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1064 if (EFI_ERROR (Status
)) {
1066 gBS
->FreePool (Buffer
);
1071 // Variable not found or other errors met.
1074 gBS
->FreePool (Buffer
);
1078 *VariableSize
= BufferSize
;
1083 SetTerminalDevicePath (
1084 IN UINT8 TerminalType
,
1085 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1086 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1089 VENDOR_DEVICE_PATH Node
;
1091 *TerminalDevicePath
= NULL
;
1092 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1093 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1096 // generate terminal device path node according to terminal type.
1098 switch (TerminalType
) {
1133 return EFI_UNSUPPORTED
;
1137 SetDevicePathNodeLength (
1139 sizeof (VENDOR_DEVICE_PATH
)
1142 // append the terminal node onto parent device path
1143 // to generate a complete terminal device path.
1145 *TerminalDevicePath
= AppendDevicePathNode (
1147 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1149 if (*TerminalDevicePath
== NULL
) {
1150 return EFI_OUT_OF_RESOURCES
;
1158 IN TERMINAL_DEV
*TerminalDevice
1162 // Make the raw fifo empty.
1164 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1168 InitializeUnicodeFiFo (
1169 IN TERMINAL_DEV
*TerminalDevice
1173 // Make the unicode fifo empty
1175 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1179 InitializeEfiKeyFiFo (
1180 IN TERMINAL_DEV
*TerminalDevice
1184 // Make the efi key fifo empty
1186 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;