2 Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and
3 Simple Text Output Protocol upon Serial IO Protocol.
5 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding
= {
23 TerminalDriverBindingSupported
,
24 TerminalDriverBindingStart
,
25 TerminalDriverBindingStop
,
32 EFI_GUID
*mTerminalType
[] = {
41 TERMINAL_DEV mTerminalDevTemplate
= {
42 TERMINAL_DEV_SIGNATURE
,
49 TerminalConInReadKeyStroke
,
54 TerminalConOutOutputString
,
55 TerminalConOutTestString
,
56 TerminalConOutQueryMode
,
57 TerminalConOutSetMode
,
58 TerminalConOutSetAttribute
,
59 TerminalConOutClearScreen
,
60 TerminalConOutSetCursorPosition
,
61 TerminalConOutEnableCursor
,
64 { // SimpleTextOutputMode
67 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
), // Attribute
72 NULL
, // TerminalConsoleModeData
78 NULL
, // EfiKeyFiFoForNotify
80 NULL
, // ControllerNameTable
82 NULL
, // TwoSecondTimeOut
92 { // SimpleTextInputEx
94 TerminalConInReadKeyStrokeEx
,
96 TerminalConInSetState
,
97 TerminalConInRegisterKeyNotify
,
98 TerminalConInUnregisterKeyNotify
,
104 NULL
// KeyNotifyProcessEvent
107 TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData
[] = {
110 // New modes can be added here.
115 Convert the GUID representation of terminal type to enum type.
117 @param Guid The GUID representation of terminal type.
119 @return The terminal type in enum type.
122 TerminalTypeFromGuid (
128 for (Type
= 0; Type
< ARRAY_SIZE (mTerminalType
); Type
++) {
129 if (CompareGuid (Guid
, mTerminalType
[Type
])) {
137 Test to see if this driver supports Controller.
139 @param This Protocol instance pointer.
140 @param Controller Handle of device to test
141 @param RemainingDevicePath Optional parameter use to pick a specific child
144 @retval EFI_SUCCESS This driver supports this device.
145 @retval EFI_ALREADY_STARTED This driver is already running on this device.
146 @retval other This driver does not support this device.
151 TerminalDriverBindingSupported (
152 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
153 IN EFI_HANDLE Controller
,
154 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
158 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
159 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
160 VENDOR_DEVICE_PATH
*Node
;
163 // If remaining device path is not NULL, then make sure it is a
164 // device path that describes a terminal communications protocol.
166 if (RemainingDevicePath
!= NULL
) {
168 // Check if RemainingDevicePath is the End of Device Path Node,
169 // if yes, go on checking other conditions
171 if (!IsDevicePathEnd (RemainingDevicePath
)) {
173 // If RemainingDevicePath isn't the End of Device Path Node,
174 // check its validation
176 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
178 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
179 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
180 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
182 return EFI_UNSUPPORTED
;
186 // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types
188 if (TerminalTypeFromGuid (&Node
->Guid
) == ARRAY_SIZE (mTerminalType
)) {
189 return EFI_UNSUPPORTED
;
194 // Open the IO Abstraction(s) needed to perform the supported test
195 // The Controller must support the Serial I/O Protocol.
196 // This driver is a bus driver with at most 1 child device, so it is
197 // ok for it to be already started.
199 Status
= gBS
->OpenProtocol (
201 &gEfiSerialIoProtocolGuid
,
203 This
->DriverBindingHandle
,
205 EFI_OPEN_PROTOCOL_BY_DRIVER
207 if (Status
== EFI_ALREADY_STARTED
) {
211 if (EFI_ERROR (Status
)) {
216 // Close the I/O Abstraction(s) used to perform the supported test
220 &gEfiSerialIoProtocolGuid
,
221 This
->DriverBindingHandle
,
226 // Open the EFI Device Path protocol needed to perform the supported test
228 Status
= gBS
->OpenProtocol (
230 &gEfiDevicePathProtocolGuid
,
231 (VOID
**) &ParentDevicePath
,
232 This
->DriverBindingHandle
,
234 EFI_OPEN_PROTOCOL_BY_DRIVER
236 if (Status
== EFI_ALREADY_STARTED
) {
240 if (EFI_ERROR (Status
)) {
245 // Close protocol, don't use device path protocol in the Support() function
249 &gEfiDevicePathProtocolGuid
,
250 This
->DriverBindingHandle
,
258 Build the terminal device path for the child device according to the
261 @param ParentDevicePath Parent device path.
262 @param RemainingDevicePath A specific child device.
264 @return The child device path built.
267 EFI_DEVICE_PATH_PROTOCOL
*
269 BuildTerminalDevpath (
270 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
271 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
274 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
275 TERMINAL_TYPE TerminalType
;
276 VENDOR_DEVICE_PATH
*Node
;
279 TerminalDevicePath
= NULL
;
282 // Use the RemainingDevicePath to determine the terminal type
284 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
286 TerminalType
= PcdGet8 (PcdDefaultTerminalType
);
288 } else if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
290 TerminalType
= TerminalTypePcAnsi
;
292 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
294 TerminalType
= TerminalTypeVt100
;
296 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
298 TerminalType
= TerminalTypeVt100Plus
;
300 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
302 TerminalType
= TerminalTypeVtUtf8
;
304 } else if (CompareGuid (&Node
->Guid
, &gEfiTtyTermGuid
)) {
306 TerminalType
= TerminalTypeTtyTerm
;
313 // Build the device path for the child device
315 Status
= SetTerminalDevicePath (
320 if (EFI_ERROR (Status
)) {
323 return TerminalDevicePath
;
327 Compare a device path data structure to that of all the nodes of a
328 second device path instance.
330 @param Multi A pointer to a multi-instance device path data structure.
331 @param Single A pointer to a single-instance device path data structure.
333 @retval TRUE If the Single is contained within Multi.
334 @retval FALSE The Single is not match within Multi.
339 IN EFI_DEVICE_PATH_PROTOCOL
*Multi
,
340 IN EFI_DEVICE_PATH_PROTOCOL
*Single
343 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
344 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
348 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
350 // Search for the match of 'Single' in 'Multi'
352 while (DevicePathInst
!= NULL
) {
354 // If the single device path is found in multiple device paths,
357 if (CompareMem (Single
, DevicePathInst
, Size
) == 0) {
358 FreePool (DevicePathInst
);
362 FreePool (DevicePathInst
);
363 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
370 Check whether the terminal device path is in the global variable.
372 @param VariableName Pointer to one global variable.
373 @param TerminalDevicePath Pointer to the terminal device's device path.
375 @retval TRUE The devcie is in the global variable.
376 @retval FALSE The devcie is not in the global variable.
380 IsTerminalInConsoleVariable (
381 IN CHAR16
*VariableName
,
382 IN EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
385 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
389 // Get global variable and its size according to the name given.
391 GetEfiGlobalVariable2 (VariableName
, (VOID
**)&Variable
, NULL
);
392 if (Variable
== NULL
) {
397 // Check whether the terminal device path is one of the variable instances.
399 ReturnFlag
= MatchDevicePaths (Variable
, TerminalDevicePath
);
407 Free notify functions list.
409 @param ListHead The list head
411 @retval EFI_SUCCESS Free the notify list successfully.
412 @retval EFI_INVALID_PARAMETER ListHead is NULL.
416 TerminalFreeNotifyList (
417 IN OUT LIST_ENTRY
*ListHead
420 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
422 if (ListHead
== NULL
) {
423 return EFI_INVALID_PARAMETER
;
425 while (!IsListEmpty (ListHead
)) {
427 ListHead
->ForwardLink
,
428 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
430 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
432 RemoveEntryList (ListHead
->ForwardLink
);
433 FreePool (NotifyNode
);
440 Initialize all the text modes which the terminal console supports.
442 It returns information for available text modes that the terminal can support.
444 @param[out] TextModeCount The total number of text modes that terminal console supports.
445 @param[out] TextModeData The buffer to the text modes column and row information.
446 Caller is responsible to free it when it's non-NULL.
448 @retval EFI_SUCCESS The supporting mode information is returned.
449 @retval EFI_INVALID_PARAMETER The parameters are invalid.
453 InitializeTerminalConsoleTextMode (
454 OUT UINTN
*TextModeCount
,
455 OUT TERMINAL_CONSOLE_MODE_DATA
**TextModeData
460 TERMINAL_CONSOLE_MODE_DATA
*ModeBuffer
;
461 TERMINAL_CONSOLE_MODE_DATA
*NewModeBuffer
;
465 if ((TextModeCount
== NULL
) || (TextModeData
== NULL
)) {
466 return EFI_INVALID_PARAMETER
;
469 Count
= sizeof (mTerminalConsoleModeData
) / sizeof (TERMINAL_CONSOLE_MODE_DATA
);
472 // Get defined mode buffer pointer.
474 ModeBuffer
= mTerminalConsoleModeData
;
477 // Here we make sure that the final mode exposed does not include the duplicated modes,
478 // and does not include the invalid modes which exceed the max column and row.
479 // Reserve 2 modes for 80x25, 80x50 of terminal console.
481 NewModeBuffer
= AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA
) * (Count
+ 2));
482 ASSERT (NewModeBuffer
!= NULL
);
485 // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.
489 NewModeBuffer
[ValidCount
].Columns
= 80;
490 NewModeBuffer
[ValidCount
].Rows
= 25;
493 NewModeBuffer
[ValidCount
].Columns
= 80;
494 NewModeBuffer
[ValidCount
].Rows
= 50;
498 // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.
500 for (Index
= 0; Index
< Count
; Index
++) {
501 if ((ModeBuffer
[Index
].Columns
== 0) || (ModeBuffer
[Index
].Rows
== 0)) {
503 // Skip the pre-defined mode which is invalid.
507 for (ValidIndex
= 0; ValidIndex
< ValidCount
; ValidIndex
++) {
508 if ((ModeBuffer
[Index
].Columns
== NewModeBuffer
[ValidIndex
].Columns
) &&
509 (ModeBuffer
[Index
].Rows
== NewModeBuffer
[ValidIndex
].Rows
)) {
511 // Skip the duplicated mode.
516 if (ValidIndex
== ValidCount
) {
517 NewModeBuffer
[ValidCount
].Columns
= ModeBuffer
[Index
].Columns
;
518 NewModeBuffer
[ValidCount
].Rows
= ModeBuffer
[Index
].Rows
;
524 for (Index
= 0; Index
< ValidCount
; Index
++) {
525 DEBUG ((EFI_D_INFO
, "Terminal - Mode %d, Column = %d, Row = %d\n",
526 Index
, NewModeBuffer
[Index
].Columns
, NewModeBuffer
[Index
].Rows
));
531 // Return valid mode count and mode information buffer.
533 *TextModeCount
= ValidCount
;
534 *TextModeData
= NewModeBuffer
;
539 Start this driver on Controller by opening a Serial IO protocol,
540 reading Device Path, and creating a child handle with a Simple Text In,
541 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
542 And store Console Device Environment Variables.
544 @param This Protocol instance pointer.
545 @param Controller Handle of device to bind driver to
546 @param RemainingDevicePath Optional parameter use to pick a specific child
549 @retval EFI_SUCCESS This driver is added to Controller.
550 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
551 @retval other This driver does not support this device.
556 TerminalDriverBindingStart (
557 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
558 IN EFI_HANDLE Controller
,
559 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
563 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
564 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
565 VENDOR_DEVICE_PATH
*Node
;
566 EFI_SERIAL_IO_MODE
*Mode
;
567 UINTN SerialInTimeOut
;
568 TERMINAL_DEV
*TerminalDevice
;
569 TERMINAL_TYPE TerminalType
;
570 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
573 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
574 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
575 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleTextInput
;
576 BOOLEAN ConInSelected
;
577 BOOLEAN ConOutSelected
;
578 BOOLEAN NullRemaining
;
579 BOOLEAN SimTxtInInstalled
;
580 BOOLEAN SimTxtOutInstalled
;
584 TerminalDevice
= NULL
;
585 ConInSelected
= FALSE
;
586 ConOutSelected
= FALSE
;
587 NullRemaining
= FALSE
;
588 SimTxtInInstalled
= FALSE
;
589 SimTxtOutInstalled
= FALSE
;
592 // Get the Device Path Protocol to build the device path of the child device
594 Status
= gBS
->OpenProtocol (
596 &gEfiDevicePathProtocolGuid
,
597 (VOID
**) &ParentDevicePath
,
598 This
->DriverBindingHandle
,
600 EFI_OPEN_PROTOCOL_BY_DRIVER
602 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
607 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
609 Status
= gBS
->OpenProtocol (
611 &gEfiSerialIoProtocolGuid
,
613 This
->DriverBindingHandle
,
615 EFI_OPEN_PROTOCOL_BY_DRIVER
617 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
621 if (Status
!= EFI_ALREADY_STARTED
) {
623 // the serial I/O protocol never be opened before, it is the first
624 // time to start the serial Io controller
630 // Serial I/O is not already open by this driver, then tag the handle
631 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
632 // StdErrDev variables with the list of possible terminal types on this
635 Status
= gBS
->OpenProtocol (
639 This
->DriverBindingHandle
,
641 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
643 if (EFI_ERROR (Status
)) {
644 Status
= gBS
->InstallMultipleProtocolInterfaces (
647 DuplicateDevicePath (ParentDevicePath
),
650 if (EFI_ERROR (Status
)) {
654 if (!IsHotPlugDevice (ParentDevicePath
)) {
656 // if the serial device is a hot plug device, do not update the
657 // ConInDev, ConOutDev, and StdErrDev variables.
659 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
660 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
661 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
666 // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols
668 // Simple In/Out Protocol will not be installed onto the handle if the
669 // device path to the handle is not present in the ConIn/ConOut
670 // environment variable. But If RemainingDevicePath is NULL, then always
671 // produce both Simple In and Simple Text Output Protocols. This is required
672 // for the connect all sequences to make sure all possible consoles are
673 // produced no matter what the current values of ConIn, ConOut, or StdErr are.
675 if (RemainingDevicePath
== NULL
) {
676 NullRemaining
= TRUE
;
679 DevicePath
= BuildTerminalDevpath (ParentDevicePath
, RemainingDevicePath
);
680 if (DevicePath
!= NULL
) {
681 ConInSelected
= IsTerminalInConsoleVariable (L
"ConIn", DevicePath
);
682 ConOutSelected
= IsTerminalInConsoleVariable (L
"ConOut", DevicePath
);
683 FreePool (DevicePath
);
688 // Not create the child terminal handle if both Simple In/In Ex and
689 // Simple text Out protocols are not required to be published
691 if ((!ConInSelected
)&&(!ConOutSelected
)&&(!NullRemaining
)) {
696 // create the child terminal handle during first entry
700 // First enther the start function
704 // Make sure a child handle does not already exist. This driver can only
705 // produce one child per serial port.
707 Status
= gBS
->OpenProtocolInformation (
709 &gEfiSerialIoProtocolGuid
,
713 if (!EFI_ERROR (Status
)) {
714 Status
= EFI_SUCCESS
;
715 for (Index
= 0; Index
< EntryCount
; Index
++) {
716 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
717 Status
= EFI_ALREADY_STARTED
;
721 FreePool (OpenInfoBuffer
);
722 if (EFI_ERROR (Status
)) {
728 // If RemainingDevicePath is NULL, use default terminal type
730 if (RemainingDevicePath
== NULL
) {
731 TerminalType
= PcdGet8 (PcdDefaultTerminalType
);
732 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
734 // If RemainingDevicePath isn't the End of Device Path Node,
735 // Use the RemainingDevicePath to determine the terminal type
737 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
738 TerminalType
= TerminalTypeFromGuid (&Node
->Guid
);
741 // If RemainingDevicePath is the End of Device Path Node,
742 // skip enumerate any device and return EFI_SUCESSS
747 ASSERT (TerminalType
< ARRAY_SIZE (mTerminalType
));
750 // Initialize the Terminal Dev
752 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
753 if (TerminalDevice
== NULL
) {
754 Status
= EFI_OUT_OF_RESOURCES
;
758 TerminalDevice
->TerminalType
= TerminalType
;
759 TerminalDevice
->SerialIo
= SerialIo
;
761 InitializeListHead (&TerminalDevice
->NotifyList
);
762 Status
= gBS
->CreateEvent (
765 TerminalConInWaitForKeyEx
,
767 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
769 if (EFI_ERROR (Status
)) {
773 Status
= gBS
->CreateEvent (
776 TerminalConInWaitForKey
,
778 &TerminalDevice
->SimpleInput
.WaitForKey
780 if (EFI_ERROR (Status
)) {
784 // Allocates and initializes the FIFO buffer to be zero, used for accommodating
785 // the pre-read pending characters.
787 TerminalDevice
->RawFiFo
= AllocateZeroPool (sizeof (RAW_DATA_FIFO
));
788 if (TerminalDevice
->RawFiFo
== NULL
) {
791 TerminalDevice
->UnicodeFiFo
= AllocateZeroPool (sizeof (UNICODE_FIFO
));
792 if (TerminalDevice
->UnicodeFiFo
== NULL
) {
795 TerminalDevice
->EfiKeyFiFo
= AllocateZeroPool (sizeof (EFI_KEY_FIFO
));
796 if (TerminalDevice
->EfiKeyFiFo
== NULL
) {
799 TerminalDevice
->EfiKeyFiFoForNotify
= AllocateZeroPool (sizeof (EFI_KEY_FIFO
));
800 if (TerminalDevice
->EfiKeyFiFoForNotify
== NULL
) {
805 // Set the timeout value of serial buffer for
806 // keystroke response performance issue
808 Mode
= TerminalDevice
->SerialIo
->Mode
;
811 if (Mode
->BaudRate
!= 0) {
812 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
815 Status
= TerminalDevice
->SerialIo
->SetAttributes (
816 TerminalDevice
->SerialIo
,
818 Mode
->ReceiveFifoDepth
,
819 (UINT32
) SerialInTimeOut
,
820 (EFI_PARITY_TYPE
) (Mode
->Parity
),
821 (UINT8
) Mode
->DataBits
,
822 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
824 if (EFI_ERROR (Status
)) {
826 // if set attributes operation fails, invalidate
827 // the value of SerialInTimeOut,thus make it
828 // inconsistent with the default timeout value
829 // of serial buffer. This will invoke the recalculation
830 // in the readkeystroke routine.
832 TerminalDevice
->SerialInTimeOut
= 0;
834 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
837 // Set Simple Text Output Protocol from template.
839 SimpleTextOutput
= CopyMem (
840 &TerminalDevice
->SimpleTextOutput
,
841 &mTerminalDevTemplate
.SimpleTextOutput
,
842 sizeof (mTerminalDevTemplate
.SimpleTextOutput
)
844 SimpleTextOutput
->Mode
= &TerminalDevice
->SimpleTextOutputMode
;
846 Status
= InitializeTerminalConsoleTextMode (&ModeCount
, &TerminalDevice
->TerminalConsoleModeData
);
847 if (EFI_ERROR (Status
)) {
850 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= (INT32
) ModeCount
;
853 // For terminal devices, cursor is always visible
855 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
856 Status
= TerminalConOutSetAttribute (
858 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
860 if (EFI_ERROR (Status
)) {
865 // Build the component name for the child device
867 TerminalDevice
->ControllerNameTable
= NULL
;
868 switch (TerminalDevice
->TerminalType
) {
869 case TerminalTypePcAnsi
:
872 gTerminalComponentName
.SupportedLanguages
,
873 &TerminalDevice
->ControllerNameTable
,
874 (CHAR16
*)L
"PC-ANSI Serial Console",
879 gTerminalComponentName2
.SupportedLanguages
,
880 &TerminalDevice
->ControllerNameTable
,
881 (CHAR16
*)L
"PC-ANSI Serial Console",
887 case TerminalTypeVt100
:
890 gTerminalComponentName
.SupportedLanguages
,
891 &TerminalDevice
->ControllerNameTable
,
892 (CHAR16
*)L
"VT-100 Serial Console",
897 gTerminalComponentName2
.SupportedLanguages
,
898 &TerminalDevice
->ControllerNameTable
,
899 (CHAR16
*)L
"VT-100 Serial Console",
905 case TerminalTypeVt100Plus
:
908 gTerminalComponentName
.SupportedLanguages
,
909 &TerminalDevice
->ControllerNameTable
,
910 (CHAR16
*)L
"VT-100+ Serial Console",
915 gTerminalComponentName2
.SupportedLanguages
,
916 &TerminalDevice
->ControllerNameTable
,
917 (CHAR16
*)L
"VT-100+ Serial Console",
923 case TerminalTypeVtUtf8
:
926 gTerminalComponentName
.SupportedLanguages
,
927 &TerminalDevice
->ControllerNameTable
,
928 (CHAR16
*)L
"VT-UTF8 Serial Console",
933 gTerminalComponentName2
.SupportedLanguages
,
934 &TerminalDevice
->ControllerNameTable
,
935 (CHAR16
*)L
"VT-UTF8 Serial Console",
941 case TerminalTypeTtyTerm
:
944 gTerminalComponentName
.SupportedLanguages
,
945 &TerminalDevice
->ControllerNameTable
,
946 (CHAR16
*)L
"Tty Terminal Serial Console",
951 gTerminalComponentName2
.SupportedLanguages
,
952 &TerminalDevice
->ControllerNameTable
,
953 (CHAR16
*)L
"Tty Terminal Serial Console",
961 // Build the device path for the child device
963 Status
= SetTerminalDevicePath (
964 TerminalDevice
->TerminalType
,
966 &TerminalDevice
->DevicePath
968 if (EFI_ERROR (Status
)) {
972 Status
= TerminalConOutReset (SimpleTextOutput
, FALSE
);
973 if (EFI_ERROR (Status
)) {
977 Status
= TerminalConOutSetMode (SimpleTextOutput
, 0);
978 if (EFI_ERROR (Status
)) {
982 Status
= TerminalConOutEnableCursor (SimpleTextOutput
, TRUE
);
983 if (EFI_ERROR (Status
)) {
987 Status
= gBS
->CreateEvent (
988 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
990 TerminalConInTimerHandler
,
992 &TerminalDevice
->TimerEvent
994 ASSERT_EFI_ERROR (Status
);
996 Status
= gBS
->SetTimer (
997 TerminalDevice
->TimerEvent
,
999 KEYBOARD_TIMER_INTERVAL
1001 ASSERT_EFI_ERROR (Status
);
1003 Status
= gBS
->CreateEvent (
1008 &TerminalDevice
->TwoSecondTimeOut
1010 ASSERT_EFI_ERROR (Status
);
1012 Status
= gBS
->CreateEvent (
1015 KeyNotifyProcessHandler
,
1017 &TerminalDevice
->KeyNotifyProcessEvent
1019 ASSERT_EFI_ERROR (Status
);
1021 Status
= gBS
->InstallProtocolInterface (
1022 &TerminalDevice
->Handle
,
1023 &gEfiDevicePathProtocolGuid
,
1024 EFI_NATIVE_INTERFACE
,
1025 TerminalDevice
->DevicePath
1027 if (EFI_ERROR (Status
)) {
1032 // Register the Parent-Child relationship via
1033 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1035 Status
= gBS
->OpenProtocol (
1037 &gEfiSerialIoProtocolGuid
,
1038 (VOID
**) &TerminalDevice
->SerialIo
,
1039 This
->DriverBindingHandle
,
1040 TerminalDevice
->Handle
,
1041 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1043 if (EFI_ERROR (Status
)) {
1049 // Find the child handle, and get its TerminalDevice private data
1051 Status
= gBS
->OpenProtocolInformation (
1053 &gEfiSerialIoProtocolGuid
,
1057 if (!EFI_ERROR (Status
)) {
1058 Status
= EFI_NOT_FOUND
;
1059 ASSERT (OpenInfoBuffer
!= NULL
);
1060 for (Index
= 0; Index
< EntryCount
; Index
++) {
1061 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1063 // Find the child terminal handle.
1064 // Test whether the SimpleTxtIn and SimpleTxtOut have been published
1066 Status
= gBS
->OpenProtocol (
1067 OpenInfoBuffer
[Index
].ControllerHandle
,
1068 &gEfiSimpleTextInProtocolGuid
,
1069 (VOID
**) &SimpleTextInput
,
1070 This
->DriverBindingHandle
,
1071 OpenInfoBuffer
[Index
].ControllerHandle
,
1072 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1074 if (!EFI_ERROR (Status
)) {
1075 SimTxtInInstalled
= TRUE
;
1076 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput
);
1079 Status
= gBS
->OpenProtocol (
1080 OpenInfoBuffer
[Index
].ControllerHandle
,
1081 &gEfiSimpleTextOutProtocolGuid
,
1082 (VOID
**) &SimpleTextOutput
,
1083 This
->DriverBindingHandle
,
1084 OpenInfoBuffer
[Index
].ControllerHandle
,
1085 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1087 if (!EFI_ERROR (Status
)) {
1088 SimTxtOutInstalled
= TRUE
;
1089 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
1091 Status
= EFI_SUCCESS
;
1096 FreePool (OpenInfoBuffer
);
1097 if (EFI_ERROR (Status
)) {
1104 ASSERT (TerminalDevice
!= NULL
);
1106 // Only do the reset if the device path is in the Conout variable
1108 if (ConInSelected
&& !SimTxtInInstalled
) {
1109 Status
= TerminalDevice
->SimpleInput
.Reset (
1110 &TerminalDevice
->SimpleInput
,
1113 if (EFI_ERROR (Status
)) {
1115 // Need to report Error Code first
1122 // Only output the configure string to remote terminal if the device path
1123 // is in the Conout variable
1125 if (ConOutSelected
&& !SimTxtOutInstalled
) {
1126 Status
= TerminalDevice
->SimpleTextOutput
.SetAttribute (
1127 &TerminalDevice
->SimpleTextOutput
,
1128 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
1130 if (EFI_ERROR (Status
)) {
1134 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
1135 &TerminalDevice
->SimpleTextOutput
,
1138 if (EFI_ERROR (Status
)) {
1142 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
1143 &TerminalDevice
->SimpleTextOutput
,
1146 if (EFI_ERROR (Status
)) {
1150 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
1151 &TerminalDevice
->SimpleTextOutput
,
1154 if (EFI_ERROR (Status
)) {
1160 // Simple In/Out Protocol will not be installed onto the handle if the
1161 // device path to the handle is not present in the ConIn/ConOut
1162 // environment variable. But If RemainingDevicePath is NULL, then always
1163 // produce both Simple In and Simple Text Output Protocols. This is required
1164 // for the connect all sequences to make sure all possible consoles are
1165 // produced no matter what the current values of ConIn, ConOut, or StdErr are.
1167 if (!SimTxtInInstalled
&& (ConInSelected
|| NullRemaining
)) {
1168 Status
= gBS
->InstallMultipleProtocolInterfaces (
1169 &TerminalDevice
->Handle
,
1170 &gEfiSimpleTextInProtocolGuid
,
1171 &TerminalDevice
->SimpleInput
,
1172 &gEfiSimpleTextInputExProtocolGuid
,
1173 &TerminalDevice
->SimpleInputEx
,
1176 if (EFI_ERROR (Status
)) {
1181 if (!SimTxtOutInstalled
&& (ConOutSelected
|| NullRemaining
)) {
1182 Status
= gBS
->InstallProtocolInterface (
1183 &TerminalDevice
->Handle
,
1184 &gEfiSimpleTextOutProtocolGuid
,
1185 EFI_NATIVE_INTERFACE
,
1186 &TerminalDevice
->SimpleTextOutput
1188 if (EFI_ERROR (Status
)) {
1197 // Report error code before exiting
1199 DevicePath
= ParentDevicePath
;
1200 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1201 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1202 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
1208 // Use the Stop() function to free all resources allocated in Start()
1210 if (TerminalDevice
!= NULL
) {
1212 if (TerminalDevice
->Handle
!= NULL
) {
1213 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
1216 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
1217 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
1220 if (TerminalDevice
->TimerEvent
!= NULL
) {
1221 gBS
->CloseEvent (TerminalDevice
->TimerEvent
);
1224 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
1225 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
1228 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
1229 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
1232 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
1234 if (TerminalDevice
->RawFiFo
!= NULL
) {
1235 FreePool (TerminalDevice
->RawFiFo
);
1237 if (TerminalDevice
->UnicodeFiFo
!= NULL
) {
1238 FreePool (TerminalDevice
->UnicodeFiFo
);
1240 if (TerminalDevice
->EfiKeyFiFo
!= NULL
) {
1241 FreePool (TerminalDevice
->EfiKeyFiFo
);
1243 if (TerminalDevice
->EfiKeyFiFoForNotify
!= NULL
) {
1244 FreePool (TerminalDevice
->EfiKeyFiFoForNotify
);
1247 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
1248 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
1251 if (TerminalDevice
->DevicePath
!= NULL
) {
1252 FreePool (TerminalDevice
->DevicePath
);
1255 if (TerminalDevice
->TerminalConsoleModeData
!= NULL
) {
1256 FreePool (TerminalDevice
->TerminalConsoleModeData
);
1259 FreePool (TerminalDevice
);
1263 This
->Stop (This
, Controller
, 0, NULL
);
1269 Stop this driver on Controller by closing Simple Text In, Simple Text
1270 In Ex, Simple Text Out protocol, and removing parent device path from
1271 Console Device Environment Variables.
1273 @param This Protocol instance pointer.
1274 @param Controller Handle of device to stop driver on
1275 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1276 children is zero stop the entire bus driver.
1277 @param ChildHandleBuffer List of Child Handles to Stop.
1279 @retval EFI_SUCCESS This driver is removed Controller.
1280 @retval other This driver could not be removed from this device.
1285 TerminalDriverBindingStop (
1286 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1287 IN EFI_HANDLE Controller
,
1288 IN UINTN NumberOfChildren
,
1289 IN EFI_HANDLE
*ChildHandleBuffer
1294 BOOLEAN AllChildrenStopped
;
1295 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
1296 TERMINAL_DEV
*TerminalDevice
;
1297 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1298 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1299 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1301 Status
= gBS
->HandleProtocol (
1303 &gEfiDevicePathProtocolGuid
,
1304 (VOID
**) &DevicePath
1306 if (EFI_ERROR (Status
)) {
1311 // Complete all outstanding transactions to Controller.
1312 // Don't allow any new transaction to Controller to be started.
1314 if (NumberOfChildren
== 0) {
1316 // Close the bus driver
1318 Status
= gBS
->OpenProtocol (
1321 (VOID
**) &ParentDevicePath
,
1322 This
->DriverBindingHandle
,
1324 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1326 if (!EFI_ERROR (Status
)) {
1328 // Remove Parent Device Path from
1329 // the Console Device Environment Variables
1331 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
1332 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
1333 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
1336 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
1338 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1346 // Free the ParentDevicePath that was duplicated in Start()
1348 if (!EFI_ERROR (Status
)) {
1349 FreePool (ParentDevicePath
);
1353 gBS
->CloseProtocol (
1355 &gEfiSerialIoProtocolGuid
,
1356 This
->DriverBindingHandle
,
1360 gBS
->CloseProtocol (
1362 &gEfiDevicePathProtocolGuid
,
1363 This
->DriverBindingHandle
,
1370 AllChildrenStopped
= TRUE
;
1372 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1374 Status
= gBS
->OpenProtocol (
1375 ChildHandleBuffer
[Index
],
1376 &gEfiSimpleTextOutProtocolGuid
,
1377 (VOID
**) &SimpleTextOutput
,
1378 This
->DriverBindingHandle
,
1379 ChildHandleBuffer
[Index
],
1380 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1382 if (!EFI_ERROR (Status
)) {
1384 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
1386 gBS
->CloseProtocol (
1388 &gEfiSerialIoProtocolGuid
,
1389 This
->DriverBindingHandle
,
1390 ChildHandleBuffer
[Index
]
1393 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1394 ChildHandleBuffer
[Index
],
1395 &gEfiSimpleTextInProtocolGuid
,
1396 &TerminalDevice
->SimpleInput
,
1397 &gEfiSimpleTextInputExProtocolGuid
,
1398 &TerminalDevice
->SimpleInputEx
,
1399 &gEfiSimpleTextOutProtocolGuid
,
1400 &TerminalDevice
->SimpleTextOutput
,
1401 &gEfiDevicePathProtocolGuid
,
1402 TerminalDevice
->DevicePath
,
1405 if (EFI_ERROR (Status
)) {
1408 &gEfiSerialIoProtocolGuid
,
1409 (VOID
**) &SerialIo
,
1410 This
->DriverBindingHandle
,
1411 ChildHandleBuffer
[Index
],
1412 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1416 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
1417 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
1420 gBS
->CloseEvent (TerminalDevice
->TimerEvent
);
1421 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
1422 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
1423 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
1424 gBS
->CloseEvent (TerminalDevice
->KeyNotifyProcessEvent
);
1425 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
1426 FreePool (TerminalDevice
->DevicePath
);
1427 if (TerminalDevice
->TerminalConsoleModeData
!= NULL
) {
1428 FreePool (TerminalDevice
->TerminalConsoleModeData
);
1430 FreePool (TerminalDevice
);
1434 if (EFI_ERROR (Status
)) {
1435 AllChildrenStopped
= FALSE
;
1439 if (!AllChildrenStopped
) {
1440 return EFI_DEVICE_ERROR
;
1447 Update terminal device path in Console Device Environment Variables.
1449 @param VariableName The Console Device Environment Variable.
1450 @param ParentDevicePath The terminal device path to be updated.
1454 TerminalUpdateConsoleDevVariable (
1455 IN CHAR16
*VariableName
,
1456 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1462 TERMINAL_TYPE TerminalType
;
1463 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1464 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1465 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1466 EDKII_SET_VARIABLE_STATUS
*SetVariableStatus
;
1469 // Get global variable and its size according to the name given.
1471 GetEfiGlobalVariable2 (VariableName
, (VOID
**)&Variable
, NULL
);
1472 if (Variable
== NULL
) {
1477 // Append terminal device path onto the variable.
1479 for (TerminalType
= 0; TerminalType
< ARRAY_SIZE (mTerminalType
); TerminalType
++) {
1480 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1481 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
1482 ASSERT (NewVariable
!= NULL
);
1483 if (Variable
!= NULL
) {
1484 FreePool (Variable
);
1487 if (TempDevicePath
!= NULL
) {
1488 FreePool (TempDevicePath
);
1491 Variable
= NewVariable
;
1494 VariableSize
= GetDevicePathSize (Variable
);
1496 Status
= gRT
->SetVariable (
1498 &gEfiGlobalVariableGuid
,
1499 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1504 if (EFI_ERROR (Status
)) {
1505 NameSize
= StrSize (VariableName
);
1506 SetVariableStatus
= AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS
) + NameSize
+ VariableSize
);
1507 if (SetVariableStatus
!= NULL
) {
1508 CopyGuid (&SetVariableStatus
->Guid
, &gEfiGlobalVariableGuid
);
1509 SetVariableStatus
->NameSize
= NameSize
;
1510 SetVariableStatus
->DataSize
= VariableSize
;
1511 SetVariableStatus
->SetStatus
= Status
;
1512 SetVariableStatus
->Attributes
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
;
1513 CopyMem (SetVariableStatus
+ 1, VariableName
, NameSize
);
1514 CopyMem (((UINT8
*) (SetVariableStatus
+ 1)) + NameSize
, Variable
, VariableSize
);
1516 REPORT_STATUS_CODE_EX (
1518 PcdGet32 (PcdErrorCodeSetVariable
),
1521 &gEdkiiStatusCodeDataTypeVariableGuid
,
1523 sizeof (EDKII_SET_VARIABLE_STATUS
) + NameSize
+ VariableSize
1526 FreePool (SetVariableStatus
);
1530 FreePool (Variable
);
1537 Remove terminal device path from Console Device Environment Variables.
1539 @param VariableName Console Device Environment Variables.
1540 @param ParentDevicePath The terminal device path to be updated.
1544 TerminalRemoveConsoleDevVariable (
1545 IN CHAR16
*VariableName
,
1546 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1554 TERMINAL_TYPE TerminalType
;
1555 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1556 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1557 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1558 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1559 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1560 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1565 // Get global variable and its size according to the name given.
1567 GetEfiGlobalVariable2 (VariableName
, (VOID
**)&Variable
, NULL
);
1568 if (Variable
== NULL
) {
1573 OriginalVariable
= Variable
;
1577 // Get first device path instance from Variable
1579 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1580 if (Instance
== NULL
) {
1581 FreePool (OriginalVariable
);
1585 // Loop through all the device path instances of Variable
1589 // Loop through all the terminal types that this driver supports
1592 for (TerminalType
= 0; TerminalType
< ARRAY_SIZE (mTerminalType
); TerminalType
++) {
1594 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1597 // Compare the generated device path to the current device path instance
1599 if (TempDevicePath
!= NULL
) {
1600 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1605 FreePool (TempDevicePath
);
1609 // If a match was not found, then keep the current device path instance
1612 SavedNewVariable
= NewVariable
;
1613 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1614 if (SavedNewVariable
!= NULL
) {
1615 FreePool (SavedNewVariable
);
1619 // Get next device path instance from Variable
1621 FreePool (Instance
);
1622 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1623 } while (Instance
!= NULL
);
1625 FreePool (OriginalVariable
);
1628 VariableSize
= GetDevicePathSize (NewVariable
);
1630 Status
= gRT
->SetVariable (
1632 &gEfiGlobalVariableGuid
,
1633 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1638 // Shrinking variable with existing variable driver implementation shouldn't fail.
1640 ASSERT_EFI_ERROR (Status
);
1643 if (NewVariable
!= NULL
) {
1644 FreePool (NewVariable
);
1651 Build terminal device path according to terminal type.
1653 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1654 @param ParentDevicePath Parent device path.
1655 @param TerminalDevicePath Returned terminal device path, if building successfully.
1657 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1658 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1659 @retval EFI_SUCCESS Build terminal device path successfully.
1663 SetTerminalDevicePath (
1664 IN TERMINAL_TYPE TerminalType
,
1665 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1666 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1669 VENDOR_DEVICE_PATH Node
;
1671 *TerminalDevicePath
= NULL
;
1672 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1673 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1676 // Generate terminal device path node according to terminal type.
1678 switch (TerminalType
) {
1680 case TerminalTypePcAnsi
:
1681 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1684 case TerminalTypeVt100
:
1685 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1688 case TerminalTypeVt100Plus
:
1689 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1692 case TerminalTypeVtUtf8
:
1693 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1696 case TerminalTypeTtyTerm
:
1697 CopyGuid (&Node
.Guid
, &gEfiTtyTermGuid
);
1701 return EFI_UNSUPPORTED
;
1705 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1707 SetDevicePathNodeLength (
1709 sizeof (VENDOR_DEVICE_PATH
)
1713 // Append the terminal node onto parent device path
1714 // to generate a complete terminal device path.
1716 *TerminalDevicePath
= AppendDevicePathNode (
1718 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1720 if (*TerminalDevicePath
== NULL
) {
1721 return EFI_OUT_OF_RESOURCES
;
1728 The user Entry Point for module Terminal. The user code starts with this function.
1730 @param ImageHandle The firmware allocated handle for the EFI image.
1731 @param SystemTable A pointer to the EFI System Table.
1733 @retval EFI_SUCCESS The entry point is executed successfully.
1734 @retval other Some error occurs when executing this entry point.
1740 IN EFI_HANDLE ImageHandle
,
1741 IN EFI_SYSTEM_TABLE
*SystemTable
1747 // Install driver model protocol(s).
1749 Status
= EfiLibInstallDriverBindingComponentName2 (
1752 &gTerminalDriverBinding
,
1754 &gTerminalComponentName
,
1755 &gTerminalComponentName2
1757 ASSERT_EFI_ERROR (Status
);
1763 Check if the device supports hot-plug through its device path.
1765 This function could be updated to check more types of Hot Plug devices.
1766 Currently, it checks USB and PCCard device.
1768 @param DevicePath Pointer to device's device path.
1770 @retval TRUE The devcie is a hot-plug device
1771 @retval FALSE The devcie is not a hot-plug device.
1776 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1779 EFI_DEVICE_PATH_PROTOCOL
*CheckDevicePath
;
1781 CheckDevicePath
= DevicePath
;
1782 while (!IsDevicePathEnd (CheckDevicePath
)) {
1784 // Check device whether is hot plug device or not throught Device Path
1786 if ((DevicePathType (CheckDevicePath
) == MESSAGING_DEVICE_PATH
) &&
1787 (DevicePathSubType (CheckDevicePath
) == MSG_USB_DP
||
1788 DevicePathSubType (CheckDevicePath
) == MSG_USB_CLASS_DP
||
1789 DevicePathSubType (CheckDevicePath
) == MSG_USB_WWID_DP
)) {
1791 // If Device is USB device
1795 if ((DevicePathType (CheckDevicePath
) == HARDWARE_DEVICE_PATH
) &&
1796 (DevicePathSubType (CheckDevicePath
) == HW_PCCARD_DP
)) {
1798 // If Device is PCCard
1803 CheckDevicePath
= NextDevicePathNode (CheckDevicePath
);