Start this driver on ControllerHandle by opening Simple Text Input Protocol,\r
reading Device Path, and installing Console In Devcice GUID on ControllerHandle.\r
\r
- If this devcie is not one hot-plug devce, append its device path into the\r
- console environment variables ConInDev.\r
+ Append its device path into the console environment variables ConInDev.\r
\r
@param This Protocol instance pointer.\r
@param ControllerHandle Handle of device to bind driver to\r
}\r
\r
//\r
- // Check the device path, if it is a hot plug device,\r
- // do not put the device path into ConInDev, and install\r
- // gEfiConsoleInDeviceGuid to the device handle directly.\r
- // The policy is, make hot plug device plug in and play immediately.\r
+ // Append the device path to the ConInDev environment variable\r
//\r
- if (IsHotPlugDevice (DevicePath)) {\r
+ ConPlatformUpdateDeviceVariable (\r
+ L"ConInDev",\r
+ DevicePath,\r
+ Append\r
+ );\r
+\r
+ //\r
+ // If the device path is an instance in the ConIn environment variable,\r
+ // then install EfiConsoleInDeviceGuid onto ControllerHandle\r
+ //\r
+ if (IsInConInVariable) {\r
gBS->InstallMultipleProtocolInterfaces (\r
&ControllerHandle,\r
&gEfiConsoleInDeviceGuid,\r
NULL,\r
NULL\r
);\r
- //\r
- // Append the device path to ConInDev only if it is in ConIn variable.\r
- //\r
- if (IsInConInVariable) {\r
- ConPlatformUpdateDeviceVariable (\r
- L"ConInDev",\r
- DevicePath,\r
- Append\r
- );\r
- }\r
} else {\r
- //\r
- // If it is not a hot-plug device, append the device path to the\r
- // ConInDev environment variable\r
- //\r
- ConPlatformUpdateDeviceVariable (\r
- L"ConInDev",\r
- DevicePath,\r
- Append\r
- );\r
-\r
- //\r
- // If the device path is an instance in the ConIn environment variable,\r
- // then install EfiConsoleInDeviceGuid onto ControllerHandle\r
- //\r
- if (IsInConInVariable) {\r
- gBS->InstallMultipleProtocolInterfaces (\r
- &ControllerHandle,\r
- &gEfiConsoleInDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
- } else {\r
- gBS->CloseProtocol (\r
- ControllerHandle,\r
- &gEfiSimpleTextInProtocolGuid,\r
- This->DriverBindingHandle,\r
- ControllerHandle\r
- );\r
- }\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
}\r
\r
return EFI_SUCCESS;\r
reading Device Path, and installing Console Out Devcic GUID, Standard Error\r
Device GUID on ControllerHandle.\r
\r
- If this devcie is not one hot-plug devce, append its device path into the\r
- console environment variables ConOutDev, ErrOutDev.\r
+ Append its device path into the console environment variables ConOutDev, ErrOutDev.\r
\r
@param This Protocol instance pointer.\r
@param ControllerHandle Handle of device to bind driver to\r
}\r
\r
//\r
- // Check the device path, if it is a hot plug device,\r
- // do not put the device path into ConOutDev and ErrOutDev,\r
- // and install gEfiConsoleOutDeviceGuid to the device handle directly.\r
- // The policy is, make hot plug device plug in and play immediately.\r
+ // Append the device path to the ConOutDev and ErrOutDev environment variable.\r
+ // For GOP device path, append the sibling device path as well.\r
//\r
- if (IsHotPlugDevice (DevicePath)) {\r
+ if (!ConPlatformUpdateGopCandidate (DevicePath)) {\r
+ ConPlatformUpdateDeviceVariable (\r
+ L"ConOutDev",\r
+ DevicePath,\r
+ Append\r
+ );\r
+ //\r
+ // Then append the device path to the ErrOutDev environment variable\r
+ //\r
+ ConPlatformUpdateDeviceVariable (\r
+ L"ErrOutDev",\r
+ DevicePath,\r
+ Append\r
+ );\r
+ }\r
+\r
+ //\r
+ // If the device path is an instance in the ConOut environment variable,\r
+ // then install EfiConsoleOutDeviceGuid onto ControllerHandle\r
+ //\r
+ if (IsInConOutVariable) {\r
+ NeedClose = FALSE;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ControllerHandle,\r
+ &gEfiConsoleOutDeviceGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+ //\r
+ // If the device path is an instance in the ErrOut environment variable,\r
+ // then install EfiStandardErrorDeviceGuid onto ControllerHandle\r
+ //\r
+ if (IsInErrOutVariable) {\r
+ NeedClose = FALSE;\r
gBS->InstallMultipleProtocolInterfaces (\r
&ControllerHandle,\r
- &gEfiConsoleOutDeviceGuid,\r
+ &gEfiStandardErrorDeviceGuid,\r
NULL,\r
NULL\r
);\r
- //\r
- // Append the device path to ConOutDev only if it is in ConOut variable.\r
- //\r
- if (IsInConOutVariable) {\r
- ConPlatformUpdateDeviceVariable (\r
- L"ConOutDev",\r
- DevicePath,\r
- Append\r
- );\r
- }\r
- //\r
- // Append the device path to ErrOutDev only if it is in ErrOut variable.\r
- //\r
- if (IsInErrOutVariable) {\r
- ConPlatformUpdateDeviceVariable (\r
- L"ErrOutDev",\r
- DevicePath,\r
- Append\r
- );\r
- }\r
- } else {\r
- //\r
- // If it is not a hot-plug device, append the device path to\r
- // the ConOutDev and ErrOutDev environment variable.\r
- // For GOP device path, append the sibling device path as well.\r
- //\r
- if (!ConPlatformUpdateGopCandidate (DevicePath)) {\r
- ConPlatformUpdateDeviceVariable (\r
- L"ConOutDev",\r
- DevicePath,\r
- Append\r
- );\r
- //\r
- // Then append the device path to the ErrOutDev environment variable\r
- //\r
- ConPlatformUpdateDeviceVariable (\r
- L"ErrOutDev",\r
- DevicePath,\r
- Append\r
- );\r
- }\r
-\r
- //\r
- // If the device path is an instance in the ConOut environment variable,\r
- // then install EfiConsoleOutDeviceGuid onto ControllerHandle\r
- //\r
- if (IsInConOutVariable) {\r
- NeedClose = FALSE;\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ControllerHandle,\r
- &gEfiConsoleOutDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
- }\r
- //\r
- // If the device path is an instance in the ErrOut environment variable,\r
- // then install EfiStandardErrorDeviceGuid onto ControllerHandle\r
- //\r
- if (IsInErrOutVariable) {\r
- NeedClose = FALSE;\r
- gBS->InstallMultipleProtocolInterfaces (\r
- &ControllerHandle,\r
- &gEfiStandardErrorDeviceGuid,\r
- NULL,\r
- NULL\r
- );\r
- }\r
+ }\r
\r
- if (NeedClose) {\r
- gBS->CloseProtocol (\r
- ControllerHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- This->DriverBindingHandle,\r
- ControllerHandle\r
- );\r
- }\r
+ if (NeedClose) {\r
+ gBS->CloseProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle\r
+ );\r
}\r
\r
return EFI_SUCCESS;\r
return (BOOLEAN) (CompareMem (Left, Right, (UINTN) NodeLeft - (UINTN) Left) == 0);\r
}\r
\r
+/**\r
+ Check whether a USB device match the specified USB Class device path. This\r
+ function follows "Load Option Processing" behavior in UEFI specification.\r
+\r
+ @param UsbIo USB I/O protocol associated with the USB device.\r
+ @param UsbClass The USB Class device path to match.\r
+\r
+ @retval TRUE The USB device match the USB Class device path.\r
+ @retval FALSE The USB device does not match the USB Class device path.\r
+\r
+**/\r
+BOOLEAN\r
+MatchUsbClass (\r
+ IN EFI_USB_IO_PROTOCOL *UsbIo,\r
+ IN USB_CLASS_DEVICE_PATH *UsbClass\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
+ EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
+ UINT8 DeviceClass;\r
+ UINT8 DeviceSubClass;\r
+ UINT8 DeviceProtocol;\r
+\r
+ if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||\r
+ (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP)){\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check Vendor Id and Product Id.\r
+ //\r
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if ((UsbClass->VendorId != 0xffff) &&\r
+ (UsbClass->VendorId != DevDesc.IdVendor)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if ((UsbClass->ProductId != 0xffff) &&\r
+ (UsbClass->ProductId != DevDesc.IdProduct)) {\r
+ return FALSE;\r
+ }\r
+\r
+ DeviceClass = DevDesc.DeviceClass;\r
+ DeviceSubClass = DevDesc.DeviceSubClass;\r
+ DeviceProtocol = DevDesc.DeviceProtocol;\r
+ if (DeviceClass == 0) {\r
+ //\r
+ // If Class in Device Descriptor is set to 0, use the Class, SubClass and\r
+ // Protocol in Interface Descriptor instead.\r
+ //\r
+ Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ DeviceClass = IfDesc.InterfaceClass;\r
+ DeviceSubClass = IfDesc.InterfaceSubClass;\r
+ DeviceProtocol = IfDesc.InterfaceProtocol;\r
+ }\r
+\r
+ //\r
+ // Check Class, SubClass and Protocol.\r
+ //\r
+ if ((UsbClass->DeviceClass != 0xff) &&\r
+ (UsbClass->DeviceClass != DeviceClass)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if ((UsbClass->DeviceSubClass != 0xff) &&\r
+ (UsbClass->DeviceSubClass != DeviceSubClass)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if ((UsbClass->DeviceProtocol != 0xff) &&\r
+ (UsbClass->DeviceProtocol != DeviceProtocol)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Check whether a USB device match the specified USB WWID device path. This\r
+ function follows "Load Option Processing" behavior in UEFI specification.\r
+\r
+ @param UsbIo USB I/O protocol associated with the USB device.\r
+ @param UsbWwid The USB WWID device path to match.\r
+\r
+ @retval TRUE The USB device match the USB WWID device path.\r
+ @retval FALSE The USB device does not match the USB WWID device path.\r
+\r
+**/\r
+BOOLEAN\r
+MatchUsbWwid (\r
+ IN EFI_USB_IO_PROTOCOL *UsbIo,\r
+ IN USB_WWID_DEVICE_PATH *UsbWwid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
+ EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
+ UINT16 *LangIdTable;\r
+ UINT16 TableSize;\r
+ UINT16 Index;\r
+ CHAR16 *CompareStr;\r
+ UINTN CompareLen;\r
+ CHAR16 *SerialNumberStr;\r
+ UINTN Length;\r
+\r
+ if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||\r
+ (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check Vendor Id and Product Id.\r
+ //\r
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+ if ((DevDesc.IdVendor != UsbWwid->VendorId) ||\r
+ (DevDesc.IdProduct != UsbWwid->ProductId)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check Interface Number.\r
+ //\r
+ Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+ if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check Serial Number.\r
+ //\r
+ if (DevDesc.StrSerialNumber == 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Get all supported languages.\r
+ //\r
+ TableSize = 0;\r
+ LangIdTable = NULL;\r
+ Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);\r
+ if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.\r
+ //\r
+ CompareStr = (CHAR16 *) (UINTN) (UsbWwid + 1);\r
+ CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);\r
+ if (CompareStr[CompareLen - 1] == L'\0') {\r
+ CompareLen--;\r
+ }\r
+\r
+ //\r
+ // Compare serial number in each supported language.\r
+ //\r
+ for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {\r
+ SerialNumberStr = NULL;\r
+ Status = UsbIo->UsbGetStringDescriptor (\r
+ UsbIo,\r
+ LangIdTable[Index],\r
+ DevDesc.StrSerialNumber,\r
+ &SerialNumberStr\r
+ );\r
+ if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {\r
+ continue;\r
+ }\r
+\r
+ Length = StrLen (SerialNumberStr);\r
+ if ((Length >= CompareLen) &&\r
+ (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {\r
+ FreePool (SerialNumberStr);\r
+ return TRUE;\r
+ }\r
+\r
+ FreePool (SerialNumberStr);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Compare whether a full console device path matches a USB shortform device path.\r
+\r
+ @param[in] FullPath Full console device path.\r
+ @param[in] ShortformPath Short-form device path. Short-form device node may in the beginning or in the middle.\r
+\r
+ @retval TRUE The full console device path matches the short-form device path.\r
+ @retval FALSE The full console device path doesn't match the short-form device path.\r
+**/\r
+BOOLEAN\r
+MatchUsbShortformDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FullPath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ShortformPath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *ShortformNode;\r
+ UINTN ParentDevicePathSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
+ EFI_USB_IO_PROTOCOL *UsbIo;\r
+ EFI_HANDLE Handle;\r
+\r
+ for ( ShortformNode = ShortformPath\r
+ ; !IsDevicePathEnd (ShortformNode)\r
+ ; ShortformNode = NextDevicePathNode (ShortformNode)\r
+ ) {\r
+ if ((DevicePathType (ShortformNode) == MESSAGING_DEVICE_PATH) &&\r
+ ((DevicePathSubType (ShortformNode) == MSG_USB_CLASS_DP) ||\r
+ (DevicePathSubType (ShortformNode) == MSG_USB_WWID_DP))\r
+ ) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Skip further compare when it's not a shortform device path.\r
+ //\r
+ if (IsDevicePathEnd (ShortformNode)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Compare the parent device path when the ShortformPath doesn't start with short-form node.\r
+ //\r
+ ParentDevicePathSize = (UINTN) ShortformNode - (UINTN) ShortformPath;\r
+ RemainingDevicePath = FullPath;\r
+ Status = gBS->LocateDevicePath (&gEfiUsbIoProtocolGuid, &RemainingDevicePath, &Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+ if (ParentDevicePathSize != 0) {\r
+ if ((ParentDevicePathSize > (UINTN) RemainingDevicePath - (UINTN) FullPath) ||\r
+ (CompareMem (FullPath, ShortformPath, ParentDevicePathSize) != 0)) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Compar the USB layer.\r
+ //\r
+ Status = gBS->HandleProtocol(\r
+ Handle,\r
+ &gEfiUsbIoProtocolGuid,\r
+ (VOID **) &UsbIo\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return MatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *)ShortformNode) ||\r
+ MatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *)ShortformNode);\r
+}\r
+\r
/**\r
Function compares a device path data structure to that of all the nodes of a\r
second device path instance.\r
// Search for the match of 'Single' in 'Multi'\r
//\r
while (DevicePathInst != NULL) {\r
- if ((CompareMem (Single, DevicePathInst, Size) == 0) || IsGopSibling (Single, DevicePathInst)) {\r
+ if ((CompareMem (Single, DevicePathInst, Size) == 0) ||\r
+ IsGopSibling (Single, DevicePathInst) || MatchUsbShortformDevicePath (Single, DevicePathInst)) {\r
if (!Delete) {\r
//\r
// If Delete is FALSE, return EFI_SUCCESS if Single is found in Multi.\r
return Status;\r
}\r
\r
-/**\r
- Check if the device supports hot-plug through its device path.\r
-\r
- This function could be updated to check more types of Hot Plug devices.\r
- Currently, it checks USB and PCCard device.\r
-\r
- @param DevicePath Pointer to device's device path.\r
-\r
- @retval TRUE The devcie is a hot-plug device\r
- @retval FALSE The devcie is not a hot-plug device.\r
-\r
-**/\r
-BOOLEAN\r
-IsHotPlugDevice (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
-\r
- CheckDevicePath = DevicePath;\r
- while (!IsDevicePathEnd (CheckDevicePath)) {\r
- //\r
- // Check device whether is hot plug device or not throught Device Path\r
- //\r
- if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
- (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
- DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
- DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
- //\r
- // If Device is USB device\r
- //\r
- return TRUE;\r
- }\r
- if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
- (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
- //\r
- // If Device is PCCard\r
- //\r
- return TRUE;\r
- }\r
-\r
- CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
/**\r
Update ConOutDev and ErrOutDev variables to add the device path of\r
GOP controller itself and the sibling controllers.\r