2 Console Platform DXE Driver, install Console Device Guids and update Console
5 Copyright (c) 2006 - 2018, 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.
16 #include "ConPlatform.h"
19 EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding
= {
20 ConPlatformTextInDriverBindingSupported
,
21 ConPlatformTextInDriverBindingStart
,
22 ConPlatformTextInDriverBindingStop
,
28 EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding
= {
29 ConPlatformTextOutDriverBindingSupported
,
30 ConPlatformTextOutDriverBindingStart
,
31 ConPlatformTextOutDriverBindingStop
,
38 Entrypoint of this module.
40 This function is the entrypoint of this module. It installs Driver Binding
41 Protocols together with Component Name Protocols.
43 @param ImageHandle The firmware allocated handle for the EFI image.
44 @param SystemTable A pointer to the EFI System Table.
46 @retval EFI_SUCCESS The entry point is executed successfully.
51 InitializeConPlatform(
52 IN EFI_HANDLE ImageHandle
,
53 IN EFI_SYSTEM_TABLE
*SystemTable
58 Status
= EfiLibInstallDriverBindingComponentName2 (
61 &gConPlatformTextInDriverBinding
,
63 &gConPlatformComponentName
,
64 &gConPlatformComponentName2
66 ASSERT_EFI_ERROR (Status
);
68 Status
= EfiLibInstallDriverBindingComponentName2 (
71 &gConPlatformTextOutDriverBinding
,
73 &gConPlatformComponentName
,
74 &gConPlatformComponentName2
76 ASSERT_EFI_ERROR (Status
);
83 Test to see if EFI_SIMPLE_TEXT_INPUT_PROTOCOL is supported on ControllerHandle.
85 @param This Protocol instance pointer.
86 @param ControllerHandle Handle of device to test.
87 @param RemainingDevicePath Optional parameter use to pick a specific child
90 @retval EFI_SUCCESS This driver supports this device.
91 @retval other This driver does not support this device.
96 ConPlatformTextInDriverBindingSupported (
97 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
98 IN EFI_HANDLE ControllerHandle
,
99 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
102 return ConPlatformDriverBindingSupported (
105 &gEfiSimpleTextInProtocolGuid
111 Test to see if EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL is supported on ControllerHandle.
113 @param This Protocol instance pointer.
114 @param ControllerHandle Handle of device to test.
115 @param RemainingDevicePath Optional parameter use to pick a specific child
118 @retval EFI_SUCCESS This driver supports this device.
119 @retval other This driver does not support this device.
124 ConPlatformTextOutDriverBindingSupported (
125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
126 IN EFI_HANDLE ControllerHandle
,
127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
130 return ConPlatformDriverBindingSupported (
133 &gEfiSimpleTextOutProtocolGuid
139 Test to see if the specified protocol is supported on ControllerHandle.
141 @param This Protocol instance pointer.
142 @param ControllerHandle Handle of device to test.
143 @param ProtocolGuid The specfic protocol.
145 @retval EFI_SUCCESS This driver supports this device.
146 @retval other This driver does not support this device.
150 ConPlatformDriverBindingSupported (
151 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
152 IN EFI_HANDLE ControllerHandle
,
153 IN EFI_GUID
*ProtocolGuid
160 // Test to see if this is a physical device by checking if
161 // it has a Device Path Protocol.
163 Status
= gBS
->OpenProtocol (
165 &gEfiDevicePathProtocolGuid
,
167 This
->DriverBindingHandle
,
169 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
171 if (EFI_ERROR (Status
)) {
175 // Test to see if this device supports the specified Protocol.
177 Status
= gBS
->OpenProtocol (
180 (VOID
**) &Interface
,
181 This
->DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
185 if (EFI_ERROR (Status
)) {
192 This
->DriverBindingHandle
,
200 Start this driver on the device for console input.
202 Start this driver on ControllerHandle by opening Simple Text Input Protocol,
203 reading Device Path, and installing Console In Devcice GUID on ControllerHandle.
205 Append its device path into the console environment variables ConInDev.
207 @param This Protocol instance pointer.
208 @param ControllerHandle Handle of device to bind driver to
209 @param RemainingDevicePath Optional parameter use to pick a specific child
212 @retval EFI_SUCCESS This driver is added to ControllerHandle
213 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
214 @retval other This driver does not support this device.
219 ConPlatformTextInDriverBindingStart (
220 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
221 IN EFI_HANDLE ControllerHandle
,
222 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
226 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
227 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
228 BOOLEAN IsInConInVariable
;
231 // Get the Device Path Protocol so the environment variables can be updated
233 Status
= gBS
->OpenProtocol (
235 &gEfiDevicePathProtocolGuid
,
236 (VOID
**) &DevicePath
,
237 This
->DriverBindingHandle
,
239 EFI_OPEN_PROTOCOL_GET_PROTOCOL
241 if (EFI_ERROR (Status
)) {
245 // Open the Simple Text Input Protocol BY_DRIVER
247 Status
= gBS
->OpenProtocol (
249 &gEfiSimpleTextInProtocolGuid
,
251 This
->DriverBindingHandle
,
253 EFI_OPEN_PROTOCOL_BY_DRIVER
255 if (EFI_ERROR (Status
)) {
259 // Check if the device path is in ConIn Variable
261 IsInConInVariable
= FALSE
;
262 Status
= ConPlatformUpdateDeviceVariable (
267 if (!EFI_ERROR (Status
)) {
268 IsInConInVariable
= TRUE
;
272 // Append the device path to the ConInDev environment variable
274 ConPlatformUpdateDeviceVariable (
281 // If the device path is an instance in the ConIn environment variable,
282 // then install EfiConsoleInDeviceGuid onto ControllerHandle
284 if (IsInConInVariable
) {
285 gBS
->InstallMultipleProtocolInterfaces (
287 &gEfiConsoleInDeviceGuid
,
294 &gEfiSimpleTextInProtocolGuid
,
295 This
->DriverBindingHandle
,
304 Start this driver on the device for console output and standard error output.
306 Start this driver on ControllerHandle by opening Simple Text Output Protocol,
307 reading Device Path, and installing Console Out Devcic GUID, Standard Error
308 Device GUID on ControllerHandle.
310 Append its device path into the console environment variables ConOutDev, ErrOutDev.
312 @param This Protocol instance pointer.
313 @param ControllerHandle Handle of device to bind driver to
314 @param RemainingDevicePath Optional parameter use to pick a specific child
317 @retval EFI_SUCCESS This driver is added to ControllerHandle
318 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
319 @retval other This driver does not support this device
324 ConPlatformTextOutDriverBindingStart (
325 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
326 IN EFI_HANDLE ControllerHandle
,
327 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
331 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
332 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
334 BOOLEAN IsInConOutVariable
;
335 BOOLEAN IsInErrOutVariable
;
340 // Get the Device Path Protocol so the environment variables can be updated
342 Status
= gBS
->OpenProtocol (
344 &gEfiDevicePathProtocolGuid
,
345 (VOID
**) &DevicePath
,
346 This
->DriverBindingHandle
,
348 EFI_OPEN_PROTOCOL_GET_PROTOCOL
350 if (EFI_ERROR (Status
)) {
354 // Open the Simple Text Output Protocol BY_DRIVER
356 Status
= gBS
->OpenProtocol (
358 &gEfiSimpleTextOutProtocolGuid
,
360 This
->DriverBindingHandle
,
362 EFI_OPEN_PROTOCOL_BY_DRIVER
364 if (EFI_ERROR (Status
)) {
368 // Check if the device path is in ConOut & ErrOut Variable
370 IsInConOutVariable
= FALSE
;
371 Status
= ConPlatformUpdateDeviceVariable (
376 if (!EFI_ERROR (Status
)) {
377 IsInConOutVariable
= TRUE
;
380 IsInErrOutVariable
= FALSE
;
381 Status
= ConPlatformUpdateDeviceVariable (
386 if (!EFI_ERROR (Status
)) {
387 IsInErrOutVariable
= TRUE
;
391 // Append the device path to the ConOutDev and ErrOutDev environment variable.
392 // For GOP device path, append the sibling device path as well.
394 if (!ConPlatformUpdateGopCandidate (DevicePath
)) {
395 ConPlatformUpdateDeviceVariable (
401 // Then append the device path to the ErrOutDev environment variable
403 ConPlatformUpdateDeviceVariable (
411 // If the device path is an instance in the ConOut environment variable,
412 // then install EfiConsoleOutDeviceGuid onto ControllerHandle
414 if (IsInConOutVariable
) {
416 Status
= gBS
->InstallMultipleProtocolInterfaces (
418 &gEfiConsoleOutDeviceGuid
,
424 // If the device path is an instance in the ErrOut environment variable,
425 // then install EfiStandardErrorDeviceGuid onto ControllerHandle
427 if (IsInErrOutVariable
) {
429 gBS
->InstallMultipleProtocolInterfaces (
431 &gEfiStandardErrorDeviceGuid
,
440 &gEfiSimpleTextOutProtocolGuid
,
441 This
->DriverBindingHandle
,
450 Stop this driver on ControllerHandle by removing Console In Devcice GUID
451 and closing the Simple Text Input protocol on ControllerHandle.
453 @param This Protocol instance pointer.
454 @param ControllerHandle Handle of device to stop driver on
455 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
456 children is zero stop the entire bus driver.
457 @param ChildHandleBuffer List of Child Handles to Stop.
459 @retval EFI_SUCCESS This driver is removed ControllerHandle
460 @retval other This driver was not removed from this device
465 ConPlatformTextInDriverBindingStop (
466 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
467 IN EFI_HANDLE ControllerHandle
,
468 IN UINTN NumberOfChildren
,
469 IN EFI_HANDLE
*ChildHandleBuffer
473 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
476 // Get the Device Path Protocol firstly
478 Status
= gBS
->OpenProtocol (
480 &gEfiDevicePathProtocolGuid
,
481 (VOID
**) &DevicePath
,
482 This
->DriverBindingHandle
,
484 EFI_OPEN_PROTOCOL_GET_PROTOCOL
487 // If there is device path on ControllerHandle
489 if (!EFI_ERROR (Status
)) {
491 // Remove DevicePath from ConInDev if exists.
493 ConPlatformUpdateDeviceVariable (
501 // Uninstall the Console Device GUIDs from Controller Handle
503 ConPlatformUnInstallProtocol (
506 &gEfiConsoleInDeviceGuid
510 // Close the Simple Text Input Protocol
514 &gEfiSimpleTextInProtocolGuid
,
515 This
->DriverBindingHandle
,
524 Stop this driver on ControllerHandle by removing Console Out Devcice GUID
525 and closing the Simple Text Output protocol on ControllerHandle.
527 @param This Protocol instance pointer.
528 @param ControllerHandle Handle of device to stop driver on
529 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
530 children is zero stop the entire bus driver.
531 @param ChildHandleBuffer List of Child Handles to Stop.
533 @retval EFI_SUCCESS This driver is removed ControllerHandle
534 @retval other This driver was not removed from this device
539 ConPlatformTextOutDriverBindingStop (
540 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
541 IN EFI_HANDLE ControllerHandle
,
542 IN UINTN NumberOfChildren
,
543 IN EFI_HANDLE
*ChildHandleBuffer
547 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
550 // Get the Device Path Protocol firstly
552 Status
= gBS
->OpenProtocol (
554 &gEfiDevicePathProtocolGuid
,
555 (VOID
**) &DevicePath
,
556 This
->DriverBindingHandle
,
558 EFI_OPEN_PROTOCOL_GET_PROTOCOL
560 if (!EFI_ERROR (Status
)) {
562 // Remove DevicePath from ConOutDev and ErrOutDev if exists.
564 ConPlatformUpdateDeviceVariable (
569 ConPlatformUpdateDeviceVariable (
577 // Uninstall the Console Device GUIDs from Controller Handle
579 ConPlatformUnInstallProtocol (
582 &gEfiConsoleOutDeviceGuid
585 ConPlatformUnInstallProtocol (
588 &gEfiStandardErrorDeviceGuid
592 // Close the Simple Text Output Protocol
596 &gEfiSimpleTextOutProtocolGuid
,
597 This
->DriverBindingHandle
,
606 Uninstall the specified protocol.
608 @param This Protocol instance pointer.
609 @param Handle Handle of device to uninstall protocol on.
610 @param ProtocolGuid The specified protocol need to be uninstalled.
614 ConPlatformUnInstallProtocol (
615 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
616 IN EFI_HANDLE Handle
,
617 IN EFI_GUID
*ProtocolGuid
622 Status
= gBS
->OpenProtocol (
626 This
->DriverBindingHandle
,
628 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
631 if (!EFI_ERROR (Status
)) {
632 gBS
->UninstallMultipleProtocolInterfaces (
644 Get the necessary size of buffer and read the variable.
646 First get the necessary size of buffer. Then read the
647 EFI variable (Name) and return a dynamically allocated
648 buffer. On failure return NULL.
650 @param Name String part of EFI variable name
652 @return Dynamically allocated memory that contains a copy of the EFI variable.
653 Caller is repsoncible freeing the buffer. Return NULL means Variable
658 ConPlatformGetVariable (
670 // Test to see if the variable exists. If it doesn't, return NULL.
672 Status
= gRT
->GetVariable (
674 &gEfiGlobalVariableGuid
,
680 if (Status
== EFI_BUFFER_TOO_SMALL
) {
682 // Allocate the buffer to return
684 Buffer
= AllocatePool (BufferSize
);
685 if (Buffer
== NULL
) {
689 // Read variable into the allocated buffer.
691 Status
= gRT
->GetVariable (
693 &gEfiGlobalVariableGuid
,
698 if (EFI_ERROR (Status
)) {
701 // To make sure Buffer is NULL if any error occurs.
711 Function returns TRUE when the two input device paths point to the two
712 GOP child handles that have the same parent.
714 @param Left A pointer to a device path data structure.
715 @param Right A pointer to a device path data structure.
717 @retval TRUE Left and Right share the same parent.
718 @retval FALSE Left and Right don't share the same parent or either of them is not
723 IN EFI_DEVICE_PATH_PROTOCOL
*Left
,
724 IN EFI_DEVICE_PATH_PROTOCOL
*Right
727 EFI_DEVICE_PATH_PROTOCOL
*NodeLeft
;
728 EFI_DEVICE_PATH_PROTOCOL
*NodeRight
;
730 for (NodeLeft
= Left
; !IsDevicePathEndType (NodeLeft
); NodeLeft
= NextDevicePathNode (NodeLeft
)) {
731 if ((DevicePathType (NodeLeft
) == ACPI_DEVICE_PATH
&& DevicePathSubType (NodeLeft
) == ACPI_ADR_DP
) ||
732 (DevicePathType (NodeLeft
) == HARDWARE_DEVICE_PATH
&& DevicePathSubType (NodeLeft
) == HW_CONTROLLER_DP
&&
733 DevicePathType (NextDevicePathNode (NodeLeft
)) == ACPI_DEVICE_PATH
&& DevicePathSubType (NextDevicePathNode (NodeLeft
)) == ACPI_ADR_DP
)) {
738 if (IsDevicePathEndType (NodeLeft
)) {
742 for (NodeRight
= Right
; !IsDevicePathEndType (NodeRight
); NodeRight
= NextDevicePathNode (NodeRight
)) {
743 if ((DevicePathType (NodeRight
) == ACPI_DEVICE_PATH
&& DevicePathSubType (NodeRight
) == ACPI_ADR_DP
) ||
744 (DevicePathType (NodeRight
) == HARDWARE_DEVICE_PATH
&& DevicePathSubType (NodeRight
) == HW_CONTROLLER_DP
&&
745 DevicePathType (NextDevicePathNode (NodeRight
)) == ACPI_DEVICE_PATH
&& DevicePathSubType (NextDevicePathNode (NodeRight
)) == ACPI_ADR_DP
)) {
750 if (IsDevicePathEndType (NodeRight
)) {
754 if (((UINTN
) NodeLeft
- (UINTN
) Left
) != ((UINTN
) NodeRight
- (UINTN
) Right
)) {
758 return (BOOLEAN
) (CompareMem (Left
, Right
, (UINTN
) NodeLeft
- (UINTN
) Left
) == 0);
762 Check whether a USB device match the specified USB Class device path. This
763 function follows "Load Option Processing" behavior in UEFI specification.
765 @param UsbIo USB I/O protocol associated with the USB device.
766 @param UsbClass The USB Class device path to match.
768 @retval TRUE The USB device match the USB Class device path.
769 @retval FALSE The USB device does not match the USB Class device path.
774 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
775 IN USB_CLASS_DEVICE_PATH
*UsbClass
779 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
780 EFI_USB_INTERFACE_DESCRIPTOR IfDesc
;
782 UINT8 DeviceSubClass
;
783 UINT8 DeviceProtocol
;
785 if ((DevicePathType (UsbClass
) != MESSAGING_DEVICE_PATH
) ||
786 (DevicePathSubType (UsbClass
) != MSG_USB_CLASS_DP
)){
791 // Check Vendor Id and Product Id.
793 Status
= UsbIo
->UsbGetDeviceDescriptor (UsbIo
, &DevDesc
);
794 if (EFI_ERROR (Status
)) {
798 if ((UsbClass
->VendorId
!= 0xffff) &&
799 (UsbClass
->VendorId
!= DevDesc
.IdVendor
)) {
803 if ((UsbClass
->ProductId
!= 0xffff) &&
804 (UsbClass
->ProductId
!= DevDesc
.IdProduct
)) {
808 DeviceClass
= DevDesc
.DeviceClass
;
809 DeviceSubClass
= DevDesc
.DeviceSubClass
;
810 DeviceProtocol
= DevDesc
.DeviceProtocol
;
811 if (DeviceClass
== 0) {
813 // If Class in Device Descriptor is set to 0, use the Class, SubClass and
814 // Protocol in Interface Descriptor instead.
816 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &IfDesc
);
817 if (EFI_ERROR (Status
)) {
821 DeviceClass
= IfDesc
.InterfaceClass
;
822 DeviceSubClass
= IfDesc
.InterfaceSubClass
;
823 DeviceProtocol
= IfDesc
.InterfaceProtocol
;
827 // Check Class, SubClass and Protocol.
829 if ((UsbClass
->DeviceClass
!= 0xff) &&
830 (UsbClass
->DeviceClass
!= DeviceClass
)) {
834 if ((UsbClass
->DeviceSubClass
!= 0xff) &&
835 (UsbClass
->DeviceSubClass
!= DeviceSubClass
)) {
839 if ((UsbClass
->DeviceProtocol
!= 0xff) &&
840 (UsbClass
->DeviceProtocol
!= DeviceProtocol
)) {
848 Check whether a USB device match the specified USB WWID device path. This
849 function follows "Load Option Processing" behavior in UEFI specification.
851 @param UsbIo USB I/O protocol associated with the USB device.
852 @param UsbWwid The USB WWID device path to match.
854 @retval TRUE The USB device match the USB WWID device path.
855 @retval FALSE The USB device does not match the USB WWID device path.
860 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
861 IN USB_WWID_DEVICE_PATH
*UsbWwid
865 EFI_USB_DEVICE_DESCRIPTOR DevDesc
;
866 EFI_USB_INTERFACE_DESCRIPTOR IfDesc
;
872 CHAR16
*SerialNumberStr
;
875 if ((DevicePathType (UsbWwid
) != MESSAGING_DEVICE_PATH
) ||
876 (DevicePathSubType (UsbWwid
) != MSG_USB_WWID_DP
)) {
881 // Check Vendor Id and Product Id.
883 Status
= UsbIo
->UsbGetDeviceDescriptor (UsbIo
, &DevDesc
);
884 if (EFI_ERROR (Status
)) {
887 if ((DevDesc
.IdVendor
!= UsbWwid
->VendorId
) ||
888 (DevDesc
.IdProduct
!= UsbWwid
->ProductId
)) {
893 // Check Interface Number.
895 Status
= UsbIo
->UsbGetInterfaceDescriptor (UsbIo
, &IfDesc
);
896 if (EFI_ERROR (Status
)) {
899 if (IfDesc
.InterfaceNumber
!= UsbWwid
->InterfaceNumber
) {
904 // Check Serial Number.
906 if (DevDesc
.StrSerialNumber
== 0) {
911 // Get all supported languages.
915 Status
= UsbIo
->UsbGetSupportedLanguages (UsbIo
, &LangIdTable
, &TableSize
);
916 if (EFI_ERROR (Status
) || (TableSize
== 0) || (LangIdTable
== NULL
)) {
921 // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.
923 CompareStr
= (CHAR16
*) (UINTN
) (UsbWwid
+ 1);
924 CompareLen
= (DevicePathNodeLength (UsbWwid
) - sizeof (USB_WWID_DEVICE_PATH
)) / sizeof (CHAR16
);
925 if (CompareStr
[CompareLen
- 1] == L
'\0') {
930 // Compare serial number in each supported language.
932 for (Index
= 0; Index
< TableSize
/ sizeof (UINT16
); Index
++) {
933 SerialNumberStr
= NULL
;
934 Status
= UsbIo
->UsbGetStringDescriptor (
937 DevDesc
.StrSerialNumber
,
940 if (EFI_ERROR (Status
) || (SerialNumberStr
== NULL
)) {
944 Length
= StrLen (SerialNumberStr
);
945 if ((Length
>= CompareLen
) &&
946 (CompareMem (SerialNumberStr
+ Length
- CompareLen
, CompareStr
, CompareLen
* sizeof (CHAR16
)) == 0)) {
947 FreePool (SerialNumberStr
);
951 FreePool (SerialNumberStr
);
958 Compare whether a full console device path matches a USB shortform device path.
960 @param[in] FullPath Full console device path.
961 @param[in] ShortformPath Short-form device path. Short-form device node may in the beginning or in the middle.
963 @retval TRUE The full console device path matches the short-form device path.
964 @retval FALSE The full console device path doesn't match the short-form device path.
967 MatchUsbShortformDevicePath (
968 IN EFI_DEVICE_PATH_PROTOCOL
*FullPath
,
969 IN EFI_DEVICE_PATH_PROTOCOL
*ShortformPath
973 EFI_DEVICE_PATH_PROTOCOL
*ShortformNode
;
974 UINTN ParentDevicePathSize
;
975 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
976 EFI_USB_IO_PROTOCOL
*UsbIo
;
979 for ( ShortformNode
= ShortformPath
980 ; !IsDevicePathEnd (ShortformNode
)
981 ; ShortformNode
= NextDevicePathNode (ShortformNode
)
983 if ((DevicePathType (ShortformNode
) == MESSAGING_DEVICE_PATH
) &&
984 ((DevicePathSubType (ShortformNode
) == MSG_USB_CLASS_DP
) ||
985 (DevicePathSubType (ShortformNode
) == MSG_USB_WWID_DP
))
992 // Skip further compare when it's not a shortform device path.
994 if (IsDevicePathEnd (ShortformNode
)) {
999 // Compare the parent device path when the ShortformPath doesn't start with short-form node.
1001 ParentDevicePathSize
= (UINTN
) ShortformNode
- (UINTN
) ShortformPath
;
1002 RemainingDevicePath
= FullPath
;
1003 Status
= gBS
->LocateDevicePath (&gEfiUsbIoProtocolGuid
, &RemainingDevicePath
, &Handle
);
1004 if (EFI_ERROR (Status
)) {
1007 if (ParentDevicePathSize
!= 0) {
1008 if ((ParentDevicePathSize
> (UINTN
) RemainingDevicePath
- (UINTN
) FullPath
) ||
1009 (CompareMem (FullPath
, ShortformPath
, ParentDevicePathSize
) != 0)) {
1015 // Compar the USB layer.
1017 Status
= gBS
->HandleProtocol(
1019 &gEfiUsbIoProtocolGuid
,
1022 ASSERT_EFI_ERROR (Status
);
1024 return MatchUsbClass (UsbIo
, (USB_CLASS_DEVICE_PATH
*)ShortformNode
) ||
1025 MatchUsbWwid (UsbIo
, (USB_WWID_DEVICE_PATH
*)ShortformNode
);
1029 Function compares a device path data structure to that of all the nodes of a
1030 second device path instance.
1032 @param Multi A pointer to a multi-instance device path data structure.
1033 @param Single A pointer to a single-instance device path data structure.
1034 @param NewDevicePath If Delete is TRUE, this parameter must not be null, and it
1035 points to the remaining device path data structure.
1036 (remaining device path = Multi - Single.)
1037 @param Delete If TRUE, means removing Single from Multi.
1038 If FALSE, the routine just check whether Single matches
1039 with any instance in Multi.
1041 @retval EFI_SUCCESS If the Single is contained within Multi.
1042 @retval EFI_NOT_FOUND If the Single is not contained within Multi.
1043 @retval EFI_INVALID_PARAMETER Multi is NULL.
1044 @retval EFI_INVALID_PARAMETER Single is NULL.
1045 @retval EFI_INVALID_PARAMETER NewDevicePath is NULL when Delete is TRUE.
1049 ConPlatformMatchDevicePaths (
1050 IN EFI_DEVICE_PATH_PROTOCOL
*Multi
,
1051 IN EFI_DEVICE_PATH_PROTOCOL
*Single
,
1052 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath OPTIONAL
,
1056 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1057 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath1
;
1058 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath2
;
1059 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
1063 // The passed in DevicePath should not be NULL
1065 if ((Multi
== NULL
) || (Single
== NULL
)) {
1066 return EFI_INVALID_PARAMETER
;
1070 // If performing Delete operation, the NewDevicePath must not be NULL.
1073 if (NewDevicePath
== NULL
) {
1074 return EFI_INVALID_PARAMETER
;
1078 TempDevicePath1
= NULL
;
1081 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
1084 // Search for the match of 'Single' in 'Multi'
1086 while (DevicePathInst
!= NULL
) {
1087 if ((CompareMem (Single
, DevicePathInst
, Size
) == 0) ||
1088 IsGopSibling (Single
, DevicePathInst
) || MatchUsbShortformDevicePath (Single
, DevicePathInst
)) {
1091 // If Delete is FALSE, return EFI_SUCCESS if Single is found in Multi.
1093 FreePool (DevicePathInst
);
1099 // If the node of Multi does not match Single, then added it back to the result.
1100 // That is, the node matching Single will be dropped and deleted from result.
1102 TempDevicePath2
= AppendDevicePathInstance (
1106 if (TempDevicePath1
!= NULL
) {
1107 FreePool (TempDevicePath1
);
1109 TempDevicePath1
= TempDevicePath2
;
1113 FreePool (DevicePathInst
);
1114 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
1119 // Return the new device path data structure with specified node deleted.
1121 *NewDevicePath
= TempDevicePath1
;
1125 return EFI_NOT_FOUND
;
1129 Update console environment variables.
1131 @param VariableName Console environment variables, ConOutDev, ConInDev
1132 ErrOutDev, ConIn ,ConOut or ErrOut.
1133 @param DevicePath Console devcie's device path.
1134 @param Operation Variable operations, including APPEND, CHECK and DELETE.
1136 @retval EFI_SUCCESS Variable operates successfully.
1137 @retval EFI_OUT_OF_RESOURCES If variable cannot be appended.
1138 @retval other Variable updating failed.
1142 ConPlatformUpdateDeviceVariable (
1143 IN CHAR16
*VariableName
,
1144 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1145 IN CONPLATFORM_VAR_OPERATION Operation
1149 EFI_DEVICE_PATH_PROTOCOL
*VariableDevicePath
;
1150 EFI_DEVICE_PATH_PROTOCOL
*NewVariableDevicePath
;
1152 VariableDevicePath
= NULL
;
1153 NewVariableDevicePath
= NULL
;
1156 // Get Variable according to variable name.
1157 // The memory for Variable is allocated within ConPlatformGetVarible(),
1158 // it is the caller's responsibility to free the memory before return.
1160 VariableDevicePath
= ConPlatformGetVariable (VariableName
);
1162 if (Operation
!= Delete
) {
1164 // Match specified DevicePath in Console Variable.
1166 Status
= ConPlatformMatchDevicePaths (
1173 if ((Operation
== Check
) || (!EFI_ERROR (Status
))) {
1175 // Branch here includes 2 cases:
1176 // 1. Operation is CHECK, simply return Status.
1177 // 2. Operation is APPEND, and device path already exists in variable, also return.
1179 if (VariableDevicePath
!= NULL
) {
1180 FreePool (VariableDevicePath
);
1186 // We reach here to append a device path that does not exist in variable.
1188 Status
= EFI_SUCCESS
;
1189 NewVariableDevicePath
= AppendDevicePathInstance (
1193 if (NewVariableDevicePath
== NULL
) {
1194 Status
= EFI_OUT_OF_RESOURCES
;
1199 // We reach here to remove DevicePath from the environment variable that
1200 // is a multi-instance device path.
1202 Status
= ConPlatformMatchDevicePaths (
1205 &NewVariableDevicePath
,
1210 if (VariableDevicePath
!= NULL
) {
1211 FreePool (VariableDevicePath
);
1214 if (EFI_ERROR (Status
)) {
1218 if (NewVariableDevicePath
!= NULL
) {
1220 // Update Console Environment Variable.
1222 Status
= gRT
->SetVariable (
1224 &gEfiGlobalVariableGuid
,
1225 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1226 GetDevicePathSize (NewVariableDevicePath
),
1227 NewVariableDevicePath
1230 FreePool (NewVariableDevicePath
);
1237 Update ConOutDev and ErrOutDev variables to add the device path of
1238 GOP controller itself and the sibling controllers.
1240 @param DevicePath Pointer to device's device path.
1242 @retval TRUE The devcie is a GOP device.
1243 @retval FALSE The devcie is not a GOP device.
1247 ConPlatformUpdateGopCandidate (
1248 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1252 EFI_HANDLE PciHandle
;
1253 EFI_HANDLE GopHandle
;
1254 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1257 // Check whether it's a GOP device.
1259 TempDevicePath
= DevicePath
;
1260 Status
= gBS
->LocateDevicePath (&gEfiGraphicsOutputProtocolGuid
, &TempDevicePath
, &GopHandle
);
1261 if (EFI_ERROR (Status
)) {
1265 // Get the parent PciIo handle in order to find all the children
1267 Status
= gBS
->LocateDevicePath (&gEfiPciIoProtocolGuid
, &DevicePath
, &PciHandle
);
1268 if (EFI_ERROR (Status
)) {
1271 TempDevicePath
= EfiBootManagerGetGopDevicePath (PciHandle
);
1272 if (TempDevicePath
!= NULL
) {
1273 ConPlatformUpdateDeviceVariable (L
"ConOutDev", TempDevicePath
, Append
);
1274 ConPlatformUpdateDeviceVariable (L
"ErrOutDev", TempDevicePath
, Append
);