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.
29 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
30 TerminalDriverBindingSupported
,
31 TerminalDriverBindingStart
,
32 TerminalDriverBindingStop
,
41 TerminalDriverBindingSupported (
42 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
43 IN EFI_HANDLE Controller
,
44 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
48 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
49 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
50 VENDOR_DEVICE_PATH
*Node
;
53 // If remaining device path is not NULL, then make sure it is a
54 // device path that describes a terminal communications protocol.
56 if (RemainingDevicePath
!= NULL
) {
58 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
60 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
61 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
62 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
64 return EFI_UNSUPPORTED
;
68 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
70 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
71 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
72 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
73 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
75 return EFI_UNSUPPORTED
;
79 // Open the IO Abstraction(s) needed to perform the supported test
81 Status
= gBS
->OpenProtocol (
83 &gEfiDevicePathProtocolGuid
,
84 (VOID
**) &ParentDevicePath
,
85 This
->DriverBindingHandle
,
87 EFI_OPEN_PROTOCOL_BY_DRIVER
89 if (Status
== EFI_ALREADY_STARTED
) {
93 if (EFI_ERROR (Status
)) {
99 &gEfiDevicePathProtocolGuid
,
100 This
->DriverBindingHandle
,
105 // The Controller must support the Serial I/O Protocol.
106 // This driver is a bus driver with at most 1 child device, so it is
107 // ok for it to be already started.
109 Status
= gBS
->OpenProtocol (
111 &gEfiSerialIoProtocolGuid
,
113 This
->DriverBindingHandle
,
115 EFI_OPEN_PROTOCOL_BY_DRIVER
117 if (Status
== EFI_ALREADY_STARTED
) {
121 if (EFI_ERROR (Status
)) {
125 // Close the I/O Abstraction(s) used to perform the supported test
129 &gEfiSerialIoProtocolGuid
,
130 This
->DriverBindingHandle
,
139 TerminalDriverBindingStart (
140 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
141 IN EFI_HANDLE Controller
,
142 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
148 Start the controller.
152 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
153 Controller - The handle of the controller to start.
154 RemainingDevicePath - A pointer to the remaining portion of a devcie path.
163 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
164 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
165 VENDOR_DEVICE_PATH
*Node
;
166 VENDOR_DEVICE_PATH
*DefaultNode
;
167 EFI_SERIAL_IO_MODE
*Mode
;
168 UINTN SerialInTimeOut
;
169 TERMINAL_DEV
*TerminalDevice
;
171 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
174 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
176 TerminalDevice
= NULL
;
179 // Get the Device Path Protocol to build the device path of the child device
181 Status
= gBS
->OpenProtocol (
183 &gEfiDevicePathProtocolGuid
,
184 (VOID
**) &ParentDevicePath
,
185 This
->DriverBindingHandle
,
187 EFI_OPEN_PROTOCOL_BY_DRIVER
189 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
194 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
196 Status
= gBS
->OpenProtocol (
198 &gEfiSerialIoProtocolGuid
,
200 This
->DriverBindingHandle
,
202 EFI_OPEN_PROTOCOL_BY_DRIVER
204 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
208 if (Status
!= EFI_ALREADY_STARTED
) {
210 // If Serial I/O is not already open by this driver, then tag the handle
211 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
212 // StdErrDev variables with the list of possible terminal types on this
215 Status
= gBS
->OpenProtocol (
219 This
->DriverBindingHandle
,
221 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
223 if (EFI_ERROR (Status
)) {
224 Status
= gBS
->InstallMultipleProtocolInterfaces (
227 DuplicateDevicePath (ParentDevicePath
),
230 if (EFI_ERROR (Status
)) {
234 // if the serial device is a hot plug device, do not update the
235 // ConInDev, ConOutDev, and StdErrDev variables.
237 Status
= gBS
->OpenProtocol (
239 &gEfiHotPlugDeviceGuid
,
241 This
->DriverBindingHandle
,
243 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
245 if (EFI_ERROR (Status
)) {
246 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
247 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
248 TerminalUpdateConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
253 // Make sure a child handle does not already exist. This driver can only
254 // produce one child per serial port.
256 Status
= gBS
->OpenProtocolInformation (
258 &gEfiSerialIoProtocolGuid
,
262 if (!EFI_ERROR (Status
)) {
263 Status
= EFI_SUCCESS
;
264 for (Index
= 0; Index
< EntryCount
; Index
++) {
265 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
266 Status
= EFI_ALREADY_STARTED
;
270 FreePool (OpenInfoBuffer
);
271 if (EFI_ERROR (Status
)) {
276 // If RemainingDevicePath is NULL, then create default device path node
278 if (RemainingDevicePath
== NULL
) {
279 DefaultNode
= AllocatePool (sizeof (VENDOR_DEVICE_PATH
));
280 if (DefaultNode
== NULL
) {
281 Status
= EFI_OUT_OF_RESOURCES
;
285 CopyMem (&DefaultNode
->Guid
, &gEfiPcAnsiGuid
, sizeof (EFI_GUID
));
286 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
289 // Use the RemainingDevicePath to determine the terminal type
291 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
293 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
295 TerminalType
= PcAnsiType
;
297 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
299 TerminalType
= VT100Type
;
301 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
303 TerminalType
= VT100PlusType
;
305 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
307 TerminalType
= VTUTF8Type
;
313 // Initialize the Terminal Dev
315 TerminalDevice
= AllocatePool (sizeof (TERMINAL_DEV
));
316 if (TerminalDevice
== NULL
) {
317 Status
= EFI_OUT_OF_RESOURCES
;
321 ZeroMem (TerminalDevice
, sizeof (TERMINAL_DEV
));
323 TerminalDevice
->Signature
= TERMINAL_DEV_SIGNATURE
;
325 TerminalDevice
->TerminalType
= TerminalType
;
327 TerminalDevice
->SerialIo
= SerialIo
;
330 // Simple Input Protocol
332 TerminalDevice
->SimpleInput
.Reset
= TerminalConInReset
;
333 TerminalDevice
->SimpleInput
.ReadKeyStroke
= TerminalConInReadKeyStroke
;
335 Status
= gBS
->CreateEvent (
338 TerminalConInWaitForKey
,
339 &TerminalDevice
->SimpleInput
,
340 &TerminalDevice
->SimpleInput
.WaitForKey
342 if (EFI_ERROR (Status
)) {
346 // initialize the FIFO buffer used for accommodating
347 // the pre-read pending characters
349 InitializeRawFiFo (TerminalDevice
);
350 InitializeUnicodeFiFo (TerminalDevice
);
351 InitializeEfiKeyFiFo (TerminalDevice
);
354 // Set the timeout value of serial buffer for
355 // keystroke response performance issue
357 Mode
= TerminalDevice
->SerialIo
->Mode
;
360 if (Mode
->BaudRate
!= 0) {
361 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
364 Status
= TerminalDevice
->SerialIo
->SetAttributes (
365 TerminalDevice
->SerialIo
,
367 Mode
->ReceiveFifoDepth
,
368 (UINT32
) SerialInTimeOut
,
369 (EFI_PARITY_TYPE
) (Mode
->Parity
),
370 (UINT8
) Mode
->DataBits
,
371 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
373 if (EFI_ERROR (Status
)) {
375 // if set attributes operation fails, invalidate
376 // the value of SerialInTimeOut,thus make it
377 // inconsistent with the default timeout value
378 // of serial buffer. This will invoke the recalculation
379 // in the readkeystroke routine.
381 TerminalDevice
->SerialInTimeOut
= 0;
383 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
386 // Build the device path for the child device
388 Status
= SetTerminalDevicePath (
389 TerminalDevice
->TerminalType
,
391 &TerminalDevice
->DevicePath
393 if (EFI_ERROR (Status
)) {
397 DevicePath
= TerminalDevice
->DevicePath
;
399 Status
= TerminalDevice
->SimpleInput
.Reset (
400 &TerminalDevice
->SimpleInput
,
403 if (EFI_ERROR (Status
)) {
405 // Need to report Error Code first
410 // Simple Text Output Protocol
412 TerminalDevice
->SimpleTextOutput
.Reset
= TerminalConOutReset
;
413 TerminalDevice
->SimpleTextOutput
.OutputString
= TerminalConOutOutputString
;
414 TerminalDevice
->SimpleTextOutput
.TestString
= TerminalConOutTestString
;
415 TerminalDevice
->SimpleTextOutput
.QueryMode
= TerminalConOutQueryMode
;
416 TerminalDevice
->SimpleTextOutput
.SetMode
= TerminalConOutSetMode
;
417 TerminalDevice
->SimpleTextOutput
.SetAttribute
= TerminalConOutSetAttribute
;
418 TerminalDevice
->SimpleTextOutput
.ClearScreen
= TerminalConOutClearScreen
;
419 TerminalDevice
->SimpleTextOutput
.SetCursorPosition
= TerminalConOutSetCursorPosition
;
420 TerminalDevice
->SimpleTextOutput
.EnableCursor
= TerminalConOutEnableCursor
;
421 TerminalDevice
->SimpleTextOutput
.Mode
= &TerminalDevice
->SimpleTextOutputMode
;
423 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= 1;
425 // For terminal devices, cursor is always visible
427 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
428 TerminalDevice
->SimpleTextOutputMode
.Attribute
= EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
);
430 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
431 &TerminalDevice
->SimpleTextOutput
,
434 if (EFI_ERROR (Status
)) {
438 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
439 &TerminalDevice
->SimpleTextOutput
,
442 if (EFI_ERROR (Status
)) {
446 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
447 &TerminalDevice
->SimpleTextOutput
,
450 if (EFI_ERROR (Status
)) {
456 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
457 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
459 Status
= gBS
->CreateEvent (
464 &TerminalDevice
->TwoSecondTimeOut
468 // Build the component name for the child device
470 TerminalDevice
->ControllerNameTable
= NULL
;
471 switch (TerminalDevice
->TerminalType
) {
475 gTerminalComponentName
.SupportedLanguages
,
476 &TerminalDevice
->ControllerNameTable
,
477 (CHAR16
*)L
"PC-ANSI Serial Console"
484 gTerminalComponentName
.SupportedLanguages
,
485 &TerminalDevice
->ControllerNameTable
,
486 (CHAR16
*)L
"VT-100 Serial Console"
493 gTerminalComponentName
.SupportedLanguages
,
494 &TerminalDevice
->ControllerNameTable
,
495 (CHAR16
*)L
"VT-100+ Serial Console"
502 gTerminalComponentName
.SupportedLanguages
,
503 &TerminalDevice
->ControllerNameTable
,
504 (CHAR16
*)L
"VT-UTF8 Serial Console"
509 // Install protocol interfaces for the serial device.
511 Status
= gBS
->InstallMultipleProtocolInterfaces (
512 &TerminalDevice
->Handle
,
513 &gEfiDevicePathProtocolGuid
,
514 TerminalDevice
->DevicePath
,
515 &gEfiSimpleTextInProtocolGuid
,
516 &TerminalDevice
->SimpleInput
,
517 &gEfiSimpleTextOutProtocolGuid
,
518 &TerminalDevice
->SimpleTextOutput
,
521 if (EFI_ERROR (Status
)) {
525 // if the serial device is a hot plug device, attaches the HotPlugGuid
526 // onto the terminal device handle.
528 Status
= gBS
->OpenProtocol (
530 &gEfiHotPlugDeviceGuid
,
532 This
->DriverBindingHandle
,
534 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
536 if (!EFI_ERROR (Status
)) {
537 Status
= gBS
->InstallMultipleProtocolInterfaces (
538 &TerminalDevice
->Handle
,
539 &gEfiHotPlugDeviceGuid
,
545 // Register the Parent-Child relationship via
546 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
548 Status
= gBS
->OpenProtocol (
550 &gEfiSerialIoProtocolGuid
,
551 (VOID
**) &TerminalDevice
->SerialIo
,
552 This
->DriverBindingHandle
,
553 TerminalDevice
->Handle
,
554 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
556 if (EFI_ERROR (Status
)) {
560 if (DefaultNode
!= NULL
) {
561 FreePool (DefaultNode
);
568 // Report error code before exiting
570 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
571 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
572 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
578 // Use the Stop() function to free all resources allocated in Start()
580 if (TerminalDevice
!= NULL
) {
582 if (TerminalDevice
->Handle
!= NULL
) {
583 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
586 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
587 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
590 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
591 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
594 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
595 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
598 if (TerminalDevice
->DevicePath
!= NULL
) {
599 FreePool (TerminalDevice
->DevicePath
);
602 FreePool (TerminalDevice
);
606 if (DefaultNode
!= NULL
) {
607 FreePool (DefaultNode
);
610 This
->Stop (This
, Controller
, 0, NULL
);
617 TerminalDriverBindingStop (
618 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
619 IN EFI_HANDLE Controller
,
620 IN UINTN NumberOfChildren
,
621 IN EFI_HANDLE
*ChildHandleBuffer
627 Stop a device controller.
631 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
632 Controller - A handle to the device being stopped.
633 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
634 ChildHandleBuffer - An array of child handles to be freed.
638 EFI_SUCCESS - Operation successful.
639 EFI_DEVICE_ERROR - Devices error.
645 BOOLEAN AllChildrenStopped
;
646 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
647 TERMINAL_DEV
*TerminalDevice
;
648 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
649 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
650 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
652 Status
= gBS
->HandleProtocol (
654 &gEfiDevicePathProtocolGuid
,
655 (VOID
**) &DevicePath
657 if (EFI_ERROR (Status
)) {
662 // Complete all outstanding transactions to Controller.
663 // Don't allow any new transaction to Controller to be started.
665 if (NumberOfChildren
== 0) {
667 // Close the bus driver
669 Status
= gBS
->OpenProtocol (
672 (VOID
**) &ParentDevicePath
,
673 This
->DriverBindingHandle
,
675 EFI_OPEN_PROTOCOL_GET_PROTOCOL
677 if (!EFI_ERROR (Status
)) {
679 // Remove Parent Device Path from
680 // the Console Device Environment Variables
682 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleInpDev
, ParentDevicePath
);
683 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarConsoleOutDev
, ParentDevicePath
);
684 TerminalRemoveConsoleDevVariable ((CHAR16
*)VarErrorOutDev
, ParentDevicePath
);
687 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
689 Status
= gBS
->UninstallMultipleProtocolInterfaces (
697 // Free the ParentDevicePath that was duplicated in Start()
699 if (!EFI_ERROR (Status
)) {
700 FreePool (ParentDevicePath
);
706 &gEfiSerialIoProtocolGuid
,
707 This
->DriverBindingHandle
,
713 &gEfiDevicePathProtocolGuid
,
714 This
->DriverBindingHandle
,
721 AllChildrenStopped
= TRUE
;
723 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
725 Status
= gBS
->OpenProtocol (
726 ChildHandleBuffer
[Index
],
727 &gEfiSimpleTextOutProtocolGuid
,
728 (VOID
**) &SimpleTextOutput
,
729 This
->DriverBindingHandle
,
730 ChildHandleBuffer
[Index
],
731 EFI_OPEN_PROTOCOL_GET_PROTOCOL
733 if (!EFI_ERROR (Status
)) {
735 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
739 &gEfiSerialIoProtocolGuid
,
740 This
->DriverBindingHandle
,
741 ChildHandleBuffer
[Index
]
744 Status
= gBS
->UninstallMultipleProtocolInterfaces (
745 ChildHandleBuffer
[Index
],
746 &gEfiSimpleTextInProtocolGuid
,
747 &TerminalDevice
->SimpleInput
,
748 &gEfiSimpleTextOutProtocolGuid
,
749 &TerminalDevice
->SimpleTextOutput
,
750 &gEfiDevicePathProtocolGuid
,
751 TerminalDevice
->DevicePath
,
754 if (EFI_ERROR (Status
)) {
757 &gEfiSerialIoProtocolGuid
,
759 This
->DriverBindingHandle
,
760 ChildHandleBuffer
[Index
],
761 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
765 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
766 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
769 Status
= gBS
->OpenProtocol (
770 ChildHandleBuffer
[Index
],
771 &gEfiHotPlugDeviceGuid
,
773 This
->DriverBindingHandle
,
775 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
777 if (!EFI_ERROR (Status
)) {
778 Status
= gBS
->UninstallMultipleProtocolInterfaces (
779 ChildHandleBuffer
[Index
],
780 &gEfiHotPlugDeviceGuid
,
785 Status
= EFI_SUCCESS
;
788 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
789 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
790 FreePool (TerminalDevice
->DevicePath
);
791 FreePool (TerminalDevice
);
795 if (EFI_ERROR (Status
)) {
796 AllChildrenStopped
= FALSE
;
800 if (!AllChildrenStopped
) {
801 return EFI_DEVICE_ERROR
;
808 TerminalUpdateConsoleDevVariable (
809 IN CHAR16
*VariableName
,
810 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
816 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
817 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
818 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
823 // Get global variable and its size according to the name given.
825 Variable
= TerminalGetVariableAndSize (
827 &gEfiGlobalVariableGuid
,
831 // Append terminal device path onto the variable.
833 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
834 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
835 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
836 if (Variable
!= NULL
) {
840 if (TempDevicePath
!= NULL
) {
841 FreePool (TempDevicePath
);
844 Variable
= NewVariable
;
847 VariableSize
= GetDevicePathSize (Variable
);
849 Status
= gRT
->SetVariable (
851 &gEfiGlobalVariableGuid
,
852 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
856 ASSERT_EFI_ERROR (Status
);
863 TerminalRemoveConsoleDevVariable (
864 IN CHAR16
*VariableName
,
865 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
871 Remove console device variable.
875 VariableName - A pointer to the variable name.
876 ParentDevicePath - A pointer to the parent device path.
888 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
889 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
890 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
891 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
892 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
893 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
899 // Get global variable and its size according to the name given.
901 Variable
= TerminalGetVariableAndSize (
903 &gEfiGlobalVariableGuid
,
906 if (Variable
== NULL
) {
911 OriginalVariable
= Variable
;
915 // Get first device path instance from Variable
917 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
918 if (Instance
== NULL
) {
919 FreePool (OriginalVariable
);
923 // Loop through all the device path instances of Variable
927 // Loop through all the terminal types that this driver supports
930 for (TerminalType
= PcAnsiType
; TerminalType
<= VTUTF8Type
; TerminalType
++) {
932 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
935 // Compare the genterated device path to the current device path instance
937 if (TempDevicePath
!= NULL
) {
938 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
943 FreePool (TempDevicePath
);
947 // If a match was not found, then keep the current device path instance
950 SavedNewVariable
= NewVariable
;
951 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
952 if (SavedNewVariable
!= NULL
) {
953 FreePool (SavedNewVariable
);
957 // Get next device path instance from Variable
960 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
961 } while (Instance
!= NULL
);
963 FreePool (OriginalVariable
);
966 VariableSize
= GetDevicePathSize (NewVariable
);
968 Status
= gRT
->SetVariable (
970 &gEfiGlobalVariableGuid
,
971 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
975 ASSERT_EFI_ERROR (Status
);
978 if (NewVariable
!= NULL
) {
979 FreePool (NewVariable
);
986 TerminalGetVariableAndSize (
988 IN EFI_GUID
*VendorGuid
,
989 OUT UINTN
*VariableSize
994 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
995 buffer, and the size of the buffer. On failure return NULL.
998 Name - String part of EFI variable name
1000 VendorGuid - GUID part of EFI variable name
1002 VariableSize - Returns the size of the EFI variable that was read
1005 Dynamically allocated memory that contains a copy of the EFI variable.
1006 Caller is repsoncible freeing the buffer.
1008 NULL - Variable was not read
1019 // Pass in a small size buffer to find the actual variable size.
1022 Buffer
= AllocatePool (BufferSize
);
1023 if (Buffer
== NULL
) {
1028 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1030 if (Status
== EFI_SUCCESS
) {
1031 *VariableSize
= BufferSize
;
1034 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
1036 // Allocate the buffer to return
1039 Buffer
= AllocatePool (BufferSize
);
1040 if (Buffer
== NULL
) {
1045 // Read variable into the allocated buffer.
1047 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1048 if (EFI_ERROR (Status
)) {
1055 // Variable not found or other errors met.
1062 *VariableSize
= BufferSize
;
1067 SetTerminalDevicePath (
1068 IN UINT8 TerminalType
,
1069 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1070 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1073 VENDOR_DEVICE_PATH Node
;
1075 *TerminalDevicePath
= NULL
;
1076 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1077 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1080 // generate terminal device path node according to terminal type.
1082 switch (TerminalType
) {
1117 return EFI_UNSUPPORTED
;
1121 SetDevicePathNodeLength (
1123 sizeof (VENDOR_DEVICE_PATH
)
1126 // append the terminal node onto parent device path
1127 // to generate a complete terminal device path.
1129 *TerminalDevicePath
= AppendDevicePathNode (
1131 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1133 if (*TerminalDevicePath
== NULL
) {
1134 return EFI_OUT_OF_RESOURCES
;
1142 IN TERMINAL_DEV
*TerminalDevice
1146 // Make the raw fifo empty.
1148 TerminalDevice
->RawFiFo
.Head
= TerminalDevice
->RawFiFo
.Tail
;
1152 InitializeUnicodeFiFo (
1153 IN TERMINAL_DEV
*TerminalDevice
1157 // Make the unicode fifo empty
1159 TerminalDevice
->UnicodeFiFo
.Head
= TerminalDevice
->UnicodeFiFo
.Tail
;
1163 InitializeEfiKeyFiFo (
1164 IN TERMINAL_DEV
*TerminalDevice
1168 // Make the efi key fifo empty
1170 TerminalDevice
->EfiKeyFiFo
.Head
= TerminalDevice
->EfiKeyFiFo
.Tail
;
1175 The user Entry Point for module Terminal. The user code starts with this function.
1177 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1178 @param[in] SystemTable A pointer to the EFI System Table.
1180 @retval EFI_SUCCESS The entry point is executed successfully.
1181 @retval other Some error occurs when executing this entry point.
1187 IN EFI_HANDLE ImageHandle
,
1188 IN EFI_SYSTEM_TABLE
*SystemTable
1194 // Install driver model protocol(s).
1196 Status
= EfiLibInstallAllDriverProtocols (
1199 &gTerminalDriverBinding
,
1201 &gTerminalComponentName
,
1205 ASSERT_EFI_ERROR (Status
);