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 - 2012, 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
*gTerminalType
[] = {
40 TERMINAL_DEV mTerminalDevTemplate
= {
41 TERMINAL_DEV_SIGNATURE
,
48 TerminalConInReadKeyStroke
,
53 TerminalConOutOutputString
,
54 TerminalConOutTestString
,
55 TerminalConOutQueryMode
,
56 TerminalConOutSetMode
,
57 TerminalConOutSetAttribute
,
58 TerminalConOutClearScreen
,
59 TerminalConOutSetCursorPosition
,
60 TerminalConOutEnableCursor
,
63 { // SimpleTextOutputMode
66 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
), // Attribute
71 NULL
, // TerminalConsoleModeData
78 NULL
, // ControllerNameTable
80 NULL
, // TwoSecondTimeOut
84 { // SimpleTextInputEx
86 TerminalConInReadKeyStrokeEx
,
88 TerminalConInSetState
,
89 TerminalConInRegisterKeyNotify
,
90 TerminalConInUnregisterKeyNotify
,
98 TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData
[] = {
101 // New modes can be added here.
106 Test to see if this driver supports Controller.
108 @param This Protocol instance pointer.
109 @param Controller Handle of device to test
110 @param RemainingDevicePath Optional parameter use to pick a specific child
113 @retval EFI_SUCCESS This driver supports this device.
114 @retval EFI_ALREADY_STARTED This driver is already running on this device.
115 @retval other This driver does not support this device.
120 TerminalDriverBindingSupported (
121 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
122 IN EFI_HANDLE Controller
,
123 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
127 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
128 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
129 VENDOR_DEVICE_PATH
*Node
;
132 // If remaining device path is not NULL, then make sure it is a
133 // device path that describes a terminal communications protocol.
135 if (RemainingDevicePath
!= NULL
) {
137 // Check if RemainingDevicePath is the End of Device Path Node,
138 // if yes, go on checking other conditions
140 if (!IsDevicePathEnd (RemainingDevicePath
)) {
142 // If RemainingDevicePath isn't the End of Device Path Node,
143 // check its validation
145 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
147 if (Node
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
148 Node
->Header
.SubType
!= MSG_VENDOR_DP
||
149 DevicePathNodeLength(&Node
->Header
) != sizeof(VENDOR_DEVICE_PATH
)) {
151 return EFI_UNSUPPORTED
;
155 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types
157 if (!CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
) &&
158 !CompareGuid (&Node
->Guid
, &gEfiVT100Guid
) &&
159 !CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
) &&
160 !CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
162 return EFI_UNSUPPORTED
;
167 // Open the IO Abstraction(s) needed to perform the supported test
168 // The Controller must support the Serial I/O Protocol.
169 // This driver is a bus driver with at most 1 child device, so it is
170 // ok for it to be already started.
172 Status
= gBS
->OpenProtocol (
174 &gEfiSerialIoProtocolGuid
,
176 This
->DriverBindingHandle
,
178 EFI_OPEN_PROTOCOL_BY_DRIVER
180 if (Status
== EFI_ALREADY_STARTED
) {
184 if (EFI_ERROR (Status
)) {
189 // Close the I/O Abstraction(s) used to perform the supported test
193 &gEfiSerialIoProtocolGuid
,
194 This
->DriverBindingHandle
,
199 // Open the EFI Device Path protocol needed to perform the supported test
201 Status
= gBS
->OpenProtocol (
203 &gEfiDevicePathProtocolGuid
,
204 (VOID
**) &ParentDevicePath
,
205 This
->DriverBindingHandle
,
207 EFI_OPEN_PROTOCOL_BY_DRIVER
209 if (Status
== EFI_ALREADY_STARTED
) {
213 if (EFI_ERROR (Status
)) {
218 // Close protocol, don't use device path protocol in the Support() function
222 &gEfiDevicePathProtocolGuid
,
223 This
->DriverBindingHandle
,
231 Build the terminal device path for the child device according to the
234 @param ParentDevicePath Parent device path.
235 @param RemainingDevicePath A specific child device.
237 @return The child device path built.
240 EFI_DEVICE_PATH_PROTOCOL
*
242 BuildTerminalDevpath (
243 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
244 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
247 EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
;
249 VENDOR_DEVICE_PATH
*Node
;
252 TerminalDevicePath
= NULL
;
253 TerminalType
= PCANSITYPE
;
256 // Use the RemainingDevicePath to determine the terminal type
258 Node
= (VENDOR_DEVICE_PATH
*) RemainingDevicePath
;
260 TerminalType
= PCANSITYPE
;
262 } else if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
264 TerminalType
= PCANSITYPE
;
266 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
268 TerminalType
= VT100TYPE
;
270 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
272 TerminalType
= VT100PLUSTYPE
;
274 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
276 TerminalType
= VTUTF8TYPE
;
283 // Build the device path for the child device
285 Status
= SetTerminalDevicePath (
290 if (EFI_ERROR (Status
)) {
293 return TerminalDevicePath
;
297 Compare a device path data structure to that of all the nodes of a
298 second device path instance.
300 @param Multi A pointer to a multi-instance device path data structure.
301 @param Single A pointer to a single-instance device path data structure.
303 @retval TRUE If the Single is contained within Multi.
304 @retval FALSE The Single is not match within Multi.
309 IN EFI_DEVICE_PATH_PROTOCOL
*Multi
,
310 IN EFI_DEVICE_PATH_PROTOCOL
*Single
313 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
314 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
318 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
320 // Search for the match of 'Single' in 'Multi'
322 while (DevicePathInst
!= NULL
) {
324 // If the single device path is found in multiple device paths,
327 if (CompareMem (Single
, DevicePathInst
, Size
) == 0) {
328 FreePool (DevicePathInst
);
332 FreePool (DevicePathInst
);
333 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
340 Check whether the terminal device path is in the global variable.
342 @param VariableName Pointer to one global variable.
343 @param TerminalDevicePath Pointer to the terminal device's device path.
345 @retval TRUE The devcie is in the global variable.
346 @retval FALSE The devcie is not in the global variable.
350 IsTerminalInConsoleVariable (
351 IN CHAR16
*VariableName
,
352 IN EFI_DEVICE_PATH_PROTOCOL
*TerminalDevicePath
355 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
359 // Get global variable and its size according to the name given.
361 GetEfiGlobalVariable2 (VariableName
, (VOID
**)&Variable
, NULL
);
362 if (Variable
== NULL
) {
367 // Check whether the terminal device path is one of the variable instances.
369 ReturnFlag
= MatchDevicePaths (Variable
, TerminalDevicePath
);
377 Free notify functions list.
379 @param ListHead The list head
381 @retval EFI_SUCCESS Free the notify list successfully.
382 @retval EFI_INVALID_PARAMETER ListHead is NULL.
386 TerminalFreeNotifyList (
387 IN OUT LIST_ENTRY
*ListHead
390 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
392 if (ListHead
== NULL
) {
393 return EFI_INVALID_PARAMETER
;
395 while (!IsListEmpty (ListHead
)) {
397 ListHead
->ForwardLink
,
398 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
400 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
402 RemoveEntryList (ListHead
->ForwardLink
);
403 FreePool (NotifyNode
);
410 Initialize all the text modes which the terminal console supports.
412 It returns information for available text modes that the terminal can support.
414 @param[out] TextModeCount The total number of text modes that terminal console supports.
415 @param[out] TextModeData The buffer to the text modes column and row information.
416 Caller is responsible to free it when it's non-NULL.
418 @retval EFI_SUCCESS The supporting mode information is returned.
419 @retval EFI_INVALID_PARAMETER The parameters are invalid.
423 InitializeTerminalConsoleTextMode (
424 OUT UINTN
*TextModeCount
,
425 OUT TERMINAL_CONSOLE_MODE_DATA
**TextModeData
430 TERMINAL_CONSOLE_MODE_DATA
*ModeBuffer
;
431 TERMINAL_CONSOLE_MODE_DATA
*NewModeBuffer
;
435 if ((TextModeCount
== NULL
) || (TextModeData
== NULL
)) {
436 return EFI_INVALID_PARAMETER
;
439 Count
= sizeof (mTerminalConsoleModeData
) / sizeof (TERMINAL_CONSOLE_MODE_DATA
);
442 // Get defined mode buffer pointer.
444 ModeBuffer
= mTerminalConsoleModeData
;
447 // Here we make sure that the final mode exposed does not include the duplicated modes,
448 // and does not include the invalid modes which exceed the max column and row.
449 // Reserve 2 modes for 80x25, 80x50 of terminal console.
451 NewModeBuffer
= AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA
) * (Count
+ 2));
452 ASSERT (NewModeBuffer
!= NULL
);
455 // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.
459 NewModeBuffer
[ValidCount
].Columns
= 80;
460 NewModeBuffer
[ValidCount
].Rows
= 25;
463 NewModeBuffer
[ValidCount
].Columns
= 80;
464 NewModeBuffer
[ValidCount
].Rows
= 50;
468 // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.
470 for (Index
= 0; Index
< Count
; Index
++) {
471 if ((ModeBuffer
[Index
].Columns
== 0) || (ModeBuffer
[Index
].Rows
== 0)) {
473 // Skip the pre-defined mode which is invalid.
477 for (ValidIndex
= 0; ValidIndex
< ValidCount
; ValidIndex
++) {
478 if ((ModeBuffer
[Index
].Columns
== NewModeBuffer
[ValidIndex
].Columns
) &&
479 (ModeBuffer
[Index
].Rows
== NewModeBuffer
[ValidIndex
].Rows
)) {
481 // Skip the duplicated mode.
486 if (ValidIndex
== ValidCount
) {
487 NewModeBuffer
[ValidCount
].Columns
= ModeBuffer
[Index
].Columns
;
488 NewModeBuffer
[ValidCount
].Rows
= ModeBuffer
[Index
].Rows
;
494 for (Index
= 0; Index
< ValidCount
; Index
++) {
495 DEBUG ((EFI_D_INFO
, "Terminal - Mode %d, Column = %d, Row = %d\n",
496 Index
, NewModeBuffer
[Index
].Columns
, NewModeBuffer
[Index
].Rows
));
501 // Return valid mode count and mode information buffer.
503 *TextModeCount
= ValidCount
;
504 *TextModeData
= NewModeBuffer
;
509 Start this driver on Controller by opening a Serial IO protocol,
510 reading Device Path, and creating a child handle with a Simple Text In,
511 Simple Text In Ex and Simple Text Out protocol, and device path protocol.
512 And store Console Device Environment Variables.
514 @param This Protocol instance pointer.
515 @param Controller Handle of device to bind driver to
516 @param RemainingDevicePath Optional parameter use to pick a specific child
519 @retval EFI_SUCCESS This driver is added to Controller.
520 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
521 @retval other This driver does not support this device.
526 TerminalDriverBindingStart (
527 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
528 IN EFI_HANDLE Controller
,
529 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
533 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
534 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
535 VENDOR_DEVICE_PATH
*Node
;
536 VENDOR_DEVICE_PATH
*DefaultNode
;
537 EFI_SERIAL_IO_MODE
*Mode
;
538 UINTN SerialInTimeOut
;
539 TERMINAL_DEV
*TerminalDevice
;
541 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
544 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
545 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
546 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleTextInput
;
547 BOOLEAN ConInSelected
;
548 BOOLEAN ConOutSelected
;
549 BOOLEAN NullRemaining
;
550 BOOLEAN SimTxtInInstalled
;
551 BOOLEAN SimTxtOutInstalled
;
555 TerminalDevice
= NULL
;
557 ConInSelected
= FALSE
;
558 ConOutSelected
= FALSE
;
559 NullRemaining
= TRUE
;
560 SimTxtInInstalled
= FALSE
;
561 SimTxtOutInstalled
= FALSE
;
564 // Get the Device Path Protocol to build the device path of the child device
566 Status
= gBS
->OpenProtocol (
568 &gEfiDevicePathProtocolGuid
,
569 (VOID
**) &ParentDevicePath
,
570 This
->DriverBindingHandle
,
572 EFI_OPEN_PROTOCOL_BY_DRIVER
574 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
579 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.
581 Status
= gBS
->OpenProtocol (
583 &gEfiSerialIoProtocolGuid
,
585 This
->DriverBindingHandle
,
587 EFI_OPEN_PROTOCOL_BY_DRIVER
589 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
593 if (Status
!= EFI_ALREADY_STARTED
) {
595 // the serial I/O protocol never be opened before, it is the first
596 // time to start the serial Io controller
602 // Serial I/O is not already open by this driver, then tag the handle
603 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and
604 // StdErrDev variables with the list of possible terminal types on this
607 Status
= gBS
->OpenProtocol (
611 This
->DriverBindingHandle
,
613 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
615 if (EFI_ERROR (Status
)) {
616 Status
= gBS
->InstallMultipleProtocolInterfaces (
619 DuplicateDevicePath (ParentDevicePath
),
622 if (EFI_ERROR (Status
)) {
626 if (!IsHotPlugDevice (ParentDevicePath
)) {
628 // if the serial device is a hot plug device, do not update the
629 // ConInDev, ConOutDev, and StdErrDev variables.
631 TerminalUpdateConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
632 TerminalUpdateConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
633 TerminalUpdateConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
638 // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols
640 // Simple In/Out Protocol will not be installed onto the handle if the
641 // device path to the handle is not present in the ConIn/ConOut
642 // environment variable. But If RemainingDevicePath is NULL, then always
643 // produce both Simple In and Simple Text Output Protocols. This is required
644 // for the connect all sequences to make sure all possible consoles are
645 // produced no matter what the current values of ConIn, ConOut, or StdErr are.
647 if (RemainingDevicePath
== NULL
) {
648 NullRemaining
= TRUE
;
651 DevicePath
= BuildTerminalDevpath (ParentDevicePath
, RemainingDevicePath
);
652 if (DevicePath
!= NULL
) {
653 ConInSelected
= IsTerminalInConsoleVariable (L
"ConIn", DevicePath
);
654 ConOutSelected
= IsTerminalInConsoleVariable (L
"ConOut", DevicePath
);
655 FreePool (DevicePath
);
660 // Not create the child terminal handle if both Simple In/In Ex and
661 // Simple text Out protocols are not required to be published
663 if ((!ConInSelected
)&&(!ConOutSelected
)&&(!NullRemaining
)) {
668 // create the child terminal handle during first entry
672 // First enther the start funciton
676 // Make sure a child handle does not already exist. This driver can only
677 // produce one child per serial port.
679 Status
= gBS
->OpenProtocolInformation (
681 &gEfiSerialIoProtocolGuid
,
685 if (!EFI_ERROR (Status
)) {
686 Status
= EFI_SUCCESS
;
687 for (Index
= 0; Index
< EntryCount
; Index
++) {
688 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
689 Status
= EFI_ALREADY_STARTED
;
693 FreePool (OpenInfoBuffer
);
694 if (EFI_ERROR (Status
)) {
700 // If RemainingDevicePath is NULL, then create default device path node
702 if (RemainingDevicePath
== NULL
) {
703 DefaultNode
= AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH
));
704 if (DefaultNode
== NULL
) {
705 Status
= EFI_OUT_OF_RESOURCES
;
709 TerminalType
= PcdGet8 (PcdDefaultTerminalType
);
711 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)
713 ASSERT (TerminalType
<= VTUTF8TYPE
);
715 CopyMem (&DefaultNode
->Guid
, gTerminalType
[TerminalType
], sizeof (EFI_GUID
));
716 RemainingDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DefaultNode
;
717 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
719 // If RemainingDevicePath isn't the End of Device Path Node,
720 // Use the RemainingDevicePath to determine the terminal type
722 Node
= (VENDOR_DEVICE_PATH
*)RemainingDevicePath
;
723 if (CompareGuid (&Node
->Guid
, &gEfiPcAnsiGuid
)) {
724 TerminalType
= PCANSITYPE
;
725 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100Guid
)) {
726 TerminalType
= VT100TYPE
;
727 } else if (CompareGuid (&Node
->Guid
, &gEfiVT100PlusGuid
)) {
728 TerminalType
= VT100PLUSTYPE
;
729 } else if (CompareGuid (&Node
->Guid
, &gEfiVTUTF8Guid
)) {
730 TerminalType
= VTUTF8TYPE
;
736 // If RemainingDevicePath is the End of Device Path Node,
737 // skip enumerate any device and return EFI_SUCESSS
743 // Initialize the Terminal Dev
745 TerminalDevice
= AllocateCopyPool (sizeof (TERMINAL_DEV
), &mTerminalDevTemplate
);
746 if (TerminalDevice
== NULL
) {
747 Status
= EFI_OUT_OF_RESOURCES
;
751 TerminalDevice
->TerminalType
= TerminalType
;
752 TerminalDevice
->SerialIo
= SerialIo
;
754 InitializeListHead (&TerminalDevice
->NotifyList
);
755 Status
= gBS
->CreateEvent (
758 TerminalConInWaitForKeyEx
,
760 &TerminalDevice
->SimpleInputEx
.WaitForKeyEx
762 if (EFI_ERROR (Status
)) {
766 Status
= gBS
->CreateEvent (
769 TerminalConInWaitForKey
,
771 &TerminalDevice
->SimpleInput
.WaitForKey
773 if (EFI_ERROR (Status
)) {
777 // Allocates and initializes the FIFO buffer to be zero, used for accommodating
778 // the pre-read pending characters.
780 TerminalDevice
->RawFiFo
= AllocateZeroPool (sizeof (RAW_DATA_FIFO
));
781 if (TerminalDevice
->RawFiFo
== NULL
) {
784 TerminalDevice
->UnicodeFiFo
= AllocateZeroPool (sizeof (UNICODE_FIFO
));
785 if (TerminalDevice
->UnicodeFiFo
== NULL
) {
788 TerminalDevice
->EfiKeyFiFo
= AllocateZeroPool (sizeof (EFI_KEY_FIFO
));
789 if (TerminalDevice
->EfiKeyFiFo
== NULL
) {
794 // Set the timeout value of serial buffer for
795 // keystroke response performance issue
797 Mode
= TerminalDevice
->SerialIo
->Mode
;
800 if (Mode
->BaudRate
!= 0) {
801 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
804 Status
= TerminalDevice
->SerialIo
->SetAttributes (
805 TerminalDevice
->SerialIo
,
807 Mode
->ReceiveFifoDepth
,
808 (UINT32
) SerialInTimeOut
,
809 (EFI_PARITY_TYPE
) (Mode
->Parity
),
810 (UINT8
) Mode
->DataBits
,
811 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
813 if (EFI_ERROR (Status
)) {
815 // if set attributes operation fails, invalidate
816 // the value of SerialInTimeOut,thus make it
817 // inconsistent with the default timeout value
818 // of serial buffer. This will invoke the recalculation
819 // in the readkeystroke routine.
821 TerminalDevice
->SerialInTimeOut
= 0;
823 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
826 // Set Simple Text Output Protocol from template.
828 SimpleTextOutput
= CopyMem (
829 &TerminalDevice
->SimpleTextOutput
,
830 &mTerminalDevTemplate
.SimpleTextOutput
,
831 sizeof (mTerminalDevTemplate
.SimpleTextOutput
)
833 SimpleTextOutput
->Mode
= &TerminalDevice
->SimpleTextOutputMode
;
835 Status
= InitializeTerminalConsoleTextMode (&ModeCount
, &TerminalDevice
->TerminalConsoleModeData
);
836 if (EFI_ERROR (Status
)) {
839 TerminalDevice
->SimpleTextOutputMode
.MaxMode
= (INT32
) ModeCount
;
842 // For terminal devices, cursor is always visible
844 TerminalDevice
->SimpleTextOutputMode
.CursorVisible
= TRUE
;
845 Status
= TerminalConOutSetAttribute (
847 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
849 if (EFI_ERROR (Status
)) {
854 // Build the component name for the child device
856 TerminalDevice
->ControllerNameTable
= NULL
;
857 switch (TerminalDevice
->TerminalType
) {
861 gTerminalComponentName
.SupportedLanguages
,
862 &TerminalDevice
->ControllerNameTable
,
863 (CHAR16
*)L
"PC-ANSI Serial Console",
868 gTerminalComponentName2
.SupportedLanguages
,
869 &TerminalDevice
->ControllerNameTable
,
870 (CHAR16
*)L
"PC-ANSI Serial Console",
879 gTerminalComponentName
.SupportedLanguages
,
880 &TerminalDevice
->ControllerNameTable
,
881 (CHAR16
*)L
"VT-100 Serial Console",
886 gTerminalComponentName2
.SupportedLanguages
,
887 &TerminalDevice
->ControllerNameTable
,
888 (CHAR16
*)L
"VT-100 Serial Console",
897 gTerminalComponentName
.SupportedLanguages
,
898 &TerminalDevice
->ControllerNameTable
,
899 (CHAR16
*)L
"VT-100+ Serial Console",
904 gTerminalComponentName2
.SupportedLanguages
,
905 &TerminalDevice
->ControllerNameTable
,
906 (CHAR16
*)L
"VT-100+ Serial Console",
915 gTerminalComponentName
.SupportedLanguages
,
916 &TerminalDevice
->ControllerNameTable
,
917 (CHAR16
*)L
"VT-UTF8 Serial Console",
922 gTerminalComponentName2
.SupportedLanguages
,
923 &TerminalDevice
->ControllerNameTable
,
924 (CHAR16
*)L
"VT-UTF8 Serial Console",
932 // Build the device path for the child device
934 Status
= SetTerminalDevicePath (
935 TerminalDevice
->TerminalType
,
937 &TerminalDevice
->DevicePath
939 if (EFI_ERROR (Status
)) {
943 Status
= TerminalConOutReset (SimpleTextOutput
, FALSE
);
944 if (EFI_ERROR (Status
)) {
948 Status
= TerminalConOutSetMode (SimpleTextOutput
, 0);
949 if (EFI_ERROR (Status
)) {
953 Status
= TerminalConOutEnableCursor (SimpleTextOutput
, TRUE
);
954 if (EFI_ERROR (Status
)) {
958 Status
= gBS
->CreateEvent (
959 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
961 TerminalConInTimerHandler
,
963 &TerminalDevice
->TimerEvent
965 ASSERT_EFI_ERROR (Status
);
967 Status
= gBS
->SetTimer (
968 TerminalDevice
->TimerEvent
,
970 KEYBOARD_TIMER_INTERVAL
972 ASSERT_EFI_ERROR (Status
);
974 Status
= gBS
->CreateEvent (
979 &TerminalDevice
->TwoSecondTimeOut
981 ASSERT_EFI_ERROR (Status
);
983 Status
= gBS
->InstallProtocolInterface (
984 &TerminalDevice
->Handle
,
985 &gEfiDevicePathProtocolGuid
,
986 EFI_NATIVE_INTERFACE
,
987 TerminalDevice
->DevicePath
989 if (EFI_ERROR (Status
)) {
994 // Register the Parent-Child relationship via
995 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
997 Status
= gBS
->OpenProtocol (
999 &gEfiSerialIoProtocolGuid
,
1000 (VOID
**) &TerminalDevice
->SerialIo
,
1001 This
->DriverBindingHandle
,
1002 TerminalDevice
->Handle
,
1003 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1005 if (EFI_ERROR (Status
)) {
1011 // Find the child handle, and get its TerminalDevice private data
1013 Status
= gBS
->OpenProtocolInformation (
1015 &gEfiSerialIoProtocolGuid
,
1019 if (!EFI_ERROR (Status
)) {
1020 Status
= EFI_NOT_FOUND
;
1021 ASSERT (OpenInfoBuffer
!= NULL
);
1022 for (Index
= 0; Index
< EntryCount
; Index
++) {
1023 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1025 // Find the child terminal handle.
1026 // Test whether the SimpleTxtIn and SimpleTxtOut have been published
1028 Status
= gBS
->OpenProtocol (
1029 OpenInfoBuffer
[Index
].ControllerHandle
,
1030 &gEfiSimpleTextInProtocolGuid
,
1031 (VOID
**) &SimpleTextInput
,
1032 This
->DriverBindingHandle
,
1033 OpenInfoBuffer
[Index
].ControllerHandle
,
1034 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1036 if (!EFI_ERROR (Status
)) {
1037 SimTxtInInstalled
= TRUE
;
1038 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput
);
1041 Status
= gBS
->OpenProtocol (
1042 OpenInfoBuffer
[Index
].ControllerHandle
,
1043 &gEfiSimpleTextOutProtocolGuid
,
1044 (VOID
**) &SimpleTextOutput
,
1045 This
->DriverBindingHandle
,
1046 OpenInfoBuffer
[Index
].ControllerHandle
,
1047 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1049 if (!EFI_ERROR (Status
)) {
1050 SimTxtOutInstalled
= TRUE
;
1051 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
1053 Status
= EFI_SUCCESS
;
1058 FreePool (OpenInfoBuffer
);
1059 if (EFI_ERROR (Status
)) {
1066 ASSERT (TerminalDevice
!= NULL
);
1068 // Only do the reset if the device path is in the Conout variable
1070 if (ConInSelected
&& !SimTxtInInstalled
) {
1071 Status
= TerminalDevice
->SimpleInput
.Reset (
1072 &TerminalDevice
->SimpleInput
,
1075 if (EFI_ERROR (Status
)) {
1077 // Need to report Error Code first
1084 // Only output the configure string to remote terminal if the device path
1085 // is in the Conout variable
1087 if (ConOutSelected
&& !SimTxtOutInstalled
) {
1088 Status
= TerminalDevice
->SimpleTextOutput
.SetAttribute (
1089 &TerminalDevice
->SimpleTextOutput
,
1090 EFI_TEXT_ATTR (EFI_LIGHTGRAY
, EFI_BLACK
)
1092 if (EFI_ERROR (Status
)) {
1096 Status
= TerminalDevice
->SimpleTextOutput
.Reset (
1097 &TerminalDevice
->SimpleTextOutput
,
1100 if (EFI_ERROR (Status
)) {
1104 Status
= TerminalDevice
->SimpleTextOutput
.SetMode (
1105 &TerminalDevice
->SimpleTextOutput
,
1108 if (EFI_ERROR (Status
)) {
1112 Status
= TerminalDevice
->SimpleTextOutput
.EnableCursor (
1113 &TerminalDevice
->SimpleTextOutput
,
1116 if (EFI_ERROR (Status
)) {
1122 // Simple In/Out Protocol will not be installed onto the handle if the
1123 // device path to the handle is not present in the ConIn/ConOut
1124 // environment variable. But If RemainingDevicePath is NULL, then always
1125 // produce both Simple In and Simple Text Output Protocols. This is required
1126 // for the connect all sequences to make sure all possible consoles are
1127 // produced no matter what the current values of ConIn, ConOut, or StdErr are.
1129 if (!SimTxtInInstalled
&& (ConInSelected
|| NullRemaining
)) {
1130 Status
= gBS
->InstallMultipleProtocolInterfaces (
1131 &TerminalDevice
->Handle
,
1132 &gEfiSimpleTextInProtocolGuid
,
1133 &TerminalDevice
->SimpleInput
,
1134 &gEfiSimpleTextInputExProtocolGuid
,
1135 &TerminalDevice
->SimpleInputEx
,
1138 if (EFI_ERROR (Status
)) {
1143 if (!SimTxtOutInstalled
&& (ConOutSelected
|| NullRemaining
)) {
1144 Status
= gBS
->InstallProtocolInterface (
1145 &TerminalDevice
->Handle
,
1146 &gEfiSimpleTextOutProtocolGuid
,
1147 EFI_NATIVE_INTERFACE
,
1148 &TerminalDevice
->SimpleTextOutput
1150 if (EFI_ERROR (Status
)) {
1154 if (DefaultNode
!= NULL
) {
1155 FreePool (DefaultNode
);
1162 // Report error code before exiting
1164 DevicePath
= ParentDevicePath
;
1165 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1166 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1167 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
1173 // Use the Stop() function to free all resources allocated in Start()
1175 if (TerminalDevice
!= NULL
) {
1177 if (TerminalDevice
->Handle
!= NULL
) {
1178 This
->Stop (This
, Controller
, 1, &TerminalDevice
->Handle
);
1181 if (TerminalDevice
->TwoSecondTimeOut
!= NULL
) {
1182 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
1185 if (TerminalDevice
->TimerEvent
!= NULL
) {
1186 gBS
->CloseEvent (TerminalDevice
->TimerEvent
);
1189 if (TerminalDevice
->SimpleInput
.WaitForKey
!= NULL
) {
1190 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
1193 if (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
1194 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
1197 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
1199 if (TerminalDevice
->RawFiFo
!= NULL
) {
1200 FreePool (TerminalDevice
->RawFiFo
);
1202 if (TerminalDevice
->UnicodeFiFo
!= NULL
) {
1203 FreePool (TerminalDevice
->UnicodeFiFo
);
1205 if (TerminalDevice
->EfiKeyFiFo
!= NULL
) {
1206 FreePool (TerminalDevice
->EfiKeyFiFo
);
1209 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
1210 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
1213 if (TerminalDevice
->DevicePath
!= NULL
) {
1214 FreePool (TerminalDevice
->DevicePath
);
1217 if (TerminalDevice
->TerminalConsoleModeData
!= NULL
) {
1218 FreePool (TerminalDevice
->TerminalConsoleModeData
);
1221 FreePool (TerminalDevice
);
1225 if (DefaultNode
!= NULL
) {
1226 FreePool (DefaultNode
);
1229 This
->Stop (This
, Controller
, 0, NULL
);
1235 Stop this driver on Controller by closing Simple Text In, Simple Text
1236 In Ex, Simple Text Out protocol, and removing parent device path from
1237 Console Device Environment Variables.
1239 @param This Protocol instance pointer.
1240 @param Controller Handle of device to stop driver on
1241 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1242 children is zero stop the entire bus driver.
1243 @param ChildHandleBuffer List of Child Handles to Stop.
1245 @retval EFI_SUCCESS This driver is removed Controller.
1246 @retval other This driver could not be removed from this device.
1251 TerminalDriverBindingStop (
1252 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1253 IN EFI_HANDLE Controller
,
1254 IN UINTN NumberOfChildren
,
1255 IN EFI_HANDLE
*ChildHandleBuffer
1260 BOOLEAN AllChildrenStopped
;
1261 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*SimpleTextOutput
;
1262 TERMINAL_DEV
*TerminalDevice
;
1263 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1264 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1265 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1267 Status
= gBS
->HandleProtocol (
1269 &gEfiDevicePathProtocolGuid
,
1270 (VOID
**) &DevicePath
1272 if (EFI_ERROR (Status
)) {
1277 // Complete all outstanding transactions to Controller.
1278 // Don't allow any new transaction to Controller to be started.
1280 if (NumberOfChildren
== 0) {
1282 // Close the bus driver
1284 Status
= gBS
->OpenProtocol (
1287 (VOID
**) &ParentDevicePath
,
1288 This
->DriverBindingHandle
,
1290 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1292 if (!EFI_ERROR (Status
)) {
1294 // Remove Parent Device Path from
1295 // the Console Device Environment Variables
1297 TerminalRemoveConsoleDevVariable (L
"ConInDev", ParentDevicePath
);
1298 TerminalRemoveConsoleDevVariable (L
"ConOutDev", ParentDevicePath
);
1299 TerminalRemoveConsoleDevVariable (L
"ErrOutDev", ParentDevicePath
);
1302 // Uninstall the Terminal Driver's GUID Tag from the Serial controller
1304 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1312 // Free the ParentDevicePath that was duplicated in Start()
1314 if (!EFI_ERROR (Status
)) {
1315 FreePool (ParentDevicePath
);
1319 gBS
->CloseProtocol (
1321 &gEfiSerialIoProtocolGuid
,
1322 This
->DriverBindingHandle
,
1326 gBS
->CloseProtocol (
1328 &gEfiDevicePathProtocolGuid
,
1329 This
->DriverBindingHandle
,
1336 AllChildrenStopped
= TRUE
;
1338 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1340 Status
= gBS
->OpenProtocol (
1341 ChildHandleBuffer
[Index
],
1342 &gEfiSimpleTextOutProtocolGuid
,
1343 (VOID
**) &SimpleTextOutput
,
1344 This
->DriverBindingHandle
,
1345 ChildHandleBuffer
[Index
],
1346 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1348 if (!EFI_ERROR (Status
)) {
1350 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput
);
1352 gBS
->CloseProtocol (
1354 &gEfiSerialIoProtocolGuid
,
1355 This
->DriverBindingHandle
,
1356 ChildHandleBuffer
[Index
]
1359 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1360 ChildHandleBuffer
[Index
],
1361 &gEfiSimpleTextInProtocolGuid
,
1362 &TerminalDevice
->SimpleInput
,
1363 &gEfiSimpleTextInputExProtocolGuid
,
1364 &TerminalDevice
->SimpleInputEx
,
1365 &gEfiSimpleTextOutProtocolGuid
,
1366 &TerminalDevice
->SimpleTextOutput
,
1367 &gEfiDevicePathProtocolGuid
,
1368 TerminalDevice
->DevicePath
,
1371 if (EFI_ERROR (Status
)) {
1374 &gEfiSerialIoProtocolGuid
,
1375 (VOID
**) &SerialIo
,
1376 This
->DriverBindingHandle
,
1377 ChildHandleBuffer
[Index
],
1378 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1382 if (TerminalDevice
->ControllerNameTable
!= NULL
) {
1383 FreeUnicodeStringTable (TerminalDevice
->ControllerNameTable
);
1386 gBS
->CloseEvent (TerminalDevice
->TimerEvent
);
1387 gBS
->CloseEvent (TerminalDevice
->TwoSecondTimeOut
);
1388 gBS
->CloseEvent (TerminalDevice
->SimpleInput
.WaitForKey
);
1389 gBS
->CloseEvent (TerminalDevice
->SimpleInputEx
.WaitForKeyEx
);
1390 TerminalFreeNotifyList (&TerminalDevice
->NotifyList
);
1391 FreePool (TerminalDevice
->DevicePath
);
1392 if (TerminalDevice
->TerminalConsoleModeData
!= NULL
) {
1393 FreePool (TerminalDevice
->TerminalConsoleModeData
);
1395 FreePool (TerminalDevice
);
1399 if (EFI_ERROR (Status
)) {
1400 AllChildrenStopped
= FALSE
;
1404 if (!AllChildrenStopped
) {
1405 return EFI_DEVICE_ERROR
;
1412 Update terminal device path in Console Device Environment Variables.
1414 @param VariableName The Console Device Environment Variable.
1415 @param ParentDevicePath The terminal device path to be updated.
1419 TerminalUpdateConsoleDevVariable (
1420 IN CHAR16
*VariableName
,
1421 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1427 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1428 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1429 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1432 // Get global variable and its size according to the name given.
1434 GetEfiGlobalVariable2 (VariableName
, (VOID
**)&Variable
, NULL
);
1435 if (Variable
== NULL
) {
1440 // Append terminal device path onto the variable.
1442 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1443 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1444 NewVariable
= AppendDevicePathInstance (Variable
, TempDevicePath
);
1445 if (Variable
!= NULL
) {
1446 FreePool (Variable
);
1449 if (TempDevicePath
!= NULL
) {
1450 FreePool (TempDevicePath
);
1453 Variable
= NewVariable
;
1456 VariableSize
= GetDevicePathSize (Variable
);
1458 Status
= gRT
->SetVariable (
1460 &gEfiGlobalVariableGuid
,
1461 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1465 ASSERT_EFI_ERROR (Status
);
1466 FreePool (Variable
);
1473 Remove terminal device path from Console Device Environment Variables.
1475 @param VariableName Console Device Environment Variables.
1476 @param ParentDevicePath The terminal device path to be updated.
1480 TerminalRemoveConsoleDevVariable (
1481 IN CHAR16
*VariableName
,
1482 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
1491 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1492 EFI_DEVICE_PATH_PROTOCOL
*Variable
;
1493 EFI_DEVICE_PATH_PROTOCOL
*OriginalVariable
;
1494 EFI_DEVICE_PATH_PROTOCOL
*NewVariable
;
1495 EFI_DEVICE_PATH_PROTOCOL
*SavedNewVariable
;
1496 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1501 // Get global variable and its size according to the name given.
1503 GetEfiGlobalVariable2 (VariableName
, (VOID
**)&Variable
, NULL
);
1504 if (Variable
== NULL
) {
1509 OriginalVariable
= Variable
;
1513 // Get first device path instance from Variable
1515 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1516 if (Instance
== NULL
) {
1517 FreePool (OriginalVariable
);
1521 // Loop through all the device path instances of Variable
1525 // Loop through all the terminal types that this driver supports
1528 for (TerminalType
= PCANSITYPE
; TerminalType
<= VTUTF8TYPE
; TerminalType
++) {
1530 SetTerminalDevicePath (TerminalType
, ParentDevicePath
, &TempDevicePath
);
1533 // Compare the generated device path to the current device path instance
1535 if (TempDevicePath
!= NULL
) {
1536 if (CompareMem (Instance
, TempDevicePath
, InstanceSize
) == 0) {
1541 FreePool (TempDevicePath
);
1545 // If a match was not found, then keep the current device path instance
1548 SavedNewVariable
= NewVariable
;
1549 NewVariable
= AppendDevicePathInstance (NewVariable
, Instance
);
1550 if (SavedNewVariable
!= NULL
) {
1551 FreePool (SavedNewVariable
);
1555 // Get next device path instance from Variable
1557 FreePool (Instance
);
1558 Instance
= GetNextDevicePathInstance (&Variable
, &InstanceSize
);
1559 } while (Instance
!= NULL
);
1561 FreePool (OriginalVariable
);
1564 VariableSize
= GetDevicePathSize (NewVariable
);
1566 Status
= gRT
->SetVariable (
1568 &gEfiGlobalVariableGuid
,
1569 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1573 ASSERT_EFI_ERROR (Status
);
1576 if (NewVariable
!= NULL
) {
1577 FreePool (NewVariable
);
1584 Build terminal device path according to terminal type.
1586 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.
1587 @param ParentDevicePath Parent device path.
1588 @param TerminalDevicePath Returned terminal device path, if building successfully.
1590 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.
1591 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.
1592 @retval EFI_SUCCESS Build terminal device path successfully.
1596 SetTerminalDevicePath (
1597 IN UINT8 TerminalType
,
1598 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
1599 OUT EFI_DEVICE_PATH_PROTOCOL
**TerminalDevicePath
1602 VENDOR_DEVICE_PATH Node
;
1604 *TerminalDevicePath
= NULL
;
1605 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1606 Node
.Header
.SubType
= MSG_VENDOR_DP
;
1609 // Generate terminal device path node according to terminal type.
1611 switch (TerminalType
) {
1614 CopyGuid (&Node
.Guid
, &gEfiPcAnsiGuid
);
1618 CopyGuid (&Node
.Guid
, &gEfiVT100Guid
);
1622 CopyGuid (&Node
.Guid
, &gEfiVT100PlusGuid
);
1626 CopyGuid (&Node
.Guid
, &gEfiVTUTF8Guid
);
1630 return EFI_UNSUPPORTED
;
1634 // Get VENDOR_DEVCIE_PATH size and put into Node.Header
1636 SetDevicePathNodeLength (
1638 sizeof (VENDOR_DEVICE_PATH
)
1642 // Append the terminal node onto parent device path
1643 // to generate a complete terminal device path.
1645 *TerminalDevicePath
= AppendDevicePathNode (
1647 (EFI_DEVICE_PATH_PROTOCOL
*) &Node
1649 if (*TerminalDevicePath
== NULL
) {
1650 return EFI_OUT_OF_RESOURCES
;
1657 The user Entry Point for module Terminal. The user code starts with this function.
1659 @param ImageHandle The firmware allocated handle for the EFI image.
1660 @param SystemTable A pointer to the EFI System Table.
1662 @retval EFI_SUCCESS The entry point is executed successfully.
1663 @retval other Some error occurs when executing this entry point.
1669 IN EFI_HANDLE ImageHandle
,
1670 IN EFI_SYSTEM_TABLE
*SystemTable
1676 // Install driver model protocol(s).
1678 Status
= EfiLibInstallDriverBindingComponentName2 (
1681 &gTerminalDriverBinding
,
1683 &gTerminalComponentName
,
1684 &gTerminalComponentName2
1686 ASSERT_EFI_ERROR (Status
);
1692 Check if the device supports hot-plug through its device path.
1694 This function could be updated to check more types of Hot Plug devices.
1695 Currently, it checks USB and PCCard device.
1697 @param DevicePath Pointer to device's device path.
1699 @retval TRUE The devcie is a hot-plug device
1700 @retval FALSE The devcie is not a hot-plug device.
1705 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1708 EFI_DEVICE_PATH_PROTOCOL
*CheckDevicePath
;
1710 CheckDevicePath
= DevicePath
;
1711 while (!IsDevicePathEnd (CheckDevicePath
)) {
1713 // Check device whether is hot plug device or not throught Device Path
1715 if ((DevicePathType (CheckDevicePath
) == MESSAGING_DEVICE_PATH
) &&
1716 (DevicePathSubType (CheckDevicePath
) == MSG_USB_DP
||
1717 DevicePathSubType (CheckDevicePath
) == MSG_USB_CLASS_DP
||
1718 DevicePathSubType (CheckDevicePath
) == MSG_USB_WWID_DP
)) {
1720 // If Device is USB device
1724 if ((DevicePathType (CheckDevicePath
) == HARDWARE_DEVICE_PATH
) &&
1725 (DevicePathSubType (CheckDevicePath
) == HW_PCCARD_DP
)) {
1727 // If Device is PCCard
1732 CheckDevicePath
= NextDevicePathNode (CheckDevicePath
);